/***************************************************************************
 *   Copyright (C) 2005-2007 by Niklas Knutsson                            *
 *   nq@altern.org                                                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <kdialog.h>
#include <tdelocale.h>

#include "kqalculate.h"
#include "qalculateinsertfunctiondialog.h"
#include "qalculate_tde_utils.h"
#include "preferences.h"
#include "qalculatepreferencesdialog.h"
#include "qalculateimportcsvdialog.h"
#include "qalculateexportcsvdialog.h"
#include "qalculateexpressionedit.h"
#include "qalculateprecisiondialog.h"
#include "qalculatedecimalsdialog.h"
#include "qalculateeditvariabledialog.h"
#include "qalculateeditmatrixvectordialog.h"
#include "qalculateeditunitdialog.h"
#include "qalculateeditfunctiondialog.h"
#include "qalculateeditdatasetdialog.h"
#include "qalculateeditunknownvariabledialog.h"
#include "qalculatevariablesdialog.h"
#include "qalculatefunctionsdialog.h"
#include "qalculateunitsdialog.h"
#include "qalculatedatasetsdialog.h"
#include "qalculateconvertunitsdialog.h"
#include "qalculateconvertnumberbasesdialog.h"
#include "qalculateperiodictabledialog.h"
#include "qalculateplotdialog.h"
#include "qalculatesetbasedialog.h"
#include "qalculateinsertmatrixvectordialog.h"

#include <twin.h>
#include <tdeglobalsettings.h>
#include <kuniqueapplication.h>
#include <kstringhandler.h>
#include <tqtable.h>
#include <kseparator.h>
#include <kiconloader.h>
#include <tqframe.h>
#include <tqvariant.h>
#include <tqtooltip.h>
#include <tqwhatsthis.h>
#include <tqclipboard.h>
#include <tqstylesheet.h>
#include <kcompletion.h>
#include <klineedit.h>
#include <tqlabel.h>
#include <tdemessagebox.h>
#include <tqpixmap.h>
#include <tqpicture.h>
#include <tqpainter.h>
#include <tqfontmetrics.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <math.h>
#include <dirent.h>
#include <pthread.h>
#include <vector>
#include <string>
#include <stack>
#include <tqsimplerichtext.h>
#include <tqstatusbar.h>
#include <tqwidgetstack.h>
#include <ktextbrowser.h>
#include <kpushbutton.h>
#include "qalculateresultdisplay.h"
#include <tqbitmap.h>
#include <tqscrollview.h>
#include <tqobject.h>
#include <tdeapplication.h>
#include <tdeaction.h>
#include <tqspinbox.h>
#include <kprogress.h>
#include <tdepopupmenu.h>
#include <tdemenubar.h>
#include <tqlayout.h>
#include <tqtimer.h>
#include <tdecompletionbox.h>
#include <tqstringlist.h>
#include <tqcombobox.h>
#include <ksystemtray.h>
#include <tdeactionclasses.h>
#include <tdeaccelmanager.h>
#include <tqbuttongroup.h>
#include <tqvbuttongroup.h>
#include <tqradiobutton.h>
#include <tqgrid.h>
#include <tdefiledialog.h>
#include <tqimage.h>
#include <tdeaccel.h>
#include <tdeio/netaccess.h>
#include <kinputdialog.h>
#include <tqstyle.h>
#include <kglobalaccel.h>
#include <kkeydialog.h>
#include <kkeybutton.h>
#include <kcombobox.h>

MathStructure *mstruct, *matrix_mstruct, *parsed_mstruct, *parsed_tostruct;
TQString result_text, result_history_text, parsed_text;
TQWidget *expressionWidget, *resultWidget, *statusWidget_l;
TQWidget *topWidget;
KQalculate *mainWin = 0;
bool prev_result_approx;
extern bool close_to_systray;
extern bool display_expression_status;
extern TQColor status_error_color;
extern TQColor status_warning_color;
extern int use_icon_buttons;
extern bool enable_expression_completion;

extern TQString initial_history;
extern tree_struct function_cats, unit_cats, variable_cats;
extern std::vector<void*> ia_units, ia_variables, ia_functions;
extern std::vector<MathFunction*> recent_functions;
extern std::vector<Variable*> recent_variables;
extern std::vector<Unit*> recent_units;
std::vector<MathStructure> result_parts;

KnownVariable *vans[5];
int vans_id_start[5];
int vans_id_end[5];

extern PrintOptions printops;
extern EvaluationOptions evalops;
extern bool rpn_mode, rpn_keypad_only;
extern bool save_mode_on_exit, save_defs_on_exit;

extern bool canplot;

extern bool use_custom_result_font, use_custom_expression_font, use_custom_status_font;
extern TQString custom_result_font, custom_expression_font, custom_status_font;

extern TQTimer *error_timer;

extern TQStringList expression_history;

bool expression_has_changed, expression_has_changed2, had_errors_before, had_warnings_before, block_result_update;

FILE *view_pipe_r, *view_pipe_w, *command_pipe_r, *command_pipe_w;
pthread_t view_thread, command_thread;
pthread_attr_t view_thread_attr, command_thread_attr;
bool b_busy, command_thread_started;
int saved_divisionline_height = 0;
uint initial_result_index = 0;

extern bool show_keypad, show_history, show_stack;

extern std::vector<mode_struct> modes;

extern TQValueVector<TQString> inhistory;
extern TQValueVector<int> inhistory_type;
extern TQValueVector<int> inhistory_id;
extern int inhistory_current_id;
int initial_inhistory_index = 0;

const MathStructure *KQalculate::getResultPart(int i) {
	if(i < 1 || (size_t) i > result_parts.size()) return NULL;
	return &result_parts[(size_t) i - 1];
}

ModeObject::ModeObject(int mode) : i_mode(mode) {}
void ModeObject::loadMode() {
	mainWin->loadMode(i_mode);
}

KQalculate::KQalculate(KUniqueApplication *parent, const char* name, WFlags fl) : TDEMainWindow(0, name, fl) {

	if(!name) setName("kqalculate");

	m_parent = parent;

	vans_id_start[0] = -1;
	vans_id_end[0] = -1;
	vans_id_start[1] = -1;
	vans_id_end[1] = -1;
	vans_id_start[2] = -1;
	vans_id_end[2] = -1;
	vans_id_start[3] = -1;
	vans_id_end[3] = -1;
	vans_id_start[4] = -1;
	vans_id_end[4] = -1;
	
	TQStyleSheet::setDefaultSheet(new QalculateStyleSheet());

	insert_matrix_dialog = NULL;
	preferences_dialog = NULL;
	precisionDialog = NULL;
	decimalsDialog = NULL;
	variable_edit_dialog = NULL;
	store_dialog = NULL;
	matrix_edit_dialog = NULL;
	import_csv_dialog = NULL;
	export_csv_dialog = NULL;
	unit_edit_dialog = NULL;
	function_edit_dialog = NULL;
	dataset_edit_dialog = NULL;
	unknown_edit_dialog = NULL;
	variables_dialog = NULL;
	functions_dialog = NULL;
	units_dialog = NULL;
	datasets_dialog = NULL;
	convert_to_unit_expression_dialog = NULL;
	convert_number_bases_dialog = NULL;
	periodic_table_dialog = NULL;
	plot_dialog = NULL;
	set_base_dialog = NULL;
	
	prev_result_approx = false;
	expression_has_changed = false;
	expression_has_changed2 = false;
	had_errors_before = false;
	had_warnings_before = false;
	block_result_update = false;
	
	history_height = 0;
	
	trayicon = NULL; 
	ActionHideSystemTrayIcon = new TDEAction(i18n("Remove from System Tray"), "hidesystemtrayicon", 0, this, TQ_SLOT(hideSystemTrayIcon()), actionCollection(), "hide_system_tray_icon");
	ActionHide = new TDEAction(i18n("Hide"), "hide", 0, this, TQ_SLOT(hide()), actionCollection(), "hide");
	showSystemTrayIcon(close_to_systray);

	setCentralWidget(new TQWidget(this));
	TQVBoxLayout *mainLayout = new TQVBoxLayout(centralWidget(), 11, 6);
	mainLayout->setResizeMode(TQLayout::Minimum);

	TQHBoxLayout *topLayout = new TQHBoxLayout(0, 0, 6);

	bool use_button_pixmaps = false;
	if(use_icon_buttons > 0) {
		use_button_pixmaps = true;
	} else if(use_icon_buttons < 0) {
		TDEConfig config("kdeglobals", true, false);	
		config.setGroup("KDE");	
		use_button_pixmaps = config.readBoolEntry("ShowIconsOnPushButtons", false);
	}

	if(use_button_pixmaps) leftButtonsLayout = new TQVBoxLayout(0, 0, 3);
	else leftButtonsLayout = new TQVBoxLayout(0, 0, 6);
	if(use_button_pixmaps) executeButton = new QalculateButton(TDEApplication::kApplication()->iconLoader()->loadIconSet("application-x-executable", TDEIcon::Small, TDEIcon::SizeSmallMedium), "", centralWidget());
	else if(rpn_mode) executeButton = new QalculateButton(i18n("Enter"), centralWidget());
	else executeButton = new QalculateButton(i18n("="), centralWidget());
	executeButton->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed, false);
	if(rpn_mode) TQToolTip::add(executeButton, i18n("Calculate expression and add to stack"));
	else TQToolTip::add(executeButton, i18n("Calculate expression"));
	leftButtonsLayout->addWidget(executeButton);
	leftButtonsSeparator = new KSeparator(TQt::Horizontal, centralWidget());
	leftButtonsLayout->addWidget(leftButtonsSeparator);
	if(use_button_pixmaps) leftButtonsSeparator->hide();
	if(use_button_pixmaps) storeButton = new QalculateButton(TDEApplication::kApplication()->iconLoader()->loadIconSet("document-save-as", TDEIcon::Small, TDEIcon::SizeSmallMedium), "", centralWidget());
	else storeButton = new QalculateButton(i18n("Store"), centralWidget());
	storeButton->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed, false);
	TQToolTip::add(storeButton, i18n("Store result as variable"));
	leftButtonsLayout->addWidget(storeButton);
	if(use_button_pixmaps) convertButton = new QalculateButton(TDEApplication::kApplication()->iconLoader()->loadIconSet("qalculate_convert", TDEIcon::Small, TDEIcon::SizeSmallMedium), "", centralWidget());
	else convertButton = new QalculateButton(i18n("Convert"), centralWidget());
	convertButton->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed, false);
	TQToolTip::add(convertButton, i18n("Convert units in result"));
	leftButtonsLayout->addWidget(convertButton);
	leftButtonsLayout->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Minimum, TQSizePolicy::Minimum));
	
	TQVBoxLayout *expressionLayout = new TQVBoxLayout(0, 0, 0);
	expressionEdit = new QalculateExpressionEdit(true, centralWidget());
	expressionLayout->addWidget(expressionEdit);
	expressionEdit->setFocus();
	expressionEdit->expression_history = expression_history;
	if(!enable_expression_completion) expressionEdit->disableCompletion();
	TQToolTip::add(expressionEdit, i18n("Enter expression here"));
	TQHBoxLayout *statusLayout = new TQHBoxLayout(0, 0, 6);
	statusLabel_l = new QalculateParseLabel(centralWidget());
	statusLabel_l->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
	statusLabel_l->setLineWidth(0);
	statusLabel_l->setMargin(0);
	statusLabel_l->setAlignment(int(TQLabel::AlignTop | TQLabel::AlignLeft));
	if(!display_expression_status) statusLabel_l->hide();
	statusLayout->addWidget(statusLabel_l);
	statusLabel_r = new TQLabel(i18n("status"), centralWidget());
	statusLabel_r->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum, false);
	statusLabel_r->setLineWidth(0);
	statusLabel_r->setMargin(0);
	statusLabel_r->setTextFormat(TQt::RichText);
	statusLabel_r->setAlignment(int(TQLabel::AlignTop | TQLabel::AlignRight));	
	statusLayout->addWidget(statusLabel_r);
	expressionLayout->addLayout(statusLayout);
	resultLabel = new QalculateResultDisplay(centralWidget());
	resultLabel->setRightMargin(10);
	expressionLayout->addWidget(resultLabel);
	
	topLayout->addLayout(expressionLayout);
	topLayout->addLayout(leftButtonsLayout);
	mainLayout->addLayout(topLayout);
	
	resultLabel->setWordWrap(TQTextEdit::WidgetWidth);
	resultLabel->setMargin(0);

	bottomLine = new KSeparator(TQt::Horizontal, centralWidget());
	mainLayout->addWidget(bottomLine);

	mainStack = new TQWidgetStack(centralWidget());
	mainStack->setEnabled(true);
	mainStack->setSizePolicy(TQSizePolicy((TQSizePolicy::SizeType) 5, (TQSizePolicy::SizeType) 7, 0, 0, mainStack->sizePolicy().hasHeightForWidth()));

	keypadPage = new TQWidget(mainStack);
	TQVBoxLayout *keypadPageLayout = new TQVBoxLayout(keypadPage, 0, 12);
	
	keypadPageLayout->addWidget(new KSeparator(TQt::Horizontal, keypadPage));

	TQHBoxLayout *keypadTopLayout = new TQHBoxLayout(0, 0, 6);
	kpExact = new QalculateButton(i18n("Exact"), keypadPage);
	TQToolTip::add(kpExact, i18n("Toggle exact mode"));
	kpExact->setToggleButton(true);
	keypadTopLayout->addWidget(kpExact);
	kpFraction = new QalculateButton(i18n("Fraction"), keypadPage);
	TQToolTip::add(kpFraction, i18n("Toggle fractional display"));
	kpFraction->setToggleButton(true);
	keypadTopLayout->addWidget(kpFraction);
	kpNumericCombo = new TQComboBox(true, keypadPage);
	TQToolTip::add(kpNumericCombo, i18n("Numerical display"));
	kpNumericCombo->setEditable(false);
	keypadTopLayout->addWidget(kpNumericCombo);
	kpNumericCombo->insertItem(i18n("Normal"));
	kpNumericCombo->insertItem(i18n("Engineering"));
	kpNumericCombo->insertItem(i18n("Scientific"));
	kpNumericCombo->insertItem(i18n("Pure"));
	kpNumericCombo->insertItem(i18n("Simple"));
	kpBaseCombo = new TQComboBox(true, keypadPage);
	TQToolTip::add(kpBaseCombo, i18n("Base in result"));
	kpBaseCombo->setEditable(false);
	keypadTopLayout->addWidget(kpBaseCombo);
	keypadPageLayout->addLayout(keypadTopLayout);
	kpBaseCombo->insertItem(i18n("Binary"));
	kpBaseCombo->insertItem(i18n("Octal"));
	kpBaseCombo->insertItem(i18n("Decimal"));
	kpBaseCombo->insertItem(i18n("Hexadecimal"));
	kpBaseCombo->insertItem(i18n("Sexagesimal"));
	kpBaseCombo->insertItem(i18n("Time Format"));
	kpBaseCombo->insertItem(i18n("Roman"));
	kpBaseCombo->insertItem(i18n("Other..."));

	TQHBoxLayout *keypadBottomLayout = new TQHBoxLayout(0, 0, 24);

	TQGridLayout *keypadFunctionsLayout = new TQGridLayout(0, 5, 3, 0, 6);
	
	functionsButton = new QalculateButton(i18n("f(x)"), keypadPage);
	TQFont fb_font(functionsButton->font());
	fb_font.setItalic(true);
	functionsButton->setFont(fb_font);
	TQToolTip::add(functionsButton, i18n("Open functions manager"));
	keypadFunctionsLayout->addWidget(functionsButton, 0, 0);
	kpSqrt = new QalculateButton(i18n("sqrt"), keypadPage);
	TQToolTip::add(kpSqrt, i18n("Square root"));
	keypadFunctionsLayout->addWidget(kpSqrt, 1, 0);
	kpRaise = new QalculateButton(keypadPage);
	kpRaise->setMarkup(i18n("x<sup>y</sup>"));
	TQToolTip::add(kpRaise, i18n("Raise (Ctrl+*)"));
	keypadFunctionsLayout->addWidget(kpRaise, 0, 1);
	kpSquare = new QalculateButton(keypadPage);
	kpSquare->setMarkup(i18n("x<sup>2</sup>"));
	TQToolTip::add(kpSquare, i18n("Square"));
	keypadFunctionsLayout->addWidget(kpSquare, 0, 2);
	kpLog = new QalculateButton(i18n("log"), keypadPage);
	TQToolTip::add(kpLog, i18n("Base-10 logarithm"));
	keypadFunctionsLayout->addWidget(kpLog, 1, 1);
	kpLn = new QalculateButton(i18n("ln"), keypadPage);
	TQToolTip::add(kpLn, i18n("Natural logarithm"));
	keypadFunctionsLayout->addWidget(kpLn, 1, 2);
	kpFactorial = new QalculateButton(i18n("x!"), keypadPage);
	TQToolTip::add(kpFactorial, i18n("Factorial"));
	keypadFunctionsLayout->addWidget(kpFactorial, 2, 0);
	kpCos = new QalculateButton(i18n("cos"), keypadPage);
	TQToolTip::add(kpCos, i18n("Cosine"));
	keypadFunctionsLayout->addWidget(kpCos, 2, 1);
	kpTan = new QalculateButton(i18n("tan"), keypadPage);
	TQToolTip::add(kpTan, i18n("Tangent"));
	keypadFunctionsLayout->addWidget(kpTan, 2, 2);
	kpHyp = new QalculateButton(i18n("hyp"), keypadPage);
	TQToolTip::add(kpHyp, i18n("Toggle hyperbolic functions"));
	kpHyp->setToggleButton(true);
	keypadFunctionsLayout->addWidget(kpHyp, 3, 0);
	kpInv = new QalculateButton(i18n("inv"), keypadPage);
	TQToolTip::add(kpInv, i18n("Toggle inverse functions"));
	kpInv->setToggleButton(true);
	keypadFunctionsLayout->addWidget(kpInv, 3, 1);
	kpSin = new QalculateButton(i18n("sin"), keypadPage);
	TQToolTip::add(kpSin, i18n("Sine"));
	keypadFunctionsLayout->addWidget(kpSin, 3, 2);
	TQHBoxLayout *keypadAngleLayout = new TQHBoxLayout(0, 0, 6);
	kpAngleGroup = new TQButtonGroup();
	kpAngleGroup->setExclusive(true);
	kpDegreesButton = new TQRadioButton(i18n("Deg"), keypadPage);
	TQToolTip::add(kpDegreesButton, i18n("Angle Unit: Degrees"));
	kpAngleGroup->insert(kpDegreesButton, 0);
	keypadAngleLayout->addWidget(kpDegreesButton);
	kpRadiansButton = new TQRadioButton(i18n("Rad"), keypadPage);
	TQToolTip::add(kpRadiansButton, i18n("Angle Unit: Radians"));
	kpAngleGroup->insert(kpRadiansButton, 1);
	keypadAngleLayout->addWidget(kpRadiansButton);
	kpGradiansButton = new TQRadioButton(i18n("Gra"), keypadPage);
	TQToolTip::add(kpGradiansButton, i18n("Angle Unit: Gradians"));
	kpAngleGroup->insert(kpGradiansButton, 2);
	keypadAngleLayout->addWidget(kpGradiansButton);
	kpNoAngleUnitButton = new TQRadioButton(i18n("None"), keypadPage);
	kpAngleGroup->insert(kpNoAngleUnitButton, 3);
	keypadAngleLayout->addWidget(kpNoAngleUnitButton);
	kpNoAngleUnitButton->hide();
	keypadAngleLayout->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Expanding, TQSizePolicy::Minimum));
	keypadFunctionsLayout->addMultiCellLayout(keypadAngleLayout, 4, 4, 0, 2);
	
	TDEAcceleratorManager::setNoAccel(kpDegreesButton);
	TDEAcceleratorManager::setNoAccel(kpRadiansButton);
	TDEAcceleratorManager::setNoAccel(kpGradiansButton);
	TDEAcceleratorManager::setNoAccel(kpNoAngleUnitButton);
	
	keypadBottomLayout->addLayout(keypadFunctionsLayout);
	
	TQGridLayout *keypadBasicsLayout = new TQGridLayout(0, 1, 1, 0, 6);
	kp7 = new QalculateButton(i18n("7"), keypadPage);
	keypadBasicsLayout->addWidget(kp7, 0, 0);
	kp8 = new QalculateButton(i18n("8"), keypadPage);
	keypadBasicsLayout->addWidget(kp8, 0, 1);
	kp9 = new QalculateButton(i18n("9"), keypadPage);
	keypadBasicsLayout->addWidget(kp9, 0, 2);
	kp4 = new QalculateButton(i18n("4"), keypadPage);
	keypadBasicsLayout->addWidget(kp4, 1, 0);
	kp5 = new QalculateButton(i18n("5"), keypadPage);
	keypadBasicsLayout->addWidget(kp5, 1, 1);
	kp6 = new QalculateButton(i18n("6"), keypadPage);
	keypadBasicsLayout->addWidget(kp6, 1, 2);
	kp1 = new QalculateButton(i18n("1"), keypadPage);
	keypadBasicsLayout->addWidget(kp1, 2, 0);
	kp2 = new QalculateButton(i18n("2"), keypadPage);
	keypadBasicsLayout->addWidget(kp2, 2, 1);
	kp3 = new QalculateButton(i18n("3"), keypadPage);
	keypadBasicsLayout->addWidget(kp3, 2, 2);
	kp0 = new QalculateButton(i18n("0"), keypadPage);
	keypadBasicsLayout->addWidget(kp0, 3, 0);
	kpDot = new QalculateButton(".", keypadPage);
	TQToolTip::add(kpDot, i18n("Decimal point"));
	keypadBasicsLayout->addWidget(kpDot, 3, 1);
	kpExp = new QalculateButton(i18n("EXP"), keypadPage);
	TQToolTip::add(kpExp, i18n("10^x (Ctrl+Shift+E)"));
	keypadBasicsLayout->addWidget(kpExp, 3, 2);
	
	kpDel = new QalculateButton(i18n("Del"), keypadPage);
	TQToolTip::add(kpDel, i18n("Delete"));
	keypadBasicsLayout->addWidget(kpDel, 0, 3);
	kpClear = new QalculateButton(i18n("AC"), keypadPage);
	TQToolTip::add(kpClear, i18n("Clear"));
	keypadBasicsLayout->addWidget(kpClear, 0, 4);
	kpTimes = new QalculateButton("*", keypadPage);
	TQToolTip::add(kpTimes, i18n("Multiply"));
	keypadBasicsLayout->addWidget(kpTimes, 1, 3);
	kpDivision = new QalculateButton("/", keypadPage);
	TQToolTip::add(kpDivision, i18n("Divide"));
	keypadBasicsLayout->addWidget(kpDivision, 1, 4);
	kpPlus = new QalculateButton("+", keypadPage);
	TQToolTip::add(kpPlus, i18n("Add"));
	keypadBasicsLayout->addWidget(kpPlus, 2, 3);
	kpMinus = new QalculateButton("-", keypadPage);
	TQToolTip::add(kpMinus, i18n("Subtract"));
	keypadBasicsLayout->addWidget(kpMinus, 2, 4);
	kpAns = new QalculateButton(i18n("Ans"), keypadPage);
	TQToolTip::add(kpAns, i18n("Previous result"));
	keypadBasicsLayout->addWidget(kpAns, 3, 3);
	if(rpn_mode) kpEquals = new QalculateButton(i18n("Ent"), keypadPage);
	else kpEquals = new QalculateButton(i18n("="), keypadPage);
	if(rpn_mode) TQToolTip::add(kpEquals, i18n("Calculate expression and add to stack"));
	else TQToolTip::add(kpEquals, i18n("Calculate expression"));
	keypadBasicsLayout->addWidget(kpEquals, 3, 4);
	keypadBottomLayout->addLayout(keypadBasicsLayout);
	
	keypadPageLayout->addLayout(keypadBottomLayout);

	keypadPageLayout->addWidget(new KSeparator(TQt::Horizontal, keypadPage));
	mainStack->addWidget(keypadPage, 0);

	historyPage = new TQWidget(mainStack, "historyPage");
	TQVBoxLayout *historyPageLayout = new TQVBoxLayout(historyPage, 0, 0);
	historyBrowser = new QalculateHistoryBrowser(historyPage, "historyBrowser");
	historyBrowser->setTextFormat(KTextBrowser::RichText);
	historyBrowser->setWordWrap(KTextBrowser::NoWrap);
	historyPageLayout->addWidget(historyBrowser);
	mainStack->addWidget(historyPage, 1);

	stackPage = new TQWidget(mainStack, "stackPage");
	TQHBoxLayout *stackPageLayout = new TQHBoxLayout(stackPage, 0, 6);
	stackList = new QalculateRPNStackListView(stackPage, "stackList");
	stackList->addColumn(i18n("Index"));
	stackList->addColumn(i18n("Value"));
	stackList->setColumnAlignment(0, TQt::AlignCenter);
	stackList->setColumnAlignment(1, TQt::AlignRight);
	stackList->setFullWidth(true);
	stackList->setResizeMode(TQListView::LastColumn);
	stackList->setSelectionMode(TQListView::Single);
	stackList->setAllColumnsShowFocus(true);
	stackList->setRootIsDecorated(false);
	stackList->setItemsMovable(true);
	stackList->setDragEnabled(true);
	stackList->setAcceptDrops(true);
	stackList->setSorting(-1);
	stackList->setItemsRenameable(true);
	stackList->setRenameable(1, true);
	stackList->setRenameable(0, false);
	stackPageLayout->addWidget(stackList);
	if(use_button_pixmaps) stackPageButtonsLayout = new TQVBoxLayout(stackPageLayout, 3);
	else stackPageButtonsLayout = new TQVBoxLayout(stackPageLayout, 6);
	if(use_button_pixmaps) registerUpButton = new QalculateButton(TDEApplication::kApplication()->iconLoader()->loadIconSet("go-up", TDEIcon::Small, TDEIcon::SizeSmallMedium), "", stackPage);
	else registerUpButton = new QalculateButton(i18n("Up"), stackPage);
	TQToolTip::add(registerUpButton, i18n("Move selected register up"));
	registerUpButton->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed, false);
	stackPageButtonsLayout->addWidget(registerUpButton);
	if(use_button_pixmaps) registerDownButton = new QalculateButton(TDEApplication::kApplication()->iconLoader()->loadIconSet("go-down", TDEIcon::Small, TDEIcon::SizeSmallMedium), "", stackPage);
	else registerDownButton = new QalculateButton(i18n("Down"), stackPage);
	TQToolTip::add(registerDownButton, i18n("Move selected register down"));
	registerDownButton->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed, false);
	stackPageButtonsLayout->addWidget(registerDownButton);
	if(use_button_pixmaps) editRegisterButton = new QalculateButton(TDEApplication::kApplication()->iconLoader()->loadIconSet("edit", TDEIcon::Small, TDEIcon::SizeSmallMedium), "", stackPage);
	else editRegisterButton = new QalculateButton(i18n("Edit"), stackPage);
	TQToolTip::add(editRegisterButton, i18n("Edit value of selected register"));
	editRegisterButton->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed, false);
	stackPageButtonsLayout->addWidget(editRegisterButton);
	if(use_button_pixmaps) deleteRegisterButton = new QalculateButton(TDEApplication::kApplication()->iconLoader()->loadIconSet("edit-delete", TDEIcon::Small, TDEIcon::SizeSmallMedium), "", stackPage);
	else deleteRegisterButton = new QalculateButton(i18n("Delete"), stackPage);
	TQToolTip::add(deleteRegisterButton, i18n("Delete selected register"));
	deleteRegisterButton->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed, false);
	stackPageButtonsLayout->addWidget(deleteRegisterButton);
	if(use_button_pixmaps) clearStackButton = new QalculateButton(TDEApplication::kApplication()->iconLoader()->loadIconSet("view_remove", TDEIcon::Small, TDEIcon::SizeSmallMedium), "", stackPage);
	else clearStackButton = new QalculateButton(i18n("Clear"), stackPage);
	TQToolTip::add(clearStackButton, i18n("Clear the RPN stack"));
	clearStackButton->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed, false);
	registerUpButton->setEnabled(false);
	registerDownButton->setEnabled(false);
	editRegisterButton->setEnabled(false);
	deleteRegisterButton->setEnabled(false);
	clearStackButton->setEnabled(false);
	stackPageButtonsLayout->addWidget(clearStackButton);
	stackPageButtonsLayout->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Minimum, TQSizePolicy::Expanding));
	mainStack->addWidget(stackPage, 2);

	updateButtonWidths();

	mainLayout->addWidget(mainStack);
	
	TQHBoxLayout *bottomLayout = new TQHBoxLayout(0, 0, 6);
	keypadButton = new TQPushButton(i18n("Keypad"), centralWidget());
	TQToolTip::add(keypadButton, i18n("Show/hide keypad"));
	keypadButton->setToggleButton(true);
	bottomLayout->addWidget(keypadButton);
	historyButton = new TQPushButton(i18n("History"), centralWidget());
	TQToolTip::add(historyButton, i18n("Show/hide history"));
	historyButton->setToggleButton(true);
	bottomLayout->addWidget(historyButton);
	stackButton = new TQPushButton(i18n("RPN Stack"), centralWidget());
	TQToolTip::add(stackButton, i18n("Show/hide RPN stack"));
	stackButton->setToggleButton(true);
	bottomLayout->addWidget(stackButton);
	if(!rpn_mode) stackButton->hide();
	bottomLayout->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Expanding, TQSizePolicy::Minimum));
	mainLayout->addLayout(bottomLayout);

	connect(stackList, TQ_SIGNAL(selectionChanged()), this, TQ_SLOT(registerSelected()));
	connect(stackList, TQ_SIGNAL(itemRenamed(TQListViewItem*)), this, TQ_SLOT(stackRegisterSet(TQListViewItem*)));
	connect(stackList, TQ_SIGNAL(moved()), this, TQ_SLOT(stackRegisterMoved()));
	connect(stackList, TQ_SIGNAL(contextMenu(TDEListView*, TQListViewItem*, const TQPoint&)), this, TQ_SLOT(popupStackMenu(TDEListView*, TQListViewItem*, const TQPoint&)));
	connect(registerUpButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(registerUp()));
	connect(registerDownButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(registerDown()));
	connect(editRegisterButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(editRegister()));
	connect(deleteRegisterButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(deleteRegister()));
	connect(clearStackButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(clearStack()));
	connect(stackButton, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(toggleStack(bool)));
	connect(historyButton, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(toggleHistory(bool)));
	connect(keypadButton, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(toggleKeypad(bool)));
	connect(kp0, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP0()));
	connect(kp1, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP1()));
	connect(kp2, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP2()));
	connect(kp3, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP3()));
	connect(kp4, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP4()));
	connect(kp5, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP5()));
	connect(kp6, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP6()));
	connect(kp7, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP7()));
	connect(kp8, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP8()));
	connect(kp9, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertKP9()));
	connect(kpDot, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertDot()));
	connect(kpExp, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertExp()));
	connect(kpAns, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertAns()));
	connect(kpEquals, TQ_SIGNAL(clicked()), this, TQ_SLOT(execute()));
	connect(kpPlus, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertPlus()));
	connect(kpMinus, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertMinus()));
	connect(kpTimes, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertTimes()));
	connect(kpDivision, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertDivision()));
	connect(kpDel, TQ_SIGNAL(clicked()), this, TQ_SLOT(expressionDel()));
	connect(kpClear, TQ_SIGNAL(clicked()), this, TQ_SLOT(clearExpression()));
	connect(kpSin, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertSin()));
	connect(kpCos, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertCos()));
	connect(kpTan, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertTan()));
	connect(kpSqrt, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertSqrt()));
	connect(kpLog, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertLog()));
	connect(kpLn, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertLn()));
	connect(kpRaise, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertRaise()));
	connect(kpSquare, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertSquare()));
	connect(kpFraction, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(setFractionMode(bool)));
	connect(kpExact, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(setExactMode(bool)));
	connect(kpAngleGroup, TQ_SIGNAL(clicked(int)), this, TQ_SLOT(kpSetAngleUnit(int)));
	connect(kpBaseCombo->listBox(), TQ_SIGNAL(selected(int)), this, TQ_SLOT(kpSetBaseSelected(int)));
	connect(kpBaseCombo, TQ_SIGNAL(activated(int)), this, TQ_SLOT(kpSetBase(int)));
	connect(kpNumericCombo, TQ_SIGNAL(activated(int)), this, TQ_SLOT(kpSetNumericalMode(int)));
	//connect(kpMod, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertMod()));
	connect(kpFactorial, TQ_SIGNAL(clicked()), this, TQ_SLOT(insertFactorial()));
	//connect(expressionEdit, TQ_SIGNAL(returnPressed()), this, TQ_SLOT(execute()));
	connect(expressionEdit, TQ_SIGNAL(textChanged(const TQString&)), this, TQ_SLOT(onExpressionChanged()));
	connect(storeButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(storeResult()));
	connect(executeButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(execute()));
	connect(convertButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(convertToUnitExpression()));
	connect(functionsButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(manageFunctions()));
	connect(expressionEdit, TQ_SIGNAL(cursorMoved()), this, TQ_SLOT(displayParseStatus()));
	connect(expressionEdit->qalculateCompletionBox, TQ_SIGNAL(hidden()), statusLabel_l, TQ_SLOT(update()));

	//tab order
	setTabOrder(expressionEdit, resultLabel);
	setTabOrder(resultLabel, historyBrowser);
	setTabOrder(historyBrowser, keypadButton);
	setTabOrder(keypadButton, historyButton);
	setTabOrder(historyButton, stackButton);

	 if(show_stack && rpn_mode) {
		bottomLine->hide();
		stackButton->setOn(true);
		mainStack->raiseWidget(2);
		mainStack->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
		resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
	} else if(show_keypad) {
		bottomLine->hide();
		keypadButton->setOn(true);
		mainStack->raiseWidget(0);
		mainStack->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
		resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
	} else if(show_history) {
		bottomLine->hide();
		historyButton->setOn(true);
		mainStack->raiseWidget(1);
		mainStack->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
		resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
	} else {
		mainStack->hide();
		mainStack->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum, false);
		resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
	}
	
	initial_history = "";

	for(TQValueVector<TQString>::size_type i = 0; i < inhistory.size(); i++) {
		switch(inhistory_type[i]) {
			case QALCULATE_HISTORY_EXPRESSION: {
				if(i != 0) {
					initial_history += "<br><hr>";
				}
				initial_history += "<a name=\"";
				initial_history += TQString::number(inhistory_id[i]);
				initial_history += "\">";
				initial_history += inhistory[i];
				initial_history += "</a>";
				initial_history += " ";
				break;
			}
			case QALCULATE_HISTORY_REGISTER_MOVED: {
				if(i != 0) {
					initial_history += "<br><hr>";
				}
				initial_history += i18n("RPN Register Moved");
				initial_history += "<br>";
				break;
			}
			case QALCULATE_HISTORY_TRANSFORMATION: {
				initial_history += "<i>";
				initial_history += "<b>";
				initial_history += inhistory[i];
				initial_history += "</i>";
				initial_history += ": ";
				break;
			}
			case QALCULATE_HISTORY_RESULT: {
				initial_history += "<a name=\"";
				initial_history += TQString::number(inhistory_id[i]);
				initial_history += "\">";
				initial_history += "= ";
				initial_history += "</a>";
				initial_history += "<b>";
				initial_history += "<a name=\"";
				initial_history += TQString::number(inhistory_id[i]);
				initial_history += "\">";
				initial_history += inhistory[i];
				initial_history += "</a>";
				initial_history += "</b>";
				initial_history += "<br>";
				break;
			}
			case QALCULATE_HISTORY_RESULT_APPROXIMATE: {
				initial_history += "<a name=\"";
				initial_history += TQString::number(inhistory_id[i]);
				initial_history += "\">";
				if(printops.use_unicode_signs && can_display_unicode_string_function(SIGN_ALMOST_EQUAL, (void*) historyBrowser)) {
					initial_history += SIGN_ALMOST_EQUAL " ";
				} else {
					initial_history += "= ";
					initial_history += i18n("approx.");
					initial_history += " ";
				}
				initial_history += "</a>";
				initial_history += "<b>";
				initial_history += "<a name=\"";
				initial_history += TQString::number(inhistory_id[i]);
				initial_history += "\">";
				initial_history += inhistory[i];
				initial_history += "</a>";
				initial_history += "</b>";
				initial_history += "<br>";
				break;
			}
			case QALCULATE_HISTORY_PARSE: {
				initial_history += "&nbsp;&nbsp;= ";
				initial_history += "<font color=\"gray40\"><i>";
				initial_history += "<a name=\"";
				initial_history += TQString::number(inhistory_id[i]);
				initial_history += "\">";
				initial_history += inhistory[i];
				initial_history += "</a>";
				initial_history += "</i></font>";
				initial_history += "<br>";
				break;
			}
			case QALCULATE_HISTORY_PARSE_APPROXIMATE: {
				initial_history += "&nbsp;&nbsp;";
				if(printops.use_unicode_signs && can_display_unicode_string_function(SIGN_ALMOST_EQUAL, (void*) historyBrowser)) {
					initial_history += SIGN_ALMOST_EQUAL " ";
				} else {
					initial_history += "= ";
					initial_history += i18n("approx.");
					initial_history += " ";
				}
				initial_history += "<font color=\"gray40\"><i>";
				initial_history += "<a name=\"";
				initial_history += TQString::number(inhistory_id[i]);
				initial_history += "\">";
				initial_history += inhistory[i];
				initial_history += "</a>";
				initial_history += "</i></font>";
				initial_history += "<br>";
				break;
			}
			case QALCULATE_HISTORY_WARNING: {
				initial_history += "<font color=\"blue\">";
				initial_history += "- ";
				initial_history += inhistory[i];
				initial_history += "</font>";
				initial_history += "<br>";
				break;
			}
			case QALCULATE_HISTORY_ERROR: {
				initial_history += "<font color=\"red\">";
				initial_history += "- ";
				initial_history += inhistory[i];
				initial_history += "</font>";
				initial_history += "<br>";
				break;
			}
			case QALCULATE_HISTORY_OLD: {
				initial_history += inhistory[i];
				initial_history += "<br>";
				break;
			}
		}	
	}

	historyBrowser->setText(initial_history);
	initial_history = "";

	if(use_custom_result_font) {
		TQFont new_font(resultLabel->font());
		new_font.fromString(custom_result_font);
		resultLabel->setFont(new_font);
	} else {
		resultLabel->unsetFont();
	}
	if(use_custom_expression_font) {
		TQFont new_font(expressionEdit->font());
		new_font.fromString(custom_expression_font);
		expressionEdit->setFont(new_font);
	} else {
		expressionEdit->unsetFont();
	}
	updateStatusLabelFonts();
	
	set_unicode_buttons();

	setupActions();

	stackMenu = new TQPopupMenu(this);
	ActionEditRegister->plug(stackMenu);
	ActionDeleteRegister->plug(stackMenu);
	stackMenu->insertSeparator();
	ActionClearStack->plug(stackMenu);

	update_status_text();

	bottomLine->setMinimumWidth(1000);

	createGUI("qalculate_tdeui.rc");
	
	menuBar()->sizeHint();
	int h = menuBar()->height();
	int w = 300;
	while(menuBar()->heightForWidth(w) > h && w < 1000) {
		w += 10;
	}
	if(w >= 1000) {
		bottomLine->setMinimumWidth(0);
		w = 0;
	} else {
		bottomLine->setMinimumWidth(w - 22);
	}

	if(!isShown()) adjustSize();
	setAutoSaveSettings();
	
	if(show_history || (rpn_mode && show_stack)) {
		resize(TQSize(10, height()).expandedTo(minimumSizeHint()));
	} else if(show_keypad) {
		resize(minimumSizeHint());
	} else {
		resize(TQSize(width(), 10).expandedTo(minimumSizeHint()));
	}

	menu_functions = (TQPopupMenu*) factory()->container("functions", this);
	menu_variables = (TQPopupMenu*) factory()->container("variables", this);
	menu_units = (TQPopupMenu*) factory()->container("units", this);
	menu_to_unit = (TQPopupMenu*) factory()->container("convert_to_unit", this);
	menu_set_prefix = (TQPopupMenu*) factory()->container("set_prefix", this);
	menu_modes = (TQPopupMenu*) factory()->container("modes", this);
	
	TQObject::connect(menu_modes, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onModesMenuItemActivated(int)));
	for(size_t i = 0; i < modes.size(); i++) {
		menu_modes->insertItem(modes[i].name, -1, i);
		if(i > 1) {
			ModeObject *mo = new ModeObject(i);
			mo->i_mode = i;
			mode_objects.push_back(mo);
			accel()->insert(TQString("Load mode: ") + modes[i].name, i18n("Load meta mode: %1").arg(modes[i].name), TQString::null, modes[i].shortcut, mo, TQ_SLOT(loadMode()));
		}
	}

	TQObject::connect(menu_functions, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onFunctionMenuItemActivated(int)));
	TQObject::connect(menu_variables, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onVariableMenuItemActivated(int)));
	TQObject::connect(menu_units, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onUnitMenuItemActivated(int)));
	TQObject::connect(menu_to_unit, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onConvertToUnitMenuItemActivated(int)));
	TQObject::connect(menu_set_prefix, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onSetPrefixMenuItemActivated(int)));

}

KQalculate::~KQalculate() {}

void KQalculate::updateStatusLabelFonts() {
	if(use_custom_status_font) {
		TQFont new_font(statusLabel_l->font());
		new_font.fromString(custom_status_font);
		statusLabel_l->setFont(new_font);
		new_font.setPointSizeFloat(new_font.pointSizeFloat() / 1.2);
		statusLabel_r->setFont(new_font);
	} else {
		statusLabel_l->unsetFont();
		statusLabel_r->unsetFont();
		TQFont new_font = statusLabel_l->font();
		new_font.setPointSizeFloat(new_font.pointSizeFloat() / 1.2);
		statusLabel_l->setFont(new_font);
		new_font = statusLabel_r->font();
		new_font.setPointSizeFloat(new_font.pointSizeFloat() / 1.44);
		statusLabel_r->setFont(new_font);
	}
}

void KQalculate::updateButtonWidths() {
	int button_width = executeButton->sizeHint().width();
	if(storeButton->sizeHint().width() > button_width) button_width = storeButton->sizeHint().width();
	if(convertButton->sizeHint().width() > button_width) button_width = convertButton->sizeHint().width();
	if(registerUpButton->sizeHint().width() > button_width) button_width = registerUpButton->sizeHint().width();
	if(registerDownButton->sizeHint().width() > button_width) button_width = registerDownButton->sizeHint().width();
	if(editRegisterButton->sizeHint().width() > button_width) button_width = editRegisterButton->sizeHint().width();
	if(deleteRegisterButton->sizeHint().width() > button_width) button_width = deleteRegisterButton->sizeHint().width();
	if(clearStackButton->sizeHint().width() > button_width) button_width = clearStackButton->sizeHint().width();
	clearStackButton->setMinimumWidth(button_width);
	executeButton->setMinimumWidth(button_width);
}

void KQalculate::fontChange(const TQFont &old_font) {
	updateStatusLabelFonts();
	functionsButton->unsetFont();
	TQFont fb_font(functionsButton->font());
	fb_font.setItalic(true);
	functionsButton->setFont(fb_font);
	kpSquare->setMarkup(i18n("x<sup>2</sup>"));
	kpRaise->setMarkup(i18n("x<sup>y</sup>"));
	result_display_updated();
	TDEMainWindow::fontChange(old_font);
	updateButtonWidths();
}

void KQalculate::showSystemTrayIcon(bool do_show) {
	if(do_show && !trayicon) {
		trayicon = new KSystemTray(this);
		TQObject::connect(trayicon, TQ_SIGNAL(quitSelected()), tqApp, TQ_SLOT(quit()));
		trayicon->setPixmap(trayicon->loadIcon(PACKAGE));
		TDEPopupMenu* traypop = trayicon->contextMenu();
		ActionHideSystemTrayIcon->plug(traypop, 1);
		TQToolTip::add(trayicon, i18n("Qalculate! - Scientific Calculator"));
	}
	if(do_show) {
		trayicon->show();
	} else if(trayicon) {
		trayicon->hide();
	}
}
void KQalculate::hideSystemTrayIcon() {
	showSystemTrayIcon(false);
	close_to_systray = false;
	show();
}

#define SET_TOGGLE_ACTION(action, value)	action->blockSignals(true); action->setChecked(value); action->blockSignals(false);
#define SET_TOGGLE_ACTION_ON(action)	action->blockSignals(true); action->setChecked(true); action->blockSignals(false);

void KQalculate::setupActions() {

	ActionNewVariable = new TDEAction(i18n("Variable"), "filenew", 0, this, TQ_SLOT(newVariable()), actionCollection(), "new_variable");
	ActionNewMatrix = new TDEAction(i18n("Matrix"), "filenew", 0, this, TQ_SLOT(newMatrix()), actionCollection(), "new_matrix");
	ActionNewVector = new TDEAction(i18n("Vector"), "filenew", 0, this, TQ_SLOT(newVector()), actionCollection(), "new_vector");
	ActionNewUnknownVariable = new TDEAction(i18n("Unknown Variable"), "filenew", 0, this, TQ_SLOT(newUnknownVariable()), actionCollection(), "new_unknown_variable");
	ActionNewFunction = new TDEAction(i18n("Function"), "filenew", 0, this, TQ_SLOT(newFunction()), actionCollection(), "new_function");
	ActionNewDataSet = new TDEAction(i18n("Data Set"), "filenew", 0, this, TQ_SLOT(newDataSet()), actionCollection(), "new_data_set");
	ActionNewUnit = new TDEAction(i18n("Unit"), "filenew", 0, this, TQ_SLOT(newUnit()), actionCollection(), "new_unit");
	ActionImportCSVFile = new TDEAction(i18n("Import CSV File..."), "fileimport", 0, this, TQ_SLOT(importCSVFile()), actionCollection(), "import_csv_file");
	ActionExportCSVFile = new TDEAction(i18n("Export CSV File..."), "filexport", 0, this, TQ_SLOT(exportCSVFile()), actionCollection(), "export_csv_file");
	ActionStoreResult = new TDEAction(i18n("Store Result..."), "filesave", CTRL+Key_S, this, TQ_SLOT(storeResult()), actionCollection(), "store_result");
	ActionSaveAsImage = new TDEAction(i18n("Save Result Image..."), "filesave", 0, this, TQ_SLOT(saveAsImage()), actionCollection(), "save_as_image");
	ActionSaveDefinitions = new TDEAction(i18n("Save Definitions"), "filesave", 0, this, TQ_SLOT(saveDefinitions()), actionCollection(), "save_definitions");
	ActionUpdateExchangeRates = new TDEAction(i18n("Update Exchange Rates"), "reload", 0, this, TQ_SLOT(updateExchangeRates()), actionCollection(), "update_exchange_rates");
	ActionPlotFunctionsData = new TDEAction(i18n("Plot Functions/Data"), 0, this, TQ_SLOT(plotFunctionsData()), actionCollection(), "plot_functions_data");
	ActionPlotFunctionsData->setEnabled(canplot);
	ActionConvertNumberBases = new TDEAction(i18n("Convert Number Bases"), 0, this, TQ_SLOT(convertNumberBases()), actionCollection(), "convert_number_bases");
	ActionPeriodicTable = new TDEAction(i18n("Periodic Table"), 0, this, TQ_SLOT(periodicTable()), actionCollection(), "periodic_table");
	if(close_to_systray) {
		ActionClose = KStdAction::close(this, TQ_SLOT(close()), actionCollection());
	} else {
		ActionClose = NULL;
	}
	globalAccel = new TDEGlobalAccel(this);
	globalAccel->insert("Show/hide Qalculate!", i18n("Show/hide main Qalculate! window"), TQString::null, TDEShortcut(), TDEShortcut(), this, TQ_SLOT(showHide()));
	globalAccel->readSettings();
	globalAccel->updateConnections();
	ActionConfigureGlobalShortcuts = new TDEAction(i18n("Configure &Global Shortcuts..."), "configure_shortcuts", 0, this, TQ_SLOT(configureGlobalShortcuts()), actionCollection(), "configure_global_shortcuts");
	ActionQuit = KStdAction::quit(tqApp, TQ_SLOT(quit()), actionCollection());
	ActionManageVariables = new TDEAction(i18n("Manage Variables"), Key_F2, this, TQ_SLOT(manageVariables()), actionCollection(), "manage_variables");
	ActionManageFunctions = new TDEAction(i18n("Manage Functions"), Key_F3, this, TQ_SLOT(manageFunctions()), actionCollection(), "manage_functions");
	ActionManageUnits = new TDEAction(i18n("Manage Units"), Key_F4, this, TQ_SLOT(manageUnits()), actionCollection(), "manage_units");
	ActionManageDataSets = new TDEAction(i18n("Manage Data Sets"), 0, this, TQ_SLOT(manageDataSets()), actionCollection(), "manage_data_sets");
	ActionFactorize = new TDEAction(i18n("Factorize"), 0, this, TQ_SLOT(factorize()), actionCollection(), "factorize");
	ActionSimplify = new TDEAction(i18n("Simplify"), 0, this, TQ_SLOT(simplify()), actionCollection(), "simplify");
	ActionSetUnknowns = new TDEAction(i18n("Set Unknowns..."), 0, this, TQ_SLOT(setUnknowns()), actionCollection(), "set_unknowns");
	ActionConvertToUnitExpression = new TDEAction(i18n("Convert to Unit Expression..."), CTRL+Key_T, this, TQ_SLOT(convertToUnitExpression()), actionCollection(), "convert_to_unit_expression");
	ActionConvertToBaseUnits = new TDEAction(i18n("Convert to Base Units"), 0, this, TQ_SLOT(convertToBaseUnits()), actionCollection(), "convert_to_base_units");
	ActionConvertToBestUnit = new TDEAction(i18n("Convert to Best Unit"), 0, this, TQ_SLOT(convertToBestUnit()), actionCollection(), "convert_to_best_unit");
	ActionInsertMatrix = new TDEAction(i18n("Insert Matrix..."), 0, this, TQ_SLOT(insertMatrix()), actionCollection(), "insert_matrix");
	ActionInsertVector = new TDEAction(i18n("Insert Vector..."), 0, this, TQ_SLOT(insertVector()), actionCollection(), "insert_vector");
	ActionCopyResult = new TDEAction(i18n("Copy Result"), "editcopy", Key_F5, this, TQ_SLOT(copyResult()), actionCollection(), "copy_result");
	ActionClearHistory = new TDEAction(i18n("Clear History"), "editclear", 0, this, TQ_SLOT(clearHistory()), actionCollection(), "clear_history");	
	ActionPreferences = new TDEAction(i18n("Configure Qalculate!"), "configure", 0, this, TQ_SLOT(preferences()), actionCollection(), "preferences");
	KStdAction::keyBindings(guiFactory(), TQ_SLOT(configureShortcuts()), actionCollection(), "keybindings");
	ActionNumberBaseBinary = new TDERadioAction(i18n("Binary"), 0, this, TQ_SLOT(numberBaseBinary()), actionCollection(), "number_base_binary");
	ActionNumberBaseBinary->setExclusiveGroup("group_number_base");
	ActionNumberBaseOctal = new TDERadioAction(i18n("Octal"), 0, this, TQ_SLOT(numberBaseOctal()), actionCollection(), "number_base_octal");
	ActionNumberBaseOctal->setExclusiveGroup("group_number_base");
	ActionNumberBaseDecimal = new TDERadioAction(i18n("Decimal"), 0, this, TQ_SLOT(numberBaseDecimal()), actionCollection(), "number_base_decimal");
	ActionNumberBaseDecimal->setExclusiveGroup("group_number_base");
	ActionNumberBaseHexadecimal = new TDERadioAction(i18n("Hexadecimal"), 0, this, TQ_SLOT(numberBaseHexadecimal()), actionCollection(), "number_base_hexadecimal");
	ActionNumberBaseHexadecimal->setExclusiveGroup("group_number_base");
	ActionNumberBaseOther = new TDERadioAction(i18n("Other..."), 0, this, TQ_SLOT(numberBaseOther()), actionCollection(), "number_base_other");
	ActionNumberBaseOther->setExclusiveGroup("group_number_base");
	ActionNumberBaseSexagesimal = new TDERadioAction(i18n("Sexagesimal"), 0, this, TQ_SLOT(numberBaseSexagesimal()), actionCollection(), "number_base_sexagesimal");
	ActionNumberBaseSexagesimal->setExclusiveGroup("group_number_base");
	ActionNumberBaseTimeFormat = new TDERadioAction(i18n("Time Format"), 0, this, TQ_SLOT(numberBaseTimeFormat()), actionCollection(), "number_base_time_format");
	ActionNumberBaseTimeFormat->setExclusiveGroup("group_number_base");
	ActionNumberBaseRomanNumerals = new TDERadioAction(i18n("Roman Numerals"), 0, this, TQ_SLOT(numberBaseRomanNumerals()), actionCollection(), "number_base_roman_numerals");
	ActionNumberBaseRomanNumerals->setExclusiveGroup("group_number_base");
	ActionSetBase = new TDEAction(i18n("Select Result and Expression Base..."), CTRL+Key_B, this, TQ_SLOT(setBase()), actionCollection(), "set_base");
	ActionNumericalDisplayNormal = new TDERadioAction(i18n("Normal"), 0, this, TQ_SLOT(numericalDisplayNormal()), actionCollection(), "numerical_display_normal");
	ActionNumericalDisplayNormal->setExclusiveGroup("group_numberical_display");
	ActionNumericalDisplayEngineering = new TDERadioAction(i18n("Engineering"), 0, this, TQ_SLOT(numericalDisplayEngineering()), actionCollection(), "numerical_display_engineering");
	ActionNumericalDisplayEngineering->setExclusiveGroup("group_numberical_display");
	ActionNumericalDisplayScientific = new TDERadioAction(i18n("Scientific"), 0, this, TQ_SLOT(numericalDisplayScientific()), actionCollection(), "numerical_display_scientific");
	ActionNumericalDisplayScientific->setExclusiveGroup("group_numberical_display");
	ActionNumericalDisplayPurelyScientific = new TDERadioAction(i18n("Purely Scientific"), 0, this, TQ_SLOT(numericalDisplayPurelyScientific()), actionCollection(), "numerical_display_purely_scientific");
	ActionNumericalDisplayPurelyScientific->setExclusiveGroup("group_numberical_display");
	ActionNumericalDisplaySimple = new TDERadioAction(i18n("Simple"), 0, this, TQ_SLOT(numericalDisplaySimple()), actionCollection(), "numerical_display_simple");
	ActionNumericalDisplaySimple->setExclusiveGroup("group_numberical_display");
	ActionIndicateInfiniteSeries = new TDEToggleAction(i18n("Indicate Infinite Series"), 0, actionCollection(), "indicate_infinite_series");
	TQObject::connect(ActionIndicateInfiniteSeries, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(indicateInfiniteSeries(bool)));
	ActionSortMinusLast = new TDEToggleAction(i18n("Sort Minus Last"), 0, actionCollection(), "sort_minus_last");
	TQObject::connect(ActionSortMinusLast, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(sortMinusLast(bool)));
	ActionNegativeExponents = new TDEToggleAction(i18n("Negative Exponents"), 0, actionCollection(), "negative_exponents");
	TQObject::connect(ActionNegativeExponents, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(negativeExponents(bool)));
	ActionShowEndingZeroes = new TDEToggleAction(i18n("Show Ending Zeroes"), 0, actionCollection(), "show_ending_zeroes");
	TQObject::connect(ActionShowEndingZeroes, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(showEndingZeroes(bool)));
	ActionRoundHalfwayNumbersToEven = new TDEToggleAction(i18n("Round Halfway Numbers to Even"), 0, actionCollection(), "round_halfway_numbers_to_even");
	TQObject::connect(ActionRoundHalfwayNumbersToEven, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(roundHalfwayNumbersToEven(bool)));
	ActionFractionalDisplayDecimal = new TDERadioAction(i18n("Decimal"), 0, this, TQ_SLOT(fractionalDisplayDecimal()), actionCollection(), "fractional_display_decimal");
	ActionFractionalDisplayDecimal->setExclusiveGroup("group_fractional_display");
	ActionFractionalDisplayDecimalTryExact = new TDERadioAction(i18n("Decimal (Try Exact)"), 0, this, TQ_SLOT(fractionalDisplayDecimalTryExact()), actionCollection(), "fractional_display_decimal_try_exact");
	ActionFractionalDisplayDecimalTryExact->setExclusiveGroup("group_fractional_display");
	ActionFractionalDisplayFraction = new TDERadioAction(i18n("Fraction"), 0, this, TQ_SLOT(fractionalDisplayFraction()), actionCollection(), "fractional_display_fraction");
	ActionFractionalDisplayFraction->setExclusiveGroup("group_fractional_display");
	ActionFractionalDisplayCombined = new TDERadioAction(i18n("Combined"), 0, this, TQ_SLOT(fractionalDisplayCombined()), actionCollection(), "fractional_display_combined");
	ActionFractionalDisplayCombined->setExclusiveGroup("group_fractional_display");
	ActionEnablePrefixes = new TDEToggleAction(i18n("Enable Prefixes"), 0, actionCollection(), "enable_prefixes");
	TQObject::connect(ActionEnablePrefixes, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(enablePrefixes(bool)));
	ActionEnableUseOfAllPrefixes = new TDEToggleAction(i18n("Enable Use of All SI Prefixes"), 0, actionCollection(), "enable_use_of_all_prefixes");
	TQObject::connect(ActionEnableUseOfAllPrefixes, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(enableUseOfAllPrefixes(bool)));
	ActionEnableDenominatorPrefixes = new TDEToggleAction(i18n("Enable Denominator Prefixes"), 0, actionCollection(), "enable_denominator_prefixes");
	TQObject::connect(ActionEnableDenominatorPrefixes, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(enableDenominatorPrefixes(bool)));
	ActionPlaceUnitsSeparately = new TDEToggleAction(i18n("Place Units Separately"), 0, actionCollection(), "place_units_separately");
	TQObject::connect(ActionPlaceUnitsSeparately, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(placeUnitsSeparately(bool)));
	ActionAutoNoConversion = new TDERadioAction(i18n("No Automatic Conversion"), 0, this, TQ_SLOT(autoNoConversion()), actionCollection(), "auto_no_conversion");
	ActionAutoNoConversion->setExclusiveGroup("group_auto_conversion");
	ActionAutoConvertToBaseUnits = new TDERadioAction(i18n("Convert to Base Units"), 0, this, TQ_SLOT(autoConvertToBaseUnits()), actionCollection(), "auto_convert_to_base_units");
	ActionAutoConvertToBaseUnits->setExclusiveGroup("group_auto_conversion");
	ActionAutoConvertToBestUnit = new TDERadioAction(i18n("Convert to Best Unit"), 0, this, TQ_SLOT(autoConvertToBestUnit()), actionCollection(), "auto_convert_to_best_unit");
	ActionAutoConvertToBestUnit->setExclusiveGroup("group_auto_conversion");
	ActionAngleUnitDegrees = new TDERadioAction(i18n("Degrees"), 0, this, TQ_SLOT(angleUnitDegrees()), actionCollection(), "angle_unit_degrees");
	ActionAngleUnitDegrees->setExclusiveGroup("group_angle_unit");
	ActionAngleUnitRadians = new TDERadioAction(i18n("Radians"), 0, this, TQ_SLOT(angleUnitRadians()), actionCollection(), "angle_unit_radians");
	ActionAngleUnitRadians->setExclusiveGroup("group_angle_unit");
	ActionAngleUnitGradians = new TDERadioAction(i18n("Gradians"), 0, this, TQ_SLOT(angleUnitGradians()), actionCollection(), "angle_unit_gradians");
	ActionAngleUnitGradians->setExclusiveGroup("group_angle_unit");
	ActionAngleUnitNone = new TDERadioAction(i18n("None"), 0, this, TQ_SLOT(angleUnitNone()), actionCollection(), "angle_unit_none");
	ActionAngleUnitNone->setExclusiveGroup("group_angle_unit");
	ActionAbbreviateNames = new TDEToggleAction(i18n("Abbreviate Names"), 0, actionCollection(), "abbreviate_names");
	TQObject::connect(ActionAbbreviateNames, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(abbreviateNames(bool)));
	ActionEnableVariables = new TDEToggleAction(i18n("Enable Variables"), 0, actionCollection(), "enable_variables");
	TQObject::connect(ActionEnableVariables, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(enableVariables(bool)));
	ActionEnableFunctions = new TDEToggleAction(i18n("Enable Functions"), 0, actionCollection(), "enable_functions");
	TQObject::connect(ActionEnableFunctions, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(enableFunctions(bool)));
	ActionEnableUnits = new TDEToggleAction(i18n("Enable Units"), 0, actionCollection(), "enable_units");
	TQObject::connect(ActionEnableUnits, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(enableUnits(bool)));
	ActionEnableUnknowns = new TDEToggleAction(i18n("Enable Unknowns"), 0, actionCollection(), "enable_unknowns");
	TQObject::connect(ActionEnableUnknowns, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(enableUnknowns(bool)));
	ActionCalculateVariables = new TDEToggleAction(i18n("Calculate Variables"), 0, actionCollection(), "calculate_variables");
	TQObject::connect(ActionCalculateVariables, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(calculateVariables(bool)));
	ActionAllowComplexResult = new TDEToggleAction(i18n("Allow Complex Result"), 0, actionCollection(), "allow_complex_result");
	TQObject::connect(ActionAllowComplexResult, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(allowComplexResult(bool)));
	ActionAllowInfiniteResult = new TDEToggleAction(i18n("Allow Infinite Result"), 0, actionCollection(), "allow_infinite_result");
	TQObject::connect(ActionAllowInfiniteResult, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(allowInfiniteResult(bool)));
	ActionApproximationTryExact = new TDERadioAction(i18n("Try Exact"), 0, this, TQ_SLOT(approximationTryExact()), actionCollection(), "approximation_try_exact");
	ActionApproximationTryExact->setExclusiveGroup("group_approximation");
	ActionApproximationAlwaysExact = new TDERadioAction(i18n("Always Exact"), 0, this, TQ_SLOT(approximationAlwaysExact()), actionCollection(), "approximation_always_exact");
	ActionApproximationAlwaysExact->setExclusiveGroup("group_approximation");
	ActionApproximationApproximate = new TDERadioAction(i18n("Approximate"), 0, this, TQ_SLOT(approximationApproximate()), actionCollection(), "approximation_approximate");
	ActionApproximationApproximate->setExclusiveGroup("group_approximation");
	ActionAssumptionTypeUnknown = new TDERadioAction(i18n("Unknown"), 0, this, TQ_SLOT(assumptionTypeUnknown()), actionCollection(), "assumption_type_unknown");
	ActionAssumptionTypeUnknown->setExclusiveGroup("group_assumption_type");
	ActionAssumptionTypeNonMatrix = new TDERadioAction(i18n("Not Matrix"), 0, this, TQ_SLOT(assumptionTypeNonMatrix()), actionCollection(), "assumption_type_nonmatrix");
	ActionAssumptionTypeNonMatrix->setExclusiveGroup("group_assumption_type");
	ActionAssumptionTypeNumber = new TDERadioAction(i18n("Number"), 0, this, TQ_SLOT(assumptionTypeNumber()), actionCollection(), "assumption_type_number");
	ActionAssumptionTypeNumber->setExclusiveGroup("group_assumption_type");
	ActionAssumptionTypeComplex = new TDERadioAction(i18n("Complex"), 0, this, TQ_SLOT(assumptionTypeComplex()), actionCollection(), "assumption_type_complex");
	ActionAssumptionTypeComplex->setExclusiveGroup("group_assumption_type");
	ActionAssumptionTypeReal = new TDERadioAction(i18n("Real"), 0, this, TQ_SLOT(assumptionTypeReal()), actionCollection(), "assumption_type_real");
	ActionAssumptionTypeReal->setExclusiveGroup("group_assumption_type");
	ActionAssumptionTypeRational = new TDERadioAction(i18n("Rational"), 0, this, TQ_SLOT(assumptionTypeRational()), actionCollection(), "assumption_type_rational");
	ActionAssumptionTypeRational->setExclusiveGroup("group_assumption_type");
	ActionAssumptionTypeInteger = new TDERadioAction(i18n("Integer"), 0, this, TQ_SLOT(assumptionTypeInteger()), actionCollection(), "assumption_type_integer");
	ActionAssumptionTypeInteger->setExclusiveGroup("group_assumption_type");
	ActionAssumptionSignUnknown = new TDERadioAction(i18n("Unknown"), 0, this, TQ_SLOT(assumptionSignUnknown()), actionCollection(), "assumption_sign_unknown");
	ActionAssumptionSignUnknown->setExclusiveGroup("group_assumption_sign");
	ActionAssumptionSignNonZero = new TDERadioAction(i18n("Non-Zero"), 0, this, TQ_SLOT(assumptionSignNonZero()), actionCollection(), "assumption_sign_non_zero");
	ActionAssumptionSignNonZero->setExclusiveGroup("group_assumption_sign");
	ActionAssumptionSignPositive = new TDERadioAction(i18n("Positive"), 0, this, TQ_SLOT(assumptionSignPositive()), actionCollection(), "assumption_sign_positive");
	ActionAssumptionSignPositive->setExclusiveGroup("group_assumption_sign");
	ActionAssumptionSignNonNegative = new TDERadioAction(i18n("Non-Negative"), 0, this, TQ_SLOT(assumptionSignNonNegative()), actionCollection(), "assumption_sign_non_negative");
	ActionAssumptionSignNonNegative->setExclusiveGroup("group_assumption_sign");
	ActionAssumptionSignNegative = new TDERadioAction(i18n("Negative"), 0, this, TQ_SLOT(assumptionSignNegative()), actionCollection(), "assumption_sign_negative");
	ActionAssumptionSignNegative->setExclusiveGroup("group_assumption_sign");
	ActionAssumptionSignNonPositive = new TDERadioAction(i18n("Non-Positive"), 0, this, TQ_SLOT(assumptionSignNonPositive()), actionCollection(), "assumption_sign_non_positive");
	ActionAssumptionSignNonPositive->setExclusiveGroup("group_assumption_sign");
	ActionNonZeroDenominators = new TDEToggleAction(i18n("Non-Zero Denominators"), 0, actionCollection(), "non_zero_denominators");
	TQObject::connect(ActionNonZeroDenominators, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(nonZeroDenominators(bool)));
	ActionWarnAboutDenominatorsAssumedNonZero = new TDEToggleAction(i18n("Warn About Denominators Assumed Non-Zero"), 0, actionCollection(), "warn_about_denominators_assumed_nonzero");
	TQObject::connect(ActionWarnAboutDenominatorsAssumedNonZero, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(warnAboutDenominatorsAssumedNonZero(bool)));
	ActionAlgebraicModeSimplify = new TDERadioAction(i18n("Simplify"), 0, this, TQ_SLOT(algebraicModeSimplify()), actionCollection(), "algebraic_mode_simplify");
	ActionAlgebraicModeSimplify->setExclusiveGroup("group_alebraic_mode");
	ActionAlgebraicModeFactorize = new TDERadioAction(i18n("Factorize"), 0, this, TQ_SLOT(algebraicModeFactorize()), actionCollection(), "algebraic_mode_factorize");
	ActionAlgebraicModeFactorize->setExclusiveGroup("group_alebraic_mode");
	ActionAlgebraicModeNone = new TDERadioAction(i18n("None"), 0, this, TQ_SLOT(algebraicModeNone()), actionCollection(), "algebraic_mode_none");
	ActionAlgebraicModeNone->setExclusiveGroup("group_alebraic_mode");
	ActionReadPrecision = new TDEToggleAction(i18n("Read Precision"), 0, actionCollection(), "read_precision");
	TQObject::connect(ActionReadPrecision, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(readPrecision(bool)));
	ActionLimitImplicitMultiplication = new TDEToggleAction(i18n("Limit Implicit Multiplication"), 0, actionCollection(), "limit_implicit_multiplication");
	TQObject::connect(ActionLimitImplicitMultiplication, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(limitImplicitMultiplication(bool)));
	ActionRPNMode = new TDEToggleAction(i18n("RPN Mode"), CTRL+Key_R, actionCollection(), "rpn_mode");
	TQObject::connect(ActionRPNMode, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(rpnMode(bool)));
	ActionRPNSyntax = new TDEToggleAction(i18n("RPN Syntax"), 0, actionCollection(), "rpn_syntax");
	TQObject::connect(ActionRPNSyntax, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(rpnSyntax(bool)));
	ActionPrecision = new TDEAction(i18n("Precision"), 0, this, TQ_SLOT(precision()), actionCollection(), "precision");
	ActionDecimals = new TDEAction(i18n("Decimals"), 0, this, TQ_SLOT(decimals()), actionCollection(), "decimals");
	ActionSaveModeAs = new TDEAction(i18n("Save Mode..."), "filesave", 0, this, TQ_SLOT(saveModeAs()), actionCollection(), "save_mode_as");
	ActionDeleteMode = new TDEAction(i18n("Delete Mode..."), "editdelete", 0, this, TQ_SLOT(deleteMode()), actionCollection(), "delete_mode");
	ActionDeleteMode->setEnabled(modes.size() > 2);
	ActionSaveMode = new TDEAction(i18n("Save Default Mode"), "filesave", 0, this, TQ_SLOT(saveMode()), actionCollection(), "save_mode");
	ActionClearStack = new TDEAction(i18n("Clear Stack"), "view_remove", 0, this, TQ_SLOT(clearStack()), actionCollection(), "clear_stack");
	ActionDeleteRegister = new TDEAction(i18n("Delete"), "editdelete", 0, this, TQ_SLOT(deleteRegister()), actionCollection(), "delete_register");
	ActionEditRegister = new TDEAction(i18n("Edit"), "edit", 0, this, TQ_SLOT(editRegister()), actionCollection(), "edit_register");

	new TDEAction(i18n("Exp RPN Operation"), CTRL+SHIFT+Key_E, this, TQ_SLOT(insertExp()), actionCollection(), "rpn_exp10");

	setModeActions();

}
void KQalculate::setAssumptionsMenu() {
	switch(CALCULATOR->defaultAssumptions()->sign()) {
		case ASSUMPTION_SIGN_POSITIVE: {SET_TOGGLE_ACTION_ON(ActionAssumptionSignPositive); break;}
		case ASSUMPTION_SIGN_NONPOSITIVE: {SET_TOGGLE_ACTION_ON(ActionAssumptionSignNonPositive); break;}
		case ASSUMPTION_SIGN_NEGATIVE: {SET_TOGGLE_ACTION_ON(ActionAssumptionSignNegative); break;}
		case ASSUMPTION_SIGN_NONNEGATIVE: {SET_TOGGLE_ACTION_ON(ActionAssumptionSignNonNegative); break;}
		case ASSUMPTION_SIGN_NONZERO: {SET_TOGGLE_ACTION_ON(ActionAssumptionSignNonZero); break;}
		default: {SET_TOGGLE_ACTION_ON(ActionAssumptionSignUnknown); }
	}
	switch(CALCULATOR->defaultAssumptions()->type()) {
		case ASSUMPTION_TYPE_INTEGER: {SET_TOGGLE_ACTION_ON(ActionAssumptionTypeInteger); break;}
		case ASSUMPTION_TYPE_RATIONAL: {SET_TOGGLE_ACTION_ON(ActionAssumptionTypeRational); break;}
		case ASSUMPTION_TYPE_COMPLEX: {SET_TOGGLE_ACTION_ON(ActionAssumptionTypeComplex); break;}
		case ASSUMPTION_TYPE_NUMBER: {SET_TOGGLE_ACTION_ON(ActionAssumptionTypeNumber); break;}
		case ASSUMPTION_TYPE_REAL: {SET_TOGGLE_ACTION_ON(ActionAssumptionTypeReal); break;}
		case ASSUMPTION_TYPE_NONMATRIX: {SET_TOGGLE_ACTION_ON(ActionAssumptionTypeNonMatrix); break;}
		default: {SET_TOGGLE_ACTION_ON(ActionAssumptionTypeUnknown); }
	}
}
void KQalculate::setModeActions() {
	
	SET_TOGGLE_ACTION(ActionAllowComplexResult, evalops.allow_complex)
	SET_TOGGLE_ACTION(ActionAllowInfiniteResult, evalops.allow_infinite)
	SET_TOGGLE_ACTION(ActionEnableVariables, evalops.parse_options.variables_enabled)
	SET_TOGGLE_ACTION(ActionEnableFunctions, evalops.parse_options.functions_enabled)
	SET_TOGGLE_ACTION(ActionEnableUnits, evalops.parse_options.units_enabled)
	SET_TOGGLE_ACTION(ActionEnableUnknowns, evalops.parse_options.unknowns_enabled)
	SET_TOGGLE_ACTION(ActionCalculateVariables, evalops.calculate_variables)
	SET_TOGGLE_ACTION(ActionReadPrecision, evalops.parse_options.read_precision != DONT_READ_PRECISION)
	SET_TOGGLE_ACTION(ActionLimitImplicitMultiplication, evalops.parse_options.limit_implicit_multiplication)
	SET_TOGGLE_ACTION(ActionRPNSyntax, evalops.parse_options.rpn)
	SET_TOGGLE_ACTION(ActionRPNMode, rpn_mode)
	SET_TOGGLE_ACTION(ActionNonZeroDenominators, evalops.assume_denominators_nonzero)
	SET_TOGGLE_ACTION(ActionWarnAboutDenominatorsAssumedNonZero, evalops.warn_about_denominators_assumed_nonzero)
	SET_TOGGLE_ACTION(ActionAbbreviateNames, printops.abbreviate_names)
	SET_TOGGLE_ACTION(ActionIndicateInfiniteSeries, printops.indicate_infinite_series)
	SET_TOGGLE_ACTION(ActionSortMinusLast, printops.sort_options.minus_last)
	SET_TOGGLE_ACTION(ActionNegativeExponents, printops.negative_exponents)
	SET_TOGGLE_ACTION(ActionShowEndingZeroes, printops.show_ending_zeroes)
	SET_TOGGLE_ACTION(ActionRoundHalfwayNumbersToEven, printops.round_halfway_to_even)
	SET_TOGGLE_ACTION(ActionEnablePrefixes, printops.use_unit_prefixes)
	SET_TOGGLE_ACTION(ActionEnableUseOfAllPrefixes, printops.use_all_prefixes)
	SET_TOGGLE_ACTION(ActionEnableDenominatorPrefixes, printops.use_denominator_prefix)
	SET_TOGGLE_ACTION(ActionPlaceUnitsSeparately, printops.place_units_separately)

	kpExact->blockSignals(true);
	switch(evalops.approximation) {
		case APPROXIMATION_EXACT: {
			SET_TOGGLE_ACTION_ON(ActionApproximationAlwaysExact);
			kpExact->setOn(true);
			break;
		}
		case APPROXIMATION_TRY_EXACT: {
			SET_TOGGLE_ACTION_ON(ActionApproximationTryExact);
			kpExact->setOn(false);
			break;
		}
		case APPROXIMATION_APPROXIMATE: {
			SET_TOGGLE_ACTION_ON(ActionApproximationApproximate);
			kpExact->setOn(false);
			break;
		}
	}
	kpExact->blockSignals(false);
	switch(evalops.auto_post_conversion) {
		case POST_CONVERSION_BEST: {
			SET_TOGGLE_ACTION_ON(ActionAutoConvertToBestUnit);
			break;
		}
		case POST_CONVERSION_BASE: {
			SET_TOGGLE_ACTION_ON(ActionAutoConvertToBaseUnits);
			break;
		}
		default: {
			SET_TOGGLE_ACTION_ON(ActionAutoNoConversion);
		}
	}
	kpAngleGroup->blockSignals(true);
	switch(evalops.parse_options.angle_unit) {
		case ANGLE_UNIT_DEGREES: {
			SET_TOGGLE_ACTION_ON(ActionAngleUnitDegrees);
			kpAngleGroup->setButton(0);
			break;
		}
		case ANGLE_UNIT_RADIANS: {
			SET_TOGGLE_ACTION_ON(ActionAngleUnitRadians);
			kpAngleGroup->setButton(1);
			break;
		}
		case ANGLE_UNIT_GRADIANS: {
			SET_TOGGLE_ACTION_ON(ActionAngleUnitGradians);
			kpAngleGroup->setButton(2);
			break;
		}
		default: {
			SET_TOGGLE_ACTION_ON(ActionAngleUnitNone);
			kpAngleGroup->setButton(3);
		}
	}
	kpAngleGroup->blockSignals(false);

	kpBaseCombo->blockSignals(true);
	switch(printops.base) {
		case BASE_BINARY: {
			SET_TOGGLE_ACTION_ON(ActionNumberBaseBinary);
			kpBaseCombo->setCurrentItem(0);
			break;
		}
		case BASE_OCTAL: {
			SET_TOGGLE_ACTION_ON(ActionNumberBaseOctal);
			kpBaseCombo->setCurrentItem(1);
			break;
		}
		case BASE_DECIMAL: {
			SET_TOGGLE_ACTION_ON(ActionNumberBaseDecimal);
			kpBaseCombo->setCurrentItem(2);
			break;
		}
		case BASE_HEXADECIMAL: {
			SET_TOGGLE_ACTION_ON(ActionNumberBaseHexadecimal);
			kpBaseCombo->setCurrentItem(3);
			break;
		}
		case BASE_ROMAN_NUMERALS: {
			SET_TOGGLE_ACTION_ON(ActionNumberBaseRomanNumerals);
			kpBaseCombo->setCurrentItem(6);
			break;
		}
		case BASE_SEXAGESIMAL: {
			SET_TOGGLE_ACTION_ON(ActionNumberBaseSexagesimal);
			kpBaseCombo->setCurrentItem(4);
			break;
		}
		case BASE_TIME: {
			SET_TOGGLE_ACTION_ON(ActionNumberBaseTimeFormat);
			kpBaseCombo->setCurrentItem(5);
			break;
		}
		default: {
			SET_TOGGLE_ACTION_ON(ActionNumberBaseOther);
			kpBaseCombo->setCurrentItem(7);
		}
	}
	kpBaseCombo->blockSignals(false);

	kpNumericCombo->blockSignals(true);
	switch(printops.min_exp) {
		case EXP_PRECISION: {
			SET_TOGGLE_ACTION_ON(ActionNumericalDisplayNormal);
			kpNumericCombo->setCurrentItem(0);
			break;
		}
		case EXP_BASE_3: {
			SET_TOGGLE_ACTION_ON(ActionNumericalDisplayEngineering);
			kpNumericCombo->setCurrentItem(1);
			break;
		}
		case EXP_SCIENTIFIC: {
			SET_TOGGLE_ACTION_ON(ActionNumericalDisplayScientific);
			kpNumericCombo->setCurrentItem(2);
			break;
		}
		case EXP_PURE: {
			SET_TOGGLE_ACTION_ON(ActionNumericalDisplayPurelyScientific);
			kpNumericCombo->setCurrentItem(3);
			break;
		}
		case EXP_NONE: {
			SET_TOGGLE_ACTION_ON(ActionNumericalDisplaySimple);
			kpNumericCombo->setCurrentItem(4);
			break;
		}
	}
	kpNumericCombo->blockSignals(false);

	kpFraction->blockSignals(true);
	switch (printops.number_fraction_format) {
		case FRACTION_DECIMAL: {
			SET_TOGGLE_ACTION_ON(ActionFractionalDisplayDecimal);
			kpFraction->setOn(false);
			break;
		}
		case FRACTION_DECIMAL_EXACT: {
			SET_TOGGLE_ACTION_ON(ActionFractionalDisplayDecimalTryExact);
			kpFraction->setOn(false);
			break;
		}
		case FRACTION_COMBINED: {
			SET_TOGGLE_ACTION_ON(ActionFractionalDisplayCombined);
			kpFraction->setOn(true);
			break;
		}
		case FRACTION_FRACTIONAL: {
			SET_TOGGLE_ACTION_ON(ActionFractionalDisplayFraction);
			kpFraction->setOn(true);
			break;
		}
	}
	kpFraction->blockSignals(false);

	setAssumptionsMenu();
	switch(evalops.structuring) {
		case STRUCTURING_SIMPLIFY: {SET_TOGGLE_ACTION_ON(ActionAlgebraicModeSimplify); break;}
		case STRUCTURING_FACTORIZE: {SET_TOGGLE_ACTION_ON(ActionAlgebraicModeFactorize); break;}
		default: {SET_TOGGLE_ACTION_ON(ActionAlgebraicModeNone); }
	}
	
}

#define TEXT_TAGS			"<font size=6>"
#define TEXT_TAGS_END			"</font>"
#define TEXT_TAGS_SMALL			"<font size=5>"
#define TEXT_TAGS_SMALL_END		"</font>"
#define TEXT_TAGS_XSMALL		"<font size=4>"
#define TEXT_TAGS_XSMALL_END		"</font>"

#define STR_MARKUP_ADD_SMALL(str, str_add) 			if(ips.power_depth > 0) {str += TEXT_TAGS "<sup>"; str += str_add; str += "</sup>" TEXT_TAGS_END;} else {str += TEXT_TAGS_SMALL; str += str_add; str += TEXT_TAGS_SMALL_END;}

#define STR_MARKUP_ADD(str, str_add)				if(ips.power_depth > 0) {str += TEXT_TAGS "<sup>"; str += str_add; str += "</sup>" TEXT_TAGS_END;} else {str += str_add;}

#define STR_MARKUP_PREPEND(str, str_add) 			TQString str_prepend; if(ips.power_depth > 0) {str_prepend += TEXT_TAGS "<sup>"; str_prepend += str_add; str_prepend += "</sup>" TEXT_TAGS_END;} else {str_prepend += str_add;} str.prepend(str_prepend);

#define STR_MARKUP_BEGIN(str) 					if(ips.power_depth > 0) {str += TEXT_TAGS "<sup>";}
#define STR_MARKUP_END(str)	 				if(ips.power_depth > 0) {str +="</sup>" TEXT_TAGS_END;}

#define STR_MARKUP_BEGIN_SMALL(str) 				if(ips.power_depth > 0) {str += TEXT_TAGS_SMALL "<sup>";} else {str += TEXT_TAGS_SMALL;}
#define STR_MARKUP_END_SMALL(str) 				if(ips.power_depth > 0) {str +="</sup>" TEXT_TAGS_SMALL_END;} else {str += TEXT_TAGS_SMALL_END;}

#define STR_MARKUP_BEGIN_CURSIVE(str) 				if(ips.power_depth > 0) {str += TEXT_TAGS "<i><sup>";} else {str += "<i>";}
#define STR_MARKUP_END_CURSIVE(str) 				if(ips.power_depth > 0) {str +="</sup></i>" TEXT_TAGS_END;} else {str += "</i>";}

TQString draw_structure(MathStructure &m, const TQFont &font, const TQColorGroup &cg, PrintOptions po = default_print_options, InternalPrintStruct ips = top_ips, bool in_matrix = false) {

	if(ips.depth == 0 && po.is_approximate) *po.is_approximate = false;

	TQString mstr;
	
	InternalPrintStruct ips_n = ips;
	if(m.isApproximate()) ips_n.parent_approximate = true;
	if(m.precision() > 0 && (ips_n.parent_precision < 1 || m.precision() < ips_n.parent_precision)) ips_n.parent_precision = m.precision();
	switch(m.type()) {
		case STRUCT_NUMBER: {
			std::string exp = "";
			bool exp_minus;
			ips_n.exp = &exp;
			ips_n.exp_minus = &exp_minus;
			STR_MARKUP_BEGIN(mstr);
			mstr += m.number().print(po, ips_n).c_str();
			if(!exp.empty()) {
				if(po.lower_case_e) {
					mstr += "e";
				} else {
					STR_MARKUP_ADD_SMALL(mstr, "E");
				}
				if(exp_minus) {
					mstr += "-";
				}
				mstr += exp.c_str();
			}
			if(po.base != BASE_DECIMAL && po.base != BASE_HEXADECIMAL && po.base > 0 && po.base <= 36) {
				if(ips.power_depth == 0) {
					mstr += "<sub>";
					mstr += TQString::number(po.base);
					mstr += "</sub>";
				} else {
					mstr += TEXT_TAGS_SMALL "<sup>"; 
					mstr += TQString::number(po.base); 
					mstr += "</sup>" TEXT_TAGS_SMALL_END;
				}
			}
			STR_MARKUP_END(mstr);
			break;
		}
		case STRUCT_SYMBOLIC: {
			result_parts.push_back(m);
			mstr = "<a name=\"";
			mstr += TQString::number(result_parts.size());
			mstr += "\">";
			STR_MARKUP_BEGIN_CURSIVE(mstr);
			mstr += m.symbol().c_str();
			STR_MARKUP_END_CURSIVE(mstr);
			mstr += "</a>";
			mstr += "<a name=\"";
			mstr += TQString::number(result_parts.size());
			mstr += "\"></a>";
			break;
		}
		case STRUCT_ADDITION: {

			ips_n.depth++;

			std::vector<TQString> terms;
			std::vector<bool> do_space;
			for(size_t i = 0; i < m.size(); i++) {
				if(m[i].type() == STRUCT_NEGATE && i > 0) {
					ips_n.wrap = m[i][0].needsParenthesis(po, ips_n, m, i + 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
					terms.push_back(draw_structure(m[i][0], font, cg, po, ips_n));
				} else {
					ips_n.wrap = m[i].needsParenthesis(po, ips_n, m, i + 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
					terms.push_back(draw_structure(m[i], font, cg, po, ips_n));
				}
				do_space.push_back(!terms[i].endsWith("valign=\"middle\">"));
			}
			for(size_t i = 0; i < terms.size(); i++) {
				if(i > 0) {
					if(do_space[i  - 1]) STR_MARKUP_ADD(mstr, " ");
					if(m[i].type() == STRUCT_NEGATE) {
						if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MINUS, po.can_display_unicode_string_arg))) {
							STR_MARKUP_ADD(mstr, SIGN_MINUS);
						} else {
							STR_MARKUP_ADD(mstr, "-");
						}
					} else {
						STR_MARKUP_ADD(mstr, "+");
					}	
					if(do_space[i]) STR_MARKUP_ADD(mstr, " ");
				}
				mstr += terms[i];
			}
			break;
		}
		case STRUCT_NEGATE: {

			ips_n.depth++;

			ips_n.wrap = m[0].needsParenthesis(po, ips_n, m, 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
			if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MINUS, po.can_display_unicode_string_arg))) {
				STR_MARKUP_ADD(mstr, SIGN_MINUS);
			} else {
				STR_MARKUP_ADD(mstr, "-");
			}
			mstr += draw_structure(m[0], font, cg, po, ips_n);
			break;
		}
		case STRUCT_MULTIPLICATION: {

			ips_n.depth++;

			TQString mul_str;
			if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) {
				STR_MARKUP_ADD(mul_str, SIGN_MULTIDOT);
			} else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIBULLET, po.can_display_unicode_string_arg))) {
				STR_MARKUP_ADD(mul_str, SIGN_MULTIBULLET);
			} else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_SMALLCIRCLE, po.can_display_unicode_string_arg))) {
				STR_MARKUP_ADD(mul_str, SIGN_SMALLCIRCLE);
			} else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) {
				STR_MARKUP_ADD(mul_str, SIGN_MULTIPLICATION);
			} else {
				STR_MARKUP_ADD(mul_str, "*");
			}

			bool par_prev = false;
			std::vector<int> nm;
			std::vector<TQString> terms;
			std::vector<bool> do_space;
			for(size_t i = 0; i < m.size(); i++) {
				ips_n.wrap = m[i].needsParenthesis(po, ips_n, m, i + 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
				terms.push_back(draw_structure(m[i], font, cg, po, ips_n));
				if(!po.short_multiplication && i > 0) {
					nm.push_back(-1);
				} else if(i > 0) {
					nm.push_back(m[i].neededMultiplicationSign(po, ips_n, m, i + 1, ips_n.wrap || (m[i].isPower() && m[i][0].needsParenthesis(po, ips_n, m[i], 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0)), par_prev, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0));
				} else {
					nm.push_back(-1);
				}
				do_space.push_back(!terms[i].endsWith("valign=\"middle\">"));
				par_prev = ips_n.wrap;
			}
			for(size_t i = 0; i < terms.size(); i++) {
				if(!po.short_multiplication && i > 0) {
					if(do_space[i - 1]) STR_MARKUP_ADD(mstr, " ");
					mstr += mul_str;
					if(do_space[i]) STR_MARKUP_ADD(mstr, " ");
				} else if(i > 0) {
					switch(nm[i]) {
						case MULTIPLICATION_SIGN_SPACE: {
							if(do_space[i - 1] && do_space[i]) STR_MARKUP_ADD(mstr, " ");
							break;
						}
						case MULTIPLICATION_SIGN_OPERATOR: {
							if(do_space[i - 1]) STR_MARKUP_ADD(mstr, " ");
							mstr += mul_str;
							if(do_space[i]) STR_MARKUP_ADD(mstr, " ");
							break;
						}
						case MULTIPLICATION_SIGN_OPERATOR_SHORT: {
							mstr += mul_str;
							break;
						}
					}
				}
				mstr += terms[i];
			}
			break;
		}
		case STRUCT_INVERSE: {}
		case STRUCT_DIVISION: {
			
			ips_n.depth++;
			ips_n.division_depth++;
			
			bool flat = ips.division_depth > 0 || ips.power_depth > 0;
			if(!flat && po.place_units_separately) {
				flat = true;
				size_t i = 0;
				if(m.isDivision()) {
					i = 1;
				}
				if(m[i].isMultiplication()) {
					for(size_t i2 = 0; i2 < m[i].size(); i2++) {
						if(!m[i][i2].isUnit_exp()) {
							flat = false;
							break;
						}
					}
				} else if(!m[i].isUnit_exp()) {
					flat = false;
				}
				if(flat) {
					ips_n.division_depth--;
				}
			}
			TQString num_str, den_str;
			if(m.type() == STRUCT_DIVISION) {
				ips_n.wrap = (!m[0].isDivision() || !flat || ips.division_depth > 0 || ips.power_depth > 0) && m[0].needsParenthesis(po, ips_n, m, 1, flat, ips.power_depth > 0);
				num_str = draw_structure(m[0], font, cg, po, ips_n);
			} else {
				MathStructure onestruct(1, 1);
				ips_n.wrap = false;
				num_str = draw_structure(onestruct, font, cg, po, ips_n);
			}
			if(m.type() == STRUCT_DIVISION) {
				ips_n.wrap = m[1].needsParenthesis(po, ips_n, m, 2, flat, ips.power_depth > 0);
				den_str = draw_structure(m[1], font, cg, po, ips_n);
			} else {
				ips_n.wrap = m[0].needsParenthesis(po, ips_n, m, 2, flat, ips.power_depth > 0);
				den_str = draw_structure(m[0], font, cg, po, ips_n);
			}

			if(flat) {
				TQString div_str;
				if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION, po.can_display_unicode_string_arg))) {
					STR_MARKUP_ADD(div_str, " " SIGN_DIVISION " ");
				} else if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION_SLASH && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION_SLASH, po.can_display_unicode_string_arg))) {
					STR_MARKUP_ADD(div_str, " " SIGN_DIVISION_SLASH " ");
				} else {
					STR_MARKUP_ADD(div_str, " / ");
				}
				mstr = num_str;
				mstr += div_str;
				mstr += den_str;
			} else {

				int den_w, num_w, w = 0, h = 0;
		
				num_str.prepend(TEXT_TAGS);
				num_str += TEXT_TAGS_END;
				den_str.prepend(TEXT_TAGS);
				den_str += TEXT_TAGS_END;
				
				TQSimpleRichText text_r(num_str, font); text_r.setWidth(10000);
				num_w = text_r.widthUsed();
				TQSimpleRichText text_rn(den_str, font); text_rn.setWidth(10000);				
				den_w = text_rn.widthUsed();

				w = den_w;
				if(num_w > w) w = num_w;
				w += 2;

				TQSimpleRichText textsmall("<font size=\"1\">X</font>", font);
				h = (int) (textsmall.height() / 1.5);
				h += h % 2;

				std::string filename = getLocalDir();
				if(saved_divisionline_height != h) {
				
					TQPixmap *pixmap = new TQPixmap(10, h);
					pixmap->fill(cg.background());
					TQPainter p(pixmap);
					TQPen ppen = p.pen();
					ppen.setColor(cg.foreground());
					p.setPen(ppen);
					p.drawLine(0, h / 2, 10, h / 2);
					p.drawLine(0, h / 2 + 1, 10, h / 2 + 1);
					p.flush();
					p.end();

					pixmap->setMask(pixmap->createHeuristicMask());					
					mkdir(filename.c_str(), S_IRWXU);
					filename += "tmp/";
					mkdir(filename.c_str(), S_IRWXU);
					filename += "divline.png";
					pixmap->save(filename.c_str(), "PNG", 100);

					delete pixmap;
					
					saved_divisionline_height = h;
					
				} else {

					filename += "tmp/divline.png";
					
				}

				mstr = TEXT_TAGS_END;
				mstr = "</td><td width=1 align=\"center\" valign=\"middle\">";
				mstr += num_str;
				mstr += "<br><font size=1><img align=\"middle\" width=";
				mstr += TQString::number(w);
				mstr += " height=";
				mstr += TQString::number(h);
				mstr += " src=\"";
				mstr += filename.c_str();
				mstr += "\"><br></font>";
				mstr += den_str;
				mstr += "</td><td width=1 align=\"center\" valign=\"middle\">";
				mstr += TEXT_TAGS;

			}
			break;
		}
		case STRUCT_POWER: {

			ips_n.depth++;

			ips_n.wrap = m[0].needsParenthesis(po, ips_n, m, 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);

			ips_n.division_depth++;
			mstr += draw_structure(m[0], font, cg, po, ips_n);
			ips_n.division_depth--;

			ips_n.power_depth++;
			ips_n.wrap = m[1].needsParenthesis(po, ips_n, m, 2, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);

			PrintOptions po2 = po;
			po2.show_ending_zeroes = false;
			if(ips.power_depth > 0) {
				mstr += TEXT_TAGS "<sup>" "^" "</sup>" TEXT_TAGS_END;
				mstr += draw_structure(m[1], font, cg, po2, ips_n);
			} else {
				mstr += draw_structure(m[1], font, cg, po2, ips_n);
			}

			break;
		}
		case STRUCT_LOGICAL_AND: {
			if(!po.preserve_format && m.size() == 2 && m[0].isComparison() && m[1].isComparison() && m[0].comparisonType() != COMPARISON_EQUALS && m[0].comparisonType() != COMPARISON_NOT_EQUALS && m[1].comparisonType() != COMPARISON_EQUALS && m[1].comparisonType() != COMPARISON_NOT_EQUALS && m[0][0] == m[1][0]) {
			
				ips_n.depth++;

				bool do_space = true;
				TQString tstr;
				ips_n.wrap = m[0][1].needsParenthesis(po, ips_n, m[0], 2, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
				tstr = draw_structure(m[0][1], font, cg, po, ips_n);
				do_space = !tstr.endsWith("valign=\"middle\">");
				mstr += tstr;
				STR_MARKUP_BEGIN(mstr);
				if(do_space) mstr += " ";
				switch(m[0].comparisonType()) {
					case COMPARISON_LESS: {
						mstr += "&gt;";
						break;
					}
					case COMPARISON_GREATER: {
						mstr += "&lt;";
						break;
					}
					case COMPARISON_EQUALS_LESS: {
						if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) {
							mstr += SIGN_GREATER_OR_EQUAL;
						} else {
							mstr += "&gt;=";
						}
						break;
					}
					case COMPARISON_EQUALS_GREATER: {
						if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) {
							mstr += SIGN_LESS_OR_EQUAL;
						} else {
							mstr += "&lt;=";
						}
						break;
					}
					default: {}
				}				
				
				ips_n.wrap = m[0][0].needsParenthesis(po, ips_n, m[0], 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
				tstr = draw_structure(m[0][0], font, cg, po, ips_n);
				do_space = !tstr.endsWith("valign=\"middle\">");
				if(do_space) mstr += " ";
				STR_MARKUP_END(mstr);
				mstr += tstr;
				STR_MARKUP_BEGIN(mstr);
				if(do_space) mstr += " ";
				
				switch(m[1].comparisonType()) {
					case COMPARISON_GREATER: {
						mstr += "&gt;";
						break;
					}
					case COMPARISON_LESS: {
						mstr += "&lt;";
						break;
					}
					case COMPARISON_EQUALS_GREATER: {
						if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) {
							mstr += SIGN_GREATER_OR_EQUAL;
						} else {
							mstr += "&gt;=";
						}
						break;
					}
					case COMPARISON_EQUALS_LESS: {
						if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) {
							mstr += SIGN_LESS_OR_EQUAL;
						} else {
							mstr += "&lt;=";
						}
						break;
					}
					default: {}
				}				
				
				ips_n.wrap = m[1][1].needsParenthesis(po, ips_n, m[1], 2, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
				tstr = draw_structure(m[1][1], font, cg, po, ips_n);
				do_space = !tstr.endsWith("valign=\"middle\">");
				if(do_space) mstr += " ";
				STR_MARKUP_END(mstr);
				mstr += tstr;
			
				break;
			}
		}
		case STRUCT_COMPARISON: {}
		case STRUCT_LOGICAL_XOR: {}
		case STRUCT_LOGICAL_OR: {}
		case STRUCT_BITWISE_AND: {}
		case STRUCT_BITWISE_XOR: {}
		case STRUCT_BITWISE_OR: {
			
			ips_n.depth++;

			TQString str;
			if(m.type() == STRUCT_COMPARISON) {
				switch(m.comparisonType()) {
					case COMPARISON_EQUALS: {						
						break;
					}
					case COMPARISON_NOT_EQUALS: {
						if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_NOT_EQUAL, po.can_display_unicode_string_arg))) {
							str += SIGN_NOT_EQUAL;
						} else {
							str += "!=";
						}
						break;
					}
					case COMPARISON_GREATER: {
						str += "&gt;";
						break;
					}
					case COMPARISON_LESS: {
						str += "&lt;";
						break;
					}
					case COMPARISON_EQUALS_GREATER: {
						if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) {
							str += SIGN_GREATER_OR_EQUAL;
						} else {
							str += "&gt;=";
						}
						break;
					}
					case COMPARISON_EQUALS_LESS: {
						if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) {
							str += SIGN_LESS_OR_EQUAL;
						} else {
							str += "&lt;=";
						}
						break;
					}
				}
			} else if(m.type() == STRUCT_LOGICAL_AND) {
				str += "<a name=\"+Logical AND\">";
				if(po.spell_out_logical_operators) str += i18n("and");
				else str += "&amp;&amp;";
				str += "</a>";
			} else if(m.type() == STRUCT_LOGICAL_OR) {
				str += "<a name=\"+Logical inclusive OR\">";
				if(po.spell_out_logical_operators) str += i18n("or");
				else str += "||";
				str += "</a>";
			} else if(m.type() == STRUCT_LOGICAL_XOR) {
				str += "<a name=\"+Logical exclusive OR\">XOR</a>";				
			} else if(m.type() == STRUCT_BITWISE_AND) {
				str += "<a name=\"+Bitwise AND\">&amp;</a>";
			} else if(m.type() == STRUCT_BITWISE_OR) {
				str += "<a name=\"+Bitwise inclusive OR\">|</a>";
			} else if(m.type() == STRUCT_BITWISE_XOR) {
				str += "<a name=\"+Bitwise exclusive XOR\">XOR</a>";
			}

			bool do_space = true, do_space_prev = true;
			TQString tstr;
			for(size_t i = 0; i < m.size(); i++) {
				do_space_prev = do_space;
				ips_n.wrap = m[i].needsParenthesis(po, ips_n, m, i + 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
				tstr = draw_structure(m[i], font, cg, po, ips_n);
				do_space = !tstr.endsWith("valign=\"middle\">");
				if(i > 0) {
					STR_MARKUP_BEGIN(mstr);
					if(do_space_prev) mstr += " ";
					if(m.isComparison() && m.comparisonType() == COMPARISON_EQUALS) {
						if(ips.depth == 0 && po.use_unicode_signs && (*po.is_approximate || m.isApproximate()) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_ALMOST_EQUAL, po.can_display_unicode_string_arg))) {
							mstr += SIGN_ALMOST_EQUAL;
						} else {
							mstr += "=";
						}
					} else {			
						mstr += str;
					}
					if(do_space) mstr += " ";
					STR_MARKUP_END(mstr);
				}
				mstr += tstr;
			}
			break;
		}
		case STRUCT_BITWISE_NOT: {

			ips_n.depth++;

			STR_MARKUP_BEGIN(mstr);

			mstr += "<a name=\"+Bitwise NOT\">~</a>";

			ips_n.wrap = m[0].needsParenthesis(po, ips_n, m, 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
			mstr += draw_structure(m[0], font, cg, po, ips_n);
			
			STR_MARKUP_END(mstr);

			break;
		}
		case STRUCT_LOGICAL_NOT: {

			ips_n.depth++;

			STR_MARKUP_BEGIN(mstr);

			mstr += "<a name=\"+Logical NOT\">!</a>";

			ips_n.wrap = m[0].needsParenthesis(po, ips_n, m, 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
			mstr += draw_structure(m[0], font, cg, po, ips_n);
			
			STR_MARKUP_END(mstr);

			break;
		}
		case STRUCT_VECTOR: {
			
			ips_n.depth++;
			
			bool is_matrix = m.isMatrix();
			if(!in_matrix) {
				result_parts.push_back(m);
				mstr = "<a name=\"";
				mstr += TQString::number(result_parts.size());
				mstr += "\">";
			}

			if(m.size() == 0) {
				STR_MARKUP_ADD(mstr, "( ");
			} else {
				STR_MARKUP_ADD(mstr, "(");
			}
			for(size_t index = 0; index < m.size(); index++) {
				if(index > 0) {
					STR_MARKUP_BEGIN(mstr);
					mstr += CALCULATOR->getComma().c_str();
					mstr += " ";
					STR_MARKUP_END(mstr);
				}
				ips_n.wrap = m[index].needsParenthesis(po, ips_n, m, index + 1, ips.division_depth > 0 || ips.power_depth > 0, ips.power_depth > 0);
				mstr += draw_structure(m[index], font, cg, po, ips_n, is_matrix);
			}
			STR_MARKUP_ADD(mstr, ")");
			if(!in_matrix) mstr += "</a>";
			break;
		}
		case STRUCT_UNIT: {

			result_parts.push_back(m);
			mstr = "<a name=\"";
			mstr += TQString::number(result_parts.size());
			mstr += "\">";

			STR_MARKUP_BEGIN(mstr);
			
			TQString str;
			const ExpressionName *ename = &m.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, m.isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
			if(m.prefix()) {
				str += m.prefix()->name(po.abbreviate_names && ename->abbreviation && (ename->suffix || ename->name.find("_") == std::string::npos), po.use_unicode_signs, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).c_str();
			}
			if(ename->suffix && ename->name.length() > 1) {
				size_t i = ename->name.rfind('_');
				bool b = i == std::string::npos || i == ename->name.length() - 1 || i == 0;
				size_t i2 = 1;
				if(b) {
					if(is_in(NUMBERS, ename->name[ename->name.length() - 1])) {
						while(ename->name.length() > i2 + 1 && is_in(NUMBERS, ename->name[ename->name.length() - 1 - i2])) {
							i2++;
						}
					}
					str += ename->name.substr(0, ename->name.length() - i2).c_str();
				} else {
					str += ename->name.substr(0, i).c_str();
				}
				if(ips.power_depth == 0) str += "<sub>";
				else str += TEXT_TAGS_SMALL "<sup>";
				if(b) str += ename->name.substr(ename->name.length() - i2, i2).c_str();
				else str += ename->name.substr(i + 1, ename->name.length() - (i + 1)).c_str();
				if(ips.power_depth == 0) str += "</sub>";
				else str += "</sup>" TEXT_TAGS_SMALL_END;
			} else {
				str += ename->name.c_str();				
			}
			str.replace("_", " ");
			mstr += str;

			STR_MARKUP_END(mstr);
			mstr += "</a>";
			mstr += "<a name=\"";
			mstr += TQString::number(result_parts.size());
			mstr += "\"></a>";
			
			break;
		}
		case STRUCT_VARIABLE: {

			result_parts.push_back(m);
			mstr = "<a name=\"";
			mstr += TQString::number(result_parts.size());
			mstr += "\">";
			if(m.variable() == CALCULATOR->v_i) {
				STR_MARKUP_BEGIN(mstr);
			} else {
				STR_MARKUP_BEGIN_CURSIVE(mstr);
			}
			
			TQString str;
			const ExpressionName *ename = &m.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
			if(ename->suffix && ename->name.length() > 1) {
				size_t i = ename->name.rfind('_');
				bool b = i == std::string::npos || i == ename->name.length() - 1 || i == 0;
				size_t i2 = 1;
				if(b) {
					if(is_in(NUMBERS, ename->name[ename->name.length() - 1])) {
						while(ename->name.length() > i2 + 1 && is_in(NUMBERS, ename->name[ename->name.length() - 1 - i2])) {
							i2++;
						}
					}
					str += ename->name.substr(0, ename->name.length() - i2).c_str();
				} else {
					str += ename->name.substr(0, i).c_str();
				}
				if(ips.power_depth == 0) str += "<sub>";
				else str += TEXT_TAGS_SMALL "<sup>";
				if(b) str += ename->name.substr(ename->name.length() - i2, i2).c_str();
				else str += ename->name.substr(i + 1, ename->name.length() - (i + 1)).c_str();
				if(ips.power_depth == 0) str += "</sub>";
				else str += "</sup>" TEXT_TAGS_SMALL_END;
			} else {
				str += ename->name.c_str();
			}
			str.replace("_", " ");
			mstr += str;
			
			if(m.variable() == CALCULATOR->v_i) {
				STR_MARKUP_END(mstr);
			} else {
				STR_MARKUP_END_CURSIVE(mstr);
			}
			mstr += "</a>";
			/*result_parts.push_back(m);
			mstr += "<a name=\"";
			mstr += TQString::number(result_parts.size());
			mstr += "\"></a>";*/
			break;
		}
		case STRUCT_FUNCTION: {

			ips_n.depth++;
			
			result_parts.push_back(m);
			mstr = "<a name=\"";
			mstr += TQString::number(result_parts.size());
			mstr += "\">";
			
			STR_MARKUP_BEGIN(mstr);
			
			TQString str;
			const ExpressionName *ename = &m.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg);
			if(ename->suffix && ename->name.length() > 1) {
				size_t i = ename->name.rfind('_');
				bool b = i == std::string::npos || i == ename->name.length() - 1 || i == 0;
				size_t i2 = 1;
				if(b) {
					if(is_in(NUMBERS, ename->name[ename->name.length() - 1])) {
						while(ename->name.length() > i2 + 1 && is_in(NUMBERS, ename->name[ename->name.length() - 1 - i2])) {
							i2++;
						}
					}
					str += ename->name.substr(0, ename->name.length() - i2).c_str();
				} else {
					str += ename->name.substr(0, i).c_str();
				}
				if(ips.power_depth == 0) str += "<sub>";
				else str += TEXT_TAGS_SMALL "<sup>";
				if(b) str += ename->name.substr(ename->name.length() - i2, i2).c_str();
				else str += ename->name.substr(i + 1, ename->name.length() - (i + 1)).c_str();
				if(ips.power_depth == 0) str += "</sub>";
				else str += "</sup>" TEXT_TAGS_SMALL_END;
			} else {
				str += ename->name.c_str();
			}
			str.replace("_", " ");
			mstr += str;

			mstr += "(";
			STR_MARKUP_END(mstr);
			mstr += "</a>";

			for(size_t index = 0; index < m.size(); index++) {
				if(index > 0) {
					STR_MARKUP_BEGIN(mstr);
					mstr += po.comma().c_str();
					mstr += " ";
					STR_MARKUP_END(mstr);
				}
				mstr += draw_structure(m[index], font, cg, po, ips_n);
			}
			STR_MARKUP_ADD(mstr, ")");
			
			break;
		}
		case STRUCT_UNDEFINED: {
			STR_MARKUP_ADD(mstr, i18n("undefined"));
			break;
		}
		default: {
		}
	}
	if(ips.wrap) {
		STR_MARKUP_PREPEND(mstr, "(");
		STR_MARKUP_ADD(mstr, ")");
	}
	if(ips.depth == 0 && !(m.isComparison() && (!(*po.is_approximate || m.isApproximate()) || (m.comparisonType() == COMPARISON_EQUALS && po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_ALMOST_EQUAL, po.can_display_unicode_string_arg)))))) {
		TQString equals_str;
		if(*po.is_approximate || m.isApproximate()) {
			if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_ALMOST_EQUAL, po.can_display_unicode_string_arg))) {
				equals_str = SIGN_ALMOST_EQUAL " ";
			} else {
				equals_str += i18n("approx.");
				equals_str += " ";
			}
		} else {
			equals_str = "= ";
		}
		mstr.prepend(equals_str);
	}
	if(ips.depth == 0) {
		mstr.prepend(TEXT_TAGS);
		mstr += TEXT_TAGS_END;
	}
	
	return mstr;
	
}

