From 368711c76ce24bedde165318b8d1fcce69ba7957 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 22 Jan 2007 11:12:01 +0000 Subject: [PATCH] initial import git-svn-id: svn://ttmath.org/publicrep/ttcalc/trunk@2 e52654a7-88a9-db11-a3e9-0013d4bc506e --- CHANGELOG | 2 + COPYRIGHT | 28 ++ TODO | 17 + res/abacus_01.bmp | Bin 0 -> 145976 bytes res/icon01.ico | Bin 0 -> 1078 bytes src/Makefile | 43 ++ src/calculation.cpp | 56 +++ src/compileconfig.h | 38 ++ src/functions.cpp | 277 +++++++++++ src/iniparser.cpp | 397 ++++++++++++++++ src/iniparser.h | 133 ++++++ src/languages.cpp | 355 ++++++++++++++ src/languages.h | 139 ++++++ src/mainwindow.cpp | 754 +++++++++++++++++++++++++++++ src/messages.h | 60 +++ src/parsermanager.cpp | 149 ++++++ src/parsermanager.h | 143 ++++++ src/programresources.cpp | 626 +++++++++++++++++++++++++ src/programresources.h | 292 ++++++++++++ src/resource.h | 139 ++++++ src/resource.rc | 188 ++++++++ src/stopcalculating.h | 122 +++++ src/tabs.cpp | 991 +++++++++++++++++++++++++++++++++++++++ src/tabs.h | 66 +++ src/threadcontroller.h | 215 +++++++++ src/variables.cpp | 270 +++++++++++ src/winmain.cpp | 113 +++++ src/winmain.h | 34 ++ 28 files changed, 5647 insertions(+) create mode 100644 CHANGELOG create mode 100644 COPYRIGHT create mode 100644 TODO create mode 100644 res/abacus_01.bmp create mode 100644 res/icon01.ico create mode 100644 src/Makefile create mode 100644 src/calculation.cpp create mode 100644 src/compileconfig.h create mode 100644 src/functions.cpp create mode 100644 src/iniparser.cpp create mode 100644 src/iniparser.h create mode 100644 src/languages.cpp create mode 100644 src/languages.h create mode 100644 src/mainwindow.cpp create mode 100644 src/messages.h create mode 100644 src/parsermanager.cpp create mode 100644 src/parsermanager.h create mode 100644 src/programresources.cpp create mode 100644 src/programresources.h create mode 100644 src/resource.h create mode 100644 src/resource.rc create mode 100644 src/stopcalculating.h create mode 100644 src/tabs.cpp create mode 100644 src/tabs.h create mode 100644 src/threadcontroller.h create mode 100644 src/variables.cpp create mode 100644 src/winmain.cpp create mode 100644 src/winmain.h diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..139597f --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,2 @@ + + diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..a99db80 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,28 @@ +Copyright (c) 2006-2007, Tomasz Sowa +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name Tomasz Sowa nor the names of contributors to this + project may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. diff --git a/TODO b/TODO new file mode 100644 index 0000000..027e908 --- /dev/null +++ b/TODO @@ -0,0 +1,17 @@ +TODO TTCalc +=========== + +* increase the input edit +* when the program should be run as the maximalized window, the window is only + resizing horizontly +* doesn't set 'always on top' if it was in the configuration file +* add the button 'error' which shows us where is incorrect character (in input edit) +* add the test when program is being starded which checks if the coordinates of the + main window actually pointing + at the valid area (for example when someone take his configuration file into a + new computer) +* add some physical constants +* make the help +* the focus (from tab key) doesn't go from tabs into their controls +* when compiling under Cygwin the program has a problem with line-ends in + the configuration file (/r/n) diff --git a/res/abacus_01.bmp b/res/abacus_01.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b750c4d616b298c8fbf2bb1fad82391ee6862119 GIT binary patch literal 145976 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 z zJ8C4npiC$x4?_|j?XE^r*aQ>?L2VarQC9VZM*&=MMIFL3LS=350;fY0fiXCa8&n{M z5iQ~tQR&;Z^E`i44iZ~uP-*2BG_JuaUr-V#@Z20SJm?XONsE4Xl>HebKo}<;aa6u@ z*+@+X0lzE=r{u`xko<^v*bzG9 zI9w=kxfN#BEuM;70^3m>ASAOCZRiz%uCw4Tv8tL>O4vshXOtXiAtR8PvSN+{6pxlW z*oIAsO%g^$RQO}iU5ci|Fk&RKY&1_3MkovUzV%h#CQpO&RGPe663uDl_VUp*rUgJb zg+@l$KVkg!8pjl@R2QO+I!9cc-BNA2C0i93IU^r*E>O^d2+=YTHYu(UQt3^c&;E!a z9))6l;VXv}sKO090x3W^BN@PgAUqO=cm{n7C=%*`4xuI+p@NxWEa)8Q{H~!2a+Xo6 z;8Xx{-psk21UZx)ojcs!N&4a^TMaiG(NQQ~v0{Z=8by&KqzodkkeMASdt^*!XTmGU z$vA&i(g-fcqP z(#X9i`hW>Zl>qIagj}gdwUbKJn~F?*9%@`&$_Ej|n>ZlY#fJkAJdlAo z$*Qpx(xN4bT@SjOb?Ov(#8O)b>53vj)zL#vVXjDY?URrKtUN1LTUi0m8I21>JOJ61 zD5RGF*55&n%0D~l;KW5eXAyS8pVs0 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

tYcAJza>};Ublupb9ewgfiD#q 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

