From 935ec5b034a2e166f174d8a517383e6110473fe8 Mon Sep 17 00:00:00 2001 From: Eivind Kvedalen Date: Sun, 29 Sep 2013 21:12:02 +0200 Subject: [PATCH] Initial implementation of Spreadsheet module (C++ version) by Eivind Kvedalen. Various fixes for Windows by Peter Lama Werner Mayer --- src/Mod/Spreadsheet/App/AppSpreadsheet.cpp | 52 + src/Mod/Spreadsheet/App/CMakeLists.txt | 69 + src/Mod/Spreadsheet/App/Cell.cpp | 814 ++ src/Mod/Spreadsheet/App/Cell.h | 190 + src/Mod/Spreadsheet/App/DisplayUnit.h | 61 + src/Mod/Spreadsheet/App/Expression.cpp | 1862 +++++ src/Mod/Spreadsheet/App/Expression.h | 548 ++ src/Mod/Spreadsheet/App/ExpressionParser.l | 267 + .../Spreadsheet/App/ExpressionParser.tab.c | 2207 +++++ src/Mod/Spreadsheet/App/ExpressionParser.y | 184 + src/Mod/Spreadsheet/App/PreCompiled.cpp | 24 + src/Mod/Spreadsheet/App/PreCompiled.h | 59 + .../Spreadsheet/App/PropertyColumnWidths.cpp | 157 + .../Spreadsheet/App/PropertyColumnWidths.h | 78 + .../App/PropertyColumnWidthsPy.xml | 19 + .../Spreadsheet/App/PropertyRowHeights.cpp | 150 + src/Mod/Spreadsheet/App/PropertyRowHeights.h | 77 + .../Spreadsheet/App/PropertyRowHeightsPy.xml | 19 + src/Mod/Spreadsheet/App/PropertySheet.cpp | 1059 +++ src/Mod/Spreadsheet/App/PropertySheet.h | 218 + src/Mod/Spreadsheet/App/PropertySheetPy.xml | 19 + src/Mod/Spreadsheet/App/Range.cpp | 86 + src/Mod/Spreadsheet/App/Range.h | 89 + src/Mod/Spreadsheet/App/Sheet.cpp | 1087 +++ src/Mod/Spreadsheet/App/Sheet.h | 281 + src/Mod/Spreadsheet/App/SheetObserver.cpp | 126 + src/Mod/Spreadsheet/App/SheetObserver.h | 52 + src/Mod/Spreadsheet/App/SheetPy.xml | 164 + src/Mod/Spreadsheet/App/SheetPyImp.cpp | 892 ++ src/Mod/Spreadsheet/App/Utils.cpp | 344 + src/Mod/Spreadsheet/App/Utils.h | 92 + src/Mod/Spreadsheet/App/create_regexps.sh | 21 + src/Mod/Spreadsheet/App/genregexps.cpp | 232 + .../Spreadsheet/App/lex.ExpressionParser.c | 7305 +++++++++++++++++ src/Mod/Spreadsheet/CMakeLists.txt | 25 +- src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp | 64 + .../Spreadsheet/Gui/AppSpreadsheetGuiPy.cpp | 71 + src/Mod/Spreadsheet/Gui/CMakeLists.txt | 91 + src/Mod/Spreadsheet/Gui/Command.cpp | 812 ++ src/Mod/Spreadsheet/Gui/PreCompiled.cpp | 24 + src/Mod/Spreadsheet/Gui/PreCompiled.h | 79 + src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp | 297 + src/Mod/Spreadsheet/Gui/PropertiesDialog.h | 77 + src/Mod/Spreadsheet/Gui/PropertiesDialog.ui | 345 + .../Spreadsheet/Gui/Resources/Spreadsheet.qrc | 19 + .../{ => Gui}/Resources/icons/Spreadsheet.svg | 0 .../icons/SpreadsheetAlignBottom.svg | 139 + .../icons/SpreadsheetAlignCenter.svg | 149 + .../Resources/icons/SpreadsheetAlignLeft.svg | 149 + .../Resources/icons/SpreadsheetAlignRight.svg | 149 + .../Resources/icons/SpreadsheetAlignTop.svg | 139 + .../icons/SpreadsheetAlignVCenter.svg | 139 + .../Resources/icons/SpreadsheetController.svg | 0 .../Gui/Resources/icons/SpreadsheetExport.svg | 654 ++ .../Gui/Resources/icons/SpreadsheetImport.svg | 554 ++ .../Resources/icons/SpreadsheetMergeCells.svg | 166 + .../Resources/icons/SpreadsheetSplitCell.svg | 192 + .../Resources/icons/SpreadsheetStyleBold.svg | 136 + .../icons/SpreadsheetStyleItalic.svg | 136 + .../icons/SpreadsheetStyleUnderline.svg | 141 + src/Mod/Spreadsheet/Gui/Sheet.ui | 56 + src/Mod/Spreadsheet/Gui/SheetModel.cpp | 435 + src/Mod/Spreadsheet/Gui/SheetModel.h | 60 + src/Mod/Spreadsheet/Gui/SheetTableView.cpp | 299 + src/Mod/Spreadsheet/Gui/SheetTableView.h | 76 + .../Spreadsheet/Gui/SpreadsheetDelegate.cpp | 79 + src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h | 51 + src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp | 327 + src/Mod/Spreadsheet/Gui/SpreadsheetView.h | 111 + .../Gui/ViewProviderSpreadsheet.cpp | 193 + .../Spreadsheet/Gui/ViewProviderSpreadsheet.h | 78 + src/Mod/Spreadsheet/Gui/Workbench.cpp | 240 + src/Mod/Spreadsheet/Gui/Workbench.h | 68 + src/Mod/Spreadsheet/Gui/qtcolorpicker.cpp | 1156 +++ src/Mod/Spreadsheet/Gui/qtcolorpicker.h | 122 + src/Mod/Spreadsheet/Init.py | 67 +- src/Mod/Spreadsheet/InitGui.py | 114 +- src/Mod/Spreadsheet/Resources/Spreadsheet.qrc | 7 - src/Mod/Spreadsheet/Spreadsheet.py | 1114 --- src/Mod/Spreadsheet/spreadsheet.dox | 3 + 80 files changed, 27086 insertions(+), 1221 deletions(-) create mode 100644 src/Mod/Spreadsheet/App/AppSpreadsheet.cpp create mode 100644 src/Mod/Spreadsheet/App/CMakeLists.txt create mode 100644 src/Mod/Spreadsheet/App/Cell.cpp create mode 100644 src/Mod/Spreadsheet/App/Cell.h create mode 100644 src/Mod/Spreadsheet/App/DisplayUnit.h create mode 100644 src/Mod/Spreadsheet/App/Expression.cpp create mode 100644 src/Mod/Spreadsheet/App/Expression.h create mode 100644 src/Mod/Spreadsheet/App/ExpressionParser.l create mode 100644 src/Mod/Spreadsheet/App/ExpressionParser.tab.c create mode 100644 src/Mod/Spreadsheet/App/ExpressionParser.y create mode 100644 src/Mod/Spreadsheet/App/PreCompiled.cpp create mode 100644 src/Mod/Spreadsheet/App/PreCompiled.h create mode 100644 src/Mod/Spreadsheet/App/PropertyColumnWidths.cpp create mode 100644 src/Mod/Spreadsheet/App/PropertyColumnWidths.h create mode 100644 src/Mod/Spreadsheet/App/PropertyColumnWidthsPy.xml create mode 100644 src/Mod/Spreadsheet/App/PropertyRowHeights.cpp create mode 100644 src/Mod/Spreadsheet/App/PropertyRowHeights.h create mode 100644 src/Mod/Spreadsheet/App/PropertyRowHeightsPy.xml create mode 100644 src/Mod/Spreadsheet/App/PropertySheet.cpp create mode 100644 src/Mod/Spreadsheet/App/PropertySheet.h create mode 100644 src/Mod/Spreadsheet/App/PropertySheetPy.xml create mode 100644 src/Mod/Spreadsheet/App/Range.cpp create mode 100644 src/Mod/Spreadsheet/App/Range.h create mode 100644 src/Mod/Spreadsheet/App/Sheet.cpp create mode 100644 src/Mod/Spreadsheet/App/Sheet.h create mode 100644 src/Mod/Spreadsheet/App/SheetObserver.cpp create mode 100644 src/Mod/Spreadsheet/App/SheetObserver.h create mode 100644 src/Mod/Spreadsheet/App/SheetPy.xml create mode 100644 src/Mod/Spreadsheet/App/SheetPyImp.cpp create mode 100644 src/Mod/Spreadsheet/App/Utils.cpp create mode 100644 src/Mod/Spreadsheet/App/Utils.h create mode 100755 src/Mod/Spreadsheet/App/create_regexps.sh create mode 100644 src/Mod/Spreadsheet/App/genregexps.cpp create mode 100644 src/Mod/Spreadsheet/App/lex.ExpressionParser.c create mode 100644 src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp create mode 100644 src/Mod/Spreadsheet/Gui/AppSpreadsheetGuiPy.cpp create mode 100644 src/Mod/Spreadsheet/Gui/CMakeLists.txt create mode 100644 src/Mod/Spreadsheet/Gui/Command.cpp create mode 100644 src/Mod/Spreadsheet/Gui/PreCompiled.cpp create mode 100644 src/Mod/Spreadsheet/Gui/PreCompiled.h create mode 100644 src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp create mode 100644 src/Mod/Spreadsheet/Gui/PropertiesDialog.h create mode 100644 src/Mod/Spreadsheet/Gui/PropertiesDialog.ui create mode 100644 src/Mod/Spreadsheet/Gui/Resources/Spreadsheet.qrc rename src/Mod/Spreadsheet/{ => Gui}/Resources/icons/Spreadsheet.svg (100%) create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignBottom.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignCenter.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignLeft.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignRight.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignTop.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignVCenter.svg rename src/Mod/Spreadsheet/{ => Gui}/Resources/icons/SpreadsheetController.svg (100%) create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetExport.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetImport.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetMergeCells.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetSplitCell.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleBold.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleItalic.svg create mode 100644 src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleUnderline.svg create mode 100644 src/Mod/Spreadsheet/Gui/Sheet.ui create mode 100644 src/Mod/Spreadsheet/Gui/SheetModel.cpp create mode 100644 src/Mod/Spreadsheet/Gui/SheetModel.h create mode 100644 src/Mod/Spreadsheet/Gui/SheetTableView.cpp create mode 100644 src/Mod/Spreadsheet/Gui/SheetTableView.h create mode 100644 src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp create mode 100644 src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h create mode 100644 src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp create mode 100644 src/Mod/Spreadsheet/Gui/SpreadsheetView.h create mode 100644 src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp create mode 100644 src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.h create mode 100644 src/Mod/Spreadsheet/Gui/Workbench.cpp create mode 100644 src/Mod/Spreadsheet/Gui/Workbench.h create mode 100644 src/Mod/Spreadsheet/Gui/qtcolorpicker.cpp create mode 100644 src/Mod/Spreadsheet/Gui/qtcolorpicker.h delete mode 100644 src/Mod/Spreadsheet/Resources/Spreadsheet.qrc delete mode 100644 src/Mod/Spreadsheet/Spreadsheet.py create mode 100644 src/Mod/Spreadsheet/spreadsheet.dox diff --git a/src/Mod/Spreadsheet/App/AppSpreadsheet.cpp b/src/Mod/Spreadsheet/App/AppSpreadsheet.cpp new file mode 100644 index 0000000000..ff6dc853dd --- /dev/null +++ b/src/Mod/Spreadsheet/App/AppSpreadsheet.cpp @@ -0,0 +1,52 @@ +/*************************************************************************** + * * + * 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. * + * for detail see the LICENCE text file. * + * Jrgen Riegel 2002 * + * Eivind Kvedalen 2015 * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif + +#include +#include "Sheet.h" +#include "Expression.h" + + +/* registration table */ +static struct PyMethodDef Spreadsheet_methods[] = { + {NULL, NULL} /* end of table marker */ +}; + +/* Python entry */ +extern "C" { +void SpreadsheetExport initSpreadsheet() { + (void) Py_InitModule("Spreadsheet", Spreadsheet_methods); /* mod name, table ptr */ + Base::Console().Log("Loading Spreadsheet module... done\n"); + + Spreadsheet::PropertyColumnWidths::init(); + Spreadsheet::PropertyRowHeights::init(); + Spreadsheet::PropertySheet::init(); + + Spreadsheet::Sheet::init(); + Spreadsheet::Expression::init(); + Spreadsheet::UnitExpression::init(); + Spreadsheet::NumberExpression::init(); + Spreadsheet::ConstantExpression::init(); + Spreadsheet::FunctionExpression::init(); + Spreadsheet::OperatorExpression::init(); + Spreadsheet::VariableExpression::init(); + Spreadsheet::ConditionalExpression::init(); + Spreadsheet::StringExpression::init(); + + return; +} + +} // extern "C" diff --git a/src/Mod/Spreadsheet/App/CMakeLists.txt b/src/Mod/Spreadsheet/App/CMakeLists.txt new file mode 100644 index 0000000000..1ca6a6a02d --- /dev/null +++ b/src/Mod/Spreadsheet/App/CMakeLists.txt @@ -0,0 +1,69 @@ +if(WIN32) + add_definitions(-DFCAppSpreadsheet) +endif(WIN32) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${PYTHON_INCLUDE_PATH} + ${Boost_INCLUDE_DIRS} + ${ZLIB_INCLUDE_DIR} + ${XERCESC_INCLUDE_DIR} + ${QT_INCLUDE_DIR} +) + +set(Spreadsheet_LIBS + FreeCADApp +) + +set(Spreadsheet_SRCS + Expression.cpp + Expression.h + Cell.cpp + Cell.h + DisplayUnit.h + PropertySheet.cpp + PropertySheet.h + PropertySheetPy.xml + PropertySheetPyImp.cpp + PropertyColumnWidths.cpp + PropertyColumnWidths.h + PropertyColumnWidthsPy.xml + PropertyColumnWidthsPyImp.cpp + PropertyRowHeights.cpp + PropertyRowHeights.h + PropertyRowHeightsPy.xml + PropertyRowHeightsPyImp.cpp + PreCompiled.cpp + PreCompiled.h + Sheet.cpp + Sheet.h + SheetPy.xml + SheetPyImp.cpp + SheetObserver.cpp + SheetObserver.h + Utils.cpp + Utils.h + Range.h + Range.cpp + AppSpreadsheet.cpp +) + +generate_from_xml(SheetPy) +generate_from_xml(PropertySheetPy) +generate_from_xml(PropertyColumnWidthsPy) +generate_from_xml(PropertyRowHeightsPy) + +add_library(Spreadsheet SHARED ${Spreadsheet_SRCS}) +target_link_libraries(Spreadsheet ${Spreadsheet_LIBS}) + + +fc_target_copy_resource(Spreadsheet + ${CMAKE_SOURCE_DIR}/src/Mod/Spreadsheet + ${CMAKE_BINARY_DIR}/Mod/Spreadsheet + Init.py) + +SET_BIN_DIR(Spreadsheet Spreadsheet /Mod/Spreadsheet) +SET_PYTHON_PREFIX_SUFFIX(Spreadsheet) + +INSTALL(TARGETS Spreadsheet DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/src/Mod/Spreadsheet/App/Cell.cpp b/src/Mod/Spreadsheet/App/Cell.cpp new file mode 100644 index 0000000000..031cf0fba7 --- /dev/null +++ b/src/Mod/Spreadsheet/App/Cell.cpp @@ -0,0 +1,814 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "Cell.h" +#include "Utils.h" +#include +#include +#include +#include "Expression.h" +#include "Sheet.h" +#include + +#ifdef _MSC_VER +#define __func__ __FUNCTION__ +#endif + +using namespace App; +using namespace Spreadsheet; + +const int Cell::EXPRESSION_SET = 1; +const int Cell::ALIGNMENT_SET = 4; +const int Cell::STYLE_SET = 8; +const int Cell::BACKGROUND_COLOR_SET = 0x10; +const int Cell::FOREGROUND_COLOR_SET = 0x20; +const int Cell::DISPLAY_UNIT_SET = 0x40; +const int Cell::COMPUTED_UNIT_SET = 0x80; +const int Cell::ALIAS_SET = 0x100; +const int Cell::SPANS_SET = 0x200; +const int Cell::MARK_SET = 0x40000000; +const int Cell::EXCEPTION_SET = 0x20000000; +const int Cell::PARSE_EXCEPTION_SET = 0x80000000; +const int Cell::RESOLVE_EXCEPTION_SET= 0x01000000; +const int Cell::SPANS_UPDATED = 0x10000000; + +/* Alignment */ +const int Cell::ALIGNMENT_LEFT = 0x01; +const int Cell::ALIGNMENT_HCENTER = 0x02; +const int Cell::ALIGNMENT_RIGHT = 0x04; +const int Cell::ALIGNMENT_HIMPLIED = 0x08; +const int Cell::ALIGNMENT_HORIZONTAL = 0x0f; +const int Cell::ALIGNMENT_TOP = 0x10; +const int Cell::ALIGNMENT_VCENTER = 0x20; +const int Cell::ALIGNMENT_BOTTOM = 0x40; +const int Cell::ALIGNMENT_VIMPLIED = 0x80; +const int Cell::ALIGNMENT_VERTICAL = 0xf0; + +/** + * Construct a CellContent object. + * + * @param _row The row of the cell in the spreadsheet that contains is. + * @param _col The column of the cell in the spreadsheet that contains is. + * @param _owner The spreadsheet that owns this cell. + * + */ + +Cell::Cell(const CellAddress &_address, PropertySheet *_owner) + : address(_address) + , owner(_owner) + , used(0) + , expression(0) + , alignment(ALIGNMENT_HIMPLIED | ALIGNMENT_LEFT | ALIGNMENT_VIMPLIED | ALIGNMENT_VCENTER) + , style() + , foregroundColor(0, 0, 0, 1) + , backgroundColor(1, 1, 1, 1) + , displayUnit() + , computedUnit() + , rowSpan(1) + , colSpan(1) + , anchor() +{ + assert(address.isValid()); +} + +/** + * Destroy a CellContent object. + * + */ + +Cell::Cell(const Cell &other) + : address(other.address) + , owner(other.owner) + , used(other.used) + , expression(other.expression ? other.expression->copy() : 0) + , style(other.style) + , alignment(other.alignment) + , foregroundColor(other.foregroundColor) + , backgroundColor(other.backgroundColor) + , displayUnit(other.displayUnit) + , computedUnit(other.computedUnit) + , colSpan(other.colSpan) + , rowSpan(other.rowSpan) +{ +} + +Cell &Cell::operator =(const Cell &rhs) +{ + PropertySheet::Signaller signaller(*owner); + + used = 0; + address = rhs.address; + owner = rhs.owner; + + setExpression(rhs.expression ? rhs.expression->copy() : 0); + setStyle(rhs.style); + setAlignment(rhs.alignment); + setForeground(rhs.foregroundColor); + setBackground(rhs.backgroundColor); + setDisplayUnit(rhs.displayUnit.stringRep); + setComputedUnit(rhs.computedUnit); + setSpans(rhs.rowSpan, rhs.colSpan); + + return *this; +} + +Cell::~Cell() +{ + if (expression) + delete expression; +} + +/** + * Set the expression tree to \a expr. + * + */ + +void Cell::setExpression(Expression *expr) +{ + PropertySheet::Signaller signaller(*owner); + + /* Remove dependencies */ + owner->removeDependencies(address); + + if (expression) + delete expression; + expression = expr; + setUsed(EXPRESSION_SET, expression != 0); + + /* Update dependencies */ + owner->addDependencies(address); +} + +/** + * Get the expression tree. + * + */ + +const Expression *Cell::getExpression() const +{ + return expression; +} + +/** + * Get string content. + * + */ + +bool Cell::getStringContent(std::string & s) const +{ + if (expression) { + if (freecad_dynamic_cast(expression)) { + s = static_cast(expression)->getText(); + char * end; + errno = 0; + strtod(s.c_str(), &end); + if (!*end && errno == 0) + s = "'" + s; + } + else if (freecad_dynamic_cast(expression)) + s = "=" + expression->toString(); + else if (freecad_dynamic_cast(expression)) + s = expression->toString(); + else + s = "=" + expression->toString(); + + return true; + } + else { + s = ""; + return false; + } +} + +void Cell::setContent(const char * value) +{ + PropertySheet::Signaller signaller(*owner); + Expression * expr = 0; + + setUsed(PARSE_EXCEPTION_SET, false); + if (value != 0) { + if (*value == '=') { + try { + expr = ExpressionParser::parse(owner->sheet(), value + 1); + } + catch (Base::Exception & e) { + QString msg = QString::fromUtf8("ERR: %1").arg(QString::fromUtf8(e.what())); + expr = new StringExpression(owner->sheet(), value); + setUsed(PARSE_EXCEPTION_SET); + } + } + else if (*value == '\'') + expr = new StringExpression(owner->sheet(), value + 1); + else if (*value != '\0') { + char * end; + errno = 0; + double float_value = strtod(value, &end); + if (!*end && errno == 0) + expr = new NumberExpression(owner->sheet(), float_value); + else { + try { + expr = ExpressionParser::parse(owner->sheet(), value); + if (expr) + delete expr->eval(); + } + catch (Base::Exception & e) { + expr = new StringExpression(owner->sheet(), value); + } + } + } + } + + setExpression(expr); +} + +/** + * Set alignment of this cell. Alignment is the or'ed value of + * vertical and horizontal alignment, given by the constants + * defined in the class. + * + */ + +void Cell::setAlignment(int _alignment) +{ + if (_alignment != alignment) { + PropertySheet::Signaller signaller(*owner); + + alignment = _alignment; + setUsed(ALIGNMENT_SET, alignment != (ALIGNMENT_HIMPLIED | ALIGNMENT_LEFT | ALIGNMENT_VIMPLIED | ALIGNMENT_VCENTER)); + } +} + +/** + * Get alignment. + * + */ + +bool Cell::getAlignment(int & _alignment) const +{ + _alignment = alignment; + return isUsed(ALIGNMENT_SET); +} + +/** + * Set style to the given set \a _style. + * + */ + +void Cell::setStyle(const std::set & _style) +{ + if (_style != style) { + PropertySheet::Signaller signaller(*owner); + + style = _style; + setUsed(STYLE_SET, style.size() > 0); + } +} + +/** + * Get the style of the cell. + * + */ + +bool Cell::getStyle(std::set & _style) const +{ + _style = style; + return isUsed(STYLE_SET); +} + +/** + * Set foreground (i.e text) color of the cell to \a color. + * + */ + +void Cell::setForeground(const Color &color) +{ + if (color != foregroundColor) { + PropertySheet::Signaller signaller(*owner); + + foregroundColor = color; + setUsed(FOREGROUND_COLOR_SET, foregroundColor != App::Color(0, 0, 0, 1)); + } +} + +/** + * Get foreground color of the cell. + * + */ + +bool Cell::getForeground(Color &color) const +{ + color = foregroundColor; + return isUsed(FOREGROUND_COLOR_SET); +} + +/** + * Set background color of the cell to \a color. + * + */ + +void Cell::setBackground(const Color &color) +{ + if (color != backgroundColor) { + PropertySheet::Signaller signaller(*owner); + + backgroundColor = color; + setUsed(BACKGROUND_COLOR_SET, backgroundColor != App::Color(1, 1, 1, 1)); + } +} + +/** + * Get the background color of the cell into \a color. + * + * @returns true if the background color was previously set. + * + */ + +bool Cell::getBackground(Color &color) const +{ + color = backgroundColor; + return isUsed(BACKGROUND_COLOR_SET); +} + +/** + * Set the display unit for the cell. + * + */ + +void Cell::setDisplayUnit(const std::string &unit) +{ + DisplayUnit newDisplayUnit; + if (unit.size() > 0) { + std::auto_ptr e(ExpressionParser::parseUnit(owner->sheet(), unit.c_str())); + + newDisplayUnit = DisplayUnit(unit, e->getUnit(), e->getScaler()); + } + + if (newDisplayUnit != displayUnit) { + PropertySheet::Signaller signaller(*owner); + + displayUnit = newDisplayUnit; + setUsed(DISPLAY_UNIT_SET, !displayUnit.isEmpty()); + } +} + +/** + * Get the display unit for the cell into unit. + * + * @returns true if the display unit was previously set. + * + */ + +bool Cell::getDisplayUnit(DisplayUnit &unit) const +{ + unit = displayUnit; + return isUsed(DISPLAY_UNIT_SET); +} + +void Cell::setAlias(const std::string &n) +{ + if (alias != n) { + PropertySheet::Signaller signaller(*owner); + + alias = n; + setUsed(ALIAS_SET, !alias.empty()); + } +} + +bool Cell::getAlias(std::string &n) const +{ + n = alias; + return isUsed(ALIAS_SET); +} + +/** + * Set the computed unit for the cell to \a unit. + * + */ + +void Cell::setComputedUnit(const Base::Unit &unit) +{ + PropertySheet::Signaller signaller(*owner); + + computedUnit = unit; + setUsed(COMPUTED_UNIT_SET, !computedUnit.isEmpty()); +} + +/** + * Get the computed unit into \a unit. + * + * @returns true if the computed unit was previously set. + * + */ + +bool Cell::getComputedUnit(Base::Unit & unit) const +{ + unit = computedUnit; + return isUsed(COMPUTED_UNIT_SET); +} + +/** + * Set the cell's row and column span to \a rows and \a columns. This + * is done when cells are merged. + * + */ + +void Cell::setSpans(int rows, int columns) +{ + if (rows != rowSpan || columns != colSpan) { + PropertySheet::Signaller signaller(*owner); + + rowSpan = rows; + colSpan = columns; + setUsed(SPANS_SET, (rowSpan != 1 || colSpan != 1) ); + setUsed(SPANS_UPDATED); + } +} + +/** + * Get the row and column spans for the cell into \a rows and \a columns. + * + */ + +bool Cell::getSpans(int &rows, int &columns) const +{ + rows = rowSpan; + columns = colSpan; + return isUsed(SPANS_SET); +} + +void Cell::setException(const std::string &e) +{ + exceptionStr = e; + setUsed(EXCEPTION_SET); +} + +void Cell::setParseException(const std::string &e) +{ + exceptionStr = e; + setUsed(PARSE_EXCEPTION_SET); +} + +void Cell::setResolveException(const std::string &e) +{ + exceptionStr = e; + setUsed(RESOLVE_EXCEPTION_SET); +} + +void Cell::clearResolveException() +{ + setUsed(RESOLVE_EXCEPTION_SET, false); +} + +void Cell::clearException() +{ + if (!isUsed(PARSE_EXCEPTION_SET)) + exceptionStr = ""; + setUsed(EXCEPTION_SET, false); +} + +void Cell::clearDirty() +{ + owner->clearDirty(address); +} + +/** + * Move the cell to a new position given by \a _row and \a _col. + * + */ + +void Cell::moveAbsolute(CellAddress newAddress) +{ + address = newAddress; +} + +/** + * Restore cell contents from \a reader. + * + */ + +void Cell::restore(Base::XMLReader &reader) +{ + const char* style = reader.hasAttribute("style") ? reader.getAttribute("style") : 0; + const char* alignment = reader.hasAttribute("alignment") ? reader.getAttribute("alignment") : 0; + const char* content = reader.hasAttribute("content") ? reader.getAttribute("content") : ""; + const char* foregroundColor = reader.hasAttribute("foregroundColor") ? reader.getAttribute("foregroundColor") : 0; + const char* backgroundColor = reader.hasAttribute("backgroundColor") ? reader.getAttribute("backgroundColor") : 0; + const char* displayUnit = reader.hasAttribute("displayUnit") ? reader.getAttribute("displayUnit") : 0; + const char* alias = reader.hasAttribute("alias") ? reader.getAttribute("alias") : 0; + const char* rowSpan = reader.hasAttribute("rowSpan") ? reader.getAttribute("rowSpan") : 0; + const char* colSpan = reader.hasAttribute("colSpan") ? reader.getAttribute("colSpan") : 0; + + // Don't trigger multiple updates below; wait until everything is loaded by calling unfreeze() below. + PropertySheet::Signaller signaller(*owner); + + if (content) { + setContent(content); + } + if (style) { + using namespace boost; + std::set styleSet; + + escaped_list_separator e('\0', '|', '\0'); + std::string line = std::string(style); + tokenizer > tok(line, e); + + for(tokenizer >::iterator i = tok.begin(); i != tok.end();++i) + styleSet.insert(*i); + setStyle(styleSet); + } + if (alignment) { + int alignmentCode = 0; + using namespace boost; + + escaped_list_separator e('\0', '|', '\0'); + std::string line = std::string(alignment); + tokenizer > tok(line, e); + + for(tokenizer >::iterator i = tok.begin(); i != tok.end();++i) + alignmentCode = decodeAlignment(*i, alignmentCode); + + setAlignment(alignmentCode); + } + if (foregroundColor) { + Color color = decodeColor(foregroundColor, Color(0, 0, 0, 1)); + + setForeground(color); + } + if (backgroundColor) { + Color color = decodeColor(backgroundColor, Color(1, 1, 1, 1)); + + setBackground(color); + } + if (displayUnit) + setDisplayUnit(displayUnit); + if (alias) + setAlias(alias); + + if (rowSpan || colSpan) { + int rs = rowSpan ? atoi(rowSpan) : 1; + int cs = colSpan ? atoi(colSpan) : 1; + + setSpans(rs, cs); + } +} + +/** + * Save cell contents into \a writer. + * + */ + +void Cell::save(Base::Writer &writer) const +{ + if (!isUsed()) + return; + + writer.Stream() << writer.ind() << "" << std::endl; +} + +/** + * Update the \a used member variable with mask (bitwise or'ed). + * + */ + +void Cell::setUsed(int mask, bool state) +{ + if (state) + used |= mask; + else + used &= ~mask; + + owner->setDirty(address); +} + +/** + * Determine whether the bits in \a mask are set in the \a used member variable. + * + */ + +bool Cell::isUsed(int mask) const +{ + return (used & mask) == mask; +} + +/** + * Determine if the any of the contents of the cell is set a non-default value. + * + */ + +bool Cell::isUsed() const +{ + return used != 0; +} + +void Cell::visit(ExpressionVisitor &v) +{ + if (expression) + v.visit(expression); +} + +/** + * Decode aligment into its internal value. + * + * @param itemStr Alignment as a string + * @param alignment Current alignment. This is or'ed with the one in \a itemStr. + * + * @returns New alignment. + * + */ + +int Cell::decodeAlignment(const std::string & itemStr, int alignment) +{ + if (itemStr == "himplied") + alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_HIMPLIED; + else if (itemStr == "left") + alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_LEFT; + else if (itemStr == "center") + alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_HCENTER; + else if (itemStr == "right") + alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_RIGHT; + else if (itemStr == "vimplied") + alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_VIMPLIED; + else if (itemStr == "top") + alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_TOP; + else if (itemStr == "vcenter") + alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_VCENTER; + else if (itemStr == "bottom") + alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_BOTTOM; + else + throw Base::Exception("Invalid alignment."); + + return alignment; +} + +/** + * Encode internal alignment value as a string. + * + * @param alignment Alignment as a binary value. + * + * @returns Alignment represented as a string. + * + */ + +std::string Cell::encodeAlignment(int alignment) +{ + std::string s; + + if (alignment & Cell::ALIGNMENT_LEFT) + s += "left"; + if (alignment & Cell::ALIGNMENT_HCENTER) + s += "center"; + if (alignment & Cell::ALIGNMENT_RIGHT) + s += "right"; + if (alignment & Cell::ALIGNMENT_HIMPLIED) + s += "|himplied"; + + if (alignment & Cell::ALIGNMENT_VERTICAL) + s += "|"; + + if (alignment & Cell::ALIGNMENT_TOP) + s += "top"; + if (alignment & Cell::ALIGNMENT_VCENTER) + s += "vcenter"; + if (alignment & Cell::ALIGNMENT_BOTTOM) + s += "bottom"; + if (alignment & Cell::ALIGNMENT_VIMPLIED) + s += "|vimplied"; + + return s; +} + +/** + * Encode \a color as a #rrggbbaa string. + * + * @param color Color to encode. + * + * @returns String with encoded color. + * + */ + +std::string Cell::encodeColor(const Color & color) +{ + std::stringstream tmp; + + tmp << "#" + << std::hex << std::setw(2) << std::setfill('0') << int(color.r * 255.0) + << std::hex << std::setw(2) << std::setfill('0') << int(color.g * 255.0) + << std::hex << std::setw(2) << std::setfill('0') << int(color.b * 255.0) + << std::hex << std::setw(2) << std::setfill('0') << int(color.a * 255.0); + + return tmp.str(); +} + +/** + * Encode set of styles as a string. + * + * @param style Set of string describing the style. + * + * @returns Set encoded as a string. + * + */ + +std::string Cell::encodeStyle(const std::set & style) +{ + std::string s; + std::set::const_iterator j = style.begin(); + std::set::const_iterator j_end = style.end(); + + while (j != j_end) { + s += *j; + ++j; + if (j != j_end) + s += "|"; + } + + return s; +} + +/** + * Decode a string of the format #rrggbb or #rrggbbaa into a Color. + * + * @param color The color to decode. + * @param defaultColor A default color in case the decoding fails. + * + * @returns Decoded color. + * + */ + +Color Cell::decodeColor(const std::string & color, const Color & defaultColor) +{ + if (color.size() == 7 || color.size() == 9) { + Color c; + + if (color[0] != '#') + return defaultColor; + unsigned int value = strtoul(color.c_str() + 1, 0, 16); + + if (color.size() == 7) + value = (value << 8) | 0xff; + + c.setPackedValue(value); + return c; + } + else + return defaultColor; +} + + diff --git a/src/Mod/Spreadsheet/App/Cell.h b/src/Mod/Spreadsheet/App/Cell.h new file mode 100644 index 0000000000..fd82e85b00 --- /dev/null +++ b/src/Mod/Spreadsheet/App/Cell.h @@ -0,0 +1,190 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef CELL_H +#define CELL_H + +#include +#include +#include +#include "DisplayUnit.h" +#include "Utils.h" + +namespace Base { +class Unit; +class XMLReader; +class Writer; +} + +namespace Spreadsheet { + +class PropertySheet; +class Expression; +class DisplayUnit; +class ExpressionVisitor; + +class SpreadsheetExport Cell { + +public: + + Cell(const CellAddress & _address, PropertySheet * _owner); + + Cell(const Cell & other); + + Cell& operator=( const Cell& rhs ); + + ~Cell(); + + const Expression * getExpression() const; + + bool getStringContent(std::string & s) const; + + void setContent(const char * value); + + void setAlignment(int _alignment); + bool getAlignment(int & _alignment) const; + + void setStyle(const std::set & _style); + bool getStyle(std::set & style) const; + + void setForeground(const App::Color &color); + bool getForeground(App::Color &color) const; + + void setBackground(const App::Color &color); + bool getBackground(App::Color &color) const; + + void setDisplayUnit(const std::string & unit); + bool getDisplayUnit(DisplayUnit &unit) const; + + void setAlias(const std::string & n); + bool getAlias(std::string & n ) const; + + void setComputedUnit(const Base::Unit & unit); + bool getComputedUnit(Base::Unit & unit) const; + + void setSpans(int rows, int columns); + bool getSpans(int & rows, int & columns) const; + + void setException(const std::string & e); + + void clearException(); + + void clearDirty(); + + void setParseException(const std::string & e); + + void setResolveException(const std::string &e); + + void clearResolveException(); + + const std::string &getException() const { return exceptionStr; } + + bool hasException() const { return isUsed(EXCEPTION_SET) || isUsed(PARSE_EXCEPTION_SET) || isUsed(RESOLVE_EXCEPTION_SET); } + + void moveAbsolute(CellAddress newAddress); + + void restore(Base::XMLReader &reader); + + void save(Base::Writer &writer) const; + + bool isUsed() const; + + void mark() { setUsed(MARK_SET); } + + bool isMarked() const { return isUsed(MARK_SET); } + + bool spansChanged() const { return isUsed(SPANS_UPDATED); } + + void visit(ExpressionVisitor & v); + + /* Alignment */ + static const int ALIGNMENT_LEFT; + static const int ALIGNMENT_HCENTER; + static const int ALIGNMENT_RIGHT; + static const int ALIGNMENT_HORIZONTAL; + static const int ALIGNMENT_HIMPLIED; + static const int ALIGNMENT_TOP; + static const int ALIGNMENT_VCENTER; + static const int ALIGNMENT_BOTTOM; + static const int ALIGNMENT_VERTICAL; + static const int ALIGNMENT_VIMPLIED; + + /* Static functions */ + static int decodeAlignment(const std::string &itemStr, int alignment); + static std::string encodeAlignment(int alignment); + + static std::string encodeStyle(const std::set &style); + + static std::string encodeColor(const App::Color &color); + static App::Color decodeColor(const std::string &color, const App::Color &defaultColor); + +private: + + //void setExpression(const Expression * expr); + + void setExpression(Expression *expr); + + void setUsed(int mask, bool state = true); + + bool isUsed(int mask) const; + + void freeze(); + + void unfreeze(); + + /* Used */ + static const int EXPRESSION_SET; + static const int ALIGNMENT_SET; + static const int STYLE_SET; + static const int BACKGROUND_COLOR_SET; + static const int FOREGROUND_COLOR_SET; + static const int DISPLAY_UNIT_SET; + static const int COMPUTED_UNIT_SET; + static const int ALIAS_SET; + static const int SPANS_SET; + static const int MARK_SET; + static const int SPANS_UPDATED; + static const int EXCEPTION_SET; + static const int PARSE_EXCEPTION_SET; + static const int RESOLVE_EXCEPTION_SET; + + CellAddress address; + PropertySheet * owner; + + int used; + Expression * expression; + int alignment; + std::set style; + App::Color foregroundColor; + App::Color backgroundColor; + DisplayUnit displayUnit; + std::string alias; + Base::Unit computedUnit; + int rowSpan; + int colSpan; + std::string exceptionStr; + CellAddress anchor; +}; + +} + +#endif // CELL_H diff --git a/src/Mod/Spreadsheet/App/DisplayUnit.h b/src/Mod/Spreadsheet/App/DisplayUnit.h new file mode 100644 index 0000000000..c4e24cbbd8 --- /dev/null +++ b/src/Mod/Spreadsheet/App/DisplayUnit.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef DISPLAYUNIT_H +#define DISPLAYUNIT_H + +#include +#include + +namespace Spreadsheet { + +class DisplayUnit { +public: + + std::string stringRep; + Base::Unit unit; + double scaler; + + DisplayUnit(const std::string _stringRep = "", const Base::Unit _unit = Base::Unit(), double _scaler = 0.0) + : stringRep(_stringRep) + , unit(_unit) + , scaler(_scaler) + { + } + + bool operator==(const DisplayUnit& c) const + { + return c.stringRep == stringRep && c.unit == unit && c.scaler == scaler; + } + + bool operator!=(const DisplayUnit& c) const + { + return !operator==(c); + } + + bool isEmpty() const { return stringRep.size() == 0; } + +}; + +} + +#endif // DISPLAYUNIT_H diff --git a/src/Mod/Spreadsheet/App/Expression.cpp b/src/Mod/Spreadsheet/App/Expression.cpp new file mode 100644 index 0000000000..bdd590f9c0 --- /dev/null +++ b/src/Mod/Spreadsheet/App/Expression.cpp @@ -0,0 +1,1862 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifdef __GNUC__ +# include +#endif + +#include "Base/Exception.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Expression.h" +#include +#include +#include "Utils.h" +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_E +#define M_E 2.71828182845904523536 +#endif +#ifndef DOUBLE_MAX +# define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ +#endif +#ifndef DOUBLE_MIN +# define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ +#endif + +using namespace Base; +using namespace App; +using namespace Spreadsheet; + +Path::Path(const App::DocumentObject * _owner, const std::string & property) + : owner(_owner) + , propertyIndex(-1) + , documentNameSet(false) + , documentObjectNameSet(false) +{ + if (property.size() > 0) + addComponent(Component::SimpleComponent(property)); +} + +bool Path::operator ==(const Path &other) const +{ + if (owner != other.owner) + return false; + if (documentName != other.documentName) + return false; + if (documentObjectName != other.documentObjectName) + return false; + if (components != other.components) + return false; + return true; +} + +bool Path::operator <(const Path &other) const +{ + if (documentName < other.documentName) + return true; + + if (documentName > other.documentName) + return false; + + if (documentObjectName < other.documentObjectName) + return true; + + if (documentObjectName > other.documentObjectName) + return false; + + if (components.size() < other.components.size()) + return true; + + if (components.size() > other.components.size()) + return false; + + for (int i = 0; i < components.size(); ++i) { + if (components[i].component < other.components[i].component) + return true; + if (components[i].component > other.components[i].component) + return false; + if (components[i].type < other.components[i].type) + return true; + if (components[i].type > other.components[i].type) + return false; + if (components[i].type == Component::ARRAY) { + if (components[i].index < other.components[i].index) + return true; + if (components[i].index > other.components[i].index) + return false; + } + else if (components[i].type == Component::MAP) { + if (components[i].key < other.components[i].key) + return true; + if (components[i].key > other.components[i].key) + return false; + } + } + return false; +} + +int Path::numComponents() const +{ + return components.size(); +} + +Path Path::parse(const DocumentObject * docObj, const char *expr) +{ + return Path(); +} + +std::string Path::toString() const +{ + std::stringstream s; + + if (documentNameSet) { + if (getDocumentName().isRealString()) + s << quote(getDocumentName().getString()) << "#"; + else + s << getDocumentName().getString() << "#"; + } + + if (documentObjectNameSet) { + if (getDocumentObjectName().isRealString()) + s << quote(getDocumentObjectName().getString()) << "."; + else + s << getDocumentObjectName().getString() << "."; + } + else if (propertyIndex > 0) + s << components[0].component << "."; + + s << getPropertyName() << getSubPathStr(); + + return s.str(); +} + +std::string Path::getPythonAccessor() const +{ + const Property * prop = getProperty(); + + if (!prop) + throw Exception("Property not found"); + + const DocumentObject * docObj = freecad_dynamic_cast(prop->getContainer()); + + if (!docObj) + throw Exception("Document object not found"); + + const Document * doc = docObj->getDocument(); + + return "App.getDocument('" + + std::string(doc->getName()) + "')." + + docObj->getNameInDocument() + "." + + getPropertyName() + + getSubPathStr(); +} + +void Path::renameDocumentObject(const std::string &oldName, const std::string &newName) +{ + if (documentObjectNameSet && documentObjectName == oldName) { + documentObjectName = newName; + resolve(); + } + else if (propertyIndex == 1 && documentObjectName == oldName) { + components[0].component = newName; + resolve(); + } +} + +void Path::renameDocument(const std::string &oldName, const std::string &newName) +{ + if (documentNameSet && documentName == oldName) { + documentName = newName; + resolve(); + } +} + +std::string Path::getSubPathStr() const +{ + std::stringstream s; + + std::vector::const_iterator i = components.begin() + propertyIndex + 1; + while (i != components.end()) { + s << "." << i->toString(); + ++i; + } + + return s.str(); +} + +Path::Component::Component(const std::string &_component, Path::Component::typeEnum _type, int _index, String _key) + : component(_component) + , type(_type) + , index(_index) + , key(_key) +{ +} + +Path::Component Path::Component::SimpleComponent(const std::string &_component) +{ + return Component(_component); +} + +Path::Component Path::Component::ArrayComponent(const std::string &_component, int _index) +{ + return Component(_component, ARRAY, _index); +} + +Path::Component Path::Component::MapComponent(const std::string &_component, const String & _key) +{ + return Component(_component, MAP, -1, _key); +} + +bool Path::Component::operator ==(const Path::Component &other) const +{ + if (type != other.type) + return false; + + if (component != other.component) + return false; + + switch (type) { + case SIMPLE: + return true; + case ARRAY: + return index == other.index; + case MAP: + return key == other.key; + default: + assert(0); + return false; + } +} + +std::string Path::Component::toString() const +{ + std::stringstream s; + + s << component; + switch (type) { + case Component::SIMPLE: + break; + case Component::MAP: + s << "[" << key.toString() << "]"; + break; + case Component::ARRAY: + s << "[" << index << "]"; + break; + default: + assert(0); + } + + return s.str(); +} + +// +// Expression base-class +// + +TYPESYSTEM_SOURCE_ABSTRACT(Spreadsheet::Expression, Base::BaseClass); + +Expression::Expression(const DocumentObject *_owner) + : owner(_owner) +{ + +} + +Expression::~Expression() +{ +} + +Expression * Expression::parse(const DocumentObject *owner, const std::string &buffer) +{ + return ExpressionParser::parse(owner, buffer.c_str()); +} + +// +// UnitExpression class +// + +TYPESYSTEM_SOURCE(Spreadsheet::UnitExpression, Spreadsheet::Expression); + +UnitExpression::UnitExpression(const DocumentObject *_owner, const Base::Quantity & _quantity, const std::string &_unitStr) + : Expression(_owner) + , quantity(_quantity) + , unitStr(_unitStr) +{ +} + +/** + * Set unit information. + * + * @param _unit A unit object + * @param _unitstr The unit expressed as a string + * @param _scaler Scale factor to convert unit into internal unit. + */ + +void UnitExpression::setUnit(const Quantity &_quantity) +{ + quantity = _quantity; +} + +/** + * Evaulate the expression + * + * @returns A NumberExpression set to 1.0. + */ + +Expression *UnitExpression::eval() const +{ + return new NumberExpression(owner, quantity); +} + +/** + * Simplify the expression. In this case, a NumberExpression is returned, + * as it cannot be simplified any more. + */ + +Expression *UnitExpression::simplify() const +{ + return new NumberExpression(owner, quantity); +} + +/** + * Return a string representation, in this case the unit string. + */ + +/** + * Return a string representation of the expression. + */ + +std::string UnitExpression::toString() const +{ + return unitStr; +} + +/** + * Return a copy of the expression. + */ + +Expression *UnitExpression::copy() const +{ + return new UnitExpression(owner, quantity); +} + +// +// NumberExpression class +// + +TYPESYSTEM_SOURCE(Spreadsheet::NumberExpression, Spreadsheet::Expression); + +NumberExpression::NumberExpression(const DocumentObject *_owner, const Quantity &_quantity) + : UnitExpression(_owner, _quantity) +{ +} + +/** + * Evalute the expression. For NumberExpressions, it is a simply copy(). + */ + +Expression * NumberExpression::eval() const +{ + return copy(); +} + +/** + * Simplify the expression. For NumberExpressions, we return a copy(), as it cannot + * be simplified any more. + */ + +Expression *NumberExpression::simplify() const +{ + return copy(); +} + +/** + * Create and return a copy of the expression. + */ + +Expression *NumberExpression::copy() const +{ + return new NumberExpression(owner, quantity); +} + +/** + * Negate the stored value. + */ + +void NumberExpression::negate() +{ + quantity.setValue(-quantity.getValue()); +} + +std::string NumberExpression::toString() const +{ + std::stringstream s; + s << quantity.getValue(); + + /* Trim of any extra spaces */ + //while (s.size() > 0 && s[s.size() - 1] == ' ') +// s.erase(s.size() - 1); + + return s.str(); +} + +// +// OperatorExpression class +// + +TYPESYSTEM_SOURCE(Spreadsheet::OperatorExpression, Spreadsheet::Expression); + +OperatorExpression::OperatorExpression(const App::DocumentObject *_owner, Expression * _left, Operator _op, Expression * _right) + : UnitExpression(_owner) + , left(_left) + , op(_op) + , right(_right) +{ + +} + +OperatorExpression::~OperatorExpression() +{ + delete left; + delete right; +} + +/** + * Determine whether the expression is touched or not, i.e relies on properties that are touched. + */ + +bool OperatorExpression::isTouched() const +{ + return left->isTouched() || right->isTouched(); +} + +/** + * Evalutate the expression. Returns a new NumberExpression with the result, or throws + * an exception if something is wrong, i.e the expression cannot be evaluated. + */ + +Expression * OperatorExpression::eval() const +{ + std::auto_ptr e1(left->eval()); + NumberExpression * v1; + std::auto_ptr e2(right->eval()); + NumberExpression * v2; + NumberExpression * output; + + v1 = freecad_dynamic_cast(e1.get()); + v2 = freecad_dynamic_cast(e2.get()); + + if (v1 == 0 || v2 == 0) + throw Exception("Invalid expression"); + + switch (op) { + case ADD: + if (v1->getUnit() != v2->getUnit()) + throw Exception("Incompatible units for + operator"); + output = new NumberExpression(owner, v1->getQuantity() + v2->getQuantity()); + break; + case SUB: + if (v1->getUnit() != v2->getUnit()) + throw Exception("Incompatible units for - operator"); + output = new NumberExpression(owner, v1->getQuantity()- v2->getQuantity()); + break; + case MUL: + case UNIT: + output = new NumberExpression(owner, v1->getQuantity() * v2->getQuantity()); + break; + case DIV: + output = new NumberExpression(owner, v1->getQuantity() / v2->getQuantity()); + break; + case POW: { + output = new NumberExpression(owner, v1->getQuantity().pow(v2->getQuantity()) ); + break; + } + case EQ: + if (v1->getUnit() != v2->getUnit()) + throw Exception("Incompatible units for + operator"); + output = new NumberExpression(owner, Quantity(fabs(v1->getValue() - v2->getValue()) < 1e-7)); + break; + case NEQ: + if (v1->getUnit() != v2->getUnit()) + throw Exception("Incompatible units for + operator"); + output = new NumberExpression(owner, Quantity(fabs(v1->getValue() - v2->getValue()) > 1e-7)); + break; + case LT: + if (v1->getUnit() != v2->getUnit()) + throw Exception("Incompatible units for + operator"); + output = new NumberExpression(owner, Quantity(v1->getValue() < v2->getValue())); + break; + case GT: + if (v1->getUnit() != v2->getUnit()) + throw Exception("Incompatible units for + operator"); + output = new NumberExpression(owner, Quantity(v1->getValue() > v2->getValue())); + break; + case LTE: + if (v1->getUnit() != v2->getUnit()) + throw Exception("Incompatible units for + operator"); + output = new NumberExpression(owner, Quantity(v1->getValue() - v2->getValue() < 1e-7)); + break; + case GTE: + if (v1->getUnit() != v2->getUnit()) + throw Exception("Incompatible units for + operator"); + output = new NumberExpression(owner, Quantity(v2->getValue() - v1->getValue()) < 1e-7); + break; + default: + assert(0); + } + + return output; +} + +/** + * Simplify the expression. For OperatorExpressions, we return a NumberExpression if + * both the left and right side can be simplified to NumberExpressions. In this case + * we can calculate the final value of the expression. + * + * @returns Simplified expression. + */ + +Expression *OperatorExpression::simplify() const +{ + Expression * v1 = left->simplify(); + Expression * v2 = right->simplify(); + + // Both arguments reduced to numerics? Then evaluate and return answer + if (freecad_dynamic_cast(v1) && freecad_dynamic_cast(v2)) { + delete v1; + delete v2; + return eval(); + } + else + return new OperatorExpression(owner, v1, op, v2); +} + +/** + * Create a string representation of the expression. + * + * @returns A string representing the expression. + */ + +std::string OperatorExpression::toString() const +{ + std::stringstream s; + + if (left->priority() < priority()) + s << "(" << left->toString() << ")"; + else + s << left->toString(); + + switch (op) { + case ADD: + s << " + "; + break; + case SUB: + s << " - "; + break; + case MUL: + s << " * "; + break; + case DIV: + s << " / "; + break; + case POW: + s << " ^ "; + break; + case EQ: + s << " == "; + break; + case NEQ: + s << " != "; + break; + case LT: + s << " < "; + break; + case GT: + s << " > "; + break; + case LTE: + s << " <= "; + break; + case GTE: + s << " >= "; + break; + case UNIT: + break; + default: + assert(0); + } + + if (right->priority() < priority()) + s << "(" << right->toString() << ")"; + else + s << right->toString(); + + return s.str(); +} + +/** + * A deep copy of the expression. + */ + +Expression *OperatorExpression::copy() const +{ + return new OperatorExpression(owner, left->copy(), op, right->copy()); +} + +/** + * Return the operators priority. This is used to add parentheses where + * needed when creating a string representation of the expression. + * + * @returns The operator's priority. + */ + +int OperatorExpression::priority() const +{ + switch (op) { + case ADD: + return 5; + case SUB: + return 5; + case MUL: + case UNIT: + return 10; + case DIV: + return 10; + case POW: + return 10; + default: + return 0; + } +} + +/** + * Compute the expressions dependencies, i.e the properties it relies on. + * + * @param props A set of strings. Each string contains the name of a property that this expression depends on. + */ + +void OperatorExpression::getDeps(std::set &props) const +{ + left->getDeps(props); + right->getDeps(props); +} + +void OperatorExpression::visit(ExpressionVisitor &v) +{ + if (left) + left->visit(v); + if (right) + right->visit(v); + v.visit(this); +} + +// +// FunctionExpression class. This class handles functions with one or two parameters. +// + +TYPESYSTEM_SOURCE(Spreadsheet::FunctionExpression, Spreadsheet::UnitExpression); + +FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f, std::vector _args) + : UnitExpression(_owner) + , f(_f) + , args(_args) +{ + switch (f) { + case NONE: + throw Exception("Unknown function"); + case MOD: + case ATAN2: + case POW: + if (args.size() != 2) + throw Exception("Invalid number of arguments."); + break; + default: + if (args.size() != 1) + throw Exception("Invalid number of arguments."); + break; + } +} + +FunctionExpression::~FunctionExpression() +{ + std::vector::iterator i = args.begin(); + + while (i != args.end()) { + delete *i; + ++i; + } +} + +/** + * Determinte whether the expressions is considered touched, i.e one or both of its arguments + * are touched. + * + * @return True if touched, false if not. + */ + +bool FunctionExpression::isTouched() const +{ + std::vector::const_iterator i = args.begin(); + + while (i != args.end()) { + if ((*i)->isTouched()) + return true; + ++i; + } + return false; +} + +/** + * Evaluate function. Returns a NumberExpression if evaluation is successfuly. + * Throws an exception if something fails. + * + * @returns A NumberExpression with the result. + */ + +Expression * FunctionExpression::eval() const +{ + switch (f) { + case SUM: + case AVERAGE: + case STDDEV: + case COUNT: + case MIN: + case MAX: + { + RangeExpression * v = freecad_dynamic_cast(args[0]); + Quantity q; + Quantity mean; + Quantity M2; + + int n = 0; + bool first = true; + + if (!v) + throw Exception("Expected range as argument"); + + Range range(v->getRange()); + + do { + Property * p = owner->getPropertyByName(range.address().c_str()); + PropertyQuantity * qp; + PropertyFloat * fp; + Quantity value; + + if (!p) + continue; + + if (qp = freecad_dynamic_cast(p)) + value = qp->getQuantityValue(); + else if (fp = freecad_dynamic_cast(p)) + value = fp->getValue(); + else + throw Exception("Invalid property type for aggregate"); + + if (first) { + q.setUnit(value.getUnit()); + mean.setUnit(value.getUnit()); + M2.setUnit(value.getUnit()); + } + + switch (f) { + case AVERAGE: + n++; + case SUM: + q = q + value; + break; + case STDDEV: { + n++; + + const Quantity delta = value - mean; + mean = mean + delta / n; + M2 = M2 + delta * (value - mean); + break; + } + case COUNT: + q = q + 1; + break; + case MIN: + if (first || value < q) + q = value; + break; + case MAX: + if (first || value > q) + q = value; + break; + } + + first = false; + } while (range.next()); + + switch (f) { + case AVERAGE: + q = q / (double)n; + break; + case STDDEV: + if (n < 2) + q = Quantity(); + else + q = (M2 / (n - 1.0)).pow(Quantity(0.5)); + break; + } + + return new NumberExpression(owner, q); + } + default: + break; + } + + + std::auto_ptr e1(args[0]->eval()); + std::auto_ptr e2(args.size() > 1 ? args[1]->eval() : 0); + NumberExpression * v1 = freecad_dynamic_cast(e1.get()); + NumberExpression * v2 = freecad_dynamic_cast(e2.get()); + double output; + Unit unit; + double scaler = 1; + + if (v1 == 0) + throw Exception("Invalid argument."); + + double value = v1->getValue(); + + /* Check units and arguments */ + switch (f) { + case COS: + case SIN: + case TAN: + if (!(v1->getUnit() == Unit::Angle || v1->getUnit().isEmpty())) + throw Exception("Unit must be either empty or an angle."); + + // Convert value to radians + value *= M_PI / 180.0; + unit = Unit(); + break; + case ACOS: + case ASIN: + case ATAN: + if (!v1->getUnit().isEmpty()) + throw Exception("Unit must be empty."); + unit = Unit::Angle; + scaler = 180.0 / M_PI; + break; + case EXP: + case LOG: + case LOG10: + case SINH: + case TANH: + case COSH: + if (!v1->getUnit().isEmpty()) + throw Exception("Unit must be empty."); + unit = Unit(); + break; + case ABS: + unit = v1->getUnit(); + break; + case SQRT: { + unit = v1->getUnit(); + + // All components of unit must be either zero or dividable by 2 + UnitSignature s = unit.getSignature(); + if ( !((s.Length % 2) == 0) && + ((s.Mass % 2) == 0) && + ((s.Time % 2) == 0) && + ((s.ElectricCurrent % 2) == 0) && + ((s.ThermodynamicTemperature % 2) == 0) && + ((s.AmountOfSubstance % 2) == 0) && + ((s.LuminoseIntensity % 2) == 0) && + ((s.Angle % 2) == 0)) + throw Exception("All dimensions must be even to compute the square root."); + + unit = Unit(s.Length /2, + s.Mass / 2, + s.Time / 2, + s.ElectricCurrent / 2, + s.ThermodynamicTemperature / 2, + s.AmountOfSubstance / 2, + s.LuminoseIntensity / 2, + s.Angle); + break; + } + case ATAN2: + if (v2 == 0) + throw Exception("Invalid second argument."); + + if (v1->getUnit() != v2->getUnit()) + throw Exception("Units must be equal"); + unit = Unit::Angle; + scaler = 180.0 / M_PI; + break; + case MOD: + if (v2 == 0) + throw Exception("Invalid second argument."); + if (!v2->getUnit().isEmpty()) + throw Exception("Second argument must have empty unit."); + unit = v1->getUnit(); + break; + case POW: { + if (v2 == 0) + throw Exception("Invalid second argument."); + + if (!v2->getUnit().isEmpty()) + throw Exception("Exponent is not allowed to have a unit."); + + // Compute new unit for exponentation + double exponent = v2->getValue(); + if (!v1->getUnit().isEmpty()) { + if (exponent - boost::math::round(exponent) < 1e-9) + unit = v1->getUnit().pow(exponent); + else + throw Exception("Exponent must be an integer when used with a unit"); + } + break; + } + default: + assert(0); + } + + /* Compute result */ + switch (f) { + case ACOS: + output = acos(value); + break; + case ASIN: + output = asin(value); + break; + case ATAN: + output = atan(value); + break; + case ABS: + output = fabs(value); + break; + case EXP: + output = exp(value); + break; + case LOG: + output = log(value); + break; + case LOG10: + output = log(value) / log(10.0); + break; + case SIN: + output = sin(value); + break; + case SINH: + output = sinh(value); + break; + case TAN: + output = tan(value); + break; + case TANH: + output = tanh(value); + break; + case SQRT: + output = sqrt(value); + break; + case COS: + output = cos(value); + break; + case COSH: + output = cosh(value); + break; + case MOD: { + output = fmod(value, v2->getValue()); + break; + } + case ATAN2: { + output = atan2(value, v2->getValue()); + break; + } + case POW: { + output = pow(value, v2->getValue()); + break; + } + default: + assert(0); + } + + return new NumberExpression(owner, Quantity(scaler * output, unit)); +} + +/** + * Try to simplify the expression, i.e calculate all constant expressions. + * + * @returns A simplified expression. + */ + +Expression *FunctionExpression::simplify() const +{ + Expression * v1 = args[0]->simplify(); + + // Argument simplified to numeric expression? Then return evaluate and return + if (freecad_dynamic_cast(v1)) { + switch (f) { + case ATAN2: + case MOD: + case POW: + Expression * v2 = args[1]->simplify(); + + if (freecad_dynamic_cast(v2)) { + delete v1; + delete v2; + return eval(); + } + else { + std::vector a; + a.push_back(v1); + a.push_back(v2); + return new FunctionExpression(owner, f, a); + } + } + delete v1; + return eval(); + } + else { + std::vector a; + a.push_back(v1); + return new FunctionExpression(owner, f, a); + } +} + +/** + * Create a string representation of the expression. + * + * @returns A string representing the expression. + */ + +std::string FunctionExpression::toString() const +{ + switch (f) { + case ACOS: + return "acos(" + args[0]->toString() + ")"; + case ASIN: + return "asin(" + args[0]->toString() + ")"; + case ATAN: + return "atan(" + args[0]->toString() + ")"; + case ABS: + return "abs(" + args[0]->toString() + ")"; + case EXP: + return "exp(" + args[0]->toString() + ")"; + case LOG: + return "log(" + args[0]->toString() + ")"; + case LOG10: + return "log10(" + args[0]->toString() + ")"; + case SIN: + return "sin(" + args[0]->toString() + ")"; + case SINH: + return "sinh(" + args[0]->toString() + ")"; + case TAN: + return "tan(" + args[0]->toString() + ")"; + case TANH: + return "tanh(" + args[0]->toString() + ")"; + case SQRT: + return "sqrt(" + args[0]->toString() + ")"; + case COS: + return "cos(" + args[0]->toString() + ")"; + case COSH: + return "cosh(" + args[0]->toString() + ")"; + case MOD: + return "mod(" + args[0]->toString() + ", " + args[1]->toString() + ")"; + case ATAN2: + return "atan2(" + args[0]->toString() + ", " + args[1]->toString() + ")"; + case POW: + return "pow(" + args[0]->toString() + ", " + args[1]->toString() + ")"; + case SUM: + return "sum(" + args[0]->toString() + ")"; + case COUNT: + return "count(" + args[0]->toString() + ")"; + case AVERAGE: + return "average(" + args[0]->toString() + ")"; + case STDDEV: + return "stddev(" + args[0]->toString() + ")"; + case MIN: + return "min(" + args[0]->toString() + ")"; + case MAX: + return "max(" + args[0]->toString() + ")"; + default: + assert(0); + return std::string(); + } +} + +/** + * Create a copy of the expression. + * + * @returns A deep copy of the expression. + */ + +Expression *FunctionExpression::copy() const +{ + std::vector::const_iterator i = args.begin(); + std::vector a; + + while (i != args.end()) { + a.push_back((*i)->copy()); + ++i; + } + return new FunctionExpression(owner, f, a); +} + +/** + * Compute the dependecy set of the expression. The set contains the names + * of all Property objects this expression relies on. + */ + +void FunctionExpression::getDeps(std::set &props) const +{ + std::vector::const_iterator i = args.begin(); + + while (i != args.end()) { + (*i)->getDeps(props); + ++i; + } +} + +void FunctionExpression::visit(ExpressionVisitor &v) +{ + std::vector::const_iterator i = args.begin(); + + while (i != args.end()) { + (*i)->visit(v); + ++i; + } + v.visit(this); +} + +// +// VariableExpression class +// + +TYPESYSTEM_SOURCE(Spreadsheet::VariableExpression, Spreadsheet::UnitExpression); + +VariableExpression::VariableExpression(const DocumentObject *_owner, Path _var) + : UnitExpression(_owner) + , var(_var) +{ +} + +VariableExpression::~VariableExpression() +{ +} + +/** + * Determine if the expression is touched or not, i.e whether the Property object it + * refers to is touched(). + * + * @returns True if the Property object is touched, false if not. + */ + +bool VariableExpression::isTouched() const +{ + try { + return getProperty()->isTouched(); + } + catch (...) { + return false; + } +} + +const App::DocumentObject * Path::getDocumentObject(const App::Document * doc, const std::string & name) const +{ + DocumentObject * o1 = 0; + DocumentObject * o2 = 0; + std::vector docObjects = doc->getObjects(); + + for (std::vector::iterator j = docObjects.begin(); j != docObjects.end(); ++j) { + if (strcmp((*j)->Label.getValue(), name.c_str()) == 0) { + // Found object with matching label + if (o1 != 0) + return 0; + o1 = *j; + } + } + + // No object found with matching label, try using name directly + o2 = doc->getObject(name.c_str()); + + if (o1 == 0 && o2 == 0) // Not found at all + return 0; + else if (o1 == 0) // Found by name + return o2; + else if (o2 == 0) // Found by label + return o1; + else if (o1 == o2) // Found by both name and label, same object + return o1; + else + return 0; // Found by both name and label, two different objects +} + +void Path::resetResolve() +{ + if (!documentNameSet) + documentName = String(); + if (!documentObjectNameSet) + documentObjectName = String(); +} + +void Path::resolve() +{ + const App::Document * doc; + const App::DocumentObject * docObject; + + /* Document name specified? */ + if (getDocumentName().getString().size() > 0) + doc = getDocument(); + else { + setDocumentName(String(owner->getDocument()->Label.getValue())); + doc = owner->getDocument(); + } + + propertyName = ""; + propertyIndex = 0; + if (doc == 0) + return; + + /* Document object name specified? */ + if (getDocumentObjectName().getString().size() > 0) { + docObject = getDocumentObject(doc, getDocumentObjectName().getString()); + if (!docObject) + return; + if (components.size() > 0) { + propertyName = components[0].component; + propertyIndex = 0; + } + else + return; + } + else { + /* Document object name not specified, resolve from path */ + if (components.size() == 1) { + setDocumentObjectName(String(owner->getNameInDocument())); + propertyName = components[0].component; + propertyIndex = 0; + } + else if (components.size() >= 2) { + if (!components[0].isSimple()) + return; + + docObject = getDocumentObject(doc, components[0].component); + + if (docObject) { + setDocumentObjectName(components[0].component); + propertyName = components[1].component; + propertyIndex = 1; + } + else { + setDocumentObjectName(String(owner->getNameInDocument())); + propertyName = components[0].component; + propertyIndex = 0; + } + } + else + return; + } +} + +Document * Path::getDocument() const +{ + App::Document * doc = 0; + const std::vector docs = App::GetApplication().getDocuments(); + + for (std::vector::const_iterator i = docs.begin(); i != docs.end(); ++i) { + if ((*i)->Label.getValue() == getDocumentName().getString()) { + if (doc != 0) + return 0; + doc = *i; + } + } + + return doc; +} + +const Property *Path::getProperty() const +{ + const App::Document * doc = getDocument(); + + if (!doc) + return 0; + + const App::DocumentObject * docObj = getDocumentObject(doc, documentObjectName); + + if (!docObj) + return 0; + + return docObj->getPropertyByName(propertyName.c_str()); +} + +/** + * Find the property this expression referse to. + * + * Unqualified names (i.e the name only without any dots) are resolved in the owning DocumentObjects. + * Qualified names are looked up in the owning Document. It is first looked up by its internal name. + * If not found, the DocumentObjects' labels searched. + * + * If something fails, an exception is thrown. + * + * @returns The Property object if it is derived from either PropertyInteger, PropertyFloat, or PropertyString. + */ + +const Property * VariableExpression::getProperty() const +{ +#ifdef FULL_EXPRESSION_SUPPORT + const Property * prop = docObject->getPropertyByPath(var); +#else + const Property * prop = var.getProperty(); +#endif + if (prop) + return prop; + else + throw Base::Exception("Property not found."); +} + +/** + * Evalute the expression. For a VariableExpression, this means to return the + * value of the referenced Property. Quantities are converted to NumberExpression with unit, + * int and floats are converted to a NumberExpression without unit. Strings properties + * are converted to StringExpression objects. + * + * @returns The result of the evaluation, i.e a new (Number|String)Expression object. + */ + +Expression * VariableExpression::eval() const +{ +#ifdef FULL_EXPRESSION_SUPPORT + const Property * prop = getProperty(); + PropertyContainer * parent = prop->getContainer(); + + if (!parent->isDerivedFrom(App::DocumentObject::getClassTypeId())) + throw Base::Exception("Property must belong to a document object."); + + return static_cast(parent)->getValue(var); +#else + std::string s = "_spreadsheet_temp_ = " + var.getPythonAccessor(); + PyObject * pyvalue = Base::Interpreter().getValue(s.c_str(), "_spreadsheet_temp_"); + Expression * output; + + if (!pyvalue) + throw Base::Exception("Failed to get property value."); + + if (PyInt_Check(pyvalue)) + output = new NumberExpression(owner, PyInt_AsLong(pyvalue)); + else if (PyFloat_Check(pyvalue)) + output = new NumberExpression(owner, PyFloat_AsDouble(pyvalue)); + else if (PyString_Check(pyvalue)) + output = new StringExpression(owner, PyString_AsString(pyvalue)); + else if (PyUnicode_Check(pyvalue)) { + PyObject * s = PyUnicode_AsUTF8String(pyvalue); + + output = new StringExpression(owner, PyString_AsString(s)); + Py_DECREF(s); + } + else if (PyObject_TypeCheck(pyvalue, &QuantityPy::Type)) { + Base::QuantityPy * qp = static_cast(pyvalue); + Base::Quantity * q = qp->getQuantityPtr(); + + output = new NumberExpression(owner, *q); + } + else { + Py_DECREF(pyvalue); + throw Base::Exception("Invalid property type."); + } + + Py_DECREF(pyvalue); + + return output; +#if 0 + + if (prop->isDerivedFrom(PropertyQuantity::getClassTypeId())) { + const PropertyQuantity * value = static_cast(prop); + return new NumberExpression(owner, value->getValue(), value->getUnit()); + } + else if (prop->isDerivedFrom(PropertyFloat::getClassTypeId())) { + const PropertyFloat * value = static_cast(prop); + return new NumberExpression(owner, value->getValue()); + } + else if (prop->isDerivedFrom(PropertyInteger::getClassTypeId())) { + const PropertyInteger * value = static_cast(prop); + return new NumberExpression(owner, value->getValue()); + } + else if (prop->isDerivedFrom(PropertyString::getClassTypeId())) { + const PropertyString * value = static_cast(prop); + return new StringExpression(owner, value->getValue()); + } + + throw Base::Exception("Property is of invalid type (not float)."); +#endif +#endif +} + +/** + * Simplify the expression. Simplification of VariableExpression objects is + * not possible (if it is instantiated it would be an evaluation instead). + * + * @returns A copy of the expression. + */ + +Expression *VariableExpression::simplify() const +{ + return copy(); +} + +/** + * Return a copy of the expression. + */ + +Expression *VariableExpression::copy() const +{ + return new VariableExpression(owner, var); +} + +/** + * Compute the dependecy of the expression. In this case \a props + * is a set of strings, i.e the names of the Property objects, and + * the variable name this expression relies on is inserted into the set. + * Notice that the variable may be unqualified, i.e without any reference + * to the owning object. This must be taken into consideration when using + * the set. + */ + +void VariableExpression::getDeps(std::set &props) const +{ + props.insert(var); +} + +void VariableExpression::resolve() +{ + var.resetResolve(); + var.resolve(); +} + +void VariableExpression::renameDocumentObject(const std::string &oldName, const std::string &newName) +{ + var.renameDocumentObject(oldName, newName); +} + +void VariableExpression::renameDocument(const std::string &oldName, const std::string &newName) +{ + var.renameDocument(oldName, newName); +} + +// +// StringExpression class +// + +TYPESYSTEM_SOURCE(Spreadsheet::StringExpression, Spreadsheet::Expression); + +StringExpression::StringExpression(const DocumentObject *_owner, const std::string &_text) + : Expression(_owner) + , text(_text) +{ +} + +/** + * Evalute the string. For strings, this is a simple copy of the object. + */ + +Expression * StringExpression::eval() const +{ + return copy(); +} + +/** + * Simplify the expression. For strings, this is a simple copy of the object. + */ + +Expression *StringExpression::simplify() const +{ + return copy(); +} + +std::string StringExpression::toString() const +{ + return quote(text); +} + +/** + * Return a copy of the expression. + */ + +Expression *StringExpression::copy() const +{ + return new StringExpression(owner, text); +} + +TYPESYSTEM_SOURCE(Spreadsheet::ConditionalExpression, Spreadsheet::Expression); + +ConditionalExpression::ConditionalExpression(const DocumentObject *_owner, Expression *_condition, Expression *_trueExpr, Expression *_falseExpr) + : Expression(_owner) + , condition(_condition) + , trueExpr(_trueExpr) + , falseExpr(_falseExpr) +{ +} + +ConditionalExpression::~ConditionalExpression() +{ + delete condition; + delete trueExpr; + delete falseExpr; +} + +bool ConditionalExpression::isTouched() const +{ + return condition->isTouched() || trueExpr->isTouched() || falseExpr->isTouched(); +} + +Expression *ConditionalExpression::eval() const +{ + std::auto_ptr e(condition->eval()); + NumberExpression * v = freecad_dynamic_cast(e.get()); + + if (v == 0) + throw Exception("Invalid expression"); + + if (fabs(v->getValue()) > 0.5) + return trueExpr->eval(); + else + return falseExpr->eval(); +} + +Expression *ConditionalExpression::simplify() const +{ + std::auto_ptr e(condition->simplify()); + NumberExpression * v = freecad_dynamic_cast(e.get()); + + if (v == 0) + return new ConditionalExpression(owner, condition->simplify(), trueExpr->simplify(), falseExpr->simplify()); + else { + if (fabs(v->getValue()) > 0.5) + return trueExpr->simplify(); + else + return falseExpr->simplify(); + } +} + +std::string ConditionalExpression::toString() const +{ + return condition->toString() + " ? " + trueExpr->toString() + " : " + falseExpr->toString(); +} + +Expression *ConditionalExpression::copy() const +{ + return new ConditionalExpression(owner, condition->copy(), trueExpr->copy(), falseExpr->copy()); +} + +int ConditionalExpression::priority() const +{ + return 10; +} + +void ConditionalExpression::getDeps(std::set &props) const +{ + condition->getDeps(props); + trueExpr->getDeps(props); + falseExpr->getDeps(props); +} + +void ConditionalExpression::visit(ExpressionVisitor &v) +{ + condition->visit(v); + trueExpr->visit(v); + falseExpr->visit(v); +} + +TYPESYSTEM_SOURCE(Spreadsheet::ConstantExpression, Spreadsheet::NumberExpression); + +ConstantExpression::ConstantExpression(const DocumentObject *_owner, std::string _name, const Quantity & _quantity) + : NumberExpression(_owner, _quantity) + , name(_name) +{ +} + +std::string ConstantExpression::toString() const +{ + return name; +} + +Expression *ConstantExpression::copy() const +{ + return new ConstantExpression(owner, name.c_str(), quantity); +} + +namespace Spreadsheet { + +namespace ExpressionParser { + +/** + * Error function for parser. Throws a generic Base::Exception with the parser error. + */ + +void ExpressionParser_yyerror(char *errorinfo) +{ +} + +/* helper function for tuning number strings with groups in a locale agnostic way... */ +double num_change(char* yytext,char dez_delim,char grp_delim) +{ + double ret_val; + char temp[40]; + int i = 0; + for(char* c=yytext;*c!='\0';c++){ + // skipp group delimiter + if(*c==grp_delim) continue; + // check for a dez delimiter othere then dot + if(*c==dez_delim && dez_delim !='.') + temp[i++] = '.'; + else + temp[i++] = *c; + // check buffor overflow + if (i>39) return 0.0; + } + temp[i] = '\0'; + + ret_val = atof( temp ); + return ret_val; +} + +static Expression * ScanResult = 0; /**< The resulting expression after a successful parsing */ +static const App::DocumentObject * DocumentObject = 0; /**< The DocumentObject that will own the expression */ +static bool unitExpression = false; /**< True if the parsed string is a unit only */ +static bool valueExpression = false; /**< True if the parsed string is a full expression */ +static std::stack labels; /**< Label string primitive */ +static std::map registered_functions; /**< Registerd functions */ + +// show the parser the lexer method +#define yylex ExpressionParserlex +int ExpressionParserlex(void); + +// Parser, defined in ExpressionParser.y +#include "ExpressionParser.tab.c" + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// Scanner, defined in ExpressionParser.l +#include "lex.ExpressionParser.c" +#endif // DOXYGEN_SHOULD_SKIP_THIS +#ifdef _MSC_VER +# define strdup _strdup +#endif + +static void initParser(const App::DocumentObject *owner) +{ + static bool has_registered_functions = false; + + using namespace Spreadsheet::ExpressionParser; + + ScanResult = 0; + Spreadsheet::ExpressionParser::DocumentObject = owner; + labels = std::stack(); + unitExpression = valueExpression = false; + +#ifdef FC_DEBUG + yydebug = 1; +#else + yydebug = 0; +#endif + + if (!has_registered_functions) { + registered_functions["acos"] = FunctionExpression::ACOS; + registered_functions["asin"] = FunctionExpression::ASIN; + registered_functions["atan"] = FunctionExpression::ATAN; + registered_functions["abs"] = FunctionExpression::ABS; + registered_functions["exp"] = FunctionExpression::EXP; + registered_functions["log"] = FunctionExpression::LOG; + registered_functions["log10"] = FunctionExpression::LOG10; + registered_functions["sin"] = FunctionExpression::SIN; + registered_functions["sinh"] = FunctionExpression::SINH; + registered_functions["tan"] = FunctionExpression::TAN; + registered_functions["tanh"] = FunctionExpression::TANH; + registered_functions["sqrt"] = FunctionExpression::SQRT; + registered_functions["cos"] = FunctionExpression::COS; + registered_functions["cosh"] = FunctionExpression::COSH; + registered_functions["atan2"] = FunctionExpression::ATAN2; + registered_functions["mod"] = FunctionExpression::MOD; + registered_functions["pow"] = FunctionExpression::POW; + + // Aggregates + registered_functions["sum"] = FunctionExpression::SUM; + registered_functions["count"] = FunctionExpression::COUNT; + registered_functions["average"] = FunctionExpression::AVERAGE; + registered_functions["stddev"] = FunctionExpression::STDDEV; + registered_functions["min"] = FunctionExpression::MIN; + registered_functions["max"] = FunctionExpression::MAX; + + has_registered_functions = true; + } +} + +} + +std::string Path::String::toString() const +{ + if (isRealString()) + return quote(str); + else + return str; +} + +TYPESYSTEM_SOURCE(Spreadsheet::RangeExpression, Spreadsheet::Expression); + +RangeExpression::RangeExpression(const DocumentObject *_owner, const std::string &begin, const std::string &end) + : Expression(_owner) + , range((begin + ":" + end).c_str()) +{ +} + +bool RangeExpression::isTouched() const +{ + Range i(range); + + do { + Property * prop = owner->getPropertyByName(i.address().c_str()); + + if (prop && prop->isTouched()) + return true; + } while (i.next()); + + return false; +} + +Expression *RangeExpression::eval() const +{ + throw Exception("Range expression cannot be evaluated"); +} + +std::string RangeExpression::toString() const +{ + return range.rangeString(); +} + +Expression *RangeExpression::copy() const +{ + return new RangeExpression(owner, range.fromCellString(), range.toCellString()); +} + +void RangeExpression::getDeps(std::set &props) const +{ + Range i(range); + + do { + props.insert(Path(owner, i.address())); + } while (i.next()); +} + +Expression *RangeExpression::simplify() const +{ + return copy(); +} + +} + +/** + * Parse the expression given by \a buffer, and use \a owner as the owner of the + * returned expression. If the parser fails for some reason, and exception is thrown. + * + * @param owner The DocumentObject that will own the expression. + * @param buffer The sting buffer to parse. + * + * @returns A pointer to an expression. + * + */ + +Expression * Spreadsheet::ExpressionParser::parse(const App::DocumentObject *owner, const char* buffer) +{ + // parse from buffer + ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser::ExpressionParser_scan_string (buffer); + + initParser(owner); + + // run the parser + int result = ExpressionParser::ExpressionParser_yyparse (); + + // free the scan buffer + ExpressionParser::ExpressionParser_delete_buffer (my_string_buffer); + + if (result != 0) + throw Base::Exception("Failed to parse expression."); + + if (ScanResult == 0) + throw Base::Exception("Unknown error in expression"); + + if (valueExpression) + return ScanResult; + else { + delete ScanResult; + throw Expression::Exception("Expression can not evaluate to a value."); + return 0; + } +} + +UnitExpression * ExpressionParser::parseUnit(const App::DocumentObject *owner, const char* buffer) +{ + // parse from buffer + ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser::ExpressionParser_scan_string (buffer); + + initParser(owner); + + // run the parser + int result = ExpressionParser::ExpressionParser_yyparse (); + + // free the scan buffer + ExpressionParser::ExpressionParser_delete_buffer (my_string_buffer); + + if (result != 0) + throw Base::Exception("Failed to parse expression."); + + if (ScanResult == 0) + throw Base::Exception("Unknown error in expression"); + + // Simplify expression + Expression * simplified = ScanResult->simplify(); + delete ScanResult; + + if (unitExpression) { + NumberExpression * num = freecad_dynamic_cast(simplified); + + if (num) { + simplified = new UnitExpression(num->getOwner(), num->getQuantity()); + delete num; + } + return freecad_dynamic_cast(simplified); + } + else { + delete simplified; + throw Expression::Exception("Expression is not a unit."); + return 0; + } +} diff --git a/src/Mod/Spreadsheet/App/Expression.h b/src/Mod/Spreadsheet/App/Expression.h new file mode 100644 index 0000000000..7827cc4512 --- /dev/null +++ b/src/Mod/Spreadsheet/App/Expression.h @@ -0,0 +1,548 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef EXPRESSION_H +#define EXPRESSION_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Spreadsheet { + +class Expression; + +class SpreadsheetExport ExpressionVisitor { +public: + virtual ~ExpressionVisitor() {} + virtual void visit(Expression * e) = 0; +}; + +class SpreadsheetExport Path { + +public: + + class String { + public: + String(const std::string & s = "", bool _isRealString = false) : str(s), isString(_isRealString) { } + + std::string getString() const { return str; } + + operator std::string() const { return str; } + + operator const char *() const { return str.c_str(); } + + bool operator==(const String & other) const { return str == other.str; } + + bool operator!=(const String & other) const { return str != other.str; } + + bool operator>=(const String & other) const { return str >= other.str; } + + bool operator<(const String & other) const { return str < other.str; } + + bool operator>(const String & other) const { return str > other.str; } + + std::string toString() const; + + bool isRealString() const { return isString; } + + std::string str; + bool isString; + }; + + struct SpreadsheetExport Component { + + enum typeEnum { + SIMPLE, + MAP, + ARRAY + } ; + + std::string component; + typeEnum type; + int index; + String key; + bool keyIsString; + + Component(const std::string & _component, typeEnum _type = SIMPLE, int _index = -1, String _key = String()); + + static Component SimpleComponent(const std::string & _component); + + static Component ArrayComponent(const std::string & _component, int _index); + + static Component MapComponent(const std::string & _component, const String &_key); + + bool operator==(const Component & other) const; + + bool isSimple() const { return type == SIMPLE; } + + bool isMap() const { return type == MAP; } + + bool isArray() const { return type == ARRAY; } + + std::string toString() const; + + }; + + Path(const App::DocumentObject * _owner = 0, const std::string & property = std::string()); + + void addComponent(const Component &c) { components.push_back(c); resolve(); } + + template + void addComponents(const C &cs) { components.insert(components.end(), cs.begin(), cs.end()); resolve(); } + + void setDocumentName(const String & name, bool force = false) { documentName = name; documentNameSet = force; } + + const String getDocumentName() const { return documentName; } + + void setDocumentObjectName(const String & name, bool force = false) { documentObjectName = name; documentObjectNameSet = force; } + + const String getDocumentObjectName() const { return documentObjectName; } + + const std::string & getPropertyName() const { return components[propertyIndex].component; } + + const Component & getPropertyComponent(int i) const { assert(i >=0 && i < components.size()); return components[propertyIndex + i]; } + + const std::string & getSubComponent(int i) const { assert(i >= 1); return components[propertyIndex - 1].component; } + + std::string getSubPathStr() const; + + bool operator==(const Path & other) const; + + bool operator!=(const Path & other) const { return !(operator==)(other); } + + bool operator<(const Path &other) const; + + int numComponents() const; + + static Path parse(const App::DocumentObject * _owner, const char * expr); + + virtual std::string toString() const; + + void resolve(); + + void resetResolve(); + + const App::Property *getProperty() const; + + std::string getPythonAccessor() const; + + void renameDocumentObject(const std::string & oldName, const std::string & newName); + + void renameDocument(const std::string &oldName, const std::string &newName); + + App::Document *getDocument() const; + +protected: + + const App::DocumentObject *getDocumentObject(const App::Document *doc, const std::string &name) const; + + const App::DocumentObject * owner; + mutable int propertyIndex; + String documentName; + bool documentNameSet; + String documentObjectName; + bool documentObjectNameSet; + std::string propertyName; + + std::vector components; +}; + +/** + * Base class for expressions. + * + */ + +class SpreadsheetExport Expression : public Base::BaseClass { + TYPESYSTEM_HEADER(); + +public: + + Expression(const App::DocumentObject * _owner); + + virtual ~Expression(); + + virtual bool isTouched() const { return false; } + + virtual Expression * eval() const = 0; + + virtual std::string toString() const = 0; + + static Expression * parse(const App::DocumentObject * owner, const std::string& buffer); + + virtual Expression * copy() const = 0; + + virtual int priority() const { return 0; } + + virtual void getDeps(std::set &props) const { } + + virtual Expression * simplify() const = 0; + + virtual void visit(ExpressionVisitor & v) { v.visit(this); } + + class Exception : public Base::Exception { + public: + Exception(const char *sMessage) : Base::Exception(sMessage) { } + }; + + const App::DocumentObject * getOwner() const { return owner; } + +protected: + const App::DocumentObject * owner; /**< The document object used to access unqualified variables (i.e local scope) */ +}; + +/** + * Part of an expressions that contains a unit. + * + */ + +class SpreadsheetExport UnitExpression : public Expression { + TYPESYSTEM_HEADER(); +public: + UnitExpression(const App::DocumentObject *_owner = 0, const Base::Quantity & _quantity = Base::Quantity(), const std::string & _unitStr = std::string()); + + virtual Expression * eval() const; + + virtual Expression * simplify() const; + + virtual std::string toString() const; + + virtual Expression * copy() const; + + virtual int priority() const { return 10; } + + void setUnit(const Base::Quantity &_quantity); + + double getValue() const { return quantity.getValue(); } + + const Base::Unit & getUnit() const { return quantity.getUnit(); } + + const Base::Quantity & getQuantity() const { return quantity; } + + const std::string getUnitString() const { return unitStr; } + + double getScaler() const { return quantity.getValue(); } + +protected: + Base::Quantity quantity; + std::string unitStr; /**< The unit string from the original parsed string */ +}; + +/** + * Class implementing a number with an optional unit + */ + +class SpreadsheetExport NumberExpression : public UnitExpression { + TYPESYSTEM_HEADER(); +public: + NumberExpression(const App::DocumentObject *_owner = 0, const Base::Quantity & quantity = Base::Quantity()); + + virtual Expression * eval() const; + + virtual Expression * simplify() const; + + virtual Expression * copy() const; + + virtual int priority() const { return 10; } + + void negate(); + + virtual std::string toString() const; + +protected: +}; + +class SpreadsheetExport ConstantExpression : public NumberExpression { + TYPESYSTEM_HEADER(); +public: + ConstantExpression(const App::DocumentObject *_owner = 0, std::string _name = "", const Base::Quantity &_quantity = Base::Quantity()); + + virtual std::string toString() const; + + virtual Expression * copy() const; + + virtual int priority() const { return 10; } + + std::string getName() const { return name; } + +protected: + std::string name; /**< Constant's name */ +}; + + +/** + * Class implementing an infix expression. + * + */ + +class SpreadsheetExport OperatorExpression : public UnitExpression { + TYPESYSTEM_HEADER(); +public: + enum Operator { + NONE, + ADD, + SUB, + MUL, + DIV, + POW, + EQ, + NEQ, + LT, + GT, + LTE, + GTE, + UNIT + }; + OperatorExpression(const App::DocumentObject *_owner = 0, Expression * _left = 0, Operator _op = NONE, Expression * _right = 0); + + virtual ~OperatorExpression(); + + virtual bool isTouched() const; + + virtual Expression * eval() const; + + virtual Expression * simplify() const; + + virtual std::string toString() const; + + virtual Expression * copy() const; + + virtual int priority() const; + + virtual void getDeps(std::set &props) const; + + virtual void visit(ExpressionVisitor & v); + +protected: + Operator op; /**< Operator working on left and right */ + Expression * left; /**< Left operand */ + Expression * right; /**< Right operand */ +}; + +class SpreadsheetExport RangeExpression : public Expression { + TYPESYSTEM_HEADER(); +public: + RangeExpression(const App::DocumentObject * _owner = 0, const std::string & begin = std::string(), const std::string & end = std::string()); + + virtual ~RangeExpression() { } + + virtual bool isTouched() const; + + virtual Expression * eval() const; + + virtual std::string toString() const; + + virtual Expression * copy() const; + + virtual int priority() const { return 0; } + + virtual void getDeps(std::set &props) const; + + virtual Expression * simplify() const; + + Range getRange() const { return range; } + +protected: + Range range; +}; + +class SpreadsheetExport ConditionalExpression : public Expression { + TYPESYSTEM_HEADER(); +public: + ConditionalExpression(const App::DocumentObject *_owner = 0, Expression * _condition = 0,Expression * _trueExpr = 0, Expression * _falseExpr = 0); + + virtual ~ConditionalExpression(); + + virtual bool isTouched() const; + + virtual Expression * eval() const; + + virtual Expression * simplify() const; + + virtual std::string toString() const; + + virtual Expression * copy() const; + + virtual int priority() const; + + virtual void getDeps(std::set &props) const; + + virtual void visit(ExpressionVisitor & v); + +protected: + + Expression * condition; /**< Condition */ + Expression * trueExpr; /**< Expression if abs(condition) is > 0.5 */ + Expression * falseExpr; /**< Expression if abs(condition) is < 0.5 */ +}; + +/** + * Class implementing various functions, e.g sin, cos, etc. + * + */ + +class SpreadsheetExport FunctionExpression : public UnitExpression { + TYPESYSTEM_HEADER(); +public: + enum Function { + NONE, + + // Normal functions taking one or two arguments + ACOS, + ASIN, + ATAN, + ABS, + EXP, + LOG, + LOG10, + SIN, + SINH, + TAN, + TANH, + SQRT, + COS, + COSH, + ATAN2, + MOD, + POW, + + // Aggregates + SUM, + AVERAGE, + STDDEV, + COUNT, + MIN, + MAX + }; + + FunctionExpression(const App::DocumentObject *_owner = 0, Function _f = NONE, std::vector _args = std::vector()); + + virtual ~FunctionExpression(); + + virtual bool isTouched() const; + + virtual Expression * eval() const; + + virtual Expression * simplify() const; + + virtual std::string toString() const; + + virtual Expression * copy() const; + + virtual int priority() const { return 10; } + + virtual void getDeps(std::set &props) const; + + virtual void visit(ExpressionVisitor & v); + +protected: + Function f; /**< Function to execute */ + std::vector args; /** Arguments to function*/ +}; + +/** + * Class implementing a reference to a property. If the name is unqualified, + * the owner of the expression is searched. If it is qualified, the document + * that contains the owning document object is searched for other document + * objects to search. Both labels and internal document names are searched. + * + */ + +class SpreadsheetExport VariableExpression : public UnitExpression { + TYPESYSTEM_HEADER(); +public: + VariableExpression(const App::DocumentObject *_owner = 0, Path _var = Path()); + + ~VariableExpression(); + + virtual bool isTouched() const; + + virtual Expression * eval() const; + + virtual Expression * simplify() const; + + virtual std::string toString() const { return var.toString(); } + + virtual Expression * copy() const; + + virtual int priority() const { return 10; } + + virtual void getDeps(std::set &props) const; + + std::string name() const { return var.getPropertyName(); } + + Path getPath() const { return var; } + + void setName(const std::string & name) { assert(0); } + + void resolve(); + + void renameDocumentObject(const std::string & oldName, const std::string & newName); + + void renameDocument(const std::string &oldName, const std::string &newName); + +protected: + + const App::Property *getProperty() const; + + Path var; /**< Variable name */ +}; + +/** + * Class implementing a string. Used to signal either a genuine string or + * a failed evaluation of an expression. + */ + +class SpreadsheetExport StringExpression : public Expression { + TYPESYSTEM_HEADER(); +public: + StringExpression(const App::DocumentObject *_owner = 0, const std::string & _text = std::string()); + + virtual Expression * eval() const; + + virtual Expression * simplify() const; + + virtual std::string toString() const; + + virtual std::string getText() const { return text; } + + virtual Expression * copy() const; + +protected: + + std::string text; /**< Text string */ +}; + +namespace ExpressionParser { +SpreadsheetExport Expression * parse(const App::DocumentObject *owner, const char *buffer); +SpreadsheetExport UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer); +SpreadsheetExport Path parsePath(const App::DocumentObject *owner, const char* buffer); +} + +} +#endif // EXPRESSION_H diff --git a/src/Mod/Spreadsheet/App/ExpressionParser.l b/src/Mod/Spreadsheet/App/ExpressionParser.l new file mode 100644 index 0000000000..8611f67fab --- /dev/null +++ b/src/Mod/Spreadsheet/App/ExpressionParser.l @@ -0,0 +1,267 @@ +%{ +/* Lexer for the FreeCAD Expression language */ +/* (c) 2010 Juergen Riegel LGPL */ +/* (c) 2015 Eivind Kvedalen LGPL */ + + +/* This disables inclusion of unistd.h, which is not available under Visual C++ + * on Win32. The C++ scanner uses STL streams instead. */ +#define YY_NO_UNISTD_H + +#ifdef _MSC_VER +#define strdup _strdup +#endif + +extern std::stack functions; /**< Function identifier */ + +%} + +/*** Flex Declarations and Options ***/ + +/* change the name of the scanner class. */ +%option prefix="ExpressionParser" + +/* the manual says "somewhat more optimized" */ +%option batch + +%option never-interactive + +/* no support for include files is planned */ +%option noyywrap nounput + +Cc ([\x00-\x1f\x7f]|\xc2[\x80-\x9f]) +Cf (\xc2\xad|\xd8[\x80-\x85\x9c]|\xdb\x9d|\xdc\x8f|\xe1(\xa0\x8e)|\xe2(\x80[\x8b-\x8f\xaa-\xae]|\x81[\xa0-\xa4\xa6-\xaf])|\xef(\xbb\xbf|\xbf[\xb9-\xbb])|\xf0(\x91(\x82\xbd))|\xf3(\xa0(\x80\x81))) +Cn11 (\xcd[\xb8-\xb9]|\xce[\x80-\x83\x8b\x8d\xa2]|\xd4\xb0|\xd5[\x97-\x98\xa0]|\xd6[\x88\x8b-\x8c\x90]|\xd7[\x88-\x8f\xab-\xaf\xb5-\xbf]|\xd8\x9d|\xdc\x8e|\xdd[\x8b-\x8c]|\xde[\xb2-\xbf]|\xdf[\xbb-\xbf]|\xe0(\xa0[\xae-\xaf\xbf]|\xa1[\x9c-\x9d\x9f-\xbf]|\xa2[\x80-\x9f\xb3-\xbf]|\xa3[\x80-\xa3]|\xa6[\x84\x8d-\x8e\x91-\x92\xa9\xb1\xb3-\xb5\xba-\xbb]|\xa7[\x85-\x86\x89-\x8a\x8f-\x96\x98-\x9b\x9e\xa4-\xa5\xbc-\xbf]|\xa8[\x80\x84\x8b-\x8e\x91-\x92\xa9\xb1\xb4\xb7\xba-\xbb\xbd]|\xa9[\x83-\x86\x89-\x8a\x8e-\x90\x92-\x98\x9d\x9f-\xa5\xb6-\xbf]|\xaa[\x80\x84\x8e\x92\xa9\xb1\xb4\xba-\xbb]|\xab[\x86\x8a\x8e-\x8f\x91-\x9f\xa4-\xa5\xb2-\xbf]|\xac[\x80\x84\x8d-\x8e\x91-\x92\xa9\xb1\xb4\xba-\xbb]|\xad[\x85-\x86\x89-\x8a\x8e-\x95\x98-\x9b\x9e\xa4-\xa5\xb8-\xbf]|\xae[\x80-\x81\x84\x8b-\x8d\x91\x96-\x98\x9b\x9d\xa0-\xa2\xa5-\xa7\xab-\xad\xba-\xbd]|\xaf[\x83-\x85\x89\x8e-\x8f\x91-\x96\x98-\xa5\xbb-\xbf]|\xb0[\x84\x8d\x91\xa9\xba-\xbc]|\xb1[\x85\x89\x8e-\x94\x97\x9a-\x9f\xa4-\xa5\xb0-\xb7]|\xb2[\x80\x84\x8d\x91\xa9\xb4\xba-\xbb]|\xb3[\x85\x89\x8e-\x94\x97-\x9d\x9f\xa4-\xa5\xb0\xb3-\xbf]|\xb4[\x80\x84\x8d\x91\xbb-\xbc]|\xb5[\x85\x89\x8f-\x96\x98-\x9f\xa4-\xa5\xb6-\xb8]|\xb6[\x80-\x81\x84\x97-\x99\xb2\xbc\xbe-\xbf]|\xb7[\x87-\x89\x8b-\x8d])) +Cn12 (\xe0(\xb7[\x8e\x95\x97\xa0-\xa5\xb0-\xb1\xb5-\xbf]|\xb8[\x80\xbb-\xbe]|\xb9[\x9c-\xbf]|\xba[\x80\x83\x85-\x86\x89\x8b-\x8c\x8e-\x93\x98\xa0\xa4\xa6\xa8-\xa9\xac\xba\xbe-\xbf]|\xbb[\x85\x87\x8e-\x8f\x9a-\x9b\xa0-\xbf]|\xbd[\x88\xad-\xb0]|\xbe[\x98\xbd]|\xbf[\x8d\x9b-\xbf])|\xe1(\x83[\x86\x88-\x8c\x8e-\x8f]|\x89[\x89\x8e-\x8f\x97\x99\x9e-\x9f]|\x8a[\x89\x8e-\x8f\xb1\xb6-\xb7\xbf]|\x8b[\x81\x86-\x87\x97]|\x8c[\x91\x96-\x97]|\x8d[\x9b-\x9c\xbd-\xbf]|\x8e[\x9a-\x9f]|\x8f[\xb5-\xbf]|\x9a[\x9d-\x9f]|\x9b[\xb9-\xbf]|\x9c[\x8d\x95-\x9f\xb7-\xbf]|\x9d[\x94-\x9f\xad\xb1\xb4-\xbf]|\x9f[\x9e-\x9f\xaa-\xaf\xba-\xbf]|\xa0[\x8f\x9a-\x9f]|\xa1[\xb8-\xbf]|\xa2[\xab-\xaf]|\xa3[\xb6-\xbf]|\xa4[\x9f\xac-\xaf\xbc-\xbf]|\xa5[\x81-\x83\xae-\xaf\xb5-\xbf]|\xa6[\xac-\xaf]|\xa7[\x8a-\x8f\x9b-\x9d]|\xa8[\x9c-\x9d]|\xa9[\x9f\xbd-\xbe]|\xaa[\x8a-\x8f\x9a-\x9f\xae-\xaf\xbf]|\xab[\x80-\xbf]|\xad[\x8c-\x8f\xbd-\xbf]|\xaf[\xb4-\xbb]|\xb0[\xb8-\xba]|\xb1[\x8a-\x8c]|\xb2[\x80-\xbc])) +Cn1 ({Cn11}|{Cn12}) +Cn21 (\xe1(\xb2[\xbd-\xbf]|\xb3[\x88-\x8f\xb7\xba-\xbf]|\xb7[\xb6-\xbb]|\xbc[\x96-\x97\x9e-\x9f]|\xbd[\x86-\x87\x8e-\x8f\x98\x9a\x9c\x9e\xbe-\xbf]|\xbe\xb5|\xbf[\x85\x94-\x95\x9c\xb0-\xb1\xb5\xbf])|\xe2(\x81[\xa5\xb2-\xb3]|\x82[\x8f\x9d-\x9f\xbe-\xbf]|\x83[\x80-\x8f\xb1-\xbf]|\x86[\x8a-\x8f]|\x8f[\xbb-\xbf]|\x90[\xa7-\xbf]|\x91[\x8b-\x9f]|\xad[\xb4-\xb5]|\xae[\x96-\x97\xba-\xbc]|\xaf[\x89\x92-\xbf]|\xb0\xaf|\xb1\x9f|\xb3[\xb4-\xb8]|\xb4[\xa6\xa8-\xac\xae-\xaf]|\xb5[\xa8-\xae\xb1-\xbe]|\xb6[\x97-\x9f\xa7\xaf\xb7\xbf]|\xb7[\x87\x8f\x97\x9f]|\xb9[\x83-\xbf]|\xba\x9a|\xbb[\xb4-\xbf]|\xbf[\x96-\xaf\xbc-\xbf])|\xe3(\x81\x80|\x82[\x97-\x98]|\x84[\x80-\x84\xae-\xb0]|\x86[\x8f\xbb-\xbf]|\x87[\xa4-\xaf]|\x88\x9f|\x8b\xbf)|\xe4(\xb6[\xb6-\xbf])|\xe9(\xbf[\x8d-\xbf])|\xea(\x92[\x8d-\x8f]|\x93[\x87-\x8f]|\x98[\xac-\xbf]|\x9a\x9e|\x9b[\xb8-\xbf]|\x9e[\x8f\xae-\xaf\xb2-\xbf]|\x9f[\x80-\x92])) +Cn22 (\xea(\x9f[\x93-\xb6]|\xa0[\xac-\xaf\xba-\xbf]|\xa1[\xb8-\xbf]|\xa3[\x85-\x8d\x9a-\x9f\xbc-\xbf]|\xa5[\x94-\x9e\xbd-\xbf]|\xa7[\x8e\x9a-\x9d\xbf]|\xa8[\xb7-\xbf]|\xa9[\x8e-\x8f\x9a-\x9b]|\xab[\x83-\x9a\xb7-\xbf]|\xac[\x80\x87-\x88\x8f-\x90\x97-\x9f\xa7\xaf]|\xad[\xa0-\xa3\xa6-\xbf]|\xae[\x80-\xbf]|\xaf[\xae-\xaf\xba-\xbf])|\xed(\x9e[\xa4-\xaf]|\x9f[\x87-\x8a\xbc-\xbf])|\xef(\xa9[\xae-\xaf]|\xab[\x9a-\xbf]|\xac[\x87-\x92\x98-\x9c\xb7\xbd\xbf]|\xad[\x82\x85]|\xaf[\x82-\x92]|\xb5[\x80-\x8f]|\xb6[\x90-\x91]|\xb7[\x88-\xaf\xbe-\xbf]|\xb8[\x9a-\x9f\xae-\xaf]|\xb9[\x93\xa7\xac-\xaf\xb5]|\xbb[\xbd-\xbe]|\xbc\x80|\xbe\xbf|\xbf[\x80-\x81\x88-\x89\x90-\x91\x98-\x99\x9d-\x9f\xa7\xaf-\xb8\xbe-\xbf])|\xf0(\x90(\x80[\x8c\xa7\xbb\xbe]|\x8e\x9e|\xa0[\x89\xb6]|\xa1\x96|\xa8[\x84\x94\x98])|\x91(\x84\xb5|\x88\x92|\x8c[\x84\xa9\xb1\xb4])|\x92(\x91\xaf)|\x96(\xa9\x9f|\xad[\x9a\xa2])|\x9d(\x91\x95|\x92[\x9d\xad\xba\xbc]|\x93\x84|\x94[\x86\x95\x9d\xba\xbf]|\x95[\x85\x91])|\x9e(\xb8[\x84\xa0\xa3\xa8\xb3\xb8\xba]|\xb9[\x88\x8a\x8c\x90\x93\x98\x9a\x9c\x9e\xa0\xa3\xab\xb3\xb8\xbd\xbf]|\xba[\x8a\xa4\xaa])|\x9f(\x83[\x80\x90]|\x84\xaf|\x93\xbf|\x95\xba|\x96\xa4))) +Cn2 ({Cn21}|{Cn22}) +Cn ({Cn1}|{Cn2}) +Co (\xee(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xef(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf])) +Ll1 ([a-z]|\xc2\xb5|\xc3[\x9f-\xb6\xb8-\xbf]|\xc4[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7-\xb8\xba\xbc\xbe]|\xc5[\x80\x82\x84\x86\x88-\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7\xba\xbc\xbe-\xbf]|\xc6[\x80\x83\x85\x88\x8c-\x8d\x92\x95\x99-\x9b\x9e\xa1\xa3\xa5\xa8\xaa-\xab\xad\xb0\xb4\xb6\xb9-\xba\xbd-\xbf]|\xc7[\x86\x89\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c-\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf-\xb0\xb3\xb5\xb9\xbb\xbd\xbf]|\xc8[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3-\xb9\xbc\xbf]|\xc9[\x80\x82\x87\x89\x8b\x8d\x8f-\xbf]|\xca[\x80-\x93\x95-\xaf]|\xcd[\xb1\xb3\xb7\xbb-\xbd]|\xce[\x90\xac-\xbf]|\xcf[\x80-\x8e\x90-\x91\x95-\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf-\xb3\xb5\xb8\xbb-\xbc]|\xd0[\xb0-\xbf]|\xd1[\x80-\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7\xb9\xbb\xbd\xbf]|\xd2[\x81\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7\xb9\xbb\xbd\xbf]|\xd3[\x82\x84\x86\x88\x8a\x8c\x8e-\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7\xb9\xbb\xbd\xbf]|\xd4[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf]|\xd5[\xa1-\xbf]|\xd6[\x80-\x87]|\xe1(\xb4[\x80-\xab]|\xb5[\xab-\xb7\xb9-\xbf]|\xb6[\x80-\x85])) +Ll2 (\xe1(\xb6[\x86-\x9a]|\xb8[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7\xb9\xbb\xbd\xbf]|\xb9[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7\xb9\xbb\xbd\xbf]|\xba[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95-\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7\xb9\xbb\xbd\xbf]|\xbb[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7\xb9\xbb\xbd\xbf]|\xbc[\x80-\x87\x90-\x95\xa0-\xa7\xb0-\xb7]|\xbd[\x80-\x85\x90-\x97\xa0-\xa7\xb0-\xbd]|\xbe[\x80-\x87\x90-\x97\xa0-\xa7\xb0-\xb4\xb6-\xb7\xbe]|\xbf[\x82-\x84\x86-\x87\x90-\x93\x96-\x97\xa0-\xa7\xb2-\xb4\xb6-\xb7])|\xe2(\x84[\x8a\x8e-\x8f\x93\xaf\xb4\xb9\xbc-\xbd]|\x85[\x86-\x89\x8e]|\x86\x84|\xb0[\xb0-\xbf]|\xb1[\x80-\x9e\xa1\xa5-\xa6\xa8\xaa\xac\xb1\xb3-\xb4\xb6-\xbb]|\xb2[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1\xb3\xb5\xb7\xb9\xbb\xbd\xbf]|\xb3[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3-\xa4\xac\xae\xb3]|\xb4[\x80-\xa5\xa7\xad])|\xea(\x99[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad]|\x9a[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b]|\x9c[\xa3\xa5\xa7\xa9\xab\xad\xaf-\xb1\xb3\xb5\xb7\xb9\xbb\xbd\xbf]|\x9d[\x81\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9\xab\xad\xaf\xb1-\xb8\xba\xbc\xbf]|\x9e[\x81\x83\x85\x87\x8c\x8e\x91\x93-\x95\x97\x99\x9b\x9d\x9f\xa1\xa3\xa5\xa7\xa9]|\x9f\xba|\xac[\xb0-\xbf]|\xad[\x80-\x9a\xa4-\xa5])|\xef(\xac[\x80-\x86\x93-\x97]|\xbd[\x81-\x9a])|\xf0(\x9d(\x92\xbb|\x9f\x8b))) +Ll ({Ll1}|{Ll2}) +Lm (\xca[\xb0-\xbf]|\xcb[\x80-\x81\x86-\x91\xa0-\xa4\xac\xae]|\xcd[\xb4\xba]|\xd5\x99|\xd9\x80|\xdb[\xa5-\xa6]|\xdf[\xb4-\xb5\xba]|\xe0(\xa0[\x9a\xa4\xa8]|\xa5\xb1|\xb9\x86|\xbb\x86)|\xe1(\x83\xbc|\x9f\x97|\xa1\x83|\xaa\xa7|\xb1[\xb8-\xbd]|\xb4[\xac-\xbf]|\xb5[\x80-\xaa\xb8]|\xb6[\x9b-\xbf])|\xe2(\x81[\xb1\xbf]|\x82[\x90-\x9c]|\xb1[\xbc-\xbd]|\xb5\xaf|\xb8\xaf)|\xe3(\x80[\x85\xb1-\xb5\xbb]|\x82[\x9d-\x9e]|\x83[\xbc-\xbe])|\xea(\x80\x95|\x93[\xb8-\xbd]|\x98\x8c|\x99\xbf|\x9a[\x9c-\x9d]|\x9c[\x97-\x9f]|\x9d\xb0|\x9e\x88|\x9f[\xb8-\xb9]|\xa7[\x8f\xa6]|\xa9\xb0|\xab[\x9d\xb3-\xb4]|\xad[\x9c-\x9f])|\xef(\xbd\xb0|\xbe[\x9e-\x9f])) +Lo11111 (\xc2[\xaa\xba]|\xc6\xbb|\xc7[\x80-\x83]|\xca\x94|\xd7[\x90-\xaa\xb0-\xb2]|\xd8[\xa0-\xbf]|\xd9[\x81-\x8a\xae-\xaf\xb1-\xbf]|\xda[\x80-\xbf]|\xdb[\x80-\x93\x95\xae-\xaf\xba-\xbc\xbf]|\xdc[\x90\x92-\xaf]|\xdd[\x8d-\xbf]|\xde[\x80-\xa5\xb1]|\xdf[\x8a-\xaa]|\xe0(\xa0[\x80-\x95]|\xa1[\x80-\x98]|\xa2[\xa0-\xb2]|\xa4[\x84-\xb9\xbd]|\xa5[\x90\x98-\xa1\xb2-\xbf]|\xa6[\x80\x85-\x8c\x8f-\x90\x93-\xa8\xaa-\xb0\xb2\xb6-\xb9\xbd]|\xa7[\x8e\x9c-\x9d\x9f-\xa1\xb0-\xb1]|\xa8[\x85-\x8a\x8f-\x90\x93-\xa8\xaa-\xb0\xb2-\xb3\xb5-\xb6\xb8-\xb9]|\xa9[\x99-\x9c\x9e\xb2-\xb4]|\xaa[\x85-\x8d\x8f-\x91\x93-\xa8\xaa-\xb0\xb2-\xb3\xb5-\xb9\xbd]|\xab[\x90\xa0-\xa1]|\xac[\x85-\x8c\x8f-\x90\x93-\xa8\xaa-\xb0\xb2-\xb3\xb5-\xb9\xbd]|\xad[\x9c-\x9d\x9f-\xa1\xb1]|\xae[\x83\x85-\x8a\x8e-\x90\x92-\x95\x99-\x9a\x9c\x9e-\x9f\xa3-\xa4\xa8-\xaa\xae-\xb9]|\xaf\x90|\xb0[\x85-\x8c\x8e-\x90\x92-\xa8\xaa-\xb9\xbd]|\xb1[\x98-\x99\xa0-\xa1]|\xb2[\x85-\x8c\x8e-\x90\x92-\xa8\xaa-\xb3\xb5-\xb9\xbd]|\xb3[\x9e\xa0-\xa1\xb1-\xb2]|\xb4[\x85-\x8c\x8e-\x90\x92-\xba\xbd]|\xb5[\x8e\xa0-\xa1\xba-\xbf]|\xb6[\x85-\x96\x9a-\xb1\xb3-\xbb\xbd]|\xb7[\x80-\x86]|\xb8[\x81-\xb0\xb2-\xb3]|\xb9[\x80-\x85]|\xba[\x81-\x82\x84\x87-\x88\x8a\x8d\x94-\x97\x99-\x9f\xa1-\xa3\xa5\xa7\xaa-\xab\xad-\xb0\xb2-\xb3\xbd]|\xbb[\x80-\x84\x9c-\x9f]|\xbc\x80|\xbd[\x80-\x87\x89-\xac]|\xbe[\x88-\x8c])|\xe1(\x80[\x80-\xaa\xbf]|\x81[\x90-\x95\x9a-\x9d\xa1\xa5-\xa6\xae-\xb0\xb5-\xbf]|\x82[\x80-\x81\x8e]|\x83[\x90-\xba\xbd-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\x8e])) +Lo11112 (\xe1(\x87[\x8f-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\x88\x8a-\x8d\x90-\x96\x98\x9a-\x9d\xa0-\xbf]|\x8a[\x80-\x88\x8a-\x8d\x90-\xb0\xb2-\xb5\xb8-\xbe]|\x8b[\x80\x82-\x85\x88-\x96\x98-\xbf]|\x8c[\x80-\x90\x92-\x95\x98-\xbf]|\x8d[\x80-\x9a]|\x8e[\x80-\x8f\xa0-\xbf]|\x8f[\x80-\xb4]|\x90[\x81-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xac\xaf-\xbf]|\x9a[\x81-\x9a\xa0-\xbf]|\x9b[\x80-\xaa\xb1-\xb8]|\x9c[\x80-\x8c\x8e-\x91\xa0-\xb1]|\x9d[\x80-\x91\xa0-\xac\xae-\xb0]|\x9e[\x80-\xb3]|\x9f\x9c|\xa0[\xa0-\xbf]|\xa1[\x80-\x82\x84-\xb7]|\xa2[\x80-\x89])) +Lo1111 ({Lo11111}|{Lo11112}) +Lo1112 (\xe1(\xa2[\x8a-\xa8\xaa\xb0-\xbf]|\xa3[\x80-\xb5]|\xa4[\x80-\x9e]|\xa5[\x90-\xad\xb0-\xb4]|\xa6[\x80-\xab]|\xa7[\x81-\x87]|\xa8[\x80-\x96\xa0-\xbf]|\xa9[\x80-\x94]|\xac[\x85-\xb3]|\xad[\x85-\x8b]|\xae[\x83-\xa0\xae-\xaf\xba-\xbf]|\xaf[\x80-\xa5]|\xb0[\x80-\xa3]|\xb1[\x8d-\x8f\x9a-\xb7]|\xb3[\xa9-\xac\xae-\xb1\xb5-\xb6])|\xe2(\x84[\xb5-\xb8]|\xb4[\xb0-\xbf]|\xb5[\x80-\xa7]|\xb6[\x80-\x96\xa0-\xa6\xa8-\xae\xb0-\xb6\xb8-\xbe]|\xb7[\x80-\x86\x88-\x8e\x90-\x96\x98-\x9e])|\xe3(\x80[\x86\xbc]|\x81[\x81-\xbf]|\x82[\x80-\x96\x9f\xa1-\xbf]|\x83[\x80-\xba\xbf]|\x84[\x85-\xad\xb1-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\x8e\xa0-\xba]|\x87[\xb0-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\x97])) +Lo111 ({Lo1111}|{Lo1112}) +Lo112 (\xe3(\xad[\x98-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe4(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xb5]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe5(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xa3])) +Lo11 ({Lo111}|{Lo112}) +Lo121 (\xe5(\x88[\xa4-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe6(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xa5])) +Lo122 (\xe6(\xa2[\xa6-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe7(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xa8])) +Lo12 ({Lo121}|{Lo122}) +Lo1 ({Lo11}|{Lo12}) +Lo211 (\xe7(\xbc[\xa9-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe8(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe9(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xaa])) +Lo212 (\xe9(\x96[\xab-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\x8c])|\xea(\x80[\x80-\x94\x96-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\x8c]|\x93[\x90-\xb7]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\x8b\x90-\x9f\xaa-\xab]|\x99\xae|\x9a[\xa0-\xbf]|\x9b[\x80-\xa5]|\x9f[\xb7\xbb-\xbf]|\xa0[\x80-\x81\x83-\x85\x87-\x8a\x8c-\xa2]|\xa1[\x80-\xb3]|\xa2[\x82-\xb3]|\xa3[\xb2-\xb7\xbb]|\xa4[\x8a-\xa5\xb0-\xbf]|\xa5[\x80-\x86\xa0-\xbc]|\xa6[\x84-\xb2]|\xa7[\xa0-\xa4\xa7-\xaf\xba-\xbe]|\xa8[\x80-\xa8]|\xa9[\x80-\x82\x84-\x8b\xa0-\xaf\xb1-\xb6\xba\xbe-\xbf]|\xaa[\x80-\xaf\xb1\xb5-\xb6\xb9-\xbd]|\xab[\x80\x82\x9b-\x9c\xa0-\xaa\xb2]|\xac[\x81-\x86\x89-\x8e\x91-\x96\xa0-\xa6\xa8-\xae]|\xaf[\x80-\xa2]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xeb(\x80[\x80-\xbf]|\x81[\x80-\x8a])) +Lo21 ({Lo211}|{Lo212}) +Lo221 (\xeb(\x81[\x8b-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xec(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\x8c])) +Lo222 (\xec(\x9b[\x8d-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xed(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xa3\xb0-\xbf]|\x9f[\x80-\x86\x8b-\xbb])|\xef(\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xad\xb0-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\x99]|\xac[\x9d\x9f-\xa8\xaa-\xb6\xb8-\xbc\xbe]|\xad[\x80-\x81\x83-\x84\x86-\xbf]|\xae[\x80-\xb1]|\xaf[\x93-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbd]|\xb5[\x90-\xbf]|\xb6[\x80-\x8f\x92-\xbf]|\xb7[\x80-\x87\xb0-\xbb]|\xb9[\xb0-\xb4\xb6-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbc]|\xbd[\xa6-\xaf\xb1-\xbf]|\xbe[\x80-\x9d\xa0-\xbe]|\xbf[\x82-\x87\x8a-\x8f\x92-\x97\x9a-\x9c])|\xf0(\x90(\xa0[\x88\xbc]|\xa8\x80)|\x91(\x85\xb6|\x87\x9a|\x8c\xbd|\x93\x87|\x99\x84|\xa3\xbf)|\x96(\xbd\x90)|\x9e(\xb8[\xa4\xa7\xb9\xbb]|\xb9[\x82\x87\x89\x8b\x94\x97\x99\x9b\x9d\x9f\xa4\xbe]))) +Lo22 ({Lo221}|{Lo222}) +Lo2 ({Lo21}|{Lo22}) +Lo ({Lo1}|{Lo2}) +Lt (\xc7[\x85\x88\x8b\xb2]|\xe1(\xbe[\x88-\x8f\x98-\x9f\xa8-\xaf\xbc]|\xbf[\x8c\xbc])) +Lu1 ([A-Z]|\xc3[\x80-\x96\x98-\x9e]|\xc4[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb9\xbb\xbd\xbf]|\xc5[\x81\x83\x85\x87\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb8-\xb9\xbb\xbd]|\xc6[\x81-\x82\x84\x86-\x87\x89-\x8b\x8e-\x91\x93-\x94\x96-\x98\x9c-\x9d\x9f-\xa0\xa2\xa4\xa6-\xa7\xa9\xac\xae-\xaf\xb1-\xb3\xb5\xb7-\xb8\xbc]|\xc7[\x84\x87\x8a\x8d\x8f\x91\x93\x95\x97\x99\x9b\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb1\xb4\xb6-\xb8\xba\xbc\xbe]|\xc8[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xba-\xbb\xbd-\xbe]|\xc9[\x81\x83-\x86\x88\x8a\x8c\x8e]|\xcd[\xb0\xb2\xb6\xbf]|\xce[\x86\x88-\x8a\x8c\x8e-\x8f\x91-\xa1\xa3-\xab]|\xcf[\x8f\x92-\x94\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb4\xb7\xb9-\xba\xbd-\xbf]|\xd0[\x80-\xaf]|\xd1[\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe]|\xd2[\x80\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe]|\xd3[\x80-\x81\x83\x85\x87\x89\x8b\x8d\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe]|\xd4[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb1-\xbf]|\xd5[\x80-\x96]|\xe1(\x82[\xa0-\xb4])) +Lu2 (\xe1(\x82[\xb5-\xbf]|\x83[\x80-\x85\x87\x8d]|\xb8[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe]|\xb9[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe]|\xba[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe]|\xbb[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe]|\xbc[\x88-\x8f\x98-\x9d\xa8-\xaf\xb8-\xbf]|\xbd[\x88-\x8d\x99\x9b\x9d\x9f\xa8-\xaf]|\xbe[\xb8-\xbb]|\xbf[\x88-\x8b\x98-\x9b\xa8-\xac\xb8-\xbb])|\xe2(\x84[\x82\x87\x8b-\x8d\x90-\x92\x95\x99-\x9d\xa4\xa6\xa8\xaa-\xad\xb0-\xb3\xbe-\xbf]|\x85\x85|\x86\x83|\xb0[\x80-\xae]|\xb1[\xa0\xa2-\xa4\xa7\xa9\xab\xad-\xb0\xb2\xb5\xbe-\xbf]|\xb2[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe]|\xb3[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xab\xad\xb2])|\xea(\x99[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac]|\x9a[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a]|\x9c[\xa2\xa4\xa6\xa8\xaa\xac\xae\xb2\xb4\xb6\xb8\xba\xbc\xbe]|\x9d[\x80\x82\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\xb9\xbb\xbd-\xbe]|\x9e[\x80\x82\x84\x86\x8b\x8d\x90\x92\x96\x98\x9a\x9c\x9e\xa0\xa2\xa4\xa6\xa8\xaa-\xad\xb0-\xb1])|\xef(\xbc[\xa1-\xba])|\xf0(\x9d(\x92[\x9c\xa2]|\x95\x86|\x9f\x8a))) +Lu ({Lu1}|{Lu2}) +Mc (\xe0(\xa4[\x83\xbb\xbe-\xbf]|\xa5[\x80\x89-\x8c\x8e-\x8f]|\xa6[\x82-\x83\xbe-\xbf]|\xa7[\x80\x87-\x88\x8b-\x8c\x97]|\xa8[\x83\xbe-\xbf]|\xa9\x80|\xaa[\x83\xbe-\xbf]|\xab[\x80\x89\x8b-\x8c]|\xac[\x82-\x83\xbe]|\xad[\x80\x87-\x88\x8b-\x8c\x97]|\xae[\xbe-\xbf]|\xaf[\x81-\x82\x86-\x88\x8a-\x8c\x97]|\xb0[\x81-\x83]|\xb1[\x81-\x84]|\xb2[\x82-\x83\xbe]|\xb3[\x80-\x84\x87-\x88\x8a-\x8b\x95-\x96]|\xb4[\x82-\x83\xbe-\xbf]|\xb5[\x80\x86-\x88\x8a-\x8c\x97]|\xb6[\x82-\x83]|\xb7[\x8f-\x91\x98-\x9f\xb2-\xb3]|\xbc[\xbe-\xbf]|\xbd\xbf)|\xe1(\x80[\xab-\xac\xb1\xb8\xbb-\xbc]|\x81[\x96-\x97\xa2-\xa4\xa7-\xad]|\x82[\x83-\x84\x87-\x8c\x8f\x9a-\x9c]|\x9e[\xb6\xbe-\xbf]|\x9f[\x80-\x85\x87-\x88]|\xa4[\xa3-\xa6\xa9-\xab\xb0-\xb1\xb3-\xb8]|\xa6[\xb0-\xbf]|\xa7[\x80\x88-\x89]|\xa8[\x99-\x9a]|\xa9[\x95\x97\xa1\xa3-\xa4\xad-\xb2]|\xac[\x84\xb5\xbb\xbd-\xbf]|\xad[\x80-\x81\x83-\x84]|\xae[\x82\xa1\xa6-\xa7\xaa]|\xaf[\xa7\xaa-\xac\xae\xb2-\xb3]|\xb0[\xa4-\xab\xb4-\xb5]|\xb3[\xa1\xb2-\xb3])|\xe3(\x80[\xae-\xaf])|\xea(\xa0[\xa3-\xa4\xa7]|\xa2[\x80-\x81\xb4-\xbf]|\xa3[\x80-\x83]|\xa5[\x92-\x93]|\xa6[\x83\xb4-\xb5\xba-\xbb\xbd-\xbf]|\xa7\x80|\xa8[\xaf-\xb0\xb3-\xb4]|\xa9[\x8d\xbb\xbd]|\xab[\xab\xae-\xaf\xb5]|\xaf[\xa3-\xa4\xa6-\xa7\xa9-\xaa\xac])|\xf0(\x91(\x80[\x80\x82]|\x82\x82|\x84\xac|\x86\x82|\x88\xb5|\x8d\x97|\x92\xb9|\x93\x81|\x96\xbe|\x98\xbe|\x9a[\xac\xb6]))) +Me (\xd2[\x88-\x89]|\xe1(\xaa\xbe)|\xe2(\x83[\x9d-\xa0\xa2-\xa4])|\xea(\x99[\xb0-\xb2])) +Mn1 (\xcc[\x80-\xbf]|\xcd[\x80-\xaf]|\xd2[\x83-\x87]|\xd6[\x91-\xbd\xbf]|\xd7[\x81-\x82\x84-\x85\x87]|\xd8[\x90-\x9a]|\xd9[\x8b-\x9f\xb0]|\xdb[\x96-\x9c\x9f-\xa4\xa7-\xa8\xaa-\xad]|\xdc[\x91\xb0-\xbf]|\xdd[\x80-\x8a]|\xde[\xa6-\xb0]|\xdf[\xab-\xb3]|\xe0(\xa0[\x96-\x99\x9b-\xa3\xa5-\xa7\xa9-\xad]|\xa1[\x99-\x9b]|\xa3[\xa4-\xbf]|\xa4[\x80-\x82\xba\xbc]|\xa5[\x81-\x88\x8d\x91-\x97\xa2-\xa3]|\xa6[\x81\xbc]|\xa7[\x81-\x84\x8d\xa2-\xa3]|\xa8[\x81-\x82\xbc]|\xa9[\x81-\x82\x87-\x88\x8b-\x8d\x91\xb0-\xb1\xb5]|\xaa[\x81-\x82\xbc]|\xab[\x81-\x85\x87-\x88\x8d\xa2-\xa3]|\xac[\x81\xbc\xbf]|\xad[\x81-\x84\x8d\x96\xa2-\xa3]|\xae\x82|\xaf[\x80\x8d]|\xb0[\x80\xbe-\xbf]|\xb1[\x80\x86-\x88\x8a-\x8d\x95-\x96\xa2-\xa3]|\xb2[\x81\xbc\xbf]|\xb3[\x86\x8c-\x8d\xa2-\xa3]|\xb4\x81|\xb5[\x81-\x84\x8d\xa2-\xa3]|\xb7[\x8a\x92-\x94\x96]|\xb8[\xb1\xb4-\xba]|\xb9[\x87-\x8e]|\xba[\xb1\xb4-\xb9\xbb-\xbc]|\xbb[\x88-\x8d]|\xbc[\x98-\x99\xb5\xb7\xb9]|\xbd[\xb1-\xbe]|\xbe[\x80-\x84\x86-\x87\x8d-\x97\x99-\x9a])) +Mn2 (\xe0(\xbe[\x9b-\xbc]|\xbf\x86)|\xe1(\x80[\xad-\xb0\xb2-\xb7\xb9-\xba\xbd-\xbe]|\x81[\x98-\x99\x9e-\xa0\xb1-\xb4]|\x82[\x82\x85-\x86\x8d\x9d]|\x8d[\x9d-\x9f]|\x9c[\x92-\x94\xb2-\xb4]|\x9d[\x92-\x93\xb2-\xb3]|\x9e[\xb4-\xb5\xb7-\xbd]|\x9f[\x86\x89-\x93\x9d]|\xa0[\x8b-\x8d]|\xa2\xa9|\xa4[\xa0-\xa2\xa7-\xa8\xb2\xb9-\xbb]|\xa8[\x97-\x98\x9b]|\xa9[\x96\x98-\x9e\xa0\xa2\xa5-\xac\xb3-\xbc\xbf]|\xaa[\xb0-\xbd]|\xac[\x80-\x83\xb4\xb6-\xba\xbc]|\xad[\x82\xab-\xb3]|\xae[\x80-\x81\xa2-\xa5\xa8-\xa9\xab-\xad]|\xaf[\xa6\xa8-\xa9\xad\xaf-\xb1]|\xb0[\xac-\xb3\xb6-\xb7]|\xb3[\x90-\x92\x94-\xa0\xa2-\xa8\xad\xb4\xb8-\xb9]|\xb7[\x80-\xb5\xbc-\xbf])|\xe2(\x83[\x90-\x9c\xa1\xa5-\xb0]|\xb3[\xaf-\xb1]|\xb5\xbf|\xb7[\xa0-\xbf])|\xe3(\x80[\xaa-\xad]|\x82[\x99-\x9a])|\xea(\x99[\xaf\xb4-\xbd]|\x9a\x9f|\x9b[\xb0-\xb1]|\xa0[\x82\x86\x8b\xa5-\xa6]|\xa3[\x84\xa0-\xb1]|\xa4[\xa6-\xad]|\xa5[\x87-\x91]|\xa6[\x80-\x82\xb3\xb6-\xb9\xbc]|\xa7\xa5|\xa8[\xa9-\xae\xb1-\xb2\xb5-\xb6]|\xa9[\x83\x8c\xbc]|\xaa[\xb0\xb2-\xb4\xb7-\xb8\xbe-\xbf]|\xab[\x81\xac-\xad\xb6]|\xaf[\xa5\xa8\xad])|\xef(\xac\x9e|\xb8[\x80-\x8f\xa0-\xad])|\xf0(\x90(\x87\xbd|\x8b\xa0|\xa8\xbf)|\x91(\x80\x81|\x85\xb3|\x88\xb4|\x8b\x9f|\x8c[\x81\xbc]|\x8d\x80|\x92\xba|\x98\xbd|\x9a[\xab\xad\xb7]))) +Mn ({Mn1}|{Mn2}) +Nd ([0-9]|\xd9[\xa0-\xa9]|\xdb[\xb0-\xb9]|\xdf[\x80-\x89]|\xe0(\xa5[\xa6-\xaf]|\xa7[\xa6-\xaf]|\xa9[\xa6-\xaf]|\xab[\xa6-\xaf]|\xad[\xa6-\xaf]|\xaf[\xa6-\xaf]|\xb1[\xa6-\xaf]|\xb3[\xa6-\xaf]|\xb5[\xa6-\xaf]|\xb7[\xa6-\xaf]|\xb9[\x90-\x99]|\xbb[\x90-\x99]|\xbc[\xa0-\xa9])|\xe1(\x81[\x80-\x89]|\x82[\x90-\x99]|\x9f[\xa0-\xa9]|\xa0[\x90-\x99]|\xa5[\x86-\x8f]|\xa7[\x90-\x99]|\xaa[\x80-\x89\x90-\x99]|\xad[\x90-\x99]|\xae[\xb0-\xb9]|\xb1[\x80-\x89\x90-\x99])|\xea(\x98[\xa0-\xa9]|\xa3[\x90-\x99]|\xa4[\x80-\x89]|\xa7[\x90-\x99\xb0-\xb9]|\xa9[\x90-\x99]|\xaf[\xb0-\xb9])|\xef(\xbc[\x90-\x99])) +Nl (\xe1(\x9b[\xae-\xb0])|\xe2(\x85[\xa0-\xbf]|\x86[\x80-\x82\x85-\x88])|\xe3(\x80[\x87\xa1-\xa9\xb8-\xba])|\xea(\x9b[\xa6-\xaf])|\xf0(\x90(\x8d[\x81\x8a]))) +No (\xc2[\xb2-\xb3\xb9\xbc-\xbe]|\xe0(\xa7[\xb4-\xb9]|\xad[\xb2-\xb7]|\xaf[\xb0-\xb2]|\xb1[\xb8-\xbe]|\xb5[\xb0-\xb5]|\xbc[\xaa-\xb3])|\xe1(\x8d[\xa9-\xbc]|\x9f[\xb0-\xb9]|\xa7\x9a)|\xe2(\x81[\xb0\xb4-\xb9]|\x82[\x80-\x89]|\x85[\x90-\x9f]|\x86\x89|\x91[\xa0-\xbf]|\x92[\x80-\x9b]|\x93[\xaa-\xbf]|\x9d[\xb6-\xbf]|\x9e[\x80-\x93]|\xb3\xbd)|\xe3(\x86[\x92-\x95]|\x88[\xa0-\xa9]|\x89[\x88-\x8f\x91-\x9f]|\x8a[\x80-\x89\xb1-\xbf])|\xea(\xa0[\xb0-\xb5])) +Pc (_|\xe2(\x80\xbf|\x81[\x80\x94])|\xef(\xb8[\xb3-\xb4]|\xb9[\x8d-\x8f]|\xbc\xbf)) +Pd (-|\xd6[\x8a\xbe]|\xe1(\x90\x80|\xa0\x86)|\xe2(\x80[\x90-\x95]|\xb8[\x97\x9a\xba-\xbb]|\xb9\x80)|\xe3(\x80[\x9c\xb0]|\x82\xa0)|\xef(\xb8[\xb1-\xb2]|\xb9[\x98\xa3]|\xbc\x8d)) +Pe ([\)\]\}]|\xe0(\xbc[\xbb\xbd])|\xe1(\x9a\x9c)|\xe2(\x81[\x86\xbe]|\x82\x8e|\x8c[\x89\x8b\xaa]|\x9d[\xa9\xab\xad\xaf\xb1\xb3\xb5]|\x9f[\x86\xa7\xa9\xab\xad\xaf]|\xa6[\x84\x86\x88\x8a\x8c\x8e\x90\x92\x94\x96\x98]|\xa7[\x99\x9b\xbd]|\xb8[\xa3\xa5\xa7\xa9])|\xe3(\x80[\x89\x8b\x8d\x8f\x91\x95\x97\x99\x9b\x9e-\x9f])|\xef(\xb4\xbe|\xb8[\x98\xb6\xb8\xba\xbc\xbe]|\xb9[\x80\x82\x84\x88\x9a\x9c\x9e]|\xbc[\x89\xbd]|\xbd[\x9d\xa0\xa3])) +Pf (\xc2\xbb|\xe2(\x80[\x99\x9d\xba]|\xb8[\x83\x85\x8a\x8d\x9d\xa1])) +Pi (\xc2\xab|\xe2(\x80[\x98\x9b-\x9c\x9f\xb9]|\xb8[\x82\x84\x89\x8c\x9c\xa0])) +Po ([!-\#%-\'\*,\.-\/\:-;\?-@\\]|\xc2[\xa1\xa7\xb6-\xb7\xbf]|\xcd\xbe|\xce\x87|\xd5[\x9a-\x9f]|\xd6\x89|\xd7[\x80\x83\x86\xb3-\xb4]|\xd8[\x89-\x8a\x8c-\x8d\x9b\x9e-\x9f]|\xd9[\xaa-\xad]|\xdb\x94|\xdc[\x80-\x8d]|\xdf[\xb7-\xb9]|\xe0(\xa0[\xb0-\xbe]|\xa1\x9e|\xa5[\xa4-\xa5\xb0]|\xab\xb0|\xb7\xb4|\xb9[\x8f\x9a-\x9b]|\xbc[\x84-\x92\x94]|\xbe\x85|\xbf[\x90-\x94\x99-\x9a])|\xe1(\x81[\x8a-\x8f]|\x83\xbb|\x8d[\xa0-\xa8]|\x99[\xad-\xae]|\x9b[\xab-\xad]|\x9c[\xb5-\xb6]|\x9f[\x94-\x96\x98-\x9a]|\xa0[\x80-\x85\x87-\x8a]|\xa5[\x84-\x85]|\xa8[\x9e-\x9f]|\xaa[\xa0-\xa6\xa8-\xad]|\xad[\x9a-\xa0]|\xaf[\xbc-\xbf]|\xb0[\xbb-\xbf]|\xb1[\xbe-\xbf]|\xb3[\x80-\x87\x93])|\xe2(\x80[\x96-\x97\xa0-\xa7\xb0-\xb8\xbb-\xbe]|\x81[\x81-\x83\x87-\x91\x93\x95-\x9e]|\xb3[\xb9-\xbc\xbe-\xbf]|\xb5\xb0|\xb8[\x80-\x81\x86-\x88\x8b\x8e-\x96\x98-\x99\x9b\x9e-\x9f\xaa-\xae\xb0-\xb9\xbc-\xbf]|\xb9\x81)|\xe3(\x80[\x81-\x83\xbd]|\x83\xbb)|\xea(\x93[\xbe-\xbf]|\x98[\x8d-\x8f]|\x99[\xb3\xbe]|\x9b[\xb2-\xb7]|\xa1[\xb4-\xb7]|\xa3[\x8e-\x8f\xb8-\xba]|\xa4[\xae-\xaf]|\xa5\x9f|\xa7[\x81-\x8d\x9e-\x9f]|\xa9[\x9c-\x9f]|\xab[\x9e-\x9f\xb0-\xb1]|\xaf\xab)|\xef(\xb8[\x90-\x96\x99\xb0]|\xb9[\x85-\x86\x89-\x8c\x90-\x92\x94-\x97\x9f-\xa1\xa8\xaa-\xab]|\xbc[\x81-\x83\x85-\x87\x8a\x8c\x8e-\x8f\x9a-\x9b\x9f-\xa0\xbc]|\xbd[\xa1\xa4-\xa5])|\xf0(\x90(\x8e\x9f|\x8f\x90|\x95\xaf|\xa1\x97|\xa4[\x9f\xbf]|\xa9\xbf)|\x91(\x87\x8d|\x93\x86)|\x96(\xab\xb5|\xad\x84)|\x9b(\xb2\x9f))) +Ps ([\(\[\{]|\xe0(\xbc[\xba\xbc])|\xe1(\x9a\x9b)|\xe2(\x80[\x9a\x9e]|\x81[\x85\xbd]|\x82\x8d|\x8c[\x88\x8a\xa9]|\x9d[\xa8\xaa\xac\xae\xb0\xb2\xb4]|\x9f[\x85\xa6\xa8\xaa\xac\xae]|\xa6[\x83\x85\x87\x89\x8b\x8d\x8f\x91\x93\x95\x97]|\xa7[\x98\x9a\xbc]|\xb8[\xa2\xa4\xa6\xa8]|\xb9\x82)|\xe3(\x80[\x88\x8a\x8c\x8e\x90\x94\x96\x98\x9a\x9d])|\xef(\xb4\xbf|\xb8[\x97\xb5\xb7\xb9\xbb\xbd\xbf]|\xb9[\x81\x83\x87\x99\x9b\x9d]|\xbc[\x88\xbb]|\xbd[\x9b\x9f\xa2])) +Sc ($|\xc2[\xa2-\xa5]|\xd6\x8f|\xd8\x8b|\xe0(\xa7[\xb2-\xb3\xbb]|\xab\xb1|\xaf\xb9|\xb8\xbf)|\xe1(\x9f\x9b)|\xe2(\x82[\xa0-\xbd])|\xea(\xa0\xb8)|\xef(\xb7\xbc|\xb9\xa9|\xbc\x84|\xbf[\xa0-\xa1\xa5-\xa6])) +Sk ([\^`]|\xc2[\xa8\xaf\xb4\xb8]|\xcb[\x82-\x85\x92-\x9f\xa5-\xab\xad\xaf-\xbf]|\xcd\xb5|\xce[\x84-\x85]|\xe1(\xbe[\xbd\xbf]|\xbf[\x80-\x81\x8d-\x8f\x9d-\x9f\xad-\xaf\xbd-\xbe])|\xe3(\x82[\x9b-\x9c])|\xea(\x9c[\x80-\x96\xa0-\xa1]|\x9e[\x89-\x8a]|\xad\x9b)|\xef(\xae[\xb2-\xbf]|\xaf[\x80-\x81]|\xbc\xbe|\xbd\x80|\xbf\xa3)) +Sm ([\+<->\|~]|\xc2[\xac\xb1]|\xc3[\x97\xb7]|\xcf\xb6|\xd8[\x86-\x88]|\xe2(\x81[\x84\x92\xba-\xbc]|\x82[\x8a-\x8c]|\x84\x98|\x85[\x80-\x84\x8b]|\x86[\x90-\x94\x9a-\x9b\xa0\xa3\xa6\xae]|\x87[\x8e-\x8f\x92\x94\xb4-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\xa0-\xa1]|\x8d\xbc|\x8e[\x9b-\xb3]|\x8f[\x9c-\xa1]|\x96\xb7|\x97[\x81\xb8-\xbf]|\x99\xaf|\x9f[\x80-\x84\x87-\xa5\xb0-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\x82\x99-\xbf]|\xa7[\x80-\x97\x9c-\xbb\xbe-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\xb0-\xbf]|\xad[\x80-\x84\x87-\x8c])|\xef(\xac\xa9|\xb9[\xa2\xa4-\xa6]|\xbc[\x8b\x9c-\x9e]|\xbd[\x9c\x9e]|\xbf[\xa2\xa9-\xac])|\xf0(\x9d(\x9b[\x81\x9b\xbb]|\x9c[\x95\xb5]|\x9d[\x8f\xaf]|\x9e[\x89\xa9]|\x9f\x83))) +So (\xc2[\xa6\xa9\xae\xb0]|\xd2\x82|\xd6[\x8d-\x8e]|\xd8[\x8e-\x8f]|\xdb[\x9e\xa9\xbd-\xbe]|\xdf\xb6|\xe0(\xa7\xba|\xad\xb0|\xaf[\xb3-\xb8\xba]|\xb1\xbf|\xb5\xb9|\xbc[\x81-\x83\x93\x95-\x97\x9a-\x9f\xb4\xb6\xb8]|\xbe[\xbe-\xbf]|\xbf[\x80-\x85\x87-\x8c\x8e-\x8f\x95-\x98])|\xe1(\x82[\x9e-\x9f]|\x8e[\x90-\x99]|\xa5\x80|\xa7[\x9e-\xbf]|\xad[\xa1-\xaa\xb4-\xbc])|\xe2(\x84[\x80-\x81\x83-\x86\x88-\x89\x94\x96-\x97\x9e-\xa3\xa5\xa7\xa9\xae\xba-\xbb]|\x85[\x8a\x8c-\x8d\x8f]|\x86[\x95-\x99\x9c-\x9f\xa1-\xa2\xa4-\xa5\xa7-\xad\xaf-\xbf]|\x87[\x80-\x8d\x90-\x91\x93\x95-\xb3]|\x8c[\x80-\x87\x8c-\x9f\xa2-\xa8\xab-\xbf]|\x8d[\x80-\xbb\xbd-\xbf]|\x8e[\x80-\x9a\xb4-\xbf]|\x8f[\x80-\x9b\xa2-\xba]|\x90[\x80-\xa6]|\x91[\x80-\x8a]|\x92[\x9c-\xbf]|\x93[\x80-\xa9]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xb6\xb8-\xbf]|\x97[\x80\x82-\xb7]|\x98[\x80-\xbf]|\x99[\x80-\xae\xb0-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xa7]|\x9e[\x94-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xac[\x80-\xaf]|\xad[\x85-\x86\x8d-\xb3\xb6-\xbf]|\xae[\x80-\x95\x98-\xb9\xbd-\xbf]|\xaf[\x80-\x88\x8a-\x91]|\xb3[\xa5-\xaa]|\xba[\x80-\x99\x9b-\xbf]|\xbb[\x80-\xb3]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\x95\xb0-\xbb])|\xe3(\x80[\x84\x92-\x93\xa0\xb6-\xb7\xbe-\xbf]|\x86[\x90-\x91\x96-\x9f]|\x87[\x80-\xa3]|\x88[\x80-\x9e\xaa-\xbf]|\x89[\x80-\x87\x90\xa0-\xbf]|\x8a[\x8a-\xb0]|\x8b[\x80-\xbe]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf])|\xe4(\xb7[\x80-\xbf])|\xea(\x92[\x90-\xbf]|\x93[\x80-\x86]|\xa0[\xa8-\xab\xb6-\xb7\xb9]|\xa9[\xb7-\xb9])|\xef(\xb7\xbd|\xbf[\xa4\xa8\xad-\xae\xbc-\xbd])|\xf0(\x90(\x86[\x8c\xa0]|\xab\x88)|\x96(\xad\x85)|\x9b(\xb2\x9c)|\x9d(\x89\x85))) +Zl (\xe2(\x80\xa8)) +Zp (\xe2(\x80\xa9)) +Zs (\x20|\xc2\xa0|\xe1(\x9a\x80)|\xe2(\x80[\x80-\x8a\xaf]|\x81\x9f)|\xe3(\x80\x80)) +L11111 ([A-Za-z]|\xc2[\xaa\xb5\xba]|\xc3[\x80-\x96\x98-\xb6\xb8-\xbf]|\xc4[\x80-\xbf]|\xc5[\x80-\xbf]|\xc6[\x80-\xbf]|\xc7[\x80-\xbf]|\xc8[\x80-\xbf]|\xc9[\x80-\xbf]|\xca[\x80-\xbf]|\xcb[\x80-\x81\x86-\x91\xa0-\xa4\xac\xae]|\xcd[\xb0-\xb4\xb6-\xb7\xba-\xbd\xbf]|\xce[\x86\x88-\x8a\x8c\x8e-\xa1\xa3-\xbf]|\xcf[\x80-\xb5\xb7-\xbf]|\xd0[\x80-\xbf]|\xd1[\x80-\xbf]|\xd2[\x80-\x81\x8a-\xbf]|\xd3[\x80-\xbf]|\xd4[\x80-\xaf\xb1-\xbf]|\xd5[\x80-\x96\x99\xa1-\xbf]|\xd6[\x80-\x87]|\xd7[\x90-\xaa\xb0-\xb2]|\xd8[\xa0-\xbf]|\xd9[\x80-\x8a\xae-\xaf\xb1-\xbf]|\xda[\x80-\xbf]|\xdb[\x80-\x93\x95\xa5-\xa6\xae-\xaf\xba-\xbc\xbf]|\xdc[\x90\x92-\xaf]|\xdd[\x8d-\xbf]|\xde[\x80-\xa5\xb1]|\xdf[\x8a-\xaa\xb4-\xb5\xba]|\xe0(\xa0[\x80-\x95\x9a\xa4\xa8]|\xa1[\x80-\x98]|\xa2[\xa0-\xb2]|\xa4[\x84-\x98])) +L11112 (\xe0(\xa4[\x99-\xb9\xbd]|\xa5[\x90\x98-\xa1\xb1-\xbf]|\xa6[\x80\x85-\x8c\x8f-\x90\x93-\xa8\xaa-\xb0\xb2\xb6-\xb9\xbd]|\xa7[\x8e\x9c-\x9d\x9f-\xa1\xb0-\xb1]|\xa8[\x85-\x8a\x8f-\x90\x93-\xa8\xaa-\xb0\xb2-\xb3\xb5-\xb6\xb8-\xb9]|\xa9[\x99-\x9c\x9e\xb2-\xb4]|\xaa[\x85-\x8d\x8f-\x91\x93-\xa8\xaa-\xb0\xb2-\xb3\xb5-\xb9\xbd]|\xab[\x90\xa0-\xa1]|\xac[\x85-\x8c\x8f-\x90\x93-\xa8\xaa-\xb0\xb2-\xb3\xb5-\xb9\xbd]|\xad[\x9c-\x9d\x9f-\xa1\xb1]|\xae[\x83\x85-\x8a\x8e-\x90\x92-\x95\x99-\x9a\x9c\x9e-\x9f\xa3-\xa4\xa8-\xaa\xae-\xb9]|\xaf\x90|\xb0[\x85-\x8c\x8e-\x90\x92-\xa8\xaa-\xb9\xbd]|\xb1[\x98-\x99\xa0-\xa1]|\xb2[\x85-\x8c\x8e-\x90\x92-\xa8\xaa-\xb3\xb5-\xb9\xbd]|\xb3[\x9e\xa0-\xa1\xb1-\xb2]|\xb4[\x85-\x8c\x8e-\x90\x92-\xba\xbd]|\xb5[\x8e\xa0-\xa1\xba-\xbf]|\xb6[\x85-\x96\x9a-\xb1\xb3-\xbb\xbd]|\xb7[\x80-\x86]|\xb8[\x81-\xb0\xb2-\xb3]|\xb9[\x80-\x86]|\xba[\x81-\x82\x84\x87-\x88\x8a\x8d\x94-\x97\x99-\x9f\xa1-\xa3\xa5\xa7\xaa-\xab\xad-\xb0\xb2-\xb3\xbd]|\xbb[\x80-\x84\x86\x9c-\x9f]|\xbc\x80|\xbd[\x80-\x87\x89-\xac]|\xbe[\x88-\x8c])|\xe1(\x80[\x80-\xaa\xbf]|\x81[\x90-\x95\x9a-\x9d\xa1\xa5-\xa6\xae-\xb0\xb5-\xbf]|\x82[\x80-\x81\x8e\xa0-\xbf]|\x83[\x80-\x85\x87\x8d\x90-\xba\xbc-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\x88\x8a-\x8d\x90-\x96\x98\x9a-\x9d\xa0-\xbf]|\x8a[\x80-\x88\x8a-\x8d\x90-\xb0\xb2-\xb5\xb8-\xbe]|\x8b[\x80\x82-\x85\x88-\x96\x98-\xbf]|\x8c[\x80-\x90\x92-\x95\x98-\xbf]|\x8d[\x80-\x9a]|\x8e[\x80-\x8f\xa0-\xbf]|\x8f[\x80-\xa8])) +L1111 ({L11111}|{L11112}) +L1112 (\xe1(\x8f[\xa9-\xb4]|\x90[\x81-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xac\xaf-\xbf]|\x9a[\x81-\x9a\xa0-\xbf]|\x9b[\x80-\xaa\xb1-\xb8]|\x9c[\x80-\x8c\x8e-\x91\xa0-\xb1]|\x9d[\x80-\x91\xa0-\xac\xae-\xb0]|\x9e[\x80-\xb3]|\x9f[\x97\x9c]|\xa0[\xa0-\xbf]|\xa1[\x80-\xb7]|\xa2[\x80-\xa8\xaa\xb0-\xbf]|\xa3[\x80-\xb5]|\xa4[\x80-\x9e]|\xa5[\x90-\xad\xb0-\xb4]|\xa6[\x80-\xab]|\xa7[\x81-\x87]|\xa8[\x80-\x96\xa0-\xbf]|\xa9[\x80-\x94]|\xaa\xa7|\xac[\x85-\xb3]|\xad[\x85-\x8b]|\xae[\x83-\xa0\xae-\xaf\xba-\xbf]|\xaf[\x80-\xa5]|\xb0[\x80-\xa3]|\xb1[\x8d-\x8f\x9a-\xbd]|\xb3[\xa9-\xac\xae-\xb1\xb5-\xb6]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\x95\x98-\x9d\xa0-\xbf]|\xbd[\x80-\x85\x88-\x8d\x90-\x97\x99\x9b\x9d\x9f-\xbd]|\xbe[\x80-\xb4\xb6-\xbc\xbe]|\xbf[\x82-\x84\x86-\x8c\x90-\x93\x96-\x9b\xa0-\xac\xb2-\xb4\xb6-\xbc])|\xe2(\x81[\xb1\xbf]|\x82[\x90-\x9c]|\x84[\x82\x87\x8a-\x93\x95\x99-\x9d\xa4\xa6\xa8\xaa-\xad\xaf-\xb9\xbc-\xbf]|\x85[\x85-\x89\x8e]|\x86[\x83-\x84]|\xb0[\x80-\xae\xb0-\xbf]|\xb1[\x80-\x9e\xa0-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xa4\xab-\xae\xb2-\xb3]|\xb4[\x80-\xa5\xa7\xad\xb0-\xbf]|\xb5[\x80-\xa7\xaf]|\xb6[\x80-\x96\xa0-\xa6\xa8-\xae\xb0-\xb6\xb8-\xbe]|\xb7[\x80-\x86\x88-\x8e\x90-\x96\x98-\x9e]|\xb8\xaf)|\xe3(\x80[\x85-\x86\xb1-\xb5\xbb-\xbc]|\x81[\x81-\xbf]|\x82[\x80-\x96\x9d-\x9f\xa1-\xbf]|\x83[\x80-\xba\xbc-\xbf]|\x84[\x85-\xad\xb1-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\x8e\xa0-\xba]|\x87[\xb0-\xbf]|\x90[\x80-\xa7])) +L111 ({L1111}|{L1112}) +L112 (\xe3(\x90[\xa8-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe4(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xa4])) +L11 ({L111}|{L112}) +L121 (\xe4(\xaf[\xa5-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xb5]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe5(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe6(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xab])) +L122 (\xe6(\x8f[\xac-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe7(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xa9])) +L12 ({L121}|{L122}) +L1 ({L11}|{L12}) +L211 (\xe7(\xae[\xaa-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe8(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xe9(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xa6])) +L2121 (\xe9(\x8d[\xa7-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\x84])) +L2122 (\xe9(\xbd[\x85-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\x8c])|\xea(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\x8c]|\x93[\x90-\xbd]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\x8c\x90-\x9f\xaa-\xab]|\x99[\x80-\xae\xbf]|\x9a[\x80-\x9d\xa0-\xbf]|\x9b[\x80-\xa5]|\x9c[\x97-\x9f\xa2-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\x88\x8b-\x8e\x90-\xad\xb0-\xb1]|\x9f[\xb7-\xbf]|\xa0[\x80-\x81\x83-\x85\x87-\x8a\x8c-\xa2]|\xa1[\x80-\xb3]|\xa2[\x82-\xb3]|\xa3[\xb2-\xb7\xbb]|\xa4[\x8a-\xa5\xb0-\xbf]|\xa5[\x80-\x86\xa0-\xbc]|\xa6[\x84-\xb2]|\xa7[\x8f\xa0-\xa4\xa6-\xaf\xba-\xbe]|\xa8[\x80-\xa8]|\xa9[\x80-\x82\x84-\x8b\xa0-\xb6\xba\xbe-\xbf]|\xaa[\x80-\xaf\xb1\xb5-\xb6\xb9-\xbd]|\xab[\x80\x82\x9b-\x9d\xa0-\xaa\xb2-\xb4]|\xac[\x81-\x86\x89-\x8e\x91-\x96\xa0-\xa6\xa8-\xae\xb0-\xbf]|\xad[\x80-\x9a\x9c-\x9f\xa4-\xa5]|\xaf[\x80-\xa2]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\x9d])) +L212 ({L2121}|{L2122}) +L21 ({L211}|{L212}) +L221 (\xea(\xb8[\x9e-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xeb(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xec(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\x9a])) +L2221 (\xec(\x97[\x9b-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xed(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xb9])) +L2222 (\xed(\x86[\xba-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xa3\xb0-\xbf]|\x9f[\x80-\x86\x8b-\xbb])|\xef(\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xad\xb0-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\x99]|\xac[\x80-\x86\x93-\x97\x9d\x9f-\xa8\xaa-\xb6\xb8-\xbc\xbe]|\xad[\x80-\x81\x83-\x84\x86-\xbf]|\xae[\x80-\xb1]|\xaf[\x93-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbd]|\xb5[\x90-\xbf]|\xb6[\x80-\x8f\x92-\xbf]|\xb7[\x80-\x87\xb0-\xbb]|\xb9[\xb0-\xb4\xb6-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbc]|\xbc[\xa1-\xba]|\xbd[\x81-\x9a\xa6-\xbf]|\xbe[\x80-\xbe]|\xbf[\x82-\x87\x8a-\x8f\x92-\x97\x9a-\x9c])|\xf0(\x90(\xa0[\x88\xbc]|\xa8\x80)|\x91(\x85\xb6|\x87\x9a|\x8c\xbd|\x93\x87|\x99\x84|\xa3\xbf)|\x96(\xbd\x90)|\x9d(\x92[\x9c\xa2\xbb]|\x95\x86|\x9f[\x8a-\x8b])|\x9e(\xb8[\xa4\xa7\xb9\xbb]|\xb9[\x82\x87\x89\x8b\x94\x97\x99\x9b\x9d\x9f\xa4\xbe]))) +L222 ({L2221}|{L2222}) +L22 ({L221}|{L222}) +L2 ({L21}|{L22}) +L ({L1}|{L2}) +C1111 ([\x00-\x1f\x7f]|\xc2[\x80-\x9f\xad]|\xcd[\xb8-\xb9]|\xce[\x80-\x83\x8b\x8d\xa2]|\xd4\xb0|\xd5[\x97-\x98\xa0]|\xd6[\x88\x8b-\x8c\x90]|\xd7[\x88-\x8f\xab-\xaf\xb5-\xbf]|\xd8[\x80-\x85\x9c-\x9d]|\xdb\x9d|\xdc[\x8e-\x8f]|\xdd[\x8b-\x8c]|\xde[\xb2-\xbf]|\xdf[\xbb-\xbf]|\xe0(\xa0[\xae-\xaf\xbf]|\xa1[\x9c-\x9d\x9f-\xbf]|\xa2[\x80-\x9f\xb3-\xbf]|\xa3[\x80-\xa3]|\xa6[\x84\x8d-\x8e\x91-\x92\xa9\xb1\xb3-\xb5\xba-\xbb]|\xa7[\x85-\x86\x89-\x8a\x8f-\x96\x98-\x9b\x9e\xa4-\xa5\xbc-\xbf]|\xa8[\x80\x84\x8b-\x8e\x91-\x92\xa9\xb1\xb4\xb7\xba-\xbb\xbd]|\xa9[\x83-\x86\x89-\x8a\x8e-\x90\x92-\x98\x9d\x9f-\xa5\xb6-\xbf]|\xaa[\x80\x84\x8e\x92\xa9\xb1\xb4\xba-\xbb]|\xab[\x86\x8a\x8e-\x8f\x91-\x9f\xa4-\xa5\xb2-\xbf]|\xac[\x80\x84\x8d-\x8e\x91-\x92\xa9\xb1\xb4\xba-\xbb]|\xad[\x85-\x86\x89-\x8a\x8e-\x95\x98-\x9b\x9e\xa4-\xa5\xb8-\xbf]|\xae[\x80-\x81\x84\x8b-\x8d\x91\x96-\x98\x9b\x9d\xa0-\xa2\xa5-\xa7\xab-\xad\xba-\xbd]|\xaf[\x83-\x85\x89\x8e-\x8f\x91-\x96\x98-\xa5\xbb-\xbf]|\xb0[\x84\x8d\x91\xa9\xba-\xbc]|\xb1[\x85\x89\x8e-\x94\x97\x9a-\x9f\xa4-\xa5\xb0-\xb7]|\xb2[\x80\x84\x8d\x91\xa9\xb4\xba-\xbb]|\xb3[\x85\x89\x8e-\x94\x97-\x9d])) +C1112 (\xe0(\xb3[\x9f\xa4-\xa5\xb0\xb3-\xbf]|\xb4[\x80\x84\x8d\x91\xbb-\xbc]|\xb5[\x85\x89\x8f-\x96\x98-\x9f\xa4-\xa5\xb6-\xb8]|\xb6[\x80-\x81\x84\x97-\x99\xb2\xbc\xbe-\xbf]|\xb7[\x87-\x89\x8b-\x8e\x95\x97\xa0-\xa5\xb0-\xb1\xb5-\xbf]|\xb8[\x80\xbb-\xbe]|\xb9[\x9c-\xbf]|\xba[\x80\x83\x85-\x86\x89\x8b-\x8c\x8e-\x93\x98\xa0\xa4\xa6\xa8-\xa9\xac\xba\xbe-\xbf]|\xbb[\x85\x87\x8e-\x8f\x9a-\x9b\xa0-\xbf]|\xbd[\x88\xad-\xb0]|\xbe[\x98\xbd]|\xbf[\x8d\x9b-\xbf])|\xe1(\x83[\x86\x88-\x8c\x8e-\x8f]|\x89[\x89\x8e-\x8f\x97\x99\x9e-\x9f]|\x8a[\x89\x8e-\x8f\xb1\xb6-\xb7\xbf]|\x8b[\x81\x86-\x87\x97]|\x8c[\x91\x96-\x97]|\x8d[\x9b-\x9c\xbd-\xbf]|\x8e[\x9a-\x9f]|\x8f[\xb5-\xbf]|\x9a[\x9d-\x9f]|\x9b[\xb9-\xbf]|\x9c[\x8d\x95-\x9f\xb7-\xbf]|\x9d[\x94-\x9f\xad\xb1\xb4-\xbf]|\x9f[\x9e-\x9f\xaa-\xaf\xba-\xbf]|\xa0[\x8e-\x8f\x9a-\x9f]|\xa1[\xb8-\xbf]|\xa2[\xab-\xaf]|\xa3[\xb6-\xbf]|\xa4[\x9f\xac-\xaf\xbc-\xbf]|\xa5[\x81-\x83\xae-\xaf\xb5-\xbf]|\xa6[\xac-\xaf]|\xa7[\x8a-\x8f\x9b-\x9d]|\xa8[\x9c-\x9d]|\xa9[\x9f\xbd-\xbe]|\xaa[\x8a-\x8f\x9a-\x9f\xae-\xaf\xbf]|\xab[\x80-\xbf]|\xad[\x8c-\x8f\xbd-\xbf]|\xaf[\xb4-\xbb]|\xb0[\xb8-\xba]|\xb1[\x8a-\x8c]|\xb2[\x80-\x8a])) +C111 ({C1111}|{C1112}) +C112 (\xe1(\xb2[\x8b-\xbf]|\xb3[\x88-\x8f\xb7\xba-\xbf]|\xb7[\xb6-\xbb]|\xbc[\x96-\x97\x9e-\x9f]|\xbd[\x86-\x87\x8e-\x8f\x98\x9a\x9c\x9e\xbe-\xbf]|\xbe\xb5|\xbf[\x85\x94-\x95\x9c\xb0-\xb1\xb5\xbf])|\xe2(\x80[\x8b-\x8f\xaa-\xae]|\x81[\xa0-\xaf\xb2-\xb3]|\x82[\x8f\x9d-\x9f\xbe-\xbf]|\x83[\x80-\x8f\xb1-\xbf]|\x86[\x8a-\x8f]|\x8f[\xbb-\xbf]|\x90[\xa7-\xbf]|\x91[\x8b-\x9f]|\xad[\xb4-\xb5]|\xae[\x96-\x97\xba-\xbc]|\xaf[\x89\x92-\xbf]|\xb0\xaf|\xb1\x9f|\xb3[\xb4-\xb8]|\xb4[\xa6\xa8-\xac\xae-\xaf]|\xb5[\xa8-\xae\xb1-\xbe]|\xb6[\x97-\x9f\xa7\xaf\xb7\xbf]|\xb7[\x87\x8f\x97\x9f]|\xb9[\x83-\xbf]|\xba\x9a|\xbb[\xb4-\xbf]|\xbf[\x96-\xaf\xbc-\xbf])|\xe3(\x81\x80|\x82[\x97-\x98]|\x84[\x80-\x84\xae-\xb0]|\x86[\x8f\xbb-\xbf]|\x87[\xa4-\xaf]|\x88\x9f|\x8b\xbf)|\xe4(\xb6[\xb6-\xbf])|\xe9(\xbf[\x8d-\xbf])|\xea(\x92[\x8d-\x8f]|\x93[\x87-\x8f]|\x98[\xac-\xbf]|\x9a\x9e|\x9b[\xb8-\xbf]|\x9e[\x8f\xae-\xaf\xb2-\xbf]|\x9f[\x80-\xb6]|\xa0[\xac-\xaf\xba-\xbf]|\xa1[\xb8-\xbf]|\xa3[\x85-\x8d\x9a-\x9f\xbc-\xbf]|\xa5[\x94-\x9e\xbd-\xbf]|\xa7[\x8e\x9a-\x9d\xbf]|\xa8[\xb7-\xbf]|\xa9[\x8e-\x8f\x9a-\x9b]|\xab[\x83-\x9a\xb7-\xbf]|\xac[\x80\x87-\x88\x8f-\x90\x97-\x9f\xa7\xaf]|\xad[\xa0-\xa3\xa6-\xbf]|\xae[\x80-\xbf]|\xaf[\xae-\xaf\xba-\xbf])|\xed(\x9e[\xa4-\xaf]|\x9f[\x87-\x8a\xbc-\xbf])|\xee(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\x87])) +C11 ({C111}|{C112}) +C12 (\xee(\x83[\x88-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xae])) +C1 ({C11}|{C12}) +C2 (\xee(\xa4[\xaf-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\xbf]|\xa7[\x80-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xbf]|\xae[\x80-\xbf]|\xaf[\x80-\xbf]|\xb0[\x80-\xbf]|\xb1[\x80-\xbf]|\xb2[\x80-\xbf]|\xb3[\x80-\xbf]|\xb4[\x80-\xbf]|\xb5[\x80-\xbf]|\xb6[\x80-\xbf]|\xb7[\x80-\xbf]|\xb8[\x80-\xbf]|\xb9[\x80-\xbf]|\xba[\x80-\xbf]|\xbb[\x80-\xbf]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\xbf])|\xef(\x80[\x80-\xbf]|\x81[\x80-\xbf]|\x82[\x80-\xbf]|\x83[\x80-\xbf]|\x84[\x80-\xbf]|\x85[\x80-\xbf]|\x86[\x80-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf]|\x90[\x80-\xbf]|\x91[\x80-\xbf]|\x92[\x80-\xbf]|\x93[\x80-\xbf]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xbf]|\x9e[\x80-\xbf]|\x9f[\x80-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\xbf]|\xa3[\x80-\xbf]|\xa9[\xae-\xaf]|\xab[\x9a-\xbf]|\xac[\x87-\x92\x98-\x9c\xb7\xbd\xbf]|\xad[\x82\x85]|\xaf[\x82-\x92]|\xb5[\x80-\x8f]|\xb6[\x90-\x91]|\xb7[\x88-\xaf\xbe-\xbf]|\xb8[\x9a-\x9f\xae-\xaf]|\xb9[\x93\xa7\xac-\xaf\xb5]|\xbb[\xbd-\xbf]|\xbc\x80|\xbe\xbf|\xbf[\x80-\x81\x88-\x89\x90-\x91\x98-\x99\x9d-\x9f\xa7\xaf-\xbb\xbe-\xbf])|\xf0(\x90(\x80[\x8c\xa7\xbb\xbe]|\x8e\x9e|\xa0[\x89\xb6]|\xa1\x96|\xa8[\x84\x94\x98])|\x91(\x82\xbd|\x84\xb5|\x88\x92|\x8c[\x84\xa9\xb1\xb4])|\x92(\x91\xaf)|\x96(\xa9\x9f|\xad[\x9a\xa2])|\x9d(\x91\x95|\x92[\x9d\xad\xba\xbc]|\x93\x84|\x94[\x86\x95\x9d\xba\xbf]|\x95[\x85\x91])|\x9e(\xb8[\x84\xa0\xa3\xa8\xb3\xb8\xba]|\xb9[\x88\x8a\x8c\x90\x93\x98\x9a\x9c\x9e\xa0\xa3\xab\xb3\xb8\xbd\xbf]|\xba[\x8a\xa4\xaa])|\x9f(\x83[\x80\x90]|\x84\xaf|\x93\xbf|\x95\xba|\x96\xa4))|\xf3(\xa0(\x80\x81))) +C ({C1}|{C2}) +M1 (\xcc[\x80-\xbf]|\xcd[\x80-\xaf]|\xd2[\x83-\x89]|\xd6[\x91-\xbd\xbf]|\xd7[\x81-\x82\x84-\x85\x87]|\xd8[\x90-\x9a]|\xd9[\x8b-\x9f\xb0]|\xdb[\x96-\x9c\x9f-\xa4\xa7-\xa8\xaa-\xad]|\xdc[\x91\xb0-\xbf]|\xdd[\x80-\x8a]|\xde[\xa6-\xb0]|\xdf[\xab-\xb3]|\xe0(\xa0[\x96-\x99\x9b-\xa3\xa5-\xa7\xa9-\xad]|\xa1[\x99-\x9b]|\xa3[\xa4-\xbf]|\xa4[\x80-\x83\xba-\xbc\xbe-\xbf]|\xa5[\x80-\x8f\x91-\x97\xa2-\xa3]|\xa6[\x81-\x83\xbc\xbe-\xbf]|\xa7[\x80-\x84\x87-\x88\x8b-\x8d\x97\xa2-\xa3]|\xa8[\x81-\x83\xbc\xbe-\xbf]|\xa9[\x80-\x82\x87-\x88\x8b-\x8d\x91\xb0-\xb1\xb5]|\xaa[\x81-\x83\xbc\xbe-\xbf]|\xab[\x80-\x85\x87-\x89\x8b-\x8d\xa2-\xa3]|\xac[\x81-\x83\xbc\xbe-\xbf]|\xad[\x80-\x84\x87-\x88\x8b-\x8d\x96-\x97\xa2-\xa3]|\xae[\x82\xbe-\xbf]|\xaf[\x80-\x82\x86-\x88\x8a-\x8d\x97]|\xb0[\x80-\x83\xbe-\xbf]|\xb1[\x80-\x84\x86-\x88\x8a-\x8d\x95-\x96\xa2-\xa3]|\xb2[\x81-\x83\xbc\xbe-\xbf]|\xb3[\x80-\x84\x86-\x88\x8a-\x8d\x95-\x96\xa2-\xa3]|\xb4[\x81-\x83\xbe-\xbf]|\xb5[\x80-\x84\x86-\x88\x8a-\x8d\x97\xa2-\xa3]|\xb6[\x82-\x83]|\xb7[\x8a\x8f-\x94\x96\x98-\x9f\xb2-\xb3]|\xb8[\xb1\xb4-\xba]|\xb9[\x87-\x8e]|\xba[\xb1\xb4-\xb9\xbb-\xbc]|\xbb[\x88-\x8d]|\xbc[\x98-\x99\xb5\xb7\xb9\xbe-\xbf]|\xbd[\xb1-\xbf]|\xbe[\x80-\x84\x86-\x87\x8d-\x97\x99-\xbc]|\xbf\x86)|\xe1(\x80[\xab-\xb6])) +M2 (\xe1(\x80[\xb7-\xbe]|\x81[\x96-\x99\x9e-\xa0\xa2-\xa4\xa7-\xad\xb1-\xb4]|\x82[\x82-\x8d\x8f\x9a-\x9d]|\x8d[\x9d-\x9f]|\x9c[\x92-\x94\xb2-\xb4]|\x9d[\x92-\x93\xb2-\xb3]|\x9e[\xb4-\xbf]|\x9f[\x80-\x93\x9d]|\xa0[\x8b-\x8d]|\xa2\xa9|\xa4[\xa0-\xab\xb0-\xbb]|\xa6[\xb0-\xbf]|\xa7[\x80\x88-\x89]|\xa8[\x97-\x9b]|\xa9[\x95-\x9e\xa0-\xbc\xbf]|\xaa[\xb0-\xbe]|\xac[\x80-\x84\xb4-\xbf]|\xad[\x80-\x84\xab-\xb3]|\xae[\x80-\x82\xa1-\xad]|\xaf[\xa6-\xb3]|\xb0[\xa4-\xb7]|\xb3[\x90-\x92\x94-\xa8\xad\xb2-\xb4\xb8-\xb9]|\xb7[\x80-\xb5\xbc-\xbf])|\xe2(\x83[\x90-\xb0]|\xb3[\xaf-\xb1]|\xb5\xbf|\xb7[\xa0-\xbf])|\xe3(\x80[\xaa-\xaf]|\x82[\x99-\x9a])|\xea(\x99[\xaf-\xb2\xb4-\xbd]|\x9a\x9f|\x9b[\xb0-\xb1]|\xa0[\x82\x86\x8b\xa3-\xa7]|\xa2[\x80-\x81\xb4-\xbf]|\xa3[\x80-\x84\xa0-\xb1]|\xa4[\xa6-\xad]|\xa5[\x87-\x93]|\xa6[\x80-\x83\xb3-\xbf]|\xa7[\x80\xa5]|\xa8[\xa9-\xb6]|\xa9[\x83\x8c-\x8d\xbb-\xbd]|\xaa[\xb0\xb2-\xb4\xb7-\xb8\xbe-\xbf]|\xab[\x81\xab-\xaf\xb5-\xb6]|\xaf[\xa3-\xaa\xac-\xad])|\xef(\xac\x9e|\xb8[\x80-\x8f\xa0-\xad])|\xf0(\x90(\x87\xbd|\x8b\xa0|\xa8\xbf)|\x91(\x80[\x80-\x82]|\x82\x82|\x84\xac|\x85\xb3|\x86\x82|\x88[\xb4-\xb5]|\x8b\x9f|\x8c[\x81\xbc]|\x8d[\x80\x97]|\x92[\xb9-\xba]|\x93\x81|\x96\xbe|\x98[\xbd-\xbe]|\x9a[\xab-\xad\xb6-\xb7]))) +M ({M1}|{M2}) +N ([0-9]|\xc2[\xb2-\xb3\xb9\xbc-\xbe]|\xd9[\xa0-\xa9]|\xdb[\xb0-\xb9]|\xdf[\x80-\x89]|\xe0(\xa5[\xa6-\xaf]|\xa7[\xa6-\xaf\xb4-\xb9]|\xa9[\xa6-\xaf]|\xab[\xa6-\xaf]|\xad[\xa6-\xaf\xb2-\xb7]|\xaf[\xa6-\xb2]|\xb1[\xa6-\xaf\xb8-\xbe]|\xb3[\xa6-\xaf]|\xb5[\xa6-\xb5]|\xb7[\xa6-\xaf]|\xb9[\x90-\x99]|\xbb[\x90-\x99]|\xbc[\xa0-\xb3])|\xe1(\x81[\x80-\x89]|\x82[\x90-\x99]|\x8d[\xa9-\xbc]|\x9b[\xae-\xb0]|\x9f[\xa0-\xa9\xb0-\xb9]|\xa0[\x90-\x99]|\xa5[\x86-\x8f]|\xa7[\x90-\x9a]|\xaa[\x80-\x89\x90-\x99]|\xad[\x90-\x99]|\xae[\xb0-\xb9]|\xb1[\x80-\x89\x90-\x99])|\xe2(\x81[\xb0\xb4-\xb9]|\x82[\x80-\x89]|\x85[\x90-\xbf]|\x86[\x80-\x82\x85-\x89]|\x91[\xa0-\xbf]|\x92[\x80-\x9b]|\x93[\xaa-\xbf]|\x9d[\xb6-\xbf]|\x9e[\x80-\x93]|\xb3\xbd)|\xe3(\x80[\x87\xa1-\xa9\xb8-\xba]|\x86[\x92-\x95]|\x88[\xa0-\xa9]|\x89[\x88-\x8f\x91-\x9f]|\x8a[\x80-\x89\xb1-\xbf])|\xea(\x98[\xa0-\xa9]|\x9b[\xa6-\xaf]|\xa0[\xb0-\xb5]|\xa3[\x90-\x99]|\xa4[\x80-\x89]|\xa7[\x90-\x99\xb0-\xb9]|\xa9[\x90-\x99]|\xaf[\xb0-\xb9])|\xef(\xbc[\x90-\x99])|\xf0(\x90(\x8d[\x81\x8a]))) +P ([!-\#%-\*,-\/\:-;\?-@\[-\]_\{\}]|\xc2[\xa1\xa7\xab\xb6-\xb7\xbb\xbf]|\xcd\xbe|\xce\x87|\xd5[\x9a-\x9f]|\xd6[\x89-\x8a\xbe]|\xd7[\x80\x83\x86\xb3-\xb4]|\xd8[\x89-\x8a\x8c-\x8d\x9b\x9e-\x9f]|\xd9[\xaa-\xad]|\xdb\x94|\xdc[\x80-\x8d]|\xdf[\xb7-\xb9]|\xe0(\xa0[\xb0-\xbe]|\xa1\x9e|\xa5[\xa4-\xa5\xb0]|\xab\xb0|\xb7\xb4|\xb9[\x8f\x9a-\x9b]|\xbc[\x84-\x92\x94\xba-\xbd]|\xbe\x85|\xbf[\x90-\x94\x99-\x9a])|\xe1(\x81[\x8a-\x8f]|\x83\xbb|\x8d[\xa0-\xa8]|\x90\x80|\x99[\xad-\xae]|\x9a[\x9b-\x9c]|\x9b[\xab-\xad]|\x9c[\xb5-\xb6]|\x9f[\x94-\x96\x98-\x9a]|\xa0[\x80-\x8a]|\xa5[\x84-\x85]|\xa8[\x9e-\x9f]|\xaa[\xa0-\xa6\xa8-\xad]|\xad[\x9a-\xa0]|\xaf[\xbc-\xbf]|\xb0[\xbb-\xbf]|\xb1[\xbe-\xbf]|\xb3[\x80-\x87\x93])|\xe2(\x80[\x90-\xa7\xb0-\xbf]|\x81[\x80-\x83\x85-\x91\x93-\x9e\xbd-\xbe]|\x82[\x8d-\x8e]|\x8c[\x88-\x8b\xa9-\xaa]|\x9d[\xa8-\xb5]|\x9f[\x85-\x86\xa6-\xaf]|\xa6[\x83-\x98]|\xa7[\x98-\x9b\xbc-\xbd]|\xb3[\xb9-\xbc\xbe-\xbf]|\xb5\xb0|\xb8[\x80-\xae\xb0-\xbf]|\xb9[\x80-\x82])|\xe3(\x80[\x81-\x83\x88-\x91\x94-\x9f\xb0\xbd]|\x82\xa0|\x83\xbb)|\xea(\x93[\xbe-\xbf]|\x98[\x8d-\x8f]|\x99[\xb3\xbe]|\x9b[\xb2-\xb7]|\xa1[\xb4-\xb7]|\xa3[\x8e-\x8f\xb8-\xba]|\xa4[\xae-\xaf]|\xa5\x9f|\xa7[\x81-\x8d\x9e-\x9f]|\xa9[\x9c-\x9f]|\xab[\x9e-\x9f\xb0-\xb1]|\xaf\xab)|\xef(\xb4[\xbe-\xbf]|\xb8[\x90-\x99\xb0-\xbf]|\xb9[\x80-\x92\x94-\xa1\xa3\xa8\xaa-\xab]|\xbc[\x81-\x83\x85-\x8a\x8c-\x8f\x9a-\x9b\x9f-\xa0\xbb-\xbd\xbf]|\xbd[\x9b\x9d\x9f-\xa5])|\xf0(\x90(\x8e\x9f|\x8f\x90|\x95\xaf|\xa1\x97|\xa4[\x9f\xbf]|\xa9\xbf)|\x91(\x87\x8d|\x93\x86)|\x96(\xab\xb5|\xad\x84)|\x9b(\xb2\x9f))) +S1 ([\$\+<->\^`\|~]|\xc2[\xa2-\xa6\xa8-\xa9\xac\xae-\xb1\xb4\xb8]|\xc3[\x97\xb7]|\xcb[\x82-\x85\x92-\x9f\xa5-\xab\xad\xaf-\xbf]|\xcd\xb5|\xce[\x84-\x85]|\xcf\xb6|\xd2\x82|\xd6[\x8d-\x8f]|\xd8[\x86-\x88\x8b\x8e-\x8f]|\xdb[\x9e\xa9\xbd-\xbe]|\xdf\xb6|\xe0(\xa7[\xb2-\xb3\xba-\xbb]|\xab\xb1|\xad\xb0|\xaf[\xb3-\xba]|\xb1\xbf|\xb5\xb9|\xb8\xbf|\xbc[\x81-\x83\x93\x95-\x97\x9a-\x9f\xb4\xb6\xb8]|\xbe[\xbe-\xbf]|\xbf[\x80-\x85\x87-\x8c\x8e-\x8f\x95-\x98])|\xe1(\x82[\x9e-\x9f]|\x8e[\x90-\x99]|\x9f\x9b|\xa5\x80|\xa7[\x9e-\xbf]|\xad[\xa1-\xaa\xb4-\xbc]|\xbe[\xbd\xbf]|\xbf[\x80-\x81\x8d-\x8f\x9d-\x9f\xad-\xaf\xbd-\xbe])|\xe2(\x81[\x84\x92\xba-\xbc]|\x82[\x8a-\x8c\xa0-\xbd]|\x84[\x80-\x81\x83-\x86\x88-\x89\x94\x96-\x98\x9e-\xa3\xa5\xa7\xa9\xae\xba-\xbb]|\x85[\x80-\x84\x8a-\x8d\x8f]|\x86[\x90-\xbf]|\x87[\x80-\xbf]|\x88[\x80-\xbf]|\x89[\x80-\xbf]|\x8a[\x80-\xbf]|\x8b[\x80-\xbf]|\x8c[\x80-\x87\x8c-\xa8\xab-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xba]|\x90[\x80-\xa6]|\x91[\x80-\x8a]|\x92[\x9c-\xbf]|\x93[\x80-\xa9]|\x94[\x80-\xbf]|\x95[\x80-\xbf]|\x96[\x80-\xbf]|\x97[\x80-\xbf]|\x98[\x80-\xbf]|\x99[\x80-\xbf]|\x9a[\x80-\xbf]|\x9b[\x80-\xbf]|\x9c[\x80-\xbf]|\x9d[\x80-\xa7]|\x9e[\x94-\xbf]|\x9f[\x80-\x84\x87-\xa5\xb0-\xbf]|\xa0[\x80-\xbf]|\xa1[\x80-\xbf]|\xa2[\x80-\x88])) +S2 (\xe2(\xa2[\x89-\xbf]|\xa3[\x80-\xbf]|\xa4[\x80-\xbf]|\xa5[\x80-\xbf]|\xa6[\x80-\x82\x99-\xbf]|\xa7[\x80-\x97\x9c-\xbb\xbe-\xbf]|\xa8[\x80-\xbf]|\xa9[\x80-\xbf]|\xaa[\x80-\xbf]|\xab[\x80-\xbf]|\xac[\x80-\xbf]|\xad[\x80-\xb3\xb6-\xbf]|\xae[\x80-\x95\x98-\xb9\xbd-\xbf]|\xaf[\x80-\x88\x8a-\x91]|\xb3[\xa5-\xaa]|\xba[\x80-\x99\x9b-\xbf]|\xbb[\x80-\xb3]|\xbc[\x80-\xbf]|\xbd[\x80-\xbf]|\xbe[\x80-\xbf]|\xbf[\x80-\x95\xb0-\xbb])|\xe3(\x80[\x84\x92-\x93\xa0\xb6-\xb7\xbe-\xbf]|\x82[\x9b-\x9c]|\x86[\x90-\x91\x96-\x9f]|\x87[\x80-\xa3]|\x88[\x80-\x9e\xaa-\xbf]|\x89[\x80-\x87\x90\xa0-\xbf]|\x8a[\x8a-\xb0]|\x8b[\x80-\xbe]|\x8c[\x80-\xbf]|\x8d[\x80-\xbf]|\x8e[\x80-\xbf]|\x8f[\x80-\xbf])|\xe4(\xb7[\x80-\xbf])|\xea(\x92[\x90-\xbf]|\x93[\x80-\x86]|\x9c[\x80-\x96\xa0-\xa1]|\x9e[\x89-\x8a]|\xa0[\xa8-\xab\xb6-\xb9]|\xa9[\xb7-\xb9]|\xad\x9b)|\xef(\xac\xa9|\xae[\xb2-\xbf]|\xaf[\x80-\x81]|\xb7[\xbc-\xbd]|\xb9[\xa2\xa4-\xa6\xa9]|\xbc[\x84\x8b\x9c-\x9e\xbe]|\xbd[\x80\x9c\x9e]|\xbf[\xa0-\xa6\xa8-\xae\xbc-\xbd])|\xf0(\x90(\x86[\x8c\xa0]|\xab\x88)|\x96(\xad\x85)|\x9b(\xb2\x9c)|\x9d(\x89\x85|\x9b[\x81\x9b\xbb]|\x9c[\x95\xb5]|\x9d[\x8f\xaf]|\x9e[\x89\xa9]|\x9f\x83))) +S ({S1}|{S2}) +Z (\x20|\xc2\xa0|\xe1(\x9a\x80)|\xe2(\x80[\x80-\x8a\xa8-\xa9\xaf]|\x81\x9f)|\xe3(\x80\x80)) + +DIGIT [0-9] +EXPO [eE][-+]?[0-9]+ + +%% /*** Filter language Part ***/ + +[ \t] ; +[\n]+ ; + +\<\<(\\(.|\n)|[^\\>\n])*\>\> yylval.string = unquote(yytext); return STRING; + +[+()=/*^,\.\{\}\[\]:;@\?#] return *yytext; + +"==" return EQ; +"!=" return NEQ; +">" return GT; +"<" return LT; +">=" return GTE; +"<=" return LTE; + +"-" return MINUSSIGN; +"\xe2\x88\x92" return MINUSSIGN; + +"nm" yylval.quantity.scaler = Quantity::NanoMetre; yylval.quantity.unitStr = yytext; return UNIT; // nano meter +"um" yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = yytext; return UNIT; // micro meter +"\xC2\xB5m" yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = yytext; return UNIT; // micro meter (greek micro in UTF8) +"mm" yylval.quantity.scaler = Quantity::MilliMetre; yylval.quantity.unitStr = yytext; return UNIT; // milli meter (internal standard length) +"cm" yylval.quantity.scaler = Quantity::CentiMetre; yylval.quantity.unitStr = yytext; return UNIT; // centi meter +"dm" yylval.quantity.scaler = Quantity::DeciMetre; yylval.quantity.unitStr = yytext; return UNIT; // deci meter +"m" yylval.quantity.scaler = Quantity::Metre; yylval.quantity.unitStr = yytext; return UNIT; // metre +"km" yylval.quantity.scaler = Quantity::KiloMetre; yylval.quantity.unitStr = yytext; return UNIT; // kilo meter + +"l" yylval.quantity.scaler = Quantity::Liter; yylval.quantity.unitStr = yytext; return UNIT; // Liter dm^3 + +"ug" yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = yytext; return UNIT; // micro gram +"\xC2\xB5g" yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = yytext; return UNIT; // micro gram +"mg" yylval.quantity.scaler = Quantity::MilliGram; yylval.quantity.unitStr = yytext; return UNIT; // milli gram +"g" yylval.quantity.scaler = Quantity::Gram; yylval.quantity.unitStr = yytext; return UNIT; // gram +"kg" yylval.quantity.scaler = Quantity::KiloGram; yylval.quantity.unitStr = yytext; return UNIT; // kilo gram (internal standard for mass) +"t" yylval.quantity.scaler = Quantity::Ton; yylval.quantity.unitStr = yytext; return UNIT; // Metric Tonne + +"s" yylval.quantity.scaler = Quantity::Second; yylval.quantity.unitStr = yytext; return UNIT; // second (internal standard time) +"min" yylval.quantity.scaler = Quantity::Minute; yylval.quantity.unitStr = yytext; return UNIT; // minute +"h" yylval.quantity.scaler = Quantity::Hour; yylval.quantity.unitStr = yytext; return UNIT; // hour + +"A" yylval.quantity.scaler = Quantity::Ampere; yylval.quantity.unitStr = yytext; return UNIT; // Ampere (internal standard electric current) +"mA" yylval.quantity.scaler = Quantity::MilliAmpere; yylval.quantity.unitStr = yytext; return UNIT; // milli Ampere +"kA" yylval.quantity.scaler = Quantity::KiloAmpere; yylval.quantity.unitStr = yytext; return UNIT; // kilo Ampere +"MA" yylval.quantity.scaler = Quantity::MegaAmpere; yylval.quantity.unitStr = yytext; return UNIT; // Mega Ampere + +"K" yylval.quantity.scaler = Quantity::Kelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin (internal standard thermodynamic temperature) +"mK" yylval.quantity.scaler = Quantity::MilliKelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin +"\xC2\xB5K" yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin +"uK" yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin + +"mol" yylval.quantity.scaler = Quantity::Mole; yylval.quantity.unitStr = yytext; return UNIT; // Mole (internal standard amount of substance) + +"cd" yylval.quantity.scaler = Quantity::Candela; yylval.quantity.unitStr = yytext; return UNIT; // Candela (internal standard luminous intensity) + +"in" yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = yytext; return UNIT; // inch +"\"" yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = yytext; return UNIT; // inch +"ft" yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = yytext; return UNIT; // foot +"'" yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = yytext; return UNIT; // foot +"thou" yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = yytext; return UNIT; // thou (in/1000) +"mil" yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = yytext; return UNIT; // mil (the thou in US) +"yd" yylval.quantity.scaler = Quantity::Yard; yylval.quantity.unitStr = yytext; return UNIT; // yard +"mi" yylval.quantity.scaler = Quantity::Mile; yylval.quantity.unitStr = yytext; return UNIT; // mile + + + +"lb" yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = yytext; return UNIT; // pound +"lbm" yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = yytext; return UNIT; // pound +"oz" yylval.quantity.scaler = Quantity::Ounce; yylval.quantity.unitStr = yytext; return UNIT; // ounce +"st" yylval.quantity.scaler = Quantity::Stone; yylval.quantity.unitStr = yytext; return UNIT; // Stone +"cwt" yylval.quantity.scaler = Quantity::Hundredweights; yylval.quantity.unitStr = yytext; return UNIT; // hundredweights + +"lbf" yylval.quantity.scaler = Quantity::PoundForce; yylval.quantity.unitStr = yytext; return UNIT; // pound + +"N" yylval.quantity.scaler = Quantity::Newton; yylval.quantity.unitStr = yytext; return UNIT; // Newton (kg*m/s^2)a-za-za-z +"kN" yylval.quantity.scaler = Quantity::KiloNewton; yylval.quantity.unitStr = yytext; return UNIT; // Newton +"MN" yylval.quantity.scaler = Quantity::MegaNewton; yylval.quantity.unitStr = yytext; return UNIT; // Newton +"mN" yylval.quantity.scaler = Quantity::MilliNewton; yylval.quantity.unitStr = yytext; return UNIT; // Newton + +"Pa" yylval.quantity.scaler = Quantity::Pascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal (kg/m*s^2 or N/m^2) +"kPa" yylval.quantity.scaler = Quantity::KiloPascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal +"MPa" yylval.quantity.scaler = Quantity::MegaPascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal +"GPa" yylval.quantity.scaler = Quantity::GigaPascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal + +"Torr" yylval.quantity.scaler = Quantity::Torr; yylval.quantity.unitStr = yytext; return UNIT; // portion of Pascal ( 101325/760 ) +"mTorr" yylval.quantity.scaler = Quantity::mTorr; yylval.quantity.unitStr = yytext; return UNIT; // +"uTorr" yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = yytext; return UNIT; // +"\xC2\xB5Torr" yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = yytext; return UNIT; // + +"psi" yylval.quantity.scaler = Quantity::PSI; yylval.quantity.unitStr = yytext; return UNIT; // pounds/in^2 +"ksi" yylval.quantity.scaler = Quantity::KSI; yylval.quantity.unitStr = yytext; return UNIT; // 1000 x pounds/in^2 + +"W" yylval.quantity.scaler = Quantity::Watt; yylval.quantity.unitStr = yytext; return UNIT; // Watt (kg*m^2/s^3) +"VA" yylval.quantity.scaler = Quantity::VoltAmpere; yylval.quantity.unitStr = yytext; return UNIT; // VoltAmpere (kg*m^2/s^3) + +"J" yylval.quantity.scaler = Quantity::Joule; yylval.quantity.unitStr = yytext; return UNIT; // Joule (kg*m^2/s^2) +"Nm" yylval.quantity.scaler = Quantity::NewtonMeter; yylval.quantity.unitStr = yytext; return UNIT; // N*m = Joule +"VAs" yylval.quantity.scaler = Quantity::VoltAmpereSecond; yylval.quantity.unitStr = yytext; return UNIT; // V*A*s = Joule +"CV" yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = yytext; return UNIT; // +"Ws" yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = yytext; return UNIT; // W*s = Joule + +"\xC2\xB0" yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = yytext; return UNIT; // degree (internal standard angle) +"deg" yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = yytext; return UNIT; // degree (internal standard angle) +"rad" yylval.quantity.scaler = Quantity::Radian; yylval.quantity.unitStr = yytext; return UNIT; // radian +"gon" yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr = yytext; return UNIT; // gon + +{DIGIT}*"."{DIGIT}+{EXPO}? yylval.fvalue = num_change(yytext,'.',','); return NUM; +{DIGIT}*","{DIGIT}+{EXPO}? yylval.fvalue = num_change(yytext,',','.'); return NUM; +{DIGIT}+ yylval.ivalue = strtoll( yytext, NULL, 0 ); return INTEGER; + +"pi" yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi +"e" yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e + +$[A-Za-z]{1,2}+${DIGIT}+ yylval.string = yytext; return CELLADDRESS; +[A-Za-z]{1,2}${DIGIT}+ yylval.string = yytext; return CELLADDRESS; +$[A-Za-z]{1,2}{DIGIT}+ yylval.string = yytext; return CELLADDRESS; + +({L}{M}*)({L}{M}*|{N}|_)*[\20\t]*\( { + std::string s = yytext; + size_t i = s.size() - 2; + while (isspace(s[i])) + --i; + s.erase(i + 1); + std::map::const_iterator j = registered_functions.find(s); + if (j != registered_functions.end()) + yylval.func = j->second; + else + yylval.func = FunctionExpression::NONE; + return FUNC; + } + +({L}{M}*)({L}{M}*|{N}|_)* yylval.string = yytext; return IDENTIFIER; diff --git a/src/Mod/Spreadsheet/App/ExpressionParser.tab.c b/src/Mod/Spreadsheet/App/ExpressionParser.tab.c new file mode 100644 index 0000000000..313deacb33 --- /dev/null +++ b/src/Mod/Spreadsheet/App/ExpressionParser.tab.c @@ -0,0 +1,2207 @@ +/* A Bison parser, made by GNU Bison 2.5. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.5" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Copy the first part of user declarations. */ + +/* Line 268 of yacc.c */ +#line 7 "ExpressionParser.y" + + +class semantic_type { +public: + struct { + Quantity scaler; + std::string unitStr; + } quantity; + Expression * expr; + Path path; + std::deque components; + int ivalue; + double fvalue; + struct { + std::string name; + double fvalue; + } constant; + std::vector arguments; + std::string string; + FunctionExpression::Function func; + Path::String string_or_identifier; + semantic_type() {} +}; + +#define YYSTYPE semantic_type + +std::stack functions; /**< Function identifier */ + + //#define YYSTYPE yystype + #define yyparse ExpressionParser_yyparse + #define yyerror ExpressionParser_yyerror + + +/* Line 268 of yacc.c */ +#line 105 "ExpressionParser.tab.c" + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + FUNC = 258, + NUM = 259, + IDENTIFIER = 260, + UNIT = 261, + INTEGER = 262, + CONSTANT = 263, + CELLADDRESS = 264, + EQ = 265, + NEQ = 266, + LT = 267, + GT = 268, + GTE = 269, + LTE = 270, + STRING = 271, + MINUSSIGN = 272, + PROPERTY_REF = 273, + DOCUMENT = 274, + OBJECT = 275, + EXPONENT = 276, + NEG = 277 + }; +#endif + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED + +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Line 343 of yacc.c */ +#line 168 "ExpressionParser.tab.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 35 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 182 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 38 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 12 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 61 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 110 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 277 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 35, 2, 2, 2, 2, + 30, 31, 24, 23, 32, 22, 34, 25, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 27, 33, + 2, 2, 2, 26, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 36, 2, 37, 29, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 28 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint8 yyprhs[] = +{ + 0, 0, 3, 5, 7, 9, 11, 13, 17, 21, + 25, 29, 33, 36, 40, 44, 48, 54, 56, 58, + 60, 63, 66, 69, 71, 73, 77, 81, 85, 89, + 93, 97, 101, 105, 109, 113, 117, 121, 123, 127, + 131, 135, 140, 144, 149, 153, 155, 159, 163, 169, + 171, 173, 178, 185, 190, 195, 202, 209, 213, 215, + 217, 219 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 39, 0, -1, 40, -1, 45, -1, 41, -1, 16, + -1, 46, -1, 40, 23, 40, -1, 40, 22, 40, + -1, 40, 24, 40, -1, 40, 25, 40, -1, 40, + 25, 45, -1, 17, 40, -1, 40, 29, 40, -1, + 30, 40, 31, -1, 3, 42, 31, -1, 44, 26, + 40, 27, 40, -1, 4, -1, 7, -1, 8, -1, + 4, 45, -1, 7, 45, -1, 8, 45, -1, 40, + -1, 43, -1, 42, 32, 40, -1, 42, 33, 40, + -1, 9, 27, 9, -1, 9, 27, 5, -1, 5, + 27, 9, -1, 5, 27, 5, -1, 40, 10, 40, + -1, 40, 11, 40, -1, 40, 12, 40, -1, 40, + 13, 40, -1, 40, 14, 40, -1, 40, 15, 40, + -1, 6, -1, 45, 25, 45, -1, 45, 24, 45, + -1, 45, 29, 4, -1, 45, 29, 22, 4, -1, + 45, 29, 7, -1, 45, 29, 17, 7, -1, 30, + 45, 31, -1, 47, -1, 49, 34, 47, -1, 48, + 35, 47, -1, 48, 35, 49, 34, 47, -1, 5, + -1, 9, -1, 5, 36, 7, 37, -1, 5, 36, + 7, 37, 34, 47, -1, 5, 36, 16, 37, -1, + 5, 36, 5, 37, -1, 5, 36, 16, 37, 34, + 47, -1, 5, 36, 5, 37, 34, 47, -1, 5, + 34, 47, -1, 16, -1, 5, -1, 16, -1, 9, + -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = +{ + 0, 84, 84, 85, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 99, 100, 101, 102, 105, 106, 107, + 108, 109, 110, 113, 114, 115, 116, 119, 120, 121, + 122, 125, 126, 127, 128, 129, 130, 133, 134, 135, + 136, 137, 138, 139, 140, 143, 147, 152, 157, 165, + 166, 167, 168, 169, 170, 171, 172, 173, 176, 177, + 180, 181 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "FUNC", "NUM", "IDENTIFIER", "UNIT", + "INTEGER", "CONSTANT", "CELLADDRESS", "EQ", "NEQ", "LT", "GT", "GTE", + "LTE", "STRING", "MINUSSIGN", "PROPERTY_REF", "DOCUMENT", "OBJECT", + "EXPONENT", "'-'", "'+'", "'*'", "'/'", "'?'", "':'", "NEG", "'^'", + "'('", "')'", "','", "';'", "'.'", "'#'", "'['", "']'", "$accept", + "input", "exp", "num", "args", "range", "cond", "unit_exp", "identifier", + "path", "document", "object", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 45, 43, 42, 47, 63, 58, 277, 94, + 40, 41, 44, 59, 46, 35, 91, 93 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 38, 39, 39, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, + 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, + 43, 44, 44, 44, 44, 44, 44, 45, 45, 45, + 45, 45, 45, 45, 45, 46, 46, 46, 46, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, + 49, 49 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 1, 1, 1, 1, 3, 3, 3, + 3, 3, 2, 3, 3, 3, 5, 1, 1, 1, + 2, 2, 2, 1, 1, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, + 3, 4, 3, 4, 3, 1, 3, 3, 5, 1, + 1, 4, 6, 4, 4, 6, 6, 3, 1, 1, + 1, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 17, 49, 37, 18, 19, 50, 5, 0, + 0, 0, 2, 4, 0, 3, 6, 45, 0, 0, + 49, 50, 0, 23, 0, 24, 0, 20, 0, 0, + 21, 22, 12, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 15, 0, 0, 49, 50, + 57, 0, 0, 0, 14, 44, 31, 32, 33, 34, + 35, 36, 8, 7, 9, 10, 11, 13, 0, 39, + 38, 40, 42, 0, 0, 60, 47, 0, 46, 30, + 29, 28, 27, 25, 26, 54, 51, 53, 0, 43, + 41, 0, 0, 0, 0, 16, 48, 56, 52, 55 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 11, 33, 13, 24, 25, 14, 34, 16, 17, + 18, 19 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -27 +static const yytype_int16 yypact[] = +{ + 55, 79, -3, -12, -27, -3, -3, 14, -21, 96, + 55, 49, 127, -27, 25, 65, -27, -27, 31, 34, + 87, 40, 96, 127, 100, -27, -3, -27, 3, -1, + 65, 65, 50, 105, 130, -27, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 55, 96, 96, -3, -3, + 48, 64, 3, 88, 97, -27, 96, 96, -2, -27, + -27, 44, 54, 70, -27, -27, 127, 127, 127, 127, + 127, 127, 133, 133, 153, 153, 63, 127, 6, 63, + 63, -27, -27, 101, 106, -27, -27, 77, -27, -27, + -27, -27, -27, 127, 127, 90, 91, 119, 96, -27, + -27, 3, 3, 3, 3, 50, -27, -27, -27, -27 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -27, -27, 0, -27, -27, -27, -27, 5, -27, -26, + -27, 84 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -62 +static const yytype_int8 yytable[] = +{ + 12, 23, 60, 4, 61, 15, 62, 27, 58, 32, + 30, 31, 59, -60, -58, 63, 36, 37, 38, 39, + 40, 41, 28, -59, 29, 86, 88, 26, 42, 43, + 44, 45, 28, 98, 29, 46, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 77, 78, -61, 35, + 76, 47, 81, 79, 80, 82, 93, 94, 1, 2, + 3, 4, 5, 6, 7, 83, 51, 54, 52, 58, + 84, 8, 9, 7, -61, 106, 107, 108, 109, 46, + 85, 95, 1, 2, 20, 10, 5, 6, 21, 48, + 49, 96, 50, 89, 50, 8, 9, 90, 105, 1, + 2, 3, 91, 5, 6, 7, 92, 97, 99, 22, + 100, 101, 8, 9, 53, 36, 37, 38, 39, 40, + 41, 28, -59, 29, 102, 103, 22, 42, 43, 44, + 45, 55, 56, 57, 46, 87, 64, 36, 37, 38, + 39, 40, 41, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 104, 48, 49, 46, 44, 45, 50, + 0, 65, 46, 36, 37, 38, 39, 40, 41, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 46 +}; + +#define yypact_value_is_default(yystate) \ + ((yystate) == (-27)) + +#define yytable_value_is_error(yytable_value) \ + YYID (0) + +static const yytype_int8 yycheck[] = +{ + 0, 1, 28, 6, 5, 0, 7, 2, 5, 9, + 5, 6, 9, 34, 35, 16, 10, 11, 12, 13, + 14, 15, 34, 35, 36, 51, 52, 30, 22, 23, + 24, 25, 34, 27, 36, 29, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 34, 0, + 45, 26, 4, 48, 49, 7, 56, 57, 3, 4, + 5, 6, 7, 8, 9, 17, 35, 27, 34, 5, + 22, 16, 17, 9, 34, 101, 102, 103, 104, 29, + 16, 37, 3, 4, 5, 30, 7, 8, 9, 24, + 25, 37, 29, 5, 29, 16, 17, 9, 98, 3, + 4, 5, 5, 7, 8, 9, 9, 37, 7, 30, + 4, 34, 16, 17, 27, 10, 11, 12, 13, 14, + 15, 34, 35, 36, 34, 34, 30, 22, 23, 24, + 25, 31, 32, 33, 29, 51, 31, 10, 11, 12, + 13, 14, 15, 10, 11, 12, 13, 14, 15, 22, + 23, 24, 25, 34, 24, 25, 29, 24, 25, 29, + -1, 31, 29, 10, 11, 12, 13, 14, 15, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 29 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 4, 5, 6, 7, 8, 9, 16, 17, + 30, 39, 40, 41, 44, 45, 46, 47, 48, 49, + 5, 9, 30, 40, 42, 43, 30, 45, 34, 36, + 45, 45, 40, 40, 45, 0, 10, 11, 12, 13, + 14, 15, 22, 23, 24, 25, 29, 26, 24, 25, + 29, 35, 34, 27, 27, 31, 32, 33, 5, 9, + 47, 5, 7, 16, 31, 31, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 45, 40, 40, 45, + 45, 4, 7, 17, 22, 16, 47, 49, 47, 5, + 9, 5, 9, 40, 40, 37, 37, 37, 27, 7, + 4, 34, 34, 34, 34, 40, 47, 47, 47, 47 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ + +#define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* This macro is provided for backward compatibility. */ + +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = 0; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + case 40: /* "exp" */ + +/* Line 1391 of yacc.c */ +#line 77 "ExpressionParser.y" + { delete (yyvaluep->expr); }; + +/* Line 1391 of yacc.c */ +#line 1207 "ExpressionParser.tab.c" + break; + case 42: /* "args" */ + +/* Line 1391 of yacc.c */ +#line 78 "ExpressionParser.y" + { std::vector::const_iterator i = (yyvaluep->arguments).begin(); while (i != (yyvaluep->arguments).end()) { delete *i; ++i; } }; + +/* Line 1391 of yacc.c */ +#line 1216 "ExpressionParser.tab.c" + break; + case 44: /* "cond" */ + +/* Line 1391 of yacc.c */ +#line 77 "ExpressionParser.y" + { delete (yyvaluep->expr); }; + +/* Line 1391 of yacc.c */ +#line 1225 "ExpressionParser.tab.c" + break; + case 45: /* "unit_exp" */ + +/* Line 1391 of yacc.c */ +#line 77 "ExpressionParser.y" + { delete (yyvaluep->expr); }; + +/* Line 1391 of yacc.c */ +#line 1234 "ExpressionParser.tab.c" + break; + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: + +/* Line 1806 of yacc.c */ +#line 84 "ExpressionParser.y" + { ScanResult = (yyvsp[(1) - (1)].expr); valueExpression = true; } + break; + + case 3: + +/* Line 1806 of yacc.c */ +#line 85 "ExpressionParser.y" + { ScanResult = (yyvsp[(1) - (1)].expr); unitExpression = true; } + break; + + case 4: + +/* Line 1806 of yacc.c */ +#line 88 "ExpressionParser.y" + { (yyval.expr) = (yyvsp[(1) - (1)].expr); } + break; + + case 5: + +/* Line 1806 of yacc.c */ +#line 89 "ExpressionParser.y" + { (yyval.expr) = new StringExpression(DocumentObject, (yyvsp[(1) - (1)].string)); } + break; + + case 6: + +/* Line 1806 of yacc.c */ +#line 90 "ExpressionParser.y" + { (yyval.expr) = new VariableExpression(DocumentObject, (yyvsp[(1) - (1)].path)); } + break; + + case 7: + +/* Line 1806 of yacc.c */ +#line 91 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::ADD, (yyvsp[(3) - (3)].expr)); } + break; + + case 8: + +/* Line 1806 of yacc.c */ +#line 92 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::SUB, (yyvsp[(3) - (3)].expr)); } + break; + + case 9: + +/* Line 1806 of yacc.c */ +#line 93 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::MUL, (yyvsp[(3) - (3)].expr)); } + break; + + case 10: + +/* Line 1806 of yacc.c */ +#line 94 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::DIV, (yyvsp[(3) - (3)].expr)); } + break; + + case 11: + +/* Line 1806 of yacc.c */ +#line 95 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::DIV, (yyvsp[(3) - (3)].expr)); } + break; + + case 12: + +/* Line 1806 of yacc.c */ +#line 96 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, + new NumberExpression(DocumentObject, -1.0), + OperatorExpression::MUL, (yyvsp[(2) - (2)].expr)); } + break; + + case 13: + +/* Line 1806 of yacc.c */ +#line 99 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::POW, (yyvsp[(3) - (3)].expr)); } + break; + + case 14: + +/* Line 1806 of yacc.c */ +#line 100 "ExpressionParser.y" + { (yyval.expr) = (yyvsp[(2) - (3)].expr); } + break; + + case 15: + +/* Line 1806 of yacc.c */ +#line 101 "ExpressionParser.y" + { (yyval.expr) = new FunctionExpression(DocumentObject, (yyvsp[(1) - (3)].func), (yyvsp[(2) - (3)].arguments)); } + break; + + case 16: + +/* Line 1806 of yacc.c */ +#line 102 "ExpressionParser.y" + { (yyval.expr) = new ConditionalExpression(DocumentObject, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); } + break; + + case 17: + +/* Line 1806 of yacc.c */ +#line 105 "ExpressionParser.y" + { (yyval.expr) = new NumberExpression(DocumentObject, (yyvsp[(1) - (1)].fvalue)); } + break; + + case 18: + +/* Line 1806 of yacc.c */ +#line 106 "ExpressionParser.y" + { (yyval.expr) = new NumberExpression(DocumentObject, (double)(yyvsp[(1) - (1)].ivalue)); } + break; + + case 19: + +/* Line 1806 of yacc.c */ +#line 107 "ExpressionParser.y" + { (yyval.expr) = new ConstantExpression(DocumentObject, (yyvsp[(1) - (1)].constant).name, (yyvsp[(1) - (1)].constant).fvalue); } + break; + + case 20: + +/* Line 1806 of yacc.c */ +#line 108 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (yyvsp[(1) - (2)].fvalue)), OperatorExpression::UNIT, (yyvsp[(2) - (2)].expr)); } + break; + + case 21: + +/* Line 1806 of yacc.c */ +#line 109 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (double)(yyvsp[(1) - (2)].ivalue)), OperatorExpression::UNIT, (yyvsp[(2) - (2)].expr)); } + break; + + case 22: + +/* Line 1806 of yacc.c */ +#line 110 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, new ConstantExpression(DocumentObject, (yyvsp[(1) - (2)].constant).name, (yyvsp[(1) - (2)].constant).fvalue), OperatorExpression::UNIT, (yyvsp[(2) - (2)].expr)); } + break; + + case 23: + +/* Line 1806 of yacc.c */ +#line 113 "ExpressionParser.y" + { (yyval.arguments).push_back((yyvsp[(1) - (1)].expr)); } + break; + + case 24: + +/* Line 1806 of yacc.c */ +#line 114 "ExpressionParser.y" + { (yyval.arguments).push_back((yyvsp[(1) - (1)].expr)); } + break; + + case 25: + +/* Line 1806 of yacc.c */ +#line 115 "ExpressionParser.y" + { (yyvsp[(1) - (3)].arguments).push_back((yyvsp[(3) - (3)].expr)); (yyval.arguments) = (yyvsp[(1) - (3)].arguments); } + break; + + case 26: + +/* Line 1806 of yacc.c */ +#line 116 "ExpressionParser.y" + { (yyvsp[(1) - (3)].arguments).push_back((yyvsp[(3) - (3)].expr)); (yyval.arguments) = (yyvsp[(1) - (3)].arguments); } + break; + + case 27: + +/* Line 1806 of yacc.c */ +#line 119 "ExpressionParser.y" + { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string)); } + break; + + case 28: + +/* Line 1806 of yacc.c */ +#line 120 "ExpressionParser.y" + { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string)); } + break; + + case 29: + +/* Line 1806 of yacc.c */ +#line 121 "ExpressionParser.y" + { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string)); } + break; + + case 30: + +/* Line 1806 of yacc.c */ +#line 122 "ExpressionParser.y" + { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string)); } + break; + + case 31: + +/* Line 1806 of yacc.c */ +#line 125 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::EQ, (yyvsp[(3) - (3)].expr)); } + break; + + case 32: + +/* Line 1806 of yacc.c */ +#line 126 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::NEQ, (yyvsp[(3) - (3)].expr)); } + break; + + case 33: + +/* Line 1806 of yacc.c */ +#line 127 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::LT, (yyvsp[(3) - (3)].expr)); } + break; + + case 34: + +/* Line 1806 of yacc.c */ +#line 128 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::GT, (yyvsp[(3) - (3)].expr)); } + break; + + case 35: + +/* Line 1806 of yacc.c */ +#line 129 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::GTE, (yyvsp[(3) - (3)].expr)); } + break; + + case 36: + +/* Line 1806 of yacc.c */ +#line 130 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::LTE, (yyvsp[(3) - (3)].expr)); } + break; + + case 37: + +/* Line 1806 of yacc.c */ +#line 133 "ExpressionParser.y" + { (yyval.expr) = new UnitExpression(DocumentObject, (yyvsp[(1) - (1)].quantity).scaler, (yyvsp[(1) - (1)].quantity).unitStr ); } + break; + + case 38: + +/* Line 1806 of yacc.c */ +#line 134 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::DIV, (yyvsp[(3) - (3)].expr)); } + break; + + case 39: + +/* Line 1806 of yacc.c */ +#line 135 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::MUL, (yyvsp[(3) - (3)].expr)); } + break; + + case 40: + +/* Line 1806 of yacc.c */ +#line 136 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::POW, new NumberExpression(DocumentObject, (yyvsp[(3) - (3)].fvalue))); } + break; + + case 41: + +/* Line 1806 of yacc.c */ +#line 137 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (4)].expr), OperatorExpression::POW, new NumberExpression(DocumentObject, -(yyvsp[(4) - (4)].fvalue))); } + break; + + case 42: + +/* Line 1806 of yacc.c */ +#line 138 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::POW, new NumberExpression(DocumentObject, (double)(yyvsp[(3) - (3)].ivalue))); } + break; + + case 43: + +/* Line 1806 of yacc.c */ +#line 139 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (4)].expr), OperatorExpression::POW, new NumberExpression(DocumentObject, -(double)(yyvsp[(4) - (4)].ivalue))); } + break; + + case 44: + +/* Line 1806 of yacc.c */ +#line 140 "ExpressionParser.y" + { (yyval.expr) = (yyvsp[(2) - (3)].expr); } + break; + + case 45: + +/* Line 1806 of yacc.c */ +#line 143 "ExpressionParser.y" + { /* Path to property within document object */ + (yyval.path) = Path(DocumentObject); + (yyval.path).addComponents((yyvsp[(1) - (1)].components)); + } + break; + + case 46: + +/* Line 1806 of yacc.c */ +#line 147 "ExpressionParser.y" + { /* Path to property within document object */ + (yyval.path) = Path(DocumentObject); + (yyval.path).setDocumentObjectName((yyvsp[(1) - (3)].string_or_identifier), true); + (yyval.path).addComponents((yyvsp[(3) - (3)].components)); + } + break; + + case 47: + +/* Line 1806 of yacc.c */ +#line 152 "ExpressionParser.y" + { /* Path to property from an external document, within a named document object */ + (yyval.path) = Path(DocumentObject); + (yyval.path).setDocumentName((yyvsp[(1) - (3)].string_or_identifier), true); + (yyval.path).addComponents((yyvsp[(3) - (3)].components)); + } + break; + + case 48: + +/* Line 1806 of yacc.c */ +#line 157 "ExpressionParser.y" + { /* Path to property from an external document, within a named document object */ + (yyval.path) = Path(DocumentObject); + (yyval.path).setDocumentName((yyvsp[(1) - (5)].string_or_identifier), true); + (yyval.path).setDocumentObjectName((yyvsp[(3) - (5)].string_or_identifier), true); + (yyval.path).addComponents((yyvsp[(5) - (5)].components)); + } + break; + + case 49: + +/* Line 1806 of yacc.c */ +#line 165 "ExpressionParser.y" + { (yyval.components).push_front(Path::Component::SimpleComponent((yyvsp[(1) - (1)].string))); } + break; + + case 50: + +/* Line 1806 of yacc.c */ +#line 166 "ExpressionParser.y" + { (yyval.components).push_front(Path::Component::SimpleComponent((yyvsp[(1) - (1)].string))); } + break; + + case 51: + +/* Line 1806 of yacc.c */ +#line 167 "ExpressionParser.y" + { (yyval.components).push_front(Path::Component::ArrayComponent((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].ivalue))); } + break; + + case 52: + +/* Line 1806 of yacc.c */ +#line 168 "ExpressionParser.y" + { (yyvsp[(6) - (6)].components).push_front(Path::Component::ArrayComponent((yyvsp[(1) - (6)].string), (yyvsp[(3) - (6)].ivalue))); (yyval.components) = (yyvsp[(6) - (6)].components); } + break; + + case 53: + +/* Line 1806 of yacc.c */ +#line 169 "ExpressionParser.y" + { (yyval.components).push_front(Path::Component::MapComponent((yyvsp[(1) - (4)].string), Path::String((yyvsp[(3) - (4)].string), true))); } + break; + + case 54: + +/* Line 1806 of yacc.c */ +#line 170 "ExpressionParser.y" + { (yyval.components).push_front(Path::Component::MapComponent((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].string))); } + break; + + case 55: + +/* Line 1806 of yacc.c */ +#line 171 "ExpressionParser.y" + { (yyvsp[(6) - (6)].components).push_front(Path::Component::MapComponent((yyvsp[(1) - (6)].string), Path::String((yyvsp[(3) - (6)].string), true))); (yyval.components) = (yyvsp[(6) - (6)].components); } + break; + + case 56: + +/* Line 1806 of yacc.c */ +#line 172 "ExpressionParser.y" + { (yyvsp[(6) - (6)].components).push_front(Path::Component::MapComponent((yyvsp[(1) - (6)].string), (yyvsp[(3) - (6)].string))); (yyval.components) = (yyvsp[(6) - (6)].components); } + break; + + case 57: + +/* Line 1806 of yacc.c */ +#line 173 "ExpressionParser.y" + { (yyvsp[(3) - (3)].components).push_front(Path::Component::SimpleComponent((yyvsp[(1) - (3)].string))); (yyval.components) = (yyvsp[(3) - (3)].components); } + break; + + case 58: + +/* Line 1806 of yacc.c */ +#line 176 "ExpressionParser.y" + { (yyval.string_or_identifier) = Path::String((yyvsp[(1) - (1)].string), true); } + break; + + case 59: + +/* Line 1806 of yacc.c */ +#line 177 "ExpressionParser.y" + { (yyval.string_or_identifier) = Path::String((yyvsp[(1) - (1)].string)); } + break; + + case 60: + +/* Line 1806 of yacc.c */ +#line 180 "ExpressionParser.y" + { (yyval.string_or_identifier) = Path::String((yyvsp[(1) - (1)].string), true); } + break; + + case 61: + +/* Line 1806 of yacc.c */ +#line 181 "ExpressionParser.y" + { (yyval.string_or_identifier) = Path::String((yyvsp[(1) - (1)].string), true); } + break; + + + +/* Line 1806 of yacc.c */ +#line 1975 "ExpressionParser.tab.c" + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + +/* Line 2067 of yacc.c */ +#line 184 "ExpressionParser.y" + + diff --git a/src/Mod/Spreadsheet/App/ExpressionParser.y b/src/Mod/Spreadsheet/App/ExpressionParser.y new file mode 100644 index 0000000000..b75936242d --- /dev/null +++ b/src/Mod/Spreadsheet/App/ExpressionParser.y @@ -0,0 +1,184 @@ +/* Parser for the FreeCAD Units language */ +/* (c) 2010 Juergen Riegel LGPL */ +/* (c) 2015 Eivind Kvedalen LGPL */ + +/* Represents the many different ways we can access our data */ + +%{ + +class semantic_type { +public: + struct { + Quantity scaler; + std::string unitStr; + } quantity; + Expression * expr; + Path path; + std::deque components; + int ivalue; + double fvalue; + struct { + std::string name; + double fvalue; + } constant; + std::vector arguments; + std::string string; + FunctionExpression::Function func; + Path::String string_or_identifier; + semantic_type() {} +}; + +#define YYSTYPE semantic_type + +std::stack functions; /**< Function identifier */ + + //#define YYSTYPE yystype + #define yyparse ExpressionParser_yyparse + #define yyerror ExpressionParser_yyerror +%} + + /* Bison declarations. */ + %token FUNC + %token NUM + %token IDENTIFIER + %token UNIT + %token INTEGER + %token CONSTANT + %token CELLADDRESS + %token EQ NEQ LT GT GTE LTE + %token STRING MINUSSIGN PROPERTY_REF + %token DOCUMENT OBJECT + %token EXPONENT + %type args + %type input exp unit_exp cond + %type UNIT + %type STRING IDENTIFIER CELLADDRESS + %type INTEGER + %type PROPERTY_REF + %type NUM + %type CONSTANT + %type num + %type range + %type identifier + %type path + %type FUNC + %type document + %type object + %left NUM + %left INTEGER + %left CONSTANT + %left '-' '+' + %left '*' '/' + %left '?' ':' EQ NEQ LT GT GTE LTE + %left NEG /* negation--unary minus */ + %right '^' /* exponentiation */ + %right EXPONENT + +%destructor { delete $$; } exp cond unit_exp +%destructor { std::vector::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args + +%start input + +%% + +input: exp { ScanResult = $1; valueExpression = true; } + | unit_exp { ScanResult = $1; unitExpression = true; } + ; + +exp: num { $$ = $1; } + | STRING { $$ = new StringExpression(DocumentObject, $1); } + | identifier { $$ = new VariableExpression(DocumentObject, $1); } + | exp '+' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::ADD, $3); } + | exp '-' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::SUB, $3); } + | exp '*' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); } + | exp '/' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } + | exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } + | MINUSSIGN exp %prec NEG { $$ = new OperatorExpression(DocumentObject, + new NumberExpression(DocumentObject, -1.0), + OperatorExpression::MUL, $2); } + | exp '^' exp %prec NUM { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); } + | '(' exp ')' { $$ = $2; } + | FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1, $2); } + | cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); } + ; + +num: NUM { $$ = new NumberExpression(DocumentObject, $1); } + | INTEGER { $$ = new NumberExpression(DocumentObject, (double)$1); } + | CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, $1.fvalue); } + | NUM unit_exp %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, $1), OperatorExpression::UNIT, $2); } + | INTEGER unit_exp { $$ = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (double)$1), OperatorExpression::UNIT, $2); } + | CONSTANT unit_exp { $$ = new OperatorExpression(DocumentObject, new ConstantExpression(DocumentObject, $1.name, $1.fvalue), OperatorExpression::UNIT, $2); } + ; + +args: exp { $$.push_back($1); } + | range { $$.push_back($1); } + | args ',' exp { $1.push_back($3); $$ = $1; } + | args ';' exp { $1.push_back($3); $$ = $1; } + ; + +range: CELLADDRESS ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); } + | CELLADDRESS ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); } + | IDENTIFIER ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); } + | IDENTIFIER ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); } + ; + +cond: exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); } + | exp NEQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::NEQ, $3); } + | exp LT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LT, $3); } + | exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); } + | exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); } + | exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); } + ; + +unit_exp: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); } + | unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } + | unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); } + | unit_exp '^' NUM %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, $3)); } + | unit_exp '^' '-' NUM %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, -$4)); } + | unit_exp '^' INTEGER %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, (double)$3)); } + | unit_exp '^' MINUSSIGN INTEGER %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, -(double)$4)); } + | '(' unit_exp ')' { $$ = $2; } + ; + +identifier: path { /* Path to property within document object */ + $$ = Path(DocumentObject); + $$.addComponents($1); + } + | object '.' path { /* Path to property within document object */ + $$ = Path(DocumentObject); + $$.setDocumentObjectName($1, true); + $$.addComponents($3); + } + | document '#' path { /* Path to property from an external document, within a named document object */ + $$ = Path(DocumentObject); + $$.setDocumentName($1, true); + $$.addComponents($3); + } + | document '#' object '.' path { /* Path to property from an external document, within a named document object */ + $$ = Path(DocumentObject); + $$.setDocumentName($1, true); + $$.setDocumentObjectName($3, true); + $$.addComponents($5); + } + ; + +path: IDENTIFIER { $$.push_front(Path::Component::SimpleComponent($1)); } + | CELLADDRESS { $$.push_front(Path::Component::SimpleComponent($1)); } + | IDENTIFIER '[' INTEGER ']' { $$.push_front(Path::Component::ArrayComponent($1, $3)); } + | IDENTIFIER '[' INTEGER ']' '.' path { $6.push_front(Path::Component::ArrayComponent($1, $3)); $$ = $6; } + | IDENTIFIER '[' STRING ']' { $$.push_front(Path::Component::MapComponent($1, Path::String($3, true))); } + | IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(Path::Component::MapComponent($1, $3)); } + | IDENTIFIER '[' STRING ']' '.' path { $6.push_front(Path::Component::MapComponent($1, Path::String($3, true))); $$ = $6; } + | IDENTIFIER '[' IDENTIFIER ']' '.' path { $6.push_front(Path::Component::MapComponent($1, $3)); $$ = $6; } + | IDENTIFIER '.' path { $3.push_front(Path::Component::SimpleComponent($1)); $$ = $3; } + ; + +document: STRING { $$ = Path::String($1, true); } + | IDENTIFIER { $$ = Path::String($1); } + ; + +object: STRING { $$ = Path::String($1, true); } + | CELLADDRESS { $$ = Path::String($1, true); } + ; + +%% diff --git a/src/Mod/Spreadsheet/App/PreCompiled.cpp b/src/Mod/Spreadsheet/App/PreCompiled.cpp new file mode 100644 index 0000000000..38b50fcba9 --- /dev/null +++ b/src/Mod/Spreadsheet/App/PreCompiled.cpp @@ -0,0 +1,24 @@ +/*************************************************************************** + * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" diff --git a/src/Mod/Spreadsheet/App/PreCompiled.h b/src/Mod/Spreadsheet/App/PreCompiled.h new file mode 100644 index 0000000000..bae4d0bfe2 --- /dev/null +++ b/src/Mod/Spreadsheet/App/PreCompiled.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef __PRECOMPILED__ +#define __PRECOMPILED__ + +#include + +// Exporting of App classes +#ifdef FC_OS_WIN32 +# define SpreadsheetExport __declspec(dllexport) +#else // for Linux +# define SpreadsheetExport +#endif + +#ifdef _PreComp_ +/// here get the warnings of to long specifieres disabled (needed for VC6) +#ifdef _MSC_VER +# pragma warning( disable : 4251 ) +# pragma warning( disable : 4503 ) +# pragma warning( disable : 4786 ) // specifier longer then 255 chars +#endif + +// standard +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#endif // _PreComp_ +#endif + diff --git a/src/Mod/Spreadsheet/App/PropertyColumnWidths.cpp b/src/Mod/Spreadsheet/App/PropertyColumnWidths.cpp new file mode 100644 index 0000000000..b064df9903 --- /dev/null +++ b/src/Mod/Spreadsheet/App/PropertyColumnWidths.cpp @@ -0,0 +1,157 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "PropertyColumnWidths.h" +#include +#include +#include "Utils.h" +#include + +using namespace App; +using namespace Spreadsheet; + +const int PropertyColumnWidths::defaultWidth = 100; +const int PropertyColumnWidths::defaultHeaderWidth = 50; + +TYPESYSTEM_SOURCE(Spreadsheet::PropertyColumnWidths , App::Property); + +PropertyColumnWidths::PropertyColumnWidths() +{ +} + +PropertyColumnWidths::PropertyColumnWidths(const PropertyColumnWidths &other) +{ + std::map::const_iterator i = other.begin(); + + while (i != other.end()) { + insert(*i); + ++i; + } +} + +App::Property *PropertyColumnWidths::Copy() const +{ + PropertyColumnWidths * prop = new PropertyColumnWidths(*this); + + return prop; +} + +void PropertyColumnWidths::Paste(const App::Property &from) +{ + aboutToSetValue(); + const PropertyColumnWidths * frompcw = static_cast(&from); + + std::map::const_iterator i; + + /* Mark all as dirty first */ + i = begin(); + while (i != end()) { + dirty.insert(i->first); + ++i; + } + + /* Clear old map */ + clear(); + + /* Copy new map from from */ + i = frompcw->begin(); + while (i != frompcw->end()) { + insert(*i); + dirty.insert(i->first); + ++i; + } + hasSetValue(); +} + +/** + * Set the width (in pixels) of column \a col to \a width. + * + * @param col Column to set + * @param width Width in pixels + * + */ + +void PropertyColumnWidths::setValue(int col, int width) +{ + if (width >= 0) { + aboutToSetValue(); + operator[](col) = width; + dirty.insert(col); + hasSetValue(); + } +} + +void PropertyColumnWidths::Save(Base::Writer &writer) const +{ + // Save column information + writer.Stream() << writer.ind() << "" << std::endl; + writer.incInd(); // indention for 'ColumnInfo' + std::map::const_iterator coli = begin(); + while (coli != end()) { + writer.Stream() << writer.ind() << "first) << "\" width=\"" << coli->second << "\" />" << std::endl; + ++coli; + } + writer.decInd(); // indention for 'ColumnInfo' + writer.Stream() << writer.ind() << "" << std::endl; +} + +void PropertyColumnWidths::Restore(Base::XMLReader &reader) +{ + int Cnt; + + // Column info + reader.readElement("ColumnInfo"); + Cnt = reader.hasAttribute("Count") ? reader.getAttributeAsInteger("Count") : 0; + for (int i = 0; i < Cnt; i++) { + reader.readElement("Column"); + const char* name = reader.hasAttribute("name") ? reader.getAttribute("name") : 0; + const char * width = reader.hasAttribute("width") ? reader.getAttribute("width") : 0; + + try { + if (name && width) { + int col = decodeColumn(name); + int colWidth = atoi(width); + + setValue(col, colWidth); + } + } + catch (...) { + // Something is wrong, skip this column + } + + } + reader.readEndElement("ColumnInfo"); +} + +PyObject *PropertyColumnWidths::getPyObject() +{ + if (PythonObject.is(Py::_None())){ + // ref counter is set to 1 + PythonObject = Py::Object(new PropertyColumnWidthsPy(this),true); + } + return Py::new_reference_to(PythonObject); +} diff --git a/src/Mod/Spreadsheet/App/PropertyColumnWidths.h b/src/Mod/Spreadsheet/App/PropertyColumnWidths.h new file mode 100644 index 0000000000..8f3bbcbd24 --- /dev/null +++ b/src/Mod/Spreadsheet/App/PropertyColumnWidths.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef PROPERTYCOLUMNWIDTHS_H +#define PROPERTYCOLUMNWIDTHS_H + +#include +#include +#include + +namespace Spreadsheet { + +class SpreadsheetExport PropertyColumnWidths : public App::Property, std::map +{ + TYPESYSTEM_HEADER(); +public: + PropertyColumnWidths(); + + PropertyColumnWidths(const PropertyColumnWidths & other); + + void setValue() { } + + void setValue(int col, int width); + + std::map getValues() const { + return *this; + } + + int getValue(int column) const { return find(column) != end() ? at(column) : defaultWidth; } + + virtual Property *Copy(void) const; + + virtual void Paste(const Property &from); + + virtual void Save (Base::Writer & writer) const; + + virtual void Restore(Base::XMLReader & reader); + + bool isDirty() const { return dirty.size() > 0; } + + void clearDirty() { dirty.clear(); } + + const std::set & getDirty() const { return dirty; } + + PyObject *getPyObject(void); + + static const int defaultWidth; + static const int defaultHeaderWidth; + +private: + + std::set dirty; + + Py::Object PythonObject; +}; + +} + +#endif // PROPERTYCOLUMNWIDTHS_H diff --git a/src/Mod/Spreadsheet/App/PropertyColumnWidthsPy.xml b/src/Mod/Spreadsheet/App/PropertyColumnWidthsPy.xml new file mode 100644 index 0000000000..36b7905a07 --- /dev/null +++ b/src/Mod/Spreadsheet/App/PropertyColumnWidthsPy.xml @@ -0,0 +1,19 @@ + + + + + + + Internal spreadsheet object + + + diff --git a/src/Mod/Spreadsheet/App/PropertyRowHeights.cpp b/src/Mod/Spreadsheet/App/PropertyRowHeights.cpp new file mode 100644 index 0000000000..68a0737e24 --- /dev/null +++ b/src/Mod/Spreadsheet/App/PropertyRowHeights.cpp @@ -0,0 +1,150 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "PropertyRowHeights.h" +#include +#include +#include "Utils.h" +#include + +using namespace App; +using namespace Spreadsheet; + +const int PropertyRowHeights::defaultHeight = 20; + +TYPESYSTEM_SOURCE(Spreadsheet::PropertyRowHeights , App::Property); + +PropertyRowHeights::PropertyRowHeights() +{ +} + +PropertyRowHeights::PropertyRowHeights(const PropertyRowHeights &other) +{ +} + +Property *PropertyRowHeights::Copy() const +{ + PropertyRowHeights * prop = new PropertyRowHeights(*this); + + return prop; +} + +void PropertyRowHeights::Paste(const Property &from) +{ + aboutToSetValue(); + const PropertyRowHeights * fromprh = static_cast(&from); + + std::map::const_iterator i; + + /* Mark all as dirty first */ + i = begin(); + while (i != end()) { + dirty.insert(i->first); + ++i; + } + + /* Clear old map */ + clear(); + + /* Copy new map from from */ + i = fromprh->begin(); + while (i != fromprh->end()) { + insert(*i); + dirty.insert(i->first); + ++i; + } + hasSetValue(); +} + +void PropertyRowHeights::Save(Base::Writer &writer) const +{ + // Save row information + writer.Stream() << writer.ind() << "" << std::endl; + writer.incInd(); // indention for 'RowInfo' + + std::map::const_iterator ri = begin(); + while (ri != end()) { + writer.Stream() << writer.ind() << "first) << "\" height=\"" << ri->second << "\" />" << std::endl; + ++ri; + } + writer.decInd(); // indention for 'RowInfo' + writer.Stream() << writer.ind() << "" << std::endl; +} + +/** + * Set height of row given by \a row to \a height in pixels. + * + * @param row Address of row + * @param height Height in pixels + * + */ + +void PropertyRowHeights::setValue(int row, int height) +{ + if (height >= 0) { + aboutToSetValue(); + operator[](row) = height; + dirty.insert(row); + hasSetValue(); + } +} + +void PropertyRowHeights::Restore(Base::XMLReader &reader) +{ + int Cnt; + + // Row info + reader.readElement("RowInfo"); + Cnt = reader.hasAttribute("Count") ? reader.getAttributeAsInteger("Count") : 0; + for (int i = 0; i < Cnt; i++) { + reader.readElement("Row"); + const char* name = reader.hasAttribute("name") ? reader.getAttribute("name") : 0; + const char * height = reader.hasAttribute("height") ? reader.getAttribute("height") : 0; + + try { + if (name && height) { + int row = decodeRow(name); + int rowHeight = atoi(height); + + setValue(row, rowHeight); + } + } + catch (...) { + // Something is wrong, skip this row + } + } + reader.readEndElement("RowInfo"); +} + +PyObject *PropertyRowHeights::getPyObject() +{ + if (PythonObject.is(Py::_None())){ + // ref counter is set to 1 + PythonObject = Py::Object(new PropertyRowHeightsPy(this),true); + } + return Py::new_reference_to(PythonObject); +} diff --git a/src/Mod/Spreadsheet/App/PropertyRowHeights.h b/src/Mod/Spreadsheet/App/PropertyRowHeights.h new file mode 100644 index 0000000000..3ec58ff4a6 --- /dev/null +++ b/src/Mod/Spreadsheet/App/PropertyRowHeights.h @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef PROPERTYROWHEIGHTS_H +#define PROPERTYROWHEIGHTS_H + +#include +#include +#include + +namespace Spreadsheet { + +class SpreadsheetExport PropertyRowHeights : public App::Property, std::map +{ + TYPESYSTEM_HEADER(); +public: + PropertyRowHeights(); + + PropertyRowHeights(const PropertyRowHeights & other); + + void setValue() { } + + void setValue(int row, int height); + + int getValue(int row) const { return find(row) != end() ? at(row) : 20; } + + std::map getValues() const { + return *this; + } + + virtual App::Property *Copy(void) const; + + virtual void Paste(const App::Property &from); + + virtual void Save (Base::Writer & writer) const; + + virtual void Restore(Base::XMLReader & reader); + + bool isDirty() const { return dirty.size() > 0; } + + void clearDirty() { dirty.clear(); } + + const std::set & getDirty() const { return dirty; } + + PyObject *getPyObject(void); + + static const int defaultHeight; + +private: + + std::set dirty; + + Py::Object PythonObject; +}; + +} + +#endif // PROPERTYROWHEIGHTS_H diff --git a/src/Mod/Spreadsheet/App/PropertyRowHeightsPy.xml b/src/Mod/Spreadsheet/App/PropertyRowHeightsPy.xml new file mode 100644 index 0000000000..59779dfbb1 --- /dev/null +++ b/src/Mod/Spreadsheet/App/PropertyRowHeightsPy.xml @@ -0,0 +1,19 @@ + + + + + + + Internal spreadsheet object + + + diff --git a/src/Mod/Spreadsheet/App/PropertySheet.cpp b/src/Mod/Spreadsheet/App/PropertySheet.cpp new file mode 100644 index 0000000000..9c3e8645ce --- /dev/null +++ b/src/Mod/Spreadsheet/App/PropertySheet.cpp @@ -0,0 +1,1059 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "PropertySheet.h" +#include "Sheet.h" +#include "Expression.h" +#include "Utils.h" +#include + +using namespace App; +using namespace Spreadsheet; + +class ResolveExpressionVisitor : public ExpressionVisitor { +public: + + void visit(Expression * node) { + VariableExpression *expr = freecad_dynamic_cast(node); + + if (expr) + expr->resolve(); + } +}; + +class RelabelDocumentObjectExpressionVisitor : public ExpressionVisitor { +public: + + RelabelDocumentObjectExpressionVisitor(const std::string & _oldName, const std::string & _newName) + : oldName(_oldName) + , newName(_newName) + { + } + + void visit(Expression * node) { + VariableExpression *expr = freecad_dynamic_cast(node); + + if (expr) + expr->renameDocumentObject(oldName, newName); + } + +private: + std::string oldName; + std::string newName; +}; + +class RelabelDocumentExpressionVisitor : public ExpressionVisitor { +public: + + RelabelDocumentExpressionVisitor(const std::string & _oldName, const std::string & _newName) + : oldName(_oldName) + , newName(_newName) + { + } + + void visit(Expression * node) { + VariableExpression *expr = freecad_dynamic_cast(node); + + if (expr) + expr->renameDocument(oldName, newName); + } + +private: + std::string oldName; + std::string newName; +}; + +TYPESYSTEM_SOURCE(Spreadsheet::PropertySheet , App::Property); + +void PropertySheet::clear() +{ + std::map::iterator i = data.begin(); + + /* Clear cells */ + while (i != data.end()) { + delete i->second; + setDirty(i->first); + ++i; + } + + /* Clear from map */ + data.clear(); + + mergedCells.clear(); + + propertyNameToCellMap.clear(); + documentObjectToCellMap.clear(); + docDeps.clear(); +} + +Cell *PropertySheet::getValue(CellAddress key) +{ + std::map::const_iterator i = data.find(key); + + if (i == data.end()) + return 0; + else + return i->second; +} + +std::set PropertySheet::getUsedCells() const +{ + std::set usedSet; + + for (std::map::const_iterator i = data.begin(); i != data.end(); ++i) { + if (i->second->isUsed()) + usedSet.insert(i->first); + } + + return usedSet; +} + +void PropertySheet::setDirty(CellAddress address) +{ + /* Merged cells will automatically force an update of the top left cell + to be consistent. */ + if (mergedCells.find(address) != mergedCells.end()) + address = mergedCells[address]; + + dirty.insert(address); +} + +Cell * PropertySheet::createCell(CellAddress address) +{ + Cell * cell = new Cell(address, this); + + data[address] = cell; + + return cell; +} + +PropertySheet::PropertySheet(Sheet *_owner) + : Property() + , owner(_owner) + , signalCounter(0) +{ +} + +PropertySheet::PropertySheet(const PropertySheet &other) + : owner(other.owner) + , dirty(other.dirty) + , mergedCells(other.mergedCells) + , propertyNameToCellMap(other.propertyNameToCellMap) + , documentObjectToCellMap(other.documentObjectToCellMap) + , signalCounter(0) +{ + std::map::const_iterator i = other.data.begin(); + + /* Copy cells */ + while (i != other.data.end()) { + data[i->first] = new Cell(*i->second); + ++i; + } +} + +PropertySheet::~PropertySheet() +{ + clear(); +} + +Property *PropertySheet::Copy(void) const +{ + return new PropertySheet(*this); +} + +void PropertySheet::Paste(const Property &from) +{ + Signaller signaller(*this); + + const PropertySheet * froms = static_cast(&from); + + std::map::iterator icurr = data.begin(); + + /* Mark all first */ + while (icurr != data.end()) { + icurr->second->mark(); + ++icurr; + } + + std::map::const_iterator ifrom = froms->data.begin(); + while (ifrom != froms->data.end()) { + std::map::iterator i = data.find(ifrom->first); + + if (i != data.end()) { + *(data[ifrom->first]) = *(ifrom->second); // Exists; assign cell directly + recomputeDependencies(ifrom->first); + } + else { + data[ifrom->first] = new Cell(*(ifrom->second)); // Doesn't exist, copy using Cell's copy constructor + } + + /* Set dirty */ + setDirty(ifrom->first); + + ++ifrom; + } + + /* Remove all that are still marked */ + icurr = data.begin(); + while (icurr != data.end()) { + Cell * cell = icurr->second; + + if (cell->isMarked()) + clear(ifrom->first); + ++icurr; + } + + mergedCells = froms->mergedCells; +} + +void PropertySheet::Save(Base::Writer &writer) const +{ + // Save cell contents + int count = 0; + + std::map::const_iterator ci = data.begin(); + while (ci != data.end()) { + if (ci->second->isUsed()) + ++count; + ++ci; + } + + writer.Stream() << writer.ind() << "" << std::endl; + writer.incInd(); + ci = data.begin(); + while (ci != data.end()) { + ci->second->save(writer); + ++ci; + } + + writer.decInd(); + writer.Stream() << writer.ind() << "" << std::endl; +} + +void PropertySheet::Restore(Base::XMLReader &reader) +{ + int Cnt; + + reader.readElement("Cells"); + Cnt = reader.getAttributeAsInteger("Count"); + for (int i = 0; i < Cnt; i++) { + reader.readElement("Cell"); + + const char* strAddress = reader.hasAttribute("address") ? reader.getAttribute("address") : 0; + + try { + CellAddress address(strAddress); + Cell * cell = createCell(address); + + cell->restore(reader); + + int rows, cols; + if (cell->getSpans(rows, cols) && (rows > 1 || cols > 1)) { + mergeCells(address, CellAddress(address.row() + rows - 1, address.col() + cols - 1)); + } + } + catch (const Base::Exception & e) { + // Something is wrong, skip this cell + } + catch (...) { + } + } + reader.readEndElement("Cells"); +} + +Cell * PropertySheet::cellAt(CellAddress address) +{ + std::map::iterator i = data.find(address); + + if (i == data.end()) { + if (mergedCells.find(address) != mergedCells.end()) { + std::map::iterator j = mergedCells.find(address); + + assert(j != mergedCells.end()); + + i = data.find(j->second); + assert(i != data.end()); + + return i->second; + } + return 0; + } + else + return i->second; +} + +const Cell * PropertySheet::cellAt(CellAddress address) const +{ + std::map::const_iterator i = data.find(address); + + if (i == data.end()) { + if (mergedCells.find(address) != mergedCells.end()) { + std::map::const_iterator j = mergedCells.find(address); + + assert(j != mergedCells.end()); + + i = data.find(j->second); + assert(i != data.end()); + + return i->second; + } + + return 0; + } + else + return i->second; +} + +Cell * PropertySheet::nonNullCellAt(CellAddress address) +{ + std::map::const_iterator i = data.find(address); + + if (i == data.end()) { + if (mergedCells.find(address) != mergedCells.end()) { + std::map::const_iterator j = mergedCells.find(address); + + assert(j != mergedCells.end()); + + i = data.find(j->second); + if (i == data.end()) + return createCell(address); + else + return i->second; + } + + return createCell(address); + } + else + return i->second; +} + +void PropertySheet::setContent(CellAddress address, const char *value) +{ + Cell * cell = nonNullCellAt(address); + + assert(cell != 0); + + cell->setContent(value); +} + +void PropertySheet::setAlignment(CellAddress address, int _alignment) +{ + nonNullCellAt(address)->setAlignment(_alignment); +} + +void PropertySheet::setStyle(CellAddress address, const std::set &_style) +{ + assert(nonNullCellAt(address) != 0); + nonNullCellAt(address)->setStyle(_style); +} + +void PropertySheet::setForeground(CellAddress address, const Color &color) +{ + assert(nonNullCellAt(address) != 0); + nonNullCellAt(address)->setForeground(color); +} + +void PropertySheet::setBackground(CellAddress address, const Color &color) +{ + assert(nonNullCellAt(address) != 0); + nonNullCellAt(address)->setBackground(color); +} + +void PropertySheet::setDisplayUnit(CellAddress address, const std::string &unit) +{ + assert(nonNullCellAt(address) != 0); + nonNullCellAt(address)->setDisplayUnit(unit); +} + + +void PropertySheet::setAlias(CellAddress address, const std::string &alias) +{ + assert(nonNullCellAt(address) != 0); + nonNullCellAt(address)->setAlias(alias); +} + +void PropertySheet::setComputedUnit(CellAddress address, const Base::Unit &unit) +{ + assert(nonNullCellAt(address) != 0); + nonNullCellAt(address)->setComputedUnit(unit); +} + +void PropertySheet::setSpans(CellAddress address, int rows, int columns) +{ + assert(nonNullCellAt(address) != 0); + nonNullCellAt(address)->setSpans(rows, columns); +} + +void PropertySheet::clear(CellAddress address) +{ + std::map::iterator i = data.find(address); + + if (i == data.end()) + return; + + Signaller signaller(*this); + + // Spit cell to clean up mergeCells map; all data is in first cell anyway + splitCell(address); + + // Delete Cell object + removeDependencies(address); + delete i->second; + + // Mark as dirty + dirty.insert(i->first); + + // Erase from internal struct + data.erase(i); +} + +void PropertySheet::moveCell(CellAddress currPos, CellAddress newPos) +{ + std::map::const_iterator i = data.find(currPos); + std::map::const_iterator j = data.find(newPos); + + Signaller signaller(*this); + + if (j != data.end()) + clear(newPos); + + if (i != data.end()) { + int row, col; + Cell * cell = data.at(currPos); + + // Remove from old + removeDependencies(currPos); + data.erase(currPos); + setDirty(currPos); + + // Insert into new spot + cell->moveAbsolute(newPos); + data[newPos] = cell; + addDependencies(newPos); + setDirty(newPos); + } +} + +/** + * @brief The RewriteExpressionVisitor class + * + * A class that visits each node of an expressions, and possibly + * rewrites variables. This is a helper class to rewrite expressions + * when rows or columns are either inserted or removed, to make + * sure that formulas referencing cells being moved to a new locations + * will still be valid, i.e rewritten. + * + */ + +class RewriteExpressionVisitor : public ExpressionVisitor { +public: + RewriteExpressionVisitor(CellAddress address, int rowCount, int colCount) + : mRow(address.row()) + , mCol(address.col()) + , mRowCount(rowCount) + , mColCount(colCount) + , mChanged(false) { } + ~RewriteExpressionVisitor() { } + + void reset() { mChanged = false; } + + bool changed() const { return mChanged; } + + void visit(Expression * node) { + VariableExpression *expr = freecad_dynamic_cast(node); + + if (expr) { + static const boost::regex e("(\\${0,1})([A-Za-z]+)(\\${0,1})([0-9]+)"); + boost::cmatch cm; + + if (boost::regex_match(expr->name().c_str(), cm, e)) { + const boost::sub_match colstr = cm[2]; + const boost::sub_match rowstr = cm[4]; + int thisRow, thisCol; + + thisCol = decodeColumn(colstr.str()); + thisRow = decodeRow(rowstr.str()); + + if (thisRow >= mRow || thisCol >= mCol) { + thisRow += mRowCount; + thisCol += mColCount; + expr->setName(columnName(thisCol) + rowName(thisRow)); + mChanged = true; + } + } + } + } +private: + int mRow; + int mCol; + int mRowCount; + int mColCount; + bool mChanged; +}; + +void PropertySheet::insertRows(int row, int count) +{ + std::vector keys; + + /* Copy all keys from cells map */ + boost::copy( data | boost::adaptors::map_keys, std::back_inserter(keys)); + + /* Sort them */ + std::sort(keys.begin(), keys.end(), boost::bind(&PropertySheet::rowSortFunc, this, _1, _2)); + + RewriteExpressionVisitor visitor(CellAddress(row, CellAddress::MAX_COLUMNS), count, 0); + + Signaller signaller(*this); + for (std::vector::const_reverse_iterator i = keys.rbegin(); i != keys.rend(); ++i) { + Cell * cell = data.at(*i); + + // Visit each cell to make changes to expressions if necessary + visitor.reset(); + cell->visit(visitor); + if (visitor.changed()) { + setDirty(*i); + recomputeDependencies(*i); + } + + if (i->row() >= row) + moveCell(*i, CellAddress(i->row() + count, i->col())); + } +} + +/** + * Sort function to sort two cell positions according to their row position. + * + */ + +bool PropertySheet::rowSortFunc(const CellAddress & a, const CellAddress & b) { + if (a.row() < b.row()) + return true; + else + return false; +} + +void PropertySheet::removeRows(int row, int count) +{ + std::vector keys; + + /* Copy all keys from cells map */ + boost::copy(data | boost::adaptors::map_keys, std::back_inserter(keys)); + + /* Sort them */ + std::sort(keys.begin(), keys.end(), boost::bind(&PropertySheet::rowSortFunc, this, _1, _2)); + + RewriteExpressionVisitor visitor(CellAddress(row + count, CellAddress::MAX_COLUMNS), -count, 0); + + Signaller signaller(*this); + for (std::vector::const_iterator i = keys.begin(); i != keys.end(); ++i) { + Cell * cell = data.at(*i); + + // Visit each cell to make changes to expressions if necessary + visitor.reset(); + cell->visit(visitor); + if (visitor.changed()) { + setDirty(*i); + recomputeDependencies(*i); + } + + if (i->row() >= row && i->row() < row + count) + clear(*i); + else if (i->row() >= row + count) + moveCell(*i, CellAddress(i->row() - count, i->col())); + } +} + +void PropertySheet::insertColumns(int col, int count) +{ + + std::vector keys; + + /* Copy all keys from cells map */ + boost::copy(data | boost::adaptors::map_keys, std::back_inserter(keys)); + + /* Sort them */ + std::sort(keys.begin(), keys.end()); + + RewriteExpressionVisitor visitor(CellAddress(CellAddress::MAX_ROWS, col), 0, count); + + Signaller signaller(*this); + for (std::vector::const_reverse_iterator i = keys.rbegin(); i != keys.rend(); ++i) { + Cell * cell = data.at(*i); + + // Visit each cell to make changes to expressions if necessary + visitor.reset(); + cell->visit(visitor); + if (visitor.changed()) { + setDirty(*i); + recomputeDependencies(*i); + } + + if (i->col() >= col) + moveCell(*i, CellAddress(i->row(), i->col() + count)); + } +} + +/** + * Sort function to sort two cell positions according to their column position. + * + */ + +bool PropertySheet::colSortFunc(const CellAddress & a, const CellAddress & b) { + if (a.col() < b.col()) + return true; + else + return false; +} + +void PropertySheet::removeColumns(int col, int count) +{ + std::vector keys; + + /* Copy all keys from cells map */ + boost::copy(data | boost::adaptors::map_keys, std::back_inserter(keys)); + + /* Sort them */ + std::sort(keys.begin(), keys.end(), boost::bind(&PropertySheet::colSortFunc, this, _1, _2)); + + RewriteExpressionVisitor visitor(CellAddress(CellAddress::MAX_ROWS, col + count), 0, -count); + + Signaller signaller(*this); + for (std::vector::const_iterator i = keys.begin(); i != keys.end(); ++i) { + Cell * cell = data.at(*i); + + // Visit each cell to make changes to expressions if necessary + visitor.reset(); + cell->visit(visitor); + if (visitor.changed()) { + setDirty(*i); + recomputeDependencies(*i); + } + + if (i->col() >= col && i->col() < col + count) + clear(*i); + else if (i->col() >= col + count) + moveCell(*i, CellAddress(i->row(), i->col() - count)); + } +} + +unsigned int PropertySheet::getMemSize() +{ + return sizeof(*this); +} + + +bool PropertySheet::mergeCells(CellAddress from, CellAddress to) +{ + // Check that this merge is not overlapping other merged cells + for (int r = from.row(); r <= to.row(); ++r) { + for (int c = from.col(); c <= to.col(); ++c) { + if (mergedCells.find(CellAddress(r, c)) != mergedCells.end()) + return false; + } + } + + Signaller signaller(*this); + + // Clear cells that will be hidden by the merge + for (int r = from.row(); r <= to.row(); ++r) + for (int c = from.col(); c <= to.col(); ++c) + if ( !(r == from.row() && c == to.row()) ) + clear(CellAddress(r, c)); + + // Update internal structure to track merged cells + for (int r = from.row(); r <= to.row(); ++r) + for (int c = from.col(); c <= to.col(); ++c) { + mergedCells[CellAddress(r, c)] = from; + setDirty(CellAddress(r, c)); + } + + setSpans(from, to.row() - from.row() + 1, to.col() - from.col() + 1); + + return true; +} + +void PropertySheet::splitCell(CellAddress address) +{ + int rows, cols; + + if (mergedCells.find(address) == mergedCells.end()) + return; + + cellAt(address)->getSpans(rows, cols); + + CellAddress anchor = mergedCells.at(address); + Signaller signaller(*this); + + for (int r = anchor.row(); r <= anchor.row() + rows; ++r) + for (int c = anchor.col(); c <= anchor.col() + cols; ++c) { + setDirty(CellAddress(r, c)); + mergedCells.erase(CellAddress(r, c)); + } + + setSpans(anchor, 1, 1); +} + +void PropertySheet::getSpans(CellAddress address, int & rows, int & cols) const +{ + if (mergedCells.find(address) != mergedCells.end()) { + CellAddress anchor = mergedCells.at(address); + + cellAt(anchor)->getSpans(rows, cols); + } + else { + rows = cols = 1; + } +} + +bool PropertySheet::isMergedCell(CellAddress address) const +{ + return mergedCells.find(address) != mergedCells.end(); +} + +bool PropertySheet::isHidden(CellAddress address) const +{ + return mergedCells.find(address) != mergedCells.end() && mergedCells.at(address) != address; +} + +/** + * Update dependencies of \a expression for cell at \a key. + * + * @param expression Expression to extract dependencies from + * @param key Address of cell containing the expression. + */ + +void PropertySheet::addDependencies(CellAddress key) +{ + Cell * cell = getValue(key); + bool hasUnresolvedDeps = false; + + if (!cell) + return; + + cell->clearResolveException(); + + const Expression * expression = cell->getExpression(); + + if (expression == 0) + return; + + std::set expressionDeps; + + // Resolve expression, if any + ResolveExpressionVisitor v; + cell->visit(v); + + // Get dependencies from expression + expression->getDeps(expressionDeps); + + std::set::const_iterator i = expressionDeps.begin(); + while (i != expressionDeps.end()) { + const Property * prop = (*i).getProperty(); + DocumentObject * docObj = prop ? freecad_dynamic_cast(prop->getContainer()) : 0; + + std::string docName = (*i).getDocumentName().getString(); + std::string docObjName = docName + "#" + (prop ? docObj->getNameInDocument() : (*i).getDocumentObjectName().getString()); + std::string propName = docObjName + "." + (*i).getPropertyName(); + + if (!prop) + cell->setResolveException("Unresolved dependency"); + else { + DocumentObject * docObject = freecad_dynamic_cast(prop->getContainer()); + + documentObjectName[docObject] = docObject->Label.getValue(); + documentName[docObject->getDocument()] = docObject->getDocument()->Label.getValue(); + + if (docObject != owner) { + docDeps.resize(docDeps.size() + 1); + docDeps[docDeps.size() - 1] = docObject; + } + } + + // Observe document to trach changes to the property + owner->observeDocument(docName); + + // Insert into maps + propertyNameToCellMap[propName].insert(key); + cellToPropertyNameMap[key].insert(propName); + + documentObjectToCellMap[docObjName].insert(key); + cellToDocumentObjectMap[key].insert(docObjName); + + ++i; + } +} + +/** + * Remove dependecies given by \a expression for cell at \a key. + * + * @param expression Expression to extract dependencies from + * @param key Address of cell containing the expression + * + */ + +void PropertySheet::removeDependencies(CellAddress key) +{ + std::map >::iterator i1 = cellToPropertyNameMap.find(key); + std::set< std::string >::iterator j; + + /* Remove from Property <-> Key maps */ + + if (i1 == cellToPropertyNameMap.end()) + return; + + j = i1->second.begin(); + + while (j != i1->second.end()) { + propertyNameToCellMap.at(*j).erase(key); + ++j; + } + + cellToPropertyNameMap.erase(i1); + + /* Remove from DocumentObject <-> Key maps */ + + std::map >::iterator i2 = cellToDocumentObjectMap.find(key); + + if (i2 == cellToDocumentObjectMap.end()) + return; + + j = i2->second.begin(); + + while (j != i2->second.end()) { + documentObjectToCellMap.at(*j).erase(key); + ++j; + } + + cellToDocumentObjectMap.erase(i2); +} + +/** + * Recompute any cells that depend on \a prop. + * + * @param prop Property that presumably has changed an triggers updates of other cells. + * + */ + +void PropertySheet::recomputeDependants(const Property *prop) +{ + DocumentObject * owner = freecad_dynamic_cast(prop->getContainer()); + const char * name = owner->getPropertyName(prop); + + assert(name != 0); + + if (owner && name) { + const char * docName = owner->getDocument()->getName(); + const char * nameInDoc = owner->getNameInDocument(); + + if (nameInDoc) { + // Recompute cells that depend on this cell + std::string fullName = std::string(docName) + "#" + std::string(nameInDoc) + "." + std::string(name); + std::map >::const_iterator i = propertyNameToCellMap.find(fullName); + + if (i == propertyNameToCellMap.end()) + return; + + std::set::const_iterator j = i->second.begin(); + std::set::const_iterator end = i->second.end(); + + while (j != end) { + setDirty(*j); + ++j; + } + } + } +} + +void PropertySheet::invalidateDependants(const DocumentObject *docObj) +{ + const char * docName = docObj->getDocument()->getName(); + const char * docObjName = docObj->getNameInDocument(); + + // Touch to force recompute + touch(); + + // Recompute cells that depend on this cell + std::string fullName = std::string(docName) + "#" + std::string(docObjName); + std::map >::const_iterator i = documentObjectToCellMap.find(fullName); + + if (i == documentObjectToCellMap.end()) + return; + + std::set s = i->second; + std::set::const_iterator j = s.begin(); + std::set::const_iterator end = s.end(); + + while (j != end) { + Cell * cell = getValue(*j); + + cell->setResolveException("Unresolved dependency"); + setDirty((*j)); + ++j; + } +} + +void PropertySheet::renamedDocumentObject(const DocumentObject * docObj) +{ + // Touch to force recompute + touch(); + + if (documentObjectName.find(docObj) == documentObjectName.end()) + return; + + std::map::iterator i = data.begin(); + + Signaller signaller(*this); + RelabelDocumentObjectExpressionVisitor v(documentObjectName[docObj], docObj->Label.getValue()); + + while (i != data.end()) { + i->second->visit(v); + recomputeDependencies(i->first); + setDirty(i->first); + ++i; + } +} + +void PropertySheet::renamedDocument(const Document * doc) +{ + // Touch to force recompute + touch(); + + if (documentName.find(doc) == documentName.end()) + return; + + std::map::iterator i = data.begin(); + + /* Resolve all cells */ + Signaller signaller(*this); + RelabelDocumentExpressionVisitor v(documentName[doc], doc->Label.getValue()); + + while (i != data.end()) { + i->second->visit(v); + recomputeDependencies(i->first); + setDirty(i->first); + ++i; + } +} + +void PropertySheet::recomputeDependants(const DocumentObject *docObj) +{ + const char * docName = docObj->getDocument()->getName(); + const char * docObjName = docObj->getNameInDocument(); + + // Touch to force recompute + touch(); + + // Recompute cells that depend on this cell + std::string fullName = std::string(docName) + "#" + std::string(docObjName); + std::map >::const_iterator i = documentObjectToCellMap.find(fullName); + + if (i == documentObjectToCellMap.end()) + return; + + std::set::const_iterator j = i->second.begin(); + std::set::const_iterator end = i->second.end(); + + while (j != end) { + setDirty((*j)); + ++j; + } +} + +const std::set &PropertySheet::getDeps(const std::string &name) const +{ + static std::set empty; + + if (propertyNameToCellMap.find(name) != propertyNameToCellMap.end()) + return propertyNameToCellMap.at(name); + else + return empty; +} + +const std::set &PropertySheet::getDeps(CellAddress pos) const +{ + static std::set empty; + + if (cellToPropertyNameMap.find(pos) != cellToPropertyNameMap.end()) + return cellToPropertyNameMap.at(pos); + else + return empty; +} + +void PropertySheet::recomputeDependencies(CellAddress key) +{ + removeDependencies(key); + addDependencies(key); +} + +PyObject *PropertySheet::getPyObject() +{ + if (PythonObject.is(Py::_None())){ + // ref counter is set to 1 + PythonObject = Py::Object(new PropertySheetPy(this),true); + } + return Py::new_reference_to(PythonObject); +} + +void PropertySheet::resolveAll() +{ + std::map::iterator i = data.begin(); + + /* Resolve all cells */ + Signaller signaller(*this); + while (i != data.end()) { + recomputeDependencies(i->first); + setDirty(i->first); + ++i; + } + touch(); +} + +PropertySheet::Signaller::Signaller(PropertySheet &sheet) + : mSheet(sheet) +{ + if (mSheet.signalCounter == 0) + mSheet.aboutToSetValue(); + mSheet.signalCounter++; +} + +PropertySheet::Signaller::~Signaller() +{ + mSheet.signalCounter--; + if (mSheet.signalCounter == 0) + mSheet.hasSetValue(); +} diff --git a/src/Mod/Spreadsheet/App/PropertySheet.h b/src/Mod/Spreadsheet/App/PropertySheet.h new file mode 100644 index 0000000000..07402dad5b --- /dev/null +++ b/src/Mod/Spreadsheet/App/PropertySheet.h @@ -0,0 +1,218 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef PROPERTYSHEET_H +#define PROPERTYSHEET_H + +#include +#include +#include +#include +#include +#include "Cell.h" + +namespace Spreadsheet +{ + +class Sheet; +class PropertySheet; +class SheetObserver; + +class PropertySheet : public App::Property { + TYPESYSTEM_HEADER(); +public: + + PropertySheet(Sheet * _owner = 0); + + PropertySheet(const PropertySheet & other); + + ~PropertySheet(); + + virtual Property *Copy(void) const; + + virtual void Paste(const Property &from); + + virtual void Save (Base::Writer & writer) const; + + virtual void Restore(Base::XMLReader & reader); + + Cell *createCell(CellAddress address); + + void setValue() { } + + void setContent(CellAddress address, const char * value); + + void setAlignment(CellAddress address, int _alignment); + + void setStyle(CellAddress address, const std::set & _style); + + void setForeground(CellAddress address, const App::Color &color); + + void setBackground(CellAddress address, const App::Color &color); + + void setDisplayUnit(CellAddress address, const std::string & unit); + + void setAlias(CellAddress address, const std::string &alias); + + void setComputedUnit(CellAddress address, const Base::Unit & unit); + + void setSpans(CellAddress address, int rows, int columns); + + void clear(CellAddress address); + + void clear(); + + Cell * getValue(CellAddress key); + + std::set getUsedCells() const; + + Sheet * sheet() const { return owner; } + + const std::set & getDirty() { return dirty; } + + void setDirty(CellAddress address); + + void clearDirty(CellAddress key) { dirty.erase(key); } + + void clearDirty() { dirty.clear(); purgeTouched(); } + + bool isDirty() const { return dirty.size() > 0; } + + void moveCell(CellAddress currPos, CellAddress newPos); + + void insertRows(int row, int count); + + void removeRows(int row, int count); + + void insertColumns(int col, int count); + + void removeColumns(int col, int count); + + unsigned int getMemSize (void); + + bool mergeCells(CellAddress from, CellAddress to); + + void splitCell(CellAddress address); + + void getSpans(CellAddress address, int &rows, int &cols) const; + + bool isMergedCell(CellAddress address) const; + + bool isHidden(CellAddress address) const; + + const std::set< CellAddress > & getDeps(const std::string & name) const; + + const std::set &getDeps(CellAddress pos) const; + + const std::vector & getDocDeps() const { return docDeps; } + + class Signaller { + public: + Signaller(PropertySheet & sheet); + ~Signaller(); + private: + PropertySheet & mSheet; + }; + + void recomputeDependencies(CellAddress key); + + PyObject *getPyObject(void); + + void resolveAll(); + + void invalidateDependants(const App::DocumentObject *docObj); + + void renamedDocumentObject(const App::DocumentObject *docObj); + + void renamedDocument(const App::Document *doc); + +private: + + friend class Signaller; + + friend class SheetObserver; + + Cell *cellAt(CellAddress address); + + Cell *nonNullCellAt(CellAddress address); + + const Cell *cellAt(CellAddress address) const; + + bool colSortFunc(const CellAddress &a, const CellAddress &b); + + bool rowSortFunc(const CellAddress &a, const CellAddress &b); + + friend class Cell; + + std::map data; + + std::set dirty; + + /* Merged cells; cell -> anchor cell */ + std::map mergedCells; + + Sheet * owner; + + /* + * Cell dependency tracking + */ + + void addDependencies(CellAddress key); + + void removeDependencies(CellAddress key); + + void recomputeDependants(const App::Property * prop); + + void recomputeDependants(const App::DocumentObject * docObj); + + /* Cell dependencies, i.e when a change occurs to property given in key, + the set of addresses needs to be recomputed. + */ + std::map > propertyNameToCellMap; + + /* Properties this cell depends on */ + std::map > cellToPropertyNameMap; + + /* Cell dependencies, i.e when a change occurs to documentObject given in key, + the set of addresses needs to be recomputed. + */ + std::map > documentObjectToCellMap; + + /* DocumentObject this cell depends on */ + std::map > cellToDocumentObjectMap; + + /* Other document objects the sheet depends on */ + std::vector docDeps; + + /* Name of document objects, used for renaming */ + std::map documentObjectName; + + /* Name of documents, used for renaming */ + std::map documentName; + + int signalCounter; + + Py::Object PythonObject; +}; + +} +#endif // PROPERTYSHEET_H diff --git a/src/Mod/Spreadsheet/App/PropertySheetPy.xml b/src/Mod/Spreadsheet/App/PropertySheetPy.xml new file mode 100644 index 0000000000..14125a8540 --- /dev/null +++ b/src/Mod/Spreadsheet/App/PropertySheetPy.xml @@ -0,0 +1,19 @@ + + + + + + + Internal spreadsheet object + + + diff --git a/src/Mod/Spreadsheet/App/Range.cpp b/src/Mod/Spreadsheet/App/Range.cpp new file mode 100644 index 0000000000..c76d1cf384 --- /dev/null +++ b/src/Mod/Spreadsheet/App/Range.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#include "Range.h" +#include +#include + +using namespace Spreadsheet; + +Range::Range(const char * range) +{ + std::string from; + std::string to; + + assert(range != NULL); + + if (strchr(range, ':') == NULL) { + from = range; + to = range; + } + else { + std::string s = range; + from = s.substr(0, s.find(':')); + to = s.substr(s.find(':') + 1); + } + + CellAddress begin(from); + CellAddress end(to); + + row_begin = begin.row(); + col_begin = begin.col(); + row_end = end.row(); + col_end = end.col(); + + row_curr = row_begin; + col_curr = col_begin; +} + +Range::Range(int _row_begin, int _col_begin, int _row_end, int _col_end) + : row_curr(_row_begin) + , col_curr(_col_begin) + , row_begin(_row_begin) + , col_begin(_col_begin) + , row_end(_row_end) + , col_end(_col_end) +{ +} + +bool Range::next() +{ + if (row_curr < row_end) { + row_curr++; + + return true; + } + if (col_curr < col_end) { + if (row_curr == row_end + 1) + return false; + row_curr = row_begin; + ++col_curr; + return true; + } + return false; +} + + diff --git a/src/Mod/Spreadsheet/App/Range.h b/src/Mod/Spreadsheet/App/Range.h new file mode 100644 index 0000000000..2c94d15b02 --- /dev/null +++ b/src/Mod/Spreadsheet/App/Range.h @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef RANGE_H +#define RANGE_H + +#include "Utils.h" + +namespace Spreadsheet { + +/** + * @brief The Range class is a spreadsheet range iterator. It takes + * a starting (row, col) and an ending (row, col). Notice that ranges + * are always at least one element. The next() functions is therefore + * used e.g as follows: + * + * do { + * ... + * while (range.next()); + * + */ + +class SpreadsheetExport Range { +public: + Range(const char *range); + + Range(int _row_begin, int _col_begin, int _row_end, int _col_end); + + bool next(); + + /** Current row */ + inline int row() const { return row_curr; } + + /** Current column */ + inline int column() const { return col_curr; } + + /** Position of start of range */ + inline CellAddress from() const { return CellAddress(row_begin, col_begin); } + + /** Position of end of range */ + inline CellAddress to() const { return CellAddress(row_end, col_end); } + + /** Start of range as a string */ + inline std::string fromCellString() const { return addressToString(CellAddress(row_begin, col_begin)); } + + /** End of range as a string */ + inline std::string toCellString() const { return addressToString(CellAddress(row_end, col_end)); } + + /** Current cell as a string */ + inline std::string address() const { return addressToString(CellAddress(row_curr, col_curr)); } + + /** The raneg as a string */ + inline std::string rangeString() const { + return addressToString(CellAddress(row_begin, col_begin)) + ":" + addressToString(CellAddress(row_end, col_end)); + } + + CellAddress operator*() const { return CellAddress(row_curr, col_curr); } + + /** Number of elements in range */ + inline int size() const { return (row_end - row_begin + 1) * (col_end - col_begin + 1); } + +private: + int row_curr, col_curr; + int row_begin, col_begin; + int row_end, col_end; +}; + +} + +#endif // RANGE_H diff --git a/src/Mod/Spreadsheet/App/Sheet.cpp b/src/Mod/Spreadsheet/App/Sheet.cpp new file mode 100644 index 0000000000..586ddd7f0c --- /dev/null +++ b/src/Mod/Spreadsheet/App/Sheet.cpp @@ -0,0 +1,1087 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Expression.h" +#include "Sheet.h" +#include "SheetObserver.h" +#include "Utils.h" +#include "Range.h" +#include "SheetPy.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace Spreadsheet; +using namespace App; + +PROPERTY_SOURCE(Spreadsheet::Sheet, App::DocumentObject) + +typedef boost::adjacency_list < +boost::vecS, // class OutEdgeListS : a Sequence or an AssociativeContainer +boost::vecS, // class VertexListS : a Sequence or a RandomAccessContainer +boost::directedS, // class DirectedS : This is a directed graph +boost::no_property, // class VertexProperty: +boost::no_property, // class EdgeProperty: +boost::no_property, // class GraphProperty: +boost::listS // class EdgeListS: +> DependencyList; +typedef boost::graph_traits Traits; +typedef Traits::vertex_descriptor Vertex; +typedef Traits::edge_descriptor Edge; + +/** + * Construct a new Sheet object. + */ + +Sheet::Sheet() + : App::DocumentObject() + , props(this) + , cells(this) +{ + ADD_PROPERTY_TYPE(docDeps, (0), "Spreadsheet", (App::PropertyType)(App::Prop_Transient|App::Prop_ReadOnly|App::Prop_Hidden), "Dependencies"); + ADD_PROPERTY_TYPE(cells, (), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Cell contents"); + ADD_PROPERTY_TYPE(columnWidths, (), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Column widths"); + ADD_PROPERTY_TYPE(rowHeights, (), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Row heights"); + ADD_PROPERTY_TYPE(currRow, (0), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Current row"); + ADD_PROPERTY_TYPE(currColumn, (0), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Current column"); + + docDeps.setSize(0); + + onRenamedDocumentConnection = App::GetApplication().signalRenameDocument.connect(boost::bind(&Spreadsheet::Sheet::onRenamedDocument, this, _1)); + onRelabledDocumentConnection = App::GetApplication().signalRelabelDocument.connect(boost::bind(&Spreadsheet::Sheet::onRelabledDocument, this, _1)); +} + +Sheet::~Sheet() +{ + clearAll(); +} + +/** + * Clear all cells in the sheet. + */ + +void Sheet::clearAll() +{ + cells.clear(); + + std::vector propNames = props.getDynamicPropertyNames(); + + for (std::vector::const_iterator i = propNames.begin(); i != propNames.end(); ++i) + props.removeDynamicProperty((*i).c_str()); + + propAddress.clear(); + + for (ObserverMap::iterator i = observers.begin(); i != observers.end(); ++i) + delete i->second; +} + +/** + * Import a file into the spreadsheet object. + * + * @param filename Name of file to import + * @param delimiter The field delimiter charater used. + * @param quoteChar Quote character, if any (set to '\0' to disable). + * @param escapeChar The escape character used, if any (set to '0' to disable). + * + * @returns True if successful, false if something failed. + */ + +bool Sheet::importFromFile(const std::string &filename, char delimiter, char quoteChar, char escapeChar) +{ + std::ifstream file; + int row = 0; + + PropertySheet::Signaller signaller(cells); + + clearAll(); + + file.open(filename.c_str(), std::ios::in); + + if (file.is_open()) { + std::string line; + + while (std::getline(file, line)) { + using namespace boost; + + try { + escaped_list_separator e; + int col = 0; + + if (quoteChar) + e = escaped_list_separator(escapeChar, delimiter, quoteChar); + else + e = escaped_list_separator('\0', delimiter, '\0'); + + tokenizer > tok(line, e); + + for(tokenizer >::iterator i = tok.begin(); i != tok.end();++i) { + if ((*i).size() > 0) + setCell(CellAddress(row, col), (*i).c_str()); + col++; + } + } + catch (...) { + return false; + } + + ++row; + } + file.close(); + return true; + } + else + return false; +} + +/** + * Write an escaped version of the string \a s to the stream \a out. + * + * @param s The string to write. + * @param quoteChar The quote character. + * @param escapeChar The escape character. + * @param stream The stream to output the escaped string to. + * + */ + +static void writeEscaped(std::string const& s, char quoteChar, char escapeChar, std::ostream & out) { + out << quoteChar; + for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) { + unsigned char c = *i; + if (c != quoteChar) + out << c; + else { + out << escapeChar; + out << c; + } + } + out << quoteChar; +} + +/** + * Export spreadsheet data to file. + * + * @param filename Filename to store data to. + * @param delimiter Field delimiter + * @param quoteChar Quote character ('\0' to disable) + * @param escapeChar Escape character ('\0' to disable) + * + * @returns True if store is successful, false if something failed. + * + */ + +bool Sheet::exportToFile(const std::string &filename, char delimiter, char quoteChar, char escapeChar) const +{ + std::ofstream file; + int row, col, prevRow = -1, prevCol = -1; + + file.open(filename.c_str(), std::ios::out | std::ios::ate | std::ios::binary); + + if (!file.is_open()) + return false; + + std::set usedCells = cells.getUsedCells(); + std::set::const_iterator i = usedCells.begin(); + + while (i != usedCells.end()) { + Property * prop = getProperty(*i); + + if (prevRow != -1 && prevRow != i->row()) { + for (int j = prevRow; j < i->row(); ++j) + file << std::endl; + prevCol = 0; + } + if (prevCol != -1 && i->col() != prevCol) { + for (int j = prevCol; j < i->col(); ++j) + file << delimiter; + } + + std::stringstream field; + + if (prop->isDerivedFrom((PropertyQuantity::getClassTypeId()))) + field << static_cast(prop)->getValue(); + else if (prop->isDerivedFrom((PropertyFloat::getClassTypeId()))) + field << static_cast(prop)->getValue(); + else if (prop->isDerivedFrom((PropertyString::getClassTypeId()))) + field << static_cast(prop)->getValue(); + else + assert(0); + + std::string str = field.str(); + + if (quoteChar && str.find(quoteChar) != std::string::npos) + writeEscaped(str, quoteChar, escapeChar, file); + else + file << str; + + prevRow = i->row(); + prevCol = i->col(); + ++i; + } + file << std::endl; + file.close(); + + return true; +} + +/** + * Merge a rectangle specified by \a from and \a to into one logical cell. + * Data in all but the upper right cell are cleared when the cells are merged. + * + * @returns True if the cells were merged, false if the merge was unsuccessful. + * + */ + +bool Sheet::mergeCells(const Range & range) +{ + return cells.mergeCells(range.from(), range.to()); +} + +/** + * Split a previously merged cell specified by \a address into its individual cells. + * The address can point to any of the cells that make up the merged cell. + * + * @param address Address of cell to split + * + */ + +void Sheet::splitCell(CellAddress address) +{ + cells.splitCell(address); +} + +/** + * Get contents of the cell specified by \a key, or 0 if it is not defined + * + * @returns A CellContent object or 0. + */ + +Cell *Sheet::getCell(CellAddress address) +{ + return cells.getValue(address); +} + +/** + * Get cell contents specified by (\a row, \a col). + * + */ + +Cell *Sheet::getNewCell(CellAddress address) +{ + Cell * cell = getCell(address); + + if (cell == 0) + cell = cells.createCell(address); + + return cell; +} + +/** + * Convert given \a key address to string. + * + * @param key Address of cell. + * + * @returns Address given as a string. + */ + +std::string Sheet::toAddress(CellAddress key) +{ + return Spreadsheet::addressToString(key); +} + +/** + * Set cell given by \a address to \a contents. + * + * @param address Address of cell to set. + * @param contents New contents of given cell. + * + */ + +void Sheet::setCell(const char * address, const char * contents) +{ + assert(address != 0 && contents != 0); + + setCell(CellAddress(address), contents); +} + +/** + * Set cell at \a row, \a col to \a expression. The original string given by the user + * is specified in \a value. If a merged cell is specified, the upper right corner of the + * merged cell must be specified. + * + * @param row Row position of cell. + * @param col Column position of cell. + * @param value String value of original expression. + * + */ + +void Sheet::setCell(CellAddress address, const char * value) +{ + Expression * e; + + assert(value != 0); + + + if (*value == '\0') { + clear(address, false); + return; + } + + // Update expression, delete old first if necessary + Cell * cell = getNewCell(address); + + if (cell->getExpression()) { + setContent(address, 0); + } + setContent(address, value); + + // Recompute dependencies + touch(); +} + +/** + * Get the Python object for the Sheet. + * + * @returns The Python object. + */ + +PyObject *Sheet::getPyObject(void) +{ + if (PythonObject.is(Py::_None())){ + // ref counter is set to 1 + PythonObject = Py::Object(new SheetPy(this),true); + } + return Py::new_reference_to(PythonObject); +} + +/** + * Get the Cell Property for the cell at \a key. + * + * @returns The Property object. + * + */ + +Property * Sheet::getProperty(CellAddress key) const +{ + return props.getDynamicPropertyByName(toAddress(key).c_str()); +} + +Property * Sheet::getProperty(const char * addr) const +{ + return props.getDynamicPropertyByName(addr); +} + +/** + * Get the address as (\a row, \a col) of the Property \a prop. This function + * throws an exception if the property is not found. + * + */ + +void Sheet::getCellAddress(const Property *prop, CellAddress & address) +{ + std::map::const_iterator i = propAddress.find(prop); + + if (i != propAddress.end()) + address = i->second; + else + throw Base::Exception("Property is not a cell"); +} + +std::map Sheet::getColumnWidths() const +{ + return columnWidths.getValues(); +} + +std::map Sheet::getRowHeights() const +{ + return rowHeights.getValues(); +} + +void Sheet::setPosition(CellAddress address) +{ + currRow.setValue(address.row()); + currColumn.setValue(address.col()); + currRow.purgeTouched(); + currColumn.purgeTouched(); +} + +/** + * Set the property for cell \key to a PropertyFloat with the value \a value. + * If the Property exists, but of wrong type, the previous Property is destroyed and recreated as the correct type. + * + * @param key The address of the cell we want to create a Property for + * @param value The value we want to assign to the Property. + * + */ + +Property * Sheet::setFloatProperty(CellAddress key, double value) +{ + Property * prop = props.getPropertyByName(toAddress(key).c_str()); + PropertyFloat * floatProp; + + if (!prop || prop->getTypeId() != PropertyFloat::getClassTypeId()) { + if (prop) { + props.removeDynamicProperty(toAddress(key).c_str()); + propAddress.erase(prop); + + std::map::iterator i = aliasProp.find(key); + if (i != aliasProp.end()) { + props.removeDynamicProperty(props.getPropertyName(i->second)); + aliasProp.erase(i); + } + } + floatProp = freecad_dynamic_cast(props.addDynamicProperty("App::PropertyFloat", toAddress(key).c_str(), 0, 0, Prop_ReadOnly | Prop_Transient, true, true)); + floatProp->StatusBits.set(3); + } + else + floatProp = static_cast(prop); + + propAddress[floatProp] = key; + floatProp->setValue(value); + + return floatProp; +} + +/** + * Set the property for cell \key to a PropertyQuantity with \a value and \a unit. + * If the Property exists, but of wrong type, the previous Property is destroyed and recreated as the correct type. + * + * @param key The address of the cell we want to create a Property for + * @param value The value we want to assign to the Property. + * @param unit The associated unit for \a value. + * + */ + +Property * Sheet::setQuantityProperty(CellAddress key, double value, const Base::Unit & unit) +{ + int row, col; + Property * prop = props.getPropertyByName(toAddress(key).c_str()); + PropertyQuantity * quantityProp; + + if (!prop || prop->getTypeId() != PropertyQuantity::getClassTypeId()) { + if (prop) { + props.removeDynamicProperty(toAddress(key).c_str()); + propAddress.erase(prop); + + std::map::iterator i = aliasProp.find(key); + if (i != aliasProp.end()) { + props.removeDynamicProperty(props.getPropertyName(i->second)); + aliasProp.erase(i); + } + } + Property * p = props.addDynamicProperty("App::PropertyQuantity", toAddress(key).c_str(), 0, 0, Prop_ReadOnly | Prop_Transient, true, true); + quantityProp = freecad_dynamic_cast(p); + quantityProp->StatusBits.set(3); + } + else + quantityProp = static_cast(prop); + + propAddress[quantityProp] = key; + quantityProp->setValue(value); + quantityProp->setUnit(unit); + + cells.setComputedUnit(key, unit); + + return quantityProp; +} + +/** + * Set the property for cell \key to a PropertyString with \a value. + * If the Property exists, but of wrong type, the previous Property is destroyed and recreated as the correct type. + * + * @param key The address of the cell we want to create a Property for + * @param value The value we want to assign to the Property. + * + */ + +Property * Sheet::setStringProperty(CellAddress key, const std::string & value) +{ + Property * prop = props.getPropertyByName(toAddress(key).c_str()); + PropertyString * stringProp = freecad_dynamic_cast(prop); + + if (!stringProp) { + if (prop) { + props.removeDynamicProperty(toAddress(key).c_str()); + propAddress.erase(prop); + + std::map::iterator i = aliasProp.find(key); + if (i != aliasProp.end()) { + props.removeDynamicProperty(props.getPropertyName(i->second)); + aliasProp.erase(i); + } + } + stringProp = freecad_dynamic_cast(props.addDynamicProperty("App::PropertyString", toAddress(key).c_str(), 0, 0, Prop_ReadOnly | Prop_Transient, true, true)); + stringProp->StatusBits.set(3); + } + + propAddress[stringProp] = key; + stringProp->setValue(value.c_str()); + + return stringProp; +} + +/** + * Update the Propery given by \a key. This will also eventually trigger recomputations of cells depending on \a key. + * + * @param key The address of the cell we want to recompute. + * + */ + +void Sheet::updateProperty(CellAddress key) +{ + const Property * prop; + const char * aliasType = 0; + + Cell * cell = getCell(key); + std::string alias; + + if (cell != 0) { + Expression * output; + const Expression * input = cell->getExpression(); + + if (input) { + output = input->eval(); + } + else { + std::string s; + + if (cell->getStringContent(s)) + output = new StringExpression(this, s); + else + output = new StringExpression(this, ""); + } + + /* Eval returns either NumberExpression or StringExpression objects */ + if (freecad_dynamic_cast(output)) { + NumberExpression * number = static_cast(output); + if (number->getUnit().isEmpty()) { + prop = setFloatProperty(key, number->getValue()); + aliasType = "App::PropertyFloat"; + } + else { + prop = setQuantityProperty(key, number->getValue(), number->getUnit()); + aliasType = "App::PropertyQuantity"; + } + } + else { + prop = setStringProperty(key, freecad_dynamic_cast(output)->getText().c_str()); + aliasType = "App::PropertyString"; + } + + delete output; + } + else + clear(key); + + if (cell && cell->getAlias(alias)) { + /* Update or create alias? */ + if (aliasProp.find(key) == aliasProp.end()) + aliasProp[key] = props.addDynamicProperty(aliasType, alias.c_str(), 0, 0, Prop_ReadOnly | Prop_Transient, true, true); + aliasProp[key]->Paste(*prop); + } + else { + /* Remove alias? */ + std::map::iterator i = aliasProp.find(key); + if (i != aliasProp.end()) { + props.removeDynamicProperty(props.getPropertyName(i->second)); + aliasProp.erase(i); + } + } + + cellUpdated(key); +} + +/** + * Retrieve a specifc Property given by \a name. + * This function might throw an exception if something fails, but might also + * return 0 in case the property is not found. + * + * @returns The property, or 0 if not found. + * + */ + +Property *Sheet::getPropertyByName(const char* name) const +{ + Property * prop = getProperty(name); + + if (prop) + return prop; + else + return DocumentObject::getPropertyByName(name); +} + +const char *Sheet::getPropertyName(const Property *prop) const +{ + const char * name = props.getPropertyName(prop); + + if (name) + return name; + else + return PropertyContainer::getPropertyName(prop); +} + +void Sheet::recomputeCell(CellAddress p) +{ + Cell * cell = cells.getValue(p); + std::string docName = getDocument()->getName(); + std::string docObjName = std::string(getNameInDocument()); + std::string name = docName + "#" + docObjName + "." + toAddress(p); + + try { + if (cell) { + cell->clearException(); + cell->clearResolveException(); + } + updateProperty(p); + cells.clearDirty(p); + cellErrors.erase(p); + } + catch (const Base::Exception & e) { + QString msg = QString::fromUtf8("ERR: %1").arg(QString::fromUtf8(e.what())); + + setStringProperty(p, msg.toStdString()); + if (cell) + cell->setException(e.what()); + + // Mark as erronous + cellErrors.insert(p); + } + + if (!cell || cell->spansChanged()) + cellSpanChanged(p); +} + +/** + * Update the document properties. + * + */ + +App::DocumentObjectExecReturn *Sheet::execute(void) +{ + // Get dirty cells that we have to recompute + std::set dirtyCells = cells.getDirty(); + + // Always recompute cells that have failed + for (std::set::const_iterator i = cellErrors.begin(); i != cellErrors.end(); ++i) { + cells.recomputeDependencies(*i); + dirtyCells.insert(*i); + } + + // Push dirty cells onto queue + for (std::set::const_iterator i = dirtyCells.begin(); i != dirtyCells.end(); ++i) { + // Create queue and a graph structure to compute order of evaluation + std::deque workQueue; + DependencyList graph; + std::map VertexList; + std::map VertexIndexList; + + workQueue.push_back(*i); + + while (workQueue.size() > 0) { + CellAddress currPos = workQueue.front(); + std::set s; + + // Get other cells that depends on the current cell (currPos) + providesTo(currPos, s); + workQueue.pop_front(); + + // Insert into map of CellPos -> Index, if it doesn't exist already + if (VertexList.find(currPos) == VertexList.end()) { + VertexList[currPos] = add_vertex(graph); + VertexIndexList[VertexList[currPos]] = currPos; + } + + // Process cells that depend on the current cell + std::set::const_iterator i = s.begin(); + while (i != s.end()) { + // Insert into map of CellPos -> Index, if it doesn't exist already + if (VertexList.find(*i) == VertexList.end()) { + VertexList[*i] = add_vertex(graph); + VertexIndexList[VertexList[*i]] = *i; + workQueue.push_back(*i); + } + // Add edge to graph to signal dependency + add_edge(VertexList[currPos], VertexList[*i], graph); + ++i; + } + } + + // Compute cells + std::list make_order; + + // Sort graph topologically to find evaluation order + try { + boost::topological_sort(graph, std::front_inserter(make_order)); + + // Recompute cells + std::list::const_iterator i = make_order.begin(); + while (i != make_order.end()) { + recomputeCell(VertexIndexList[*i]); + ++i; + } + } + catch (std::exception) { + // Cycle detected; flag all with errors + + std::map::const_iterator i = VertexList.begin(); + while (i != VertexList.end()) { + Cell * cell = cells.getValue(i->first); + + // Mark as erronous + cellErrors.insert(i->first); + + if (cell) + cell->setException("Circular dependency."); + updateProperty(i->first); + ++i; + } + } + + } + + // Signal update of column widths + const std::set & dirtyColumns = columnWidths.getDirty(); + + for (std::set::const_iterator i = dirtyColumns.begin(); i != dirtyColumns.end(); ++i) + columnWidthChanged(*i, columnWidths.getValue(*i)); + + // Signal update of row heights + const std::set & dirtyRows = rowHeights.getDirty(); + + for (std::set::const_iterator i = dirtyRows.begin(); i != dirtyRows.end(); ++i) + rowHeightChanged(*i, rowHeights.getValue(*i)); + + //cells.clearDirty(); + rowHeights.clearDirty(); + columnWidths.clearDirty(); + + positionChanged(CellAddress(currRow.getValue(), currColumn.getValue())); + + currRow.purgeTouched(); + currColumn.purgeTouched(); + + docDeps.setValues(cells.getDocDeps()); + + purgeTouched(); + + if (cellErrors.size() == 0) + return App::DocumentObject::StdReturn; + else + return new DocumentObjectExecReturn("One or more cells failed contains errors.", this); +} + +/** + * Unimplemented. + * + */ + +short Sheet::mustExecute(void) const +{ + if (cellErrors.size() > 0 || cells.isTouched() || columnWidths.isTouched() || rowHeights.isTouched()) + return 1; + else if (cells.getDocDeps().size() == 0) + return 0; + else + return -1; +} + + + +/** + * Clear the cell at \a address. If \a all is false, only the text or expression + * contents are cleared. If \a all is true everything in the cell + * is cleared, including color, style, etc. + * + * @param address Address of cell to clear + * @param all Whether we should clear all or not. + * + */ + +void Sheet::clear(CellAddress address, bool all) +{ + std::string addr = toAddress(address); + Property * prop = props.getDynamicPropertyByName(addr.c_str()); + + cells.clear(address); + + propAddress.erase(prop); + props.removeDynamicProperty(addr.c_str()); +} + +/** + * Get row an column span for the cell at (row, col). + * + * @param row Row address of cell + * @param col Column address of cell + * @param rows The number of unit cells this cell spans + * @param cols The number of unit rows this cell spans + * + */ + +void Sheet::getSpans(CellAddress address, int &rows, int &cols) const +{ + return cells.getSpans(address, rows, cols); +} + +/** + * Determine whether this cell is merged with another or not. + * + * @param row + * @param col + * + * @returns True if cell is merged, false if not. + * + */ + +bool Sheet::isMergedCell(CellAddress address) const +{ + return cells.isMergedCell(address); +} + +void Sheet::setColumnWidth(int col, int width) +{ + columnWidths.setValue(col, width); +} + +int Sheet::getColumnWidth(int col) const +{ + return columnWidths.getValue(col); +} + +void Sheet::setRowHeight(int row, int height) +{ + rowHeights.setValue(row, height); +} + +int Sheet::getRowHeight(int row) const +{ + return rowHeights.getValue(row); +} + +/** + * Get a vector of strings with addresses of all used cells. + * + * @returns vector of strings. + * + */ + +std::vector Sheet::getUsedCells() const +{ + std::vector usedCells; + + // Insert int usedSet + std::set usedSet = cells.getUsedCells(); + + for (std::set::const_iterator i = usedSet.begin(); i != usedSet.end(); ++i) + usedCells.push_back(toAddress(*i)); + + return usedCells; +} + +/** + * Insert \a count columns at before column \a col in the spreadsheet. + * + * @param col Address of column where the columns are inserted. + * @param count Number of columns to insert + * + */ + +void Sheet::insertColumns(int col, int count) +{ + + cells.insertColumns(col, count); +} + +/** + * Remove \a count columns at column \a col. + * + * @param col Address of first column to remove. + * @param count Number of columns to remove. + * + */ + +void Sheet::removeColumns(int col, int count) +{ + cells.removeColumns(col, count); +} + +/** + * Inser \a count rows at row \a row. + * + * @param row Address of row where the rows are inserted. + * @param count Number of rows to insert. + * + */ + +void Sheet::insertRows(int row, int count) +{ + cells.insertRows(row, count); +} + +/** + * Remove \a count rows starting at \a row from the spreadsheet. + * + * @param row Address of first row to remove. + * @param count Number of rows to remove. + * + */ + +void Sheet::removeRows(int row, int count) +{ + cells.removeRows(row, count); +} + +void Sheet::setContent(CellAddress address, const char *value) +{ + cells.setContent(address, value); +} + +void Sheet::setAlignment(CellAddress address, int _alignment) +{ + cells.setAlignment(address, _alignment); +} + +void Sheet::setStyle(CellAddress address, const std::set &_style) +{ + cells.setStyle(address, _style); +} + +void Sheet::setForeground(CellAddress address, const Color &color) +{ + cells.setForeground(address, color); +} + +void Sheet::setBackground(CellAddress address, const Color &color) +{ + cells.setBackground(address, color); +} + +void Sheet::setDisplayUnit(CellAddress address, const std::string &unit) +{ + cells.setDisplayUnit(address, unit); +} + +void Sheet::setComputedUnit(CellAddress address, const Base::Unit &unit) +{ + cells.setComputedUnit(address, unit); +} + +void Sheet::setAlias(CellAddress address, const std::string &alias) +{ + cells.setAlias(address, alias); +} + +void Sheet::setSpans(CellAddress address, int rows, int columns) +{ + cells.setSpans(address, rows, columns); +} + +/** + * Move a cell from \a currPos to \a newPos. If the cell at new position + * contains data, it is overwritten by the move. + * + */ + +void Sheet::moveCell(CellAddress currPos, CellAddress newPos) +{ + cells.moveCell(currPos, newPos); +} + +void Sheet::renamedDocumentObject(const App::DocumentObject * docObj) +{ + cells.renamedDocumentObject(docObj); + cells.touch(); +} + +std::set Sheet::dependsOn(CellAddress address) const +{ + return cells.getDeps(address); +} + +void Sheet::providesTo(CellAddress address, std::set & result) const +{ + const char * docName = getDocument()->getName(); + const char * docObjName = getNameInDocument(); + std::string fullName = std::string(docName) + "#" + std::string(docObjName) + "." + toAddress(address); + std::set tmpResult = cells.getDeps(fullName); + + for (std::set::const_iterator i = tmpResult.begin(); i != tmpResult.end(); ++i) + result.insert(std::string(docName) + "#" + std::string(docObjName) + "." + toAddress(*i)); +} + +void Sheet::providesTo(CellAddress address, std::set & result) const +{ + const char * docName = getDocument()->getName(); + const char * docObjName = getNameInDocument(); + std::string fullName = std::string(docName) + "#" + std::string(docObjName) + "." + toAddress(address); + result = cells.getDeps(fullName); +} + +void Sheet::onDocumentRestored() +{ + cells.resolveAll(); + execute(); +} + +void Sheet::onRelabledDocument(const Document &document) +{ + cells.renamedDocument(&document); +} + +void Sheet::onRenamedDocument(const Document &document) +{ +} + +void Sheet::observeDocument(const std::string & docName) +{ + ObserverMap::const_iterator it = observers.find(docName); + if (it != observers.end()) { + // An observer already exists, increase reference counter for it + it->second->ref(); + } + else { + // Create a new observer + SheetObserver * observer = new SheetObserver(GetApplication().getDocument(docName.c_str()), &cells); + + observers[docName] = observer; + } +} diff --git a/src/Mod/Spreadsheet/App/Sheet.h b/src/Mod/Spreadsheet/App/Sheet.h new file mode 100644 index 0000000000..d39d06d862 --- /dev/null +++ b/src/Mod/Spreadsheet/App/Sheet.h @@ -0,0 +1,281 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef Spreadsheet_Spreadsheet_H +#define Spreadsheet_Spreadsheet_H + +#ifdef signals +#undef signals +#define signals signals +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "PropertySheet.h" +#include "PropertyColumnWidths.h" +#include "PropertyRowHeights.h" +#include "Utils.h" + +namespace Spreadsheet +{ + +class Sheet; +class Cell; +class Expression; +class Range; +class SheetObserver; + + +class SpreadsheetExport Sheet : public App::DocumentObject +{ + PROPERTY_HEADER(Sheet::Sheet); + +public: + + /// Constructor + Sheet(); + virtual ~Sheet(); + + /// returns the type name of the ViewProvider + virtual const char* getViewProviderName(void) const { + return "SpreadsheetGui::ViewProviderSheet"; + } + + bool importFromFile(const std::string & filename, char delimiter = '\t', char quoteChar = '\0', char escapeChar = '\\'); + + bool exportToFile(const std::string & filename, char delimiter = '\t', char quoteChar = '\0', char escapeChar = '\\') const; + + bool mergeCells(const Range &range); + + void splitCell(CellAddress address); + + Cell * getCell(CellAddress address); + + Cell *getNewCell(CellAddress address); + + void setCell(const char *address, const char *value); + + void setCell(CellAddress address, const char *value); + + void clearAll(); + + void clear(CellAddress address, bool all = true); + + void getSpans(CellAddress address, int & rows, int & cols) const; + + bool isMergedCell(CellAddress address) const; + + void setColumnWidth(int col, int width); + + int getColumnWidth(int col) const; + + void setRowHeight(int row, int height); + + int getRowHeight(int row) const; + + std::vector getUsedCells() const; + + void insertColumns(int col, int count); + + void removeColumns(int col, int count); + + void insertRows(int row, int count); + + void removeRows(int row, int count); + + void setContent(CellAddress address, const char * value); + + void setAlignment(CellAddress address, int _alignment); + + void setStyle(CellAddress address, const std::set & _style); + + void setForeground(CellAddress address, const App::Color &color); + + void setBackground(CellAddress address, const App::Color &color); + + void setDisplayUnit(CellAddress address, const std::string & unit); + + void setComputedUnit(CellAddress address, const Base::Unit & unit); + + void setAlias(CellAddress address, const std::string & alias); + + void setSpans(CellAddress address, int rows, int columns); + + std::set dependsOn(CellAddress address) const; + + void providesTo(CellAddress address, std::set & result) const; + + PyObject *getPyObject(); + + App::Property *getPropertyByName(const char *name) const; + + const char* getPropertyName(const App::Property* prop) const; + + virtual short mustExecute(void) const; + + App::DocumentObjectExecReturn *execute(void); + + void getCellAddress(const App::Property *prop, CellAddress &address); + + std::map getColumnWidths() const; + + std::map getRowHeights() const; + + void setPosition(CellAddress address); + + // Signals + + boost::signal cellUpdated; + + boost::signal cellSpanChanged; + + boost::signal columnWidthChanged; + + boost::signal rowHeightChanged; + + boost::signal positionChanged; + + + /** @name Access properties */ + //@{ + App::Property* addDynamicProperty( + const char* type, const char* name=0, + const char* group=0, const char* doc=0, + short attr=0, bool ro=false, bool hidden=false) { + return props.addDynamicProperty(type, name, group, doc, attr, ro, hidden); + } + virtual bool removeDynamicProperty(const char* name) { + return props.removeDynamicProperty(name); + } + std::vector getDynamicPropertyNames() const { + return props.getDynamicPropertyNames(); + } + App::Property *getDynamicPropertyByName(const char* name) const { + return props.getDynamicPropertyByName(name); + } + virtual void addDynamicProperties(const App::PropertyContainer* cont) { + return props.addDynamicProperties(cont); + } + /// get all properties of the class (including properties of the parent) + virtual void getPropertyList(std::vector &List) const { + props.getPropertyList(List); + } + /// get all properties of the class (including parent) + void getPropertyMap(std::map &Map) const { + props.getPropertyMap(Map); + } + + short getPropertyType(const App::Property *prop) const { + props.getPropertyType(prop); + } + + /// get the name of a property + virtual const char* getName(const App::Property* prop) const { + return props.getPropertyName(prop); + } + //@} + + void observeDocument(const std::string &docName); + +protected: + + void providesTo(CellAddress address, std::set & result) const; + + void onDocumentRestored(); + + void onRelabledDocument(const App::Document & document); + + void onRenamedDocument(const App::Document & document); + + void recomputeCell(CellAddress p); + + App::Property *getProperty(CellAddress key) const; + + App::Property *getProperty(const char * addr) const; + + void updateProperty(CellAddress key); + + App::Property *setStringProperty(CellAddress key, const std::string & value) ; + + App::Property *setFloatProperty(CellAddress key, double value); + + App::Property *setQuantityProperty(CellAddress key, double value, const Base::Unit &unit); + + static std::string toAddress(CellAddress key); + + void moveCell(CellAddress currPos, CellAddress newPos); + + void renamedDocumentObject(const App::DocumentObject * docObj); + + /* Properties for used cells */ + App::DynamicProperty props; + + /* Mapping of properties to cell position */ + std::map propAddress; + + /* Mapping of cell position to alias property */ + std::map aliasProp; + + /* Set of cells with errors */ + std::set cellErrors; + + /* Properties */ + + /* Cell data */ + PropertySheet cells; + + /* Column widths */ + PropertyColumnWidths columnWidths; + + /* Row heights */ + PropertyRowHeights rowHeights; + + App::PropertyInteger currRow; + App::PropertyInteger currColumn; + + /* Dependencies to other documents */ + App::PropertyLinkList docDeps; + + /* Document observers to track changes to external properties */ + typedef std::map ObserverMap; + ObserverMap observers; + + boost::BOOST_SIGNALS_NAMESPACE::scoped_connection onRelabledDocumentConnection; + boost::BOOST_SIGNALS_NAMESPACE::scoped_connection onRenamedDocumentConnection; + + friend class SheetObserver; + + friend class PropertySheet; +}; + +} //namespace Spreadsheet + + +#endif // Spreadsheet_Spreadsheet_H diff --git a/src/Mod/Spreadsheet/App/SheetObserver.cpp b/src/Mod/Spreadsheet/App/SheetObserver.cpp new file mode 100644 index 0000000000..8235d9fb2d --- /dev/null +++ b/src/Mod/Spreadsheet/App/SheetObserver.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#include "SheetObserver.h" +#include "PropertySheet.h" + +using namespace Spreadsheet; +using namespace App; + +/** + * The SheetObserver constructor. + * + * @param document The Document we are observing + * @param _sheet The sheet owning this observer. + * + */ + +SheetObserver::SheetObserver(App::Document * document, PropertySheet *_sheet) + : DocumentObserver(document) + , sheet(_sheet) + , refCount(1) +{ +} + +/** + * Unimplemented. + * + */ + +void SheetObserver::slotCreatedDocument(const App::Document &Doc) +{ +} + +/** + * Unimplemented. + * + */ + +void SheetObserver::slotDeletedDocument(const App::Document &Doc) +{ +} + +/** + * Invalidate cells that depend on this document object. + * + */ + +void SheetObserver::slotCreatedObject(const DocumentObject &Obj) +{ + sheet->invalidateDependants(&Obj); +} + +/** + * Invalidate cells that depend on this document object. + * + */ + +void SheetObserver::slotDeletedObject(const DocumentObject &Obj) +{ + sheet->invalidateDependants(&Obj); +} + +/** + * Invoke the sheets recomputeDependants when a change to a Property occurs. + * + */ + +void SheetObserver::slotChangedObject(const DocumentObject &Obj, const Property &Prop) +{ + const char * name = Obj.getPropertyName(&Prop); + assert(name != 0); + + if (&Prop == &Obj.Label) + sheet->renamedDocumentObject(&Obj); + else { + + if (isUpdating.find(name) != isUpdating.end()) + return; + + isUpdating.insert(name); + sheet->recomputeDependants(&Prop); + isUpdating.erase(name); + } +} + +/** + * Increase reference count. + * + */ + +void SheetObserver::ref() +{ + refCount++; +} + +/** + * Decrease reference count. + * + */ + +bool SheetObserver::unref() +{ + refCount--; + return refCount; +} + diff --git a/src/Mod/Spreadsheet/App/SheetObserver.h b/src/Mod/Spreadsheet/App/SheetObserver.h new file mode 100644 index 0000000000..ef8659803c --- /dev/null +++ b/src/Mod/Spreadsheet/App/SheetObserver.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef SHEETOBSERVER_H +#define SHEETOBSERVER_H + +#include + +namespace Spreadsheet { + +class PropertySheet; + +class SheetObserver : public App::DocumentObserver { +public: + SheetObserver(App::Document* document, PropertySheet *_sheet); + ~SheetObserver() { } + virtual void slotCreatedDocument(const App::Document& Doc); + virtual void slotDeletedDocument(const App::Document& Doc); + virtual void slotCreatedObject(const App::DocumentObject& Obj); + virtual void slotDeletedObject(const App::DocumentObject& Obj); + virtual void slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop); + void ref(); + bool unref(); + App::Document* getDocument() const { return App::DocumentObserver::getDocument(); } +private: + std::set isUpdating; + int refCount; + PropertySheet * sheet; +}; + +} + +#endif // SHEETOBSERVER_H diff --git a/src/Mod/Spreadsheet/App/SheetPy.xml b/src/Mod/Spreadsheet/App/SheetPy.xml new file mode 100644 index 0000000000..f4476ef689 --- /dev/null +++ b/src/Mod/Spreadsheet/App/SheetPy.xml @@ -0,0 +1,164 @@ + + + + + + + With this object you can manipulate spreadsheets + + + + Set data into a cell + + + + + Get evaluated cell contents + + + + + Get cell contents + + + + + Clear a cell + + + + + Clear all cells in the spreadsheet + + + + + Import file into spreadsheet + + + + + Export file from spreadsheet + + + + + Merge given cell area into one cell + + + + + Split a perviously merged cell + + + + + Insert a given number of columns into the spreadsheet. + + + + + Remove a given number of columns from the spreadsheet. + + + + + Insert a given number of rows into the spreadsheet. + + + + + Remove a given number of rows from the spreadsheet. + + + + + Set alignment of the cell + + + + + Get alignment of the cell + + + + + Set style of the cell + + + + + Get style of the cell + + + + + Set display unit for cell + + + + + Set alias for cell address + + + + + Get display unit for cell + + + + + Set foreground color of the cell + + + + + Get foreground color of the cell + + + + + Set background color of the cell + + + + + Get background color of the cell + + + + + Set given spreadsheet column to given width + + + + + Get given spreadsheet column width + + + + + Set given spreadsheet row to given height + + + + + Get given spreadsheet row height + + + + + Set focused cell for attached view(s). + + + + diff --git a/src/Mod/Spreadsheet/App/SheetPyImp.cpp b/src/Mod/Spreadsheet/App/SheetPyImp.cpp new file mode 100644 index 0000000000..7b81d573a4 --- /dev/null +++ b/src/Mod/Spreadsheet/App/SheetPyImp.cpp @@ -0,0 +1,892 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#include +#include +#include +#include +#include "Utils.h" +#include "Range.h" + +// inclusion of the generated files (generated out of SheetPy.xml) +#include "SheetPy.h" +#include "SheetPy.cpp" + +using namespace Spreadsheet; +using namespace App; + +// returns a string which represents the object e.g. when printed in python +std::string SheetPy::representation(void) const +{ + return std::string(""); +} + +PyObject *SheetPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of SheetPy and the Twin object + return new SheetPy(new Sheet()); +} + +// constructor method +int SheetPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) +{ + return 0; +} + +// +++ methodes implementer ++++++++++++++++++++++++++++++++++++++++++++++++ + +PyObject* SheetPy::set(PyObject *args) +{ + char *address; + char *contents; + + + if (!PyArg_ParseTuple(args, "ss:set", &address, &contents)) + return 0; + + try { + Range rangeIter(address); + do { + getSheetPtr()->setCell(rangeIter.address().c_str(), contents); + } while (rangeIter.next()); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } + + Py_Return; +} + +PyObject* SheetPy::get(PyObject *args) +{ + char *address; + + if (!PyArg_ParseTuple(args, "s:get", &address)) + return 0; + + App::Property * prop = this->getSheetPtr()->getPropertyByName(address); + + if (prop == 0) { + PyErr_SetString(PyExc_ValueError, "Invalid address or property."); + return 0; + } + return prop->getPyObject(); +} + +PyObject* SheetPy::getContents(PyObject *args) +{ + char *strAddress; + CellAddress address; + + if (!PyArg_ParseTuple(args, "s:getContents", &strAddress)) + return 0; + + try { + address = stringToAddress(strAddress); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } + + std::string contents; + const Cell * cell = this->getSheetPtr()->getCell(address); + + if (cell) + cell->getStringContent( contents ); + + return Py::new_reference_to( Py::String( contents ) ); +} + +PyObject* SheetPy::clear(PyObject *args) +{ + const char * strAddress; + int all = 1; + + if (!PyArg_ParseTuple(args, "s|p:clear", &strAddress, &all)) + return 0; + + try { + Range rangeIter(strAddress); + do { + this->getSheetPtr()->clear(*rangeIter, all); + } while (rangeIter.next()); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } + + Py_Return; +} + +PyObject* SheetPy::clearAll(PyObject *args) +{ + this->getSheetPtr()->clearAll(); + Py_Return; +} + +PyObject* SheetPy::importFile(PyObject *args) +{ + const char * filename; + const char * delimiter = "\t"; + const char * quoteChar = "\""; + const char * escapeChar = "\\"; + + if (!PyArg_ParseTuple(args, "s|sss:importFile", &filename, &delimiter, "eChar, &escapeChar)) + return 0; + + if (getSheetPtr()->importFromFile(filename, delimiter[0], quoteChar[0], escapeChar[0])) + return Py::new_reference_to( Py::Boolean(true) ); + else + return Py::new_reference_to( Py::Boolean(false) ); +} + +PyObject* SheetPy::exportFile(PyObject *args) +{ + const char * filename; + const char * delimiter = "\t"; + const char * quoteChar = "\""; + const char * escapeChar = "\\"; + + if (!PyArg_ParseTuple(args, "s|sss:importFile", &filename, &delimiter, "eChar, &escapeChar)) + return 0; + + if (getSheetPtr()->exportToFile(filename, delimiter[0], quoteChar[0], escapeChar[0])) + return Py::new_reference_to( Py::Boolean(true) ); + else + return Py::new_reference_to( Py::Boolean(false) ); +} + +PyObject* SheetPy::mergeCells(PyObject *args) +{ + const char * range; + + if (!PyArg_ParseTuple(args, "s:mergeCells", &range)) + return 0; + + getSheetPtr()->mergeCells(Range(range)); + Py_Return; +} + +PyObject* SheetPy::splitCell(PyObject *args) +{ + const char * strAddress; + + if (!PyArg_ParseTuple(args, "s:splitCell", &strAddress)) + return 0; + + CellAddress address; + try { + address = stringToAddress(strAddress); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } + + getSheetPtr()->splitCell(address); + Py_Return; +} + +PyObject* SheetPy::insertColumns(PyObject *args) +{ + const char * column; + int count; + + if (!PyArg_ParseTuple(args, "si:insertColumns", &column, &count)) + return 0; + + getSheetPtr()->insertColumns(decodeColumn(column), count); + Py_Return; +} + +PyObject* SheetPy::removeColumns(PyObject *args) +{ + const char * column; + int count; + + if (!PyArg_ParseTuple(args, "si:removeColumns", &column, &count)) + return 0; + + getSheetPtr()->removeColumns(decodeColumn(column), count); + Py_Return; +} + +PyObject* SheetPy::insertRows(PyObject *args) +{ + const char * row; + int count; + + if (!PyArg_ParseTuple(args, "si:insertRows", &row, &count)) + return 0; + + getSheetPtr()->insertRows(decodeRow(std::string(row)), count); + Py_Return; +} + +PyObject* SheetPy::removeRows(PyObject *args) +{ + const char * row; + int count; + + if (!PyArg_ParseTuple(args, "si:removeRows", &row, &count)) + return 0; + + getSheetPtr()->removeRows(decodeRow(std::string(row)), count); + Py_Return; +} + +PyObject* SheetPy::setStyle(PyObject *args) +{ + const char * cell; + PyObject * value; + std::set style; + const char * options = "replace"; + + if (!PyArg_ParseTuple(args, "sO|s:setStyle", &cell, &value, &options)) + return 0; + + if (PySet_Check(value)) { + PyObject * copy = PySet_New(value); + + while (PySet_Size(copy) > 0) { + PyObject * item = PySet_Pop(copy); + + // check on the key: + if (PyString_Check(item)) + style.insert(PyString_AsString(item)); + else { + std::string error = std::string("type of the set need to be a string, not ") + item->ob_type->tp_name; + PyErr_SetString(PyExc_TypeError, error.c_str()); + Py_DECREF(copy); + return 0; + } + } + Py_DECREF(copy); + } + else if (PyString_Check(value)) { + using namespace boost; + + escaped_list_separator e('\0', '|', '\0'); + std::string line = PyString_AsString(value); + tokenizer > tok(line, e); + + for(tokenizer >::iterator i = tok.begin(); i != tok.end();++i) + style.insert(*i); + } + else { + std::string error = std::string("style must be either set or string, not ") + value->ob_type->tp_name; + PyErr_SetString(PyExc_TypeError, error.c_str()); + return 0; + } + + if (strcmp(options, "replace") == 0) { + Range rangeIter(cell); + do { + getSheetPtr()->setStyle(*rangeIter, style); + } while (rangeIter.next()); + } + else if (strcmp(options, "add") == 0) { + Range rangeIter(cell); + + do { + std::set oldStyle; + const Cell * cell = getSheetPtr()->getCell(*rangeIter); + + // Get old styles first + if (cell) + cell->getStyle(oldStyle); + + for (std::set::const_iterator it = oldStyle.begin(); it != oldStyle.end(); ++it) + style.insert(*it); + + // Set new style + getSheetPtr()->setStyle(*rangeIter, style); + } while (rangeIter.next()); + } + else if (strcmp(options, "remove") == 0) { + Range rangeIter(cell); + + do { + std::set oldStyle; + const Cell * cell = getSheetPtr()->getCell(*rangeIter); + + // Get old styles first + if (cell) + cell->getStyle(oldStyle); + + for (std::set::const_iterator it = style.begin(); it != style.end(); ++it) + oldStyle.erase(*it); + + // Set new style + getSheetPtr()->setStyle(*rangeIter, oldStyle); + } while (rangeIter.next()); + } + else if (strcmp(options, "invert") == 0) { + Range rangeIter(cell); + + do { + std::set oldStyle; + std::set newStyle; + const Cell * cell = getSheetPtr()->getCell(*rangeIter); + + // Get old styles first + if (cell) { + cell->getStyle(oldStyle); + newStyle = oldStyle; + } + + for (std::set::const_iterator i = style.begin(); i != style.end(); ++i) { + if (oldStyle.find(*i) == oldStyle.end()) + // Not found in oldstyle; add it to newStyle + newStyle.insert(*i); + else + // Found in oldStyle, remove it from newStyle + newStyle.erase(*i); + } + + // Set new style + getSheetPtr()->setStyle(*rangeIter, newStyle); + } while (rangeIter.next()); + } + else { + PyErr_SetString(PyExc_ValueError, "Optional parameter must be either 'replace', 'add', 'remove', or 'invert'"); + return 0; + } + + Py_Return; +} + +PyObject* SheetPy::getStyle(PyObject *args) +{ + const char * strAddress; + CellAddress address; + + if (!PyArg_ParseTuple(args, "s:getStyle", &strAddress)) + return 0; + + try { + address = stringToAddress(strAddress); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } + + std::set style; + const Cell * cell = getSheetPtr()->getCell(address); + + if (cell && cell->getStyle(style)) { + PyObject * s = PySet_New(NULL); + + for (std::set::const_iterator i = style.begin(); i != style.end(); ++i) + PySet_Add(s, PyString_FromString((*i).c_str())); + + return s; + } + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +PyObject* SheetPy::setDisplayUnit(PyObject *args) +{ + int row, col; + const char * cell; + const char * value; + + if (!PyArg_ParseTuple(args, "ss:setDisplayUnit", &cell, &value)) + return 0; + + try { + Range rangeIter(cell); + + do { + getSheetPtr()->setDisplayUnit(*rangeIter, value); + } while (rangeIter.next()); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } + + Py_Return; +} + +PyObject* SheetPy::setAlias(PyObject *args) +{ + CellAddress address; + const char * strAddress; + const char * value; + + if (!PyArg_ParseTuple(args, "ss:setAlias", &strAddress, &value)) + return 0; + + try { + address = stringToAddress(strAddress); + getSheetPtr()->setAlias(address, value); + Py_Return; + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} + +PyObject* SheetPy::getDisplayUnit(PyObject *args) +{ + const char * strAddress; + CellAddress address; + + if (!PyArg_ParseTuple(args, "s:getDisplayUnit", &strAddress)) + return 0; + + try { + address = stringToAddress(strAddress); + + Spreadsheet::DisplayUnit unit; + + const Cell * cell = getSheetPtr()->getCell(address); + + if ( cell && cell->getDisplayUnit(unit) ) + return Py::new_reference_to( Py::String( unit.stringRep ) ); + else + Py_Return; + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} + +PyObject* SheetPy::setAlignment(PyObject *args) +{ + const char * cell; + PyObject * value; + int alignment = 0; + const char * options = "replace"; + + if (!PyArg_ParseTuple(args, "sO|s:setAlignment", &cell, &value, &options)) + return 0; + + if (PySet_Check(value)) { + // Argument is a set of strings + PyObject * copy = PySet_New(value); + int n = PySet_Size(copy); + + while (n-- > 0) { + PyObject * item = PySet_Pop(copy); + + if (PyString_Check(item)) + alignment = Cell::decodeAlignment(PyString_AsString(item), alignment); + else { + std::string error = std::string("type of the key need to be a string, not") + item->ob_type->tp_name; + PyErr_SetString(PyExc_TypeError, error.c_str()); + Py_DECREF(copy); + return 0; + } + } + + Py_DECREF(copy); + } + else if (PyString_Check(value)) { + // Argument is a string, combination of alignments, separated by the pipe character + using namespace boost; + + escaped_list_separator e('\0', '|', '\0'); + std::string line = PyString_AsString(value); + tokenizer > tok(line, e); + + for(tokenizer >::iterator i = tok.begin(); i != tok.end();++i) + alignment = Cell::decodeAlignment(*i, alignment); + } + else { + std::string error = std::string("style must be either set or string, not ") + value->ob_type->tp_name; + PyErr_SetString(PyExc_TypeError, error.c_str()); + return 0; + } + + // Set alignment depending on 'options' variable + if (strcmp(options, "replace") == 0) { + Range rangeIter(cell); + + do { + getSheetPtr()->setAlignment(*rangeIter, alignment); + } while (rangeIter.next()); + } + else if (strcmp(options, "keep") == 0) { + Range rangeIter(cell); + + do { + int oldAlignment = 0; + const Cell * cell = getSheetPtr()->getCell(*rangeIter); + + if (cell) + cell->getAlignment(oldAlignment); + + if (alignment & Cell::ALIGNMENT_VERTICAL) + oldAlignment &= ~Cell::ALIGNMENT_VERTICAL; + if (alignment & Cell::ALIGNMENT_HORIZONTAL) + oldAlignment &= ~Cell::ALIGNMENT_HORIZONTAL; + + getSheetPtr()->setAlignment(*rangeIter, alignment | oldAlignment); + } while (rangeIter.next()); + } + else { + PyErr_SetString(PyExc_ValueError, "Optional parameter must be either 'replace' or 'keep'"); + return 0; + } + Py_Return; +} + +PyObject* SheetPy::getAlignment(PyObject *args) +{ + const char * strAddress; + CellAddress address; + + if (!PyArg_ParseTuple(args, "s:getAlignment", &strAddress)) + return 0; + + try { + address = stringToAddress(strAddress); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } + + + int alignment; + const Cell * cell = getSheetPtr()->getCell(address); + if (cell && cell->getAlignment(alignment)) { + PyObject * s = PySet_New(NULL); + + if (alignment & Cell::ALIGNMENT_LEFT) + PySet_Add(s, PyString_FromString("left")); + if (alignment & Cell::ALIGNMENT_HCENTER) + PySet_Add(s, PyString_FromString("center")); + if (alignment & Cell::ALIGNMENT_RIGHT) + PySet_Add(s, PyString_FromString("right")); + if (alignment & Cell::ALIGNMENT_TOP) + PySet_Add(s, PyString_FromString("top")); + if (alignment & Cell::ALIGNMENT_VCENTER) + PySet_Add(s, PyString_FromString("vcenter")); + if (alignment & Cell::ALIGNMENT_BOTTOM) + PySet_Add(s, PyString_FromString("bottom")); + + return s; + } + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +static float decodeFloat(const PyObject * obj) +{ + if (PyFloat_Check(obj)) + return PyFloat_AsDouble((PyObject *)obj); + else if (PyInt_Check(obj)) + return PyInt_AsLong((PyObject *)obj); + throw Base::TypeError("Float or integer expected"); +} + +static void decodeColor(PyObject * value, Color & c) +{ + if (PyTuple_Check(value)) { + if (PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4) + throw Base::TypeError("Tuple must be either of 3 or 4 floats/ints."); + + c.r = decodeFloat(PyTuple_GetItem(value, 0)); + c.g = decodeFloat(PyTuple_GetItem(value, 1)); + c.b = decodeFloat(PyTuple_GetItem(value, 2)); + if (PyTuple_Size(value) == 4) { + c.a = decodeFloat(PyTuple_GetItem(value, 3)); + return; + } + else + c.a = 1.0; + } + else + throw Base::TypeError("Tuple required."); +} + +PyObject* SheetPy::setForeground(PyObject *args) +{ + try { + const char * range; + PyObject * value; + Color c; + + if (!PyArg_ParseTuple(args, "sO:setForeground", &range, &value)) + return 0; + + decodeColor(value, c); + + Range rangeIter(range); + do { + getSheetPtr()->setForeground(*rangeIter, c); + } while (rangeIter.next()); + Py_Return; + } + catch (const Base::TypeError & e) { + PyErr_SetString(PyExc_TypeError, e.what()); + return 0; + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} + +PyObject* SheetPy::getForeground(PyObject *args) +{ + const char * strAddress; + CellAddress address; + + if (!PyArg_ParseTuple(args, "s:getForeground", &strAddress)) + return 0; + + try { + address = stringToAddress(strAddress); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } + + Color c; + const Cell * cell = getSheetPtr()->getCell(address); + if (cell && cell->getForeground(c)) { + PyObject * t = PyTuple_New(4); + + PyTuple_SetItem(t, 0, Py::new_reference_to( Py::Float(c.r) )); + PyTuple_SetItem(t, 1, Py::new_reference_to( Py::Float(c.g) )); + PyTuple_SetItem(t, 2, Py::new_reference_to( Py::Float(c.b) )); + PyTuple_SetItem(t, 3, Py::new_reference_to( Py::Float(c.a) )); + + return t; + } + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +PyObject* SheetPy::setBackground(PyObject *args) +{ + try { + const char * strAddress; + PyObject * value; + Color c; + + if (!PyArg_ParseTuple(args, "sO:setBackground", &strAddress, &value)) + return 0; + + decodeColor(value, c); + Range rangeIter(strAddress); + + do { + getSheetPtr()->setBackground(*rangeIter, c); + } while (rangeIter.next()); + Py_Return; + } + catch (const Base::TypeError & e) { + PyErr_SetString(PyExc_TypeError, e.what()); + return 0; + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} + +PyObject* SheetPy::getBackground(PyObject *args) +{ + const char * strAddress; + CellAddress address; + + if (!PyArg_ParseTuple(args, "s:setStyle", &strAddress)) + return 0; + + try { + address = stringToAddress(strAddress); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } + + Color c; + const Cell * cell = getSheetPtr()->getCell(address); + if (cell && cell->getBackground(c)) { + PyObject * t = PyTuple_New(4); + + PyTuple_SetItem(t, 0, Py::new_reference_to( Py::Float(c.r) )); + PyTuple_SetItem(t, 1, Py::new_reference_to( Py::Float(c.g) )); + PyTuple_SetItem(t, 2, Py::new_reference_to( Py::Float(c.b) )); + PyTuple_SetItem(t, 3, Py::new_reference_to( Py::Float(c.a) )); + + return t; + } + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +PyObject* SheetPy::setPosition(PyObject *args) +{ + const char * strAddress; + CellAddress address; + + if (!PyArg_ParseTuple(args, "s:setPosition", &strAddress)) + return 0; + + try { + address = stringToAddress(strAddress); + getSheetPtr()->setPosition(address); + Py_Return; + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} + +PyObject* SheetPy::setColumnWidth(PyObject *args) +{ + const char * columnStr; + int width; + CellAddress address; + + if (!PyArg_ParseTuple(args, "si:setColumnWidth", &columnStr, &width)) + return 0; + + try { + std::string cellAddr = std::string(columnStr) + "1"; + + address = stringToAddress(cellAddr.c_str()); + getSheetPtr()->setColumnWidth(address.col(), width); + Py_Return; + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} + +PyObject* SheetPy::getColumnWidth(PyObject *args) +{ + const char * columnStr; + + if (!PyArg_ParseTuple(args, "s:getColumnWidth", &columnStr)) + return 0; + + try { + CellAddress address(std::string(columnStr) + "1"); + + return Py::new_reference_to( Py::Int( getSheetPtr()->getColumnWidth(address.col()) ) ); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} + +PyObject* SheetPy::setRowHeight(PyObject *args) +{ + const char * rowStr; + int height; + + if (!PyArg_ParseTuple(args, "si:setRowHeight", &rowStr, &height)) + return 0; + + try { + CellAddress address("A" + std::string(rowStr)); + + getSheetPtr()->setRowHeight(address.row(), height); + Py_Return; + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} + +PyObject* SheetPy::getRowHeight(PyObject *args) +{ + const char * rowStr; + int row, col; + + if (!PyArg_ParseTuple(args, "s:getRowHeight", &rowStr)) + return 0; + + try { + CellAddress address("A" + std::string(rowStr)); + + return Py::new_reference_to( Py::Int( getSheetPtr()->getRowHeight(address.row()) ) ); + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} + +// +++ custom attributes implementer ++++++++++++++++++++++++++++++++++++++++ + +PyObject *SheetPy::getCustomAttributes(const char* attr) const +{ + App::Property * prop = this->getSheetPtr()->getPropertyByName(attr); + + if (prop == 0) { + PyErr_SetString(PyExc_ValueError, "Invalid address or property."); + return 0; + } + return prop->getPyObject(); +} + +int SheetPy::setCustomAttributes(const char* attr, PyObject* obj) +{ + // Parse attr; if it looks like a cell address specifier, it probably is... + char *contents; + + if (!PyArg_ParseTuple(obj, "s:setCustomAttributes", &contents)) + return 0; + + try { + CellAddress address(attr); + + getSheetPtr()->setCell(address, contents); + return 0; + } + catch (const Base::Exception & e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return 0; + } +} diff --git a/src/Mod/Spreadsheet/App/Utils.cpp b/src/Mod/Spreadsheet/App/Utils.cpp new file mode 100644 index 0000000000..25ee3b89e2 --- /dev/null +++ b/src/Mod/Spreadsheet/App/Utils.cpp @@ -0,0 +1,344 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "Utils.h" +#include +#include +#include +#include +#include "Sheet.h" + +const int Spreadsheet::CellAddress::MAX_ROWS = 16384; +const int Spreadsheet::CellAddress::MAX_COLUMNS = 26 * 26 + 26; + +/** + * Encode \a col as a string. + * + * @param col Column given as a 0-based column position. + * + * @returns String with column position, with "A" being the first column, "B" being the second and so on. + * + */ + +std::string Spreadsheet::columnName(int col) +{ + std::stringstream s; + + if (col < 26) + s << ((char)('A' + col)); + else + s << ((char)('A' + (col - 26) / 26 )) << ((char)('A' + (col - 26) % 26)); + + return s.str(); +} + +/** + * Encode \a row as a string. + * + * @param row Row given as a 0-based row position. + * + * @returns String with row position, with "1" being the first row. + * + */ + +std::string Spreadsheet::rowName(int row) +{ + std::stringstream s; + + s << (row + 1); + + return s.str(); +} + +/** + * Decode a row specification into a 0-based integer. + * + * @param rowstr Row specified as a string, with "1" being the first row. + * + * @returns The row. + */ + +int Spreadsheet::decodeRow(const std::string &rowstr) +{ + char * end; + int i = strtol(rowstr.c_str(), &end, 10); + + if (i <0 || i >= CellAddress::MAX_ROWS || *end) + throw Base::Exception("Invalid row specification."); + + return i - 1; +} + +/** + * Decode a column specification into a 0-based integer. + * + * @param colstr Column specified as a string, with "A" begin the first column. + * + * @returns The column. + * + */ + +int Spreadsheet::decodeColumn(const std::string &colstr) +{ + int col = 0; + + if (colstr.length() == 1) { + if ((colstr[0] >= 'A' && colstr[0] <= 'Z')) + col = colstr[0] - 'A'; + else + col = colstr[0] - 'a'; + } + else { + col = 0; + for (std::string::const_reverse_iterator i = colstr.rbegin(); i != colstr.rend(); ++i) { + int v; + + if ((*i >= 'A' && *i <= 'Z')) + v = *i - 'A'; + else if ((*i >= 'a' && *i <= 'z')) + v = *i - 'a'; + else + throw Base::Exception("Invalid column specification"); + + col = col * 26 + v; + } + col += 26; + } + return col; +} + +/** + * Convert a string address into integer \a row and \a column. + * row and col are 0-based. + * + * This function will throw an exception if the specified \a address is invalid. + * + * @param address Address to parse. + * @param row Reference to integer where row position is stored. + * @param col Reference to integer where col position is stored. + * + */ + +Spreadsheet::CellAddress Spreadsheet::stringToAddress(const char * strAddress) +{ + int i = 0; + static const boost::regex e("\\${0,1}([A-Za-z]+)\\${0,1}([0-9]+)"); + boost::cmatch cm; + + Q_ASSERT(strAddress != 0); + + if (boost::regex_match(strAddress, cm, e)) { + const boost::sub_match colstr = cm[1]; + const boost::sub_match rowstr = cm[2]; + + return CellAddress(Spreadsheet::decodeRow(rowstr.str()), Spreadsheet::decodeColumn(colstr.str())); + } + else + throw Base::Exception("Invalid cell specifier."); +} + +/** + * Convert given \a row and \a col into a string address. + * + * @param row Row address. + * @param col Column address. + * + * @returns Address given as a string. + */ + +std::string Spreadsheet::addressToString(const CellAddress &address) +{ + std::stringstream s; + + if (address.col() < 26) + s << (char)('A' + address.col()); + else { + int col = address.col() - 26; + + s << (char)('A' + (col / 26)); + s << (char)('A' + (col % 26)); + } + + s << (address.row() + 1); + + return s.str(); +} + +void Spreadsheet::createRectangles(std::set > & cells, std::map, std::pair > & rectangles) +{ + while (cells.size() != 0) { + int row, col; + int orgRow; + int rows = 1; + int cols = 1; + + orgRow = row = (*cells.begin()).first; + col = (*cells.begin()).second; + + // Expand right first + while (cells.find(std::make_pair(row, col + cols)) != cells.end()) + ++cols; + + // Expand left + while (cells.find(std::make_pair(row, col + cols)) != cells.end()) { + col--; + ++cols; + } + + // Try to expand cell up (the complete row above from [col,col + cols> needs to be in the cells variable) + bool ok = true; + while (ok) { + for (int i = col; i < col + cols; ++i) { + if ( cells.find(std::make_pair(row - 1, i)) == cells.end()) { + ok = false; + break; + } + } + if (ok) { + // Complete row + row--; + rows++; + } + else + break; + } + + // Try to expand down (the complete row below from [col,col + cols> needs to be in the cells variable) + ok = true; + while (ok) { + for (int i = col; i < col + cols; ++i) { + if ( cells.find(std::make_pair(orgRow + 1, i)) == cells.end()) { + ok = false; + break; + } + } + if (ok) { + // Complete row + orgRow++; + rows++; + } + else + break; + } + + // Remove entries from cell set for this rectangle + for (int r = row; r < row + rows; ++r) + for (int c = col; c < col + cols; ++c) + cells.erase(std::make_pair(r, c)); + + // Insert into output variable + rectangles[std::make_pair(row, col)] = std::make_pair(rows, cols); + } +} + +std::string Spreadsheet::quote(const std::string &input) +{ + std::stringstream output; + + std::string::const_iterator cur = input.begin(); + std::string::const_iterator end = input.end(); + + output << "<<"; + while (cur != end) { + switch (*cur) { + case '\t': + output << "\\t"; + break; + case '\n': + output << "\\n"; + break; + case '\r': + output << "\\r"; + break; + case '\\': + output << "\\\\"; + break; + case '\'': + output << "\\'"; + break; + case '"': + output << "\\\""; + break; + case '>': + output << "\\>"; + break; + default: + output << *cur; + } + ++cur; + } + output << ">>"; + + return output.str(); +} + +std::string Spreadsheet::unquote(const std::string & input) +{ + assert(input.size() >= 4); + + std::string output; + std::string::const_iterator cur = input.begin() + 2; + std::string::const_iterator end = input.end() - 2; + + output.reserve(input.size()); + + bool escaped = false; + while (cur != end) { + if (escaped) { + switch (*cur) { + case 't': + output += '\t'; + break; + case 'n': + output += '\n'; + break; + case 'r': + output += '\r'; + break; + case '\\': + output += '\\'; + break; + case '\'': + output += '\''; + break; + case '"': + output += '"'; + break; + } + escaped = false; + } + else { + if (*cur == '\\') + escaped = true; + else + output += *cur; + } + ++cur; + } + + return output; +} diff --git a/src/Mod/Spreadsheet/App/Utils.h b/src/Mod/Spreadsheet/App/Utils.h new file mode 100644 index 0000000000..2d760926d1 --- /dev/null +++ b/src/Mod/Spreadsheet/App/Utils.h @@ -0,0 +1,92 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef UTILS_H +#define UTILS_H + +#include +#include +#include +#include +#include + +namespace Spreadsheet { + +struct CellAddress; + +SpreadsheetExport std::string columnName(int col); +SpreadsheetExport std::string rowName(int row); +int decodeColumn(const std::string &colstr); +int decodeRow(const std::string &rowstr); +SpreadsheetExport CellAddress stringToAddress(const char *strAddress); +SpreadsheetExport void createRectangles(std::set > & cells, std::map, std::pair > & rectangles); +SpreadsheetExport std::string quote(const std::string &input); +SpreadsheetExport std::string unquote(const std::string & input); + +SpreadsheetExport std::string addressToString(const CellAddress & address); + +struct CellAddress { + CellAddress(unsigned int _value) : value(_value) { } + + CellAddress(int row = -1, int col = -1) : value(((row & 0xffff) << 16) | (col & 0xffff)) { } + + CellAddress(const char * address) { + *this = stringToAddress(address); + } + + CellAddress(const std::string & address) { + *this = stringToAddress(address.c_str()); + } + + inline int row() const { return (value >> 16) & 0xffff; } + + inline int col() const { return value & 0xffff; } + + inline bool operator<(const CellAddress & other) const { return value < other.value; } + + inline bool operator==(const CellAddress & other) const { return value == other.value; } + + inline bool operator!=(const CellAddress & other) const { return value != other.value; } + + inline bool isValid() { return (row() >=0 && row() < MAX_ROWS && col() >= 0 && col() < MAX_COLUMNS); } + + // Static members + + static const int MAX_ROWS; + + static const int MAX_COLUMNS; + +protected: + unsigned int value; +}; + +template T * freecad_dynamic_cast(Base::BaseClass * t) +{ + if (t && t->isDerivedFrom(T::getClassTypeId())) + return static_cast(t); + else + return 0; +} + +} + +#endif // UTILS_H diff --git a/src/Mod/Spreadsheet/App/create_regexps.sh b/src/Mod/Spreadsheet/App/create_regexps.sh new file mode 100755 index 0000000000..ca5390852e --- /dev/null +++ b/src/Mod/Spreadsheet/App/create_regexps.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# DerivedGeneralCategory.txt used below can be downloaded from +# http://www.unicode.org/Public/UNIDATA/extracted/DerivedGeneralCategory.txt + +exec 2>/dev/null + +export PATH=../../../../build/src/Mod/Spreadsheet/App:$PATH + +for l in Cc Cf Cn Co Cs Ll Lm Lo Lt Lu Mc Me Mn Nd Nl No Pc Pd Pe Pf Pi Po Ps Sc Sk Sm So Zl Zp Zs ; do + grep "; $l" DerivedGeneralCategory.txt > $l.txt + genregexps $l $l.txt +done + +genregexps L Ll.txt Lm.txt Lo.txt Lt.txt Lu.txt +genregexps C Cc.txt Cf.txt Cn.txt Co.txt Cs.txt +genregexps M Mc.txt Me.txt Mn.txt +genregexps N Nd.txt Nl.txt No.txt +genregexps P Pc.txt Pd.txt Pe.txt Pf.txt Pi.txt Po.txt Ps.txt +genregexps S Sc.txt Sk.txt Sm.txt So.txt +genregexps Z Zl.txt Zp.txt Zs.txt diff --git a/src/Mod/Spreadsheet/App/genregexps.cpp b/src/Mod/Spreadsheet/App/genregexps.cpp new file mode 100644 index 0000000000..7b40890556 --- /dev/null +++ b/src/Mod/Spreadsheet/App/genregexps.cpp @@ -0,0 +1,232 @@ +#include +#include +#include +#include +#include +#include + +int genUtf8(int c, unsigned char * b) +{ + if (c<0x80) { *b++=c, *b++ = '\0'; return 1; } + else if (c<0x800) { *b++=192+c/64, *b++=128+c%64, *b++ = '\0'; return 2; } + else if (c-0xd800u < 0x800) goto error; + else if (c<0x10000) { *b++=224+c/4096, *b++=128+c/64%64, *b++=128+c%64, *b++ = '\0'; return 3; } + else if (c<0x110000) { *b++=240+c/262144, *b++=128+c/4096%64, *b++=128+c/64%64, *b++=128+c%64, *b++ = '\0'; return 4; } + else goto error; +error: + // printf("Error! %x\n", c); + // exit(1); + return -1; +} + +typedef std::basic_string String; +typedef std::vector StringList; + +StringList list; + +unsigned char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + +static String escape(unsigned char c) +{ + switch (c) { + case '*': + case '+': + case '-': + case '(': + case ')': + case '\\': + case '.': + case '[': + case ']': + case '?': + case '{': + case '}': + case '#': + case '^': + case '|': + case ':': + case '$': + case '/': + case '\'': + case '"': + return String((const unsigned char*)"\\") + c; + default: + return String((const unsigned char*)"") + c; + } +} + +static String encode(unsigned char c) +{ + if (c <= 32 || c > 126) + return String((const unsigned char*)"\\x") + hex[c >> 4] + hex[c & 0xf]; + else { + return String((const unsigned char*)"") + c; + } +} + +static String encodeString(String c) +{ + int i; + String result; + + for (i = 0; i < c.size(); ++i) + result += encode(c[i]); + + return result; +} + +static String encodeRange(String r) +{ + String result; + int i, j; + + for (i = 0; i < r.size(); ++i) { + int n = 0; + + for (j = i; j < r.size() && r[i] + n == r[j]; ++j, ++n); + + if (n > 1) { + result += escape(r[i]); + result += (const unsigned char*)"-"; + result += escape(r[j - 1]); + i = j - 1; + } + else + result += escape(r[i]); + } + + return result; +} + +static String commonPrefix(int indent, StringList::const_iterator S, StringList::const_iterator E, int k) +{ + StringList::const_iterator i = S; + String leafs; + String branches; + int nBranches = 0; + bool first = true; + + if (S->size() <= k) + return String((const unsigned char*)""); + + while (i != E) { + StringList::const_iterator start = i; + StringList::const_iterator end = i; + int n = 0; + + if (i->size() == k + 1) { + leafs += i->at(k); + ++i; + } + else { + /* Common path */ + while (end != E && + end->size() >= start->size() && + end->at(k) == start->at(k)) { + ++n; + ++end; + } + + //if (leafs.size() > 0) + if (!first) + branches += (const unsigned char*)"|"; + branches += escape(start->at(k)) + commonPrefix(indent + 1, start, end, k + 1); + + first = false; + nBranches++; + i = end; + } + } + + if (leafs.size() > 1) + leafs = (const unsigned char*)"[" + encodeRange(leafs) + (const unsigned char*)"]"; + + if (nBranches == 0) + return leafs; + else { + if (leafs.size() > 0) + leafs += (const unsigned char*)"|"; + return (const unsigned char*)"(" + leafs + branches + (const unsigned char*)")"; + } +} + +static void readFile(FILE * f) +{ + while (!feof(f)) { + char line[2048]; + int start; + int end; + char cat[128]; + unsigned char out[8]; + int i; + + if (fgets(line, sizeof(line), f) == NULL) + break; + + if (sscanf(line, "%4X..%4X ; %s", &start, &end, cat) == 3) { + for (i = start; i <= end; ++i) { + int n = genUtf8(i, out); + + if (n > 0) { + list.push_back(String(out, n)); + fprintf(stderr, "%6X %d %s\n", i, n, out); + } + } + } + else if (sscanf(line, "%X ; %s", &start, cat) == 2) { + int n = genUtf8(start, out); + + if (n > 0) { + list.push_back(String(out, n)); + fprintf(stderr, "%6X %d %s\n", start, n, out); + } + } + } +} + +static String subdivide(String prefix, StringList::const_iterator S, StringList::const_iterator E, StringList & result) +{ + String regexp = commonPrefix(0, S, E, 0); + + regexp = encodeString(regexp); + if (regexp.size() < 2000) { + return regexp; + } + else { + int n = E - S; + StringList::const_iterator M = S + n / 2; + + result.push_back( prefix + (const unsigned char*)"1\t" + subdivide(prefix + (const unsigned char*)"1", S, M, result) + (const unsigned char*)"\n"); + result.push_back( prefix + (const unsigned char*)"2\t" + subdivide(prefix + (const unsigned char*)"2", M, E, result) + (const unsigned char*)"\n"); + + return (const unsigned char*)"({" + prefix + (const unsigned char*)"1}|" + + (const unsigned char*)"{" + prefix + (const unsigned char*)"2})"; + } +} + +int main(int argc, char * argv[]) +{ + for (int i = 2; i < argc; ++i) { + FILE * f = fopen(argv[i], "r"); + + if (f == NULL) { + perror("fopen"); + return 1; + } + + readFile(f); + + fclose(f); + } + + sort(list.begin(), list.end()); + StringList result; + + String regexp = subdivide((const unsigned char*)argv[1], list.begin(), list.end(), result); + + for (StringList::const_iterator i = result.begin(); i != result.end(); ++i) + printf("%s", i->c_str()); + + printf("%s\t%s\n", argv[1], regexp.c_str()); + +} diff --git a/src/Mod/Spreadsheet/App/lex.ExpressionParser.c b/src/Mod/Spreadsheet/App/lex.ExpressionParser.c new file mode 100644 index 0000000000..ac1860f593 --- /dev/null +++ b/src/Mod/Spreadsheet/App/lex.ExpressionParser.c @@ -0,0 +1,7305 @@ + +#line 3 "lex.ExpressionParser.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer ExpressionParser_create_buffer +#define yy_delete_buffer ExpressionParser_delete_buffer +#define yy_flex_debug ExpressionParser_flex_debug +#define yy_init_buffer ExpressionParser_init_buffer +#define yy_flush_buffer ExpressionParser_flush_buffer +#define yy_load_buffer_state ExpressionParser_load_buffer_state +#define yy_switch_to_buffer ExpressionParser_switch_to_buffer +#define yyin ExpressionParserin +#define yyleng ExpressionParserleng +#define yylex ExpressionParserlex +#define yylineno ExpressionParserlineno +#define yyout ExpressionParserout +#define yyrestart ExpressionParserrestart +#define yytext ExpressionParsertext +#define yywrap ExpressionParserwrap +#define yyalloc ExpressionParseralloc +#define yyrealloc ExpressionParserrealloc +#define yyfree ExpressionParserfree + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE ExpressionParserrestart(ExpressionParserin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int ExpressionParserleng; + +extern FILE *ExpressionParserin, *ExpressionParserout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up ExpressionParsertext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up ExpressionParsertext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via ExpressionParserrestart()), so that the user can continue scanning by + * just pointing ExpressionParserin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when ExpressionParsertext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int ExpressionParserleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow ExpressionParserwrap()'s to do buffer switches + * instead of setting up a fresh ExpressionParserin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void ExpressionParserrestart (FILE *input_file ); +void ExpressionParser_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE ExpressionParser_create_buffer (FILE *file,int size ); +void ExpressionParser_delete_buffer (YY_BUFFER_STATE b ); +void ExpressionParser_flush_buffer (YY_BUFFER_STATE b ); +void ExpressionParserpush_buffer_state (YY_BUFFER_STATE new_buffer ); +void ExpressionParserpop_buffer_state (void ); + +static void ExpressionParserensure_buffer_stack (void ); +static void ExpressionParser_load_buffer_state (void ); +static void ExpressionParser_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER ExpressionParser_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE ExpressionParser_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE ExpressionParser_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE ExpressionParser_scan_bytes (yyconst char *bytes,int len ); + +void *ExpressionParseralloc (yy_size_t ); +void *ExpressionParserrealloc (void *,yy_size_t ); +void ExpressionParserfree (void * ); + +#define yy_new_buffer ExpressionParser_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + ExpressionParserensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + ExpressionParser_create_buffer(ExpressionParserin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + ExpressionParserensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + ExpressionParser_create_buffer(ExpressionParserin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +#define ExpressionParserwrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *ExpressionParserin = (FILE *) 0, *ExpressionParserout = (FILE *) 0; + +typedef int yy_state_type; + +extern int ExpressionParserlineno; + +int ExpressionParserlineno = 1; + +extern char *ExpressionParsertext; +#define yytext_ptr ExpressionParsertext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up ExpressionParsertext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + ExpressionParserleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 90 +#define YY_END_OF_BUFFER 91 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[2205] = + { 0, + 0, 0, 91, 90, 1, 2, 90, 42, 4, 90, + 44, 4, 11, 4, 82, 8, 4, 7, 31, 89, + 89, 89, 71, 35, 89, 55, 89, 89, 89, 69, + 89, 89, 84, 89, 25, 30, 89, 89, 21, 19, + 89, 89, 89, 89, 28, 27, 89, 89, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 2, 6, 0, 81, 80, 0, 0, + + 82, 0, 10, 5, 9, 0, 0, 88, 89, 89, + 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, 0, 0, 0, 0, 0, 74, 89, 34, + 57, 89, 72, 59, 89, 70, 75, 40, 17, 89, + 89, 18, 43, 89, 41, 33, 56, 89, 26, 20, + 89, 49, 32, 36, 58, 89, 24, 48, 16, 89, + 13, 51, 83, 89, 89, 52, 89, 38, 89, 22, + + 14, 47, 89, 76, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 0, 0, 0, + 0, 0, 0, 86, 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, 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, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 62, 61, 89, 73, 53, + 77, 79, 60, 68, 54, 50, 89, 46, 29, 39, + 67, 78, 89, 89, 37, 89, 23, 15, 89, 89, + 89, 89, 89, 12, 89, 89, 89, 89, 89, 89, + + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, + 0, 0, 81, 0, 80, 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, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 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, 89, 89, 89, 89, 89, 89, 89, 89, + + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 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, 63, 89, 45, 89, 89, + 89, 89, 89, 89, 0, 0, 0, 0, 89, 89, + 89, 89, 89, 89, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 89, 89, 89, 89, 89, 89, 64, 65, 89, + + 89, 89, 66, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 5, 6, 7, 8, 9, 1, 1, 10, 11, + 8, 8, 12, 13, 14, 15, 8, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 8, 8, 17, + 18, 19, 8, 8, 20, 21, 22, 21, 23, 21, + 24, 21, 21, 25, 26, 21, 27, 28, 21, 29, + 21, 21, 21, 30, 21, 31, 32, 21, 21, 21, + 8, 33, 8, 8, 34, 1, 35, 36, 37, 38, + + 39, 40, 41, 42, 43, 21, 44, 45, 46, 47, + 48, 49, 21, 50, 51, 52, 53, 21, 54, 21, + 55, 56, 8, 1, 8, 1, 1, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 1, 1, 121, 122, 123, 124, 125, 126, 127, + + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 1, 165, 166, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[167] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 1, 3, 1, + 1, 1, 1, 1, 1, 4, 1, 1, 1, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 1, 1, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int16_t yy_base[2352] = + { 0, + 0, 0, 4679,19593,19593, 4598, 4575,19593,19593, 0, + 19593, 4574,19593, 4573, 154, 154, 4557, 4556, 171, 0, + 4412, 4409, 0, 0, 148, 4391, 4399, 4357, 4369, 4336, + 190, 135, 0, 4323, 4324, 0, 4314, 209, 4322, 213, + 4309, 4298, 135, 4318, 4297, 4302, 205, 4301, 143, 0, + 150, 152, 154, 160, 165, 167, 169, 281, 280, 299, + 172, 177, 263, 336, 296, 298, 331, 371, 0, 0, + 0, 297, 0, 347, 375, 0, 388, 415, 478, 541, + 598, 662, 726, 790, 854, 918, 982, 1046, 1110, 1174, + 1238, 1234, 201, 4320,19593, 174, 247, 423, 4306, 4263, + + 252, 252,19593,19593,19593, 459, 4245,19593, 1353, 476, + 0, 365, 0, 301, 325, 356, 387, 389, 498, 521, + 1353, 0, 1352, 1463, 532, 551, 552, 1372, 554, 1335, + 1451, 1519, 428, 1491, 1582, 555, 1646, 1690, 1536, 1722, + 1773, 1800, 1864, 1927, 1984, 2048, 2112, 2176, 2240, 2304, + 2368, 2432, 2496, 2560, 2624, 2620, 1471, 2739, 4220, 0, + 0, 4206, 0, 0, 3966, 3950, 0, 0, 0, 3948, + 3952, 0, 0, 3941, 0, 0, 0, 3947, 0, 0, + 3921, 139, 0, 0, 0, 3915, 0, 231, 0, 3889, + 0, 0, 0, 3879, 3878, 0, 3867, 0, 3861, 0, + + 0, 0, 2787,19593, 1500, 0, 1528, 1751, 2736, 0, + 2851, 1920, 2875, 1777, 2888, 334, 368, 1527, 0, 3820, + 1954, 1277, 2881, 1905, 2853, 2885, 2927, 1710, 2905, 1959, + 0, 2761, 3831, 2924, 1563, 0, 0, 0, 2976, 3002, + 3012, 3022, 3032, 3042, 2904, 3054, 3075, 3110, 0, 2766, + 3094, 0, 3826, 3825, 3806, 3786, 3774, 3771, 3769, 3760, + 1311, 1727, 3104, 0, 1894, 3127, 104, 0, 1251, 3153, + 181, 0, 0, 2749, 2781, 3178, 3210, 3719, 1816, 3179, + 3231, 3203, 3061, 3238, 3026, 3740, 3735, 3720, 3565, 3563, + 3562, 3493, 1472, 3281, 1504, 3316, 260, 3332, 0, 3236, + + 280, 3455, 3378, 100, 3425, 3390, 3330, 3281, 3431, 3464, + 3422, 3415, 0, 3247, 365, 3256, 3463, 0, 3464, 3528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3555, 0, 0, 0, 0, 0, + 0, 3334, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3485, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 3577, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3602, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3282, 0, 3549, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3666, 3679, + 0, 0, 0, 0, 0, 3648, 277, 3673, 3705, 0, + 3724, 3688, 546, 3441, 3728, 3702, 3770, 0, 3792, 3828, + 573, 3794, 3772, 3876, 3922, 2662, 1278, 0, 0, 0, + + 0, 0, 0, 0, 0, 3970, 4034, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 4064, 4128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3422, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3855, 3872, 0, 0, 0, 0, 0, 512, 0, + 0, 0, 412, 4105, 4169, 0, 0, 0, 0, 1309, + 1375, 1474, 4185, 4157, 0, 1500, 0, 4221, 3363, 4257, + + 399, 4281, 3357, 1548, 1442, 3457, 3455, 491, 1439, 1851, + 458, 3437, 3439, 3416, 4372, 4324, 0, 4176, 0, 0, + 4356, 4350, 4264, 3788, 0, 4482, 4509, 4572, 4635, 4692, + 4756, 4784, 3938, 0, 4360, 4421, 4848, 1722, 4476, 4911, + 4975, 5019, 4503, 4628, 5051, 5078, 5142, 5205, 5262, 5326, + 5354, 4273, 5473, 5583, 1599, 4833, 0, 5629, 5693, 3504, + 5757, 5422, 5815, 5028, 5869, 3099, 4277, 1934, 5917, 5920, + 5968, 5475, 5485, 5990, 6032, 6085, 6149, 6011, 6201, 4835, + 3100, 6076, 6227, 3395, 3340, 6193, 6291, 6353, 4894, 0, + 0, 0, 0, 0, 5206, 5465, 3307, 2836, 6385, 6240, + + 6405, 0, 3341, 3276, 3261, 3256, 3254, 3168, 3123, 3115, + 2919, 3735, 6469, 1922, 5199, 5834, 6533, 6100, 4482, 4615, + 5898, 6560, 4636, 5728, 6470, 6480, 6603, 6667, 3844, 6730, + 6782, 6763, 3887, 6846, 5456, 3106, 3088, 3063, 6872, 3055, + 3049, 3045, 3039, 3807, 6888, 2860, 6936, 6588, 6998, 0, + 0, 4315, 6652, 0, 0, 6985, 6639, 7049, 7069, 1919, + 2982, 7082, 4185, 7109, 7138, 7202, 2978, 7261, 0, 5971, + 1771, 4199, 3015, 7309, 6708, 6936, 7261, 0, 7373, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7400, 0, 0, 0, 0, 0, 0, + 7025, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7297, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7332, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7425, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 3962, 0, 7178, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7396, 7489, 0, + 0, 0, 0, 7473, 7468, 1547, 7518, 7521, 0, 5973, + 6362, 7566, 7576, 6742, 7628, 7688, 7691, 7592, 7736, 7670, + 7796, 7774, 7822, 7863, 7873, 7892, 0, 0, 0, 0, + 0, 0, 0, 0, 7950, 8014, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8044, + 8108, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 4619, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7701, 6221, 0, 0, 0, 0, 0, 1629, 0, 0, + 2979, 2683, 8085, 8149, 0, 0, 0, 0, 1936, 2683, + 2785, 8165, 0, 8137, 0, 3130, 7822, 7862, 2921, 8223, + 6606, 8252, 2921, 3081, 2793, 8343, 0, 2980, 0, 0, + 0, 0, 0, 0, 0, 0, 2960, 0, 0, 0, + 0, 0, 2944, 2927, 0, 2918, 0, 0, 8269, 0, + 0, 0, 0,19593, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2882, 2897, 2835, 2837, 2795, + 2847, 2848, 2717, 2750, 3221, 2472, 2927, 3276, 8451, 2144, + 1962, 1862, 1850, 1800, 1749,19593, 0, 5983, 8375, 8450, + 8498, 8489, 6893, 8527, 6020, 8543, 3195, 8563, 0, 8581, + 3293, 8608, 6906, 8641, 6894, 8343, 5825, 8656, 8674, 8736, + 0, 8762, 8767, 6945, 4423, 0, 8704, 8803, 8829, 0, + 2942, 8877, 8897, 8840, 8914, 0, 6474, 8977, 8981, 9029, + 9050, 4703, 9074, 9076, 6676, 5030, 8868, 1626, 9103, 9136, + 9151, 0, 0, 9165, 9190, 5190, 7549, 9222, 9254, 0, + + 9113, 9287, 7154, 9347, 9326, 9388, 9394, 0, 2936, 8261, + 9507, 9617, 3408, 0, 9663, 9727, 6497, 9791, 9456, 9849, + 5770, 9903, 5031, 9498, 3378, 9951, 9954,10002, 9964, 9517, + 10024,10066,10119,10183,10045,10235, 8665, 9529,10110,10261, + 5265, 1660,10227,10325,10387,10419, 3458,10438,10471,10535, + 9909,10552,10585, 7756,10649,10272,10655,10719, 5835,10782, + 10834,10815, 6004,10104,10898, 0, 5464,10877,10962,11021, + 3033,10456, 4243,11044,11104,10694,11158,11218,10801, 3075, + 11281,10991,11108, 9989, 8238,11230, 1597, 0, 6948,11344, + 11435,11361, 0,11387, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1519, 1473, 215, + 2959, 2893, 3730, 1494, 1448, 2636, 1483, 1445, 3103, 1385, + 3758, 1947, 3101, 304, 1311, 3115, 1351, 5478, 1266, 1292, + 3762, 1293, 3288, 4480,11543, 0, 1297, 0, 1099, 724, + 0, 0, 0, 0, 608, 534, 518, 557, 0, 0, + 0, 0, 0, 0, 493, 501, 2925, 3883, 526, 401, + 3046, 406, 3286, 338, 4895, 2692, 3309, 1546, 264, 3361, + 6034, 0, 0, 0, 0, 0, 0, 0, 0, 292, + + 0, 0, 0,19593, 264,11657,11705,11724,11788,11852, + 11916, 3973,11971,12035,12099,12162,12197,12261,12298,12344, + 12405,12462,12524,12572,12636,12700,12726,12790,12808,12872, + 12887,12938,13001,13065,13124,13188,13252,13316,13380,13444, + 13508,13572,13636,13700,13764,13828,13892,13956,14000,14061, + 14125,14189,14253,14317,14381,14407,14437, 4010,14501,14565, + 14613,14632,14696,14760,14824,14874,14922,14986,15036,15028, + 15092,15154,15217,15279,15343,15404,15467,15531,15573,15631, + 15668,15710,15757,15816,15848,15912,15939,16003,16067,16131, + 16195,16259,16323,16387,16451,16515,16579,16643,16707,16771, + + 16835,16899,16943,17004,17059,17123,17187,17251,17315,17379, + 17405,17468,17498, 1436,17557,17594,17640,17701,17745,17808, + 17870,17934,17998,18062,18096,18160,18191,18253,18317,18381, + 18435,18496,18559,18551,18615,18677,18740,18802,18866,18927, + 18991,19033,19081,19123,19172,19234,19298,19362,19423,19478, + 19541 + } ; + +static yyconst flex_int16_t yy_def[2352] = + { 0, + 2204, 1, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2205, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 2204, 2206, + 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2204, 2204, 2206, + 2206, 2206, 2206, 60, 2206, 2206, 2206, 2204, 2207, 2208, + 2209, 2206, 2210, 2207, 60, 2211, 2207, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2212, 2204, 2204, 2204, 2204, + + 2204, 2213, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 109, + 109, 2204, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, + 2204, 2215, 2215, 2214, 2214, 2214, 2214, 2214, 2214, 2214, + 2214, 2215, 2216, 2217, 2204, 2214, 2204, 2217, 124, 2216, + 140, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + + 158, 158, 158, 2204, 203, 2218, 2218, 2204, 2219, 2220, + 2219, 2204, 211, 2204, 211, 2204, 211, 2204, 2221, 2204, + 2219, 2204, 2219, 2204, 2219, 2204, 2219, 2204, 2219, 2204, + 2222, 2204, 2204, 229, 2204, 2223, 2224, 2225, 2225, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 2226, 2225, + 2223, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, + 2227, 2227, 2227, 2228, 2228, 263, 2204, 2229, 266, 2227, + 266, 2230, 2231, 266, 2204, 2227, 2204, 2204, 266, 2204, + 2230, 2230, 2230, 2229, 2204, 2227, 2227, 2227, 2227, 2227, + 2227, 2227, 2227, 2227, 2227, 294, 2204, 2204, 2232, 2204, + + 2204, 2204, 2232, 303, 303, 303, 303, 306, 303, 308, + 2204, 2204, 2233, 2233, 2233, 2233, 2233, 2234, 2204, 2233, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2236, 2236, 2236, + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + 2236, 2236, 2236, 2236, 2236, 2237, 2237, 2237, 2237, 2237, + 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2239, 2239, 2239, 2239, 2239, 2239, + + 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + + 2241, 2241, 2241, 2241, 2241, 2242, 2242, 2242, 2242, 2242, + 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, + 2242, 2242, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2244, 2244, 2244, 2244, + 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, + + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2246, 2246, 2204, + 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, + 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2204, 2247, + 2247, 2247, 2247, 2247, 2248, 2247, 2247, 776, 770, 2247, + 776, 2204, 778, 776, 776, 2204, 770, 2249, 776, 2204, + 778, 2249, 2247, 2204, 2247, 778, 778, 2247, 2247, 2247, + + 2247, 2247, 2247, 2247, 2247, 2204, 806, 807, 807, 807, + 807, 807, 807, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2251, 2251, 2251, + 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, + 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, + + 2204, 901, 902, 902, 902, 902, 902, 902, 902, 902, + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + 902, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2253, 2253, + 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, + 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, + 2253, 2253, 2253, 2254, 2254, 2254, 2254, 2254, 2254, 2254, + 2255, 2256, 2254, 2254, 2256, 2254, 2254, 2254, 2254, 2254, + 985, 2254, 2204, 2204, 2254, 2254, 2257, 2254, 2254, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2258, 2204, 2204, + 2259, 2204, 2259, 2204, 2204, 2204, 2260, 2204, 2261, 2262, + 2263, 2264, 2261, 2260, 2265, 2265, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2266, 2266, 2260, 2266, 2261, 2267, 2204, + 2204, 2267, 2260, 2268, 2268, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2269, 2204, 2270, 2204, 2204, 2271, + 2204, 2271, 2204, 1062, 2204, 1062, 1061, 2272, 2204, 1062, + 1065, 1062, 1065, 1062, 1073, 1062, 2204, 1076, 2204, 2273, + 1079, 2274, 1078, 2275, 2204, 2276, 2204, 2276, 2276, 2276, + 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2204, 2276, + + 2276, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, + 2277, 2277, 2277, 2278, 2278, 2277, 2204, 2279, 1113, 2277, + 1113, 1116, 2280, 1116, 2204, 2277, 1122, 2204, 1116, 2204, + 1122, 1122, 1132, 2277, 2281, 2277, 2277, 2277, 2281, 2277, + 2277, 2277, 2277, 2277, 2277, 2277, 1145, 2204, 2204, 2282, + 2283, 2284, 2204, 2285, 2286, 2204, 2204, 2204, 2283, 1159, + 1159, 1159, 1159, 1162, 1159, 2204, 2204, 2204, 2287, 2287, + 2287, 2287, 2287, 2287, 2204, 2204, 2204, 2288, 2287, 2289, + 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + + 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + 2289, 2289, 2289, 2289, 2289, 2289, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2291, 2291, 2291, 2291, 2291, 2291, + 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2293, 2293, 2293, 2293, 2293, 2293, 2293, + 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2294, + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2296, 2296, 2296, 2296, 2296, 2296, + 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, + 2296, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2298, 2298, 2298, 2298, 2298, + 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + + 2299, 2299, 2299, 2299, 2299, 2299, 2300, 2300, 2204, 2301, + 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, + 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2204, 2301, 2301, + 2301, 2301, 2301, 2302, 2301, 2301, 2302, 1629, 2301, 2302, + 2204, 2302, 2302, 1635, 2204, 2301, 2303, 1635, 2204, 1643, + 2303, 2301, 2304, 2303, 2302, 1650, 2301, 2301, 2301, 2301, + 2301, 2301, 2301, 2301, 2204, 1665, 1666, 1666, 1666, 1666, + 1666, 1666, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2306, 2306, 2306, 2306, + 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, + 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2204, + 1760, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, + 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, + 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, + 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, + + 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2308, 2308, 2308, + 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, + 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, + 2308, 2308, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2310, + 2311, 2309, 2309, 2311, 2309, 2309, 2309, 2309, 2309, 1844, + 2309, 2204, 2312, 2204, 2309, 2309, 2313, 2309, 2309, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 1866, 1866, 1866, 1866, + 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, + 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1889, + 1889, 1889, 1889, 2204, 1889, 1889, 1889, 1889, 1889, 1889, + + 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, + 1889, 1889, 1889, 1889, 1889, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2314, 2204, 2204, 2204, 2204, 2204, 2315, 2315, 2316, 2317, + 2316, 2204, 1941, 2204, 1941, 2204, 1941, 2204, 2318, 2204, + 2316, 2204, 2316, 2204, 2316, 2319, 2316, 2204, 2316, 2204, + 2320, 2204, 2204, 1959, 2204, 2321, 2322, 2323, 2204, 2324, + 2324, 2324, 2204, 2325, 1972, 2326, 1972, 2204, 1975, 2204, + 2204, 1972, 2204, 2326, 2326, 2326, 2204, 2327, 2327, 1989, + 2204, 2328, 2329, 2329, 2329, 2330, 2329, 2204, 1994, 2331, + + 2329, 2204, 2329, 2331, 2329, 2204, 2330, 2332, 2204, 2204, + 2204, 2204, 2333, 2334, 2204, 2204, 2335, 2204, 2335, 2204, + 2019, 2204, 2019, 2018, 2336, 2204, 2019, 2022, 2019, 2022, + 2019, 2030, 2019, 2204, 2033, 2204, 2337, 2036, 2338, 2035, + 2339, 2204, 2340, 2204, 2340, 2204, 2341, 2341, 2341, 2204, + 2342, 2049, 2049, 2049, 2204, 2052, 2053, 2204, 2049, 2204, + 2053, 2053, 2062, 2343, 2343, 2344, 2345, 2345, 2204, 2204, + 2346, 2347, 2347, 2347, 2074, 2347, 2204, 2347, 2348, 2076, + 2204, 2074, 2348, 2347, 2349, 2075, 2350, 2351, 2204, 2204, + 2204, 2091, 2091, 2091, 2091, 2092, 2094, 2091, 2094, 2091, + + 2092, 2091, 2094, 2092, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2094, 2092, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2092, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2091, 2091, 2091, 2091, 2091, + 2092, 2092, 2092, 2092, 2204, 2204, 2204, 2204, 2091, 2091, + 2091, 2091, 2091, 2091, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2092, 2091, 2092, 2091, 2091, 2091, 2091, 2091, 2091, + + 2091, 2091, 2091, 0, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204 + } ; + +static yyconst flex_int16_t yy_nxt[19760] = + { 0, + 4, 5, 6, 4, 5, 7, 8, 9, 10, 11, + 9, 9, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 20, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 4, 4, 20, 20, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 20, 48, 20, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 4, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 99, 160, 100, 101, + 102, 103, 106, 171, 106, 161, 162, 193, 1875, 107, + 172, 108, 1006, 1892, 1876, 194, 109, 2204, 1892, 1007, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + + 110, 110, 110, 1893, 111, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 168, 176, 203, + 198, 203, 183, 203, 199, 169, 177, 178, 184, 203, + 185, 203, 186, 170, 203, 200, 203, 204, 203, 179, + 201, 203, 205, 187, 180, 188, 203, 203, 189, 181, + 190, 203, 97, 203, 99, 203, 100, 101, 96, 1009, + 1012, 203, 109, 1001, 1002, 1878, 203, 1879, 203, 1003, + 203, 109, 2204, 203, 1013, 1009, 1004, 1005, 203, 1892, + 1892, 112, 113, 114, 115, 116, 117, 118, 119, 120, + + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 203, 203, 1893, + 1893, 2203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 2204, 2204, 2204, 2204, 2204, + 2204, 2194, 2204, 2204, 2204, 1893, 2204, 2195, 2204, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 1893, + 1015, 203, 2202, 203, 203, 203, 203, 203, 203, 2204, + 203, 203, 203, 203, 203, 203, 203, 203, 2204, 203, + + 2204, 2204, 2204, 203, 1015, 203, 1890, 203, 203, 203, + 203, 2204, 1015, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 1895, 1890, 1890, 2204, 2202, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 1015, 1015, 2204, 98, 2204, + 2204, 2204, 203, 2204, 203, 1010, 203, 203, 203, 203, + 203, 2204, 2204, 2204, 203, 203, 203, 203, 203, 203, + 106, 1010, 106, 1015, 2202, 203, 1015, 1015, 1015, 108, + 2204, 109, 109, 2204, 1015, 1890, 1012, 1890, 109, 1015, + 2204, 109, 109, 109, 107, 1053, 1053, 1916, 1053, 1053, + 1013, 1053, 2204, 2204, 2204, 1917, 203, 203, 1015, 1006, + + 1015, 2202, 203, 206, 207, 208, 1007, 209, 210, 211, + 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 1015, 279, 280, + 281, 282, 283, 284, 2202, 285, 286, 287, 288, 2201, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + + 1015, 299, 300, 301, 2204, 302, 1034, 1035, 2204, 1015, + 2201, 1015, 1036, 2204, 2204, 2204, 1037, 1038, 1039, 1040, + 2195, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, + 1015, 1015, 1015, 1015, 1015, 2195, 1050, 2204, 2204, 2204, + 1051, 1052, 2204, 1015, 2195, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 1015, 1015, 2193, 1015, 1015, 1908, 1908, 1908, + 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, + + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 421, 422, 2200, 423, 424, 425, 426, 427, 428, + 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, + + 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, + 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, + 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, + 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, + 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, + 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, + + 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, + 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, + 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, + 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, + 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, + 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, + 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, + 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, + 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, + 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, + + 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, + 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, + 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, + 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, + 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, + 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, + 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, + 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, + 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, + + 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, + 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, + 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, + 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, + 789, 790, 791, 792, 793, 794, 795, 796, 2199, 797, + 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, + 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, + 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, + 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, + 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, + + 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, + 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, + 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, + 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, + 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, + 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, + 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, + 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, + 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, + 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, + + 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, + 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, + 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, + 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, + 988, 989, 990, 991, 992, 993, 2198, 994, 995, 996, + 997, 998, 999, 1000, 106, 2196, 106, 1890, 1890, 1892, + 1892, 1892, 1892, 108, 2193, 1890, 1890, 1892, 109, 2204, + 2204, 2204, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 2195, 111, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 2195, 2204, 2204, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 2204, 2204, 2194, + 2204, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1931, 2204, + 1931, 1015, 1015, 1015, 1015, 1015, 1015, 1915, 1915, 1915, + 1932, 1015, 1932, 1015, 1933, 1015, 1015, 1015, 1015, 1015, + 1015, 2204, 1015, 1015, 2204, 2204, 1015, 1015, 1015, 1015, + 2204, 1015, 2194, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 1015, 1016, 124, 125, 126, 127, 1017, + 129, 130, 131, 1018, 1019, 1020, 1021, 136, 1022, 1023, + + 1024, 1025, 1026, 1027, 1028, 1029, 1030, 146, 147, 148, + 149, 150, 151, 1031, 153, 154, 155, 1032, 1033, 2204, + 2204, 2204, 2204, 2204, 2204, 1885, 2204, 2195, 1892, 1886, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 1887, 2194, 1015, 1861, 1862, 1888, 2204, 2204, 2194, 1863, + 2204, 2204, 2194, 2204, 1928, 1929, 1864, 1865, 2204, 2204, + 1892, 2192, 1015, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + + 1053, 1053, 1053, 2202, 2204, 1015, 1889, 1889, 1889, 2195, + 2204, 1890, 1890, 2204, 1890, 1890, 1890, 2204, 2204, 2204, + 2204, 2204, 1925, 2204, 2204, 1926, 1015, 1890, 1890, 1890, + 1890, 1890, 1890, 2204, 2119, 1927, 2192, 2204, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 2092, 2092, 2092, 2174, 1015, 1015, 1053, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 2169, 1015, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 2204, 2204, 1053, 1053, 1053, 1053, 1053, 1053, 1015, + 1015, 1053, 1053, 2099, 1053, 1053, 1053, 1053, 1015, 1015, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 1015, 1015, 1015, 1053, 1935, 1015, 1890, 1890, 1890, 1890, + 1890, 1890, 1890, 1015, 1015, 1015, 1015, 1015, 1015, 2011, + 2011, 1015, 2011, 2011, 1015, 2011, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1053, 1053, 1053, 1053, 1053, 1053, + + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 2204, 2204, 2204, 2204, 2204, 1935, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 2102, 2204, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 1889, + 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, + 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1890, 1890, + 1890, 1890, 1934, 1890, 1934, 1933, 1935, 1015, 1015, 1015, + 1015, 1015, 2204, 2204, 2204, 2204, 2204, 1933, 1053, 1053, + 1053, 1015, 1015, 1890, 1890, 1890, 2204, 1015, 1054, 1055, + 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, + + 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, + 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, + 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, + 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, + 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, + 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, + 1126, 1127, 1128, 1892, 1129, 1130, 1131, 1132, 1133, 1134, + 1006, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, + 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, + 1890, 1890, 2092, 1890, 1890, 2204, 2096, 2096, 2096, 2204, + + 1154, 1155, 1156, 2194, 1890, 1890, 2204, 1890, 1890, 1890, + 1890, 1890, 1157, 1158, 2204, 1890, 1890, 1890, 1890, 1890, + 1890, 1890, 2100, 2204, 1890, 1890, 2194, 2204, 2096, 2096, + 2096, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, + 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, + 1178, 2204, 2092, 2092, 2204, 2204, 1179, 1180, 1181, 1182, + 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, + 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, + 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, + 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, + + 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, + 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, + 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, + 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, + 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, + 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1930, + 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, + 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, + 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, + 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, + + 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, + 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, + 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, + 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, + 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, + 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, + 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, + 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, + 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, + 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, + + 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, + 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, + 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, + 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, + 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, + 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, + 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, + 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, + 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, + 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, + + 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, + 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, + 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, + 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, + 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, + 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, + 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, + 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, + 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, + 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, + + 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, + 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, + 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, + 1652, 1653, 1654, 1655, 2163, 1656, 1657, 1658, 1659, 1660, + 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, + 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, + 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, + 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, + 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, + 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, + + 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, + 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, + 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, + 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, + 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, + 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, + 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, + 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, + 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, + 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, + + 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, + 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, + 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, + 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, + 106, 2204, 106, 2194, 2204, 2204, 2195, 107, 2202, 108, + 2204, 2204, 2204, 2204, 109, 2126, 2126, 2126, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 2202, 111, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 2204, 1889, 1889, 1889, 1889, + + 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, + 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1890, 1890, 1890, + 1890, 1890, 2161, 1890, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 2162, 1891, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1890, 1890, 1890, 1890, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 1034, + 1035, 124, 125, 126, 127, 1036, 129, 130, 131, 1037, + 1038, 1039, 1040, 136, 1041, 1042, 1043, 1044, 1045, 1046, + 1047, 1048, 1049, 146, 147, 148, 149, 150, 151, 1050, + + 153, 154, 155, 1051, 1052, 2154, 2155, 1890, 2162, 2204, + 2162, 2204, 2162, 2204, 2204, 2204, 2098, 122, 123, 2162, + 2204, 2204, 2204, 128, 2204, 2204, 2204, 132, 133, 134, + 135, 2204, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 2204, 2204, 2204, 2204, 2162, 2161, 152, 2204, 2193, + 2204, 156, 157, 2161, 2204, 1890, 2204, 1890, 2204, 2204, + 2204, 1890, 1890, 1890, 1890, 2160, 1891, 1890, 1891, 2204, + 1891, 1891, 1891, 1890, 1890, 2098, 2159, 2204, 2204, 2204, + 1890, 2193, 1890, 2204, 1890, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2163, 2163, 1890, 2158, 1890, 2161, 1890, + + 1890, 1890, 1890, 1890, 1890, 2130, 2204, 2204, 2204, 2157, + 2204, 2098, 2192, 2204, 2204, 2204, 2204, 2204, 2204, 1891, + 2204, 2204, 2204, 2193, 2131, 2204, 2204, 2204, 2204, 2156, + 2204, 2204, 2165, 2204, 1891, 1891, 1891, 1891, 2150, 1891, + 2204, 1890, 1890, 2204, 2201, 1891, 2204, 2204, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 2127, 1891, 1891, 1891, 1891, + 1891, 2102, 1891, 1891, 1891, 2193, 1891, 1891, 1891, 1891, + 1891, 2100, 1891, 1891, 1891, 2100, 1891, 1891, 1891, 1891, + 1891, 2204, 1891, 1891, 1891, 2098, 1891, 1891, 1891, 1891, + + 1891, 2098, 1891, 1891, 1891, 2098, 1891, 1891, 1891, 1891, + 1891, 2098, 1891, 1891, 2172, 2172, 1891, 1891, 1891, 2098, + 1891, 1891, 1891, 1892, 1892, 1892, 1892, 1891, 1892, 1892, + 1892, 1892, 2204, 2173, 2173, 1892, 1892, 1891, 2204, 1891, + 1891, 1891, 1891, 1891, 2098, 1891, 1891, 1891, 1892, 1892, + 1892, 1892, 1892, 2202, 2204, 2151, 2195, 1891, 2152, 2204, + 1892, 2204, 2098, 2204, 2204, 2204, 2093, 2093, 2153, 1891, + 2204, 2098, 1891, 2204, 1891, 1891, 1891, 1891, 1891, 2098, + 1891, 1891, 2173, 2204, 2093, 2093, 2093, 2093, 2204, 2204, + 1891, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + + 1892, 1892, 1892, 2204, 2204, 2204, 2204, 2204, 2204, 1892, + 2093, 2194, 2194, 2204, 2194, 2194, 2093, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2098, 1891, 1892, 1892, 1892, 1892, + 1892, 1892, 2194, 2194, 1892, 2204, 2204, 2204, 2204, 2204, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 2204, 2204, 2204, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1893, 1893, 1893, + + 1893, 1893, 2093, 1895, 2093, 2163, 1893, 1892, 1892, 1892, + 2098, 2163, 2098, 2204, 2204, 2204, 2204, 2098, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 2204, 2204, 2204, 2204, + 2204, 2204, 2098, 1892, 1892, 2204, 2163, 1892, 1906, 1906, + 1906, 1906, 1906, 2204, 2204, 1892, 1892, 1892, 1892, 1892, + 1892, 2204, 2204, 2204, 2196, 2196, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2164, 2204, + 2204, 2164, 2204, 2204, 1893, 1893, 1893, 2204, 1892, 1892, + 2204, 2204, 2204, 2204, 1893, 2204, 2204, 2204, 2204, 2164, + 2204, 2164, 2204, 2204, 2202, 2202, 1892, 2098, 1892, 2204, + + 2204, 2204, 2092, 2204, 1893, 1893, 1893, 1893, 1893, 1893, + 1893, 1893, 1893, 1893, 1893, 1893, 1893, 2204, 2204, 2204, + 2204, 2204, 2202, 2202, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 1014, 2204, 2204, 1893, 1893, 2169, 1893, 1893, 1893, + 1893, 1011, 1893, 1893, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 1893, 1936, 1893, 1893, 1893, 2093, + 2093, 2093, 2093, 2093, 1893, 1893, 1893, 1893, 1893, 1893, + 1007, 1893, 1930, 1893, 1924, 1893, 1895, 1895, 2202, 2202, + 1893, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2169, + 2169, 2169, 1893, 1893, 2204, 2204, 2169, 2169, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 1895, + 1895, 1895, 1895, 1895, 1895, 1893, 2204, 2204, 1893, 1894, + 1895, 1895, 2170, 2170, 2170, 2204, 1914, 1914, 1914, 1914, + 1914, 1914, 2204, 2204, 1908, 1908, 1908, 1908, 1908, 1892, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2092, 2092, 2092, 2170, 2170, 2170, 2204, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1901, 1901, 1901, 1901, 1901, + 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, + + 1901, 1901, 1901, 1901, 1901, 1907, 1907, 1907, 1907, 1907, + 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1892, 1892, + 2092, 1892, 2092, 2092, 1896, 1896, 1896, 1896, 1896, 1896, + 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, + 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1898, 1898, + 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, + 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, + 1898, 1898, 1898, 1898, 1898, 1903, 1903, 1903, 1903, 1903, + 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, + 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1906, 1906, 1906, + + 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, + 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, + 1906, 1906, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 1892, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2194, 2194, 2194, 2204, + 2204, 1892, 2204, 2204, 2204, 2204, 1892, 2204, 2204, 1908, + + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1892, 2194, 1892, 1908, 2204, 2204, + 2204, 2204, 2204, 1908, 1908, 1892, 2204, 1892, 1908, 1908, + 1892, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1892, 2204, 2204, 2204, 2196, 2204, 2204, 2204, + 2204, 2204, 2196, 2204, 2204, 2204, 2204, 1908, 1908, 1908, + 1908, 1908, 1892, 2098, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2194, 2195, 2204, 2196, 2204, 2204, + 2204, 1892, 1892, 2204, 2204, 2204, 2204, 1890, 1908, 1908, + 2204, 2204, 1890, 2204, 2204, 1908, 1908, 1908, 1908, 1908, + + 2096, 2096, 2096, 2096, 2096, 2204, 2204, 2204, 1884, 2204, + 2204, 2204, 1908, 1908, 1883, 1882, 1908, 1908, 1908, 1908, + 1908, 1881, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1880, 1908, 2204, 2204, 2204, 2204, 2202, + 2202, 2202, 1908, 1908, 1908, 1908, 1908, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 1908, + 1908, 1908, 1877, 1874, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1008, 1008, 1008, 2204, 2096, + 2096, 1873, 1908, 1908, 1908, 2204, 2204, 1872, 2204, 2204, + 2204, 2204, 1871, 2204, 2204, 2096, 2096, 2096, 2096, 1870, + + 1869, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2009, 2010, 1931, 1931, 1931, 1868, 1863, 2204, 2115, 2115, + 2115, 2115, 2115, 1864, 1865, 2204, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1909, 1909, 1909, 1909, + 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, + 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, + 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, + 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, + + 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, + 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, 1909, + 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, + 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, + 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1912, 1912, 1912, + 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, + 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, + 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, + 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, + 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, + + 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, 1912, + 1912, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1867, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1866, 1915, 2204, 2204, 2204, 2204, + 1014, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 2204, 98, 2204, + 1915, 2204, 2204, 2204, 2204, 2204, 1915, 2204, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + + 1915, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 1915, 1915, 1915, 1915, 1915, + 1915, 97, 94, 1915, 1915, 1915, 1915, 1915, 1915, 2204, + 2173, 1915, 1915, 1915, 1915, 1915, 1915, 2204, 202, 1915, + 1915, 1915, 1918, 197, 1919, 2089, 2090, 2204, 196, 1920, + 2117, 1863, 195, 192, 191, 2092, 1921, 182, 1864, 1865, + 175, 2117, 1922, 1015, 1015, 1015, 1015, 1015, 2204, 2204, + 2204, 174, 1923, 106, 173, 106, 2100, 2100, 2100, 2100, + 2100, 2204, 108, 2094, 2094, 2100, 167, 109, 166, 2204, + 2204, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 165, 111, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 164, 1015, 1015, 163, 159, 1015, 1015, + 1015, 1015, 158, 1015, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 1015, 1015, 1015, 1015, 1015, 2204, + 1015, 1015, 2204, 2204, 1015, 1015, 1015, 1015, 2204, 1015, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2093, 2093, 2093, + 2093, 2093, 112, 113, 114, 115, 116, 117, 118, 119, + + 120, 121, 1034, 1035, 124, 125, 126, 127, 1036, 129, + 130, 131, 1037, 1038, 1039, 1040, 136, 1041, 1042, 1043, + 1044, 1045, 1046, 1047, 1048, 1049, 146, 147, 148, 149, + 150, 151, 1050, 153, 154, 155, 1051, 1052, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2204, 2204, 2197, 105, 104, 2197, 1015, 1015, 1015, 1015, + 1015, 2098, 2098, 2098, 2098, 2098, 2098, 2204, 98, 97, + 1015, 1015, 95, 2197, 2204, 2197, 1015, 1937, 1938, 1056, + + 94, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, + 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, + 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, + 1968, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, + 1098, 1969, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, + 1108, 1109, 1110, 1111, 1112, 1113, 1970, 1971, 1972, 1973, + 1974, 1119, 1975, 1121, 1976, 1123, 1977, 1978, 1979, 1980, + 1981, 2098, 1982, 1983, 1984, 1985, 1986, 1134, 2204, 1987, + 1136, 1137, 1138, 2204, 1140, 1141, 1142, 1143, 1144, 1145, + 1146, 1147, 1148, 1149, 2204, 1151, 1152, 1153, 2097, 2097, + + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 1154, 1155, + 1156, 2204, 2096, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 1157, 1158, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2125, 2125, 2125, 2125, 2125, 2125, 1159, + 1160, 1161, 1988, 1163, 1989, 1165, 1990, 1167, 1991, 1169, + 1992, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 2204, + 2204, 2204, 2204, 2204, 1179, 1180, 1181, 1182, 1183, 1184, + 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, + 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, + 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, + + 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, + 1225, 1226, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, + 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, + 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1993, 1994, 1995, + 1638, 1639, 1640, 1641, 1996, 1643, 1997, 1998, 1999, 2000, + 2001, 2002, 2003, 2004, 2005, 2006, 1654, 1655, 2204, 2007, + 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, + 1667, 1668, 1669, 1670, 1671, 1672, 1833, 1834, 1835, 1836, + 1837, 1838, 1839, 1840, 2008, 1842, 1843, 1844, 1845, 1846, + 1847, 1848, 1849, 1850, 1851, 1852, 2204, 1854, 1855, 1856, + + 1857, 1858, 1859, 1860, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2092, 2204, 2204, 2092, 2092, 2092, 2092, 2092, 2092, 2204, + 2092, 2092, 2202, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 109, + + 109, 109, 109, 109, 109, 109, 109, 109, 109, 2204, + 2204, 2202, 2195, 1015, 1015, 2011, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 2204, 1015, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2204, 2204, 2011, 2011, 2011, 2011, 2011, 2011, 1015, 1015, + 2011, 2011, 2204, 2011, 2011, 2011, 2011, 1015, 1015, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 1015, + 1015, 1015, 2011, 2204, 1015, 2093, 2093, 2093, 2093, 2093, + + 2204, 2093, 1015, 1015, 1015, 1015, 1015, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 2098, 2098, 2098, + 2098, 2098, 2204, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2093, + 2204, 2204, 2093, 2204, 2204, 2093, 2204, 2204, 2093, 2204, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 1015, + 1015, 2204, 2204, 2204, 2204, 1015, 2012, 2013, 1056, 2014, + 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, + 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, + 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, + + 2045, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, + 1098, 2046, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, + 1108, 1109, 1110, 1111, 1112, 1113, 2047, 2048, 2049, 2050, + 2051, 1119, 2052, 1121, 2053, 1123, 2054, 2055, 2056, 2057, + 2058, 2204, 2059, 2060, 2061, 2062, 2063, 1134, 2204, 2064, + 1136, 1137, 1138, 2065, 1140, 1141, 1142, 1143, 1144, 1145, + 1146, 1147, 1148, 1149, 2066, 1151, 1152, 1153, 2098, 2204, + 2204, 2204, 2204, 2096, 2096, 2204, 2204, 2204, 1154, 1155, + 1156, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 1157, 1158, 2204, 2204, 2118, 2118, 2118, 2118, 2118, 2118, + + 2204, 2204, 2204, 2204, 2204, 2096, 2096, 2204, 2204, 1159, + 1160, 1161, 2067, 1163, 2068, 1165, 2069, 1167, 2070, 1169, + 2071, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 2093, + 2093, 2093, 2093, 2093, 1179, 1180, 1181, 1182, 1183, 1184, + 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, + 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, + 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, + 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, + 1225, 1226, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, + 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, + + 1628, 1629, 1630, 1631, 1632, 1633, 1634, 2072, 2073, 2074, + 1638, 1639, 1640, 1641, 2075, 1643, 2076, 2077, 2078, 2079, + 2080, 2081, 2082, 2083, 2084, 2085, 1654, 1655, 2204, 2086, + 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, + 1667, 1668, 1669, 1670, 1671, 1672, 1833, 1834, 1835, 1836, + 1837, 1838, 1839, 1840, 2087, 1842, 1843, 1844, 1845, 1846, + 1847, 1848, 1849, 1850, 1851, 1852, 2088, 1854, 1855, 1856, + 1857, 1858, 1859, 1860, 106, 2204, 106, 2204, 2204, 2092, + 2092, 2092, 2204, 108, 2204, 2204, 2204, 2204, 109, 2204, + 2204, 2204, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 1015, 2204, 111, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 2093, + 2204, 2093, 2204, 2204, 2204, 2204, 2204, 2204, 2092, 2204, + 2092, 2092, 2093, 2093, 2204, 2093, 2204, 2092, 2204, 2093, + 2204, 2092, 2204, 2098, 2098, 2098, 2098, 2204, 2098, 2098, + 2098, 2098, 2092, 2092, 2204, 2098, 2098, 2171, 2171, 2171, + 2204, 2093, 2204, 2204, 2204, 2204, 2204, 2194, 2194, 2194, + 2093, 2099, 2204, 2204, 2204, 2204, 2093, 2204, 2194, 2194, + 2093, 2093, 2093, 112, 113, 114, 115, 116, 117, 118, + + 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, 157, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2092, 2092, 2092, 2092, 2091, 2092, 2092, 2092, 2092, + 2092, 2092, 2092, 2092, 2092, 2091, 2092, 2092, 2092, 2091, + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2092, 2092, 2092, 2093, 2092, 2092, 2092, + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, + 2092, 2092, 2092, 2092, 2092, 2093, 2092, 2092, 2092, 2092, + 2092, 2092, 2092, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2092, 2092, 2204, 2204, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2204, 2093, 2093, + + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2092, 2092, 2092, 2092, 2092, 2204, 2204, + 2092, 2092, 2204, 2204, 2092, 2092, 2092, 2093, 2204, 2204, + 2204, 2204, 2096, 2096, 2096, 2096, 2092, 2093, 2093, 2093, + 2204, 2093, 2093, 2093, 2093, 2093, 2093, 2092, 2092, 2204, + 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2093, 2093, 2204, 2204, 2094, 2094, 2094, 2094, 2094, + 2094, 2092, 2092, 2092, 2204, 2204, 2204, 2204, 2092, 2092, + 2204, 2093, 2092, 2092, 2092, 2204, 2204, 2093, 2092, 2204, + 2098, 2170, 2170, 2170, 2170, 2170, 2093, 2093, 2093, 2093, + + 2204, 2093, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2092, + 2092, 2093, 2093, 2093, 2092, 2092, 2092, 2092, 2092, 2092, + 2092, 2204, 2092, 2092, 2092, 2204, 2092, 2092, 2092, 2093, + 2093, 2093, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2096, 2096, 2096, 2096, 2204, 2204, 2204, 2093, 2093, 2092, + 2092, 2204, 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2092, 2092, 2092, 2092, 2204, 2204, 2092, + 2092, 2092, 2204, 2092, 2092, 2092, 2092, 2093, 2093, 2093, + 2093, 2204, 2204, 2204, 2093, 2204, 2092, 2098, 2098, 2098, + + 2098, 2098, 2098, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2204, 2093, 2204, 2102, 2093, 2204, + 2092, 2093, 2204, 2204, 2092, 2204, 2204, 2093, 2204, 2204, + 2204, 2204, 2117, 2117, 2204, 2092, 2092, 2204, 2093, 2093, + 2204, 2204, 2104, 2104, 2204, 2204, 2204, 2093, 2093, 2204, + 2093, 2091, 2091, 2091, 2093, 2204, 2204, 2204, 2093, 2093, + 2093, 2093, 2204, 2117, 2117, 2204, 2204, 2117, 2117, 2204, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2093, 2204, 2093, + 2093, 2093, 2093, 2093, 2204, 2093, 2170, 2170, 2093, 2204, + + 2204, 2093, 2093, 2204, 2093, 2204, 2204, 2093, 2204, 2204, + 2204, 2092, 2170, 2170, 2170, 2170, 2092, 2093, 2204, 2092, + 2092, 2092, 2092, 2092, 2092, 2092, 2204, 2093, 2204, 2093, + 2204, 2204, 2093, 2202, 2202, 2202, 2094, 2094, 2094, 2094, + 2094, 2094, 2204, 2204, 2202, 2202, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2092, 2092, 2093, 2093, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2096, 2096, 2096, + 2204, 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2093, 2204, 2204, 2092, 2204, 2092, 2204, 2092, + 2093, 2204, 2204, 2093, 2092, 2092, 2093, 2204, 2204, 2093, + + 2093, 2204, 2093, 2204, 2204, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2204, 2204, 2204, 2092, 2204, 2204, 2204, 2204, + 2092, 2092, 2092, 2092, 2092, 2092, 2204, 2092, 2204, 2092, + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2204, 2204, 2204, + 2204, 2204, 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2204, 2204, 2092, 2092, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2092, 2092, 2092, 2092, 2092, 2092, + 2092, 2092, 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2093, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + + 1053, 1053, 1053, 1053, 2096, 2096, 2096, 2096, 2096, 2096, + 2096, 2096, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2092, 2092, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2092, 2092, 2092, 2092, 2092, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2204, 2204, 2204, + 2204, 2204, 2204, 2095, 2095, 2095, 2095, 2095, 2095, 2096, + 2096, 2096, 2096, 2095, 2095, 2095, 2095, 2096, 2096, 2096, + 2095, 2096, 2096, 2096, 2095, 2095, 2096, 2096, 2096, 2096, + 2096, 2096, 2096, 2095, 2095, 2095, 2096, 2096, 2096, 2096, + + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2096, 2096, 2096, 2204, 2096, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2096, 2096, 2096, 2096, 2204, + 2204, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2204, 2204, + 2096, 2096, 2096, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + + 2097, 2097, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2098, 2096, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2096, 2096, 2098, 2204, 2204, 2204, + 2204, 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2204, 2169, 2169, 2169, 2204, 2204, 2096, + 2096, 2096, 2096, 2096, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2097, 2097, 2097, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2096, + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2204, + 2204, 2204, 2098, 2169, 2204, 2169, 2169, 2098, 2096, 2204, + 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2204, 2204, 2204, 2204, 2204, 2204, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2204, 2096, 2096, + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2204, 2204, 2204, 2204, 2096, 2096, 2096, 2096, 2204, 2128, + 2204, 2204, 2204, 2129, 2204, 2130, 2204, 2204, 2204, 2204, + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2204, 2204, 2099, 2100, 2131, 2204, 2099, 2099, 2099, 2099, + + 2099, 2099, 2132, 2096, 2096, 2096, 2096, 2100, 2099, 2099, + 2099, 2100, 2100, 2099, 2099, 2099, 2099, 2099, 2204, 2096, + 2204, 2204, 2096, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2204, 2204, 2204, 2204, 2204, 2204, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2204, + 2204, 2204, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2204, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2096, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2119, 2119, + + 2204, 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2204, 2096, + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2096, 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2117, 2117, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2204, 2204, 2204, + 2119, 2119, 2204, 2096, 2096, 2096, 2096, 2204, 2204, 2098, + 2098, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2096, 2096, 2098, 2098, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2098, 2098, 2098, 2098, + + 2098, 2098, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2204, 2204, 2204, 2204, 2204, 2204, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2096, 2096, + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2096, 2096, 2096, 2096, 2098, 2204, 2204, 2096, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2096, 2096, + 2096, 2096, 2204, 2204, 2204, 2204, 2204, 2204, 2098, 2098, + + 2093, 2093, 2093, 2204, 2204, 2204, 2204, 2204, 2093, 2204, + 2204, 2175, 2204, 2204, 2204, 2176, 2098, 2130, 2098, 2204, + 2204, 2204, 2204, 2204, 2103, 2103, 2103, 2103, 2103, 2103, + 2103, 2103, 2103, 2103, 2204, 2204, 2131, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2177, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2204, 2204, 2204, 2204, 2204, 2204, + 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, + 2100, 2100, 2100, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2100, 2100, 2204, 2100, 2100, + 2100, 2100, 2204, 2100, 2100, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2100, 2204, 2100, 2100, 2100, + 2204, 2204, 2204, 2204, 2204, 2100, 2100, 2100, 2100, 2100, + 2100, 2204, 2100, 2204, 2100, 2204, 2100, 2204, 2204, 2204, + 2204, 2100, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2100, 2100, 2101, 2101, 2101, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2099, + + 2204, 2204, 2100, 2100, 2100, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2100, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2101, 2204, + 2204, 2204, 2204, 2204, 2116, 2116, 2116, 2116, 2116, 2116, + 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2100, 2100, + 2100, 2100, 2100, 2100, 2100, 2204, 2100, 2100, 2100, 2100, + 2100, 2100, 2100, 2204, 2100, 2100, 2100, 2100, 2100, 2100, + 2100, 2204, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2204, + 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, + + 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, + 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, + 2101, 2101, 2102, 2102, 2103, 2103, 2103, 2103, 2103, 2103, + 2103, 2103, 2103, 2204, 2103, 2103, 2103, 2103, 2103, 2103, + 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2204, + 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2104, + 2104, 2104, 2104, 2104, 2104, 2102, 2102, 2102, 2102, 2102, + 2102, 2204, 2204, 2103, 2103, 2103, 2102, 2102, 2204, 2204, + 2204, 2204, 2204, 2103, 2103, 2103, 2103, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2110, 2110, 2110, + + 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, + 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2102, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2204, 2204, 2105, + 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, + 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, + 2105, 2105, 2105, 2107, 2107, 2107, 2107, 2107, 2107, 2107, + + 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, + 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, + 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, + 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, + 2115, 2115, 2115, 2115, 2115, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + 2118, 2119, 2119, 2119, 2119, 2204, 2119, 2119, 2119, 2119, + 2119, 2119, 2119, 2119, 2119, 2119, 2204, 2117, 2117, 2117, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + 2118, 2118, 2119, 2119, 2119, 2204, 2204, 2204, 2119, 2204, + 2204, 2204, 2204, 2119, 2204, 2117, 2117, 2117, 2204, 2117, + 2117, 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2119, 2119, + 2119, 2119, 2117, 2117, 2117, 2117, 2117, 2119, 2119, 2119, + 2119, 2119, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2118, 2118, 2118, 2118, 2118, 2118, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2119, 2119, 2119, 2119, 2119, 2204, + 2204, 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2117, 2119, + + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + 2119, 2119, 2204, 2204, 2204, 2204, 2119, 2119, 2119, 2119, + 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, + 2119, 2119, 2119, 2119, 2117, 2117, 2117, 2117, 2117, 2117, + 2204, 2204, 2204, 2117, 2118, 2118, 2118, 2118, 2118, 2118, + 2118, 2118, 2118, 2118, 2119, 2119, 2119, 2119, 2119, 2119, + 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, + 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, + 2119, 2204, 2119, 2119, 2119, 2119, 2119, 2119, 2119, 2119, + 2204, 2204, 2119, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2117, 2118, 2118, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2204, 2204, + 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2117, 2117, 2119, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + 2117, 2117, 2117, 2117, 2117, 2119, 2204, 2204, 2204, 2204, + 2170, 2170, 2170, 2170, 2119, 2119, 2204, 2204, 2118, 2118, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2119, 2119, + 2119, 2119, 2119, 2204, 2204, 2119, 2119, 2204, 2204, 2204, + 2204, 2204, 2119, 2119, 109, 109, 109, 109, 109, 109, + + 109, 109, 109, 109, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2119, 2119, 2119, 2117, 2117, 2204, 2204, 2204, 2204, + 2204, 2119, 2119, 2119, 2119, 2119, 2204, 2204, 2204, 2204, + 2204, 2119, 2119, 2204, 2204, 2204, 2204, 2204, 2204, 2117, + 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2117, 2117, 2117, 2119, 2119, 2119, 2119, 2119, 2119, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2118, 2118, 2118, 2118, + + 2118, 2118, 2118, 2118, 2118, 2118, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2120, 2120, 2120, 2120, + 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, + 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, + 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, + 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, + 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, + 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, 2120, + + 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, + 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, + 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2123, 2123, 2123, + 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, + 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, + 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, + 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, + 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, + 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, 2123, + 2123, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2204, 2204, 2204, + 2126, 2204, 2204, 2204, 2204, 2204, 2126, 2204, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2204, 2204, 2126, + 2126, 2126, 2126, 2126, 2126, 2173, 2204, 2126, 2126, 2126, + + 2126, 2126, 2126, 2204, 2204, 2126, 2126, 2126, 2133, 2204, + 2134, 2204, 2135, 2136, 2137, 2138, 2139, 2204, 2204, 2140, + 2141, 2142, 2166, 2204, 2138, 2204, 2143, 2144, 2204, 2167, + 2145, 2204, 2146, 2147, 2148, 2204, 2168, 2173, 2173, 2173, + 2173, 2173, 2147, 2149, 106, 2204, 106, 2173, 2173, 2204, + 2204, 2204, 2149, 108, 2204, 2204, 2204, 2204, 109, 2204, + 2204, 2204, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 2204, 111, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 122, + + 123, 2204, 2204, 2204, 2204, 128, 2204, 2204, 2204, 132, + 133, 134, 135, 2093, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 2204, 2204, 2204, 2204, 2204, 2204, 152, + 2204, 2093, 2093, 156, 157, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2204, 2093, 2093, 2093, + 2093, 2093, 2093, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 1034, 1035, 124, 125, 126, 127, 1036, + 129, 130, 131, 1037, 1038, 1039, 1040, 136, 1041, 1042, + 1043, 1044, 1045, 1046, 1047, 1048, 1049, 146, 147, 148, + + 149, 150, 151, 1050, 153, 154, 155, 1051, 1052, 2164, + 2204, 2204, 2204, 2204, 2164, 2204, 2164, 2204, 2164, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2164, 2204, 2204, + 2164, 2204, 2164, 2204, 2164, 2204, 2164, 2204, 2164, 2204, + 2204, 2204, 2204, 2164, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2093, 2204, 2204, 2204, 2204, 2093, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2164, + 2204, 2204, 2204, 2093, 2093, 2204, 2093, 2093, 2093, 2204, + 2204, 2204, 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2093, 2093, 2204, 2204, 2094, 2094, 2094, + + 2094, 2094, 2094, 2204, 2204, 2204, 2204, 2204, 2093, 2093, + 2093, 2093, 2204, 2093, 2204, 2093, 2204, 2204, 2204, 2204, + 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2093, 2093, 2093, 2093, 2093, 2204, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2093, 2093, 2204, + 2093, 2093, 2093, 2093, 2204, 2204, 2204, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2204, 2093, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2093, 2093, + 2204, 2204, 2204, 2204, 2204, 2204, 2093, 2093, 2204, 2204, + + 2204, 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2204, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2093, 2204, 2093, + 2093, 2093, 2093, 2093, 2204, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2204, 2093, 2093, 2204, 2204, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2169, 2204, 2204, 2169, 2169, 2169, 2169, 2169, 2169, 2204, + 2169, 2169, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2204, 2204, 2093, 2093, 2093, 2093, + 2204, 2204, 2204, 2204, 2204, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2204, 2204, 2204, 2204, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2098, 2204, 2204, 2204, + 2204, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2204, + 2098, 2098, 2098, 2098, 2204, 2204, 2098, 2098, 2098, 2204, + 2204, 2098, 2204, 2098, 2098, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2204, 2204, 2204, 2204, 2204, + + 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2098, 2204, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + + 2098, 2098, 2098, 2098, 2098, 2098, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2204, 2204, 2204, 2204, + 2204, 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2204, 2204, 2204, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2204, 2204, 2204, 2098, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2098, 2098, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2098, 2098, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2098, 2098, 2098, 2098, 2098, 2098, 2100, 2100, 2100, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2100, 2204, 2204, 2204, + 2204, 2204, 2102, 2102, 2103, 2204, 2117, 2117, 2117, 2117, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2102, 2102, 2102, 2102, + 2102, 2204, 2204, 2103, 2103, 2103, 2102, 2102, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2118, 2118, 2118, 2118, 2118, 2118, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + + 2118, 2118, 2118, 2118, 2204, 2204, 2204, 2204, 2204, 2204, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2117, 2117, + 2117, 2117, 2117, 2117, 2204, 2204, 2204, 2117, 2204, 2204, + 2117, 2117, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2117, 2118, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2204, + 2204, 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2117, 2117, + 2204, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + + 2118, 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2204, 2204, + 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2204, 2204, 2118, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2117, + 2204, 2117, 2204, 2204, 2204, 2117, 2117, 2204, 2204, 2117, + 2117, 2117, 2117, 2117, 2117, 2204, 2117, 2204, 2204, 2204, + 2204, 2204, 2117, 2204, 2204, 2204, 2117, 2204, 2204, 2204, + 2204, 2117, 2204, 2204, 2204, 2117, 2117, 2204, 2204, 2204, + 2204, 2117, 2117, 2117, 2204, 2204, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2204, 2118, 2118, + + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 106, 2204, + 106, 2204, 2204, 2169, 2169, 2169, 2204, 108, 2204, 2204, + 2204, 2204, 109, 2204, 2204, 2204, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 2204, + 111, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 2093, 2204, 2093, 2204, 2204, 2204, 2204, + 2204, 2204, 2169, 2204, 2169, 2169, 2169, 2204, 2204, 2169, + 2204, 2204, 2204, 2169, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2169, 2169, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2093, 2094, 2094, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2093, 2093, 2093, 2093, 2204, 2204, 2204, + 2204, 2204, 2093, 2093, 2204, 2204, 2204, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 1034, 1035, 124, + 125, 126, 127, 1036, 129, 130, 131, 1037, 1038, 1039, + 1040, 136, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, + 1049, 146, 147, 148, 149, 150, 151, 1050, 153, 154, + 155, 1051, 1052, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2169, 2169, 2169, 2169, 2091, + + 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2091, + 2169, 2169, 2169, 2091, 2169, 2169, 2169, 2169, 2169, 2169, + 2169, 2169, 2169, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2169, 2169, 2169, + 2093, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2093, + + 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2169, 2169, 2204, + 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2204, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2169, 2169, 2169, + 2169, 2169, 2204, 2204, 2169, 2169, 2204, 2204, 2169, 2169, + 2169, 2093, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2169, 2204, 2204, 2204, 2204, 2093, 2093, 2204, 2093, 2093, + 2093, 2169, 2169, 2204, 2204, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2093, 2093, 2204, 2204, 2094, + + 2094, 2094, 2094, 2094, 2094, 2169, 2169, 2169, 2204, 2204, + 2204, 2204, 2169, 2169, 2204, 2204, 2169, 2169, 2169, 2204, + 2204, 2204, 2169, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2093, 2093, 2093, 2093, 2204, 2093, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2169, 2169, 2093, 2093, 2093, 2169, 2169, + 2169, 2169, 2169, 2169, 2169, 2204, 2169, 2169, 2169, 2204, + 2169, 2169, 2169, 2204, 2204, 2093, 2170, 2170, 2170, 2204, + 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2093, 2093, 2169, 2169, 2204, 2204, 2094, 2094, 2094, + + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2169, 2169, 2169, + 2169, 2204, 2204, 2169, 2169, 2169, 2204, 2169, 2169, 2169, + 2169, 2093, 2093, 2093, 2093, 2204, 2204, 2204, 2093, 2204, + 2169, 2093, 2093, 2204, 2093, 2204, 2204, 2204, 2093, 2204, + 2204, 2204, 2204, 2204, 2204, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2204, 2093, + 2204, 2204, 2093, 2204, 2169, 2093, 2204, 2204, 2169, 2093, + 2204, 2093, 2204, 2204, 2204, 2093, 2204, 2204, 2204, 2169, + 2169, 2093, 2093, 2093, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2093, 2093, 2173, 2093, 2173, 2173, 2173, 2093, 2204, + + 2173, 2173, 2093, 2093, 2093, 2093, 2204, 2173, 2173, 2204, + 2204, 2204, 2204, 2204, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2093, 2204, 2204, 2093, 2093, 2093, 2204, 2204, 2093, + 2204, 2204, 2093, 2204, 2204, 2093, 2093, 2204, 2093, 2204, + 2204, 2093, 2204, 2204, 2204, 2169, 2204, 2204, 2204, 2204, + 2169, 2093, 2204, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + 2204, 2204, 2204, 2204, 2204, 2204, 2093, 2204, 2204, 2204, + 2094, 2094, 2094, 2094, 2094, 2094, 2204, 2204, 2204, 2204, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2169, 2169, 2093, 2093, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2098, 2098, 2098, 2098, 2204, 2098, 2098, 2098, 2098, + 2204, 2204, 2204, 2098, 2098, 2204, 2093, 2204, 2204, 2169, + 2204, 2169, 2204, 2169, 2093, 2204, 2204, 2093, 2169, 2169, + 2093, 2204, 2204, 2093, 2093, 2204, 2093, 2204, 2204, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2204, 2204, 2204, 2169, + 2204, 2204, 2204, 2204, 2169, 2169, 2169, 2169, 2169, 2169, + 2204, 2169, 2204, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + 2169, 2204, 2204, 2204, 2204, 2204, 2204, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2204, 2204, 2169, + 2169, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2169, 2169, + + 2169, 2169, 2169, 2169, 2169, 2169, 2204, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2093, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2170, 2170, + 2170, 2170, 2170, 2170, 2170, 2170, 2204, 2204, 2204, 2204, + 2204, 2170, 2170, 2170, 2170, 2170, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2169, 2169, 2098, + 2204, 2098, 2098, 2098, 2098, 2098, 2169, 2169, 2169, 2169, + 2169, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2204, 2204, 2204, 2204, 2204, 2204, 2095, 2095, 2095, + + 2095, 2095, 2095, 2170, 2170, 2170, 2170, 2095, 2095, 2095, + 2095, 2170, 2170, 2170, 2095, 2170, 2170, 2170, 2095, 2095, + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2095, 2095, 2095, + 2170, 2170, 2170, 2170, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2204, 2170, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2170, + 2170, 2170, 2170, 2204, 2204, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + + 2095, 2095, 2204, 2204, 2170, 2170, 2170, 2098, 2204, 2204, + 2204, 2204, 2170, 2170, 2204, 2204, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2204, 2204, 2204, 2204, + 2098, 2204, 2204, 2204, 2170, 2170, 2204, 2204, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2173, + 2173, 2173, 2173, 2204, 2173, 2173, 2173, 2173, 2173, 2173, + 2173, 2173, 2173, 2173, 2204, 2204, 2204, 2204, 2204, 2170, + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2204, 2204, 2204, 2098, 2204, 2204, 2204, 2204, 2098, + 2170, 2204, 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2204, 2204, 2204, 2204, 2204, 2204, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2170, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2204, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2170, 2170, 2204, 2204, 2204, 2204, 2170, + 2170, 2170, 2170, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2170, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2170, 2170, 2204, 2204, 2204, 2204, 2204, + 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2173, 2173, 2204, 2204, 2204, 2170, 2170, 2170, 2170, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2170, 2204, 2204, 2170, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2204, 2204, 2204, 2204, 2204, + 2204, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, + + 2097, 2117, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, + 2173, 2173, 2173, 2173, 2098, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2204, 2204, 2204, 2204, 2097, 2097, 2097, 2097, 2097, 2097, + 2097, 2097, 2097, 2097, 2173, 2173, 2173, 2173, 2173, 2173, + 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2204, 2204, 2204, + 2204, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2204, + 2204, 2204, 2204, 2204, 2204, 2170, 2170, 2170, 2170, 2204, + 2204, 2098, 2098, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2170, 2170, 2098, 2098, 2097, 2097, + 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2097, 2098, 2098, + 2098, 2098, 2098, 2098, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2100, 2100, 2100, 2170, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2171, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2170, 2170, 2170, 2170, 2100, 2100, + 2100, 2100, 2100, 2100, 2100, 2204, 2100, 2100, 2100, 2100, + 2100, 2100, 2100, 2204, 2100, 2100, 2100, 2100, 2100, 2100, + 2100, 2204, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2204, + 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, + 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, + 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, + 2171, 2171, 2102, 2102, 2103, 2117, 2117, 2117, 2173, 2173, + 2173, 2173, 2173, 2173, 2173, 2204, 2204, 2173, 2173, 2173, + + 2173, 2173, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2172, + 2172, 2172, 2172, 2172, 2172, 2204, 2102, 2102, 2102, 2102, + 2102, 2204, 2204, 2103, 2103, 2103, 2102, 2102, 2118, 2118, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2173, 2173, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2173, 2204, 2204, 2204, 2173, 2173, 2204, 2204, + 2204, 2173, 2204, 2204, 2204, 2204, 2173, 2173, 2204, 2204, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + 2204, 2204, 2204, 2204, 2204, 2173, 2173, 2173, 2173, 2173, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2118, 2118, + 2118, 2118, 2118, 2118, 2173, 2173, 2173, 2173, 2173, 2204, + 2204, 2204, 2204, 2173, 2173, 2173, 2117, 2117, 2204, 2204, + 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + 2204, 2204, 2204, 2204, 2204, 2204, 2173, 2173, 2173, 2173, + 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, + 2173, 2173, 2173, 2173, 2117, 2117, 2117, 2117, 2117, 2117, + 2204, 2204, 2204, 2117, 2118, 2118, 2118, 2118, 2118, 2118, + 2118, 2118, 2118, 2118, 2204, 2204, 2204, 2204, 2117, 2204, + 2204, 2204, 2117, 2204, 2204, 2204, 2204, 2117, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2173, 2173, 2173, 2173, 2173, 2173, 2173, 2173, + 2204, 2204, 2204, 2204, 2204, 2117, 2173, 2173, 2173, 2204, + 2173, 2173, 2204, 2204, 2204, 2204, 2117, 2173, 2204, 2204, + 2118, 2118, 2118, 2118, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2117, 2118, 2118, 2118, 2118, 2118, 2118, 2118, + 2118, 2118, 2118, 2204, 2204, 2204, 2204, 2204, 2204, 2117, + 2117, 2117, 2117, 2117, 2173, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2118, 2118, 2118, 2118, 2118, + 2118, 2118, 2118, 2118, 2118, 2117, 2117, 2117, 2117, 2117, + + 2178, 2204, 2179, 2204, 2180, 2181, 2182, 2138, 2183, 2204, + 2204, 2184, 2185, 2186, 2204, 2204, 2204, 2204, 2187, 2188, + 2204, 2204, 2189, 2204, 2190, 2147, 2191, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2149, 106, 2204, 106, 2204, + 2204, 2204, 2204, 2204, 2204, 108, 2204, 2204, 2204, 2204, + 109, 2204, 2204, 2204, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 2204, 111, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 122, 123, 2204, 2204, 2204, 2204, 128, 2204, 2204, + + 2204, 132, 133, 134, 135, 2204, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 2204, 2204, 2204, 1016, 2204, + 2204, 152, 2204, 1017, 2204, 156, 157, 1018, 1019, 1020, + 1021, 2204, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, + 1030, 2204, 2204, 2204, 2204, 2204, 2204, 1031, 2204, 2204, + 2204, 1032, 1033, 2204, 2204, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 1034, 1035, 124, 125, 126, + 127, 1036, 129, 130, 131, 1037, 1038, 1039, 1040, 136, + 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 146, + 147, 148, 149, 150, 151, 1050, 153, 154, 155, 1051, + + 1052, 2197, 2204, 2204, 2204, 2204, 2197, 2204, 2197, 2204, + 2197, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2197, + 2204, 2204, 2197, 2204, 2197, 2204, 2197, 2204, 2197, 2204, + 2197, 2204, 2204, 2204, 2204, 2197, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2197, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 2204, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 2204, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 2204, 2204, 2204, 2204, 2204, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + + 203, 203, 203, 203, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 203, + 203, 2204, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 2204, 203, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 203, 203, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 203, 203, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 203, 203, 203, 2204, 2204, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 203, 1011, 2204, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 2204, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 2204, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1015, 1015, + 2204, 1015, 1015, 2204, 1015, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 2204, 2204, 2204, 2204, 2204, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 2204, + 2204, 2204, 2204, 2204, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1889, 1889, 1889, 1889, + 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, + 1889, 1889, 1889, 1889, 1889, 1889, 1889, 1889, 2204, 2204, + 2204, 2204, 1889, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 1889, 2204, 2204, 2204, 1889, 1890, 1890, 1890, + 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, + 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, + 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, + 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, + 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, + 1890, 2204, 2204, 2204, 1890, 1890, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 1890, 1890, 1890, 1890, 1890, 1890, 1890, + 1890, 1890, 1890, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 1890, 1890, + + 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, + 1890, 1890, 1890, 1890, 2204, 1890, 1890, 1890, 1890, 1890, + 1890, 2204, 2204, 2204, 1890, 1890, 1890, 2204, 1890, 1890, + 1890, 1890, 2204, 2204, 2204, 1890, 1890, 2204, 1890, 2204, + 1890, 1890, 2204, 2204, 2204, 1890, 1890, 2204, 2204, 2204, + 1890, 1890, 1890, 2204, 2204, 2204, 1890, 1890, 1890, 1890, + 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 1890, + 2204, 1890, 2204, 2204, 1890, 1890, 2204, 1890, 2204, 2204, + 1890, 2204, 2204, 2204, 2204, 2204, 2204, 1890, 1890, 1890, + 1890, 2204, 1890, 1890, 1890, 1890, 1890, 1890, 1890, 2204, + + 1890, 1890, 1890, 2204, 1890, 2204, 1890, 2204, 2204, 1890, + 1890, 2204, 1890, 1890, 1890, 1890, 2204, 1890, 1890, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 1890, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 2204, + + 2204, 2204, 2204, 1891, 1891, 1891, 1891, 2204, 2204, 2204, + 1891, 2204, 2204, 2204, 1891, 1891, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 1891, 1891, 1891, 2204, 2204, 2204, 2204, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 1891, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, 1891, + 1891, 1891, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 2204, 1892, + 1892, 1892, 1892, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, + 1892, 1892, 1892, 1892, 1892, 1892, 1892, 1892, 2204, 2204, + 1892, 1892, 1892, 1892, 1892, 1893, 2204, 2204, 2204, 2204, + 1893, 2204, 2204, 1893, 1893, 1893, 1893, 1893, 1893, 1893, + 1893, 1893, 1893, 2204, 1893, 2204, 2204, 2204, 1893, 1893, + 1893, 1893, 1893, 2204, 2204, 2204, 2204, 2204, 2204, 1893, + 2204, 1893, 2204, 1893, 2204, 1893, 1893, 1893, 1893, 2204, + 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, 1893, + + 1893, 2204, 2204, 1893, 1893, 1893, 1893, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, + 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1895, 1896, + 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, + 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, + 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, + 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, + 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, + 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, + 1896, 1896, 1896, 1897, 1897, 1897, 1897, 1897, 1897, 1897, + + 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, + 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, + 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, + 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, + 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, + 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1898, 1898, 1898, + 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, + 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, + 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, + 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, + + 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, + 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, 1898, + 1898, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, + 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, + 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, + 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, + 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, + 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, 1899, + 1899, 1899, 1899, 1899, 1899, 1900, 1900, 1900, 1900, 1900, + 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, + + 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, + 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, + 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, + 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, + 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1901, + 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, + 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, + 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, + 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, + 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, + + 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, 1901, + 1901, 1901, 1901, 1902, 1902, 1902, 1902, 1902, 1902, 1902, + 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, + 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, + 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, + 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, + 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1902, + 1902, 1902, 1902, 1902, 1902, 1902, 1902, 1903, 1903, 1903, + 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, + 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, + + 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, + 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, + 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, + 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, 1903, + 1903, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, + 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, + 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, + 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, + 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, + 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, 1904, + + 1904, 1904, 1904, 1904, 1904, 1905, 1905, 1905, 1905, 1905, + 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, + 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, + 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, + 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, + 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, + 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1905, 1906, + 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, + 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, + 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, + + 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, + 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, + 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, 1906, + 1906, 1906, 1906, 1907, 1907, 1907, 1907, 1907, 1907, 1907, + 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, + 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, + 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, + 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, + 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1907, + 1907, 1907, 1907, 1907, 1907, 1907, 1907, 1908, 1908, 1908, + + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 2204, 2204, 2204, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, 1908, + 1908, 1908, 1908, 1908, 1908, 1908, 1910, 1910, 1910, 1910, + 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, + 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, + 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, + + 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, + 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, + 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, 1910, + 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, + 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, + 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, + 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, + 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, + 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, 1911, + 1911, 1911, 1911, 1911, 1913, 1913, 1913, 1913, 1913, 1913, + + 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, + 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, + 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, + 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, + 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, + 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 1915, 1915, 1915, 1915, 1915, 2204, 2204, 2204, 2204, + 2204, 1915, 2204, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 2204, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 2204, 1915, 1915, + 1915, 1915, 1915, 2204, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, 1915, + + 1915, 1011, 2204, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1015, 1015, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 2204, 2204, 2204, 2204, 2204, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 2204, 2204, 2204, 2204, 1015, 1015, 2204, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 2204, 1015, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 1015, 1015, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 2204, 2204, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 1015, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 2204, 2204, 2204, 2204, 2204, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2092, + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2093, 2093, 2093, + + 2093, 2204, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2204, 2204, 2093, 2093, 2204, 2204, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2204, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2204, 2093, 2204, 2204, + 2204, 2093, 2093, 2093, 2093, 2204, 2204, 2093, 2093, 2093, + 2093, 2093, 2093, 2204, 2093, 2093, 2093, 2093, 2093, 2093, + 2204, 2204, 2204, 2093, 2093, 2093, 2204, 2093, 2093, 2093, + 2093, 2204, 2204, 2204, 2093, 2093, 2204, 2093, 2204, 2093, + 2093, 2204, 2204, 2204, 2093, 2093, 2204, 2204, 2204, 2093, + + 2093, 2093, 2204, 2204, 2204, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2204, 2204, 2204, + 2204, 2093, 2093, 2093, 2093, 2204, 2093, 2204, 2204, 2093, + 2093, 2204, 2093, 2204, 2204, 2093, 2204, 2204, 2204, 2204, + 2204, 2204, 2093, 2093, 2093, 2093, 2204, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2204, 2093, 2093, 2093, 2204, 2093, + 2204, 2093, 2204, 2204, 2093, 2093, 2204, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2204, 2093, 2093, 2093, 2094, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2094, 2094, + 2204, 2204, 2204, 2204, 2204, 2204, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2204, 2094, 2204, 2094, + 2204, 2094, 2204, 2204, 2204, 2204, 2094, 2094, 2092, 2092, + 2092, 2092, 2092, 2204, 2092, 2092, 2092, 2092, 2092, 2092, + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, + 2092, 2092, 2204, 2092, 2092, 2092, 2092, 2092, 2092, 2092, + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, + + 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2204, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2204, 2204, 2098, 2098, 2098, 2098, 2098, 2098, + + 2098, 2098, 2098, 2098, 2204, 2204, 2204, 2204, 2204, 2204, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2204, 2204, 2098, 2098, 2098, 2098, 2098, 2096, + 2096, 2096, 2204, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, + 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2204, 2096, + 2096, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, + 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, + 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, + 2101, 2101, 2101, 2101, 2100, 2204, 2204, 2204, 2204, 2100, + 2204, 2204, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, + 2100, 2100, 2204, 2100, 2204, 2204, 2204, 2100, 2100, 2100, + 2100, 2100, 2204, 2204, 2204, 2204, 2204, 2204, 2100, 2204, + + 2100, 2204, 2100, 2204, 2100, 2100, 2100, 2100, 2204, 2100, + 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, + 2204, 2204, 2100, 2100, 2100, 2100, 2099, 2099, 2099, 2099, + 2099, 2204, 2204, 2204, 2204, 2099, 2204, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, 2099, + 2099, 2099, 2099, 2099, 2099, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2103, 2103, + 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2103, 2103, 2103, + 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, 2103, + 2103, 2103, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, + 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, + 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, + + 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, + 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, + 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, 2105, + 2105, 2105, 2105, 2105, 2105, 2105, 2106, 2106, 2106, 2106, + 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, + 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, + 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, + 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, + 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, + 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, 2106, + + 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, + 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, + 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, + 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, + 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, + 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, 2107, + 2107, 2107, 2107, 2107, 2108, 2108, 2108, 2108, 2108, 2108, + 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, + 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, + 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, + + 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, + 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, + 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2108, 2109, 2109, + 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, + 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, + 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, + 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, + 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, + 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, 2109, + 2109, 2109, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, + + 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, + 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, + 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, + 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, + 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, 2110, + 2110, 2110, 2110, 2110, 2110, 2110, 2111, 2111, 2111, 2111, + 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, + 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, + 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, + 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, + + 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, + 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, 2111, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2113, 2113, 2113, 2113, 2113, 2113, + 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, + + 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, + 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, + 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, + 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, + 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2113, 2114, 2114, + 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, + 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, + 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, + 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, + 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, + + 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, 2114, + 2114, 2114, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, + 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, + 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, + 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, + 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, + 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, + 2115, 2115, 2115, 2115, 2115, 2115, 2116, 2116, 2116, 2116, + 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, + 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, + + 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, + 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, + 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, + 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, 2116, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2204, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2204, + 2204, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2117, + 2117, 2117, 2117, 2117, 2121, 2121, 2121, 2121, 2121, 2121, + 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, + 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, + 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, + + 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, + 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, + 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2121, 2122, 2122, + 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, + 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, + 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, + 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, + 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, + 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, 2122, + 2122, 2122, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, + + 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, + 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, + 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, + 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, + 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, 2124, + 2124, 2124, 2124, 2124, 2124, 2124, 2125, 2125, 2125, 2125, + 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, + 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, + 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, + 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, + + 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, + 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, 2125, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2126, + 2126, 2126, 2126, 2126, 2204, 2204, 2204, 2204, 2204, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2204, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2204, 2126, 2126, 2126, 2126, + 2126, 2204, 2126, 2127, 2127, 2127, 2127, 2127, 2127, 2127, + 2127, 2127, 2127, 2127, 2127, 2127, 2127, 2127, 2127, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2127, 2127, 2127, 2127, 2127, + 2127, 2127, 2127, 2127, 2127, 2127, 2127, 2127, 2127, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2204, 2204, 2204, 2204, 2091, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2091, 2204, + + 2204, 2204, 2091, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2204, 2204, 2204, + 2093, 2093, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2204, + 2204, 2204, 2204, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2204, 2093, 2093, 2093, 2093, 2093, 2093, + + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2204, 2093, 2093, 2093, 2093, 2093, 2093, 2204, 2204, 2204, + 2093, 2093, 2093, 2204, 2093, 2093, 2093, 2093, 2204, 2204, + 2204, 2093, 2093, 2204, 2093, 2204, 2093, 2093, 2204, 2204, + 2204, 2093, 2093, 2204, 2204, 2204, 2093, 2093, 2093, 2204, + 2204, 2204, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2094, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2094, 2094, 2204, 2204, 2204, 2204, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + + 2094, 2094, 2094, 2094, 2204, 2204, 2204, 2204, 2094, 2094, + 2094, 2094, 2094, 2094, 2093, 2093, 2204, 2093, 2204, 2204, + 2093, 2093, 2204, 2093, 2204, 2204, 2093, 2204, 2204, 2204, + 2204, 2204, 2204, 2093, 2093, 2093, 2093, 2204, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2204, 2093, 2093, 2093, 2204, + 2093, 2204, 2093, 2204, 2204, 2093, 2093, 2204, 2093, 2093, + 2093, 2093, 2204, 2093, 2093, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2093, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2204, + 2204, 2204, 2204, 2204, 2204, 2095, 2095, 2095, 2095, 2095, + 2095, 2204, 2204, 2204, 2204, 2095, 2095, 2095, 2095, 2204, + 2204, 2204, 2095, 2204, 2204, 2204, 2095, 2095, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2095, 2095, 2095, 2204, 2204, + 2204, 2204, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + + 2095, 2095, 2095, 2095, 2095, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2095, 2204, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2204, + 2204, 2204, 2204, 2204, 2204, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2204, 2098, 2098, 2098, 2098, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2098, + + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2204, 2204, 2204, + 2204, 2204, 2204, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2100, 2100, 2100, 2100, + + 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, + 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, + 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, + 2100, 2100, 2100, 2204, 2204, 2204, 2204, 2204, 2204, 2100, + 2100, 2100, 2100, 2204, 2204, 2204, 2100, 2100, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2100, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2204, 2204, 2204, 2204, 2204, 2204, 2102, 2102, 2102, + 2204, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2204, 2117, + 2117, 2117, 2204, 2117, 2117, 2117, 2117, 2204, 2117, 2117, + + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + + 2117, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2126, 2126, 2126, 2126, 2126, 2204, 2204, 2204, 2204, 2204, + 2126, 2204, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2204, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2204, 2126, 2126, 2126, + 2126, 2126, 2204, 2126, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + + 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + 2093, 2093, 2093, 2093, 2204, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2204, 2204, 2093, 2093, 2204, 2204, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2093, 2204, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2204, + 2093, 2204, 2204, 2204, 2093, 2093, 2093, 2093, 2204, 2204, + 2093, 2093, 2093, 2093, 2093, 2093, 2204, 2093, 2093, 2093, + 2093, 2093, 2093, 2204, 2204, 2204, 2093, 2093, 2093, 2204, + + 2093, 2093, 2093, 2093, 2204, 2204, 2204, 2093, 2093, 2204, + 2093, 2204, 2093, 2093, 2204, 2204, 2204, 2093, 2093, 2204, + 2204, 2204, 2093, 2093, 2093, 2204, 2204, 2204, 2093, 2093, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + 2204, 2204, 2204, 2204, 2093, 2093, 2093, 2093, 2204, 2093, + 2204, 2204, 2093, 2093, 2204, 2093, 2204, 2204, 2093, 2204, + 2204, 2204, 2204, 2204, 2204, 2093, 2093, 2093, 2093, 2204, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2204, 2093, 2093, + 2093, 2204, 2093, 2204, 2093, 2204, 2204, 2093, 2093, 2204, + 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, 2093, + + 2093, 2093, 2093, 2204, 2093, 2093, 2093, 2094, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2094, 2094, 2204, 2204, 2204, 2204, 2204, 2204, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2204, + 2094, 2204, 2094, 2204, 2094, 2204, 2204, 2204, 2204, 2094, + 2094, 2169, 2169, 2169, 2169, 2169, 2204, 2169, 2169, 2169, + 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + 2169, 2169, 2169, 2169, 2169, 2204, 2169, 2169, 2169, 2169, + + 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, 2169, + 2169, 2169, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, 2095, + 2095, 2095, 2095, 2095, 2095, 2095, 2098, 2098, 2098, 2098, + + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2204, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2204, 2204, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2204, 2204, 2204, 2204, 2204, 2204, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, + + 2098, 2098, 2170, 2170, 2170, 2204, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, 2170, + 2170, 2204, 2170, 2170, 2171, 2171, 2171, 2171, 2171, 2171, + 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, + 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2171, + 2171, 2171, 2171, 2171, 2171, 2171, 2171, 2100, 2100, 2100, + 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, + 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, + + 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, + 2100, 2100, 2100, 2100, 2204, 2204, 2204, 2204, 2204, 2204, + 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2100, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2204, 2204, 2102, 2102, 2204, 2204, 2102, 2102, + 2102, 2204, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, 2102, + + 2102, 2102, 2102, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2204, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2204, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2117, + + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2117, 2117, 2117, 2204, 2204, + 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, 2117, + 2117, 2117, 2117, 2117, 2117, 2117, 2204, 2204, 2117, 2117, + 2117, 2117, 2117, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2126, 2126, 2126, 2126, 2126, 2204, 2204, 2204, + 2204, 2204, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2204, 2126, 2126, 2126, 2126, 2126, + 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2126, 2204, 2126, + 2126, 2126, 2126, 2126, 2204, 2126, 2174, 2174, 2174, 2174, + 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, + 2174, 2174, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2174, 2174, + 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, 2174, + 2174, 2174, 3, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204 + } ; + +static yyconst flex_int16_t yy_chk[19760] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 15, 25, 15, 15, + 16, 16, 19, 32, 19, 25, 25, 43, 182, 19, + 32, 19, 96, 267, 182, 43, 19, 304, 267, 96, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + + 19, 19, 19, 304, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 31, 38, 51, + 47, 52, 40, 53, 47, 31, 38, 38, 40, 54, + 40, 49, 40, 31, 55, 47, 56, 49, 57, 38, + 47, 61, 49, 40, 38, 40, 62, 49, 40, 38, + 40, 51, 97, 52, 101, 53, 101, 101, 2205, 97, + 102, 54, 2130, 93, 93, 188, 55, 188, 56, 93, + 57, 2130, 61, 61, 102, 97, 93, 93, 62, 271, + 271, 19, 19, 19, 19, 19, 19, 19, 19, 19, + + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 58, 58, 301, + 301, 2200, 63, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 60, 60, 60, 60, 60, + 60, 2144, 60, 777, 777, 297, 60, 2144, 60, 58, + 58, 58, 58, 58, 63, 65, 72, 66, 60, 297, + 114, 58, 2189, 58, 59, 59, 59, 59, 59, 60, + 59, 59, 64, 64, 59, 59, 59, 59, 64, 59, + + 64, 64, 66, 64, 115, 64, 216, 65, 72, 66, + 60, 67, 114, 67, 67, 67, 67, 67, 67, 67, + 74, 315, 216, 216, 217, 2184, 64, 68, 68, 68, + 68, 68, 68, 68, 68, 116, 115, 75, 98, 75, + 75, 75, 67, 75, 75, 98, 74, 74, 74, 74, + 74, 74, 74, 74, 77, 77, 77, 77, 77, 77, + 106, 98, 106, 112, 2182, 75, 117, 116, 118, 106, + 983, 112, 112, 983, 112, 217, 1011, 217, 112, 112, + 315, 112, 112, 112, 110, 133, 133, 1001, 133, 133, + 1011, 133, 77, 77, 77, 1001, 77, 77, 117, 1008, + + 118, 2180, 77, 78, 78, 78, 1008, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 119, 79, 79, + 79, 79, 79, 79, 2179, 79, 79, 79, 79, 2176, + 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, + + 120, 80, 80, 80, 783, 80, 110, 110, 783, 119, + 2175, 125, 110, 783, 979, 979, 110, 110, 110, 110, + 2168, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 126, 127, 120, 129, 136, 2167, 110, 783, 783, 783, + 110, 110, 125, 125, 2166, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, + 81, 81, 126, 127, 2165, 129, 136, 791, 791, 791, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 2160, 82, 82, 82, 82, 82, 82, + 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + + 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 2159, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, + + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 2157, 92, 92, 92, + 92, 92, 92, 92, 109, 2152, 109, 222, 222, 269, + 269, 269, 269, 109, 2150, 222, 222, 261, 109, 797, + 797, 797, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 2149, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + + 109, 109, 109, 109, 109, 109, 109, 109, 109, 121, + 121, 2147, 261, 261, 130, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 990, 990, 2145, + 128, 128, 128, 128, 128, 128, 128, 128, 2314, 130, + 2314, 121, 121, 121, 121, 121, 130, 991, 991, 991, + 1009, 128, 1009, 121, 1009, 121, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 2140, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 128, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 124, + 124, 124, 124, 124, 124, 205, 124, 2138, 293, 205, + 124, 131, 124, 131, 131, 131, 131, 131, 131, 131, + 205, 2137, 124, 157, 157, 205, 992, 992, 2135, 157, + 293, 293, 2134, 124, 1005, 1005, 157, 157, 293, 293, + 295, 2129, 131, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 124, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 139, 139, 139, 139, 139, 139, 139, 139, + + 139, 139, 139, 2188, 139, 139, 207, 207, 207, 2188, + 207, 218, 218, 295, 218, 218, 218, 996, 996, 996, + 207, 295, 1004, 295, 207, 1004, 139, 235, 235, 235, + 235, 235, 218, 1636, 1636, 1004, 2128, 132, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 1055, 1055, 1055, 2087, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + + 135, 135, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 2042, 137, 137, 137, 137, 137, 137, 137, + 137, 1838, 1838, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 1988, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 138, 1935, 137, 228, 228, 228, 228, + 228, 228, 228, 138, 138, 138, 138, 138, 140, 1038, + 1038, 140, 1038, 1038, 140, 1038, 140, 140, 140, 140, + 140, 140, 140, 140, 138, 138, 138, 138, 138, 138, + + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 262, 262, 262, 262, 262, 1934, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 1171, 140, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 208, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, 214, 214, + 214, 214, 1010, 214, 1010, 1933, 1010, 141, 141, 141, + 141, 141, 279, 279, 279, 279, 279, 1932, 141, 141, + 141, 141, 141, 214, 214, 214, 1171, 141, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 265, 143, 143, 143, 143, 143, 143, + 1931, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, + 212, 224, 1068, 224, 224, 265, 1114, 1114, 1114, 265, + + 144, 144, 144, 2142, 212, 212, 1160, 212, 212, 212, + 224, 224, 144, 144, 221, 230, 230, 230, 230, 230, + 230, 230, 1160, 221, 212, 212, 2142, 221, 1114, 1114, + 1114, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 221, 1068, 1068, 1849, 1849, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + + 145, 145, 145, 145, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 1930, + 146, 146, 146, 146, 146, 146, 146, 146, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, + + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 1926, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 158, 1842, 158, 2136, 1842, 796, 2136, 158, 2186, 158, + 796, 796, 796, 796, 158, 1850, 1850, 1850, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 2186, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 203, 209, 209, 209, 209, + + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 232, 232, 232, + 232, 232, 1924, 232, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 1923, 250, 275, 275, + 275, 275, 275, 275, 275, 232, 232, 232, 232, 274, + 274, 274, 274, 274, 274, 274, 274, 1851, 1851, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + + 158, 158, 158, 158, 158, 1865, 1865, 211, 1922, 1098, + 1921, 211, 1920, 225, 1098, 1098, 1146, 203, 203, 1919, + 211, 211, 225, 203, 211, 211, 225, 203, 203, 203, + 203, 213, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 223, 213, 213, 215, 1918, 1916, 203, 211, 2132, + 223, 203, 203, 1917, 223, 226, 211, 215, 211, 211, + 211, 215, 229, 229, 229, 1886, 245, 225, 245, 1146, + 245, 245, 245, 226, 226, 1111, 1884, 1146, 223, 1146, + 234, 2177, 213, 245, 213, 245, 213, 227, 234, 223, + 245, 245, 213, 1927, 1927, 215, 1883, 215, 1916, 226, + + 226, 226, 226, 226, 226, 2009, 227, 227, 227, 1877, + 229, 1971, 2132, 229, 229, 229, 229, 229, 229, 245, + 1111, 1111, 229, 2131, 2009, 234, 234, 234, 234, 1868, + 234, 234, 2009, 227, 239, 239, 239, 239, 1863, 239, + 1859, 227, 227, 1971, 2177, 239, 239, 1971, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 240, 1841, 240, 240, 240, 240, + 240, 1173, 240, 240, 241, 2131, 241, 241, 241, 241, + 241, 1167, 241, 241, 242, 1161, 242, 242, 242, 242, + 242, 239, 242, 242, 243, 1143, 243, 243, 243, 243, + + 243, 1142, 243, 243, 244, 1141, 244, 244, 244, 244, + 244, 1140, 244, 244, 2071, 2071, 246, 240, 246, 1138, + 246, 246, 246, 285, 285, 285, 285, 241, 285, 285, + 285, 285, 247, 2080, 2080, 285, 285, 242, 247, 247, + 247, 247, 247, 247, 1137, 247, 247, 243, 283, 283, + 283, 283, 283, 2181, 247, 1864, 2181, 244, 1864, 246, + 263, 1081, 1136, 1081, 246, 246, 1066, 1066, 1864, 246, + 1081, 1110, 248, 246, 248, 248, 248, 248, 248, 1109, + 248, 248, 2080, 248, 1081, 1081, 1081, 1081, 248, 248, + 247, 251, 251, 251, 251, 251, 251, 251, 251, 251, + + 251, 251, 251, 263, 263, 263, 263, 263, 263, 270, + 1066, 2139, 2139, 251, 2143, 2143, 1066, 263, 263, 263, + 263, 263, 263, 263, 1108, 248, 266, 266, 266, 266, + 266, 266, 2146, 2146, 276, 266, 266, 266, 266, 266, + 280, 280, 280, 280, 280, 280, 280, 1856, 1856, 1856, + 270, 1947, 270, 270, 270, 270, 270, 276, 276, 276, + 276, 276, 276, 276, 276, 276, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 281, 281, 281, + 282, 282, 282, 282, 282, 282, 282, 300, 300, 300, + + 300, 300, 1947, 314, 1947, 1925, 300, 284, 284, 284, + 1107, 1925, 1106, 316, 316, 316, 316, 1105, 281, 281, + 284, 284, 284, 284, 284, 284, 314, 314, 314, 314, + 314, 314, 1104, 281, 281, 314, 1925, 294, 748, 748, + 748, 748, 748, 294, 294, 281, 281, 281, 281, 281, + 281, 294, 294, 1951, 2153, 2153, 284, 284, 316, 316, + 316, 294, 1951, 294, 1097, 294, 1951, 294, 1928, 1097, + 1097, 1928, 296, 296, 308, 308, 308, 296, 296, 296, + 308, 308, 308, 308, 308, 296, 1097, 308, 308, 1928, + 1951, 1928, 296, 296, 2183, 2183, 296, 1103, 296, 294, + + 294, 296, 1085, 296, 298, 298, 298, 298, 298, 298, + 298, 298, 298, 298, 298, 298, 298, 296, 296, 296, + 296, 296, 2187, 2187, 307, 296, 307, 307, 307, 307, + 307, 1014, 307, 296, 303, 303, 2025, 303, 303, 303, + 303, 1013, 303, 303, 422, 422, 422, 422, 422, 422, + 422, 422, 422, 422, 303, 1012, 303, 303, 303, 1084, + 1084, 1084, 1084, 1084, 303, 303, 303, 303, 303, 303, + 1007, 303, 1006, 303, 1003, 303, 312, 312, 2190, 2190, + 303, 303, 999, 306, 306, 306, 306, 306, 306, 2013, + 2013, 2013, 303, 303, 306, 306, 2025, 2025, 306, 306, + + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 309, 309, 309, 309, 309, 309, 309, 309, 309, 317, + 312, 312, 312, 312, 312, 311, 309, 310, 305, 302, + 312, 312, 2047, 2047, 2047, 310, 948, 948, 948, 948, + 948, 948, 309, 310, 784, 784, 784, 784, 784, 292, + 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, + 784, 1060, 1060, 1060, 2047, 2047, 2047, 310, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 319, 319, 320, 510, 510, 510, 510, 510, + 510, 510, 510, 510, 510, 510, 510, 510, 510, 510, + + 510, 510, 510, 510, 510, 750, 750, 750, 750, 750, + 750, 750, 750, 750, 750, 750, 750, 750, 291, 290, + 1060, 289, 1060, 1060, 320, 320, 320, 320, 320, 320, + 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, + 320, 320, 320, 320, 320, 320, 320, 320, 415, 415, + 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, + 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, + 415, 415, 415, 415, 415, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 700, 700, 700, + + 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, + 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, + 700, 700, 769, 769, 769, 769, 769, 769, 769, 769, + 769, 769, 769, 769, 769, 770, 770, 770, 770, 770, + 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, + 770, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 778, 778, 778, + 778, 778, 778, 778, 778, 778, 288, 779, 779, 779, + 779, 779, 779, 779, 785, 785, 2133, 2133, 2133, 781, + 781, 287, 778, 779, 779, 781, 286, 770, 770, 782, + + 782, 782, 782, 782, 782, 782, 782, 782, 786, 786, + 786, 786, 786, 786, 278, 2141, 260, 786, 1112, 1112, + 1112, 1112, 1112, 779, 779, 259, 781, 258, 781, 781, + 257, 785, 785, 785, 785, 785, 787, 787, 787, 787, + 787, 787, 256, 781, 1024, 1024, 2151, 785, 789, 789, + 789, 789, 2151, 792, 1024, 1024, 1024, 792, 792, 792, + 792, 792, 255, 1144, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 787, 2141, 2141, 793, 2151, 793, 793, + 793, 254, 253, 793, 793, 1144, 1144, 233, 787, 787, + 793, 793, 220, 1144, 1144, 789, 789, 789, 789, 790, + + 1129, 1129, 1129, 1129, 1129, 792, 792, 792, 199, 792, + 792, 789, 792, 792, 197, 195, 790, 790, 790, 790, + 790, 194, 790, 790, 790, 790, 790, 790, 790, 790, + 790, 790, 794, 190, 794, 973, 973, 973, 973, 2178, + 2178, 2178, 790, 790, 790, 790, 790, 972, 972, 972, + 972, 972, 972, 972, 972, 972, 972, 972, 972, 794, + 794, 794, 186, 181, 794, 794, 794, 794, 794, 794, + 794, 794, 794, 794, 794, 2212, 2212, 2212, 795, 1133, + 1133, 178, 794, 794, 794, 795, 795, 174, 973, 973, + 973, 973, 171, 795, 795, 1133, 1133, 1133, 1133, 170, + + 166, 795, 795, 795, 795, 795, 795, 795, 795, 795, + 1033, 1033, 2258, 2258, 2258, 165, 1033, 795, 1607, 1607, + 1607, 1607, 1607, 1033, 1033, 795, 806, 806, 806, 806, + 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, + 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, + 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, + 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, + 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, + 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, + 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, + + 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, + 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, + 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, + 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, + 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, + 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, + 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, + 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, + 901, 901, 901, 901, 902, 902, 902, 902, 902, 902, + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + 902, 984, 984, 984, 984, 984, 984, 984, 984, 984, + 984, 984, 984, 984, 984, 985, 985, 985, 985, 985, + 985, 985, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, + 162, 993, 993, 993, 993, 993, 993, 993, 993, 985, + 985, 985, 985, 985, 159, 985, 1172, 1172, 1172, 1172, + 107, 994, 994, 994, 994, 994, 985, 994, 994, 994, + 994, 994, 994, 994, 994, 994, 994, 998, 100, 1163, + 985, 1163, 1163, 1163, 1163, 1163, 985, 1163, 985, 993, + 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, + + 993, 1172, 1172, 1172, 998, 998, 998, 998, 998, 998, + 998, 998, 998, 998, 998, 1000, 1000, 1000, 1000, 1000, + 1000, 99, 94, 1000, 1000, 1000, 1000, 1000, 1000, 2073, + 2073, 1000, 1000, 1000, 1000, 1000, 1000, 1023, 48, 1000, + 1000, 1000, 1002, 46, 1002, 1052, 1052, 1067, 45, 1002, + 2073, 1052, 44, 42, 41, 1067, 1002, 39, 1052, 1052, + 37, 2073, 1002, 1023, 1023, 1023, 1023, 1023, 1023, 1023, + 1023, 35, 1002, 1015, 34, 1015, 1152, 1152, 1152, 1152, + 1152, 1067, 1015, 1067, 1067, 1152, 30, 1015, 29, 1067, + 1067, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 28, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1016, 1016, + 1016, 1016, 1016, 27, 1016, 1016, 26, 22, 1016, 1016, + 1016, 1016, 21, 1016, 1021, 1021, 1021, 1021, 1021, 1021, + 1021, 1021, 1021, 1021, 1022, 1022, 1022, 1022, 1022, 1022, + 1022, 1022, 1022, 1022, 1035, 1035, 1035, 1035, 1035, 1035, + 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1965, 1965, 1965, + 1965, 1965, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1026, 1026, + 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1039, 1039, + 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1043, + 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, + 1043, 1043, 2154, 18, 17, 2154, 1026, 1026, 1026, 1026, + 1026, 1119, 1119, 1119, 1119, 1119, 1119, 1026, 14, 12, + 1026, 1026, 7, 2154, 1119, 2154, 1026, 1027, 1027, 1027, + + 6, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, + 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, + 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1028, 1028, + 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, + 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, + 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, + 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, + 1028, 1120, 1028, 1028, 1028, 1028, 1028, 1028, 3, 1028, + 1028, 1028, 1028, 0, 1028, 1028, 1028, 1028, 1028, 1028, + 1028, 1028, 1029, 1029, 0, 1029, 1029, 1029, 1123, 1123, + + 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1029, 1029, + 1029, 0, 1120, 0, 1120, 1120, 1120, 1120, 1120, 0, + 1029, 1029, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, + 1044, 1044, 1044, 1807, 1807, 1807, 1807, 1807, 1807, 1029, + 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1030, 1030, + 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1982, + 1982, 1982, 1982, 1982, 1030, 1030, 1030, 1030, 1030, 1030, + 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, + 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, + 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, + + 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, + 1030, 1030, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, + 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, + 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, + 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, + 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 0, 1031, + 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, + 1031, 1031, 1031, 1031, 1031, 1031, 1032, 1032, 1032, 1032, + 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, + 1032, 1032, 1032, 1032, 1032, 1032, 0, 1032, 1032, 1032, + + 1032, 1032, 1032, 1032, 1037, 1037, 1037, 1037, 1037, 1037, + 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, + 1037, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, + 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, + 1080, 0, 0, 1080, 1080, 1080, 1080, 1080, 1080, 0, + 1080, 1080, 2185, 0, 0, 0, 1089, 0, 1089, 1089, + 1089, 1089, 1089, 0, 1089, 1089, 1037, 1040, 1040, 1040, + 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, + 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, + 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, + + 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1089, + 0, 2185, 2185, 1040, 1040, 1040, 1040, 1040, 1040, 1040, + 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, + 1040, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, + 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, + 1041, 0, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, + 0, 0, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, + 1041, 1041, 0, 1041, 1041, 1041, 1041, 1041, 1041, 1041, + 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, + 1041, 1041, 1042, 0, 1041, 1064, 1064, 1064, 2023, 2023, + + 0, 1064, 1042, 1042, 1042, 1042, 1042, 1045, 1045, 1045, + 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1986, 1986, 1986, + 1986, 1986, 0, 1042, 1042, 1042, 1042, 1042, 1042, 1042, + 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1064, + 0, 0, 2023, 0, 0, 1064, 0, 0, 2023, 0, + 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, + 1045, 0, 0, 0, 0, 1045, 1046, 1046, 1046, 1046, + 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, + 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1047, 1047, + + 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, + 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, + 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, + 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, + 1047, 0, 1047, 1047, 1047, 1047, 1047, 1047, 0, 1047, + 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, + 1047, 1047, 1048, 1048, 1048, 1048, 1048, 1048, 1115, 0, + 0, 1095, 0, 1115, 1115, 1115, 1095, 1095, 1048, 1048, + 1048, 0, 0, 0, 0, 1095, 0, 1095, 0, 0, + 1048, 1048, 1095, 1095, 1996, 1996, 1996, 1996, 1996, 1996, + + 1115, 0, 0, 0, 1115, 1115, 1115, 1115, 0, 1048, + 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1049, 1049, + 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 2041, + 2041, 2041, 2041, 2041, 1049, 1049, 1049, 1049, 1049, 1049, + 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, + 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, + 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, + 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, + 1049, 1049, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, + 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, + + 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, + 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, + 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 0, 1050, + 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, + 1050, 1050, 1050, 1050, 1050, 1050, 1051, 1051, 1051, 1051, + 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, + 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, + 1051, 1051, 1051, 1051, 1053, 0, 1053, 0, 1062, 1062, + 1062, 1062, 0, 1053, 0, 0, 0, 0, 1053, 1062, + 1062, 0, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + + 1053, 1053, 1053, 1053, 1053, 0, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1062, + 1096, 1062, 0, 1062, 0, 1096, 1096, 0, 1062, 1062, + 1062, 1062, 1072, 1072, 0, 1072, 1073, 1073, 0, 1072, + 1073, 1073, 0, 1135, 1135, 1135, 1135, 1073, 1135, 1135, + 1135, 1135, 1073, 1073, 0, 1135, 1135, 2067, 2067, 2067, + 1096, 1073, 0, 0, 0, 1096, 1096, 2148, 2148, 2148, + 1072, 2067, 0, 0, 1096, 0, 1072, 0, 2148, 2148, + 1073, 1073, 1072, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1054, + 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, + 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, + 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, + 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, + 1054, 1054, 1054, 1054, 1054, 1058, 1058, 1058, 1058, 1058, + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, + + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1059, + 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, + 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, + 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, + 1059, 1059, 1059, 1059, 1059, 0, 0, 1059, 1059, 1059, + 1059, 1059, 1059, 1059, 1059, 1059, 1059, 0, 1059, 1059, + + 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, + 1059, 1059, 1059, 1061, 1061, 1061, 1061, 1061, 0, 0, + 1061, 1061, 0, 0, 1061, 1061, 1061, 1061, 1124, 1124, + 1124, 1124, 1124, 1124, 1124, 1124, 1061, 2021, 2021, 2021, + 0, 1061, 1061, 2021, 1061, 1061, 1061, 1061, 1061, 0, + 0, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, + 1061, 1061, 1061, 0, 0, 1061, 1061, 1061, 1061, 1061, + 1061, 1063, 1063, 1063, 0, 0, 0, 0, 1063, 1063, + 0, 2021, 1063, 1063, 1063, 1957, 0, 2021, 1063, 0, + 1116, 2059, 2059, 2059, 2059, 2059, 1063, 1063, 1063, 1063, + + 0, 1063, 0, 0, 1957, 1957, 1957, 0, 0, 1063, + 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + 1063, 1063, 1063, 1063, 1063, 1065, 1065, 1065, 1065, 1065, + 1065, 1957, 1065, 1065, 1065, 0, 1065, 1065, 1065, 1957, + 1957, 1065, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, + 1116, 1116, 1116, 1116, 0, 0, 0, 1065, 1065, 1065, + 1065, 0, 0, 1065, 1065, 1065, 1065, 1065, 1065, 1065, + 1065, 1065, 1065, 1069, 1069, 1069, 1070, 0, 0, 1069, + 1069, 1069, 0, 1069, 1069, 1069, 1069, 1070, 1070, 1069, + 1070, 0, 0, 0, 1070, 0, 1069, 1121, 1121, 1121, + + 1121, 1121, 1121, 0, 0, 0, 0, 0, 1121, 1121, + 1121, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, + 1069, 1069, 1069, 1069, 0, 1070, 0, 1170, 1070, 1071, + 1071, 1070, 0, 1071, 1071, 0, 1070, 1070, 1640, 1640, + 1071, 0, 1640, 1640, 0, 1071, 1071, 0, 1071, 1071, + 1170, 1170, 1170, 1170, 1170, 1170, 0, 1074, 1074, 1170, + 1074, 1938, 1938, 1938, 1074, 1938, 0, 0, 1078, 1078, + 1078, 1078, 0, 1640, 1640, 1938, 1945, 1640, 1640, 1938, + 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1074, 0, 1945, + 1078, 1078, 1078, 1945, 0, 1074, 2063, 2063, 1074, 0, + + 0, 1074, 1075, 0, 1074, 0, 1074, 1074, 0, 1075, + 1075, 1075, 2063, 2063, 2063, 2063, 1078, 1078, 1075, 1078, + 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1945, 1078, 1945, + 0, 0, 1082, 2191, 2191, 2191, 1075, 1075, 1075, 1075, + 1075, 1075, 1076, 0, 2191, 2191, 1075, 1075, 1075, 1075, + 1075, 1075, 1076, 1076, 1076, 1076, 1082, 1082, 1076, 1076, + 0, 0, 0, 0, 1076, 1076, 1076, 1118, 1118, 1118, + 0, 0, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1076, 0, 0, 1082, 0, 1082, 0, 1082, + 1076, 1076, 0, 1076, 1082, 1082, 1076, 0, 0, 1076, + + 1076, 1076, 1076, 1076, 1076, 1077, 1077, 1077, 1077, 1077, + 1077, 1077, 0, 0, 0, 1077, 0, 0, 0, 0, + 1077, 1077, 1077, 1077, 1077, 1077, 0, 1077, 0, 1077, + 1077, 1077, 1077, 1077, 1077, 1077, 1077, 0, 0, 0, + 0, 0, 0, 1077, 1077, 1077, 1077, 1077, 1077, 1077, + 1077, 1077, 1077, 0, 0, 1077, 1077, 1079, 1079, 1079, + 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, + 1079, 1079, 0, 1079, 1079, 1079, 1079, 1079, 1079, 1079, + 1079, 1079, 1079, 1083, 1832, 1832, 1832, 1832, 0, 0, + 0, 1083, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, + + 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, + 1086, 1086, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, + 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1083, 1083, + 1083, 1083, 0, 1083, 1083, 0, 0, 1832, 1832, 1832, + 1832, 0, 1083, 1083, 1083, 1083, 1083, 1087, 1087, 1087, + 1087, 1087, 1087, 1087, 1087, 1087, 1087, 0, 0, 0, + 0, 0, 0, 1087, 1087, 1087, 1087, 1087, 1087, 1087, + 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, + 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, + 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, + + 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, + 1087, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, + 1088, 1088, 1088, 0, 1088, 1088, 1088, 1088, 1088, 1088, + 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1088, + 1088, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, + 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, + 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 0, 0, + 1099, 1099, 1099, 1641, 1641, 1641, 1641, 1641, 1641, 1641, + 1641, 1641, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, + 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, + + 1099, 1099, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, + 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, + 1101, 1101, 1101, 1101, 1101, 1113, 1125, 1125, 1125, 1125, + 1125, 1125, 1125, 1125, 1125, 1125, 1126, 0, 0, 0, + 0, 0, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, + 1125, 1125, 1125, 0, 2017, 2017, 2017, 0, 0, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1113, 1113, + 1113, 1113, 1113, 1113, 1977, 1977, 1977, 1977, 1977, 1977, + 1977, 1977, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1117, + 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, + + 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 0, + 0, 0, 1117, 2017, 0, 2017, 2017, 1117, 1117, 0, + 0, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, + 1117, 0, 0, 0, 0, 0, 0, 1117, 1117, 1117, + 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1122, 1122, 1122, + 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, + 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 0, 1861, + 0, 0, 0, 1861, 0, 1861, 1122, 1122, 1122, 1122, + 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, + 0, 0, 1148, 1148, 1861, 0, 1148, 1148, 1148, 1148, + + 1148, 1148, 1861, 1127, 1127, 1127, 1127, 1148, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 0, 1127, + 0, 0, 1127, 1128, 1128, 1128, 1128, 1128, 1128, 1128, + 1128, 1128, 1128, 0, 0, 0, 0, 0, 0, 1128, + 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1157, + 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 0, + 0, 0, 1128, 1985, 1985, 1985, 1985, 1985, 1985, 1985, + 0, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, + 1128, 1128, 1128, 1128, 1128, 1128, 1130, 1130, 1130, 1130, + 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1644, 1644, + + 0, 0, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, + 1130, 1130, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, + 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 0, 1130, + 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1131, 1131, + 1131, 0, 0, 0, 0, 1644, 1644, 1644, 1644, 1644, + 1132, 1132, 1132, 1132, 1132, 1132, 1132, 0, 0, 0, + 1644, 1644, 0, 1132, 1132, 1132, 1132, 0, 0, 1131, + 1131, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 0, + 0, 0, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, + 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, + + 1131, 1131, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, + 1134, 1134, 1134, 1134, 1134, 0, 0, 0, 1134, 1134, + 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1139, 1139, + 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, + 1139, 1139, 1139, 1139, 1145, 0, 0, 1139, 0, 1943, + 1145, 1145, 0, 0, 1955, 0, 0, 0, 1145, 1145, + 1943, 1943, 0, 1955, 1134, 1134, 1953, 1955, 1145, 0, + 1145, 0, 1145, 0, 1145, 1953, 0, 0, 0, 1953, + 0, 0, 1139, 0, 1139, 1139, 0, 0, 1139, 1139, + 1139, 1139, 1147, 1147, 0, 0, 0, 1147, 1147, 1147, + + 1943, 1964, 1943, 1953, 1943, 1147, 1145, 1145, 1955, 1964, + 1943, 2089, 1147, 1147, 1953, 2089, 1147, 2089, 1147, 0, + 0, 1147, 0, 1147, 1176, 1176, 1176, 1176, 1176, 1176, + 1176, 1176, 1176, 1176, 0, 0, 2089, 1147, 1147, 1147, + 1147, 1147, 0, 0, 2089, 1147, 1964, 1964, 1964, 1964, + 0, 1964, 1964, 1147, 1149, 1149, 1149, 1149, 1149, 1149, + 1149, 1149, 1149, 1149, 0, 0, 0, 0, 0, 0, + 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, + 1149, 1149, 1149, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + + 1156, 1156, 1156, 1156, 1156, 1158, 1158, 1158, 1158, 1158, + 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, + 1158, 1158, 1158, 1158, 1158, 1159, 1159, 0, 1159, 1159, + 1159, 1159, 0, 1159, 1159, 1281, 1281, 1281, 1281, 1281, + 1281, 1281, 1281, 1281, 1281, 1159, 0, 1159, 1159, 1159, + 0, 0, 0, 0, 0, 1159, 1159, 1159, 1159, 1159, + 1159, 0, 1159, 0, 1159, 0, 1159, 0, 0, 0, + 0, 1159, 1159, 0, 0, 1162, 1162, 1162, 1162, 1162, + 1162, 0, 0, 1159, 1159, 1162, 1162, 1162, 0, 0, + 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, + + 1162, 1162, 1164, 1164, 1164, 0, 0, 0, 1164, 1164, + 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1165, 1165, 1165, + 1165, 1165, 1165, 1165, 1165, 1165, 1164, 0, 1164, 0, + 0, 0, 0, 1165, 1609, 1609, 1609, 1609, 1609, 1609, + 1609, 1609, 1609, 1609, 1609, 1609, 1609, 0, 0, 1165, + 0, 2003, 2003, 2003, 2003, 2003, 2003, 1165, 1166, 1166, + 1166, 1166, 1166, 1166, 1166, 0, 1166, 1166, 1166, 1166, + 1166, 1166, 1166, 2003, 1166, 1166, 1166, 1166, 1166, 1166, + 1166, 0, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 0, + 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, + + 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, + 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, + 1166, 1166, 1168, 1168, 1168, 1177, 1177, 1177, 1177, 1177, + 1177, 1177, 1177, 0, 1177, 1177, 1177, 1177, 1177, 1177, + 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 0, + 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, + 1168, 1168, 1168, 1168, 1168, 1174, 1168, 1168, 1168, 1168, + 1168, 0, 0, 1168, 1168, 1168, 1168, 1168, 0, 0, + 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, + 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1369, 1369, 1369, + + 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, + 1369, 1369, 1369, 1369, 1369, 1369, 1369, 0, 0, 0, + 0, 0, 0, 0, 1174, 1174, 1174, 1174, 1174, 1179, + 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, + 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, + 1464, 1464, 1628, 1628, 1628, 1628, 1628, 1628, 1628, 1628, + 1628, 1628, 1628, 1628, 1628, 0, 0, 0, 0, 1179, + 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, + 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, + 1179, 1179, 1179, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + + 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, + 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, 1559, + 1559, 1559, 1559, 1559, 1559, 1629, 1629, 1629, 1629, 1629, + 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, 1629, + 1629, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, 1634, + 1634, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1635, + 1635, 1635, 1635, 1635, 1635, 1635, 1635, 1637, 1637, 1637, + 0, 0, 0, 1638, 1638, 1638, 1638, 1638, 1638, 1638, + + 0, 0, 0, 0, 0, 1997, 1997, 1629, 1629, 1638, + 1638, 0, 1637, 1637, 1637, 1637, 1637, 1637, 1637, 1637, + 1637, 1637, 1637, 1637, 1642, 0, 0, 0, 1642, 0, + 0, 0, 0, 1642, 0, 1642, 1642, 1642, 0, 1638, + 1638, 0, 0, 0, 0, 1643, 1643, 1643, 1648, 1648, + 1648, 1648, 1997, 1997, 1997, 1997, 1997, 1642, 1642, 1642, + 1642, 1642, 1642, 1642, 1642, 1642, 0, 0, 1997, 0, + 1642, 1642, 1642, 1642, 1642, 1642, 1643, 1643, 1643, 1643, + 1643, 1643, 1643, 1643, 1645, 1645, 1645, 1645, 1645, 0, + 0, 0, 0, 0, 0, 1648, 1648, 1648, 1648, 1648, + + 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, + 1648, 1648, 0, 0, 0, 0, 1645, 1645, 1645, 1645, + 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, + 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, 1645, + 0, 0, 0, 1645, 1646, 1646, 1646, 1646, 1646, 1646, + 1646, 1646, 1646, 1646, 1647, 1647, 1647, 1647, 1647, 1647, + 1647, 1647, 1647, 1647, 1647, 1647, 1647, 1650, 1650, 1650, + 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1650, + 1650, 0, 1646, 1646, 1646, 1646, 1646, 1646, 1646, 1646, + 1646, 1646, 1649, 1831, 1831, 1831, 1831, 1831, 1831, 1831, + + 1831, 1831, 1831, 1831, 1831, 0, 0, 1649, 1649, 1649, + 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 0, 0, + 0, 0, 0, 0, 1649, 1649, 1649, 1649, 1649, 1649, + 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, + 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, 1649, + 1649, 1649, 1649, 1649, 1649, 1651, 2054, 2054, 2054, 2054, + 2054, 2054, 2054, 2054, 1651, 1651, 1651, 1651, 1651, 1651, + 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1652, 1653, + 1652, 1652, 1652, 0, 0, 1652, 1652, 0, 0, 0, + 0, 0, 1652, 1652, 1857, 1857, 1857, 1857, 1857, 1857, + + 1857, 1857, 1857, 1857, 0, 0, 0, 1651, 1651, 1651, + 0, 1651, 1651, 1651, 1651, 1651, 0, 0, 1858, 1654, + 0, 1653, 1653, 1653, 1653, 1653, 1654, 1654, 0, 0, + 0, 1653, 1653, 0, 1654, 1654, 0, 0, 0, 1654, + 1654, 1654, 1655, 1655, 1655, 1858, 1858, 1858, 1858, 1858, + 1858, 1858, 1858, 1858, 1858, 1858, 1655, 0, 1654, 0, + 0, 1655, 1655, 1655, 1655, 0, 1654, 1655, 1655, 1655, + 1655, 1655, 1655, 0, 0, 0, 0, 0, 0, 0, + 1654, 1654, 1654, 1656, 1656, 1656, 1656, 1656, 1656, 0, + 0, 1656, 0, 0, 1656, 1656, 1656, 1656, 1656, 1656, + + 1656, 1656, 1656, 1656, 1656, 1656, 1665, 1665, 1665, 1665, + 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, + 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, + 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, + 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, + 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, + 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, + 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, + 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, + 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, 1666, + + 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, + 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, + 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, + 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, + 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, + 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, + 1760, 1760, 1760, 1760, 1761, 1761, 1761, 1761, 1761, 1761, + 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, + 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, + 1761, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, 1843, + + 1843, 1843, 1843, 1843, 1843, 1844, 1844, 1844, 1844, 1844, + 1844, 1844, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1844, + 1844, 1844, 1844, 1844, 0, 0, 0, 0, 0, 0, + 0, 1854, 1854, 1854, 1854, 1854, 1844, 1854, 1854, 1854, + 1854, 1854, 1854, 1854, 1854, 1854, 1854, 0, 0, 0, + 1844, 0, 0, 0, 0, 0, 1844, 0, 1844, 1852, + 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, + 1852, 1860, 1860, 1860, 1860, 1860, 1860, 0, 0, 1860, + 1860, 1860, 1860, 1860, 1860, 2085, 0, 1860, 1860, 1860, + + 1860, 1860, 1860, 0, 0, 1860, 1860, 1860, 1862, 0, + 1862, 0, 1862, 1862, 1862, 1862, 1862, 0, 0, 1862, + 1862, 1862, 2010, 0, 2010, 0, 1862, 1862, 0, 2010, + 1862, 0, 1862, 1862, 1862, 0, 2010, 2085, 2085, 2085, + 2085, 2085, 2010, 1862, 1866, 0, 1866, 2085, 2085, 0, + 0, 0, 2010, 1866, 0, 0, 0, 0, 1866, 0, + 0, 0, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, + 1866, 1866, 1866, 1866, 1866, 0, 1866, 1866, 1866, 1866, + 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, + 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1889, + + 1889, 0, 0, 0, 0, 1889, 0, 0, 0, 1889, + 1889, 1889, 1889, 1956, 1889, 1889, 1889, 1889, 1889, 1889, + 1889, 1889, 1889, 0, 0, 0, 0, 0, 0, 1889, + 0, 1956, 1956, 1889, 1889, 1939, 1939, 1939, 1939, 1939, + 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, + 1939, 1939, 1939, 1939, 1939, 1939, 0, 1956, 1956, 1956, + 1956, 1956, 1956, 1866, 1866, 1866, 1866, 1866, 1866, 1866, + 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, + 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, + 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, + + 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1929, + 0, 0, 0, 0, 1929, 0, 1929, 0, 1929, 0, + 0, 0, 0, 0, 0, 0, 0, 1929, 0, 0, + 1929, 0, 1929, 0, 1929, 0, 1929, 0, 1929, 0, + 0, 0, 0, 1929, 1940, 1940, 1940, 1940, 1940, 1940, + 1940, 1940, 1940, 1940, 1941, 0, 0, 0, 1941, 1942, + 0, 0, 0, 0, 0, 0, 0, 1941, 1941, 1929, + 0, 1941, 1941, 1942, 1942, 0, 1942, 1942, 1942, 0, + 0, 0, 0, 1942, 1942, 1942, 1942, 1942, 1942, 1942, + 1942, 1942, 1942, 1942, 1942, 1941, 0, 1942, 1942, 1942, + + 1942, 1942, 1942, 1941, 0, 1941, 1941, 1941, 1944, 1944, + 1944, 1944, 0, 1944, 0, 1946, 0, 0, 0, 0, + 0, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, + 1944, 1946, 1946, 1944, 1944, 1944, 0, 1946, 1946, 1946, + 1946, 1946, 1946, 1946, 1946, 1946, 1946, 1948, 1948, 0, + 1948, 1948, 1948, 1950, 0, 0, 0, 1948, 1948, 1948, + 1948, 1948, 1948, 1948, 1948, 1948, 1948, 0, 1948, 1948, + 1948, 1948, 1948, 1948, 1948, 1950, 1950, 1950, 1950, 1950, + 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1952, 1952, + 0, 0, 0, 0, 0, 0, 1952, 1952, 0, 0, + + 0, 0, 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1952, + 1952, 1952, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 0, + 1952, 1952, 1952, 1952, 1952, 1952, 1952, 1954, 0, 1954, + 1954, 1959, 1959, 1959, 0, 1954, 1954, 1954, 1954, 1954, + 1954, 1954, 1954, 1954, 1954, 0, 1954, 1954, 0, 0, + 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, + 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, 1967, + 2037, 0, 0, 2037, 2037, 2037, 2037, 2037, 2037, 1959, + 2037, 2037, 1959, 1959, 1959, 1959, 1959, 1959, 0, 0, + 0, 1959, 1960, 1960, 1960, 1960, 1960, 1960, 1960, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 1960, 1960, + 1960, 1960, 1960, 1960, 1960, 1960, 1960, 1960, 1962, 1962, + 1962, 1962, 1962, 1963, 1962, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1962, 1962, 1962, 1962, 1962, 1962, + 1962, 1962, 1962, 1962, 0, 0, 1962, 1962, 1962, 1962, + 0, 0, 0, 0, 0, 1963, 1963, 1963, 1963, 1963, + 1963, 1963, 1963, 1963, 1963, 1963, 1963, 1963, 1963, 1963, + 1963, 1963, 1963, 1963, 1963, 1968, 1968, 1968, 1968, 1968, + 1968, 1968, 1968, 1968, 1968, 1969, 1969, 1969, 1969, 1969, + 1969, 1969, 1969, 1969, 1969, 1969, 1969, 1969, 1969, 1969, + + 1969, 1969, 1969, 1969, 1969, 1969, 1969, 1969, 1969, 1969, + 1969, 1969, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, + 1974, 1974, 0, 0, 0, 0, 1969, 1969, 1969, 1969, + 1969, 1969, 1969, 1969, 1969, 1969, 1969, 1969, 1969, 1969, + 1969, 1969, 1969, 1969, 1969, 1969, 1972, 0, 0, 0, + 0, 1972, 1972, 1972, 1972, 1972, 1972, 1972, 1972, 1972, + 1972, 1972, 1972, 1972, 1972, 1987, 1987, 1987, 1987, 0, + 1987, 1987, 1987, 1987, 0, 0, 1973, 1987, 1987, 0, + 0, 1973, 0, 1972, 1972, 1973, 1973, 1973, 1973, 1973, + 1973, 1973, 1973, 1973, 1973, 0, 0, 0, 0, 0, + + 0, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, 1973, + 1973, 1975, 0, 1975, 1975, 1975, 1975, 1975, 0, 0, + 0, 0, 1975, 1975, 1975, 1975, 1975, 1975, 1975, 1975, + 1975, 1975, 1975, 1975, 1978, 1978, 1978, 1978, 1978, 1978, + 1978, 0, 0, 0, 0, 0, 0, 0, 0, 1978, + 1978, 1978, 1978, 1978, 1978, 1978, 1978, 1978, 1978, 1978, + 1979, 1979, 1979, 1979, 1979, 1979, 1979, 1979, 1979, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1979, 0, + 1979, 1979, 1979, 1979, 1979, 1980, 1980, 1980, 1980, 1980, + 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, + + 1980, 1980, 1980, 1980, 1980, 1980, 1981, 1981, 1981, 1981, + 1981, 1981, 1981, 1981, 1981, 1981, 0, 0, 0, 0, + 0, 0, 1981, 1981, 1981, 1981, 1981, 1981, 1981, 1981, + 1981, 1981, 1984, 1984, 1984, 1983, 1983, 1983, 1983, 1983, + 1983, 1983, 0, 0, 0, 1981, 1983, 1983, 1983, 1983, + 1983, 1983, 1983, 1983, 1983, 1983, 0, 0, 0, 0, + 0, 0, 0, 1984, 1984, 0, 0, 0, 0, 2001, + 2001, 2001, 2001, 0, 0, 0, 0, 0, 1984, 1984, + 1984, 1984, 1984, 1984, 1984, 1984, 1984, 1984, 1984, 1984, + 1984, 1984, 1984, 1984, 1984, 1984, 1989, 1989, 1989, 1990, + + 0, 0, 1989, 1989, 1989, 1989, 1989, 1990, 0, 1989, + 1989, 0, 1991, 1991, 1991, 1990, 2001, 2001, 2001, 2001, + 1989, 0, 0, 1990, 1990, 1990, 1990, 1990, 1990, 1990, + 1990, 1990, 2001, 0, 0, 0, 0, 0, 0, 1990, + 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 1991, 0, + 0, 1994, 1994, 0, 0, 0, 1991, 1991, 1991, 1991, + 1991, 0, 0, 1991, 1991, 1991, 1991, 1991, 1994, 1994, + 1994, 1994, 1994, 1994, 1994, 1994, 1994, 1994, 1994, 1994, + 1994, 1994, 1994, 1994, 1995, 1995, 1995, 1995, 1995, 1995, + 1995, 1995, 1995, 1995, 1998, 1998, 1998, 1998, 1998, 1998, + + 1998, 1998, 1998, 1998, 0, 0, 0, 0, 0, 1995, + 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, + 0, 0, 0, 0, 0, 0, 0, 0, 1998, 1998, + 1998, 1998, 1998, 1998, 0, 0, 0, 1998, 0, 0, + 1999, 1999, 0, 0, 0, 0, 0, 0, 1999, 1999, + 1999, 1999, 1999, 1999, 1999, 1999, 1999, 1999, 2002, 2002, + 2002, 2002, 2002, 2002, 2002, 2002, 2002, 2002, 2002, 0, + 0, 0, 0, 0, 0, 2002, 2002, 2002, 2002, 2002, + 0, 2002, 2002, 2002, 2002, 2002, 2002, 2002, 2002, 2002, + 2002, 2002, 2002, 2002, 2002, 2002, 2002, 2002, 2002, 2002, + + 2002, 2002, 2002, 2002, 2002, 2002, 2004, 0, 0, 0, + 2004, 2004, 2004, 2004, 2004, 0, 0, 0, 0, 2004, + 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2005, + 0, 2005, 0, 0, 0, 2005, 2005, 0, 0, 2005, + 2005, 2005, 2005, 2005, 2006, 2005, 2006, 0, 0, 0, + 0, 0, 2007, 0, 0, 0, 2007, 0, 2004, 2004, + 2004, 2007, 2004, 2004, 0, 2004, 2004, 0, 0, 0, + 0, 2006, 2006, 2006, 0, 0, 2006, 2006, 2006, 2006, + 2006, 2006, 2006, 2006, 2006, 2006, 2006, 0, 0, 0, + 0, 0, 0, 0, 2006, 2006, 2006, 0, 2007, 2007, + + 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2011, 0, + 2011, 0, 2019, 2019, 2019, 2019, 0, 2011, 0, 0, + 0, 0, 2011, 2019, 2019, 0, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 0, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2019, 0, 2019, 0, 2019, 2024, 0, + 0, 0, 2019, 2019, 2019, 2019, 2024, 0, 2030, 2030, + 0, 0, 2030, 2030, 0, 0, 0, 0, 0, 2030, + 2038, 0, 2038, 0, 2030, 2030, 0, 0, 0, 2038, + + 0, 0, 2024, 2030, 2024, 2024, 0, 0, 0, 0, + 2024, 2024, 0, 2038, 2038, 2038, 2038, 0, 0, 0, + 0, 0, 2030, 2030, 0, 0, 0, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2012, 2012, 2012, 2012, 2012, 2012, 2012, + 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, + 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, + + 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, + 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2015, + 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, + 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, + 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, + 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, + 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, + 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, + 2015, 2015, 2015, 2016, 2016, 2016, 2016, 2016, 2016, 2016, + 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, + + 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, + 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 0, + 0, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, + 2016, 0, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, + 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2018, 2018, 2018, + 2018, 2018, 0, 0, 2018, 2018, 0, 0, 2018, 2018, + 2018, 2018, 0, 0, 0, 0, 0, 0, 0, 0, + 2018, 0, 0, 0, 0, 2018, 2018, 0, 2018, 2018, + 2018, 2018, 2018, 0, 0, 2018, 2018, 2018, 2018, 2018, + 2018, 2018, 2018, 2018, 2018, 2018, 2018, 0, 0, 2018, + + 2018, 2018, 2018, 2018, 2018, 2020, 2020, 2020, 0, 0, + 0, 0, 2020, 2020, 0, 0, 2020, 2020, 2020, 0, + 0, 0, 2020, 0, 0, 0, 0, 0, 0, 0, + 2020, 2020, 2020, 2020, 0, 2020, 0, 0, 0, 0, + 0, 0, 0, 2020, 2020, 2020, 2020, 2020, 2020, 2020, + 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2022, + 2022, 2022, 2022, 2022, 2022, 0, 2022, 2022, 2022, 0, + 2022, 2022, 2022, 0, 0, 2022, 2051, 2051, 2051, 0, + 0, 2051, 2051, 2051, 2051, 2051, 2051, 2051, 2051, 2051, + 2051, 2022, 2022, 2022, 2022, 0, 0, 2022, 2022, 2022, + + 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2026, 2026, 2026, + 2027, 0, 0, 2026, 2026, 2026, 0, 2026, 2026, 2026, + 2026, 2027, 2027, 2026, 2027, 0, 0, 0, 2027, 0, + 2026, 2029, 2029, 0, 2029, 0, 0, 0, 2029, 0, + 0, 0, 0, 0, 0, 2026, 2026, 2026, 2026, 2026, + 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 0, 2027, + 0, 0, 2027, 2028, 2028, 2027, 0, 2028, 2028, 2029, + 2027, 2027, 0, 0, 2028, 2029, 0, 0, 0, 2028, + 2028, 2029, 2028, 2028, 0, 0, 0, 0, 0, 0, + 0, 2031, 2031, 2084, 2031, 2084, 2084, 2084, 2031, 0, + + 2084, 2084, 2035, 2035, 2035, 2035, 0, 2084, 2084, 0, + 0, 0, 0, 0, 2028, 2028, 2028, 2028, 2028, 2028, + 2028, 2031, 0, 0, 2035, 2035, 2035, 0, 0, 2031, + 0, 0, 2031, 0, 0, 2031, 2032, 0, 2031, 0, + 2031, 2031, 0, 2032, 2032, 2032, 0, 0, 0, 0, + 2035, 2035, 2032, 2035, 2035, 2035, 2035, 2035, 2035, 2035, + 2035, 0, 2035, 0, 0, 0, 2039, 0, 0, 0, + 2032, 2032, 2032, 2032, 2032, 2032, 2033, 0, 0, 0, + 2032, 2032, 2032, 2032, 2032, 2032, 2033, 2033, 2033, 2033, + 2039, 2039, 2033, 2033, 0, 0, 0, 0, 2033, 2033, + + 2033, 2064, 2064, 2064, 2064, 0, 2064, 2064, 2064, 2064, + 0, 0, 0, 2064, 2064, 0, 2033, 0, 0, 2039, + 0, 2039, 0, 2039, 2033, 2033, 0, 2033, 2039, 2039, + 2033, 0, 0, 2033, 2033, 2033, 2033, 2033, 2033, 2034, + 2034, 2034, 2034, 2034, 2034, 2034, 0, 0, 0, 2034, + 0, 0, 0, 0, 2034, 2034, 2034, 2034, 2034, 2034, + 0, 2034, 0, 2034, 2034, 2034, 2034, 2034, 2034, 2034, + 2034, 0, 0, 0, 0, 0, 0, 2034, 2034, 2034, + 2034, 2034, 2034, 2034, 2034, 2034, 2034, 0, 0, 2034, + 2034, 2036, 2036, 2036, 2036, 2036, 2036, 2036, 2036, 2036, + + 2036, 2036, 2036, 2036, 2036, 2036, 0, 2036, 2036, 2036, + 2036, 2036, 2036, 2036, 2036, 2036, 2036, 2040, 0, 0, + 0, 0, 0, 0, 0, 2040, 2043, 2043, 2043, 2043, + 2043, 2043, 2043, 2043, 2043, 2043, 2043, 2043, 2043, 2043, + 2043, 2043, 2043, 2043, 2043, 2043, 0, 0, 0, 0, + 0, 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056, 2056, + 0, 0, 2040, 2040, 2040, 2040, 0, 2040, 2040, 2056, + 0, 2056, 2056, 2056, 2056, 2056, 2040, 2040, 2040, 2040, + 2040, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, + 2044, 0, 0, 0, 0, 0, 0, 2044, 2044, 2044, + + 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, + 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, + 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, + 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, 2044, + 2044, 2044, 2044, 2044, 2044, 2045, 2045, 2045, 2045, 2045, + 2045, 2045, 2045, 2045, 2045, 2045, 2045, 0, 2045, 2045, + 2045, 2045, 2045, 2045, 2045, 2045, 2045, 2045, 2045, 2045, + 2045, 2045, 2045, 2045, 2045, 2046, 2046, 2046, 2046, 2046, + 2046, 2046, 2046, 2046, 2046, 2046, 2046, 2046, 2046, 2046, + 2046, 2046, 2046, 2046, 2046, 2046, 2046, 2046, 2046, 2046, + + 2046, 2046, 0, 0, 2046, 2046, 2046, 2048, 0, 0, + 0, 0, 2048, 2048, 2048, 0, 2046, 2046, 2046, 2046, + 2046, 2046, 2046, 2046, 2046, 2046, 2046, 2046, 2046, 2046, + 2046, 2046, 2046, 2046, 2046, 2046, 0, 0, 0, 2048, + 2049, 0, 0, 2048, 2048, 2048, 2048, 0, 2049, 2049, + 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2072, + 2072, 2072, 2072, 0, 2072, 2072, 2072, 2072, 2072, 2072, + 2072, 2072, 2072, 2072, 0, 0, 0, 0, 0, 2049, + 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049, + 2049, 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2050, + + 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2050, + 2050, 0, 0, 0, 2050, 0, 0, 0, 0, 2050, + 2050, 0, 0, 2050, 2050, 2050, 2050, 2050, 2050, 2050, + 2050, 2050, 2050, 0, 0, 0, 0, 0, 0, 2050, + 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2052, + 0, 2052, 2052, 2052, 2052, 2052, 0, 0, 0, 0, + 2052, 2052, 2052, 2052, 2052, 2052, 2052, 2052, 2052, 2052, + 2052, 2052, 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 0, 0, 0, 0, 0, 0, 0, + + 0, 2053, 2053, 2053, 2053, 2055, 2055, 2055, 2055, 2055, + 2055, 2055, 2055, 2055, 2055, 0, 0, 0, 0, 0, + 0, 2055, 2055, 2055, 2055, 2055, 2055, 2055, 2055, 2055, + 2055, 2055, 2057, 2057, 2057, 2057, 2057, 2057, 2057, 2057, + 2057, 2057, 0, 0, 0, 0, 0, 0, 0, 0, + 2076, 2076, 0, 0, 0, 2057, 2057, 2057, 2057, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2057, 0, 0, 2057, 2058, 2058, 2058, 2058, 2058, + 2058, 2058, 2058, 2058, 2058, 0, 0, 0, 0, 0, + 0, 2058, 2058, 2058, 2058, 2058, 2058, 2058, 2058, 2058, + + 2058, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, + 2076, 2076, 2076, 2076, 2058, 0, 0, 0, 0, 0, + 0, 0, 0, 2058, 2058, 2058, 2058, 2058, 2058, 2058, + 2058, 2058, 2058, 2058, 2058, 2058, 2058, 2058, 2060, 2060, + 2060, 2060, 2060, 2060, 2060, 2060, 2060, 2060, 2060, 2060, + 0, 0, 0, 0, 2060, 2060, 2060, 2060, 2060, 2060, + 2060, 2060, 2060, 2060, 2079, 2079, 2079, 2079, 2079, 2079, + 2079, 2079, 2079, 2079, 2079, 2079, 2079, 0, 0, 0, + 0, 2060, 2060, 2060, 2060, 2060, 2060, 2060, 2060, 2060, + 2061, 2061, 2061, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 2062, 2062, 2062, 2062, 2062, 2062, 2062, 0, + 0, 0, 0, 0, 0, 2062, 2062, 2062, 2062, 0, + 0, 2061, 2061, 2062, 2062, 2062, 2062, 2062, 2062, 2062, + 2062, 0, 0, 0, 2061, 2061, 2061, 2061, 2061, 2061, + 2061, 2061, 2061, 2061, 2061, 2061, 2061, 2061, 2061, 2061, + 2061, 2061, 2061, 2061, 2065, 2065, 2065, 2065, 2065, 2065, + 2065, 2065, 2065, 2065, 2065, 2065, 2065, 2065, 2065, 2065, + 2068, 2068, 2068, 2065, 0, 0, 2068, 2068, 2068, 2068, + 0, 2068, 2068, 2068, 2068, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2068, 0, 2068, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 2065, 0, + 2065, 2065, 0, 0, 2065, 2065, 2065, 2065, 2069, 2069, + 2069, 2069, 2069, 2069, 2069, 0, 2069, 2069, 2069, 2069, + 2069, 2069, 2069, 0, 2069, 2069, 2069, 2069, 2069, 2069, + 2069, 0, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 0, + 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, + 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, + 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, 2069, + 2069, 2069, 2070, 2070, 2070, 2082, 2082, 2082, 2082, 2082, + 2082, 2082, 2082, 2082, 2082, 0, 0, 2082, 2082, 2082, + + 2082, 2082, 0, 0, 0, 0, 0, 0, 0, 0, + 2070, 2070, 2070, 2070, 2070, 2070, 2070, 2070, 2070, 2070, + 2070, 2070, 2070, 2070, 2070, 0, 2070, 2070, 2070, 2070, + 2070, 0, 0, 2070, 2070, 2070, 2070, 2070, 2074, 2074, + 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, + 2074, 0, 2074, 2074, 2074, 2074, 2074, 2074, 2074, 2074, + 2074, 2074, 2075, 2074, 0, 0, 2075, 2083, 0, 0, + 0, 2075, 0, 0, 0, 0, 2083, 2083, 2083, 2083, + 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, 2083, + 0, 0, 0, 0, 0, 2075, 2075, 2075, 2075, 2075, + + 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, 2075, + 2075, 2075, 2075, 2075, 2077, 2077, 2077, 2077, 2077, 2083, + 2083, 2083, 0, 2083, 2083, 2083, 2083, 2083, 0, 0, + 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, + 0, 0, 0, 0, 0, 0, 2077, 2077, 2077, 2077, + 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, + 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, 2077, + 0, 0, 0, 2077, 2078, 2078, 2078, 2078, 2078, 2078, + 2078, 2078, 2078, 2078, 0, 0, 0, 0, 2086, 0, + 0, 0, 2086, 0, 0, 0, 0, 2086, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, + 2078, 2078, 0, 0, 0, 2078, 2086, 2086, 2086, 0, + 2086, 2086, 0, 0, 0, 0, 2078, 2081, 0, 0, + 2086, 2086, 2086, 2086, 0, 0, 0, 0, 0, 0, + 0, 0, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, + 2081, 2081, 2081, 0, 0, 0, 0, 0, 0, 2081, + 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, + 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, + 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, + + 2090, 0, 2090, 0, 2090, 2090, 2090, 2090, 2090, 0, + 0, 2090, 2090, 2090, 0, 0, 0, 0, 2090, 2090, + 0, 0, 2090, 0, 2090, 2090, 2090, 0, 0, 0, + 0, 0, 0, 0, 0, 2090, 2091, 0, 2091, 0, + 0, 0, 0, 0, 0, 2091, 0, 0, 0, 0, + 2091, 0, 0, 0, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 0, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2092, 2092, 0, 0, 0, 0, 2092, 0, 0, + + 0, 2092, 2092, 2092, 2092, 0, 2092, 2092, 2092, 2092, + 2092, 2092, 2092, 2092, 2092, 0, 0, 2094, 2094, 0, + 0, 2092, 0, 2094, 0, 2092, 2092, 2094, 2094, 2094, + 2094, 0, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, + 2094, 0, 0, 0, 0, 0, 0, 2094, 0, 0, + 0, 2094, 2094, 0, 0, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091, + + 2091, 2155, 0, 0, 0, 0, 2155, 0, 2155, 0, + 2155, 0, 0, 0, 0, 0, 0, 0, 0, 2155, + 0, 0, 2155, 0, 2155, 0, 2155, 0, 2155, 0, + 2155, 0, 0, 0, 0, 2155, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2155, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, + 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, + 2206, 2206, 2206, 2206, 2206, 0, 2206, 2206, 2206, 2206, + 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, + + 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, 2206, + 2206, 2206, 2206, 2206, 2206, 2206, 2206, 0, 2206, 2206, + 2206, 2206, 2206, 2206, 2206, 2206, 2207, 2207, 2207, 2207, + 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, + 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, + 2207, 2207, 2207, 0, 0, 0, 0, 0, 2207, 2207, + 2207, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, + 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, + 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, 2208, + 2208, 2208, 2208, 2209, 2209, 2209, 2209, 2209, 2209, 2209, + + 2209, 2209, 2209, 2209, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2209, + 2209, 0, 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2209, + 2209, 2209, 2209, 2209, 2209, 2209, 2209, 2210, 2210, 2210, + 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, + 2210, 2210, 2210, 2210, 2210, 2210, 2210, 0, 2210, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2210, 2210, 0, 0, 0, 0, + + 0, 0, 0, 2210, 2210, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2210, 2210, 2210, 0, 0, + 2210, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, + 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, + 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, + 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 2211, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2211, 2213, 0, 2213, 2213, 2213, 2213, 2213, 2213, 2213, + 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, + 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, + + 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, + 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, + 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, + 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, 2213, + 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, + 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, + 2214, 2214, 2214, 0, 2214, 2214, 2214, 2214, 2214, 2214, + 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, + 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, 2214, + 2214, 2214, 2214, 2214, 2214, 0, 2214, 2214, 2214, 2214, + + 2214, 2214, 2214, 2214, 2215, 2215, 2215, 2215, 2215, 2215, + 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, + 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, + 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, + 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, + 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, + 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 2216, 2216, + 0, 2216, 2216, 0, 2216, 0, 0, 0, 0, 0, + 0, 0, 0, 2216, 2216, 2216, 2216, 2216, 2216, 2216, + 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, + + 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, 2216, + 0, 0, 0, 0, 0, 2216, 2216, 2216, 2217, 2217, + 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 0, + 0, 0, 0, 0, 2217, 2217, 2217, 2217, 2217, 2217, + 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, + 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, 2217, + 2217, 2217, 2217, 2217, 2217, 2217, 2218, 2218, 2218, 2218, + 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, + 2218, 2218, 2218, 2218, 2218, 2218, 2218, 2218, 0, 0, + 0, 0, 2218, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 2218, 0, 0, 0, 2218, 2219, 2219, 2219, + 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, + 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, + 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, + 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, + 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, + 2219, 0, 0, 0, 2219, 2220, 0, 0, 0, 0, + 0, 0, 0, 2220, 2220, 2220, 2220, 2220, 2220, 2220, + 2220, 2220, 2220, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2220, 2220, + + 2220, 2220, 2220, 2220, 2220, 2220, 2220, 2220, 2220, 2220, + 2220, 2220, 2220, 2221, 0, 2221, 2221, 2221, 2221, 2221, + 2221, 0, 0, 0, 2221, 2221, 2221, 0, 2221, 2221, + 2221, 2221, 0, 0, 0, 2221, 2221, 0, 2221, 0, + 2221, 2221, 0, 0, 0, 2221, 2221, 0, 0, 0, + 2221, 2221, 2221, 0, 0, 0, 2221, 2221, 2221, 2221, + 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2221, 2222, 2222, + 0, 2222, 0, 0, 2222, 2222, 0, 2222, 0, 0, + 2222, 0, 0, 0, 0, 0, 0, 2222, 2222, 2222, + 2222, 0, 2222, 2222, 2222, 2222, 2222, 2222, 2222, 0, + + 2222, 2222, 2222, 0, 2222, 0, 2222, 0, 0, 2222, + 2222, 0, 2222, 2222, 2222, 2222, 0, 2222, 2222, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2222, 2223, + 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, + 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, + 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, + 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, 2223, + 2223, 2223, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2223, 2224, 2224, 2224, 2224, 2224, 2224, 0, + + 0, 0, 0, 2224, 2224, 2224, 2224, 0, 0, 0, + 2224, 0, 0, 0, 2224, 2224, 0, 0, 0, 0, + 0, 0, 0, 2224, 2224, 2224, 0, 0, 0, 0, + 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, 2224, + 2224, 2225, 2225, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2225, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2225, 2225, 2225, 2225, 2225, 2225, 2225, + 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, + 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, 2225, + + 2225, 2225, 2225, 2225, 2225, 2226, 2226, 2226, 2226, 2226, + 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, + 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, 2226, + 2226, 2226, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, + 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, + 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, + 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, + 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, + 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, 2227, + 2227, 2227, 2227, 2227, 2227, 2228, 2228, 2228, 2228, 2228, + + 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, 0, 2228, + 2228, 2228, 2228, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2228, 2228, 2228, + 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, 2228, + 2228, 2228, 2228, 2228, 2228, 2229, 2229, 2229, 2229, 2229, + 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, + 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2229, + 2229, 2229, 2229, 2229, 2229, 2229, 2229, 2230, 2230, 2230, + 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, + 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, + + 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2230, 2231, 2231, + 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, + 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, + 2231, 2231, 2231, 2231, 2231, 2231, 2231, 2231, 0, 0, + 2231, 2231, 2231, 2231, 2231, 2232, 0, 0, 0, 0, + 2232, 0, 0, 2232, 2232, 2232, 2232, 2232, 2232, 2232, + 2232, 2232, 2232, 0, 2232, 0, 0, 0, 2232, 2232, + 2232, 2232, 2232, 0, 0, 0, 0, 0, 0, 2232, + 0, 2232, 0, 2232, 0, 2232, 2232, 2232, 2232, 0, + 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, 2232, + + 2232, 0, 0, 2232, 2232, 2232, 2232, 2233, 2233, 2233, + 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, + 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, + 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, + 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, + 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, + 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, 2233, + 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, + 2234, 2234, 2234, 2234, 2234, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, + 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, + 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2234, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, 2235, + 2235, 2235, 2235, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2236, + 2236, 2236, 2236, 2236, 2236, 2236, 2236, 2237, 2237, 2237, + 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, + 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, + 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, + 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, + + 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, + 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, 2237, + 2237, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, 2238, + 2238, 2238, 2238, 2238, 2238, 2239, 2239, 2239, 2239, 2239, + 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, + + 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, + 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, + 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, + 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, + 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2239, 2240, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + + 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, 2240, + 2240, 2240, 2240, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2241, + 2241, 2241, 2241, 2241, 2241, 2241, 2241, 2242, 2242, 2242, + 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, + 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, + + 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, + 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, + 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, + 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, 2242, + 2242, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + + 2243, 2243, 2243, 2243, 2243, 2244, 2244, 2244, 2244, 2244, + 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, + 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, + 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, + 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, + 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, + 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2244, 2245, + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, + 2245, 2245, 2245, 2246, 2246, 2246, 2246, 2246, 2246, 2246, + 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, + 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, + 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, + 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, + 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2246, + 2246, 2246, 2246, 2246, 2246, 2246, 2246, 2247, 2247, 2247, + + 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, + 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, + 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, + 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, + 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, + 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, 2247, + 2247, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, + 2248, 2248, 2248, 2248, 0, 0, 0, 2248, 2248, 2248, + 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, 2248, + 2248, 2248, 2248, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 2248, 2248, 2249, 2249, 2249, 2249, 2249, + 2249, 2249, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2249, 2249, 2249, + 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, + 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, 2249, + 2249, 2249, 2249, 2249, 2249, 2249, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, 2250, + 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, + 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, + 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, + 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, + 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, + 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, 2251, + 2251, 2251, 2251, 2251, 2252, 2252, 2252, 2252, 2252, 2252, + + 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, + 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, + 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, + 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, + 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, + 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2252, 2253, 2253, + 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, + 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, + 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, + 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, + + 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, + 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, 2253, + 2253, 2253, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, + 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, + 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, + 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, + 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, + 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, 2254, + 2254, 2254, 2254, 2254, 2254, 2254, 2255, 2255, 2255, 2255, + 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, + + 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, 2255, + 2255, 2255, 2256, 2256, 2256, 2256, 2256, 2256, 2256, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2256, 2256, 2256, 2256, 2256, 0, 0, 0, 0, + 0, 2256, 0, 2256, 2256, 2256, 2256, 2256, 2256, 2256, + 2256, 2256, 2256, 0, 2256, 2256, 2256, 2256, 2256, 2256, + 2256, 2256, 2256, 2256, 2256, 2256, 2256, 0, 2256, 2256, + 2256, 2256, 2256, 0, 2256, 2257, 2257, 2257, 2257, 2257, + 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, + 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, 2257, + + 2257, 2259, 0, 2259, 2259, 2259, 2259, 2259, 2259, 2259, + 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, + 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, + 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, + 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, + 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, + 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, 2259, + 2260, 2260, 0, 0, 0, 0, 0, 0, 0, 0, + 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, + 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, + + 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, + 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, + 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, 2260, + 2260, 2260, 2260, 2260, 2261, 2261, 2261, 2261, 2261, 2261, + 2261, 2261, 2261, 2261, 2261, 2261, 2261, 2261, 2261, 2261, + 2261, 2261, 2261, 2261, 2261, 2261, 2261, 2261, 2261, 2261, + 2261, 0, 0, 0, 0, 0, 2261, 2261, 2261, 2262, + 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, + 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, + 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, + + 2262, 2263, 2263, 2263, 2263, 2263, 2263, 2263, 2263, 2263, + 2263, 2263, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2263, 2263, 2263, 2263, 2263, 2263, 2263, + 2263, 2263, 2263, 0, 0, 0, 0, 2263, 2263, 0, + 2263, 2263, 2263, 2263, 2263, 2263, 2263, 2263, 2263, 2263, + 2263, 2263, 2263, 2263, 2263, 2264, 2264, 2264, 2264, 2264, + 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264, + 2264, 2264, 2264, 2264, 2264, 0, 2264, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 2264, 2264, 0, 0, 0, 0, 0, 0, + 0, 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264, 2264, + 2264, 2264, 2264, 2264, 2264, 2264, 0, 0, 2264, 2265, + 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, + 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, + 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, 2265, + 2265, 2265, 2265, 2265, 2265, 2265, 2265, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2265, 2266, + 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, + 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, + + 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, + 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, + 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, + 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, 2266, + 2266, 2266, 2266, 2267, 2267, 2267, 2267, 2267, 2267, 2267, + 2267, 2267, 2267, 2267, 0, 0, 0, 0, 0, 2267, + 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, + 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, + 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, 2267, + 2267, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, + + 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, + 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, + 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, + 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, 2268, + 2268, 2269, 2269, 2269, 2269, 2269, 2269, 2269, 2269, 2269, + 2269, 2269, 2269, 2269, 2269, 2269, 2269, 2269, 2269, 2269, + 2269, 2269, 2269, 2269, 2269, 2269, 2269, 2269, 2269, 2270, + 2270, 2270, 2270, 2270, 2270, 2270, 2270, 2270, 2270, 2270, + 2270, 2270, 2270, 2270, 2270, 2270, 2270, 2270, 2270, 2270, + 2270, 2270, 2270, 2270, 2270, 2270, 2270, 2271, 2271, 2271, + + 2271, 0, 2271, 2271, 2271, 2271, 2271, 2271, 2271, 2271, + 0, 0, 2271, 2271, 0, 0, 2271, 2271, 2271, 2271, + 2271, 2271, 2271, 2271, 2271, 2271, 2271, 2271, 2271, 2271, + 2271, 2271, 2271, 2271, 2271, 2271, 2271, 2271, 0, 2271, + 2271, 2271, 2271, 2271, 2271, 2271, 0, 2271, 0, 0, + 0, 2271, 2271, 2271, 2271, 0, 0, 2271, 2271, 2271, + 2271, 2272, 2272, 0, 2272, 2272, 2272, 2272, 2272, 2272, + 0, 0, 0, 2272, 2272, 2272, 0, 2272, 2272, 2272, + 2272, 0, 0, 0, 2272, 2272, 0, 2272, 0, 2272, + 2272, 0, 0, 0, 2272, 2272, 0, 0, 0, 2272, + + 2272, 2272, 0, 0, 0, 2272, 2272, 2272, 2272, 2272, + 2272, 2272, 2272, 2272, 2272, 2272, 2272, 0, 0, 0, + 0, 2272, 2272, 2273, 2273, 0, 2273, 0, 0, 2273, + 2273, 0, 2273, 0, 0, 2273, 0, 0, 0, 0, + 0, 0, 2273, 2273, 2273, 2273, 0, 2273, 2273, 2273, + 2273, 2273, 2273, 2273, 0, 2273, 2273, 2273, 0, 2273, + 0, 2273, 0, 0, 2273, 2273, 0, 2273, 2273, 2273, + 2273, 2273, 2273, 2273, 2273, 2273, 2273, 2273, 2273, 2273, + 0, 2273, 2273, 2273, 2274, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 2274, 2274, + 0, 0, 0, 0, 0, 0, 2274, 2274, 2274, 2274, + 2274, 2274, 2274, 2274, 2274, 2274, 2274, 2274, 2274, 2274, + 2274, 2274, 2274, 2274, 2274, 2274, 0, 2274, 0, 2274, + 0, 2274, 0, 0, 0, 0, 2274, 2274, 2275, 2275, + 2275, 2275, 2275, 0, 2275, 2275, 2275, 2275, 2275, 2275, + 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, + 2275, 2275, 0, 2275, 2275, 2275, 2275, 2275, 2275, 2275, + 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, + 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, + + 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2275, 2276, + 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, + 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, + 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, + 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, + 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, + 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, 2276, + 2276, 2276, 2276, 2277, 2277, 2277, 2277, 2277, 2277, 2277, + 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, + 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, + + 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, + 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, + 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, + 2277, 2277, 2277, 2277, 2277, 2277, 2278, 2278, 2278, 2278, + 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2278, 0, + 2278, 2278, 2278, 2278, 2278, 2278, 2278, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2278, 2278, + 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2278, + 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2279, + 2279, 2279, 0, 0, 2279, 2279, 2279, 2279, 2279, 2279, + + 2279, 2279, 2279, 2279, 0, 0, 0, 0, 0, 0, + 2279, 2279, 2279, 2279, 2279, 2279, 2279, 2279, 2279, 2279, + 2279, 2279, 2279, 2279, 2279, 2279, 2279, 2279, 2279, 2279, + 2279, 2279, 2279, 2279, 2279, 2279, 2279, 2279, 2279, 2279, + 2279, 2279, 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, + 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, + 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, + 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, 2280, + 2280, 2280, 0, 0, 2280, 2280, 2280, 2280, 2280, 2281, + 2281, 2281, 0, 2281, 2281, 2281, 2281, 2281, 2281, 2281, + + 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, + 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, + 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 0, 2281, + 2281, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, + 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, + 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, 2282, + 2282, 2282, 2282, 2282, 2283, 0, 0, 0, 0, 2283, + 0, 0, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, + 2283, 2283, 0, 2283, 0, 0, 0, 2283, 2283, 2283, + 2283, 2283, 0, 0, 0, 0, 0, 0, 2283, 0, + + 2283, 0, 2283, 0, 2283, 2283, 2283, 2283, 0, 2283, + 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, 2283, + 0, 0, 2283, 2283, 2283, 2283, 2284, 2284, 2284, 2284, + 2284, 0, 0, 0, 0, 2284, 0, 2284, 2284, 2284, + 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, + 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, + 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, + 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, 2284, + 2284, 2284, 2284, 2284, 2284, 2285, 2285, 2285, 2285, 2285, + 2285, 2285, 2285, 2285, 2285, 2285, 2285, 2285, 2285, 2285, + + 2285, 2285, 2285, 2285, 2285, 2285, 2285, 2285, 2285, 2285, + 2285, 2285, 2285, 2285, 2285, 2285, 2285, 2286, 2286, 2286, + 2286, 2286, 2286, 2286, 2286, 2286, 2286, 2286, 2286, 2286, + 2286, 2286, 2286, 2286, 2286, 2286, 2286, 2286, 2286, 2286, + 2286, 2286, 2286, 2286, 2286, 2287, 2287, 2287, 2287, 2287, + 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, + 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, + 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, + 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, + 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, + + 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2288, 2288, + 2288, 2288, 2288, 2288, 2288, 2288, 2288, 2288, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2288, 2288, 2288, + 2288, 2288, 2288, 2288, 2288, 2288, 2288, 2288, 2288, 2288, + 2288, 2288, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + + 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, 2289, + 2289, 2289, 2289, 2289, 2289, 2289, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, 2290, + + 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, + 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, + 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, + 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, + 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, + 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, 2291, + 2291, 2291, 2291, 2291, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, + 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2292, 2293, 2293, + 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, + 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, + 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, + 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, + 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, + 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, 2293, + 2293, 2293, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, 2294, + 2294, 2294, 2294, 2294, 2294, 2294, 2295, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, 2295, + 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, + 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, + 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, + 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, + 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, + 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, 2296, + 2296, 2296, 2296, 2296, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, + 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2297, 2298, 2298, + 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, + 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, + 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, + 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, + 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, + + 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, + 2298, 2298, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, + 2299, 2299, 2299, 2299, 2299, 2299, 2300, 2300, 2300, 2300, + 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, + 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, + + 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, + 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, + 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, + 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, + 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, + 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, + 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, + 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, + 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, + 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, 2301, + + 2301, 2301, 2301, 2301, 2302, 2302, 2302, 2302, 2302, 2302, + 2302, 2302, 2302, 2302, 2302, 2302, 2302, 0, 0, 0, + 2302, 2302, 2302, 2302, 2302, 2302, 2302, 2302, 2302, 2302, + 2302, 2302, 2302, 2302, 2302, 2302, 2302, 2302, 2302, 2302, + 2302, 2302, 2302, 2302, 2302, 2302, 2302, 2302, 2303, 2303, + 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, + 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, + 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, + + 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2303, 2304, + 2304, 2304, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2304, 2304, 2304, 0, + 0, 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, + 2304, 2304, 2304, 2304, 2304, 2304, 2304, 0, 0, 2304, + 2304, 2304, 2304, 2304, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, + 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2305, 2306, 2306, + 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, + 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, + 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, + 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, + 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, + 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, 2306, + 2306, 2306, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, + + 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, + 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, + 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, + 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, + 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, 2307, + 2307, 2307, 2307, 2307, 2307, 2307, 2308, 2308, 2308, 2308, + 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, + 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, + 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, + 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, + + 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, + 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, 2308, + 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, + 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, + 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, + 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, + 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, + 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, 2309, + 2309, 2309, 2309, 2309, 2310, 2310, 2310, 2310, 2310, 2310, + 2310, 2310, 2310, 2310, 2310, 2310, 2310, 2310, 2310, 2310, + + 2310, 2310, 2310, 2310, 2310, 2310, 2310, 2310, 2310, 2310, + 2311, 2311, 2311, 2311, 2311, 2311, 2311, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2311, + 2311, 2311, 2311, 2311, 0, 0, 0, 0, 0, 2311, + 2311, 2311, 2311, 2311, 2311, 2311, 2311, 2311, 2311, 2311, + 2311, 0, 2311, 2311, 2311, 2311, 2311, 2311, 2311, 2311, + 2311, 2311, 2311, 2311, 2311, 0, 2311, 2311, 2311, 2311, + 2311, 0, 2311, 2312, 2312, 2312, 2312, 2312, 2312, 2312, + 2312, 2312, 2312, 2312, 2312, 2312, 2312, 2312, 2312, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 2312, 2312, 2312, 2312, 2312, + 2312, 2312, 2312, 2312, 2312, 2312, 2312, 2312, 2312, 2313, + 2313, 2313, 2313, 2313, 2313, 2313, 2313, 2313, 2313, 0, + 0, 0, 0, 0, 0, 0, 2313, 2313, 2313, 2313, + 2313, 2313, 2313, 2313, 2313, 2313, 2313, 2313, 2313, 2313, + 2313, 2313, 2313, 2313, 2313, 2313, 2313, 2313, 2313, 2313, + 2313, 2313, 2315, 2315, 2315, 2315, 2315, 2315, 2315, 2315, + 2315, 2315, 2315, 2315, 2315, 2315, 2315, 2315, 2315, 2315, + 2315, 2315, 2315, 2315, 0, 0, 0, 0, 2315, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2315, 0, + + 0, 0, 2315, 2316, 2316, 2316, 2316, 2316, 2316, 2316, + 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, + 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, + 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, + 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, 2316, + 2316, 2316, 2316, 2316, 2316, 2316, 2316, 0, 0, 0, + 2316, 2317, 0, 0, 0, 0, 0, 0, 0, 2317, + 2317, 2317, 2317, 2317, 2317, 2317, 2317, 2317, 2317, 0, + 0, 0, 0, 2317, 2317, 2317, 2317, 2317, 2317, 2317, + 2317, 2317, 2317, 0, 2317, 2317, 2317, 2317, 2317, 2317, + + 2317, 2317, 2317, 2317, 2317, 2317, 2317, 2317, 2317, 2318, + 0, 2318, 2318, 2318, 2318, 2318, 2318, 0, 0, 0, + 2318, 2318, 2318, 0, 2318, 2318, 2318, 2318, 0, 0, + 0, 2318, 2318, 0, 2318, 0, 2318, 2318, 0, 0, + 0, 2318, 2318, 0, 0, 0, 2318, 2318, 2318, 0, + 0, 0, 2318, 2318, 2318, 2318, 2318, 2318, 2318, 2318, + 2318, 2318, 2318, 2318, 2319, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2319, 2319, 0, 0, 0, 0, 2319, 2319, + 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, + + 2319, 2319, 2319, 2319, 0, 0, 0, 0, 2319, 2319, + 2319, 2319, 2319, 2319, 2320, 2320, 0, 2320, 0, 0, + 2320, 2320, 0, 2320, 0, 0, 2320, 0, 0, 0, + 0, 0, 0, 2320, 2320, 2320, 2320, 0, 2320, 2320, + 2320, 2320, 2320, 2320, 2320, 0, 2320, 2320, 2320, 0, + 2320, 0, 2320, 0, 0, 2320, 2320, 0, 2320, 2320, + 2320, 2320, 0, 2320, 2320, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2320, 2321, 2321, 2321, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, + + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2321, 2322, + 2322, 2322, 2322, 2322, 2322, 2322, 2322, 2322, 2322, 0, + 0, 0, 0, 0, 0, 2322, 2322, 2322, 2322, 2322, + 2322, 0, 0, 0, 0, 2322, 2322, 2322, 2322, 0, + 0, 0, 2322, 0, 0, 0, 2322, 2322, 0, 0, + 0, 0, 0, 0, 0, 2322, 2322, 2322, 0, 0, + 0, 0, 2322, 2322, 2322, 2322, 2322, 2322, 2322, 2322, + + 2322, 2322, 2322, 2323, 2323, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2323, 0, 2323, + 2323, 2323, 2323, 2323, 2323, 2323, 2323, 2323, 2323, 0, + 0, 0, 0, 0, 0, 2323, 2323, 2323, 2323, 2323, + 2323, 2323, 2323, 2323, 2323, 2323, 2323, 2323, 2323, 2323, + 2323, 2323, 2323, 2323, 2323, 2323, 2323, 2323, 2323, 2323, + 2323, 2323, 2323, 2323, 2323, 2323, 2323, 2324, 2324, 2324, + 2324, 2324, 2324, 2324, 2324, 2324, 2324, 2324, 2324, 2324, + 0, 2324, 2324, 2324, 2324, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2324, + + 2324, 2324, 2324, 2324, 2324, 2324, 2324, 2324, 2324, 2324, + 2324, 2324, 2324, 2324, 2324, 2324, 2324, 2325, 2325, 2325, + 2325, 2325, 2325, 2325, 2325, 2325, 2325, 0, 0, 0, + 0, 0, 0, 2325, 2325, 2325, 2325, 2325, 2325, 2325, + 2325, 2325, 2325, 2325, 2325, 2325, 2325, 2325, 2325, 2325, + 2325, 2325, 2325, 2325, 2325, 2325, 2325, 2325, 2325, 2325, + 2325, 2325, 2325, 2325, 2325, 2326, 2326, 2326, 2326, 2326, + 2326, 2326, 2326, 2326, 2326, 2326, 2326, 2326, 2326, 2326, + 2326, 2326, 2326, 2326, 2326, 2326, 2326, 2326, 2326, 2326, + 2326, 2326, 2326, 2326, 2326, 2326, 2327, 2327, 2327, 2327, + + 2327, 2327, 2327, 2327, 2327, 2327, 2327, 2327, 2327, 2327, + 2327, 2327, 2327, 2327, 2327, 2327, 2327, 2327, 2327, 2327, + 2327, 2327, 2327, 2327, 2327, 2327, 2327, 2327, 2327, 2327, + 2327, 2327, 2327, 0, 0, 0, 0, 0, 0, 2327, + 2327, 2327, 2327, 0, 0, 0, 2327, 2327, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2327, 2328, 2328, + 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, + 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, + 2328, 0, 0, 0, 0, 0, 0, 2328, 2328, 2328, + 0, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, + + 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, + 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, 2328, + 2328, 2328, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, + 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, + 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, + 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, + 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 2329, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2329, 2330, 2330, 0, 2330, + 2330, 2330, 0, 2330, 2330, 2330, 2330, 0, 2330, 2330, + + 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330, + 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330, 2330, + 2330, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2330, 2330, 2330, 2330, 2330, 2330, + 2331, 2331, 2331, 2331, 2331, 2331, 2331, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2331, 2331, 2331, 2331, 2331, 2331, 2331, 2331, + 2331, 2331, 2331, 2331, 2331, 2331, 2331, 2331, 2331, 2331, + 2331, 2331, 2331, 2331, 2331, 2331, 2331, 2331, 2331, 2331, + + 2331, 2332, 2332, 2332, 2332, 2332, 2332, 2332, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2332, 2332, 2332, 2332, 2332, 0, 0, 0, 0, 0, + 2332, 0, 2332, 2332, 2332, 2332, 2332, 2332, 2332, 2332, + 2332, 2332, 0, 2332, 2332, 2332, 2332, 2332, 2332, 2332, + 2332, 2332, 2332, 2332, 2332, 2332, 0, 2332, 2332, 2332, + 2332, 2332, 0, 2332, 2333, 2333, 2333, 2333, 2333, 2333, + 2333, 2333, 2333, 2333, 2333, 2333, 2333, 2333, 2333, 2333, + 2333, 2333, 2333, 2333, 2333, 2333, 2333, 2333, 2333, 2333, + 2333, 2333, 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334, + + 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334, + 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334, 2334, + 2335, 2335, 2335, 2335, 0, 2335, 2335, 2335, 2335, 2335, + 2335, 2335, 2335, 0, 0, 2335, 2335, 0, 0, 2335, + 2335, 2335, 2335, 2335, 2335, 2335, 2335, 2335, 2335, 2335, + 2335, 2335, 2335, 2335, 2335, 2335, 2335, 2335, 2335, 2335, + 2335, 0, 2335, 2335, 2335, 2335, 2335, 2335, 2335, 0, + 2335, 0, 0, 0, 2335, 2335, 2335, 2335, 0, 0, + 2335, 2335, 2335, 2335, 2336, 2336, 0, 2336, 2336, 2336, + 2336, 2336, 2336, 0, 0, 0, 2336, 2336, 2336, 0, + + 2336, 2336, 2336, 2336, 0, 0, 0, 2336, 2336, 0, + 2336, 0, 2336, 2336, 0, 0, 0, 2336, 2336, 0, + 0, 0, 2336, 2336, 2336, 0, 0, 0, 2336, 2336, + 2336, 2336, 2336, 2336, 2336, 2336, 2336, 2336, 2336, 2336, + 0, 0, 0, 0, 2336, 2336, 2337, 2337, 0, 2337, + 0, 0, 2337, 2337, 0, 2337, 0, 0, 2337, 0, + 0, 0, 0, 0, 0, 2337, 2337, 2337, 2337, 0, + 2337, 2337, 2337, 2337, 2337, 2337, 2337, 0, 2337, 2337, + 2337, 0, 2337, 0, 2337, 0, 0, 2337, 2337, 0, + 2337, 2337, 2337, 2337, 2337, 2337, 2337, 2337, 2337, 2337, + + 2337, 2337, 2337, 0, 2337, 2337, 2337, 2338, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2338, 2338, 0, 0, 0, 0, 0, 0, 2338, + 2338, 2338, 2338, 2338, 2338, 2338, 2338, 2338, 2338, 2338, + 2338, 2338, 2338, 2338, 2338, 2338, 2338, 2338, 2338, 0, + 2338, 0, 2338, 0, 2338, 0, 0, 0, 0, 2338, + 2338, 2339, 2339, 2339, 2339, 2339, 0, 2339, 2339, 2339, + 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, + 2339, 2339, 2339, 2339, 2339, 0, 2339, 2339, 2339, 2339, + + 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, + 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, + 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, 2339, + 2339, 2339, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, + 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, + 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, + 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, + 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, + 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, 2340, + 2340, 2340, 2340, 2340, 2340, 2340, 2341, 2341, 2341, 2341, + + 2341, 2341, 2341, 2341, 2341, 2341, 2341, 2341, 2341, 0, + 2341, 2341, 2341, 2341, 2341, 2341, 2341, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2341, 2341, + 2341, 2341, 2341, 2341, 2341, 2341, 2341, 2341, 2341, 2341, + 2341, 2341, 2341, 2341, 2341, 2341, 2341, 2341, 2341, 2342, + 2342, 2342, 0, 0, 2342, 2342, 2342, 2342, 2342, 2342, + 2342, 2342, 2342, 2342, 0, 0, 0, 0, 0, 0, + 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2342, + 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2342, + 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2342, + + 2342, 2342, 2343, 2343, 2343, 0, 2343, 2343, 2343, 2343, + 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, + 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, + 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, + 2343, 0, 2343, 2343, 2344, 2344, 2344, 2344, 2344, 2344, + 2344, 2344, 2344, 2344, 2344, 2344, 2344, 2344, 2344, 2344, + 2344, 2344, 2344, 2344, 2344, 2344, 2344, 2344, 2344, 2344, + 2344, 2344, 2344, 2344, 2344, 2344, 2344, 2345, 2345, 2345, + 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, + 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, + + 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, + 2345, 2345, 2345, 2345, 0, 0, 0, 0, 0, 0, + 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 2345, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2345, 2346, + 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, + 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, + 2346, 2346, 0, 0, 2346, 2346, 0, 0, 2346, 2346, + 2346, 0, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, + 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, + 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, 2346, + + 2346, 2346, 2346, 2347, 2347, 2347, 2347, 2347, 2347, 2347, + 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, + 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, + 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, + 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, + 2347, 2347, 2347, 2347, 0, 2347, 2347, 2347, 2347, 2347, + 2347, 2347, 2347, 2347, 2347, 0, 2347, 2348, 2348, 2348, + 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, + 2348, 2348, 2348, 2348, 2348, 2348, 2348, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2348, + + 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, + 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, + 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2349, 2349, + 2349, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2349, 2349, 2349, 0, 0, + 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, 2349, + 2349, 2349, 2349, 2349, 2349, 2349, 0, 0, 2349, 2349, + 2349, 2349, 2349, 2350, 2350, 2350, 2350, 2350, 2350, 2350, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 2350, 2350, 2350, 2350, 2350, 0, 0, 0, + 0, 0, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, + 2350, 2350, 2350, 2350, 0, 2350, 2350, 2350, 2350, 2350, + 2350, 2350, 2350, 2350, 2350, 2350, 2350, 2350, 0, 2350, + 2350, 2350, 2350, 2350, 0, 2350, 2351, 2351, 2351, 2351, + 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351, + 2351, 2351, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2351, 2351, + 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351, 2351, + 2351, 2351, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, + 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204, 2204 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int ExpressionParser_flex_debug; +int ExpressionParser_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *ExpressionParsertext; +#line 1 "ExpressionParser.l" +#line 2 "ExpressionParser.l" +/* Lexer for the FreeCAD Expression language */ +/* (c) 2010 Juergen Riegel LGPL */ +/* (c) 2013 Eivind Kvedalen LGPL */ + + +/* This disables inclusion of unistd.h, which is not available under Visual C++ + * on Win32. The C++ scanner uses STL streams instead. */ +#define YY_NO_UNISTD_H + +#ifdef _MSC_VER +#define strdup _strdup +#endif + +extern std::stack functions; /**< Function identifier */ + +/*** Flex Declarations and Options ***/ +/* change the name of the scanner class. */ +/* the manual says "somewhat more optimized" */ +/* no support for include files is planned */ +#line 5617 "lex.ExpressionParser.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int ExpressionParserlex_destroy (void ); + +int ExpressionParserget_debug (void ); + +void ExpressionParserset_debug (int debug_flag ); + +YY_EXTRA_TYPE ExpressionParserget_extra (void ); + +void ExpressionParserset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *ExpressionParserget_in (void ); + +void ExpressionParserset_in (FILE * in_str ); + +FILE *ExpressionParserget_out (void ); + +void ExpressionParserset_out (FILE * out_str ); + +int ExpressionParserget_leng (void ); + +char *ExpressionParserget_text (void ); + +int ExpressionParserget_lineno (void ); + +void ExpressionParserset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int ExpressionParserwrap (void ); +#else +extern int ExpressionParserwrap (void ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( ExpressionParsertext, ExpressionParserleng, 1, ExpressionParserout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( ExpressionParserin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( ExpressionParserin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, ExpressionParserin))==0 && ferror(ExpressionParserin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(ExpressionParserin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int ExpressionParserlex (void); + +#define YY_DECL int ExpressionParserlex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after ExpressionParsertext and ExpressionParserleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 136 "ExpressionParser.l" + + +#line 5805 "lex.ExpressionParser.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! ExpressionParserin ) + ExpressionParserin = stdin; + + if ( ! ExpressionParserout ) + ExpressionParserout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + ExpressionParserensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + ExpressionParser_create_buffer(ExpressionParserin,YY_BUF_SIZE ); + } + + ExpressionParser_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of ExpressionParsertext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 2205 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 2204 ); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 138 "ExpressionParser.l" +; + YY_BREAK +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 139 "ExpressionParser.l" +; + YY_BREAK +case 3: +/* rule 3 can match eol */ +YY_RULE_SETUP +#line 141 "ExpressionParser.l" +yylval.string = unquote(ExpressionParsertext); return STRING; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 143 "ExpressionParser.l" +return *ExpressionParsertext; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 145 "ExpressionParser.l" +return EQ; + YY_BREAK +case 6: +YY_RULE_SETUP +#line 146 "ExpressionParser.l" +return NEQ; + YY_BREAK +case 7: +YY_RULE_SETUP +#line 147 "ExpressionParser.l" +return GT; + YY_BREAK +case 8: +YY_RULE_SETUP +#line 148 "ExpressionParser.l" +return LT; + YY_BREAK +case 9: +YY_RULE_SETUP +#line 149 "ExpressionParser.l" +return GTE; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 150 "ExpressionParser.l" +return LTE; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 152 "ExpressionParser.l" +return MINUSSIGN; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 153 "ExpressionParser.l" +return MINUSSIGN; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 155 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::NanoMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // nano meter + YY_BREAK +case 14: +YY_RULE_SETUP +#line 156 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro meter + YY_BREAK +case 15: +YY_RULE_SETUP +#line 157 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro meter (greek micro in UTF8) + YY_BREAK +case 16: +YY_RULE_SETUP +#line 158 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MilliMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // milli meter (internal standard length) + YY_BREAK +case 17: +YY_RULE_SETUP +#line 159 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::CentiMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // centi meter + YY_BREAK +case 18: +YY_RULE_SETUP +#line 160 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::DeciMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // deci meter + YY_BREAK +case 19: +YY_RULE_SETUP +#line 161 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Metre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // metre + YY_BREAK +case 20: +YY_RULE_SETUP +#line 162 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::KiloMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // kilo meter + YY_BREAK +case 21: +YY_RULE_SETUP +#line 164 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Liter; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Liter dm^3 + YY_BREAK +case 22: +YY_RULE_SETUP +#line 166 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro gram + YY_BREAK +case 23: +YY_RULE_SETUP +#line 167 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro gram + YY_BREAK +case 24: +YY_RULE_SETUP +#line 168 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MilliGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // milli gram + YY_BREAK +case 25: +YY_RULE_SETUP +#line 169 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Gram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // gram + YY_BREAK +case 26: +YY_RULE_SETUP +#line 170 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::KiloGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // kilo gram (internal standard for mass) + YY_BREAK +case 27: +YY_RULE_SETUP +#line 171 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Ton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Metric Tonne + YY_BREAK +case 28: +YY_RULE_SETUP +#line 173 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Second; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // second (internal standard time) + YY_BREAK +case 29: +YY_RULE_SETUP +#line 174 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Minute; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // minute + YY_BREAK +case 30: +YY_RULE_SETUP +#line 175 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Hour; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // hour + YY_BREAK +case 31: +YY_RULE_SETUP +#line 177 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Ampere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Ampere (internal standard electric current) + YY_BREAK +case 32: +YY_RULE_SETUP +#line 178 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MilliAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // milli Ampere + YY_BREAK +case 33: +YY_RULE_SETUP +#line 179 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::KiloAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // kilo Ampere + YY_BREAK +case 34: +YY_RULE_SETUP +#line 180 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MegaAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Mega Ampere + YY_BREAK +case 35: +YY_RULE_SETUP +#line 182 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Kelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin (internal standard thermodynamic temperature) + YY_BREAK +case 36: +YY_RULE_SETUP +#line 183 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MilliKelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin + YY_BREAK +case 37: +YY_RULE_SETUP +#line 184 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin + YY_BREAK +case 38: +YY_RULE_SETUP +#line 185 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin + YY_BREAK +case 39: +YY_RULE_SETUP +#line 187 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Mole; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Mole (internal standard amount of substance) + YY_BREAK +case 40: +YY_RULE_SETUP +#line 189 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Candela; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Candela (internal standard luminous intensity) + YY_BREAK +case 41: +YY_RULE_SETUP +#line 191 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // inch + YY_BREAK +case 42: +YY_RULE_SETUP +#line 192 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // inch + YY_BREAK +case 43: +YY_RULE_SETUP +#line 193 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // foot + YY_BREAK +case 44: +YY_RULE_SETUP +#line 194 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // foot + YY_BREAK +case 45: +YY_RULE_SETUP +#line 195 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // thou (in/1000) + YY_BREAK +case 46: +YY_RULE_SETUP +#line 196 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // mil (the thou in US) + YY_BREAK +case 47: +YY_RULE_SETUP +#line 197 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Yard; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // yard + YY_BREAK +case 48: +YY_RULE_SETUP +#line 198 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Mile; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // mile + YY_BREAK +case 49: +YY_RULE_SETUP +#line 202 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pound + YY_BREAK +case 50: +YY_RULE_SETUP +#line 203 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pound + YY_BREAK +case 51: +YY_RULE_SETUP +#line 204 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Ounce; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // ounce + YY_BREAK +case 52: +YY_RULE_SETUP +#line 205 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Stone; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Stone + YY_BREAK +case 53: +YY_RULE_SETUP +#line 206 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Hundredweights; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // hundredweights + YY_BREAK +case 54: +YY_RULE_SETUP +#line 208 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::PoundForce; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pound + YY_BREAK +case 55: +YY_RULE_SETUP +#line 210 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Newton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton (kg*m/s^2)a-za-za-z + YY_BREAK +case 56: +YY_RULE_SETUP +#line 211 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::KiloNewton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton + YY_BREAK +case 57: +YY_RULE_SETUP +#line 212 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MegaNewton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton + YY_BREAK +case 58: +YY_RULE_SETUP +#line 213 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MilliNewton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton + YY_BREAK +case 59: +YY_RULE_SETUP +#line 215 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Pascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal (kg/m*s^2 or N/m^2) + YY_BREAK +case 60: +YY_RULE_SETUP +#line 216 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::KiloPascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal + YY_BREAK +case 61: +YY_RULE_SETUP +#line 217 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::MegaPascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal + YY_BREAK +case 62: +YY_RULE_SETUP +#line 218 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::GigaPascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal + YY_BREAK +case 63: +YY_RULE_SETUP +#line 220 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Torr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // portion of Pascal ( 101325/760 ) + YY_BREAK +case 64: +YY_RULE_SETUP +#line 221 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::mTorr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // + YY_BREAK +case 65: +YY_RULE_SETUP +#line 222 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // + YY_BREAK +case 66: +YY_RULE_SETUP +#line 223 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // + YY_BREAK +case 67: +YY_RULE_SETUP +#line 225 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::PSI; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pounds/in^2 + YY_BREAK +case 68: +YY_RULE_SETUP +#line 226 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::KSI; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // 1000 x pounds/in^2 + YY_BREAK +case 69: +YY_RULE_SETUP +#line 228 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Watt; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Watt (kg*m^2/s^3) + YY_BREAK +case 70: +YY_RULE_SETUP +#line 229 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::VoltAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // VoltAmpere (kg*m^2/s^3) + YY_BREAK +case 71: +YY_RULE_SETUP +#line 231 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Joule; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Joule (kg*m^2/s^2) + YY_BREAK +case 72: +YY_RULE_SETUP +#line 232 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::NewtonMeter; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // N*m = Joule + YY_BREAK +case 73: +YY_RULE_SETUP +#line 233 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::VoltAmpereSecond; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // V*A*s = Joule + YY_BREAK +case 74: +YY_RULE_SETUP +#line 234 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // + YY_BREAK +case 75: +YY_RULE_SETUP +#line 235 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // W*s = Joule + YY_BREAK +case 76: +YY_RULE_SETUP +#line 237 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // degree (internal standard angle) + YY_BREAK +case 77: +YY_RULE_SETUP +#line 238 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // degree (internal standard angle) + YY_BREAK +case 78: +YY_RULE_SETUP +#line 239 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Radian; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // radian + YY_BREAK +case 79: +YY_RULE_SETUP +#line 240 "ExpressionParser.l" +yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // gon + YY_BREAK +case 80: +YY_RULE_SETUP +#line 242 "ExpressionParser.l" +yylval.fvalue = num_change(ExpressionParsertext,'.',','); return NUM; + YY_BREAK +case 81: +YY_RULE_SETUP +#line 243 "ExpressionParser.l" +yylval.fvalue = num_change(ExpressionParsertext,',','.'); return NUM; + YY_BREAK +case 82: +YY_RULE_SETUP +#line 244 "ExpressionParser.l" +yylval.ivalue = strtoll( ExpressionParsertext, NULL, 0 ); return INTEGER; + YY_BREAK +case 83: +YY_RULE_SETUP +#line 246 "ExpressionParser.l" +yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi + YY_BREAK +case 84: +YY_RULE_SETUP +#line 247 "ExpressionParser.l" +yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e + YY_BREAK +case 85: +YY_RULE_SETUP +#line 249 "ExpressionParser.l" +yylval.string = ExpressionParsertext; return CELLADDRESS; + YY_BREAK +case 86: +YY_RULE_SETUP +#line 250 "ExpressionParser.l" +yylval.string = ExpressionParsertext; return CELLADDRESS; + YY_BREAK +case 87: +YY_RULE_SETUP +#line 251 "ExpressionParser.l" +yylval.string = ExpressionParsertext; return CELLADDRESS; + YY_BREAK +case 88: +YY_RULE_SETUP +#line 253 "ExpressionParser.l" +{ + std::string s = ExpressionParsertext; + size_t i = s.size() - 2; + while (isspace(s[i])) + --i; + s.erase(i + 1); + std::map::const_iterator j = registered_functions.find(s); + if (j != registered_functions.end()) + yylval.func = j->second; + else + yylval.func = FunctionExpression::NONE; + return FUNC; + } + YY_BREAK +case 89: +YY_RULE_SETUP +#line 267 "ExpressionParser.l" +yylval.string = ExpressionParsertext; return IDENTIFIER; + YY_BREAK +case 90: +YY_RULE_SETUP +#line 268 "ExpressionParser.l" +ECHO; + YY_BREAK +#line 6348 "lex.ExpressionParser.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed ExpressionParserin at a new source and called + * ExpressionParserlex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = ExpressionParserin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( ExpressionParserwrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * ExpressionParsertext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of ExpressionParserlex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + ExpressionParserrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + ExpressionParserrestart(ExpressionParserin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) ExpressionParserrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 2205 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 2205 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 2204); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + ExpressionParserrestart(ExpressionParserin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( ExpressionParserwrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve ExpressionParsertext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void ExpressionParserrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + ExpressionParserensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + ExpressionParser_create_buffer(ExpressionParserin,YY_BUF_SIZE ); + } + + ExpressionParser_init_buffer(YY_CURRENT_BUFFER,input_file ); + ExpressionParser_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void ExpressionParser_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * ExpressionParserpop_buffer_state(); + * ExpressionParserpush_buffer_state(new_buffer); + */ + ExpressionParserensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + ExpressionParser_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (ExpressionParserwrap()) processing, but the only time this flag + * is looked at is after ExpressionParserwrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void ExpressionParser_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + ExpressionParserin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE ExpressionParser_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) ExpressionParseralloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in ExpressionParser_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) ExpressionParseralloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in ExpressionParser_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + ExpressionParser_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with ExpressionParser_create_buffer() + * + */ + void ExpressionParser_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + ExpressionParserfree((void *) b->yy_ch_buf ); + + ExpressionParserfree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a ExpressionParserrestart() or at EOF. + */ + static void ExpressionParser_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + ExpressionParser_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then ExpressionParser_init_buffer was _probably_ + * called from ExpressionParserrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void ExpressionParser_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + ExpressionParser_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void ExpressionParserpush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + ExpressionParserensure_buffer_stack(); + + /* This block is copied from ExpressionParser_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from ExpressionParser_switch_to_buffer. */ + ExpressionParser_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void ExpressionParserpop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + ExpressionParser_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + ExpressionParser_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void ExpressionParserensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)ExpressionParseralloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in ExpressionParserensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)ExpressionParserrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in ExpressionParserensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE ExpressionParser_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) ExpressionParseralloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in ExpressionParser_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + ExpressionParser_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to ExpressionParserlex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * ExpressionParser_scan_bytes() instead. + */ +YY_BUFFER_STATE ExpressionParser_scan_string (yyconst char * yystr ) +{ + + return ExpressionParser_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to ExpressionParserlex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE ExpressionParser_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) ExpressionParseralloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in ExpressionParser_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = ExpressionParser_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in ExpressionParser_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up ExpressionParsertext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + ExpressionParsertext[ExpressionParserleng] = (yy_hold_char); \ + (yy_c_buf_p) = ExpressionParsertext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + ExpressionParserleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int ExpressionParserget_lineno (void) +{ + + return ExpressionParserlineno; +} + +/** Get the input stream. + * + */ +FILE *ExpressionParserget_in (void) +{ + return ExpressionParserin; +} + +/** Get the output stream. + * + */ +FILE *ExpressionParserget_out (void) +{ + return ExpressionParserout; +} + +/** Get the length of the current token. + * + */ +int ExpressionParserget_leng (void) +{ + return ExpressionParserleng; +} + +/** Get the current token. + * + */ + +char *ExpressionParserget_text (void) +{ + return ExpressionParsertext; +} + +/** Set the current line number. + * @param line_number + * + */ +void ExpressionParserset_lineno (int line_number ) +{ + + ExpressionParserlineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see ExpressionParser_switch_to_buffer + */ +void ExpressionParserset_in (FILE * in_str ) +{ + ExpressionParserin = in_str ; +} + +void ExpressionParserset_out (FILE * out_str ) +{ + ExpressionParserout = out_str ; +} + +int ExpressionParserget_debug (void) +{ + return ExpressionParser_flex_debug; +} + +void ExpressionParserset_debug (int bdebug ) +{ + ExpressionParser_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from ExpressionParserlex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + ExpressionParserin = stdin; + ExpressionParserout = stdout; +#else + ExpressionParserin = (FILE *) 0; + ExpressionParserout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * ExpressionParserlex_init() + */ + return 0; +} + +/* ExpressionParserlex_destroy is for both reentrant and non-reentrant scanners. */ +int ExpressionParserlex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + ExpressionParser_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + ExpressionParserpop_buffer_state(); + } + + /* Destroy the stack itself. */ + ExpressionParserfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * ExpressionParserlex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *ExpressionParseralloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *ExpressionParserrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void ExpressionParserfree (void * ptr ) +{ + free( (char *) ptr ); /* see ExpressionParserrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 268 "ExpressionParser.l" diff --git a/src/Mod/Spreadsheet/CMakeLists.txt b/src/Mod/Spreadsheet/CMakeLists.txt index b96ff2d4ca..32ee8e58ad 100644 --- a/src/Mod/Spreadsheet/CMakeLists.txt +++ b/src/Mod/Spreadsheet/CMakeLists.txt @@ -1,19 +1,9 @@ PYSIDE_WRAP_RC(Spreadsheet_QRC_SRCS Resources/Spreadsheet.qrc) -SET(Spreadsheet_SRCS - Init.py - InitGui.py - Spreadsheet.py -) -SOURCE_GROUP("" FILES ${Spreadsheet_SRCS}) - -SET(all_files ${Spreadsheet_SRCS}) - -ADD_CUSTOM_TARGET(Spreadsheet ALL - SOURCES ${all_files} ${Spreadsheet_QRC_SRCS} -) - -fc_copy_sources(Spreadsheet "${CMAKE_BINARY_DIR}/Mod/Spreadsheet" ${all_files}) +add_subdirectory(App) +if(BUILD_GUI) + add_subdirectory(Gui) +endif(BUILD_GUI) fc_target_copy_resource(Spreadsheet ${CMAKE_CURRENT_BINARY_DIR} @@ -21,6 +11,9 @@ fc_target_copy_resource(Spreadsheet Spreadsheet_rc.py) INSTALL( - FILES ${Spreadsheet_SRCS} ${Spreadsheet_QRC_SRCS} - DESTINATION Mod/Spreadsheet + FILES + Init.py + InitGui.py + DESTINATION + Mod/Spreadsheet ) diff --git a/src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp b/src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp new file mode 100644 index 0000000000..14f5461f25 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + * * + * 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. * + * for detail see the LICENCE text file. * + * Jrgen Riegel 2002 * + * Eivind Kvedalen 2015 * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif + +#include +#include +#include +#include "Workbench.h" +#include "ViewProviderSpreadsheet.h" +#include "SpreadsheetView.h" +#include "qrc_Spreadsheet.cxx" + +// use a different name to CreateCommand() +void CreateSpreadsheetCommands(void); + +void loadSpreadsheetResource() +{ + // add resources and reloads the translators + Q_INIT_RESOURCE(Spreadsheet); + Gui::Translator::instance()->refresh(); +} + +/* registration table */ +extern struct PyMethodDef SpreadsheetGui_Import_methods[]; + + +/* Python entry */ +extern "C" { +void SpreadsheetGuiExport initSpreadsheetGui() +{ + if (!Gui::Application::Instance) { + PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); + return; + } + + (void) Py_InitModule("SpreadsheetGui", SpreadsheetGui_Import_methods); /* mod name, table ptr */ + Base::Console().Log("Loading GUI of Spreadsheet module... done\n"); + + // instantiating the commands + CreateSpreadsheetCommands(); + + SpreadsheetGui::ViewProviderSheet::init(); + SpreadsheetGui::Workbench::init(); +// SpreadsheetGui::SheetView::init(); + + // add resources and reloads the translators + loadSpreadsheetResource(); +} + +} // extern "C" { diff --git a/src/Mod/Spreadsheet/Gui/AppSpreadsheetGuiPy.cpp b/src/Mod/Spreadsheet/Gui/AppSpreadsheetGuiPy.cpp new file mode 100644 index 0000000000..1e54c107fd --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/AppSpreadsheetGuiPy.cpp @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) * + * Copyright (c) 2006 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +#endif + +#include "SpreadsheetView.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace SpreadsheetGui; +using namespace Spreadsheet; + +/* module functions */ +static PyObject * +open(PyObject *self, PyObject *args) +{ + const char* Name; + const char* DocName=0; + if (!PyArg_ParseTuple(args, "s|s",&Name,&DocName)) + return NULL; + + PY_TRY { + Base::FileInfo file(Name); + App::Document *pcDoc = App::GetApplication().newDocument(DocName ? DocName : QT_TR_NOOP("Unnamed")); + Sheet *pcSheet = (Sheet *)pcDoc->addObject("Spreadsheet::Sheet", file.fileNamePure().c_str()); + + pcSheet->importFromFile(Name, '\t', '"', '\\'); + pcSheet->execute(); + } PY_CATCH; + + Py_Return; +} + +/* registration table */ +struct PyMethodDef SpreadsheetGui_Import_methods[] = { + {"open" ,open , 1}, /* method name, C func ptr, always-tuple */ + {NULL, NULL} /* end of table marker */ +}; diff --git a/src/Mod/Spreadsheet/Gui/CMakeLists.txt b/src/Mod/Spreadsheet/Gui/CMakeLists.txt new file mode 100644 index 0000000000..98b98321ad --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/CMakeLists.txt @@ -0,0 +1,91 @@ +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${Boost_INCLUDE_DIRS} + ${COIN3D_INCLUDE_DIR} + ${QT_INCLUDE_DIR} + ${ZLIB_INCLUDE_DIR} + ${SOQT_INCLUDE_DIR} + ${PYTHON_INCLUDE_PATH} + ${XERCESC_INCLUDE_DIR} +) + +set(SpreadsheetGui_LIBS + Spreadsheet + FreeCADGui +) + +set(SpreadsheetGui_MOC_HDRS + SpreadsheetView.h + SheetModel.h + SheetTableView.h + SpreadsheetDelegate.h + Workbench.h + PropertiesDialog.h + qtcolorpicker.h +) + +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/moc_qtcolorpicker-internal.cpp + COMMAND ${QT_MOC_EXECUTABLE} -o ${CMAKE_CURRENT_BINARY_DIR}/moc_qtcolorpicker-internal.cpp ${CMAKE_CURRENT_SOURCE_DIR}/qtcolorpicker.cpp + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/qtcolorpicker.cpp) + +set_property(SOURCE qtcolorpicker.cpp APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/moc_qtcolorpicker-internal.cpp) + +fc_wrap_cpp(SpreadsheetGui_MOC_SRCS ${SpreadsheetGui_MOC_HDRS}) +SOURCE_GROUP("Moc" FILES ${SpreadsheetGui_MOC_SRCS}) + + +SET(SpreadsheetGui_RES_SRCS + Resources/Spreadsheet.qrc +) + +#fc_add_resources(SpreadsheetGui_QRC_SRCS ${SpreadsheetGui_RES_SRCS}) +qt4_add_resources(SpreadsheetGui_QRC_SRCS ${SpreadsheetGui_RES_SRCS}) + +set(SpreadsheetGui_UIC_SRCS + Sheet.ui + PropertiesDialog.ui +) + +qt4_wrap_ui(SpreadsheetGui_UIC_HDRS ${SpreadsheetGui_UIC_SRCS}) + +SET(SpreadsheetGui_SRCS +# ${SpreadsheetGui_MOC_SRCS} +# ${SpreadsheetGui_QRC_SRCS} + AppSpreadsheetGui.cpp + AppSpreadsheetGuiPy.cpp + Command.cpp + ViewProviderSpreadsheet.cpp + ViewProviderSpreadsheet.h + Resources/Spreadsheet.qrc + SpreadsheetView.cpp + SpreadsheetView.h + SpreadsheetDelegate.h + SpreadsheetDelegate.cpp + SheetTableView.cpp + SheetTableView.h + SheetModel.h + SheetModel.cpp + PreCompiled.cpp + PreCompiled.h + Workbench.cpp + Workbench.h + qtcolorpicker.h + qtcolorpicker.cpp + PropertiesDialog.h + PropertiesDialog.cpp + ${SpreadsheetGui_UIC_HDRS} +) + +add_library(SpreadsheetGui SHARED ${SpreadsheetGui_SRCS}) +target_link_libraries(SpreadsheetGui ${SpreadsheetGui_LIBS}) + +fc_target_copy_resource(SpreadsheetGui + ${CMAKE_SOURCE_DIR}/src/Mod/Spreadsheet + ${CMAKE_BINARY_DIR}/Mod/Spreadsheet + InitGui.py) + +SET_BIN_DIR(SpreadsheetGui SpreadsheetGui /Mod/Spreadsheet) +SET_PYTHON_PREFIX_SUFFIX(SpreadsheetGui) + +INSTALL(TARGETS SpreadsheetGui DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/src/Mod/Spreadsheet/Gui/Command.cpp b/src/Mod/Spreadsheet/Gui/Command.cpp new file mode 100644 index 0000000000..b56524a0ee --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Command.cpp @@ -0,0 +1,812 @@ +/*************************************************************************** + * * + * 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. * + * for detail see the LICENCE text file. * + * Jürgen Riegel 2002 * + * Eivind Kvedalen 2015 * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +# include + +#include "SpreadsheetView.h" +#include "../App/Sheet.h" +#include "../App/Range.h" +#include "ViewProviderSpreadsheet.h" + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +using namespace SpreadsheetGui; +using namespace Spreadsheet; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetMergeCells); + +CmdSpreadsheetMergeCells::CmdSpreadsheetMergeCells() + : Command("Spreadsheet_MergeCells") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Merge cells"); + sToolTipText = QT_TR_NOOP("Merge selected cells in spreadsheet"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetMergeCells"; +} + +void CmdSpreadsheetMergeCells::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + std::vector ranges = sheetView->selectedRanges(); + + // Execute mergeCells commands + if (ranges.size() > 0) { + Gui::Command::openCommand("Merge cells"); + std::vector::const_iterator i = ranges.begin(); + for (; i != ranges.end(); ++i) + if (i->size() > 1) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.mergeCells('%s')", sheet->getNameInDocument(), + i->rangeString().c_str()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.setPosition('%s')", sheet->getNameInDocument(), + ranges[0].address().c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetMergeCells::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetSplitCell); + +CmdSpreadsheetSplitCell::CmdSpreadsheetSplitCell() + : Command("Spreadsheet_SplitCell") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Split cell"); + sToolTipText = QT_TR_NOOP("Split previously merged cells in spreadsheet"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetSplitCell"; +} + +void CmdSpreadsheetSplitCell::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + QModelIndex current = sheetView->currentIndex(); + + if (current.isValid()) { + std::string address = addressToString(CellAddress(current.row(), current.column())); + Gui::Command::openCommand("Split cell"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.splitCell('%s')", sheet->getNameInDocument(), + address.c_str()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetSplitCell::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + QModelIndex current = sheetView->currentIndex(); + Sheet * sheet = sheetView->getSheet(); + + if (current.isValid()) + return sheet->isMergedCell(CellAddress(current.row(), current.column())); + } + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetImport); + +CmdSpreadsheetImport::CmdSpreadsheetImport() + : Command("Spreadsheet_Import") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Import spreadsheet"); + sToolTipText = QT_TR_NOOP("Import CSV file into spreadsheet"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetImport"; +} + +void CmdSpreadsheetImport::activated(int iMsg) +{ + QString selectedFilter; + QString formatList = QObject::tr("All (*)"); + QString fileName = Gui::FileDialog::getOpenFileName(Gui::getMainWindow(), + QObject::tr("Import file"), + QString(), + formatList, + &selectedFilter); + if (!fileName.isEmpty()) { + std::string FeatName = getUniqueObjectName("Spreadsheet"); + Sheet * sheet = freecad_dynamic_cast(App::GetApplication().getActiveDocument()->addObject("Spreadsheet::Sheet", FeatName.c_str())); + + sheet->importFromFile(fileName.toStdString(), '\t', '"', '\\'); + sheet->execute(); + } +} + +bool CmdSpreadsheetImport::isActive() +{ + return getActiveGuiDocument() ? true : false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetExport); + +CmdSpreadsheetExport::CmdSpreadsheetExport() + : Command("Spreadsheet_Export") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Export spreadsheet"); + sToolTipText = QT_TR_NOOP("Export spreadsheet to CSV file"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetExport"; +} + +void CmdSpreadsheetExport::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + QString selectedFilter; + QString formatList = QObject::tr("All (*)"); + QString fileName = Gui::FileDialog::getSaveFileName(Gui::getMainWindow(), + QObject::tr("Export file"), + QString(), + formatList, + &selectedFilter); + if (!fileName.isEmpty()) + sheet->exportToFile(fileName.toStdString(), '\t', '"', '\\'); + } + } +} + +bool CmdSpreadsheetExport::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetAlignLeft); + +CmdSpreadsheetAlignLeft::CmdSpreadsheetAlignLeft() + : Command("Spreadsheet_AlignLeft") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Align left"); + sToolTipText = QT_TR_NOOP("Left-align contents of selected cells"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetAlignLeft"; +} + +void CmdSpreadsheetAlignLeft::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + std::vector ranges = sheetView->selectedRanges(); + + if (ranges.size() > 0) { + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Left-align cell"); + for (; i != ranges.end(); ++i) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'left', 'keep')", sheet->getNameInDocument(), + i->rangeString().c_str()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetAlignLeft::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetAlignCenter); + +CmdSpreadsheetAlignCenter::CmdSpreadsheetAlignCenter() + : Command("Spreadsheet_AlignCenter") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Align center"); + sToolTipText = QT_TR_NOOP("Center-align contents of selected cells"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetAlignCenter"; +} + +void CmdSpreadsheetAlignCenter::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + std::vector ranges = sheetView->selectedRanges(); + + if (ranges.size() > 0) { + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Center cell"); + for (; i != ranges.end(); ++i) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'center', 'keep')", sheet->getNameInDocument(), + i->rangeString().c_str()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetAlignCenter::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetAlignRight); + +CmdSpreadsheetAlignRight::CmdSpreadsheetAlignRight() + : Command("Spreadsheet_AlignRight") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Align right"); + sToolTipText = QT_TR_NOOP("Right-align contents of selected cells"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetAlignRight"; +} + +void CmdSpreadsheetAlignRight::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + std::vector ranges = sheetView->selectedRanges(); + + if (ranges.size() > 0) { + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Right-align cell"); + for (; i != ranges.end(); ++i) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'right', 'keep')", sheet->getNameInDocument(), + i->rangeString().c_str()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetAlignRight::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetAlignTop); + +CmdSpreadsheetAlignTop::CmdSpreadsheetAlignTop() + : Command("Spreadsheet_AlignTop") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Align top"); + sToolTipText = QT_TR_NOOP("Top-align contents of selected cells"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetAlignTop"; +} + +void CmdSpreadsheetAlignTop::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + std::vector ranges = sheetView->selectedRanges(); + + if (ranges.size() > 0) { + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Top-align cell"); + for (; i != ranges.end(); ++i) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'top', 'keep')", sheet->getNameInDocument(), + i->rangeString().c_str()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetAlignTop::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetAlignBottom); + +CmdSpreadsheetAlignBottom::CmdSpreadsheetAlignBottom() + : Command("Spreadsheet_AlignBottom") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Align bottom"); + sToolTipText = QT_TR_NOOP("Bottom-align contents of selected cells"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetAlignBottom"; +} + +void CmdSpreadsheetAlignBottom::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + std::vector ranges = sheetView->selectedRanges(); + + if (ranges.size() > 0) { + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Bottom-align cell"); + for (; i != ranges.end(); ++i) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'bottom', 'keep')", sheet->getNameInDocument(), + i->rangeString().c_str()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetAlignBottom::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetAlignVCenter); + +CmdSpreadsheetAlignVCenter::CmdSpreadsheetAlignVCenter() + : Command("Spreadsheet_AlignVCenter") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Vertically center-align"); + sToolTipText = QT_TR_NOOP("Center-align contents vertically of selected cells"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetAlignVCenter"; +} + +void CmdSpreadsheetAlignVCenter::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + std::vector ranges = sheetView->selectedRanges(); + + if (ranges.size() > 0) { + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Vertically center cells"); + for (; i != ranges.end(); ++i) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'vcenter', 'keep')", sheet->getNameInDocument(), + i->rangeString().c_str()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetAlignVCenter::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetStyleBold); + +CmdSpreadsheetStyleBold::CmdSpreadsheetStyleBold() + : Command("Spreadsheet_StyleBold") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Bold text"); + sToolTipText = QT_TR_NOOP("Set bold text in selected cells"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetStyleBold"; +} + +void CmdSpreadsheetStyleBold::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + QModelIndexList selection = sheetView->selectedIndexes(); + + if (selection.size() > 0) { + bool allBold = true; + + for (QModelIndexList::const_iterator it = selection.begin(); it != selection.end(); ++it) { + std::set style; + + sheet->getCell(CellAddress((*it).row(), (*it).column()))->getStyle(style); + if (style.find("bold") == style.end()) { + allBold = false; + break; + } + } + + std::vector ranges = sheetView->selectedRanges(); + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Set bold text"); + for (; i != ranges.end(); ++i) { + if (!allBold) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'bold', 'add')", sheet->getNameInDocument(), + i->rangeString().c_str()); + else + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'bold', 'remove')", sheet->getNameInDocument(), + i->rangeString().c_str()); + } + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetStyleBold::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetStyleItalic); + +CmdSpreadsheetStyleItalic::CmdSpreadsheetStyleItalic() + : Command("Spreadsheet_StyleItalic") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Italic text"); + sToolTipText = QT_TR_NOOP("Set italic text in selected cells"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetStyleItalic"; +} + +void CmdSpreadsheetStyleItalic::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + QModelIndexList selection = sheetView->selectedIndexes(); + + if (selection.size() > 0) { + bool allItalic = true; + + for (QModelIndexList::const_iterator it = selection.begin(); it != selection.end(); ++it) { + std::set style; + + sheet->getCell(CellAddress((*it).row(), (*it).column()))->getStyle(style); + if (style.find("italic") == style.end()) { + allItalic = false; + break; + } + } + + std::vector ranges = sheetView->selectedRanges(); + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Set italic text"); + for (; i != ranges.end(); ++i) { + if (!allItalic) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'italic', 'add')", sheet->getNameInDocument(), + i->rangeString().c_str()); + else + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'italic', 'remove')", sheet->getNameInDocument(), + i->rangeString().c_str()); + } + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetStyleItalic::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdSpreadsheetStyleUnderline); + +CmdSpreadsheetStyleUnderline::CmdSpreadsheetStyleUnderline() + : Command("Spreadsheet_StyleUnderline") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Underline text"); + sToolTipText = QT_TR_NOOP("Set underline text in selected cells"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "SpreadsheetStyleUnderline"; +} + +void CmdSpreadsheetStyleUnderline::activated(int iMsg) +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + QModelIndexList selection = sheetView->selectedIndexes(); + + if (selection.size() > 0) { + bool allUnderline = true; + + for (QModelIndexList::const_iterator it = selection.begin(); it != selection.end(); ++it) { + std::set style; + + sheet->getCell(CellAddress((*it).row(), (*it).column()))->getStyle(style); + if (style.find("underline") == style.end()) { + allUnderline = false; + break; + } + } + + std::vector ranges = sheetView->selectedRanges(); + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Set underline text"); + for (; i != ranges.end(); ++i) { + if (!allUnderline) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'underline', 'add')", sheet->getNameInDocument(), + i->rangeString().c_str()); + else + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'underline', 'remove')", sheet->getNameInDocument(), + i->rangeString().c_str()); + } + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +bool CmdSpreadsheetStyleUnderline::isActive() +{ + if (getActiveGuiDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + if (activeWindow && freecad_dynamic_cast(activeWindow)) + return true; + + } + return false; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +DEF_STD_CMD_A(CmdCreateSpreadsheet); + +CmdCreateSpreadsheet::CmdCreateSpreadsheet() + :Command("Spreadsheet_CreateSheet") +{ + sAppModule = "Spreadsheet"; + sGroup = QT_TR_NOOP("Spreadsheet"); + sMenuText = QT_TR_NOOP("Create spreadsheet"); + sToolTipText = QT_TR_NOOP("Create a new spreadsheet"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "Spreadsheet"; +} + +void CmdCreateSpreadsheet::activated(int iMsg) +{ + std::string FeatName = getUniqueObjectName("Spreadsheet"); + + openCommand("Create Spreadsheet"); + doCommand(Doc,"App.activeDocument().addObject('Spreadsheet::Sheet','%s\')",FeatName.c_str()); + commitCommand(); +} + +bool CmdCreateSpreadsheet::isActive() +{ + return App::GetApplication().getActiveDocument(); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +void CreateSpreadsheetCommands(void) +{ + Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + + rcCmdMgr.addCommand(new CmdCreateSpreadsheet()); + + rcCmdMgr.addCommand(new CmdSpreadsheetMergeCells()); + rcCmdMgr.addCommand(new CmdSpreadsheetSplitCell()); + + rcCmdMgr.addCommand(new CmdSpreadsheetImport()); + rcCmdMgr.addCommand(new CmdSpreadsheetExport()); + + rcCmdMgr.addCommand(new CmdSpreadsheetAlignLeft()); + rcCmdMgr.addCommand(new CmdSpreadsheetAlignCenter()); + rcCmdMgr.addCommand(new CmdSpreadsheetAlignRight()); + + rcCmdMgr.addCommand(new CmdSpreadsheetAlignTop()); + rcCmdMgr.addCommand(new CmdSpreadsheetAlignVCenter()); + rcCmdMgr.addCommand(new CmdSpreadsheetAlignBottom()); + + rcCmdMgr.addCommand(new CmdSpreadsheetStyleBold()); + rcCmdMgr.addCommand(new CmdSpreadsheetStyleItalic()); + rcCmdMgr.addCommand(new CmdSpreadsheetStyleUnderline()); +} + diff --git a/src/Mod/Spreadsheet/Gui/PreCompiled.cpp b/src/Mod/Spreadsheet/Gui/PreCompiled.cpp new file mode 100644 index 0000000000..38b50fcba9 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/PreCompiled.cpp @@ -0,0 +1,24 @@ +/*************************************************************************** + * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" diff --git a/src/Mod/Spreadsheet/Gui/PreCompiled.h b/src/Mod/Spreadsheet/Gui/PreCompiled.h new file mode 100644 index 0000000000..59e66e414b --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/PreCompiled.h @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef __PRECOMPILED_GUI__ +#define __PRECOMPILED_GUI__ + +#include + +// Importing of App classes +#ifdef FC_OS_WIN32 +# define SpreadsheetExport __declspec(dllimport) +# define SpreadsheetGuiExport __declspec(dllexport) +#else // for Linux +# define SpreadsheetExport +# define SpreadsheetGuiExport +#endif + + +// here get the warnings of too long specifiers disabled (needed for VC6) +#ifdef _MSC_VER +# pragma warning( disable : 4251 ) +# pragma warning( disable : 4503 ) +# pragma warning( disable : 4786 ) // specifier longer then 255 chars +#endif + +#ifdef _PreComp_ + +// Python +#include + +// standard +#include +#include +#include + +// STL +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef FC_OS_WIN32 +# include +#endif + +// Qt Toolkit +#ifndef __Qt4All__ +# include +#endif + + +#endif //_PreComp_ + +#endif // __PRECOMPILED_GUI__ diff --git a/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp b/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp new file mode 100644 index 0000000000..58fa3097d8 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp @@ -0,0 +1,297 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PropertiesDialog.h" +#include +#include +#include +#include +#include "ui_PropertiesDialog.h" + +using namespace Spreadsheet; +using namespace SpreadsheetGui; + +PropertiesDialog::PropertiesDialog(Sheet *_sheet, const std::vector &_ranges, QWidget *parent) : + QDialog(parent), + sheet(_sheet), + ranges(_ranges), + ui(new Ui::PropertiesDialog), + alignment(0), + displayUnitOk(true), + aliasOk(true) +{ + ui->setupUi(this); + ui->foregroundColor->setStandardColors(); + ui->backgroundColor->setStandardColors(); + + assert(ranges.size() > 0); + Range range = ranges[0]; + + sheet->getNewCell(*range)->getForeground(foregroundColor); + sheet->getCell(*range)->getBackground(backgroundColor); + sheet->getCell(*range)->getAlignment(alignment); + sheet->getCell(*range)->getStyle(style); + sheet->getCell(*range)->getDisplayUnit(displayUnit); + sheet->getCell(*range)->getAlias(alias); + + orgForegroundColor = foregroundColor; + orgBackgroundColor = backgroundColor; + orgAlignment = alignment; + orgStyle = style; + orgDisplayUnit = displayUnit; + orgAlias = alias; + + ui->foregroundColor->setCurrentColor(QColor::fromRgbF(foregroundColor.r, + foregroundColor.g, + foregroundColor.b, + foregroundColor.a)); + ui->backgroundColor->setCurrentColor(QColor::fromRgbF(backgroundColor.r, + backgroundColor.g, + backgroundColor.b, + backgroundColor.a)); + + if (alignment & Cell::ALIGNMENT_LEFT) + ui->alignLeft->setChecked(true); + else if (alignment & Cell::ALIGNMENT_HCENTER) + ui->alignHCenter->setChecked(true); + else if (alignment & Cell::ALIGNMENT_RIGHT) + ui->alignRight->setChecked(true); + + if (alignment & Cell::ALIGNMENT_TOP) + ui->alignTop->setChecked(true); + else if (alignment & Cell::ALIGNMENT_VCENTER) + ui->alignVCenter->setChecked(true); + else if (alignment & Cell::ALIGNMENT_BOTTOM) + ui->alignBottom->setChecked(true); + + if (style.find("bold") != style.end()) + ui->styleBold->setChecked(true); + if (style.find("italic") != style.end()) + ui->styleItalic->setChecked(true); + if (style.find("underline") != style.end()) + ui->styleUnderline->setChecked(true); + + ui->displayUnit->setText(QString::fromStdString(displayUnit.stringRep)); + + ui->alias->setText(QString::fromStdString(alias)); + + // Colors + connect(ui->foregroundColor, SIGNAL(colorChanged(QColor)), this, SLOT(foregroundColorChanged(QColor))); + connect(ui->backgroundColor, SIGNAL(colorChanged(QColor)), this, SLOT(backgroundColorChanged(QColor))); + + // Alignment + connect(ui->alignLeft, SIGNAL(clicked()), this, SLOT(alignmentChanged())); + connect(ui->alignRight, SIGNAL(clicked()), this, SLOT(alignmentChanged())); + connect(ui->alignHCenter, SIGNAL(clicked()), this, SLOT(alignmentChanged())); + connect(ui->alignTop, SIGNAL(clicked()), this, SLOT(alignmentChanged())); + connect(ui->alignVCenter, SIGNAL(clicked()), this, SLOT(alignmentChanged())); + connect(ui->alignBottom, SIGNAL(clicked()), this, SLOT(alignmentChanged())); + + // Style + connect(ui->styleBold, SIGNAL(clicked()), this, SLOT(styleChanged())); + connect(ui->styleItalic, SIGNAL(clicked()), this, SLOT(styleChanged())); + connect(ui->styleUnderline, SIGNAL(clicked()), this, SLOT(styleChanged())); + + // Display unit + connect(ui->displayUnit, SIGNAL(textEdited(QString)), this, SLOT(displayUnitChanged(QString))); + + // Alias is only allowed for a single cell + ui->tabWidget->widget(4)->setEnabled(_ranges.size() == 1 && _ranges[0].size() == 1); + + // Alias + connect(ui->alias, SIGNAL(textEdited(QString)), this, SLOT(aliasChanged(QString))); + + ui->tabWidget->setCurrentIndex(0); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(displayUnitOk && aliasOk); +} + +void PropertiesDialog::foregroundColorChanged(const QColor & color) +{ + foregroundColor = App::Color(color.redF(), color.greenF(), color.blueF(), color.alphaF()); +} + +void PropertiesDialog::backgroundColorChanged(const QColor & color) +{ + backgroundColor = App::Color(color.redF(), color.greenF(), color.blueF(), color.alphaF()); +} + +void PropertiesDialog::alignmentChanged() +{ + if (sender() == ui->alignLeft) + alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_LEFT; + else if (sender() == ui->alignHCenter) + alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_HCENTER; + else if (sender() == ui->alignRight) + alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_RIGHT; + else if (sender() == ui->alignTop) + alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_TOP; + else if (sender() == ui->alignVCenter) + alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_VCENTER; + else if (sender() == ui->alignBottom) + alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_BOTTOM; +} + +void PropertiesDialog::styleChanged() +{ + if (sender() == ui->styleBold) { + if (ui->styleBold->isChecked()) + style.insert("bold"); + else + style.erase("bold"); + } + else if (sender() == ui->styleItalic) { + if (ui->styleItalic->isChecked()) + style.insert("italic"); + else + style.erase("italic"); + } + else if (sender() == ui->styleUnderline) { + if (ui->styleUnderline->isChecked()) + style.insert("underline"); + else + style.erase("underline"); + } +} + +void PropertiesDialog::displayUnitChanged(const QString & text) +{ + if (text == "") { + displayUnit = DisplayUnit(); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + return; + } + + QPalette palette = ui->displayUnit->palette(); + try { + std::auto_ptr e(ExpressionParser::parseUnit(sheet, text.toUtf8().constData())); + + displayUnit = DisplayUnit(text.toUtf8().constData(), e->getUnit(), e->getScaler()); + palette.setColor(QPalette::Text, Qt::black); + displayUnitOk = true; + } + catch (...) { + displayUnit = DisplayUnit(); + palette.setColor(QPalette::Text, text.size() == 0 ? Qt::black : Qt::red); + displayUnitOk = false; + } + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(displayUnitOk && aliasOk); + ui->displayUnit->setPalette(palette); +} + +void PropertiesDialog::aliasChanged(const QString & text) +{ + QPalette palette = ui->alias->palette(); + + if (text.indexOf(QRegExp("^[A-Za-z][_A-Za-z0-9]*$")) >= 0) { + try { + CellAddress address(text.toUtf8().constData()); + + palette.setColor(QPalette::Text, Qt::red); + aliasOk = false; + alias = ""; + } + catch (...) { + aliasOk = true; + palette.setColor(QPalette::Text, Qt::black); + alias = text.toStdString(); + } + } + else { + if (text == "") { + aliasOk = true; + palette.setColor(QPalette::Text, Qt::black); + } + else { + aliasOk = false; + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + palette.setColor(QPalette::Text, Qt::red); + } + alias = ""; + } + + ui->alias->setPalette(palette); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(displayUnitOk && aliasOk); +} + +PropertiesDialog::~PropertiesDialog() +{ + delete ui; +} + +void PropertiesDialog::apply() +{ + if (ranges.size() > 0) { + Gui::Command::openCommand("Set cell properties"); + std::vector::const_iterator i = ranges.begin(); + bool changes = false; + + for (; i != ranges.end(); ++i) { + if (orgAlignment != alignment) { + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', '%s')", sheet->getNameInDocument(), + i->rangeString().c_str(), Cell::encodeAlignment(alignment).c_str()); + changes = true; + } + if (orgStyle != style) { + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', '%s')", sheet->getNameInDocument(), + i->rangeString().c_str(), Cell::encodeStyle(style).c_str()); + changes = true; + } + if (orgForegroundColor != foregroundColor) { + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setForeground('%s', (%f,%f,%f,%f))", sheet->getNameInDocument(), + i->rangeString().c_str(), + foregroundColor.r, + foregroundColor.g, + foregroundColor.b, + foregroundColor.a); + changes = true; + } + if (orgBackgroundColor != backgroundColor) { + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setBackground('%s', (%f,%f,%f,%f))", sheet->getNameInDocument(), + i->rangeString().c_str(), + backgroundColor.r, + backgroundColor.g, + backgroundColor.b, + backgroundColor.a); + changes = true; + } + if (orgDisplayUnit != displayUnit) { + std::string escapedstr = Base::Tools::escapedUnicodeFromUtf8(displayUnit.stringRep.c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setDisplayUnit('%s', '%s')", sheet->getNameInDocument(), + i->rangeString().c_str(), escapedstr.c_str()); + changes = true; + } + if (ranges.size() == 1 && ranges[0].size() == 1 && orgAlias != alias) { + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlias('%s', '%s')", sheet->getNameInDocument(), + i->address().c_str(), alias.c_str()); + changes = true; + } + } + if (changes) { + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + else + Gui::Command::abortCommand(); + } +} + +#include "moc_PropertiesDialog.cpp" diff --git a/src/Mod/Spreadsheet/Gui/PropertiesDialog.h b/src/Mod/Spreadsheet/Gui/PropertiesDialog.h new file mode 100644 index 0000000000..e1f1a0f9bc --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/PropertiesDialog.h @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef PROPERTIESDIALOG_H +#define PROPERTIESDIALOG_H + +#include +#include "PreCompiled.h" +#include + +namespace Ui { +class PropertiesDialog; +} + +namespace SpreadsheetGui { + +class PropertiesDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PropertiesDialog(Spreadsheet::Sheet *_sheet, const std::vector & _ranges, QWidget *parent = 0); + ~PropertiesDialog(); + + void apply(); + +private Q_SLOTS: + void foregroundColorChanged(const QColor &color); + void backgroundColorChanged(const QColor &color); + void alignmentChanged(); + void styleChanged(); + void displayUnitChanged(const QString &text); + void aliasChanged(const QString &text); +private: + Spreadsheet::Sheet * sheet; + std::vector ranges; + Ui::PropertiesDialog *ui; + App::Color foregroundColor; + App::Color backgroundColor; + int alignment; + std::set style; + Spreadsheet::DisplayUnit displayUnit; + std::string alias; + + App::Color orgForegroundColor; + App::Color orgBackgroundColor; + int orgAlignment; + std::set orgStyle; + Spreadsheet::DisplayUnit orgDisplayUnit; + std::string orgAlias; + + bool displayUnitOk; + bool aliasOk; +}; + +} + +#endif // PROPERTIESDIALOG_H diff --git a/src/Mod/Spreadsheet/Gui/PropertiesDialog.ui b/src/Mod/Spreadsheet/Gui/PropertiesDialog.ui new file mode 100644 index 0000000000..ce7685279f --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/PropertiesDialog.ui @@ -0,0 +1,345 @@ + + + PropertiesDialog + + + + 0 + 0 + 426 + 249 + + + + Cell properties + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + 0 + + + + &Color + + + + + + Text + + + + + + + Qt::Horizontal + + + + 240 + 20 + + + + + + + + + + + Background + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Alignment + + + + + + + + Horizontal + + + + + + + Left + + + + + + + Center + + + + + + + Right + + + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Vertical + + + + + + + Top + + + + + + + Center + + + + + + + Bottom + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Style + + + + + + + + Bold + + + + + + + Italic + + + + + + + Underline + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Display unit + + + + + + + + + Qt::Vertical + + + + 20 + 123 + + + + + + + + Unit string + + + + + + + + A&lias + + + + + + + + + Alias for this cell + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + QtColorPicker + QWidget +
qtcolorpicker.h
+ 1 +
+
+ + + + buttonBox + accepted() + PropertiesDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + PropertiesDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/src/Mod/Spreadsheet/Gui/Resources/Spreadsheet.qrc b/src/Mod/Spreadsheet/Gui/Resources/Spreadsheet.qrc new file mode 100644 index 0000000000..0a7cbc1a63 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/Spreadsheet.qrc @@ -0,0 +1,19 @@ + + + icons/Spreadsheet.svg + icons/SpreadsheetController.svg + icons/SpreadsheetImport.svg + icons/SpreadsheetExport.svg + icons/SpreadsheetSplitCell.svg + icons/SpreadsheetMergeCells.svg + icons/SpreadsheetAlignRight.svg + icons/SpreadsheetAlignLeft.svg + icons/SpreadsheetAlignCenter.svg + icons/SpreadsheetAlignVCenter.svg + icons/SpreadsheetAlignTop.svg + icons/SpreadsheetAlignBottom.svg + icons/SpreadsheetStyleUnderline.svg + icons/SpreadsheetStyleItalic.svg + icons/SpreadsheetStyleBold.svg + + diff --git a/src/Mod/Spreadsheet/Resources/icons/Spreadsheet.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/Spreadsheet.svg similarity index 100% rename from src/Mod/Spreadsheet/Resources/icons/Spreadsheet.svg rename to src/Mod/Spreadsheet/Gui/Resources/icons/Spreadsheet.svg diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignBottom.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignBottom.svg new file mode 100644 index 0000000000..77bd08bd31 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignBottom.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignCenter.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignCenter.svg new file mode 100644 index 0000000000..ace3fd97a1 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignCenter.svg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignLeft.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignLeft.svg new file mode 100644 index 0000000000..35c7c1b28f --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignLeft.svg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignRight.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignRight.svg new file mode 100644 index 0000000000..5df917396b --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignRight.svg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignTop.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignTop.svg new file mode 100644 index 0000000000..d1165f169b --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignTop.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignVCenter.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignVCenter.svg new file mode 100644 index 0000000000..50ece07c4b --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetAlignVCenter.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Resources/icons/SpreadsheetController.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetController.svg similarity index 100% rename from src/Mod/Spreadsheet/Resources/icons/SpreadsheetController.svg rename to src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetController.svg diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetExport.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetExport.svg new file mode 100644 index 0000000000..ed68e6721c --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetExport.svg @@ -0,0 +1,654 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Jakub Steiner + + + + + hdd + hard drive + save + io + store + + + + + http://jimmac.musichall.cz + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetImport.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetImport.svg new file mode 100644 index 0000000000..b6be03dfbb --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetImport.svg @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-01-31 + + + Jakub Steiner + + + + http://jimmac.musichall.cz + Active state - when files are being dragged to. + + + Novell, Inc. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetMergeCells.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetMergeCells.svg new file mode 100644 index 0000000000..e3768c846b --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetMergeCells.svg @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetSplitCell.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetSplitCell.svg new file mode 100644 index 0000000000..df0b9c4fa5 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetSplitCell.svg @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleBold.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleBold.svg new file mode 100644 index 0000000000..d519c2f762 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleBold.svg @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + B + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleItalic.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleItalic.svg new file mode 100644 index 0000000000..d1b0ff6f30 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleItalic.svg @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + i + + diff --git a/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleUnderline.svg b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleUnderline.svg new file mode 100644 index 0000000000..7a3bb97bf2 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Resources/icons/SpreadsheetStyleUnderline.svg @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + U + + + diff --git a/src/Mod/Spreadsheet/Gui/Sheet.ui b/src/Mod/Spreadsheet/Gui/Sheet.ui new file mode 100644 index 0000000000..ccd47aab42 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Sheet.ui @@ -0,0 +1,56 @@ + + + Sheet + + + + 0 + 0 + 727 + 596 + + + + Form + + + + + + + + &Contents + + + cellContent + + + + + + + false + + + + + + + + + + + + + SpreadsheetGui::SheetTableView + QTableView +
SheetTableView.h
+
+
+ + cells + cellContent + + + +
diff --git a/src/Mod/Spreadsheet/Gui/SheetModel.cpp b/src/Mod/Spreadsheet/Gui/SheetModel.cpp new file mode 100644 index 0000000000..edd9b91c59 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/SheetModel.cpp @@ -0,0 +1,435 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#include +# include +# include +#endif + +#include "SheetModel.h" +#include +#include +#include "../App/Sheet.h" +#include +#include +#include + +using namespace SpreadsheetGui; +using namespace Spreadsheet; +using namespace App; + +SheetModel::SheetModel(Sheet *_sheet, QObject *parent) + : QAbstractTableModel(parent) + , sheet(_sheet) +{ + cellUpdatedConnection = sheet->cellUpdated.connect(bind(&SheetModel::cellUpdated, this, _1)); +} + +SheetModel::~SheetModel() +{ + cellUpdatedConnection.disconnect(); +} + +int SheetModel::rowCount(const QModelIndex &parent) const +{ + return 16384; +} + +int SheetModel::columnCount(const QModelIndex &parent) const +{ + return 26 * 26 + 26; +} + +static void appendUnit(int l, bool isNumerator, std::string unit, std::vector & v) +{ + if (l == 0) + return; + if ((l < 0) ^ isNumerator ) { + std::ostringstream s; + + s << unit; + if (abs(l) > 1) + s << "^" << abs(l); + + v.push_back(s.str()); + } +} + +static std::string getUnitString(const Base::Unit & unit) +{ + std::vector numerator; + std::vector denominator; + const Base::UnitSignature & sig = unit.getSignature(); + + // Nominator + appendUnit(sig.Length, true, "mm", numerator); + appendUnit(sig.Mass, true, "kg", numerator); + appendUnit(sig.Time, true, "s", numerator); + appendUnit(sig.ElectricCurrent, true, "A", numerator); + appendUnit(sig.ThermodynamicTemperature, true, "K", numerator); + appendUnit(sig.AmountOfSubstance, true, "mol", numerator); + appendUnit(sig.LuminoseIntensity, true, "cd", numerator); + appendUnit(sig.Angle, true, "deg", numerator); + + // Denominator + appendUnit(sig.Length, false, "mm", denominator); + appendUnit(sig.Mass, false, "kg", denominator); + appendUnit(sig.Time, false, "s", denominator); + appendUnit(sig.ElectricCurrent, false, "A", denominator); + appendUnit(sig.ThermodynamicTemperature, false, "K", denominator); + appendUnit(sig.AmountOfSubstance, false, "mol", denominator); + appendUnit(sig.LuminoseIntensity, false, "cd", denominator); + appendUnit(sig.Angle, false, "deg", denominator); + + std::string unitStr; + + if (numerator.size() > 0) { + for (int i = 0; i < numerator.size(); ++i) { + if (i > 0) + unitStr += "*"; + unitStr += numerator[i]; + } + } + + if (denominator.size() > 0) { + if (numerator.size() == 0) + unitStr = "1"; + unitStr += "/"; + + if (denominator.size() > 1) + unitStr += "("; + for (int i = 0; i < denominator.size(); ++i) { + if (i > 0) + unitStr += "*"; + unitStr += denominator[i]; + } + if (denominator.size() > 1) + unitStr += ")"; + } + + return unitStr; +} + +QVariant SheetModel::data(const QModelIndex &index, int role) const +{ + static const Cell * emptyCell = new Cell(CellAddress(0, 0), 0); + int row = index.row(); + int col = index.column(); + const Cell * cell = sheet->getCell(CellAddress(row, col)); + + if (cell == 0) + cell = emptyCell; + +//#define DEBUG_DEPS +#ifdef DEBUG_DEPS + if (role == Qt::ToolTipRole) { + QString v; + + std::set deps = sheet->dependsOn(row, col); + std::set provides; + + sheet->providesTo(row, col, provides); + + if (deps.size() > 0) { + v += QString::fromUtf8("Depends on:"); + for (std::set::const_iterator i = deps.begin(); i != deps.end(); ++i) + v += QString::fromUtf8("\n\t") + QString::fromStdString(*i); + v += QString::fromUtf8("\n"); + } + if (provides.size() > 0) { + v += QString::fromUtf8("Used by:"); + for (std::set::const_iterator i = provides.begin(); i != provides.end(); ++i) + v += QString::fromUtf8("\n\t") + QString::fromStdString(*i); + v += QString::fromUtf8("\n"); + } + return QVariant(v); + } +#endif + + if (cell->hasException()) { + switch (role) { + case Qt::ToolTipRole: + return QVariant::fromValue(QString::fromStdString(cell->getException())); + case Qt::DisplayRole: +#ifdef DEBUG_DEPS + return QVariant::fromValue(QString::fromUtf8("#ERR: %1").arg(QString::fromStdString(cell->getException()))); +#else + return QVariant::fromValue(QString::fromUtf8("#ERR")); +#endif + case Qt::TextAlignmentRole: + return QVariant(Qt::AlignVCenter | Qt::AlignLeft); + default: + break; + } + } + + // Get edit value by querying the sheet + if (role == Qt::EditRole || role == Qt::StatusTipRole) { + std::string str; + + if (cell->getStringContent(str)) + return QVariant(QString::fromUtf8(str.c_str())); + else + return QVariant(); + } + + // Get display value as computed property + std::string address = addressToString(CellAddress(row, col)); + Property * prop = sheet->getPropertyByName(address.c_str()); + + if (prop == 0) + return QVariant(); + + Color color; + if (role == Qt::TextColorRole || role == Qt::ForegroundRole) { + if (cell->getForeground(color)) + return QVariant::fromValue(QColor(255.0 * color.r, 255.0 * color.g, 255.0 * color.b, 255.0 * color.a)); + else + return QVariant(); + } + + if (role == Qt::BackgroundRole) { + if (cell->getBackground(color)) + return QVariant::fromValue(QColor(255.0 * color.r, 255.0 * color.g, 255.0 * color.b, 255.0 * color.a)); + else + return QVariant(); + } + + int qtAlignment = 0; + + int alignment; + cell->getAlignment(alignment); + + if (alignment & Cell::ALIGNMENT_LEFT) + qtAlignment |= Qt::AlignLeft; + if (alignment & Cell::ALIGNMENT_HCENTER) + qtAlignment |= Qt::AlignHCenter; + if (alignment & Cell::ALIGNMENT_RIGHT) + qtAlignment |= Qt::AlignRight; + if (alignment & Cell::ALIGNMENT_TOP) + qtAlignment |= Qt::AlignTop; + if (alignment & Cell::ALIGNMENT_VCENTER) + qtAlignment |= Qt::AlignVCenter; + if (alignment & Cell::ALIGNMENT_BOTTOM) + qtAlignment |= Qt::AlignBottom; + + std::set style; + if (role == Qt::FontRole && cell->getStyle(style)) { + QFont f; + + for (std::set::const_iterator i = style.begin(); i != style.end(); ++i) { + if (*i == "bold") + f.setBold(true); + else if (*i == "italic") + f.setItalic(true); + else if (*i == "underline") + f.setUnderline(true); + } + + return QVariant::fromValue(f); + } + + if (prop->isDerivedFrom(App::PropertyString::getClassTypeId())) { + /* String */ + const App::PropertyString * stringProp = static_cast(prop); + + switch (role) { + case Qt::TextColorRole: + return QVariant::fromValue(QColor(Qt::black)); + case Qt::DisplayRole: + return QVariant(QString::fromUtf8(stringProp->getValue())); + case Qt::TextAlignmentRole: { + if (alignment & Cell::ALIGNMENT_HIMPLIED) { + qtAlignment &= ~(Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight); + qtAlignment |= Qt::AlignLeft; + } + if (alignment & Cell::ALIGNMENT_VIMPLIED) { + qtAlignment &= ~(Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom); + qtAlignment |= Qt::AlignVCenter; + } + return QVariant::fromValue(qtAlignment); + } + default: + return QVariant(); + } + } + else if (prop->isDerivedFrom(App::PropertyQuantity::getClassTypeId())) { + /* Number */ + const App::PropertyQuantity * floatProp = static_cast(prop); + + switch (role) { + case Qt::TextColorRole: + if (floatProp->getValue() < 0) + return QVariant::fromValue(QColor(Qt::red)); + else + return QVariant::fromValue(QColor(Qt::blue)); + case Qt::TextAlignmentRole: { + if (alignment & Cell::ALIGNMENT_HIMPLIED) { + qtAlignment &= ~(Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight); + qtAlignment |= Qt::AlignRight; + } + if (alignment & Cell::ALIGNMENT_VIMPLIED) { + qtAlignment &= ~(Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom); + qtAlignment |= Qt::AlignVCenter; + } + return QVariant::fromValue(qtAlignment); + } + case Qt::DisplayRole: { + QString v; + const Base::Unit & computedUnit = floatProp->getUnit(); + DisplayUnit displayUnit; + + if (cell->getDisplayUnit(displayUnit)) { + if (computedUnit.isEmpty() || computedUnit == displayUnit.unit) + v = QString::number(floatProp->getValue() / displayUnit.scaler) + QString::fromStdString(" " + displayUnit.stringRep); + else + v = QString::fromUtf8("ERR: unit"); + } + else { + if (!computedUnit.isEmpty()) + v = QString::number(floatProp->getValue()) + QString::fromStdString(" " + getUnitString(computedUnit)); + else + v = QString::number(floatProp->getValue()); + } + + return QVariant(v); + } + default: + return QVariant(); + } + } + else if (prop->isDerivedFrom(App::PropertyFloat::getClassTypeId())) { + /* Number */ + const App::PropertyFloat * floatProp = static_cast(prop); + + switch (role) { + case Qt::TextColorRole: + if (floatProp->getValue() < 0) + return QVariant::fromValue(QColor(Qt::red)); + else + return QVariant::fromValue(QColor(Qt::blue)); + case Qt::TextAlignmentRole: { + if (alignment & Cell::ALIGNMENT_HIMPLIED) { + qtAlignment &= ~(Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight); + qtAlignment |= Qt::AlignRight; + } + if (alignment & Cell::ALIGNMENT_VIMPLIED) { + qtAlignment &= ~(Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom); + qtAlignment |= Qt::AlignVCenter; + } + return QVariant::fromValue(qtAlignment); + } + case Qt::DisplayRole: { + QString v; + DisplayUnit displayUnit; + + if (cell->getDisplayUnit(displayUnit)) + v = QString::number(floatProp->getValue() / displayUnit.scaler) + QString::fromStdString(" " + displayUnit.stringRep); + else + v = QString::number(floatProp->getValue()); + return QVariant(v); + } + default: + return QVariant(); + } + } +} + +QVariant SheetModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::SizeHintRole) { + if (orientation == Qt::Horizontal) + return QVariant(QSize(sheet->getColumnWidth(section), PropertyRowHeights::defaultHeight)); + else + return QVariant(QSize(PropertyColumnWidths::defaultHeaderWidth, sheet->getRowHeight(section))); + } + if (role == Qt::DisplayRole) { + if (orientation == Qt::Horizontal) { + static QString labels = QString::fromUtf8("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + if (section < 26) { + return QVariant(labels[section]); + } + else { + section -= 26; + return QVariant(QString(labels[section / 26]) + QString(labels[section % 26])); + } + } + else { + return QString::number(section + 1); + } + } + return QVariant(); +} + +bool SheetModel::setData(const QModelIndex & index, const QVariant & value, int role) +{ + if (role == Qt::DisplayRole) { + // Nothing to do, it will get updated by the sheet in the application logic + } + else if (role == Qt::EditRole) { + CellAddress address(index.row(), index.column()); + + try { + std::string strAddress = addressToString(address); + std::string next_address = addressToString(CellAddress(address.row() + 1, address.col())); + QString str = value.toString(); + std::string content; + Cell * cell = sheet->getCell(address); + + if (cell) + cell->getStringContent(content); + + if ( content != str.toStdString()) { + str.replace(QString::fromUtf8("'"), QString::fromUtf8("\\'")); + Gui::Command::openCommand("Edit cell"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.set('%s', '%s')", sheet->getNameInDocument(), + strAddress.c_str(), str.toUtf8().constData()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setPosition('%s')", sheet->getNameInDocument(), + next_address.c_str()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + catch (const Base::Exception& e) { + QMessageBox::critical(qApp->activeWindow(), QObject::tr("Cell contents"), QString::fromUtf8(e.what())); + Gui::Command::abortCommand(); + } + } + return true; +} + +Qt::ItemFlags SheetModel::flags(const QModelIndex & /*index*/) const +{ + return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled; +} + +void SheetModel::cellUpdated(CellAddress address) +{ + QModelIndex i = index(address.row(), address.col()); + + dataChanged(i, i); +} + +#include "moc_SheetModel.cpp" diff --git a/src/Mod/Spreadsheet/Gui/SheetModel.h b/src/Mod/Spreadsheet/Gui/SheetModel.h new file mode 100644 index 0000000000..577c5e6603 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/SheetModel.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef SHEETMODEL_H +#define SHEETMODEL_H + +#include +#include +#include + +namespace Spreadsheet { +class Sheet; +} + +namespace SpreadsheetGui { + +class SheetModel : public QAbstractTableModel +{ + Q_OBJECT +public: + explicit SheetModel(Spreadsheet::Sheet * _sheet, QObject *parent = 0); + ~SheetModel(); + + SheetModel(QObject *parent); + int rowCount(const QModelIndex &parent = QModelIndex()) const ; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); + Qt::ItemFlags flags(const QModelIndex &) const; + +private: + void cellUpdated(Spreadsheet::CellAddress address); + + boost::BOOST_SIGNALS_NAMESPACE::scoped_connection cellUpdatedConnection; + Spreadsheet::Sheet * sheet; +}; + +} + +#endif // SHEETMODEL_H diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp new file mode 100644 index 0000000000..09c5d36bdc --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp @@ -0,0 +1,299 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include "SheetTableView.h" +#include +#include +#include +#include "PropertiesDialog.h" +#include "../App/Utils.h" +#include "../App/Range.h" +#include + +using namespace SpreadsheetGui; +using namespace Spreadsheet; + +void SheetViewHeader::mouseReleaseEvent(QMouseEvent *event) +{ + QHeaderView::mouseReleaseEvent(event); + resizeFinished(); +} + +SheetTableView::SheetTableView(QWidget *parent) + : QTableView(parent) +{ + QAction * insertRows = new QAction(tr("Insert rows"), this); + QAction * removeRows = new QAction(tr("Remove rows"), this); + QAction * insertColumns = new QAction(tr("Insert columns"), this); + QAction * removeColumns = new QAction(tr("Remove columns"), this); + + setHorizontalHeader(new SheetViewHeader(Qt::Horizontal)); + setVerticalHeader(new SheetViewHeader(Qt::Vertical)); + + horizontalHeader()->addAction(insertColumns); + horizontalHeader()->addAction(removeColumns); + horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu); + + verticalHeader()->addAction(insertRows); + verticalHeader()->addAction(removeRows); + verticalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu); + + connect(insertRows, SIGNAL(triggered()), this, SLOT(insertRows())); + connect(insertColumns, SIGNAL(triggered()), this, SLOT(insertColumns())); + connect(removeRows, SIGNAL(triggered()), this, SLOT(removeRows())); + connect(removeColumns, SIGNAL(triggered()), this, SLOT(removeColumns())); + + QAction * cellProperties = new QAction(tr("Properties..."), this); + setContextMenuPolicy(Qt::ActionsContextMenu); + addAction(cellProperties); + + connect(cellProperties, SIGNAL(triggered()), this, SLOT(cellProperties())); +} + +void SheetTableView::cellProperties() +{ + std::auto_ptr dialog(new PropertiesDialog(sheet, selectedRanges(), this)); + + if (dialog->exec() == QDialog::Accepted) { + dialog->apply(); + } +} + +std::vector SheetTableView::selectedRanges() const +{ + QModelIndexList list = selectionModel()->selectedIndexes(); + std::vector result; + + // Insert selected cells into set. This variable should ideally be a hash_set + // but that is not part of standard stl. + std::set > cells; + for (QModelIndexList::const_iterator it = list.begin(); it != list.end(); ++it) + cells.insert(std::make_pair((*it).row(), (*it).column())); + + // Create rectangular cells from the unordered collection of selected cells + std::map, std::pair > rectangles; + createRectangles(cells, rectangles); + + std::map, std::pair >::const_iterator i = rectangles.begin(); + for (; i != rectangles.end(); ++i) { + std::pair ul = (*i).first; + std::pair size = (*i).second; + + result.push_back(Range(ul.first, ul.second, + ul.first + size.first - 1, ul.second + size.second - 1)); + } + + return result; +} + +void SheetTableView::insertRows() +{ + assert(sheet != 0); + + QModelIndexList rows = selectionModel()->selectedRows(); + std::vector sortedRows; + + /* Make sure rows are sorted in ascending order */ + for (QModelIndexList::const_iterator it = rows.begin(); it != rows.end(); ++it) + sortedRows.push_back(it->row()); + std::sort(sortedRows.begin(), sortedRows.end()); + + /* Insert rows */ + Gui::Command::openCommand("Insert rows"); + std::vector::const_reverse_iterator it = sortedRows.rbegin(); + while (it != sortedRows.rend()) { + int prev = *it; + int count = 1; + + /* Collect neighbouring rows into one chunk */ + ++it; + while (it != sortedRows.rend()) { + if (*it == prev - 1) { + prev = *it; + ++count; + ++it; + } + else + break; + } + + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.insertRows('%s', %d)", sheet->getNameInDocument(), + rowName(prev).c_str(), count); + } + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); +} + +void SheetTableView::removeRows() +{ + assert(sheet != 0); + + QModelIndexList rows = selectionModel()->selectedRows(); + std::vector sortedRows; + int extra = 0; + + /* Make sure rows are sorted in descending order */ + for (QModelIndexList::const_iterator it = rows.begin(); it != rows.end(); ++it) + sortedRows.push_back(it->row()); + std::sort(sortedRows.begin(), sortedRows.end(), std::greater()); + + /* Remove rows */ + Gui::Command::openCommand("Remove rows"); + for (std::vector::const_iterator it = sortedRows.begin(); it != sortedRows.end(); ++it) { + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.removeRows('%s', %d)", sheet->getNameInDocument(), + rowName(*it).c_str(), 1); + } + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); +} + +void SheetTableView::insertColumns() +{ + assert(sheet != 0); + + QModelIndexList cols = selectionModel()->selectedColumns(); + std::vector sortedColumns; + + /* Make sure rows are sorted in ascending order */ + for (QModelIndexList::const_iterator it = cols.begin(); it != cols.end(); ++it) + sortedColumns.push_back(it->column()); + std::sort(sortedColumns.begin(), sortedColumns.end()); + + /* Insert columns */ + Gui::Command::openCommand("Insert columns"); + std::vector::const_reverse_iterator it = sortedColumns.rbegin(); + while (it != sortedColumns.rend()) { + int prev = *it; + int count = 1; + + /* Collect neighbouring columns into one chunk */ + ++it; + while (it != sortedColumns.rend()) { + if (*it == prev - 1) { + prev = *it; + ++count; + ++it; + } + else + break; + } + + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.insertColumns('%s', %d)", sheet->getNameInDocument(), + columnName(prev).c_str(), count); + } + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); +} + +void SheetTableView::removeColumns() +{ + assert(sheet != 0); + + QModelIndexList cols = selectionModel()->selectedColumns(); + std::vector sortedColumns; + + /* Make sure rows are sorted in descending order */ + for (QModelIndexList::const_iterator it = cols.begin(); it != cols.end(); ++it) + sortedColumns.push_back(it->column()); + std::sort(sortedColumns.begin(), sortedColumns.end(), std::greater()); + + /* Remove columns */ + Gui::Command::openCommand("Remove rows"); + for (std::vector::const_iterator it = sortedColumns.begin(); it != sortedColumns.end(); ++it) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.removeColumns('%s', %d)", sheet->getNameInDocument(), + columnName(*it).c_str(), 1); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); +} + +SheetTableView::~SheetTableView() +{ + +} + +void SheetTableView::updateCellSpan(Spreadsheet::CellAddress address) +{ + int rows, cols; + + sheet->getSpans(address, rows, cols); + + if (rows != rowSpan(address.row(), address.col()) || cols != columnSpan(address.row(), address.col())) + setSpan(address.row(), address.col(), rows, cols); +} + +void SheetTableView::setSheet(Sheet * _sheet) +{ + sheet = _sheet; + cellSpanChangedConnection = sheet->cellSpanChanged.connect(bind(&SheetTableView::updateCellSpan, this, _1)); + + // Update row and column spans + std::vector usedCells = sheet->getUsedCells(); + + for (std::vector::const_iterator i = usedCells.begin(); i != usedCells.end(); ++i) { + CellAddress address(*i); + + if (sheet->isMergedCell(address)) + updateCellSpan(address); + } + + // Update column widths and row height + std::map columWidths = sheet->getColumnWidths(); + for (std::map::const_iterator i = columWidths.begin(); i != columWidths.end(); ++i) { + int newSize = i->second; + + if (newSize > 0 && horizontalHeader()->sectionSize(i->first) != newSize) + setColumnWidth(i->first, newSize); + } + + std::map rowHeights = sheet->getRowHeights(); + for (std::map::const_iterator i = rowHeights.begin(); i != rowHeights.end(); ++i) { + int newSize = i->second; + + if (newSize > 0 && verticalHeader()->sectionSize(i->first) != newSize) + setRowHeight(i->first, newSize); + } + +} + +void SheetTableView::commitData ( QWidget * editor ) +{ + QTableView::commitData(editor); +} + +bool SheetTableView::edit ( const QModelIndex & index, EditTrigger trigger, QEvent * event ) +{ + if (trigger & (QAbstractItemView::DoubleClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed) ) + currentEditIndex = index; + return QTableView::edit(index, trigger, event); +} + +void SheetTableView::edit ( const QModelIndex & index ) +{ + currentEditIndex = index; + QTableView::edit(index); +} + +#include "moc_SheetTableView.cpp" diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.h b/src/Mod/Spreadsheet/Gui/SheetTableView.h new file mode 100644 index 0000000000..4959000f09 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/SheetTableView.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef SHEETTABLEVIEW_H +#define SHEETTABLEVIEW_H + +#include +#include +#include +#include "PreCompiled.h" +#include +#include + +namespace SpreadsheetGui { + +class SheetViewHeader : public QHeaderView { + Q_OBJECT +public: + SheetViewHeader(Qt::Orientation o) : QHeaderView(o) { + setClickable(true); + } +Q_SIGNALS: + void resizeFinished(); +protected: + void mouseReleaseEvent(QMouseEvent * event); +}; + +class SheetTableView : public QTableView +{ + Q_OBJECT +public: + explicit SheetTableView(QWidget *parent = 0); + ~SheetTableView(); + + void edit(const QModelIndex &index); + void setSheet(Spreadsheet::Sheet *_sheet); + std::vector selectedRanges() const; +protected Q_SLOTS: + void commitData(QWidget *editor); + void updateCellSpan(Spreadsheet::CellAddress address); + void insertRows(); + void removeRows(); + void insertColumns(); + void removeColumns(); + void cellProperties(); +protected: + bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event); + + QModelIndex currentEditIndex; + Spreadsheet::Sheet * sheet; + + boost::BOOST_SIGNALS_NAMESPACE::scoped_connection cellSpanChangedConnection; +}; + +} + +#endif // SHEETTABLEVIEW_H diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp new file mode 100644 index 0000000000..f301fba470 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This file is based on the Qt spreadsheet example code. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "SpreadsheetDelegate.h" +#include +#include + +using namespace SpreadsheetGui; + +SpreadsheetDelegate::SpreadsheetDelegate(QWidget *parent) : + QItemDelegate(parent) +{ +} + +QWidget *SpreadsheetDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &, + const QModelIndex &index) const +{ + QLineEdit *editor = new QLineEdit(parent); + + connect(editor, SIGNAL(returnPressed()), this, SLOT(commitAndCloseEditor())); + return editor; +} + +void SpreadsheetDelegate::commitAndCloseEditor() +{ + QLineEdit *editor = qobject_cast(sender()); + emit commitData(editor); + emit closeEditor(editor); +} + +void SpreadsheetDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const +{ + QLineEdit *edit = qobject_cast(editor); + if (edit) { + edit->setText(index.model()->data(index, Qt::EditRole).toString()); + return; + } +} + +void SpreadsheetDelegate::setModelData(QWidget *editor, + QAbstractItemModel *model, const QModelIndex &index) const +{ + QLineEdit *edit = qobject_cast(editor); + if (edit) { + model->setData(index, edit->text()); + return; + } +} + +QSize SpreadsheetDelegate::sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + return QSize(); +} + +#include "moc_SpreadsheetDelegate.cpp" + diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h new file mode 100644 index 0000000000..575cd58745 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This file is based on the Qt spreadsheet example code. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef SPREADSHEETDELEGATE_H +#define SPREADSHEETDELEGATE_H + +#include + +namespace SpreadsheetGui { + +class SpreadsheetDelegate : public QItemDelegate +{ + Q_OBJECT +public: + explicit SpreadsheetDelegate(QWidget *parent = 0); + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, + const QModelIndex &index) const; + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; +private Q_SLOTS: + void commitAndCloseEditor(); + +}; + +} + +#endif // SPREADSHEETDELEGATE_H diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp new file mode 100644 index 0000000000..4465d08cf8 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp @@ -0,0 +1,327 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include "SpreadsheetView.h" +#include "SpreadsheetDelegate.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qtcolorpicker.h" + +#include "ui_Sheet.h" + +using namespace SpreadsheetGui; +using namespace Spreadsheet; +using namespace Gui; + +/* TRANSLATOR SpreadsheetGui::SheetView */ + +TYPESYSTEM_SOURCE_ABSTRACT(SpreadsheetGui::SheetView, Gui::MDIView); + +SheetView::SheetView(Gui::Document *pcDocument, App::DocumentObject *docObj, QWidget *parent) + : MDIView(pcDocument, parent) + , sheet(static_cast(docObj)) +{ + // Set up ui + + model = new SheetModel(static_cast(docObj)); + + ui = new Ui::Sheet(); + QWidget * w = new QWidget(this); + ui->setupUi(w); + setCentralWidget(w); + + delegate = new SpreadsheetDelegate(); + ui->cells->setModel(model); + ui->cells->setItemDelegate(delegate); + ui->cells->setSheet(sheet); + + // Connect signals + connect(ui->cells->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), + this, SLOT( currentChanged( QModelIndex, QModelIndex ) ) ); + + connect(ui->cells->horizontalHeader(), SIGNAL(resizeFinished()), + this, SLOT(columnResizeFinished())); + connect(ui->cells->horizontalHeader(), SIGNAL(sectionResized ( int, int, int ) ), + this, SLOT(columnResized(int, int, int))); + + connect(ui->cells->verticalHeader(), SIGNAL(resizeFinished()), + this, SLOT(rowResizeFinished())); + connect(ui->cells->verticalHeader(), SIGNAL(sectionResized ( int, int, int ) ), + this, SLOT(rowResized(int, int, int))); + + connect(ui->cellContent, SIGNAL(returnPressed()), this, SLOT( editingFinished() )); + + columnWidthChangedConnection = sheet->columnWidthChanged.connect(bind(&SheetView::resizeColumn, this, _1, _2)); + rowHeightChangedConnection = sheet->rowHeightChanged.connect(bind(&SheetView::resizeRow, this, _1, _2)); + positionChangedConnection = sheet->positionChanged.connect(bind(&SheetView::setPosition, this, _1)); + + QPalette palette = ui->cells->palette(); + palette.setColor(QPalette::Base, QColor(255, 255, 255)); + palette.setColor(QPalette::Text, QColor(0, 0, 0)); + ui->cells->setPalette(palette); + + QList bgList = Gui::getMainWindow()->findChildren(QString::fromAscii("Spreadsheet_BackgroundColor")); + if (bgList.size() > 0) + bgList[0]->setCurrentColor(palette.color(QPalette::Base)); + + QList fgList = Gui::getMainWindow()->findChildren(QString::fromAscii("Spreadsheet_ForegroundColor")); + if (fgList.size() > 0) + fgList[0]->setCurrentColor(palette.color(QPalette::Text)); +} + +SheetView::~SheetView() +{ + Application::Instance->detachView(this); + //delete delegate; +} + +bool SheetView::onMsg(const char *pMsg, const char **ppReturn) +{ + if(strcmp("Undo",pMsg) == 0 ) { + getGuiDocument()->undo(1); + App::Document* doc = getAppDocument(); + if (doc) + doc->recomputeFeature(sheet); + return true; + } + else if(strcmp("Redo",pMsg) == 0 ) { + getGuiDocument()->redo(1); + App::Document* doc = getAppDocument(); + if (doc) + doc->recomputeFeature(sheet); + return true; + } + else if (strcmp("Save",pMsg) == 0) { + getGuiDocument()->save(); + return true; + } + else if (strcmp("SaveAs",pMsg) == 0) { + getGuiDocument()->saveAs(); + return true; + } + else + return false; +} + +bool SheetView::onHasMsg(const char *pMsg) const +{ + if (strcmp("Undo",pMsg) == 0) { + App::Document* doc = getAppDocument(); + return doc && doc->getAvailableUndos() > 0; + } + else if (strcmp("Redo",pMsg) == 0) { + App::Document* doc = getAppDocument(); + return doc && doc->getAvailableRedos() > 0; + } + else if (strcmp("Save",pMsg) == 0) + return true; + else if (strcmp("SaveAs",pMsg) == 0) + return true; + else + return false; +} + +void SheetView::setCurrentCell(QString str) +{ + updateContentLine(); +} + +void SheetView::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Delete) { + if (event->modifiers() == 0) { + //model()->setData(currentIndex(), QVariant(), Qt::EditRole); + } + else if (event->modifiers() == Qt::ControlModifier) { + //model()->setData(currentIndex(), QVariant(), Qt::EditRole); + } + } + else + Gui::MDIView::keyPressEvent(event); +} + +void SheetView::updateContentLine() +{ + QModelIndex i = ui->cells->currentIndex(); + + if (i.isValid()) { + std::string str; + Cell * cell = sheet->getCell(CellAddress(i.row(), i.column())); + + if (cell) + cell->getStringContent(str); + ui->cellContent->setText(QString::fromUtf8(str.c_str())); + ui->cellContent->setEnabled(true); + } +} + +void SheetView::columnResizeFinished() +{ + if (newColumnSizes.size() == 0) + return; + + blockSignals(true); + Gui::Command::openCommand("Resize column"); + + QMap::const_iterator i = newColumnSizes.begin(); + while (i != newColumnSizes.end()) { + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setColumnWidth('%s', %d)", sheet->getNameInDocument(), + columnName(i.key()).c_str(), i.value()); + ++i; + } + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + blockSignals(false); + newColumnSizes.clear(); +} + +void SheetView::rowResizeFinished() +{ + if (newRowSizes.size() == 0) + return; + + blockSignals(true); + Gui::Command::openCommand("Resize row"); + + QMap::const_iterator i = newRowSizes.begin(); + while (i != newRowSizes.end()) { + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setRowHeight('%s', %d)", sheet->getNameInDocument(), + rowName(i.key()).c_str(), i.value()); + ++i; + } + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + blockSignals(false); + newRowSizes.clear(); +} + +void SheetView::columnResized(int col, int oldSize, int newSize) +{ + newColumnSizes[col] = newSize; +} + +void SheetView::rowResized(int row, int oldSize, int newSize) +{ + newRowSizes[row] = newSize; +} + +void SheetView::resizeColumn(int col, int newSize) +{ + if (ui->cells->horizontalHeader()->sectionSize(col) != newSize) + ui->cells->setColumnWidth(col, newSize); +} + +void SheetView::setPosition(CellAddress address) +{ + QModelIndex curr = ui->cells->currentIndex(); + QModelIndex i = ui->cells->model()->index(address.row(), address.col()); + + if (i.isValid() && (curr.row() != address.row() || curr.column() != address.col())) { + ui->cells->clearSelection(); + ui->cells->setCurrentIndex(i); + } +} + +void SheetView::resizeRow(int col, int newSize) +{ + if (ui->cells->verticalHeader()->sectionSize(col) != newSize) + ui->cells->setRowHeight(col, newSize); +} + +void SheetView::editingFinished() +{ + QModelIndex i = ui->cells->currentIndex(); + + // Update data in cell + ui->cells->model()->setData(i, QVariant(ui->cellContent->text()), Qt::EditRole); +} + +void SheetView::currentChanged ( const QModelIndex & current, const QModelIndex & previous ) +{ + updateContentLine(); + sheet->setPosition(CellAddress(current.row(), current.column())); +} + +void SheetView::updateCell(const App::Property *prop) +{ + try { + CellAddress address; + + sheet->getCellAddress(prop, address); + updateContentLine(); + } + catch (...) { + // Property is not a cell + return; + } +} + +std::vector SheetView::selectedRanges() const +{ + return ui->cells->selectedRanges(); +} + +QModelIndexList SheetView::selectedIndexes() const +{ + return ui->cells->selectionModel()->selectedIndexes(); +} + +QModelIndex SheetView::currentIndex() const +{ + return ui->cells->currentIndex(); +} + +PyObject *SheetView::getPyObject() +{ + Py_Return; +} + +void SheetView::deleteSelf() +{ + Gui::MDIView::deleteSelf(); +} + +#include "moc_SpreadsheetView.cpp" diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetView.h b/src/Mod/Spreadsheet/Gui/SpreadsheetView.h new file mode 100644 index 0000000000..11905493a7 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetView.h @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef SpreadsheetView_H +#define SpreadsheetView_H + +#include +#include +#include "SheetModel.h" +#include + +class QSlider; +class QAction; +class QActionGroup; +class QPopupMenu; +class QToolBar; + +namespace App { +class DocumentObject; +class Property; +} + +namespace Ui { +class Sheet; +} + +class QTableWidgetItem; + +namespace SpreadsheetGui +{ + +class SpreadsheetDelegate; + +class SpreadsheetGuiExport SheetView : public Gui::MDIView +{ + Q_OBJECT + + TYPESYSTEM_HEADER(); + +public: + SheetView(Gui::Document* pcDocument, App::DocumentObject* docObj, QWidget* parent); + ~SheetView(); + + const char *getName(void) const {return "SheetView";} + + bool onMsg(const char* pMsg,const char** ppReturn); + bool onHasMsg(const char* pMsg) const; + + void updateCell(const App::Property * prop); + + Spreadsheet::Sheet * getSheet() { return sheet; } + + std::vector selectedRanges() const; + + QModelIndexList selectedIndexes() const; + + QModelIndex currentIndex() const; + + PyObject *getPyObject(void); + + virtual void deleteSelf(); + +protected Q_SLOTS: + void editingFinished(); + void currentChanged( const QModelIndex & current, const QModelIndex & previous ); + void columnResized(int col, int oldSize, int newSize); + void rowResized(int row, int oldSize, int newSize); + void columnResizeFinished(); + void rowResizeFinished(); +protected: + void setPosition(Spreadsheet::CellAddress address); + void updateContentLine(); + void setCurrentCell(QString str); + void keyPressEvent(QKeyEvent *event); + void resizeColumn(int col, int newSize); + void resizeRow(int col, int newSize); + + Ui::Sheet * ui; + Spreadsheet::Sheet * sheet; + SpreadsheetDelegate * delegate; + SheetModel * model; + boost::BOOST_SIGNALS_NAMESPACE::scoped_connection columnWidthChangedConnection; + boost::BOOST_SIGNALS_NAMESPACE::scoped_connection rowHeightChangedConnection; + boost::BOOST_SIGNALS_NAMESPACE::scoped_connection positionChangedConnection; + + QMap newColumnSizes; + QMap newRowSizes; +}; + +} // namespace SpreadsheetModGui + +#endif // SpreadsheetView_H diff --git a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp new file mode 100644 index 0000000000..5ca86f1fed --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp @@ -0,0 +1,193 @@ +/*************************************************************************** + * Copyright (c) 2011 Jrgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +# include +#endif + +#include "ViewProviderSpreadsheet.h" +#include "SpreadsheetView.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Gui; +using namespace SpreadsheetGui; +using namespace Spreadsheet; + + +PROPERTY_SOURCE(SpreadsheetGui::ViewProviderSheet, Gui::ViewProviderDocumentObject) + +ViewProviderSheet::ViewProviderSheet() + : Gui::ViewProviderDocumentObject() +{ +} + +ViewProviderSheet::~ViewProviderSheet() +{ + if (!view.isNull()) { + Gui::getMainWindow()->removeWindow(view); +// delete view; + } +} + +void ViewProviderSheet::setDisplayMode(const char* ModeName) +{ + ViewProviderDocumentObject::setDisplayMode(ModeName); +} + +std::vector ViewProviderSheet::getDisplayModes(void) const +{ + std::vector StrList; + StrList.push_back("Spreadsheet"); + return StrList; +} + +QIcon ViewProviderSheet::getIcon() const +{ + static const char * const Points_Feature_xpm[] = { + "16 16 3 1", + " c None", + ". c #000000", + "+ c #FFFFFF", + " ", + " ", + "................", + ".++++.++++.++++.", + ".++++.++++.++++.", + "................", + ".++++.++++.++++.", + ".++++.++++.++++.", + "................", + ".++++.++++.++++.", + ".++++.++++.++++.", + "................", + ".++++.++++.++++.", + ".++++.++++.++++.", + "................", + " "}; + QPixmap px(Points_Feature_xpm); + return px; +} + +bool ViewProviderSheet::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default) { + if (!this->view) { + showSpreadsheetView(); + view->viewAll(); + } + Gui::getMainWindow()->setActiveWindow(this->view); + return false; + } + return false; +} + +bool ViewProviderSheet::doubleClicked() +{ + if (!this->view) { + showSpreadsheetView(); + view->viewAll(); + } + Gui::getMainWindow()->setActiveWindow(this->view); + return true; +} + +void ViewProviderSheet::setupContextMenu(QMenu * menu, QObject *receiver, const char *member) +{ + QAction* act; + act = menu->addAction(QObject::tr("Show spreadsheet"), receiver, member); + act->setData(QVariant((int)ViewProvider::Default)); +} + +Sheet *ViewProviderSheet::getSpreadsheetObject() const +{ + return freecad_dynamic_cast(pcObject); +} + +bool ViewProviderSheet::onDelete(const std::vector &) +{ + // If view is closed, delete the object + if (view.isNull()) + return true; + + // View is not closed, delete cell contents instead if it is active + if (Gui::Application::Instance->activeDocument()) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + QModelIndexList selection = sheetView->selectedIndexes(); + + if (selection.size() > 0) { + Gui::Command::openCommand("Clear cell(s)"); + for (QModelIndexList::const_iterator it = selection.begin(); it != selection.end(); ++it) { + std::string address = Spreadsheet::addressToString(CellAddress((*it).row(), (*it).column())); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.clear('%s')", sheet->getNameInDocument(), + address.c_str()); + } + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } + + return false; +} + +SheetView *ViewProviderSheet::showSpreadsheetView() +{ + if (!view){ + Gui::Document* doc = Gui::Application::Instance->getDocument + (this->pcObject->getDocument()); + view = new SheetView(doc, this->pcObject, Gui::getMainWindow()); + view->setWindowIcon(Gui::BitmapFactory().pixmap(":icons/Spreadsheet.svg")); + view->setWindowTitle(QString::fromUtf8(pcObject->Label.getValue()) + QString::fromAscii("[*]")); + Gui::getMainWindow()->addWindow(view); + startEditing(); + } + + return view; +} + +void ViewProviderSheet::updateData(const App::Property* prop) +{ + if (view) + view->updateCell(prop); +} diff --git a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.h b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.h new file mode 100644 index 0000000000..40e32b20a7 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (c) 2011 Jrgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef SPREADSHEET_ViewProviderImagePlane_H +#define SPREADSHEET_ViewProviderImagePlane_H + +#include +#include + +namespace Spreadsheet { +class Sheet; +} + +namespace SpreadsheetGui +{ + +class SheetView; + +class SpreadsheetGuiExport ViewProviderSheet : public Gui::ViewProviderDocumentObject +{ + PROPERTY_HEADER(SpreadsheetGui::ViewProviderSheet); + +public: + /// constructor. + ViewProviderSheet(); + + /// destructor. + ~ViewProviderSheet(); + + void setDisplayMode(const char* ModeName); + virtual bool useNewSelectionModel(void) const {return false;} + std::vector getDisplayModes() const; + + virtual bool doubleClicked(void); + void setupContextMenu(QMenu* menu, QObject* receiver, const char* member); + + Spreadsheet::Sheet* getSpreadsheetObject() const; + + virtual bool onDelete(const std::vector &); + + QIcon getIcon() const; + + virtual bool setEdit(int ModNum); + + virtual bool isShow(void) const { return true; } + +protected: + SheetView* showSpreadsheetView(); + void updateData(const App::Property *prop); +private: + QPointer view; +}; + +} //namespace Spreadsheet + + +#endif // SPREADSHEET_ViewProviderSpreadsheet_H diff --git a/src/Mod/Spreadsheet/Gui/Workbench.cpp b/src/Mod/Spreadsheet/Gui/Workbench.cpp new file mode 100644 index 0000000000..4cbe898359 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Workbench.cpp @@ -0,0 +1,240 @@ +/*************************************************************************** + * Copyright (c) 2005 Werner Mayer * + * Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +#include "Workbench.h" +#include +#include +#include +#include +#include +#include +#include "qtcolorpicker.h" +#include "Mod/Spreadsheet/App/Sheet.h" +#include "Mod/Spreadsheet/App/Range.h" +#include "Mod/Spreadsheet/Gui/SpreadsheetView.h" + +using namespace SpreadsheetGui; +using namespace Spreadsheet; + +#if 0 // needed for Qt's lupdate utility + qApp->translate("Workbench", "Spreadsheet"); +#endif + +/// @namespace ImageGui @class Workbench +TYPESYSTEM_SOURCE(SpreadsheetGui::Workbench, Gui::StdWorkbench) + +Workbench::Workbench() + : Gui::StdWorkbench() + , initialized(false) + , workbenchHelper(new WorkbenchHelper) +{ +} + +Workbench::~Workbench() +{ +} + +void Workbench::activated() +{ + if (!initialized) { + QList bars = Gui::getMainWindow()->findChildren(QString::fromAscii("Spreadsheet")); + + if (bars.size() == 1) { + QToolBar * bar = bars[0]; + QtColorPicker * foregroundColor; + QtColorPicker * backgroundColor; + QPalette palette = Gui::getMainWindow()->palette(); + + QList fgList = Gui::getMainWindow()->findChildren(QString::fromAscii("Spreadsheet_ForegroundColor")); + if (fgList.size() > 0) + foregroundColor = fgList[0]; + else { + foregroundColor = new QtColorPicker(); + foregroundColor->setObjectName(QString::fromAscii("Spreadsheet_ForegroundColor")); + foregroundColor->setStandardColors(); + foregroundColor->setCurrentColor(palette.color(QPalette::Foreground)); + QObject::connect(foregroundColor, SIGNAL(colorSet(QColor)), workbenchHelper.get(), SLOT(setForegroundColor(QColor))); + } + bar->addWidget(foregroundColor); + + QList bgList = Gui::getMainWindow()->findChildren(QString::fromAscii("Spreadsheet_BackgroundColor")); + if (bgList.size() > 0) + backgroundColor = bgList[0]; + else { + backgroundColor = new QtColorPicker(); + backgroundColor->setObjectName(QString::fromAscii("Spreadsheet_BackgroundColor")); + backgroundColor->setStandardColors(); + backgroundColor->setCurrentColor(palette.color(QPalette::Base)); + QObject::connect(backgroundColor, SIGNAL(colorSet(QColor)), workbenchHelper.get(), SLOT(setBackgroundColor(QColor))); + } + bar->addWidget(backgroundColor); + + initialized = false; + } + } +} + +void WorkbenchHelper::setForegroundColor(const QColor & color) +{ + Gui::Document * doc = Gui::Application::Instance->activeDocument(); + + if (doc) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + std::vector ranges = sheetView->selectedRanges(); + + // Execute mergeCells commands + if (ranges.size() > 0) { + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Set foreground color"); + for (; i != ranges.end(); ++i) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setForeground('%s', (%f,%f,%f))", sheet->getNameInDocument(), + i->rangeString().c_str(), color.redF(), color.greenF(), color.blueF()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +void WorkbenchHelper::setBackgroundColor(const QColor & color) +{ + Gui::Document * doc = Gui::Application::Instance->activeDocument(); + + if (doc) { + Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); + SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast(activeWindow); + + if (sheetView) { + Sheet * sheet = sheetView->getSheet(); + std::vector ranges = sheetView->selectedRanges(); + + // Execute mergeCells commands + if (ranges.size() > 0) { + std::vector::const_iterator i = ranges.begin(); + + Gui::Command::openCommand("Set background color"); + for (; i != ranges.end(); ++i) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setBackground('%s', (%f,%f,%f))", sheet->getNameInDocument(), + i->rangeString().c_str(), color.redF(), color.greenF(), color.blueF()); + Gui::Command::commitCommand(); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + } + } +} + +Gui::MenuItem *Workbench::setupMenuBar() const +{ + Gui::MenuItem* root = StdWorkbench::setupMenuBar(); + Gui::MenuItem* item = root->findItem("&Windows"); + + Gui::MenuItem* spreadsheet = new Gui::MenuItem; + root->insertItem(item, spreadsheet); + + // utilities + Gui::MenuItem* alignments = new Gui::MenuItem; + alignments->setCommand("&Alignment"); + *alignments + << "Spreadsheet_AlignLeft" + << "Spreadsheet_AlignCenter" + << "Spreadsheet_AlignRight" + << "Spreadsheet_AlignTop" + << "Spreadsheet_AlignVCenter" + << "Spreadsheet_AlignBottom" + ; + + Gui::MenuItem* styles = new Gui::MenuItem; + styles->setCommand("&Styles"); + *styles + << "Spreadsheet_StyleBold" + << "Spreadsheet_StyleItalic" + << "Spreadsheet_StyleUnderline" + ; + + spreadsheet->setCommand("&Spreadsheet"); + *spreadsheet << "Spreadsheet_CreateSheet" + << "Separator" + << "Spreadsheet_Import" + << "Spreadsheet_Export" + << "Separator" + << "Spreadsheet_MergeCells" + << "Spreadsheet_SplitCell" + << "Separator" + << alignments + << styles + ; + + return root; +} + +Gui::ToolBarItem* Workbench::setupToolBars() const +{ + Gui::ToolBarItem* root = StdWorkbench::setupToolBars(); + Gui::ToolBarItem* part = new Gui::ToolBarItem(root); + part->setCommand("Spreadsheet"); + *part << "Spreadsheet_CreateSheet" + << "Separator" + << "Spreadsheet_Import" + << "Spreadsheet_Export" + << "Separator" + << "Spreadsheet_MergeCells" + << "Spreadsheet_SplitCell" + << "Separator" + << "Spreadsheet_AlignLeft" + << "Spreadsheet_AlignCenter" + << "Spreadsheet_AlignRight" + << "Spreadsheet_AlignTop" + << "Spreadsheet_AlignVCenter" + << "Spreadsheet_AlignBottom" + << "Separator" + << "Spreadsheet_StyleBold" + << "Spreadsheet_StyleItalic" + << "Spreadsheet_StyleUnderline" + << "Separator" + ; + + return root; +} + +Gui::ToolBarItem* Workbench::setupCommandBars() const +{ + Gui::ToolBarItem* root = new Gui::ToolBarItem; + Gui::ToolBarItem* ss = new Gui::ToolBarItem(root); + ss->setCommand("Spreadsheet"); + *ss << "Spreadsheet_Open"; + return root; +} + +#include "moc_Workbench.cpp" diff --git a/src/Mod/Spreadsheet/Gui/Workbench.h b/src/Mod/Spreadsheet/Gui/Workbench.h new file mode 100644 index 0000000000..6d6240b256 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/Workbench.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (c) 2005 Werner Mayer * + * Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef SPREADSHEET_WORKBENCH_H +#define SPREADSHEET_WORKBENCH_H + +#include + +class QtColorPicker; + +namespace SpreadsheetGui { + +/** + * @author Eivind Kvedalen + */ + +class SpreadsheetGuiExport WorkbenchHelper : public QObject +{ + Q_OBJECT +protected Q_SLOTS: + void setForegroundColor(const QColor &color); + void setBackgroundColor(const QColor &color); +}; + +class SpreadsheetGuiExport Workbench : public Gui::StdWorkbench +{ + TYPESYSTEM_HEADER(); + +public: + Workbench(); + virtual ~Workbench(); + void activated(); + +private: + bool initialized; + std::auto_ptr workbenchHelper; + +protected: + Gui::MenuItem *setupMenuBar() const; + Gui::ToolBarItem* setupToolBars() const; + Gui::ToolBarItem* setupCommandBars() const; +}; + +} // namespace SpreadsheetModGui + + +#endif // SPREADSHEET_WORKBENCH_H diff --git a/src/Mod/Spreadsheet/Gui/qtcolorpicker.cpp b/src/Mod/Spreadsheet/Gui/qtcolorpicker.cpp new file mode 100644 index 0000000000..be32e03dcf --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/qtcolorpicker.cpp @@ -0,0 +1,1156 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qtcolorpicker.h" + +/*! \class QtColorPicker + + \brief The QtColorPicker class provides a widget for selecting + colors from a popup color grid. + + Users can invoke the color picker by clicking on it, or by + navigating to it and pressing Space. They can use the mouse or + arrow keys to navigate between colors on the grid, and select a + color by clicking or by pressing Enter or Space. The + colorChanged() signal is emitted whenever the color picker's color + changes. + + The widget also supports negative selection: Users can click and + hold the mouse button on the QtColorPicker widget, then move the + mouse over the color grid and release the mouse button over the + color they wish to select. + + The color grid shows a customized selection of colors. An optional + ellipsis "..." button (signifying "more") can be added at the + bottom of the grid; if the user presses this, a QColorDialog pops + up and lets them choose any color they like. This button is made + available by using setColorDialogEnabled(). + + When a color is selected, the QtColorPicker widget shows the color + and its name. If the name cannot be determined, the translatable + name "Custom" is used. + + The QtColorPicker object is optionally initialized with the number + of columns in the color grid. Colors are then added left to right, + top to bottom using insertColor(). If the number of columns is not + set, QtColorPicker calculates the number of columns and rows that + will make the grid as square as possible. + + \code + DrawWidget::DrawWidget(QWidget *parent, const char *name) + { + QtColorPicker *picker = new QtColorPicker(this); + picker->insertColor(red, "Red")); + picker->insertColor(QColor("green"), "Green")); + picker->insertColor(QColor(0, 0, 255), "Blue")); + picker->insertColor(white); + + connect(colors, SIGNAL(colorChanged(const QColor &)), SLOT(setCurrentColor(const QColor &))); + } + \endcode + + An alternative to adding colors manually is to initialize the grid + with QColorDialog's standard colors using setStandardColors(). + + QtColorPicker also provides a the static function getColor(), + which pops up the grid of standard colors at any given point. + + \img colorpicker1.png + \img colorpicker2.png + + \sa QColorDialog +*/ + +/*! \fn QtColorPicker::colorChanged(const QColor &color) + + This signal is emitted when the QtColorPicker's color is changed. + \a color is the new color. + + To obtain the color's name, use text(). +*/ + +/* + A class that acts very much like a QPushButton. It's not styled, + so we can expect the exact same look, feel and geometry + everywhere. Also, this button always emits clicked on + mouseRelease, even if the mouse button was not pressed inside the + widget. +*/ +class ColorPickerButton : public QFrame +{ + Q_OBJECT + +public: + ColorPickerButton(QWidget *parent); + +signals: + void clicked(); + +protected: + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void keyPressEvent(QKeyEvent *e); + void keyReleaseEvent(QKeyEvent *e); + void paintEvent(QPaintEvent *e); + void focusInEvent(QFocusEvent *e); + void focusOutEvent(QFocusEvent *e); +}; + +/* + This class represents each "color" or item in the color grid. +*/ +class ColorPickerItem : public QFrame +{ + Q_OBJECT + +public: + ColorPickerItem(const QColor &color = Qt::white, const QString &text = QString::null, + QWidget *parent = 0); + ~ColorPickerItem(); + + QColor color() const; + QString text() const; + + void setSelected(bool); + bool isSelected() const; +signals: + void clicked(); + void selected(); + +public slots: + void setColor(const QColor &color, const QString &text = QString()); + +protected: + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void paintEvent(QPaintEvent *e); + +private: + QColor c; + QString t; + bool sel; +}; + +/* + +*/ +class ColorPickerPopup : public QFrame +{ + Q_OBJECT + +public: + ColorPickerPopup(int width, bool withColorDialog, + QWidget *parent = 0); + ~ColorPickerPopup(); + + void insertColor(const QColor &col, const QString &text, int index); + void exec(); + + void setExecFlag(); + + QColor lastSelected() const; + + ColorPickerItem *find(const QColor &col) const; + QColor color(int index) const; + + void setLastSel(const QColor & col); + +signals: + void selected(const QColor &); + void hid(); + +public slots: + void getColorFromDialog(); + +protected slots: + void updateSelected(); + +protected: + void keyPressEvent(QKeyEvent *e); + void showEvent(QShowEvent *e); + void hideEvent(QHideEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + + void regenerateGrid(); + +private: + QMap > widgetAt; + QList items; + QGridLayout *grid; + ColorPickerButton *moreButton; + QEventLoop *eventLoop; + + int lastPos; + int cols; + QColor lastSel; +}; + +/*! + Constructs a QtColorPicker widget. The popup will display a grid + with \a cols columns, or if \a cols is -1, the number of columns + will be calculated automatically. + + If \a enableColorDialog is true, the popup will also have a "More" + button (signified by an ellipsis "...") that presents a + QColorDialog when clicked. + + After constructing a QtColorPicker, call insertColor() to add + individual colors to the popup grid, or call setStandardColors() + to add all the standard colors in one go. + + The \a parent argument is passed to QFrame's constructor. + + \sa QFrame +*/ +QtColorPicker::QtColorPicker(QWidget *parent, + int cols, bool enableColorDialog) + : QPushButton(parent), popup(0), withColorDialog(enableColorDialog) +{ + setFocusPolicy(Qt::StrongFocus); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + setAutoDefault(false); + setAutoFillBackground(true); + setCheckable(true); + + // Set text + setText(tr("Black")); + firstInserted = false; + + // Create and set icon + col = Qt::black; + dirty = true; + + // Create color grid popup and connect to it. + popup = new ColorPickerPopup(cols, withColorDialog, this); + connect(popup, SIGNAL(selected(const QColor &)), + SLOT(setCurrentColor(const QColor &))); + connect(popup, SIGNAL(hid()), SLOT(popupClosed())); + + // Connect this push button's pressed() signal. + connect(this, SIGNAL(toggled(bool)), SLOT(buttonPressed(bool))); +} + +/*! + Destructs the QtColorPicker. +*/ +QtColorPicker::~QtColorPicker() +{ +} + +/*! \internal + + Pops up the color grid, and makes sure the status of + QtColorPicker's button is right. +*/ +void QtColorPicker::buttonPressed(bool toggled) +{ + if (!toggled) + return; + + const QRect desktop = QApplication::desktop()->geometry(); + // Make sure the popup is inside the desktop. + QPoint pos = mapToGlobal(rect().bottomLeft()); + if (pos.x() < desktop.left()) + pos.setX(desktop.left()); + if (pos.y() < desktop.top()) + pos.setY(desktop.top()); + + if ((pos.x() + popup->sizeHint().width()) > desktop.width()) + pos.setX(desktop.width() - popup->sizeHint().width()); + if ((pos.y() + popup->sizeHint().height()) > desktop.bottom()) + pos.setY(desktop.bottom() - popup->sizeHint().height()); + popup->move(pos); + + if (ColorPickerItem *item = popup->find(col)) + item->setSelected(true); + + // Remove focus from this widget, preventing the focus rect + // from showing when the popup is shown. Order an update to + // make sure the focus rect is cleared. + clearFocus(); + update(); + + // Allow keyboard navigation as soon as the popup shows. + popup->setFocus(); + + // Execute the popup. The popup will enter the event loop. + popup->show(); +} + +/*! + \internal +*/ +void QtColorPicker::paintEvent(QPaintEvent *e) +{ + if (dirty) { + int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize); + QPixmap pix(iconSize, iconSize); + pix.fill(palette().button().color()); + + QPainter p(&pix); + + int w = pix.width(); // width of cell in pixels + int h = pix.height(); // height of cell in pixels + p.setPen(QPen(Qt::gray)); + p.setBrush(col); + p.drawRect(2, 2, w - 5, h - 5); + setIcon(QIcon(pix)); + + dirty = false; + } + QPushButton::paintEvent(e); +} + +/*! \internal + + Makes sure the button isn't pressed when the popup hides. +*/ +void QtColorPicker::popupClosed() +{ + setChecked(false); + setFocus(); +} + +/*! + Returns the currently selected color. + + \sa text() +*/ +QColor QtColorPicker::currentColor() const +{ + return col; +} + +/*! + Returns the color at position \a index. +*/ +QColor QtColorPicker::color(int index) const +{ + return popup->color(index); +} + +/*! + Adds the 17 predefined colors from the Qt namespace. + + (The names given to the colors, "Black", "White", "Red", etc., are + all translatable.) + + \sa insertColor() +*/ +void QtColorPicker::setStandardColors() +{ + insertColor(Qt::black, tr("Black")); + insertColor(Qt::white, tr("White")); + insertColor(Qt::red, tr("Red")); + insertColor(Qt::darkRed, tr("Dark red")); + insertColor(Qt::green, tr("Green")); + insertColor(Qt::darkGreen, tr("Dark green")); + insertColor(Qt::blue, tr("Blue")); + insertColor(Qt::darkBlue, tr("Dark blue")); + insertColor(Qt::cyan, tr("Cyan")); + insertColor(Qt::darkCyan, tr("Dark cyan")); + insertColor(Qt::magenta, tr("Magenta")); + insertColor(Qt::darkMagenta, tr("Dark magenta")); + insertColor(Qt::yellow, tr("Yellow")); + insertColor(Qt::darkYellow, tr("Dark yellow")); + insertColor(Qt::gray, tr("Gray")); + insertColor(Qt::darkGray, tr("Dark gray")); + insertColor(Qt::lightGray, tr("Light gray")); +} + + +/*! + Makes \a color current. If \a color is not already in the color grid, it + is inserted with the text "Custom". + + This function emits the colorChanged() signal if the new color is + valid, and different from the old one. +*/ +void QtColorPicker::setCurrentColor(const QColor &color) +{ + if (color.isValid() && col == color) { + emit colorSet(color); + return; + } + if (col == color || !color.isValid()) + return; + + ColorPickerItem *item = popup->find(color); + if (!item) { + insertColor(color, tr("Custom")); + item = popup->find(color); + } + + popup->setLastSel(color); + + col = color; + setText(item->text()); + + dirty = true; + + popup->hide(); + repaint(); + + item->setSelected(true); + emit colorChanged(color); + emit colorSet(color); +} + +/*! + Adds the color \a color with the name \a text to the color grid, + at position \a index. If index is -1, the color is assigned + automatically assigned a position, starting from left to right, + top to bottom. +*/ +void QtColorPicker::insertColor(const QColor &color, const QString &text, int index) +{ + popup->insertColor(color, text, index); + if (!firstInserted) { + col = color; + setText(text); + firstInserted = true; + } +} + +/*! \property QtColorPicker::colorDialog + \brief Whether the ellipsis "..." (more) button is available. + + If this property is set to TRUE, the color grid popup will include + a "More" button (signified by an ellipsis, "...") which pops up a + QColorDialog when clicked. The user will then be able to select + any custom color they like. +*/ +void QtColorPicker::setColorDialogEnabled(bool enabled) +{ + withColorDialog = enabled; +} +bool QtColorPicker::colorDialogEnabled() const +{ + return withColorDialog; +} + +/*! + Pops up a color grid with Qt default colors at \a point, using + global coordinates. If \a allowCustomColors is true, there will + also be a button on the popup that invokes QColorDialog. + + For example: + + \code + void Drawer::mouseReleaseEvent(QMouseEvent *e) + { + if (e->button() & RightButton) { + QColor color = QtColorPicker::getColor(mapToGlobal(e->pos())); + } + } + \endcode +*/ +QColor QtColorPicker::getColor(const QPoint &point, bool allowCustomColors) +{ + ColorPickerPopup popup(-1, allowCustomColors); + + popup.insertColor(Qt::black, tr("Black"), 0); + popup.insertColor(Qt::white, tr("White"), 1); + popup.insertColor(Qt::red, tr("Red"), 2); + popup.insertColor(Qt::darkRed, tr("Dark red"), 3); + popup.insertColor(Qt::green, tr("Green"), 4); + popup.insertColor(Qt::darkGreen, tr("Dark green"), 5); + popup.insertColor(Qt::blue, tr("Blue"), 6); + popup.insertColor(Qt::darkBlue, tr("Dark blue"), 7); + popup.insertColor(Qt::cyan, tr("Cyan"), 8); + popup.insertColor(Qt::darkCyan, tr("Dark cyan"), 9); + popup.insertColor(Qt::magenta, tr("Magenta"), 10); + popup.insertColor(Qt::darkMagenta, tr("Dark magenta"), 11); + popup.insertColor(Qt::yellow, tr("Yellow"), 12); + popup.insertColor(Qt::darkYellow, tr("Dark yellow"), 13); + popup.insertColor(Qt::gray, tr("Gray"), 14); + popup.insertColor(Qt::darkGray, tr("Dark gray"), 15); + popup.insertColor(Qt::lightGray, tr("Light gray"), 16); + + popup.move(point); + popup.exec(); + return popup.lastSelected(); +} + +/*! \internal + + Constructs the popup widget. +*/ +ColorPickerPopup::ColorPickerPopup(int width, bool withColorDialog, + QWidget *parent) + : QFrame(parent, Qt::Popup) +{ + setFrameStyle(QFrame::StyledPanel); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + + setFocusPolicy(Qt::StrongFocus); + setMouseTracking(true); + cols = width; + + if (withColorDialog) { + moreButton = new ColorPickerButton(this); + moreButton->setFixedWidth(24); + moreButton->setFixedHeight(21); + moreButton->setFrameRect(QRect(2, 2, 20, 17)); + connect(moreButton, SIGNAL(clicked()), SLOT(getColorFromDialog())); + } else { + moreButton = 0; + } + + eventLoop = 0; + grid = 0; + regenerateGrid(); +} + + +/*! \internal + + Destructs the popup widget. +*/ +ColorPickerPopup::~ColorPickerPopup() +{ + if (eventLoop) + eventLoop->exit(); +} + +/*! \internal + + If there is an item whole color is equal to \a col, returns a + pointer to this item; otherwise returns 0. +*/ +ColorPickerItem *ColorPickerPopup::find(const QColor &col) const +{ + for (int i = 0; i < items.size(); ++i) { + if (items.at(i) && items.at(i)->color() == col) + return items.at(i); + } + + return 0; +} + +/*! \internal + + Adds \a item to the grid. The items are added from top-left to + bottom-right. +*/ +void ColorPickerPopup::insertColor(const QColor &col, const QString &text, int index) +{ + // Don't add colors that we have already. + ColorPickerItem *existingItem = find(col); + ColorPickerItem *lastSelectedItem = find(lastSelected()); + + if (existingItem) { + if (lastSelectedItem && existingItem != lastSelectedItem) + lastSelectedItem->setSelected(false); + existingItem->setFocus(); + existingItem->setSelected(true); + return; + } + + ColorPickerItem *item = new ColorPickerItem(col, text, this); + + if (lastSelectedItem) { + lastSelectedItem->setSelected(false); + } + else { + item->setSelected(true); + lastSel = col; + } + item->setFocus(); + + connect(item, SIGNAL(selected()), SLOT(updateSelected())); + + if (index == -1) + index = items.count(); + + items.insert((unsigned int)index, item); + regenerateGrid(); + + update(); +} + +/*! \internal + +*/ +QColor ColorPickerPopup::color(int index) const +{ + if (index < 0 || index > (int) items.count() - 1) + return QColor(); + + ColorPickerPopup *that = (ColorPickerPopup *)this; + return that->items.at(index)->color(); +} + +/*! \internal + +*/ +void ColorPickerPopup::exec() +{ + show(); + + QEventLoop e; + eventLoop = &e; + (void) e.exec(); + eventLoop = 0; +} + +/*! \internal + +*/ +void ColorPickerPopup::updateSelected() +{ + QLayoutItem *layoutItem; + int i = 0; + while ((layoutItem = grid->itemAt(i)) != 0) { + QWidget *w = layoutItem->widget(); + if (w && w->inherits("ColorPickerItem")) { + ColorPickerItem *litem = reinterpret_cast(layoutItem->widget()); + if (litem != sender()) + litem->setSelected(false); + } + ++i; + } + + if (sender() && sender()->inherits("ColorPickerItem")) { + ColorPickerItem *item = (ColorPickerItem *)sender(); + lastSel = item->color(); + emit selected(item->color()); + } + + hide(); +} + +/*! \internal + +*/ +void ColorPickerPopup::mouseReleaseEvent(QMouseEvent *e) +{ + if (!rect().contains(e->pos())) + hide(); +} + +/*! \internal + + Controls keyboard navigation and selection on the color grid. +*/ +void ColorPickerPopup::keyPressEvent(QKeyEvent *e) +{ + int curRow = 0; + int curCol = 0; + + bool foundFocus = false; + for (int j = 0; !foundFocus && j < grid->rowCount(); ++j) { + for (int i = 0; !foundFocus && i < grid->columnCount(); ++i) { + if (widgetAt[j][i] && widgetAt[j][i]->hasFocus()) { + curRow = j; + curCol = i; + foundFocus = true; + break; + } + } + } + + switch (e->key()) { + case Qt::Key_Left: + if (curCol > 0) --curCol; + else if (curRow > 0) { --curRow; curCol = grid->columnCount() - 1; } + break; + case Qt::Key_Right: + if (curCol < grid->columnCount() - 1 && widgetAt[curRow][curCol + 1]) ++curCol; + else if (curRow < grid->rowCount() - 1) { ++curRow; curCol = 0; } + break; + case Qt::Key_Up: + if (curRow > 0) --curRow; + else curCol = 0; + break; + case Qt::Key_Down: + if (curRow < grid->rowCount() - 1) { + QWidget *w = widgetAt[curRow + 1][curCol]; + if (w) { + ++curRow; + } else for (int i = 1; i < grid->columnCount(); ++i) { + if (!widgetAt[curRow + 1][i]) { + curCol = i - 1; + ++curRow; + break; + } + } + } + break; + case Qt::Key_Space: + case Qt::Key_Return: + case Qt::Key_Enter: { + QWidget *w = widgetAt[curRow][curCol]; + if (w && w->inherits("ColorPickerItem")) { + ColorPickerItem *wi = reinterpret_cast(w); + wi->setSelected(true); + + QLayoutItem *layoutItem; + int i = 0; + while ((layoutItem = grid->itemAt(i)) != 0) { + QWidget *w = layoutItem->widget(); + if (w && w->inherits("ColorPickerItem")) { + ColorPickerItem *litem + = reinterpret_cast(layoutItem->widget()); + if (litem != wi) + litem->setSelected(false); + } + ++i; + } + + lastSel = wi->color(); + emit selected(wi->color()); + hide(); + } else if (w && w->inherits("QPushButton")) { + ColorPickerItem *wi = reinterpret_cast(w); + wi->setSelected(true); + + QLayoutItem *layoutItem; + int i = 0; + while ((layoutItem = grid->itemAt(i)) != 0) { + QWidget *w = layoutItem->widget(); + if (w && w->inherits("ColorPickerItem")) { + ColorPickerItem *litem + = reinterpret_cast(layoutItem->widget()); + if (litem != wi) + litem->setSelected(false); + } + ++i; + } + + lastSel = wi->color(); + emit selected(wi->color()); + hide(); + } + } + break; + case Qt::Key_Escape: + hide(); + break; + default: + e->ignore(); + break; + } + + widgetAt[curRow][curCol]->setFocus(); +} + +/*! \internal + +*/ +void ColorPickerPopup::hideEvent(QHideEvent *e) +{ + if (eventLoop) { + eventLoop->exit(); + } + + setFocus(); + + emit hid(); + QFrame::hideEvent(e); +} + +/*! \internal + +*/ +QColor ColorPickerPopup::lastSelected() const +{ + return lastSel; +} + +/*! \internal + + Sets focus on the popup to enable keyboard navigation. Draws + focusRect and selection rect. +*/ +void ColorPickerPopup::showEvent(QShowEvent *) +{ + bool foundSelected = false; + for (int i = 0; i < grid->columnCount(); ++i) { + for (int j = 0; j < grid->rowCount(); ++j) { + QWidget *w = widgetAt[j][i]; + if (w && w->inherits("ColorPickerItem")) { + if (((ColorPickerItem *)w)->isSelected()) { + w->setFocus(); + foundSelected = true; + break; + } + } + } + } + + if (!foundSelected) { + if (items.count() == 0) + setFocus(); + else + widgetAt[0][0]->setFocus(); + } +} + +/*! + +*/ +void ColorPickerPopup::regenerateGrid() +{ + widgetAt.clear(); + + int columns = cols; + if (columns == -1) + columns = (int) ceil(sqrt((float) items.count())); + + // When the number of columns grows, the number of rows will + // fall. There's no way to shrink a grid, so we create a new + // one. + if (grid) delete grid; + grid = new QGridLayout(this); + grid->setMargin(1); + grid->setSpacing(0); + + int ccol = 0, crow = 0; + for (int i = 0; i < items.size(); ++i) { + if (items.at(i)) { + widgetAt[crow][ccol] = items.at(i); + grid->addWidget(items.at(i), crow, ccol++); + if (ccol == columns) { + ++crow; + ccol = 0; + } + } + } + + if (moreButton) { + grid->addWidget(moreButton, crow, ccol); + widgetAt[crow][ccol] = moreButton; + } + updateGeometry(); +} + +/*! \internal + + Copies the color dialog's currently selected item and emits + itemSelected(). +*/ +void ColorPickerPopup::getColorFromDialog() +{ + bool ok; + //QRgb rgb = QColorDialog::getRgba(lastSel.rgba(), &ok, parentWidget()); + QColor col = QColorDialog::getColor(lastSel,parentWidget(),0,QColorDialog::ShowAlphaChannel); + if (!col.isValid()) + return; + + //QColor col = QColor::fromRgba(rgb); + insertColor(col, tr("Custom"), -1); + lastSel = col; + emit selected(col); +} + +void ColorPickerPopup::setLastSel(const QColor & col) { lastSel = col; } + +/*! + Constructs a ColorPickerItem whose color is set to \a color, and + whose name is set to \a text. +*/ +ColorPickerItem::ColorPickerItem(const QColor &color, const QString &text, + QWidget *parent) + : QFrame(parent), c(color), t(text), sel(false) +{ + setToolTip(t); + setFixedWidth(24); + setFixedHeight(21); +} + +/*! + Destructs a ColorPickerItem. + */ +ColorPickerItem::~ColorPickerItem() +{ +} + +/*! + Returns the item's color. + + \sa text() +*/ +QColor ColorPickerItem::color() const +{ + return c; +} + +/*! + Returns the item's text. + + \sa color() +*/ +QString ColorPickerItem::text() const +{ + return t; +} + +/*! + +*/ +bool ColorPickerItem::isSelected() const +{ + return sel; +} + +/*! + +*/ +void ColorPickerItem::setSelected(bool selected) +{ + sel = selected; + update(); +} + +/*! + Sets the item's color to \a color, and its name to \a text. +*/ +void ColorPickerItem::setColor(const QColor &color, const QString &text) +{ + c = color; + t = text; + setToolTip(t); + update(); +} + +/*! + +*/ +void ColorPickerItem::mouseMoveEvent(QMouseEvent *) +{ + setFocus(); + update(); +} + +/*! + +*/ +void ColorPickerItem::mouseReleaseEvent(QMouseEvent *) +{ + sel = true; + emit selected(); +} + +/*! + +*/ +void ColorPickerItem::mousePressEvent(QMouseEvent *) +{ + setFocus(); + update(); +} + +/*! + +*/ +void ColorPickerItem::paintEvent(QPaintEvent *) +{ + QPainter p(this); + int w = width(); // width of cell in pixels + int h = height(); // height of cell in pixels + + p.setPen( QPen( Qt::gray, 0, Qt::SolidLine ) ); + + if (sel) + p.drawRect(1, 1, w - 3, h - 3); + + p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) ); + p.drawRect(3, 3, w - 7, h - 7); + p.fillRect(QRect(4, 4, w - 8, h - 8), QBrush(c)); + + if (hasFocus()) + p.drawRect(0, 0, w - 1, h - 1); +} + +/*! + +*/ +ColorPickerButton::ColorPickerButton(QWidget *parent) + : QFrame(parent) +{ + setFrameStyle(StyledPanel); +} + +/*! + +*/ +void ColorPickerButton::mousePressEvent(QMouseEvent *) +{ + setFrameShadow(Sunken); + update(); +} + +/*! + +*/ +void ColorPickerButton::mouseMoveEvent(QMouseEvent *) +{ + setFocus(); + update(); +} + +/*! + +*/ +void ColorPickerButton::mouseReleaseEvent(QMouseEvent *) +{ + setFrameShadow(Raised); + repaint(); + emit clicked(); +} + +/*! + +*/ +void ColorPickerButton::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Up + || e->key() == Qt::Key_Down + || e->key() == Qt::Key_Left + || e->key() == Qt::Key_Right) { + qApp->sendEvent(parent(), e); + } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) { + setFrameShadow(Sunken); + update(); + } else { + QFrame::keyPressEvent(e); + } +} + +/*! + +*/ +void ColorPickerButton::keyReleaseEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Up + || e->key() == Qt::Key_Down + || e->key() == Qt::Key_Left + || e->key() == Qt::Key_Right) { + qApp->sendEvent(parent(), e); + } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) { + setFrameShadow(Raised); + repaint(); + emit clicked(); + } else { + QFrame::keyReleaseEvent(e); + } + +} + +/*! + +*/ +void ColorPickerButton::focusInEvent(QFocusEvent *e) +{ + setFrameShadow(Raised); + update(); + QFrame::focusOutEvent(e); +} + +/*! + +*/ +void ColorPickerButton::focusOutEvent(QFocusEvent *e) +{ + setFrameShadow(Raised); + update(); + QFrame::focusOutEvent(e); +} + +/*! + +*/ +void ColorPickerButton::paintEvent(QPaintEvent *e) +{ + QFrame::paintEvent(e); + + QPainter p(this); + p.fillRect(contentsRect(), palette().button()); + + QRect r = rect(); + + int offset = frameShadow() == Sunken ? 1 : 0; + + QPen pen(palette().buttonText(), 1); + p.setPen(pen); + + p.drawRect(r.center().x() + offset - 4, r.center().y() + offset, 1, 1); + p.drawRect(r.center().x() + offset , r.center().y() + offset, 1, 1); + p.drawRect(r.center().x() + offset + 4, r.center().y() + offset, 1, 1); + if (hasFocus()) { + p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) ); + p.drawRect(0, 0, width() - 1, height() - 1); + } + + p.end(); + +} + +#include "moc_qtcolorpicker.cpp" +#include diff --git a/src/Mod/Spreadsheet/Gui/qtcolorpicker.h b/src/Mod/Spreadsheet/Gui/qtcolorpicker.h new file mode 100644 index 0000000000..7b10da3321 --- /dev/null +++ b/src/Mod/Spreadsheet/Gui/qtcolorpicker.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef QTCOLORPICKER_H +#define QTCOLORPICKER_H +#include +#include +#include + +#include +#include +#include + +#if defined(Q_WS_WIN) +# if !defined(QT_QTCOLORPICKER_EXPORT) && !defined(QT_QTCOLORPICKER_IMPORT) +# define QT_QTCOLORPICKER_EXPORT +# elif defined(QT_QTCOLORPICKER_IMPORT) +# if defined(QT_QTCOLORPICKER_EXPORT) +# undef QT_QTCOLORPICKER_EXPORT +# endif +# define QT_QTCOLORPICKER_EXPORT __declspec(dllimport) +# elif defined(QT_QTCOLORPICKER_EXPORT) +# undef QT_QTCOLORPICKER_EXPORT +# define QT_QTCOLORPICKER_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTCOLORPICKER_EXPORT +#endif + +class ColorPickerPopup; + +class QT_QTCOLORPICKER_EXPORT QtColorPicker : public QPushButton +{ + Q_OBJECT + + Q_PROPERTY(bool colorDialog READ colorDialogEnabled WRITE setColorDialogEnabled) + +public: + QtColorPicker(QWidget *parent = 0, + int columns = -1, bool enableColorDialog = true); + + ~QtColorPicker(); + + void insertColor(const QColor &color, const QString &text = QString::null, int index = -1); + + QColor currentColor() const; + + QColor color(int index) const; + + void setColorDialogEnabled(bool enabled); + bool colorDialogEnabled() const; + + void setStandardColors(); + + static QColor getColor(const QPoint &pos, bool allowCustomColors = true); + +public Q_SLOTS: + void setCurrentColor(const QColor &col); + +Q_SIGNALS: + void colorChanged(const QColor &); + void colorSet(const QColor &); + +protected: + void paintEvent(QPaintEvent *e); + +private Q_SLOTS: + void buttonPressed(bool toggled); + void popupClosed(); + +private: + ColorPickerPopup *popup; + QColor col; + bool withColorDialog; + bool dirty; + bool firstInserted; +}; + +#endif diff --git a/src/Mod/Spreadsheet/Init.py b/src/Mod/Spreadsheet/Init.py index cbf318f756..d19013758a 100644 --- a/src/Mod/Spreadsheet/Init.py +++ b/src/Mod/Spreadsheet/Init.py @@ -1,26 +1,41 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2013 - Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* 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 Library 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 * -#* * -#*************************************************************************** - -# Supported file types -FreeCAD.addImportType("Spreadsheet (*.csv)","Spreadsheet") -FreeCAD.addExportType("Spreadsheet (*.csv)","Spreadsheet") - +# FreeCAD init script of the Spreadsheet module +# (c) 2001 Juergen Riegel + +#*************************************************************************** +#* (c) Juergen Riegel (juergen.riegel@web.de) 2002 * +#* Copyright (c) 2013 - Yorik van Havre * +#* Copyright (c) 2013 Eivind Kvedalen (eivind@kvedalen.name) * +#* * +#* This file is part of the FreeCAD CAx development system. * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* FreeCAD 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 Library General Public * +#* License along with FreeCAD; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#* Juergen Riegel 2002 * +#***************************************************************************/ + + + +# Get the Parameter Group of this module +ParGrp = App.ParamGet("System parameter:Modules").GetGroup("Spreadsheet") + +# Set the needed information +ParGrp.SetString("HelpIndex", "Spreadsheet/Help/index.html") +ParGrp.SetString("WorkBenchName", "Spreadsheet") +ParGrp.SetString("WorkBenchModule", "SpreadsheetWorkbench.py") + + + diff --git a/src/Mod/Spreadsheet/InitGui.py b/src/Mod/Spreadsheet/InitGui.py index 2cb4a4cd70..677d6e59b9 100644 --- a/src/Mod/Spreadsheet/InitGui.py +++ b/src/Mod/Spreadsheet/InitGui.py @@ -1,76 +1,74 @@ +# Spreadsheet gui init module +# (c) 2003 Juergen Riegel +# +# Gathering all the information to start FreeCAD +# This is the second one of three init scripts, the third one +# runs when the gui is up + #*************************************************************************** +#* (c) Juergen Riegel (juergen.riegel@web.de) 2002 * +#* Copyright (c) 2013 Eivind Kvedalen (eivind@kvedalen.name) * #* * -#* Copyright (c) 2013 - Yorik van Havre * +#* This file is part of the FreeCAD CAx development system. * #* * #* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* it under the terms of the GNU General Public License (GPL) * #* as published by the Free Software Foundation; either version 2 of * #* the License, or (at your option) any later version. * #* for detail see the LICENCE text file. * #* * -#* This program is distributed in the hope that it will be useful, * +#* FreeCAD is distributed in the hope that it will be useful, * #* but WITHOUT ANY WARRANTY; without even the implied warranty of * #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * #* GNU Library General Public License for more details. * #* * #* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * +#* License along with FreeCAD; if not, write to the Free Software * #* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * #* USA * #* * -#*************************************************************************** - -class SpreadsheetWorkbench(Workbench): - "Spreadsheet workbench object" - Icon = """ - /* XPM */ - static char * Spreadsheet_xpm[] = { - "16 16 5 1", - " c None", - ". c #151614", - "+ c #575956", - "@ c #969895", - "# c #F7F9F6", - " ", - " ", - " ...............", - ".@##@+########@.", - ".+@@+.@@@@@@@@+.", - "..+++.+++++++++.", - ".@##@+########@.", - ".+@@+.@@@@@@@@+.", - "..+++.+++++++++.", - ".@##@+########@.", - ".+@@+.@@@@@@@@+.", - "..+++.+++++++++.", - ".@##@+########@.", - "..+++.+++++++++.", - " ", - " "};""" - - MenuText = "Spreadsheet" - ToolTip = "Spreadsheet workbench" - - def Initialize(self): - def QT_TRANSLATE_NOOP(scope, text): return text - import Spreadsheet,Spreadsheet_rc - from DraftTools import translate - commands = ["Spreadsheet_Create","Spreadsheet_Controller","Spreadsheet_PropertyController"] - self.appendToolbar(QT_TRANSLATE_NOOP("Workbench","Spreadsheet tools"),commands) - self.appendMenu(str(translate("Spreadsheet","&Spreadsheet")),commands) - FreeCADGui.addIconPath(":/icons") - FreeCADGui.addLanguagePath(":/translations") - Log ('Loading Spreadsheet module... done\n') - - def Activated(self): - Msg("Spreadsheet workbench activated\n") - - def Deactivated(self): - Msg("Spreadsheet workbench deactivated\n") - - def GetClassName(self): - return "Gui::PythonWorkbench" - -FreeCADGui.addWorkbench(SpreadsheetWorkbench) +#* Juergen Riegel 2002 * +#***************************************************************************/ +class SpreadsheetWorkbench ( Workbench ): + "Spreadsheet workbench object" + Icon = """ + /* XPM */ + static char * Spreadsheet_xpm[] = { + "16 16 5 1", + " c None", + ". c #151614", + "+ c #575956", + "@ c #969895", + "# c #F7F9F6", + " ", + " ", + " ...............", + ".@##@+########@.", + ".+@@+.@@@@@@@@+.", + "..+++.+++++++++.", + ".@##@+########@.", + ".+@@+.@@@@@@@@+.", + "..+++.+++++++++.", + ".@##@+########@.", + ".+@@+.@@@@@@@@+.", + "..+++.+++++++++.", + ".@##@+########@.", + "..+++.+++++++++.", + " ", + " "};""" + MenuText = "Spreadsheet" + ToolTip = "Spreadsheet workbench" + + def Initialize(self): + # load the module + import SpreadsheetGui + + def GetClassName(self): + return "SpreadsheetGui::Workbench" + +Gui.addWorkbench(SpreadsheetWorkbench()) + +# Append the open handler +FreeCAD.EndingAdd("Spreadsheet formats (*.csv)","SpreadsheetGui") diff --git a/src/Mod/Spreadsheet/Resources/Spreadsheet.qrc b/src/Mod/Spreadsheet/Resources/Spreadsheet.qrc deleted file mode 100644 index 4ad2c81fd8..0000000000 --- a/src/Mod/Spreadsheet/Resources/Spreadsheet.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - icons/Spreadsheet.svg - icons/SpreadsheetController.svg - icons/SpreadsheetPropertyController.svg - - diff --git a/src/Mod/Spreadsheet/Spreadsheet.py b/src/Mod/Spreadsheet/Spreadsheet.py deleted file mode 100644 index b8aac22eab..0000000000 --- a/src/Mod/Spreadsheet/Spreadsheet.py +++ /dev/null @@ -1,1114 +0,0 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2013 - Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* 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 Library 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 * -#* * -#*************************************************************************** - -import re, math, FreeCAD, FreeCADGui -from PySide import QtCore,QtGui -DEBUG = True # set to True to show debug messages - -if open.__module__ == '__builtin__': - pyopen = open # because we'll redefine open below - -class MathParser: - "A math expression parser" - # code adapted from http://www.nerdparadise.com/tech/python/parsemath/ - def __init__(self, string, vars={}): - self.string = string - self.index = 0 - self.vars = { - 'pi' : math.pi, - 'e' : math.e - } - for var in vars.keys(): - if self.vars.get(var) != None: - raise RuntimeError("Cannot redefine the value of " + var) - self.vars[var] = vars[var] - - def getValue(self): - value = self.parseExpression() - self.skipWhitespace() - if self.hasNext(): - raise SyntaxError( - "Unexpected character found: '" + - self.peek() + - "' at index " + - str(self.index)) - return value - - def peek(self): - return self.string[self.index:self.index + 1] - - def hasNext(self): - return self.index < len(self.string) - - def skipWhitespace(self): - while self.hasNext(): - if self.peek() in ' \t\n\r': - self.index += 1 - else: - return - - def parseExpression(self): - return self.parseAddition() - - def parseAddition(self): - values = [self.parseMultiplication()] - while True: - self.skipWhitespace() - char = self.peek() - if char == '+': - self.index += 1 - values.append(self.parseMultiplication()) - elif char == '-': - self.index += 1 - values.append(-1 * self.parseMultiplication()) - else: - break - return sum(values) - - def parseMultiplication(self): - values = [self.parseParenthesis()] - while True: - self.skipWhitespace() - char = self.peek() - if char == '*': - self.index += 1 - values.append(self.parseParenthesis()) - elif char == '/': - div_index = self.index - self.index += 1 - denominator = self.parseParenthesis() - if denominator == 0: - raise ZeroDivisionError( - "Division by 0 kills baby whales (occured at index " + - str(div_index) + - ")") - values.append(1.0 / denominator) - else: - break - value = 1.0 - for factor in values: - value *= factor - return value - - def parseParenthesis(self): - self.skipWhitespace() - char = self.peek() - if char == '(': - self.index += 1 - value = self.parseExpression() - self.skipWhitespace() - if self.peek() != ')': - raise SyntaxError( - "No closing parenthesis found at character " - + str(self.index)) - self.index += 1 - return value - else: - return self.parseNegative() - - def parseNegative(self): - self.skipWhitespace() - char = self.peek() - if char == '-': - self.index += 1 - return -1 * self.parseParenthesis() - else: - return self.parseValue() - - def parseValue(self): - self.skipWhitespace() - char = self.peek() - if char in '0123456789.': - return self.parseNumber() - else: - return self.parseVariable() - - def parseVariable(self): - self.skipWhitespace() - var = '' - while self.hasNext(): - char = self.peek() - if char.lower() in '_abcdefghijklmnopqrstuvwxyz0123456789': - var += char - self.index += 1 - else: - break - - value = self.vars.get(var, None) - if value == None: - raise ValueError( - "Unrecognized variable: '" + - var + - "'") - return float(value) - - def parseNumber(self): - self.skipWhitespace() - strValue = '' - decimal_found = False - char = '' - - while self.hasNext(): - char = self.peek() - if char == '.': - if decimal_found: - raise SyntaxError( - "Found an extra period in a number at character " + - str(self.index) + - ". Are you European?") - decimal_found = True - strValue += '.' - elif char in '0123456789': - strValue += char - else: - break - self.index += 1 - - if len(strValue) == 0: - if char == '': - raise SyntaxError("Unexpected end found") - else: - raise SyntaxError( - "I was expecting to find a number at character " + - str(self.index) + - " but instead I found a '" + - char + - "'. What's up with that?") - - return float(strValue) - -class Spreadsheet: - """An object representing a spreadsheet. Can be used as a - FreeCAD object or as a standalone python object. - Cells of the spreadsheet can be got/set as arguments, as: - - myspreadsheet = Spreadsheet() - myspreadsheet.a1 = 54 - print(myspreadsheet.a1) - myspreadsheet.a2 = "My text" - myspreadsheet.b1 = "=a1*3" - print(myspreadsheet.b1) - - The cell names are case-insensitive (a1 = A1) - """ - - def __init__(self,obj=None): - if obj: - obj.Proxy = self - obj.addProperty("App::PropertyLinkList","Controllers","Base","Cell controllers of this object") - self.Object = obj.Name - self._cells = {} # this stores cell contents - self._relations = {} # this stores relations - currently not used - self.cols = [] # this stores filled columns - self.rows = [] # this stores filed rows - self.Type = "Spreadsheet" - - def __repr__(self): - return "Spreadsheet object containing " + str(len(self._cells)) + " cells" - - def __setattr__(self, key, value): - if self.isKey(key): - key = key.lower() - if DEBUG: print "Setting key ",key," to value ",value - if (value == "") or (value == None): - # remove cell - if key in self._cells.keys(): - del self._cells[key] - else: - # add cell - self._cells[key] = value - if value: - if self.isFunction(value): - self._updateDependencies(key,value) - c,r = self.splitKey(key) - if not c in self.cols: - self.cols.append(c) - self.cols.sort() - if not r in self.rows: - self.rows.append(r) - self.rows.sort() - self._updateControllers() - else: - self.__dict__.__setitem__(key,value) - - def __getattr__(self, key): - if key.lower() in self._cells: - key = key.lower() - if self.isFunction(self._cells[key]): - try: - e = self.evaluate(key) - except: - print "Spreadsheet: Error evaluating formula" - return None - else: - return e - else: - return self._cells[key] - else: - return self.__dict__.__getitem__(key) - - def __setitem__(self, key, value): - __setattr__(self, key, value) - - def __getitem__(self, key): - return __getattr__(self, key) - - def __getstate__(self): - self._cells["Type"] = self.Type - if hasattr(self,"Object"): - self._cells["Object"] = self.Object - return self._cells - - def __setstate__(self,state): - if state: - self._cells = state - # extracting Type - if "Type" in self._cells.keys(): - self.Type = self._cells["Type"] - del self._cells["Type"] - if "Object" in self._cells.keys(): - self.Object = self._cells["Object"] - del self._cells["Object"] - # updating relation tables - self.rows = [] - self.cols = [] - self._relations = {} - for key in self._cells.keys(): - c,r = self.splitKey(key) - if not r in self.rows: - self.rows.append(r) - self.rows.sort() - if not c in self.cols: - self.cols.append(c) - self.cols.sort() - if self.isFunction(key): - self._updateDependencies(key) - - def _updateDependencies(self,key,value=None): - "search for ancestors in the value and updates the table" - ancestors = [] - if not value: - value = self._cells[key] - for v in re.findall(r"[\w']+",value): - if self.isKey(v): - ancestors.append(v) - for a in ancestors: - if a in self._relations: - if not key in self._relations[a]: - self._relations[a].append(key) - else: - self._relations[a] = [key] - - def _updateControllers(self): - "triggers the property controllers" - if hasattr(self,"Object"): - obj = FreeCAD.ActiveDocument.getObject(self.Object) - if obj: - import Draft - if Draft.getType(obj) == "Spreadsheet": - if hasattr(obj,"Controllers"): - for co in obj.Controllers: - if Draft.getType(co) == "SpreadsheetPropertyController": - co.Proxy.execute(co) - - def execute(self,obj): - pass - - def isFunction(self,key): - "isFunction(cell): returns True if the given cell or value is a function" - if str(key).lower() in self._cells: - key = key.lower() - if str(self._cells[key])[0] == "=": - return True - elif str(key)[0] == "=": - return True - else: - return False - - def isNumeric(self,key): - "isNumeric(cell): returns True if the given cell returns a number" - key = key.lower() - if self.isFunction(key): - res = self.evaluate(key) - else: - res = self._cells[key] - if isinstance(res,float) or isinstance(res,int): - return True - else: - return False - - def isKey(self,value): - "isKey(val): returns True if the given value is a valid cell number" - allowMoreThanOneLetter = False - al = False - nu = False - for v in value: - if not v.isalnum(): - return False - elif not al: - if v.isalpha(): - al = True - else: - return False - else: - if not nu: - # forbidden to set items at row 0 - if v == "0": - return False - if v.isalpha(): - if not allowMoreThanOneLetter: - return False - elif nu: - return False - elif v.isdigit(): - nu = True - if not nu: - return False - return True - - def splitKey(self,key): - "splitKey(cell): splits a key between column and row" - c = '' - r = '' - for ch in key: - if ch.isalpha(): - c += ch - else: - r += ch - return c,r - - def getFunction(self,key): - "getFunction(cell): returns the function contained in the given cell, instead of the value" - key = key.lower() - if key in self._cells: - return self._cells[key] - else: - return None - - def getSize(self): - "getSize(): returns a tuple with number of columns and rows of this spreadsheet" - return (len(self.columns),len(self.rows)) - - def getCells(self,index): - "getCells(index): returns the cells from the given column of row number" - cells = {} - for k in self._cells.keys(): - c,r = self.splitKey(k) - if index in [c,r]: - cells[k] = self._cells[k] - return cells - - def evaluate(self,key): - "evaluate(key): evaluates the given formula" - key = key.lower() - elts = re.split(r'(\W+)',self._cells[key][1:]) - result = "" - for e in elts: - if self.isKey(e): - if self.isFunction(e): - if self.isNumeric(e): - result += str(self.evaluate(e)) - else: - print "Spreadsheet: Error evaluating formula" - return - elif self.isNumeric(e): - result += str(self._cells[e.lower()]) - else: - result += e - if DEBUG: print "Evaluating ",result - try: - p = MathParser(result) - result = p.getValue() - except Exception as (ex): - raise # - #msg = ex.message - #raise Exception(msg) #would discard the type - return result - - def recompute(self,obj): - "Fills the controlled cells and properties" - if obj: - if hasattr(obj,"Controllers"): - import Draft - for co in obj.Controllers: - if Draft.getType(co) == "SpreadsheetController": - co.Proxy.setCells(co,obj) - elif Draft.getType(co) == "SpreadsheetPropertyController": - co.Proxy.compute(co) - - def getControlledCells(self,obj): - "returns a list of cells managed by controllers" - cells = [] - if hasattr(obj,"Controllers"): - import Draft - for co in obj.Controllers: - if Draft.getType(co) == "SpreadsheetController": - cells.extend(co.Proxy.getCells(co,obj)) - return cells - - def getControllingCells(self,obj): - "returns a list of controlling cells managed by controllers" - cells = [] - if hasattr(obj,"Controllers"): - import Draft - for co in obj.Controllers: - if Draft.getType(co) == "SpreadsheetPropertyController": - if co.Cell: - cells.append(co.Cell.lower()) - return cells - - -class ViewProviderSpreadsheet(object): - def __init__(self, vobj): - vobj.Proxy = self - - def getIcon(self): - import Spreadsheet_rc - return ":/icons/Spreadsheet.svg" - - def attach(self,vobj): - self.Object = vobj.Object - - def setEdit(self,vobj,mode=0): - if hasattr(self,"editor"): - pass - else: - self.editor = SpreadsheetView(vobj.Object) - addSpreadsheetView(self.editor) - return True - - def unsetEdit(self,vobj,mode=0): - return False - - def doubleClicked(self,vobj): - self.setEdit(vobj) - - def claimChildren(self): - if hasattr(self,"Object"): - if hasattr(self.Object,"Controllers"): - return self.Object.Controllers - - def __getstate__(self): - return None - - def __setstate__(self,state): - return None - - -class SpreadsheetController: - "A spreadsheet cell controller object" - def __init__(self,obj): - obj.Proxy = self - self.Type = "SpreadsheetController" - obj.addProperty("App::PropertyEnumeration","FilterType","Filter","The type of filter to apply to the scene objects") - obj.addProperty("App::PropertyString","Filter","Filter","The filter to apply to the scene objects") - obj.addProperty("App::PropertyEnumeration","DataType","Data","The type of data to extract from the objects") - obj.addProperty("App::PropertyString","Data","Data","The data to extract from the objects") - obj.addProperty("App::PropertyString","BaseCell","Base","The starting cell of this controller") - obj.addProperty("App::PropertyEnumeration","Direction","Base","The cells direction of this controller") - obj.FilterType = ["Object Type","Object Name"] - obj.DataType = ["Get Property","Count"] - obj.Direction = ["Horizontal","Vertical"] - - def execute(self,obj): - pass - - def __getstate__(self): - return self.Type - - def __setstate__(self,state): - if state: - self.Type = state - - def onChanged(self,obj,prop): - if prop == "DataType": - if obj.DataType == "Count": - obj.setEditorMode('Data',1) - else: - obj.setEditorMode('Data',0) - - def getDataSet(self,obj): - "returns a list of objects to be considered by this controller" - result = [] - if hasattr(obj,"FilterType"): - import Draft - baseset = FreeCAD.ActiveDocument.Objects - if obj.FilterType == "Object Type": - for o in baseset: - if not ("Spreadsheet" in Draft.getType(o)): - t = Draft.getType(o) - if t == "Part": - t = obj.TypeId - if obj.Filter: - if obj.Filter in t: - result.append(o) - else: - result.append(o) - elif obj.FilterType == "Object Name": - for o in baseset: - if not ("Spreadsheet" in Draft.getType(o)): - if obj.Filter: - if obj.Filter in o.Label: - result.append(o) - else: - result.append(o) - return result - - def getCells(self,obj,spreadsheet): - "returns a list of cells controlled by this controller" - cells = [] - if obj.BaseCell: - if obj.DataType == "Count": - return obj.BaseCell - for i in range(len(self.getDataSet(obj))): - # get the correct cell key - c,r = spreadsheet.Proxy.splitKey(obj.BaseCell) - if obj.Direction == "Horizontal": - c = c.lower() - c = "abcdefghijklmnopqrstuvwxyz".index(c) - c += i - c = "abcdefghijklmnopqrstuvwxyz"[c] - else: - r = int(r) + i - cells.append(c+str(r)) - return cells - - def setCells(self,obj,spreadsheet): - "Fills the controlled cells of the given spreadsheet" - if obj.BaseCell: - dataset = self.getDataSet(obj) - if obj.DataType == "Count": - if spreadsheet.Proxy.isKey(obj.BaseCell): - try: - setattr(spreadsheet.Proxy,obj.BaseCell,len(dataset)) - except: - print "Spreadsheet: Error counting objects" - elif obj.Data: - for i in range(len(dataset)): - # get the correct cell key - c,r = spreadsheet.Proxy.splitKey(obj.BaseCell) - if obj.Direction == "Horizontal": - c = c.lower() - c = "abcdefghijklmnopqrstuvwxyz".index(c) - c += i - c = "abcdefghijklmnopqrstuvwxyz"[c] - else: - r = int(r) + i - cell = c+str(r) - if DEBUG: print "auto setting cell ",cell - if spreadsheet.Proxy.isKey(cell): - # get the contents - args = obj.Data.split(".") - value = dataset[i] - for arg in args: - print arg - if hasattr(value,arg): - value = getattr(value,arg) - try: - if isinstance(value,float) or isinstance(value,int): - pass - else: - value = str(value) - value = ''.join([ c for c in value if c not in ('<','>',':')]) - setattr(spreadsheet.Proxy,cell,value) - if DEBUG: print "setting cell ",cell," to value ",value - except: - print "Spreadsheet: Error retrieving property "+obj.Data+" from object "+dataset[i].Name - - -class ViewProviderSpreadsheetController: - "A view provider for the spreadsheet cell controller" - def __init__(self,vobj): - vobj.Proxy = self - - def getIcon(self): - import Spreadsheet_rc - return ":/icons/SpreadsheetController.svg" - - -class SpreadsheetPropertyController: - "A spreadsheet property controller object" - def __init__(self,obj): - obj.Proxy = self - self.Type = "SpreadsheetPropertyController" - obj.addProperty("App::PropertyEnumeration","TargetType","Base","The type of item to control") - obj.addProperty("App::PropertyLink","TargetObject","Base","The object that must be controlled") - obj.addProperty("App::PropertyString","TargetProperty","Base","The property or constraint of the target object to control") - obj.addProperty("App::PropertyString","Cell","Base","The cell that contains the value to apply to the property") - obj.TargetType = ["Property","Constraint"] - - def execute(self,obj): - pass - - def compute(self,obj): - if obj.Cell and obj.TargetObject and obj.TargetProperty and obj.InList: - sp = obj.InList[0] - import Draft - if Draft.getType(sp) == "Spreadsheet": - try: - value = getattr(sp.Proxy,obj.Cell) - except: - if DEBUG: print "No value for cell ",obj.Cell," in spreadsheet." - return - if obj.TargetType == "Property": - b = obj.TargetObject - props = obj.TargetProperty.split(".") - for p in props: - if hasattr(b,p): - if p != props[-1]: - b = getattr(b,p) - else: - return - try: - setattr(b,p,value) - FreeCAD.ActiveDocument.recompute() - if DEBUG: print "setting property ",obj.TargetProperty, " of object ",obj.TargetObject.Name, " to ",value - except: - if DEBUG: print "unable to set property ",obj.TargetProperty, " of object ",obj.TargetObject.Name, " to ",value - else: - if Draft.getType(obj.TargetObject) == "Sketch": - if obj.TargetProperty.isdigit(): - # try setting by constraint id - try: - c = int(obj.TargetProperty) - obj.TargetObject.setDatum(c,float(value)) - FreeCAD.ActiveDocument.recompute() - if DEBUG: print "setting constraint ",obj.TargetProperty, " of object ",obj.TargetObject.Name, " to ",value - except: - if DEBUG: print "unable to set constraint ",obj.TargetProperty, " of object ",obj.TargetObject.Name, " to ",value - else: - # try setting by constraint name - try: - obj.TargetObject.setDatum(obj.TargetProperty,float(value)) - FreeCAD.ActiveDocument.recompute() - if DEBUG: print "setting constraint ",obj.TargetProperty, " of object ",obj.TargetObject.Name, " to ",value - except: - if DEBUG: print "unable to set constraint ",obj.TargetProperty, " of object ",obj.TargetObject.Name, " to ",value - - - def __getstate__(self): - return self.Type - - def __setstate__(self,state): - if state: - self.Type = state - - def onChanged(self,obj,prop): - pass - - -class ViewProviderSpreadsheetPropertyController: - "A view provider for the spreadsheet property controller" - def __init__(self,vobj): - vobj.Proxy = self - - def getIcon(self): - import Spreadsheet_rc - return ":/icons/SpreadsheetPropertyController.svg" - - -class SpreadsheetView(QtGui.QWidget): - "A spreadsheet viewer for FreeCAD" - - def __init__(self,spreadsheet=None): - from DraftTools import translate - QtGui.QWidget.__init__(self) - - self.setWindowTitle(str(translate("Spreadsheet","Spreadsheet"))) - self.setObjectName("Spreadsheet viewer") - self.verticalLayout = QtGui.QVBoxLayout(self) - self.doNotChange = False - - # add editor line - self.horizontalLayout = QtGui.QHBoxLayout() - self.label = QtGui.QLabel(self) - self.label.setMinimumSize(QtCore.QSize(82, 0)) - self.label.setText(translate("Spreadsheet","Cell")+" A1 :") - self.lineEdit = QtGui.QLineEdit(self) - self.applyButton = QtGui.QPushButton(self) - self.applyButton.setText(translate("Spreadsheet","Apply")) - self.applyButton.setIcon(QtGui.QIcon(":/icons/edit_OK.svg")) - self.applyButton.setToolTip(translate("Spreadsheet","Apply the changes to the current cell")) - self.wipeButton = QtGui.QPushButton(self) - self.wipeButton.setText(translate("Spreadsheet","Delete")) - self.wipeButton.setIcon(QtGui.QIcon(":/icons/process-stop.svg")) - self.wipeButton.setToolTip(translate("Spreadsheet","Deletes the contents of the current cell")) - self.computeButton = QtGui.QPushButton(self) - self.computeButton.setText(translate("Spreadsheet","Compute")) - self.computeButton.setIcon(QtGui.QIcon(":/icons/view-refresh.svg")) - self.computeButton.setToolTip(translate("Spreadsheet","Updates the values handled by controllers")) - self.horizontalLayout.addWidget(self.label) - self.horizontalLayout.addWidget(self.lineEdit) - self.horizontalLayout.addWidget(self.applyButton) - self.horizontalLayout.addWidget(self.wipeButton) - self.horizontalLayout.addWidget(self.computeButton) - self.verticalLayout.addLayout(self.horizontalLayout) - - # add table - self.table = QtGui.QTableWidget(30,26,self) - for i in range(26): - ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i] - self.table.setHorizontalHeaderItem(i, QtGui.QTableWidgetItem(ch)) - self.verticalLayout.addWidget(self.table) - self.table.setCurrentCell(0,0) - self.spreadsheet = spreadsheet - self.update() - - QtCore.QObject.connect(self.table, QtCore.SIGNAL("cellChanged(int,int)"), self.changeCell) - QtCore.QObject.connect(self.table, QtCore.SIGNAL("currentCellChanged(int,int,int,int)"), self.setEditLine) - QtCore.QObject.connect(self.lineEdit, QtCore.SIGNAL("returnPressed()"), self.getEditLine) - QtCore.QObject.connect(self.applyButton, QtCore.SIGNAL("clicked()"), self.getEditLine) - QtCore.QObject.connect(self.wipeButton, QtCore.SIGNAL("clicked()"), self.wipeCell) - QtCore.QObject.connect(self.computeButton, QtCore.SIGNAL("clicked()"), self.recompute) - - def closeEvent(self, event): - #if DEBUG: print "Closing spreadsheet view" - if self.spreadsheet: - # before deleting this view, we remove the reference to it in the object - if hasattr(self.spreadsheet,"ViewObject"): - if self.spreadsheet.ViewObject: - if hasattr(self.spreadsheet.ViewObject.Proxy,"editor"): - del self.spreadsheet.ViewObject.Proxy.editor - if FreeCADGui: - if FreeCADGui.ActiveDocument: - FreeCADGui.ActiveDocument.resetEdit() - - def update(self): - "updates the cells with the contents of the spreadsheet" - if self.spreadsheet: - controlled = self.spreadsheet.Proxy.getControlledCells(self.spreadsheet) - controlling = self.spreadsheet.Proxy.getControllingCells(self.spreadsheet) - for cell in self.spreadsheet.Proxy._cells.keys(): - if not cell in ["Type","Object"]: - c,r = self.spreadsheet.Proxy.splitKey(cell) - c = "abcdefghijklmnopqrstuvwxyz".index(c) - r = int(str(r))-1 - content = getattr(self.spreadsheet.Proxy,cell) - if self.spreadsheet.Proxy.isFunction(cell): - self.doNotChange = True - if content == None: - content = "" - if DEBUG: print "Updating ",cell," to ",content - if self.table.item(r,c): - self.table.item(r,c).setText(str(content)) - else: - self.table.setItem(r,c,QtGui.QTableWidgetItem(str(content))) - if cell in controlled: - brush = QtGui.QBrush(QtGui.QColor(255, 0, 0)) - brush.setStyle(QtCore.Qt.Dense6Pattern) - if self.table.item(r,c): - self.table.item(r,c).setBackground(brush) - elif cell in controlling: - brush = QtGui.QBrush(QtGui.QColor(0, 0, 255)) - brush.setStyle(QtCore.Qt.Dense6Pattern) - if self.table.item(r,c): - self.table.item(r,c).setBackground(brush) - else: - brush = QtGui.QBrush() - if self.table.item(r,c): - self.table.item(r,c).setBackground(brush) - - def changeCell(self,r,c,value=None): - "changes the contens of a cell" - if self.doNotChange: - if DEBUG: print "DoNotChange flag is set" - self.doNotChange = False - elif self.spreadsheet: - key = "abcdefghijklmnopqrstuvwxyz"[c]+str(r+1) - if value == None: - value = self.table.item(r,c).text() - if value == "": - if DEBUG: print "Wiping "+key - if self.table.item(r,c): - self.table.item(r,c).setText("") - if key in self.spreadsheet.Proxy._cells.keys(): - del self.spreadsheet.Proxy._cells[key] - else: - if DEBUG: print "Changing "+key+" to "+value - # store the entry as best as possible - try: - v = int(value) - except: - try: - v = float(value) - except: - try: - v = v = str(value) - except: - v = value - setattr(self.spreadsheet.Proxy,key,v) - self.update() - # TODO do not update the whole spreadsheet when only one cell has changed: - # use the _relations table and recursively update only cells based on this one - self.setEditLine(r,c) - - def setEditLine(self,r,c,orr=None,orc=None): - "copies the contents of the active cell to the edit line" - if self.spreadsheet: - c = "abcdefghijklmnopqrstuvwxyz"[c] - r = r+1 - if DEBUG: print "Active cell "+c+str(r) - from DraftTools import translate - self.label.setText(str(translate("Spreadsheet","Cell"))+" "+c.upper()+str(r)+" :") - content = self.spreadsheet.Proxy.getFunction(c+str(r)) - if content == None: - content = "" - self.lineEdit.setText(str(content)) - - def getEditLine(self): - "called when something has been entered in the edit line" - txt = str(self.lineEdit.text()) - if DEBUG: print "Text edited ",txt - r = self.table.currentRow() - c = self.table.currentColumn() - self.changeCell(r,c,txt) - - def wipeCell(self): - if DEBUG: print "Wiping cell" - self.lineEdit.setText("") - self.getEditLine() - - def recompute(self): - if self.spreadsheet: - self.spreadsheet.Proxy.recompute(self.spreadsheet) - self.update() - -class _Command_Spreadsheet_Create: - "the Spreadsheet_Create FreeCAD command" - def GetResources(self): - return {'Pixmap' : 'Spreadsheet', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_Create","Spreadsheet"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_Create","Adds a spreadsheet object to the active document")} - - def Activated(self): - from DraftTools import translate - FreeCAD.ActiveDocument.openTransaction(str(translate("Spreadsheet","Create Spreadsheet"))) - FreeCADGui.doCommand("import Spreadsheet") - FreeCADGui.doCommand("s = Spreadsheet.makeSpreadsheet()") - FreeCADGui.doCommand("FreeCAD.ActiveDocument.recompute()") - FreeCADGui.doCommand("FreeCADGui.ActiveDocument.setEdit(s.Name,0)") - FreeCAD.ActiveDocument.commitTransaction() - - -class _Command_Spreadsheet_Controller: - "the Spreadsheet_Controller FreeCAD command" - def GetResources(self): - return {'Pixmap' : 'SpreadsheetController', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_Controller","Add controller"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_Controller","Adds a cell controller to a selected spreadsheet")} - - def IsActive(self): - if FreeCADGui.Selection.getSelection(): - return True - else: - return False - - def Activated(self): - import Draft - if Draft.getType(FreeCADGui.Selection.getSelection()[0]) == "Spreadsheet": - from DraftTools import translate - n = FreeCADGui.Selection.getSelection()[0].Name - FreeCAD.ActiveDocument.openTransaction(str(translate("Spreadsheet","Add controller"))) - FreeCADGui.doCommand("import Spreadsheet") - FreeCADGui.doCommand("Spreadsheet.makeSpreadsheetController(FreeCAD.ActiveDocument."+n+")") - FreeCAD.ActiveDocument.commitTransaction() - FreeCAD.ActiveDocument.recompute() - - -class _Command_Spreadsheet_PropertyController: - "the Spreadsheet_Controller FreeCAD command" - def GetResources(self): - return {'Pixmap' : 'SpreadsheetPropertyController', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_PropertyController","Add property controller"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_PropertyController","Adds a property controller to a selected spreadsheet")} - - def IsActive(self): - if FreeCADGui.Selection.getSelection(): - return True - else: - return False - - def Activated(self): - import Draft - from DraftTools import translate - sel = FreeCADGui.Selection.getSelection() - if (len(sel) == 1) and Draft.getType(sel[0]) == "Spreadsheet": - n = FreeCADGui.Selection.getSelection()[0].Name - FreeCAD.ActiveDocument.openTransaction(str(translate("Spreadsheet","Add property controller"))) - FreeCADGui.doCommand("import Spreadsheet") - FreeCADGui.doCommand("Spreadsheet.makeSpreadsheetPropertyController(FreeCAD.ActiveDocument."+n+")") - FreeCAD.ActiveDocument.commitTransaction() - FreeCAD.ActiveDocument.recompute() - elif (len(sel) == 2): - if (Draft.getType(sel[0]) == "Spreadsheet") and (Draft.getType(sel[1]) == "SpreadsheetPropertyController"): - s = sel[0].Name - o = sel[1].Name - elif (Draft.getType(sel[1]) == "Spreadsheet") and (Draft.getType(sel[0]) == "SpreadsheetPropertyController"): - s = sel[1].Name - o = sel[0].Name - else: - return - FreeCAD.ActiveDocument.openTransaction(str(translate("Spreadsheet","Add property controller"))) - FreeCADGui.doCommand("import Spreadsheet") - FreeCADGui.doCommand("Spreadsheet.makeSpreadsheetPropertyController(FreeCAD.ActiveDocument."+s+",FreeCAD.ActiveDocument."+o+")") - FreeCAD.ActiveDocument.commitTransaction() - FreeCAD.ActiveDocument.recompute() - - -def makeSpreadsheet(): - "makeSpreadsheet(): adds a spreadsheet object to the active document" - obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Spreadsheet") - Spreadsheet(obj) - if FreeCAD.GuiUp: - ViewProviderSpreadsheet(obj.ViewObject) - return obj - - -def makeSpreadsheetController(spreadsheet,cell=None,direction=None): - """makeSpreadsheetController(spreadsheet,[cell,direction]): adds a - controller to the given spreadsheet. Call can be a starting cell such as "A5", - and direction can be "Horizontal" or "Vertical".""" - obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","CellController") - SpreadsheetController(obj) - if FreeCAD.GuiUp: - ViewProviderSpreadsheetController(obj.ViewObject) - conts = spreadsheet.Controllers - conts.append(obj) - spreadsheet.Controllers = conts - if cell: - obj.BaseCell = cell - if direction: - obj.Direction = direction - return obj - - -def makeSpreadsheetPropertyController(spreadsheet,object=None,prop=None,cell=None): - """makeSpreadsheetPropertyController(spreadsheet,[object,prop,cell]): adds a - property controller, targetting the given object if any, to the given spreadsheet. - You can give a property (such as "Length" or "Proxy.Length") and a cell address - (such as "B6").""" - obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","PropertyController") - SpreadsheetPropertyController(obj) - if FreeCAD.GuiUp: - ViewProviderSpreadsheetPropertyController(obj.ViewObject) - conts = spreadsheet.Controllers - conts.append(obj) - spreadsheet.Controllers = conts - if cell: - obj.Cell = cell - if prop: - obj.Property = prop - return obj - - -def addSpreadsheetView(view): - "addSpreadsheetView(view): adds the given spreadsheet view to the FreeCAD MDI area" - if FreeCAD.GuiUp: - import Spreadsheet_rc - mw = FreeCADGui.getMainWindow() - mdi = mw.findChild(QtGui.QMdiArea) - sw = mdi.addSubWindow(view) - sw.setWindowIcon(QtGui.QIcon(":/icons/Spreadsheet.svg")) - sw.show() - mdi.setActiveSubWindow(sw) - - -def open(filename): - "called when freecad opens a csv file" - import os - docname = os.path.splitext(os.path.basename(filename))[0] - doc = FreeCAD.newDocument(docname) - FreeCAD.ActiveDocument = doc - read(filename) - doc.recompute() - return doc - - -def insert(filename,docname): - "called when freecad wants to import a csv file" - try: - doc = FreeCAD.getDocument(docname) - except NameError: - doc = FreeCAD.newDocument(docname) - FreeCAD.ActiveDocument = doc - read(filename) - doc.recompute() - return doc - - -def read(filename): - "creates a spreadsheet with the contents of a csv file" - sp = makeSpreadsheet() - import csv - with pyopen(filename, 'rb') as csvfile: - csvfile = csv.reader(csvfile) - rn = 1 - for row in csvfile: - cn = 0 - for c in row[:26]: - cl = "abcdefghijklmnopqrstuvwxyz"[cn] - #print "setting ",cl+str(rn)," ",c - try: - c = int(c) - except ValueError: - try: - c = float(c) - except ValueError: - c = str(c) - setattr(sp.Proxy,cl+str(rn),c) - cn += 1 - rn += 1 - print "successfully imported ",filename - - -def export(exportList,filename): - "called when freecad exports a csv file" - import csv, Draft - if not exportList: - print "Spreadsheet: Nothing to export" - return - obj = exportList[0] - if Draft.getType(obj) != "Spreadsheet": - print "Spreadhseet: The selected object is not a spreadsheet" - return - if not obj.Proxy._cells: - print "Spreadsheet: The selected spreadsheet contains no cell" - return - numcols = ("abcdefghijklmnopqrstuvwxyz".index(str(obj.Proxy.cols[-1])))+1 - numrows = int(obj.Proxy.rows[-1]) - with pyopen(filename, 'wb') as csvfile: - csvfile = csv.writer(csvfile) - for i in range(numrows): - r = [] - for j in range(numcols): - key = "abcdefghijklmnopqrstuvwxyz"[j]+str(i+1) - if key in obj.Proxy._cells.keys(): - r.append(str(obj.Proxy.getFunction(key))) - else: - r.append("") - csvfile.writerow(r) - print "successfully exported ",filename - - -FreeCADGui.addCommand('Spreadsheet_Create',_Command_Spreadsheet_Create()) -FreeCADGui.addCommand('Spreadsheet_Controller',_Command_Spreadsheet_Controller()) -FreeCADGui.addCommand('Spreadsheet_PropertyController',_Command_Spreadsheet_PropertyController()) diff --git a/src/Mod/Spreadsheet/spreadsheet.dox b/src/Mod/Spreadsheet/spreadsheet.dox new file mode 100644 index 0000000000..118275a0fa --- /dev/null +++ b/src/Mod/Spreadsheet/spreadsheet.dox @@ -0,0 +1,3 @@ +/** \defgroup IMAGE Image + * \ingroup WORKBENCHES */ +