#define STATUS_SPACE	if(b) str += "  "; else b = true;

void KQalculate::update_status_text() {

	TQString str;
	bool b = false;
	
	if(evalops.approximation == APPROXIMATION_EXACT) {
		STATUS_SPACE
		str += i18n("EXACT");
	} else if(evalops.approximation == APPROXIMATION_APPROXIMATE) {
		STATUS_SPACE
		str += i18n("APPROX");
	}
	if(evalops.parse_options.rpn) {
		STATUS_SPACE
		str += i18n("RPN");
	}
	switch(evalops.parse_options.base) {
		case BASE_DECIMAL: {
			break;
		}
		case BASE_BINARY: {
			STATUS_SPACE
			str += i18n("BIN");
			break;
		}
		case BASE_OCTAL: {
			STATUS_SPACE
			str += i18n("OCT");
			break;
		}
		case BASE_HEXADECIMAL: {
			STATUS_SPACE
			str += i18n("HEX");
			break;
		}
		case BASE_ROMAN_NUMERALS: {
			STATUS_SPACE
			str += i18n("ROMAN");
			break;
		}
		default: {
			STATUS_SPACE
			str += TQString::number(evalops.parse_options.base);
			break;
		}
	}
	switch (evalops.parse_options.angle_unit) {
		case ANGLE_UNIT_DEGREES: {
			STATUS_SPACE
			str += i18n("DEG");
			break;
		}
		case ANGLE_UNIT_RADIANS: {
			STATUS_SPACE
			str += i18n("RAD");
			break;
		}
		case ANGLE_UNIT_GRADIANS: {
			STATUS_SPACE
			str += i18n("GRA");
			break;
		}
		default: {}
	}
	if(evalops.parse_options.read_precision != DONT_READ_PRECISION) {
		STATUS_SPACE
		str += i18n("PREC");
	}
	if(!evalops.parse_options.functions_enabled) {
		STATUS_SPACE
		str += "<s>";
		str += i18n("FUNC");
		str += "</s>";
	}
	if(!evalops.parse_options.units_enabled) {
		STATUS_SPACE
		str += "<s>";
		str += i18n("UNIT");
		str += "</s>";
	}
	if(!evalops.parse_options.variables_enabled) {
		STATUS_SPACE
		str += "<s>";
		str += i18n("VAR");
		str += "</s>";
	}
	if(!evalops.allow_infinite) {
		STATUS_SPACE
		str += "<s>";
		str += i18n("INF");
		str += "</s>";
	}
	if(!evalops.allow_complex) {
		STATUS_SPACE
		str += "<s>";
		str += i18n("CPLX");
		str += "</s>";
	}
	str = str.stripWhiteSpace();
	if(b) str += "&nbsp;";
	else str += "&nbsp;&nbsp;";
	
	if(str != statusLabel_r->text()) {
		statusLabel_r->setText(str);
		tqApp->processEvents();
		displayParseStatus();
	}
	
}


