initial import

git-svn-id: svn://ttmath.org/publicrep/ttcalc/trunk@2 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2007-01-22 11:12:01 +00:00
commit 368711c76c
28 changed files with 5647 additions and 0 deletions

2
CHANGELOG Normal file
View File

@ -0,0 +1,2 @@

28
COPYRIGHT Normal file
View File

@ -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.

17
TODO Normal file
View File

@ -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)

BIN
res/abacus_01.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

BIN
res/icon01.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

43
src/Makefile Normal file
View File

@ -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)

56
src/calculation.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "compileconfig.h"
#include "parsermanager.h"
#include <process.h>
/*!
the function for the second thread
*/
//DWORD WINAPI CalculationsProcedure(LPVOID lpParameter)
unsigned __stdcall CalculationsProcedure(void *)
{
/*
using namespace ttmath;
Parser<Big<3,9> > 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;
}

38
src/compileconfig.h Normal file
View File

@ -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

277
src/functions.cpp Normal file
View File

@ -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<char*>( 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<char*>( 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<char*>( 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

397
src/iniparser.cpp Normal file
View File

@ -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<std::string, std::string> * result)
{
table_whole_section.insert( std::make_pair(std::string(pattern), result) );
}
void IniParser::Associate(const std::string & pattern, std::map<std::string, std::string> * 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);
}

133
src/iniparser.h Normal file
View File

@ -0,0 +1,133 @@
#ifndef headerfileiniparser
#define headerfileiniparser
/*!
\file iniparser.h
\brief A Parser witch we use for parsing 'ini' files
*/
#include <string>
#include <fstream>
#include <map>
/*!
\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<std::string, std::string> 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<std::string, std::string> * result);
void Associate(const std::string & pattern, std::map<std::string, std::string> * 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<std::string, std::string *> Table;
typedef std::map<std::string, Section *> 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

355
src/languages.cpp Normal file
View File

@ -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<unsigned int>( country );
if( cid >= error_messages_tab.size() )
return unk_err;
std::map<ttmath::ErrorCode, std::string>::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<ttmath::ErrorCode, std::string>() );
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<ttmath::ErrorCode, std::string>() );
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<unsigned int>( country );
if( cid >= gui_messages_tab.size() )
return unk_msg;
std::map<GuiMsg, std::string>::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<GuiMsg, std::string>() );
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<GuiMsg, std::string>() );
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");
}

139
src/languages.h Normal file
View File

@ -0,0 +1,139 @@
#ifndef headerfilelanguages
#define headerfilelanguages
#include <string>
#include <map>
#include <vector>
#include <ttmath/ttmathtypes.h>
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<std::map<ttmath::ErrorCode, std::string> > error_messages_tab;
std::vector<std::map<GuiMsg, std::string> > 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

754
src/mainwindow.cpp Normal file
View File

@ -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<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::menu_view) );
SetMenuItemInfo(menu, IDM_VIEW_INDEX, true, &mi);
mi.dwTypeData = const_cast<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::menu_edit) );
SetMenuItemInfo(menu, IDM_EDIT_INDEX, true, &mi);
mi.dwTypeData = const_cast<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::menu_help) );
SetMenuItemInfo(menu, IDM_HELP_INDEX, true, &mi);
mi.dwTypeData = const_cast<char*>( 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

60
src/messages.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef headerfilemessages
#define headerfilemessages
#include <map>
#include <windows.h>
class Messages
{
public:
typedef BOOL (*MessageFunction)(HWND, UINT, WPARAM, LPARAM);
typedef std::map<UINT, MessageFunction> 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

149
src/parsermanager.cpp Normal file
View File

@ -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 ; i<buffer_len-1 && pchar[i]!=0 ; ++i)
buffer[i] = pchar[i];
buffer[i] = 0;
//
variables = *GetPrgRes()->GetVariables();
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) );
}
}

143
src/parsermanager.h Normal file
View File

@ -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 <ttmath/ttmathparser.h>
#include "programresources.h"
#include <windows.h>
/*!
\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<ttmath::Big<1,3> > parser1;
ttmath::Parser<ttmath::Big<2,6> > parser2;
ttmath::Parser<ttmath::Big<3,9> > 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<class ValueType>
void PrintResult(ttmath::Parser<ValueType> & matparser)
{
std::string result, part;
unsigned int i = 0;
for(i=0 ; i<matparser.stack.size() ; ++i)
{
if( matparser.stack[i].value.ToString(part,base_output, always_scientific, when_scientific, rounding) )
{
// we shouldn't have this error in the new version of ToStrign(...)
// (it could be if were using very big mantissa and exponent
// in the Big type)
//
// look at this: part.erase()
//
// we're using it because it's something wrong on gcc
// when we're compiling with -O3 optimization flag
//
// gcc version 3.4.2 (mingw-special) with -O3
// program tell us if there was an error here (from ToString())
// but in fact it shouldn't have been here
// I don't know where is the problem (I think in optimization,
// with -O1 and -O2 program works well and visual express works perfectly
// as well)
part.erase();
// we can omit this part.erase() and use operator+= instead of
// operator= below, for example:
// part += GetPrgRes()->GetLanguages()->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

626
src/programresources.cpp Normal file
View File

@ -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<buffer_len-1 && IsDecDigit(*pchar) ; ++i, ++pchar)
buffer[i] = *pchar;
buffer[i] = 0;
*param = atoi(buffer);
if(*param < 0)
*param = 0;
else
if(*param > 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, &reg_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<BYTE*>(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, &param) )
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;
}

292
src/programresources.h Normal file
View File

@ -0,0 +1,292 @@
#ifndef headerfileprogramresources
#define headerfileprogramresources
/*!
\file programresources.h
\brief various kinds of objects using by the application
*/
#include <ttmath/ttmathobjects.h>
#include "iniparser.h"
#include "languages.h"
#include "threadcontroller.h"
#include <string>
#include <windows.h>
/*!
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

139
src/resource.h Normal file
View File

@ -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

188
src/resource.rc Normal file
View File

@ -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"

122
src/stopcalculating.h Normal file
View File

@ -0,0 +1,122 @@
#ifndef headerfilestopcalculating
#define headerfilestopcalculating
/*!
\file stopcalculating.h
\brief it tells us whether there was a stop signal or not
*/
#include <ttmath/ttmathtypes.h>
#include <windows.h>
/*!
\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

991
src/tabs.cpp Normal file
View File

@ -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<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_variables_header_1) );
ListView_SetColumn(list,0,&column);
column.mask = LVCF_TEXT;
column.pszText = const_cast<char*>( 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<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_1) );
ListView_SetColumn(list,0,&column);
column.mask = LVCF_TEXT;
column.pszText = const_cast<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_2) );
ListView_SetColumn(list,1,&column);
column.mask = LVCF_TEXT;
column.pszText = const_cast<char*>( 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<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::tab_standard) );
TabCtrl_SetItem(hTab,tab_standard, &tab);
tab.pszText = const_cast<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::tab_variables) );
TabCtrl_SetItem(hTab,tab_variables, &tab);
tab.pszText = const_cast<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::tab_functions) );
TabCtrl_SetItem(hTab,tab_functions, &tab);
tab.pszText = const_cast<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::tab_precision) );
TabCtrl_SetItem(hTab,tab_precision, &tab);
tab.pszText = const_cast<char*>( 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<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_variables_header_1) );
ListView_InsertColumn(list, 0, &column);
column.cx = list_cx - 60 - 10;
column.pszText = const_cast<char*>( 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<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_1) );
ListView_InsertColumn(list, 0, &column);
column.cx = 40;
column.pszText = const_cast<char*>( GetPrgRes()->GetLanguages()->GuiMessage(Languages::list_functions_header_2) );
ListView_InsertColumn(list, 1, &column);
column.cx = list_cx - 60 - 40 - 10;
column.pszText = const_cast<char*>( 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

66
src/tabs.h Normal file
View File

@ -0,0 +1,66 @@
#ifndef headerfiletabs
#define headerfiletabs
#include <windows.h>
#include <commctrl.h>
#include <string>
#include <memory>
#include "resource.h"
#include "messages.h"
#include <ttmath/ttmathtypes.h>
#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

215
src/threadcontroller.h Normal file
View File

@ -0,0 +1,215 @@
#ifndef headerfilethreadcontroller
#define headerfilethreadcontroller
/*!
\file threadcontroller.h
\brief class ThreadController manages our two threads
*/
#include <ttmath/ttmathobjects.h>
#include <windows.h>
#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

270
src/variables.cpp Normal file
View File

@ -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<char*>( name.c_str() );
item.iSubItem = 0;
int id = ListView_InsertItem(list, &item);
ListView_SetItemText(list,id,1,const_cast<char*>( 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<char*>( 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

113
src/winmain.cpp Normal file
View File

@ -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<int>( 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 ; i<GetPrgRes()->HowManyTabWindows() && !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);
}

34
src/winmain.h Normal file
View File

@ -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 <windows.h>
#include <commctrl.h>
#include <process.h>
#include <map>
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