commit 368711c76ce24bedde165318b8d1fcce69ba7957 Author: Tomasz Sowa Date: Mon Jan 22 11:12:01 2007 +0000 initial import git-svn-id: svn://ttmath.org/publicrep/ttcalc/trunk@2 e52654a7-88a9-db11-a3e9-0013d4bc506e 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 0000000..b750c4d Binary files /dev/null and b/res/abacus_01.bmp differ diff --git a/res/icon01.ico b/res/icon01.ico new file mode 100644 index 0000000..7735d56 Binary files /dev/null and b/res/icon01.ico differ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..f930729 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,43 @@ +CC = g++ +o = resource.o calculation.o functions.o iniparser.o languages.o mainwindow.o parsermanager.o programresources.o tabs.o variables.o winmain.o +CFLAGS = -Wall -pedantic -s -O3 -mwindows -mthreads -I../../../ttmath + + +name = ttcalc.exe +dir_output = ../../output + + + +.SUFFIXES: .cpp .o + +.cpp.o: + $(CC) -c $(CFLAGS) $< + + +all: ttcalc + + +ttcalc: $(o) + $(CC) -o $(dir_output)/$(name) $(CFLAGS) $(o) -lcomctl32 + + +resource.o: resource.rc + windres resource.rc resource.o + +calculation.o: calculation.cpp compileconfig.h parsermanager.h resource.h programresources.h iniparser.h languages.h threadcontroller.h stopcalculating.h +functions.o: functions.cpp compileconfig.h tabs.h resource.h messages.h programresources.h iniparser.h languages.h threadcontroller.h stopcalculating.h +iniparser.o: iniparser.cpp compileconfig.h iniparser.h +languages.o: languages.cpp compileconfig.h languages.h +mainwindow.o: mainwindow.cpp compileconfig.h winmain.h programresources.h iniparser.h languages.h threadcontroller.h stopcalculating.h resource.h messages.h tabs.h +parsermanager.o: parsermanager.cpp compileconfig.h parsermanager.h resource.h programresources.h iniparser.h languages.h threadcontroller.h stopcalculating.h +programresources.o: programresources.cpp compileconfig.h programresources.h iniparser.h languages.h threadcontroller.h stopcalculating.h +tabs.o: tabs.cpp compileconfig.h tabs.h resource.h messages.h programresources.h iniparser.h languages.h threadcontroller.h stopcalculating.h +variables.o: variables.cpp compileconfig.h tabs.h resource.h messages.h programresources.h iniparser.h languages.h threadcontroller.h stopcalculating.h +winmain.o: winmain.cpp compileconfig.h winmain.h programresources.h iniparser.h languages.h threadcontroller.h stopcalculating.h resource.h messages.h tabs.h + + +clean: + rm -f *.o + rm -f *.s + rm -f $(dir_output)/$(name) + rm -f $(name_cons) diff --git a/src/calculation.cpp b/src/calculation.cpp new file mode 100644 index 0000000..ef3052a --- /dev/null +++ b/src/calculation.cpp @@ -0,0 +1,56 @@ +#include "compileconfig.h" +#include "parsermanager.h" + +#include + +/*! + 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