void on_abort_display() {
	pthread_cancel(view_thread);
	CALCULATOR->restoreState();
	CALCULATOR->clearBuffers();
	b_busy = false;
	pthread_create(&view_thread, &view_thread_attr, view_proc, view_pipe_r);
}

void *view_proc(void *pipe) {

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);	
	FILE *view_pipe = (FILE*) pipe;

	while(true) {

		bool *do_wrap;
		void *x = NULL;
		fread(&x, sizeof(void*), 1, view_pipe);
		KQalculate *win = (KQalculate*) x;
		fread(&x, sizeof(void*), 1, view_pipe);
		MathStructure m(*((MathStructure*) x));
		fread(&x, sizeof(void*), 1, view_pipe);
		MathStructure *mm = (MathStructure*) x;
		fread(&do_wrap, sizeof(bool*), 1, view_pipe);
		fread(&x, sizeof(void*), 1, view_pipe);
		printops.can_display_unicode_string_arg = (void*) win->historyBrowser;
		if(x) {
			PrintOptions po;
			po.preserve_format = true;
			po.show_ending_zeroes = true;
			po.lower_case_e = printops.lower_case_e;
			po.lower_case_numbers = printops.lower_case_numbers;
			po.base_display = printops.base_display;
			po.abbreviate_names = false;
			po.use_unicode_signs = printops.use_unicode_signs;
			po.multiplication_sign = printops.multiplication_sign;
			po.division_sign = printops.division_sign;
			po.short_multiplication = false;
			po.excessive_parenthesis = true;
			po.improve_division_multipliers = false;
			po.can_display_unicode_string_function = &can_display_unicode_string_function;
			po.can_display_unicode_string_arg = (void*) win->statusLabel_l;
			po.spell_out_logical_operators = printops.spell_out_logical_operators;
			po.restrict_to_parent_precision = false;
			MathStructure mp(*((MathStructure*) x));
			fread(&po.is_approximate, sizeof(bool*), 1, view_pipe);
			mp.format(po);
			parsed_text = mp.print(po).c_str();
			fread(&x, sizeof(void*), 1, view_pipe);
			mp.set(*((MathStructure*) x));
			if(!mp.isUndefined()) {
				mp.format(po);
				parsed_text += CALCULATOR->localToString().c_str();
				parsed_text += mp.print(po).c_str();
			}
		}
		printops.allow_non_usable = false;
		if(mm && m.isMatrix()) {
			mm->set(m);
			MathStructure mm2(m);
			std::string mstr;
			int c = mm->columns(), r = mm->rows();
			for(int index_r = 0; index_r < r; index_r++) {
				for(int index_c = 0; index_c < c; index_c++) {
					mm->getElement(index_r + 1, index_c + 1)->set(i18n("aborted").ascii());
				}
			}
			for(int index_r = 0; index_r < r; index_r++) {
				for(int index_c = 0; index_c < c; index_c++) {
					mm2.getElement(index_r + 1, index_c + 1)->format(printops);
					mstr = mm2.getElement(index_r + 1, index_c + 1)->print(printops);
					mm->getElement(index_r + 1, index_c + 1)->set(mstr);
				}
			}
		}
		m.format(printops);
		result_history_text = m.print(printops).c_str();
		printops.can_display_unicode_string_arg = NULL;
		/*if(result_history_text.length() > 5000) {
			result_text = i18n("result is too long\nsee history");
			*printops.is_approximate = false;
		} else */
		if(mm && result_text == i18n("aborted")) {
			result_text = i18n("calculation was aborted");
			*printops.is_approximate = false;
		} else if(mm) {
			printops.allow_non_usable = true;
			printops.can_display_unicode_string_arg = (void*) win->resultLabel;
			TQFont font(win->resultLabel->font());
			result_text = draw_structure(m, font, win->resultLabel->colorGroup(), printops);
			if(result_text.find("</td>") >= 0) {
				result_text.prepend("<div align=\"right\"><table width=1 cellspacing=0 cellpadding=0 border=0><tr><td width=1 align=\"center\" valign=\"middle\">");
				result_text += "</td></tr></table></div>";
				*do_wrap = false;
			} else {
				result_text.prepend("<div align=\"right\"><font size=2>&nbsp;<br></font>");
				result_text += "</div>";
				*do_wrap = true;
			}
			printops.can_display_unicode_string_arg = NULL;
			printops.allow_non_usable = false;
		}
		b_busy = false;
	}
	return NULL;
}

