ttcalc/src/programresources.cpp

878 lines
17 KiB
C++

/*
* This file is a part of TTCalc - a mathematical calculator
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* Copyright (c) 2006-2009, 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.
*/
#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, true);
else
MoveWindow(main_window, x_pos, y_pos, x_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 < -1 )
r = -1;
if( r > 99 )
r = 99;
display_rounding = r;
}
int ProgramResources::GetDisplayRounding()
{
return display_rounding;
}
void ProgramResources::SetRemovingZeroes(bool r)
{
remove_zeroes = r;
}
bool ProgramResources::GetRemovingZeroes()
{
return remove_zeroes;
}
void ProgramResources::SetDegRadGrad(int angle)
{
if( angle < 0 || angle > 2 )
angle = 1;
angle_deg_rad_grad = angle;
}
int ProgramResources::GetDegRadGrad()
{
return angle_deg_rad_grad;
}
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;
}
void ProgramResources::SetDecimalPoint(int decimal)
{
decimal_point = decimal;
if( decimal_point<0 || decimal_point>1 )
decimal_point = 0;
}
int ProgramResources::GetDecimalPoint()
{
return decimal_point;
}
//
ttmath::Objects * ProgramResources::GetVariables()
{
return &variables;
}
ttmath::Objects * ProgramResources::GetFunctions()
{
return &functions;
}
void ProgramResources::VariablesChanged()
{
++variables_id;
}
void ProgramResources::FunctionsChanged()
{
++functions_id;
}
int ProgramResources::GetVariablesId()
{
return variables_id;
}
int ProgramResources::GetFunctionsId()
{
return functions_id;
}
Languages * ProgramResources::GetLanguages()
{
return &languages;
}
Convert * ProgramResources::GetConvert()
{
return &convert;
}
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()
{
// if you want to change the input buffer you have also to change
// ParserManager::ParserManager() : buffer_len(2048) in parsermanager.cpp
buffer_size = 2048;
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 = 8;
display_rounding = -1;
remove_zeroes = true;
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;
// !!! put into Convert constructor
#ifdef TTCALC_CONVERT
convert.Init();
#endif
decimal_point = 0;
angle_deg_rad_grad = 1; // rad is default
variables_id = 0;
functions_id = 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::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";
// if there'll be an error we assume that the current directory will be used
// (in the portable version the configuration file is in a current directory)
configuration_file = std::string(".\\") + simple_file_name;
#ifndef TTCALC_PORTABLE
static const char simple_directory_name[] = "TTCalc";
std::string application_data;
// we're trying to read the value "AppData" from registry
// which can be, for instance, as:
// "C:\Documents and Settings\user\data application" on WinNT
// or "C:\Windows\Data Application\" on Win9x
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 have to remember the currect directory
// (because we're using it when we're opening the help)
char * buffer = new char[_MAX_PATH];
if( GetCurrentDirectory(_MAX_PATH, buffer) )
{
// we're testing whether we've got our directory or not
if( SetCurrentDirectory( application_directory.c_str() ) )
success = true;
else
// now we must create our directory inside it
if( CreateDirectory(application_directory.c_str(), 0) )
success = true;
if( success )
configuration_file = application_directory + '\\' + simple_file_name;
SetCurrentDirectory(buffer);
}
delete [] buffer;
}
#endif
}
void ProgramResources::CheckCoordinates()
{
if( x_pos < -50 )
x_pos = 0;
if( y_pos < -50 )
y_pos = 0;
if( x_size < 100 )
x_size = 100;
if( y_size < 30 )
y_size = 30;
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
if( x_size > cx+10 )
x_size = cx;
if( y_size > cy+10 )
y_size = cy;
if( x_pos > cx-50 )
x_pos = cx - x_size;
if( y_pos > cy-50 )
y_pos = cy - y_size;
}
void ProgramResources::AddVariablesFunctions( IniParser::Section & temp_variables,
IniParser::Section & temp_functions,
bool if_not_exist)
{
IniParser::Section::iterator ic;
// we're adding variables
if( !if_not_exist )
{
variables.Clear();
VariablesChanged();
}
for( ic = temp_variables.begin() ; ic!=temp_variables.end() ; ++ic )
if( !if_not_exist || !variables.IsDefined(ic->first) )
{
variables.Add(ic->first, ic->second);
VariablesChanged();
}
// we're adding functions
if( !if_not_exist )
{
functions.Clear();
FunctionsChanged();
}
for( ic = temp_functions.begin() ; ic!=temp_functions.end() ; ++ic )
{
const char * name;
int param;
if( !if_not_exist || !functions.IsDefined(ic->first) )
if( SplitFunction(ic->second, &name, &param) )
{
functions.Add(ic->first, name, param);
FunctionsChanged();
}
}
}
IniParser::Error ProgramResources::ReadVariablesFunctionsFromFile()
{
IniParser iparser;
IniParser::Section temp_variables, temp_functions;
iparser.ConvertValueToSmallLetters(false);
iparser.SectionCaseSensitive(false);
// we have variables and functions case-sensitive
iparser.PatternCaseSensitive(true);
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;
AddVariablesFunctions(temp_variables, temp_functions, true);
if( err != IniParser::err_ok )
bad_line = iparser.GetBadLine();
return err;
}
IniParser::Error ProgramResources::ReadFromFile()
{
IniParser iparser;
IniParser::Section temp_variables, temp_functions;
IniParser::Section::iterator ic;
std::string ini_value[20];
iparser.ConvertValueToSmallLetters(false);
iparser.SectionCaseSensitive(false);
// we have variables and functions case-sensitive
iparser.PatternCaseSensitive(true);
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( "global|size.y", &ini_value[12] );
iparser.Associate( "global|language", &ini_value[13] );
iparser.Associate( "global|disp.dec.point", &ini_value[14] );
iparser.Associate( "global|disp.remove.zeroes", &ini_value[15] );
iparser.Associate( "global|disp.deg_rad_grad", &ini_value[16] );
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;
AddVariablesFunctions(temp_variables, temp_functions, false);
// 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() );
y_size = atoi( ini_value[12].c_str() );
CheckCoordinates();
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()) );
SetRemovingZeroes( bool(atoi(ini_value[15].c_str())) );
if( ini_value[13] == "2" )
languages.SetCurrentLanguage(Languages::sp);
else
if( ini_value[13] == "1" )
languages.SetCurrentLanguage(Languages::pl);
else
languages.SetCurrentLanguage(Languages::en);
SetDecimalPoint( atoi(ini_value[14].c_str()) );
SetDegRadGrad( atoi(ini_value[16].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 << "size.y = " << y_size << std::endl;
file << "precision = " << precision << std::endl;
file << "disp.input = " << base_input << std::endl;
file << "disp.output = " << base_output << std::endl;
file << "language = " << static_cast<int>(languages.GetCurrentLanguage())
<< 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 << "disp.remove.zeroes = " << (int)remove_zeroes << std::endl;
file << "disp.dec.point = " << decimal_point << std::endl;
file << "disp.deg_rad_grad = " << angle_deg_rad_grad << std::endl;
file << "\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[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;
}