<&HNx4OUn~64?S%ne$~5#$F^mT?-5P*_ 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 literal 0 HcmV?d00001 diff --git a/res/icon01.ico b/res/icon01.ico new file mode 100644 index 0000000000000000000000000000000000000000..7735d5648be13fe54d701efb7fd8fb81e4c2a4e8 GIT binary patch literal 1078 zcmbVKy-veG4F1xh{0(V3vV|g{J_G}g5(xe#1<#NKDNm7lm|`$MAIOC`|}*7YxTT_M?w(nK|yBT9lgIf6h#oYFwt zRKZ&$Ia*?>;v$)&Wqnk^yG7FGn>j#j>i#m%B)_!8dPCreX_JOHyi+NRD>hFp=$ zNql$=xgwX7*zseRbKu7==Mn!t*L*!c!p7wr{$CT0e7w5)JU=b8zN+WP=|bzP`uoJ` zwvhTT@E;1vH(=~EA2O|s^|*Y*@>XH2kR8qR5XSl_Y)bYi^6uh{l^P#6&VaQB(Kj&d zIBKR3&8+Rt_p35rUl+ZLM$W5}lXC#}v}a{n2o z*2 + +/*! + the function for the second thread +*/ +//DWORD WINAPI CalculationsProcedure(LPVOID lpParameter) +unsigned __stdcall CalculationsProcedure(void *) +{ +/* + using namespace ttmath; + + Parser > parser; + + parser.Parse("6"); + std::string buf; + + parser.stack[0].value.ToString(buf); + MessageBox(0, buf.c_str(), "", 0); +*/ + + + ParserManager parser_manager; + + parser_manager.Init(); + + // the main loop of calculations + while( GetPrgRes()->GetThreadController()->WaitForCalculatingAndBlockForStop() ) + { + // for the first we must copy all variables which we're using + // (at this moment all calling from the main thread are stopped) + parser_manager.MakeCopyOfVariables(); + + // then we can set 'thread_controller' as being ready for 'stop' signal + GetPrgRes()->GetThreadController()->ReadyForStop(); + // (now the main thread can call various methods for changing state) + + // and finally we're cleaning the output window and parsing the input string + SetDlgItemText(GetPrgRes()->GetMainWindow(),IDC_OUTPUT_EDIT,""); + parser_manager.Parse(); + + // if there was a stop signal we continue the main loop without printing any values + if( GetPrgRes()->GetThreadController()->WasStopSignal() ) + continue; + + // at the end we're printing the result + parser_manager.PrintResult(); + } + +_endthreadex(0); +return 0; +} + + diff --git a/src/compileconfig.h b/src/compileconfig.h new file mode 100644 index 0000000..9786adf --- /dev/null +++ b/src/compileconfig.h @@ -0,0 +1,38 @@ +#ifndef headerfilecompileconfig +#define headerfilecompileconfig + + +/*! + this macro disables visual c warnings about deprecated unsafe standard functions + like fopen etc. +*/ +#define _CRT_SECURE_NO_DEPRECATE + + + +/*! + the number of build + (autoincrement by a compile script) +*/ +#define TTCALC_BUILD 1 + + +/*! + the version of the application +*/ +#define TTCALC_MAJOR_VER 0 +#define TTCALC_MINOR_VER 7 +#define TTCALC_REVISION_VER 0 + + +/*! + this disables a Visual C++ warning about converting int to bool + "warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)" +*/ +#ifdef _MSC_VER +#pragma warning (disable : 4800) +#endif + +#define _WIN32_IE 0x0501 + +#endif diff --git a/src/functions.cpp b/src/functions.cpp new file mode 100644 index 0000000..e27da89 --- /dev/null +++ b/src/functions.cpp @@ -0,0 +1,277 @@ +#include "compileconfig.h" +#include "tabs.h" + + +namespace TabWindowFunctions +{ +namespace Functions +{ +std::string caption,name,value; +int parameters; +bool adding; + + +BOOL CALLBACK DialogProcFunction(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +static const int temporary_buffer_size = 200; +char * pchar; +char short_buffer[20]; +int i; + + switch(message) + { + case WM_INITDIALOG: + SetWindowText(hWnd, caption.c_str()); + + SetDlgItemText(hWnd, IDC_STATIC_FUNCTION_NAME, GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_1)); + SetDlgItemText(hWnd, IDC_STATIC_FUNCTION_PARAM, GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_2)); + SetDlgItemText(hWnd, IDC_STATIC_FUNCTION_VALUE, GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_3)); + + SetDlgItemText(hWnd, IDOK, GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_ok)); + SetDlgItemText(hWnd, IDCANCEL,GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_cancel)); + + SetDlgItemText(hWnd,IDC_EDIT_FUNCTION_NAME, name.c_str()); + SetDlgItemText(hWnd,IDC_EDIT_FUNCTION_VALUE, value.c_str()); + + for(i=0 ; i<10 ; ++i) + { + sprintf(short_buffer,"%u", i); + SendDlgItemMessage(hWnd,IDC_COMBO_FUNCTION_PARAM,CB_ADDSTRING,0,(LPARAM)short_buffer); + } + + if( parameters < 0 ) + parameters = 0; + else + if( parameters > 9 ) + parameters = 9; + + SendDlgItemMessage(hWnd,IDC_COMBO_FUNCTION_PARAM,CB_SETCURSEL,parameters,0); + + if( adding ) + { + SetFocus(GetDlgItem(hWnd,IDC_EDIT_FUNCTION_NAME)); + } + else + { + EnableWindow(GetDlgItem(hWnd,IDC_EDIT_FUNCTION_NAME), false); + SetFocus(GetDlgItem(hWnd,IDC_EDIT_FUNCTION_VALUE)); + } + + return false; + + case WM_COMMAND: + if( LOWORD(wParam) == IDOK ) + { + pchar = new char[temporary_buffer_size]; + + GetDlgItemText(hWnd, IDC_EDIT_FUNCTION_NAME, pchar, temporary_buffer_size); + name = Variables::ChangeToSmallLetters( Variables::StripWhiteCharacters(pchar) ); + + GetDlgItemText(hWnd, IDC_EDIT_FUNCTION_VALUE, pchar, temporary_buffer_size); + value = Variables::ChangeToSmallLetters( Variables::StripWhiteCharacters(pchar) ); + + parameters = (int)SendDlgItemMessage(hWnd,IDC_COMBO_FUNCTION_PARAM,CB_GETCURSEL,0,0); + + delete [] pchar; + + EndDialog(hWnd,1); + } + else + if( LOWORD(wParam) == IDCANCEL ) + { + EndDialog(hWnd,0); + return true; + } + + break; + } + +return false; +} + + +void AddNewItemToFunctionList(HWND list, const std::string & name, const std::string & value, int parameters) +{ +LVITEM item; +char buffer[20]; + + item.mask = LVIF_TEXT; + item.pszText = const_cast( name.c_str() ); + item.iSubItem = 0; + + int id = ListView_InsertItem(list, &item); + + sprintf(buffer,"%u", parameters); + ListView_SetItemText(list,id,1, buffer); + + ListView_SetItemText(list,id,2,const_cast( value.c_str() )); +} + + + + + +void SetNewFunctionValueIntoList(HWND list, int id) +{ +ttmath::ErrorCode code; +char buffer[20]; + + GetPrgRes()->GetThreadController()->StopCalculating(); + code = GetPrgRes()->GetFunctions()->Edit(name, value, parameters); + GetPrgRes()->GetThreadController()->StartCalculating(); + + if( code == ttmath::err_unknown_object ) + { + // there is probably an internal error + // because we should have had this function + + MessageBox( list, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_edit_function_unknown_function), + GetPrgRes()->GetLanguages()->GuiMessage(Languages::message_box_caption), + MB_ICONERROR); + + return; + } + + sprintf(buffer,"%u",parameters); + ListView_SetItemText(list,id,1,buffer); + + ListView_SetItemText(list,id,2,const_cast( value.c_str() )); +} + + +BOOL WmTabCommand_AddFunction(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + caption = GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_add_function_caption); + name = ""; + value = ""; + adding = true; + parameters = 1; + + if( DialogBox(GetPrgRes()->GetInstance(), MAKEINTRESOURCE(IDD_DIALOG_ADD_FUNCTION), hWnd, DialogProcFunction) ) + { + HWND list = GetDlgItem(hWnd, IDC_FUNCTIONS_LIST); + ttmath::ErrorCode code; + + GetPrgRes()->GetThreadController()->StopCalculating(); + code = GetPrgRes()->GetFunctions()->Add(name, value, parameters); + GetPrgRes()->GetThreadController()->StartCalculating(); + + if( code == ttmath::err_object_exists ) + { + MessageBox( hWnd, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_add_function_function_exists), + GetPrgRes()->GetLanguages()->GuiMessage(Languages::message_box_caption), + MB_ICONERROR); + + return true; + } + + AddNewItemToFunctionList(list, name, value, parameters); + } + +return true; +} + + + +/*! + (we're also using this method directly without using the main loop of messages) + (we don't define the 'lParam' parameter there) +*/ +BOOL WmTabCommand_EditFunction(HWND hWnd, UINT message, WPARAM wParam, LPARAM) +{ +HWND list = GetDlgItem(hWnd, IDC_FUNCTIONS_LIST); + + if( ListView_GetSelectedCount(list) != 1 ) + // there must be only one item selected + return true; + + int id = ListView_GetSelectionMark(list); + + const int buffer_size = 300; + char * buffer = new char[buffer_size]; + + caption = GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_edit_function_caption); + + ListView_GetItemText(list,id,0,buffer, buffer_size); + name = buffer; + + ListView_GetItemText(list,id,2,buffer, buffer_size); + value = buffer; + + ListView_GetItemText(list,id,1,buffer, buffer_size); + parameters = atoi(buffer); + + delete [] buffer; + + adding = false; + + if( DialogBox(GetPrgRes()->GetInstance(), MAKEINTRESOURCE(IDD_DIALOG_ADD_FUNCTION), hWnd, DialogProcFunction) ) + { + SetNewFunctionValueIntoList(list, id); + } + +return true; +} + + +BOOL WmTabCommand_DeleteFunction(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +HWND list = GetDlgItem(hWnd, IDC_FUNCTIONS_LIST); +int items = ListView_GetSelectedCount(list); + + if( items == 0 ) + // there must be at least one item selected + return true; + + if( items > 1 ) + { + // we're showing a message to confirm deleting + if( MessageBox( hWnd, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_delete_function_confirm), + GetPrgRes()->GetLanguages()->GuiMessage(Languages::message_box_caption), + MB_ICONWARNING | MB_YESNO) == IDNO ) + return true; + } + + int id; + const int buffer_size = 300; + char * buffer = new char[buffer_size]; + bool all_deleted = true; + + GetPrgRes()->GetThreadController()->StopCalculating(); + + for( id = ListView_GetItemCount(list)-1 ; id!=-1 ; --id ) + { + if( ListView_GetItemState(list, id, LVIS_SELECTED) == LVIS_SELECTED ) + { + ListView_GetItemText(list,id,0,buffer,buffer_size); + if( GetPrgRes()->GetFunctions()->Delete(buffer) == ttmath::err_unknown_object ) + all_deleted = false; + else + ListView_DeleteItem(list, id); + } + } + + GetPrgRes()->GetThreadController()->StartCalculating(); + + delete [] buffer; + + if( !all_deleted ) + // there are some items which we've not deleted + // probably an internal error + MessageBox( hWnd, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_function_not_all_deleted), + GetPrgRes()->GetLanguages()->GuiMessage(Languages::message_box_caption), + MB_ICONERROR); + +return true; +} + + + + + +} // namespace +} // namespace diff --git a/src/iniparser.cpp b/src/iniparser.cpp new file mode 100644 index 0000000..5de19e6 --- /dev/null +++ b/src/iniparser.cpp @@ -0,0 +1,397 @@ +#include "compileconfig.h" + +#include "iniparser.h" + + +IniParser::IniParser() +{ + strip_white_characters_from_value = true; + convert_value_to_small_letters = true; +} + + +void IniParser::Associate(const char * pattern, std::string * result) +{ + table.insert( std::make_pair(std::string(pattern), result) ); +} + + +void IniParser::Associate(const std::string & pattern, std::string * result) +{ + table.insert( std::make_pair(pattern, result) ); +} + +void IniParser::Associate(const char * pattern, std::map * result) +{ + table_whole_section.insert( std::make_pair(std::string(pattern), result) ); +} + +void IniParser::Associate(const std::string & pattern, std::map * result) +{ + table_whole_section.insert( std::make_pair(pattern, result) ); +} + +void IniParser::Clear() +{ + table.clear(); + table_whole_section.clear(); +} + + +IniParser::Error IniParser::ReadFromFile(const char * path) +{ + file.open(path); + + if(!file) + return err_cant_open_file; + + Error err = Read(); + +return err; +} + + +int IniParser::GetBadLine() +{ + return line; +} + + + +IniParser::Error IniParser::Read() +{ +std::string section, pattern, value; +Error err; + + line = 1; + + do + { + err = ReadSection(section); + if( err != err_ok ) + break; + + err = ReadExpression(pattern, value); + + while( err == err_ok ) + { + if( strip_white_characters_from_value ) + StripWhiteCharacters(value); + + CheckAndSet( section, pattern, value ); + + err = ReadExpression(pattern, value); + } + + } + while( err == err_is_section ); + + + if( err == err_file_end ) + err = err_ok; + +return err; +} + + + +IniParser::Error IniParser::ReadSection(std::string & section) +{ + section.erase(); + + int c = SkipCommentaryAndEmptyLines(); + if( c == EOF ) + return err_file_end; + + if( c != '[' ) + { + // this line is not for a section (empty section?) + ReturnCharacter(c); + return err_ok; + } + + while( IsSectionCharacter( (c = ReadCharacter()) ) ) + section += LowerCase(c); + + if( c != ']' ) + { + ReturnCharacter(c); + return err_incorrect_character; + } + +return err_ok; +} + + + +int IniParser::SkipCommentaryAndEmptyLines() +{ +int c; + + do + { + SkipWhiteCharacters(); + c = ReadCharacter(); + + if( c == '#' ) + SkipLine(); + else + if( c == 10 ) + c='#'; + } + while( c == '#' ); + +return c; +} + + +/* +IniParser::Error IniParser::CheckEndOfLine() +{ + SkipWhiteCharacters(); + int c = ReadCharacter(); + + if( c == EOF ) + return err_file_end; + + if( c != 10 ) + { + ReturnCharacter(c); + return err_incorrect_character; + } + +return err_ok; +} +*/ + + + +IniParser::Error IniParser::ReadExpression(std::string & pattern, std::string & value) +{ + pattern.erase(); + value.erase(); + + int c = SkipCommentaryAndEmptyLines(); + if( c == EOF ) + return err_file_end; + + if( c == '[' ) + { + ReturnCharacter(c); + return err_is_section; + } + + while( IsPatternCharacter(c) ) + { + pattern += LowerCase(c); + c = ReadCharacter(); + } + + if( IsWhiteCharacter(c) ) + { + SkipWhiteCharacters(); + c = ReadCharacter(); + } + + if( c != '=' ) + { + ReturnCharacter(c); + return err_incorrect_character; + } + + SkipWhiteCharacters(); + + while( IsValueCharacter( (c = ReadCharacter()) ) ) + if( convert_value_to_small_letters ) + value += LowerCase(c); + else + value += c; + + ReturnCharacter(c); + +//return CheckEndOfLine(); +return err_ok; +} + + + +void IniParser::CheckAndSet(const std::string & section, const std::string & pattern, const std::string & value) +{ + TableWholeSection::iterator iw = table_whole_section.find( section ); + + if( iw != table_whole_section.end() ) + { + (*iw->second).insert( std::make_pair( pattern, value ) ); + return; + } + + + Table::iterator i = table.find( section + '|' + pattern ); + + if( i == table.end() ) + return; + + *i->second = value; +} + + + +bool IniParser::IsWhiteCharacter(int c) +{ + // 13 is in 'dos and windows' systems at the end of a text file (13 and 10 exactly) + if( c==' ' || c=='\t' || c==13 ) + return true; + +return false; +} + + + +void IniParser::SkipWhiteCharacters() +{ +int c; + + while( IsWhiteCharacter( (c=ReadCharacter()) ) ); + + ReturnCharacter(c); +} + + +int IniParser::ReadCharacter() +{ + int c = file.get(); + + if( !file ) + c = EOF; + else + if( c == 10 ) + ++line; + +return c; +} + + + +void IniParser::ReturnCharacter(int c) +{ + file.unget(); + + if( c == 10 ) + --line; +} + + +bool IniParser::IsSectionCharacter(int c) +{ + if( (c>='a' && c<='z') || + (c>='A' && c<='Z') || + (c>='0' && c<='9') || + c=='_' || c=='.' ) + + return true; + +return false; +} + + +bool IniParser::IsPatternCharacter(int c) +{ + return IsSectionCharacter(c); +} + + + +bool IniParser::IsValueCharacter(int c) +{ + if( c!=10 && c!=EOF ) + return true; + +return false; +} + + + +void IniParser::SkipLine() +{ + while( ReadCharacter() != 10 ); +} + + +int IniParser::LowerCase(int c) +{ + if( c>='A' && c<='Z') + return c - 'A' + 'a'; + +return c; +} + + + +/*! + this function sets '*start' and '*end' to point to the middle part of the string + without any whitespaces at the end and at the beginning + + '*start' will be the first correct character + '*end' will be after the last correct character +*/ +void IniParser::CheckWhiteCharacters(const char * string, const char ** start, const char ** end) +{ +const char * p; + + // we're setting 'p' at the end of the string (at '\0' character) + for( p = string ; *p ; ++p ); + + if( p == string ) + { + // an empty string + *start = *end = string; + return; + } + + // we're looking for a last character which is different than a white character + for( --p ; p != string && (*p==' ' || *p=='\t') ; --p ); + + // 'end' will be after the last character + *end = p+1; + + // we're looking for a first character which is different than a white character + for( p = string ; *p==' ' || *p=='\t' ; ++p ); + + *start = p; +} + + + + +void IniParser::StripWhiteCharacters(std::string & string) +{ +const char *s, * start, * end; + + s = string.c_str(); + CheckWhiteCharacters(s, &start, &end); + + + std::string::size_type istart, iend; + + istart = start - s; + iend = end - s; + + string.erase(iend, string.length() - iend); + string.erase(0, istart); +} + + + + + + + + + + + + + + + + diff --git a/src/iniparser.h b/src/iniparser.h new file mode 100644 index 0000000..6491aec --- /dev/null +++ b/src/iniparser.h @@ -0,0 +1,133 @@ +#ifndef headerfileiniparser +#define headerfileiniparser + +/*! + \file iniparser.h + \brief A Parser witch we use for parsing 'ini' files +*/ + +#include +#include +#include + + +/*! + \brief it implements the parser for reading 'ini' files + + how it works? + first you have to create an object of this class + IniParser ini_parser; + then you must associate a pattern and its value which'll be set after parsing + ini_parser.Associate( "sec|pattern", &value ); + where 'value' is std::string type + + when the parser meet in the file following sequences: + + ---- file.ini ------- + # some commentary + [sec] + pattern = some_values with space itd + --------------------- + + then the value 'some_values with space etc.' will be set into the 'value' variable, + you can use '#' as first character in a line which means the line is only a commentary, + a pattern and its value have to be in one line. + + + you can also read the whole section, for example: + [test] + item1 = 10 + item2 = 20 + item3 = 30 + etc. + by using ... +*/ +class IniParser +{ +public: + + typedef std::map Section; + + enum Error + { + err_ok = 0, + err_file_end, + err_is_section, + + err_cant_open_file, + err_incorrect_character + }; + + IniParser(); + + /*! + these methods associate pattern and its value + (look at a description of this class) + */ + void Associate(const char * pattern, std::string * result); + void Associate(const std::string & pattern, std::string * result); + + /*! + these methods associate pattern to the whole its section + */ + void Associate(const char * pattern, std::map * result); + void Associate(const std::string & pattern, std::map * result); + + /*! + this method clears patterns and their values + */ + void Clear(); + + + /*! + when the parser could not read correctly a ini file + this method returns a number of a bad line + */ + int GetBadLine(); + + + /*! + this method attempts to read a file + + if the reading was good it returns 'err_ok' + else it returns either 'err_cant_open_file' or 'err_incorrect_character' + + */ + Error ReadFromFile(const char * path); + + +private: + + typedef std::map Table; + typedef std::map TableWholeSection; + + Table table; + TableWholeSection table_whole_section; + std::ifstream file; + int line; + bool strip_white_characters_from_value; + bool convert_value_to_small_letters; + + Error Read(); + Error ReadSection(std::string & section); + int SkipCommentaryAndEmptyLines(); + //Error CheckEndOfLine(); + Error ReadExpression(std::string & pattern, std::string & value); + void CheckAndSet(const std::string & section, const std::string & pattern, const std::string & value); + bool IsWhiteCharacter(int c); + void SkipWhiteCharacters(); + int ReadCharacter(); + void ReturnCharacter(int c); + bool IsSectionCharacter(int c); + bool IsPatternCharacter(int c); + bool IsValueCharacter(int c); + void SkipLine(); + int LowerCase(int c); + +public: + static void CheckWhiteCharacters(const char * string, const char ** start, const char ** end); + static void StripWhiteCharacters(std::string & string); +}; + + +#endif diff --git a/src/languages.cpp b/src/languages.cpp new file mode 100644 index 0000000..f8cc493 --- /dev/null +++ b/src/languages.cpp @@ -0,0 +1,355 @@ +#include "compileconfig.h" + +#include "languages.h" + + + + + + +const char * Languages::ErrorMessage(Country country, ttmath::ErrorCode code) +{ +const char * unk_err = "unknown error"; + + if( error_messages_tab.empty() ) + InitErrorMessagesTab(); + + unsigned int cid = static_cast( country ); + if( cid >= error_messages_tab.size() ) + return unk_err; + + std::map::const_iterator i; + + i = error_messages_tab[cid].find( code ); + if( i == error_messages_tab[cid].end() ) + return unk_err; + +return i->second.c_str(); +} + + +const char * Languages::ErrorMessage(ttmath::ErrorCode code) +{ + return ErrorMessage(current_country, code); +} + + + +void Languages::InsertErrorPair(ttmath::ErrorCode code, const char * message) +{ + if( error_messages_tab.empty() ) + return; + + error_messages_tab.back().insert( std::make_pair(code, message) ); +} + + +void Languages::InitErrorMessagesTab() +{ + error_messages_tab.push_back( std::map() ); + + InsertErrorPair(ttmath::err_ok,"ok"); + InsertErrorPair(ttmath::err_nothing_has_read,""); + InsertErrorPair(ttmath::err_unknown_character,"Unknown character"); + InsertErrorPair(ttmath::err_unexpected_final_bracket,"An unexpected final bracket"); + InsertErrorPair(ttmath::err_stack_not_clear,"An unknown character has left"); + InsertErrorPair(ttmath::err_unknown_variable,"An unknown variable"); + InsertErrorPair(ttmath::err_division_by_zero,"Division by zero"); + InsertErrorPair(ttmath::err_interrupt,"?"); + InsertErrorPair(ttmath::err_overflow,"Overflow"); + InsertErrorPair(ttmath::err_unknown_function,"An unknown function"); + InsertErrorPair(ttmath::err_unexpected_semicolon_operator,"An unexpected semicolon operator"); + InsertErrorPair(ttmath::err_improper_amount_of_arguments,"Improper amount of arguments"); + InsertErrorPair(ttmath::err_improper_argument,"Improper argument"); + InsertErrorPair(ttmath::err_unexpected_end,"Unexpected end"); + InsertErrorPair(ttmath::err_internal_error,"An internal error"); + + InsertErrorPair(ttmath::err_incorrect_name,"Incorrect name of a variable or function"); + InsertErrorPair(ttmath::err_incorrect_value,"Incorrect value of a variable or function"); + InsertErrorPair(ttmath::err_variable_exists,"This variable already exists"); + InsertErrorPair(ttmath::err_variable_loop,"There's a recurrence between variables"); + InsertErrorPair(ttmath::err_functions_loop,"There's a recurrence between functions"); + InsertErrorPair(ttmath::err_must_be_only_one_value,"Variables or functions must return only one value"); + + InsertErrorPair(ttmath::err_this_cant_be_used,"?"); + +// pl + + error_messages_tab.push_back( std::map() ); + + InsertErrorPair(ttmath::err_ok,"ok"); + InsertErrorPair(ttmath::err_nothing_has_read,""); + InsertErrorPair(ttmath::err_unknown_character,"Nieznany znak"); + InsertErrorPair(ttmath::err_unexpected_final_bracket,"Nieoczekiwany nawias zamykaj¹cy"); + InsertErrorPair(ttmath::err_stack_not_clear,"Pozosta³ nieznany znak"); + InsertErrorPair(ttmath::err_unknown_variable,"Nieznana zmienna"); + InsertErrorPair(ttmath::err_division_by_zero,"Dzielenie przez zero"); + InsertErrorPair(ttmath::err_interrupt,"?"); + InsertErrorPair(ttmath::err_overflow,"Przekroczony zakres"); + InsertErrorPair(ttmath::err_unknown_function,"Nieznana funkcja"); + InsertErrorPair(ttmath::err_unexpected_semicolon_operator,"Nieoczekiwany operator 'œrednik'"); + InsertErrorPair(ttmath::err_improper_amount_of_arguments,"Niew³aœciwa liczba argumentów"); + InsertErrorPair(ttmath::err_improper_argument,"Niew³aœciwy argument"); + InsertErrorPair(ttmath::err_unexpected_end,"Nieoczekiwany koniec"); + InsertErrorPair(ttmath::err_internal_error,"B³¹d wewnêtrzny programu!"); + + InsertErrorPair(ttmath::err_incorrect_name,"Nieprawid³owa nazwa zmiennej lub funkcji"); + InsertErrorPair(ttmath::err_incorrect_value,"Nieprawid³owa wartoœæ zmiennej lub funkcji"); + InsertErrorPair(ttmath::err_variable_exists,"Ta zmienna juz istnieje"); + InsertErrorPair(ttmath::err_variable_loop,"Pomiêdzy zmiennymi zachodzi wywo³anie rekurencyjne"); + InsertErrorPair(ttmath::err_functions_loop,"Pomiêdzy funkcjami zachodzi wywo³anie rekurencyjne"); + InsertErrorPair(ttmath::err_must_be_only_one_value,"Zmienne albo funkcje mog¹ posiadaæ (zwracaæ) tylko jedn¹ wartoœæ"); + + InsertErrorPair(ttmath::err_this_cant_be_used,"?"); + + + +} + + + +// for gui messages + + + + +const char * Languages::GuiMessage(Country country, GuiMsg code) +{ +const char * unk_msg = "unknown"; + + if( gui_messages_tab.empty() ) + InitGuiMessagesTab(); + + unsigned int cid = static_cast( country ); + if( cid >= gui_messages_tab.size() ) + return unk_msg; + + std::map::const_iterator i; + + i = gui_messages_tab[cid].find( code ); + if( i == gui_messages_tab[cid].end() ) + return unk_msg; + +return i->second.c_str(); +} + +const char * Languages::GuiMessage(GuiMsg code) +{ + return GuiMessage(current_country, code); +} +void Languages::InsertGuiPair(GuiMsg code, const char * message) +{ + if( gui_messages_tab.empty() ) + return; + + gui_messages_tab.back().insert( std::make_pair(code, message) ); +} + + +void Languages::InitGuiMessagesTab() +{ + // en + gui_messages_tab.push_back( std::map() ); + + InsertGuiPair(button_ok,"Ok"); + InsertGuiPair(button_cancel,"Cancel"); + InsertGuiPair(message_box_caption,"TTCalc"); + + InsertGuiPair(dialog_box_add_variable_caption,"Add a new variable"); + InsertGuiPair(dialog_box_edit_variable_caption,"Edit a variable"); + InsertGuiPair(dialog_box_add_variable_incorrect_name,"Incorrect name of variable"); + InsertGuiPair(dialog_box_add_variable_incorrect_value,"Incorrect value of variable"); + InsertGuiPair(dialog_box_add_variable_variable_exists,"This variable already exists"); + InsertGuiPair(dialog_box_edit_variable_unknown_variable,"There isn't this variable in my table. There's probably an internal error!"); + InsertGuiPair(dialog_box_delete_variable_confirm,"Are you sure that you want to delete those variables?"); + InsertGuiPair(dialog_box_variable_not_all_deleted,"There are some variables which I was not able to delete. Probably an internal error!"); + InsertGuiPair(dialog_box_add_function_caption,"Add a new function"); + InsertGuiPair(dialog_box_edit_function_caption,"Edit a function"); + InsertGuiPair(dialog_box_add_function_function_exists,"This function already exists"); + InsertGuiPair(dialog_box_edit_function_unknown_function,"There isn't this function in my table. There's probably an internal error!"); + InsertGuiPair(dialog_box_delete_function_confirm,"Are you sure that you want to delete those functions?"); + InsertGuiPair(dialog_box_function_not_all_deleted,"There are some functions which I was not able to delete. Probably an internal error!"); + + InsertGuiPair(list_variables_header_1,"Name"); + InsertGuiPair(list_variables_header_2,"Value"); + InsertGuiPair(list_functions_header_1,"Name"); + InsertGuiPair(list_functions_header_2,"Param."); + InsertGuiPair(list_functions_header_3,"Value"); + + InsertGuiPair(button_add,"Add"); + InsertGuiPair(button_edit,"Edit"); + InsertGuiPair(button_delete,"Delete"); + InsertGuiPair(button_clear,"C"); + InsertGuiPair(tab_standard,"Standard"); + InsertGuiPair(tab_variables,"Variables"); + InsertGuiPair(tab_functions,"Functions"); + InsertGuiPair(tab_precision,"Precision"); + InsertGuiPair(tab_display,"Display"); + + InsertGuiPair(radio_precision_1,"Small - 96 bits for mantissa, 32 bits for exponent"); + InsertGuiPair(radio_precision_2,"Medium - 192 bits for mantissa, 64 bits for exponent"); + InsertGuiPair(radio_precision_3,"Big - 288 bits for mantissa, 96 bits for exponent"); + + InsertGuiPair(precision_1_info,"(+/-)6.9 e+646457021, 26 valid digits (decimal)"); + InsertGuiPair(precision_2_info,"(+/-)4.3 e+2776511644261678623, 56 valid digits"); + InsertGuiPair(precision_3_info,"(+/-)2.5 e+11925026709067095507636213441, 85 valid digits"); + + InsertGuiPair(overflow_during_printing,"Overflow during printing"); + + InsertGuiPair(combo_rounding_none,"None"); + InsertGuiPair(combo_rounding_cut_last_digits,"Cut off last non-valid digits"); + InsertGuiPair(combo_rounding_integer,"Round to the nearest integer"); + InsertGuiPair(combo_rounding_to_number,"to"); + InsertGuiPair(combo_rounding_after_comma,"digit(s) after comma"); + InsertGuiPair(display_input, "Input"); + InsertGuiPair(display_output, "Output"); + InsertGuiPair(display_rounding, "Rounding"); + InsertGuiPair(display_always_scientific,"Always"); + InsertGuiPair(display_not_always_scientific,"When the exp is greater than:"); + InsertGuiPair(display_digit, "digits"); + InsertGuiPair(display_group_scientific, "Print the result as the scientific value"); + + InsertGuiPair(menu_view, "&View"); + InsertGuiPair(menu_edit, "&Edit"); + InsertGuiPair(menu_help, "&Help"); + InsertGuiPair(menu_language, "&Language"); + InsertGuiPair(menu_view_new_window, "&New window"); + InsertGuiPair(menu_view_normal_view, "No&rmal view"); + InsertGuiPair(menu_view_compact_view, "C&ompact view"); + InsertGuiPair(menu_view_always_on_top, "&Always on top"); + InsertGuiPair(menu_view_lang_english, "&English"); + InsertGuiPair(menu_view_lang_polish, "&Polish"); + InsertGuiPair(menu_view_close_program, "&Close"); + InsertGuiPair(menu_view_edit_undo, "&Undo"); + InsertGuiPair(menu_view_edit_paste, "&Paste"); + InsertGuiPair(menu_view_edit_copy_result,"&Copy the result"); + InsertGuiPair(menu_view_help_about, "&About"); + InsertGuiPair(cant_init_calculations, "I could not initialize the module of calculations"); + InsertGuiPair(message_box_error_caption,"TTCalc"); + InsertGuiPair(cant_create_thread, "I could not create the second thread for calculating"); + InsertGuiPair(cant_create_main_window, "I could not create the main window of the application"); + InsertGuiPair(cant_init_common_controls,"I could not initialize the common controls (InitCommonControlsEx)"); + InsertGuiPair(about_text, + "Mathematical calculator TTCalc %d.%d.%d\r\n" + "Author: Tomasz Sowa\r\n" + "Contact: t.sowa@slimaczek.pl\r\n" + "Licence: (New) BSD licence\r\n" + "Project page: \r\n" + "Mathemathical library: TTMath %d.%d.%d\r\n" + "Programming language: C++\r\n" + "Compiler: %s\r\n" + "\r\n" + "This program uses the TTMath mathematical library" + " which can be found at http://sourceforge.net/projects/ttmath\r\n" + "\r\n" + "If you have any questions, advices or interesting ideas about" + " this program or if you want to join to this project as" + " the developer or programmer just contact with me." + ); + InsertGuiPair(about_box_title, "About"); + + + + // pl + gui_messages_tab.push_back( std::map() ); + + InsertGuiPair(button_ok,"Ok"); + InsertGuiPair(button_cancel,"Anuluj"); + InsertGuiPair(message_box_caption,"TTCalc"); + + InsertGuiPair(dialog_box_add_variable_caption,"Dodaj now¹ zmienn¹"); + InsertGuiPair(dialog_box_edit_variable_caption,"Zmieñ wartoœæ zmiennej"); + InsertGuiPair(dialog_box_add_variable_incorrect_name,"Nie prawid³owa nazwa zmiennej"); + InsertGuiPair(dialog_box_add_variable_incorrect_value,"Nie prawid³owa wartoœæ zmiennej"); + InsertGuiPair(dialog_box_add_variable_variable_exists,"Podana zmienna ju¿ istnieje"); + InsertGuiPair(dialog_box_edit_variable_unknown_variable,"Podanej zmiennej nie ma w tablicy. Prawdopodobnie b³¹d wewnêtrzny programu."); + InsertGuiPair(dialog_box_delete_variable_confirm,"Czy napewno usun¹æ zaznaczone zmienne?"); + InsertGuiPair(dialog_box_variable_not_all_deleted,"Zosta³o kilka zmiennych których nie mo¿na by³o skasowaæ. Prawdopodobnie b³¹d wewnêtrzny programu."); + InsertGuiPair(dialog_box_add_function_caption,"Dodaj now¹ funkcjê"); + InsertGuiPair(dialog_box_edit_function_caption,"Zmieñ wartoœæ funkcji"); + InsertGuiPair(dialog_box_add_function_function_exists,"Podana funkcja ju¿ istnieje"); + InsertGuiPair(dialog_box_edit_function_unknown_function,"Podanej funkcji nie ma w tablicy. Prawdopodobnie b³¹d wewnêtrzny programu."); + InsertGuiPair(dialog_box_delete_function_confirm,"Czy napewno usun¹æ zaznaczone funkcje?"); + InsertGuiPair(dialog_box_function_not_all_deleted,"Zosta³o kilka funkcji których nie mo¿na by³o skasowaæ. Prawdopodobnie b³¹d wewnêtrzny programu."); + + InsertGuiPair(list_variables_header_1,"Nazwa"); + InsertGuiPair(list_variables_header_2,"Wartoœæ"); + InsertGuiPair(list_functions_header_1,"Nazwa"); + InsertGuiPair(list_functions_header_2,"Parametry"); + InsertGuiPair(list_functions_header_3,"Wartoœæ"); + + InsertGuiPair(button_add,"Dodaj"); + InsertGuiPair(button_edit,"Edytuj"); + InsertGuiPair(button_delete,"Usuñ"); + InsertGuiPair(button_clear,"C"); + InsertGuiPair(tab_standard,"Standard"); + InsertGuiPair(tab_variables,"Zmienne"); + InsertGuiPair(tab_functions,"Funkcje"); + InsertGuiPair(tab_precision,"Precyzja"); + InsertGuiPair(tab_display,"Wyœwietlanie"); + + InsertGuiPair(radio_precision_1,"Ma³a - 96 bitowa mantysa, 32 bitowy wyk³adnik"); + InsertGuiPair(radio_precision_2,"Œrednia - 192 bitowa mantysa, 64 bitowy wyk³adnik"); + InsertGuiPair(radio_precision_3,"Du¿a - 288 bitowa mantysa, 96 bitowy wyk³adnik"); + + InsertGuiPair(precision_1_info,"(+/-)6.9 e+646457021, 26 cyfr znacz¹cych (w rozwiniêciu dziesiêtnym)"); + InsertGuiPair(precision_2_info,"(+/-)4.3 e+2776511644261678623, 56 cyfr znacz¹cych"); + InsertGuiPair(precision_3_info,"(+/-)2.5 e+11925026709067095507636213441, 85 cyfr znacz¹cych"); + + InsertGuiPair(overflow_during_printing,"Przepe³nienie podczas wypisywania"); + + InsertGuiPair(combo_rounding_none,"bez zaokr¹glania"); + InsertGuiPair(combo_rounding_cut_last_digits,"skasowaæ nie znacz¹ce zera"); + InsertGuiPair(combo_rounding_integer,"do najbli¿szej ca³kowitej"); + InsertGuiPair(combo_rounding_to_number,"do"); + InsertGuiPair(combo_rounding_after_comma,"cyfr(y) po przecinku"); + + InsertGuiPair(display_input,"Wejœcie"); + InsertGuiPair(display_output,"Wyjœcie"); + InsertGuiPair(display_rounding,"Zaokr¹glenie"); + InsertGuiPair(display_always_scientific,"Zawsze"); + InsertGuiPair(display_not_always_scientific,"Jeœli eksponent wiêkszy ni¿"); + InsertGuiPair(display_digit, "cyfr"); + InsertGuiPair(display_group_scientific, "Wyœwietl wynik w postaci naukowej"); + + InsertGuiPair(menu_view, "&Widok"); + InsertGuiPair(menu_edit, "&Edycja"); + InsertGuiPair(menu_help, "&Pomoc"); + InsertGuiPair(menu_language, "&Jêzyk"); + InsertGuiPair(menu_view_new_window, "&Nowe okno"); + InsertGuiPair(menu_view_normal_view, "Widok no&rmalny"); + InsertGuiPair(menu_view_compact_view, "Widok &kompaktowy"); + InsertGuiPair(menu_view_always_on_top, "Zawsze na &wierzchu"); + InsertGuiPair(menu_view_lang_english, "Jêzyk &angielski"); + InsertGuiPair(menu_view_lang_polish, "Jêzyk &polski"); + InsertGuiPair(menu_view_close_program, "&Zamknij"); + InsertGuiPair(menu_view_edit_undo, "&Cofnij"); + InsertGuiPair(menu_view_edit_paste, "&Wklej"); + InsertGuiPair(menu_view_edit_copy_result,"&Kopiuj wynik"); + InsertGuiPair(menu_view_help_about, "&O programie"); + InsertGuiPair(cant_init_calculations, "Nie uda³o siê zainicjalizowaæ modu³u obs³ugi obliczeñ"); + InsertGuiPair(message_box_error_caption,"TTCalc"); + InsertGuiPair(cant_create_thread, "Nie uda³o siê utworzyæ drugiego w¹tku do obliczeñ"); + InsertGuiPair(cant_create_main_window, "Nie uda³o siê utworzyæ g³ównego okna aplikacji"); + InsertGuiPair(cant_init_common_controls,"Nie uda³o siê zainicjalizowaæ obs³ugi Common Controls (InitCommonControlsEx)"); + InsertGuiPair(about_text, + "Kalkulator matematyczny TTCalc %d.%d.%d\r\n" + "Autor: Tomasz Sowa\r\n" + "Kontakt: t.sowa@slimaczek.pl\r\n" + "Licencja: (New) BSD\r\n" + "Strona projektu: \r\n" + "Biblioteka matematyczna: TTMath %d.%d.%d\r\n" + "Jêzyk programowania: C++\r\n" + "Kompilator: %s\r\n" + "\r\n" + "Ten program u¿ywa biblioteki matematycznej TTMath" + " która jest dostêpna na http://sourceforge.net/projects/ttmath\r\n" + "\r\n" + "Je¿eli masz jakieœ pytania, rady, ciekawe pomys³y dotycz¹ce" + " tego programu lub chcia³byœ do³¹czyæ jako projektant/programista" + " poprostu skontaktuj siê ze mn¹." + ); + InsertGuiPair(about_box_title, "O programie"); + +} + diff --git a/src/languages.h b/src/languages.h new file mode 100644 index 0000000..06ac591 --- /dev/null +++ b/src/languages.h @@ -0,0 +1,139 @@ +#ifndef headerfilelanguages +#define headerfilelanguages + +#include +#include +#include + +#include + + +class Languages +{ +public: + + enum GuiMsg + { + button_ok, + button_cancel, + message_box_caption, + dialog_box_add_variable_caption, + dialog_box_edit_variable_caption, + dialog_box_add_variable_incorrect_name, + dialog_box_add_variable_incorrect_value, + dialog_box_add_variable_variable_exists, + dialog_box_edit_variable_unknown_variable, + dialog_box_delete_variable_confirm, + dialog_box_variable_not_all_deleted, + dialog_box_add_function_caption, + dialog_box_edit_function_caption, + dialog_box_add_function_function_exists, + dialog_box_edit_function_unknown_function, + dialog_box_delete_function_confirm, + dialog_box_function_not_all_deleted, + list_variables_header_1, + list_variables_header_2, + list_functions_header_1, + list_functions_header_2, + list_functions_header_3, + button_add, + button_edit, + button_delete, + button_clear, + tab_standard, + tab_variables, + tab_functions, + tab_precision, + tab_display, + radio_precision_1, + radio_precision_2, + radio_precision_3, + precision_1_info, + precision_2_info, + precision_3_info, + overflow_during_printing, + combo_rounding_none, + combo_rounding_cut_last_digits, + combo_rounding_integer, + combo_rounding_to_number, + combo_rounding_after_comma, + display_input, + display_output, + display_rounding, + display_always_scientific, + display_not_always_scientific, + menu_view, + menu_edit, + menu_help, + menu_language, + menu_view_new_window, + menu_view_normal_view, + menu_view_compact_view, + menu_view_always_on_top, + menu_view_lang_english, + menu_view_lang_polish, + menu_view_close_program, + menu_view_edit_undo, + menu_view_edit_paste, + menu_view_edit_copy_result, + menu_view_help_about, + cant_init_calculations, + message_box_error_caption, + cant_create_thread, + cant_create_main_window, + cant_init_common_controls, + about_text, + about_box_title, + display_digit, + display_group_scientific + }; + + // the first item must be with zero index + // and next items must be about one greater (0,1,2,3..) + // (after conversion to 'int' we pass it into the std::vector) + enum Country + { + en = 0, pl + }; + +private: + + Country current_country; + + std::vector > error_messages_tab; + std::vector > gui_messages_tab; + + void InsertErrorPair(ttmath::ErrorCode code, const char * message); + void InitErrorMessagesTab(); + + void InsertGuiPair(GuiMsg code, const char * message); + void InitGuiMessagesTab(); + +public: + + + + Languages() + { + current_country = en; + } + + void SetCurrentLanguage(Country c) + { + current_country = c; + } + + Country GetCurrentLanguage() + { + return current_country; + } + + const char * ErrorMessage(Country country, ttmath::ErrorCode code); + const char * ErrorMessage(ttmath::ErrorCode code); + const char * GuiMessage(Country country, GuiMsg code); + const char * GuiMessage(GuiMsg code); + +}; + + +#endif diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp new file mode 100644 index 0000000..3ddbdbd --- /dev/null +++ b/src/mainwindow.cpp @@ -0,0 +1,754 @@ +#include "compileconfig.h" +#include "winmain.h" + + + + +namespace MainWindowFunctions +{ + + + +void SetActiveTab(unsigned int i) +{ +static int last_shown_dialog = -1; + + if( last_shown_dialog != -1 ) + ShowWindow( GetPrgRes()->GetTabWindow(last_shown_dialog), SW_HIDE); + + if( i >= GetPrgRes()->HowManyTabWindows() ) + { + last_shown_dialog = -1; + return; + } + + ShowWindow(GetPrgRes()->GetTabWindow(i), SW_SHOWNORMAL); + last_shown_dialog = i; +} + + +inline void SetMenuLanguageItem(HMENU menu, DWORD menu_id, Languages::GuiMsg msg) +{ +Languages * pLang = GetPrgRes()->GetLanguages(); + + ModifyMenu(menu, menu_id, MF_BYCOMMAND|MF_STRING, menu_id, pLang->GuiMessage(msg) ); +} + + +void SetMenuLanguage(HWND hWnd) +{ +HMENU menu = GetMenu(hWnd); + + if( !menu ) + return; + + MENUITEMINFO mi; + mi.cbSize = sizeof(mi); + mi.fMask = MIIM_TYPE; + mi.fType = MFT_STRING; + + // on popup menus we're using indexes because they don't want to work correctly + // with the identifiers + mi.dwTypeData = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::menu_view) ); + SetMenuItemInfo(menu, IDM_VIEW_INDEX, true, &mi); + + mi.dwTypeData = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::menu_edit) ); + SetMenuItemInfo(menu, IDM_EDIT_INDEX, true, &mi); + + mi.dwTypeData = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::menu_help) ); + SetMenuItemInfo(menu, IDM_HELP_INDEX, true, &mi); + + mi.dwTypeData = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::menu_language) ); + SetMenuItemInfo(GetSubMenu(menu,IDM_VIEW_INDEX), IDM_LANGUAGE_INDEX, true, &mi); + + SetMenuLanguageItem(menu, IDM_NEW_WINDOW, Languages::menu_view_new_window); + SetMenuLanguageItem(menu, IDM_NORMAL_VIEW, Languages::menu_view_normal_view); + SetMenuLanguageItem(menu, IDM_COMPACT_VIEW, Languages::menu_view_compact_view); + SetMenuLanguageItem(menu, IDM_ALWAYS_ON_TOP, Languages::menu_view_always_on_top); + SetMenuLanguageItem(menu, IDM_LANGUAGE_ENGLISH, Languages::menu_view_lang_english); + SetMenuLanguageItem(menu, IDM_LANGUAGE_POLISH, Languages::menu_view_lang_polish); + SetMenuLanguageItem(menu, IDM_CLOSE_PROGRAM, Languages::menu_view_close_program); + SetMenuLanguageItem(menu, IDM_EDIT_UNDO, Languages::menu_view_edit_undo); + SetMenuLanguageItem(menu, IDM_EDIT_PASTE, Languages::menu_view_edit_paste); + SetMenuLanguageItem(menu, IDM_EDIT_COPY_RESULT, Languages::menu_view_edit_copy_result); + SetMenuLanguageItem(menu, IDM_HELP_ABOUT, Languages::menu_view_help_about); + + DrawMenuBar(hWnd); +} + + +void WmInitDialogCalculateMainWindowSize(HWND hTab) +{ +RECT r; + + GetWindowRect(hTab, &r); + + + int cy_add = 2 * GetSystemMetrics(SM_CYDLGFRAME) + + GetSystemMetrics(SM_CYCAPTION) + + GetSystemMetrics(SM_CYMENU); + + int cx_add = 2 * GetSystemMetrics(SM_CXDLGFRAME) + + r.right - r.left; + + GetPrgRes()->SetYSizeNormal ( 244 + cy_add ); + GetPrgRes()->SetYSizeCompact( 59 + cy_add ); + GetPrgRes()->SetXSizeMin ( 4 + cx_add ); +} + + + +HWND WmInitDialogCreateControlsOnTab(HWND hTab, LPCSTR dialog, DLGPROC dialog_proc) +{ +HRSRC tab1res = FindResource(GetPrgRes()->GetInstance(), dialog, RT_DIALOG); +HGLOBAL tab1global = LoadResource(GetPrgRes()->GetInstance(), tab1res); +DLGTEMPLATE * tab1template = (DLGTEMPLATE*)LockResource(tab1global); + + if( tab1template ) + { + HWND hDialog = CreateDialogIndirect(GetPrgRes()->GetInstance(), tab1template, hTab , dialog_proc); + + // for windres + + SetWindowLong(hDialog, GWL_STYLE, GetWindowLong(hDialog, GWL_STYLE) & ~(WS_CAPTION | WS_OVERLAPPED) ); + + // + + int frame_cx = GetSystemMetrics(SM_CXEDGE); + int frame_cy = GetSystemMetrics(SM_CYEDGE); + int caption_cy = GetSystemMetrics(SM_CYCAPTION)+10; // the caption plus some white space + + RECT r; + GetWindowRect(hTab, &r); + + SetWindowPos(hDialog, HWND_TOP, frame_cx, frame_cy + caption_cy, + r.right-r.left- 2*frame_cx, + r.bottom-r.top- 2*frame_cy - caption_cy, 0); + + return hDialog; + } + +return 0; +} + + +void WmInitDialogCreateTab(HWND hTab, int tab_index, int tab_resource, DLGPROC tab_proc) +{ + HWND dialogh = WmInitDialogCreateControlsOnTab( + hTab, + MAKEINTRESOURCE(tab_resource), + tab_proc ); + + GetPrgRes()->SetTabWindow( tab_index, dialogh ); +} + + +void WmInitDialogCreateAndInitTabs(HWND hTab) +{ +using namespace TabWindowFunctions; + +TCITEM tab_item; + + // the name of a tab we'll set when we call the 'SetLanguage()' function + tab_item.mask = 0; + + tab_standard = 0; + tab_variables = 1; + tab_functions = 2; + tab_precision = 3; + tab_display = 4; + + // this insertion must be in the ascending order + // (the second parameter of 'TabCtrl_InsertItem') + TabCtrl_InsertItem(hTab, tab_standard, &tab_item); + TabCtrl_InsertItem(hTab, tab_variables, &tab_item); + TabCtrl_InsertItem(hTab, tab_functions, &tab_item); + TabCtrl_InsertItem(hTab, tab_precision, &tab_item); + TabCtrl_InsertItem(hTab, tab_display, &tab_item); + + WmInitDialogCreateTab(hTab, tab_standard, IDD_DIALOG_STANDARD, TabWindowProc); + WmInitDialogCreateTab(hTab, tab_variables, IDD_DIALOG_VARIABLES, TabWindowProc); + WmInitDialogCreateTab(hTab, tab_functions, IDD_DIALOG_FUNCTIONS, TabWindowProc); + WmInitDialogCreateTab(hTab, tab_precision, IDD_DIALOG_PRECISION, TabWindowProc); + WmInitDialogCreateTab(hTab, tab_display, IDD_DIALOG_DISPLAY, TabWindowProc); + + SendMessage(GetPrgRes()->GetTabWindow(tab_variables), WM_INIT_TAB_VARIABLES, 0,0); + SendMessage(GetPrgRes()->GetTabWindow(tab_functions), WM_INIT_TAB_FUNCTIONS, 0,0); + SendMessage(GetPrgRes()->GetTabWindow(tab_precision), WM_INIT_TAB_PRECISION, 0,0); + SendMessage(GetPrgRes()->GetTabWindow(tab_display), WM_INIT_TAB_DISPLAY, 0,0); + + TabWindowFunctions::SetLanguage(hTab); + + TabCtrl_SetCurSel(hTab, tab_standard); + SetActiveTab( tab_standard ); +} + + + + +BOOL WmInitDialog(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +HWND hTab = GetDlgItem(hWnd,IDC_TAB); + + GetPrgRes()->SetMainWindow(hWnd); + + WmInitDialogCalculateMainWindowSize(hTab); + WmInitDialogCreateAndInitTabs(hTab); + + HICON program_icon = LoadIcon(GetPrgRes()->GetInstance(),MAKEINTRESOURCE(IDI_ICON1)); + if( program_icon ) + SendMessage(hWnd,WM_SETICON,ICON_BIG,(LPARAM)program_icon); + + GetPrgRes()->SetAlwaysOnTop( GetPrgRes()->GetAlwaysOnTop() ); + GetPrgRes()->SetMaximized ( GetPrgRes()->GetMaximized() ); + GetPrgRes()->SetView ( GetPrgRes()->GetView() ); + + ShowWindow(hWnd,SW_SHOW); + + SendDlgItemMessage(hWnd,IDC_INPUT_EDIT,EM_SETLIMITTEXT,GetPrgRes()->GetBufferSize()-1,0); + SetMenuLanguage(hWnd); + +return true; +} + +/* + a function for WM_MOVE +*/ +BOOL WmMove(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +RECT r; + + GetWindowRect(hWnd,&r); + + GetPrgRes()->SetXPos( r.left ); + GetPrgRes()->SetYPos( r.top ); + +return 0; +} + + +/* + a function for WM_CLOSE +*/ +BOOL WmClose(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + GetPrgRes()->GetThreadController()->StopCalculatingAndExitThread(); + DestroyWindow(GetPrgRes()->GetMainWindow()); + PostQuitMessage(0); + +return 0; +} + + +/* + a function for WM_GETMINMAXINFO +*/ +BOOL WmGetMinMaxInfo(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +MINMAXINFO * lpmmi = (LPMINMAXINFO) lParam; + + lpmmi->ptMinTrackSize.x = GetPrgRes()->GetXSizeMin(); + + if( GetPrgRes()->GetView() == ProgramResources::view_normal ) + { + lpmmi->ptMinTrackSize.y = GetPrgRes()->GetYSizeNormal(); + //lpmmi->ptMaxTrackSize.y = cy_normalny; + } + else + {// kompaktowy + lpmmi->ptMinTrackSize.y = GetPrgRes()->GetYSizeCompact(); + lpmmi->ptMaxTrackSize.y = GetPrgRes()->GetYSizeCompact(); + } + +return 0; +} + + +/*! + a function for WM_SIZING + + when user drags the border of the main window this method checks if + the new boundary is near to the standard width and height, if it is + the dragging box is attracted to the standard size +*/ +BOOL WmSizing(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +RECT * pr = (RECT*) lParam; +int cx_min = GetPrgRes()->GetXSizeMin(); +const int margin = 20; + + if( GetPrgRes()->GetView() == ProgramResources::view_normal ) + { + int cy_min = GetPrgRes()->GetYSizeNormal(); + + if( (pr->bottom - pr->top) < cy_min + margin ) + { + if( (wParam == WMSZ_BOTTOM) || (wParam == WMSZ_BOTTOMRIGHT) || (wParam == WMSZ_BOTTOMLEFT) ) + pr->bottom = pr->top + cy_min; + else + if( (wParam == WMSZ_TOP) || (wParam == WMSZ_TOPRIGHT) || (wParam == WMSZ_TOPLEFT) ) + pr->top = pr->bottom - cy_min; + } + } + + if( (pr->right-pr->left) < cx_min + margin ) + { + if( (wParam == WMSZ_RIGHT) || (wParam == WMSZ_BOTTOMRIGHT) || (wParam == WMSZ_TOPRIGHT) ) + pr->right = pr->left + cx_min; + else + if( (wParam == WMSZ_LEFT) || (wParam == WMSZ_BOTTOMLEFT) || (wParam == WMSZ_TOPLEFT) ) + pr->left = pr->right - cx_min; + } + +return 1; +} + + +/* + a function for WM_SIZE +*/ +BOOL WmSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +int fwSizeType = int(wParam); +RECT r; +POINT p; + + if( fwSizeType == SIZE_MAXIMIZED ) + GetPrgRes()->SetMaximized(true); + else + if( fwSizeType == SIZE_RESTORED ) + GetPrgRes()->SetMaximized(false); + + int cx = LOWORD(lParam); + int cy = HIWORD(lParam); + + GetWindowRect(GetDlgItem(hWnd,IDC_INPUT_EDIT),&r); + p.x = r.left; + p.y = r.top; + ScreenToClient(hWnd,&p); + MoveWindow(GetDlgItem(hWnd,IDC_INPUT_EDIT),p.x, p.y, cx, r.bottom-r.top, true); + + GetWindowRect(GetDlgItem(hWnd,IDC_OUTPUT_EDIT),&r); + p.x = r.left; + p.y = r.top; + ScreenToClient(hWnd,&p); + MoveWindow(GetDlgItem(hWnd,IDC_OUTPUT_EDIT),p.x, p.y, cx, r.bottom-r.top, true); + + GetWindowRect(GetDlgItem(hWnd,IDC_TAB),&r); + p.x = r.left; + p.y = r.top; + ScreenToClient(hWnd,&p); + MoveWindow(GetDlgItem(hWnd,IDC_TAB),p.x, p.y, cx, cy-p.y, true); + + TabWindowFunctions::SetSizeOfVariablesList(); + TabWindowFunctions::SetSizeOfFunctionsList(); + + if( fwSizeType != SIZE_MINIMIZED ) + { + GetWindowRect(hWnd,&r); + GetPrgRes()->SetXSize( r.right - r.left ); + } + +return 0; +} + +void WmInitMenuPopUpView(HMENU menu) +{ + if( GetPrgRes()->GetAlwaysOnTop() ) + CheckMenuItem(menu,IDM_ALWAYS_ON_TOP,MF_BYCOMMAND|MF_CHECKED); + else + CheckMenuItem(menu,IDM_ALWAYS_ON_TOP,MF_BYCOMMAND|MF_UNCHECKED); + + + if( GetPrgRes()->GetView() == ProgramResources::view_normal ) + { + CheckMenuItem(menu,IDM_NORMAL_VIEW,MF_BYCOMMAND|MF_CHECKED); + CheckMenuItem(menu,IDM_COMPACT_VIEW,MF_BYCOMMAND|MF_UNCHECKED); + } + else + { + CheckMenuItem(menu,IDM_COMPACT_VIEW,MF_BYCOMMAND|MF_CHECKED); + CheckMenuItem(menu,IDM_NORMAL_VIEW,MF_BYCOMMAND|MF_UNCHECKED); + } + + if( GetPrgRes()->GetLanguages()->GetCurrentLanguage() == Languages::en ) + { + CheckMenuItem(menu, IDM_LANGUAGE_ENGLISH, MF_BYCOMMAND|MF_CHECKED); + CheckMenuItem(menu, IDM_LANGUAGE_POLISH, MF_BYCOMMAND|MF_UNCHECKED); + } + else + { + CheckMenuItem(menu, IDM_LANGUAGE_POLISH, MF_BYCOMMAND|MF_CHECKED); + CheckMenuItem(menu, IDM_LANGUAGE_ENGLISH, MF_BYCOMMAND|MF_UNCHECKED); + } +} + + +void WmInitMenuPopUpEdit(HWND hWnd, HMENU menu) +{ +char buffer[5]; + + bool can_undo = SendDlgItemMessage(hWnd, IDC_INPUT_EDIT, EM_CANUNDO, 0 ,0); + + if( can_undo ) + EnableMenuItem(menu,IDM_EDIT_UNDO,MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(menu,IDM_EDIT_UNDO,MF_BYCOMMAND | MF_GRAYED); + + + if( IsClipboardFormatAvailable(CF_TEXT) ) + EnableMenuItem(menu,IDM_EDIT_PASTE,MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(menu,IDM_EDIT_PASTE,MF_BYCOMMAND | MF_GRAYED); + + + GetDlgItemText(hWnd,IDC_OUTPUT_EDIT,buffer,sizeof(buffer)); + + if( buffer[0] == 0 ) + EnableMenuItem(menu,IDM_EDIT_COPY_RESULT,MF_BYCOMMAND | MF_GRAYED); + else + EnableMenuItem(menu,IDM_EDIT_COPY_RESULT,MF_BYCOMMAND | MF_ENABLED); +} + + +BOOL WmInitMenuPopUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if( LOWORD(lParam) == IDM_VIEW_INDEX ) + { + WmInitMenuPopUpView( (HMENU)wParam ); + + return true; + } + else + if( LOWORD(lParam) == IDM_EDIT_INDEX ) + { + WmInitMenuPopUpEdit( hWnd, (HMENU)wParam ); + + return true; + } + +return false; +} + + +/* + a function for WM_NOTIFY +*/ +BOOL WmNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +NMHDR * pnmh = (LPNMHDR) lParam; +HWND hTab = GetDlgItem(hWnd,IDC_TAB); + + if( pnmh->hwndFrom==hTab && pnmh->code==TCN_SELCHANGE ) + SetActiveTab( TabCtrl_GetCurSel(hTab) ); + +return true; +} + + +/* + a group of functions using when the WM_COMMAND message is sent +*/ + + +BOOL WmCommand_AlwaysOnTop(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + GetPrgRes()->SetAlwaysOnTop( !GetPrgRes()->GetAlwaysOnTop() ); + +return true; +} + + +BOOL WmCommand_NormalView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + GetPrgRes()->SetView(ProgramResources::view_normal); + +return true; +} + + +BOOL WmCommand_CompactView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + GetPrgRes()->SetView(ProgramResources::view_compact); + +return true; +} + + +BOOL WmCommand_HelpAbout(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + DialogBox(GetPrgRes()->GetInstance(),MAKEINTRESOURCE(IDD_ABOUT_DIALOG),hWnd,AboutProc); + +return true; +} + + +BOOL WmCommand_NewWindow(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +STARTUPINFO si; +PROCESS_INFORMATION pi; + + GetPrgRes()->SetXPos( GetPrgRes()->GetXPos()+10 ); + GetPrgRes()->SetYPos( GetPrgRes()->GetYPos()+10 ); + GetPrgRes()->SaveToFile(); + GetPrgRes()->SetXPos( GetPrgRes()->GetXPos()-10 ); + GetPrgRes()->SetYPos( GetPrgRes()->GetYPos()-10 ); + + char * buffer = new char[MAX_PATH+1]; + + GetModuleFileName(GetPrgRes()->GetInstance(),buffer, MAX_PATH); + + memset(&si,0,sizeof(si)); + si.cb = sizeof(si); + CreateProcess(buffer,"",0,0,false,NORMAL_PRIORITY_CLASS,0,0,&si,&pi); + + delete [] buffer; + +return true; +} + + + +BOOL WmCommand_CloseProgram(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + GetPrgRes()->GetThreadController()->StopCalculatingAndExitThread(); + DestroyWindow(GetPrgRes()->GetMainWindow()); + PostQuitMessage(0); + +return true; +} + + + +BOOL WmCommand_InputEditNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if( HIWORD(wParam) != EN_CHANGE ) + return false; + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetDlgItemText(hWnd,IDC_INPUT_EDIT, (char*)GetPrgRes()->GetBuffer(), GetPrgRes()->GetBufferSize()-1); + GetPrgRes()->GetThreadController()->StartCalculating(); + +return true; +} + + + +BOOL WmCommand_EditUndo(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + SendDlgItemMessage(hWnd, IDC_INPUT_EDIT, EM_UNDO, 0, 0); + +return true; +} + +BOOL WmCommand_EditPaste(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + SendDlgItemMessage(hWnd, IDC_INPUT_EDIT, WM_PASTE, 0, 0); + +return true; +} + + +BOOL WmCommand_EditCopyResult(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + SendDlgItemMessage(hWnd, IDC_OUTPUT_EDIT, EM_SETSEL, 0, LPARAM(-1)); + SendDlgItemMessage(hWnd, IDC_OUTPUT_EDIT, WM_COPY, 0, 0); + SendDlgItemMessage(hWnd, IDC_OUTPUT_EDIT, EM_SETSEL, WPARAM(-1), 0); + +return true; +} + + +/*! + a user has pressed 'ESC' key in the main window + we're cleaning the input edit +*/ +BOOL WmCommand_IDCANCEL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + SetDlgItemText(hWnd, IDC_INPUT_EDIT, ""); + +return true; +} + + + +BOOL WmCommand_LanguageEnglish(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->GetLanguages()->SetCurrentLanguage(Languages::en); + GetPrgRes()->GetThreadController()->StartCalculating(); + + SetMenuLanguage(hWnd); + TabWindowFunctions::SetLanguage( GetDlgItem(hWnd, IDC_TAB) ); + GetPrgRes()->GetThreadController()->StartCalculating(); + +return true; +} + + +BOOL WmCommand_LanguagePolish(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->GetLanguages()->SetCurrentLanguage(Languages::pl); + GetPrgRes()->GetThreadController()->StartCalculating(); + + SetMenuLanguage(hWnd); + TabWindowFunctions::SetLanguage( GetDlgItem(hWnd, IDC_TAB) ); + GetPrgRes()->GetThreadController()->StartCalculating(); + +return true; +} + + +void CreateCommandMessagesTable(Messages & cmessages) +{ + + + cmessages.Associate(IDM_ALWAYS_ON_TOP, WmCommand_AlwaysOnTop); + cmessages.Associate(IDM_NORMAL_VIEW, WmCommand_NormalView); + cmessages.Associate(IDM_COMPACT_VIEW, WmCommand_CompactView); + cmessages.Associate(IDM_HELP_ABOUT, WmCommand_HelpAbout); + cmessages.Associate(IDM_NEW_WINDOW, WmCommand_NewWindow); + cmessages.Associate(IDM_CLOSE_PROGRAM, WmCommand_CloseProgram); + + cmessages.Associate(IDC_INPUT_EDIT, WmCommand_InputEditNotify); + + cmessages.Associate(IDM_EDIT_UNDO, WmCommand_EditUndo); + cmessages.Associate(IDM_EDIT_PASTE, WmCommand_EditPaste); + cmessages.Associate(IDM_EDIT_COPY_RESULT, WmCommand_EditCopyResult); + + + cmessages.Associate(IDCANCEL, WmCommand_IDCANCEL); + + cmessages.Associate(IDM_LANGUAGE_ENGLISH, WmCommand_LanguageEnglish); + cmessages.Associate(IDM_LANGUAGE_POLISH, WmCommand_LanguagePolish); +} + + +BOOL WmCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +static Messages command_messages; + + if( command_messages.Empty() ) + // initiation + CreateCommandMessagesTable(command_messages); + + +return command_messages.Call(LOWORD(wParam), hWnd, message, wParam, lParam); +} + + +void CreateMainMessagesTable(Messages & messages) +{ + messages.Associate(WM_INITDIALOG, WmInitDialog); + messages.Associate(WM_MOVE, WmMove); + messages.Associate(WM_CLOSE, WmClose); + messages.Associate(WM_GETMINMAXINFO, WmGetMinMaxInfo); + messages.Associate(WM_SIZE, WmSize); + messages.Associate(WM_INITMENUPOPUP, WmInitMenuPopUp); + messages.Associate(WM_COMMAND, WmCommand); + messages.Associate(WM_NOTIFY, WmNotify); + messages.Associate(WM_SIZING, WmSizing); +} + +/*! + this method prepares a text which is printed on the about dialog box +*/ +void CreateAboutText(char * buffer) +{ +char compiler[30]; + + #ifdef __GNUC__ + + #ifdef __VERSION__ + sprintf(compiler,"GCC %s", __VERSION__); + #else + sprintf( + compiler, + "GCC %d.%d.%d", + __GNUC__, + __GNUC_MINOR__, + __GNUC_PATCHLEVEL__ + ); + #endif + + #elif _MSC_VER + + char msvc_ver[20]; + int i; + sprintf(msvc_ver, "%d", _MSC_VER); + /* + from msdn: + _MSC_VER reports the major and minor versions of the compiler. + For example, 1310 for Microsoft Visual C++ .NET 2003. 1310 represents + version 13 and a 1.0 point release. The Visual C++ 2005 compiler + version is 1400. + + If there is, for example, version 1400 we rather want to show it as 14.00, + so we put a simple dot on the third position + */ + for(i=0; msvc_ver[i] ; ++i); + for( ; i>=2 ; --i) + msvc_ver[i+1] = msvc_ver[i]; + + msvc_ver[2] = '.'; + + sprintf( + compiler, + "Microsoft Visual C++ %s", + msvc_ver + ); + + #else + + sprintf(compiler, "unknown"); + + #endif + + + sprintf( + buffer, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::about_text), + TTCALC_MAJOR_VER, TTCALC_MINOR_VER, TTCALC_REVISION_VER, + TTMATH_MAJOR_VER, TTMATH_MINOR_VER, TTMATH_REVISION_VER, + compiler); + +} + +/*! + it displays the about-window +*/ +BOOL CALLBACK AboutProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +char * about_buffer; + + switch(message) + { + case WM_INITDIALOG: + SetWindowText( + hWnd, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::about_box_title) ); + + about_buffer = new char[2000]; + CreateAboutText(about_buffer); + SetDlgItemText(hWnd, IDC_ABOUT_TEXT, about_buffer); + delete [] about_buffer; + + return true; + + + case WM_COMMAND: + if(LOWORD(wParam)==IDOK || LOWORD(wParam)==IDCANCEL) + { + EndDialog(hWnd,0); + return true; + } + + break; + } + +return false; +} + +} // namespace MainWindowFunctions + diff --git a/src/messages.h b/src/messages.h new file mode 100644 index 0000000..8a63f6b --- /dev/null +++ b/src/messages.h @@ -0,0 +1,60 @@ +#ifndef headerfilemessages +#define headerfilemessages + +#include +#include + + + + + + + + + + + +class Messages +{ +public: + typedef BOOL (*MessageFunction)(HWND, UINT, WPARAM, LPARAM); + typedef std::map MessageTable; + + + void Associate(UINT message, MessageFunction message_function) + { + message_table.insert( std::make_pair(message, message_function) ); + } + + + void Clear() + { + message_table.clear(); + } + + + BOOL Call(UINT key, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) + { + MessageTable::iterator i = message_table.find(key); + + if( i == message_table.end() ) + return false; + + return i->second(hWnd, message, wParam, lParam); + } + + + bool Empty() const + { + return message_table.empty(); + } + + +private: + + MessageTable message_table; + +}; + + +#endif diff --git a/src/parsermanager.cpp b/src/parsermanager.cpp new file mode 100644 index 0000000..dd0d43f --- /dev/null +++ b/src/parsermanager.cpp @@ -0,0 +1,149 @@ +#include "compileconfig.h" +#include "parsermanager.h" + + + + +ParserManager::ParserManager() : buffer_len(300) +{ + buffer = 0; + base_input = base_output = 10; + always_scientific = 0; + when_scientific = 15; + rounding = -2; +} + + +ParserManager::ParserManager(const ParserManager & p) : buffer_len(p.buffer_len) +{ + buffer = 0; + base_input = p.base_input; + base_output = p.base_output; + always_scientific = p.always_scientific; + when_scientific = p.when_scientific; + rounding = p.rounding; +} + + +ParserManager & ParserManager::operator=(const ParserManager & p) +{ + buffer = 0; + +return *this; +} + + +ParserManager::~ParserManager() +{ + delete [] buffer; +} + + +ttmath::ErrorCode ParserManager::Parse() +{ + try + { + switch( precision ) + { + case 0: + parser1.SetBase(base_input); + code = parser1.Parse(buffer); + break; + + case 1: + parser2.SetBase(base_input); + code = parser2.Parse(buffer); + break; + + default: + parser3.SetBase(base_input); + code = parser3.Parse(buffer); + break; + } + } + catch(...) + { + // we are in a thread, we shouldn't go up + code = ttmath::err_internal_error; + } + +return code; +} + + +void ParserManager::MakeCopyOfVariables() +{ +unsigned int i; + + char * pchar = (char*)GetPrgRes()->GetBuffer(); + for(i = 0 ; iGetVariables(); + functions = *GetPrgRes()->GetFunctions(); + + // + base_input = GetPrgRes()->GetBaseInput(); + base_output = GetPrgRes()->GetBaseOutput(); + + always_scientific = GetPrgRes()->GetDisplayAlwaysScientific(); + when_scientific = GetPrgRes()->GetDisplayWhenScientific(); + rounding = GetPrgRes()->GetDisplayRounding(); + precision = GetPrgRes()->GetPrecision(); + + country = GetPrgRes()->GetLanguages()->GetCurrentLanguage(); +} + + +void ParserManager::Init() +{ + buffer = new char[buffer_len]; + buffer[0] = 0; + + parser1.SetStopObject( GetPrgRes()->GetThreadController()->GetStopObject() ); + parser1.SetVariables( &variables ); + parser1.SetFunctions( &functions ); + + parser2.SetStopObject( GetPrgRes()->GetThreadController()->GetStopObject() ); + parser2.SetVariables( &variables ); + parser2.SetFunctions( &functions ); + + parser3.SetStopObject( GetPrgRes()->GetThreadController()->GetStopObject() ); + parser3.SetVariables( &variables ); + parser3.SetFunctions( &functions ); +} + + +void ParserManager::PrintResult() +{ + if( code == ttmath::err_ok ) + { + switch( precision ) + { + case 0: + return PrintResult(parser1); + + case 1: + return PrintResult(parser2); + + default: + return PrintResult(parser3); + } + } + else + { + // we can call GetPrgRes() here because we're reading + // static value like GetMainWindow() which are set only once + // at the beginning of the program and will never be changed later + // by the first thread + + SetDlgItemText( + GetPrgRes()->GetMainWindow(), + IDC_OUTPUT_EDIT, + GetPrgRes()->GetLanguages()->ErrorMessage(country, code) ); + } +} diff --git a/src/parsermanager.h b/src/parsermanager.h new file mode 100644 index 0000000..90bbf79 --- /dev/null +++ b/src/parsermanager.h @@ -0,0 +1,143 @@ +#ifndef headerfilecalculation +#define headerfilecalculation + +/*! + \file parsermanager.h + \brief object of type ParserManager we're using during calculating +*/ + +#include "resource.h" +#include +#include "programresources.h" + +#include + + +/*! + \brief object of type ParserManager we're using during calculating + + In our program we're using three kind of precisions. First is the smallest + , and the third is the biggest. Because precision is established during + compilation (templates) we need three different objects. ParserManager + helps us to maintain these objects. +*/ +class ParserManager +{ +public: + + ParserManager(); + ParserManager(const ParserManager & p); + ParserManager & operator=(const ParserManager & p); + ~ParserManager(); + + + /*! + the main method which call parserX.Parse(...) + */ + ttmath::ErrorCode Parse(); + + + /*! + we call this method directly after when we have left + WaitForCalculatingAndBlockForStop() method from the ThreadController + + only in this method we can read variables which can be changed + by the first thread + */ + void MakeCopyOfVariables(); + + + /*! + it prepares our three parsers to work, it should be called only once + */ + void Init(); + + + /*! + this method prints result + (a correct value if was or an error instead) + */ + void PrintResult(); + + +private: + + ttmath::Parser > parser1; + ttmath::Parser > parser2; + ttmath::Parser > parser3; + + ttmath::Objects variables, functions; + + const unsigned int buffer_len; + char * buffer; + + int base_input, base_output; + + bool always_scientific; + int when_scientific; + int rounding; + int precision; + Languages::Country country; + ttmath::ErrorCode code; + + + template + void PrintResult(ttmath::Parser & matparser) + { + std::string result, part; + unsigned int i = 0; + + + for(i=0 ; iGetLanguages()->GuiMessage(country, Languages::overflow_during_printing); + // will be working correctly on gcc with -O3 + + // this error doesn't appear always, it can be seen, for example, + // if we use Big<1,3> type and we give '2^32' for calculating + + // I didn't check this error on a new version of gcc + + part = GetPrgRes()->GetLanguages()->GuiMessage(country, Languages::overflow_during_printing); + } + + result += part; + + if( i < matparser.stack.size()-1 ) + result += " "; + } + + SetDlgItemText(GetPrgRes()->GetMainWindow(),IDC_OUTPUT_EDIT,result.c_str()); + } + + +}; + + + + +#endif diff --git a/src/programresources.cpp b/src/programresources.cpp new file mode 100644 index 0000000..4d3adc0 --- /dev/null +++ b/src/programresources.cpp @@ -0,0 +1,626 @@ +#include "compileconfig.h" +#include "programresources.h" + + + +namespace ProgramResourcesGlobal +{ + ProgramResources program_resource; +} + + +ProgramResources * GetPrgRes() +{ + return &ProgramResourcesGlobal::program_resource; +} + + + + + + +void ProgramResources::SetXPos(int x) +{ + x_pos = x; +} + + +void ProgramResources::SetYPos(int y) +{ + y_pos = y; +} + + +int ProgramResources::GetXPos() +{ + return x_pos; +} + + +int ProgramResources::GetYPos() +{ + return y_pos; +} + + +void ProgramResources::SetXSize(int x) +{ + x_size = x; +} + +void ProgramResources::SetYSize(int y) +{ + y_size = y; +} + +int ProgramResources::GetXSize() +{ + return x_size; +} + +int ProgramResources::GetYSize() +{ + return y_size; +} + +void ProgramResources::SetYSizeNormal(int y) +{ + y_size_normal = y; +} + +int ProgramResources::GetYSizeNormal() +{ + return y_size_normal; +} + +void ProgramResources::SetYSizeCompact(int y) +{ + y_size_compact = y; +} + +int ProgramResources::GetYSizeCompact() +{ + return y_size_compact; +} + +void ProgramResources::SetXSizeMin(int x) +{ + x_size_min = x; +} + +int ProgramResources::GetXSizeMin() +{ + return x_size_min; +} + + +void ProgramResources::SetView(ProgramResources::View v) +{ + view = v; + + if( v == view_normal) + MoveWindow(main_window, x_pos, y_pos, x_size, y_size_normal, true); + else + MoveWindow(main_window, x_pos, y_pos, y_size, y_size_compact, true); +} + + +ProgramResources::View ProgramResources::GetView() +{ + return view; +} + + +void ProgramResources::SetMaximized(bool max) +{ + maximized = max; + + if( maximized ) + ShowWindow(main_window, SW_SHOWMAXIMIZED); + else + ShowWindow(main_window, SW_SHOWNORMAL); +} + + +bool ProgramResources::GetMaximized() +{ + return maximized; +} + +void ProgramResources::SetAlwaysOnTop(bool always) +{ + always_on_top = always; + + if( always ) + SetWindowPos(main_window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + else + SetWindowPos(main_window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +} + +bool ProgramResources::GetAlwaysOnTop() +{ + return always_on_top; +} + + +void ProgramResources::SetDisplayRounding(int r) +{ + if(r<-2) + r = -2; + + if(r>99) + r = 99; + + display_rounding = r; +} + +int ProgramResources::GetDisplayRounding() +{ + return display_rounding; +} + +void ProgramResources::SetDisplayAlwaysScientific(bool a) +{ + display_always_scientific = a; +} + +bool ProgramResources::GetDisplayAlwaysScientific() +{ + return display_always_scientific; +} + +void ProgramResources::SetDisplayWhenScientific(int w) +{ + if(w<1) + w = 1; + + if( w > 99 ) + w = 99; + + display_when_scientific = w; +} + +int ProgramResources::GetDisplayWhenScientific() +{ + return display_when_scientific; +} + + + +void ProgramResources::SetBaseInput(int i) +{ + if(i<2) + i = 2; + + if(i>16) + i = 16; + +base_input = i; +} + + +int ProgramResources::GetBaseInput() +{ + return base_input; +} + + +void ProgramResources::SetBaseOutput(int i) +{ + if(i<2) + i = 2; + + if(i>16) + i = 16; + +base_output = i; +} + + +int ProgramResources::GetBaseOutput() +{ + return base_output; +} + + + +// + +ttmath::Objects * ProgramResources::GetVariables() +{ + return &variables; +} + +ttmath::Objects * ProgramResources::GetFunctions() +{ + return &functions; +} + +Languages * ProgramResources::GetLanguages() +{ + return &languages; +} + +void ProgramResources::SetInstance(HINSTANCE h) +{ + hInstance = h; +} + +HINSTANCE ProgramResources::GetInstance() +{ + return hInstance; +} + +void ProgramResources::SetMainWindow(HWND h) +{ + main_window = h; +} + +HWND ProgramResources::GetMainWindow() +{ + return main_window; +} + +void ProgramResources::SetTabWindow(unsigned int id, HWND h) +{ + if( id >= sizeof(tab_window) / sizeof(HWND) ) + return; + +tab_window[id] = h; +} + +HWND ProgramResources::GetTabWindow(unsigned int id) +{ + if( id >= sizeof(tab_window) / sizeof(HWND) ) + return 0; + +return tab_window[id]; +} + +unsigned int ProgramResources::HowManyTabWindows() +{ + return sizeof(tab_window) / sizeof(HWND); +} + +char * ProgramResources::GetBuffer() +{ + return buffer; +} + +unsigned int ProgramResources::GetBufferSize() +{ + return buffer_size; +} + +volatile ThreadController * ProgramResources::GetThreadController() +{ + return &thread_controller; +} + +void ProgramResources::SetPrecision(int p) +{ + if( p < 0 ) + p = 0; + + if( p > 2 ) + p = 2; + +precision = p; +} + +int ProgramResources::GetPrecision() +{ + return precision; +} + + + +ProgramResources::ProgramResources() +{ + buffer_size = 300; + buffer = new char[buffer_size]; + buffer[0] = 0; + + + always_on_top = false; + view = view_normal; + + maximized = false; + + precision = 0; + + hInstance = 0; + main_window = 0; + + base_input = 10; + base_output = 10; + + display_always_scientific = false; + display_when_scientific = 15; + display_rounding = -2; + + for(int i=HowManyTabWindows()-1 ; i!=-1 ; --i) + tab_window[i] = 0; + + x_pos = 0; + y_pos = 0; + x_size = 100; + y_size = 100; + + y_size_normal = 0; + y_size_compact = 0; + x_size_min = 0; +} + + +ProgramResources::~ProgramResources() +{ + delete [] buffer; +} + + + +bool ProgramResources::IsWhiteCharacter(int c) +{ + if( c==' ' || c=='\t' || c==13 || c=='\n' ) + return true; + +return false; +} + +const char * ProgramResources::SkipWhiteCharacters(const char * string) +{ + while( IsWhiteCharacter(*string) ) + ++string; + +return string; +} + +bool ProgramResources::IsDecDigit(int c) +{ + if( c>='0' && c<='9' ) + return true; + +return false; +} + +bool ProgramResources::SplitFunction(const std::string & input, const char * * name, int * param) +{ +const char * pchar = input.c_str(); +const int buffer_len = 20; +char buffer[buffer_len]; +int i; + + pchar = SkipWhiteCharacters(pchar); + + for(i=0 ; i 9) + *param = 9; + + + // + while( IsDecDigit(*pchar) ); + + pchar = SkipWhiteCharacters(pchar); + if( *pchar != '|' ) + return false; + + pchar = SkipWhiteCharacters(pchar+1); + + *name = pchar; + +return true; +} + + +bool ProgramResources::IsWindowsNt() +{ +OSVERSIONINFO os_info; + + os_info.dwOSVersionInfoSize = sizeof( os_info ); + + if( !GetVersionEx( &os_info ) ) + return false; + + if( os_info.dwPlatformId != VER_PLATFORM_WIN32_NT ) + // we've got Windows 3.1, Windows 95 or Windows 98 + return false; + +return true; +} + + +bool ProgramResources::ReadTextValueFromRegistry(HKEY main_key, const char * sub_key, const char * value, std::string & result) +{ +HKEY reg_key; + + if( RegOpenKeyEx( main_key, sub_key, 0, KEY_QUERY_VALUE, ®_key ) != ERROR_SUCCESS ) + return false; + + bool status = false; + DWORD result_type; + char result_buffer[300]; + DWORD buffer_size = sizeof(result_buffer) / sizeof(char); + + if( RegQueryValueEx( reg_key, value, 0, &result_type, reinterpret_cast(result_buffer), &buffer_size ) == ERROR_SUCCESS ) + { + if( result_type == REG_SZ ) + { + result = result_buffer; + status = true; + } + } + + RegCloseKey(reg_key); + +return status; +} + + + +void ProgramResources::SetNameOfConfigurationFile() +{ +static const char simple_file_name[] = "ttcalc.ini"; +static const char simple_directory_name[] = "ttcalc"; +std::string application_data; + + // if there'll be an error we assume that the current directory will be used + configuration_file = std::string(".\\") + simple_file_name; + + // for the first we must check which operating system we're using + if( !IsWindowsNt() ) + return; + + // we're trying to read the value "AppData" from registry + // which can be, for instance, as: + // "C:\Documents and Settings\user\data application" + if( ReadTextValueFromRegistry( + HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + "AppData", + application_data) ) + { + std::string application_directory = application_data + '\\' + simple_directory_name; + bool success = false; + + // we're testing whether we've got our directory or not + if( SetCurrentDirectory( application_directory.c_str() ) ) + success = true; + else + // now we must make our directory inside it + if( CreateDirectory(application_directory.c_str(), 0) ) + success = true; + + if( success ) + configuration_file = application_directory + '\\' + simple_file_name; + } +} + + + +IniParser::Error ProgramResources::ReadFromFile() +{ +IniParser iparser; +IniParser::Section temp_variables, temp_functions; +IniParser::Section::iterator ic; +std::string ini_value[12]; + + + iparser.Associate( "global|always.on.top", &ini_value[0] ); + iparser.Associate( "global|view", &ini_value[1] ); + iparser.Associate( "global|maximized", &ini_value[2] ); + iparser.Associate( "global|x", &ini_value[3] ); + iparser.Associate( "global|y", &ini_value[4] ); + iparser.Associate( "global|size.x", &ini_value[5] ); + iparser.Associate( "global|precision", &ini_value[6] ); + iparser.Associate( "global|disp.input", &ini_value[7] ); + iparser.Associate( "global|disp.output", &ini_value[8] ); + iparser.Associate( "global|disp.alw.scientific", &ini_value[9] ); + iparser.Associate( "global|disp.when.scientific", &ini_value[10] ); + iparser.Associate( "global|disp.rounding", &ini_value[11] ); + + iparser.Associate( "variables", &temp_variables ); + iparser.Associate( "functions", &temp_functions ); + + bad_line = -1; + IniParser::Error err = iparser.ReadFromFile( configuration_file.c_str() ); + + if( err == IniParser::err_cant_open_file ) + return err; + + // we're adding variables + variables.Clear(); + for( ic = temp_variables.begin() ; ic!=temp_variables.end() ; ++ic ) + variables.Add(ic->first, ic->second); + + // we're adding functions + functions.Clear(); + for( ic = temp_functions.begin() ; ic!=temp_functions.end() ; ++ic ) + { + const char * name; + int param; + + if( SplitFunction(ic->second, &name, ¶m) ) + functions.Add(ic->first, name, param); + } + + // we're setting various values + always_on_top = bool( atoi(ini_value[0].c_str()) ); + view = atoi(ini_value[1].c_str()) == 0 ? view_normal : view_compact; + maximized = bool( atoi(ini_value[2].c_str()) ); + x_pos = atoi( ini_value[3].c_str() ); + y_pos = atoi( ini_value[4].c_str() ); + x_size = atoi( ini_value[5].c_str() ); + + SetPrecision( atoi(ini_value[6].c_str()) ); + SetBaseInput( atoi(ini_value[7].c_str()) ); + SetBaseOutput( atoi(ini_value[8].c_str()) ); + + SetDisplayAlwaysScientific( bool(atoi(ini_value[9].c_str())) ); + SetDisplayWhenScientific( atoi(ini_value[10].c_str()) ); + SetDisplayRounding( atoi(ini_value[11].c_str()) ); + + if( err != IniParser::err_ok ) + bad_line = iparser.GetBadLine(); + +return err; +} + + + +void ProgramResources::SaveToFile() +{ +std::ofstream file( configuration_file.c_str() ); + + if( !file ) + return; + + file << "# the configuration file of the program ttcalc\n\n"; + file << "[GLOBAL]\n"; + + file << "always.on.top = " << (int)always_on_top << std::endl; + file << "view = " << (int)view << std::endl; + file << "maximized = " << (int)maximized << std::endl; + file << "x = " << x_pos << std::endl; + file << "y = " << y_pos << std::endl; + file << "size.x = " << x_size << std::endl; + file << "precision = " << precision << std::endl; + file << "disp.input = " << base_input << std::endl; + file << "disp.output = " << base_output << std::endl; + + file << "disp.alw.scientific = " << (int)display_always_scientific << std::endl; + file << "disp.when.scientific = " << display_when_scientific << std::endl; + file << "disp.rounding = " << display_rounding << std::endl; + + file << "\n\n[variables]\n"; + + ttmath::Objects::CIterator iv = variables.Begin(); + + for( ; iv != variables.End() ; ++iv ) + file << iv->first.c_str() << " = " << iv->second.value.c_str() << std::endl; + + file << "\n\n[functions]\n"; + + iv = functions.Begin(); + for( ; iv != functions.End() ; ++iv ) + file << iv->first.c_str() << " = " << iv->second.param << + " | " << iv->second.value.c_str() << std::endl; + +} + + +int ProgramResources::GetBadLine() +{ + return bad_line; +} + + + diff --git a/src/programresources.h b/src/programresources.h new file mode 100644 index 0000000..2f8d887 --- /dev/null +++ b/src/programresources.h @@ -0,0 +1,292 @@ +#ifndef headerfileprogramresources +#define headerfileprogramresources + +/*! + \file programresources.h + \brief various kinds of objects using by the application +*/ + +#include +#include "iniparser.h" +#include "languages.h" +#include "threadcontroller.h" + +#include +#include + + +/*! + you don't have to create an object of this class but instead of it you can + get the pointer to the object by using 'GetPrgRes()' + (there'll be only one object of this type) + + you must remember that some of these methods are used by the second thread as well + and when you want to change a state you must do it between calling + StopCalculating() and StartCalculating() in the main thread + for example if you want to change the precision of displaying you can do as follow: + (in the main thread) + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetPrecision( new_precision ); + GetPrgRes()->GetThreadController()->StartCalculating(); + + methods which are used by the second thread: + GetBuffer(), GetVariables(), GetFunctions(), GetBaseInput(), GetBaseOutput() + GetDisplayAlwaysScientific(), GetDisplayWhenScientific(), GetDisplayRounding() + GetCurrentLanguage(), GetPrecision() + + and if you're using methods which begin with Set..... you must call it + between StopCalculating() and StartCalculating() +*/ +class ProgramResources +{ +public: + + + /*! + types of the main window's view + view_normal - standard view with all controls on the dialog + view_compact - only the input and output edits are shown + */ + enum View + { + view_normal = 0, view_compact + }; + + + /*! + position of the left top corner of the main window and its size + */ + void SetXPos(int x); + void SetYPos(int y); + int GetXPos(); + int GetYPos(); + void SetXSize(int x); + void SetYSize(int y); + int GetXSize(); + int GetYSize(); + + + /*! + size of the main window when 'normal view' is selected + */ + void SetYSizeNormal(int y); + int GetYSizeNormal(); + + + /*! + size of the main window when 'compact view' is selected + */ + void SetYSizeCompact(int y); + int GetYSizeCompact(); + + + /*! + minimum horizontal size of the main window + */ + void SetXSizeMin(int x); + int GetXSizeMin(); + + + /*! + the kind of the view + */ + void SetView(View v); + View GetView(); + + + /*! + maximizing of the main window + */ + void SetMaximized(bool max); + bool GetMaximized(); + + + /*! + the main window is always on top or not + */ + void SetAlwaysOnTop(bool always); + bool GetAlwaysOnTop(); + + + /*! + rounding of the calculation's result + */ + void SetDisplayRounding(int r); + int GetDisplayRounding(); + + + /*! + displaying always scientific format + */ + void SetDisplayAlwaysScientific(bool a); + bool GetDisplayAlwaysScientific(); + + + /*! + when scientific format will be used + (when the exponent of the result will be greater than w) + */ + void SetDisplayWhenScientific(int w); + int GetDisplayWhenScientific(); + + + /*! + they sets the base of input and output values (2-16) + */ + void SetBaseInput(int i); + int GetBaseInput(); + void SetBaseOutput(int i); + int GetBaseOutput(); + + + /*! + the instance of the application + (the same as that one which was passed to the WinMain(...)) + */ + void SetInstance(HINSTANCE h); + HINSTANCE GetInstance(); + + + /*! + the main window of the application + */ + void SetMainWindow(HWND h); + HWND GetMainWindow(); + + + /*! + handles to the dialogs which are placed on the tab control + */ + void SetTabWindow(unsigned int id, HWND h); + HWND GetTabWindow(unsigned int id); + unsigned int HowManyTabWindows(); + + + /*! + the precision of our calculations (0-2) + 0 - small + 1 - medium + 2 - big + */ + void SetPrecision(int p); + int GetPrecision(); + + + /*! + the object which is used for synchronizing threads + */ + volatile ThreadController * GetThreadController(); + + + /*! + pointers to variables' table, functions' table, the language's object + and to the characters' buffer + */ + ttmath::Objects * GetVariables(); + ttmath::Objects * GetFunctions(); + Languages * GetLanguages(); + char * GetBuffer(); + unsigned int GetBufferSize(); + + + /*! + the constructor and destructor + */ + ProgramResources(); + ~ProgramResources(); + + + /*! + it returns true if we're using windows nt/2000/xp etc. + */ + bool IsWindowsNt(); + + + /*! + we're reading a particular text-value from windows' registry + if there'll be an error we don't change the output string 'result' and return 'false' + */ + bool ReadTextValueFromRegistry(HKEY main_key, const char * sub_key, const char * value, std::string & result); + + + /*! + we're trying to set the name of the configuration file of the program + + if we run the application on windows 9x the file will be in the same + directory in which the program has been run + + when we're using windows nt/2000/xp etc. the configuration file + will be in a special directory for a particular user, for example: + "C:\Documents and Settings\user\applitacion data" + */ + void SetNameOfConfigurationFile(); + + + /*! + reading and writing to a file + */ + IniParser::Error ReadFromFile(); + void SaveToFile(); + + + /*! + it returns a number of line where there was an error + during last parsing + */ + int GetBadLine(); + + +private: + + bool IsWhiteCharacter(int c); + const char * SkipWhiteCharacters(const char * string); + bool IsDecDigit(int c); + bool SplitFunction(const std::string & input, const char * * name, int * param); + + ttmath::Objects variables; + ttmath::Objects functions; + Languages languages; + volatile ThreadController thread_controller; + + unsigned int buffer_size; + char * buffer; + + HINSTANCE hInstance; + HWND main_window; + HWND tab_window[5]; + + int precision; + bool always_on_top; + bool maximized; + View view; + + std::string configuration_file; + + int y_size_normal; + int y_size_compact; + int x_size_min; + + int x_pos; + int y_pos; + int x_size; + int y_size; + + int base_input; + int base_output; + + bool display_always_scientific; + int display_when_scientific; + int display_rounding; + + int bad_line; +}; + + +/*! + a global function which returns the pointer to the object of ProgramResource's type + (there's only one object of this type) +*/ +ProgramResources * GetPrgRes(); + + +#endif diff --git a/src/resource.h b/src/resource.h new file mode 100644 index 0000000..d2bd38c --- /dev/null +++ b/src/resource.h @@ -0,0 +1,139 @@ +#ifndef headerfileresource +#define headerfileresource + +/*! + \file resource.h + \brief the name tags for all controls + + There are the name tags of all the controls which we're using. + Note that in resource.rc file we don't use these tags but + there are only simple numbers there then if you change the numbers here + you must change them in the resource.rc file as well. +*/ + +#define IDD_MAIN_DIALOG 101 +#define IDD_ABOUT_DIALOG 200 +#define IDD_DIALOG_ADD_VARIABLE 102 +#define IDD_DIALOG_ADD_FUNCTION 103 + +#define IDD_DIALOG_STANDARD 110 +#define IDD_DIALOG_VARIABLES 111 +#define IDD_DIALOG_FUNCTIONS 112 +#define IDD_DIALOG_PRECISION 113 +#define IDD_DIALOG_DISPLAY 114 + +#define IDR_MENU 200 +#define IDC_TAB 1010 +#define IDI_ICON1 104 +#define IDC_INPUT_EDIT 1000 +#define IDC_OUTPUT_EDIT 1001 + + +// all controls on the tabs should have different numbers +// because we're using the same window proc for all tabs +// (for all dialogs which will be kinds of the tab control) + +// standard tab +// values from IDC_BUTTON_PRESS_0 to IDC_BUTTON_PRESS_9 should be with the step equal one +#define IDC_BUTTON_PRESS_0 1100 +#define IDC_BUTTON_PRESS_1 1101 +#define IDC_BUTTON_PRESS_2 1102 +#define IDC_BUTTON_PRESS_3 1103 +#define IDC_BUTTON_PRESS_4 1104 +#define IDC_BUTTON_PRESS_5 1105 +#define IDC_BUTTON_PRESS_6 1106 +#define IDC_BUTTON_PRESS_7 1107 +#define IDC_BUTTON_PRESS_8 1108 +#define IDC_BUTTON_PRESS_9 1109 +#define IDC_BUTTON_CLEAR 1110 +#define IDC_BUTTON_FIRST_BRACKET 1111 +#define IDC_BUTTON_LAST_BRACKET 1112 +#define IDC_BUTTON_DIV 1113 +#define IDC_BUTTON_MUL 1114 +#define IDC_BUTTON_SUB 1115 +#define IDC_BUTTON_ADD 1116 +#define IDC_BUTTON_COMMA 1117 +#define IDC_BUTTON_E 1118 +#define IDC_BUTTON_PI 1119 +#define IDC_BUTTON_SIN 1120 +#define IDC_BUTTON_COS 1121 +#define IDC_BUTTON_TAN 1122 +#define IDC_BUTTON_CTAN 1123 +#define IDC_BUTTON_LN 1124 +#define IDC_BUTTON_LOG 1125 +#define IDC_BUTTON_ABS 1126 +#define IDC_BUTTON_FACTORIAL 1127 +#define IDC_BUTTON_POWER 1128 +#define IDC_BUTTON_INT 1129 +#define IDC_BUTTON_ROUND 1130 +#define IDC_BUTTON_EXP 1131 + +// variables tab +#define IDC_VARIABLES_LIST 1132 +#define IDC_BUTTON_ADD_VARIABLE 1133 +#define IDC_EDIT_VARIABLE_NAME 1134 +#define IDC_EDIT_VARIABLE_VALUE 1135 +#define IDC_STATIC_VARIABLE_NAME 1136 +#define IDC_STATIC_VARIABLE_VALUE 1137 +#define IDC_BUTTON_EDIT_VARIABLE 1138 +#define IDC_BUTTON_DELETE_VARIABLE 1139 + +// functions tab +#define IDC_BUTTON_ADD_FUNCTION 1140 +#define IDC_BUTTON_EDIT_FUNCTION 1141 +#define IDC_BUTTON_DELETE_FUNCTION 1142 +#define IDC_FUNCTIONS_LIST 1143 +#define IDC_EDIT_FUNCTION_NAME 1144 +#define IDC_EDIT_FUNCTION_VALUE 1145 +#define IDC_COMBO_FUNCTION_PARAM 1146 +#define IDC_STATIC_FUNCTION_NAME 1147 +#define IDC_STATIC_FUNCTION_PARAM 1148 +#define IDC_STATIC_FUNCTION_VALUE 1149 + +// precision tab +// there must be the following order: +// IDC_RADIO_PRECISION_2 = IDC_RADIO_PRECISION_1 + 1 +// IDC_RADIO_PRECISION_3 = IDC_RADIO_PRECISION_2 + 1 +#define IDC_RADIO_PRECISION_1 1150 +#define IDC_RADIO_PRECISION_2 1151 +#define IDC_RADIO_PRECISION_3 1152 +#define IDC_LABEL_PRECISION_1_INFO 1153 +#define IDC_LABEL_PRECISION_2_INFO 1154 +#define IDC_LABEL_PRECISION_3_INFO 1155 + +// display tab +#define IDC_COMBO_DISPLAY_INPUT 1156 +#define IDC_COMBO_DISPLAY_OUTPUT 1157 +#define IDC_COMBO_DISPLAY_ROUNDING 1159 +#define IDC_RADIO_DISPLAY_ALWAYS_SCIENTIFIC 1160 +#define IDC_RADIO_DISPLAY_NOT_ALWAYS_SCIENTIFIC 1161 +#define IDC_LABEL_DISPLAY_INPUT 1162 +#define IDC_LABEL_DISPLAY_OUTPUT 1163 +#define IDC_LABEL_DISPLAY_ROUNDING 1164 +#define IDC_UPDOWN_DISPLAY_WHEN_SCIENTIFIC 1165 +#define IDC_EDIT_DISPLAY_WHEN_SCIENTIFIC 1166 +#define IDC_LABEL_DIGIT 1167 +#define IDC_LABEL_GROUP_SCIENTIFIC 1168 + +// menu +#define IDM_VIEW_INDEX 0 +#define IDM_EDIT_INDEX 1 +#define IDM_HELP_INDEX 2 +#define IDM_LANGUAGE_INDEX 6 +#define IDM_NEW_WINDOW 40001 +#define IDM_NORMAL_VIEW 40002 +#define IDM_COMPACT_VIEW 40003 +#define IDM_ALWAYS_ON_TOP 40004 +#define IDM_LANGUAGE_ENGLISH 40010 +#define IDM_LANGUAGE_POLISH 40011 +#define IDM_CLOSE_PROGRAM 40020 +#define IDM_EDIT_UNDO 40030 +#define IDM_EDIT_PASTE 40031 +#define IDM_EDIT_COPY_RESULT 40032 +#define IDM_HELP_ABOUT 40040 + +// about dialog +#define IDC_ABOUT_TEXT 1200 +#define IDB_BITMAP_ABOUT 1201 + +#endif diff --git a/src/resource.rc b/src/resource.rc new file mode 100644 index 0000000..94fb0ac --- /dev/null +++ b/src/resource.rc @@ -0,0 +1,188 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "afxres.h" +#undef APSTUDIO_READONLY_SYMBOLS + + +LANGUAGE LANG_POLISH, 1 +104 ICON "..\\res\\icon01.ico" + + +LANGUAGE LANG_NEUTRAL, 0 +200 MENU +FIXED IMPURE LOADONCALL DISCARDABLE +BEGIN + POPUP "&View" + BEGIN + MENUITEM "&New window", 40001 + MENUITEM SEPARATOR + MENUITEM "No&rmal", 40002 + MENUITEM "&Compact", 40003 + MENUITEM SEPARATOR + MENUITEM "&Always on top", 40004 + POPUP "&Language" + BEGIN + MENUITEM "&English", 40010 + MENUITEM "&Polish", 40011 + END + MENUITEM SEPARATOR + MENUITEM "&Close", 40020 + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo", 40030 + MENUITEM "&Paste", 40031 + MENUITEM "&Copy the result", 40032 + END + POPUP "&Help" + BEGIN + MENUITEM "&About", 40040 + END +END + +101 DIALOG 0, 0, 265, 150 +STYLE DS_SETFONT |DS_CENTER |WS_POPUP |WS_SYSMENU |WS_THICKFRAME |WS_MAXIMIZEBOX |WS_MINIMIZEBOX |WS_CAPTION +MENU 200 +CAPTION "TTCalc" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "",1000,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,0,6,260,14 + CONTROL "",1001,"EDIT",ES_READONLY |ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,0,21,260,14 + CONTROL "",1010,"SysTabControl32",WS_CHILD |WS_TABSTOP |WS_VISIBLE ,0,39,261,110 +END + +102 DIALOG 0, 0, 265, 61 +STYLE DS_FIXEDSYS |DS_SETFONT |DS_CENTER |WS_POPUP |WS_VISIBLE |WS_THICKFRAME |WS_CAPTION +CAPTION "Add a new variable" +FONT 8, "Ms Shell Dlg" +BEGIN + CONTROL "Ok",1,"BUTTON",BS_DEFPUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,205,10,50,14 + CONTROL "Cancel",2,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,205,28,50,14 + CONTROL "",1134,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,38,10,67,14 + CONTROL "",1135,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,38,28,147,14 + CONTROL "name:",1136,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,7,12,27,8 + CONTROL "value:",1137,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,7,30,27,8 +END + +103 DIALOG 0, 0, 265, 73 +STYLE DS_FIXEDSYS |DS_SETFONT |DS_CENTER |WS_POPUP |WS_VISIBLE |WS_THICKFRAME |WS_CAPTION +CAPTION "Add a new function" +FONT 8, "Ms Shell Dlg" +BEGIN + CONTROL "Ok",1,"BUTTON",BS_DEFPUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,205,10,50,14 + CONTROL "Cancel",2,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,205,28,50,14 + CONTROL "",1144,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,46,10,67,14 + CONTROL "",1146,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,46,28,67,130 + CONTROL "",1145,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,46,45,147,14 + CONTROL "name:",1147,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,7,12,31,8 + CONTROL "value:",1149,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,7,47,33,8 + CONTROL "param:",1148,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,7,30,33,8 +END + +110 DIALOG 0, 0, 287, 90 +STYLE DS_3DLOOK |DS_FIXEDSYS |DS_SETFONT |WS_CHILD +FONT 8, "Ms Shell Dlg" +BEGIN + CONTROL "Clear",1110,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,3,26,14 + CONTROL "7",1107,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,20,26,14 + CONTROL "4",1104,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,37,26,14 + CONTROL "1",1101,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,54,26,14 + CONTROL "0",1100,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,71,56,14 + CONTROL "(",1111,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,33,3,26,14 + CONTROL "8",1108,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,33,20,26,14 + CONTROL "5",1105,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,33,37,26,14 + CONTROL "2",1102,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,33,54,26,14 + CONTROL ")",1112,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,62,3,26,14 + CONTROL "9",1109,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,62,20,26,14 + CONTROL "6",1106,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,62,37,26,14 + CONTROL "3",1103,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,62,54,26,14 + CONTROL ",",1117,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,62,71,26,14 + CONTROL "^",1128,"BUTTON",BS_PUSHBUTTON |BS_BOTTOM |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,3,26,14 + CONTROL "/",1113,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,20,26,14 + CONTROL "*",1114,"BUTTON",BS_PUSHBUTTON |BS_BOTTOM |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,37,26,14 + CONTROL "-",1115,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,54,26,14 + CONTROL "+",1116,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,71,26,14 + CONTROL "sin",1120,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,131,3,26,14 + CONTROL "cos",1121,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,131,20,26,14 + CONTROL "tan",1122,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,131,37,26,14 + CONTROL "ctg",1123,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,131,54,26,14 + CONTROL "int",1129,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,131,71,26,14 + CONTROL "ln",1124,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,160,3,26,14 + CONTROL "log",1125,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,160,20,26,14 + CONTROL "exp",1131,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,160,37,26,14 + CONTROL "abs",1126,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,160,54,26,14 + CONTROL "round",1130,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,160,71,26,14 + CONTROL "!",1127,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,189,3,26,14 + CONTROL "e",1118,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,229,3,26,14 + CONTROL "pi",1119,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,229,20,26,14 +END + +111 DIALOG 0, 0, 287, 90 +STYLE DS_3DLOOK |DS_FIXEDSYS |DS_SETFONT |WS_CHILD +CAPTION "tab2" +FONT 8, "Ms Shell Dlg" +BEGIN + CONTROL "Add",1133,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,3,50,14 + CONTROL "Edit",1138,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,21,50,14 + CONTROL "Delete",1139,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,39,50,14 + CONTROL "",1132,"SysListView32",LVS_REPORT |LVS_SHOWSELALWAYS |LVS_SORTASCENDING |LVS_ALIGNLEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,57,3,223,85 +END + +112 DIALOG 0, 0, 287, 90 +STYLE DS_3DLOOK |DS_FIXEDSYS |DS_SETFONT |WS_CHILD +CAPTION "tab3" +FONT 8, "Ms Shell Dlg" +BEGIN + CONTROL "Add",1140,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,3,50,14 + CONTROL "Edit",1141,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,21,50,14 + CONTROL "Delete",1142,"BUTTON",BS_PUSHBUTTON |BS_VCENTER |BS_CENTER |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,3,39,50,14 + CONTROL "",1143,"SysListView32",LVS_REPORT |LVS_SHOWSELALWAYS |LVS_SORTASCENDING |LVS_ALIGNLEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,57,3,223,85 +END + +113 DIALOG 0, 0, 287, 90 +STYLE DS_3DLOOK |DS_FIXEDSYS |DS_SETFONT |WS_CHILD +CAPTION "tab4" +FONT 8, "Ms Shell Dlg" +BEGIN + CONTROL "precision 1",1150,"BUTTON",BS_AUTORADIOBUTTON |BS_LEFT |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,15,4,252,10 + CONTROL "precision 2",1151,"BUTTON",BS_AUTORADIOBUTTON |BS_LEFT |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,15,33,252,10 + CONTROL "precision 3",1152,"BUTTON",BS_AUTORADIOBUTTON |BS_LEFT |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,15,62,252,10 + CONTROL "info 1",1153,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,28,17,245,8 + CONTROL "info 2",1154,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,28,46,245,8 + CONTROL "info 3",1155,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,28,74,245,8 +END + +114 DIALOG DISCARDABLE 0, 0, 255, 90 +STYLE DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_CAPTION +CAPTION "tab5" +FONT 8, "Ms Shell Dlg" +BEGIN + COMBOBOX 1156,58,5,63,200,CBS_DROPDOWNLIST | WS_TABSTOP + COMBOBOX 1157,58,19,63,200,CBS_DROPDOWNLIST | WS_TABSTOP + LTEXT "Input",1162,11,7,27,8 + LTEXT "Output",1163,11,22,29,8 + CONTROL "Always",1160,"Button",BS_AUTORADIOBUTTON | BS_LEFT | + WS_TABSTOP,19,65,44,10 + CONTROL "When exp greater than:",1161,"Button", + BS_AUTORADIOBUTTON | BS_LEFT | WS_TABSTOP,77,65,112,10 + LTEXT "Rounding",1164,11,36,43,8 + COMBOBOX 1159,58,33,121,200,CBS_DROPDOWNLIST | WS_TABSTOP + CONTROL "",1165,"msctls_updown32",UDS_SETBUDDYINT | + UDS_ALIGNRIGHT | UDS_ARROWKEYS,213,37,11,14 + EDITTEXT 1166,194,63,29,14,ES_NUMBER + GROUPBOX "Print scientific value",1168,11,51,240,31 + LTEXT "Digit",1167,227,65,20,8 +END + + +200 DIALOG 0, 0, 349, 202 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL 1201,0,"Static",SS_BITMAP,3,3,101,197 + EDITTEXT 1200,112,3,231,197,ES_MULTILINE | ES_READONLY | NOT + WS_BORDER | NOT WS_TABSTOP +END + +1201 BITMAP "..\\res\\abacus_01.bmp" + diff --git a/src/stopcalculating.h b/src/stopcalculating.h new file mode 100644 index 0000000..1444092 --- /dev/null +++ b/src/stopcalculating.h @@ -0,0 +1,122 @@ +#ifndef headerfilestopcalculating +#define headerfilestopcalculating + +/*! + \file stopcalculating.h + \brief it tells us whether there was a stop signal or not +*/ + +#include +#include + + +/*! + \brief it tells us whether there was a stop signal or not + + we can pass a pointer to the object of this class to the certain + calculating methods especially for the method which calculates the + Factorial (1*2*3*4....), such methods as the Factorial takes a lot of time + and sometimes we want to break the calculations for example when we've got + a new input string + + those methods which take a lot of time check the object of type NewStopCalculating + and if there was a stop signal they stop and return immediately without returning + a correct result + + the stop signal can be caused by another thread in our case by the first (gui) thread + + there'll be only one object of this class + (it'll be as an variable of ThreadController class) +*/ +class NewStopCalculating : public ttmath::StopCalculating +{ +public: + + + /*! + the constructor + */ + NewStopCalculating() + { + stop = 0; + } + + + /*! + the destructor + */ + ~NewStopCalculating() + { + if(stop) CloseHandle(stop); + } + + + /*! + it initializes an object of this class + + this method will be called from Init() of the ThreadController object + */ + bool Init() volatile + { + char buffer[80]; + + // with 'GetTickCount()' we're generating an unique identifier of our event + // (there can be another window of ttcalc) + sprintf(buffer,"TTCalcStopEventForStoppingCalculations7756%u", + (unsigned int)GetTickCount()); + + // 'stop' will be manual-reseted and initialized as non-signaled + if( (stop = CreateEvent(0,true,false,buffer))==NULL) + return false; + + return true; + } + + + /*! + when we want to stop the calculations for example when the user changed somewhat + we call the Stop() method from the first (gui) thread + */ + void Stop() volatile + { + SetEvent(stop); + } + + + /*! + when we start the calculations we call this method + + (we call it from WaitForCalculatingAndBlockForStop() method of + ThreadController class) + */ + void Start() volatile + { + ResetEvent(stop); + } + + + /*! + it returns 'true' if there was a stop signal + + it's useful for the second thread and functions which take plenty of time + for calculating, when this method returns 'true' those methods break the + calculations and return without returning a correct value + */ + virtual bool WasStopSignal() const volatile + { + if( WaitForSingleObject(stop,0) == WAIT_OBJECT_0 ) + return true; + + return false; + } + + +private: + +// manual-reset, initialized as non-signaled +HANDLE stop; + +}; + + +#endif diff --git a/src/tabs.cpp b/src/tabs.cpp new file mode 100644 index 0000000..2a70253 --- /dev/null +++ b/src/tabs.cpp @@ -0,0 +1,991 @@ +#include "compileconfig.h" +#include "tabs.h" + +namespace TabWindowFunctions +{ +int tab_standard; +int tab_variables; +int tab_functions; +int tab_precision; +int tab_display; + + +void WpiszTekst(const char * tekst, int cofnac = 0) +{ + SetFocus(GetDlgItem(GetPrgRes()->GetMainWindow(),IDC_INPUT_EDIT)); + + for( ; *tekst ; ++tekst ) + SendDlgItemMessage(GetPrgRes()->GetMainWindow(),IDC_INPUT_EDIT,WM_CHAR,*tekst,0x20001); + + if(cofnac) + { + DWORD l1,l2; + + SendDlgItemMessage(GetPrgRes()->GetMainWindow(),IDC_INPUT_EDIT,EM_GETSEL,(WPARAM)&l1,(LPARAM)&l2); + // l1 bedzie rowne l2 gdyz wczesniej posylalismy WM_CHAR + + SendDlgItemMessage(GetPrgRes()->GetMainWindow(),IDC_INPUT_EDIT,EM_SETSEL,l1+cofnac,l2+cofnac); + } +} + +/* + a function for WM_COMMAND and LOWORD(wParam) + from IDC_BUTTON_PRESS_0 to IDC_BUTTON_PRESS_9 +*/ +BOOL WmTabCommand_Press_0_9(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + SetFocus(GetDlgItem(GetPrgRes()->GetMainWindow(),IDC_INPUT_EDIT)); + SendDlgItemMessage(GetPrgRes()->GetMainWindow(),IDC_INPUT_EDIT,WM_CHAR,LOWORD(wParam)-IDC_BUTTON_PRESS_0+'0',0x20001); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON28 +*/ +BOOL WmTabCommand_Press_e(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("e",0); + +return true; +} + + +BOOL WmTabCommand_Press_comma(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst(".",0); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON27 +*/ +BOOL WmTabCommand_Press_pi(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("pi",0); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON10 +*/ +BOOL WmTabCommand_Press_sin(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("sin()",-1); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON11 +*/ +BOOL WmTabCommand_Press_cos(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("cos()",-1); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON12 +*/ +BOOL WmTabCommand_Press_tan(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("tan()",-1); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON13 +*/ +BOOL WmTabCommand_Press_ctan(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("ctan()",-1); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON14 +*/ +BOOL WmTabCommand_Press_ln(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("ln()",-1); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON24 +*/ +BOOL WmTabCommand_Press_log(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("log( ; )",-4); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON26 +*/ +BOOL WmTabCommand_Press_abs(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("abs()",-1); + +return true; +} + + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_factorial(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("factorial()",-1); + +return true; +} + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_div(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("/", 0); + +return true; +} + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_mul(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("*",0); + +return true; +} + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_sub(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("-",0); + +return true; +} + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_add(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("+",0); + +return true; +} +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_first_bracket(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("(",0); + +return true; +} +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_last_bracket(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst(")",0); + +return true; +} + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_clear(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + SetDlgItemText(GetPrgRes()->GetMainWindow(), IDC_INPUT_EDIT, ""); + +return true; +} + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_power(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("^",0); + +return true; +} +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_int(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("int()",-1); + +return true; +} +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_round(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("round()",-1); + +return true; +} + +/* + a function for WM_COMMAND and LOWORD(wParam)==IDC_BUTTON25 +*/ +BOOL WmTabCommand_Press_exp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WpiszTekst("exp()",-1); + +return true; +} + + + + + +BOOL WmTabCommand_Ok(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +int tab = TabCtrl_GetCurSel(GetParent(hWnd)); + + if( tab == tab_variables ) + { + Variables::WmTabCommand_EditVariable(hWnd, WM_COMMAND, IDC_BUTTON_EDIT_VARIABLE, 0); + } + else + if( tab == tab_functions ) + { + Functions::WmTabCommand_EditFunction(hWnd, WM_COMMAND, IDC_BUTTON_EDIT_FUNCTION, 0); + } + +return true; +} + + + +void SetLanguageTabStandard(HWND hWnd) +{ + SetDlgItemText( hWnd,IDC_BUTTON_CLEAR, GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_clear) ); +} + +void SetLanguageTabVariables(HWND hWnd) +{ + SetDlgItemText( hWnd,IDC_BUTTON_ADD_VARIABLE, GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_add) ); + SetDlgItemText( hWnd,IDC_BUTTON_EDIT_VARIABLE, GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_edit) ); + SetDlgItemText( hWnd,IDC_BUTTON_DELETE_VARIABLE, GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_delete) ); + + HWND list = GetDlgItem(hWnd, IDC_VARIABLES_LIST); + LVCOLUMN column; + + column.mask = LVCF_TEXT; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_variables_header_1) ); + ListView_SetColumn(list,0,&column); + + column.mask = LVCF_TEXT; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_variables_header_2) ); + ListView_SetColumn(list,1,&column); +} + +void SetLanguageTabFunctions(HWND hWnd) +{ + SetDlgItemText( hWnd,IDC_BUTTON_ADD_FUNCTION, GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_add) ); + SetDlgItemText( hWnd,IDC_BUTTON_EDIT_FUNCTION, GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_edit) ); + SetDlgItemText( hWnd,IDC_BUTTON_DELETE_FUNCTION, GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_delete) ); + + HWND list = GetDlgItem(hWnd, IDC_FUNCTIONS_LIST); + LVCOLUMN column; + + column.mask = LVCF_TEXT; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_1) ); + ListView_SetColumn(list,0,&column); + + column.mask = LVCF_TEXT; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_2) ); + ListView_SetColumn(list,1,&column); + + column.mask = LVCF_TEXT; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_3) ); + ListView_SetColumn(list,2,&column); +} + + +void SetLanguageTabPrecision(HWND hWnd) +{ + SetDlgItemText(hWnd, IDC_RADIO_PRECISION_1, GetPrgRes()->GetLanguages()->GuiMessage(Languages::radio_precision_1) ); + SetDlgItemText(hWnd, IDC_RADIO_PRECISION_2, GetPrgRes()->GetLanguages()->GuiMessage(Languages::radio_precision_2) ); + SetDlgItemText(hWnd, IDC_RADIO_PRECISION_3, GetPrgRes()->GetLanguages()->GuiMessage(Languages::radio_precision_3) ); + + SetDlgItemText(hWnd, IDC_LABEL_PRECISION_1_INFO, GetPrgRes()->GetLanguages()->GuiMessage(Languages::precision_1_info) ); + SetDlgItemText(hWnd, IDC_LABEL_PRECISION_2_INFO, GetPrgRes()->GetLanguages()->GuiMessage(Languages::precision_2_info) ); + SetDlgItemText(hWnd, IDC_LABEL_PRECISION_3_INFO, GetPrgRes()->GetLanguages()->GuiMessage(Languages::precision_3_info) ); +} + +void SetLanguageTabDisplay(HWND hWnd) +{ +char buffer[50]; +int i; + + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_ROUNDING, CB_RESETCONTENT, 0, 0); + + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_ROUNDING, CB_ADDSTRING, 0, (LPARAM)GetPrgRes()->GetLanguages()->GuiMessage(Languages::combo_rounding_cut_last_digits) ); + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_ROUNDING, CB_ADDSTRING, 0, (LPARAM)GetPrgRes()->GetLanguages()->GuiMessage(Languages::combo_rounding_none) ); + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_ROUNDING, CB_ADDSTRING, 0, (LPARAM)GetPrgRes()->GetLanguages()->GuiMessage(Languages::combo_rounding_integer) ); + + const int max_r = 9; + for(i=1 ; i<=max_r ; ++i) + { + sprintf(buffer,"%s %d %s", + GetPrgRes()->GetLanguages()->GuiMessage(Languages::combo_rounding_to_number), + i, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::combo_rounding_after_comma) ); + + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_ROUNDING, CB_ADDSTRING, 0, (LPARAM)buffer); + } + + int r = GetPrgRes()->GetDisplayRounding(); + if( r > max_r ) + r = max_r; + + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_ROUNDING, CB_SETCURSEL, r+2, 0); + + + SetDlgItemText(hWnd, IDC_LABEL_DISPLAY_INPUT, GetPrgRes()->GetLanguages()->GuiMessage(Languages::display_input)); + SetDlgItemText(hWnd, IDC_LABEL_DISPLAY_OUTPUT, GetPrgRes()->GetLanguages()->GuiMessage(Languages::display_output)); + SetDlgItemText(hWnd, IDC_LABEL_DISPLAY_ROUNDING, GetPrgRes()->GetLanguages()->GuiMessage(Languages::display_rounding)); + + SetDlgItemText(hWnd, IDC_RADIO_DISPLAY_ALWAYS_SCIENTIFIC, GetPrgRes()->GetLanguages()->GuiMessage(Languages::display_always_scientific)); + SetDlgItemText(hWnd, IDC_RADIO_DISPLAY_NOT_ALWAYS_SCIENTIFIC, GetPrgRes()->GetLanguages()->GuiMessage(Languages::display_not_always_scientific)); + + SetDlgItemText(hWnd, IDC_LABEL_DIGIT, GetPrgRes()->GetLanguages()->GuiMessage(Languages::display_digit)); + SetDlgItemText(hWnd, IDC_LABEL_GROUP_SCIENTIFIC, GetPrgRes()->GetLanguages()->GuiMessage(Languages::display_group_scientific)); +} + + +void SetLanguage(HWND hTab) +{ +TCITEM tab; + + tab.mask = TCIF_TEXT; + + tab.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::tab_standard) ); + TabCtrl_SetItem(hTab,tab_standard, &tab); + + tab.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::tab_variables) ); + TabCtrl_SetItem(hTab,tab_variables, &tab); + + tab.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::tab_functions) ); + TabCtrl_SetItem(hTab,tab_functions, &tab); + + tab.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::tab_precision) ); + TabCtrl_SetItem(hTab,tab_precision, &tab); + + tab.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::tab_display) ); + TabCtrl_SetItem(hTab,tab_display, &tab); + + SetLanguageTabStandard( GetPrgRes()->GetTabWindow(tab_standard) ); + SetLanguageTabVariables( GetPrgRes()->GetTabWindow(tab_variables) ); + SetLanguageTabFunctions( GetPrgRes()->GetTabWindow(tab_functions) ); + SetLanguageTabPrecision( GetPrgRes()->GetTabWindow(tab_precision) ); + SetLanguageTabDisplay( GetPrgRes()->GetTabWindow(tab_display) ); + + InvalidateRect(hTab, 0, false); +} + + +BOOL WmTabCommand_SetPrecision1(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + // there are another messages besides that one + // which is sent when a user clicks on the radio button + if( IsDlgButtonChecked(hWnd, IDC_RADIO_PRECISION_1) != BST_CHECKED ) + return false; + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetPrecision(0); + GetPrgRes()->GetThreadController()->StartCalculating(); + +return true; +} + +BOOL WmTabCommand_SetPrecision2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + // there are another messages besides that one + // which is sent when a user clicks on the radio button + if( IsDlgButtonChecked(hWnd, IDC_RADIO_PRECISION_2) != BST_CHECKED ) + return false; + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetPrecision(1); + GetPrgRes()->GetThreadController()->StartCalculating(); + +return true; +} + +BOOL WmTabCommand_SetPrecision3(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + // there are another messages besides that one + // which is sent when a user clicks on the radio button + if( IsDlgButtonChecked(hWnd, IDC_RADIO_PRECISION_3) != BST_CHECKED ) + return false; + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetPrecision(2); + GetPrgRes()->GetThreadController()->StartCalculating(); + +return true; +} + +BOOL WmTabCommand_DisplayInputChanged(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if( HIWORD(wParam) != CBN_SELCHANGE ) + return false; + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetBaseInput( (int)SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_INPUT, CB_GETCURSEL, 0, 0) + 2 ); + GetPrgRes()->GetThreadController()->StartCalculating(); + +return true; +} + + +BOOL WmTabCommand_DisplayOutputChanged(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if( HIWORD(wParam) != CBN_SELCHANGE ) + return false; + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetBaseOutput( (int)SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_OUTPUT, CB_GETCURSEL, 0, 0) + 2); + GetPrgRes()->GetThreadController()->StartCalculating(); + +return true; +} + + +BOOL WmTabCommand_DisplayRoundingChanged(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if( HIWORD(wParam) != CBN_SELCHANGE ) + return false; + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetDisplayRounding( (int)SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_ROUNDING, CB_GETCURSEL, 0, 0) - 2); + GetPrgRes()->GetThreadController()->StartCalculating(); + +return true; +} + + +void SetDisablingDisplayWhenScientific(HWND hWnd) +{ + if( IsDlgButtonChecked(hWnd, IDC_RADIO_DISPLAY_ALWAYS_SCIENTIFIC) == BST_CHECKED ) + { + EnableWindow(GetDlgItem(hWnd, IDC_UPDOWN_DISPLAY_WHEN_SCIENTIFIC), false); + EnableWindow(GetDlgItem(hWnd, IDC_EDIT_DISPLAY_WHEN_SCIENTIFIC), false); + EnableWindow(GetDlgItem(hWnd, IDC_LABEL_DIGIT), false); + } + else + { + EnableWindow(GetDlgItem(hWnd, IDC_UPDOWN_DISPLAY_WHEN_SCIENTIFIC), true); + EnableWindow(GetDlgItem(hWnd, IDC_EDIT_DISPLAY_WHEN_SCIENTIFIC), true); + EnableWindow(GetDlgItem(hWnd, IDC_LABEL_DIGIT), true); + } +} + + +BOOL WmTabCommand_SetDisplayAlwaysScientific(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + // there are another messages besides that one + // which is sent when a user clicks on the radio button + if( IsDlgButtonChecked(hWnd, IDC_RADIO_DISPLAY_ALWAYS_SCIENTIFIC) != BST_CHECKED ) + return false; + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetDisplayAlwaysScientific(true); + GetPrgRes()->GetThreadController()->StartCalculating(); + + SetDisablingDisplayWhenScientific(hWnd); + +return true; +} + + +BOOL WmTabCommand_SetDisplayNotAlwaysScientific(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + // there are another messages besides that one + // which is sent when a user clicks on the radio button + if( IsDlgButtonChecked(hWnd, IDC_RADIO_DISPLAY_NOT_ALWAYS_SCIENTIFIC) != BST_CHECKED ) + return false; + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetDisplayAlwaysScientific(false); + GetPrgRes()->GetThreadController()->StartCalculating(); + + SetDisablingDisplayWhenScientific(hWnd); + +return true; +} + + + +BOOL WmTabCommand_SetDisplayWhenScientific(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +static bool correct_insertion = false; + + if( HIWORD(wParam)==EN_CHANGE && !correct_insertion ) + { + char buffer[20]; + + GetDlgItemText(hWnd, IDC_EDIT_DISPLAY_WHEN_SCIENTIFIC, buffer, sizeof(buffer)/sizeof(char)); + int w2,w1 = atoi(buffer); + + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetDisplayWhenScientific(w1); + w2 = GetPrgRes()->GetDisplayWhenScientific(); + GetPrgRes()->GetThreadController()->StartCalculating(); + + if( w1 != w2 ) + { + sprintf(buffer,"%d", w2); + + // + correct_insertion = true; + SetDlgItemText(hWnd, IDC_EDIT_DISPLAY_WHEN_SCIENTIFIC, buffer); + correct_insertion = false; + } + } + + + +return true; +} + + + +void CreateTabCommandMessagesTable(Messages & cmessages) +{ + cmessages.Associate(IDC_BUTTON_PRESS_0, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_PRESS_1, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_PRESS_2, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_PRESS_3, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_PRESS_4, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_PRESS_5, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_PRESS_6, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_PRESS_7, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_PRESS_8, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_PRESS_9, WmTabCommand_Press_0_9); + cmessages.Associate(IDC_BUTTON_COMMA, WmTabCommand_Press_comma); + + cmessages.Associate(IDC_BUTTON_E, WmTabCommand_Press_e); + cmessages.Associate(IDC_BUTTON_PI, WmTabCommand_Press_pi); + cmessages.Associate(IDC_BUTTON_SIN, WmTabCommand_Press_sin); + cmessages.Associate(IDC_BUTTON_COS, WmTabCommand_Press_cos); + cmessages.Associate(IDC_BUTTON_TAN, WmTabCommand_Press_tan); + cmessages.Associate(IDC_BUTTON_CTAN, WmTabCommand_Press_ctan); + cmessages.Associate(IDC_BUTTON_LN, WmTabCommand_Press_ln); + cmessages.Associate(IDC_BUTTON_LOG, WmTabCommand_Press_log); + cmessages.Associate(IDC_BUTTON_ABS, WmTabCommand_Press_abs); + cmessages.Associate(IDC_BUTTON_FACTORIAL, WmTabCommand_Press_factorial); + + + cmessages.Associate(IDC_BUTTON_DIV, WmTabCommand_Press_div); + cmessages.Associate(IDC_BUTTON_MUL, WmTabCommand_Press_mul); + cmessages.Associate(IDC_BUTTON_SUB, WmTabCommand_Press_sub); + cmessages.Associate(IDC_BUTTON_ADD, WmTabCommand_Press_add); + cmessages.Associate(IDC_BUTTON_FIRST_BRACKET, WmTabCommand_Press_first_bracket); + cmessages.Associate(IDC_BUTTON_LAST_BRACKET, WmTabCommand_Press_last_bracket); + + cmessages.Associate(IDC_BUTTON_CLEAR, WmTabCommand_Press_clear); + + + + cmessages.Associate(IDC_BUTTON_POWER, WmTabCommand_Press_power); + cmessages.Associate(IDC_BUTTON_INT, WmTabCommand_Press_int); + cmessages.Associate(IDC_BUTTON_ROUND, WmTabCommand_Press_round); + cmessages.Associate(IDC_BUTTON_EXP, WmTabCommand_Press_exp); + + cmessages.Associate(IDC_BUTTON_ADD_VARIABLE, Variables::WmTabCommand_AddVariable); + cmessages.Associate(IDC_BUTTON_EDIT_VARIABLE, Variables::WmTabCommand_EditVariable); + cmessages.Associate(IDC_BUTTON_DELETE_VARIABLE, Variables::WmTabCommand_DeleteVariable); + + cmessages.Associate(IDOK, WmTabCommand_Ok); + + cmessages.Associate(IDC_BUTTON_ADD_FUNCTION, Functions::WmTabCommand_AddFunction); + cmessages.Associate(IDC_BUTTON_EDIT_FUNCTION, Functions::WmTabCommand_EditFunction); + cmessages.Associate(IDC_BUTTON_DELETE_FUNCTION, Functions::WmTabCommand_DeleteFunction); + + cmessages.Associate(IDC_RADIO_PRECISION_1, WmTabCommand_SetPrecision1); + cmessages.Associate(IDC_RADIO_PRECISION_2, WmTabCommand_SetPrecision2); + cmessages.Associate(IDC_RADIO_PRECISION_3, WmTabCommand_SetPrecision3); + + cmessages.Associate(IDC_COMBO_DISPLAY_INPUT, WmTabCommand_DisplayInputChanged); + cmessages.Associate(IDC_COMBO_DISPLAY_OUTPUT, WmTabCommand_DisplayOutputChanged); + cmessages.Associate(IDC_COMBO_DISPLAY_ROUNDING, WmTabCommand_DisplayRoundingChanged); + cmessages.Associate(IDC_RADIO_DISPLAY_ALWAYS_SCIENTIFIC, WmTabCommand_SetDisplayAlwaysScientific); + cmessages.Associate(IDC_RADIO_DISPLAY_NOT_ALWAYS_SCIENTIFIC, WmTabCommand_SetDisplayNotAlwaysScientific); + cmessages.Associate(IDC_EDIT_DISPLAY_WHEN_SCIENTIFIC, WmTabCommand_SetDisplayWhenScientific); + +} + +/* + a function for WM_COMMAND for dialogs which are on the tab +*/ +BOOL WmTabCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +static Messages command_messages; + + if( command_messages.Empty() ) + // initiation + CreateTabCommandMessagesTable(command_messages); + +return command_messages.Call(LOWORD(wParam), hWnd, message, wParam, lParam); +} + +BOOL WmTabInitDialog(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + return true; +} + +/* +int SetSizeOfList(HWND list) +{ + return 0; + + RECT r1,r2; + GetWindowRect(GetParent(list), &r1); + GetWindowRect(list, &r2); + + int cx = (r1.right - r1.left) - GetSystemMetrics(SM_CXEDGE) - 87; + SetWindowPos(list,0,0,0,cx,r2.bottom-r2.top,SWP_NOOWNERZORDER|SWP_NOMOVE); + +return cx; +} +*/ + +/*! + this function is enabling or disabling the 'edit' and 'delete' buttons + on the variable's tab depending on how many variables are selected in the list +*/ +void SetDisablingEditDeleteVariableButtons(HWND hWnd) +{ +HWND list = GetDlgItem(hWnd,IDC_VARIABLES_LIST); + +int count = ListView_GetSelectedCount(list); + + if( count == 1 ) + EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_EDIT_VARIABLE), true); + else + EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_EDIT_VARIABLE), false); + + + if( count != 0 ) + EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_DELETE_VARIABLE), true); + else + EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_DELETE_VARIABLE), false); +} + + +/*! + this function is enabling or disabling the 'edit' and 'delete' buttons + on the function's tab depending on how many variables are selected in the list +*/ +void SetDisablingEditDeleteFunctionButtons(HWND hWnd) +{ +HWND list = GetDlgItem(hWnd,IDC_FUNCTIONS_LIST); + +int count = ListView_GetSelectedCount(list); + + if( count == 1 ) + EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_EDIT_FUNCTION), true); + else + EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_EDIT_FUNCTION), false); + + + if( count != 0 ) + EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_DELETE_FUNCTION), true); + else + EnableWindow(GetDlgItem(hWnd, IDC_BUTTON_DELETE_FUNCTION), false); +} + +void FillUpVariableList(HWND list) +{ + // we don't have to block the second thread here + // because it can only read from variables' table + // (we can read and the second thread can read in the same time as well) + ttmath::Objects::CIterator iv = GetPrgRes()->GetVariables()->Begin(); + + for( ; iv != GetPrgRes()->GetVariables()->End() ; ++iv ) + Variables::AddNewItemToVariableList(list, iv->first, iv->second.value); +} + +void FillUpFunctionList(HWND list) +{ + // we don't have to block the second thread here + // because it can only read from functions' table + // (we can read and the second thread can read in the same time as well) + ttmath::Objects::CIterator iv = GetPrgRes()->GetFunctions()->Begin(); + + for( ; iv != GetPrgRes()->GetFunctions()->End() ; ++iv ) + Functions::AddNewItemToFunctionList(list, iv->first, iv->second.value, iv->second.param); +} + + +BOOL WmInitTabVariables(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +HWND list = GetDlgItem(hWnd, IDC_VARIABLES_LIST); +LVCOLUMN column; + + //int list_cx = SetSizeOfList(list); + int list_cx = 280; + + column.mask = LVCF_TEXT | LVCF_WIDTH; + column.cx = 60; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_variables_header_1) ); + ListView_InsertColumn(list, 0, &column); + + column.cx = list_cx - 60 - 10; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_variables_header_2) ); + ListView_InsertColumn(list, 1, &column); + + ListView_SetExtendedListViewStyle(list,LVS_EX_FULLROWSELECT); + + SetDisablingEditDeleteVariableButtons(hWnd); + FillUpVariableList(list); + +return true; +} + +BOOL WmInitTabFunctions(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +HWND list = GetDlgItem(hWnd, IDC_FUNCTIONS_LIST); +LVCOLUMN column; + + //int list_cx = SetSizeOfList(list); + int list_cx = 280; + + column.mask = LVCF_TEXT | LVCF_WIDTH; + column.cx = 60; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_1) ); + ListView_InsertColumn(list, 0, &column); + + column.cx = 40; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_2) ); + ListView_InsertColumn(list, 1, &column); + + column.cx = list_cx - 60 - 40 - 10; + column.pszText = const_cast( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_3) ); + ListView_InsertColumn(list, 2, &column); + + ListView_SetExtendedListViewStyle(list,LVS_EX_FULLROWSELECT); + + SetDisablingEditDeleteFunctionButtons(hWnd); + FillUpFunctionList(list); + +return true; +} + + +BOOL WmInitTabPrecision(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + CheckDlgButton(hWnd, IDC_RADIO_PRECISION_1 + GetPrgRes()->GetPrecision(), BST_CHECKED); + +return true; +} + + + + +BOOL WmInitTabDisplay(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +int i; +char buffer[20]; + + for(i=2 ; i<=16 ; ++i) + { + sprintf(buffer,"%d",i); + + switch( i ) + { + case 2: + strcat(buffer, " (bin)"); + break; + + case 8: + strcat(buffer, " (oct)"); + break; + + case 10: + strcat(buffer, " (dec)"); + break; + + case 16: + strcat(buffer, " (hex)"); + break; + } + + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_INPUT, CB_ADDSTRING, 0, (LPARAM)buffer); + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_OUTPUT, CB_ADDSTRING, 0, (LPARAM)buffer); + } // for + + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_INPUT, CB_SETCURSEL, GetPrgRes()->GetBaseInput()-2, 0); + SendDlgItemMessage(hWnd, IDC_COMBO_DISPLAY_OUTPUT, CB_SETCURSEL, GetPrgRes()->GetBaseOutput()-2, 0); + + + if( GetPrgRes()->GetDisplayAlwaysScientific() ) + CheckDlgButton(hWnd, IDC_RADIO_DISPLAY_ALWAYS_SCIENTIFIC, BST_CHECKED); + else + CheckDlgButton(hWnd, IDC_RADIO_DISPLAY_NOT_ALWAYS_SCIENTIFIC, BST_CHECKED); + + SetDisablingDisplayWhenScientific(hWnd); + + SendDlgItemMessage(hWnd, IDC_UPDOWN_DISPLAY_WHEN_SCIENTIFIC, UDM_SETBASE, 10,0); + SendDlgItemMessage(hWnd, IDC_UPDOWN_DISPLAY_WHEN_SCIENTIFIC, UDM_SETRANGE, 0, MAKELONG(99,1)); + SendDlgItemMessage(hWnd, IDC_UPDOWN_DISPLAY_WHEN_SCIENTIFIC, UDM_SETPOS, 0, 5); + SendDlgItemMessage(hWnd, IDC_UPDOWN_DISPLAY_WHEN_SCIENTIFIC, UDM_SETBUDDY, (WPARAM)GetDlgItem(hWnd, IDC_EDIT_DISPLAY_WHEN_SCIENTIFIC), 0); + SendDlgItemMessage(hWnd, IDC_EDIT_DISPLAY_WHEN_SCIENTIFIC, EM_SETLIMITTEXT, 2, 0); + + sprintf(buffer,"%d", GetPrgRes()->GetDisplayWhenScientific()); + SetDlgItemText(hWnd, IDC_EDIT_DISPLAY_WHEN_SCIENTIFIC, buffer); + +return true; +} + +BOOL WmNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +NMHDR * pnmh = (LPNMHDR) lParam; +HWND var_list = GetDlgItem(hWnd,IDC_VARIABLES_LIST); +HWND fun_list = GetDlgItem(hWnd,IDC_FUNCTIONS_LIST); + + if( pnmh->hwndFrom == var_list ) + { + if( pnmh->code == LVN_ITEMCHANGED ) + { + SetDisablingEditDeleteVariableButtons( hWnd ); + return true; + } + + if( pnmh->code == UINT(NM_DBLCLK) ) + { + Variables::WmTabCommand_EditVariable(hWnd, WM_COMMAND, IDC_BUTTON_EDIT_VARIABLE, 0); + return true; + } + } + + if( pnmh->hwndFrom == fun_list ) + { + if( pnmh->code == LVN_ITEMCHANGED ) + { + SetDisablingEditDeleteFunctionButtons( hWnd ); + return true; + } + + if( pnmh->code == UINT(NM_DBLCLK) ) + { + Functions::WmTabCommand_EditFunction(hWnd, WM_COMMAND, IDC_BUTTON_EDIT_FUNCTION, 0); + return true; + } + } + +return false; +} + + +void CreateTabMessagesTable(Messages & messages) +{ + messages.Associate(WM_INITDIALOG, WmTabInitDialog); + messages.Associate(WM_COMMAND, WmTabCommand); + messages.Associate(WM_INIT_TAB_VARIABLES, WmInitTabVariables); + messages.Associate(WM_INIT_TAB_FUNCTIONS, WmInitTabFunctions); + messages.Associate(WM_INIT_TAB_PRECISION, WmInitTabPrecision); + messages.Associate(WM_INIT_TAB_DISPLAY, WmInitTabDisplay); + messages.Associate(WM_NOTIFY, WmNotify); +} + + + +BOOL CALLBACK TabWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +static Messages messages; + + if( messages.Empty() ) + // initiation + CreateTabMessagesTable(messages); + +return messages.Call(message, hWnd, message, wParam, lParam); +} + + + +void SetSizeOfFunctionVariableList(int tab_id, int list_id) +{ +HWND main = GetPrgRes()->GetMainWindow(); +HWND tab = GetDlgItem(main, IDC_TAB); + +POINT p,p2; +RECT r_main, r; + + HWND dialog = GetPrgRes()->GetTabWindow(tab_id); + HWND list = GetDlgItem(dialog, list_id); + + GetWindowRect(main, &r_main); + int cx = r_main.right - r_main.left; + int cy = r_main.bottom - r_main.top; + int border_x = GetSystemMetrics(SM_CXDLGFRAME)*2; + int border_y = GetSystemMetrics(SM_CYDLGFRAME)*2; + + GetWindowRect(dialog, &r); + p.x = r.left; + p.y = r.top; + p2 = p; + p2.x -= r_main.left; + p2.y -= r_main.top; + ScreenToClient(tab, &p); + MoveWindow(dialog, p.x, p.y, cx-p2.x-border_x-2, cy-p2.y-border_y-2, true); + + GetWindowRect(list, &r); + p.x = r.left; + p.y = r.top; + p2 = p; + p2.x -= r_main.left; + p2.y -= r_main.top; + ScreenToClient(dialog, &p); + MoveWindow(list, p.x, p.y, cx-p2.x-border_x-2, cy-p2.y-border_y-2, true); +} + + +void SetSizeOfVariablesList() +{ + SetSizeOfFunctionVariableList(TabWindowFunctions::tab_variables, IDC_VARIABLES_LIST); +} + +void SetSizeOfFunctionsList() +{ + SetSizeOfFunctionVariableList(TabWindowFunctions::tab_functions, IDC_FUNCTIONS_LIST); +} + + +} // namespace TabWindowFunctions + + + diff --git a/src/tabs.h b/src/tabs.h new file mode 100644 index 0000000..48f8204 --- /dev/null +++ b/src/tabs.h @@ -0,0 +1,66 @@ +#ifndef headerfiletabs +#define headerfiletabs + +#include +#include +#include +#include + +#include "resource.h" +#include "messages.h" +#include +#include "programresources.h" + + +//#define WM_INIT_TAB_VARIABLES WM_USER+2 +//#define WM_INIT_TAB_FUNCTIONS WM_USER+3 +//#define WM_INIT_TAB_PRECISION WM_USER+4 + +#define WM_INIT_TAB_VARIABLES WM_APP +#define WM_INIT_TAB_FUNCTIONS WM_APP+1 +#define WM_INIT_TAB_PRECISION WM_APP+2 +#define WM_INIT_TAB_DISPLAY WM_APP+3 + +namespace TabWindowFunctions +{ +extern int tab_standard; +extern int tab_variables; +extern int tab_functions; +extern int tab_precision; +extern int tab_display; + + BOOL CALLBACK TabWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + void SetLanguage(HWND hTab); + void SetSizeOfVariablesList(); + void SetSizeOfFunctionsList(); + + namespace Variables + { + extern std::string caption,name,value; + extern bool adding; + + char * ChangeToSmallLetters(char * string); + char * StripWhiteCharacters(char * string); + + void AddNewItemToVariableList(HWND list, const std::string & name, const std::string & value); + + BOOL WmTabCommand_AddVariable(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + BOOL WmTabCommand_EditVariable(HWND hWnd, UINT message, WPARAM wParam, LPARAM); + BOOL WmTabCommand_DeleteVariable(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + } + + namespace Functions + { + extern std::string caption,name,value; + extern bool adding; + + void AddNewItemToFunctionList(HWND list, const std::string & name, const std::string & value, int parameters); + + BOOL WmTabCommand_AddFunction(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + BOOL WmTabCommand_EditFunction(HWND hWnd, UINT message, WPARAM wParam, LPARAM); + BOOL WmTabCommand_DeleteFunction(HWND hWnd, UINT message, WPARAM wParam, LPARAM); + } +} + + +#endif diff --git a/src/threadcontroller.h b/src/threadcontroller.h new file mode 100644 index 0000000..cc0fcde --- /dev/null +++ b/src/threadcontroller.h @@ -0,0 +1,215 @@ +#ifndef headerfilethreadcontroller +#define headerfilethreadcontroller + +/*! + \file threadcontroller.h + \brief class ThreadController manages our two threads +*/ + +#include +#include +#include "stopcalculating.h" + + +/*! + \brief the object of this class (there's only one) will be 'managing' our two threads + + the first main thread is started with the application (when the system + runs the programme) and the second one is when the application creates it + at the beginning in WinMain function, the second thread is only used for calculating + + as you know we have some common objects for example the string for parsing, + user-defined variables and functions etc. and those objects are set in the first + thread (the first thread is joined with gui), and when we want to make our calculations + we must put them to the second thread and then we need an object which helps us + with that job + + there's only one object of this class in our application, we can get a pointer + to it by using GetPrgRes() function and then by GetThreadController() method + + when we would like to change for example the input string first we must call + StopCalculating() method then we can change what we want to change and then + we must call StartCalculating(), for example if we wanted to change the precision + of displaying we'd have to do: + GetPrgRes()->GetThreadController()->StopCalculating(); + GetPrgRes()->SetPrecision( ..new_precision.. ); + GetPrgRes()->GetThreadController()->StartCalculating(); +*/ +class ThreadController +{ +public: + + /*! + the default constructor + (notice that there'll be only one object of this class) + */ + ThreadController() + { + calculations = 0; + ready_for_stop = 0; + exit_thread = false; + } + + + /*! + the destructor + */ + ~ThreadController() + { + if(calculations) CloseHandle(calculations); + if(ready_for_stop) CloseHandle(ready_for_stop); + } + + + /*! + it initializes an object of this class + + we create two system event and initialize the 'stop_calculating' object + */ + bool Init() volatile + { + char * buffer = new char[300]; + + // with 'GetTickCount()' we're generating an unique identifier of our event + // (there can be another window of ttcalc) + sprintf((char*)buffer,"TTCalcEventForManagingThreads9928%u", + (unsigned int)GetTickCount()); + + // 'calculations' will be for auto-reseting and initialized as non-signaled + if( (calculations = CreateEvent(0,false,false,(char*)buffer))==NULL) + { + delete [] buffer; + return false; + } + + sprintf((char*)buffer,"TTCalcEventReadyForStop5567%u", + (unsigned int)GetTickCount()); + + // 'ready_for_stop' will be for manual-reseting and initialized as signaled + // 'manual-reset' means that we must call ResetEvent() function (from WinAPI) + // to manually reset the state to nonsignaled + if( (ready_for_stop = CreateEvent(0,true,true,(char*)buffer))==NULL) + { + delete [] buffer; + return false; + } + + delete [] buffer; + + return stop_calculating.Init(); + } + + + /*! + when the second thread leaves the WaitForCalculatingAndBlockForStop() method + then there's special time for making copy of certain objects (e.g. the input + string, user-defined variables, functions etc.) and when the second thread + will have finished that then it call ReadyForStop() method + */ + void ReadyForStop() volatile + { + SetEvent( ready_for_stop ); + } + + + /*! + if we want to close the application for example when the user pushed the + close button we call StopCalculatingAndExitThread() from the first main thread (gui), + it means that the second thread (calculations) will finish itself + */ + void StopCalculatingAndExitThread() volatile + { + WaitForSingleObject(ready_for_stop,INFINITE); + + stop_calculating.Stop(); + exit_thread = true; + SetEvent(calculations); + } + + + /*! + when we want to change something for caltulating for example the input string + first we must call StopCalculating() + + StopCalculating() waits for the second thread (if it is in the special time + of copying variables) then sets the 'stop object' for signaled and returns to + the caller + */ + void StopCalculating() volatile + { + WaitForSingleObject(ready_for_stop, INFINITE); + + stop_calculating.Stop(); + } + + + /*! + when we have changed what we wanted we call StartCalculating() + in other words it means that the calculations will start + (maybe now, maybe at once if the second thread is still working) + */ + void StartCalculating() volatile + { + SetEvent(calculations); + } + + + /*! + this is the main method which is used by the second thread, + if there's nothing to do this method (and the second thread as well) waits + */ + volatile bool WaitForCalculatingAndBlockForStop() volatile + { + WaitForSingleObject(calculations,INFINITE); + ResetEvent(ready_for_stop); + + stop_calculating.Start(); + + return !exit_thread; + } + + + /*! + this method returns the pointer to the 'stop object' + it's used by the second thread during calculating + */ + const volatile ttmath::StopCalculating * GetStopObject() volatile const + { + return &stop_calculating; + } + + + /*! + it returns 'true' if there was a stop signal during calculating + the stop signal can be caused by the first thread (gui thread) + */ + bool WasStopSignal() volatile const + { + return stop_calculating.WasStopSignal(); + } + + +private: + +// auto-reset, initialized as non-signaled +HANDLE calculations; + +// manual-reset, initialized as signaled +HANDLE ready_for_stop; + +bool exit_thread; + +NewStopCalculating stop_calculating; + + + /*! + we make the copy-constructor private so that nobody will be able + to make a copy of the one object of this class + */ + ThreadController(const ThreadController & c) + { + } +}; + + +#endif diff --git a/src/variables.cpp b/src/variables.cpp new file mode 100644 index 0000000..155a96e --- /dev/null +++ b/src/variables.cpp @@ -0,0 +1,270 @@ +#include "compileconfig.h" +#include "tabs.h" + + +namespace TabWindowFunctions +{ +namespace Variables +{ +std::string caption,name,value; +bool adding; + + + +/*! + this method changes the whole string into a string consists of small letters + (it returns the same pointer) +*/ +char * ChangeToSmallLetters(char * string) +{ +char * p; + + for( p = string ; *p>='A' && *p<='Z' ; ++p ) + *p = *p - 'A' + 'a'; + +return string; +} + +char * StripWhiteCharacters(char * string) +{ +char * start, * end; + + IniParser::CheckWhiteCharacters(string, (const char**)&start, (const char**)&end); + + *end = 0; + +return start; +} + +BOOL CALLBACK DialogProcVariables(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +static const int temporary_buffer_size = 200; +char * pchar; + + switch(message) + { + case WM_INITDIALOG: + SetWindowText(hWnd, caption.c_str()); + + SetDlgItemText(hWnd, IDC_STATIC_VARIABLE_NAME, GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_variables_header_1)); + SetDlgItemText(hWnd, IDC_STATIC_VARIABLE_VALUE, GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_variables_header_2)); + + SetDlgItemText(hWnd, IDOK, GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_ok)); + SetDlgItemText(hWnd, IDCANCEL,GetPrgRes()->GetLanguages()->GuiMessage(Languages::button_cancel)); + + SetDlgItemText(hWnd,IDC_EDIT_VARIABLE_NAME, name.c_str()); + SetDlgItemText(hWnd,IDC_EDIT_VARIABLE_VALUE, value.c_str()); + + if( adding ) + { + SetFocus(GetDlgItem(hWnd,IDC_EDIT_VARIABLE_NAME)); + } + else + { + EnableWindow(GetDlgItem(hWnd,IDC_EDIT_VARIABLE_NAME), false); + SetFocus(GetDlgItem(hWnd,IDC_EDIT_VARIABLE_VALUE)); + } + + return false; + + case WM_COMMAND: + if( LOWORD(wParam) == IDOK ) + { + pchar = new char[temporary_buffer_size]; + + GetDlgItemText(hWnd, IDC_EDIT_VARIABLE_NAME, pchar, temporary_buffer_size); + name = ChangeToSmallLetters( StripWhiteCharacters(pchar) ); + + GetDlgItemText(hWnd, IDC_EDIT_VARIABLE_VALUE, pchar, temporary_buffer_size); + value = ChangeToSmallLetters( StripWhiteCharacters(pchar) ); + + delete [] pchar; + + EndDialog(hWnd,1); + } + else + if( LOWORD(wParam) == IDCANCEL ) + { + EndDialog(hWnd,0); + return true; + } + + break; + } + +return false; +} + + +void AddNewItemToVariableList(HWND list, const std::string & name, const std::string & value) +{ +LVITEM item; + + item.mask = LVIF_TEXT; + item.pszText = const_cast( name.c_str() ); + item.iSubItem = 0; + + int id = ListView_InsertItem(list, &item); + ListView_SetItemText(list,id,1,const_cast( value.c_str() )); +} + + + + + +void SetNewVariableValueIntoList(HWND list, int id) +{ +ttmath::ErrorCode code; + + GetPrgRes()->GetThreadController()->StopCalculating(); + code = GetPrgRes()->GetVariables()->Edit(name, value); + GetPrgRes()->GetThreadController()->StartCalculating(); + + if( code == ttmath::err_unknown_object ) + { + // there is probably an internal error + // because we should have had this variable + + MessageBox( list, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_edit_variable_unknown_variable), + GetPrgRes()->GetLanguages()->GuiMessage(Languages::message_box_caption), + MB_ICONERROR); + + return; + } + + ListView_SetItemText(list,id,1,const_cast( value.c_str() )); +} + + +BOOL WmTabCommand_AddVariable(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + caption = GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_add_variable_caption); + name = ""; + value = ""; + adding = true; + + if( DialogBox(GetPrgRes()->GetInstance(), MAKEINTRESOURCE(IDD_DIALOG_ADD_VARIABLE), hWnd, DialogProcVariables) ) + { + HWND list = GetDlgItem(hWnd, IDC_VARIABLES_LIST); + ttmath::ErrorCode code; + + GetPrgRes()->GetThreadController()->StopCalculating(); + code = GetPrgRes()->GetVariables()->Add(name, value); + GetPrgRes()->GetThreadController()->StartCalculating(); + + if( code == ttmath::err_object_exists ) + { + MessageBox( hWnd, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_add_variable_variable_exists), + GetPrgRes()->GetLanguages()->GuiMessage(Languages::message_box_caption), + MB_ICONERROR); + + return true; + } + + AddNewItemToVariableList(list, name, value); + } + +return true; +} + + + +/*! + (we're also using this method directly without using the main loop of messages) + (we don't define the 'lParam' parameter there) +*/ +BOOL WmTabCommand_EditVariable(HWND hWnd, UINT message, WPARAM wParam, LPARAM) +{ +HWND list = GetDlgItem(hWnd, IDC_VARIABLES_LIST); + + if( ListView_GetSelectedCount(list) != 1 ) + // there must be only one item selected + return true; + + int id = ListView_GetSelectionMark(list); + + const int buffer_size = 300; + char * buffer = new char[buffer_size]; + + caption = GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_edit_variable_caption); + + ListView_GetItemText(list,id,0,buffer, buffer_size); + name = buffer; + + ListView_GetItemText(list,id,1,buffer, buffer_size); + value = buffer; + + delete [] buffer; + + adding = false; + + if( DialogBox(GetPrgRes()->GetInstance(), MAKEINTRESOURCE(IDD_DIALOG_ADD_VARIABLE), hWnd, DialogProcVariables) ) + { + SetNewVariableValueIntoList(list, id); + } + +return true; +} + + +BOOL WmTabCommand_DeleteVariable(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +HWND list = GetDlgItem(hWnd, IDC_VARIABLES_LIST); +int items = ListView_GetSelectedCount(list); + + if( items == 0 ) + // there must be at least one item selected + return true; + + if( items > 1 ) + { + // we're showing a message to confirm deleting + if( MessageBox( hWnd, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_delete_variable_confirm), + GetPrgRes()->GetLanguages()->GuiMessage(Languages::message_box_caption), + MB_ICONWARNING | MB_YESNO) == IDNO ) + return true; + } + + int id; + const int buffer_size = 300; + char * buffer = new char[buffer_size]; + bool all_deleted = true; + + GetPrgRes()->GetThreadController()->StopCalculating(); + + for( id = ListView_GetItemCount(list)-1 ; id!=-1 ; --id ) + { + if( ListView_GetItemState(list, id, LVIS_SELECTED) == LVIS_SELECTED ) + { + ListView_GetItemText(list,id,0,buffer,buffer_size); + if( GetPrgRes()->GetVariables()->Delete(buffer) == ttmath::err_unknown_object ) + all_deleted = false; + else + ListView_DeleteItem(list, id); + } + } + + GetPrgRes()->GetThreadController()->StartCalculating(); + + delete [] buffer; + + if( !all_deleted ) + // there are some items which we've not deleted + // probably an internal error + MessageBox( hWnd, + GetPrgRes()->GetLanguages()->GuiMessage(Languages::dialog_box_variable_not_all_deleted), + GetPrgRes()->GetLanguages()->GuiMessage(Languages::message_box_caption), + MB_ICONERROR); + +return true; +} + + + + + +} // namespace +} // namespace diff --git a/src/winmain.cpp b/src/winmain.cpp new file mode 100644 index 0000000..15a89db --- /dev/null +++ b/src/winmain.cpp @@ -0,0 +1,113 @@ +#include "compileconfig.h" +#include "winmain.h" + +/*! + \file mainwin.cpp + \brief There's defined the entry point to the application +*/ + + + +/*! + here our application starts +*/ +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) +{ + GetPrgRes()->SetInstance(hInstance); + GetPrgRes()->GetLanguages()->SetCurrentLanguage(Languages::en); + GetPrgRes()->SetNameOfConfigurationFile(); + GetPrgRes()->ReadFromFile(); + + INITCOMMONCONTROLSEX common_ctrl; + common_ctrl.dwSize = sizeof(common_ctrl); + common_ctrl.dwICC = ICC_WIN95_CLASSES; + + if( !InitCommonControlsEx(&common_ctrl) ) + return ShowError( Languages::cant_init_common_controls ); + + if( !GetPrgRes()->GetThreadController()->Init() ) + return ShowError( Languages::cant_init_calculations ); + + unsigned int thread_id; + uintptr_t thread_handle; + if( (thread_handle = _beginthreadex(0,0,CalculationsProcedure, 0, 0, &thread_id)) == 0 ) + return ShowError( Languages::cant_create_thread ); + + CreateDialog( hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), 0, MainWindowProc); + + if( !GetPrgRes()->GetMainWindow() ) + return ShowError( Languages::cant_create_main_window ); + + + // there's the main loop of messages here + MainMessagesLoop(); + + GetPrgRes()->SaveToFile(); + CloseHandle( (HANDLE)thread_handle ); + +return 0; +} + + +/*! + it displays a message box with an error + (it's only used during initiation) +*/ +int ShowError( Languages::GuiMsg error_code ) +{ + MessageBox(0, GetPrgRes()->GetLanguages()->GuiMessage( error_code ), + GetPrgRes()->GetLanguages()->GuiMessage( Languages::message_box_error_caption ), + MB_ICONERROR); + +return static_cast( error_code ); +} + + +/*! + the main loop of messages +*/ +void MainMessagesLoop() +{ +MSG msg; + + while( GetMessage(&msg,0,0,0) ) + { + bool sended = false; + + // firt we try to send our message to dialogs + // (the dialogs on the tab control) + for(unsigned int i=0 ; iHowManyTabWindows() && !sended ; ++i) + { + if( IsDialogMessage(GetPrgRes()->GetTabWindow(i), &msg) ) + sended = true; + } + + // if it's not a message to any of our dialogs we send it + // to the main window (it's a dialog as well) + if( !sended ) + { + if( !IsDialogMessage(GetPrgRes()->GetMainWindow(), &msg) ) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } +} + + +/*! + the window-procedure for the main window +*/ +BOOL CALLBACK MainWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +static Messages messages; + + if( messages.Empty() ) + // initiation + MainWindowFunctions::CreateMainMessagesTable(messages); + +// in the Messages class we're using the std::map +// so that we have the logarythmic time to find the special function to call +return messages.Call(message, hWnd, message, wParam, lParam); +} diff --git a/src/winmain.h b/src/winmain.h new file mode 100644 index 0000000..bd09497 --- /dev/null +++ b/src/winmain.h @@ -0,0 +1,34 @@ +#ifndef headerfilewinmain +#define headerfilewinmain + +/*! + \file mainwin.h + \brief some declarations of variables or functions used in winmain.cpp and mainwindow.cpp +*/ + +#include "programresources.h" +#include "resource.h" +#include "messages.h" +#include "tabs.h" + +#include +#include +#include + +#include + + +BOOL CALLBACK MainWindowProc(HWND hWnd, UINT messge, WPARAM wParam, LPARAM lParam); +//DWORD WINAPI CalculationsProcedure(LPVOID lpParameter); +unsigned __stdcall CalculationsProcedure(void *); +int ShowError( Languages::GuiMsg error_code ); +void MainMessagesLoop(); + + +namespace MainWindowFunctions +{ + void CreateMainMessagesTable(Messages & messages); + BOOL CALLBACK AboutProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +} + +#endif