void KQalculate::clearresult() {	
	resultLabel->setRightMargin(10);
	resultLabel->setText("<font size=6> </font>");
	parsed_text = "";
	result_parts.clear();
}

void reduceDivLineSize(QalculateResultDisplay *resultLabel) {

	TQString str = result_text;
	TQColorGroup cg = resultLabel->colorGroup();
	int rt_i = 0;
	while(true) {
			
		int i2 = str.find("</td><td width=1 align=\"center\" valign=\"middle\">", 0);
		if(i2 < 0) break;
		str.remove(0, i2 + 48);
		rt_i += i2 + 48;
		i2 = str.find("<br>", 0);
		if(i2 < 0) break;
		int width_i = rt_i + i2 + 43;
		TQString num_str = str;
		num_str.truncate(i2);
		
		i2 = str.find("<br>", i2 + 4);
		if(i2 < 0) break;
		str.remove(0, i2 + 11);
		rt_i += i2 + 11;
		i2 = str.find("</td><td width=1 align=\"center\" valign=\"middle\">", 0);
		if(i2 < 0) break;
		TQString den_str = str;
		den_str.truncate(i2);
		str.remove(0, i2 + 48);
		rt_i += i2 + 48;
				
		int den_w, num_w, w = 0, h = 0;
		TQSimpleRichText text_r(num_str, resultLabel->font()); text_r.setWidth(10000);
		num_w = text_r.widthUsed();
		TQSimpleRichText text_rn(den_str, resultLabel->font()); text_rn.setWidth(10000);				
		den_w = text_rn.widthUsed();
			
		w = den_w;
		if(num_w > w) w = num_w;
		w += 2;
				
		TQSimpleRichText textsmall("<font size=\"1\">X</font>", resultLabel->font());
		h = (int) (textsmall.height() / 1.5);
		h += h % 2;

		std::string filename = getLocalDir();
		if(saved_divisionline_height != h) {
				
			TQPixmap *pixmap = new TQPixmap(10, h);
			pixmap->fill(cg.background());
			TQPainter p(pixmap);
			TQPen ppen = p.pen();
			ppen.setColor(cg.foreground());
			p.setPen(ppen);
			p.drawLine(0, h / 2, 10, h / 2);
			p.drawLine(0, h / 2 + 1, 10, h / 2 + 1);
			p.flush();
			p.end();

			pixmap->setMask(pixmap->createHeuristicMask());					
			mkdir(filename.c_str(), S_IRWXU);
			filename += "tmp/";
			mkdir(filename.c_str(), S_IRWXU);
			filename += "divline.png";
			pixmap->save(filename.c_str(), "PNG", 100);

			delete pixmap;
					
			saved_divisionline_height = h;
					
		} else {

			filename += "tmp/divline.png";
					
		}
				
		int height_i = result_text.find(" height=", width_i);
		if(height_i < 0) break;
		num_str = TQString::number(w);
		result_text.replace(width_i, height_i - width_i, num_str);
		int i_diff = num_str.length() - (height_i - width_i);
		rt_i += i_diff;
		height_i += i_diff;
		height_i += 8;
		int height_i_end = result_text.find(" src=", height_i);
		if(height_i_end < 0) break;
		num_str = TQString::number(h);
		result_text.replace(height_i, height_i_end - height_i, num_str);
		i_diff = num_str.length() - (height_i_end - height_i);
		rt_i += i_diff;
				
	}
	
}

Prefix *set_result_prefix;
bool set_result_update_history;
bool set_result_update_parse;
bool set_result_force;
TQString set_result_transformation;
size_t set_result_stack_index;
bool set_result_register_moved;

void KQalculate::setResult(Prefix *prefix, bool update_history, bool update_parse, bool force, TQString transformation, size_t stack_index, bool register_moved) {
	if(expression_has_changed && !rpn_mode) {
		if(!force) return;
		execute_expression();
		if(!prefix) return;
	}
	set_result_prefix = prefix;
	set_result_update_history = update_history;
	set_result_update_parse = update_parse;
	set_result_force = force;
	set_result_transformation = transformation;
	set_result_stack_index = stack_index;
	set_result_register_moved = register_moved;
	TQTimer::singleShot(0, this, TQ_SLOT(setResult2()));
}
void KQalculate::setResult2() {
	if(block_result_update) return;
	Prefix *prefix = set_result_prefix;
	bool update_history = set_result_update_history;
	bool update_parse = set_result_update_parse;
	bool force = set_result_force;
	bool register_moved = set_result_register_moved;
	TQString transformation = set_result_transformation;
	size_t stack_index = set_result_stack_index;

	if(!rpn_mode) stack_index = 0;
	if(stack_index != 0) {
		update_history = true;
		update_parse = false;
	}
	if(register_moved) {
		update_history = true;
		update_parse = false;
	}

	error_timer->stop();
	b_busy = true;	

	uint history_index = 0;
	int inhistory_index = 0;
	if(update_history) {
		if(update_parse || register_moved) {
			TQString text;
			if(register_moved) {
				text = i18n("RPN Register Moved");
				inhistory.insert(inhistory.begin(), TQString::null);
				inhistory_type.insert(inhistory_type.begin(), QALCULATE_HISTORY_REGISTER_MOVED);
				inhistory_id.insert(inhistory_id.begin(), inhistory_current_id);
				inhistory_current_id++;
				inhistory_index++;
			} else {
				TQString text2 = result_history_text;
				text2.replace("&", "&amp;");
				text2.replace(">", "&gt;");
				text2.replace("<", "&lt;");
				text = "<a name=\"";
				text += TQString::number(inhistory_current_id);
				text += "\">";
				text += text2;
				text += "</a>";
				inhistory.insert(inhistory.begin(), text2);
				inhistory_type.insert(inhistory_type.begin(), QALCULATE_HISTORY_EXPRESSION);
				inhistory_id.insert(inhistory_id.begin(), inhistory_current_id);
				inhistory_index++;
				inhistory_current_id++;
			}
			int l = text.length();
			text += " <br><hr>";
			text += historyBrowser->text();
			history_index = l + 1;
			historyBrowser->setText(text);
		} else if(initial_result_index == 0) {
			b_busy = false;
			error_timer->start(100);
			return;
		} else {
			inhistory_index = initial_inhistory_index;
			if(!transformation.isEmpty()) {
				transformation.replace("&", "&amp;");
				transformation.replace(">", "&gt;");
				transformation.replace("<", "&lt;");
				inhistory.insert(inhistory.begin(), transformation);
				inhistory_type.insert(inhistory_type.begin() + inhistory_index, QALCULATE_HISTORY_TRANSFORMATION);
				inhistory_id.insert(inhistory_id.begin() + inhistory_index, inhistory_current_id);
				inhistory_current_id++;
				inhistory_index++;
				transformation.insert(0, "<i>");
				transformation += ":  </i><br>";
				TQString text = historyBrowser->text();
				text.insert(initial_result_index, transformation);
				historyBrowser->setText(text);
				initial_result_index += transformation.length() - 4;
			}
			history_index = initial_result_index;
		}
		result_history_text = "?";
	}
	if(update_parse) {
		parsed_text = i18n("aborted");
	}

	if(stack_index == 0) {
		resultLabel->setRightMargin(10);
		resultLabel->setText("<font size=6> </font>");
		result_parts.clear();
		result_text = i18n("result processing was aborted");
	}

	*printops.is_approximate = false;

	printops.prefix = prefix;

	CALCULATOR->saveState();

	bool parsed_approx = false;
	bool do_wrap = true;
	KQalculate *win = this;
	fwrite(&win, sizeof(void*), 1, view_pipe_w);
	if(stack_index == 0) {
		fwrite(&mstruct, sizeof(void*), 1, view_pipe_w);
		matrix_mstruct->clear();
		fwrite(&matrix_mstruct, sizeof(void*), 1, view_pipe_w);
	} else {
		MathStructure *mreg = CALCULATOR->getRPNRegister(stack_index + 1);
		fwrite(&mreg, sizeof(void*), 1, view_pipe_w);
		void *x = NULL;
		fwrite(&x, sizeof(void*), 1, view_pipe_w);
	}
	bool *b = &do_wrap;
	fwrite(&b, sizeof(bool*), 1, view_pipe_w);
	if(update_parse) {
		fwrite(&parsed_mstruct, sizeof(void*), 1, view_pipe_w);
		bool *parsed_approx_p = &parsed_approx;
		fwrite(&parsed_approx_p, sizeof(void*), 1, view_pipe_w);
		fwrite(&parsed_tostruct, sizeof(void*), 1, view_pipe_w);
	} else {
		void *x = NULL;
		fwrite(&x, sizeof(void*), 1, view_pipe_w);
	}
	fflush(view_pipe_w);

	struct timespec rtime;
	rtime.tv_sec = 0;
	rtime.tv_nsec = 20000000;
	int i = 0;
	while(b_busy && i < 50) {
		nanosleep(&rtime, NULL);
		i++;
	}
	i = 0;

	KProgressDialog *dialog = NULL;
	if(b_busy) {
		dialog = new KProgressDialog(this, "display_progress_dialog", i18n("Processing..."), i18n("Processing..."), true);
		dialog->progressBar()->setPercentageVisible(false);
		dialog->progressBar()->setTotalSteps(0);
		dialog->showCancelButton(true);
		dialog->setButtonText(i18n("Abort"));
		dialog->show();
	}
	if(dialog && dialog->wasCancelled()) on_abort_display();
	rtime.tv_nsec = 100000000;
	while(b_busy) {
		dialog->progressBar()->advance(1);
		tqApp->processEvents();
		nanosleep(&rtime, NULL);
		if(dialog->wasCancelled()) on_abort_display();
	}

	b_busy = true;
	if(dialog) {
		dialog->hide();
		delete dialog;
	}

	if(stack_index == 0) {
		if(do_wrap) {
			resultLabel->setVScrollBarMode(TQScrollView::Auto);
			resultLabel->setRightMargin(10);
			resultLabel->setWordWrap(TQTextEdit::NoWrap);
		} else {
			resultLabel->setVScrollBarMode(TQScrollView::AlwaysOff);
			resultLabel->setWordWrap(TQTextEdit::NoWrap);
			resultLabel->setRightMargin(0);
			TQString str = result_text;
			str.replace("width=1 ", "");
			TQSimpleRichText testrt(str, resultLabel->font());
			testrt.setWidth(resultLabel->visibleWidth() * 4);
			if(testrt.widthUsed() > resultLabel->visibleWidth()) {
				result_text.replace("<font size=5", "<font size=4");
				result_text.replace("<font size=6", "<font size=5");
				reduceDivLineSize(resultLabel);
			}
		}
	 	resultLabel->setText(result_text);
	}

	if(register_moved) {
		update_parse = true;
		parsed_text = result_history_text;
	}

	if(update_history) {
		if(result_history_text.length() > 500000) {
			result_history_text = "(...)";
		}
		if(parsed_text.length() > 500000) {
			parsed_text = "(...)";
		}
		TQString new_text;
		if(update_parse) {
			TQString str = "&nbsp;&nbsp;";
			if(!parsed_approx) {
				str += "=";
				inhistory_type.insert(inhistory_type.begin() + inhistory_index, QALCULATE_HISTORY_PARSE);
			} else {
				if(printops.use_unicode_signs && can_display_unicode_string_function(SIGN_ALMOST_EQUAL, (void*) historyBrowser)) {
					str += SIGN_ALMOST_EQUAL;
				} else {
					str += i18n("approx.");
				}
				inhistory_type.insert(inhistory_type.begin() + inhistory_index, QALCULATE_HISTORY_PARSE_APPROXIMATE);
			}
			str += " ";
			TQString str2 = parsed_text;
			str2.replace("&", "&amp;");
			str2.replace(">", "&gt;");
			str2.replace("<", "&lt;");
			inhistory.insert(inhistory.begin() + inhistory_index, str2);
			inhistory_id.insert(inhistory_id.begin() + inhistory_index, inhistory_current_id);
			inhistory_index++;
			str += str2;
			new_text += "<font color=\"gray40\"><i>";
			new_text += "<a name=\"";
			new_text += TQString::number(inhistory_current_id);
			new_text += "\">";
			new_text += str;
			new_text += "</a>";
			new_text += "</i></font>";
			new_text += "<br>";
			inhistory_current_id++;
		}
		if(stack_index == 0) {
			display_errors(&new_text, &inhistory_index);
			new_text += "<a name=\"";
			new_text += TQString::number(inhistory_current_id);
			new_text += "\">";
			if(!(*printops.is_approximate) && !mstruct->isApproximate() && (update_parse || !prev_result_approx)) {
				inhistory_type.insert(inhistory_type.begin() + inhistory_index, QALCULATE_HISTORY_RESULT);
				new_text += "=";
			} else {
				inhistory_type.insert(inhistory_type.begin() + inhistory_index, QALCULATE_HISTORY_RESULT_APPROXIMATE);
				if(printops.use_unicode_signs && can_display_unicode_string_function(SIGN_ALMOST_EQUAL, (void*) historyBrowser)) {
					new_text += SIGN_ALMOST_EQUAL;
				} else {
					TQString str_approx = "= ";
					str_approx += i18n("approx.");
					new_text += str_approx;
				}
			}
			new_text += " ";
			new_text += "</a>";
		} else {
			display_errors();
		}
		if(rpn_mode && !register_moved) {
			RPNRegisterChanged(result_history_text, stack_index);
		}
		if(stack_index == 0) {
			TQString str2 = result_history_text;
			str2.replace("&", "&amp;");
			str2.replace(">", "&gt;");
			str2.replace("<", "&lt;");
			new_text += "<b>";
			new_text += "<a name=\"";
			new_text += TQString::number(inhistory_current_id);
			new_text += "\">";
			new_text += str2;
			new_text += " </a>";
			new_text += "</b>";
			inhistory.insert(inhistory.begin() + inhistory_index, str2);
			inhistory_id.insert(inhistory_id.begin() + inhistory_index, inhistory_current_id);
			inhistory_current_id++;
			TQString text = historyBrowser->text();
			initial_result_index = history_index + new_text.length() + 4;
			initial_inhistory_index = inhistory_index + 1;
			if(!update_parse && transformation.isEmpty()) {
				new_text += "<br>";
			}
			text.insert(history_index, new_text);
			historyBrowser->setText(text);
			prev_result_approx = *printops.is_approximate;
		}
	}
	printops.prefix = NULL;
	
	b_busy = false;
	display_errors();
	
	if(!register_moved && stack_index == 0 && mstruct->isMatrix() && matrix_mstruct->isMatrix()) {
		tqApp->processEvents();
		expressionEdit->setFocus();
		if(update_history && update_parse && force) expressionEdit->selectAll();
		insertMatrixVector(matrix_mstruct, false, true, true);
	}
	error_timer->start(100);
}

void on_abort_command() {
	pthread_cancel(command_thread);
	CALCULATOR->restoreState();
	CALCULATOR->clearBuffers();
	b_busy = false;
	command_thread_started = false;
}

void *command_proc(void *pipe) {

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);	
	FILE *command_pipe = (FILE*) pipe;
	
	while(true) {
	
		void *x = NULL;
		int command_type;
		fread(&command_type, sizeof(int), 1, command_pipe);
		fread(&x, sizeof(void*), 1, command_pipe);
		switch(command_type) {
			case COMMAND_FACTORIZE: {
				if(!((MathStructure*) x)->integerFactorize()) {
					((MathStructure*) x)->factorize(evalops);
				}
				break;
			}
			case COMMAND_SIMPLIFY: {
				((MathStructure*) x)->simplify(evalops);
				break;
			}
		}
		b_busy = false;
		
	}
	return NULL;
}

int execute_command_command_type;

void KQalculate::executeCommand(int command_type) {
	execute_command_command_type = command_type;
	if(expression_has_changed && !rpn_mode) {
		execute_expression();
	}
	TQTimer::singleShot(0, this, TQ_SLOT(executeCommand2()));
}
void KQalculate::executeCommand2() {
	int command_type = execute_command_command_type;

	error_timer->stop();	

	b_busy = true;	
	bool command_aborted = false;
	CALCULATOR->saveState();

	if(!command_thread_started) {
		pthread_create(&command_thread, &command_thread_attr, command_proc, command_pipe_r);
		command_thread_started = true;
	}

	fwrite(&command_type, sizeof(int), 1, command_pipe_w);
	MathStructure *mfactor = new MathStructure(*mstruct);
	fwrite(&mfactor, sizeof(void*), 1, command_pipe_w);
	
	fflush(command_pipe_w);

	struct timespec rtime;
	rtime.tv_sec = 0;
	rtime.tv_nsec = 20000000;
	int i = 0;
	while(b_busy && i < 50) {
		nanosleep(&rtime, NULL);
		i++;
	}
	i = 0;
	
	KProgressDialog *dialog = NULL;
	if(b_busy) {
		TQString progress_str;
		switch(command_type) {
			case COMMAND_FACTORIZE: {
				progress_str = i18n("Factorizing...");
				break;
			}
			case COMMAND_SIMPLIFY: {
				progress_str = i18n("Simplifying...");
				break;
			}
		}
		dialog = new KProgressDialog(this, "display_progress_dialog", progress_str, progress_str, true);
		dialog->progressBar()->setPercentageVisible(false);
		dialog->progressBar()->setTotalSteps(0);
		dialog->showCancelButton(true);
		dialog->setButtonText(i18n("Abort"));
		dialog->show();
	}
	if(dialog && dialog->wasCancelled()) {
		on_abort_command();
		command_aborted = true;
	}
	rtime.tv_nsec = 100000000;
	while(b_busy) {
		dialog->progressBar()->advance(1);
		tqApp->processEvents();
		nanosleep(&rtime, NULL);
		if(dialog->wasCancelled()) {			
			on_abort_command();
			command_aborted = true;
		}
	}

	b_busy = true;
	if(dialog) {
		dialog->hide();
		delete dialog;
	}

	b_busy = false;
	
	if(!command_aborted) {
		mstruct->unref();
		mstruct = mfactor;
		switch(command_type) {
			case COMMAND_FACTORIZE: {
				printops.allow_factorization = true;
				break;
			}
			case COMMAND_SIMPLIFY: {
				printops.allow_factorization = false;
				break;
			}
		}
		set_result_prefix = NULL;
		set_result_update_history = true;
		set_result_update_parse = false;
		set_result_force = true;
		set_result_transformation = "";
		set_result_stack_index = 0;
		set_result_register_moved = false;
		setResult2();
		expressionEdit->setFocus();
	}

	error_timer->start(100);

}

void KQalculate::result_display_updated() {
	setResult(NULL, false, false, false);
	update_status_text();
	expressionEdit->setFocus();
}
void KQalculate::result_format_updated() {
	setResult(NULL, true, false, false);
	update_status_text();
	expressionEdit->setFocus();
}
void KQalculate::result_action_executed() {
	//display_errors();
	printops.allow_factorization = (evalops.structuring == STRUCTURING_FACTORIZE);
	setResult(NULL, true, false, true);
	expressionEdit->setFocus();
}
void KQalculate::result_prefix_changed(Prefix *prefix) {
	setResult(prefix, true, false, true);
	expressionEdit->setFocus();
}
void KQalculate::expression_calculation_updated() {
	expression_has_changed2 = true;
	displayParseStatus();
	if(!rpn_mode) execute_expression(false);
	update_status_text();
	expressionEdit->setFocus();
}
void KQalculate::expression_format_updated(bool recalculate) {
	if(rpn_mode) recalculate = false;
	expression_has_changed2 = true;
	displayParseStatus();
	if(!expression_has_changed && !recalculate && !rpn_mode) {	
		clearresult();
	}
	if(recalculate) {
		execute_expression(false);
	}
	update_status_text();
	expressionEdit->setFocus();
}

/*
	calculate entered expression and display result
*/
size_t execute_expression_stack_index;
bool execute_expression_do_stack;
bool execute_expression_force;
bool execute_expression_do_mathoperation;
MathOperation execute_expression_op;
MathFunction *execute_expression_f;
void KQalculate::execute_expression(bool force) {
	execute_expression_force = force;
	execute_expression_do_stack = false;
	execute_expression_do_mathoperation = false;
	TQTimer::singleShot(0, this, TQ_SLOT(execute_expression2()));
}
void KQalculate::execute_expression2() {

	bool force = execute_expression_force;
	bool do_stack = execute_expression_do_stack;	
	size_t stack_index = execute_expression_stack_index;
	bool do_mathoperation = execute_expression_do_mathoperation;
	MathOperation op = execute_expression_op;
	MathFunction *f = execute_expression_f;

	TQString str;

	if(do_stack) {
		str = getRPNRegister(stack_index)->text(1).stripWhiteSpace();
		error_timer->stop();
	} else {
		str = expressionEdit->text().stripWhiteSpace();
		if(!force && (expression_has_changed || str.isEmpty())) return;
		error_timer->stop();
		expression_has_changed = false;
		if(!do_mathoperation && !str.isEmpty()) expressionEdit->addToHistory(expressionEdit->text());
	}

	size_t stack_size = 0;

	b_busy = true;

	if(!do_stack || stack_index == 0) {
		parsed_text = "";
	}
	if(do_stack) {
		stack_size = CALCULATOR->RPNStackSize();
		CALCULATOR->setRPNRegister(stack_index + 1, CALCULATOR->unlocalizeExpression(str.ascii(), evalops.parse_options), 0, evalops, parsed_mstruct, parsed_tostruct, !printops.negative_exponents);
	} else if(rpn_mode) {
		stack_size = CALCULATOR->RPNStackSize();
		if(do_mathoperation) {
			if(f) CALCULATOR->calculateRPN(f, 0, evalops, parsed_mstruct);
			else CALCULATOR->calculateRPN(op, 0, evalops, parsed_mstruct);
		} else {
			std::string str2 = CALCULATOR->unlocalizeExpression(str.ascii(), evalops.parse_options);
			CALCULATOR->parseSigns(str2);
			if(str2.length() == 1) {
				do_mathoperation = true;
				switch(str2[0]) {
					case '^': {CALCULATOR->calculateRPN(OPERATION_RAISE, 0, evalops, parsed_mstruct); break;}
					case '+': {CALCULATOR->calculateRPN(OPERATION_ADD, 0, evalops, parsed_mstruct); break;}
					case '-': {CALCULATOR->calculateRPN(OPERATION_SUBTRACT, 0, evalops, parsed_mstruct); break;}
					case '*': {CALCULATOR->calculateRPN(OPERATION_MULTIPLY, 0, evalops, parsed_mstruct); break;}
					case '/': {CALCULATOR->calculateRPN(OPERATION_DIVIDE, 0, evalops, parsed_mstruct); break;}
					case '&': {CALCULATOR->calculateRPN(OPERATION_BITWISE_AND, 0, evalops, parsed_mstruct); break;}
					case '|': {CALCULATOR->calculateRPN(OPERATION_BITWISE_OR, 0, evalops, parsed_mstruct); break;}
					case '~': {CALCULATOR->calculateRPNBitwiseNot(0, evalops, parsed_mstruct); break;}
					case '!': {CALCULATOR->calculateRPN(CALCULATOR->f_factorial, 0, evalops, parsed_mstruct); break;}
					case '>': {CALCULATOR->calculateRPN(OPERATION_GREATER, 0, evalops, parsed_mstruct); break;}
					case '<': {CALCULATOR->calculateRPN(OPERATION_LESS, 0, evalops, parsed_mstruct); break;}
					case '=': {CALCULATOR->calculateRPN(OPERATION_EQUALS, 0, evalops, parsed_mstruct); break;}
					default: {do_mathoperation = false;}
				}
			} else if(str2.length() == 2) {
				if(str2 == "**") {
					CALCULATOR->calculateRPN(OPERATION_RAISE, 0, evalops, parsed_mstruct);
					do_mathoperation = true;
				} else if(str2 == "!!") {
					CALCULATOR->calculateRPN(CALCULATOR->f_factorial2, 0, evalops, parsed_mstruct);
					do_mathoperation = true;
				} else if(str2 == "!=" || str == "=!" || str == "<>") {
					CALCULATOR->calculateRPN(OPERATION_NOT_EQUALS, 0, evalops, parsed_mstruct);
					do_mathoperation = true;
				} else if(str2 == "<=" || str == "=<") {
					CALCULATOR->calculateRPN(OPERATION_EQUALS_LESS, 0, evalops, parsed_mstruct);
					do_mathoperation = true;
				} else if(str2 == ">=" || str == "=>") {
					CALCULATOR->calculateRPN(OPERATION_EQUALS_GREATER, 0, evalops, parsed_mstruct);
					do_mathoperation = true;
				} else if(str2 == "==") {
					CALCULATOR->calculateRPN(OPERATION_EQUALS, 0, evalops, parsed_mstruct);
					do_mathoperation = true;
				}
			}
			if(!do_mathoperation) {
				bool had_nonnum = false, test_function = true;
				int in_par = 0;
				for(size_t i = 0; i < str2.length(); i++) {
					if(is_in(NUMBERS, str2[i])) {
						if(!had_nonnum || in_par) {
							test_function = false;
							break;
						}
					} else if(str2[i] == '(') {
						if(in_par || !had_nonnum) {
							test_function = false;
							break;
						}
						in_par = i;
					} else if(str2[i] == ')') {
						if(i != str2.length() - 1) {
							test_function = false;
							break;
						}
					} else if(str2[i] == ' ') {
						if(!in_par) {
							test_function = false;
							break;
						}
					} else if(is_in(NOT_IN_NAMES, str2[i])) {
						test_function = false;
						break;
					} else {
						if(in_par) {
							test_function = false;
							break;
						}
						had_nonnum = true;
					}
				}
				f = NULL;
				if(test_function) {
					if(in_par) f = CALCULATOR->getActiveFunction(str2.substr(0, in_par));
					else f = CALCULATOR->getActiveFunction(str2);
				}
				if(f && f->minargs() > 1) {
					KMessageBox::error(this, "Can only apply functions wich requires one argument on RPN stack.");
					f = NULL;
					return;
				}
				if(f && f->minargs() > 0) {
					do_mathoperation = true;
					CALCULATOR->calculateRPN(f, 0, evalops, parsed_mstruct);
				} else {
					CALCULATOR->RPNStackEnter(str2, 0, evalops, parsed_mstruct, parsed_tostruct, !printops.negative_exponents);
				}
			}
		}
	} else {
		CALCULATOR->calculate(mstruct, CALCULATOR->unlocalizeExpression(str.ascii(), evalops.parse_options), 0, evalops, parsed_mstruct, parsed_tostruct, !printops.negative_exponents);
	}
	struct timespec rtime;
	rtime.tv_sec = 0;
	rtime.tv_nsec = 20000000;
	int i = 0;
	while(CALCULATOR->busy() && i < 50) {
		nanosleep(&rtime, NULL);
		i++;
	}
	i = 0;
	KProgressDialog *dialog = NULL;
	if(CALCULATOR->busy()) {
		dialog = new KProgressDialog(this, "calculation_progress_dialog", i18n("Calculating..."), i18n("Calculating..."), true);
		dialog->progressBar()->setPercentageVisible(false);
		dialog->progressBar()->setTotalSteps(0);
		dialog->showCancelButton(true);
		dialog->setButtonText(i18n("Abort"));
		dialog->show();
	}
	if(dialog && dialog->wasCancelled()) CALCULATOR->abort();
	rtime.tv_nsec = 100000000;
	while(CALCULATOR->busy()) {
		dialog->progressBar()->advance(1);
		tqApp->processEvents();
		nanosleep(&rtime, NULL);
		if(dialog->wasCancelled()) CALCULATOR->abort();
	}
	if(dialog) {
		dialog->hide();
		delete dialog;
		expressionEdit->setFocus();
	}
	b_busy = false;

	if(rpn_mode && (!do_stack || stack_index == 0)) {
		mstruct->unref();
		mstruct = CALCULATOR->getRPNRegister(1);
		if(!mstruct) mstruct = new MathStructure();
		else mstruct->ref();
	}
	
	//update "ans" variables
	if(!do_stack || stack_index == 0) {
		vans[4]->set(vans[3]->get());
		vans_id_start[4] = vans_id_start[3];
		vans_id_end[4] = vans_id_end[3];
		vans[3]->set(vans[2]->get());
		vans_id_start[3] = vans_id_start[2];
		vans_id_end[3] = vans_id_end[2];
		vans[2]->set(vans[1]->get());
		vans_id_start[2] = vans_id_start[1];
		vans_id_end[2] = vans_id_end[1];
		vans[1]->set(vans[0]->get());
		vans_id_start[1] = vans_id_start[0];
		vans_id_end[1] = inhistory_current_id - 1;
		vans[0]->set(*mstruct);
		vans_id_start[0] = inhistory_current_id;
		vans_id_end[0] = -1;
	}

	if(do_stack && stack_index > 0) {
	} else if(rpn_mode && do_mathoperation) {
		result_history_text = i18n("RPN Operation");
	} else {
		result_history_text = str;
	}
	printops.allow_factorization = (evalops.structuring == STRUCTURING_FACTORIZE);
	set_result_prefix = NULL;
	set_result_update_history = true;
	set_result_update_parse = (!do_stack || stack_index == 0);
	set_result_force = true;
	set_result_transformation = "";
	set_result_register_moved = false;
	if(!do_stack) set_result_stack_index = 0;
	else set_result_stack_index = stack_index;
	if(rpn_mode && (!do_stack || stack_index == 0)) {
		expressionEdit->clear();
		if(CALCULATOR->RPNStackSize() < stack_size) {
			RPNRegisterRemoved(1);
		} else if(CALCULATOR->RPNStackSize() > stack_size) {
			RPNRegisterAdded("");
		}
	}
	setResult2();
	if(!do_stack || stack_index == 0) {
		expressionEdit->setFocus();
		expressionEdit->selectAll();
	}
	error_timer->start(100);
}

void KQalculate::display_errors(TQString *new_text, int *inhistory_index) {
	if(!CALCULATOR->message()) return;
	error_timer->stop();
	bool error = false;
	MessageType mtype;
	TQStringList strlst;
	TQString error_str = "";
	while(true) {
		mtype = CALCULATOR->message()->type();
		if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
			TQString text = CALCULATOR->message()->message().c_str();
			text.replace("&", "&amp;");
			text.replace(">", "&gt;");
			text.replace("<", "&lt;");
			if(inhistory_index) {
				inhistory.insert(inhistory.begin() + *inhistory_index, text);
				inhistory_id.insert(inhistory_id.begin() + *inhistory_index, inhistory_current_id);
				inhistory_current_id++;
				if(mtype == MESSAGE_ERROR) inhistory_type.insert(inhistory_type.begin() + *inhistory_index, QALCULATE_HISTORY_ERROR);
				else inhistory_type.insert(inhistory_type.begin() + *inhistory_index, QALCULATE_HISTORY_WARNING);
				*inhistory_index += 1;
			}
			strlst.push_back(CALCULATOR->message()->message().c_str());
			if(mtype == MESSAGE_ERROR) error = true;
			if(mtype == MESSAGE_ERROR) error_str += "<font color=\"red\">";
			else error_str += "<font color=\"blue\">";
			error_str += "- ";
			error_str += text;
			error_str += "</font>";
			error_str += "<br>";
		} else {
			KMessageBox::information(this, CALCULATOR->message()->message().c_str());
		}
		if(!CALCULATOR->nextMessage()) break;
	}
	if(!error_str.isEmpty() && new_text) {
		new_text->append(error_str);
	}
	if(strlst.size() > 1) {	
		if(error) KMessageBox::error(this, strlst.join("\n"), i18n("Errors"));
		else KMessageBox::error(this, strlst.join("\n"), i18n("Warnings"));
	} else if(strlst.size() == 1) {
		if(error) KMessageBox::error(this, strlst[0], i18n("Error"));
		else KMessageBox::error(this, strlst[0], i18n("Warning"));
	}
	error_timer->start(100);
}

void save_defs() {
	if(!CALCULATOR->saveDefinitions()) {
		KMessageBox::error(0, i18n("Couldn't write definitions"));
	}
}


void KQalculate::create_vmenu() {

	TQPopupMenu *sub, *sub3;

	menu_variables->clear();
	sub = menu_variables;
	Variable *v;
	tree_struct *titem, *titem2;
	variable_cats.rit = variable_cats.items.rbegin();
	if(variable_cats.rit != variable_cats.items.rend()) {
		titem = &*variable_cats.rit;
		++variable_cats.rit;
		titem->rit = titem->items.rbegin();
	} else {
		titem = NULL;
	}

	menu_variables_ids.clear();

	std::stack<TQPopupMenu*> menus;
	menus.push(sub);
	sub3 = sub;
	while(titem) {
		sub = new TQPopupMenu();
		TQObject::connect(sub, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onVariableMenuItemActivated(int)));
		if(titem->item.find('&') != std::string::npos) {
			TQString str2 = titem->item.c_str();
			str2.replace("&", "&&");
			sub3->insertItem(str2, sub, -1, 0);
		} else {
			sub3->insertItem(titem->item.c_str(), sub, -1, 0);
		}
		menus.push(sub);
		sub3 = sub;
		for(size_t i = 0; i < titem->objects.size(); i++) {
			v = (Variable*) titem->objects[i];
			if(v->isActive() && !v->isHidden()) {
				if(v->title(true).find('&') != std::string::npos) {
					TQString str2 = v->title(true).c_str();
					str2.replace("&", "&&");
					menu_variables_ids[sub->insertItem(str2)] = v;
				} else {
					menu_variables_ids[sub->insertItem(v->title(true).c_str())] = v;
				}
			}
		}
		while(titem && titem->rit == titem->items.rend()) {
			titem = titem->parent;
			menus.pop();
			if(menus.size() > 0) sub3 = menus.top();
		}	
		if(titem) {
			titem2 = &*titem->rit;
			++titem->rit;
			titem = titem2;
			titem->rit = titem->items.rbegin();	
		}

	}

	for(size_t i = 0; i < variable_cats.objects.size(); i++) {		
		v = (Variable*) variable_cats.objects[i];
		if(v->isActive() && !v->isHidden()) {
			menu_variables_ids[menu_variables->insertItem(v->title(true).c_str())] = v;
		}
	}		

}

void KQalculate::recreate_recent_variables() {
	recent_variable_ids.clear();
	bool b = false;
	for(size_t i = 0; i < recent_variables.size(); i++) {
		if(!CALCULATOR->stillHasVariable(recent_variables[i])) {
			recent_variables.erase(recent_variables.begin() + i);
			i--;
		} else {
			if(!b) {
				menu_variables->insertSeparator(0);
				b = true;
			}
			int id = menu_variables->insertItem(recent_variables[i]->title(true).c_str(), -1, 0);
			recent_variable_ids.push_back(id);
			menu_variables_ids[id] = recent_variables[i];
		}
	}
}
void KQalculate::update_vmenu() {
	generate_variables_tree_struct();
	create_vmenu();
	recreate_recent_variables();
	if(variables_dialog) variables_dialog->updateVariableTree();
	update_completion();
}

void KQalculate::create_fmenu() {

	TQPopupMenu *sub, *sub3;

	menu_functions->clear();
	sub = menu_functions;
	MathFunction *f;
	tree_struct *titem, *titem2;
	function_cats.rit = function_cats.items.rbegin();
	if(function_cats.rit != function_cats.items.rend()) {
		titem = &*function_cats.rit;
		++function_cats.rit;
		titem->rit = titem->items.rbegin();
	} else {
		titem = NULL;
	}

	menu_functions_ids.clear();

	std::stack<TQPopupMenu*> menus;
	menus.push(sub);
	sub3 = sub;
	while(titem) {
		sub = new TQPopupMenu();
		TQObject::connect(sub, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onFunctionMenuItemActivated(int)));
		if(titem->item.find('&') != std::string::npos) {
			TQString str2 = titem->item.c_str();
			str2.replace("&", "&&");
			sub3->insertItem(str2, sub, -1, 0);
		} else {
			sub3->insertItem(titem->item.c_str(), sub, -1, 0);
		}
		menus.push(sub);
		sub3 = sub;
		for(size_t i = 0; i < titem->objects.size(); i++) {
			f = (MathFunction*) titem->objects[i];
			if(f->isActive() && !f->isHidden()) {
				if(f->title(true).find('&') != std::string::npos) {
					TQString str2 = f->title(true).c_str();
					str2.replace("&", "&&");
					menu_functions_ids[sub->insertItem(str2)] = f;
				} else {
					menu_functions_ids[sub->insertItem(f->title(true).c_str())] = f;
				}
			}
		}
		while(titem && titem->rit == titem->items.rend()) {
			titem = titem->parent;
			menus.pop();
			if(menus.size() > 0) sub3 = menus.top();
		}	
		if(titem) {
			titem2 = &*titem->rit;
			++titem->rit;
			titem = titem2;
			titem->rit = titem->items.rbegin();	
		}

	}

	for(size_t i = 0; i < function_cats.objects.size(); i++) {
		f = (MathFunction*) function_cats.objects[i];
		if(f->isActive() && !f->isHidden()) {
			menu_functions_ids[menu_functions->insertItem(f->title(true).c_str())] = f;
		}
	}		

}
void KQalculate::recreate_recent_functions() {
	recent_function_ids.clear();
	bool b = false;
	for(size_t i = 0; i < recent_functions.size(); i++) {
		if(!CALCULATOR->stillHasFunction(recent_functions[i])) {
			recent_functions.erase(recent_functions.begin() + i);
			i--;
		} else {
			if(!b) {
				menu_functions->insertSeparator(0);
				b = true;
			}
			int id = menu_functions->insertItem(recent_functions[i]->title(true).c_str(), -1, 0);
			recent_function_ids.push_back(id);
			menu_functions_ids[id] = recent_functions[i];
		}
	}
}
void KQalculate::update_fmenu() {
	generate_functions_tree_struct();
	create_fmenu();
	recreate_recent_functions();
	if(functions_dialog) functions_dialog->updateFunctionTree();
	if(datasets_dialog) {
		datasets_dialog->updateDataSetTree();
		if(!datasets_dialog->dataSetsView->selectedItem()) datasets_dialog->dataSetSelected();
	}
	update_completion();
}

void KQalculate::create_umenu() {

	TQPopupMenu *sub, *sub3;

	menu_units->clear();
	sub = menu_units;
	Unit *u;
	tree_struct *titem, *titem2;
	unit_cats.rit = unit_cats.items.rbegin();
	if(unit_cats.rit != unit_cats.items.rend()) {
		titem = &*unit_cats.rit;
		++unit_cats.rit;
		titem->rit = titem->items.rbegin();
	} else {
		titem = NULL;
	}

	menu_units_ids.clear();

	std::stack<TQPopupMenu*> menus;
	menus.push(sub);
	sub3 = sub;
	while(titem) {
		sub = new TQPopupMenu();
		TQObject::connect(sub, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onUnitMenuItemActivated(int)));
		if(titem->item.find('&') != std::string::npos) {
			TQString str2 = titem->item.c_str();
			str2.replace("&", "&&");
			sub3->insertItem(str2, sub, -1, 0);
		} else {
			sub3->insertItem(titem->item.c_str(), sub, -1, 0);
		}
		menus.push(sub);
		sub3 = sub;
		for(size_t i = 0; i < titem->objects.size(); i++) {
			u = (Unit*) titem->objects[i];
			if(u->isActive() && !u->isHidden()) {
				if(u->title(true).find('&') != std::string::npos) {
					TQString str2 = u->title(true).c_str();
					str2.replace("&", "&&");
					menu_units_ids[sub->insertItem(str2)] = u;
				} else {
					menu_units_ids[sub->insertItem(u->title(true).c_str())] = u;
				}
			}
		}
		while(titem && titem->rit == titem->items.rend()) {
			titem = titem->parent;
			menus.pop();
			if(menus.size() > 0) sub3 = menus.top();
		}	
		if(titem) {
			titem2 = &*titem->rit;
			++titem->rit;
			titem = titem2;
			titem->rit = titem->items.rbegin();	
		}

	}

	for(size_t i = 0; i < unit_cats.objects.size(); i++) {
		u = (Unit*) unit_cats.objects[i];
		if(u->isActive() && !u->isHidden()) {
			menu_units_ids[menu_units->insertItem(u->title(true).c_str())] = u;
		}
	}

	sub = new TQPopupMenu();
	TQObject::connect(sub, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onUnitsPrefixMenuItemActivated(int)));
	menu_units->insertSeparator();
	menu_units->insertItem(i18n("Prefixes"), sub);
	int index = 0;
	Prefix *p = CALCULATOR->getPrefix(index);
	while(p) {
		TQString pstr;
		switch(p->type()) {
			case PREFIX_DECIMAL: {
				TQTextOStream(&pstr) << p->name(false, true, &can_display_unicode_string_function, (void*) menu_units).c_str() << "\t(10e" << ((DecimalPrefix*) p)->exponent() << ")";				
				break;
			}
			case PREFIX_BINARY: {
				TQTextOStream(&pstr) << p->name(false, true, &can_display_unicode_string_function, (void*) menu_units).c_str() << "\t(2e" << ((BinaryPrefix*) p)->exponent() << ")";
				break;
			}
			case PREFIX_NUMBER: {				
				TQTextOStream(&pstr) << p->name(false, true, &can_display_unicode_string_function, (void*) menu_units).c_str();
				break;
			}			
		}
		menu_units_prefixes_ids[sub->insertItem(pstr)] = p;
		index++;
		p = CALCULATOR->getPrefix(index);
	}

}

void KQalculate::recreate_recent_units() {
	recent_unit_ids.clear();
	bool b = false;
	for(size_t i = 0; i < recent_units.size(); i++) {
		if(!CALCULATOR->stillHasUnit(recent_units[i])) {
			recent_units.erase(recent_units.begin() + i);
			i--;
		} else {
			if(!b) {
				menu_units->insertSeparator(0);
				b = true;
			}
			int id = menu_units->insertItem(recent_units[i]->title(true).c_str(), -1, 0);
			recent_unit_ids.push_back(id);
			menu_units_ids[id] = recent_units[i];
		}
	}
}
void KQalculate::update_umenus() {
	generate_units_tree_struct();
	create_umenu();
	recreate_recent_units();
	create_toumenu();
	if(units_dialog) units_dialog->updateUnitTree();
	if(convert_to_unit_expression_dialog) convert_to_unit_expression_dialog->updateUnitTree();
	update_completion();
}

void KQalculate::create_toumenu() {

	TQPopupMenu *sub, *sub3;

	menu_to_unit->clear();
	sub = menu_to_unit;
	Unit *u;
	tree_struct *titem, *titem2;
	unit_cats.rit = unit_cats.items.rbegin();
	if(unit_cats.rit != unit_cats.items.rend()) {
		titem = &*unit_cats.rit;
		++unit_cats.rit;
		titem->rit = titem->items.rbegin();
	} else {
		titem = NULL;
	}

	menu_to_unit_ids.clear();

	std::stack<TQPopupMenu*> menus;
	menus.push(sub);
	sub3 = sub;
	while(titem) {
		sub = new TQPopupMenu();
		TQObject::connect(sub, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onConvertToUnitMenuItemActivated(int)));
		if(titem->item.find('&') != std::string::npos) {
			TQString str2 = titem->item.c_str();
			str2.replace("&", "&&");
			sub3->insertItem(str2, sub, -1, 0);
		} else {
			sub3->insertItem(titem->item.c_str(), sub, -1, 0);
		}
		menus.push(sub);
		sub3 = sub;
		for(size_t i = 0; i < titem->objects.size(); i++) {
			u = (Unit*) titem->objects[i];
			if(u->isActive() && !u->isHidden()) {
				if(u->title(true).find('&') != std::string::npos) {
					TQString str2 = u->title(true).c_str();
					str2.replace("&", "&&");
					menu_to_unit_ids[sub->insertItem(str2)] = u;
				} else {
					menu_to_unit_ids[sub->insertItem(u->title(true).c_str())] = u;
				}
			}
		}
		while(titem && titem->rit == titem->items.rend()) {
			titem = titem->parent;
			menus.pop();
			if(menus.size() > 0) sub3 = menus.top();
		}	
		if(titem) {
			titem2 = &*titem->rit;
			++titem->rit;
			titem = titem2;
			titem->rit = titem->items.rbegin();	
		}

	}

	for(size_t i = 0; i < unit_cats.objects.size(); i++) {
		u = (Unit*) unit_cats.objects[i];
		if(u->isActive() && !u->isHidden()) {
			menu_to_unit_ids[menu_to_unit->insertItem(u->title(true).c_str())] = u;
		}
	}

}

void KQalculate::create_setpmenu() {
	menu_set_prefix->clear();
	TQObject::connect(menu_set_prefix, TQ_SIGNAL(activated(int)), this, TQ_SLOT(onSetPrefixMenuItemActivated(int)));
	int index = 0;
	menu_set_prefix_ids[menu_set_prefix->insertItem(i18n("No Prefix"))] = CALCULATOR->decimal_null_prefix;
	Prefix *p = CALCULATOR->getPrefix(index);
	while(p) {
		TQString pstr;
		switch(p->type()) {
			case PREFIX_DECIMAL: {
				TQTextOStream(&pstr) << p->name(false, true, &can_display_unicode_string_function, (void*) menu_units).c_str() << "\t(10e" << ((DecimalPrefix*) p)->exponent() << ")";				
				break;
			}
			case PREFIX_BINARY: {
				TQTextOStream(&pstr) << p->name(false, true, &can_display_unicode_string_function, (void*) menu_units).c_str() << "\t(2e" << ((BinaryPrefix*) p)->exponent() << ")";
				break;
			}
			case PREFIX_NUMBER: {				
				TQTextOStream(&pstr) << p->name(false, true, &can_display_unicode_string_function, (void*) menu_units).c_str();
				break;
			}			
		}
		menu_set_prefix_ids[menu_set_prefix->insertItem(pstr)] = p;
		index++;
		p = CALCULATOR->getPrefix(index);
	}
}


void KQalculate::insert_text(TQString name) {
	expressionEdit->insert(name);
	expressionEdit->setFocus();
}
/*
	insert one-argument function when button clicked
*/
void KQalculate::insertButtonFunction(TQString text, bool append_space) {
	if(expressionEdit->hasSelectedText()) {
		//set selection as argument
		text += "(";
		text += expressionEdit->selectedText();
		text += ")";
		insert_text(text);
	} else {
		//one-argument functions do not need parenthesis
		if(append_space) {
			text += " ";
		}
		insert_text(text);
	}
}
void KQalculate::insertButtonFunction(MathFunction *f) {
	const ExpressionName *ename = &f->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) expressionEdit);
	if(f->minargs() > 1) {
		TQString text = ename->name.c_str();
		bool b = expressionEdit->hasSelectedText();
		text += "(";
		if(b) text += expressionEdit->selectedText();
		for(int i = 1; i < f->minargs(); i++) {
			text += CALCULATOR->getComma().c_str();
			text += " ";
		}
		text += ")";
		insert_text(text);
		if(b) expressionEdit->cursorBackward(false, 1 + (f->minargs() - 2) * 2);
		else expressionEdit->cursorBackward(false, 1 + (f->minargs() - 1) * 2);
	} else {
		if(rpn_mode && f->args() == 1) {
			calculateRPN(f);
			return;
		}
		insertButtonFunction(ename->name.c_str(), !text_length_is_one(ename->name));
	}
}

void KQalculate::function_inserted(MathFunction *object) {
	if(!object) {
		return;
	}
	if(recent_function_ids.size() <= 0) {
		menu_functions->insertSeparator(0);
	}
	for(size_t i = 0; i < recent_functions.size(); i++) {
		if(recent_functions[i] == object) {
			recent_functions.erase(recent_functions.begin() + i);
			menu_functions->removeItem(recent_function_ids[i]);
			recent_function_ids.erase(recent_function_ids.begin() + i);
			break;
		}
	}
	if(recent_function_ids.size() >= 5) {
		recent_functions.erase(recent_functions.begin());
		menu_functions->removeItem(recent_function_ids[0]);
		recent_function_ids.erase(recent_function_ids.begin());
	}
	int id = menu_functions->insertItem(object->title(true).c_str(), -1, 0);
	menu_functions_ids[id] = object;
	recent_function_ids.push_back(id);
	recent_functions.push_back(object);
}
void KQalculate::variable_inserted(Variable *object) {
	if(!object) {
		return;
	}
	if(recent_variable_ids.size() <= 0) {
		menu_variables->insertSeparator(0);
	}
	for(size_t i = 0; i < recent_variables.size(); i++) {
		if(recent_variables[i] == object) {
			recent_variables.erase(recent_variables.begin() + i);
			menu_variables->removeItem(recent_variable_ids[i]);
			recent_variable_ids.erase(recent_variable_ids.begin() + i);
			break;
		}
	}
	if(recent_variable_ids.size() >= 5) {
		recent_variables.erase(recent_variables.begin());
		menu_variables->removeItem(recent_variable_ids[0]);
		recent_variable_ids.erase(recent_variable_ids.begin());
	}
	int id = menu_variables->insertItem(object->title(true).c_str(), -1, 0);
	menu_variables_ids[id] = object;
	recent_variable_ids.push_back(id);
	recent_variables.push_back(object);
}
void KQalculate::unit_inserted(Unit *object) {
	if(!object) {
		return;
	}
	if(recent_unit_ids.size() <= 0) {
		menu_units->insertSeparator(0);
	}
	for(size_t i = 0; i < recent_units.size(); i++) {
		if(recent_units[i] == object) {
			recent_units.erase(recent_units.begin() + i);
			menu_units->removeItem(recent_unit_ids[i]);
			recent_unit_ids.erase(recent_unit_ids.begin() + i);
			break;
		}
	}
	if(recent_unit_ids.size() >= 5) {
		recent_units.erase(recent_units.begin());
		menu_units->removeItem(recent_unit_ids[0]);
		recent_unit_ids.erase(recent_unit_ids.begin());
	}
	int id = menu_units->insertItem(object->title(true).c_str(), -1, 0);
	menu_units_ids[id] = object;
	recent_unit_ids.push_back(id);
	recent_units.push_back(object);
}

void KQalculate::onVariableMenuItemActivated(int id) {
	if(!menu_variables_ids.contains(id)) return;
	Variable *v = menu_variables_ids[id];
	if(!CALCULATOR->stillHasVariable(v)) {
		KMessageBox::error(this, i18n("Variable does not exist anymore."));
		update_vmenu();
		return;
	}
	insert_text(v->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) expressionEdit).name.c_str());
	variable_inserted(v);
}
void KQalculate::onFunctionMenuItemActivated(int id) {
	if(!menu_functions_ids.contains(id)) return;
	MathFunction *f = menu_functions_ids[id];
	insertFunction(f, this);
}
void KQalculate::onUnitMenuItemActivated(int id) {
	if(!menu_units_ids.contains(id)) return;
	Unit *u = menu_units_ids[id];
	if(!CALCULATOR->stillHasUnit(u)) {
		KMessageBox::error(this, i18n("Unit does not exist anymore."));
		update_umenus();
		return;
	}
	if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) {
		insert_text(((CompositeUnit*) u)->print(true, printops.abbreviate_names, printops.use_unicode_signs, &can_display_unicode_string_function, (void*) expressionEdit).c_str());
	} else {
		insert_text(u->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, true, false, &can_display_unicode_string_function, (void*) expressionEdit).name.c_str());
	}
	unit_inserted(u);
}
void KQalculate::onUnitsPrefixMenuItemActivated(int id) {
	if(!menu_units_prefixes_ids.contains(id)) return;
	insert_text(menu_units_prefixes_ids[id]->name(printops.abbreviate_names, printops.use_unicode_signs, &can_display_unicode_string_function, (void*) expressionEdit).c_str());
}

void KQalculate::update_completion() {
	expressionEdit->updateCompletion();
	if(plot_dialog) {
		plot_dialog->expressionEdit->updateCompletion();
	}
}

void KQalculate::set_unicode_buttons() {
	if(printops.use_unicode_signs) {
		if(can_display_unicode_string_function(SIGN_MINUS, (void*) kpMinus)) kpMinus->setText(SIGN_MINUS);
		else kpMinus->setText(MINUS);
		if(can_display_unicode_string_function(SIGN_PLUS, (void*) kpPlus)) kpPlus->setText(SIGN_PLUS);
		else kpPlus->setText(PLUS);
		if(can_display_unicode_string_function(SIGN_MULTIPLICATION, (void*) kpTimes)) kpTimes->setText(SIGN_MULTIPLICATION);
		else kpTimes->setText(MULTIPLICATION);
		if(can_display_unicode_string_function(SIGN_DIVISION_SLASH, (void*) kpDivision)) kpDivision->setText(SIGN_DIVISION_SLASH);
		else if(can_display_unicode_string_function(SIGN_DIVISION, (void*) kpDivision)) kpDivision->setText(SIGN_DIVISION);
		else kpDivision->setText(DIVISION);	
		if(can_display_unicode_string_function(SIGN_SQRT, (void*) kpSqrt)) kpSqrt->setText(SIGN_SQRT);
		else kpSqrt->setText("Sqrt");
		if(can_display_unicode_string_function(SIGN_MULTIDOT, (void*) kpDot)) kpDot->setText(SIGN_MULTIDOT);
		else kpDot->setText(CALCULATOR->getDecimalPoint().c_str());
	} else {
		kpMinus->setText(MINUS);
		kpPlus->setText(PLUS);
		kpTimes->setText(MULTIPLICATION);
		kpDivision->setText(DIVISION);	
		kpSqrt->setText("Sqrt");
		kpDot->setText(CALCULATOR->getDecimalPoint().c_str());
	}
}

void KQalculate::onExpressionChanged() {
	expression_has_changed = true;
	expression_has_changed2 = true;
	if(!rpn_mode) clearresult();	
	if(!expressionEdit->dont_change_index) expressionEdit->expression_history_index = -1;
	displayParseStatus();
}

void KQalculate::execute() {
	execute_expression_force = true;
	execute_expression_do_stack = false;
	execute_expression_do_mathoperation = false;
	execute_expression2();
}

bool KQalculate::fetch_exchange_rates(int) {
	KURL url(CALCULATOR->getExchangeRatesUrl().c_str());
	TQString filename(CALCULATOR->getExchangeRatesFileName().c_str());
	if(TDEIO::NetAccess::download(url, filename, this)) {
		return true;
	} else {
		TQString errorstr = i18n("Failed to download exchange rates from ECB.");
		errorstr += "\n";
		errorstr += TDEIO::NetAccess::lastErrorString();
		KMessageBox::error(this, errorstr);
		return false;
	}
}

void KQalculate::onErrorTimeout() {
	if(CALCULATOR->checkSaveFunctionCalled()) {
		update_vmenu();
	}
	display_errors();
}

void KQalculate::toggleHistory(bool on) {
	if(on) {
		bool b = mainStack->isVisible();
		int new_height = height();
		if(bottomLine->isVisible()) new_height -= bottomLine->height();
		if(mainStack->height() > history_height) history_height = mainStack->height();
		bottomLine->hide();
		mainStack->show();
		mainStack->raiseWidget(1);
		keypadButton->setOn(false);
		stackButton->setOn(false);
		mainStack->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
		resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
		if(!b) {
			new_height += history_height;
			resize(width(), new_height);
		} else if(history_height != mainStack->height()) {
			resize(width(), height() - mainStack->height() + history_height);
		}
	} else {
		if(!keypadButton->isOn() && !stackButton->isOn()) {
			history_height = mainStack->height();
			int new_height = height() - mainStack->height();
			mainStack->hide();
			bottomLine->show();
			tqApp->processEvents();
			if(new_height < height()) resize(width(), new_height + bottomLine->height());
			mainStack->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
			resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
		}
	}
}

void KQalculate::toggleStack(bool on) {
	if(on) {
		bool b = mainStack->isVisible();
		int new_height = height();
		if(bottomLine->isVisible()) new_height -= bottomLine->height();
		if(mainStack->height() > history_height) history_height = mainStack->height();
		bottomLine->hide();
		mainStack->show();
		mainStack->raiseWidget(2);
		keypadButton->setOn(false);
		historyButton->setOn(false);
		mainStack->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
		resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
		if(!b) {
			new_height += history_height;
			resize(width(), new_height);
		} else if(history_height != mainStack->height()) {
			resize(width(), height() - mainStack->height() + history_height);
		}
	} else {
		if(!keypadButton->isOn() && !historyButton->isOn()) {
			history_height = mainStack->height();
			int new_height = height() - mainStack->height();
			mainStack->hide();
			bottomLine->show();
			tqApp->processEvents();
			if(new_height < height()) resize(width(), new_height + bottomLine->height());
			mainStack->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
			resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
		}
	}
}

void KQalculate::toggleKeypad(bool on) {
	if(on) {
		bool b = mainStack->isVisible();
		if(b) history_height = mainStack->height();
		int new_height = height() - bottomLine->height();
		mainStack->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
		resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
		mainStack->show();
		bottomLine->hide();
		mainStack->raiseWidget(0);
		historyButton->setOn(false);
		stackButton->setOn(false);
		if(!b) {
			tqApp->processEvents();
			new_height += mainStack->height();
			resize(width(), new_height);
		} else {
			resize(width(), minimumSizeHint().height());
		}
	} else {
		if(!historyButton->isOn() && !stackButton->isOn()) {
			int new_height = height() - mainStack->height();
			mainStack->hide();
			bottomLine->show();
			tqApp->processEvents();
			if(new_height < height()) resize(width(), new_height + bottomLine->height());
			mainStack->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum, false);
			resultLabel->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding, false);
		}
	}
}

void KQalculate::showHide() {
	if(isVisible()) {
		hide();
	} else {
			KWin::WindowInfo info = KWin::windowInfo(winId(), (unsigned long) NET::WMGeometry);
			KWin::setOnDesktop(winId(), KWin::currentDesktop());
			move(info.geometry().topLeft());
			setShown(true);
			show();
			raise();
			KWin::activateWindow(winId());
	}
}
void KQalculate::configureGlobalShortcuts() {
	KKeyDialog::configure(globalAccel, 0, false);
	globalAccel->writeSettings();
	globalAccel->updateConnections();
}

void KQalculate::abbreviateNames(bool b) {
	printops.abbreviate_names = b;
	result_format_updated();
}

void KQalculate::approximationAlwaysExact() {
	kpExact->blockSignals(true);
	evalops.approximation = APPROXIMATION_EXACT;
	expression_calculation_updated();
	kpExact->setOn(true);
	kpExact->blockSignals(false);
}
void KQalculate::approximationTryExact() {
	kpExact->blockSignals(true);
	evalops.approximation = APPROXIMATION_TRY_EXACT;
	expression_calculation_updated();
	kpExact->setOn(false);
	kpExact->blockSignals(false);
}
void KQalculate::approximationApproximate() {
	kpExact->blockSignals(true);
	evalops.approximation = APPROXIMATION_APPROXIMATE;
	expression_calculation_updated();
	kpExact->setOn(false);
	kpExact->blockSignals(false);
}

void KQalculate::fractionalDisplayDecimal() {
	kpFraction->blockSignals(true);
	printops.number_fraction_format = FRACTION_DECIMAL;
	result_format_updated();
	kpFraction->setOn(false);
	kpFraction->blockSignals(false);
}
void KQalculate::fractionalDisplayDecimalTryExact() {
	kpFraction->blockSignals(true);
	printops.number_fraction_format = FRACTION_DECIMAL_EXACT;
	result_format_updated();
	kpFraction->setOn(false);
	kpFraction->blockSignals(false);
}
void KQalculate::fractionalDisplayFraction() {
	kpFraction->blockSignals(true);
	printops.number_fraction_format = FRACTION_FRACTIONAL;
	result_format_updated();
	kpFraction->setOn(true);
	kpFraction->blockSignals(false);
}
void KQalculate::fractionalDisplayCombined() {
	kpFraction->blockSignals(true);
	printops.number_fraction_format = FRACTION_COMBINED;
	result_format_updated();
	kpFraction->setOn(true);
	kpFraction->blockSignals(false);
}

void KQalculate::numericalDisplayNormal() {
	kpNumericCombo->blockSignals(true);
	printops.min_exp = EXP_PRECISION;
	result_format_updated();
	kpNumericCombo->setCurrentItem(0);
	kpNumericCombo->blockSignals(false);
}
void KQalculate::numericalDisplayEngineering() {
	kpNumericCombo->blockSignals(true);
	printops.min_exp = EXP_BASE_3;
	result_format_updated();
	kpNumericCombo->setCurrentItem(1);
	kpNumericCombo->blockSignals(false);
}
void KQalculate::numericalDisplayScientific() {
	kpNumericCombo->blockSignals(true);
	printops.min_exp = EXP_SCIENTIFIC;
	result_format_updated();
	kpNumericCombo->setCurrentItem(2);
	kpNumericCombo->blockSignals(false);
}
void KQalculate::numericalDisplayPurelyScientific() {
	kpNumericCombo->blockSignals(true);
	printops.min_exp = EXP_PURE;
	result_format_updated();
	kpNumericCombo->setCurrentItem(3);
	kpNumericCombo->blockSignals(false);
}
void KQalculate::numericalDisplaySimple() {
	kpNumericCombo->blockSignals(true);
	printops.min_exp = EXP_NONE;
	result_format_updated();
	kpNumericCombo->setCurrentItem(4);
	kpNumericCombo->blockSignals(false);
}

void KQalculate::roundHalfwayNumbersToEven(bool b) {
	printops.round_halfway_to_even = b;
	result_format_updated();
}


void KQalculate::indicateInfiniteSeries(bool b) {
	printops.indicate_infinite_series = b;
	result_format_updated();
}

void KQalculate::sortMinusLast(bool b) {
	printops.sort_options.minus_last = b;
	result_format_updated();
}

void KQalculate::negativeExponents(bool b) {
	printops.negative_exponents = b;
	result_format_updated();
}

void KQalculate::showEndingZeroes(bool b) {
	printops.show_ending_zeroes = b;
	result_format_updated();
}

void KQalculate::updateBaseOther() {
	if(set_base_dialog) {
		set_base_dialog->outputBaseBox->blockSignals(true);
		set_base_dialog->radiogroup_output->blockSignals(true);
		set_base_dialog->outputBaseBox->setEnabled(false);
		switch(printops.base) {
			case BASE_BINARY: {
				set_base_dialog->radiogroup_output->setButton(0);
				break;
			}
			case BASE_OCTAL: {
				set_base_dialog->radiogroup_output->setButton(1);
				break;
			}
			case BASE_DECIMAL: {
				set_base_dialog->radiogroup_output->setButton(2);
				break;
			}
			case BASE_HEXADECIMAL: {
				set_base_dialog->radiogroup_output->setButton(3);
				break;
			}
			case BASE_SEXAGESIMAL: {
				set_base_dialog->radiogroup_output->setButton(5);
				break;
			}
			case BASE_TIME: {
				set_base_dialog->radiogroup_output->setButton(6);
				break;
			}
			case BASE_ROMAN_NUMERALS: {
				set_base_dialog->radiogroup_output->setButton(7);
				break;
			}
			default: {
				set_base_dialog->radiogroup_output->setButton(4);
				set_base_dialog->outputBaseBox->setEnabled(true);
				set_base_dialog->outputBaseBox->setValue(printops.base);
			}
		}
		set_base_dialog->outputBaseBox->blockSignals(false);
		set_base_dialog->radiogroup_output->blockSignals(false);
	}
}
void KQalculate::numberBaseBinary() {
	kpBaseCombo->blockSignals(true);
	printops.base = BASE_BINARY;
	updateBaseOther();
	result_format_updated();
	kpBaseCombo->setCurrentItem(0);
	kpBaseCombo->blockSignals(false);
}
void KQalculate::numberBaseOctal() {
	kpBaseCombo->blockSignals(true);
	printops.base = BASE_OCTAL;
	updateBaseOther();
	result_format_updated();
	kpBaseCombo->setCurrentItem(1);
	kpBaseCombo->blockSignals(false);
}
void KQalculate::numberBaseDecimal() {
	kpBaseCombo->blockSignals(true);
	printops.base = BASE_DECIMAL;
	updateBaseOther();
	result_format_updated();
	kpBaseCombo->setCurrentItem(2);
	kpBaseCombo->blockSignals(false);
}
void KQalculate::numberBaseHexadecimal() {
	kpBaseCombo->blockSignals(true);
	printops.base = BASE_HEXADECIMAL;
	updateBaseOther();
	result_format_updated();
	kpBaseCombo->setCurrentItem(3);
	kpBaseCombo->blockSignals(false);
}
void KQalculate::numberBaseSexagesimal() {
	kpBaseCombo->blockSignals(true);
	printops.base = BASE_SEXAGESIMAL;
	updateBaseOther();
	result_format_updated();
	kpBaseCombo->setCurrentItem(4);
	kpBaseCombo->blockSignals(false);
}
void KQalculate::numberBaseTimeFormat() {
	kpBaseCombo->blockSignals(true);
	printops.base = BASE_TIME;
	updateBaseOther();
	result_format_updated();
	kpBaseCombo->setCurrentItem(5);
	kpBaseCombo->blockSignals(false);
}
void KQalculate::numberBaseRomanNumerals() {
	kpBaseCombo->blockSignals(true);
	printops.base = BASE_ROMAN_NUMERALS;
	updateBaseOther();
	result_format_updated();
	kpBaseCombo->setCurrentItem(6);
	kpBaseCombo->blockSignals(false);
}
void KQalculate::numberBaseOther() {
	setBase();
	set_base_dialog->radiogroup_output->setButton(4);
	setBaseInResultFromDialogGroup(4);
	set_base_dialog->outputBaseBox->setFocus();
	setBaseInResultFromDialogBox(set_base_dialog->outputBaseBox->value());
}

void KQalculate::setBaseInExpressionFromDialogBox(int value) {
	evalops.parse_options.base = value;
	expression_format_updated(true);
}
void KQalculate::setBaseInExpressionFromDialogGroup(int id) {
	switch(id) {
		case 0: {
			set_base_dialog->inputBaseBox->setEnabled(false);
			evalops.parse_options.base = BASE_BINARY;
			break;
		}
		case 1: {
			set_base_dialog->inputBaseBox->setEnabled(false);
			evalops.parse_options.base = BASE_OCTAL;
			break;
		}
		case 2: {
			set_base_dialog->inputBaseBox->setEnabled(false);
			evalops.parse_options.base = BASE_DECIMAL;
			break;
		}
		case 3: {
			set_base_dialog->inputBaseBox->setEnabled(false);
			evalops.parse_options.base = BASE_HEXADECIMAL;
			break;
		}
		case 4: {
			set_base_dialog->inputBaseBox->setEnabled(true);
			evalops.parse_options.base = set_base_dialog->inputBaseBox->value();
			break;
		}
		case 5: {
			set_base_dialog->inputBaseBox->setEnabled(false);
			evalops.parse_options.base = BASE_ROMAN_NUMERALS;
			break;
		}
	}
	expression_format_updated(true);
}
void KQalculate::setBaseInResultFromDialogBox(int value) {
	bool b = (printops.base == value);
	printops.base = value;
	kpBaseCombo->blockSignals(true);
	switch(value) {
		case BASE_BINARY: {
			ActionNumberBaseBinary->setChecked(true);			
			kpBaseCombo->setCurrentItem(0);
			break;
		}
		case BASE_OCTAL: {
			ActionNumberBaseOctal->setChecked(true);
			kpBaseCombo->setCurrentItem(1);
			break;
		}
		case BASE_DECIMAL: {
			ActionNumberBaseDecimal->setChecked(true);
			kpBaseCombo->setCurrentItem(2);
			break;
		}
		case BASE_HEXADECIMAL: {
			ActionNumberBaseHexadecimal->setChecked(true);
			kpBaseCombo->setCurrentItem(3);
			break;
		}
		default: {
			ActionNumberBaseOther->setChecked(true);
			kpBaseCombo->setCurrentItem(7);			
			break;
		}
	}
	kpBaseCombo->blockSignals(false);			
	if(!b) result_format_updated();
}
void KQalculate::setBaseInResultFromDialogGroup(int id) {
	switch(id) {
		case 0: {
			set_base_dialog->outputBaseBox->setEnabled(false);
			ActionNumberBaseBinary->activate();
			break;
		}
		case 1: {
			set_base_dialog->outputBaseBox->setEnabled(false);
			ActionNumberBaseOctal->activate();
			break;
		}
		case 2: {
			set_base_dialog->outputBaseBox->setEnabled(false);
			ActionNumberBaseDecimal->activate();
			break;
		}
		case 3: {
			set_base_dialog->outputBaseBox->setEnabled(false);
			ActionNumberBaseHexadecimal->activate();
			break;
		}
		case 4: {
			set_base_dialog->outputBaseBox->setEnabled(true);
			ActionNumberBaseOther->setChecked(true);
			kpBaseCombo->blockSignals(true);
			bool b = (printops.base == set_base_dialog->outputBaseBox->value());
			printops.base = set_base_dialog->outputBaseBox->value();
			kpBaseCombo->setCurrentItem(7);
			kpBaseCombo->blockSignals(false);
			if(!b) result_format_updated();
			break;
		}
		case 5: {
			set_base_dialog->outputBaseBox->setEnabled(false);
			ActionNumberBaseSexagesimal->activate();
			break;
		}
		case 6: {
			set_base_dialog->outputBaseBox->setEnabled(false);
			ActionNumberBaseTimeFormat->activate();
			break;
		}
		case 7: {
			set_base_dialog->outputBaseBox->setEnabled(false);
			ActionNumberBaseRomanNumerals->activate();
			break;
		}
	}
}
void KQalculate::setBase() {
	if(!set_base_dialog) {
		set_base_dialog = new QalculateSetBaseDialog(this);
		TQObject::connect(set_base_dialog->radiogroup_input, TQ_SIGNAL(clicked(int)), this, TQ_SLOT(setBaseInExpressionFromDialogGroup(int)));
		TQObject::connect(set_base_dialog->inputBaseBox, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(setBaseInExpressionFromDialogBox(int)));
		TQObject::connect(set_base_dialog->radiogroup_output, TQ_SIGNAL(clicked(int)), this, TQ_SLOT(setBaseInResultFromDialogGroup(int)));
		TQObject::connect(set_base_dialog->outputBaseBox, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(setBaseInResultFromDialogBox(int)));
	}
	set_base_dialog->inputBaseBox->blockSignals(true);
	set_base_dialog->radiogroup_input->blockSignals(true);
	set_base_dialog->inputBaseBox->setEnabled(false);
	switch(evalops.parse_options.base) {
		case BASE_BINARY: {
			set_base_dialog->radiogroup_input->setButton(0);
			break;
		}
		case BASE_OCTAL: {
			set_base_dialog->radiogroup_input->setButton(1);
			break;
		}
		case BASE_DECIMAL: {
			set_base_dialog->radiogroup_input->setButton(2);
			break;
		}
		case BASE_HEXADECIMAL: {
			set_base_dialog->radiogroup_input->setButton(3);
			break;
		}
		case BASE_ROMAN_NUMERALS: {
			set_base_dialog->radiogroup_input->setButton(5);
			break;
		}
		default: {
			set_base_dialog->radiogroup_input->setButton(4);
			set_base_dialog->inputBaseBox->setEnabled(true);
			set_base_dialog->inputBaseBox->setValue(evalops.parse_options.base);
		}
	}
	set_base_dialog->inputBaseBox->blockSignals(false);
	set_base_dialog->radiogroup_input->blockSignals(false);
	updateBaseOther();
	set_base_dialog->show();
}

void KQalculate::nonZeroDenominators(bool b) {
	evalops.assume_denominators_nonzero = b;
	expression_calculation_updated();
}
void KQalculate::warnAboutDenominatorsAssumedNonZero(bool b) {
	evalops.warn_about_denominators_assumed_nonzero = b;
	if(evalops.warn_about_denominators_assumed_nonzero) expression_calculation_updated();
}

void KQalculate::readPrecision(bool b) {
	if(b) evalops.parse_options.read_precision = READ_PRECISION_WHEN_DECIMALS;
	else evalops.parse_options.read_precision = DONT_READ_PRECISION;
	expression_format_updated(true);
}

void KQalculate::limitImplicitMultiplication(bool b) {
	evalops.parse_options.limit_implicit_multiplication = b;
	printops.limit_implicit_multiplication = b;
	expression_format_updated(true);
	result_format_updated();
}

void KQalculate::rpnMode(bool b) {
	if(b == rpn_mode) return;
	rpn_mode = b;
	if(rpn_mode) {
		stackButton->show();
		show_history = historyButton->isOn();
		show_keypad = keypadButton->isOn();
		if(show_stack) {
			stackButton->toggle();
		}
	} else {
		show_stack = stackButton->isOn();
		if(show_stack) {
			if(show_history) historyButton->toggle();
			else if(show_keypad) keypadButton->toggle();
			else stackButton->toggle();
		}
		stackButton->hide();
		CALCULATOR->clearRPNStack();
		stackList->clear();
	}
	if(leftButtonsSeparator->isVisible()) {
		if(rpn_mode) executeButton->setText(i18n("Enter"));
		else executeButton->setText(i18n("="));
	}
	if(rpn_mode) {
		kpEquals->setText(i18n("Ent"));
		TQToolTip::add(kpEquals, i18n("Calculate expression and add to stack"));
		TQToolTip::add(executeButton, i18n("Calculate expression and add to stack"));
	} else {
		kpEquals->setText(i18n("="));
		TQToolTip::add(kpEquals, i18n("Calculate expression"));
		TQToolTip::add(executeButton, i18n("Calculate expression"));
	}
}

void KQalculate::rpnSyntax(bool b) {
	evalops.parse_options.rpn = b;
	expression_format_updated(false);
}

void KQalculate::setMinDecimals(int i) {
	printops.min_decimals = i;
	if(i <= 0) printops.use_min_decimals = false;
	else printops.use_min_decimals = true;
	result_format_updated();	
}
void KQalculate::setMaxDecimals(int i) {
	printops.max_decimals = i;
	if(i < 0) printops.use_max_decimals = false;
	else printops.use_max_decimals = true;
	result_format_updated();	
}

void KQalculate::decimals() {
	if(!decimalsDialog) {
		decimalsDialog = new QalculateDecimalsDialog(this);
		TQObject::connect(decimalsDialog->minDecimalsBox, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(setMinDecimals(int)));
		TQObject::connect(decimalsDialog->maxDecimalsBox, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(setMaxDecimals(int)));
	}
	decimalsDialog->minDecimalsBox->blockSignals(true);
	decimalsDialog->maxDecimalsBox->blockSignals(true);
	if(printops.use_min_decimals && printops.min_decimals > 0) decimalsDialog->minDecimalsBox->setValue(printops.min_decimals);
	else decimalsDialog->minDecimalsBox->setValue(0);
	if(printops.use_max_decimals && printops.max_decimals >= 0) decimalsDialog->maxDecimalsBox->setValue(printops.max_decimals);
	else decimalsDialog->maxDecimalsBox->setValue(-1);
	decimalsDialog->minDecimalsBox->blockSignals(false);
	decimalsDialog->maxDecimalsBox->blockSignals(false);
	decimalsDialog->show();
}

void KQalculate::setPrecision(int i) {
	if(i != CALCULATOR->getPrecision()) CALCULATOR->setPrecision(i);
}
void KQalculate::precision() {
	if(!precisionDialog) {
		precisionDialog = new QalculatePrecisionDialog(this);
		TQObject::connect(precisionDialog, TQ_SIGNAL(applyClicked()), this, TQ_SLOT(precisionRecalculate()));
		TQObject::connect(precisionDialog->precisionBox, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(setPrecision(int)));
	}
	precisionDialog->precisionBox->setValue(CALCULATOR->getPrecision());
	precisionDialog->show();
}

void KQalculate::precisionRecalculate() {
	if(precisionDialog->precisionBox->value() != CALCULATOR->getPrecision()) CALCULATOR->setPrecision(precisionDialog->precisionBox->value());
	expression_calculation_updated();
}

void KQalculate::assumptionTypeUnknown() {
	CALCULATOR->defaultAssumptions()->setType(ASSUMPTION_TYPE_NONE);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionTypeNonMatrix() {
	CALCULATOR->defaultAssumptions()->setType(ASSUMPTION_TYPE_NONMATRIX);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionTypeNumber() {
	CALCULATOR->defaultAssumptions()->setType(ASSUMPTION_TYPE_NUMBER);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionTypeComplex() {
	CALCULATOR->defaultAssumptions()->setType(ASSUMPTION_TYPE_COMPLEX);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionTypeReal() {
	CALCULATOR->defaultAssumptions()->setType(ASSUMPTION_TYPE_REAL);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionTypeRational() {
	CALCULATOR->defaultAssumptions()->setType(ASSUMPTION_TYPE_RATIONAL);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionTypeInteger() {
	CALCULATOR->defaultAssumptions()->setType(ASSUMPTION_TYPE_INTEGER);
	setAssumptionsMenu();
	expression_calculation_updated();
}

void KQalculate::assumptionSignUnknown() {
	CALCULATOR->defaultAssumptions()->setSign(ASSUMPTION_SIGN_UNKNOWN);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionSignNonZero() {
	CALCULATOR->defaultAssumptions()->setSign(ASSUMPTION_SIGN_NONZERO);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionSignPositive() {
	CALCULATOR->defaultAssumptions()->setSign(ASSUMPTION_SIGN_POSITIVE);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionSignNonNegative() {
	CALCULATOR->defaultAssumptions()->setSign(ASSUMPTION_SIGN_NONNEGATIVE);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionSignNegative() {
	CALCULATOR->defaultAssumptions()->setSign(ASSUMPTION_SIGN_NEGATIVE);
	setAssumptionsMenu();
	expression_calculation_updated();
}
void KQalculate::assumptionSignNonPositive() {
	CALCULATOR->defaultAssumptions()->setSign(ASSUMPTION_SIGN_NONPOSITIVE);
	setAssumptionsMenu();
	expression_calculation_updated();
}

void KQalculate::algebraicModeSimplify() {
	evalops.structuring = STRUCTURING_SIMPLIFY;
	printops.allow_factorization = false;
	expression_calculation_updated();
}
void KQalculate::algebraicModeFactorize() {
	evalops.structuring = STRUCTURING_FACTORIZE;
	printops.allow_factorization = true;
	expression_calculation_updated();
}
void KQalculate::algebraicModeNone() {
	evalops.structuring = STRUCTURING_NONE;
	printops.allow_factorization = false;
	expression_calculation_updated();
}

void KQalculate::onModesMenuItemActivated(int id) {
	loadMode(menu_modes->indexOf(id));
}
void KQalculate::loadMode(int index) {
	if(index < 0) return;
	size_t i = (size_t) index;
	if(i >= modes.size()) return;
	printops.min_decimals = modes[i].po.min_decimals;
	printops.use_min_decimals = modes[i].po.use_min_decimals;
	printops.max_decimals = modes[i].po.max_decimals;
	printops.use_max_decimals = modes[i].po.use_max_decimals;	
	CALCULATOR->setPrecision(modes[i].precision);
	printops.min_exp = modes[i].po.min_exp;
	printops.negative_exponents = modes[i].po.negative_exponents;
	printops.sort_options.minus_last = modes[i].po.sort_options.minus_last;
	printops.number_fraction_format = modes[i].po.number_fraction_format;	
	printops.use_unit_prefixes = modes[i].po.use_unit_prefixes;
	printops.abbreviate_names = modes[i].po.abbreviate_names;
	printops.use_all_prefixes = modes[i].po.use_all_prefixes;
	printops.use_denominator_prefix = modes[i].po.use_denominator_prefix;
	printops.place_units_separately = modes[i].po.place_units_separately;
	evalops.auto_post_conversion = modes[i].eo.auto_post_conversion;	
	printops.base = modes[i].po.base;
	evalops.parse_options.base = modes[i].eo.parse_options.base;
	evalops.parse_options.read_precision = modes[i].eo.parse_options.read_precision;
	evalops.assume_denominators_nonzero = modes[i].eo.assume_denominators_nonzero;
	evalops.warn_about_denominators_assumed_nonzero = modes[i].eo.warn_about_denominators_assumed_nonzero;
	evalops.parse_options.angle_unit = modes[i].eo.parse_options.angle_unit;
	evalops.parse_options.functions_enabled = modes[i].eo.parse_options.functions_enabled;
	evalops.parse_options.variables_enabled = modes[i].eo.parse_options.variables_enabled;
	evalops.calculate_functions = modes[i].eo.calculate_functions;	
	evalops.calculate_variables = modes[i].eo.calculate_variables;	
	evalops.sync_units = modes[i].eo.sync_units;	
	evalops.parse_options.unknowns_enabled = modes[i].eo.parse_options.unknowns_enabled;
	evalops.parse_options.units_enabled = modes[i].eo.parse_options.units_enabled;
	evalops.allow_complex = modes[i].eo.allow_complex;
	evalops.allow_infinite = modes[i].eo.allow_infinite;
	evalops.structuring = modes[i].eo.structuring;
	printops.indicate_infinite_series = modes[i].po.indicate_infinite_series;
	printops.show_ending_zeroes = modes[i].po.show_ending_zeroes;
	printops.round_halfway_to_even = modes[i].po.round_halfway_to_even;
	evalops.approximation = modes[i].eo.approximation;	
	evalops.parse_options.rpn = modes[i].eo.parse_options.rpn;
	evalops.parse_options.limit_implicit_multiplication = modes[i].eo.parse_options.limit_implicit_multiplication;
	printops.limit_implicit_multiplication = modes[i].po.limit_implicit_multiplication;
	printops.spacious = modes[i].po.spacious;
	printops.excessive_parenthesis = modes[i].po.excessive_parenthesis;
	printops.short_multiplication = modes[i].po.short_multiplication;
	CALCULATOR->defaultAssumptions()->setType(modes[i].at);
	CALCULATOR->defaultAssumptions()->setSign(modes[i].as);
	if(modes[i].rpn_mode != rpn_mode) {
		rpnMode(modes[i].rpn_mode);
	}
	
	setModeActions();
	
	if(decimalsDialog) {
		decimalsDialog->minDecimalsBox->blockSignals(true);
		decimalsDialog->maxDecimalsBox->blockSignals(true);
		if(printops.use_min_decimals && printops.min_decimals > 0) decimalsDialog->minDecimalsBox->setValue(printops.min_decimals);
		else decimalsDialog->minDecimalsBox->setValue(0);
		if(printops.use_max_decimals && printops.max_decimals >= 0) decimalsDialog->maxDecimalsBox->setValue(printops.max_decimals);
		else decimalsDialog->maxDecimalsBox->setValue(-1);
		decimalsDialog->minDecimalsBox->blockSignals(false);
		decimalsDialog->maxDecimalsBox->blockSignals(false);
	}
	if(precisionDialog) {
		precisionDialog->precisionBox->setValue(CALCULATOR->getPrecision());
	}
	updateBaseOther();
	if(set_base_dialog) {
		set_base_dialog->inputBaseBox->blockSignals(true);
		set_base_dialog->radiogroup_input->blockSignals(true);
		set_base_dialog->inputBaseBox->setEnabled(false);
		switch(evalops.parse_options.base) {
			case BASE_BINARY: {
				set_base_dialog->radiogroup_input->setButton(0);
				break;
			}
			case BASE_OCTAL: {
				set_base_dialog->radiogroup_input->setButton(1);
				break;
			}
			case BASE_DECIMAL: {
				set_base_dialog->radiogroup_input->setButton(2);
				break;
			}
			case BASE_HEXADECIMAL: {
				set_base_dialog->radiogroup_input->setButton(3);
				break;
			}
			case BASE_ROMAN_NUMERALS: {
				set_base_dialog->radiogroup_input->setButton(5);
				break;
			}
			default: {
				set_base_dialog->radiogroup_input->setButton(4);
				set_base_dialog->inputBaseBox->setEnabled(true);
				set_base_dialog->inputBaseBox->setValue(evalops.parse_options.base);
			}
		}
		set_base_dialog->inputBaseBox->blockSignals(false);
		set_base_dialog->radiogroup_input->blockSignals(false);
	}

	update_status_text();
	printops.allow_factorization = (evalops.structuring == STRUCTURING_FACTORIZE);
	TQString str = expressionEdit->text().stripWhiteSpace();
	if(expression_has_changed || str.isEmpty()) {
		setResult(NULL, true, false, false);
	} else {
		execute_expression(false);
	}
	
	expression_has_changed2 = true;
	displayParseStatus();
	expressionEdit->setFocus();	
}
QalculateModeDialog::QalculateModeDialog(TQWidget *parent) : KDialogBase(parent, 0, true, i18n("Save Mode"), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true) {
	setMainWidget(new TQWidget(this));
	TQGridLayout *grid = new TQGridLayout(mainWidget(), 2, 2, 0, spacingHint());
	grid->addWidget(new TQLabel(i18n("Mode name:"), mainWidget()), 0, 0);
	modeCombo = new KComboBox(mainWidget());
	modeCombo->setEditable(true);
	for(size_t i = 2; i < modes.size(); i++) {
		modeCombo->insertItem(modes[i].name);
	}
	modeCombo->lineEdit()->clear();
	modeCombo->setFocus();
	modeCombo->setSizePolicy(TQSizePolicy::Expanding, modeCombo->sizePolicy().verData());
	grid->addWidget(modeCombo, 0, 1);
	grid->addWidget(new TQLabel(i18n("Shortcut:"), mainWidget()), 1, 0);
	keyButton = new KKeyButton(mainWidget());	
	grid->addWidget(keyButton, 1, 1);

	connect(keyButton, TQ_SIGNAL(capturedShortcut(const TDEShortcut&)), this, TQ_SLOT(updateShortcut(const TDEShortcut&)));
	connect(modeCombo, TQ_SIGNAL(activated(int)), this, TQ_SLOT(modeSelected(int)));
	
}
QalculateModeDialog::~QalculateModeDialog() {}
void QalculateModeDialog::modeSelected(int index) {
	index += 2;
	if(index < (int) modes.size()) {
		keyButton->setShortcut(modes[index].shortcut, false);
	}
}
void QalculateModeDialog::updateShortcut(const TDEShortcut &shortcut) {
	keyButton->setShortcut(shortcut, false);
}
TQString QalculateModeDialog::modeName() {
	return modeCombo->currentText();
}
const TDEShortcut &QalculateModeDialog::modeShortcut() {
	return keyButton->shortcut();
}
void QalculateModeDialog::slotOk() {
	TQString name = modeName();
	if(name.isEmpty()) {
		KMessageBox::error(this, i18n("Empty mode name."));
		return;
	} else if(name == modes[0].name) {
		KMessageBox::error(this, i18n("Preset mode cannot be overwritten."));
		return;
	}
	KDialogBase::slotOk();	
}
void KQalculate::saveModeAs() {
	QalculateModeDialog *dialog = new QalculateModeDialog(this);
	if(dialog->exec() == TQDialog::Accepted) {
		bool new_mode = true;
		TQString name = dialog->modeName().stripWhiteSpace();		
		size_t index = save_mode_as(name, &new_mode);
		modes[index].shortcut = dialog->modeShortcut();		
		if(new_mode) {
			menu_modes->insertItem(modes[index].name, -1, index);
			ActionDeleteMode->setEnabled(true);
			ModeObject *mo = new ModeObject(index);
			mo->i_mode = index;
			mode_objects.push_back(mo);
			accel()->insert(TQString("Load mode: ") + modes[index].name, i18n("Load meta mode: %1").arg(modes[index].name), TQString::null, modes[index].shortcut, mo, TQ_SLOT(loadMode()));
		} else {
			accel()->setShortcut(TQString("Load mode: ") + modes[index].name, modes[index].shortcut);
		}		
	}
	delete dialog;
}
void KQalculate::deleteMode() {
	bool b_ok = false;
	TQStringList mode_names;
	for(size_t i = 2; i < modes.size(); i++) {
		mode_names += modes[i].name;
	}
	TQString name = KInputDialog::getItem(i18n("Delete Mode"), i18n("Mode:"), mode_names, 0, false, &b_ok, this).stripWhiteSpace();
	if(b_ok) {
		for(size_t i = 2; i < modes.size(); i++) {
			if(modes[i].name == name) {
				accel()->remove(TQString("Load mode: ") + name);
				modes.erase(modes.begin() + i);
				delete mode_objects[i - 2];
				mode_objects.erase(mode_objects.begin() + (i - 2));
				for(TQValueVector<ModeObject*>::size_type i2 = 0; i2 < mode_objects.size(); i2++) {
					mode_objects[i2]->i_mode = i2 + 2;
				}
				menu_modes->removeItemAt(i);
				if(modes.size() < 3) {
					ActionDeleteMode->setEnabled(false);
				}
			}
		}
	}
}
void KQalculate::saveMode() {
	save_mode();
}

void KQalculate::aboutToQuit() {
	if(plot_dialog) plot_dialog->saveMode();
	if(save_mode_on_exit) {
		save_mode();
	} else {
		save_preferences();
	}
	if(save_defs_on_exit) {
		save_defs();
	}
	pthread_cancel(view_thread);
	CALCULATOR->terminateThreads();	
}

void KQalculate::angleUnitDegrees() {
	kpAngleGroup->blockSignals(true);
	evalops.parse_options.angle_unit = ANGLE_UNIT_DEGREES;
	expression_format_updated(true);
	kpAngleGroup->setButton(0);
	kpAngleGroup->blockSignals(false);
}
void KQalculate::angleUnitRadians() {
	kpAngleGroup->blockSignals(true);
	evalops.parse_options.angle_unit = ANGLE_UNIT_RADIANS;
	expression_format_updated(true);
	kpAngleGroup->setButton(1);
	kpAngleGroup->blockSignals(false);
}
void KQalculate::angleUnitGradians() {
	kpAngleGroup->blockSignals(true);
	evalops.parse_options.angle_unit = ANGLE_UNIT_GRADIANS;
	expression_format_updated(true);
	kpAngleGroup->setButton(2);
	kpAngleGroup->blockSignals(false);
}
void KQalculate::angleUnitNone() {
	kpAngleGroup->blockSignals(true);
	evalops.parse_options.angle_unit = ANGLE_UNIT_NONE;
	expression_format_updated(true);
	kpAngleGroup->setButton(3);
	kpAngleGroup->blockSignals(false);
}

void KQalculate::placeUnitsSeparately(bool b) {
	printops.place_units_separately = b;
	result_format_updated();
}


void KQalculate::enableDenominatorPrefixes(bool b) {
	printops.use_denominator_prefix = b;
	result_format_updated();
}


void KQalculate::enableUseOfAllPrefixes(bool b) {
	printops.use_all_prefixes = b;
	result_format_updated();
}


void KQalculate::enablePrefixes(bool b) {
	printops.use_unit_prefixes = b;
	result_format_updated();
}

void KQalculate::autoNoConversion() {
	evalops.auto_post_conversion = POST_CONVERSION_NONE;
	expression_calculation_updated();
}
void KQalculate::autoConvertToBaseUnits() {
	evalops.auto_post_conversion = POST_CONVERSION_BASE;
	expression_calculation_updated();
}
void KQalculate::autoConvertToBestUnit() {
	evalops.auto_post_conversion = POST_CONVERSION_BEST;
	expression_calculation_updated();
}

void KQalculate::allowInfiniteResult(bool b) {
	evalops.allow_infinite = b;
	expression_calculation_updated();
}


void KQalculate::allowComplexResult(bool b) {
	evalops.allow_complex = b;
	expression_calculation_updated();
}


void KQalculate::calculateVariables(bool b) {
	evalops.calculate_variables = b;
	expression_calculation_updated();
}


void KQalculate::enableUnknowns(bool b) {
	evalops.parse_options.unknowns_enabled = b;
	expression_format_updated(b);
}


void KQalculate::enableUnits(bool b) {
	evalops.parse_options.units_enabled = b;
	expression_format_updated(b);
}


void KQalculate::enableFunctions(bool b) {
	evalops.parse_options.functions_enabled = b;
	expression_format_updated(b);
}


void KQalculate::enableVariables(bool b) {
	evalops.parse_options.variables_enabled = b;
	expression_format_updated(b);
}

void KQalculate::updateExchangeRates() {
	if(fetch_exchange_rates(15)) {
		CALCULATOR->loadExchangeRates();
	}
	expression_calculation_updated();
}

void KQalculate::insertRaise() {
	if(rpn_mode) {
		calculateRPN(OPERATION_RAISE);
		return;
	}
	if(!evalops.parse_options.rpn) {
		expressionEdit->wrapSelection();
		expressionEdit->deselect();
	}
	insert_text("^");
}


void KQalculate::insertLn() {
	insertButtonFunction(CALCULATOR->f_ln);
}


void KQalculate::insertLog() {
	MathFunction *f = CALCULATOR->getActiveFunction("log10");
	if(f) {
		insertButtonFunction(f);
	} else {
		KMessageBox::error(this, i18n("log10 function not found."));
	}
}


void KQalculate::insertSqrt() {
	insertButtonFunction(CALCULATOR->f_sqrt);
}


void KQalculate::insertTan() {
	if(kpHyp->isOn()) {
		if(kpInv->isOn()) {
			insertButtonFunction(CALCULATOR->f_atanh);
		} else {
			insertButtonFunction(CALCULATOR->f_tanh);
		}
	} else {
		if(kpInv->isOn()) {
			insertButtonFunction(CALCULATOR->f_atan);
		} else {
			insertButtonFunction(CALCULATOR->f_tan);
		}
	}
}


void KQalculate::insertSin() {
	if(kpHyp->isOn()) {
		kpHyp->setOn(false);
		if(kpInv->isOn()) {
			kpInv->setOn(false);
			insertButtonFunction(CALCULATOR->f_asinh);
		} else {
			insertButtonFunction(CALCULATOR->f_sinh);
		}
	} else {
		if(kpInv->isOn()) {
			kpInv->setOn(false);
			insertButtonFunction(CALCULATOR->f_asin);
		} else {
			insertButtonFunction(CALCULATOR->f_sin);
		}
	}
}


void KQalculate::insertCos() {
	if(kpHyp->isOn()) {
		kpHyp->setOn(false);
		if(kpInv->isOn()) {
			kpInv->setOn(false);
			insertButtonFunction(CALCULATOR->f_acosh);
		} else {
			insertButtonFunction(CALCULATOR->f_cosh);
		}
	} else {
		if(kpInv->isOn()) {
			kpInv->setOn(false);
			insertButtonFunction(CALCULATOR->f_acos);
		} else {
			insertButtonFunction(CALCULATOR->f_cos);
		}
	}
}


void KQalculate::insertDivision() {
	if(rpn_mode) {
		calculateRPN(OPERATION_DIVIDE);
		return;
	}
	if(!evalops.parse_options.rpn) {
		expressionEdit->wrapSelection();
		expressionEdit->deselect();
	}
	if(printops.use_unicode_signs && printops.division_sign == DIVISION_SIGN_DIVISION && can_display_unicode_string_function(SIGN_DIVISION, (void*) expressionEdit)) {
		insert_text(SIGN_DIVISION);
	} else {
		insert_text("/");
	}
}


void KQalculate::insertTimes() {
	if(rpn_mode) {
		calculateRPN(OPERATION_MULTIPLY);
		return;
	}
	if(!evalops.parse_options.rpn) {
		expressionEdit->wrapSelection();
		expressionEdit->deselect();
	}
	if(printops.use_unicode_signs && printops.multiplication_sign == MULTIPLICATION_SIGN_DOT && can_display_unicode_string_function(SIGN_MULTIDOT, (void*) expressionEdit)) {
		insert_text(SIGN_MULTIDOT);
	} else if(printops.use_unicode_signs && printops.multiplication_sign == MULTIPLICATION_SIGN_DOT && can_display_unicode_string_function(SIGN_SMALLCIRCLE, (void*) expressionEdit)) {
		insert_text(SIGN_SMALLCIRCLE);
	} else if(printops.use_unicode_signs && printops.multiplication_sign == MULTIPLICATION_SIGN_X && can_display_unicode_string_function(SIGN_MULTIPLICATION, (void*) expressionEdit)) {
		insert_text(SIGN_MULTIPLICATION);
	} else {
		insert_text("*");
	}
}


void KQalculate::calculateRPN(int op) {
	if(expression_has_changed && !expressionEdit->text().stripWhiteSpace().isEmpty()) {
		execute();
	}
	execute_expression_force = true;
	execute_expression_do_stack = false;
	execute_expression_do_mathoperation = true;
	execute_expression_op = (MathOperation) op;
	execute_expression_f = NULL;
	execute_expression2();
}
void KQalculate::calculateRPN(MathFunction *f) {
	if(expression_has_changed && !expressionEdit->text().stripWhiteSpace().isEmpty()) {
		execute();
	}
	execute_expression_force = true;
	execute_expression_do_stack = false;
	execute_expression_do_mathoperation = true;
	execute_expression_f = f;
	execute_expression2();
}
void KQalculate::RPNStackEnter(Variable *v) {
	CALCULATOR->RPNStackEnter(new MathStructure(v), true);
	mstruct->unref();
	mstruct = CALCULATOR->getRPNRegister(1);
	mstruct->ref();
	RPNRegisterAdded(v->preferredDisplayName(printops.abbreviate_names, printops.use_unicode_signs, false, printops.use_reference_names, printops.can_display_unicode_string_function, (void*) stackList).name.c_str());
}
void KQalculate::RPNRegisterAdded(const TQString &text, size_t index) {
	if(index == 0) {
		new TDEListViewItem(stackList, TQString::number(index + 1), text);
	} else {
		new TDEListViewItem(stackList, getRPNRegister(index - 1), TQString::number(index + 1), text);
	}
	updateRPNIndexes();
	clearStackButton->setEnabled(true);
}
void KQalculate::RPNRegisterRemoved(size_t index) {
	delete getRPNRegister(index);
	updateRPNIndexes();
	if(CALCULATOR->RPNStackSize() == 0) {
		clearStackButton->setEnabled(false);
	}
}
void KQalculate::RPNRegisterChanged(const TQString &text, size_t index) {
	getRPNRegister(index)->setText(1, text);
}
TQListViewItem *KQalculate::getRPNRegister(size_t index) {
	TQListViewItem *li = stackList->firstChild();
	while(li) {
		if(index == 0) return li;
		index--;
		li = li->nextSibling();
	}
	return NULL;
}
void KQalculate::clearStack() {
	CALCULATOR->clearRPNStack();
	stackList->clear();
	clearresult();
	mstruct->clear();
	clearStackButton->setEnabled(false);
}
void KQalculate::registerUp() {
	TQListViewItem *li = stackList->selectedItem();
	if(li) {
		size_t index = (size_t) li->text(0).toUInt() - 1;
		if(index == 0) return;
		CALCULATOR->moveRPNRegisterUp(index + 1);
		TQListViewItem *li2 = li->itemAbove();
		TQString str = li2->text(1);
		li2->setText(1, li->text(1));
		li->setText(1, str);
		stackList->setSelected(li2, true);
		if(index == 1) {
			mstruct->unref();
			mstruct = CALCULATOR->getRPNRegister(1);
			mstruct->ref();
			setResult(NULL, true, false, false, "", 0, true);
		}
	}
}
void KQalculate::registerDown() {
	TQListViewItem *li = stackList->selectedItem();
	if(li) {
		size_t index = (size_t) li->text(0).toUInt() - 1;
		if(index + 1 == CALCULATOR->RPNStackSize()) return;
		CALCULATOR->moveRPNRegisterDown(index + 1);
		TQListViewItem *li2 = li->nextSibling();
		TQString str = li2->text(1);
		li2->setText(1, li->text(1));
		li->setText(1, str);
		stackList->setSelected(li2, true);
		if(index == 0) {
			mstruct->unref();
			mstruct = CALCULATOR->getRPNRegister(1);
			mstruct->ref();
			setResult(NULL, true, false, false, "", 0, true);
		}
	}
}
void KQalculate::deleteRegister() {
	TQListViewItem *li = stackList->selectedItem();
	if(li) {
		size_t index = (size_t) li->text(0).toUInt() - 1;
		CALCULATOR->deleteRPNRegister(index + 1);
		delete li;
		if(CALCULATOR->RPNStackSize() == 0) {
			clearresult();
			mstruct->clear();
			clearStackButton->setEnabled(false);
		} else if(index == 0) {
			mstruct->unref();
			mstruct = CALCULATOR->getRPNRegister(1);
			mstruct->ref();
			setResult(NULL, true, false, false, "", 0, true);
		}
		updateRPNIndexes();
	}
}
void KQalculate::editRegister() {
	TQListViewItem *li = stackList->selectedItem();
	if(!li) return;
	stackList->rename(li, 1);
}
void KQalculate::updateRPNIndexes() {
	TQListViewItem *li = stackList->firstChild();
	size_t i = 1;
	while(li) {
		li->setText(0, TQString::number(i));
		i++;
		li = li->nextSibling();
	}
}
void KQalculate::stackRegisterMoved() {
	TQListViewItem *li = stackList->firstChild();
	size_t i = 0;
	size_t old_index;
	while(li) {
		old_index = (size_t) li->text(0).toUInt() - 1;
		if(old_index != i) {
			CALCULATOR->moveRPNRegister(old_index + 1, i + 1);
			if(i == 0) {
				mstruct->unref();
				mstruct = CALCULATOR->getRPNRegister(1);
				mstruct->ref();
				setResult(NULL, true, false, false, "", 0, true);
			}
			updateRPNIndexes();
			registerSelected();
			return;
		}
		i++;
		li = li->nextSibling();
	}
}
void KQalculate::stackRegisterSet(TQListViewItem *li) {
	execute_expression_stack_index = (size_t) li->text(0).toUInt() - 1;
	execute_expression_force = true;
	execute_expression_do_stack = true;
	execute_expression_do_mathoperation = false;
	execute_expression2();
}
void KQalculate::popupStackMenu(TDEListView*, TQListViewItem *li, const TQPoint &p) {
	stackMenu->setItemEnabled(stackMenu->idAt(0), li != NULL);
	stackMenu->setItemEnabled(stackMenu->idAt(1), li != NULL);
	stackMenu->setItemEnabled(stackMenu->idAt(3), CALCULATOR->RPNStackSize() > 0);
	stackMenu->popup(p);
}
void KQalculate::registerSelected() {
	TQListViewItem *li = stackList->selectedItem();
	if(li) {
		size_t index = (size_t) li->text(0).toUInt() - 1;
		registerUpButton->setEnabled(index != 0);
		registerDownButton->setEnabled(index + 1 < CALCULATOR->RPNStackSize());
		editRegisterButton->setEnabled(true);
		deleteRegisterButton->setEnabled(true);
	} else {
		registerUpButton->setEnabled(false);
		registerDownButton->setEnabled(false);
		editRegisterButton->setEnabled(false);
		deleteRegisterButton->setEnabled(false);
	}
}

void KQalculate::insertPlus() {
	if(rpn_mode) {
		calculateRPN(OPERATION_ADD);
		return;
	}
	if(!evalops.parse_options.rpn) {
		expressionEdit->wrapSelection();
		expressionEdit->deselect();
	}
	insert_text("+");
}

void KQalculate::insertMinus() {
	if(rpn_mode) {
		calculateRPN(OPERATION_SUBTRACT);
		return;
	}
	if(!evalops.parse_options.rpn) {
		expressionEdit->wrapSelection();
		expressionEdit->deselect();
	}
	if(printops.use_unicode_signs && can_display_unicode_string_function(SIGN_MINUS, (void*) expressionEdit)) insert_text(SIGN_MINUS);
	else insert_text("-");
}

void KQalculate::insertAns() {
	insert_text(vans[0]->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) expressionEdit).name.c_str());
}


void KQalculate::insertExp() {
	if(rpn_mode) {
		calculateRPN(OPERATION_EXP10);
		return;
	}
	if(printops.lower_case_e) insert_text("e");
	else insert_text("E");	
}


void KQalculate::insertDot() {
	insert_text(CALCULATOR->getDecimalPoint().c_str());
}


void KQalculate::insertKP0() {
	insert_text("0");
}


void KQalculate::insertKP9() {
	insert_text("9");
}


void KQalculate::insertKP8() {
	insert_text("8");
}


void KQalculate::insertKP7() {
	insert_text("7");
}


void KQalculate::insertKP6() {
	insert_text("6");
}


void KQalculate::insertKP5() {
	insert_text("5");
}


void KQalculate::insertKP4() {
	insert_text("4");
}


void KQalculate::insertKP3() {
	insert_text("3");
}


void KQalculate::insertKP2() {
	insert_text("2");
}


void KQalculate::insertKP1() {
	insert_text("1");
}

void KQalculate::expressionDel() {
	expressionEdit->del();
}


void KQalculate::clearExpression() {
	expressionEdit->clear();
}

void KQalculate::insertSquare() {
	if(rpn_mode) {
		calculateRPN(CALCULATOR->f_sq);
		return;
	}
	if(evalops.parse_options.rpn) {
		insertButtonFunction(CALCULATOR->f_sq);
	} else {
		expressionEdit->wrapSelection();
		expressionEdit->deselect();
		insert_text("^2");
	}
}

void KQalculate::setFractionMode(bool b) {
	if(b) {
		ActionFractionalDisplayFraction->activate();
	} else {
		ActionFractionalDisplayDecimal->activate();
	}
}

void KQalculate::setExactMode(bool b) {
	if(b) {
		ActionApproximationAlwaysExact->activate();
	} else {
		ActionApproximationTryExact->activate();
	}
}

void KQalculate::kpSetAngleUnit(int index) {
	switch(index) {
		case 0: {
			ActionAngleUnitDegrees->activate();
			break;
		}
		case 1: {
			ActionAngleUnitRadians->activate();
			break;
		}
		case 2: {
			ActionAngleUnitGradians->activate();
			break;
		}
		case 3: {
			ActionAngleUnitNone->activate();
			break;
		}
	}
}

void KQalculate::kpSetNumericalMode(int index) {
	switch(index) {
		case 0: {
			printops.negative_exponents = false;
			printops.sort_options.minus_last = true;
			ActionNumericalDisplayNormal->activate();
			break;
		}
		case 1: {
			ActionNumericalDisplayEngineering->activate();
			break;
		}
		case 2: {
			printops.negative_exponents = true;
			printops.sort_options.minus_last = false;
			ActionNumericalDisplayScientific->activate();
			break;
		}
		case 3: {
			printops.negative_exponents = true;
			printops.sort_options.minus_last = false;
			ActionNumericalDisplayPurelyScientific->activate();
			break;
		}
		case 4: {
			printops.negative_exponents = false;
			printops.sort_options.minus_last = true;
			ActionNumericalDisplaySimple->activate();
			break;
		}
	}
	ActionNegativeExponents->setChecked(printops.negative_exponents);
	ActionSortMinusLast->setChecked(printops.sort_options.minus_last);
}


void KQalculate::kpSetBaseSelected(int index) {
	switch(index) {
		case 7: {
			numberBaseOther();
			break;
		}
	}
}
void KQalculate::kpSetBase(int index) {
	switch(index) {
		case 0: {
			ActionNumberBaseBinary->activate();
			break;
		}
		case 1: {
			ActionNumberBaseOctal->activate();
			break;
		}
		case 2: {
			ActionNumberBaseDecimal->activate();
			break;
		}
		case 3: {
			ActionNumberBaseHexadecimal->activate();
			break;
		}
		case 4: {
			ActionNumberBaseSexagesimal->activate();
			break;
		}
		case 5: {
			ActionNumberBaseTimeFormat->activate();
			break;
		}
		case 6: {
			ActionNumberBaseRomanNumerals->activate();
			break;
		}
		case 7: {
			ActionNumberBaseOther->activate();
			break;
		}
	}
}

void KQalculate::insertMod() {
	insertButtonFunction(CALCULATOR->f_mod);
}


void KQalculate::insertFactorial() {
	if(rpn_mode) {
		insertButtonFunction(CALCULATOR->f_factorial);
		return;
	}
	expressionEdit->wrapSelection();
	expressionEdit->deselect();
	insert_text("!");
}

void KQalculate::storeResult() {
	if(!store_dialog) {
		store_dialog = new QalculateEditVariableDialog(this);
	}
	Variable *v = store_dialog->editVariable(i18n("Temporary"), NULL, mstruct, true);
	if(v) {
		update_vmenu();
		variable_inserted(v);
	}
}

void KQalculate::manageVariables() {
	if(!variables_dialog) {
		variables_dialog = new QalculateVariablesDialog();
		variables_dialog->updateVariableTree();
		TQObject::connect(variables_dialog, TQ_SIGNAL(variablesChanged()), this, TQ_SLOT(update_vmenu()));
		TQObject::connect(variables_dialog, TQ_SIGNAL(insertRequest(Variable*)), this, TQ_SLOT(insertVariable(Variable*)));
	}
	variables_dialog->show();
}
void KQalculate::insertVariable(Variable *v) {
	insert_text(v->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) expressionEdit).name.c_str());
	variable_inserted(v);
}
void KQalculate::insertFunction(MathFunction *f, TQWidget *parent) {
	if(!CALCULATOR->stillHasFunction(f)) {
		KMessageBox::error(parent, i18n("Function does not exist anymore."));
		update_fmenu();
		return;
	}
	if(f->args() == 0) {
		TQString str = f->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) expressionEdit).name.c_str();
		str += "()";
		insert_text(str);
		function_inserted(f);
	} else {
		QalculateInsertFunctionDialog *dialog = new QalculateInsertFunctionDialog(f, parent, expressionEdit->selectedText());
		int rcode = dialog->exec();
		if(rcode != TQDialog::Rejected) {
			if(rcode == TQDialog::Accepted) {
				insert_text(dialog->functionExpression());
			} else {
				expressionEdit->setText(dialog->functionExpression());
				execute();
				expressionEdit->setFocus();
			}
			function_inserted(f);
		}
		delete dialog;
	}
}
void KQalculate::applyFunction(MathFunction *f, TQWidget *parent) {
	if(!CALCULATOR->stillHasFunction(f)) {
		KMessageBox::error(parent, i18n("Function does not exist anymore."));
		update_fmenu();
		return;
	}
	if(rpn_mode) {
		calculateRPN(f);
		return;
	}
	TQString str = f->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) expressionEdit).name.c_str();
	if(f->args() == 0) {
		str += "()";
	} else {
		str += "(";
		str += vans[0]->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) expressionEdit).name.c_str();
		str += ")";
	}
	insert_text(str);
	function_inserted(f);
	execute();
}

void KQalculate::convertToUnitConvertToDialogExpression() {
	error_timer->stop();
	mstruct->set(CALCULATOR->convert(*mstruct, convert_to_unit_expression_dialog->unitExpressionEdit->text().ascii(), evalops));
	result_action_executed();
	error_timer->start(100);
}

void KQalculate::convertToUnitExpression() {
	if(!convert_to_unit_expression_dialog) {
		convert_to_unit_expression_dialog = new QalculateConvertUnitsDialog(this);
		convert_to_unit_expression_dialog->updateUnitTree();
		TQObject::connect(convert_to_unit_expression_dialog, TQ_SIGNAL(applyClicked()), this, TQ_SLOT(convertToUnitConvertToDialogExpression()));
		TQObject::connect(convert_to_unit_expression_dialog, TQ_SIGNAL(okClicked()), this, TQ_SLOT(convertToUnitConvertToDialogExpression()));
		TQObject::connect(convert_to_unit_expression_dialog, TQ_SIGNAL(unitsChanged()), this, TQ_SLOT(update_umenus()));
	}
	convert_to_unit_expression_dialog->show();
}

void KQalculate::convertNumberBases() {
	if(!convert_number_bases_dialog) {
		convert_number_bases_dialog = new QalculateConvertNumberBasesDialog();
	}
	convert_number_bases_dialog->show();
}

void KQalculate::insertManagedFunction(MathFunction *f) {
	insertFunction(f, functions_dialog);
}
void KQalculate::applyManagedFunction(MathFunction *f) {
	applyFunction(f, functions_dialog);
}
void KQalculate::manageFunctions() {
	if(!functions_dialog) {
		functions_dialog = new QalculateFunctionsDialog();
		functions_dialog->updateFunctionTree();
		TQObject::connect(functions_dialog, TQ_SIGNAL(functionsChanged()), this, TQ_SLOT(update_fmenu()));
		TQObject::connect(functions_dialog, TQ_SIGNAL(insertRequest(MathFunction*)), this, TQ_SLOT(insertManagedFunction(MathFunction*)));
		TQObject::connect(functions_dialog, TQ_SIGNAL(applyRequest(MathFunction*)), this, TQ_SLOT(applyManagedFunction(MathFunction*)));
	}
	functions_dialog->show();
}

void KQalculate::newUnit() {
	if(!unit_edit_dialog) {
		unit_edit_dialog = new QalculateEditUnitDialog(this);
	}
	Unit *u = unit_edit_dialog->editUnit();
	if(u) {
		update_umenus();
		unit_inserted(u);
	}
}


void KQalculate::newDataSet() {
	if(!dataset_edit_dialog) {
		dataset_edit_dialog = new QalculateEditDataSetDialog(this);
	}
	MathFunction *f = dataset_edit_dialog->editDataSet();
	if(f) {
		update_fmenu();
		function_inserted(f);
	}
}


void KQalculate::newFunction() {
	if(!function_edit_dialog) {
		function_edit_dialog = new QalculateEditFunctionDialog(this);
	}
	MathFunction *f = function_edit_dialog->editFunction();
	if(f) {
		update_fmenu();
		function_inserted(f);
	}
}


void KQalculate::newUnknownVariable() {
	if(!unknown_edit_dialog) {
		unknown_edit_dialog = new QalculateEditUnknownVariableDialog(this);
	}
	Variable *v = unknown_edit_dialog->editVariable(i18n("My Variables"));
	if(v) {
		update_vmenu();
		variable_inserted(v);
	}
}


void KQalculate::newVector() {
	if(!matrix_edit_dialog) {
		matrix_edit_dialog = new QalculateEditMatrixVectorDialog(this);
	}
	Variable *v = matrix_edit_dialog->newVector(i18n("Vectors"));
	if(v) {
		update_vmenu();
		variable_inserted(v);
	}
}


void KQalculate::newMatrix() {
	if(!matrix_edit_dialog) {
		matrix_edit_dialog = new QalculateEditMatrixVectorDialog(this);
	}
	Variable *v = matrix_edit_dialog->newMatrix(i18n("Matrices"));
	if(v) {
		update_vmenu();
		variable_inserted(v);
	}
}


void KQalculate::newVariable() {
	if(!variable_edit_dialog) {
		variable_edit_dialog = new QalculateEditVariableDialog(0);
	}
	Variable *v = variable_edit_dialog->editVariable(i18n("My Variables"));
	if(v) {
		update_vmenu();
		variable_inserted(v);
	}
}


void KQalculate::exportCSVFile() {
	if(!export_csv_dialog) {
		export_csv_dialog = new QalculateExportCSVDialog(this);
	}
	export_csv_dialog->exportCSVFile();
}


void KQalculate::importCSVFile() {
	if(!import_csv_dialog) {
		import_csv_dialog = new QalculateImportCSVDialog(this);
	}
	if(import_csv_dialog->importCSVFile()) {
		update_vmenu();
	}
}


void KQalculate::saveAsImage() {
	TQString filename;
	while(true) {
		filename = KFileDialog::getSaveFileName("qalculate.png", "image/png", this, i18n("Save Image"));
		if(filename.isEmpty()) {
			return;
		} else {
			if(TQFile::exists(filename)) {
				if(KMessageBox::warningContinueCancel(this, i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?" ).arg(filename), i18n("Overwrite File?"), i18n( "&Overwrite" )) != KMessageBox::Cancel) {
					break;
				}
			} else {
				break;
			}
		}
	}
	TQString str = result_text;
	str.replace("width=1 ", "");
	TQSimpleRichText text(str, resultLabel->font());
	TQPicture picture;
	TQPainter p(&picture);
	text.setWidth(1000);
	text.draw(&p, 0, 0, TQRect(), TQColorGroup(TQt::black, TQt::white, TQt::white, TQt::white, TQt::white, TQt::black, TQt::white));
	p.flush();
	p.end();
	TQPixmap pixmap(picture.boundingRect().width(), picture.boundingRect().height());
	pixmap.fill(TQt::white);
	TQPainter p2(&pixmap);
	p2.drawPicture(-picture.boundingRect().x(), -picture.boundingRect().y(), picture);
	p2.flush();
	p2.end();
	TQImage image(pixmap.convertToImage());
	image.setAlphaBuffer(true);
	int h = image.height(), w = image.width();
	TQRgb pixel;
	for(int r =0; r < h; r++) {
		for(int c =0; c < w; c++) {
			pixel = image.pixel(c, r);
			image.setPixel(c, r, tqRgba(0, 0, 0, 0xff - ((tqRed(pixel) + tqBlue(pixel) + tqGreen(pixel))/ 3)));
		}
	}
	if(!image.save(filename, "PNG")) {
		KMessageBox::error(this, i18n("Failed to save image."));
	}
}


void KQalculate::saveDefinitions() {
	save_defs();
}


void KQalculate::plotFunctionsData() {
	if(!plot_dialog) {
		plot_dialog = new QalculatePlotDialog();
	}
	plot_dialog->expressionEdit->setText(expressionEdit->text());
	plot_dialog->show();
}


void KQalculate::periodicTable() {
	if(!periodic_table_dialog) {
		periodic_table_dialog = new QalculatePeriodicTableDialog();
	}
	periodic_table_dialog->show();
}


void KQalculate::onSetPrefixMenuItemActivated(int id) {
	if(!menu_set_prefix_ids.contains(id)) return;
	result_prefix_changed(menu_set_prefix_ids[id]);
}


void KQalculate::onConvertToUnitMenuItemActivated(int id) {
	if(!menu_to_unit_ids.contains(id)) return;
	error_timer->stop();
	mstruct->set(CALCULATOR->convert(*mstruct, menu_to_unit_ids[id], evalops));
	result_action_executed();
	error_timer->start(100);
}



void KQalculate::preferences() {
	if(!preferences_dialog) {
		preferences_dialog = new QalculatePreferencesDialog(this);
	}
	close_to_systray_was = close_to_systray;
	display_expression_status_was = display_expression_status;
	preferences_dialog->editPreferences();
}

void KQalculate::applyPreferences() {
	if(use_custom_result_font) {
		TQFont font(resultLabel->font());
		font.fromString(custom_result_font);
		resultLabel->setFont(font);
	} else {
		resultLabel->unsetFont();
	}
	if(use_custom_expression_font) {
		TQFont font(expressionEdit->font());
		font.fromString(custom_expression_font);
		expressionEdit->setFont(font);
	} else {
		expressionEdit->unsetFont();
	}
	updateStatusLabelFonts();
	set_unicode_buttons();
	result_display_updated();
	if(close_to_systray != close_to_systray_was) {
		showSystemTrayIcon(close_to_systray);
	}
	if(display_expression_status != display_expression_status_was) {
		if(display_expression_status) {
			statusLabel_l->show();				
		} else {
			statusLabel_l->hide();
		}
	}
	displayParseStatus();
		
	bool use_button_pixmaps = false;
	if(use_icon_buttons > 0) {
		use_button_pixmaps = true;
	} else if(use_icon_buttons < 0) {
		TDEConfig config("kdeglobals", true, false);	
		config.setGroup("KDE");	
		use_button_pixmaps = config.readBoolEntry("ShowIconsOnPushButtons", false);
	}

	if(leftButtonsSeparator->isVisible() == use_button_pixmaps) {
		if(use_button_pixmaps) {
			leftButtonsLayout->setSpacing(3);
			executeButton->setText("");	
			executeButton->setIconSet(TDEApplication::kApplication()->iconLoader()->loadIconSet("application-x-executable", TDEIcon::Small, TDEIcon::SizeSmallMedium));
			storeButton->setText("");	
			storeButton->setIconSet(TDEApplication::kApplication()->iconLoader()->loadIconSet("document-save-as", TDEIcon::Small, TDEIcon::SizeSmallMedium));
			convertButton->setText("");	
			convertButton->setIconSet(TDEApplication::kApplication()->iconLoader()->loadIconSet("qalculate_convert", TDEIcon::Small, TDEIcon::SizeSmallMedium));
			leftButtonsSeparator->hide();
			stackPageButtonsLayout->setSpacing(3);
			registerUpButton->setText("");
			registerUpButton->setIconSet(TDEApplication::kApplication()->iconLoader()->loadIconSet("go-up", TDEIcon::Small, TDEIcon::SizeSmallMedium));
			registerDownButton->setText("");
			registerDownButton->setIconSet(TDEApplication::kApplication()->iconLoader()->loadIconSet("go-down", TDEIcon::Small, TDEIcon::SizeSmallMedium));
			editRegisterButton->setText("");
			editRegisterButton->setIconSet(TDEApplication::kApplication()->iconLoader()->loadIconSet("edit", TDEIcon::Small, TDEIcon::SizeSmallMedium));
			deleteRegisterButton->setText("");
			deleteRegisterButton->setIconSet(TDEApplication::kApplication()->iconLoader()->loadIconSet("edit-delete", TDEIcon::Small, TDEIcon::SizeSmallMedium));
			clearStackButton->setText("");
			clearStackButton->setIconSet(TDEApplication::kApplication()->iconLoader()->loadIconSet("view_remove", TDEIcon::Small, TDEIcon::SizeSmallMedium));
		} else {
			leftButtonsLayout->setSpacing(6);
			if(rpn_mode) executeButton->setText(i18n("Enter"));
			else executeButton->setText(i18n("="));
			executeButton->setIconSet(TQIconSet());
			storeButton->setText(i18n("Store"));	
			storeButton->setIconSet(TQIconSet());
			convertButton->setText(i18n("Convert"));	
			convertButton->setIconSet(TQIconSet());
			leftButtonsSeparator->show();
			stackPageButtonsLayout->setSpacing(6);
			registerUpButton->setText(i18n("Up"));
			registerUpButton->setIconSet(TQIconSet());
			registerDownButton->setText(i18n("Down"));
			registerDownButton->setIconSet(TQIconSet());
			editRegisterButton->setText(i18n("Edit"));
			editRegisterButton->setIconSet(TQIconSet());
			deleteRegisterButton->setText(i18n("Delete"));
			deleteRegisterButton->setIconSet(TQIconSet());
			clearStackButton->setText(i18n("Clear"));
			clearStackButton->setIconSet(TQIconSet());
		}
		updateButtonWidths();
	}
}


void KQalculate::copyResult() {
	TQApplication::clipboard()->setText(result_history_text, TQClipboard::Clipboard);
}

void KQalculate::clearHistory() {
	historyBrowser->setText("&nbsp;");
	expressionEdit->setFocus();
	inhistory.clear();
	inhistory_type.clear();
	inhistory_current_id = 0;
	inhistory_id.clear();
	initial_inhistory_index = 0;
	initial_result_index = 0;
}

void KQalculate::convertToBestUnit() {
	error_timer->stop();
	mstruct->set(CALCULATOR->convertToBestUnit(*mstruct, evalops));
	result_action_executed();
	error_timer->start(100);
}

void KQalculate::convertToBaseUnits() {
	error_timer->stop();
	mstruct->set(CALCULATOR->convertToBaseUnits(*mstruct, evalops));
	result_action_executed();
	error_timer->start(100);
}

void KQalculate::applySetUnknowns(bool okclicked) {
	TQString str;
	TQString result_mod = "";
	bool b = false;
	mstruct->set(*mstruct_before_unknowns);
	for(size_t i = 1; i <= unknowns_mstruct->size(); i++) {
		str = unknowns_entries[i - 1]->text().stripWhiteSpace();
		if(unknown_changed[i - 1] || !str.isEmpty()) {
			if(!result_mod.isEmpty()) {
				result_mod += CALCULATOR->getComma().c_str();
				result_mod += " ";
			}
			result_mod += unknowns_mstruct->getChild(i)->print().c_str();
			result_mod += "=";
			if(str.isEmpty()) {
				result_mod += "?";
			} else {
				result_mod += str;
				mstruct->replace(*unknowns_mstruct->getChild(i), CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(str.ascii(), evalops.parse_options), evalops));
				b = true;
				unknown_changed[i - 1] = true;
			}
		}
	}
	if(b) {
		b_unknowns_changed = true;
		if(okclicked && !rpn_mode) {
			MathStructure mp(*mstruct);
			printops.can_display_unicode_string_arg = historyBrowser;
			mp.format(printops);
			str = mp.print(printops).c_str();
			expressionEdit->blockSignals(true);			
			expressionEdit->setText(str);
			printops.can_display_unicode_string_arg = NULL;
			//expressionEdit->addToHistory(str);
			expressionEdit->expression_history_index = -1;
			expressionEdit->blockSignals(false);
			expressionEdit->setFocus();
			expressionEdit->selectAll();
			expression_has_changed2 = true;
			displayParseStatus();
		}
		mstruct->eval(evalops);
	}
	if(b_unknowns_changed) {
		printops.allow_factorization = (evalops.structuring == STRUCTURING_FACTORIZE);
		setResult(NULL, true, false, false, result_mod);
	}	
	//if(!okclicked && b) mstruct->set(*mstruct_before_unknowns);
}
void KQalculate::setUnknownsApplyClicked() {
	applySetUnknowns(false);
}
void KQalculate::setUnknowns() {
	if(expression_has_changed && !rpn_mode) execute_expression(true);
	unknowns_mstruct = new MathStructure();
	mstruct->findAllUnknowns(*unknowns_mstruct);
	if(unknowns_mstruct->size() == 0) {
		KMessageBox::error(this, i18n("No unknowns in result."));
		return;
	}
	KDialogBase *dialog = new KDialogBase(this, 0, true, i18n("Set Unknowns"));
	TQObject::connect(dialog, TQ_SIGNAL(applyClicked()), this, TQ_SLOT(setUnknownsApplyClicked()));
	TQGrid *grid = dialog->makeGridMainWidget(2, TQt::Horizontal);
	unknowns_entries.clear();
	for(size_t i = 1; i <= unknowns_mstruct->size(); i++) {
		new TQLabel(unknowns_mstruct->getChild(i)->print().c_str(), grid);
		unknowns_entries.push_back(new KLineEdit(grid));
		if(i == 1) unknowns_entries[0]->setFocus();
	}
	mstruct_before_unknowns = new MathStructure(*mstruct);
	b_unknowns_changed = false;
	unknown_changed.clear();
	unknown_changed.resize(unknowns_mstruct->size(), false);
	int response = dialog->exec();
	if(response == TQDialog::Accepted) {
		applySetUnknowns(true);
	} else {
		if(b_unknowns_changed) {
			TQString result_mod = "";
			for(size_t i = 1; i <= unknowns_mstruct->size(); i++) {
				if(unknown_changed[i - 1]) {
					if(!result_mod.isEmpty()) {
						result_mod += CALCULATOR->getComma().c_str();
						result_mod += " ";
					}
					result_mod += unknowns_mstruct->getChild(i)->print().c_str();
					result_mod += "=";
					result_mod += "?";
				}
			}
			mstruct->set(*mstruct_before_unknowns);
			printops.allow_factorization = (evalops.structuring == STRUCTURING_FACTORIZE);
			setResult(NULL, true, false, false, result_mod);
			expressionEdit->setFocus();
		}
	}
	delete dialog;
	delete mstruct_before_unknowns;
	delete unknowns_mstruct;
}


void KQalculate::manageDataSets() {
	if(!datasets_dialog) {
		datasets_dialog = new QalculateDataSetsDialog();
		datasets_dialog->updateDataSetTree();
		TQObject::connect(datasets_dialog, TQ_SIGNAL(dataSetsChanged()), this, TQ_SLOT(update_fmenu()));
	}
	datasets_dialog->show();
}

void KQalculate::factorize() {
	executeCommand(COMMAND_FACTORIZE);
}
void KQalculate::simplify() {
	executeCommand(COMMAND_SIMPLIFY);
}

void KQalculate::manageUnits() {
	if(!units_dialog) {
		units_dialog = new QalculateUnitsDialog();
		units_dialog->updateUnitTree();
		TQObject::connect(units_dialog, TQ_SIGNAL(unitsChanged()), this, TQ_SLOT(update_umenus()));
		TQObject::connect(units_dialog, TQ_SIGNAL(insertRequest(Unit*)), this, TQ_SLOT(insertUnit(Unit*)));
		TQObject::connect(units_dialog, TQ_SIGNAL(convertRequest(Unit*)), this, TQ_SLOT(convertResult(Unit*)));
	}
	units_dialog->show();
}
void KQalculate::insertUnit(Unit *u) {
	if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) {
		insert_text(((CompositeUnit*) u)->print(true, printops.abbreviate_names, printops.use_unicode_signs, &can_display_unicode_string_function, (void*) expressionEdit).c_str());
	} else {
		insert_text(u->preferredInputName(printops.abbreviate_names, printops.use_unicode_signs, true, false, &can_display_unicode_string_function, (void*) expressionEdit).name.c_str());
	}
	unit_inserted(u);
}
void KQalculate::convertResult(Unit *u) {
	error_timer->stop();
	mstruct->set(CALCULATOR->convert(*mstruct, u, evalops));
	result_action_executed();
	error_timer->start(100);
}
void KQalculate::insertMatrixVector(const MathStructure *m, bool do_vector, bool is_text_struct, bool is_result) {
	if(!insert_matrix_dialog) {
		insert_matrix_dialog = new QalculateInsertMatrixVectorDialog(this);
	}
	TQString str = insert_matrix_dialog->editMatrixVector(m, do_vector, is_text_struct, is_result);
	if(!str.isEmpty()) {
		insert_text(str);
	}
}
void KQalculate::insertMatrix() {
	TQString str = expressionEdit->selectedText().stripWhiteSpace();
	if(!str.isEmpty()) {
		MathStructure mstruct_sel;
		CALCULATOR->beginTemporaryStopMessages();
		CALCULATOR->parse(&mstruct_sel, CALCULATOR->unlocalizeExpression(str.ascii(), evalops.parse_options), evalops.parse_options);
		CALCULATOR->endTemporaryStopMessages();
		if(mstruct_sel.isMatrix()) {
			insertMatrixVector(&mstruct_sel, false);
			return;
		}
	}
	insertMatrixVector(NULL, false);
}
void KQalculate::insertVector() {
	TQString str = expressionEdit->selectedText().stripWhiteSpace();
	if(!str.isEmpty()) {
		MathStructure mstruct_sel;
		CALCULATOR->beginTemporaryStopMessages();
		CALCULATOR->parse(&mstruct_sel, CALCULATOR->unlocalizeExpression(str.ascii(), evalops.parse_options), evalops.parse_options);
		CALCULATOR->endTemporaryStopMessages();
		if(mstruct_sel.isVector() && !mstruct_sel.isMatrix()) {
			insertMatrixVector(&mstruct_sel, true);
			return;
		}
	}
	insertMatrixVector(NULL, true);
}

void KQalculate::keyPressEvent(TQKeyEvent *e) {
	TDEMainWindow::keyPressEvent(e);
	if(e->isAccepted()) return;
	if(close_to_systray && e->key() == Key_Escape && e->state() == 0) {
		e->accept();
		hide();
		return;
	}
	if(!expressionEdit->hasFocus() && e->key() != TQt::Key_Control && e->key() != TQt::Key_Meta && e->key() != TQt::Key_Shift && e->key() != TQt::Key_Alt) {
		expressionEdit->setFocus();
		expressionEdit->keyPressEvent(e);
	}
}

bool KQalculate::queryClose() {
	if(m_parent->sessionSaving() || !close_to_systray) return true;
	hide();
	setShown(false);
	return false;
}
void KQalculate::saveProperties(TDEConfig*) {
	TDEConfig *cfg = TDEGlobal::config();
	cfg->setGroup("Session");
	cfg->writeEntry("docked", isHidden());
}
void KQalculate::readProperties(TDEConfig*) {
	TDEConfig *cfg = TDEGlobal::config();
	cfg->setGroup("Session");
	if(close_to_systray && cfg->readBoolEntry("docked", true)) {
		hide();
	} else {
		show();
	}
}

void KQalculate::display_function_hint(MathFunction *f, int arg_index) {
	if(!f) return;
	int iargs = f->maxargs();
	Argument *arg;
	Argument default_arg;
	TQString str, str2, str3;
	const ExpressionName *ename = &f->preferredName(false, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) statusLabel_l);
	bool last_is_vctr = f->getArgumentDefinition(iargs) && f->getArgumentDefinition(iargs)->type() == ARGUMENT_TYPE_VECTOR;
	if(arg_index > iargs && iargs >= 0 && !last_is_vctr) {
		statusLabel_l->setText(i18n("Too many arguments for %1().").arg(ename->name.c_str()), false, false, true);
		return;
	}
	str += ename->name.c_str();
	if(iargs < 0) {
		iargs = f->minargs() + 1;
		if(arg_index > iargs) arg_index = iargs;
	}
	if(arg_index > iargs && last_is_vctr) arg_index = iargs;
	
	str += "(";
	int i_reduced = 0;
	if(iargs != 0) {
		for(int i2 = 1; i2 <= iargs; i2++) {			
			if(i2 > f->minargs() && arg_index < i2) {
				str += "[";
			}
			if(i2 > 1) {
				str += CALCULATOR->getComma().c_str();
				str += " ";
			}
			if(i2 == arg_index) str += "<b>";
			arg = f->getArgumentDefinition(i2);
			if(arg && !arg->name().empty()) {
				str2 = arg->name().c_str();
			} else {
				str2 = i18n("argument");
				str2 += " ";
				str2 += TQString::number(i2);
			}
			if(i2 == arg_index) {
				if(arg) {
					if(i_reduced == 2) str3 = arg->print().c_str();
					else str3 = arg->printlong().c_str();
				} else {
					Argument arg_default;
					if(i_reduced == 2) str3 = arg_default.print().c_str();
					else str3 = arg_default.printlong().c_str();
				}
				if(!str3.isEmpty()) {
					str2 += ": ";
					str2 += str3;
				}
				str2.replace("&", "&amp;");
				str2.replace(">", "&gt;");
				str2.replace("<", "&lt;");
				str += str2;
				str += "</b>";
				if(i_reduced < 2) {
					TQSimpleRichText qsrt(str, statusLabel_l->font());
					qsrt.setWidth(statusLabel_l->contentsRect().width() + 100);
					if(qsrt.widthUsed() > statusLabel_l->contentsRect().width() - 4) {
						str = ename->name.c_str();	
						str += "(";
						if(i2 != 1) {
							str += "...";
							i_reduced++;
						} else {
							i_reduced = 2;
						}
						i2--;
					}
				} else {
					i_reduced = 0;
				}
			} else {
				str2.replace("&", "&amp;");
				str2.replace(">", "&gt;");
				str2.replace("<", "&lt;");
				str += str2;
				if(i2 > f->minargs() && arg_index < i2) {
					str += "]";
				}
			}
		}
		if(f->maxargs() < 0) {
			str += CALCULATOR->getComma().c_str();
			str += " ...";
		}
	}
	str += ")";
	statusLabel_l->setText(str, false, false, false);
}

void KQalculate::displayParseStatus() {
	if(!display_expression_status) return;
	if(expressionEdit->text().length() == 0) {
		statusLabel_l->setText("", true, false, false);
		parsed_expression = "";
		expression_has_changed2 = false;
		had_errors_before = false;
		had_warnings_before = false;
		return;
	}
	MathStructure mparse, mfunc;
	std::string str_e, str_u;
	int pos = expressionEdit->cursorPosition();
	bool full_parsed = false;
	bool had_errors = false, had_warnings = false;
	evalops.parse_options.preserve_format = true;
	if(pos > 0) {
		evalops.parse_options.unended_function = &mfunc;
		CALCULATOR->beginTemporaryStopMessages();
		if(pos < (int) expressionEdit->text().length()) {
			TQString str = expressionEdit->text();
			str.truncate(pos);
			str_e = CALCULATOR->unlocalizeExpression(str.ascii(), evalops.parse_options);
			if(!CALCULATOR->separateToExpression(str_e, str_u, evalops)) {
				CALCULATOR->parse(&mparse, str_e, evalops.parse_options);
			}
		} else {
			str_e = CALCULATOR->unlocalizeExpression(expressionEdit->text().ascii(), evalops.parse_options);
			CALCULATOR->separateToExpression(str_e, str_u, evalops);
			CALCULATOR->parse(&mparse, str_e, evalops.parse_options);
			full_parsed = true;
		}
		int warnings_count;
		had_errors = CALCULATOR->endTemporaryStopMessages(NULL, &warnings_count) > 0;
		had_warnings = warnings_count > 0;
		evalops.parse_options.unended_function = NULL;
	}
	if(mfunc.isFunction()) {
		if(mfunc.countChildren() == 0) {
			display_function_hint(mfunc.function(), 1);
		} else {
			display_function_hint(mfunc.function(), mfunc.countChildren());
		}
	}
	if(expression_has_changed2) {
		if(!full_parsed) {
			CALCULATOR->beginTemporaryStopMessages();
			str_e = CALCULATOR->unlocalizeExpression(expressionEdit->text().ascii(), evalops.parse_options);
			CALCULATOR->separateToExpression(str_e, str_u, evalops);
			CALCULATOR->parse(&mparse, str_e, evalops.parse_options);
			int warnings_count;
			had_errors = CALCULATOR->endTemporaryStopMessages(NULL, &warnings_count) > 0;
			had_warnings = warnings_count > 0;
		}
		PrintOptions po;
		po.preserve_format = true;
		po.show_ending_zeroes = true;
		po.lower_case_e = printops.lower_case_e;
		po.lower_case_numbers = printops.lower_case_numbers;
		po.base_display = printops.base_display;
		po.abbreviate_names = false;
		po.hide_underscore_spaces = true;
		po.use_unicode_signs = printops.use_unicode_signs;
		po.multiplication_sign = printops.multiplication_sign;
		po.division_sign = printops.division_sign;
		po.short_multiplication = false;
		po.excessive_parenthesis = true;
		po.improve_division_multipliers = false;
		po.can_display_unicode_string_function = &can_display_unicode_string_function;
		po.can_display_unicode_string_arg = (void*) statusLabel_l;
		po.spell_out_logical_operators = printops.spell_out_logical_operators;
		po.restrict_to_parent_precision = false;
		mparse.format(po);
		parsed_expression = mparse.print(po).c_str();
		if(!str_u.empty()) {
			parsed_expression += CALCULATOR->localToString().c_str();
			CALCULATOR->beginTemporaryStopMessages();
			CompositeUnit cu("", "temporary_composite_parse", "", str_u);
			int warnings_count;
			had_errors = CALCULATOR->endTemporaryStopMessages(NULL, &warnings_count) > 0 || had_errors;
			had_warnings = had_warnings || warnings_count > 0;
			mparse = cu.generateMathStructure(!printops.negative_exponents);
			mparse.format(po);
			parsed_expression += mparse.print(po).c_str();
		}
		parsed_expression.replace("&", "&amp;");
		parsed_expression.replace(">", "&gt;");
		parsed_expression.replace("<", "&lt;");
		if(!mfunc.isFunction()) statusLabel_l->setText(parsed_expression, true, had_errors, had_warnings);
		expression_has_changed2 = false;
		had_errors_before = had_errors;
		had_warnings_before = had_warnings;
	} else if(!mfunc.isFunction()) {	
		statusLabel_l->setText(parsed_expression, true, had_errors_before, had_warnings_before);
	}
	evalops.parse_options.preserve_format = false;
}

void KQalculate::editHistoryExpression() {
	if(current_history_index < inhistory.size()) {
		TQString text = inhistory[current_history_index];
		text.replace("&amp;", "&");
		text.replace("&gt;", ">");
		text.replace("&lt;", "<");
		text.replace("<br>", " ");
		expressionEdit->setText(text);
		expressionEdit->setFocus();
	}
}
void KQalculate::editHistoryParse() {
	if(current_history_index < inhistory.size()) {
		TQString text = inhistory[current_history_index];
		text.replace("&amp;", "&");
		text.replace("&gt;", ">");
		text.replace("&lt;", "<");
		text.replace("<br>", " ");
		expressionEdit->setText(text);
		expressionEdit->setFocus();
	}
}
void KQalculate::editHistoryResult() {
	if(current_history_index < inhistory.size()) {
		TQString text = inhistory[current_history_index];
		text.replace("&amp;", "&");
		text.replace("&gt;", ">");
		text.replace("&lt;", "<");
		text.replace("<br>", " ");
		expressionEdit->setText(text);
		expressionEdit->setFocus();
	}
}
void KQalculate::insertHistoryResultVariable() {
	if(current_history_index < inhistory.size()) {
		int id = inhistory_id[current_history_index];
		for(size_t i = 0; i < 5; i++) {
			if(vans_id_start[i] != -1 && id >= vans_id_start[i] && (vans_id_end[i] == -1 || id <= vans_id_end[i])) {
				insertVariable(vans[i]);
			}
		}
	}
}

QalculateHistoryBrowser::QalculateHistoryBrowser(TQWidget *parent, const char *name) : KTextBrowser(parent, name) {}
QalculateHistoryBrowser::~QalculateHistoryBrowser() {}

TQPopupMenu *QalculateHistoryBrowser::createPopupMenu(const TQPoint &pos) {

	TQPopupMenu *menu = KTextBrowser::createPopupMenu(pos);
	menu->insertSeparator();
	mainWin->ActionClearHistory->plug(menu);
	TQString name = anchorAt(pos, TQt::AnchorName);
	if(!name.isEmpty()) {
		int id = name.toInt();
		TQValueVector<int>::size_type i = 0;
		for(; i < inhistory_id.size(); i++) {
			if(inhistory_id[i] == id) {
				break;
			}
		}
		mainWin->current_history_index = i;
		if(i < inhistory_id.size()) {
			switch(inhistory_type[i]) {
				case QALCULATE_HISTORY_PARSE: {}
				case QALCULATE_HISTORY_PARSE_APPROXIMATE: {
					menu->insertItem(i18n("Edit Expression"), mainWin, TQ_SLOT(editHistoryParse()));
					break;
				}
				case QALCULATE_HISTORY_EXPRESSION: {
					menu->insertItem(i18n("Edit Expression"), mainWin, TQ_SLOT(editHistoryExpression()));
					break;
				}
				case QALCULATE_HISTORY_RESULT_APPROXIMATE: {}
				case QALCULATE_HISTORY_RESULT: {
					menu->insertItem(i18n("Edit Result"), mainWin, TQ_SLOT(editHistoryResult()));
					for(size_t i = 0; i < 5; i++) {
						if(vans_id_start[i] != -1 && id >= vans_id_start[i] && (vans_id_end[i] == -1 || id <= vans_id_end[i])) {
							menu->insertItem(i18n("Insert Result Variable"), mainWin, TQ_SLOT(insertHistoryResultVariable()));
							break;
						}
					}
					break;
				}
				default: {}
			}
		}
	}
	return menu;

}


QalculateParseLabel::QalculateParseLabel(TQWidget *parent, const char *name) : TQLabel(parent, name) {
	TQLabel::setText("<b>A</b>");
	bb = false;
	ec = false;
	wc = false;
}
QalculateParseLabel::~QalculateParseLabel() {}
void QalculateParseLabel::setText(TQString text, bool break_begin, bool error_color, bool warning_color) {
	bb = break_begin;
	ec = error_color;
	wc = warning_color;
	parsetext = "<nobr>";
	parsetext += text;
	parsetext += "</nobr>";
	update();
}
void QalculateParseLabel::drawContents(TQPainter *p) {
	TQColorGroup cg = colorGroup();
	if(ec) {
		cg.setColor(TQColorGroup::Text, status_error_color);
	} else if(wc) {
		cg.setColor(TQColorGroup::Text, status_warning_color);
	} else if(backgroundMode() != PaletteBase && isEnabled()) {
		cg.setColor(TQColorGroup::Text, paletteForegroundColor());
	}

	TQRect cr = contentsRect();
	cr.setX(cr.x() + 4);
	cr.setWidth(cr.width() - 4);
	TQSimpleRichText qsrt(parsetext, font());
	qsrt.setWidth(p, cr.width() + 100);
	if(qsrt.widthUsed() > cr.width()) {
		if(bb) {
			TQSimpleRichText qsrt_dots("...", font());
			qsrt_dots.draw(p, cr.x(), cr.y(), cr, cg, 0);
			cr.setX(cr.x() + qsrt_dots.widthUsed());
			cr.setWidth(cr.width() - qsrt_dots.widthUsed());
			qsrt.draw(p, cr.x() + cr.width() - qsrt.widthUsed(), cr.y(), cr, cg, 0);
		} else {
			TQSimpleRichText qsrt_dots("...", font());
			qsrt_dots.draw(p, cr.x() + cr.width() - qsrt_dots.widthUsed(), cr.y(), cr, cg, 0);
			cr.setWidth(cr.width() - qsrt_dots.widthUsed());
			qsrt.draw(p, cr.x(), cr.y(), cr, cg, 0);
		}
	} else {
		qsrt.draw(p, cr.x(), cr.y(), cr, cg, 0);
	}
}

QalculateButton::QalculateButton(TQWidget *parent, const char *name) : TQPushButton(parent, name) {
	setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum));
	umtcw = true;
	TDEAcceleratorManager::setNoAccel(this);

}
QalculateButton::QalculateButton(const TQString &text, TQWidget *parent, const char *name) : TQPushButton(text, parent, name) {
	setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum));
	umtcw = true;
	TDEAcceleratorManager::setNoAccel(this);
}
QalculateButton::QalculateButton(const TQIconSet &icon, const TQString &text, TQWidget *parent, const char *name) : TQPushButton(icon, text, parent, name) {
	setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum));
	umtcw = true;
	TDEAcceleratorManager::setNoAccel(this);
}
QalculateButton::~QalculateButton() {}

void QalculateButton::setUseMinThreeCharWidth(bool b) {
	umtcw = b;
}
void QalculateButton::setMarkup(const TQString &str) {
	TQColorGroup cg(colorGroup());
	cg.setColor(TQColorGroup::Text, paletteForegroundColor());
	TQSimpleRichText rtext(str, font());
	TQPicture picture;
	TQPainter p(&picture);
	rtext.draw(&p, 0, 0, TQRect(), cg);
	p.flush();
	p.end();
	TQRect r = picture.boundingRect();
	TQPixmap pixmap(r.width(), rtext.height());
	pixmap.fill(cg.background());
	TQPainter p2(&pixmap);
	p2.drawPicture(-r.x(), 0, picture);
	p2.flush();
	p2.end();
	pixmap.setMask(pixmap.createHeuristicMask());	
	setPixmap(pixmap);	
}

TQSize QalculateButton::sizeHint() const {

	constPolish();

	int w = 0, h = 0;
    

#ifndef TQT_NO_ICONSET
	if(iconSet() && !iconSet()->isNull()) {
		w = iconSet()->pixmap( TQIconSet::Small, TQIconSet::Normal ).width() + 10;
		h = iconSet()->pixmap( TQIconSet::Small, TQIconSet::Normal ).height() + 10;
		return TQSize(w, h).expandedTo(TQApplication::globalStrut());
	}
#endif

	TQSize sz;

	if(pixmap()) {
		TQPixmap *pm = (TQPixmap *)pixmap();
		w = pm->width();
		h = pm->height();
		if(umtcw) {
			TQFontMetrics fm = fontMetrics();
			sz = fm.size(ShowPrefix, TQString::fromLatin1("XXX"));
			if(w < sz.width()) w = sz.width();
			if(w < sz.height()) w = sz.height();
		}
		sz.setWidth(w);
		sz.setHeight(h);
		w += 12;
		h += 10;
	} else {
		TQFontMetrics fm = fontMetrics();
		if(umtcw && (text().isEmpty() || text().length() < 3)) {
			sz = fm.size(ShowPrefix, TQString::fromLatin1("XXX"));
		} else {
			sz = fm.size(ShowPrefix, text());
		}
		w = sz.width() + 12;
		h = sz.height() + 10;
	}

	return TQSize(w, h).boundedTo(style().sizeFromContents(TQStyle::CT_PushButton, this, sz)).expandedTo(TQApplication::globalStrut());

}

QalculateStyleSheet::QalculateStyleSheet(TQObject *parent, const char *name) : TQStyleSheet(parent, name) {}
QalculateStyleSheet::~QalculateStyleSheet() {}
	
void QalculateStyleSheet::scaleFont(TQFont &font, int logicalSize) const {

	if(logicalSize <= 1) {
		font.setPixelSize(1);
	} else if(logicalSize == 2) {
		logicalSize = 1;
	} else if(logicalSize > 7) {
		logicalSize = 7;
	}
	
	int baseSize = font.pointSize();
	
	bool pixel = false;
	if(baseSize == -1){
		baseSize = font.pixelSize();
		pixel = true;
	}

	float factor = baseSize;
	int i;
	int scale_level = logicalSize - 3;

	if(scale_level > 0) {
		i = 0;
		while (i < scale_level) {
			factor *= 1.2;
			++i;
		}
	} else if(scale_level < 0) {
		i = scale_level;
		while (i < 0) {
			factor /= 1.2;
			++i;
		}
	}
	
	if(pixel) font.setPixelSize((int) roundf(factor));
	else font.setPointSizeFloat(factor);
	
}

QalculateRPNStackListView::QalculateRPNStackListView(TQWidget *parent, const char *name) : TDEListView(parent, name) {}
QalculateRPNStackListView::~QalculateRPNStackListView() {}

void QalculateRPNStackListView::keyPressEvent(TQKeyEvent *e) {
	switch(e->key()) {
		case Key_Prior: {}
		case Key_Next: {}
		case Key_Home: {}
		case Key_End: {}
		case Key_Up: {}
		case Key_Down: {
			TDEListView::keyPressEvent(e);
			break;
		}
		default: {
			if(e->key() == TDEGlobalSettings::contextMenuKey()) TDEListView::keyPressEvent(e);
			else e->ignore();
		}
	}
}

#include "kqalculate.moc"
