diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:44:25 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:44:25 +0200 |
commit | c63d9b438572f06f555e2232a15bd3c46bd10546 (patch) | |
tree | 92f2eca00f2a915078ee979acf26906670d75e5f | |
download | FreeFileSync-c63d9b438572f06f555e2232a15bd3c46bd10546.tar.gz FreeFileSync-c63d9b438572f06f555e2232a15bd3c46bd10546.tar.bz2 FreeFileSync-c63d9b438572f06f555e2232a15bd3c46bd10546.zip |
1.2
35 files changed, 14121 insertions, 0 deletions
diff --git a/Application.cpp b/Application.cpp new file mode 100644 index 00000000..1ce4739e --- /dev/null +++ b/Application.cpp @@ -0,0 +1,624 @@ +/*************************************************************** + * Name: FreeFileSyncApp.cpp + * Purpose: Code for Application Class + * Author: ZenJu (zhnmju123@gmx.de) + * Created: 2008-07-16 + * Copyright: ZenJu () + * License: + **************************************************************/ + +#include "Application.h" +#include "UI\MainDialog.h" +#include <wx/stdpaths.h> +#include <wx/filename.h> +#include <stdexcept> //for std::runtime_error +#include <wx/wfstream.h> +#include <wx/zipstrm.h> +#include "library\globalFunctions.h" + +IMPLEMENT_APP(Application); + +bool Application::ProcessIdle() +{ + static bool firstExecution = true; + + if (firstExecution) + { + firstExecution = false; + initialize(); //here the program initialization takes place + } + return wxApp::ProcessIdle(); +} + +//Note: initialization is done in the FIRST idle event instead in OnInit. Reason: Commandline mode requires the wxApp eventhandler to be established +//for UI update events. This is not given in OnInit. + +bool Application::OnInit() +{ + returnValue = 0; + //do not call wxApp::OnInit() to avoid parsing commandline now but use own parser later + return true; +} + + +void Application::initialize() +{ + //set working directory to current executable directory + if (!wxSetWorkingDirectory(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath())) + throw runtime_error(_("Could not set working directory to directory containing executable file!")); + + //set program language + programLanguage = new CustomLocale; + + //activate support for .png files + wxImage::AddHandler(new wxPNGHandler); + + //load icon and animation resources (also needed for commandline: status dialog, error dialog + GlobalResources::loadResourceFiles(); + + if (parsedCommandline()) //Note: "return false" is a must here for commandline usage with "-silent" since program crashes if "return true" and no windows have been created + if (applicationRunsOnCommandLineWithoutWindows) + { + ExitMainLoop(); //exit programm on next main loop iteration + return; + } + else + return; //wait for the user to close the status window + + //show UI dialog + MainDialog* frame = new MainDialog(0L); + frame->SetIcon(wxICON(aaaa)); // To Set App Icon + + frame->Show(); +} + + +int Application::OnRun() +{ + try + { + wxApp::OnRun(); + } + catch (std::runtime_error& theException) //catch runtime errors during main event loop + { + wxMessageBox(_(theException.what()), _("An exception occured!"), wxOK | wxICON_ERROR); + return -1; + } + return returnValue; +} + + +int Application::OnExit() +{ + delete programLanguage; + GlobalResources::unloadResourceFiles(); + return 0; +} + + +SyncDirection convertCmdlineCfg(const wxString& cfg, const int i) +{ + assert (cfg.Len() == 5); + assert (0 <= i <= 4); + + switch (cfg[i]) + { + case 'L': + return SyncDirLeft; + break; + case 'R': + return SyncDirRight; + break; + case 'N': + return SyncDirNone; + break; + default: + assert(false); + } + //dummy return value to suppress compiler warning + return SyncDirNone; +} + + +void Application::initLog() +{ + wxString tmp = wxDateTime::Now().FormatISOTime(); + tmp.Replace(":", ""); + wxString logfileName = wxString("FFS_") + wxDateTime::Now().FormatISODate() + '_' + tmp + ".log"; + + logFile.open(logfileName.c_str()); + if (!logFile) + throw std::runtime_error(_("Unable to create logfile!")); + logFile<<_("FreeFileSync (Date: ") + wxDateTime::Now().FormatDate() + _(" Time: ") + wxDateTime::Now().FormatTime() + ")"<<endl; + logFile<<_("-------------------------------------------------")<<endl; + logFile<<endl; + logFile<<_("Log-messages:")<<endl; + logFile<<endl; +} + + +void Application::writeLog(const wxString& logText, const wxString& problemType) +{ + if (problemType != wxEmptyString) + logFile<<problemType<<": "; + logFile<<logText<<endl; +} + + +void Application::closeLog() +{ + logFile.close(); +} + + +bool Application::parsedCommandline() +{ + //commandline-descriptor must be initialized here AFTER the program language is set + const wxCmdLineEntryDesc cmdLineDesc [] = + { + { wxCMD_LINE_SWITCH, + wxT("h"), + wxT("help"), + wxT(_("Displays help on the command line parameters\n")), + wxCMD_LINE_VAL_NONE, + wxCMD_LINE_OPTION_HELP + }, + + { + wxCMD_LINE_OPTION, + "cmp", + NULL, + _("Specify algorithm to test if files are equal:\n\n\t\tSIZEDATE: check filesize and date\n\t\tCONTENT: check file content\n"), + wxCMD_LINE_VAL_STRING, + wxCMD_LINE_OPTION_MANDATORY + }, + + { + wxCMD_LINE_OPTION, + "cfg", + NULL, + _("Specify the sync-direction used for each type of file by a string of five chars:\n\n\t\tChar 1: Folders/files that exist on left side only\n\t\tChar 2: Folders/files that exist on right side only\n\t\tChar 3: Files that exist on both sides, left one is newer\n\t\tChar 4: Files that exist on both sides, right one is newer\n\t\tChar 5: Files that exist on both sides and are different\n\n\t\tSync-direction: L: left, R: right, N: none\n"), + wxCMD_LINE_VAL_STRING, + wxCMD_LINE_OPTION_MANDATORY + }, + + { + wxCMD_LINE_PARAM, + NULL, + NULL, + _("<left directory>"), + wxCMD_LINE_VAL_STRING + }, + + { + wxCMD_LINE_PARAM, + NULL, + NULL, + _("<right directory>"), + wxCMD_LINE_VAL_STRING + }, + + { + wxCMD_LINE_OPTION, + "incl", + NULL, + _("Specify names to be included separated by ';'. Wildcards '*' and '?' are supported. Default: \"*\"\n"), + wxCMD_LINE_VAL_STRING, + }, + + { + wxCMD_LINE_OPTION, + "excl", + NULL, + _("Specify names to be excluded separated by ';'. Wildcards '*' and '?' are supported. Default: \"\"\n"), + wxCMD_LINE_VAL_STRING, + }, + + { + wxCMD_LINE_SWITCH, + "skiperrors", + NULL, + _("If errors occur during folder comparison or synchronization they are ignored and the process continues.\n") + }, + + { + wxCMD_LINE_SWITCH, + "silent", + NULL, + _("\tDo not show UI messages but write to a logfile instead\n\nExamples:\n\n1.) FreeFileSync -cmp SIZEDATE -cfg RRRRR C:\\Source C:\\Target\n2.) FreeFileSync -cmp sizedate -cfg rlrln c:\\dir1 c:\\dir2 -incl *.doc\n\n1: Creates a mirror backup of the left directory\n2: Synchronizes all *.doc files from both directories simultaneously\n\n") + }, + + { + wxCMD_LINE_NONE + } + }; + + + if (argc <= 1) + return false; //no parameters passed, continue with UI + + //now set the parser with all MANDATORY options and parameters + wxCmdLineParser parser(cmdLineDesc, argc, argv); + parser.SetSwitchChars(wxT("-")); + if (parser.Parse() != 0) //if commandline is used incorrectly display help dialog and exit program + return true; + + //commandline parameters + wxString cmp; + wxString cfg; + wxString leftDir; + wxString rightDir; + wxString included; + wxString excluded; + bool skipErrors = parser.Found("skiperrors"); + bool silent = parser.Found("silent"); + + applicationRunsOnCommandLineWithoutWindows = silent; //this value is needed for the application to decide whether to wait for windows to close or not + + +//check existence of all commandline parameters + if (!parser.Found("cmp", &cmp) || + !parser.Found("cfg", &cfg) || + parser.GetParamCount() != 2) + { + parser.Usage(); + return true; + } + + cmp.UpperCase(); + cfg.UpperCase(); + leftDir = parser.GetParam(0); + rightDir = parser.GetParam(1); + +//evaluate filter settings + bool filteringEnabled = false; + if (parser.Found("incl", &included)) + filteringEnabled = true; + else + included = "*"; + + if (parser.Found("excl", &excluded)) + filteringEnabled = true; + else + excluded = ""; + +//until here all options and parameters have been set +//-------------------------------------------------------------------- + +//check consistency of all commandline parameters + if ((cmp != "SIZEDATE" && cmp != "CONTENT") || + cfg.Len() != 5 || + (cfg[0] != 'L' && cfg[0] != 'R' && cfg[0] != 'N') || + (cfg[1] != 'L' && cfg[1] != 'R' && cfg[1] != 'N') || + (cfg[2] != 'L' && cfg[2] != 'R' && cfg[2] != 'N') || + (cfg[3] != 'L' && cfg[3] != 'R' && cfg[3] != 'N') || + (cfg[4] != 'L' && cfg[4] != 'R' && cfg[4] != 'N')) + { + parser.Usage(); + return true; + } + +//init logfile + if (silent) initLog(); + + wxString logText; + + //check if directories exist + if (!wxDirExists(leftDir)) + { + wxString errorMessage = wxString(_("Directory ")) + leftDir + _(" does not exist. \n\nSynchronization aborted!"); + if (silent) writeLog(errorMessage, _("Warning")); + if (silent) closeLog(); + else wxMessageBox(errorMessage, _("Warning"), wxICON_WARNING); + + returnValue = -2; + return true; + } + else if (!wxDirExists(rightDir)) + { + wxString errorMessage = wxString(_("Directory ")) + rightDir + _(" does not exist. \n\nSynchronization aborted!"); + if (silent) writeLog(errorMessage, _("Warning")); + if (silent) closeLog(); + else wxMessageBox(errorMessage, _("Warning"), wxICON_WARNING); + + returnValue = -2; + return true; + } + +//until here all options and parameters are consistent +//-------------------------------------------------------------------- + + CompareVariant cmpVar = CompareByMD5; //dummy value to suppress compiler warning + SyncConfiguration syncConfiguration; + FileCompareResult currentGridData; + + if (cmp == "SIZEDATE") + cmpVar = CompareByTimeAndSize; + else if (cmp == "CONTENT") + cmpVar = CompareByMD5; + else + assert (false); + + syncConfiguration.exLeftSideOnly = convertCmdlineCfg(cfg, 0); + syncConfiguration.exRightSideOnly = convertCmdlineCfg(cfg, 1); + syncConfiguration.leftNewer = convertCmdlineCfg(cfg, 2); + syncConfiguration.rightNewer = convertCmdlineCfg(cfg, 3); + syncConfiguration.different = convertCmdlineCfg(cfg, 4); + + //class handling status updates and error messages + CommandLineStatusUpdater statusUpdater(this, skipErrors, silent); + + //begin of synchronization process (all in one try-catch block) + try + { +//COMPARE DIRECTORIES + //unsigned int startTime = GetTickCount(); + FreeFileSync::getModelDiff(currentGridData, + FreeFileSync::getFormattedDirectoryName(leftDir), + FreeFileSync::getFormattedDirectoryName(rightDir), + cmpVar, + &statusUpdater); + //wxMessageBox(wxString::Format(wxT("%i"), unsigned(GetTickCount()) - startTime)); + + //check if folders are already in sync + bool nothingToSync = true; + for (FileCompareResult::const_iterator i = currentGridData.begin(); i != currentGridData.end(); ++i) + if (i->cmpResult != FilesEqual) + { + nothingToSync = false; + break; + } + + if (nothingToSync) + { + wxString errorMessage = _("Nothing to synchronize. Both directories seem to contain the same data!"); + if (silent) writeLog("\n"); + if (silent) writeLog(errorMessage); + if (silent) closeLog(); + else statusUpdater.updateFinalStatus(errorMessage); + + returnValue = -3; + return true; + } + +//APPLY FILTERS + if (filteringEnabled) + FreeFileSync::filterCurrentGridData(currentGridData, included, excluded); + +//START SYNCHRONIZATION + //adjust progress indicator + statusUpdater.switchToSyncProcess(FreeFileSync::calcTotalBytesToTransfer(currentGridData, syncConfiguration).get_d()); + + //unsigned int startTime = GetTickCount(); + FreeFileSync::startSynchronizationProcess(currentGridData, syncConfiguration, &statusUpdater, false); //default: do not use recycle bin since it's not sure if its possible + //wxMessageBox(wxString::Format(wxT("%i"), unsigned(GetTickCount()) - startTime)); + +//show success message + wxString successMessage = _("Synchronization completed!"); + if (silent) writeLog("\n"); + if (silent) writeLog(successMessage); + if (silent) closeLog(); + else + statusUpdater.updateFinalStatus(successMessage); + + } + catch (AbortThisProcess& theException) //exit used by statusUpdater + { + if (silent) writeLog("\n\nSynchronization aborted!"); + if (silent) closeLog(); + + returnValue = -4; + return true; + } + + return true; //exit program and skip UI dialogs +} +//###################################################################################################### + + +CommandLineStatusUpdater::CommandLineStatusUpdater(Application* application, bool skipErr, bool silent) : + app(application), + skipErrors(skipErr), + silentMode(silent), + switchedToSynchronisation(false) //used for changing mode of gauge +{ + if (!silentMode) + { + syncStatusFrame = new SyncStatus(this, 0); + syncStatusFrame->Show(); + } +} + +CommandLineStatusUpdater::~CommandLineStatusUpdater() +{ + if (!silentMode) + { + if (abortionRequested) + syncStatusFrame->processHasFinished(_("Aborted!")); //enable okay and close events + else + syncStatusFrame->processHasFinished(_("Completed")); + + //print the results list + unsigned int failedItems = unhandledErrors.GetCount(); + wxString result; + if (failedItems) + { + result = wxString(_("Warning: Synchronization failed for ")) + GlobalFunctions::numberToWxString(failedItems) + _(" item(s):\n\n"); + for (unsigned int j = 0; j < failedItems; ++j) + result+= unhandledErrors[j] + "\n"; + } + syncStatusFrame->setStatusText_NoUpdate(result); + syncStatusFrame->updateStatusDialogNow(); + } +} + +inline +void CommandLineStatusUpdater::updateStatus(const wxString& text) +{ + + if (!silentMode) + syncStatusFrame->setStatusText_NoUpdate(text); +} + + +inline +void CommandLineStatusUpdater::updateProgressIndicator(double number) +{ + if (!silentMode) + { + if (switchedToSynchronisation) + syncStatusFrame->incProgressIndicator_NoUpdate(number); + else + syncStatusFrame->m_gauge1->Pulse(); + } +} + + +int CommandLineStatusUpdater::reportError(const wxString& text) +{ + if (silentMode) //write error message log and abort the complete session + { + app->writeLog(text, _("Error")); + + if (skipErrors) // <- /|\ before return, the logfile is written!!! + return StatusUpdater::Continue; + else + { + abortionRequested = true; + throw AbortThisProcess(); + } + + } + else //show dialog to user who can decide how to continue + { + if (skipErrors) //this option can be set from commandline or by the user in the error dialog on UI + { + unhandledErrors.Add(text); + return StatusUpdater::Continue; + } + + wxString errorMessage = text + _("\n\nContinue with next object, retry or abort synchronization?"); + + ErrorDlg* errorDlg = new ErrorDlg(errorMessage, skipErrors); + + int rv = errorDlg->ShowModal(); + errorDlg->Destroy(); + + switch (rv) + { + case ErrorDlg::ContinueButtonPressed: + unhandledErrors.Add(text); + return StatusUpdater::Continue; + case ErrorDlg::RetryButtonPressed: + return StatusUpdater::Retry; + case ErrorDlg::AbortButtonPressed: + { + unhandledErrors.Add(text); + abortionRequested = true; + throw AbortThisProcess(); + } + default: + assert (false); + } + } + + return StatusUpdater::Continue; //dummy return value +} + + +inline +void CommandLineStatusUpdater::triggerUI_Refresh() +{ + if (abortionRequested) throw AbortThisProcess(); + + if (!silentMode) + if (updateUI_IsAllowed()) //test if specific time span between ui updates is over + syncStatusFrame->updateStatusDialogNow(); +} + + +inline +void CommandLineStatusUpdater::updateFinalStatus(const wxString& text) //set by parsedCommandline() to communicate e.g. the final "success message" +{ + if (!silentMode) + syncStatusFrame->m_textCtrlInfo->SetValue(text); +} + + +inline +void CommandLineStatusUpdater::switchToSyncProcess(double number) +{ + if (!silentMode) + { + syncStatusFrame->resetGauge(number); //usually this number is set in SyncStatus constructor, but in case of commandline + //the total number is known only ofter "compare" so it has to be set later + switchedToSynchronisation = true; + } +} + +//###################################################################################################### + + +wxString exchangeEscapeChars(char* temp) +{ + wxString output(temp); + output.Replace("\\\\", "\\"); + output.Replace("\\n", "\n"); + output.Replace("\\t", "\t"); + output.Replace("\"\"", """"); + output.Replace("\\\"", "\""); + return output; +} + + +CustomLocale::CustomLocale(int language, int flags) + :wxLocale(language, flags) +{ + char temp[100000]; +// wxString languageFile; +// switch (language) +// { +// case wxLANGUAGE_GERMAN: + wxString languageFile = "language.dat"; +// break; +// default: ; +// } + + //load language file into buffer + if (languageFile.size() != 0) + { + ifstream langFile(languageFile.c_str()); + if (langFile) + { + int rowNumber = 0; + TranslationLine currentLine; + while (langFile.getline(temp, 100000)) + { + if (rowNumber%2 == 0) + currentLine.original = exchangeEscapeChars(temp); + else + { + currentLine.translation = exchangeEscapeChars(temp); + translationDB.insert(currentLine); + } + rowNumber++; + } + langFile.close(); + } + } +} + + +const wxChar* CustomLocale::GetString(const wxChar* szOrigString, const wxChar* szDomain) const +{ + TranslationLine currentLine; + currentLine.original = szOrigString; + + //look for translation in buffer table + Translation::iterator i; + if ((i = translationDB.find(currentLine)) != translationDB.end()) + return (i->translation.c_str()); + //fallback + return (szOrigString); +} + diff --git a/Application.h b/Application.h new file mode 100644 index 00000000..362f8269 --- /dev/null +++ b/Application.h @@ -0,0 +1,112 @@ +/*************************************************************** + * Name: FreeFileSyncApp.h + * Purpose: Defines Application Class + * Author: ZenJu (zhnmju123@gmx.de) + * Created: 2008-07-16 + * Copyright: ZenJu () + * License: + **************************************************************/ + +#ifndef FREEFILESYNCAPP_H +#define FREEFILESYNCAPP_H + +#include <wx/app.h> +#include <wx/cmdline.h> +#include <set> +#include <fstream> +#include "FreeFileSync.h" +#include "ui\SmallDialogs.h" + +struct TranslationLine +{ + wxString original; + wxString translation; + + bool operator>(const TranslationLine& b ) const + { + return (original > b.original); + } + bool operator<(const TranslationLine& b) const + { + return (original < b.original); + } + bool operator==(const TranslationLine& b) const + { + return (original == b.original); + } +}; + +typedef set<TranslationLine> Translation; + + +class CustomLocale : public wxLocale +{ +public: + CustomLocale(int language = wxLANGUAGE_ENGLISH, + int flags = wxLOCALE_LOAD_DEFAULT | wxLOCALE_CONV_ENCODING); + + ~CustomLocale() {} + + const wxChar* GetString(const wxChar* szOrigString, const wxChar* szDomain = NULL) const; + +private: + Translation translationDB; +}; + + +class Application : public wxApp +{ +public: + bool OnInit(); + int OnRun(); + int OnExit(); + + void initialize(); + bool ProcessIdle(); //virtual method + + friend class CommandLineStatusUpdate; + + //methods for writing logs + void initLog(); + void writeLog(const wxString& logText, const wxString& problemType = wxEmptyString); + void closeLog(); + +private: + bool parsedCommandline(); + + bool applicationRunsOnCommandLineWithoutWindows; + + ofstream logFile; + CustomLocale* programLanguage; + + int returnValue; +}; + + +class CommandLineStatusUpdater : public StatusUpdater +{ +public: + CommandLineStatusUpdater(Application* application, bool skipErr, bool silent); + ~CommandLineStatusUpdater(); + + void updateStatus(const wxString& text); + void updateProgressIndicator(double number); + int reportError(const wxString& text); + + void triggerUI_Refresh(); + + void switchToSyncProcess(double number); + void updateFinalStatus(const wxString& text); + +private: + Application* app; + SyncStatus* syncStatusFrame; + bool skipErrors; + bool silentMode; + + bool switchedToSynchronisation; + wxArrayString unhandledErrors; //list of non-resolved errors +}; + + +#endif // FREEFILESYNCAPP_H diff --git a/COMPILE.cmd b/COMPILE.cmd new file mode 100644 index 00000000..f43e171a --- /dev/null +++ b/COMPILE.cmd @@ -0,0 +1,16 @@ +set widgets=C:\Programme\CodeBlocks\wxWidgets +set sources=C:\Programme\CodeBlocks\Projects\FreeFileSync + +mingw32-g++.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\Application.cpp -o obj\Release\Application.o +mingw32-g++.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\FreeFileSync.cpp -o obj\Release\FreeFileSync.o +mingw32-g++.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\Library\globalFunctions.cpp -o obj\Release\Library\globalFunctions.o +mingw32-g++.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\UI\GUI_Generated.cpp -o obj\Release\UI\GUI_Generated.o +mingw32-g++.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\UI\MainDialog.cpp -o obj\Release\UI\MainDialog.o +mingw32-g++.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\UI\SyncDialog.cpp -o obj\Release\UI\SyncDialog.o +mingw32-g++.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\library\CustomGrid.cpp -o obj\Release\library\CustomGrid.o +mingw32-g++.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\ui\Resources.cpp -o obj\Release\ui\Resources.o +mingw32-g++.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\ui\SmallDialogs.cpp -o obj\Release\ui\SmallDialogs.o +windres.exe -i %sources%\resource.rc -J rc -o obj\Release\resource.res -O coff -I%widgets%\include -I%widgets%\lib\gcc_lib\msw +mingw32-gcc.exe -Wall -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -O2 -DNDEBUG -I%widgets%\wxWidgets\include -I%widgets%\contrib\include -I%widgets%\lib\gcc_lib\msw -c %sources%\Library\md5.c -o obj\Release\Library\md5.o +mingw32-g++.exe -L%widgets%\lib\gcc_lib -o FreeFileSync.exe obj\Release\Application.o obj\Release\FreeFileSync.o obj\Release\Library\globalFunctions.o obj\Release\Library\md5.o obj\Release\UI\GUI_Generated.o obj\Release\UI\MainDialog.o obj\Release\UI\SyncDialog.o obj\Release\library\CustomGrid.o obj\Release\ui\Resources.o obj\Release\ui\SmallDialogs.o obj\Release\resource.res -s -mthreads -lwxmsw28_adv -lwxmsw28_core -lwxbase28 -lwxpng -lwxzlib -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lcomctl32 -lwsock32 -lodbc32 Library\GMP\lib\libgmpxx.a Library\GMP\lib\libgmp.a -mwindows +pause
\ No newline at end of file diff --git a/FreeFileSync.cbp b/FreeFileSync.cbp new file mode 100644 index 00000000..66270622 --- /dev/null +++ b/FreeFileSync.cbp @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="FreeFileSync" /> + <Option pch_mode="2" /> + <Option compiler="gcc" /> + <Build> + <Target title="Debug"> + <Option output="FreeFileSync" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj\Debug\" /> + <Option type="0" /> + <Option compiler="gcc" /> + <Option projectLinkerOptionsRelation="2" /> + <Compiler> + <Add option="-g" /> + <Add option="-D__WXDEBUG__" /> + <Add directory="C:\Programme\CodeBlocks\wxWidgets\lib\gcc_lib\mswd" /> + </Compiler> + <ResourceCompiler> + <Add directory="C:\Programme\CodeBlocks\wxWidgets\lib\gcc_lib\mswd" /> + </ResourceCompiler> + <Linker> + <Add library="libwxmsw28d_adv.a" /> + <Add library="libwxmsw28d_core.a" /> + <Add library="libwxbase28d.a" /> + <Add library="libwxpngd.a" /> + <Add library="libwxzlibd.a" /> + <Add directory="C:\Programme\CodeBlocks\wxWidgets\lib\gcc_lib" /> + </Linker> + </Target> + <Target title="Release"> + <Option output="FreeFileSync" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj\Release\" /> + <Option type="0" /> + <Option compiler="gcc" /> + <Option projectLinkerOptionsRelation="2" /> + <Compiler> + <Add option="-O2" /> + <Add option="-DNDEBUG" /> + <Add directory="C:\Programme\CodeBlocks\wxWidgets\lib\gcc_lib\msw" /> + </Compiler> + <ResourceCompiler> + <Add directory="C:\Programme\CodeBlocks\wxWidgets\lib\gcc_lib\msw" /> + </ResourceCompiler> + <Linker> + <Add option="-s" /> + <Add library="libwxmsw28_adv.a" /> + <Add library="libwxmsw28_core.a" /> + <Add library="libwxbase28.a" /> + <Add library="libwxpng.a" /> + <Add library="libwxzlib.a" /> + <Add directory="C:\Programme\CodeBlocks\wxWidgets\lib\gcc_lib" /> + </Linker> + </Target> + </Build> + <Compiler> + <Add option="-Wall" /> + <Add option="-pipe" /> + <Add option="-mthreads" /> + <Add option='[[if (PLATFORM == PLATFORM_MSW && (GetCompilerFactory().GetCompilerVersionString(_T("gcc")) >= _T("4.0.0"))) print(_T("-Wno-attributes"));]]' /> + <Add option="-D__GNUWIN32__" /> + <Add option="-D__WXMSW__" /> + <Add directory="C:\Programme\CodeBlocks\wxWidgets\include" /> + <Add directory="C:\Programme\CodeBlocks\wxWidgets\contrib\include" /> + </Compiler> + <ResourceCompiler> + <Add directory="C:\Programme\CodeBlocks\wxWidgets\include" /> + </ResourceCompiler> + <Linker> + <Add option="-mthreads" /> + <Add library="libkernel32.a" /> + <Add library="libuser32.a" /> + <Add library="libgdi32.a" /> + <Add library="libwinspool.a" /> + <Add library="libcomdlg32.a" /> + <Add library="libadvapi32.a" /> + <Add library="libshell32.a" /> + <Add library="libole32.a" /> + <Add library="liboleaut32.a" /> + <Add library="libuuid.a" /> + <Add library="libcomctl32.a" /> + <Add library="libwsock32.a" /> + <Add library="libodbc32.a" /> + <Add library="Library\GMP\lib\libgmpxx.a" /> + <Add library="Library\GMP\lib\libgmp.a" /> + </Linker> + <Unit filename="Application.cpp" /> + <Unit filename="Application.h" /> + <Unit filename="FreeFileSync.cpp" /> + <Unit filename="FreeFileSync.h" /> + <Unit filename="Library\GMP\include\gmp.h" /> + <Unit filename="Library\globalFunctions.cpp" /> + <Unit filename="Library\globalFunctions.h" /> + <Unit filename="Library\md5.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="Library\md5.h" /> + <Unit filename="UI\GUI_Generated.cpp" /> + <Unit filename="UI\GUI_Generated.h" /> + <Unit filename="UI\MainDialog.cpp" /> + <Unit filename="UI\MainDialog.h" /> + <Unit filename="UI\SyncDialog.cpp" /> + <Unit filename="UI\SyncDialog.h" /> + <Unit filename="WxWizFrame.fbp" /> + <Unit filename="library\CustomGrid.cpp" /> + <Unit filename="library\CustomGrid.h" /> + <Unit filename="library\wxWidgets.h" /> + <Unit filename="resource.rc"> + <Option compilerVar="WINDRES" /> + </Unit> + <Unit filename="ui\Resources.cpp" /> + <Unit filename="ui\Resources.h" /> + <Unit filename="ui\SmallDialogs.cpp" /> + <Unit filename="ui\SmallDialogs.h" /> + <Extensions> + <code_completion /> + <envvars /> + <debugger /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/FreeFileSync.cpp b/FreeFileSync.cpp new file mode 100644 index 00000000..6269fd60 --- /dev/null +++ b/FreeFileSync.cpp @@ -0,0 +1,1278 @@ +#include <wx/arrstr.h> +#include <wx/dir.h> +#include <wx/msgdlg.h> +#include "FreeFileSync.h" +#include "library\md5.h" +#include <stdexcept> //for std::runtime_error +#include "library\globalfunctions.h" +#include "library\GMP\include\gmp.h" +#include <wx/filename.h> + +using namespace GlobalFunctions; + +inline +wxString formatTime(unsigned int number) +{ + assert (number < 100); + + if (number <= 9) + { + wxChar result[3]; + + *result = '0'; + result[1] = '0' + number; + result[2] = 0; + + return result; + } + else + { + wxString result; + if (result.Printf(wxT("%d"), number) < 0) + throw std::runtime_error("Error when converting int to wxString"); + return result; + } +} + + +bool filetimeCmpSmallerThan(const FILETIME a,const FILETIME b) +{ + if (a.dwHighDateTime != b.dwHighDateTime) + return (a.dwHighDateTime < b.dwHighDateTime); + else + return (a.dwLowDateTime < b.dwLowDateTime); +} + +bool filetimeCmpEqual(const FILETIME a,const FILETIME b) +{ + if (a.dwHighDateTime == b.dwHighDateTime && a.dwLowDateTime == b.dwLowDateTime) + return (true); + else + return (false); +} + +void FreeFileSync::getFileInformation(FileInfo& output, const wxString& filename) +{ + WIN32_FIND_DATA winFileInfo; + FILETIME localFileTime; + SYSTEMTIME time; + HANDLE fileHandle; + + if ((fileHandle = FindFirstFile(filename.c_str(), &winFileInfo)) == INVALID_HANDLE_VALUE) + throw FileError((wxString(_("Could not retrieve file info for: ")) + "\"" + filename.c_str() + "\"").c_str()); + + FindClose(fileHandle); + + /* if (FileTimeToLocalFileTime( + &winFileInfo.ftCreationTime, // pointer to UTC file time to convert + &localFileTime // pointer to converted file time + ) == 0) + throw std::runtime_error("Error converting FILETIME to local FILETIME"); + + if (FileTimeToSystemTime( + &localFileTime, // pointer to file time to convert + &time // pointer to structure to receive system time + ) == 0) + throw std::runtime_error("Error converting FILETIME to SYSTEMTIME"); + + output.creationTime = numberToString(time.wYear) + "." + + formatTime(time.wMonth) + "." + + formatTime(time.wDay) + " " + + formatTime(time.wHour) + ":" + + formatTime(time.wMinute) + ":" + + formatTime(time.wSecond);*/ + +//***************************************************************************** + if (FileTimeToLocalFileTime( + &winFileInfo.ftLastWriteTime, // pointer to UTC file time to convert + &localFileTime // pointer to converted file time + ) == 0) + throw std::runtime_error(_("Error converting FILETIME to local FILETIME")); + + + if (FileTimeToSystemTime( + &localFileTime, // pointer to file time to convert + &time // pointer to structure to receive system time + ) == 0) + throw std::runtime_error(_("Error converting FILETIME to SYSTEMTIME")); + + output.lastWriteTime = numberToWxString(time.wYear) + "-" + + formatTime(time.wMonth) + "-" + + formatTime(time.wDay) + " " + + formatTime(time.wHour) + ":" + + formatTime(time.wMinute) + ":" + + formatTime(time.wSecond); + + //UTC times + output.lastWriteTimeUTC = winFileInfo.ftLastWriteTime; + + mpz_t largeInt; + mpz_init_set_ui(largeInt, winFileInfo.nFileSizeHigh); + mpz_mul_ui(largeInt, largeInt, 65536); + mpz_mul_ui(largeInt, largeInt, 65536); + mpz_add_ui(largeInt, largeInt, winFileInfo.nFileSizeLow); + output.fileSize = mpz_get_str(0, 10, largeInt); + mpz_clear(largeInt); +} + +wxString FreeFileSync::calculateMD5Hash(const wxString& filename) +{ + const unsigned int bufferSize = 4096; + + char md5_output[33]; + unsigned char signature[16]; + unsigned char buffer[bufferSize]; + md5_t state; + + md5_init(&state); + FILE* inputFile = fopen( filename.c_str(), "rb"); + if (!inputFile) + throw FileError((wxString(_("Could not open file: ")) + "\"" + filename + "\"").c_str()); + do + { + unsigned int length = fread(buffer, 1, bufferSize, inputFile); + if (!ferror(inputFile)) md5_process(&state, buffer, length); + } + while (!feof(inputFile)); + + fclose(inputFile); + + md5_finish(&state, signature); + + for (int i=0;i<16;i++) sprintf(md5_output + i*2, "%02x", signature[i]); + + return md5_output; +} + + +void FreeFileSync::generateFileAndFolderDescriptions(DirectoryDescrType& output, const wxString& directory, StatusUpdater* updateClass) +{ + assert (updateClass); + + output.clear(); + + //get all files and folders from directory (and subdirectories) + information + GetAllFilesFull traverser(output, getFormattedDirectoryName(directory), updateClass); + wxDir dir(directory); + dir.Traverse(traverser); +} + + +void FreeFileSync::getModelDiff(FileCompareResult& output, const wxString& dirLeft, const wxString& dirRight, CompareVariant cmpVar, StatusUpdater* updateClass) +{ + assert (updateClass); + + try + { + //retrieve sets of files (with description data) + DirectoryDescrType directoryLeft; + DirectoryDescrType directoryRight; + generateFileAndFolderDescriptions(directoryLeft, dirLeft, updateClass); + generateFileAndFolderDescriptions(directoryRight, dirRight, updateClass); + + FileCompareLine gridLine; + + output.clear(); + + //find files/folders that exist in left file model but not in right model + for (DirectoryDescrType::iterator i = directoryLeft.begin(); i != directoryLeft.end(); i++) + if (directoryRight.find(*i) == directoryRight.end()) + { + gridLine.fileDescrLeft = *i; + gridLine.fileDescrRight = FileDescrLine(); + gridLine.fileDescrRight.directory = dirRight; + gridLine.cmpResult = FileOnLeftSideOnly; + output.push_back(gridLine); + } + + for (DirectoryDescrType::iterator j = directoryRight.begin(); j != directoryRight.end(); j++) + { + DirectoryDescrType::iterator i; + + //find files/folders that exist in right file model but not in left model + if ((i = directoryLeft.find(*j)) == directoryLeft.end()) + { + gridLine.fileDescrLeft = FileDescrLine(); + gridLine.fileDescrLeft.directory = dirLeft; + gridLine.fileDescrRight = *j; + gridLine.cmpResult = FileOnRightSideOnly; + output.push_back(gridLine); + } + //find files that exist in left and right file model + else + { //objType != isNothing + if (i->objType == IsDirectory && j->objType == IsDirectory) + { + gridLine.fileDescrLeft = *i; + gridLine.fileDescrRight = *j; + gridLine.cmpResult = FilesEqual; + output.push_back(gridLine); + } + //if we have a nameclash between a file and a directory: split into separate rows + else if (i->objType != j->objType) + { + gridLine.fileDescrLeft = *i; + gridLine.fileDescrRight = FileDescrLine(); + gridLine.fileDescrRight.directory = dirRight; + gridLine.cmpResult = FileOnLeftSideOnly; + output.push_back(gridLine); + + gridLine.fileDescrLeft = FileDescrLine(); + gridLine.fileDescrLeft.directory = dirLeft; + gridLine.fileDescrRight = *j; + gridLine.cmpResult = FileOnRightSideOnly; + output.push_back(gridLine); + } + else if (cmpVar == CompareByTimeAndSize) + { + //check files that exist in left and right model but have different properties + if (!filetimeCmpEqual(i->lastWriteTimeUTC, j->lastWriteTimeUTC) || + i->fileSize != j->fileSize) + { + gridLine.fileDescrLeft = *i; + gridLine.fileDescrRight = *j; + + if (filetimeCmpEqual(i->lastWriteTimeUTC, j->lastWriteTimeUTC)) + gridLine.cmpResult = FilesDifferent; + else if (filetimeCmpSmallerThan(i->lastWriteTimeUTC, j->lastWriteTimeUTC)) + gridLine.cmpResult = RightFileNewer; + else + gridLine.cmpResult = LeftFileNewer; + output.push_back(gridLine); + } + else + { + gridLine.fileDescrLeft = *i; + gridLine.fileDescrRight = *j; + gridLine.cmpResult = FilesEqual; + output.push_back(gridLine); + } + } + else if (cmpVar == CompareByMD5) + { + while (true) + { + try + { + //check files that exist in left and right model but have different checksums + if (j->fileSize != i->fileSize || calculateMD5Hash(i->filename) != calculateMD5Hash(j->filename)) + { + gridLine.fileDescrLeft = *i; + gridLine.fileDescrRight = *j; + + gridLine.cmpResult = FilesDifferent; + output.push_back(gridLine); + } + else + { + gridLine.fileDescrLeft = *i; + gridLine.fileDescrRight = *j; + gridLine.cmpResult = FilesEqual; + output.push_back(gridLine); + } + break; + } + catch (FileError& error) + { + //if (updateClass) -> is mandatory + int rv = updateClass->reportError(error.show()); + if ( rv == StatusUpdater::Continue) + break; + else if (rv == StatusUpdater::Retry) + ; //continue with loop + else + assert (false); + } + } + } + else assert (false); + } + } + updateClass->triggerUI_Refresh(); + } + catch (std::runtime_error& theException) + { + wxMessageBox(_(theException.what()), _("An exception occured!"), wxOK | wxICON_ERROR); + return; + } +} + + +void FreeFileSync::swapGrids(FileCompareResult& grid) +{ + FileDescrLine tmp; + + for (FileCompareResult::iterator i = grid.begin(); i != grid.end(); ++i) + { + //swap compare result + if (i->cmpResult == FileOnLeftSideOnly) + i->cmpResult = FileOnRightSideOnly; + else if (i->cmpResult == FileOnRightSideOnly) + i->cmpResult = FileOnLeftSideOnly; + else if (i->cmpResult == RightFileNewer) + i->cmpResult = LeftFileNewer; + else if (i->cmpResult == LeftFileNewer) + i->cmpResult = RightFileNewer; + + //swap file descriptors + tmp = i->fileDescrLeft; + i->fileDescrLeft = i->fileDescrRight; + i->fileDescrRight = tmp; + } +} + + +GetAllFilesFull::GetAllFilesFull(DirectoryDescrType& output, wxString dirThatIsSearched, StatusUpdater* updateClass) + : m_output(output), directory(dirThatIsSearched), statusUpdater(updateClass) +{ + assert(updateClass); + prefixLength = directory.Len(); +} + + +wxDirTraverseResult GetAllFilesFull::OnFile(const wxString& filename) +{ + fileDescr.filename = filename; + fileDescr.directory = directory; + fileDescr.relFilename = filename.Mid(prefixLength, wxSTRING_MAXLEN); + while (true) + { + try + { + FreeFileSync::getFileInformation(currentFileInfo, filename); + break; + } + catch (FileError& error) + { + //if (updateClass) -> is mandatory + int rv = statusUpdater->reportError(error.show()); + if ( rv == StatusUpdater::Continue) + return wxDIR_CONTINUE; + else if (rv == StatusUpdater::Retry) + ; //continue with loop + else + assert (false); + } + } + + fileDescr.lastWriteTime = currentFileInfo.lastWriteTime; + fileDescr.lastWriteTimeUTC = currentFileInfo.lastWriteTimeUTC; + fileDescr.fileSize = currentFileInfo.fileSize; + fileDescr.objType = IsFile; + m_output.insert(fileDescr); + + //update UI/commandline status information + statusUpdater->updateStatus(filename); // NO performance issue at all + //add 1 element to the progress indicator + statusUpdater->updateProgressIndicator(1); // NO performance issue at all + //trigger display refresh + statusUpdater->triggerUI_Refresh(); + + return wxDIR_CONTINUE; +} + + +wxDirTraverseResult GetAllFilesFull::OnDir(const wxString& dirname) +{ + if (dirname.EndsWith("\\RECYCLER")) + return wxDIR_IGNORE; + if (dirname.EndsWith("\\System Volume Information")) + return wxDIR_IGNORE; + + fileDescr.filename = dirname; + fileDescr.directory = directory; + fileDescr.relFilename = dirname.Mid(prefixLength, wxSTRING_MAXLEN); + while (true) + { + try + { + FreeFileSync::getFileInformation(currentFileInfo, dirname); + break; + } + catch (FileError& error) + { + //if (updateClass) -> is mandatory + int rv = statusUpdater->reportError(error.show()); + if ( rv == StatusUpdater::Continue) + return wxDIR_IGNORE; + else if (rv == StatusUpdater::Retry) + ; //continue with loop + else + assert (false); + } + } + fileDescr.lastWriteTime = currentFileInfo.lastWriteTime; + fileDescr.lastWriteTimeUTC = currentFileInfo.lastWriteTimeUTC; + fileDescr.fileSize = "0"; //currentFileInfo.fileSize should be "0" as well, but just to be sure... <- isn't needed anyway... + fileDescr.objType = IsDirectory; + m_output.insert(fileDescr); + + //update UI/commandline status information + statusUpdater->updateStatus(dirname); // NO performance issue at all + //add 1 element to the progress indicator + statusUpdater->updateProgressIndicator(1); // NO performance issue at all + //trigger display refresh + statusUpdater->triggerUI_Refresh(); + + return wxDIR_CONTINUE; +} + + +wxDirTraverseResult GetAllFilesFull::OnOpenError(const wxString& openerrorname) +{ + wxMessageBox(openerrorname, _("Error opening file")); + return wxDIR_IGNORE; +} + + +//##################################################################################################### +//file functions + +class GetAllFilesSimple : public wxDirTraverser +{ +public: + GetAllFilesSimple(wxArrayString& files, wxArrayString& subDirectories) : + allFiles(files), + subdirs(subDirectories) + {} + + wxDirTraverseResult OnDir(const wxString& dirname) + { + subdirs.Add(dirname); + return wxDIR_CONTINUE; + } + + wxDirTraverseResult OnFile(const wxString& filename) + { + allFiles.Add(filename); + return wxDIR_CONTINUE; + } + + wxDirTraverseResult OnOpenError(const wxString& openerrorname) + { + wxMessageBox(openerrorname, _("Error opening file")); + return wxDIR_IGNORE; + } + +private: + wxArrayString& allFiles; + wxArrayString& subdirs; +}; + + +void FreeFileSync::moveToRecycleBin(const char* filename) +{ + BOOL aborted = false; + SHFILEOPSTRUCT fileOp; + + char filenameDoubleNull[MAX_PATH + 1]; + strcpy (filenameDoubleNull, filename); + filenameDoubleNull[strlen(filenameDoubleNull) + 1] = 0; + + fileOp.hwnd = NULL; + fileOp.wFunc = FO_DELETE; + fileOp.pFrom = filenameDoubleNull; + fileOp.pTo = NULL; + fileOp.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT; + fileOp.fAnyOperationsAborted = aborted; + fileOp.hNameMappings = NULL; + fileOp.lpszProgressTitle = NULL; + + if (fileOperation(&fileOp //Pointer to an SHFILEOPSTRUCT structure that contains information the function needs to carry out. + ) != 0 || aborted) throw FileError(string(_("Error moving file ")) + filename + _(" to recycle bin!")); +} + + +inline +void FreeFileSync::removeFile(const char* filename) +{ + if (!wxFileExists(filename)) return; + + if (recycleBinAvailable) + { + moveToRecycleBin(filename); + return; + } + + if (!SetFileAttributes( + filename, // address of filename + FILE_ATTRIBUTE_NORMAL // address of attributes to set + )) throw FileError(string(_("Error deleting file ")) + filename); + + if (!DeleteFile(filename)) throw FileError(string(_("Error deleting file ")) + filename); +} + + +void FreeFileSync::removeDirectory(const char* directory) +{ + if (!wxDirExists(directory)) return; + + if (recycleBinAvailable) + { + moveToRecycleBin(directory); + return; + } + + wxDir dir(directory); + + //get all files and directories from current directory (and subdirectories) + wxArrayString fileList; + wxArrayString dirList; + GetAllFilesSimple traverser(fileList, dirList); + dir.Traverse(traverser); + + for (unsigned int j = 0; j < fileList.GetCount(); ++j) + removeFile(fileList[j].c_str()); + + dirList.Insert(directory, 0); //this directory will be deleted last + + for (int j = int(dirList.GetCount()) - 1; j >= 0 ; --j) + if (!RemoveDirectory(dirList[j].c_str() // address of directory to remove + )) throw FileError(string(_("Error deleting directory ")) + dirList[j].c_str()); +} + + +inline +void FreeFileSync::copyOverwriting(const char* source, const char* target) +{ + if (!SetFileAttributes( + target, // address of filename + FILE_ATTRIBUTE_NORMAL // address of attributes to set + )) throw FileError(string(_("Error overwriting file ")) + target); + + if (!CopyFile( + source, // pointer to name of an existing file + target, // pointer to filename to copy to + FALSE // overwrite if file exists + )) throw FileError(string(_("Error copying file ")) + source + _(" to ") + target); +} + + +void FreeFileSync::createDirectory(const wxString& directory, int level) +{ + if (wxDirExists(directory)) + return; + + if (level == 50) //catch endless loop + return; + +//try to create directory + if (CreateDirectory( + directory.c_str(), // pointer to a directory path string + NULL // pointer to a security descriptor + )) return; + + //if not successfull try to create containing folders first + wxString createFirstDir = wxDir(directory).GetName().BeforeLast('\\'); + + //call function recursively + if (createFirstDir.IsEmpty()) return; + + createDirectory(createFirstDir, level + 1); + + //now creation should be possible + if (!CreateDirectory( + directory.c_str(), // pointer to a directory path string + NULL // pointer to a security descriptor + )) + { + if (level == 0) + throw FileError(string(_("Error creating directory ")) + directory.c_str()); + } +} + + +void FreeFileSync::copyfile(const char* source, const char* target) +{ + if (!CopyFile( + source, // pointer to name of an existing file + target, // pointer to filename to copy to + TRUE // break if file exists + )) throw FileError(string(_("Error copying file ")) + source + _(" to ") + target); +} + + +void FreeFileSync::copyCreatingDirs(const wxString& source, const wxString& target) +{ + wxString targetPath = wxFileName(target).GetPath(); + createDirectory(targetPath); + + if (!CopyFile( + source.c_str(), // pointer to name of an existing file + target.c_str(), // pointer to filename to copy to + TRUE // break if file exists + )) throw FileError(string(_("Error copying file ")) + source.c_str() + _(" to ") + target.c_str()); +} + +//########################################################################################### + +wxCriticalSection CopyThread::copyFileCritSec; +bool CopyThread::threadIsFinished = true; +bool CopyThread::threadWasSuccessful = true; + +CopyThread::CopyThread(const wxString& sourceFile, const wxString& targetFile) : + source(sourceFile), + target(targetFile) +{} + + +wxThread::ExitCode CopyThread::Entry() +{ + bool success = (CopyFile( + source.c_str(), // pointer to name of an existing file + target.c_str(), // pointer to filename to copy to + TRUE // break if file exists + )); + + copyFileCritSec.Enter(); + + //report status to main thread + threadIsFinished = true; + threadWasSuccessful = success; + + copyFileCritSec.Leave(); + + return 0; +} + + +void FreeFileSync::copyfileMultithreaded(const wxString& source, const wxString& target, StatusUpdater* updateClass) +{ + //at this point threadIsRunning is not shared between threads + CopyThread::threadIsFinished = false; + + //create thread for copying of (large) files + CopyThread* copyFileThread = new CopyThread(source, target); //quite faster than joinable threads + + copyFileThread->Create(); + copyFileThread->SetPriority(80); + copyFileThread->Run(); + + bool processCompleted; + while (true) + { + CopyThread::copyFileCritSec.Enter(); + processCompleted = CopyThread::threadIsFinished; //always put shared data into mutextes/critical sections + CopyThread::copyFileCritSec.Leave(); + + if (processCompleted) //if completed the data is not shared anymore + { + if (!CopyThread::threadWasSuccessful) + { + throw FileError(string(_("Error copying file ")) + source.c_str() + _(" to ") + target.c_str()); + } + else return; + } + + updateClass->triggerUI_Refresh(); + } +} + + +FreeFileSync::FreeFileSync() + : recycleBinAvailable(false) +{ + // Get a handle to the DLL module containing Recycle Bin functionality + hinstShell = LoadLibrary("shell32.dll"); + if (hinstShell == NULL) + recycleBinAvailable = false; + else + { + fileOperation = (DLLFUNC)GetProcAddress(hinstShell, "SHFileOperation"); + if (fileOperation == NULL ) + { + FreeLibrary(hinstShell); + recycleBinAvailable = false; + } + else + recycleBinAvailable = true; + } +} + + +FreeFileSync::~FreeFileSync() +{ + if (recycleBinAvailable) + FreeLibrary(hinstShell); +} + + +bool FreeFileSync::recycleBinExists() +{ + FreeFileSync dummyObject; + return dummyObject.recycleBinAvailable; +} + + +bool FreeFileSync::setRecycleBinUsage(bool activate) +{ //If recycleBin is not available it mustn't be activated: This should NEVER happen! + if (!recycleBinAvailable && activate) + throw std::runtime_error("Initialization of Recycle Bin failed! It cannot be used!"); + else + recycleBinAvailable = activate; + return true; +} + + +inline +SyncDirection getSyncDirection(const CompareFilesResult cmpResult, const SyncConfiguration& config) +{ + switch (cmpResult) + { + case FileOnLeftSideOnly: + return config.exLeftSideOnly; + break; + + case FileOnRightSideOnly: + return config.exRightSideOnly; + break; + + case RightFileNewer: + return config.rightNewer; + break; + + case LeftFileNewer: + return config.leftNewer; + break; + + case FilesDifferent: + return config.different; + break; + + default: + assert (false); + } + return SyncDirNone; +} + + +void FreeFileSync::getBytesToTransfer(mpz_t& result, const FileCompareLine& fileCmpLine, const SyncConfiguration& config) +{ + mpz_set_ui(result, 0); //always initialize variables + + //do not add filtered entries + if (!fileCmpLine.selectedForSynchronization) + return; + + int returnValue = 0; + + switch (fileCmpLine.cmpResult) + { + case FileOnLeftSideOnly: + if (config.exLeftSideOnly == SyncDirRight) + //copy files to right + returnValue = mpz_set_str(result, fileCmpLine.fileDescrLeft.fileSize.c_str(), 10); + break; + + case FileOnRightSideOnly: + if (config.exRightSideOnly == SyncDirLeft) + //copy files to left + returnValue = mpz_set_str(result, fileCmpLine.fileDescrRight.fileSize.c_str(), 10); + break; + + case LeftFileNewer: + case RightFileNewer: + case FilesDifferent: + switch (getSyncDirection(fileCmpLine.cmpResult, config)) + { + case SyncDirLeft: //copy from right to left + returnValue = mpz_set_str(result, fileCmpLine.fileDescrRight.fileSize.c_str(), 10); + break; + case SyncDirRight: //copy from left to right + returnValue = mpz_set_str(result, fileCmpLine.fileDescrLeft.fileSize.c_str(), 10); + break; + case SyncDirNone: + break; + } + break; + + case FilesEqual: + break; + }; + assert (returnValue == 0); +} + + +mpz_class FreeFileSync::calcTotalBytesToTransfer(const FileCompareResult& fileCmpResult, const SyncConfiguration& config) +{ + mpz_t largeTmpInt, result_c; + mpz_init(largeTmpInt); + mpz_init(result_c); + + for (FileCompareResult::const_iterator i = fileCmpResult.begin(); i != fileCmpResult.end(); ++i) + { //only sum up sizes of files, not directories + if (i->fileDescrLeft.objType == IsFile || i->fileDescrRight.objType == IsFile) + { + getBytesToTransfer(largeTmpInt, *i, config); + mpz_add(result_c, result_c, largeTmpInt); //much faster than converting this to mpz_class for each iteration + } + } + + mpz_class result(result_c); + + mpz_clear(largeTmpInt); + mpz_clear(result_c); + + return result; +} + + +void FreeFileSync::synchronizeFile(const FileCompareLine& filename, const SyncConfiguration& config, StatusUpdater* statusUpdater) +{ + assert (statusUpdater); + + if (!filename.selectedForSynchronization) return; + + wxString target; + + //synchronize file: + switch (filename.cmpResult) + { + case FileOnLeftSideOnly: + switch (config.exLeftSideOnly) + { + case SyncDirLeft: //delete files on left + statusUpdater->updateStatus(wxString(_("Deleting file ") + filename.fileDescrLeft.filename)); + removeFile(filename.fileDescrLeft.filename.c_str()); + break; + case SyncDirRight: //copy files to right + target = filename.fileDescrRight.directory + filename.fileDescrLeft.relFilename.c_str(); + statusUpdater->updateStatus(wxString(_("Copying file ")) + filename.fileDescrLeft.filename + + _(" to ") + target); + + copyfileMultithreaded(filename.fileDescrLeft.filename, target, statusUpdater); + break; + case SyncDirNone: + break; + default: + assert (false); + } + break; + + case FileOnRightSideOnly: + switch (config.exRightSideOnly) + { + case SyncDirLeft: //copy files to left + target = filename.fileDescrLeft.directory + filename.fileDescrRight.relFilename; + statusUpdater->updateStatus(wxString(_("Copying file ")) + filename.fileDescrRight.filename + + _(" to ") + target); + + copyfileMultithreaded(filename.fileDescrRight.filename, target, statusUpdater); + break; + case SyncDirRight: //delete files on right + statusUpdater->updateStatus(wxString(_("Deleting file ") + filename.fileDescrRight.filename)); + removeFile(filename.fileDescrRight.filename.c_str()); + break; + case SyncDirNone: + break; + default: + assert (false); + } + break; + + case LeftFileNewer: + case RightFileNewer: + case FilesDifferent: + switch (getSyncDirection(filename.cmpResult, config)) + { + case SyncDirLeft: //copy from right to left + statusUpdater->updateStatus(wxString(_("Copying file ")) + filename.fileDescrRight.filename + + _(" overwriting ") + filename.fileDescrLeft.filename); + + removeFile(filename.fileDescrLeft.filename.c_str()); //only used if switch activated by user, else file is simply deleted + copyfileMultithreaded(filename.fileDescrRight.filename, filename.fileDescrLeft.filename, statusUpdater); + break; + case SyncDirRight: //copy from left to right + statusUpdater->updateStatus(wxString(_("Copying file ")) + filename.fileDescrLeft.filename + + _(" overwriting ") + filename.fileDescrRight.filename); + + removeFile(filename.fileDescrRight.filename.c_str()); //only used if switch activated by user, else file is simply deleted + copyfileMultithreaded(filename.fileDescrLeft.filename, filename.fileDescrRight.filename, statusUpdater); + break; + case SyncDirNone: + break; + default: + assert (false); + } + break; + + case FilesEqual: + break; + + default: + assert (false); + } + return; +} + + +void FreeFileSync::synchronizeFolder(const FileCompareLine& filename, const SyncConfiguration& config, StatusUpdater* statusUpdater) +{ + assert (statusUpdater); + + if (!filename.selectedForSynchronization) return; + + wxString target; + + //synchronize folders: + switch (filename.cmpResult) + { + case FileOnLeftSideOnly: + switch (config.exLeftSideOnly) + { + case SyncDirLeft: //delete folders on left + statusUpdater->updateStatus(wxString(_("Deleting folder ") + filename.fileDescrLeft.filename)); + removeDirectory(filename.fileDescrLeft.filename.c_str()); + break; + case SyncDirRight: //create folders on right + target = filename.fileDescrRight.directory + filename.fileDescrLeft.relFilename; + statusUpdater->updateStatus(wxString(_("Creating folder ") + target)); + + //some check to catch the error that directory on source has been deleted externally after the "compare"... + if (!wxDirExists(filename.fileDescrLeft.filename)) + throw FileError(string(_("Error: Source directory does not exist anymore: ")) + filename.fileDescrLeft.filename.c_str()); + createDirectory(target); + break; + case SyncDirNone: + break; + default: + assert (false); + } + break; + + case FileOnRightSideOnly: + switch (config.exRightSideOnly) + { + case SyncDirLeft: //create folders on left + target = filename.fileDescrLeft.directory + filename.fileDescrRight.relFilename; + statusUpdater->updateStatus(wxString(_("Creating folder ") + target)); + + //some check to catch the error that directory on source has been deleted externally after the "compare"... + if (!wxDirExists(filename.fileDescrRight.filename)) + throw FileError(string(_("Error: Source directory does not exist anymore: ")) + filename.fileDescrRight.filename.c_str()); + createDirectory(target); + break; + case SyncDirRight: //delete folders on right + statusUpdater->updateStatus(wxString(_("Deleting folder ") + filename.fileDescrRight.filename)); + removeDirectory(filename.fileDescrRight.filename.c_str()); + break; + case SyncDirNone: + break; + default: + assert (false); + } + break; + + case FilesEqual: + break; + case RightFileNewer: + case LeftFileNewer: + case FilesDifferent: + default: + assert (false); + } + return; +} + + +wxString FreeFileSync::formatFilesizeToShortString(const mpz_class& filesize) +{ + const char* DigitsSeparator = _("."); + + mpf_class nrOfBytes = filesize; + + wxString unit = " Byte"; + if (nrOfBytes > 999) + { + nrOfBytes/= 1024; + unit = " kB"; + if (nrOfBytes > 999) + { + nrOfBytes/= 1024; + unit = " MB"; + if (nrOfBytes > 999) + { + nrOfBytes/= 1024; + unit = " GB"; + if (nrOfBytes > 999) + { + nrOfBytes/= 1024; + unit = " TB"; + if (nrOfBytes > 999) + { + nrOfBytes/= 1024; + unit = " PB"; + } + } + } + } + } + + mp_exp_t exponent = 0; + + string temp; + if (unit == " Byte") //no decimal places in case of bytes + { + temp = nrOfBytes.get_str(exponent, 10, 3); + if (!temp.length()) //if nrOfBytes is zero GMP returns an empty string + temp = "0"; + } + else + { + temp = string(nrOfBytes.get_str(exponent, 10, 3) + "000").substr(0, 3); //returns mantisse of length 3 in all cases + + if (exponent < 0 || exponent > 3) + temp = _("Error"); + else + switch (exponent) + { + case 0: + temp = string("0") + DigitsSeparator + temp.substr(0, 2); //shorten mantisse as a 0 will be inserted + break; + case 1: + case 2: + temp.insert(exponent, DigitsSeparator); + break; + case 3: + break; + } + } + temp+= unit; + return temp.c_str(); +} + + +void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, const wxString& includeFilter, const wxString& excludeFilter) +{ + wxString includeFilterTmp(includeFilter); + wxString excludeFilterTmp(excludeFilter); + + //make sure filters end with ";" - no problem with empty strings here + if (!includeFilterTmp.EndsWith(";")) + includeFilterTmp.Append(';'); + if (!excludeFilterTmp.EndsWith(";")) + excludeFilterTmp.Append(';'); + + //load filters into vectors + vector<wxString> includeList; + vector<wxString> excludeList; + + unsigned int indexStart = 0; + unsigned int indexEnd = 0; + while ((indexEnd = includeFilterTmp.find(';', indexStart )) != string::npos) + { + if (indexStart != indexEnd) //do not add empty strings + includeList.push_back( includeFilterTmp.substr(indexStart, indexEnd - indexStart) ); + indexStart = indexEnd + 1; + } + + indexStart = 0; + indexEnd = 0; + while ((indexEnd = excludeFilterTmp.find(';', indexStart )) != string::npos) + { + if (indexStart != indexEnd) //do not add empty strings + excludeList.push_back( excludeFilterTmp.substr(indexStart, indexEnd - indexStart) ); + indexStart = indexEnd + 1; + } + +//########################### + + //filter currentGridData + for (FileCompareResult::iterator i = currentGridData.begin(); i != currentGridData.end(); i++) + { + //process include filters + if (i->fileDescrLeft.objType != IsNothing) + { + bool includedLeft = false; + for (vector<wxString>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) + if (i->fileDescrLeft.filename.Matches(*j)) + { + includedLeft = true; + break; + } + + if (!includedLeft) + { + i->selectedForSynchronization = false; + continue; + } + } + + if (i->fileDescrRight.objType != IsNothing) + { + bool includedRight = false; + for (vector<wxString>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) + if (i->fileDescrRight.filename.Matches(*j)) + { + includedRight = true; + break; + } + + if (!includedRight) + { + i->selectedForSynchronization = false; + continue; + } + } + + //process exclude filters + bool excluded = false; + for (vector<wxString>::const_iterator j = excludeList.begin(); j != excludeList.end(); ++j) + if (i->fileDescrLeft.filename.Matches(*j) || + i->fileDescrRight.filename.Matches(*j)) + { + excluded = true; + break; + } + + if (excluded) + { + i->selectedForSynchronization = false; + continue; + } + + i->selectedForSynchronization = true; + } +} + +void FreeFileSync::removeFilterOnCurrentGridData(FileCompareResult& currentGridData) +{ + //remove all filters on currentGridData + for (FileCompareResult::iterator i = currentGridData.begin(); i != currentGridData.end(); i++) + i->selectedForSynchronization = true; +} + + +wxString FreeFileSync::getFormattedDirectoryName(const wxString& dirname) +{ //this formatting is needed since functions in FreeFileSync.cpp expect the directory to end with '\' to be able to split the relative names + //Actually all it needs, is the length of the directory + + //let wxWidgets do the directory formatting, e.g. replace '/' with '\' + wxString result = wxDir(dirname).GetName(); + + result.Append('\\'); + return result; +} + + +inline +bool deletionImminent(const FileCompareLine& line, const SyncConfiguration& config) +{ //test if current sync-line will result in deletion of files -> used to avoid disc space bottlenecks + if ((line.cmpResult == FileOnLeftSideOnly && config.exLeftSideOnly == SyncDirLeft) || + (line.cmpResult == FileOnRightSideOnly && config.exRightSideOnly == SyncDirRight)) + return true; + else + return false; +} + + +void FreeFileSync::startSynchronizationProcess(FileCompareResult& grid, const SyncConfiguration& config, StatusUpdater* statusUpdater, bool useRecycleBin) +{ + assert (statusUpdater); + + try + { + FreeFileSync fileSyncObject; //currently only needed for recycle bin + fileSyncObject.setRecycleBinUsage(useRecycleBin); + + FileCompareResult resultsGrid; + + // it should never happen, that a directory on left side has same name as file on right side. GetModelDiff should take care of this + // and split into two "exists on one side only" cases + // Note: this case is not handled by this tool as this is considered to be a bug and must be solved by the user + + //synchronize folders: + for (FileCompareResult::const_iterator i = grid.begin(); i != grid.end(); ++i) + { + if (i->fileDescrLeft.objType == IsDirectory || i->fileDescrRight.objType == IsDirectory) + { + while (true) + { //trigger display refresh + statusUpdater->triggerUI_Refresh(); + + try + { + fileSyncObject.synchronizeFolder(*i, config, statusUpdater); + break; + } + catch (FileError& error) + { + //if (updateClass) -> is mandatory + int rv = statusUpdater->reportError(error.show()); + + if ( rv == StatusUpdater::Continue) + { + resultsGrid.push_back(*i); //append folders that have not been synced successfully + break; + } + else if (rv == StatusUpdater::Retry) + ; //continue with loop + else + assert (false); + } + } + //progress indicator update + //indicator is updated no matter if errors occured or not! + statusUpdater->updateProgressIndicator(0); //each call represents one processed file/directory + } + } + + //synchronize files: + for (int k = 0; k < 2; ++k) //loop over all files twice; reason: first delete, then copy (no sorting necessary: performance) + { + bool deleteLoop = !k; //-> first loop: delete files, second loop: copy files + + for (FileCompareResult::const_iterator i = grid.begin(); i != grid.end(); ++i) + { + if (i->fileDescrLeft.objType == IsFile || i->fileDescrRight.objType == IsFile) + { + if (deleteLoop && deletionImminent(*i, config) || + !deleteLoop && !deletionImminent(*i, config)) + { + while (true) + { //trigger display refresh + statusUpdater->triggerUI_Refresh(); + + try + { + fileSyncObject.synchronizeFile(*i, config, statusUpdater); + break; + } + catch (FileError& error) + { + //if (updateClass) -> is mandatory + int rv = statusUpdater->reportError(error.show()); + + if ( rv == StatusUpdater::Continue) + { + resultsGrid.push_back(*i); //append files that have not been synced successfully + break; + } + else if (rv == StatusUpdater::Retry) + ; //continue with loop + else + assert (false); + } + } + //progress indicator update + //indicator is updated no matter if errors occured or not! + mpz_t largeTmpInt; + mpz_init(largeTmpInt); + FreeFileSync::getBytesToTransfer(largeTmpInt, *i, config); + statusUpdater->updateProgressIndicator(mpz_get_d(largeTmpInt)); + mpz_clear(largeTmpInt); + } + } + } + } + + //return files that couldn't be processed + grid = resultsGrid; + } + catch (std::runtime_error& theException) + { + wxMessageBox(_(theException.what()), _("An exception occured!"), wxOK | wxICON_ERROR); + return; + } +} + diff --git a/FreeFileSync.h b/FreeFileSync.h new file mode 100644 index 00000000..62abc81d --- /dev/null +++ b/FreeFileSync.h @@ -0,0 +1,254 @@ +#ifndef FREEFILESYNC_H_INCLUDED +#define FREEFILESYNC_H_INCLUDED + +#include <wx/string.h> +#include <set> +#include <vector> +#include <wx/dir.h> +#include <windows.h> +#include "library\GMP\include\gmpxx.h" + +using namespace std; + +enum SyncDirection +{ + SyncDirLeft, + SyncDirRight, + SyncDirNone +}; + +struct SyncConfiguration +{ + SyncDirection exLeftSideOnly; + SyncDirection exRightSideOnly; + SyncDirection leftNewer; + SyncDirection rightNewer; + SyncDirection different; +}; + +typedef struct +{ + wxString fileSize; + wxString lastWriteTime; + FILETIME lastWriteTimeUTC; +} FileInfo; + +enum ObjectType +{ + IsNothing, + IsDirectory, + IsFile +}; + +struct FileDescrLine +{ + FileDescrLine() : objType(IsNothing) {}; + + wxString filename; // == directory + relFilename + wxString directory; //directory to be synced + wxString relFilename; //filename without directory that is being synchronized + wxString lastWriteTime; + FILETIME lastWriteTimeUTC; + wxString fileSize; + ObjectType objType; //is it a file or directory or initial? + + //the following operators are needed by template class "set" + //DO NOT CHANGE THESE RELATIONS!!! + bool operator>(const FileDescrLine& b ) const + { //Windows does NOT distinguish upper/lower-case + return (relFilename.CmpNoCase(b.relFilename) > 0); + } + bool operator<(const FileDescrLine& b) const + { //Windows does NOT distinguish upper/lower-case + return (relFilename.CmpNoCase(b.relFilename) < 0); + } + bool operator==(const FileDescrLine& b) const + { //Windows does NOT distinguish upper/lower-case + return (relFilename.CmpNoCase(b.relFilename) == 0); + } +}; +typedef set<FileDescrLine> DirectoryDescrType; + + +enum CompareFilesResult +{ + FileOnLeftSideOnly, + FileOnRightSideOnly, + RightFileNewer, + LeftFileNewer, + FilesDifferent, + FilesEqual +}; + +struct FileCompareLine +{ + FileCompareLine() : selectedForSynchronization(true) {} + + FileDescrLine fileDescrLeft; + FileDescrLine fileDescrRight; + + CompareFilesResult cmpResult; + bool selectedForSynchronization; +}; +typedef vector<FileCompareLine> FileCompareResult; + + +enum CompareVariant +{ + CompareByMD5, + CompareByTimeAndSize +}; + +//interface for status updates (can be implemented by UI or commandline) +//overwrite virtual methods for respective functionality +class StatusUpdater +{ +public: + StatusUpdater() : abortionRequested(false) {} + virtual ~StatusUpdater() {} + + //these three methods have to be implemented in the derived classes to handle error and status information + virtual void updateStatus(const wxString& text) = 0; + virtual void updateProgressIndicator(double number) = 0; + virtual int reportError(const wxString& text) = 0; + + //this method is triggered repeatedly and can be used to refresh the ui by dispatching pending events + virtual void triggerUI_Refresh() {} + + void requestAbortion() //opportunity to abort must be implemented in the three virtual status and error methods (for example in triggerUI_Refresh()) + { //currently used by the UI status information screen, when button "Abort is pressed" + abortionRequested = true; + } + static const int Continue = -1; + static const int Retry = -2; + +protected: + bool abortionRequested; +}; + + +class GetAllFilesFull : public wxDirTraverser +{ +public: + GetAllFilesFull(DirectoryDescrType& output, wxString dirThatIsSearched, StatusUpdater* updateClass = 0); + + wxDirTraverseResult OnFile(const wxString& filename); + + wxDirTraverseResult OnDir(const wxString& dirname); + + wxDirTraverseResult OnOpenError(const wxString& openerrorname); + +private: + DirectoryDescrType& m_output; + wxString directory; + int prefixLength; + FileInfo currentFileInfo; + FileDescrLine fileDescr; + StatusUpdater* statusUpdater; +}; + +typedef WINSHELLAPI int (*DLLFUNC)(LPSHFILEOPSTRUCT lpFileOp); + + +class FreeFileSync +{ +public: + FreeFileSync(); + ~FreeFileSync(); + + friend class GetAllFilesFull; + friend class CopyThread; + + //main function for compare + static void getModelDiff(FileCompareResult& output, const wxString& dirLeft, const wxString& dirRight, CompareVariant cmpVar, StatusUpdater* updateClass); + + //main function for synchronization + static void startSynchronizationProcess(FileCompareResult& grid, const SyncConfiguration& config, StatusUpdater* statusUpdater, bool useRecycleBin); + + static bool recycleBinExists(); //test existence of Recycle Bin API + bool setRecycleBinUsage(bool activate); //enables/disables Recycle Bin usage (but only if usage is possible at all): RV: Setting was successful or not + + static void filterCurrentGridData(FileCompareResult& currentGridData, const wxString& includeFilter, const wxString& excludeFilter); + static void removeFilterOnCurrentGridData(FileCompareResult& currentGridData); + + static wxString formatFilesizeToShortString(const mpz_class& filesize); + static wxString getFormattedDirectoryName(const wxString& dirname); + + static mpz_class calcTotalBytesToTransfer(const FileCompareResult& fileCmpResult, const SyncConfiguration& config); + static void swapGrids(FileCompareResult& grid); + +private: + void synchronizeFile(const FileCompareLine& filename, const SyncConfiguration& config, StatusUpdater* statusUpdater); // true if successful + void synchronizeFolder(const FileCompareLine& filename, const SyncConfiguration& config, StatusUpdater* statusUpdater); // true if successful + + //windows file copy functionality + void removeDirectory(const char* directory); + void removeFile(const char* filename); + static void copyOverwriting(const char* source, const char* target); + static void copyfile(const char* source, const char* target); + static void copyCreatingDirs(const wxString& source, const wxString& target); + static void createDirectory(const wxString& directory, int level = 0); //level is used internally only + //some special file functions + void moveToRecycleBin(const char* filename); + void copyfileMultithreaded(const wxString& source, const wxString& target, StatusUpdater* updateClass); + + + static void getBytesToTransfer(mpz_t& result, const FileCompareLine& fileCmpLine, const SyncConfiguration& config); + + static void generateFileAndFolderDescriptions(DirectoryDescrType& output, const wxString& directory, StatusUpdater* updateClass = 0); + + static void getFileInformation(FileInfo& output, const wxString& filename); + + static wxString calculateMD5Hash(const wxString& filename); + + bool recycleBinAvailable; + HINSTANCE hinstShell; + DLLFUNC fileOperation; +}; + + +class FileError //Exception class used to notify file/directory copy/delete errors +{ +public: + FileError(string txt) : errorMessage(txt) {} + + string show() + { + return errorMessage; + } + +private: + string errorMessage; +}; + + +class AbortThisProcess //Exception class used to abort the "compare" and "sync" process +{ +public: + AbortThisProcess() {} + ~AbortThisProcess() {} +}; + + +class CopyThread : public wxThread +{ +public: + CopyThread(const wxString& sourceFile, const wxString& targetFile); + ~CopyThread() {} + + ExitCode Entry(); + + static wxCriticalSection copyFileCritSec; + + //shared thread data -> protect with critical section! + static bool threadIsFinished; + static bool threadWasSuccessful; + // + +private: + const wxString& source; + const wxString& target; +}; + + +#endif // FREEFILESYNC_H_INCLUDED diff --git a/FreeFileSync.ico b/FreeFileSync.ico Binary files differnew file mode 100644 index 00000000..bceb6ee4 --- /dev/null +++ b/FreeFileSync.ico diff --git a/Readme.txt b/Readme.txt new file mode 100644 index 00000000..c111862c --- /dev/null +++ b/Readme.txt @@ -0,0 +1,55 @@ +FreeFileSync v1.2 +----------------- + +Usage +----- +1. Choose left and right directories and "Compare" them. +2. Select "Synchronize..." to specify settings and begin synchronization. + + +Features +-------- +1. Compare files (bytewise or by date) and synchronize them. +2. No limitations: An unlimited number of files can be synchronized. +3. Subfolders are also synchronized, especially empty folders. +4. Network support. +5. Lean & easy accessible UI: Optimized for speed and large sets of data. +6. Algorithms coded in C/C++ completely. +7. Focus on usability: + - Only necessary functionality on UI: no overloaded menus or icon jungle. + - Select folders via drag & drop. + - Your last configuration and screen settings are loaded on startup and saved on exit. + - Double-click to show file in explorer. + - copy & paste support to export file-lists. + - Progress indicators, status information and error reporting + - Sort file-lists by name, size or date. + - Display statistical data: total filesizes, amount of bytes that will be transfered with the current settings. +8. Easy commandline mode for automated synchronization (can be scheduled or used in Batch jobs). +9. Support for filesizes > 4 GB. +10. Option to move files to Recycle Bin instead of deleting/overwriting them. +11. UTC (coordinated world time) is used when comparing file times avoiding problems with time zones or daylight saving time. +12. Automatically ignore directories "\RECYCLER" and "System Volume Information" when comparing and syncing. +13. Localized German version available. +14. Based on wxWidgets Framework => Portable to many operating systems. +15. Filter functionality to include/exclude files from synchronization +16. Include/exclude specific files from synchronization manually. + + +Links +------ +FreeFileSync on SourceForge: + +http://sourceforge.net/projects/freefilesync/ + + +Contact +------- +For feedback, suggestions or bug-reports you can write an email to: +zhnmju123 [at] gmx [dot] de + +or directly report to: +http://sourceforge.net/projects/freefilesync/ + + +Have fun! +-ZenJu diff --git a/Resources.a01 b/Resources.a01 Binary files differnew file mode 100644 index 00000000..804d3f1f --- /dev/null +++ b/Resources.a01 diff --git a/Resources.dat b/Resources.dat Binary files differnew file mode 100644 index 00000000..6574346e --- /dev/null +++ b/Resources.dat diff --git a/language.dat b/language.dat new file mode 100644 index 00000000..adeaeec8 --- /dev/null +++ b/language.dat @@ -0,0 +1,356 @@ + Time: + Uhrzeit: + does not exist. Aborting! + existiert nicht. Abbruch! + does not exist. \n\nSynchronization aborted! + existiert nicht. \n\nSynchronisation abgebrochen! + item(s) remaining + Element(e) übrig + item(s):\n\n + Element(e):\n\n + items on left, + Elemente links, + items on right, + Elemente rechts, + of + von + overwriting + und überschreibe + row in view + Zeile zur Ansicht + rows in view + Zeilen zur Ansicht + to + nach + to recycle bin! + in den Papierkorb! + total) + gesamt) +!= files are different\n +!= Dateien sind verschieden\n +(-) filtered out from sync-process\n +(-) nicht synchronisieren\n +(Build: +(Build: +, +. +------------------------------------------------- +----------------------------------------------------- +---------\n +-----------\n +-Open-Source file synchronization- +-Open-Source Datei-Synchronisation- +. +, +/ +/ +1 item on left, +1 Element links, +1 item on right, +1 Element rechts, +1 row in view ( +1 Zeile zur Ansicht ( +10,0 MB +10,0 MB +1000000 +1000000 +<< left file is newer\n +<< linke Datei ist neuer\n +<Directory> +<Verzeichnis> +<left directory> +<linkes Verzeichnis> +<right directory> +<rechtes Verzeichnis> +<| file on left side only\n +<| Datei existiert nur links\n +== files are equal\n\n +== Dateien sind gleich\n\n +>> right file is newer\n +>> rechte Datei ist neuer\n +Abort +Abbruch +Aborted! +Abgebrochen! +About +Info +Action +Aktion +An error occured +Fehler +An exception occured +Eine Exception wurde geworfen +An exception occured! +Eine Exception wurde geworfen! +Back +Zurück +Begin Synchronization +Starte Synchronisation +Benchmark: +Benchmark: +Choose to hide filtered files/directories from list +Gefilterte Dateien ein-/ausblenden +Compare both sides +Beide Seiten vergleichen +Compare by +Vergleichen nach +Compare by \"File size and date\"\n----------------------------------------\nThis compare variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time. For the latter the system's UTC time (coordinated word time) is used internally, although the local file time is displayed on the result list. So there are no problems concerning different time zones or daylight saving time.\n\nWhen \"Compare\" is triggered with this option set the following decision tree is processed:\n\n -----------------\n |Decision tree|\n -----------------\n ________|___________\n | |\n file exists on both sides on one side only\n _____|______ __|___\n | | | |\nequal different left right\n _________|_____________\n | | |\n left newer right newer different (but same date)\n\nAs a result 6 different status can be returned to categorize all files:\n\n- exists left only\n- exists right only\n- left newer\n- right newer\n- different (but same date)\n- equal\n\n\nCompare by \"File content\"\n----------------------------------------\nAs the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller:\n\n -----------------\n |Decision tree|\n -----------------\n ________|___________\n | |\n file exists on both sides on one side only\n _____|______ __|___\n | | | |\nequal different left right\n\nAs a result the files are separated into the following categories:\n\n- exists left only\n- exists right only\n- different\n- equal +Vergleichen nach \"Dateigröße und -datum\"\n---------------------------------------------------\nDiese Variante identifiziert zwei gleichnamige Dateien als gleich, wenn sie die gleiche Dateigröße haben UND der Zeitpunkt des letzten Zugriffs derselbe ist. Für Letzteres wird intern die UTC-Zeit (koordinierte Weltzeit) verwendet, auch wenn die lokale Zeit in der Ergebnisliste angezeigt wird. Dadurch werden Probleme vermieden, die durch verschiedene Zeitzonen oder Sommer-/Winterzeit entstehen.\n\nNachdem \"Compare\" mit dieser Einstellung gestartet wurde, wird der folgende Entscheidungsbaum abgearbeitet:\n\n -------------------------\n |Entscheidungsbaum|\n -------------------------\n __________|___________\n | |\n Datei ex. auf beiden Seiten nur auf einer Seite\n ________|____ __|___\n | | | |\n gleich verschieden links rechts\n __________|___________\n | | |\n links neuer rechts neuer verschieden (bei gleichem Datum)\n\nAls Ergebnis werden 6 verschiedene Status zurückgegeben, um Dateien zu kategorisieren:\n\n- existiert nur links\n- existiert nur rechts\n- links neuer\n- rechts neuer\n- verschieden (bei gleichem Datum)\n- gleich\n\n\nVergleichen nach \"Dateiinhalt\"\n------------------------------------\nWie der Name bereits sagt, werden zwei Dateien mit gleichem Namen genau dann als gleich angesehen, wenn sie den gleichen Dateiinhalt haben. Diese Einstellung ist eher für Konsistenzprüfungen geeignet als für Backup-Operationen. Aus diesem Grund wird der Zeitpunkt der letzten Änderung der Dateien nicht berücksichtigt.\n\nDer Entscheidungsbaum ist in diesem Fall kleiner:\n\n -------------------------\n |Entscheidungsbaum|\n -------------------------\n __________|___________\n | |\n Datei ex. auf beiden Seiten nur auf einer Seite\n ________|____ __|___\n | | | |\n gleich verschieden links rechts\n\nDas Ergebnis ist eine Aufteilung in folgende Kategorien:\n\n- existiert nur links\n- existiert nur rechts\n- verschieden\n- gleich +Completed +Fertig +Configuration +Konfiguration +Configure Filter... +Konfiguriere Filter... +Configure filter settings +Konfiguriere Filter +Configure your own synchronization rules. +Eigene Synchronisationsregeln definieren. +Continue +Fortfahren +Copy from left to right +Von links nach rechts kopieren +Copy from left to right overwriting +Von links nach rechts kopieren und überschreiben +Copy from right to left +Von rechts nach links kopieren +Copy from right to left overwriting +Von rechts nach links kopieren und überschreiben +Copying file +Kopiere Datei +Could not change attributes of +Attribute der Datei konnten nicht geändert werden: +Could not open +Fehler beim Öffnen von +Could not open ""config.dat"" for write access! +Fehler beim Schreiben von ""config.dat""! +Could not open file: +Fehler beim Öffnen der Datei: +Could not retrieve file info for: +Fehler beim Lesen der Dateiattribute von: +Could not set working directory to directory containing executable file! +Arbeitsverzeichnisses konnte nicht auf Pfad der .exe-Datei gelegt werden! +Creating folder +Erstelle Verzeichnis +Current operation: +Aktuelle Operation: +Custom +Eigene +Data copied: +Kopierte Daten: +Data to be transferred: +Zu übertragende Daten: +Date +Datum +Default +Standard +Delete files existing on left side only +Lösche Dateien, die nur links existieren +Delete files existing on right side only +Lösche Dateien, die nur rechts existieren +Deleting file +Lösche Datei +Deleting folder +Lösche Verzeichnis +Directory +Verzeichnis +Directory on the left does not exist. Please select a new one! +Verzeichnis auf der linken Seite existiert nicht. Bitte ein anderes auswählen! +Directory on the right does not exist. Please select a new one! +Verzeichnis auf der rechten Seite existiert nicht. Bitte ein anderes auswählen! +Displays help on the command line parameters\n +Hilfe zu den Kommandozeilenparametern\n +Do nothing +Nichts tun +Donate with Paypal +Spenden mit Paypal +Drag && drop +Drag && Drop +Email: +Email: +Equality condition +Vergleich nach: +Error +Fehler +Error converting FILETIME to SYSTEMTIME +Fehler beim Konvertieren der FILETIME nach SYSTEMTIME +Error converting FILETIME to local FILETIME +Fehler beim Konvertieren der FILETIME nach (lokale) FILETIME +Error copying file +Fehler beim Kopieren der Datei +Error creating directory +Fehler beim Erstellen des Verzeichnisses +Error deleting directory +Fehler beim Löschen des Verzeichnisses +Error deleting file +Fehler beim Löschen der Datei +Error moving file +Fehler beim Verschieben der Datei +Error opening file +Fehler beim Öffnen der Datei +Error overwriting file +Fehler beim Überschreiben der Datei +Error when modifying GUI grid +Fehler beim Modifizieren des UI Grids +Error: Source directory does not exist anymore: +Fehler: Quellverzeichnis existiert nicht mehr: +Exclude +Ausschließen +Feedback and suggestions are welcome at: +Feedback und Vorschläge sind willkommen unter: +File content +Dateiinhalt +File size and date +Dateigröße und -datum +Filename +Dateiname +Files are found equal if\n - file content\nis the same. +Dateien gelten als gleich, wenn\n - der Inhalt\ngleich ist. +Files are found equal if\n - filesize\n - last write time (UTC) and date\nare the same. +Dateien gelten als gleich, wenn\n - die Größe\n - Datum und Uhrzeit(UTC) des letzten Zugriffs\ngleich sind. +Files that are different +Unterschiedliche Dateien +Files that are equal +Gleiche Dateien +Files that are newer on left +Dateien, die auf beiden Seiten existieren; linke Datei ist neuer +Files that are newer on right +Dateien, die auf beiden Seiten existieren; rechte Datei ist neuer +Files that exist on both sides and are different +Dateien, die auf beiden Seiten existieren und verschieden sind +Files that exist on both sides, left one is newer +Dateien, die auf beiden Seiten existieren; linke Datei ist neuer +Files that exist on both sides, right one is newer +Dateien, die auf beiden Seiten existieren; rechte Datei ist neuer +Files that exist on left view only +Dateien, die nur links existieren +Files that exist on right view only +Dateien, die nur rechts existieren +Filter +Filter +Filter active: Press again to deactivate +Filter aktiv: Zum Deaktivieren erneut auswählen +Filter files +Dateien filtern +Filter view +Ansicht filtern +Folders/files that exist on left side only +Ordner/Dateien, die nur links existieren +Folders/files that exist on right side only +Ordner/Dateien, die nur rechts existieren +FreeFileSync (Date: +FreeFileSync (Datum: +FreeFileSync - Folder Synchronization +FreeFileSync - Dateisynchronisation +FreeFileSync at Sourceforge +FreeFileSync bei Sourceforge +Help +Hilfe +Hide filtered items +Gefilterte Elemente ausblenden +Hide further error messages +Weitere Fehlermeldungen unterdrücken +Hide further messages during current process +Weitere Meldungen während dieser Operation ausblenden +Homepage: +Homepage: +If errors occur during folder comparison or synchronization they are ignored and the process continues.\n +Wenn Fehler während des Vergleichs oder der Synchronisation auftreten, werden diese ignoriert und der Vorgang fortgesetzt.\n +If you like FFS: +FFS unterstützen: +Include +Einschließen +Information +Information +It was not possible to gain access to Recycle Bin!\n\nIt's likely that you are not using Windows XP. (Probably Vista)\nIf you want this feature included, please contact the author. :) +Die Papierkorbfunktion steht nicht zur Verfügung!\n\nWahrscheinlich ist das aktuelle Betriebssystem nicht Windows XP. (Möglicherweise Vista)\nWenn Sie diese Funktion benötigen kontaktieren Sie bitte den Autor. :) +Items completed: +Elemente komplett: +Legend\n +Legende\n +Log-messages: +Lognachrichten: +Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. +Backup des linken Ordners erstellen: Der rechte Ordner wird dabei überschrieben und nach der Synchronisation dem linken exakt gleichen. +Nothing to synchronize. Both directories seem to contain the same data! +Nichts zu synchronisieren. Beide Verzeichnisse scheinen dieselben Daten zu enthalten! +OK +OK +One way -> +Nach rechts -> +Only files/directories that pass filtering will be relevant for synchronization.\n\n1. Enter full file or directory names separated by ';'.\n2. Wildcard characters '*' and '?' are supported.\n3. Case sensitive expressions!\n\nExample: *.tmp;C:\\data\\dummy.log;*filename*;*directory* +Nur Dateien/Ordner, die zu den Filtereinstellungen passen, werden bei der\nSynchronisation berücksichtigt.\n\n1. Komplette Datei- oder Verzeichnisnamen getrennt durch ';' eingeben.\n2. Die Platzhalter '*' und '?' werden unterstützt.\n3. Groß-/Kleinschreibung wird unterschieden!\n\nBeispiel: *.tmp;C:\\data\\dummy.log;*filename*;*directory* +Open synchronization dialog +Zeige Synchronisationseinstellungen +Please select directories for both sides! +Bitte für beide Seiten ein Verzeichnis wählen! +Press button to activate filter +Auswählen, um Filter zu aktivieren +Quit +Beenden +Relative path +Relativer Pfad +Result +Ergebnis +Retry +Wiederholen +Running... +Gestarted... +Scanning files/folders: +Scanne Dateien/Ordner: +Select a folder +Verzeichnis wählen +Select variant: +Variante auswählen: +Set filter for synchronization +Filter einstellen +Size +Größe +Source code written completely in C++ utilizing:\n\nMinGW \t\t- Windows port of GNU Compiler Collection\nwxWidgets \t- Open-Source GUI framework\nwxFormBuilder\t- wxWidgets GUI-builder\nGMP \t\t- arithmetic calculations\nCodeBlocks \t- Open-Source IDE\n\n by ZenJu +Sourcecode komplett in C++ geschrieben unter Verwendung von:\n\nMinGW \t\t- Windows-Port der GNU Compiler Collection\nwxWidgets \t- Open-Source GUI-Framework\nwxFormBuilder\t- wxWidgets GUI-Builder\nGMP \t\t- Arithmetische Berechnungen\nCodeBlocks \t- Open-Source IDE\n\n ZenJu +Specify algorithm to test if files are equal:\n\n\t\tSIZEDATE: check filesize and date\n\t\tCONTENT: check file content\n +Methode angeben, um gleiche Dateien zu erkennen:\n\n\t\tSIZEDATE: Prüfung auf Dateigröße und -datum\n\t\tCONTENT: Prüfung auf Dateiinhalt\n +Specify names to be excluded separated by ';'. Wildcards '*' and '?' are supported. Default: \"\"\n +Auszuschließende Namen, getrennt durch ';', angeben. Platzhalter '*' und '?' werden unterstützt. Standard: \"\"\n +Specify names to be included separated by ';'. Wildcards '*' and '?' are supported. Default: \"*\"\n +Einzuschließende Namen, getrennt durch ';', angeben. Platzhalter '*' und '?' werden unterstützt. Standard: \"*\"\n +Specify the sync-direction used for each type of file by a string of five chars:\n\n\t\tChar 1: Folders/files that exist on left side only\n\t\tChar 2: Folders/files that exist on right side only\n\t\tChar 3: Files that exist on both sides, left one is newer\n\t\tChar 4: Files that exist on both sides, right one is newer\n\t\tChar 5: Files that exist on both sides and are different\n\n\t\tSync-direction: L: left, R: right, N: none\n +Synchronisationseinstellungen durch Zeichenkette der Länge 5 spezifizieren:\n\n\t\t1. Zeichen: Ordner/Dateien, die nur links existieren\n\t\t2. Zeichen: Ordner/Dateien, die nur rechts existieren\n\t\t3. Zeichen: Dateien, die auf beiden Seiten existieren; linke Datei ist neuer\n\t\t4. Zeichen: Dateien, die auf beiden Seiten existieren; rechte Datei ist neuer\n\t\t5. Zeichen: Dateien, die auf beiden Seiten existieren und verschieden sind\n\n\t\tSynchronisationsrichtung: L: links, R: rechts, N: nichts tun\n +Start synchronizing files +Beginne Synchronisation der Daten +Swap sides +Vertausche Seiten +Synchronization completed! +Synchronisation abgeschlossen! +Synchronization settings +Synchronisationseinstellungen +Synchronization status +Synchronisation: Status +Synchronize both sides simultaneously: Copy new or updated files in both directions. +Beide Seiten gleichzeitig synchronisieren: Kopiere neue oder aktualisierte Dateien auf die jeweils andere Seite. +Two way <-> +Beidseitig <-> +Unable to create logfile! +Fehler beim Erstellen der Logdatei! +Unable to load Resources.dat! +Fehler beim Laden von Resources.dat! +Use Recycle Bin +Papierkorb verwenden +Use Recycle Bin when deleting or overwriting files during synchronization +Papierkorb für zu löschende oder überschreibende Dateien nutzen +Warning +Warnung +Warning: Synchronization failed for +Warnung: Synchronisation fehlgeschlagen für +\n\nContinue with next object, retry or abort comparison? +\n\nMit nächstem Objekt fortsetzen, wiederholen oder abbrechen? +\n\nContinue with next object, retry or abort synchronization? +\n\nMit nächstem Objekt fortsetzen, wiederholen oder abbrechen? +\n\nSkip this directory and continue synchronization? +\n\nDieses Verzeichnis überspringen und mit Synchronisation fortfahren? +\n\nSkip this file and continue synchronization? +\n\nDiese Datei überspringen und mit Synchronisation fortfahren? +\tDo not show UI messages but write to a logfile instead\n\nExamples:\n\n1.) FreeFileSync -cmp SIZEDATE -cfg RRRRR C:\\Source C:\\Target\n2.) FreeFileSync -cmp sizedate -cfg rlrln c:\\dir1 c:\\dir2 -incl *.doc\n\n1: Creates a mirror backup of the left directory\n2: Synchronizes all *.doc files from both directories simultaneously\n\n +\tKeine UI-Meldungen anzeigen, sondern eine Logdatei schreiben\n\nBeispiele:\n\n1.) FreeFileSync -cmp SIZEDATE -cfg RRRRR C:\\Source C:\\Target\n2.) FreeFileSync -cmp sizedate -cfg rlrln c:\\dir1 c:\\dir2 -incl *.doc\n\n1: Erzeugt ein Backup des linken Verzeichnisses\n2: Synchronisiert alle *.doc Dateien aus beiden Verzeichnissen\n\n +|> file on right side only\n +|> Datei existiert nur rechts\n diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp new file mode 100644 index 00000000..76e22441 --- /dev/null +++ b/library/CustomGrid.cpp @@ -0,0 +1,335 @@ +#include "CustomGrid.h" + +const unsigned int MinimumRows = 15; + +//class containing pure grid data: basically the same as wxGridStringTable, but adds cell formatting +class CustomGridTableBase : public wxGridStringTable +{ +public: + CustomGridTableBase(int numRows, int numCols) : wxGridStringTable(numRows, numCols), gridIdentifier(0), currentUI_ViewPtr(0), lastNrRows(MinimumRows) + { + lightBlue = new wxColour(80, 110, 255); + } + + ~CustomGridTableBase() + { + delete lightBlue; + } + + + void setGridDataTable(UI_Grid* currentUI_ViewPtr) + { + this->currentUI_ViewPtr = currentUI_ViewPtr; + } + + void SetGridIdentifier(int id) + { + gridIdentifier = id; + } + +//########################################################################### +//grid standard input output methods, redirected directly to UIGrid to improve performance + + virtual int GetNumberRows() + { + if (currentUI_ViewPtr) + return max(currentUI_ViewPtr->size(), MinimumRows); + return MinimumRows; //grid is initialized with this number of rows + } + + virtual bool IsEmptyCell( int row, int col ) + { + return (GetValue(row, col) == wxEmptyString); + } + + virtual wxString GetValue( int row, int col ) + { + if (currentUI_ViewPtr) + { + if (currentUI_ViewPtr->size() > unsigned(row)) + { + switch (gridIdentifier) + { + case 1: + if (4 > col) + { + switch (col) + { + case 0: + return (*currentUI_ViewPtr)[row].leftFilename; + case 1: + return (*currentUI_ViewPtr)[row].leftRelativePath; + case 2: + return (*currentUI_ViewPtr)[row].leftSize; + case 3: + return (*currentUI_ViewPtr)[row].leftDate; + } + } + break; + + case 2: + if (4 > col) + { + switch (col) + { + case 0: + return (*currentUI_ViewPtr)[row].rightFilename; + case 1: + return (*currentUI_ViewPtr)[row].rightRelativePath; + case 2: + return (*currentUI_ViewPtr)[row].rightSize; + case 3: + return (*currentUI_ViewPtr)[row].rightDate; + } + } + break; + + case 3: + if (1 > col) + { + return (*currentUI_ViewPtr)[row].cmpResult; + } + break; + + default: + break; + } + } + } + //if data not found in UIgrid table: + return wxEmptyString; + } + + virtual void SetValue( int row, int col, const wxString& value ) + { + assert (false); //should not be used, since values are retrieved directly from currentUI_ViewPtr + } + virtual void Clear() + { + assert (false); // we don't want to use this, since the visible grid is directly connected to currentUI_ViewPtr} + } + virtual bool InsertRows( size_t pos = 0, size_t numRows = 1 ) + { + assert (false); // we don't want to use this, since the visible grid is directly connected to currentUI_ViewPtr} + return true; + } + virtual bool AppendRows( size_t numRows = 1 ) + { + assert (false); // we don't want to use this, since the visible grid is directly connected to currentUI_ViewPtr} + return true; + } + virtual bool DeleteRows( size_t pos = 0, size_t numRows = 1 ) + { + assert (false); // we don't want to use this, since the visible grid is directly connected to currentUI_ViewPtr} + return true; + } + + //update dimensions of grid: no need for InsertRows, AppendRows, DeleteRows anymore!!! + void updateGridSizes() + { + if (currentUI_ViewPtr) + { + int currentNrRows = GetNumberRows(); + + if (lastNrRows < currentNrRows) + { + if ( GetView() ) + { + wxGridTableMessage msg(this, + wxGRIDTABLE_NOTIFY_ROWS_APPENDED, + currentNrRows - lastNrRows); + + GetView()->ProcessTableMessage( msg ); + } + } + else if (lastNrRows > currentNrRows) + { + if ( GetView() ) + { + wxGridTableMessage msg(this, + wxGRIDTABLE_NOTIFY_ROWS_DELETED, + 0, + lastNrRows - currentNrRows); + + GetView()->ProcessTableMessage( msg ); + } + } + lastNrRows = currentNrRows; + } + } +//########################################################################### + + + bool markThisRow(int row) + { + if (currentUI_ViewPtr) + { + if (currentUI_ViewPtr->size() > unsigned(row)) + { + if ((*currentUI_ViewPtr)[row].cmpResult == ConstFilteredOut) + return true; + } + } + return false; + } + + wxGridCellAttr* GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind) + { + wxGridCellAttr* result = wxGridTableBase::GetAttr(row, col, kind); + + // MARK FILTERED ROWS: + if (result) + { //if kind is not a cell or row attribute, we have to clone the cell attribute, since we don't want to change e.g. all column attribs + if (result->GetKind() != wxGridCellAttr::Cell && result->GetKind() != wxGridCellAttr::Row) + { + wxGridCellAttr* attr = result->Clone(); + result->DecRef(); + result = attr; + } + + if (markThisRow(row)) + result->SetBackgroundColour(*lightBlue); + else + result->SetBackgroundColour(*wxWHITE); + } + else + { + result = new wxGridCellAttr; + if (markThisRow(row)) + result->SetBackgroundColour(*lightBlue); + } + + return result; + } + +private: + wxColour* lightBlue; + int gridIdentifier; + UI_Grid* currentUI_ViewPtr; //(fast) access to underlying grid data :) + int lastNrRows; +}; + + + +//######################################################################################################## + +CustomGrid::CustomGrid( wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) + : wxGrid(parent, id, pos, size, style, name), + scrollbarsEnabled(true), + m_grid1(0), m_grid2(0), m_grid3(0), + gridDataTable(0), + currentSortColumn(-1), + sortMarker(0) {} + +CustomGrid::~CustomGrid() {} + +bool CustomGrid::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) +{ + //use custom wxGridTableBase class for management of large sets of formatted data. + //This is done in CreateGrid instead of SetTable method since source code is generated and wxFormbuilder invokes CreatedGrid by default. + + gridDataTable = new CustomGridTableBase(numRows, numCols); + SetTable(gridDataTable, true, selmode); //give ownership to CustomGrid: gridDataTable is deleted automatically in CustomGrid destructor + return true; +} + + +void CustomGrid::deactivateScrollbars() +{ + scrollbarsEnabled = false; +} + + +//overwrite virtual method to finally get rid of the scrollbars +void CustomGrid::SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh) +{ + if (scrollbarsEnabled) + wxWindow::SetScrollbar(orientation, position, thumbSize, range, refresh); + else + wxWindow::SetScrollbar(orientation, 0, 0, 0, refresh); +} + + +//this method is called when grid view changes: useful for parallel updating of multiple grids +void CustomGrid::DoPrepareDC(wxDC& dc) +{ + wxScrollHelper::DoPrepareDC(dc); + + int x, y = 0; + if (leadingPanel == 1 && this == m_grid1) //avoid back coupling + { + GetViewStart(&x, &y); + m_grid2->Scroll(x, y); + m_grid3->Scroll(-1, y); //scroll in y-direction only + } + else if (leadingPanel == 2 && this == m_grid2) //avoid back coupling + { + GetViewStart(&x, &y); + m_grid1->Scroll(x, y); + m_grid3->Scroll(-1, y); + } + else if (leadingPanel == 3 && this == m_grid3) //avoid back coupling + { + GetViewStart(&x, &y); + m_grid1->Scroll(-1, y); + m_grid2->Scroll(-1, y); + } +} + +//these classes will scroll together, hence the name ;) +void CustomGrid::setScrollFriends(CustomGrid* grid1, CustomGrid* grid2, CustomGrid* grid3) +{ + m_grid1 = grid1; + m_grid2 = grid2; + m_grid3 = grid3; + + assert(gridDataTable); + if (this == m_grid1) + gridDataTable->SetGridIdentifier(1); + else if (this == m_grid2) + gridDataTable->SetGridIdentifier(2); + else if (this == m_grid3) + gridDataTable->SetGridIdentifier(3); + else + assert (false); +} + + +void CustomGrid::setGridDataTable(UI_Grid* currentUI_ViewPtr) +{ + //set underlying grid data + assert(gridDataTable); + gridDataTable->setGridDataTable(currentUI_ViewPtr); +} + + +void CustomGrid::updateGridSizes() +{ + assert(gridDataTable); + gridDataTable->updateGridSizes(); +} + + +void CustomGrid::setSortMarker(const int sortColumn, const wxBitmap* bitmap) +{ + currentSortColumn = sortColumn; + sortMarker = bitmap; +} + + +void CustomGrid::DrawColLabel( wxDC& dc, int col ) +{ + assert(0 <= col && col < 4); + + wxGrid::DrawColLabel(dc, col); + + if (col == currentSortColumn) + { + dc.DrawBitmap(*sortMarker, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border + } +} diff --git a/library/CustomGrid.h b/library/CustomGrid.h new file mode 100644 index 00000000..93a378b4 --- /dev/null +++ b/library/CustomGrid.h @@ -0,0 +1,62 @@ +#ifndef CUSTOMGRID_H_INCLUDED +#define CUSTOMGRID_H_INCLUDED + +#include "../ui/MainDialog.h" +#include <vector> +#include <wx/grid.h> + +using namespace std; + +extern int leadingPanel; + +class CustomGridTableBase; + +//################################################################################## + +class CustomGrid : public wxGrid +{ +public: + CustomGrid( wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxWANTS_CHARS, + const wxString& name = wxGridNameStr ); + + ~CustomGrid(); + + bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); + + void deactivateScrollbars(); + + //overwrite virtual method to finally get rid of the scrollbars + void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh = true); + + //this method is called when grid view changes: useful for parallel updating of multiple grids + void DoPrepareDC(wxDC& dc); + + void setScrollFriends(CustomGrid* grid1, CustomGrid* grid2, CustomGrid* grid3); + + void setGridDataTable(UI_Grid* currentUI_ViewPtr); + + void updateGridSizes(); + + //set sort direction indicator on UI + void setSortMarker(const int sortColumn, const wxBitmap* bitmap = &wxNullBitmap); + + void DrawColLabel( wxDC& dc, int col ); + +private: + bool scrollbarsEnabled; + + CustomGrid* m_grid1; + CustomGrid* m_grid2; + CustomGrid* m_grid3; + + CustomGridTableBase* gridDataTable; + + int currentSortColumn; + const wxBitmap* sortMarker; +}; + +#endif // CUSTOMGRID_H_INCLUDED diff --git a/library/GMP/include/gmp.h b/library/GMP/include/gmp.h new file mode 100644 index 00000000..1268c74d --- /dev/null +++ b/library/GMP/include/gmp.h @@ -0,0 +1,2182 @@ +/* Definitions for GNU multiple precision functions. -*- mode: c -*- + +Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, +2004, 2005, 2006, 2007 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +#ifndef __GMP_H__ + +#if defined (__cplusplus) +#include <iosfwd> /* for std::istream, std::ostream, std::string */ +#endif + + +/* Instantiated by configure. */ +#if ! defined (__GMP_WITHIN_CONFIGURE) +#define __GMP_BITS_PER_MP_LIMB 32 +#define __GMP_HAVE_HOST_CPU_FAMILY_power 0 +#define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 0 +#define GMP_LIMB_BITS 32 +#define GMP_NAIL_BITS 0 +#endif +#define GMP_NUMB_BITS (GMP_LIMB_BITS - GMP_NAIL_BITS) +#define GMP_NUMB_MASK ((~ __GMP_CAST (mp_limb_t, 0)) >> GMP_NAIL_BITS) +#define GMP_NUMB_MAX GMP_NUMB_MASK +#define GMP_NAIL_MASK (~ GMP_NUMB_MASK) + + +/* The following (everything under ifndef __GNU_MP__) must be identical in + gmp.h and mp.h to allow both to be included in an application or during + the library build. */ +#ifndef __GNU_MP__ +#define __GNU_MP__ 4 + +#define __need_size_t /* tell gcc stddef.h we only want size_t */ +#if defined (__cplusplus) +#include <cstddef> /* for size_t */ +#else +#include <stddef.h> /* for size_t */ +#endif +#undef __need_size_t + +/* Instantiated by configure. */ +#if ! defined (__GMP_WITHIN_CONFIGURE) +/* #undef _LONG_LONG_LIMB */ +#define __GMP_LIBGMP_DLL 0 +#endif + + +/* __STDC__ - some ANSI compilers define this only to 0, hence the use of + "defined" and not "__STDC__-0". In particular Sun workshop C 5.0 + sets __STDC__ to 0, but requires "##" for token pasting. + + _AIX - gnu ansidecl.h asserts that all known AIX compilers are ANSI but + don't always define __STDC__. + + __DECC - current versions of DEC C (5.9 for instance) for alpha are ANSI, + but don't define __STDC__ in their default mode. Don't know if old + versions might have been K&R, but let's not worry about that unless + someone is still using one. + + _mips - gnu ansidecl.h says the RISC/OS MIPS compiler is ANSI in SVR4 + mode, but doesn't define __STDC__. + + _MSC_VER - Microsoft C is ANSI, but __STDC__ is undefined unless the /Za + option is given (in which case it's 1). + + _WIN32 - tested for by gnu ansidecl.h, no doubt on the assumption that + all w32 compilers are ansi. + + Note: This same set of tests is used by gen-psqr.c and + demos/expr/expr-impl.h, so if anything needs adding, then be sure to + update those too. */ + +#if defined (__STDC__) \ + || defined (__cplusplus) \ + || defined (_AIX) \ + || defined (__DECC) \ + || (defined (__mips) && defined (_SYSTYPE_SVR4)) \ + || defined (_MSC_VER) \ + || defined (_WIN32) +#define __GMP_HAVE_CONST 1 +#define __GMP_HAVE_PROTOTYPES 1 +#define __GMP_HAVE_TOKEN_PASTE 1 +#else +#define __GMP_HAVE_CONST 0 +#define __GMP_HAVE_PROTOTYPES 0 +#define __GMP_HAVE_TOKEN_PASTE 0 +#endif + + +#if __GMP_HAVE_CONST +#define __gmp_const const +#define __gmp_signed signed +#else +#define __gmp_const +#define __gmp_signed +#endif + + +/* __GMP_DECLSPEC supports Windows DLL versions of libgmp, and is empty in + all other circumstances. + + When compiling objects for libgmp, __GMP_DECLSPEC is an export directive, + or when compiling for an application it's an import directive. The two + cases are differentiated by __GMP_WITHIN_GMP defined by the GMP Makefiles + (and not defined from an application). + + __GMP_DECLSPEC_XX is similarly used for libgmpxx. __GMP_WITHIN_GMPXX + indicates when building libgmpxx, and in that case libgmpxx functions are + exports, but libgmp functions which might get called are imports. + + libmp.la uses __GMP_DECLSPEC, just as if it were libgmp.la. libgmp and + libmp don't call each other, so there's no conflict or confusion. + + Libtool DLL_EXPORT define is not used. + + There's no attempt to support GMP built both static and DLL. Doing so + would mean applications would have to tell us which of the two is going + to be used when linking, and that seems very tedious and error prone if + using GMP by hand, and equally tedious from a package since autoconf and + automake don't give much help. + + __GMP_DECLSPEC is required on all documented global functions and + variables, the various internals in gmp-impl.h etc can be left unadorned. + But internals used by the test programs or speed measuring programs + should have __GMP_DECLSPEC, and certainly constants or variables must + have it or the wrong address will be resolved. + + In gcc __declspec can go at either the start or end of a prototype. + + In Microsoft C __declspec must go at the start, or after the type like + void __declspec(...) *foo()". There's no __dllexport or anything to + guard against someone foolish #defining dllexport. _export used to be + available, but no longer. + + In Borland C _export still exists, but needs to go after the type, like + "void _export foo();". Would have to change the __GMP_DECLSPEC syntax to + make use of that. Probably more trouble than it's worth. */ + +#if defined (__GNUC__) +#define __GMP_DECLSPEC_EXPORT __declspec(__dllexport__) +#define __GMP_DECLSPEC_IMPORT __declspec(__dllimport__) +#endif +#if defined (_MSC_VER) || defined (__BORLANDC__) +#define __GMP_DECLSPEC_EXPORT __declspec(dllexport) +#define __GMP_DECLSPEC_IMPORT __declspec(dllimport) +#endif +#ifdef __WATCOMC__ +#define __GMP_DECLSPEC_EXPORT __export +#define __GMP_DECLSPEC_IMPORT __import +#endif +#ifdef __IBMC__ +#define __GMP_DECLSPEC_EXPORT _Export +#define __GMP_DECLSPEC_IMPORT _Import +#endif + +#if __GMP_LIBGMP_DLL +#if __GMP_WITHIN_GMP +/* compiling to go into a DLL libgmp */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into an application which will link to a DLL libgmp */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC +#endif + + +#ifdef __GMP_SHORT_LIMB +typedef unsigned int mp_limb_t; +typedef int mp_limb_signed_t; +#else +#ifdef _LONG_LONG_LIMB +typedef unsigned long long int mp_limb_t; +typedef long long int mp_limb_signed_t; +#else +typedef unsigned long int mp_limb_t; +typedef long int mp_limb_signed_t; +#endif +#endif + +/* For reference, note that the name __mpz_struct gets into C++ mangled + function names, which means although the "__" suggests an internal, we + must leave this name for binary compatibility. */ +typedef struct +{ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the _mp_d field. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; + +#endif /* __GNU_MP__ */ + + +typedef __mpz_struct MP_INT; /* gmp 1 source compatibility */ +typedef __mpz_struct mpz_t[1]; + +typedef mp_limb_t * mp_ptr; +typedef __gmp_const mp_limb_t * mp_srcptr; +#if defined (_CRAY) && ! defined (_CRAYMPP) +/* plain `int' is much faster (48 bits) */ +#define __GMP_MP_SIZE_T_INT 1 +typedef int mp_size_t; +typedef int mp_exp_t; +#else +#define __GMP_MP_SIZE_T_INT 0 +typedef long int mp_size_t; +typedef long int mp_exp_t; +#endif + +typedef struct +{ + __mpz_struct _mp_num; + __mpz_struct _mp_den; +} __mpq_struct; + +typedef __mpq_struct MP_RAT; /* gmp 1 source compatibility */ +typedef __mpq_struct mpq_t[1]; + +typedef struct +{ + int _mp_prec; /* Max precision, in number of `mp_limb_t's. + Set by mpf_init and modified by + mpf_set_prec. The area pointed to by the + _mp_d field contains `prec' + 1 limbs. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpf_struct; + +/* typedef __mpf_struct MP_FLOAT; */ +typedef __mpf_struct mpf_t[1]; + +/* Available random number generation algorithms. */ +typedef enum +{ + GMP_RAND_ALG_DEFAULT = 0, + GMP_RAND_ALG_LC = GMP_RAND_ALG_DEFAULT /* Linear congruential. */ +} gmp_randalg_t; + +/* Random state struct. */ +typedef struct +{ + mpz_t _mp_seed; /* _mp_d member points to state of the generator. */ + gmp_randalg_t _mp_alg; /* Currently unused. */ + union + { + void *_mp_lc; /* Pointer to function pointers structure. */ + } _mp_algdata; +} __gmp_randstate_struct; +typedef __gmp_randstate_struct gmp_randstate_t[1]; + +/* Types for function declarations in gmp files. */ +/* ??? Should not pollute user name space with these ??? */ +typedef __gmp_const __mpz_struct *mpz_srcptr; +typedef __mpz_struct *mpz_ptr; +typedef __gmp_const __mpf_struct *mpf_srcptr; +typedef __mpf_struct *mpf_ptr; +typedef __gmp_const __mpq_struct *mpq_srcptr; +typedef __mpq_struct *mpq_ptr; + + +/* This is not wanted in mp.h, so put it outside the __GNU_MP__ common + section. */ +#if __GMP_LIBGMP_DLL +#if __GMP_WITHIN_GMPXX +/* compiling to go into a DLL libgmpxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into a application which will link to a DLL libgmpxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC_XX +#endif + + +#if __GMP_HAVE_PROTOTYPES +#define __GMP_PROTO(x) x +#else +#define __GMP_PROTO(x) () +#endif + +#ifndef __MPN +#if __GMP_HAVE_TOKEN_PASTE +#define __MPN(x) __gmpn_##x +#else +#define __MPN(x) __gmpn_/**/x +#endif +#endif + +/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, + <iostream> defines EOF but not FILE. */ +#if defined (FILE) \ + || defined (H_STDIO) \ + || defined (_H_STDIO) /* AIX */ \ + || defined (_STDIO_H) /* glibc, Sun, SCO */ \ + || defined (_STDIO_H_) /* BSD, OSF */ \ + || defined (__STDIO_H) /* Borland */ \ + || defined (__STDIO_H__) /* IRIX */ \ + || defined (_STDIO_INCLUDED) /* HPUX */ \ + || defined (__dj_include_stdio_h_) /* DJGPP */ \ + || defined (_FILE_DEFINED) /* Microsoft */ \ + || defined (__STDIO__) /* Apple MPW MrC */ \ + || defined (_MSL_STDIO_H) /* Metrowerks */ \ + || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ + || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ +#define _GMP_H_HAVE_FILE 1 +#endif + +/* In ISO C, if a prototype involving "struct obstack *" is given without + that structure defined, then the struct is scoped down to just the + prototype, causing a conflict if it's subsequently defined for real. So + only give prototypes if we've got obstack.h. */ +#if defined (_OBSTACK_H) /* glibc <obstack.h> */ +#define _GMP_H_HAVE_OBSTACK 1 +#endif + +/* The prototypes for gmp_vprintf etc are provided only if va_list is + available, via an application having included <stdarg.h> or <varargs.h>. + Usually va_list is a typedef so can't be tested directly, but C99 + specifies that va_start is a macro (and it was normally a macro on past + systems too), so look for that. + + <stdio.h> will define some sort of va_list for vprintf and vfprintf, but + let's not bother trying to use that since it's not standard and since + application uses for gmp_vprintf etc will almost certainly require the + whole <stdarg.h> or <varargs.h> anyway. */ + +#ifdef va_start +#define _GMP_H_HAVE_VA_LIST 1 +#endif + +/* Test for gcc >= maj.min, as per __GNUC_PREREQ in glibc */ +#if defined (__GNUC__) && defined (__GNUC_MINOR__) +#define __GMP_GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GMP_GNUC_PREREQ(maj, min) 0 +#endif + +/* "pure" is in gcc 2.96 and up, see "(gcc)Function Attributes". Basically + it means a function does nothing but examine its arguments and memory + (global or via arguments) to generate a return value, but changes nothing + and has no side-effects. __GMP_NO_ATTRIBUTE_CONST_PURE lets + tune/common.c etc turn this off when trying to write timing loops. */ +#if __GMP_GNUC_PREREQ (2,96) && ! defined (__GMP_NO_ATTRIBUTE_CONST_PURE) +#define __GMP_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +#define __GMP_ATTRIBUTE_PURE +#endif + + +/* __GMP_CAST allows us to use static_cast in C++, so our macros are clean + to "g++ -Wold-style-cast". + + Casts in "extern inline" code within an extern "C" block don't induce + these warnings, so __GMP_CAST only needs to be used on documented + macros. */ + +#ifdef __cplusplus +#define __GMP_CAST(type, expr) (static_cast<type> (expr)) +#else +#define __GMP_CAST(type, expr) ((type) (expr)) +#endif + + +/* An empty "throw ()" means the function doesn't throw any C++ exceptions, + this can save some stack frame info in applications. + + Currently it's given only on functions which never divide-by-zero etc, + don't allocate memory, and are expected to never need to allocate memory. + This leaves open the possibility of a C++ throw from a future GMP + exceptions scheme. + + mpz_set_ui etc are omitted to leave open the lazy allocation scheme + described in doc/tasks.html. mpz_get_d etc are omitted to leave open + exceptions for float overflows. + + Note that __GMP_NOTHROW must be given on any inlines the same as on their + prototypes (for g++ at least, where they're used together). Note also + that g++ 3.0 demands that __GMP_NOTHROW is before other attributes like + __GMP_ATTRIBUTE_PURE. */ + +#if defined (__cplusplus) +#define __GMP_NOTHROW throw () +#else +#define __GMP_NOTHROW +#endif + + +/* PORTME: What other compilers have a useful "extern inline"? "static + inline" would be an acceptable substitute if the compiler (or linker) + discards unused statics. */ + +/* gcc has __inline__ in all modes, including strict ansi. Give a prototype + for an inline too, so as to correctly specify "dllimport" on windows, in + case the function is called rather than inlined. + GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. */ +#ifdef __GNUC__ +#ifdef __GNUC_STDC_INLINE__ +#define __GMP_EXTERN_INLINE extern __inline__ __attribute__ ((__gnu_inline__)) +#else +#define __GMP_EXTERN_INLINE extern __inline__ +#endif +#define __GMP_INLINE_PROTOTYPES 1 +#endif + +/* DEC C (eg. version 5.9) supports "static __inline foo()", even in -std1 + strict ANSI mode. Inlining is done even when not optimizing (ie. -O0 + mode, which is the default), but an unnecessary local copy of foo is + emitted unless -O is used. "extern __inline" is accepted, but the + "extern" appears to be ignored, ie. it becomes a plain global function + but which is inlined within its file. Don't know if all old versions of + DEC C supported __inline, but as a start let's do the right thing for + current versions. */ +#ifdef __DECC +#define __GMP_EXTERN_INLINE static __inline +#endif + +/* SCO OpenUNIX 8 cc supports "static inline foo()" but not in -Xc strict + ANSI mode (__STDC__ is 1 in that mode). Inlining only actually takes + place under -O. Without -O "foo" seems to be emitted whether it's used + or not, which is wasteful. "extern inline foo()" isn't useful, the + "extern" is apparently ignored, so foo is inlined if possible but also + emitted as a global, which causes multiple definition errors when + building a shared libgmp. */ +#ifdef __SCO_VERSION__ +#if __SCO_VERSION__ > 400000000 && __STDC__ != 1 \ + && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE static inline +#endif +#endif + +/* C++ always has "inline" and since it's a normal feature the linker should + discard duplicate non-inlined copies, or if it doesn't then that's a + problem for everyone, not just GMP. */ +#if defined (__cplusplus) && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE inline +#endif + +/* Don't do any inlining within a configure run, since if the compiler ends + up emitting copies of the code into the object file it can end up + demanding the various support routines (like mpn_popcount) for linking, + making the "alloca" test and perhaps others fail. And on hppa ia64 a + pre-release gcc 3.2 was seen not respecting the "extern" in "extern + __inline__", triggering this problem too. */ +#if defined (__GMP_WITHIN_CONFIGURE) && ! __GMP_WITHIN_CONFIGURE_INLINE +#undef __GMP_EXTERN_INLINE +#endif + +/* By default, don't give a prototype when there's going to be an inline + version. Note in particular that Cray C++ objects to the combination of + prototype and inline. */ +#ifdef __GMP_EXTERN_INLINE +#ifndef __GMP_INLINE_PROTOTYPES +#define __GMP_INLINE_PROTOTYPES 0 +#endif +#else +#define __GMP_INLINE_PROTOTYPES 1 +#endif + + +#define __GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) +#define __GMP_MAX(h,i) ((h) > (i) ? (h) : (i)) + +/* __GMP_USHRT_MAX is not "~ (unsigned short) 0" because short is promoted + to int by "~". */ +#define __GMP_UINT_MAX (~ (unsigned) 0) +#define __GMP_ULONG_MAX (~ (unsigned long) 0) +#define __GMP_USHRT_MAX ((unsigned short) ~0) + + +/* __builtin_expect is in gcc 3.0, and not in 2.95. */ +#if __GMP_GNUC_PREREQ (3,0) +#define __GMP_LIKELY(cond) __builtin_expect ((cond) != 0, 1) +#define __GMP_UNLIKELY(cond) __builtin_expect ((cond) != 0, 0) +#else +#define __GMP_LIKELY(cond) (cond) +#define __GMP_UNLIKELY(cond) (cond) +#endif + +#ifdef _CRAY +#define __GMP_CRAY_Pragma(str) _Pragma (str) +#else +#define __GMP_CRAY_Pragma(str) +#endif + + +/* Allow direct user access to numerator and denominator of a mpq_t object. */ +#define mpq_numref(Q) (&((Q)->_mp_num)) +#define mpq_denref(Q) (&((Q)->_mp_den)) + + +#if defined (__cplusplus) +extern "C" +{ +#ifdef _GMP_H_HAVE_FILE + using std::FILE; +#endif +#endif + +#define mp_set_memory_functions __gmp_set_memory_functions + __GMP_DECLSPEC void mp_set_memory_functions __GMP_PROTO ((void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t))) __GMP_NOTHROW; + +#define mp_get_memory_functions __gmp_get_memory_functions + __GMP_DECLSPEC void mp_get_memory_functions __GMP_PROTO ((void *(**) (size_t), + void *(**) (void *, size_t, size_t), + void (**) (void *, size_t))) __GMP_NOTHROW; + +#define mp_bits_per_limb __gmp_bits_per_limb + __GMP_DECLSPEC extern __gmp_const int mp_bits_per_limb; + +#define gmp_errno __gmp_errno + __GMP_DECLSPEC extern int gmp_errno; + +#define gmp_version __gmp_version + __GMP_DECLSPEC extern __gmp_const char * __gmp_const gmp_version; + + + /**************** Random number routines. ****************/ + + /* obsolete */ +#define gmp_randinit __gmp_randinit + __GMP_DECLSPEC void gmp_randinit __GMP_PROTO ((gmp_randstate_t, gmp_randalg_t, ...)); + +#define gmp_randinit_default __gmp_randinit_default + __GMP_DECLSPEC void gmp_randinit_default __GMP_PROTO ((gmp_randstate_t)); + +#define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp + __GMP_DECLSPEC void gmp_randinit_lc_2exp __GMP_PROTO ((gmp_randstate_t, + mpz_srcptr, unsigned long int, + unsigned long int)); + +#define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size + __GMP_DECLSPEC int gmp_randinit_lc_2exp_size __GMP_PROTO ((gmp_randstate_t, unsigned long)); + +#define gmp_randinit_mt __gmp_randinit_mt + __GMP_DECLSPEC void gmp_randinit_mt __GMP_PROTO ((gmp_randstate_t)); + +#define gmp_randinit_set __gmp_randinit_set + void gmp_randinit_set __GMP_PROTO ((gmp_randstate_t, __gmp_const __gmp_randstate_struct *)); + +#define gmp_randseed __gmp_randseed + __GMP_DECLSPEC void gmp_randseed __GMP_PROTO ((gmp_randstate_t, mpz_srcptr)); + +#define gmp_randseed_ui __gmp_randseed_ui + __GMP_DECLSPEC void gmp_randseed_ui __GMP_PROTO ((gmp_randstate_t, unsigned long int)); + +#define gmp_randclear __gmp_randclear + __GMP_DECLSPEC void gmp_randclear __GMP_PROTO ((gmp_randstate_t)); + +#define gmp_urandomb_ui __gmp_urandomb_ui + unsigned long gmp_urandomb_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); + +#define gmp_urandomm_ui __gmp_urandomm_ui + unsigned long gmp_urandomm_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); + + + /**************** Formatted output routines. ****************/ + +#define gmp_asprintf __gmp_asprintf + __GMP_DECLSPEC int gmp_asprintf __GMP_PROTO ((char **, __gmp_const char *, ...)); + +#define gmp_fprintf __gmp_fprintf +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC int gmp_fprintf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +#endif + +#define gmp_obstack_printf __gmp_obstack_printf +#if defined (_GMP_H_HAVE_OBSTACK) + __GMP_DECLSPEC int gmp_obstack_printf __GMP_PROTO ((struct obstack *, __gmp_const char *, ...)); +#endif + +#define gmp_obstack_vprintf __gmp_obstack_vprintf +#if defined (_GMP_H_HAVE_OBSTACK) && defined (_GMP_H_HAVE_VA_LIST) + __GMP_DECLSPEC int gmp_obstack_vprintf __GMP_PROTO ((struct obstack *, __gmp_const char *, va_list)); +#endif + +#define gmp_printf __gmp_printf + __GMP_DECLSPEC int gmp_printf __GMP_PROTO ((__gmp_const char *, ...)); + +#define gmp_snprintf __gmp_snprintf + __GMP_DECLSPEC int gmp_snprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, ...)); + +#define gmp_sprintf __gmp_sprintf + __GMP_DECLSPEC int gmp_sprintf __GMP_PROTO ((char *, __gmp_const char *, ...)); + +#define gmp_vasprintf __gmp_vasprintf +#if defined (_GMP_H_HAVE_VA_LIST) + __GMP_DECLSPEC int gmp_vasprintf __GMP_PROTO ((char **, __gmp_const char *, va_list)); +#endif + +#define gmp_vfprintf __gmp_vfprintf +#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) + __GMP_DECLSPEC int gmp_vfprintf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +#endif + +#define gmp_vprintf __gmp_vprintf +#if defined (_GMP_H_HAVE_VA_LIST) + __GMP_DECLSPEC int gmp_vprintf __GMP_PROTO ((__gmp_const char *, va_list)); +#endif + +#define gmp_vsnprintf __gmp_vsnprintf +#if defined (_GMP_H_HAVE_VA_LIST) + __GMP_DECLSPEC int gmp_vsnprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, va_list)); +#endif + +#define gmp_vsprintf __gmp_vsprintf +#if defined (_GMP_H_HAVE_VA_LIST) + __GMP_DECLSPEC int gmp_vsprintf __GMP_PROTO ((char *, __gmp_const char *, va_list)); +#endif + + + /**************** Formatted input routines. ****************/ + +#define gmp_fscanf __gmp_fscanf +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC int gmp_fscanf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +#endif + +#define gmp_scanf __gmp_scanf + __GMP_DECLSPEC int gmp_scanf __GMP_PROTO ((__gmp_const char *, ...)); + +#define gmp_sscanf __gmp_sscanf + __GMP_DECLSPEC int gmp_sscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, ...)); + +#define gmp_vfscanf __gmp_vfscanf +#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) + __GMP_DECLSPEC int gmp_vfscanf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +#endif + +#define gmp_vscanf __gmp_vscanf +#if defined (_GMP_H_HAVE_VA_LIST) + __GMP_DECLSPEC int gmp_vscanf __GMP_PROTO ((__gmp_const char *, va_list)); +#endif + +#define gmp_vsscanf __gmp_vsscanf +#if defined (_GMP_H_HAVE_VA_LIST) + __GMP_DECLSPEC int gmp_vsscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, va_list)); +#endif + + + /**************** Integer (i.e. Z) routines. ****************/ + +#define _mpz_realloc __gmpz_realloc +#define mpz_realloc __gmpz_realloc + __GMP_DECLSPEC void *_mpz_realloc __GMP_PROTO ((mpz_ptr, mp_size_t)); + +#define mpz_abs __gmpz_abs +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_abs) + __GMP_DECLSPEC void mpz_abs __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#endif + +#define mpz_add __gmpz_add + __GMP_DECLSPEC void mpz_add __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_add_ui __gmpz_add_ui + __GMP_DECLSPEC void mpz_add_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_addmul __gmpz_addmul + __GMP_DECLSPEC void mpz_addmul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_addmul_ui __gmpz_addmul_ui + __GMP_DECLSPEC void mpz_addmul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_and __gmpz_and + __GMP_DECLSPEC void mpz_and __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_array_init __gmpz_array_init + __GMP_DECLSPEC void mpz_array_init __GMP_PROTO ((mpz_ptr, mp_size_t, mp_size_t)); + +#define mpz_bin_ui __gmpz_bin_ui + __GMP_DECLSPEC void mpz_bin_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_bin_uiui __gmpz_bin_uiui + __GMP_DECLSPEC void mpz_bin_uiui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); + +#define mpz_cdiv_q __gmpz_cdiv_q + __GMP_DECLSPEC void mpz_cdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_cdiv_q_2exp __gmpz_cdiv_q_2exp + __GMP_DECLSPEC void mpz_cdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_cdiv_q_ui __gmpz_cdiv_q_ui + __GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_cdiv_qr __gmpz_cdiv_qr + __GMP_DECLSPEC void mpz_cdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_cdiv_qr_ui __gmpz_cdiv_qr_ui + __GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_cdiv_r __gmpz_cdiv_r + __GMP_DECLSPEC void mpz_cdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_cdiv_r_2exp __gmpz_cdiv_r_2exp + __GMP_DECLSPEC void mpz_cdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_cdiv_r_ui __gmpz_cdiv_r_ui + __GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_cdiv_ui __gmpz_cdiv_ui + __GMP_DECLSPEC unsigned long int mpz_cdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_clear __gmpz_clear + __GMP_DECLSPEC void mpz_clear __GMP_PROTO ((mpz_ptr)); + +#define mpz_clrbit __gmpz_clrbit + __GMP_DECLSPEC void mpz_clrbit __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_cmp __gmpz_cmp + __GMP_DECLSPEC int mpz_cmp __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmp_d __gmpz_cmp_d + __GMP_DECLSPEC int mpz_cmp_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; + +#define _mpz_cmp_si __gmpz_cmp_si + __GMP_DECLSPEC int _mpz_cmp_si __GMP_PROTO ((mpz_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define _mpz_cmp_ui __gmpz_cmp_ui + __GMP_DECLSPEC int _mpz_cmp_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs __gmpz_cmpabs + __GMP_DECLSPEC int mpz_cmpabs __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs_d __gmpz_cmpabs_d + __GMP_DECLSPEC int mpz_cmpabs_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs_ui __gmpz_cmpabs_ui + __GMP_DECLSPEC int mpz_cmpabs_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_com __gmpz_com + __GMP_DECLSPEC void mpz_com __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_combit __gmpz_combit + __GMP_DECLSPEC void mpz_combit __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_congruent_p __gmpz_congruent_p + __GMP_DECLSPEC int mpz_congruent_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_congruent_2exp_p __gmpz_congruent_2exp_p + __GMP_DECLSPEC int mpz_congruent_2exp_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_congruent_ui_p __gmpz_congruent_ui_p + __GMP_DECLSPEC int mpz_congruent_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_divexact __gmpz_divexact + __GMP_DECLSPEC void mpz_divexact __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_divexact_ui __gmpz_divexact_ui + __GMP_DECLSPEC void mpz_divexact_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_divisible_p __gmpz_divisible_p + __GMP_DECLSPEC int mpz_divisible_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_divisible_ui_p __gmpz_divisible_ui_p + __GMP_DECLSPEC int mpz_divisible_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_divisible_2exp_p __gmpz_divisible_2exp_p + __GMP_DECLSPEC int mpz_divisible_2exp_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_dump __gmpz_dump + __GMP_DECLSPEC void mpz_dump __GMP_PROTO ((mpz_srcptr)); + +#define mpz_export __gmpz_export + __GMP_DECLSPEC void *mpz_export __GMP_PROTO ((void *, size_t *, int, size_t, int, size_t, mpz_srcptr)); + +#define mpz_fac_ui __gmpz_fac_ui + __GMP_DECLSPEC void mpz_fac_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_fdiv_q __gmpz_fdiv_q + __GMP_DECLSPEC void mpz_fdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_fdiv_q_2exp __gmpz_fdiv_q_2exp + __GMP_DECLSPEC void mpz_fdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_q_ui __gmpz_fdiv_q_ui + __GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_qr __gmpz_fdiv_qr + __GMP_DECLSPEC void mpz_fdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_fdiv_qr_ui __gmpz_fdiv_qr_ui + __GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_r __gmpz_fdiv_r + __GMP_DECLSPEC void mpz_fdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_fdiv_r_2exp __gmpz_fdiv_r_2exp + __GMP_DECLSPEC void mpz_fdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_r_ui __gmpz_fdiv_r_ui + __GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_ui __gmpz_fdiv_ui + __GMP_DECLSPEC unsigned long int mpz_fdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_fib_ui __gmpz_fib_ui + __GMP_DECLSPEC void mpz_fib_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_fib2_ui __gmpz_fib2_ui + __GMP_DECLSPEC void mpz_fib2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); + +#define mpz_fits_sint_p __gmpz_fits_sint_p + __GMP_DECLSPEC int mpz_fits_sint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_slong_p __gmpz_fits_slong_p + __GMP_DECLSPEC int mpz_fits_slong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_sshort_p __gmpz_fits_sshort_p + __GMP_DECLSPEC int mpz_fits_sshort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_uint_p __gmpz_fits_uint_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_uint_p) + __GMP_DECLSPEC int mpz_fits_uint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_fits_ulong_p __gmpz_fits_ulong_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ulong_p) + __GMP_DECLSPEC int mpz_fits_ulong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_fits_ushort_p __gmpz_fits_ushort_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ushort_p) + __GMP_DECLSPEC int mpz_fits_ushort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_gcd __gmpz_gcd + __GMP_DECLSPEC void mpz_gcd __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_gcd_ui __gmpz_gcd_ui + __GMP_DECLSPEC unsigned long int mpz_gcd_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_gcdext __gmpz_gcdext + __GMP_DECLSPEC void mpz_gcdext __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_get_d __gmpz_get_d + __GMP_DECLSPEC double mpz_get_d __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_get_d_2exp __gmpz_get_d_2exp + __GMP_DECLSPEC double mpz_get_d_2exp __GMP_PROTO ((signed long int *, mpz_srcptr)); + +#define mpz_get_si __gmpz_get_si + __GMP_DECLSPEC /* signed */ long int mpz_get_si __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_get_str __gmpz_get_str + __GMP_DECLSPEC char *mpz_get_str __GMP_PROTO ((char *, int, mpz_srcptr)); + +#define mpz_get_ui __gmpz_get_ui +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_get_ui) + __GMP_DECLSPEC unsigned long int mpz_get_ui __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_getlimbn __gmpz_getlimbn +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_getlimbn) + __GMP_DECLSPEC mp_limb_t mpz_getlimbn __GMP_PROTO ((mpz_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_hamdist __gmpz_hamdist + __GMP_DECLSPEC unsigned long int mpz_hamdist __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_import __gmpz_import + __GMP_DECLSPEC void mpz_import __GMP_PROTO ((mpz_ptr, size_t, int, size_t, int, size_t, __gmp_const void *)); + +#define mpz_init __gmpz_init + __GMP_DECLSPEC void mpz_init __GMP_PROTO ((mpz_ptr)); + +#define mpz_init2 __gmpz_init2 + __GMP_DECLSPEC void mpz_init2 __GMP_PROTO ((mpz_ptr, unsigned long)); + +#define mpz_init_set __gmpz_init_set + __GMP_DECLSPEC void mpz_init_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_init_set_d __gmpz_init_set_d + __GMP_DECLSPEC void mpz_init_set_d __GMP_PROTO ((mpz_ptr, double)); + +#define mpz_init_set_si __gmpz_init_set_si + __GMP_DECLSPEC void mpz_init_set_si __GMP_PROTO ((mpz_ptr, signed long int)); + +#define mpz_init_set_str __gmpz_init_set_str + __GMP_DECLSPEC int mpz_init_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); + +#define mpz_init_set_ui __gmpz_init_set_ui + __GMP_DECLSPEC void mpz_init_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_inp_raw __gmpz_inp_raw +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC size_t mpz_inp_raw __GMP_PROTO ((mpz_ptr, FILE *)); +#endif + +#define mpz_inp_str __gmpz_inp_str +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC size_t mpz_inp_str __GMP_PROTO ((mpz_ptr, FILE *, int)); +#endif + +#define mpz_invert __gmpz_invert + __GMP_DECLSPEC int mpz_invert __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_ior __gmpz_ior + __GMP_DECLSPEC void mpz_ior __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_jacobi __gmpz_jacobi + __GMP_DECLSPEC int mpz_jacobi __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_kronecker mpz_jacobi /* alias */ + +#define mpz_kronecker_si __gmpz_kronecker_si + __GMP_DECLSPEC int mpz_kronecker_si __GMP_PROTO ((mpz_srcptr, long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_kronecker_ui __gmpz_kronecker_ui + __GMP_DECLSPEC int mpz_kronecker_ui __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_si_kronecker __gmpz_si_kronecker + __GMP_DECLSPEC int mpz_si_kronecker __GMP_PROTO ((long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_ui_kronecker __gmpz_ui_kronecker + __GMP_DECLSPEC int mpz_ui_kronecker __GMP_PROTO ((unsigned long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_lcm __gmpz_lcm + __GMP_DECLSPEC void mpz_lcm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_lcm_ui __gmpz_lcm_ui + __GMP_DECLSPEC void mpz_lcm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_legendre mpz_jacobi /* alias */ + +#define mpz_lucnum_ui __gmpz_lucnum_ui + __GMP_DECLSPEC void mpz_lucnum_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_lucnum2_ui __gmpz_lucnum2_ui + __GMP_DECLSPEC void mpz_lucnum2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); + +#define mpz_millerrabin __gmpz_millerrabin + __GMP_DECLSPEC int mpz_millerrabin __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_mod __gmpz_mod + __GMP_DECLSPEC void mpz_mod __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_mod_ui mpz_fdiv_r_ui /* same as fdiv_r because divisor unsigned */ + +#define mpz_mul __gmpz_mul + __GMP_DECLSPEC void mpz_mul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_mul_2exp __gmpz_mul_2exp + __GMP_DECLSPEC void mpz_mul_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_mul_si __gmpz_mul_si + __GMP_DECLSPEC void mpz_mul_si __GMP_PROTO ((mpz_ptr, mpz_srcptr, long int)); + +#define mpz_mul_ui __gmpz_mul_ui + __GMP_DECLSPEC void mpz_mul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_neg __gmpz_neg +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_neg) + __GMP_DECLSPEC void mpz_neg __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#endif + +#define mpz_nextprime __gmpz_nextprime + __GMP_DECLSPEC void mpz_nextprime __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_out_raw __gmpz_out_raw +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC size_t mpz_out_raw __GMP_PROTO ((FILE *, mpz_srcptr)); +#endif + +#define mpz_out_str __gmpz_out_str +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC size_t mpz_out_str __GMP_PROTO ((FILE *, int, mpz_srcptr)); +#endif + +#define mpz_perfect_power_p __gmpz_perfect_power_p + __GMP_DECLSPEC int mpz_perfect_power_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_perfect_square_p __gmpz_perfect_square_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_perfect_square_p) + __GMP_DECLSPEC int mpz_perfect_square_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_popcount __gmpz_popcount +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_popcount) + __GMP_DECLSPEC unsigned long int mpz_popcount __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_pow_ui __gmpz_pow_ui + __GMP_DECLSPEC void mpz_pow_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_powm __gmpz_powm + __GMP_DECLSPEC void mpz_powm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_powm_ui __gmpz_powm_ui + __GMP_DECLSPEC void mpz_powm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr)); + +#define mpz_probab_prime_p __gmpz_probab_prime_p + __GMP_DECLSPEC int mpz_probab_prime_p __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_random __gmpz_random + __GMP_DECLSPEC void mpz_random __GMP_PROTO ((mpz_ptr, mp_size_t)); + +#define mpz_random2 __gmpz_random2 + __GMP_DECLSPEC void mpz_random2 __GMP_PROTO ((mpz_ptr, mp_size_t)); + +#define mpz_realloc2 __gmpz_realloc2 + __GMP_DECLSPEC void mpz_realloc2 __GMP_PROTO ((mpz_ptr, unsigned long)); + +#define mpz_remove __gmpz_remove + __GMP_DECLSPEC unsigned long int mpz_remove __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_root __gmpz_root + __GMP_DECLSPEC int mpz_root __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_rootrem __gmpz_rootrem + __GMP_DECLSPEC void mpz_rootrem __GMP_PROTO ((mpz_ptr,mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_rrandomb __gmpz_rrandomb + __GMP_DECLSPEC void mpz_rrandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); + +#define mpz_scan0 __gmpz_scan0 + __GMP_DECLSPEC unsigned long int mpz_scan0 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_scan1 __gmpz_scan1 + __GMP_DECLSPEC unsigned long int mpz_scan1 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_set __gmpz_set + __GMP_DECLSPEC void mpz_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_set_d __gmpz_set_d + __GMP_DECLSPEC void mpz_set_d __GMP_PROTO ((mpz_ptr, double)); + +#define mpz_set_f __gmpz_set_f + __GMP_DECLSPEC void mpz_set_f __GMP_PROTO ((mpz_ptr, mpf_srcptr)); + +#define mpz_set_q __gmpz_set_q +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_set_q) + __GMP_DECLSPEC void mpz_set_q __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +#endif + +#define mpz_set_si __gmpz_set_si + __GMP_DECLSPEC void mpz_set_si __GMP_PROTO ((mpz_ptr, signed long int)); + +#define mpz_set_str __gmpz_set_str + __GMP_DECLSPEC int mpz_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); + +#define mpz_set_ui __gmpz_set_ui + __GMP_DECLSPEC void mpz_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_setbit __gmpz_setbit + __GMP_DECLSPEC void mpz_setbit __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_size __gmpz_size +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_size) + __GMP_DECLSPEC size_t mpz_size __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_sizeinbase __gmpz_sizeinbase + __GMP_DECLSPEC size_t mpz_sizeinbase __GMP_PROTO ((mpz_srcptr, int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_sqrt __gmpz_sqrt + __GMP_DECLSPEC void mpz_sqrt __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_sqrtrem __gmpz_sqrtrem + __GMP_DECLSPEC void mpz_sqrtrem __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); + +#define mpz_sub __gmpz_sub + __GMP_DECLSPEC void mpz_sub __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_sub_ui __gmpz_sub_ui + __GMP_DECLSPEC void mpz_sub_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_ui_sub __gmpz_ui_sub + __GMP_DECLSPEC void mpz_ui_sub __GMP_PROTO ((mpz_ptr, unsigned long int, mpz_srcptr)); + +#define mpz_submul __gmpz_submul + __GMP_DECLSPEC void mpz_submul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_submul_ui __gmpz_submul_ui + __GMP_DECLSPEC void mpz_submul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_swap __gmpz_swap + __GMP_DECLSPEC void mpz_swap __GMP_PROTO ((mpz_ptr, mpz_ptr)) __GMP_NOTHROW; + +#define mpz_tdiv_ui __gmpz_tdiv_ui + __GMP_DECLSPEC unsigned long int mpz_tdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_tdiv_q __gmpz_tdiv_q + __GMP_DECLSPEC void mpz_tdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp + __GMP_DECLSPEC void mpz_tdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_q_ui __gmpz_tdiv_q_ui + __GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_qr __gmpz_tdiv_qr + __GMP_DECLSPEC void mpz_tdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_tdiv_qr_ui __gmpz_tdiv_qr_ui + __GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_r __gmpz_tdiv_r + __GMP_DECLSPEC void mpz_tdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_tdiv_r_2exp __gmpz_tdiv_r_2exp + __GMP_DECLSPEC void mpz_tdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_r_ui __gmpz_tdiv_r_ui + __GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tstbit __gmpz_tstbit + __GMP_DECLSPEC int mpz_tstbit __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_ui_pow_ui __gmpz_ui_pow_ui + __GMP_DECLSPEC void mpz_ui_pow_ui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); + +#define mpz_urandomb __gmpz_urandomb + __GMP_DECLSPEC void mpz_urandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); + +#define mpz_urandomm __gmpz_urandomm + __GMP_DECLSPEC void mpz_urandomm __GMP_PROTO ((mpz_ptr, gmp_randstate_t, mpz_srcptr)); + +#define mpz_xor __gmpz_xor +#define mpz_eor __gmpz_xor + __GMP_DECLSPEC void mpz_xor __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + + + /**************** Rational (i.e. Q) routines. ****************/ + +#define mpq_abs __gmpq_abs +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_abs) + __GMP_DECLSPEC void mpq_abs __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#endif + +#define mpq_add __gmpq_add + __GMP_DECLSPEC void mpq_add __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_canonicalize __gmpq_canonicalize + __GMP_DECLSPEC void mpq_canonicalize __GMP_PROTO ((mpq_ptr)); + +#define mpq_clear __gmpq_clear + __GMP_DECLSPEC void mpq_clear __GMP_PROTO ((mpq_ptr)); + +#define mpq_cmp __gmpq_cmp + __GMP_DECLSPEC int mpq_cmp __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define _mpq_cmp_si __gmpq_cmp_si + __GMP_DECLSPEC int _mpq_cmp_si __GMP_PROTO ((mpq_srcptr, long, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define _mpq_cmp_ui __gmpq_cmp_ui + __GMP_DECLSPEC int _mpq_cmp_ui __GMP_PROTO ((mpq_srcptr, unsigned long int, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpq_div __gmpq_div + __GMP_DECLSPEC void mpq_div __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_div_2exp __gmpq_div_2exp + __GMP_DECLSPEC void mpq_div_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); + +#define mpq_equal __gmpq_equal + __GMP_DECLSPEC int mpq_equal __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpq_get_num __gmpq_get_num + __GMP_DECLSPEC void mpq_get_num __GMP_PROTO ((mpz_ptr, mpq_srcptr)); + +#define mpq_get_den __gmpq_get_den + __GMP_DECLSPEC void mpq_get_den __GMP_PROTO ((mpz_ptr, mpq_srcptr)); + +#define mpq_get_d __gmpq_get_d + __GMP_DECLSPEC double mpq_get_d __GMP_PROTO ((mpq_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpq_get_str __gmpq_get_str + __GMP_DECLSPEC char *mpq_get_str __GMP_PROTO ((char *, int, mpq_srcptr)); + +#define mpq_init __gmpq_init + __GMP_DECLSPEC void mpq_init __GMP_PROTO ((mpq_ptr)); + +#define mpq_inp_str __gmpq_inp_str +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC size_t mpq_inp_str __GMP_PROTO ((mpq_ptr, FILE *, int)); +#endif + +#define mpq_inv __gmpq_inv + __GMP_DECLSPEC void mpq_inv __GMP_PROTO ((mpq_ptr, mpq_srcptr)); + +#define mpq_mul __gmpq_mul + __GMP_DECLSPEC void mpq_mul __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_mul_2exp __gmpq_mul_2exp + __GMP_DECLSPEC void mpq_mul_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); + +#define mpq_neg __gmpq_neg +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_neg) + __GMP_DECLSPEC void mpq_neg __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#endif + +#define mpq_out_str __gmpq_out_str +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC size_t mpq_out_str __GMP_PROTO ((FILE *, int, mpq_srcptr)); +#endif + +#define mpq_set __gmpq_set + __GMP_DECLSPEC void mpq_set __GMP_PROTO ((mpq_ptr, mpq_srcptr)); + +#define mpq_set_d __gmpq_set_d + __GMP_DECLSPEC void mpq_set_d __GMP_PROTO ((mpq_ptr, double)); + +#define mpq_set_den __gmpq_set_den + __GMP_DECLSPEC void mpq_set_den __GMP_PROTO ((mpq_ptr, mpz_srcptr)); + +#define mpq_set_f __gmpq_set_f + __GMP_DECLSPEC void mpq_set_f __GMP_PROTO ((mpq_ptr, mpf_srcptr)); + +#define mpq_set_num __gmpq_set_num + __GMP_DECLSPEC void mpq_set_num __GMP_PROTO ((mpq_ptr, mpz_srcptr)); + +#define mpq_set_si __gmpq_set_si + __GMP_DECLSPEC void mpq_set_si __GMP_PROTO ((mpq_ptr, signed long int, unsigned long int)); + +#define mpq_set_str __gmpq_set_str + __GMP_DECLSPEC int mpq_set_str __GMP_PROTO ((mpq_ptr, __gmp_const char *, int)); + +#define mpq_set_ui __gmpq_set_ui + __GMP_DECLSPEC void mpq_set_ui __GMP_PROTO ((mpq_ptr, unsigned long int, unsigned long int)); + +#define mpq_set_z __gmpq_set_z + __GMP_DECLSPEC void mpq_set_z __GMP_PROTO ((mpq_ptr, mpz_srcptr)); + +#define mpq_sub __gmpq_sub + __GMP_DECLSPEC void mpq_sub __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_swap __gmpq_swap + __GMP_DECLSPEC void mpq_swap __GMP_PROTO ((mpq_ptr, mpq_ptr)) __GMP_NOTHROW; + + + /**************** Float (i.e. F) routines. ****************/ + +#define mpf_abs __gmpf_abs + __GMP_DECLSPEC void mpf_abs __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_add __gmpf_add + __GMP_DECLSPEC void mpf_add __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_add_ui __gmpf_add_ui + __GMP_DECLSPEC void mpf_add_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +#define mpf_ceil __gmpf_ceil + __GMP_DECLSPEC void mpf_ceil __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_clear __gmpf_clear + __GMP_DECLSPEC void mpf_clear __GMP_PROTO ((mpf_ptr)); + +#define mpf_cmp __gmpf_cmp + __GMP_DECLSPEC int mpf_cmp __GMP_PROTO ((mpf_srcptr, mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_d __gmpf_cmp_d + __GMP_DECLSPEC int mpf_cmp_d __GMP_PROTO ((mpf_srcptr, double)) __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_si __gmpf_cmp_si + __GMP_DECLSPEC int mpf_cmp_si __GMP_PROTO ((mpf_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_ui __gmpf_cmp_ui + __GMP_DECLSPEC int mpf_cmp_ui __GMP_PROTO ((mpf_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_div __gmpf_div + __GMP_DECLSPEC void mpf_div __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_div_2exp __gmpf_div_2exp + __GMP_DECLSPEC void mpf_div_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_div_ui __gmpf_div_ui + __GMP_DECLSPEC void mpf_div_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_dump __gmpf_dump + __GMP_DECLSPEC void mpf_dump __GMP_PROTO ((mpf_srcptr)); + +#define mpf_eq __gmpf_eq + __GMP_DECLSPEC int mpf_eq __GMP_PROTO ((mpf_srcptr, mpf_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_sint_p __gmpf_fits_sint_p + __GMP_DECLSPEC int mpf_fits_sint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_slong_p __gmpf_fits_slong_p + __GMP_DECLSPEC int mpf_fits_slong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_sshort_p __gmpf_fits_sshort_p + __GMP_DECLSPEC int mpf_fits_sshort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_uint_p __gmpf_fits_uint_p + __GMP_DECLSPEC int mpf_fits_uint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_ulong_p __gmpf_fits_ulong_p + __GMP_DECLSPEC int mpf_fits_ulong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_ushort_p __gmpf_fits_ushort_p + __GMP_DECLSPEC int mpf_fits_ushort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_floor __gmpf_floor + __GMP_DECLSPEC void mpf_floor __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_get_d __gmpf_get_d + __GMP_DECLSPEC double mpf_get_d __GMP_PROTO ((mpf_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpf_get_d_2exp __gmpf_get_d_2exp + __GMP_DECLSPEC double mpf_get_d_2exp __GMP_PROTO ((signed long int *, mpf_srcptr)); + +#define mpf_get_default_prec __gmpf_get_default_prec + __GMP_DECLSPEC unsigned long int mpf_get_default_prec __GMP_PROTO ((void)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_prec __gmpf_get_prec + __GMP_DECLSPEC unsigned long int mpf_get_prec __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_si __gmpf_get_si + __GMP_DECLSPEC long mpf_get_si __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_str __gmpf_get_str + __GMP_DECLSPEC char *mpf_get_str __GMP_PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr)); + +#define mpf_get_ui __gmpf_get_ui + __GMP_DECLSPEC unsigned long mpf_get_ui __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_init __gmpf_init + __GMP_DECLSPEC void mpf_init __GMP_PROTO ((mpf_ptr)); + +#define mpf_init2 __gmpf_init2 + __GMP_DECLSPEC void mpf_init2 __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_init_set __gmpf_init_set + __GMP_DECLSPEC void mpf_init_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_init_set_d __gmpf_init_set_d + __GMP_DECLSPEC void mpf_init_set_d __GMP_PROTO ((mpf_ptr, double)); + +#define mpf_init_set_si __gmpf_init_set_si + __GMP_DECLSPEC void mpf_init_set_si __GMP_PROTO ((mpf_ptr, signed long int)); + +#define mpf_init_set_str __gmpf_init_set_str + __GMP_DECLSPEC int mpf_init_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); + +#define mpf_init_set_ui __gmpf_init_set_ui + __GMP_DECLSPEC void mpf_init_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_inp_str __gmpf_inp_str +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC size_t mpf_inp_str __GMP_PROTO ((mpf_ptr, FILE *, int)); +#endif + +#define mpf_integer_p __gmpf_integer_p + __GMP_DECLSPEC int mpf_integer_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_mul __gmpf_mul + __GMP_DECLSPEC void mpf_mul __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_mul_2exp __gmpf_mul_2exp + __GMP_DECLSPEC void mpf_mul_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_mul_ui __gmpf_mul_ui + __GMP_DECLSPEC void mpf_mul_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_neg __gmpf_neg + __GMP_DECLSPEC void mpf_neg __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_out_str __gmpf_out_str +#ifdef _GMP_H_HAVE_FILE + __GMP_DECLSPEC size_t mpf_out_str __GMP_PROTO ((FILE *, int, size_t, mpf_srcptr)); +#endif + +#define mpf_pow_ui __gmpf_pow_ui + __GMP_DECLSPEC void mpf_pow_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_random2 __gmpf_random2 + __GMP_DECLSPEC void mpf_random2 __GMP_PROTO ((mpf_ptr, mp_size_t, mp_exp_t)); + +#define mpf_reldiff __gmpf_reldiff + __GMP_DECLSPEC void mpf_reldiff __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_set __gmpf_set + __GMP_DECLSPEC void mpf_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_set_d __gmpf_set_d + __GMP_DECLSPEC void mpf_set_d __GMP_PROTO ((mpf_ptr, double)); + +#define mpf_set_default_prec __gmpf_set_default_prec + __GMP_DECLSPEC void mpf_set_default_prec __GMP_PROTO ((unsigned long int)) __GMP_NOTHROW; + +#define mpf_set_prec __gmpf_set_prec + __GMP_DECLSPEC void mpf_set_prec __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_set_prec_raw __gmpf_set_prec_raw + __GMP_DECLSPEC void mpf_set_prec_raw __GMP_PROTO ((mpf_ptr, unsigned long int)) __GMP_NOTHROW; + +#define mpf_set_q __gmpf_set_q + __GMP_DECLSPEC void mpf_set_q __GMP_PROTO ((mpf_ptr, mpq_srcptr)); + +#define mpf_set_si __gmpf_set_si + __GMP_DECLSPEC void mpf_set_si __GMP_PROTO ((mpf_ptr, signed long int)); + +#define mpf_set_str __gmpf_set_str + __GMP_DECLSPEC int mpf_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); + +#define mpf_set_ui __gmpf_set_ui + __GMP_DECLSPEC void mpf_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_set_z __gmpf_set_z + __GMP_DECLSPEC void mpf_set_z __GMP_PROTO ((mpf_ptr, mpz_srcptr)); + +#define mpf_size __gmpf_size + __GMP_DECLSPEC size_t mpf_size __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_sqrt __gmpf_sqrt + __GMP_DECLSPEC void mpf_sqrt __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_sqrt_ui __gmpf_sqrt_ui + __GMP_DECLSPEC void mpf_sqrt_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_sub __gmpf_sub + __GMP_DECLSPEC void mpf_sub __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_sub_ui __gmpf_sub_ui + __GMP_DECLSPEC void mpf_sub_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_swap __gmpf_swap + __GMP_DECLSPEC void mpf_swap __GMP_PROTO ((mpf_ptr, mpf_ptr)) __GMP_NOTHROW; + +#define mpf_trunc __gmpf_trunc + __GMP_DECLSPEC void mpf_trunc __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_ui_div __gmpf_ui_div + __GMP_DECLSPEC void mpf_ui_div __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); + +#define mpf_ui_sub __gmpf_ui_sub + __GMP_DECLSPEC void mpf_ui_sub __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); + +#define mpf_urandomb __gmpf_urandomb + __GMP_DECLSPEC void mpf_urandomb __GMP_PROTO ((mpf_t, gmp_randstate_t, unsigned long int)); + + + /************ Low level positive-integer (i.e. N) routines. ************/ + + /* This is ugly, but we need to make user calls reach the prefixed function. */ + +#define mpn_add __MPN(add) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add) + __GMP_DECLSPEC mp_limb_t mpn_add __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +#endif + +#define mpn_add_1 __MPN(add_1) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add_1) + __GMP_DECLSPEC mp_limb_t mpn_add_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +#endif + +#define mpn_add_n __MPN(add_n) + __GMP_DECLSPEC mp_limb_t mpn_add_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); + +#define mpn_addmul_1 __MPN(addmul_1) + __GMP_DECLSPEC mp_limb_t mpn_addmul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_bdivmod __MPN(bdivmod) + __GMP_DECLSPEC mp_limb_t mpn_bdivmod __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, unsigned long int)); + +#define mpn_cmp __MPN(cmp) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_cmp) + __GMP_DECLSPEC int mpn_cmp __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpn_divexact_by3(dst,src,size) \ + mpn_divexact_by3c (dst, src, size, __GMP_CAST (mp_limb_t, 0)) + +#define mpn_divexact_by3c __MPN(divexact_by3c) + __GMP_DECLSPEC mp_limb_t mpn_divexact_by3c __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_divmod_1(qp,np,nsize,dlimb) \ + mpn_divrem_1 (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dlimb) + +#define mpn_divrem __MPN(divrem) + __GMP_DECLSPEC mp_limb_t mpn_divrem __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t)); + +#define mpn_divrem_1 __MPN(divrem_1) + __GMP_DECLSPEC mp_limb_t mpn_divrem_1 __GMP_PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_divrem_2 __MPN(divrem_2) + __GMP_DECLSPEC mp_limb_t mpn_divrem_2 __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr)); + +#define mpn_gcd __MPN(gcd) + __GMP_DECLSPEC mp_size_t mpn_gcd __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); + +#define mpn_gcd_1 __MPN(gcd_1) + __GMP_DECLSPEC mp_limb_t mpn_gcd_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_gcdext __MPN(gcdext) + __GMP_DECLSPEC mp_size_t mpn_gcdext __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); + +#define mpn_get_str __MPN(get_str) + __GMP_DECLSPEC size_t mpn_get_str __GMP_PROTO ((unsigned char *, int, mp_ptr, mp_size_t)); + +#define mpn_hamdist __MPN(hamdist) + __GMP_DECLSPEC unsigned long int mpn_hamdist __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpn_lshift __MPN(lshift) + __GMP_DECLSPEC mp_limb_t mpn_lshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); + +#define mpn_mod_1 __MPN(mod_1) + __GMP_DECLSPEC mp_limb_t mpn_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_mul __MPN(mul) + __GMP_DECLSPEC mp_limb_t mpn_mul __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); + +#define mpn_mul_1 __MPN(mul_1) + __GMP_DECLSPEC mp_limb_t mpn_mul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_mul_n __MPN(mul_n) + __GMP_DECLSPEC void mpn_mul_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); + +#define mpn_perfect_square_p __MPN(perfect_square_p) + __GMP_DECLSPEC int mpn_perfect_square_p __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_popcount __MPN(popcount) + __GMP_DECLSPEC unsigned long int mpn_popcount __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpn_pow_1 __MPN(pow_1) + __GMP_DECLSPEC mp_size_t mpn_pow_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr)); + + /* undocumented now, but retained here for upward compatibility */ +#define mpn_preinv_mod_1 __MPN(preinv_mod_1) + __GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_random __MPN(random) + __GMP_DECLSPEC void mpn_random __GMP_PROTO ((mp_ptr, mp_size_t)); + +#define mpn_random2 __MPN(random2) + __GMP_DECLSPEC void mpn_random2 __GMP_PROTO ((mp_ptr, mp_size_t)); + +#define mpn_rshift __MPN(rshift) + __GMP_DECLSPEC mp_limb_t mpn_rshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); + +#define mpn_scan0 __MPN(scan0) + __GMP_DECLSPEC unsigned long int mpn_scan0 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpn_scan1 __MPN(scan1) + __GMP_DECLSPEC unsigned long int mpn_scan1 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpn_set_str __MPN(set_str) + __GMP_DECLSPEC mp_size_t mpn_set_str __GMP_PROTO ((mp_ptr, __gmp_const unsigned char *, size_t, int)); + +#define mpn_sqrtrem __MPN(sqrtrem) + __GMP_DECLSPEC mp_size_t mpn_sqrtrem __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t)); + +#define mpn_sub __MPN(sub) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub) + __GMP_DECLSPEC mp_limb_t mpn_sub __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +#endif + +#define mpn_sub_1 __MPN(sub_1) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub_1) + __GMP_DECLSPEC mp_limb_t mpn_sub_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +#endif + +#define mpn_sub_n __MPN(sub_n) + __GMP_DECLSPEC mp_limb_t mpn_sub_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); + +#define mpn_submul_1 __MPN(submul_1) + __GMP_DECLSPEC mp_limb_t mpn_submul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_tdiv_qr __MPN(tdiv_qr) + __GMP_DECLSPEC void mpn_tdiv_qr __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); + + + /**************** mpz inlines ****************/ + + /* The following are provided as inlines where possible, but always exist as + library functions too, for binary compatibility. + + Within gmp itself this inlining generally isn't relied on, since it + doesn't get done for all compilers, whereas if something is worth + inlining then it's worth arranging always. + + There are two styles of inlining here. When the same bit of code is + wanted for the inline as for the library version, then __GMP_FORCE_foo + arranges for that code to be emitted and the __GMP_EXTERN_INLINE + directive suppressed, eg. mpz_fits_uint_p. When a different bit of code + is wanted for the inline than for the library version, then + __GMP_FORCE_foo arranges the inline to be suppressed, eg. mpz_abs. */ + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_abs) + __GMP_EXTERN_INLINE void + mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) + { + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = __GMP_ABS (__gmp_w->_mp_size); + } +#endif + +#if GMP_NAIL_BITS == 0 +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval)); +#else +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval) \ + || (__gmp_n == 2 && __gmp_p[1] <= ((mp_limb_t) maxval >> GMP_NUMB_BITS))); +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_uint_p) +#if ! defined (__GMP_FORCE_mpz_fits_uint_p) + __GMP_EXTERN_INLINE +#endif + int + mpz_fits_uint_p (mpz_srcptr __gmp_z) __GMP_NOTHROW + { + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_UINT_MAX); + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ulong_p) +#if ! defined (__GMP_FORCE_mpz_fits_ulong_p) + __GMP_EXTERN_INLINE +#endif + int + mpz_fits_ulong_p (mpz_srcptr __gmp_z) __GMP_NOTHROW + { + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_ULONG_MAX); + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ushort_p) +#if ! defined (__GMP_FORCE_mpz_fits_ushort_p) + __GMP_EXTERN_INLINE +#endif + int + mpz_fits_ushort_p (mpz_srcptr __gmp_z) __GMP_NOTHROW + { + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_USHRT_MAX); + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_get_ui) +#if ! defined (__GMP_FORCE_mpz_get_ui) + __GMP_EXTERN_INLINE +#endif + unsigned long + mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW + { + mp_ptr __gmp_p = __gmp_z->_mp_d; + mp_size_t __gmp_n = __gmp_z->_mp_size; + mp_limb_t __gmp_l = __gmp_p[0]; + /* This is a "#if" rather than a plain "if" so as to avoid gcc warnings + about "<< GMP_NUMB_BITS" exceeding the type size, and to avoid Borland + C++ 6.0 warnings about condition always true for something like + "__GMP_ULONG_MAX < GMP_NUMB_MASK". */ +#if GMP_NAIL_BITS == 0 || defined (_LONG_LONG_LIMB) + /* limb==long and no nails, or limb==longlong, one limb is enough */ + return (__gmp_n != 0 ? __gmp_l : 0); +#else + /* limb==long and nails, need two limbs when available */ + __gmp_n = __GMP_ABS (__gmp_n); + if (__gmp_n <= 1) + return (__gmp_n != 0 ? __gmp_l : 0); + else + return __gmp_l + (__gmp_p[1] << GMP_NUMB_BITS); +#endif + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_getlimbn) +#if ! defined (__GMP_FORCE_mpz_getlimbn) + __GMP_EXTERN_INLINE +#endif + mp_limb_t + mpz_getlimbn (mpz_srcptr __gmp_z, mp_size_t __gmp_n) __GMP_NOTHROW + { + mp_limb_t __gmp_result = 0; + if (__GMP_LIKELY (__gmp_n >= 0 && __gmp_n < __GMP_ABS (__gmp_z->_mp_size))) + __gmp_result = __gmp_z->_mp_d[__gmp_n]; + return __gmp_result; + } +#endif + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_neg) + __GMP_EXTERN_INLINE void + mpz_neg (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) + { + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = - __gmp_w->_mp_size; + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_perfect_square_p) +#if ! defined (__GMP_FORCE_mpz_perfect_square_p) + __GMP_EXTERN_INLINE +#endif + int + mpz_perfect_square_p (mpz_srcptr __gmp_a) + { + mp_size_t __gmp_asize; + int __gmp_result; + + __gmp_asize = __gmp_a->_mp_size; + __gmp_result = (__gmp_asize >= 0); /* zero is a square, negatives are not */ + if (__GMP_LIKELY (__gmp_asize > 0)) + __gmp_result = mpn_perfect_square_p (__gmp_a->_mp_d, __gmp_asize); + return __gmp_result; + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_popcount) +#if ! defined (__GMP_FORCE_mpz_popcount) + __GMP_EXTERN_INLINE +#endif + unsigned long + mpz_popcount (mpz_srcptr __gmp_u) __GMP_NOTHROW + { + mp_size_t __gmp_usize; + unsigned long __gmp_result; + + __gmp_usize = __gmp_u->_mp_size; + __gmp_result = (__gmp_usize < 0 ? __GMP_ULONG_MAX : 0); + if (__GMP_LIKELY (__gmp_usize > 0)) + __gmp_result = mpn_popcount (__gmp_u->_mp_d, __gmp_usize); + return __gmp_result; + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_set_q) +#if ! defined (__GMP_FORCE_mpz_set_q) + __GMP_EXTERN_INLINE +#endif + void + mpz_set_q (mpz_ptr __gmp_w, mpq_srcptr __gmp_u) + { + mpz_tdiv_q (__gmp_w, mpq_numref (__gmp_u), mpq_denref (__gmp_u)); + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_size) +#if ! defined (__GMP_FORCE_mpz_size) + __GMP_EXTERN_INLINE +#endif + size_t + mpz_size (mpz_srcptr __gmp_z) __GMP_NOTHROW + { + return __GMP_ABS (__gmp_z->_mp_size); + } +#endif + + + /**************** mpq inlines ****************/ + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_abs) + __GMP_EXTERN_INLINE void + mpq_abs (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) + { + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = __GMP_ABS (__gmp_w->_mp_num._mp_size); + } +#endif + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_neg) + __GMP_EXTERN_INLINE void + mpq_neg (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) + { + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size; + } +#endif + + + /**************** mpn inlines ****************/ + + /* The comments with __GMPN_ADD_1 below apply here too. + + The test for FUNCTION returning 0 should predict well. If it's assumed + {yp,ysize} will usually have a random number of bits then the high limb + won't be full and a carry out will occur a good deal less than 50% of the + time. + + ysize==0 isn't a documented feature, but is used internally in a few + places. + + Producing cout last stops it using up a register during the main part of + the calculation, though gcc (as of 3.0) on an "if (mpn_add (...))" + doesn't seem able to move the true and false legs of the conditional up + to the two places cout is generated. */ + +#define __GMPN_AORS(cout, wp, xp, xsize, yp, ysize, FUNCTION, TEST) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x; \ + \ + /* ASSERT ((ysize) >= 0); */ \ + /* ASSERT ((xsize) >= (ysize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, xp, xsize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, yp, ysize)); */ \ + \ + __gmp_i = (ysize); \ + if (__gmp_i != 0) \ + { \ + if (FUNCTION (wp, xp, yp, __gmp_i)) \ + { \ + do \ + { \ + if (__gmp_i >= (xsize)) \ + { \ + (cout) = 1; \ + goto __gmp_done; \ + } \ + __gmp_x = (xp)[__gmp_i]; \ + } \ + while (TEST); \ + } \ + } \ + if ((wp) != (xp)) \ + __GMPN_COPY_REST (wp, xp, xsize, __gmp_i); \ + (cout) = 0; \ + __gmp_done: \ + ; \ + } while (0) + +#define __GMPN_ADD(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_add_n, \ + (((wp)[__gmp_i++] = (__gmp_x + 1) & GMP_NUMB_MASK) == 0)) +#define __GMPN_SUB(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_sub_n, \ + (((wp)[__gmp_i++] = (__gmp_x - 1) & GMP_NUMB_MASK), __gmp_x == 0)) + + + /* The use of __gmp_i indexing is designed to ensure a compile time src==dst + remains nice and clear to the compiler, so that __GMPN_COPY_REST can + disappear, and the load/add/store gets a chance to become a + read-modify-write on CISC CPUs. + + Alternatives: + + Using a pair of pointers instead of indexing would be possible, but gcc + isn't able to recognise compile-time src==dst in that case, even when the + pointers are incremented more or less together. Other compilers would + very likely have similar difficulty. + + gcc could use "if (__builtin_constant_p(src==dst) && src==dst)" or + similar to detect a compile-time src==dst. This works nicely on gcc + 2.95.x, it's not good on gcc 3.0 where __builtin_constant_p(p==p) seems + to be always false, for a pointer p. But the current code form seems + good enough for src==dst anyway. + + gcc on x86 as usual doesn't give particularly good flags handling for the + carry/borrow detection. It's tempting to want some multi instruction asm + blocks to help it, and this was tried, but in truth there's only a few + instructions to save and any gain is all too easily lost by register + juggling setting up for the asm. */ + +#if GMP_NAIL_BITS == 0 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r; \ + if (CB (__gmp_r, __gmp_x, (v))) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r; \ + ++__gmp_i; \ + if (!CB (__gmp_r, __gmp_x, 1)) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif + +#if GMP_NAIL_BITS >= 1 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r & GMP_NUMB_MASK; \ + if (__gmp_r >> GMP_NUMB_BITS != 0) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r & GMP_NUMB_MASK; \ + ++__gmp_i; \ + if (__gmp_r >> GMP_NUMB_BITS == 0) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif + +#define __GMPN_ADDCB(r,x,y) ((r) < (y)) +#define __GMPN_SUBCB(r,x,y) ((x) < (y)) + +#define __GMPN_ADD_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, +, __GMPN_ADDCB) +#define __GMPN_SUB_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, -, __GMPN_SUBCB) + + + /* Compare {xp,size} and {yp,size}, setting "result" to positive, zero or + negative. size==0 is allowed. On random data usually only one limb will + need to be examined to get a result, so it's worth having it inline. */ +#define __GMPN_CMP(result, xp, yp, size) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_y; \ + \ + /* ASSERT ((size) >= 0); */ \ + \ + (result) = 0; \ + __gmp_i = (size); \ + while (--__gmp_i >= 0) \ + { \ + __gmp_x = (xp)[__gmp_i]; \ + __gmp_y = (yp)[__gmp_i]; \ + if (__gmp_x != __gmp_y) \ + { \ + /* Cannot use __gmp_x - __gmp_y, may overflow an "int" */ \ + (result) = (__gmp_x > __gmp_y ? 1 : -1); \ + break; \ + } \ + } \ + } while (0) + + +#if defined (__GMPN_COPY) && ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + __GMPN_COPY ((dst)+(start), (src)+(start), (size)-(start)); \ + } while (0) +#endif + + /* Copy {src,size} to {dst,size}, starting at "start". This is designed to + keep the indexing dst[j] and src[j] nice and simple for __GMPN_ADD_1, + __GMPN_ADD, etc. */ +#if ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + mp_size_t __gmp_j; \ + /* ASSERT ((size) >= 0); */ \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size)); */ \ + __GMP_CRAY_Pragma ("_CRI ivdep"); \ + for (__gmp_j = (start); __gmp_j < (size); __gmp_j++) \ + (dst)[__gmp_j] = (src)[__gmp_j]; \ + } while (0) +#endif + + /* Enhancement: Use some of the smarter code from gmp-impl.h. Maybe use + mpn_copyi if there's a native version, and if we don't mind demanding + binary compatibility for it (on targets which use it). */ + +#if ! defined (__GMPN_COPY) +#define __GMPN_COPY(dst, src, size) __GMPN_COPY_REST (dst, src, size, 0) +#endif + + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add) +#if ! defined (__GMP_FORCE_mpn_add) + __GMP_EXTERN_INLINE +#endif + mp_limb_t + mpn_add (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) + { + mp_limb_t __gmp_c; + __GMPN_ADD (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add_1) +#if ! defined (__GMP_FORCE_mpn_add_1) + __GMP_EXTERN_INLINE +#endif + mp_limb_t + mpn_add_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW + { + mp_limb_t __gmp_c; + __GMPN_ADD_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_cmp) +#if ! defined (__GMP_FORCE_mpn_cmp) + __GMP_EXTERN_INLINE +#endif + int + mpn_cmp (mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, mp_size_t __gmp_size) __GMP_NOTHROW + { + int __gmp_result; + __GMPN_CMP (__gmp_result, __gmp_xp, __gmp_yp, __gmp_size); + return __gmp_result; + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub) +#if ! defined (__GMP_FORCE_mpn_sub) + __GMP_EXTERN_INLINE +#endif + mp_limb_t + mpn_sub (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) + { + mp_limb_t __gmp_c; + __GMPN_SUB (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; + } +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub_1) +#if ! defined (__GMP_FORCE_mpn_sub_1) + __GMP_EXTERN_INLINE +#endif + mp_limb_t + mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW + { + mp_limb_t __gmp_c; + __GMPN_SUB_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; + } +#endif + +#if defined (__cplusplus) +} +#endif + + +/* Allow faster testing for negative, zero, and positive. */ +#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0) +#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0) +#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0) + +/* When using GCC, optimize certain common comparisons. */ +#if defined (__GNUC__) +#define mpz_cmp_ui(Z,UI) \ + (__builtin_constant_p (UI) && (UI) == 0 \ + ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) +#define mpz_cmp_si(Z,SI) \ + (__builtin_constant_p (SI) && (SI) == 0 ? mpz_sgn (Z) \ + : __builtin_constant_p (SI) && (SI) > 0 \ + ? _mpz_cmp_ui (Z, __GMP_CAST (unsigned long int, SI)) \ + : _mpz_cmp_si (Z,SI)) +#define mpq_cmp_ui(Q,NUI,DUI) \ + (__builtin_constant_p (NUI) && (NUI) == 0 \ + ? mpq_sgn (Q) : _mpq_cmp_ui (Q,NUI,DUI)) +#define mpq_cmp_si(q,n,d) \ + (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ + ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ + : _mpq_cmp_si (q, n, d)) +#else +#define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI) +#define mpz_cmp_si(Z,UI) _mpz_cmp_si (Z,UI) +#define mpq_cmp_ui(Q,NUI,DUI) _mpq_cmp_ui (Q,NUI,DUI) +#define mpq_cmp_si(q,n,d) _mpq_cmp_si(q,n,d) +#endif + + +/* Using "&" rather than "&&" means these can come out branch-free. Every + mpz_t has at least one limb allocated, so fetching the low limb is always + allowed. */ +#define mpz_odd_p(z) (((z)->_mp_size != 0) & __GMP_CAST (int, (z)->_mp_d[0])) +#define mpz_even_p(z) (! mpz_odd_p (z)) + + +/**************** C++ routines ****************/ + +#ifdef __cplusplus +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpz_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpq_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpf_srcptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpz_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpq_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpf_ptr); +#endif + + +/* Source-level compatibility with GMP 2 and earlier. */ +#define mpn_divmod(qp,np,nsize,dp,dsize) \ + mpn_divrem (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dp, dsize) + +/* Source-level compatibility with GMP 1. */ +#define mpz_mdiv mpz_fdiv_q +#define mpz_mdivmod mpz_fdiv_qr +#define mpz_mmod mpz_fdiv_r +#define mpz_mdiv_ui mpz_fdiv_q_ui +#define mpz_mdivmod_ui(q,r,n,d) \ + (((r) == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) +#define mpz_mmod_ui(r,n,d) \ + (((r) == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) + +/* Useful synonyms, but not quite compatible with GMP 1. */ +#define mpz_div mpz_fdiv_q +#define mpz_divmod mpz_fdiv_qr +#define mpz_div_ui mpz_fdiv_q_ui +#define mpz_divmod_ui mpz_fdiv_qr_ui +#define mpz_div_2exp mpz_fdiv_q_2exp +#define mpz_mod_2exp mpz_fdiv_r_2exp + +enum +{ + GMP_ERROR_NONE = 0, + GMP_ERROR_UNSUPPORTED_ARGUMENT = 1, + GMP_ERROR_DIVISION_BY_ZERO = 2, + GMP_ERROR_SQRT_OF_NEGATIVE = 4, + GMP_ERROR_INVALID_ARGUMENT = 8 +}; + +/* Major version number is the value of __GNU_MP__ too, above and in mp.h. */ +#define __GNU_MP_VERSION 4 +#define __GNU_MP_VERSION_MINOR 2 +#define __GNU_MP_VERSION_PATCHLEVEL 2 + +#define __GMP_H__ +#endif /* __GMP_H__ */ diff --git a/library/GMP/include/gmpxx.h b/library/GMP/include/gmpxx.h new file mode 100644 index 00000000..76a72678 --- /dev/null +++ b/library/GMP/include/gmpxx.h @@ -0,0 +1,3337 @@ +/* gmpxx.h -- C++ class wrapper for GMP types. -*- C++ -*- + +Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +/* the C++ compiler must implement the following features: + - member templates + - partial specialization of templates + - namespace support + for g++, this means version 2.91 or higher + for other compilers, I don't know */ +#ifdef __GNUC__ +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91) +#error gmpxx.h requires g++ version 2.91 (egcs 1.1.2) or higher +#endif +#endif + +#ifndef __GMP_PLUSPLUS__ +#define __GMP_PLUSPLUS__ + +#include <iosfwd> + +#include <cstring> /* for strlen */ +#include <string> +#include <stdexcept> +#include <gmp.h> + + +/**************** Function objects ****************/ +/* Any evaluation of a __gmp_expr ends up calling one of these functions + all intermediate functions being inline, the evaluation should optimize + to a direct call to the relevant function, thus yielding no overhead + over the C interface. */ + +struct __gmp_unary_plus +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); } + static void eval(mpq_ptr q, mpq_srcptr r) { mpq_set(q, r); } + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_set(f, g); } +}; + +struct __gmp_unary_minus +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_neg(z, w); } + static void eval(mpq_ptr q, mpq_srcptr r) { mpq_neg(q, r); } + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_neg(f, g); } +}; + +struct __gmp_unary_com +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_com(z, w); } +}; + +struct __gmp_binary_plus +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_add(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_add_ui(z, w, l); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { mpz_add_ui(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { + if (l >= 0) + mpz_add_ui(z, w, l); + else + mpz_sub_ui(z, w, -l); + } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { + if (l >= 0) + mpz_add_ui(z, w, l); + else + mpz_sub_ui(z, w, -l); + } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_add(z, w, temp); + mpz_clear(temp); + } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_add(z, temp, w); + mpz_clear(temp); + } + + static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) + { mpq_add(q, r, s); } + + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { mpq_set(q, r); mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); } + static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) + { mpq_set(q, r); mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); } + static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) + { + mpq_set(q, r); + if (l >= 0) + mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); + else + mpz_submul_ui(mpq_numref(q), mpq_denref(q), -l); + } + static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) + { + mpq_set(q, r); + if (l >= 0) + mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); + else + mpz_submul_ui(mpq_numref(q), mpq_denref(q), -l); + } + static void eval(mpq_ptr q, mpq_srcptr r, double d) + { + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + mpq_add(q, r, temp); + mpq_clear(temp); + } + static void eval(mpq_ptr q, double d, mpq_srcptr r) + { + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + mpq_add(q, temp, r); + mpq_clear(temp); + } + + static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z) + { mpq_set(q, r); mpz_addmul(mpq_numref(q), mpq_denref(q), z); } + static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r) + { mpq_set(q, r); mpz_addmul(mpq_numref(q), mpq_denref(q), z); } + + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { mpf_add(f, g, h); } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_add_ui(f, g, l); } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { mpf_add_ui(f, g, l); } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { + if (l >= 0) + mpf_add_ui(f, g, l); + else + mpf_sub_ui(f, g, -l); + } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { + if (l >= 0) + mpf_add_ui(f, g, l); + else + mpf_sub_ui(f, g, -l); + } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_add(f, g, temp); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_add(f, temp, g); + mpf_clear(temp); + } +}; + +struct __gmp_binary_minus +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_sub(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_sub_ui(z, w, l); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { mpz_ui_sub(z, l, w); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { + if (l >= 0) + mpz_sub_ui(z, w, l); + else + mpz_add_ui(z, w, -l); + } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { + if (l >= 0) + mpz_ui_sub(z, l, w); + else + { + mpz_add_ui(z, w, -l); + mpz_neg(z, z); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_sub(z, w, temp); + mpz_clear(temp); + } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_sub(z, temp, w); + mpz_clear(temp); + } + + static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) + { mpq_sub(q, r, s); } + + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { mpq_set(q, r); mpz_submul_ui(mpq_numref(q), mpq_denref(q), l); } + static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) + { mpq_neg(q, r); mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); } + static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) + { + mpq_set(q, r); + if (l >= 0) + mpz_submul_ui(mpq_numref(q), mpq_denref(q), l); + else + mpz_addmul_ui(mpq_numref(q), mpq_denref(q), -l); + } + static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) + { + mpq_neg(q, r); + if (l >= 0) + mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); + else + mpz_submul_ui(mpq_numref(q), mpq_denref(q), -l); + } + static void eval(mpq_ptr q, mpq_srcptr r, double d) + { + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + mpq_sub(q, r, temp); + mpq_clear(temp); + } + static void eval(mpq_ptr q, double d, mpq_srcptr r) + { + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + mpq_sub(q, temp, r); + mpq_clear(temp); + } + + static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z) + { mpq_set(q, r); mpz_submul(mpq_numref(q), mpq_denref(q), z); } + static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r) + { mpq_neg(q, r); mpz_addmul(mpq_numref(q), mpq_denref(q), z); } + + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { mpf_sub(f, g, h); } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_sub_ui(f, g, l); } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { mpf_ui_sub(f, l, g); } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { + if (l >= 0) + mpf_sub_ui(f, g, l); + else + mpf_add_ui(f, g, -l); + } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { + if (l >= 0) + mpf_sub_ui(f, g, l); + else + mpf_add_ui(f, g, -l); + mpf_neg(f, f); + } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_sub(f, g, temp); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_sub(f, temp, g); + mpf_clear(temp); + } +}; + +struct __gmp_binary_multiplies +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_mul(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_mul_ui(z, w, l); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { mpz_mul_ui(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { mpz_mul_si (z, w, l); } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { mpz_mul_si (z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_mul(z, w, temp); + mpz_clear(temp); + } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_mul(z, temp, w); + mpz_clear(temp); + } + + static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) + { mpq_mul(q, r, s); } + + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { + mpq_t temp; + mpq_init(temp); + mpq_set_ui(temp, l, 1); + mpq_mul(q, r, temp); + mpq_clear(temp); + } + static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) + { + mpq_t temp; + mpq_init(temp); + mpq_set_ui(temp, l, 1); + mpq_mul(q, temp, r); + mpq_clear(temp); + } + static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) + { + mpq_t temp; + mpq_init(temp); + mpq_set_si(temp, l, 1); + mpq_mul(q, r, temp); + mpq_clear(temp); + } + static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) + { + mpq_t temp; + mpq_init(temp); + mpq_set_si(temp, l, 1); + mpq_mul(q, temp, r); + mpq_clear(temp); + } + static void eval(mpq_ptr q, mpq_srcptr r, double d) + { + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + mpq_mul(q, r, temp); + mpq_clear(temp); + } + static void eval(mpq_ptr q, double d, mpq_srcptr r) + { + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + mpq_mul(q, temp, r); + mpq_clear(temp); + } + + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { mpf_mul(f, g, h); } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_mul_ui(f, g, l); } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { mpf_mul_ui(f, g, l); } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { + if (l >= 0) + mpf_mul_ui(f, g, l); + else + { + mpf_mul_ui(f, g, -l); + mpf_neg(f, f); + } + } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { + if (l >= 0) + mpf_mul_ui(f, g, l); + else + { + mpf_mul_ui(f, g, -l); + mpf_neg(f, f); + } + } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_mul(f, g, temp); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_mul(f, temp, g); + mpf_clear(temp); + } +}; + +struct __gmp_binary_divides +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_tdiv_q(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_tdiv_q_ui(z, w, l); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { + if (mpz_sgn(w) >= 0) + { + if (mpz_fits_ulong_p(w)) + mpz_set_ui(z, l / mpz_get_ui(w)); + else + mpz_set_ui(z, 0); + } + else + { + mpz_neg(z, w); + if (mpz_fits_ulong_p(z)) + { + mpz_set_ui(z, l / mpz_get_ui(z)); + mpz_neg(z, z); + } + else + mpz_set_ui(z, 0); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { + if (l >= 0) + mpz_tdiv_q_ui(z, w, l); + else + { + mpz_tdiv_q_ui(z, w, -l); + mpz_neg(z, z); + } + } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { + if (mpz_fits_slong_p(w)) + mpz_set_si(z, l / mpz_get_si(w)); + else + { + /* if w is bigger than a long then the quotient must be zero, unless + l==LONG_MIN and w==-LONG_MIN in which case the quotient is -1 */ + mpz_set_si (z, (mpz_cmpabs_ui (w, (l >= 0 ? l : -l)) == 0 ? -1 : 0)); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_tdiv_q(z, w, temp); + mpz_clear(temp); + } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_tdiv_q(z, temp, w); + mpz_clear(temp); + } + + static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) + { mpq_div(q, r, s); } + + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { + mpq_t temp; + mpq_init(temp); + mpq_set_ui(temp, l, 1); + mpq_div(q, r, temp); + mpq_clear(temp); + } + static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) + { + mpq_t temp; + mpq_init(temp); + mpq_set_ui(temp, l, 1); + mpq_div(q, temp, r); + mpq_clear(temp); + } + static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) + { + mpq_t temp; + mpq_init(temp); + mpq_set_si(temp, l, 1); + mpq_div(q, r, temp); + mpq_clear(temp); + } + static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) + { + mpq_t temp; + mpq_init(temp); + mpq_set_si(temp, l, 1); + mpq_div(q, temp, r); + mpq_clear(temp); + } + static void eval(mpq_ptr q, mpq_srcptr r, double d) + { + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + mpq_div(q, r, temp); + mpq_clear(temp); + } + static void eval(mpq_ptr q, double d, mpq_srcptr r) + { + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + mpq_div(q, temp, r); + mpq_clear(temp); + } + + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { mpf_div(f, g, h); } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_div_ui(f, g, l); } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { mpf_ui_div(f, l, g); } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { + if (l >= 0) + mpf_div_ui(f, g, l); + else + { + mpf_div_ui(f, g, -l); + mpf_neg(f, f); + } + } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { + if (l >= 0) + mpf_ui_div(f, l, g); + else + { + mpf_ui_div(f, -l, g); + mpf_neg(f, f); + } + } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_div(f, g, temp); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_div(f, temp, g); + mpf_clear(temp); + } +}; + +struct __gmp_binary_modulus +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_tdiv_r(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_tdiv_r_ui(z, w, l); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { + if (mpz_sgn(w) >= 0) + { + if (mpz_fits_ulong_p(w)) + mpz_set_ui(z, l % mpz_get_ui(w)); + else + mpz_set_ui(z, l); + } + else + { + mpz_neg(z, w); + if (mpz_fits_ulong_p(z)) + mpz_set_ui(z, l % mpz_get_ui(z)); + else + mpz_set_ui(z, l); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { + mpz_tdiv_r_ui (z, w, (l >= 0 ? l : -l)); + } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { + if (mpz_fits_slong_p(w)) + mpz_set_si(z, l % mpz_get_si(w)); + else + { + /* if w is bigger than a long then the remainder is l unchanged, + unless l==LONG_MIN and w==-LONG_MIN in which case it's 0 */ + mpz_set_si (z, mpz_cmpabs_ui (w, (l >= 0 ? l : -l)) == 0 ? 0 : l); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_tdiv_r(z, w, temp); + mpz_clear(temp); + } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { + mpz_t temp; + mpz_init_set_d(temp, d); + mpz_tdiv_r(z, temp, w); + mpz_clear(temp); + } +}; + +struct __gmp_binary_and +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_and(z, w, v); } +}; + +struct __gmp_binary_ior +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_ior(z, w, v); } +}; + +struct __gmp_binary_xor +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_xor(z, w, v); } +}; + +struct __gmp_binary_lshift +{ + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_mul_2exp(z, w, l); } + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { mpq_mul_2exp(q, r, l); } + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_mul_2exp(f, g, l); } +}; + +struct __gmp_binary_rshift +{ + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_tdiv_q_2exp(z, w, l); } + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { mpq_div_2exp(q, r, l); } + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_div_2exp(f, g, l); } +}; + +struct __gmp_binary_equal +{ + static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; } + + static bool eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l) == 0; } + static bool eval(unsigned long int l, mpz_srcptr z) + { return mpz_cmp_ui(z, l) == 0; } + static bool eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l) == 0; } + static bool eval(signed long int l, mpz_srcptr z) + { return mpz_cmp_si(z, l) == 0; } + static bool eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d) == 0; } + static bool eval(double d, mpz_srcptr z) + { return mpz_cmp_d(z, d) == 0; } + + static bool eval(mpq_srcptr q, mpq_srcptr r) + { return mpq_equal(q, r) != 0; } + + static bool eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1) == 0; } + static bool eval(unsigned long int l, mpq_srcptr q) + { return mpq_cmp_ui(q, l, 1) == 0; } + static bool eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1) == 0; } + static bool eval(signed long int l, mpq_srcptr q) + { return mpq_cmp_si(q, l, 1) == 0; } + static bool eval(mpq_srcptr q, double d) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_equal(q, temp) != 0); + mpq_clear(temp); + return b; + } + static bool eval(double d, mpq_srcptr q) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_equal(temp, q) != 0); + mpq_clear(temp); + return b; + } + + static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; } + + static bool eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l) == 0; } + static bool eval(unsigned long int l, mpf_srcptr f) + { return mpf_cmp_ui(f, l) == 0; } + static bool eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l) == 0; } + static bool eval(signed long int l, mpf_srcptr f) + { return mpf_cmp_si(f, l) == 0; } + static bool eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d) == 0; } + static bool eval(double d, mpf_srcptr f) + { return mpf_cmp_d(f, d) == 0; } +}; + +struct __gmp_binary_not_equal +{ + static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) != 0; } + + static bool eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l) != 0; } + static bool eval(unsigned long int l, mpz_srcptr z) + { return mpz_cmp_ui(z, l) != 0; } + static bool eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l) != 0; } + static bool eval(signed long int l, mpz_srcptr z) + { return mpz_cmp_si(z, l) != 0; } + static bool eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d) != 0; } + static bool eval(double d, mpz_srcptr z) + { return mpz_cmp_d(z, d) != 0; } + + static bool eval(mpq_srcptr q, mpq_srcptr r) + { return mpq_equal(q, r) == 0; } + + static bool eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1) != 0; } + static bool eval(unsigned long int l, mpq_srcptr q) + { return mpq_cmp_ui(q, l, 1) != 0; } + static bool eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1) != 0; } + static bool eval(signed long int l, mpq_srcptr q) + { return mpq_cmp_si(q, l, 1) != 0; } + static bool eval(mpq_srcptr q, double d) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_equal(q, temp) == 0); + mpq_clear(temp); + return b; + } + static bool eval(double d, mpq_srcptr q) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_equal(temp, q) == 0); + mpq_clear(temp); + return b; + } + + static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) != 0; } + + static bool eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l) != 0; } + static bool eval(unsigned long int l, mpf_srcptr f) + { return mpf_cmp_ui(f, l) != 0; } + static bool eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l) != 0; } + static bool eval(signed long int l, mpf_srcptr f) + { return mpf_cmp_si(f, l) != 0; } + static bool eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d) != 0; } + static bool eval(double d, mpf_srcptr f) + { return mpf_cmp_d(f, d) != 0; } +}; + +struct __gmp_binary_less +{ + static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) < 0; } + + static bool eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l) < 0; } + static bool eval(unsigned long int l, mpz_srcptr z) + { return mpz_cmp_ui(z, l) > 0; } + static bool eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l) < 0; } + static bool eval(signed long int l, mpz_srcptr z) + { return mpz_cmp_si(z, l) > 0; } + static bool eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d) < 0; } + static bool eval(double d, mpz_srcptr z) + { return mpz_cmp_d(z, d) > 0; } + + static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) < 0; } + + static bool eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1) < 0; } + static bool eval(unsigned long int l, mpq_srcptr q) + { return mpq_cmp_ui(q, l, 1) > 0; } + static bool eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1) < 0; } + static bool eval(signed long int l, mpq_srcptr q) + { return mpq_cmp_si(q, l, 1) > 0; } + static bool eval(mpq_srcptr q, double d) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_cmp(q, temp) < 0); + mpq_clear(temp); + return b; + } + static bool eval(double d, mpq_srcptr q) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_cmp(temp, q) < 0); + mpq_clear(temp); + return b; + } + + static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; } + + static bool eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l) < 0; } + static bool eval(unsigned long int l, mpf_srcptr f) + { return mpf_cmp_ui(f, l) > 0; } + static bool eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l) < 0; } + static bool eval(signed long int l, mpf_srcptr f) + { return mpf_cmp_si(f, l) > 0; } + static bool eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d) < 0; } + static bool eval(double d, mpf_srcptr f) + { return mpf_cmp_d(f, d) > 0; } +}; + +struct __gmp_binary_less_equal +{ + static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) <= 0; } + + static bool eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l) <= 0; } + static bool eval(unsigned long int l, mpz_srcptr z) + { return mpz_cmp_ui(z, l) >= 0; } + static bool eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l) <= 0; } + static bool eval(signed long int l, mpz_srcptr z) + { return mpz_cmp_si(z, l) >= 0; } + static bool eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d) <= 0; } + static bool eval(double d, mpz_srcptr z) + { return mpz_cmp_d(z, d) >= 0; } + + static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) <= 0; } + + static bool eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1) <= 0; } + static bool eval(unsigned long int l, mpq_srcptr q) + { return mpq_cmp_ui(q, l, 1) >= 0; } + static bool eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1) <= 0; } + static bool eval(signed long int l, mpq_srcptr q) + { return mpq_cmp_si(q, l, 1) >= 0; } + static bool eval(mpq_srcptr q, double d) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_cmp(q, temp) <= 0); + mpq_clear(temp); + return b; + } + static bool eval(double d, mpq_srcptr q) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_cmp(temp, q) <= 0); + mpq_clear(temp); + return b; + } + + static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) <= 0; } + + static bool eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l) <= 0; } + static bool eval(unsigned long int l, mpf_srcptr f) + { return mpf_cmp_ui(f, l) >= 0; } + static bool eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l) <= 0; } + static bool eval(signed long int l, mpf_srcptr f) + { return mpf_cmp_si(f, l) >= 0; } + static bool eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d) <= 0; } + static bool eval(double d, mpf_srcptr f) + { return mpf_cmp_d(f, d) >= 0; } +}; + +struct __gmp_binary_greater +{ + static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) > 0; } + + static bool eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l) > 0; } + static bool eval(unsigned long int l, mpz_srcptr z) + { return mpz_cmp_ui(z, l) < 0; } + static bool eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l) > 0; } + static bool eval(signed long int l, mpz_srcptr z) + { return mpz_cmp_si(z, l) < 0; } + static bool eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d) > 0; } + static bool eval(double d, mpz_srcptr z) + { return mpz_cmp_d(z, d) < 0; } + + static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) > 0; } + + static bool eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1) > 0; } + static bool eval(unsigned long int l, mpq_srcptr q) + { return mpq_cmp_ui(q, l, 1) < 0; } + static bool eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1) > 0; } + static bool eval(signed long int l, mpq_srcptr q) + { return mpq_cmp_si(q, l, 1) < 0; } + static bool eval(mpq_srcptr q, double d) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_cmp(q, temp) > 0); + mpq_clear(temp); + return b; + } + static bool eval(double d, mpq_srcptr q) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_cmp(temp, q) > 0); + mpq_clear(temp); + return b; + } + + static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) > 0; } + + static bool eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l) > 0; } + static bool eval(unsigned long int l, mpf_srcptr f) + { return mpf_cmp_ui(f, l) < 0; } + static bool eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l) > 0; } + static bool eval(signed long int l, mpf_srcptr f) + { return mpf_cmp_si(f, l) < 0; } + static bool eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d) > 0; } + static bool eval(double d, mpf_srcptr f) + { return mpf_cmp_d(f, d) < 0; } +}; + +struct __gmp_binary_greater_equal +{ + static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) >= 0; } + + static bool eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l) >= 0; } + static bool eval(unsigned long int l, mpz_srcptr z) + { return mpz_cmp_ui(z, l) <= 0; } + static bool eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l) >= 0; } + static bool eval(signed long int l, mpz_srcptr z) + { return mpz_cmp_si(z, l) <= 0; } + static bool eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d) >= 0; } + static bool eval(double d, mpz_srcptr z) + { return mpz_cmp_d(z, d) <= 0; } + + static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) >= 0; } + + static bool eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1) >= 0; } + static bool eval(unsigned long int l, mpq_srcptr q) + { return mpq_cmp_ui(q, l, 1) <= 0; } + static bool eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1) >= 0; } + static bool eval(signed long int l, mpq_srcptr q) + { return mpq_cmp_si(q, l, 1) <= 0; } + static bool eval(mpq_srcptr q, double d) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_cmp(q, temp) >= 0); + mpq_clear(temp); + return b; + } + static bool eval(double d, mpq_srcptr q) + { + bool b; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + b = (mpq_cmp(temp, q) >= 0); + mpq_clear(temp); + return b; + } + + static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) >= 0; } + + static bool eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l) >= 0; } + static bool eval(unsigned long int l, mpf_srcptr f) + { return mpf_cmp_ui(f, l) <= 0; } + static bool eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l) >= 0; } + static bool eval(signed long int l, mpf_srcptr f) + { return mpf_cmp_si(f, l) <= 0; } + static bool eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d) >= 0; } + static bool eval(double d, mpf_srcptr f) + { return mpf_cmp_d(f, d) <= 0; } +}; + +struct __gmp_unary_increment +{ + static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); } + static void eval(mpq_ptr q) + { mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); } + static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); } +}; + +struct __gmp_unary_decrement +{ + static void eval(mpz_ptr z) { mpz_sub_ui(z, z, 1); } + static void eval(mpq_ptr q) + { mpz_sub(mpq_numref(q), mpq_numref(q), mpq_denref(q)); } + static void eval(mpf_ptr f) { mpf_sub_ui(f, f, 1); } +}; + +struct __gmp_abs_function +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_abs(z, w); } + static void eval(mpq_ptr q, mpq_srcptr r) { mpq_abs(q, r); } + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_abs(f, g); } +}; + +struct __gmp_trunc_function +{ + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_trunc(f, g); } +}; + +struct __gmp_floor_function +{ + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_floor(f, g); } +}; + +struct __gmp_ceil_function +{ + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_ceil(f, g); } +}; + +struct __gmp_sqrt_function +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_sqrt(z, w); } + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_sqrt(f, g); } +}; + +struct __gmp_hypot_function +{ + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_mul(f, h, h); + mpf_add(f, f, temp); + mpf_sqrt(f, f); + mpf_clear(temp); + } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_set_ui(f, l); + mpf_mul(f, f, f); + mpf_add(f, f, temp); + mpf_sqrt(f, f); + mpf_clear(temp); + } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_set_ui(f, l); + mpf_mul(f, f, f); + mpf_add(f, f, temp); + mpf_sqrt(f, f); + mpf_clear(temp); + } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_set_si(f, l); + mpf_mul(f, f, f); + mpf_add(f, f, temp); + mpf_sqrt(f, f); + mpf_clear(temp); + } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_set_si(f, l); + mpf_mul(f, f, f); + mpf_add(f, f, temp); + mpf_sqrt(f, f); + mpf_clear(temp); + } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_set_d(f, d); + mpf_mul(f, f, f); + mpf_add(f, f, temp); + mpf_sqrt(f, f); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_set_d(f, d); + mpf_mul(f, f, f); + mpf_add(f, f, temp); + mpf_sqrt(f, f); + mpf_clear(temp); + } +}; + +struct __gmp_sgn_function +{ + static int eval(mpz_srcptr z) { return mpz_sgn(z); } + static int eval(mpq_srcptr q) { return mpq_sgn(q); } + static int eval(mpf_srcptr f) { return mpf_sgn(f); } +}; + +struct __gmp_cmp_function +{ + static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); } + + static int eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l); } + static int eval(unsigned long int l, mpz_srcptr z) + { return -mpz_cmp_ui(z, l); } + static int eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l); } + static int eval(signed long int l, mpz_srcptr z) + { return -mpz_cmp_si(z, l); } + static int eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d); } + static int eval(double d, mpz_srcptr z) + { return -mpz_cmp_d(z, d); } + + static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); } + + static int eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1); } + static int eval(unsigned long int l, mpq_srcptr q) + { return -mpq_cmp_ui(q, l, 1); } + static int eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1); } + static int eval(signed long int l, mpq_srcptr q) + { return -mpq_cmp_si(q, l, 1); } + static int eval(mpq_srcptr q, double d) + { + int i; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + i = mpq_cmp(q, temp); + mpq_clear(temp); + return i; + } + static int eval(double d, mpq_srcptr q) + { + int i; + mpq_t temp; + mpq_init(temp); + mpq_set_d(temp, d); + i = mpq_cmp(temp, q); + mpq_clear(temp); + return i; + } + + static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); } + + static int eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l); } + static int eval(unsigned long int l, mpf_srcptr f) + { return -mpf_cmp_ui(f, l); } + static int eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l); } + static int eval(signed long int l, mpf_srcptr f) + { return -mpf_cmp_si(f, l); } + static int eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d); } + static int eval(double d, mpf_srcptr f) + { return -mpf_cmp_d(f, d); } +}; + +struct __gmp_rand_function +{ + static void eval(mpz_ptr z, gmp_randstate_t s, unsigned long int l) + { mpz_urandomb(z, s, l); } + static void eval(mpz_ptr z, gmp_randstate_t s, mpz_srcptr w) + { mpz_urandomm(z, s, w); } + static void eval(mpf_ptr f, gmp_randstate_t s, unsigned long int prec) + { mpf_urandomb(f, s, prec); } +}; + + +/**************** Auxiliary classes ****************/ + +/* this is much the same as gmp_allocated_string in gmp-impl.h + since gmp-impl.h is not publicly available, I redefine it here + I use a different name to avoid possible clashes */ +struct __gmp_alloc_cstring +{ + char *str; + __gmp_alloc_cstring(char *s) { str = s; } + ~__gmp_alloc_cstring() + { + void (*freefunc) (void *, size_t); + mp_get_memory_functions (NULL, NULL, &freefunc); + (*freefunc) (str, std::strlen(str)+1); + } +}; + + +// general expression template class +template <class T, class U> +class __gmp_expr; + + +// templates for resolving expression types +template <class T> +struct __gmp_resolve_ref +{ + typedef T ref_type; +}; + +template <class T, class U> +struct __gmp_resolve_ref<__gmp_expr<T, U> > +{ + typedef const __gmp_expr<T, U> & ref_type; +}; + + +template <class T, class U = T> +struct __gmp_resolve_expr; + +template <> +struct __gmp_resolve_expr<mpz_t> +{ + typedef mpz_t value_type; + typedef mpz_ptr ptr_type; +}; + +template <> +struct __gmp_resolve_expr<mpq_t> +{ + typedef mpq_t value_type; + typedef mpq_ptr ptr_type; +}; + +template <> +struct __gmp_resolve_expr<mpf_t> +{ + typedef mpf_t value_type; + typedef mpf_ptr ptr_type; +}; + +template <> +struct __gmp_resolve_expr<mpz_t, mpq_t> +{ + typedef mpq_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpq_t, mpz_t> +{ + typedef mpq_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpz_t, mpf_t> +{ + typedef mpf_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpf_t, mpz_t> +{ + typedef mpf_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpq_t, mpf_t> +{ + typedef mpf_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpf_t, mpq_t> +{ + typedef mpf_t value_type; +}; + + + +template <class T, class U, class V> +struct __gmp_resolve_temp +{ + typedef __gmp_expr<T, T> temp_type; +}; + +template <class T> +struct __gmp_resolve_temp<T, T, T> +{ + typedef const __gmp_expr<T, T> & temp_type; +}; + + +// classes for evaluating unary and binary expressions +template <class T, class Op> +struct __gmp_unary_expr +{ + const T &val; + + __gmp_unary_expr(const T &v) : val(v) { } +private: + __gmp_unary_expr(); +}; + +template <class T, class U, class Op> +struct __gmp_binary_expr +{ + typename __gmp_resolve_ref<T>::ref_type val1; + typename __gmp_resolve_ref<U>::ref_type val2; + + __gmp_binary_expr(const T &v1, const U &v2) : val1(v1), val2(v2) { } +private: + __gmp_binary_expr(); +}; + + +// functions for evaluating expressions +template <class T, class U> +void __gmp_set_expr(mpz_ptr, const __gmp_expr<T, U> &); +template <class T, class U> +void __gmp_set_expr(mpq_ptr, const __gmp_expr<T, U> &); +template <class T, class U> +void __gmp_set_expr(mpf_ptr, const __gmp_expr<T, U> &); + + +/**************** Macros for in-class declarations ****************/ +/* This is just repetitive code that is easier to maintain if it's written + only once */ + +#define __GMPP_DECLARE_COMPOUND_OPERATOR(fun) \ + template <class T, class U> \ + __gmp_expr<value_type, value_type> & fun(const __gmp_expr<T, U> &); + +#define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \ + __gmp_expr & fun(signed char); \ + __gmp_expr & fun(unsigned char); \ + __gmp_expr & fun(signed int); \ + __gmp_expr & fun(unsigned int); \ + __gmp_expr & fun(signed short int); \ + __gmp_expr & fun(unsigned short int); \ + __gmp_expr & fun(signed long int); \ + __gmp_expr & fun(unsigned long int); \ + __gmp_expr & fun(float); \ + __gmp_expr & fun(double); \ + __gmp_expr & fun(long double); + +#define __GMP_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPP_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPN_DECLARE_COMPOUND_OPERATOR(fun) + +#define __GMP_DECLARE_COMPOUND_OPERATOR_UI(fun) \ + __gmp_expr & fun(unsigned long int); + +#define __GMP_DECLARE_INCREMENT_OPERATOR(fun) \ + inline __gmp_expr & fun(); \ + inline __gmp_expr fun(int); + + +/**************** mpz_class -- wrapper for mpz_t ****************/ + +template <> +class __gmp_expr<mpz_t, mpz_t> +{ +private: + typedef mpz_t value_type; + value_type mp; +public: + unsigned long int get_prec() const { return mpf_get_default_prec(); } + + // constructors and destructor + __gmp_expr() { mpz_init(mp); } + + __gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); } + template <class T, class U> + __gmp_expr(const __gmp_expr<T, U> &expr) + { mpz_init(mp); __gmp_set_expr(mp, expr); } + + __gmp_expr(signed char c) { mpz_init_set_si(mp, c); } + __gmp_expr(unsigned char c) { mpz_init_set_ui(mp, c); } + + __gmp_expr(signed int i) { mpz_init_set_si(mp, i); } + __gmp_expr(unsigned int i) { mpz_init_set_ui(mp, i); } + + __gmp_expr(signed short int s) { mpz_init_set_si(mp, s); } + __gmp_expr(unsigned short int s) { mpz_init_set_ui(mp, s); } + + __gmp_expr(signed long int l) { mpz_init_set_si(mp, l); } + __gmp_expr(unsigned long int l) { mpz_init_set_ui(mp, l); } + + __gmp_expr(float f) { mpz_init_set_d(mp, f); } + __gmp_expr(double d) { mpz_init_set_d(mp, d); } + // __gmp_expr(long double ld) { mpz_init_set_d(mp, ld); } + + explicit __gmp_expr(const char *s) + { + if (mpz_init_set_str (mp, s, 0) != 0) + { + mpz_clear (mp); + throw std::invalid_argument ("mpz_set_str"); + } + } + __gmp_expr(const char *s, int base) + { + if (mpz_init_set_str (mp, s, base) != 0) + { + mpz_clear (mp); + throw std::invalid_argument ("mpz_set_str"); + } + } + explicit __gmp_expr(const std::string &s) + { + if (mpz_init_set_str (mp, s.c_str(), 0) != 0) + { + mpz_clear (mp); + throw std::invalid_argument ("mpz_set_str"); + } + } + __gmp_expr(const std::string &s, int base) + { + if (mpz_init_set_str(mp, s.c_str(), base) != 0) + { + mpz_clear (mp); + throw std::invalid_argument ("mpz_set_str"); + } + } + + explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); } + + ~__gmp_expr() { mpz_clear(mp); } + + // assignment operators + __gmp_expr & operator=(const __gmp_expr &z) + { mpz_set(mp, z.mp); return *this; } + template <class T, class U> + __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr) + { __gmp_set_expr(mp, expr); return *this; } + + __gmp_expr & operator=(signed char c) { mpz_set_si(mp, c); return *this; } + __gmp_expr & operator=(unsigned char c) { mpz_set_ui(mp, c); return *this; } + + __gmp_expr & operator=(signed int i) { mpz_set_si(mp, i); return *this; } + __gmp_expr & operator=(unsigned int i) { mpz_set_ui(mp, i); return *this; } + + __gmp_expr & operator=(signed short int s) + { mpz_set_si(mp, s); return *this; } + __gmp_expr & operator=(unsigned short int s) + { mpz_set_ui(mp, s); return *this; } + + __gmp_expr & operator=(signed long int l) + { mpz_set_si(mp, l); return *this; } + __gmp_expr & operator=(unsigned long int l) + { mpz_set_ui(mp, l); return *this; } + + __gmp_expr & operator=(float f) { mpz_set_d(mp, f); return *this; } + __gmp_expr & operator=(double d) { mpz_set_d(mp, d); return *this; } + // __gmp_expr & operator=(long double ld) + // { mpz_set_ld(mp, ld); return *this; } + + __gmp_expr & operator=(const char *s) + { + if (mpz_set_str (mp, s, 0) != 0) + throw std::invalid_argument ("mpz_set_str"); + return *this; + } + __gmp_expr & operator=(const std::string &s) + { + if (mpz_set_str(mp, s.c_str(), 0) != 0) + throw std::invalid_argument ("mpz_set_str"); + return *this; + } + + // string input/output functions + int set_str(const char *s, int base) + { return mpz_set_str(mp, s, base); } + int set_str(const std::string &s, int base) + { return mpz_set_str(mp, s.c_str(), base); } + std::string get_str(int base = 10) const + { + __gmp_alloc_cstring temp(mpz_get_str(0, base, mp)); + return std::string(temp.str); + } + + // conversion functions + mpz_srcptr __get_mp() const { return mp; } + mpz_ptr __get_mp() { return mp; } + mpz_srcptr get_mpz_t() const { return mp; } + mpz_ptr get_mpz_t() { return mp; } + + signed long int get_si() const { return mpz_get_si(mp); } + unsigned long int get_ui() const { return mpz_get_ui(mp); } + double get_d() const { return mpz_get_d(mp); } + + // bool fits_schar_p() const { return mpz_fits_schar_p(mp); } + // bool fits_uchar_p() const { return mpz_fits_uchar_p(mp); } + bool fits_sint_p() const { return mpz_fits_sint_p(mp); } + bool fits_uint_p() const { return mpz_fits_uint_p(mp); } + bool fits_sshort_p() const { return mpz_fits_sshort_p(mp); } + bool fits_ushort_p() const { return mpz_fits_ushort_p(mp); } + bool fits_slong_p() const { return mpz_fits_slong_p(mp); } + bool fits_ulong_p() const { return mpz_fits_ulong_p(mp); } + // bool fits_float_p() const { return mpz_fits_float_p(mp); } + // bool fits_double_p() const { return mpz_fits_double_p(mp); } + // bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); } + + // member operators + __GMP_DECLARE_COMPOUND_OPERATOR(operator+=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator-=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator*=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator/=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator%=) + + __GMPP_DECLARE_COMPOUND_OPERATOR(operator&=) + __GMPP_DECLARE_COMPOUND_OPERATOR(operator|=) + __GMPP_DECLARE_COMPOUND_OPERATOR(operator^=) + + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) + + __GMP_DECLARE_INCREMENT_OPERATOR(operator++) + __GMP_DECLARE_INCREMENT_OPERATOR(operator--) +}; + +typedef __gmp_expr<mpz_t, mpz_t> mpz_class; + + +/**************** mpq_class -- wrapper for mpq_t ****************/ + +template <> +class __gmp_expr<mpq_t, mpq_t> +{ +private: + typedef mpq_t value_type; + value_type mp; +public: + unsigned long int get_prec() const { return mpf_get_default_prec(); } + void canonicalize() { mpq_canonicalize(mp); } + + // constructors and destructor + __gmp_expr() { mpq_init(mp); } + + __gmp_expr(const __gmp_expr &q) { mpq_init(mp); mpq_set(mp, q.mp); } + template <class T, class U> + __gmp_expr(const __gmp_expr<T, U> &expr) + { mpq_init(mp); __gmp_set_expr(mp, expr); } + + __gmp_expr(signed char c) { mpq_init(mp); mpq_set_si(mp, c, 1); } + __gmp_expr(unsigned char c) { mpq_init(mp); mpq_set_ui(mp, c, 1); } + + __gmp_expr(signed int i) { mpq_init(mp); mpq_set_si(mp, i, 1); } + __gmp_expr(unsigned int i) { mpq_init(mp); mpq_set_ui(mp, i, 1); } + + __gmp_expr(signed short int s) { mpq_init(mp); mpq_set_si(mp, s, 1); } + __gmp_expr(unsigned short int s) { mpq_init(mp); mpq_set_ui(mp, s, 1); } + + __gmp_expr(signed long int l) { mpq_init(mp); mpq_set_si(mp, l, 1); } + __gmp_expr(unsigned long int l) { mpq_init(mp); mpq_set_ui(mp, l, 1); } + + __gmp_expr(float f) { mpq_init(mp); mpq_set_d(mp, f); } + __gmp_expr(double d) { mpq_init(mp); mpq_set_d(mp, d); } + // __gmp_expr(long double ld) { mpq_init(mp); mpq_set_ld(mp, ld); } + + explicit __gmp_expr(const char *s) + { + mpq_init (mp); + if (mpq_set_str (mp, s, 0) != 0) + { + mpq_clear (mp); + throw std::invalid_argument ("mpq_set_str"); + } + } + __gmp_expr(const char *s, int base) + { + mpq_init (mp); + if (mpq_set_str(mp, s, base) != 0) + { + mpq_clear (mp); + throw std::invalid_argument ("mpq_set_str"); + } + } + explicit __gmp_expr(const std::string &s) + { + mpq_init (mp); + if (mpq_set_str (mp, s.c_str(), 0) != 0) + { + mpq_clear (mp); + throw std::invalid_argument ("mpq_set_str"); + } + } + __gmp_expr(const std::string &s, int base) + { + mpq_init(mp); + if (mpq_set_str (mp, s.c_str(), base) != 0) + { + mpq_clear (mp); + throw std::invalid_argument ("mpq_set_str"); + } + } + explicit __gmp_expr(mpq_srcptr q) { mpq_init(mp); mpq_set(mp, q); } + + __gmp_expr(const mpz_class &num, const mpz_class &den) + { + mpq_init(mp); + mpz_set(mpq_numref(mp), num.get_mpz_t()); + mpz_set(mpq_denref(mp), den.get_mpz_t()); + } + + ~__gmp_expr() { mpq_clear(mp); } + + // assignment operators + __gmp_expr & operator=(const __gmp_expr &q) + { mpq_set(mp, q.mp); return *this; } + template <class T, class U> + __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr) + { __gmp_set_expr(mp, expr); return *this; } + + __gmp_expr & operator=(signed char c) + { mpq_set_si(mp, c, 1); return *this; } + __gmp_expr & operator=(unsigned char c) + { mpq_set_ui(mp, c, 1); return *this; } + + __gmp_expr & operator=(signed int i) { mpq_set_si(mp, i, 1); return *this; } + __gmp_expr & operator=(unsigned int i) + { mpq_set_ui(mp, i, 1); return *this; } + + __gmp_expr & operator=(signed short int s) + { mpq_set_si(mp, s, 1); return *this; } + __gmp_expr & operator=(unsigned short int s) + { mpq_set_ui(mp, s, 1); return *this; } + + __gmp_expr & operator=(signed long int l) + { mpq_set_si(mp, l, 1); return *this; } + __gmp_expr & operator=(unsigned long int l) + { mpq_set_ui(mp, l, 1); return *this; } + + __gmp_expr & operator=(float f) { mpq_set_d(mp, f); return *this; } + __gmp_expr & operator=(double d) { mpq_set_d(mp, d); return *this; } + // __gmp_expr & operator=(long double ld) + // { mpq_set_ld(mp, ld); return *this; } + + __gmp_expr & operator=(const char *s) + { + if (mpq_set_str (mp, s, 0) != 0) + throw std::invalid_argument ("mpq_set_str"); + return *this; + } + __gmp_expr & operator=(const std::string &s) + { + if (mpq_set_str(mp, s.c_str(), 0) != 0) + throw std::invalid_argument ("mpq_set_str"); + return *this; + } + + // string input/output functions + int set_str(const char *s, int base) + { return mpq_set_str(mp, s, base); } + int set_str(const std::string &s, int base) + { return mpq_set_str(mp, s.c_str(), base); } + std::string get_str(int base = 10) const + { + __gmp_alloc_cstring temp(mpq_get_str(0, base, mp)); + return std::string(temp.str); + } + + // conversion functions + + // casting a reference to an mpz_t to mpz_class & is a dirty hack, + // but works because the internal representation of mpz_class is + // exactly an mpz_t + const mpz_class & get_num() const + { return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); } + mpz_class & get_num() + { return reinterpret_cast<mpz_class &>(*mpq_numref(mp)); } + const mpz_class & get_den() const + { return reinterpret_cast<const mpz_class &>(*mpq_denref(mp)); } + mpz_class & get_den() + { return reinterpret_cast<mpz_class &>(*mpq_denref(mp)); } + + mpq_srcptr __get_mp() const { return mp; } + mpq_ptr __get_mp() { return mp; } + mpq_srcptr get_mpq_t() const { return mp; } + mpq_ptr get_mpq_t() { return mp; } + + mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); } + mpz_ptr get_num_mpz_t() { return mpq_numref(mp); } + mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); } + mpz_ptr get_den_mpz_t() { return mpq_denref(mp); } + + double get_d() const { return mpq_get_d(mp); } + + // compound assignments + __GMP_DECLARE_COMPOUND_OPERATOR(operator+=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator-=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator*=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator/=) + + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) + + __GMP_DECLARE_INCREMENT_OPERATOR(operator++) + __GMP_DECLARE_INCREMENT_OPERATOR(operator--) +}; + +typedef __gmp_expr<mpq_t, mpq_t> mpq_class; + + +/**************** mpf_class -- wrapper for mpf_t ****************/ + +template <> +class __gmp_expr<mpf_t, mpf_t> +{ +private: + typedef mpf_t value_type; + value_type mp; +public: + unsigned long int get_prec() const { return mpf_get_prec(mp); } + + void set_prec(unsigned long int prec) { mpf_set_prec(mp, prec); } + void set_prec_raw(unsigned long int prec) { mpf_set_prec_raw(mp, prec); } + + // constructors and destructor + __gmp_expr() { mpf_init(mp); } + + __gmp_expr(const __gmp_expr &f) + { mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); } + __gmp_expr(const __gmp_expr &f, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set(mp, f.mp); } + template <class T, class U> + __gmp_expr(const __gmp_expr<T, U> &expr) + { mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); } + template <class T, class U> + __gmp_expr(const __gmp_expr<T, U> &expr, unsigned long int prec) + { mpf_init2(mp, prec); __gmp_set_expr(mp, expr); } + + __gmp_expr(signed char c) { mpf_init_set_si(mp, c); } + __gmp_expr(signed char c, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_si(mp, c); } + __gmp_expr(unsigned char c) { mpf_init_set_ui(mp, c); } + __gmp_expr(unsigned char c, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, c); } + + __gmp_expr(signed int i) { mpf_init_set_si(mp, i); } + __gmp_expr(signed int i, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_si(mp, i); } + __gmp_expr(unsigned int i) { mpf_init_set_ui(mp, i); } + __gmp_expr(unsigned int i, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, i); } + + __gmp_expr(signed short int s) { mpf_init_set_si(mp, s); } + __gmp_expr(signed short int s, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_si(mp, s); } + __gmp_expr(unsigned short int s) { mpf_init_set_ui(mp, s); } + __gmp_expr(unsigned short int s, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, s); } + + __gmp_expr(signed long int l) { mpf_init_set_si(mp, l); } + __gmp_expr(signed long int l, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_si(mp, l); } + __gmp_expr(unsigned long int l) { mpf_init_set_ui(mp, l); } + __gmp_expr(unsigned long int l, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, l); } + + __gmp_expr(float f) { mpf_init_set_d(mp, f); } + __gmp_expr(float f, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_d(mp, f); } + __gmp_expr(double d) { mpf_init_set_d(mp, d); } + __gmp_expr(double d, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_d(mp, d); } + // __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); } + // __gmp_expr(long double ld, unsigned long int prec) + // { mpf_init2(mp, prec); mpf_set_d(mp, ld); } + + explicit __gmp_expr(const char *s) + { + if (mpf_init_set_str (mp, s, 0) != 0) + { + mpf_clear (mp); + throw std::invalid_argument ("mpf_set_str"); + } + } + __gmp_expr(const char *s, unsigned long int prec, int base = 0) + { + mpf_init2(mp, prec); + if (mpf_set_str(mp, s, base) != 0) + { + mpf_clear (mp); + throw std::invalid_argument ("mpf_set_str"); + } + } + explicit __gmp_expr(const std::string &s) + { + if (mpf_init_set_str(mp, s.c_str(), 0) != 0) + { + mpf_clear (mp); + throw std::invalid_argument ("mpf_set_str"); + } + } + __gmp_expr(const std::string &s, unsigned long int prec, int base = 0) + { + mpf_init2(mp, prec); + if (mpf_set_str(mp, s.c_str(), base) != 0) + { + mpf_clear (mp); + throw std::invalid_argument ("mpf_set_str"); + } + } + + explicit __gmp_expr(mpf_srcptr f) + { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); } + __gmp_expr(mpf_srcptr f, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set(mp, f); } + + ~__gmp_expr() { mpf_clear(mp); } + + // assignment operators + __gmp_expr & operator=(const __gmp_expr &f) + { mpf_set(mp, f.mp); return *this; } + template <class T, class U> + __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr) + { __gmp_set_expr(mp, expr); return *this; } + + __gmp_expr & operator=(signed char c) { mpf_set_si(mp, c); return *this; } + __gmp_expr & operator=(unsigned char c) { mpf_set_ui(mp, c); return *this; } + + __gmp_expr & operator=(signed int i) { mpf_set_si(mp, i); return *this; } + __gmp_expr & operator=(unsigned int i) { mpf_set_ui(mp, i); return *this; } + + __gmp_expr & operator=(signed short int s) + { mpf_set_si(mp, s); return *this; } + __gmp_expr & operator=(unsigned short int s) + { mpf_set_ui(mp, s); return *this; } + + __gmp_expr & operator=(signed long int l) + { mpf_set_si(mp, l); return *this; } + __gmp_expr & operator=(unsigned long int l) + { mpf_set_ui(mp, l); return *this; } + + __gmp_expr & operator=(float f) { mpf_set_d(mp, f); return *this; } + __gmp_expr & operator=(double d) { mpf_set_d(mp, d); return *this; } + // __gmp_expr & operator=(long double ld) + // { mpf_set_ld(mp, ld); return *this; } + + __gmp_expr & operator=(const char *s) + { + if (mpf_set_str (mp, s, 0) != 0) + throw std::invalid_argument ("mpf_set_str"); + return *this; + } + __gmp_expr & operator=(const std::string &s) + { + if (mpf_set_str(mp, s.c_str(), 0) != 0) + throw std::invalid_argument ("mpf_set_str"); + return *this; + } + + // string input/output functions + int set_str(const char *s, int base) + { return mpf_set_str(mp, s, base); } + int set_str(const std::string &s, int base) + { return mpf_set_str(mp, s.c_str(), base); } + std::string get_str(mp_exp_t &expo, int base = 10, size_t size = 0) const + { + __gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, size, mp)); + return std::string(temp.str); + } + + // conversion functions + mpf_srcptr __get_mp() const { return mp; } + mpf_ptr __get_mp() { return mp; } + mpf_srcptr get_mpf_t() const { return mp; } + mpf_ptr get_mpf_t() { return mp; } + + signed long int get_si() const { return mpf_get_si(mp); } + unsigned long int get_ui() const { return mpf_get_ui(mp); } + double get_d() const { return mpf_get_d(mp); } + + // bool fits_schar_p() const { return mpf_fits_schar_p(mp); } + // bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); } + bool fits_sint_p() const { return mpf_fits_sint_p(mp); } + bool fits_uint_p() const { return mpf_fits_uint_p(mp); } + bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); } + bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); } + bool fits_slong_p() const { return mpf_fits_slong_p(mp); } + bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); } + // bool fits_float_p() const { return mpf_fits_float_p(mp); } + // bool fits_double_p() const { return mpf_fits_double_p(mp); } + // bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); } + + // compound assignments + __GMP_DECLARE_COMPOUND_OPERATOR(operator+=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator-=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator*=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator/=) + + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) + + __GMP_DECLARE_INCREMENT_OPERATOR(operator++) + __GMP_DECLARE_INCREMENT_OPERATOR(operator--) +}; + +typedef __gmp_expr<mpf_t, mpf_t> mpf_class; + + + +/**************** I/O operators ****************/ + +// these should (and will) be provided separately + +template <class T> +inline std::ostream & operator<< +(std::ostream &o, const __gmp_expr<T, T> &expr) +{ + return o << expr.__get_mp(); +} + +template <class T, class U> +inline std::ostream & operator<< +(std::ostream &o, const __gmp_expr<T, U> &expr) +{ + __gmp_expr<T, T> temp(expr); + return o << temp.__get_mp(); +} + + +template <class T> +inline std::istream & operator>>(std::istream &i, __gmp_expr<T, T> &expr) +{ + return i >> expr.__get_mp(); +} + +inline std::istream & operator>>(std::istream &i, mpq_class &q) +{ + i >> q.get_mpq_t(); + // q.canonicalize(); // you might want to uncomment this + return i; +} + + +/**************** Functions for type conversion ****************/ + +template <> +inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w) +{ + mpz_set(z, w.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpz_t, T> &expr) +{ + expr.eval(z); +} + +template <> +inline void __gmp_set_expr(mpz_ptr z, const mpq_class &q) +{ + mpz_set_q(z, q.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpq_t, T> &expr) +{ + mpq_class temp(expr); + mpz_set_q(z, temp.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const mpf_class &f) +{ + mpz_set_f(z, f.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpf_t, T> &expr) +{ + mpf_class temp(expr); + mpz_set_f(z, temp.get_mpf_t()); +} + +template <> +inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z) +{ + mpq_set_z(q, z.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpz_t, T> &expr) +{ + mpz_class temp(expr); + mpq_set_z(q, temp.get_mpz_t()); +} + +template <> +inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r) +{ + mpq_set(q, r.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpq_t, T> &expr) +{ + expr.eval(q); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const mpf_class &f) +{ + mpq_set_f(q, f.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpf_t, T> &expr) +{ + mpf_class temp(expr); + mpq_set_f(q, temp.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const mpz_class &z) +{ + mpf_set_z(f, z.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpz_t, T> &expr) +{ + mpz_class temp(expr); + mpf_set_z(f, temp.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const mpq_class &q) +{ + mpf_set_q(f, q.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpq_t, T> &expr) +{ + mpq_class temp(expr); + mpf_set_q(f, temp.get_mpq_t()); +} + +template <> +inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g) +{ + mpf_set(f, g.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpf_t, T> &expr) +{ + expr.eval(f, mpf_get_prec(f)); +} + + +/**************** Specializations of __gmp_expr ****************/ +/* The eval() method of __gmp_expr<T, U> evaluates the corresponding + expression and assigns the result to its argument, which is either an + mpz_t, mpq_t, or mpf_t as specified by the T argument. + Compound expressions are evaluated recursively (temporaries are created + to hold intermediate values), while for simple expressions the eval() + method of the appropriate function object (available as the Op argument + of either __gmp_unary_expr<T, Op> or __gmp_binary_expr<T, U, Op>) is + called. */ + + +/**************** Unary expressions ****************/ +/* cases: + - simple: argument is mp*_class, that is, __gmp_expr<T, T> + - compound: argument is __gmp_expr<T, U> (with U not equal to T) */ + + +// simple expressions + +template <class T, class Op> +class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, T>, Op> > +{ +private: + typedef __gmp_expr<T, T> val_type; + + __gmp_unary_expr<val_type, Op> expr; +public: + __gmp_expr(const val_type &val) : expr(val) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int = 0) const + { Op::eval(p, expr.val.__get_mp()); } + const val_type & get_val() const { return expr.val; } + unsigned long int get_prec() const { return expr.val.get_prec(); } +}; + + +// compound expressions + +template <class T, class U, class Op> +class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, Op> > +{ +private: + typedef __gmp_expr<T, U> val_type; + + __gmp_unary_expr<val_type, Op> expr; +public: + __gmp_expr(const val_type &val) : expr(val) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { __gmp_expr<T, T> temp(expr.val); Op::eval(p, temp.__get_mp()); } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { __gmp_expr<T, T> temp(expr.val, prec); Op::eval(p, temp.__get_mp()); } + const val_type & get_val() const { return expr.val; } + unsigned long int get_prec() const { return expr.val.get_prec(); } +}; + + +/**************** Binary expressions ****************/ +/* simple: + - arguments are both mp*_class + - one argument is mp*_class, one is a built-in type + compound: + - one is mp*_class, one is __gmp_expr<T, U> + - one is __gmp_expr<T, U>, one is built-in + - both arguments are __gmp_expr<...> */ + + +// simple expressions + +template <class T, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, T>, Op> > +{ +private: + typedef __gmp_expr<T, T> val1_type; + typedef __gmp_expr<T, T> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int = 0) const + { Op::eval(p, expr.val1.__get_mp(), expr.val2.__get_mp()); } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +// simple expressions, T is a built-in numerical type + +template <class T, class U, class Op> +class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, T>, U, Op> > +{ +private: + typedef __gmp_expr<T, T> val1_type; + typedef U val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int = 0) const + { Op::eval(p, expr.val1.__get_mp(), expr.val2); } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const { return expr.val1.get_prec(); } +}; + +template <class T, class U, class Op> +class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, T>, Op> > +{ +private: + typedef U val1_type; + typedef __gmp_expr<T, T> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int = 0) const + { Op::eval(p, expr.val1, expr.val2.__get_mp()); } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const { return expr.val2.get_prec(); } +}; + + +// compound expressions, one argument is a subexpression + +template <class T, class U, class V, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<U, V>, Op> > +{ +private: + typedef __gmp_expr<T, T> val1_type; + typedef __gmp_expr<U, V> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_expr<T, T> temp(expr.val2); + Op::eval(p, expr.val1.__get_mp(), temp.__get_mp()); + } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { + __gmp_expr<T, T> temp(expr.val2, prec); + Op::eval(p, expr.val1.__get_mp(), temp.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class V, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, T>, Op> > +{ +private: + typedef __gmp_expr<U, V> val1_type; + typedef __gmp_expr<T, T> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_expr<T, T> temp(expr.val1); + Op::eval(p, temp.__get_mp(), expr.val2.__get_mp()); + } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { + __gmp_expr<T, T> temp(expr.val1, prec); + Op::eval(p, temp.__get_mp(), expr.val2.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, U>, Op> > +{ +private: + typedef __gmp_expr<T, T> val1_type; + typedef __gmp_expr<T, U> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_expr<T, T> temp(expr.val2); + Op::eval(p, expr.val1.__get_mp(), temp.__get_mp()); + } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { + __gmp_expr<T, T> temp(expr.val2, prec); + Op::eval(p, expr.val1.__get_mp(), temp.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, T>, Op> > +{ +private: + typedef __gmp_expr<T, U> val1_type; + typedef __gmp_expr<T, T> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_expr<T, T> temp(expr.val1); + Op::eval(p, temp.__get_mp(), expr.val2.__get_mp()); + } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { + __gmp_expr<T, T> temp(expr.val1, prec); + Op::eval(p, temp.__get_mp(), expr.val2.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +// one argument is a subexpression, one is a built-in + +template <class T, class U, class V, class Op> +class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> > +{ +private: + typedef __gmp_expr<T, U> val1_type; + typedef V val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_expr<T, T> temp(expr.val1); + Op::eval(p, temp.__get_mp(), expr.val2); + } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { + __gmp_expr<T, T> temp(expr.val1, prec); + Op::eval(p, temp.__get_mp(), expr.val2); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const { return expr.val1.get_prec(); } +}; + +template <class T, class U, class V, class Op> +class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, V>, Op> > +{ +private: + typedef U val1_type; + typedef __gmp_expr<T, V> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_expr<T, T> temp(expr.val2); + Op::eval(p, expr.val1, temp.__get_mp()); + } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { + __gmp_expr<T, T> temp(expr.val2, prec); + Op::eval(p, expr.val1, temp.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const { return expr.val2.get_prec(); } +}; + + +// both arguments are subexpressions + +template <class T, class U, class V, class W, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> > +{ +private: + typedef __gmp_expr<T, U> val1_type; + typedef __gmp_expr<V, W> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_expr<T, T> temp1(expr.val1), temp2(expr.val2); + Op::eval(p, temp1.__get_mp(), temp2.__get_mp()); + } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { + __gmp_expr<T, T> temp1(expr.val1, prec), temp2(expr.val2, prec); + Op::eval(p, temp1.__get_mp(), temp2.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class V, class W, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, W>, Op> > +{ +private: + typedef __gmp_expr<U, V> val1_type; + typedef __gmp_expr<T, W> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_expr<T, T> temp1(expr.val1), temp2(expr.val2); + Op::eval(p, temp1.__get_mp(), temp2.__get_mp()); + } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { + __gmp_expr<T, T> temp1(expr.val1, prec), temp2(expr.val2, prec); + Op::eval(p, temp1.__get_mp(), temp2.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class V, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, V>, Op> > +{ +private: + typedef __gmp_expr<T, U> val1_type; + typedef __gmp_expr<T, V> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_expr<T, T> temp1(expr.val1), temp2(expr.val2); + Op::eval(p, temp1.__get_mp(), temp2.__get_mp()); + } + void eval(typename __gmp_resolve_expr<T>::ptr_type p, + unsigned long int prec) const + { + __gmp_expr<T, T> temp1(expr.val1, prec), temp2(expr.val2, prec); + Op::eval(p, temp1.__get_mp(), temp2.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +/**************** Special cases ****************/ + +/* Some operations (i.e., add and subtract) with mixed mpz/mpq arguments + can be done directly without first converting the mpz to mpq. + Appropriate specializations of __gmp_expr are required. */ + + +#define __GMPZQ_DEFINE_EXPR(eval_fun) \ + \ +template <> \ +class __gmp_expr<mpq_t, __gmp_binary_expr<mpz_class, mpq_class, eval_fun> > \ +{ \ +private: \ + typedef mpz_class val1_type; \ + typedef mpq_class val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { eval_fun::eval(q, expr.val1.get_mpz_t(), expr.val2.get_mpq_t()); } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <> \ +class __gmp_expr<mpq_t, __gmp_binary_expr<mpq_class, mpz_class, eval_fun> > \ +{ \ +private: \ + typedef mpq_class val1_type; \ + typedef mpz_class val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { eval_fun::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpz_t()); } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr \ +<mpq_t, __gmp_binary_expr<mpz_class, __gmp_expr<mpq_t, T>, eval_fun> > \ +{ \ +private: \ + typedef mpz_class val1_type; \ + typedef __gmp_expr<mpq_t, T> val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpq_class temp(expr.val2); \ + eval_fun::eval(q, expr.val1.get_mpz_t(), temp.get_mpq_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr \ +<mpq_t, __gmp_binary_expr<mpq_class, __gmp_expr<mpz_t, T>, eval_fun> > \ +{ \ +private: \ + typedef mpq_class val1_type; \ + typedef __gmp_expr<mpz_t, T> val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp(expr.val2); \ + eval_fun::eval(q, expr.val1.get_mpq_t(), temp.get_mpz_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr \ +<mpq_t, __gmp_binary_expr<__gmp_expr<mpz_t, T>, mpq_class, eval_fun> > \ +{ \ +private: \ + typedef __gmp_expr<mpz_t, T> val1_type; \ + typedef mpq_class val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp(expr.val1); \ + eval_fun::eval(q, temp.get_mpz_t(), expr.val2.get_mpq_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr \ +<mpq_t, __gmp_binary_expr<__gmp_expr<mpq_t, T>, mpz_class, eval_fun> > \ +{ \ +private: \ + typedef __gmp_expr<mpq_t, T> val1_type; \ + typedef mpz_class val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpq_class temp(expr.val1); \ + eval_fun::eval(q, temp.get_mpq_t(), expr.val2.get_mpz_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T, class U> \ +class __gmp_expr<mpq_t, __gmp_binary_expr \ +<__gmp_expr<mpz_t, T>, __gmp_expr<mpq_t, U>, eval_fun> > \ +{ \ +private: \ + typedef __gmp_expr<mpz_t, T> val1_type; \ + typedef __gmp_expr<mpq_t, U> val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp1(expr.val1); \ + mpq_class temp2(expr.val2); \ + eval_fun::eval(q, temp1.get_mpz_t(), temp2.get_mpq_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T, class U> \ +class __gmp_expr<mpq_t, __gmp_binary_expr \ +<__gmp_expr<mpq_t, T>, __gmp_expr<mpz_t, U>, eval_fun> > \ +{ \ +private: \ + typedef __gmp_expr<mpq_t, T> val1_type; \ + typedef __gmp_expr<mpz_t, U> val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpq_class temp1(expr.val1); \ + mpz_class temp2(expr.val2); \ + eval_fun::eval(q, temp1.get_mpq_t(), temp2.get_mpz_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; + + +__GMPZQ_DEFINE_EXPR(__gmp_binary_plus) +__GMPZQ_DEFINE_EXPR(__gmp_binary_minus) + + + +/**************** Macros for defining functions ****************/ +/* Results of operators and functions are instances of __gmp_expr<T, U>. + T determines the numerical type of the expression: it can be either + mpz_t, mpq_t, or mpf_t. When the arguments of a binary + expression have different numerical types, __gmp_resolve_expr is used + to determine the "larger" type. + U is either __gmp_unary_expr<V, Op> or __gmp_binary_expr<V, W, Op>, + where V and W are the arguments' types -- they can in turn be + expressions, thus allowing to build compound expressions to any + degree of complexity. + Op is a function object that must have an eval() method accepting + appropriate arguments. + Actual evaluation of a __gmp_expr<T, U> object is done when it gets + assigned to an mp*_class ("lazy" evaluation): this is done by calling + its eval() method. */ + + +// non-member unary operators and functions + +#define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun) \ + \ +template <class T, class U> \ +inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \ +} + +#define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_temp<T, T, U>::temp_type temp(expr); \ + return eval_fun::eval(temp.__get_mp()); \ +} + + +// non-member binary operators and functions + +#define __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ + \ +template <class T, class U, class V, class W> \ +inline __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \ +__gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<V, W> &expr2) \ +{ \ + return __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \ + __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \ + (expr1, expr2); \ +} + +#define __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, bigtype) \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, type t) \ +{ \ + return __gmp_expr \ + <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >(expr, t); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> > \ +fun(type t, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr \ + <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >(t, expr); \ +} + +#define __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ +__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, signed long int) + +#define __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ +__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, unsigned long int) + +#define __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ +__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, double) + +#define __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ +__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, long double) + +#define __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ +__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed char) \ +__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned char) \ +__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed int) \ +__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned int) \ +__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed short int) \ +__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned short int) \ +__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long int) \ +__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long int) \ +__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, float) \ +__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, double) \ +__GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, long double) + +#define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ +__GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ +__GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun) + + +#define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun) \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, unsigned long int l) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, l); \ +} + + +#define __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ + \ +template <class T, class U, class V, class W> \ +inline type fun(const __gmp_expr<T, U> &expr1, \ + const __gmp_expr<V, W> &expr2) \ +{ \ + typedef typename __gmp_resolve_expr<T, V>::value_type eval_type; \ + typename __gmp_resolve_temp<eval_type, T, U>::temp_type temp1(expr1); \ + typename __gmp_resolve_temp<eval_type, V, W>::temp_type temp2(expr2); \ + return eval_fun::eval(temp1.__get_mp(), temp2.__get_mp()); \ +} + +#define __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \ + type2, bigtype) \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, type2 t) \ +{ \ + typename __gmp_resolve_temp<T, T, U>::temp_type temp(expr); \ + return eval_fun::eval(temp.__get_mp(), static_cast<bigtype>(t)); \ +} \ + \ +template <class T, class U> \ +inline type fun(type2 t, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_temp<T, T, U>::temp_type temp(expr); \ + return eval_fun::eval(static_cast<bigtype>(t), temp.__get_mp()); \ +} + +#define __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \ + type2, signed long int) + +#define __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \ + type2, unsigned long int) + +#define __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, double) + +#define __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, long double) + +#define __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ +__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed char) \ +__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned char) \ +__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed int) \ +__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned int) \ +__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed short int) \ +__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned short int) \ +__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long int) \ +__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long int) \ +__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, float) \ +__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, double) \ +__GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, long double) + +#define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ +__GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ +__GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) + + +// member operators + +#define __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ + \ +template <class T, class U> \ +inline type##_class & type##_class::fun(const __gmp_expr<T, U> &expr) \ +{ \ + __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr \ + <type##_class, __gmp_expr<T, U>, eval_fun> >(*this, expr)); \ + return *this; \ +} + +#define __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \ + type2, bigtype) \ + \ +inline type##_class & type##_class::fun(type2 t) \ +{ \ + __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr \ + <type##_class, bigtype, eval_fun> >(*this, t)); \ + return *this; \ +} + +#define __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \ + type2, signed long int) + +#define __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \ + type2, unsigned long int) + +#define __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, double) + +#define __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, long double) + +#define __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ +__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed char) \ +__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned char) \ +__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed int) \ +__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned int) \ +__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed short int) \ +__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned short int) \ +__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long int) \ +__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long int) \ +__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, float) \ +__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, double) \ +/* __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, long double) */ + +#define __GMP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ +__GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ +__GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) + +#define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun) + +#define __GMPZZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ +__GMPP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun) + +#define __GMPQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR(mpq, fun, eval_fun) + +#define __GMPF_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR(mpf, fun, eval_fun) + + + +#define __GMP_DEFINE_COMPOUND_OPERATOR_UI(type, fun, eval_fun) \ + \ +inline type##_class & type##_class::fun(unsigned long int l) \ +{ \ + __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr \ + <type##_class, unsigned long int, eval_fun> >(*this, l)); \ + return *this; \ +} + +#define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpz, fun, eval_fun) + +#define __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpq, fun, eval_fun) + +#define __GMPF_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpf, fun, eval_fun) + + + +#define __GMP_DEFINE_INCREMENT_OPERATOR(type, fun, eval_fun) \ + \ +inline type##_class & type##_class::fun() \ +{ \ + eval_fun::eval(mp); \ + return *this; \ +} \ + \ +inline type##_class type##_class::fun(int) \ +{ \ + type##_class temp(*this); \ + eval_fun::eval(mp); \ + return temp; \ +} + +#define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_INCREMENT_OPERATOR(mpz, fun, eval_fun) + +#define __GMPQ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_INCREMENT_OPERATOR(mpq, fun, eval_fun) + +#define __GMPF_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_INCREMENT_OPERATOR(mpf, fun, eval_fun) + + + +/**************** Arithmetic operators and functions ****************/ + +// non-member operators and functions + +__GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus) +__GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus) +__GMP_DEFINE_UNARY_FUNCTION(operator~, __gmp_unary_com) + +__GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus) +__GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus) +__GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies) +__GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides) +__GMP_DEFINE_BINARY_FUNCTION(operator%, __gmp_binary_modulus) +__GMP_DEFINE_BINARY_FUNCTION(operator&, __gmp_binary_and) +__GMP_DEFINE_BINARY_FUNCTION(operator|, __gmp_binary_ior) +__GMP_DEFINE_BINARY_FUNCTION(operator^, __gmp_binary_xor) + +__GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift) +__GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift) + +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, __gmp_binary_not_equal) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, __gmp_binary_less_equal) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, \ + __gmp_binary_greater_equal) + +__GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function) +__GMP_DEFINE_UNARY_FUNCTION(trunc, __gmp_trunc_function) +__GMP_DEFINE_UNARY_FUNCTION(floor, __gmp_floor_function) +__GMP_DEFINE_UNARY_FUNCTION(ceil, __gmp_ceil_function) +__GMP_DEFINE_UNARY_FUNCTION(sqrt, __gmp_sqrt_function) +__GMP_DEFINE_BINARY_FUNCTION(hypot, __gmp_hypot_function) + +__GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(int, cmp, __gmp_cmp_function) + +// member operators for mpz_class + +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus) + +__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and) +__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior) +__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor) + +__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) +__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) + +__GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) +__GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + +// member operators for mpq_class + +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) + +__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) +__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) + +__GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) +__GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + +// member operators for mpf_class + +__GMPF_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) +__GMPF_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) +__GMPF_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) +__GMPF_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) + +__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) +__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) + +__GMPF_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) +__GMPF_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + + + +/**************** Class wrapper for gmp_randstate_t ****************/ + +class __gmp_urandomb_value { }; +class __gmp_urandomm_value { }; + +template <> +class __gmp_expr<mpz_t, __gmp_urandomb_value> +{ +private: + __gmp_randstate_struct *state; + unsigned long int bits; +public: + __gmp_expr(gmp_randstate_t s, unsigned long int l) : state(s), bits(l) { } + void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, bits); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <> +class __gmp_expr<mpz_t, __gmp_urandomm_value> +{ +private: + __gmp_randstate_struct *state; + mpz_class range; +public: + __gmp_expr(gmp_randstate_t s, const mpz_class &z) : state(s), range(z) { } + void eval(mpz_ptr z) const + { __gmp_rand_function::eval(z, state, range.get_mpz_t()); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <> +class __gmp_expr<mpf_t, __gmp_urandomb_value> +{ +private: + __gmp_randstate_struct *state; + unsigned long int bits; +public: + __gmp_expr(gmp_randstate_t s, unsigned long int l) : state(s), bits(l) { } + void eval(mpf_ptr f, unsigned long int prec) const + { __gmp_rand_function::eval(f, state, (bits>0) ? get_prec() : prec); } + unsigned long int get_prec() const + { + if (bits == 0) + return mpf_get_default_prec(); + else + return bits; + } +}; + +extern "C" { + typedef void __gmp_randinit_default_t (gmp_randstate_t); + typedef void __gmp_randinit_lc_2exp_t (gmp_randstate_t, mpz_srcptr, unsigned long int, unsigned long int); + typedef int __gmp_randinit_lc_2exp_size_t (gmp_randstate_t, unsigned long int); +} + +class gmp_randclass +{ +private: + gmp_randstate_t state; + + // copy construction and assignment not allowed + gmp_randclass(const gmp_randclass &); + void operator=(const gmp_randclass &); +public: + // constructors and destructor + gmp_randclass(gmp_randalg_t alg, unsigned long int size) + { + switch (alg) + { + case GMP_RAND_ALG_LC: // no other cases for now + default: + gmp_randinit(state, alg, size); + break; + } + } + + // gmp_randinit_default + gmp_randclass(__gmp_randinit_default_t* f) { f(state); } + + // gmp_randinit_lc_2exp + gmp_randclass(__gmp_randinit_lc_2exp_t* f, + mpz_class z, unsigned long int l1, unsigned long int l2) + { f(state, z.get_mpz_t(), l1, l2); } + + // gmp_randinit_lc_2exp_size + gmp_randclass(__gmp_randinit_lc_2exp_size_t* f, + unsigned long int size) + { + if (f (state, size) == 0) + throw std::length_error ("gmp_randinit_lc_2exp_size"); + } + + ~gmp_randclass() { gmp_randclear(state); } + + // initialize + void seed(); // choose a random seed some way (?) + void seed(unsigned long int s) { gmp_randseed_ui(state, s); } + void seed(const mpz_class &z) { gmp_randseed(state, z.get_mpz_t()); } + + // get random number + __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(unsigned long int l) + { return __gmp_expr<mpz_t, __gmp_urandomb_value>(state, l); } + __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(const mpz_class &z) + { return get_z_bits(z.get_ui()); } + + __gmp_expr<mpz_t, __gmp_urandomm_value> get_z_range(const mpz_class &z) + { return __gmp_expr<mpz_t, __gmp_urandomm_value>(state, z); } + + __gmp_expr<mpf_t, __gmp_urandomb_value> get_f(unsigned long int prec = 0) + { return __gmp_expr<mpf_t, __gmp_urandomb_value>(state, prec); } +}; + + +/**************** #undef all private macros ****************/ + +#undef __GMPP_DECLARE_COMPOUND_OPERATOR +#undef __GMPN_DECLARE_COMPOUND_OPERATOR +#undef __GMP_DECLARE_COMPOUND_OPERATOR +#undef __GMP_DECLARE_COMPOUND_OPERATOR_UI +#undef __GMP_DECLARE_INCREMENT_OPERATOR + +#undef __GMPZQ_DEFINE_EXPR +#undef __GMP_DEFINE_TERNARY_EXPR + +#undef __GMP_DEFINE_UNARY_FUNCTION +#undef __GMP_DEFINE_UNARY_TYPE_FUNCTION + +#undef __GMPP_DEFINE_BINARY_FUNCTION +#undef __GMPNN_DEFINE_BINARY_FUNCTION +#undef __GMPNS_DEFINE_BINARY_FUNCTION +#undef __GMPNU_DEFINE_BINARY_FUNCTION +#undef __GMPND_DEFINE_BINARY_FUNCTION +#undef __GMPNLD_DEFINE_BINARY_FUNCTION +#undef __GMPN_DEFINE_BINARY_FUNCTION +#undef __GMP_DEFINE_BINARY_FUNCTION + +#undef __GMP_DEFINE_BINARY_FUNCTION_UI + +#undef __GMPP_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPNN_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPNS_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPNU_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPND_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPN_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMP_DEFINE_BINARY_TYPE_FUNCTION + +#undef __GMPP_DECLARE_COMPOUND_OPERATOR +#undef __GMPN_DECLARE_COMPOUND_OPERATOR +#undef __GMP_DECLARE_COMPOUND_OPERATOR + +#undef __GMP_DECLARE_COMPOUND_OPERATOR_UI +#undef __GMP_DECLARE_INCREMENT_OPERATOR + +#undef __GMPZ_DEFINE_COMPOUND_OPERATOR +#undef __GMPZZ_DEFINE_COMPOUND_OPERATOR +#undef __GMPZN_DEFINE_COMPOUND_OPERATOR +#undef __GMPZNN_DEFINE_COMPOUND_OPERATOR +#undef __GMPZNS_DEFINE_COMPOUND_OPERATOR +#undef __GMPZNU_DEFINE_COMPOUND_OPERATOR +#undef __GMPZND_DEFINE_COMPOUND_OPERATOR +#undef __GMPZNLD_DEFINE_COMPOUND_OPERATOR + +#undef __GMPP_DEFINE_COMPOUND_OPERATOR +#undef __GMPNN_DEFINE_COMPOUND_OPERATOR +#undef __GMPNS_DEFINE_COMPOUND_OPERATOR +#undef __GMPNU_DEFINE_COMPOUND_OPERATOR +#undef __GMPND_DEFINE_COMPOUND_OPERATOR +#undef __GMPNLD_DEFINE_COMPOUND_OPERATOR +#undef __GMPN_DEFINE_COMPOUND_OPERATOR +#undef __GMP_DEFINE_COMPOUND_OPERATOR + +#undef __GMPZ_DEFINE_COMPOUND_OPERATOR +#undef __GMPZZ_DEFINE_COMPOUND_OPERATOR +#undef __GMPQ_DEFINE_COMPOUND_OPERATOR +#undef __GMPF_DEFINE_COMPOUND_OPERATOR + +#undef __GMP_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPZ_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPQ_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPF_DEFINE_COMPOUND_OPERATOR_UI + +#undef __GMP_DEFINE_INCREMENT_OPERATOR +#undef __GMPZ_DEFINE_INCREMENT_OPERATOR +#undef __GMPQ_DEFINE_INCREMENT_OPERATOR +#undef __GMPF_DEFINE_INCREMENT_OPERATOR + +#endif /* __GMP_PLUSPLUS__ */ diff --git a/library/GMP/lib/libgmp.a b/library/GMP/lib/libgmp.a Binary files differnew file mode 100644 index 00000000..041ee6c7 --- /dev/null +++ b/library/GMP/lib/libgmp.a diff --git a/library/GMP/lib/libgmp.la b/library/GMP/lib/libgmp.la new file mode 100644 index 00000000..ee6e9a74 --- /dev/null +++ b/library/GMP/lib/libgmp.la @@ -0,0 +1,35 @@ +# libgmp.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.24 (1.1220.2.455 2007/06/24 02:13:29) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libgmp.a' + +# Libraries that this one depends upon. +dependency_libs='' + +# Version information for libgmp. +current=7 +age=4 +revision=2 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/c/gmp/lib' diff --git a/library/GMP/lib/libgmpxx.a b/library/GMP/lib/libgmpxx.a Binary files differnew file mode 100644 index 00000000..90ca1d40 --- /dev/null +++ b/library/GMP/lib/libgmpxx.a diff --git a/library/GMP/lib/libgmpxx.la b/library/GMP/lib/libgmpxx.la new file mode 100644 index 00000000..e608eba7 --- /dev/null +++ b/library/GMP/lib/libgmpxx.la @@ -0,0 +1,35 @@ +# libgmpxx.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.24 (1.1220.2.455 2007/06/24 02:13:29) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libgmpxx.a' + +# Libraries that this one depends upon. +dependency_libs=' /c/gmp/lib/libgmp.la' + +# Version information for libgmpxx. +current=4 +age=0 +revision=2 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/c/gmp/lib' diff --git a/library/globalFunctions.cpp b/library/globalFunctions.cpp new file mode 100644 index 00000000..d8a3a67b --- /dev/null +++ b/library/globalFunctions.cpp @@ -0,0 +1,109 @@ +#include "globalFunctions.h" +#include <wx/intl.h> + +inline +int GlobalFunctions::round(const double d) +{ + return static_cast<int>(d<0?d-.5:d+.5); +} + +inline +int GlobalFunctions::abs(const int d) +{ + return(d<0?-d:d); +} + +inline +unsigned int GlobalFunctions::abs(const unsigned int d) +{ + return(d<0?-d:d); +} + +inline +float GlobalFunctions::abs(const float d) +{ + return(d<0?-d:d); +}; + +inline +double GlobalFunctions::abs(const double d) +{ + return(d<0?-d:d); +} + +string GlobalFunctions::numberToString(const unsigned int number) +{ + char result[100]; + sprintf( result, "%u", number); + return string(result); +} + +string GlobalFunctions::numberToString(const int number) +{ + char result[100]; + sprintf( result, "%d", number); + return string(result); +} + +string GlobalFunctions::numberToString(const float number) +{ + char result[100]; + sprintf( result, "%f", number); + return string(result); +} + +wxString GlobalFunctions::numberToWxString(const unsigned int number) +{ + return wxString::Format(wxT("%u"), number); +} + +wxString GlobalFunctions::numberToWxString(const int number) +{ + return wxString::Format(wxT("%i"), number); +} + +wxString GlobalFunctions::numberToWxString(const float number) +{ + return wxString::Format(wxT("%f"), number); +} + +inline +int GlobalFunctions::stringToInt(const string& number) +{ + return atoi(number.c_str()); +} + +inline +double GlobalFunctions::stringToDouble(const string& number) +{ + return atof(number.c_str()); +} + +inline +int GlobalFunctions::wxStringToInt(const wxString& number) +{ + long result = 0; + if (number.ToLong(&result)) + return result; + else + throw std::runtime_error("Error when converting number to long"); +} + +inline +double GlobalFunctions::wxStringToDouble(const wxString& number) +{ + double result = 0; + if (number.ToDouble(&result)) + return result; + else + throw std::runtime_error("Error when converting number to double"); +} + +wxString& GlobalFunctions::includeNumberSeparator(wxString& number) +{ + const wxChar* NumberSeparator = _(","); + + for (int i = number.size() - 3; i > 0; i-= 3) + number.insert(i, NumberSeparator); + return number; +} diff --git a/library/globalFunctions.h b/library/globalFunctions.h new file mode 100644 index 00000000..90c4aa99 --- /dev/null +++ b/library/globalFunctions.h @@ -0,0 +1,36 @@ +#ifndef GLOBALFUNCTIONS_H_INCLUDED +#define GLOBALFUNCTIONS_H_INCLUDED + +#include <string> +#include <algorithm> +#include <wx/string.h> +#include <stdexcept> //for std::runtime_error + +using namespace std; + +namespace GlobalFunctions +{ + int round(double d); //little rounding function + + int abs(const int d); //absolute value + unsigned int abs(const unsigned int d); //absolute value + float abs(const float d); //absolute value + double abs(const double d); //absolute value + + string numberToString(const unsigned int number); //Convert number to string + string numberToString(const int number); //Convert number to string + string numberToString(const float number); //Convert number to string + + wxString numberToWxString(const unsigned int number); //Convert number to wxString + wxString numberToWxString(const int number); //Convert number to wxString + wxString numberToWxString(const float number); //Convert number to wxString + + int stringToInt( const string& number); //Convert String to number + double stringToDouble(const string& number); //Convert String to number + + int wxStringToInt( const wxString& number); //Convert wxString to number + double wxStringToDouble(const wxString& number); //Convert wxString to number + + wxString& includeNumberSeparator(wxString& number); +} +#endif // GLOBALFUNCTIONS_H_INCLUDED diff --git a/library/md5.c b/library/md5.c new file mode 100644 index 00000000..041860b4 --- /dev/null +++ b/library/md5.c @@ -0,0 +1,650 @@ +/* + * Functions to compute MD5 message digest of files or memory blocks + * according to the definition of MD5 in RFC 1321 from April 1992. + * Copyright (C) 1995, 1996 Free Software Foundation, Inc. NOTE: The + * canonical source of this file is maintained with the GNU C Library. + * Bugs can be reported to bug-glibc@prep.ai.mit.edu. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + * Modified by Gray Watson <http://256.com/gray/>, 1997. + * + * $Id: md5.c,v 1.7 2006/03/05 15:38:09 gray Exp $ + */ + +/* + * NOTE: during quick performance tests on a Sun Sparc Ultra 1 and an + * Alpha 255 300, these functions performed upwards of 3mb/sec + * including disk I/O time. + */ + +/* + * MD5 Test Suite from RFC1321: http://ds.internic.net:/rfc/rfc1321.txt + * + * MD5 ("") = d41d8cd98f00b204e9800998ecf8427e + * MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 + * MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 + * MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 + * MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b + * MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = + * d174ab98d277d9f5a5611c2c9f419d9f + * MD5 ("123456789012345678901234567890123456789012345678901234567890123456 + * 78901234567890") = 57edf4a22be3c955ac49da2e2107b67a + */ + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include "md5.h" + +#define HEX_STRING "0123456789abcdef" /* to convert to hex */ +#define BLOCK_SIZE_MASK (MD5_BLOCK_SIZE - 1) + +/* + * Define my endian-ness. Could not do in a portable manner using the + * include files -- grumble. + */ +#if defined(__alpha) || defined(WIN32) || defined(__i386__) +/* + * little endian + */ +#define SWAP(n) (n) +#endif + +#if defined(__sparc) || defined(__powerpc__) +/* + * big endian - big is better + */ +#define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#endif + +/* + * These are the four functions used in the four steps of the MD5 + * algorithm and defined in the RFC 1321. The first function is a + * little bit optimized (as found in Colin Plumbs public domain + * implementation). + */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF(d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* + * It is unfortunate that C does not provide an operator for cyclic + * rotation. Hope the C compiler is smart enough. -- Modified to + * remove the w = at the front - Gray 2/97 + */ +#define CYCLIC(w, s) ((w << s) | (w >> (32 - s))) + +/* + * First Round: using the given function, the context and a constant + * the next context is computed. Because the algorithms processing + * unit is a 32-bit word and it is determined to work on words in + * little endian byte order we perhaps have to change the byte order + * before the computation. To reduce the work for the next steps we + * store the swapped words in the array CORRECT_WORDS. -- Modified to + * fix the handling of unaligned buffer spaces - Gray 7/97 + */ +#define OP1(a, b, c, d, b_p, c_p, s, T) \ + do { \ + memcpy(c_p, b_p, sizeof(md5_uint32)); \ + *c_p = SWAP(*c_p); \ + a += FF (b, c, d) + *c_p + T; \ + a = CYCLIC (a, s); \ + a += b; \ + b_p = (char *)b_p + sizeof(md5_uint32); \ + c_p++; \ + } while (0) + +/* + * Second to Fourth Round: we have the possibly swapped words in + * CORRECT_WORDS. Redefine the macro to take an additional first + * argument specifying the function to use. + */ +#define OP234(FUNC, a, b, c, d, k, s, T) \ + do { \ + a += FUNC (b, c, d) + k + T; \ + a = CYCLIC (a, s); \ + a += b; \ + } while (0) + +/****************************** local routines *******************************/ + +/* + * process_block + * + * DESCRIPTION: + * + * Process a block of bytes into a MD5 state structure. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * md5_p - Pointer to MD5 structure from which we are getting the result. + * + * buffer - A buffer of bytes whose MD5 signature we are calculating. + * + * buf_len - The length of the buffer. + */ +static void process_block(md5_t *md5_p, const void *buffer, + const unsigned int buf_len) +{ + md5_uint32 correct[16]; + const void *buf_p = buffer, *end_p; + unsigned int words_n; + md5_uint32 A, B, C, D; + + words_n = buf_len / sizeof(md5_uint32); + end_p = (char *)buf_p + words_n * sizeof(md5_uint32); + + A = md5_p->md_A; + B = md5_p->md_B; + C = md5_p->md_C; + D = md5_p->md_D; + + /* + * First increment the byte count. RFC 1321 specifies the possible + * length of the file up to 2^64 bits. Here we only compute the + * number of bytes with a double word increment. Modified to do + * this to better avoid overflows in the lower word -- Gray 10/97. + */ + if (md5_p->md_total[0] > MAX_MD5_UINT32 - buf_len) + { + md5_p->md_total[1]++; + md5_p->md_total[0] -= (MAX_MD5_UINT32 + 1 - buf_len); + } + else + { + md5_p->md_total[0] += buf_len; + } + + /* + * Process all bytes in the buffer with MD5_BLOCK bytes in each + * round of the loop. + */ + while (buf_p < end_p) + { + md5_uint32 A_save, B_save, C_save, D_save; + md5_uint32 *corr_p = correct; + + A_save = A; + B_save = B; + C_save = C; + D_save = D; + + /* + * Before we start, one word to the strange constants. They are + * defined in RFC 1321 as + * + * T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..MD5_BLOCK + */ + + /* Round 1. */ + OP1 (A, B, C, D, buf_p, corr_p, 7, 0xd76aa478); + OP1 (D, A, B, C, buf_p, corr_p, 12, 0xe8c7b756); + OP1 (C, D, A, B, buf_p, corr_p, 17, 0x242070db); + OP1 (B, C, D, A, buf_p, corr_p, 22, 0xc1bdceee); + OP1 (A, B, C, D, buf_p, corr_p, 7, 0xf57c0faf); + OP1 (D, A, B, C, buf_p, corr_p, 12, 0x4787c62a); + OP1 (C, D, A, B, buf_p, corr_p, 17, 0xa8304613); + OP1 (B, C, D, A, buf_p, corr_p, 22, 0xfd469501); + OP1 (A, B, C, D, buf_p, corr_p, 7, 0x698098d8); + OP1 (D, A, B, C, buf_p, corr_p, 12, 0x8b44f7af); + OP1 (C, D, A, B, buf_p, corr_p, 17, 0xffff5bb1); + OP1 (B, C, D, A, buf_p, corr_p, 22, 0x895cd7be); + OP1 (A, B, C, D, buf_p, corr_p, 7, 0x6b901122); + OP1 (D, A, B, C, buf_p, corr_p, 12, 0xfd987193); + OP1 (C, D, A, B, buf_p, corr_p, 17, 0xa679438e); + OP1 (B, C, D, A, buf_p, corr_p, 22, 0x49b40821); + + /* Round 2. */ + OP234 (FG, A, B, C, D, correct[ 1], 5, 0xf61e2562); + OP234 (FG, D, A, B, C, correct[ 6], 9, 0xc040b340); + OP234 (FG, C, D, A, B, correct[ 11], 14, 0x265e5a51); + OP234 (FG, B, C, D, A, correct[ 0], 20, 0xe9b6c7aa); + OP234 (FG, A, B, C, D, correct[ 5], 5, 0xd62f105d); + OP234 (FG, D, A, B, C, correct[ 10], 9, 0x02441453); + OP234 (FG, C, D, A, B, correct[ 15], 14, 0xd8a1e681); + OP234 (FG, B, C, D, A, correct[ 4], 20, 0xe7d3fbc8); + OP234 (FG, A, B, C, D, correct[ 9], 5, 0x21e1cde6); + OP234 (FG, D, A, B, C, correct[ 14], 9, 0xc33707d6); + OP234 (FG, C, D, A, B, correct[ 3], 14, 0xf4d50d87); + OP234 (FG, B, C, D, A, correct[ 8], 20, 0x455a14ed); + OP234 (FG, A, B, C, D, correct[ 13], 5, 0xa9e3e905); + OP234 (FG, D, A, B, C, correct[ 2], 9, 0xfcefa3f8); + OP234 (FG, C, D, A, B, correct[ 7], 14, 0x676f02d9); + OP234 (FG, B, C, D, A, correct[ 12], 20, 0x8d2a4c8a); + + /* Round 3. */ + OP234 (FH, A, B, C, D, correct[ 5], 4, 0xfffa3942); + OP234 (FH, D, A, B, C, correct[ 8], 11, 0x8771f681); + OP234 (FH, C, D, A, B, correct[ 11], 16, 0x6d9d6122); + OP234 (FH, B, C, D, A, correct[ 14], 23, 0xfde5380c); + OP234 (FH, A, B, C, D, correct[ 1], 4, 0xa4beea44); + OP234 (FH, D, A, B, C, correct[ 4], 11, 0x4bdecfa9); + OP234 (FH, C, D, A, B, correct[ 7], 16, 0xf6bb4b60); + OP234 (FH, B, C, D, A, correct[ 10], 23, 0xbebfbc70); + OP234 (FH, A, B, C, D, correct[ 13], 4, 0x289b7ec6); + OP234 (FH, D, A, B, C, correct[ 0], 11, 0xeaa127fa); + OP234 (FH, C, D, A, B, correct[ 3], 16, 0xd4ef3085); + OP234 (FH, B, C, D, A, correct[ 6], 23, 0x04881d05); + OP234 (FH, A, B, C, D, correct[ 9], 4, 0xd9d4d039); + OP234 (FH, D, A, B, C, correct[ 12], 11, 0xe6db99e5); + OP234 (FH, C, D, A, B, correct[ 15], 16, 0x1fa27cf8); + OP234 (FH, B, C, D, A, correct[ 2], 23, 0xc4ac5665); + + /* Round 4. */ + OP234 (FI, A, B, C, D, correct[ 0], 6, 0xf4292244); + OP234 (FI, D, A, B, C, correct[ 7], 10, 0x432aff97); + OP234 (FI, C, D, A, B, correct[ 14], 15, 0xab9423a7); + OP234 (FI, B, C, D, A, correct[ 5], 21, 0xfc93a039); + OP234 (FI, A, B, C, D, correct[ 12], 6, 0x655b59c3); + OP234 (FI, D, A, B, C, correct[ 3], 10, 0x8f0ccc92); + OP234 (FI, C, D, A, B, correct[ 10], 15, 0xffeff47d); + OP234 (FI, B, C, D, A, correct[ 1], 21, 0x85845dd1); + OP234 (FI, A, B, C, D, correct[ 8], 6, 0x6fa87e4f); + OP234 (FI, D, A, B, C, correct[ 15], 10, 0xfe2ce6e0); + OP234 (FI, C, D, A, B, correct[ 6], 15, 0xa3014314); + OP234 (FI, B, C, D, A, correct[ 13], 21, 0x4e0811a1); + OP234 (FI, A, B, C, D, correct[ 4], 6, 0xf7537e82); + OP234 (FI, D, A, B, C, correct[ 11], 10, 0xbd3af235); + OP234 (FI, C, D, A, B, correct[ 2], 15, 0x2ad7d2bb); + OP234 (FI, B, C, D, A, correct[ 9], 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + md5_p->md_A = A; + md5_p->md_B = B; + md5_p->md_C = C; + md5_p->md_D = D; +} + +/* + * md5_get_result + * + * DESCRIPTION: + * + * Copy the resulting MD5 signature from MD5_P into the first 16 bytes + * (MD5_SIZE) of the result buffer. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * md5_p - Pointer to MD5 structure from which we are getting the result. + * + * result - A 16 byte buffer that will contain the MD5 signature. + */ +static void md5_get_result(const md5_t *md5_p, void *result) +{ + md5_uint32 hold; + void *res_p = result; + + hold = SWAP(md5_p->md_A); + memcpy(res_p, &hold, sizeof(md5_uint32)); + res_p = (char *)res_p + sizeof(md5_uint32); + + hold = SWAP(md5_p->md_B); + memcpy(res_p, &hold, sizeof(md5_uint32)); + res_p = (char *)res_p + sizeof(md5_uint32); + + hold = SWAP(md5_p->md_C); + memcpy(res_p, &hold, sizeof(md5_uint32)); + res_p = (char *)res_p + sizeof(md5_uint32); + + hold = SWAP(md5_p->md_D); + memcpy(res_p, &hold, sizeof(md5_uint32)); +} + +/***************************** exported routines *****************************/ + +/* + * md5_init + * + * DESCRIPTION: + * + * Initialize structure containing state of MD5 computation. (RFC 1321, + * 3.3: Step 3). This is for progressive MD5 calculations only. If + * you have the complete string available, md5_buffer should be used. + * md5_process should be called for each bunch of bytes and after the + * last process call, md5_finish should be called to get the + * signature. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * md5_p - Pointer to md5 structure that we are initializing. + */ +void md5_init(md5_t *md5_p) +{ + md5_p->md_A = 0x67452301; + md5_p->md_B = 0xefcdab89; + md5_p->md_C = 0x98badcfe; + md5_p->md_D = 0x10325476; + + md5_p->md_total[0] = 0; + md5_p->md_total[1] = 0; + md5_p->md_buf_len = 0; +} + +/* + * md5_process + * + * DESCRIPTION: + * + * This function is used to progressively calculate a MD5 signature some + * number of bytes at a time. If you have the complete string + * available, md5_buffer should be used. The MD5 structure should + * have been initialized with md5_init and after the last process + * call, md5_finish should be called to get the results. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * md5_p - Pointer to MD5 structure which we are progressively updating. + * + * buffer - A buffer of bytes whose MD5 signature we are calculating. + * + * buf_len - The length of the buffer. + */ +void md5_process(md5_t *md5_p, const void *buffer, + const unsigned int buf_len) +{ + unsigned int len = buf_len; + unsigned int in_block, add; + + /* + * When we already have some bytes in our internal buffer, copy some + * from the user to fill the block. + */ + if (md5_p->md_buf_len > 0) + { + + in_block = md5_p->md_buf_len; + if (in_block + len > sizeof(md5_p->md_buffer)) + { + add = sizeof(md5_p->md_buffer) - in_block; + } + else + { + add = len; + } + + memcpy (md5_p->md_buffer + in_block, buffer, add); + md5_p->md_buf_len += add; + in_block += add; + + if (in_block > MD5_BLOCK_SIZE) + { + process_block (md5_p, md5_p->md_buffer, in_block & ~BLOCK_SIZE_MASK); + /* the regions in the following copy operation will not overlap. */ + memcpy (md5_p->md_buffer, + md5_p->md_buffer + (in_block & ~BLOCK_SIZE_MASK), + in_block & BLOCK_SIZE_MASK); + md5_p->md_buf_len = in_block & BLOCK_SIZE_MASK; + } + + buffer = (const char *)buffer + add; + len -= add; + } + + /* process available complete blocks right from the user buffer */ + if (len > MD5_BLOCK_SIZE) + { + process_block (md5_p, buffer, len & ~BLOCK_SIZE_MASK); + buffer = (const char *) buffer + (len & ~BLOCK_SIZE_MASK); + len &= BLOCK_SIZE_MASK; + } + + /* copy remaining bytes into the internal buffer */ + if (len > 0) + { + memcpy (md5_p->md_buffer, buffer, len); + md5_p->md_buf_len = len; + } +} + +/* + * md5_finish + * + * DESCRIPTION: + * + * Finish a progressing MD5 calculation and copy the resulting MD5 + * signature into the result buffer which should be 16 bytes + * (MD5_SIZE). After this call, the MD5 structure is invalid. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * md5_p - Pointer to MD5 structure which we are finishing. + * + * signature - A 16 byte buffer that will contain the MD5 signature. + */ +void md5_finish(md5_t *md5_p, void *signature) +{ + md5_uint32 bytes, hold; + int pad; + + /* take yet unprocessed bytes into account */ + bytes = md5_p->md_buf_len; + + /* + * Count remaining bytes. Modified to do this to better avoid + * overflows in the lower word -- Gray 10/97. + */ + if (md5_p->md_total[0] > MAX_MD5_UINT32 - bytes) + { + md5_p->md_total[1]++; + md5_p->md_total[0] -= (MAX_MD5_UINT32 + 1 - bytes); + } + else + { + md5_p->md_total[0] += bytes; + } + + /* + * Pad the buffer to the next MD5_BLOCK-byte boundary. (RFC 1321, + * 3.1: Step 1). We need enough room for two size words and the + * bytes left in the buffer. For some reason even if we are equal + * to the block-size, we add an addition block of pad bytes. + */ + pad = MD5_BLOCK_SIZE - (sizeof(md5_uint32) * 2) - bytes; + if (pad <= 0) + { + pad += MD5_BLOCK_SIZE; + } + + /* + * Modified from a fixed array to this assignment and memset to be + * more flexible with block-sizes -- Gray 10/97. + */ + if (pad > 0) + { + /* some sort of padding start byte */ + md5_p->md_buffer[bytes] = (unsigned char)0x80; + if (pad > 1) + { + memset (md5_p->md_buffer + bytes + 1, 0, pad - 1); + } + bytes += pad; + } + + /* + * Put the 64-bit file length in _bits_ (i.e. *8) at the end of the + * buffer. + */ + hold = SWAP((md5_p->md_total[0] & 0x1FFFFFFF) << 3); + memcpy(md5_p->md_buffer + bytes, &hold, sizeof(md5_uint32)); + bytes += sizeof(md5_uint32); + + /* shift the high word over by 3 and add in the top 3 bits from the low */ + hold = SWAP((md5_p->md_total[1] << 3) | + ((md5_p->md_total[0] & 0xE0000000) >> 29)); + memcpy(md5_p->md_buffer + bytes, &hold, sizeof(md5_uint32)); + bytes += sizeof(md5_uint32); + + /* process last bytes, the padding chars, and size words */ + process_block(md5_p, md5_p->md_buffer, bytes); + md5_get_result(md5_p, signature); +} + +/* + * md5_buffer + * + * DESCRIPTION: + * + * This function is used to calculate a MD5 signature for a buffer of + * bytes. If you only have part of a buffer that you want to process + * then md5_init, md5_process, and md5_finish should be used. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * buffer - A buffer of bytes whose MD5 signature we are calculating. + * + * buf_len - The length of the buffer. + * + * signature - A 16 byte buffer that will contain the MD5 signature. + */ +void md5_buffer(const char *buffer, const unsigned int buf_len, + void *signature) +{ + md5_t md5; + + /* initialize the computation context */ + md5_init(&md5); + + /* process whole buffer but last buf_len % MD5_BLOCK bytes */ + md5_process(&md5, buffer, buf_len); + + /* put result in desired memory area */ + md5_finish(&md5, signature); +} + +/* + * md5_sig_to_string + * + * DESCRIPTION: + * + * Convert a MD5 signature in a 16 byte buffer into a hexadecimal string + * representation. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * signature - a 16 byte buffer that contains the MD5 signature. + * + * str - a string of charactes which should be at least 33 bytes long (2 + * characters per MD5 byte and 1 for the \0). + * + * str_len - the length of the string. + */ +void md5_sig_to_string(void *signature, char *str, const int str_len) +{ + unsigned char *sig_p; + char *str_p, *max_p; + unsigned int high, low; + + str_p = str; + max_p = str + str_len; + + for (sig_p = (unsigned char *)signature; + sig_p < (unsigned char *)signature + MD5_SIZE; + sig_p++) + { + high = *sig_p / 16; + low = *sig_p % 16; + /* account for 2 chars */ + if (str_p + 1 >= max_p) + { + break; + } + *str_p++ = HEX_STRING[high]; + *str_p++ = HEX_STRING[low]; + } + /* account for 2 chars */ + if (str_p < max_p) + { + *str_p++ = '\0'; + } +} + +/* + * md5_sig_from_string + * + * DESCRIPTION: + * + * Convert a MD5 signature from a hexadecimal string representation into + * a 16 byte buffer. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * signature - A 16 byte buffer that will contain the MD5 signature. + * + * str - A string of charactes which _must_ be at least 32 bytes long (2 + * characters per MD5 byte). + */ +void md5_sig_from_string(void *signature, const char *str) +{ + unsigned char *sig_p; + const char *str_p; + char *hex; + unsigned int high, low, val; + + hex = HEX_STRING; + sig_p = signature; + + for (str_p = str; str_p < str + MD5_SIZE * 2; str_p += 2) + { + high = strchr(hex, *str_p) - hex; + low = strchr(hex, *(str_p + 1)) - hex; + val = high * 16 + low; + *sig_p++ = val; + } +} diff --git a/library/md5.h b/library/md5.h new file mode 100644 index 00000000..29c20847 --- /dev/null +++ b/library/md5.h @@ -0,0 +1,218 @@ +/* + * Declaration of functions and data types used for MD5 sum computing + * library functions. Copyright (C) 1995, 1996 Free Software + * Foundation, Inc. NOTE: The canonical source of this file is + * maintained with the GNU C Library. Bugs can be reported to + * bug-glibc@prep.ai.mit.edu. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * $Id: md5.h,v 1.4 2000/03/09 04:06:41 gray Exp $ + */ + +/* + * NOTE: during quick performance tests on a sun ultra and an alpha + * 255 300, the md5 libraries performed upwards of 3mb/sec. That + * included disk i/o on bobcat and panther. + */ + +#ifndef __MD5_H__ +#define __MD5_H__ + +/* + * Size of a standard MD5 signature in bytes. This definition is for + * external programs only. The MD5 routines themselves reference the + * signature as 4 unsigned 32-bit integers. + */ +#define MD5_SIZE 16 + +/* + * NOTE: the following is assumed to generate a 32-bit unsigned data + * type. + */ +typedef unsigned int md5_uint32; +#define MAX_MD5_UINT32 ((md5_uint32)4294967295U) + +/* + * The MD5 algorithm works on blocks of characters of 64 bytes. This + * is an internal value only and is not necessary for external use. + */ +#define MD5_BLOCK_SIZE 64 + +/* + * Structure to save state of computation between the single steps. + */ +typedef struct +{ + md5_uint32 md_A; /* accumulater 1 */ + md5_uint32 md_B; /* accumulater 2 */ + md5_uint32 md_C; /* accumulater 3 */ + md5_uint32 md_D; /* accumulater 4 */ + + md5_uint32 md_total[2]; /* totaling storage */ + md5_uint32 md_buf_len; /* length of the storage buffer */ + char md_buffer[MD5_BLOCK_SIZE * 2]; /* character storage buffer */ +} md5_t; + +/*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ + +/* + * md5_init + * + * DESCRIPTION: + * + * Initialize structure containing state of MD5 computation. (RFC 1321, + * 3.3: Step 3). This is for progressive MD5 calculations only. If + * you have the complete string available, md5_buffer should be used. + * md5_process should be called for each bunch of bytes and after the + * last process call, md5_finish should be called to get the + * signature. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * md5_p - Pointer to md5 structure that we are initializing. + */ +#ifdef __cplusplus +extern "C" +{ +#endif + + void md5_init(md5_t *md5_p); + + /* + * md5_process + * + * DESCRIPTION: + * + * This function is used to progressively calculate a MD5 signature some + * number of bytes at a time. If you have the complete string + * available, md5_buffer should be used. The MD5 structure should + * have been initialized with md5_init and after the last process + * call, md5_finish should be called to get the results. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * md5_p - Pointer to MD5 structure which we are progressively updating. + * + * buffer - A buffer of bytes whose MD5 signature we are calculating. + * + * buf_len - The length of the buffer. + */ + void md5_process(md5_t *md5_p, const void *buffer, + const unsigned int buf_len); + + /* + * md5_finish + * + * DESCRIPTION: + * + * Finish a progressing MD5 calculation and copy the resulting MD5 + * signature into the result buffer which should be 16 bytes + * (MD5_SIZE). After this call, the MD5 structure is invalid. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * md5_p - Pointer to MD5 structure which we are finishing. + * + * signature - A 16 byte buffer that will contain the MD5 signature. + */ + void md5_finish(md5_t *md5_p, void *signature); + + /* + * md5_buffer + * + * DESCRIPTION: + * + * This function is used to calculate a MD5 signature for a buffer of + * bytes. If you only have part of a buffer that you want to process + * then md5_init, md5_process, and md5_finish should be used. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * buffer - A buffer of bytes whose MD5 signature we are calculating. + * + * buf_len - The length of the buffer. + * + * signature - A 16 byte buffer that will contain the MD5 signature. + */ + void md5_buffer(const char *buffer, const unsigned int buf_len, + void *signature); + + /* + * md5_sig_to_string + * + * DESCRIPTION: + * + * Convert a MD5 signature in a 16 byte buffer into a hexadecimal string + * representation. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * signature - a 16 byte buffer that contains the MD5 signature. + * + * str - a string of charactes which should be at least 33 bytes long (2 + * characters per MD5 byte and 1 for the \0). + * + * str_len - the length of the string. + */ + void md5_sig_to_string(void *signature, char *str, const int str_len); + + /* + * md5_sig_from_string + * + * DESCRIPTION: + * + * Convert a MD5 signature from a hexadecimal string representation into + * a 16 byte buffer. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * signature - A 16 byte buffer that will contain the MD5 signature. + * + * str - A string of charactes which _must_ be at least 32 bytes long (2 + * characters per MD5 byte). + */ + void md5_sig_from_string(void *signature, const char *str); + + /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ +#ifdef __cplusplus +} /* end extern "C" */ +#endif +#endif /* ! __MD5_H__ */ diff --git a/library/wxWidgets.h b/library/wxWidgets.h new file mode 100644 index 00000000..dd27498c --- /dev/null +++ b/library/wxWidgets.h @@ -0,0 +1,16 @@ +#ifndef WXWIDGETS_H_INCLUDED +#define WXWIDGETS_H_INCLUDED + +// For compilers that support precompilation +#include <wx/wxprec.h> + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif //__BORLANDC__ + +#ifndef WX_PRECOMP +// Include your minimal set of headers here, or wx.h +#include <wx/wx.h> +#endif + +#endif // WXWIDGETS_H_INCLUDED diff --git a/resource.rc b/resource.rc new file mode 100644 index 00000000..bdfb28d9 --- /dev/null +++ b/resource.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" +aaaa ICON DISCARDABLE "FreeFileSync.ico" diff --git a/ui/GUI_Generated.cpp b/ui/GUI_Generated.cpp new file mode 100644 index 00000000..fc88dd7d --- /dev/null +++ b/ui/GUI_Generated.cpp @@ -0,0 +1,1189 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 16 2008) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif //__BORLANDC__ + +#ifndef WX_PRECOMP +#include <wx/wx.h> +#endif //WX_PRECOMP + +#include "..\library\CustomGrid.h" + +#include "GUI_Generated.h" + +/////////////////////////////////////////////////////////////////////////// + +GUI_Generated::GUI_Generated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + bSizer1 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer6; + bSizer6 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer6->Add( 40, 0, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer30; + bSizer30 = new wxBoxSizer( wxHORIZONTAL ); + + m_bpButtonCompare = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 190,37 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE ); + m_bpButtonCompare->SetToolTip( _("Compare both sides") ); + + m_bpButtonCompare->SetToolTip( _("Compare both sides") ); + + bSizer30->Add( m_bpButtonCompare, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 ); + + m_buttonAbort = new wxButton( this, wxID_ANY, _("Abort"), wxDefaultPosition, wxSize( 186,33 ), 0 ); + m_buttonAbort->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Tahoma") ) ); + m_buttonAbort->Hide(); + + bSizer30->Add( m_buttonAbort, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 ); + + bSizer6->Add( bSizer30, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxStaticBoxSizer* sbSizer6; + sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Compare by") ), wxVERTICAL ); + + m_radioBtnSizeDate = new wxRadioButton( this, wxID_ANY, _("File size and date"), wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnSizeDate->SetValue( true ); + m_radioBtnSizeDate->SetToolTip( _("Files are found equal if\n - filesize\n - last write time (UTC) and date\nare the same.") ); + + sbSizer6->Add( m_radioBtnSizeDate, 0, wxRIGHT|wxLEFT, 5 ); + + m_radioBtnContent = new wxRadioButton( this, wxID_ANY, _("File content"), wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnContent->SetToolTip( _("Files are found equal if\n - file content\nis the same.") ); + + sbSizer6->Add( m_radioBtnContent, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + bSizer6->Add( sbSizer6, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 2 ); + + m_bpButton14 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + bSizer6->Add( m_bpButton14, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + bSizer6->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer9; + sbSizer9 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Filter files") ), wxHORIZONTAL ); + + m_bpButtonFilter = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE ); + sbSizer9->Add( m_bpButtonFilter, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bSizer23; + bSizer23 = new wxBoxSizer( wxVERTICAL ); + + m_hyperlinkCfgFilter = new wxHyperlinkCtrl( this, wxID_ANY, _("Configure Filter..."), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + + m_hyperlinkCfgFilter->SetNormalColour( wxColour( 0, 0, 255 ) ); + m_hyperlinkCfgFilter->SetVisitedColour( wxColour( 0, 0, 255 ) ); + m_hyperlinkCfgFilter->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_APPWORKSPACE ) ); + + bSizer23->Add( m_hyperlinkCfgFilter, 0, wxALL, 5 ); + + m_checkBoxHideFilt = new wxCheckBox( this, wxID_ANY, _("Hide filtered items"), wxDefaultPosition, wxDefaultSize, 0 ); + + m_checkBoxHideFilt->SetToolTip( _("Choose to hide filtered files/directories from list") ); + + bSizer23->Add( m_checkBoxHideFilt, 0, 0, 5 ); + + sbSizer9->Add( bSizer23, 1, wxEXPAND, 5 ); + + bSizer6->Add( sbSizer9, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonSync = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 190,37 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE ); + m_bpButtonSync->SetToolTip( _("Open synchronization dialog") ); + + m_bpButtonSync->SetToolTip( _("Open synchronization dialog") ); + + bSizer6->Add( m_bpButtonSync, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + + bSizer6->Add( 40, 0, 0, wxEXPAND, 5 ); + + bSizer1->Add( bSizer6, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer( wxHORIZONTAL ); + + m_panel1 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer2; + sbSizer2 = new wxStaticBoxSizer( new wxStaticBox( m_panel1, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); + + m_directoryPanel1 = new wxTextCtrl( m_panel1, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + sbSizer2->Add( m_directoryPanel1, 1, wxALIGN_BOTTOM, 5 ); + + m_dirPicker1 = new wxDirPickerCtrl( m_panel1, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, wxDIRP_DIR_MUST_EXIST ); + sbSizer2->Add( m_dirPicker1, 0, wxALIGN_BOTTOM, 5 ); + + bSizer7->Add( sbSizer2, 0, wxEXPAND, 5 ); + + m_grid1 = new CustomGrid( m_panel1, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_grid1->CreateGrid( 15, 4 ); + m_grid1->EnableEditing( false ); + m_grid1->EnableGridLines( true ); + m_grid1->EnableDragGridSize( true ); + m_grid1->SetMargins( 0, 0 ); + + // Columns + m_grid1->SetColSize( 0, 138 ); + m_grid1->SetColSize( 1, 118 ); + m_grid1->SetColSize( 2, 67 ); + m_grid1->SetColSize( 3, 113 ); + m_grid1->EnableDragColMove( false ); + m_grid1->EnableDragColSize( true ); + m_grid1->SetColLabelSize( 20 ); + m_grid1->SetColLabelValue( 0, _("Filename") ); + m_grid1->SetColLabelValue( 1, _("Relative path") ); + m_grid1->SetColLabelValue( 2, _("Size") ); + m_grid1->SetColLabelValue( 3, _("Date") ); + m_grid1->SetColLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); + + // Rows + m_grid1->EnableDragRowSize( false ); + m_grid1->SetRowLabelSize( 38 ); + m_grid1->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_grid1->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); + bSizer7->Add( m_grid1, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 ); + + m_panel1->SetSizer( bSizer7 ); + m_panel1->Layout(); + bSizer7->Fit( m_panel1 ); + bSizer2->Add( m_panel1, 1, wxEXPAND|wxLEFT, 5 ); + + m_panel3 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer18; + bSizer18 = new wxBoxSizer( wxVERTICAL ); + + m_bpButtonSwap = new wxBitmapButton( m_panel3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + m_bpButtonSwap->SetToolTip( _("Swap sides") ); + + m_bpButtonSwap->SetToolTip( _("Swap sides") ); + + bSizer18->Add( m_bpButtonSwap, 0, wxTOP|wxALIGN_CENTER_HORIZONTAL, 3 ); + + m_grid3 = new CustomGrid( m_panel3, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER ); + + // Grid + m_grid3->CreateGrid( 15, 1 ); + m_grid3->EnableEditing( false ); + m_grid3->EnableGridLines( true ); + m_grid3->EnableDragGridSize( false ); + m_grid3->SetMargins( 0, 50 ); + + // Columns + m_grid3->SetColSize( 0, 45 ); + m_grid3->EnableDragColMove( false ); + m_grid3->EnableDragColSize( false ); + m_grid3->SetColLabelSize( 20 ); + m_grid3->SetColLabelValue( 0, _("Filter") ); + m_grid3->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Rows + m_grid3->EnableDragRowSize( false ); + m_grid3->SetRowLabelSize( 0 ); + m_grid3->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_grid3->SetDefaultCellFont( wxFont( 12, 74, 90, 92, false, wxT("Arial") ) ); + m_grid3->SetDefaultCellAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + bSizer18->Add( m_grid3, 1, wxBOTTOM|wxTOP|wxALIGN_CENTER_HORIZONTAL, 3 ); + + m_panel3->SetSizer( bSizer18 ); + m_panel3->Layout(); + bSizer18->Fit( m_panel3 ); + bSizer2->Add( m_panel3, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + m_panel2 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer10; + bSizer10 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer3; + sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panel2, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); + + m_directoryPanel2 = new wxTextCtrl( m_panel2, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + sbSizer3->Add( m_directoryPanel2, 1, wxALIGN_BOTTOM, 5 ); + + m_dirPicker2 = new wxDirPickerCtrl( m_panel2, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, wxDIRP_DIR_MUST_EXIST ); + sbSizer3->Add( m_dirPicker2, 0, wxALIGN_BOTTOM, 5 ); + + bSizer10->Add( sbSizer3, 0, wxEXPAND, 5 ); + + m_grid2 = new CustomGrid( m_panel2, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_grid2->CreateGrid( 15, 4 ); + m_grid2->EnableEditing( false ); + m_grid2->EnableGridLines( true ); + m_grid2->EnableDragGridSize( true ); + m_grid2->SetMargins( 0, 0 ); + + // Columns + m_grid2->SetColSize( 0, 138 ); + m_grid2->SetColSize( 1, 118 ); + m_grid2->SetColSize( 2, 67 ); + m_grid2->SetColSize( 3, 113 ); + m_grid2->EnableDragColMove( false ); + m_grid2->EnableDragColSize( true ); + m_grid2->SetColLabelSize( 20 ); + m_grid2->SetColLabelValue( 0, _("Filename") ); + m_grid2->SetColLabelValue( 1, _("Relative path") ); + m_grid2->SetColLabelValue( 2, _("Size") ); + m_grid2->SetColLabelValue( 3, _("Date") ); + m_grid2->SetColLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); + + // Rows + m_grid2->EnableDragRowSize( false ); + m_grid2->SetRowLabelSize( 38 ); + m_grid2->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_grid2->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); + bSizer10->Add( m_grid2, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_panel2->SetSizer( bSizer10 ); + m_panel2->Layout(); + bSizer10->Fit( m_panel2 ); + bSizer2->Add( m_panel2, 1, wxEXPAND|wxRIGHT, 5 ); + + bSizer1->Add( bSizer2, 1, wxEXPAND, 5 ); + + m_panel4 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer3; + bSizer3 = new wxBoxSizer( wxHORIZONTAL ); + + m_bpButton11 = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 50,50 ), wxBU_AUTODRAW ); + m_bpButton11->SetToolTip( _("About") ); + + m_bpButton11->SetToolTip( _("About") ); + + bSizer3->Add( m_bpButton11, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + bSizer3->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer31; + sbSizer31 = new wxStaticBoxSizer( new wxStaticBox( m_panel4, wxID_ANY, _("Filter view") ), wxHORIZONTAL ); + + m_bpButton20 = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButton20->SetToolTip( _("Files that exist on left view only") ); + + m_bpButton20->SetToolTip( _("Files that exist on left view only") ); + + sbSizer31->Add( m_bpButton20, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButton21 = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButton21->SetToolTip( _("Files that are newer on left") ); + + m_bpButton21->SetToolTip( _("Files that are newer on left") ); + + sbSizer31->Add( m_bpButton21, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButton25 = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButton25->SetToolTip( _("Files that are equal") ); + + m_bpButton25->SetToolTip( _("Files that are equal") ); + + sbSizer31->Add( m_bpButton25, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButton22 = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButton22->SetToolTip( _("Files that are different") ); + + m_bpButton22->SetToolTip( _("Files that are different") ); + + sbSizer31->Add( m_bpButton22, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButton23 = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButton23->SetToolTip( _("Files that are newer on right") ); + + m_bpButton23->SetToolTip( _("Files that are newer on right") ); + + sbSizer31->Add( m_bpButton23, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButton24 = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButton24->SetToolTip( _("Files that exist on right view only") ); + + m_bpButton24->SetToolTip( _("Files that exist on right view only") ); + + sbSizer31->Add( m_bpButton24, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer3->Add( sbSizer31, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer3->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_bpButton10 = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 50,50 ), wxBU_AUTODRAW ); + m_bpButton10->SetToolTip( _("Quit") ); + + m_bpButton10->SetToolTip( _("Quit") ); + + bSizer3->Add( m_bpButton10, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_panel4->SetSizer( bSizer3 ); + m_panel4->Layout(); + bSizer3->Fit( m_panel4 ); + bSizer1->Add( m_panel4, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + this->SetSizer( bSizer1 ); + this->Layout(); + m_statusBar1 = this->CreateStatusBar( 5, wxST_SIZEGRIP, wxID_ANY ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GUI_Generated::OnClose ) ); + m_bpButtonCompare->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnCompare ), NULL, this ); + m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnAbortCompare ), NULL, this ); + m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( GUI_Generated::OnChangeCompareVariant ), NULL, this ); + m_radioBtnContent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( GUI_Generated::OnChangeCompareVariant ), NULL, this ); + m_bpButton14->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnShowHelpDialog ), NULL, this ); + m_bpButtonFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnFilterButton ), NULL, this ); + m_hyperlinkCfgFilter->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( GUI_Generated::OnConfigureFilter ), NULL, this ); + m_checkBoxHideFilt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( GUI_Generated::OnHideFilteredButton ), NULL, this ); + m_bpButtonSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnSync ), NULL, this ); + m_directoryPanel1->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( GUI_Generated::OnEnterLeftDir ), NULL, this ); + m_dirPicker1->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( GUI_Generated::OnDirChangedPanel1 ), NULL, this ); + m_grid1->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( GUI_Generated::OnLeftGridDoubleClick ), NULL, this ); + m_grid1->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( GUI_Generated::OnSortLeftGrid ), NULL, this ); + m_bpButtonSwap->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnSwapDirs ), NULL, this ); + m_grid3->Connect( wxEVT_GRID_RANGE_SELECT, wxGridRangeSelectEventHandler( GUI_Generated::OnGrid3SelectRange ), NULL, this ); + m_grid3->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( GUI_Generated::OnGrid3SelectCell ), NULL, this ); + m_directoryPanel2->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( GUI_Generated::OnEnterRightDir ), NULL, this ); + m_dirPicker2->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( GUI_Generated::OnDirChangedPanel2 ), NULL, this ); + m_grid2->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( GUI_Generated::OnRightGridDoubleClick ), NULL, this ); + m_grid2->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( GUI_Generated::OnSortRightGrid ), NULL, this ); + m_bpButton11->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnAbout ), NULL, this ); + m_bpButton20->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnLeftOnlyFiles ), NULL, this ); + m_bpButton21->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnLeftNewerFiles ), NULL, this ); + m_bpButton25->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnEqualFiles ), NULL, this ); + m_bpButton22->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnDifferentFiles ), NULL, this ); + m_bpButton23->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnRightNewerFiles ), NULL, this ); + m_bpButton24->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnRightOnlyFiles ), NULL, this ); + m_bpButton10->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnQuit ), NULL, this ); +} + +GUI_Generated::~GUI_Generated() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GUI_Generated::OnClose ) ); + m_bpButtonCompare->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnCompare ), NULL, this ); + m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnAbortCompare ), NULL, this ); + m_radioBtnSizeDate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( GUI_Generated::OnChangeCompareVariant ), NULL, this ); + m_radioBtnContent->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( GUI_Generated::OnChangeCompareVariant ), NULL, this ); + m_bpButton14->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnShowHelpDialog ), NULL, this ); + m_bpButtonFilter->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnFilterButton ), NULL, this ); + m_hyperlinkCfgFilter->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( GUI_Generated::OnConfigureFilter ), NULL, this ); + m_checkBoxHideFilt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( GUI_Generated::OnHideFilteredButton ), NULL, this ); + m_bpButtonSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnSync ), NULL, this ); + m_directoryPanel1->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( GUI_Generated::OnEnterLeftDir ), NULL, this ); + m_dirPicker1->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( GUI_Generated::OnDirChangedPanel1 ), NULL, this ); + m_grid1->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( GUI_Generated::OnLeftGridDoubleClick ), NULL, this ); + m_grid1->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( GUI_Generated::OnSortLeftGrid ), NULL, this ); + m_bpButtonSwap->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnSwapDirs ), NULL, this ); + m_grid3->Disconnect( wxEVT_GRID_RANGE_SELECT, wxGridRangeSelectEventHandler( GUI_Generated::OnGrid3SelectRange ), NULL, this ); + m_grid3->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( GUI_Generated::OnGrid3SelectCell ), NULL, this ); + m_directoryPanel2->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( GUI_Generated::OnEnterRightDir ), NULL, this ); + m_dirPicker2->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( GUI_Generated::OnDirChangedPanel2 ), NULL, this ); + m_grid2->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( GUI_Generated::OnRightGridDoubleClick ), NULL, this ); + m_grid2->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( GUI_Generated::OnSortRightGrid ), NULL, this ); + m_bpButton11->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnAbout ), NULL, this ); + m_bpButton20->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnLeftOnlyFiles ), NULL, this ); + m_bpButton21->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnLeftNewerFiles ), NULL, this ); + m_bpButton25->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnEqualFiles ), NULL, this ); + m_bpButton22->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnDifferentFiles ), NULL, this ); + m_bpButton23->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnRightNewerFiles ), NULL, this ); + m_bpButton24->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnRightOnlyFiles ), NULL, this ); + m_bpButton10->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GUI_Generated::OnQuit ), NULL, this ); +} + +SyncDialogGenerated::SyncDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer181; + bSizer181 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer181->Add( 5, 0, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer29; + bSizer29 = new wxBoxSizer( wxVERTICAL ); + + + bSizer29->Add( 0, 5, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer201; + bSizer201 = new wxBoxSizer( wxHORIZONTAL ); + + m_bpButton18 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 140,58 ), wxBU_AUTODRAW ); + m_bpButton18->SetToolTip( _("Start synchronizing files") ); + + m_bpButton18->SetToolTip( _("Start synchronizing files") ); + + bSizer201->Add( m_bpButton18, 0, wxRIGHT, 5 ); + + wxBoxSizer* bSizer211; + bSizer211 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText14 = new wxStaticText( this, wxID_ANY, _("Data to be transferred:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText14->Wrap( -1 ); + m_staticText14->SetFont( wxFont( 10, 74, 93, 90, false, wxT("Tahoma") ) ); + + bSizer211->Add( m_staticText14, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrl5 = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 55,-1 ), wxTE_READONLY ); + m_textCtrl5->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer211->Add( m_textCtrl5, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer201->Add( bSizer211, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + bSizer29->Add( bSizer201, 0, wxEXPAND, 5 ); + + + bSizer29->Add( 0, 3, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer23; + bSizer23 = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticBoxSizer* sbSizer7; + sbSizer7 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + m_staticText1 = new wxStaticText( this, wxID_ANY, _("Select variant:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1->Wrap( -1 ); + m_staticText1->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + sbSizer7->Add( m_staticText1, 0, wxALL, 5 ); + + wxFlexGridSizer* fgSizer1; + fgSizer1 = new wxFlexGridSizer( 3, 3, 0, 0 ); + fgSizer1->SetFlexibleDirection( wxBOTH ); + fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_radioBtn1 = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtn1->SetValue( true ); + m_radioBtn1->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_radioBtn1, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonOneWay = new wxButton( this, wxID_ANY, _("One way ->"), wxDefaultPosition, wxSize( 130,-1 ), 0 ); + m_buttonOneWay->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_buttonOneWay, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + m_staticText8 = new wxStaticText( this, wxID_ANY, _("Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText8->Wrap( 200 ); + fgSizer1->Add( m_staticText8, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_radioBtn2 = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtn2->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_radioBtn2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonTwoWay = new wxButton( this, wxID_ANY, _("Two way <->"), wxDefaultPosition, wxSize( 130,-1 ), 0 ); + m_buttonTwoWay->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_buttonTwoWay, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + m_staticText10 = new wxStaticText( this, wxID_ANY, _("Synchronize both sides simultaneously: Copy new or updated files in both directions."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText10->Wrap( 200 ); + fgSizer1->Add( m_staticText10, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_radioBtn3 = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtn3->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_radioBtn3, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText23 = new wxStaticText( this, wxID_ANY, _("Custom"), wxDefaultPosition, wxSize( 130,-1 ), wxALIGN_CENTRE|wxSTATIC_BORDER ); + m_staticText23->Wrap( -1 ); + m_staticText23->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_staticText23, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + m_staticText9 = new wxStaticText( this, wxID_ANY, _("Configure your own synchronization rules."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText9->Wrap( 200 ); + fgSizer1->Add( m_staticText9, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer7->Add( fgSizer1, 1, wxEXPAND, 5 ); + + bSizer23->Add( sbSizer7, 0, wxEXPAND, 5 ); + + + bSizer23->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer29->Add( bSizer23, 0, wxEXPAND, 5 ); + + + bSizer29->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer291; + bSizer291 = new wxBoxSizer( wxHORIZONTAL ); + + m_button6 = new wxButton( this, wxID_ANY, _("Back"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_button6->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer291->Add( m_button6, 0, wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer291->Add( 82, 0, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + m_checkBoxUseRecycler = new wxCheckBox( this, wxID_ANY, _("Use Recycle Bin"), wxDefaultPosition, wxDefaultSize, 0 ); + + m_checkBoxUseRecycler->SetToolTip( _("Use Recycle Bin when deleting or overwriting files during synchronization") ); + + bSizer291->Add( m_checkBoxUseRecycler, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer29->Add( bSizer291, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer181->Add( bSizer29, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer30; + bSizer30 = new wxBoxSizer( wxVERTICAL ); + + + bSizer30->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer6; + sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Configuration") ), wxVERTICAL ); + + wxBoxSizer* bSizer21; + bSizer21 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText2 = new wxStaticText( this, wxID_ANY, _("Result"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText2->Wrap( -1 ); + m_staticText2->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer21->Add( m_staticText2, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer21->Add( 15, 0, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText3 = new wxStaticText( this, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText3->Wrap( -1 ); + m_staticText3->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer21->Add( m_staticText3, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer6->Add( bSizer21, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + sbSizer6->Add( m_staticline3, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer9; + bSizer9 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer20; + bSizer20 = new wxBoxSizer( wxVERTICAL ); + + m_bitmap13 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + m_bitmap13->SetToolTip( _("Folders/files that exist on left side only") ); + + bSizer20->Add( m_bitmap13, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_bitmap14 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + m_bitmap14->SetToolTip( _("Folders/files that exist on right side only") ); + + bSizer20->Add( m_bitmap14, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_bitmap15 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + m_bitmap15->SetToolTip( _("Files that exist on both sides, left one is newer") ); + + bSizer20->Add( m_bitmap15, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_bitmap16 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + m_bitmap16->SetToolTip( _("Files that exist on both sides, right one is newer") ); + + bSizer20->Add( m_bitmap16, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_bitmap17 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + m_bitmap17->SetToolTip( _("Files that exist on both sides and are different") ); + + bSizer20->Add( m_bitmap17, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer9->Add( bSizer20, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer9->Add( 5, 0, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer19; + bSizer19 = new wxBoxSizer( wxVERTICAL ); + + m_bpButton5 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer19->Add( m_bpButton5, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 ); + + + bSizer19->Add( 0, 5, 0, wxEXPAND, 5 ); + + m_bpButton6 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer19->Add( m_bpButton6, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + bSizer19->Add( 0, 5, 1, wxEXPAND, 5 ); + + m_bpButton7 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer19->Add( m_bpButton7, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 ); + + + bSizer19->Add( 0, 5, 1, wxEXPAND, 5 ); + + m_bpButton8 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer19->Add( m_bpButton8, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + bSizer19->Add( 0, 5, 1, wxEXPAND, 5 ); + + m_bpButton9 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer19->Add( m_bpButton9, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer9->Add( bSizer19, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer9->Add( 5, 0, 0, wxEXPAND, 5 ); + + sbSizer6->Add( bSizer9, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer30->Add( sbSizer6, 0, wxALIGN_RIGHT|wxBOTTOM, 5 ); + + bSizer181->Add( bSizer30, 0, wxEXPAND|wxALIGN_BOTTOM, 5 ); + + + bSizer181->Add( 5, 0, 0, wxEXPAND, 5 ); + + bSizer7->Add( bSizer181, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer7 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncDialogGenerated::OnClose ) ); + m_bpButton18->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnStartSync ), NULL, this ); + m_radioBtn1->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncDialogGenerated::OnSyncLeftToRight ), NULL, this ); + m_buttonOneWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnSyncLeftToRight ), NULL, this ); + m_radioBtn2->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncDialogGenerated::OnSyncBothSides ), NULL, this ); + m_buttonTwoWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnSyncBothSides ), NULL, this ); + m_radioBtn3->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncDialogGenerated::OnSyncCostum ), NULL, this ); + m_button6->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnBack ), NULL, this ); + m_checkBoxUseRecycler->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnSelectRecycleBin ), NULL, this ); + m_bpButton5->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnExLeftSideOnly ), NULL, this ); + m_bpButton6->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnExRightSideOnly ), NULL, this ); + m_bpButton7->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnLeftNewer ), NULL, this ); + m_bpButton8->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnRightNewer ), NULL, this ); + m_bpButton9->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnDifferent ), NULL, this ); +} + +SyncDialogGenerated::~SyncDialogGenerated() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncDialogGenerated::OnClose ) ); + m_bpButton18->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnStartSync ), NULL, this ); + m_radioBtn1->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncDialogGenerated::OnSyncLeftToRight ), NULL, this ); + m_buttonOneWay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnSyncLeftToRight ), NULL, this ); + m_radioBtn2->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncDialogGenerated::OnSyncBothSides ), NULL, this ); + m_buttonTwoWay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnSyncBothSides ), NULL, this ); + m_radioBtn3->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncDialogGenerated::OnSyncCostum ), NULL, this ); + m_button6->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnBack ), NULL, this ); + m_checkBoxUseRecycler->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnSelectRecycleBin ), NULL, this ); + m_bpButton5->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnExLeftSideOnly ), NULL, this ); + m_bpButton6->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnExRightSideOnly ), NULL, this ); + m_bpButton7->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnLeftNewer ), NULL, this ); + m_bpButton8->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnRightNewer ), NULL, this ); + m_bpButton9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDialogGenerated::OnDifferent ), NULL, this ); +} + +HelpDlgGenerated::HelpDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer20; + bSizer20 = new wxBoxSizer( wxVERTICAL ); + + + bSizer20->Add( 0, 10, 0, wxEXPAND, 5 ); + + m_staticText12 = new wxStaticText( this, wxID_ANY, _("Help"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText12->Wrap( -1 ); + m_staticText12->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer20->Add( m_staticText12, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 ); + + + bSizer20->Add( 0, 5, 0, wxEXPAND, 5 ); + + m_textCtrl8 = new wxTextCtrl( this, wxID_ANY, _("Compare by \"File size and date\"\n----------------------------------------\nThis compare variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time. For the latter the system's UTC time (coordinated word time) is used internally, although the local file time is displayed on the result list. So there are no problems concerning different time zones or daylight saving time.\n\nWhen \"Compare\" is triggered with this option set the following decision tree is processed:\n\n -----------------\n |Decision tree|\n -----------------\n ________|___________\n | |\n file exists on both sides on one side only\n _____|______ __|___\n | | | |\nequal different left right\n _________|_____________\n | | |\n left newer right newer different (but same date)\n\nAs a result 6 different status can be returned to categorize all files:\n\n- exists left only\n- exists right only\n- left newer\n- right newer\n- different (but same date)\n- equal\n\n\nCompare by \"File content\"\n----------------------------------------\nAs the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller:\n\n -----------------\n |Decision tree|\n -----------------\n ________|___________\n | |\n file exists on both sides on one side only\n _____|______ __|___\n | | | |\nequal different left right\n\nAs a result the files are separated into the following categories:\n\n- exists left only\n- exists right only\n- different\n- equal"), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrl8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer20->Add( m_textCtrl8, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + m_button8 = new wxButton( this, wxID_ANY, _("OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_button8->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer20->Add( m_button8, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + this->SetSizer( bSizer20 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HelpDlgGenerated::OnClose ) ); + m_button8->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HelpDlgGenerated::OnOK ), NULL, this ); +} + +HelpDlgGenerated::~HelpDlgGenerated() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HelpDlgGenerated::OnClose ) ); + m_button8->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HelpDlgGenerated::OnOK ), NULL, this ); +} + +AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer31; + bSizer31 = new wxBoxSizer( wxVERTICAL ); + + + bSizer31->Add( 0, 10, 0, wxEXPAND, 5 ); + + m_staticText14 = new wxStaticText( this, wxID_ANY, _("FreeFileSync v1.2"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText14->Wrap( -1 ); + m_staticText14->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_staticText14, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_staticText15 = new wxStaticText( this, wxID_ANY, _("-Open-Source file synchronization-"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText15->Wrap( -1 ); + m_staticText15->SetFont( wxFont( 8, 74, 93, 90, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_staticText15, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_build = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_build->Wrap( -1 ); + bSizer31->Add( m_build, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + + bSizer31->Add( 0, 10, 0, wxEXPAND, 5 ); + + m_textCtrl3 = new wxTextCtrl( this, wxID_ANY, _("Source code written completely in C++ utilizing:\n\nMinGW \t\t- Windows port of GNU Compiler Collection\nwxWidgets \t- Open-Source GUI framework\nwxFormBuilder\t- wxWidgets GUI-builder\nGMP \t\t- arithmetic calculations\nCodeBlocks \t- Open-Source IDE\n\n by ZenJu"), wxDefaultPosition, wxSize( 350,140 ), wxTE_MULTILINE|wxTE_NO_VSCROLL|wxTE_READONLY|wxDOUBLE_BORDER ); + m_textCtrl3->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer31->Add( m_textCtrl3, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 0 ); + + + bSizer31->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer7; + sbSizer7 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + m_staticText131 = new wxStaticText( this, wxID_ANY, _("Feedback and suggestions are welcome at:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText131->Wrap( -1 ); + m_staticText131->SetFont( wxFont( 11, 74, 90, 90, false, wxT("Tahoma") ) ); + + sbSizer7->Add( m_staticText131, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer31->Add( sbSizer7, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxFlexGridSizer* fgSizer2; + fgSizer2 = new wxFlexGridSizer( 3, 3, 0, 0 ); + fgSizer2->SetFlexibleDirection( wxBOTH ); + fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_bitmap9 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + fgSizer2->Add( m_bitmap9, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_staticText11 = new wxStaticText( this, wxID_ANY, _("Homepage:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText11->Wrap( -1 ); + m_staticText11->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer2->Add( m_staticText11, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_hyperlink1 = new wxHyperlinkCtrl( this, wxID_ANY, _("FreeFileSync at Sourceforge"), wxT("http://sourceforge.net/projects/freefilesync/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink1->SetToolTip( _("http://sourceforge.net/projects/freefilesync/") ); + + fgSizer2->Add( m_hyperlink1, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + fgSizer2->Add( m_bitmap10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_staticText13 = new wxStaticText( this, wxID_ANY, _("Email:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText13->Wrap( -1 ); + m_staticText13->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer2->Add( m_staticText13, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_hyperlink2 = new wxHyperlinkCtrl( this, wxID_ANY, _("zhnmju123@gmx.de"), wxT("mailto:zhnmju123@gmx.de"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + fgSizer2->Add( m_hyperlink2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_animationControl1 = new wxAnimationCtrl(this, wxID_ANY, wxNullAnimation, wxDefaultPosition, wxSize( 48,48 )); + fgSizer2->Add( m_animationControl1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_staticText151 = new wxStaticText( this, wxID_ANY, _("If you like FFS:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText151->Wrap( -1 ); + m_staticText151->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer2->Add( m_staticText151, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_hyperlink3 = new wxHyperlinkCtrl( this, wxID_ANY, _("Donate with Paypal"), wxT("https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=florian%2db%40gmx%2enet&no_shipping=0&no_note=1&tax=0¤cy_code=EUR&lc=DE&bn=PP%2dDonationsBF&charset=UTF%2d8"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + fgSizer2->Add( m_hyperlink3, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer31->Add( fgSizer2, 0, wxEXPAND|wxLEFT, 10 ); + + m_button8 = new wxButton( this, wxID_ANY, _("OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_button8->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_button8, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + this->SetSizer( bSizer31 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::OnClose ) ); + m_button8->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOK ), NULL, this ); +} + +AboutDlgGenerated::~AboutDlgGenerated() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::OnClose ) ); + m_button8->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOK ), NULL, this ); +} + +FilterDlgGenerated::FilterDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer21; + bSizer21 = new wxBoxSizer( wxVERTICAL ); + + m_staticText17 = new wxStaticText( this, wxID_ANY, _("Set filter for synchronization"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText17->Wrap( -1 ); + m_staticText17->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); + + bSizer21->Add( m_staticText17, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 10 ); + + + bSizer21->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText18 = new wxStaticText( this, wxID_ANY, _("Only files/directories that pass filtering will be relevant for synchronization.\n\n1. Enter full file or directory names separated by ';'.\n2. Wildcard characters '*' and '?' are supported.\n3. Case sensitive expressions!\n\nExample: *.tmp;C:\\data\\dummy.log;*filename*;*directory*"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText18->Wrap( -1 ); + bSizer21->Add( m_staticText18, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxStaticBoxSizer* sbSizer8; + sbSizer8 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer3; + fgSizer3 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer3->SetFlexibleDirection( wxBOTH ); + fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + fgSizer3->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText15 = new wxStaticText( this, wxID_ANY, _("Include"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText15->Wrap( -1 ); + m_staticText15->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer3->Add( m_staticText15, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_bitmap8 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); + fgSizer3->Add( m_bitmap8, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_textCtrlInclude = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 400,-1 ), 0 ); + fgSizer3->Add( m_textCtrlInclude, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer8->Add( fgSizer3, 0, 0, 5 ); + + wxFlexGridSizer* fgSizer4; + fgSizer4 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer4->SetFlexibleDirection( wxBOTH ); + fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText16 = new wxStaticText( this, wxID_ANY, _("Exclude"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText16->Wrap( -1 ); + m_staticText16->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer4->Add( m_staticText16, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_bitmap9 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); + fgSizer4->Add( m_bitmap9, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_textCtrlExclude = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 400,-1 ), 0 ); + fgSizer4->Add( m_textCtrlExclude, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer8->Add( fgSizer4, 0, 0, 5 ); + + bSizer21->Add( sbSizer8, 0, wxRIGHT|wxLEFT, 5 ); + + + bSizer21->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer22; + bSizer22 = new wxBoxSizer( wxHORIZONTAL ); + + m_button9 = new wxButton( this, wxID_ANY, _("Default"), wxDefaultPosition, wxSize( 80,30 ), 0 ); + m_button9->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer22->Add( m_button9, 0, wxALL, 5 ); + + + bSizer22->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_button10 = new wxButton( this, wxID_ANY, _("OK"), wxDefaultPosition, wxSize( 80,30 ), 0 ); + m_button10->SetDefault(); + m_button10->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer22->Add( m_button10, 0, wxALL, 5 ); + + bSizer21->Add( bSizer22, 0, wxEXPAND|wxTOP, 5 ); + + this->SetSizer( bSizer21 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FilterDlgGenerated::OnClose ) ); + m_button9->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnDefault ), NULL, this ); + m_button10->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnOK ), NULL, this ); +} + +FilterDlgGenerated::~FilterDlgGenerated() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FilterDlgGenerated::OnClose ) ); + m_button9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnDefault ), NULL, this ); + m_button10->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnOK ), NULL, this ); +} + +ErrorDlgGenerated::ErrorDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); + + + bSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer26; + bSizer26 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + bSizer26->Add( m_bitmap10, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrl8 = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 320,140 ), wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrl8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer26->Add( m_textCtrl8, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + bSizer24->Add( bSizer26, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + + bSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_checkBoxSuppress = new wxCheckBox( this, wxID_ANY, _("Hide further messages during current process"), wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer24->Add( m_checkBoxSuppress, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer25; + bSizer25 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonContinue = new wxButton( this, wxID_ANY, _("Continue"), wxDefaultPosition, wxSize( 80,30 ), 0 ); + m_buttonContinue->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonContinue, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_buttonRetry = new wxButton( this, wxID_ANY, _("Retry"), wxDefaultPosition, wxSize( 80,30 ), 0 ); + m_buttonRetry->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonRetry, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_buttonAbort = new wxButton( this, wxID_ANY, _("Abort"), wxDefaultPosition, wxSize( 80,30 ), 0 ); + m_buttonAbort->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonAbort, 0, wxALL, 5 ); + + bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + this->SetSizer( bSizer24 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ErrorDlgGenerated::OnClose ) ); + m_buttonContinue->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnContinue ), NULL, this ); + m_buttonRetry->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnRetry ), NULL, this ); + m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnAbort ), NULL, this ); +} + +ErrorDlgGenerated::~ErrorDlgGenerated() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ErrorDlgGenerated::OnClose ) ); + m_buttonContinue->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnContinue ), NULL, this ); + m_buttonRetry->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnRetry ), NULL, this ); + m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnAbort ), NULL, this ); +} + +SyncStatusGenerated::SyncStatusGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer27; + bSizer27 = new wxBoxSizer( wxVERTICAL ); + + + bSizer27->Add( 0, 15, 0, wxEXPAND, 5 ); + + m_staticText20 = new wxStaticText( this, wxID_ANY, _("Synchronization status"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText20->Wrap( -1 ); + m_staticText20->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer27->Add( m_staticText20, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_staticTextStatus = new wxStaticText( this, wxID_ANY, _("Running..."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatus->Wrap( -1 ); + m_staticTextStatus->SetFont( wxFont( 14, 74, 93, 90, false, wxT("Tahoma") ) ); + + bSizer27->Add( m_staticTextStatus, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bSizer31; + bSizer31 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText21 = new wxStaticText( this, wxID_ANY, _("Current operation:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText21->Wrap( -1 ); + m_staticText21->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_staticText21, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer31->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText25 = new wxStaticText( this, wxID_ANY, _("Items completed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText25->Wrap( -1 ); + m_staticText25->SetFont( wxFont( 10, 74, 93, 90, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_staticText25, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextProcessedObj = new wxStaticText( this, wxID_ANY, _("1000000"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_staticTextProcessedObj->Wrap( -1 ); + m_staticTextProcessedObj->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_staticTextProcessedObj, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer27->Add( bSizer31, 0, wxEXPAND, 5 ); + + m_textCtrlInfo = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrlInfo->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer27->Add( m_textCtrlInfo, 3, wxALL|wxEXPAND, 5 ); + + m_gauge1 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,20 ), wxGA_HORIZONTAL ); + bSizer27->Add( m_gauge1, 0, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer28; + bSizer28 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer32; + bSizer32 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText26 = new wxStaticText( this, wxID_ANY, _("Data copied:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText26->Wrap( -1 ); + m_staticText26->SetFont( wxFont( 10, 74, 93, 90, false, wxT("Tahoma") ) ); + + bSizer32->Add( m_staticText26, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_staticTextBytesCurrent = new wxStaticText( this, wxID_ANY, _("10,0 MB"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextBytesCurrent->Wrap( -1 ); + m_staticTextBytesCurrent->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer32->Add( m_staticTextBytesCurrent, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_staticText30 = new wxStaticText( this, wxID_ANY, _("/"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText30->Wrap( -1 ); + m_staticText30->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer32->Add( m_staticText30, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextBytesTotal = new wxStaticText( this, wxID_ANY, _("10,0 MB"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextBytesTotal->Wrap( -1 ); + m_staticTextBytesTotal->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer32->Add( m_staticTextBytesTotal, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + bSizer28->Add( bSizer32, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer28->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_buttonOK = new wxButton( this, wxID_ANY, _("OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_buttonOK->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + m_buttonOK->Hide(); + + bSizer28->Add( m_buttonOK, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonAbort = new wxButton( this, wxID_ANY, _("Abort"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_buttonAbort->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer28->Add( m_buttonAbort, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer28->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer33; + bSizer33 = new wxBoxSizer( wxVERTICAL ); + + m_staticText32 = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText32->Wrap( -1 ); + m_staticText32->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer33->Add( m_staticText32, 0, wxALL, 5 ); + + bSizer28->Add( bSizer33, 1, wxEXPAND, 5 ); + + bSizer27->Add( bSizer28, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + + bSizer27->Add( 0, 5, 0, wxEXPAND, 5 ); + + this->SetSizer( bSizer27 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncStatusGenerated::OnClose ) ); + m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusGenerated::OnOkay ), NULL, this ); + m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusGenerated::OnAbort ), NULL, this ); +} + +SyncStatusGenerated::~SyncStatusGenerated() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncStatusGenerated::OnClose ) ); + m_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusGenerated::OnOkay ), NULL, this ); + m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusGenerated::OnAbort ), NULL, this ); +} diff --git a/ui/GUI_Generated.h b/ui/GUI_Generated.h new file mode 100644 index 00000000..f7ef37a7 --- /dev/null +++ b/ui/GUI_Generated.h @@ -0,0 +1,371 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 16 2008) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __GUI_Generated__ +#define __GUI_Generated__ + +#include <wx/intl.h> + +class CustomGrid; + +#include <wx/bitmap.h> +#include <wx/image.h> +#include <wx/icon.h> +#include <wx/bmpbuttn.h> +#include <wx/gdicmn.h> +#include <wx/font.h> +#include <wx/colour.h> +#include <wx/settings.h> +#include <wx/string.h> +#include <wx/button.h> +#include <wx/sizer.h> +#include <wx/radiobut.h> +#include <wx/statbox.h> +#include <wx/hyperlink.h> +#include <wx/checkbox.h> +#include <wx/textctrl.h> +#include <wx/filepicker.h> +#include <wx/grid.h> +#include <wx/panel.h> +#include <wx/statusbr.h> +#include <wx/frame.h> +#include <wx/stattext.h> +#include <wx/statline.h> +#include <wx/statbmp.h> +#include <wx/dialog.h> +#include <wx/animate.h> +#include <wx/gauge.h> + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class GUI_Generated +/////////////////////////////////////////////////////////////////////////////// +class GUI_Generated : public wxFrame +{ + private: + + protected: + wxBoxSizer* bSizer1; + + wxBitmapButton* m_bpButtonCompare; + wxButton* m_buttonAbort; + wxRadioButton* m_radioBtnSizeDate; + wxRadioButton* m_radioBtnContent; + wxBitmapButton* m_bpButton14; + + wxBitmapButton* m_bpButtonFilter; + wxHyperlinkCtrl* m_hyperlinkCfgFilter; + wxCheckBox* m_checkBoxHideFilt; + wxBitmapButton* m_bpButtonSync; + + wxPanel* m_panel1; + wxTextCtrl* m_directoryPanel1; + wxDirPickerCtrl* m_dirPicker1; + CustomGrid* m_grid1; + wxPanel* m_panel3; + wxBitmapButton* m_bpButtonSwap; + CustomGrid* m_grid3; + wxPanel* m_panel2; + wxTextCtrl* m_directoryPanel2; + wxDirPickerCtrl* m_dirPicker2; + CustomGrid* m_grid2; + wxPanel* m_panel4; + wxBitmapButton* m_bpButton11; + + wxBitmapButton* m_bpButton20; + wxBitmapButton* m_bpButton21; + wxBitmapButton* m_bpButton25; + wxBitmapButton* m_bpButton22; + wxBitmapButton* m_bpButton23; + wxBitmapButton* m_bpButton24; + + wxBitmapButton* m_bpButton10; + wxStatusBar* m_statusBar1; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnCompare( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAbortCompare( wxCommandEvent& event ){ event.Skip(); } + virtual void OnChangeCompareVariant( wxCommandEvent& event ){ event.Skip(); } + virtual void OnShowHelpDialog( wxCommandEvent& event ){ event.Skip(); } + virtual void OnFilterButton( wxCommandEvent& event ){ event.Skip(); } + virtual void OnConfigureFilter( wxHyperlinkEvent& event ){ event.Skip(); } + virtual void OnHideFilteredButton( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSync( wxCommandEvent& event ){ event.Skip(); } + virtual void OnEnterLeftDir( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDirChangedPanel1( wxFileDirPickerEvent& event ){ event.Skip(); } + virtual void OnLeftGridDoubleClick( wxGridEvent& event ){ event.Skip(); } + virtual void OnSortLeftGrid( wxGridEvent& event ){ event.Skip(); } + virtual void OnSwapDirs( wxCommandEvent& event ){ event.Skip(); } + virtual void OnGrid3SelectRange( wxGridRangeSelectEvent& event ){ event.Skip(); } + virtual void OnGrid3SelectCell( wxGridEvent& event ){ event.Skip(); } + virtual void OnEnterRightDir( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDirChangedPanel2( wxFileDirPickerEvent& event ){ event.Skip(); } + virtual void OnRightGridDoubleClick( wxGridEvent& event ){ event.Skip(); } + virtual void OnSortRightGrid( wxGridEvent& event ){ event.Skip(); } + virtual void OnAbout( wxCommandEvent& event ){ event.Skip(); } + virtual void OnLeftOnlyFiles( wxCommandEvent& event ){ event.Skip(); } + virtual void OnLeftNewerFiles( wxCommandEvent& event ){ event.Skip(); } + virtual void OnEqualFiles( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDifferentFiles( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRightNewerFiles( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRightOnlyFiles( wxCommandEvent& event ){ event.Skip(); } + virtual void OnQuit( wxCommandEvent& event ){ event.Skip(); } + + + public: + GUI_Generated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("FreeFileSync - Folder Synchronization"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 930,603 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); + ~GUI_Generated(); + +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class SyncDialogGenerated +/////////////////////////////////////////////////////////////////////////////// +class SyncDialogGenerated : public wxDialog +{ + private: + + protected: + + + wxBitmapButton* m_bpButton18; + wxStaticText* m_staticText14; + wxTextCtrl* m_textCtrl5; + + wxStaticText* m_staticText1; + wxRadioButton* m_radioBtn1; + wxButton* m_buttonOneWay; + wxStaticText* m_staticText8; + wxRadioButton* m_radioBtn2; + wxButton* m_buttonTwoWay; + wxStaticText* m_staticText10; + wxRadioButton* m_radioBtn3; + wxStaticText* m_staticText23; + wxStaticText* m_staticText9; + + + wxButton* m_button6; + + wxCheckBox* m_checkBoxUseRecycler; + + wxStaticText* m_staticText2; + + wxStaticText* m_staticText3; + wxStaticLine* m_staticline3; + wxStaticBitmap* m_bitmap13; + wxStaticBitmap* m_bitmap14; + wxStaticBitmap* m_bitmap15; + wxStaticBitmap* m_bitmap16; + wxStaticBitmap* m_bitmap17; + + wxBitmapButton* m_bpButton5; + + wxBitmapButton* m_bpButton6; + + wxBitmapButton* m_bpButton7; + + wxBitmapButton* m_bpButton8; + + wxBitmapButton* m_bpButton9; + + + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnStartSync( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSyncLeftToRight( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSyncBothSides( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSyncCostum( wxCommandEvent& event ){ event.Skip(); } + virtual void OnBack( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSelectRecycleBin( wxCommandEvent& event ){ event.Skip(); } + virtual void OnExLeftSideOnly( wxCommandEvent& event ){ event.Skip(); } + virtual void OnExRightSideOnly( wxCommandEvent& event ){ event.Skip(); } + virtual void OnLeftNewer( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRightNewer( wxCommandEvent& event ){ event.Skip(); } + virtual void OnDifferent( wxCommandEvent& event ){ event.Skip(); } + + + public: + SyncDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Synchronization settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 533,349 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~SyncDialogGenerated(); + +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class HelpDlgGenerated +/////////////////////////////////////////////////////////////////////////////// +class HelpDlgGenerated : public wxDialog +{ + private: + + protected: + + wxStaticText* m_staticText12; + + wxTextCtrl* m_textCtrl8; + wxButton* m_button8; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnOK( wxCommandEvent& event ){ event.Skip(); } + + + public: + HelpDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 557,385 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~HelpDlgGenerated(); + +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class AboutDlgGenerated +/////////////////////////////////////////////////////////////////////////////// +class AboutDlgGenerated : public wxDialog +{ + private: + + protected: + + wxStaticText* m_staticText14; + wxStaticText* m_staticText15; + wxStaticText* m_build; + + wxTextCtrl* m_textCtrl3; + + wxStaticText* m_staticText131; + wxStaticBitmap* m_bitmap9; + wxStaticText* m_staticText11; + wxHyperlinkCtrl* m_hyperlink1; + wxStaticBitmap* m_bitmap10; + wxStaticText* m_staticText13; + wxHyperlinkCtrl* m_hyperlink2; + wxAnimationCtrl* m_animationControl1; + wxStaticText* m_staticText151; + wxHyperlinkCtrl* m_hyperlink3; + wxButton* m_button8; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnOK( wxCommandEvent& event ){ event.Skip(); } + + + public: + AboutDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("About"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 438,495 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~AboutDlgGenerated(); + +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class FilterDlgGenerated +/////////////////////////////////////////////////////////////////////////////// +class FilterDlgGenerated : public wxDialog +{ + private: + + protected: + wxStaticText* m_staticText17; + + wxStaticText* m_staticText18; + + wxStaticText* m_staticText15; + wxStaticBitmap* m_bitmap8; + wxTextCtrl* m_textCtrlInclude; + + wxStaticText* m_staticText16; + wxStaticBitmap* m_bitmap9; + wxTextCtrl* m_textCtrlExclude; + + wxButton* m_button9; + + wxButton* m_button10; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnDefault( wxCommandEvent& event ){ event.Skip(); } + virtual void OnOK( wxCommandEvent& event ){ event.Skip(); } + + + public: + FilterDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Configure filter settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 484,350 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~FilterDlgGenerated(); + +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class ErrorDlgGenerated +/////////////////////////////////////////////////////////////////////////////// +class ErrorDlgGenerated : public wxDialog +{ + private: + + protected: + + wxStaticBitmap* m_bitmap10; + wxTextCtrl* m_textCtrl8; + + wxCheckBox* m_checkBoxSuppress; + + wxButton* m_buttonContinue; + wxButton* m_buttonRetry; + wxButton* m_buttonAbort; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnContinue( wxCommandEvent& event ){ event.Skip(); } + virtual void OnRetry( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAbort( wxCommandEvent& event ){ event.Skip(); } + + + public: + ErrorDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("An error occured"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 411,266 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~ErrorDlgGenerated(); + +}; + +/////////////////////////////////////////////////////////////////////////////// +/// Class SyncStatusGenerated +/////////////////////////////////////////////////////////////////////////////// +class SyncStatusGenerated : public wxDialog +{ + private: + + protected: + + wxStaticText* m_staticText20; + wxStaticText* m_staticText21; + + wxStaticText* m_staticText25; + wxStaticText* m_staticTextProcessedObj; + wxStaticText* m_staticText26; + wxStaticText* m_staticTextBytesCurrent; + wxStaticText* m_staticText30; + wxStaticText* m_staticTextBytesTotal; + + + wxStaticText* m_staticText32; + + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } + virtual void OnOkay( wxCommandEvent& event ){ event.Skip(); } + virtual void OnAbort( wxCommandEvent& event ){ event.Skip(); } + + + public: + wxStaticText* m_staticTextStatus; + wxTextCtrl* m_textCtrlInfo; + wxGauge* m_gauge1; + wxButton* m_buttonOK; + wxButton* m_buttonAbort; + SyncStatusGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 614,371 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~SyncStatusGenerated(); + +}; + +#endif //__GUI_Generated__ diff --git a/ui/MainDialog.cpp b/ui/MainDialog.cpp new file mode 100644 index 00000000..97288b90 --- /dev/null +++ b/ui/MainDialog.cpp @@ -0,0 +1,1719 @@ +/*************************************************************** + * Name: FreeFileSyncMain.cpp + * Purpose: Code for Application Frame + * Author: ZenJu (zhnmju123@gmx.de) + * Created: 2008-07-16 + * Copyright: ZenJu () + * License: + **************************************************************/ + +#include "MainDialog.h" +#include <wx/filename.h> +#include <stdexcept> //for std::runtime_error +#include "..\library\globalfunctions.h" +#include <fstream> +#include <wx/clipbrd.h> +#include "..\library\CustomGrid.h" +#include <cmath> +#include <wx/msgdlg.h> + +using namespace GlobalFunctions; + +int leadingPanel = 0; + +MainDialog::MainDialog(wxFrame* frame) : + GUI_Generated(frame), + parent(frame), + selectedRangeBegin(0), + selectedRangeEnd(0), + selectionLead(0), + filteringPending(false), + cmpStatusUpdaterTmp(0) +{ + //initialize sync configuration + readConfigurationFromHD("config.dat"); + + //set icons for this dialog + m_bpButton11->SetBitmapLabel(*GlobalResources::bitmapAbout); + m_bpButton10->SetBitmapLabel(*GlobalResources::bitmapExit); + m_bpButtonCompare->SetBitmapLabel(*GlobalResources::bitmapCompare); + m_bpButtonSync->SetBitmapLabel(*GlobalResources::bitmapSync); + m_bpButtonSync->SetBitmapDisabled(*GlobalResources::bitmapSyncDisabled); + m_bpButtonSwap->SetBitmapLabel(*GlobalResources::bitmapSwap); + m_bpButton14->SetBitmapLabel(*GlobalResources::bitmapHelp); + + m_panel1->DragAcceptFiles(true); + m_panel2->DragAcceptFiles(true); + m_panel1->Connect(wxEVT_DROP_FILES, wxDropFilesEventHandler(MainDialog::onFilesDroppedPanel1), NULL, this); + m_panel2->Connect(wxEVT_DROP_FILES, wxDropFilesEventHandler(MainDialog::onFilesDroppedPanel2), NULL, this); + + //support for CTRL + C + m_grid1->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGrid1ButtonEvent), NULL, this); + m_grid2->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGrid2ButtonEvent), NULL, this); + + //identify leading grid by keyboard input or scroll action + m_grid1->Connect(wxEVT_KEY_DOWN, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Connect(wxEVT_SCROLLWIN_TOP, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Connect(wxEVT_SCROLLWIN_BOTTOM, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Connect(wxEVT_SCROLLWIN_LINEUP, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Connect(wxEVT_SCROLLWIN_LINEDOWN, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Connect(wxEVT_SCROLLWIN_PAGEUP, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Connect(wxEVT_SCROLLWIN_PAGEDOWN, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Connect(wxEVT_SCROLLWIN_THUMBRELEASE, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Connect(wxEVT_GRID_LABEL_LEFT_CLICK, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxEventHandler(MainDialog::onGrid1access), NULL, this); + + m_grid2->Connect(wxEVT_KEY_DOWN, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Connect(wxEVT_SCROLLWIN_TOP, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Connect(wxEVT_SCROLLWIN_BOTTOM, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Connect(wxEVT_SCROLLWIN_LINEUP, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Connect(wxEVT_SCROLLWIN_LINEDOWN, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Connect(wxEVT_SCROLLWIN_PAGEUP, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Connect(wxEVT_SCROLLWIN_PAGEDOWN, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Connect(wxEVT_SCROLLWIN_THUMBRELEASE, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Connect(wxEVT_GRID_LABEL_LEFT_CLICK, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxEventHandler(MainDialog::onGrid2access), NULL, this); + + m_grid3->Connect(wxEVT_KEY_DOWN, wxEventHandler(MainDialog::onGrid3access), NULL, this); + m_grid3->Connect(wxEVT_SCROLLWIN_LINEUP, wxEventHandler(MainDialog::onGrid3access), NULL, this); + m_grid3->Connect(wxEVT_SCROLLWIN_LINEDOWN, wxEventHandler(MainDialog::onGrid3access), NULL, this); + m_grid3->GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxEventHandler(MainDialog::onGrid3access), NULL, this); + + m_grid3->GetGridWindow()->Connect(wxEVT_IDLE, wxEventHandler(MainDialog::OnIdleToFilterManually), NULL, this); + m_grid3->GetGridWindow()->Connect(wxEVT_LEFT_UP, wxEventHandler(MainDialog::OnGrid3LeftMouseUp), NULL, this); + + wxString toolTip = wxString(_("Legend\n")) + + _("---------\n") + + _("<| file on left side only\n") + + _("|> file on right side only\n") + + _("<< left file is newer\n") + + _(">> right file is newer\n") + + _("!= files are different\n") + + _("== files are equal\n\n") + + _("(-) filtered out from sync-process\n"); + m_grid3->GetGridWindow()->SetToolTip(toolTip); + + //enable parallel scrolling + m_grid1->setScrollFriends(m_grid1, m_grid2, m_grid3); + m_grid2->setScrollFriends(m_grid1, m_grid2, m_grid3); + m_grid3->setScrollFriends(m_grid1, m_grid2, m_grid3); + + //share UI grid data with grids + m_grid1->setGridDataTable(¤tUI_View); + m_grid2->setGridDataTable(¤tUI_View); + m_grid3->setGridDataTable(¤tUI_View); + + updateViewFilterButtons(); + + //disable sync button as long as "compare" hasn't been triggered. + m_bpButtonSync->Enable(false); + + //make filesize right justified on grids + wxGridCellAttr* cellAttributes = m_grid1->GetOrCreateCellAttr(0, 2); + cellAttributes->SetAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE); + m_grid1->SetColAttr(2, cellAttributes); + + cellAttributes = m_grid2->GetOrCreateCellAttr(0, 2); //leave these two rows, might be necessary 'cause wxGridCellAttr is ref-counting + cellAttributes->SetAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE); //and SetColAttr takes ownership (means: it will call DecRef()) + m_grid2->SetColAttr(2, cellAttributes); + + //as the name says: disable them + m_grid3->deactivateScrollbars(); + + //set status of filter button + updateFilterButton(); + //set status of "hide filtered items" checkbox + m_checkBoxHideFilt->SetValue(hideFiltered); + + //mainly to update row label sizes... + writeGrid(currentGridData); +} + + +MainDialog::~MainDialog() +{ + m_grid1->setGridDataTable(0); + m_grid2->setGridDataTable(0); + m_grid3->setGridDataTable(0); + + m_grid1->setSortMarker(-1); + m_grid2->setSortMarker(-1); + + m_grid1->Disconnect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGrid1ButtonEvent), NULL, this); + m_grid2->Disconnect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGrid2ButtonEvent), NULL, this); + + m_panel1->Disconnect(wxEVT_DROP_FILES, wxDropFilesEventHandler(MainDialog::onFilesDroppedPanel1), NULL, this); + m_panel2->Disconnect(wxEVT_DROP_FILES, wxDropFilesEventHandler(MainDialog::onFilesDroppedPanel2), NULL, this); + + m_grid1->Disconnect(wxEVT_KEY_DOWN, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Disconnect(wxEVT_SCROLLWIN_TOP, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Disconnect(wxEVT_SCROLLWIN_BOTTOM, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Disconnect(wxEVT_SCROLLWIN_LINEUP, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Disconnect(wxEVT_SCROLLWIN_LINEDOWN, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Disconnect(wxEVT_SCROLLWIN_PAGEUP, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Disconnect(wxEVT_SCROLLWIN_PAGEDOWN, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Disconnect(wxEVT_SCROLLWIN_THUMBTRACK, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Disconnect(wxEVT_SCROLLWIN_THUMBRELEASE, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->Disconnect(wxEVT_GRID_LABEL_LEFT_CLICK, wxEventHandler(MainDialog::onGrid1access), NULL, this); + m_grid1->GetGridWindow()->Disconnect(wxEVT_LEFT_DOWN, wxEventHandler(MainDialog::onGrid1access), NULL, this); + + m_grid2->Disconnect(wxEVT_KEY_DOWN, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Disconnect(wxEVT_SCROLLWIN_TOP, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Disconnect(wxEVT_SCROLLWIN_BOTTOM, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Disconnect(wxEVT_SCROLLWIN_LINEUP, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Disconnect(wxEVT_SCROLLWIN_LINEDOWN, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Disconnect(wxEVT_SCROLLWIN_PAGEUP, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Disconnect(wxEVT_SCROLLWIN_PAGEDOWN, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Disconnect(wxEVT_SCROLLWIN_THUMBTRACK, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Disconnect(wxEVT_SCROLLWIN_THUMBRELEASE, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->Disconnect(wxEVT_GRID_LABEL_LEFT_CLICK, wxEventHandler(MainDialog::onGrid2access), NULL, this); + m_grid2->GetGridWindow()->Disconnect(wxEVT_LEFT_DOWN, wxEventHandler(MainDialog::onGrid2access), NULL, this); + + m_grid3->Disconnect(wxEVT_KEY_DOWN, wxEventHandler(MainDialog::onGrid3access), NULL, this); + m_grid3->Disconnect(wxEVT_SCROLLWIN_LINEUP, wxEventHandler(MainDialog::onGrid3access), NULL, this); + m_grid3->Disconnect(wxEVT_SCROLLWIN_LINEDOWN, wxEventHandler(MainDialog::onGrid3access), NULL, this); + m_grid3->GetGridWindow()->Disconnect(wxEVT_LEFT_DOWN, wxEventHandler(MainDialog::onGrid3access), NULL, this); + + m_grid3->GetGridWindow()->Disconnect(wxEVT_IDLE, wxEventHandler(MainDialog::OnIdleToFilterManually), NULL, this); + m_grid3->GetGridWindow()->Disconnect(wxEVT_LEFT_UP, wxEventHandler(MainDialog::OnGrid3LeftMouseUp), NULL, this); + + try + { + writeConfigurationToHD("config.dat"); //don't trow exceptions in destructors + } + catch (std::runtime_error& theException) + { + wxMessageBox(_(theException.what()), _("An exception occured!"), wxOK | wxICON_ERROR); + } +} + + +void MainDialog::onGrid1access(wxEvent& event) +{ + if (leadingPanel != 1) + { + leadingPanel = 1; + m_grid1->SetFocus(); + + m_grid2->ClearSelection(); //clear selection on grid2 + } + event.Skip(); +} + + +void MainDialog::onGrid2access(wxEvent& event) +{ + if (leadingPanel != 2) + { + leadingPanel = 2; + m_grid2->SetFocus(); + + m_grid1->ClearSelection(); //clear selection on grid1 + } + event.Skip(); +} + + +void MainDialog::onGrid3access(wxEvent& event) +{ + if (leadingPanel != 3) + { + leadingPanel = 3; + m_grid1->ClearSelection(); //clear selection on grid1 + m_grid2->ClearSelection(); //clear selection on grid1 + } + event.Skip(); +} + + +void MainDialog::filterRangeManual(int begin, int end, int leadingRow) +{ + int currentUI_Size = currentUI_View.size(); + + int topRow = max(begin, 0); + int bottomRow = min(end, currentUI_Size - 1); + + if (topRow <= bottomRow) // bottomRow might be -1 ? + { + bool newSelection = false; //default: deselect range + + //lastSelected Row should be set in OnDeselectRow() + if (leadingRow < currentUI_Size) + newSelection = !currentGridData[currentUI_View[leadingRow].linkToCurrentGridData].selectedForSynchronization; + + if (hideFiltered) + assert (!newSelection); //if hidefiltered is active, there should be no filtered elements on screen => current element was filtered out + + for (int i = topRow; i <= bottomRow; ++ i) + { + bool& currentSelection = currentGridData[currentUI_View[i].linkToCurrentGridData].selectedForSynchronization; + CompareFilesResult currentCmpResult = currentGridData[currentUI_View[i].linkToCurrentGridData].cmpResult; + + //toggle selection of current row + currentSelection = newSelection; + + //update currentUI_View, in case of sorting without refresh (mapping of griddata to ui model) + currentUI_View[i].cmpResult = evaluateCmpResult(currentCmpResult, currentSelection); + } + + //signal UI that grids need to be refreshed on next Update() + m_grid1->ForceRefresh(); + m_grid2->ForceRefresh(); + m_grid3->ForceRefresh(); + + if (hideFiltered) + { + //some delay to show user the rows he has filtered out before they are removed + Update(); //show changes resulting from ForceRefresh() + wxMilliSleep(400); + + //delete rows, that are filtered out: + currentUI_View.erase(currentUI_View.begin() + topRow, currentUI_View.begin() + bottomRow + 1); + + //redraw grid neccessary to update new dimensions + writeGrid(currentGridData, true); //use UI buffer, no mapping from currentGridData to UI model again, just a re-dimensioning of grids + updateStatusInformation(currentUI_View); //status information has to be recalculated! + } + } + //clear selection on grid + m_grid3->ClearSelection(); +} + +/*grid event choreography: +1. UI-Mouse-Down => OnGrid3SelectCell +2. UI-Mouse-Up => OnGrid3SelectRange (if at least two rows are marked) + +=> the decision if a range or a single cell is selected can be made only after Mouse-UP. But OnGrid3SelectRange unfortunately is not always +executed (e.g. if single cell selected) + +=> new choreography: + +1. UI-Mouse-Down => OnGrid3SelectCell +2. UI-Mouse-Up => OnGrid3LeftMouseUp (notify that filtering shall be started on next idle event +3. UI-Mouse-Up => OnGrid3SelectRange, possibly +4. Idle event => OnIdleToFilterManually + + It's !crazy! but it works! +*/ + +void MainDialog::OnGrid3SelectCell(wxGridEvent& event) +{ + selectionLead = selectedRangeBegin = selectedRangeEnd = event.GetRow(); + event.Skip(); +} + + +void MainDialog::OnGrid3LeftMouseUp(wxEvent& event) +{ + filteringPending = true; + event.Skip(); +} + + +void MainDialog::OnGrid3SelectRange(wxGridRangeSelectEvent& event) +{ + if (event.Selecting()) + { + selectedRangeBegin = event.GetTopRow(); + selectedRangeEnd = event.GetBottomRow(); + } + event.Skip(); +} + + +void MainDialog::OnIdleToFilterManually(wxEvent& event) +{ + if (filteringPending) + { + filteringPending = false; + filterRangeManual(selectedRangeBegin, selectedRangeEnd, selectionLead); + } + event.Skip(); +} + + +void copySelectionToClipboard(wxGrid* grid) +{ + int rowTop, rowBottom, colLeft, colRight; //coords of selection + wxString clipboardString; + + wxArrayInt selectedRows, selectedColumns; + selectedRows = grid->GetSelectedRows(); + selectedColumns = grid->GetSelectedCols(); + + if (!selectedRows.IsEmpty()) + { + for (unsigned int i = 0; i < selectedRows.GetCount(); ++i) + { + for (int k = 0; k < grid->GetNumberCols(); ++k) + { + clipboardString+= grid->GetCellValue(selectedRows[i], k); + if (k != grid->GetNumberCols() - 1) + clipboardString+= '\t'; + } + clipboardString+= '\n'; + } + } + else if (!selectedColumns.IsEmpty()) + { + for (int k = 0; k < grid->GetNumberRows(); ++k) + { + for (unsigned int i = 0; i < selectedColumns.GetCount(); ++i) + { + clipboardString+= grid->GetCellValue(k, selectedColumns[i]); + if (i != selectedColumns.GetCount() - 1) + clipboardString+= '\t'; + } + clipboardString+= '\n'; + } + } + else + { + wxGridCellCoordsArray tmpArray; + + tmpArray = grid->GetSelectionBlockTopLeft(); + if (!tmpArray.IsEmpty()) + { + wxGridCellCoords topLeft = tmpArray[0]; + + rowTop = topLeft.GetRow(); + colLeft = topLeft.GetCol(); + + tmpArray = grid->GetSelectionBlockBottomRight(); + if (!tmpArray.IsEmpty()) + { + wxGridCellCoords bottomRight = tmpArray[0]; + + rowBottom = bottomRight.GetRow(); + colRight = bottomRight.GetCol(); + + //save selection in one big string + for (int j = rowTop; j <= rowBottom; ++j) + { + for (int i = colLeft; i <= colRight; ++i) + { + clipboardString+= grid->GetCellValue(j, i); + if (i != colRight) + clipboardString+= '\t'; + } + clipboardString+= '\n'; + } + } + } + } + + if (!clipboardString.IsEmpty()) + // Write some text to the clipboard + if (wxTheClipboard->Open()) + { + // This data objects are held by the clipboard, + // so do not delete them in the app. + wxTheClipboard->SetData( new wxTextDataObject(clipboardString) ); + wxTheClipboard->Close(); + } +} + + +void MainDialog::onGrid1ButtonEvent(wxKeyEvent& event) +{ + //CTRL + C || CTRL + INS + if (event.ControlDown() && event.GetKeyCode() == 67 || + event.ControlDown() && event.GetKeyCode() == WXK_INSERT) + copySelectionToClipboard(m_grid1); + event.Skip(); +} + +void MainDialog::onGrid2ButtonEvent(wxKeyEvent& event) +{ + //CTRL + C || CTRL + INS + if (event.ControlDown() && event.GetKeyCode() == 67 || + event.ControlDown() && event.GetKeyCode() == WXK_INSERT) + copySelectionToClipboard(m_grid2); + event.Skip(); +} + + +void MainDialog::OnEnterLeftDir( wxCommandEvent& event ) +{ + wxString newDir = m_directoryPanel1->GetValue(); + m_dirPicker1->SetPath(newDir); + + event.Skip(); +} + + +void MainDialog::OnEnterRightDir( wxCommandEvent& event ) +{ + wxString newDir = m_directoryPanel2->GetValue(); + m_dirPicker2->SetPath(newDir); + + event.Skip(); +} + + +void MainDialog::OnDirChangedPanel1(wxFileDirPickerEvent& event) +{ + wxString newPath = m_dirPicker1->GetPath(); + + m_directoryPanel1->SetValue(newPath); + + //disable the sync button + m_bpButtonSync->Enable(false); + + //clear grids + currentGridData.clear(); + writeGrid(currentGridData); + + event.Skip(); +} + +void MainDialog::OnDirChangedPanel2(wxFileDirPickerEvent& event) +{ + wxString newPath = m_dirPicker2->GetPath(); + + m_directoryPanel2->SetValue(newPath); + + //disable the sync button + m_bpButtonSync->Enable(false); + //clear grids + currentGridData.clear(); + writeGrid(currentGridData); + + event.Skip(); +} + +void onFilesDropped(wxString elementName, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker) +{ + if (wxDirExists(elementName)) + { + txtCtrl->SetValue(elementName); + dirPicker->SetPath(elementName); + } + else + { + elementName = wxFileName(elementName).GetPath(); + if (wxDirExists(elementName)) + { + txtCtrl->SetValue(elementName); + dirPicker->SetPath(elementName); + } + } +} + + +void MainDialog::onFilesDroppedPanel1(wxDropFilesEvent& event) +{ + if (event.m_noFiles >= 1) + { + onFilesDropped(event.GetFiles()[0], m_directoryPanel1, m_dirPicker1); + + //disable the sync button + m_bpButtonSync->Enable(false); + //clear grids + currentGridData.clear(); + writeGrid(currentGridData); + } + event.Skip(); +} + +void MainDialog::onFilesDroppedPanel2(wxDropFilesEvent& event) +{ + if (event.m_noFiles >= 1) + { + onFilesDropped(event.GetFiles()[0], m_directoryPanel2, m_dirPicker2); + + //disable the sync button + m_bpButtonSync->Enable(false); + //clear grids + currentGridData.clear(); + writeGrid(currentGridData); + } + event.Skip(); +} + + +void MainDialog::OnChangeCompareVariant(wxCommandEvent& event) +{ + //disable the sync button + m_bpButtonSync->Enable(false); + //clear grids + currentGridData.clear(); + writeGrid(currentGridData); +} + + +void MainDialog::OnClose(wxCloseEvent &event) +{ + Destroy(); +} + + +void MainDialog::OnQuit(wxCommandEvent &event) +{ + Destroy(); +} + + +void MainDialog::readConfigurationFromHD(const wxString& filename) +{ + //default values + syncConfiguration.exLeftSideOnly = SyncDirRight; + syncConfiguration.exRightSideOnly = SyncDirRight; + syncConfiguration.leftNewer = SyncDirRight; + syncConfiguration.rightNewer = SyncDirRight; + syncConfiguration.different = SyncDirRight; + + leftOnlyFilesActive = true; + leftNewerFilesActive = true; + differentFilesActive = true; + rightNewerFilesActive = true; //do not put these bool values into config.dat! + rightOnlyFilesActive = true; //it's more convenient to have them defaulted for each execution + equalFilesActive = false; + + includeFilter = "*"; //include all files/folders + excludeFilter = ""; //exlude nothing + hideFiltered = false; //show filtered items + filterIsActive = false; //do not filter by default + + useRecycleBin = false; //do not use: in case OS doesn't support this, user will have to activate first and then get the error message +//##################################################### + + ifstream config(filename.c_str()); + if (!config) + return; + + //read sync configuration + syncConfiguration.exLeftSideOnly = SyncDirection(config.get()); + syncConfiguration.exRightSideOnly = SyncDirection(config.get()); + syncConfiguration.leftNewer = SyncDirection(config.get()); + syncConfiguration.rightNewer = SyncDirection(config.get()); + syncConfiguration.different = SyncDirection(config.get()); + + //read find method + switch (int(config.get())) + { + case CompareByTimeAndSize: + m_radioBtnSizeDate->SetValue(true); + break; + case CompareByMD5: + m_radioBtnContent->SetValue(true); + break; + default: + assert (false); + } + + char bigBuffer[10000]; + + //read column sizes + for (int i = 0; i < m_grid1->GetNumberCols(); ++i) + { + config.getline(bigBuffer, 100, char(0)); + m_grid1->SetColSize(i, atoi(bigBuffer)); + } + for (int i = 0; i < m_grid2->GetNumberCols(); ++i) + { + config.getline(bigBuffer, 100, char(0)); + m_grid2->SetColSize(i, atoi(bigBuffer)); + } + + //read application window size and position + Maximize(bool(config.get())); + + config.getline(bigBuffer, 100, char(0)); + int width = atoi(bigBuffer); + config.getline(bigBuffer, 100, char(0)); + int height = atoi(bigBuffer); + config.getline(bigBuffer, 100, char(0)); + int posX = atoi(bigBuffer); + config.getline(bigBuffer, 100, char(0)); + int posY = atoi(bigBuffer); + SetSize(posX, posY, width, height); + + //read last directory selection + config.getline(bigBuffer, 10000, char(0)); + m_directoryPanel1->SetValue(bigBuffer); + if (wxDirExists(bigBuffer)) + m_dirPicker1->SetPath(bigBuffer); + + config.getline(bigBuffer, 10000, char(0)); + m_directoryPanel2->SetValue(bigBuffer); + if (wxDirExists(bigBuffer)) + m_dirPicker2->SetPath(bigBuffer); + + //read filter settings: + hideFiltered = bool(config.get()); + filterIsActive = bool(config.get()); + + //include + config.getline(bigBuffer, 10000, char(0)); + includeFilter = bigBuffer; + + //exclude + config.getline(bigBuffer, 10000, char(0)); + excludeFilter = bigBuffer; + + useRecycleBin = bool(config.get()); + + config.close(); +} + +void MainDialog::writeConfigurationToHD(const wxString& filename) +{ + DWORD dwFileAttributes; + + //make config file visible: needed for ofstream + if (wxFileExists(filename)) + { + dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + if (!SetFileAttributes( + filename.c_str(), // address of filename + dwFileAttributes // address of attributes to set + )) throw runtime_error(string(_("Could not change attributes of ")) + filename.c_str()); + } + + ofstream config(filename.c_str()); + if (!config) + throw runtime_error(string(_("Could not open ")) + filename.c_str()); + + //write sync configuration + config<<char(syncConfiguration.exLeftSideOnly) + <<char(syncConfiguration.exRightSideOnly) + <<char(syncConfiguration.leftNewer) + <<char(syncConfiguration.rightNewer) + <<char(syncConfiguration.different); + + //write find method + if (m_radioBtnSizeDate->GetValue()) + config<<char(CompareByTimeAndSize); + else if (m_radioBtnContent->GetValue()) + config<<char(CompareByMD5); + else assert (false); + + + //write column sizes + for (int i = 0; i < m_grid1->GetNumberCols(); ++i) + config<<m_grid1->GetColSize(i)<<char(0); + for (int i = 0; i < m_grid2->GetNumberCols(); ++i) + config<<m_grid2->GetColSize(i)<<char(0); + + //write application window size + config<<char(IsMaximized()); + //window size + int width = 0; + int height = 0; + GetSize(&width, &height); + config<<width<<char(0); + config<<height<<char(0); + //window position + int posX = 0; + int posY = 0; + GetPosition(&posX, &posY); + config<<posX<<char(0); + config<<posY<<char(0); + + //write last directory selection + config<<m_directoryPanel1->GetValue().c_str()<<char(0) + <<m_directoryPanel2->GetValue().c_str()<<char(0); + + //write filter settings + config<<char(hideFiltered); + config<<char(filterIsActive); + + config<<includeFilter.c_str()<<char(0) + <<excludeFilter.c_str()<<char(0); + + config<<char(useRecycleBin); + + config.close(); + + //hide config file + dwFileAttributes = FILE_ATTRIBUTE_HIDDEN; + if (!SetFileAttributes( + filename.c_str(), // address of filename + dwFileAttributes // address of attributes to set + )) throw runtime_error(string(_("Could not change attributes of ")) + filename.c_str()); +} + +void MainDialog::OnAbout(wxCommandEvent &event) +{ + AboutDlg* aboutDlg = new AboutDlg(this); + aboutDlg->ShowModal(); +} + +void MainDialog::OnShowHelpDialog(wxCommandEvent &event) +{ + HelpDlg* helpDlg = new HelpDlg(this); + helpDlg->ShowModal(); +} + +void MainDialog::OnFilterButton(wxCommandEvent &event) +{ //toggle filter on/off + filterIsActive = !filterIsActive; + + if (filterIsActive) + FreeFileSync::filterCurrentGridData(currentGridData, includeFilter, excludeFilter); + else + FreeFileSync::removeFilterOnCurrentGridData(currentGridData); + + writeGrid(currentGridData); + + //make sure, button-appearance and "filterIsActive" are in sync. + updateFilterButton(); +} + + +void MainDialog::OnHideFilteredButton(wxCommandEvent &event) +{ //toggle showing filtered rows + hideFiltered = !hideFiltered; + + writeGrid(currentGridData); + + //make sure, checkbox and "hideFiltered" are in sync + m_checkBoxHideFilt->SetValue(hideFiltered); +} + + +void MainDialog::OnConfigureFilter(wxHyperlinkEvent &event) +{ + FilterDlg* filterDlg = new FilterDlg(this); + if (filterDlg->ShowModal() == OkayButtonPressed) + { + if (filterIsActive) + { + FreeFileSync::filterCurrentGridData(currentGridData, includeFilter, excludeFilter); + + writeGrid(currentGridData); + } + } + //no event.Skip() here, to not start browser +} + +void MainDialog::OnLeftOnlyFiles(wxCommandEvent& event) +{ + leftOnlyFilesActive = !leftOnlyFilesActive; + updateViewFilterButtons(); + writeGrid(currentGridData); +}; + +void MainDialog::OnLeftNewerFiles(wxCommandEvent& event) +{ + leftNewerFilesActive = !leftNewerFilesActive; + updateViewFilterButtons(); + writeGrid(currentGridData); +}; + +void MainDialog::OnDifferentFiles(wxCommandEvent& event) +{ + differentFilesActive = !differentFilesActive; + updateViewFilterButtons(); + writeGrid(currentGridData); +}; + +void MainDialog::OnRightNewerFiles(wxCommandEvent& event) +{ + rightNewerFilesActive = !rightNewerFilesActive; + updateViewFilterButtons(); + writeGrid(currentGridData); +}; + +void MainDialog::OnRightOnlyFiles(wxCommandEvent& event) +{ + rightOnlyFilesActive = !rightOnlyFilesActive; + updateViewFilterButtons(); + writeGrid(currentGridData); +}; + +void MainDialog::OnEqualFiles(wxCommandEvent& event) +{ + equalFilesActive = !equalFilesActive; + updateViewFilterButtons(); + writeGrid(currentGridData); +}; + +void MainDialog::updateViewFilterButtons() +{ + if (leftOnlyFilesActive) + m_bpButton20->SetBitmapLabel(*GlobalResources::bitmapLeftOnly); + else + m_bpButton20->SetBitmapLabel(*GlobalResources::bitmapLeftOnlyDeact); + + if (leftNewerFilesActive) + m_bpButton21->SetBitmapLabel(*GlobalResources::bitmapLeftNewer); + else + m_bpButton21->SetBitmapLabel(*GlobalResources::bitmapLeftNewerDeact); + + if (differentFilesActive) + m_bpButton22->SetBitmapLabel(*GlobalResources::bitmapDifferent); + else + m_bpButton22->SetBitmapLabel(*GlobalResources::bitmapDifferentDeact); + + if (rightNewerFilesActive) + m_bpButton23->SetBitmapLabel(*GlobalResources::bitmapRightNewer); + else + m_bpButton23->SetBitmapLabel(*GlobalResources::bitmapRightNewerDeact); + + if (rightOnlyFilesActive) + m_bpButton24->SetBitmapLabel(*GlobalResources::bitmapRightOnly); + else + m_bpButton24->SetBitmapLabel(*GlobalResources::bitmapRightOnlyDeact); + + if (equalFilesActive) + m_bpButton25->SetBitmapLabel(*GlobalResources::bitmapEqual); + else + m_bpButton25->SetBitmapLabel(*GlobalResources::bitmapEqualDeact); +} + + +void MainDialog::updateFilterButton() +{ + if (filterIsActive) + { + m_bpButtonFilter->SetBitmapLabel(*GlobalResources::bitmapFilterOn); + m_bpButtonFilter->SetToolTip(_("Filter active: Press again to deactivate")); + } + else + { + m_bpButtonFilter->SetBitmapLabel(*GlobalResources::bitmapFilterOff); + m_bpButtonFilter->SetToolTip(_("Press button to activate filter")); + } +} + + +void MainDialog::OnCompare(wxCommandEvent &event) +{ + if (m_directoryPanel1->GetValue().IsEmpty() || m_directoryPanel2->GetValue().IsEmpty()) + { + wxMessageBox(_("Please select directories for both sides!"), _("Information")); + return; + } + m_statusBar1->SetStatusText(""); + m_statusBar1->SetStatusText("", 1); + m_statusBar1->SetStatusText("", 2); + m_statusBar1->SetStatusText("", 3); + m_statusBar1->SetStatusText("", 4); + + //check if directories exist if loaded by config file + if (!wxDirExists(m_directoryPanel1->GetValue())) + { + wxMessageBox(_("Directory on the left does not exist. Please select a new one!"), _("Warning"), wxICON_WARNING); + return; + } + else if (!wxDirExists(m_directoryPanel2->GetValue())) + { + wxMessageBox(_("Directory on the right does not exist. Please select a new one!"), _("Warning"), wxICON_WARNING); + return; + } + + wxBeginBusyCursor(); + + CompareVariant cmpVar = CompareByTimeAndSize; //assign a value to suppress compiler warning + if (m_radioBtnSizeDate->GetValue()) + cmpVar = CompareByTimeAndSize; + else if (m_radioBtnContent->GetValue()) + cmpVar = CompareByMD5; + else assert (false); + + try + { //class handling status display and error messages + CompareStatusUpdater statusUpdater(this, m_statusBar1); + cmpStatusUpdaterTmp = &statusUpdater; + + //unsigned int startTime3 = GetTickCount(); + FreeFileSync::getModelDiff(currentGridData, + FreeFileSync::getFormattedDirectoryName(m_directoryPanel1->GetValue()), + FreeFileSync::getFormattedDirectoryName(m_directoryPanel2->GetValue()), + cmpVar, + &statusUpdater); + //wxMessageBox(numberToWxString(unsigned(GetTickCount()) - startTime3)); + + + //filter currentGridData if option is set + if (filterIsActive) + FreeFileSync::filterCurrentGridData(currentGridData, includeFilter, excludeFilter); + + writeGrid(currentGridData); + + //once compare is finished enable the sync button + m_bpButtonSync->Enable(true); + + cmpStatusUpdaterTmp = 0; + } + catch (AbortThisProcess& theException) + { + //disable the sync button + m_bpButtonSync->Enable(false); + } + + wxEndBusyCursor(); +} + + +void MainDialog::OnAbortCompare(wxCommandEvent& event) +{ + if (cmpStatusUpdaterTmp) + cmpStatusUpdaterTmp->requestAbortion(); +} + + +inline +wxString MainDialog::evaluateCmpResult(const CompareFilesResult result, const bool selectedForSynchronization) +{ + if (selectedForSynchronization) + switch (result) + { + case FileOnLeftSideOnly: + return "<|"; + break; + case FileOnRightSideOnly: + return "|>"; + break; + case RightFileNewer: + return ">>"; + break; + case LeftFileNewer: + return "<<"; + break; + case FilesDifferent: + return "!="; + break; + case FilesEqual: + return "=="; + break; + default: + assert (false); + } + else return ConstFilteredOut; +} + + +void MainDialog::writeGrid(const FileCompareResult& gridData, bool useUI_GridCache) +{ + //unsigned int startTime = GetTickCount(); + + if (!useUI_GridCache) + { + mapFileModelToUI(currentUI_View, gridData); //update currentUI_View + updateStatusInformation(currentUI_View); //write status information for currentUI_View + } + + m_grid1->BeginBatch(); + m_grid2->BeginBatch(); + m_grid3->BeginBatch(); + + //all three grids retrieve their data directly from currentUI_View via a pointer!!! + //the only thing left to do is notify the grids to update their sizes (nr of rows), since this has to be communicated via messages by the grids + m_grid1->updateGridSizes(); + m_grid2->updateGridSizes(); + m_grid3->updateGridSizes(); + + //enlarge label width to display row numbers correctly + int nrOfRows = m_grid1->GetNumberRows(); + if (nrOfRows >= 1) + { + int nrOfDigits = int(floor(log10(double(nrOfRows)) + 1)); + m_grid1->SetRowLabelSize(nrOfDigits * 8 + 4); + m_grid2->SetRowLabelSize(nrOfDigits * 8 + 4); + } + + //hide sort direction indicator on UI grids + m_grid1->setSortMarker(-1); + m_grid2->setSortMarker(-1); + + + m_grid1->EndBatch(); + m_grid2->EndBatch(); + m_grid3->EndBatch(); + + //wxMessageBox(wxString("Benchmark: ") + numberToWxString(unsigned(GetTickCount()) - startTime) + " ms"); +} + + +void MainDialog::OnSync( wxCommandEvent& event ) +{ + //check if there are files/folders that can be synced + bool nothingToSync = true; + for (FileCompareResult::const_iterator i = currentGridData.begin(); i != currentGridData.end(); ++i) + if (i->cmpResult != FilesEqual) + { + nothingToSync = false; + break; + } + + if (nothingToSync) + { + wxMessageBox(_("Nothing to synchronize. Both directories seem to contain the same data!"), _("Information"), wxICON_WARNING); + return; + } + + SyncDialog* syncDlg = new SyncDialog(this); + if (syncDlg->ShowModal() == SyncDialog::StartSynchronizationProcess) + { + wxBeginBusyCursor(); + + m_statusBar1->SetStatusText(""); + m_statusBar1->SetStatusText("", 1); + m_statusBar1->SetStatusText("", 2); + m_statusBar1->SetStatusText("", 3); + m_statusBar1->SetStatusText("", 4); + + //unsigned int startTime = GetTickCount(); + synchronizeFolders(currentGridData, syncConfiguration); + //wxMessageBox(numberToWxString(unsigned(GetTickCount()) - startTime)); + + wxEndBusyCursor(); + } +} + + +void MainDialog::OnLeftGridDoubleClick(wxGridEvent& event) +{ //default + wxString command = "explorer " + FreeFileSync::getFormattedDirectoryName(m_directoryPanel1->GetValue()); + + if (event.GetRow() < int(currentUI_View.size())) + { + wxString filename = currentGridData[currentUI_View[event.GetRow()].linkToCurrentGridData].fileDescrLeft.filename; + + if (!filename.IsEmpty()) + command = "explorer /select," + filename; + } + wxExecute(command); +} + +void MainDialog::OnRightGridDoubleClick(wxGridEvent& event) +{ //default + wxString command = "explorer " + FreeFileSync::getFormattedDirectoryName(m_directoryPanel2->GetValue()); + + if (event.GetRow() < int(currentUI_View.size())) + { + wxString filename = currentGridData[currentUI_View[event.GetRow()].linkToCurrentGridData].fileDescrRight.filename; + + if (!filename.IsEmpty()) + command = "explorer /select," + filename; + } + wxExecute(command); +} + +//these two global variables are ONLY used for the sorting in the following methods +unsigned int currentSortColumn = 0; +bool sortAscending = true; +FileCompareResult* currentGridDataPtr = 0; + +inline +bool cmpString(const wxString& a, const wxString& b) +{ + if (a.IsEmpty()) + return false; // if a and b are empty: false, if a empty, b not empty: also false, since empty rows should be put below on grid + else if (b.IsEmpty()) + return true; // empty rows after filled rows: return true + + //if a and b not empty: + if (sortAscending) + return (a < b); + else return (a > b); +} + +inline +bool cmpLargeInt(const wxString& a, const wxString& b) +{ + //if a and b not empty: + bool result = true; + wxString tmpString; + mpz_t largeTempIntegerA; + mpz_t largeTempIntegerB; + mpz_init(largeTempIntegerA); + mpz_init(largeTempIntegerB); + mpz_set_str(largeTempIntegerA, a.c_str(), 10); + //return value should be checked: if function fails, largeTempIntegerA is not changed: no issue here + mpz_set_str(largeTempIntegerB, b.c_str(), 10); + //return value should be checked: if function fails, largeTempIntegerA is not changed: no issue here + if (sortAscending) + result = (mpz_cmp(largeTempIntegerA, largeTempIntegerB) < 0); // true if A < B + else + result = (mpz_cmp(largeTempIntegerA, largeTempIntegerB) > 0); // true if A > B + mpz_clear(largeTempIntegerA); + mpz_clear(largeTempIntegerB); + return result; +} + + +bool sortGridLeft(const UI_GridLine& a, const UI_GridLine& b) +{ + switch (currentSortColumn) + { + case 0: + return cmpString(a.leftFilename, b.leftFilename); + break; + case 1: + return cmpString(a.leftRelativePath, b.leftRelativePath); + break; + case 2: + ObjectType typeA = (*currentGridDataPtr)[a.linkToCurrentGridData].fileDescrLeft.objType; + ObjectType typeB = (*currentGridDataPtr)[b.linkToCurrentGridData].fileDescrLeft.objType; + + //presort types: first files, then directories then empty rows + if (typeA == IsNothing) + return false; //empty rows always last + else if (typeB == IsNothing) + return true; //empty rows always last + else if (typeA == IsDirectory) + return false; + else if (typeB == IsDirectory) + return true; + else //use unformatted filesizes and sort by size + return cmpLargeInt((*currentGridDataPtr)[a.linkToCurrentGridData].fileDescrLeft.fileSize, (*currentGridDataPtr)[b.linkToCurrentGridData].fileDescrLeft.fileSize); + + break; + case 3: + return cmpString(a.leftDate, b.leftDate); + break; + default: + assert(false); + } + return true; //dummy command +} + +bool sortGridRight(const UI_GridLine& a, const UI_GridLine& b) +{ + switch (currentSortColumn) + { + case 0: + return cmpString(a.rightFilename, b.rightFilename); + break; + case 1: + return cmpString(a.rightRelativePath, b.rightRelativePath); + break; + case 2: + ObjectType typeA = (*currentGridDataPtr)[a.linkToCurrentGridData].fileDescrRight.objType; + ObjectType typeB = (*currentGridDataPtr)[b.linkToCurrentGridData].fileDescrRight.objType; + + //presort types: first files, then directories then empty rows + if (typeA == IsNothing) + return false; //empty rows always last + else if (typeB == IsNothing) + return true; //empty rows always last + else if (typeA == IsDirectory) + return false; + else if (typeB == IsDirectory) + return true; + else //use unformatted filesizes and sort by size + return cmpLargeInt((*currentGridDataPtr)[a.linkToCurrentGridData].fileDescrRight.fileSize, (*currentGridDataPtr)[b.linkToCurrentGridData].fileDescrRight.fileSize); + + break; + case 3: + return cmpString(a.rightDate, b.rightDate); + break; + default: + assert(false); + } + return true; //dummy command +} + +void MainDialog::OnSortLeftGrid(wxGridEvent& event) +{ + static bool columnSortAscending[4] = {true, true, false, true}; + + currentSortColumn = event.GetCol(); + currentGridDataPtr = ¤tGridData; + if (0 <= currentSortColumn && currentSortColumn <= 3) + { + sortAscending = columnSortAscending[currentSortColumn]; + columnSortAscending[currentSortColumn] = !columnSortAscending[currentSortColumn]; + sort(currentUI_View.begin(), currentUI_View.end(), sortGridLeft); + writeGrid(currentGridData, true); //use UI buffer, no mapping from currentGridData to UI model again + //set sort direction indicator on UI + if (sortAscending) + m_grid1->setSortMarker(currentSortColumn, GlobalResources::bitmapSmallUp); + else + m_grid1->setSortMarker(currentSortColumn, GlobalResources::bitmapSmallDown); + m_grid2->setSortMarker(-1); + } + event.Skip(); +} + +void MainDialog::OnSortRightGrid(wxGridEvent& event) +{ + static bool columnSortAscending[4] = {true, true, false, true}; + + currentSortColumn = event.GetCol(); + currentGridDataPtr = ¤tGridData; + if (0 <= currentSortColumn && currentSortColumn <= 3) + { + sortAscending = columnSortAscending[currentSortColumn]; + columnSortAscending[currentSortColumn] = !columnSortAscending[currentSortColumn]; + sort(currentUI_View.begin(), currentUI_View.end(), sortGridRight); + writeGrid(currentGridData, true); + //set sort direction indicator on UI + m_grid1->setSortMarker(-1); + if (sortAscending) + m_grid2->setSortMarker(currentSortColumn, GlobalResources::bitmapSmallUp); + else + m_grid2->setSortMarker(currentSortColumn, GlobalResources::bitmapSmallDown); + } + event.Skip(); +} + + +void MainDialog::OnSwapDirs( wxCommandEvent& event ) +{ + //swap directory names + wxString tmp = m_directoryPanel1->GetValue(); + m_directoryPanel1->SetValue(m_directoryPanel2->GetValue()); + m_directoryPanel2->SetValue(tmp); + + //swap grid information + FreeFileSync::swapGrids(currentGridData); + writeGrid(currentGridData); +} + + +void MainDialog::synchronizeFolders(FileCompareResult& grid, const SyncConfiguration config) +{ + try + { //class handling status updates and error messages + SyncStatusUpdater statusUpdater(this, FreeFileSync::calcTotalBytesToTransfer(grid, config).get_d()); + + //start synchronization and return elements that were errorneous in "grid" + + //unsigned int startTime3 = GetTickCount(); + FreeFileSync::startSynchronizationProcess(grid, config, &statusUpdater, useRecycleBin); + //wxMessageBox(numberToWxString(unsigned(GetTickCount()) - startTime3)); + + + //display files that couldn't be processed + writeGrid(grid); + } + catch (AbortThisProcess& theException) + { + //disable the sync button + m_bpButtonSync->Enable(false); + } +} + +//this sorting method is currently NOT used +bool cmpGridSmallerThan(const UI_GridLine& a, const UI_GridLine& b) +{ + wxString cmpStringA; + wxString cmpStringB; + + for (int i = 0; i < 4; ++i) + { + switch (i) + { + case 0: + cmpStringA = a.leftRelativePath; + cmpStringB = b.leftRelativePath; + break; + case 1: + cmpStringA = a.leftFilename; + cmpStringB = b.leftFilename; + break; + case 2: + cmpStringA = a.rightRelativePath; + cmpStringB = b.rightRelativePath; + break; + case 3: + cmpStringA = a.rightFilename; + cmpStringB = b.rightFilename; + break; + default: + assert (false); + } + if (cmpStringA.IsEmpty()) + cmpStringA = '\255'; + if (cmpStringB.IsEmpty()) + cmpStringB = '\255'; + + if (cmpStringA != cmpStringB) + return (cmpStringA < cmpStringB); + } + return (false); +} + + +void MainDialog::updateStatusInformation(const UI_Grid& visibleGrid) +{ + unsigned int objectsOnLeftView = 0; + unsigned int objectsOnRightView = 0; + mpz_t filesizeLeftView, filesizeRightView, tmpInt; + mpz_init(filesizeLeftView); + mpz_init(filesizeRightView); + mpz_init(tmpInt); + + int returnValue = 0; + + for (UI_Grid::const_iterator i = visibleGrid.begin(); i != visibleGrid.end(); i++) + { + const FileCompareLine& refLine = currentGridData[i->linkToCurrentGridData]; + + //calculate total number of bytes for each sied + if (refLine.fileDescrLeft.objType != IsNothing) + { + mpz_set_ui(tmpInt, 0); + returnValue = mpz_set_str(tmpInt, refLine.fileDescrLeft.fileSize.c_str(), 10); + mpz_add(filesizeLeftView, filesizeLeftView, tmpInt); + assert (returnValue == 0); + + objectsOnLeftView++; + } + + if (refLine.fileDescrRight.objType != IsNothing) + { + mpz_set_ui(tmpInt, 0); + returnValue = mpz_set_str(tmpInt, refLine.fileDescrRight.fileSize.c_str(), 10); + mpz_add(filesizeRightView, filesizeRightView, tmpInt); + assert (returnValue == 0); + + objectsOnRightView++; + } + } + + //show status information on "root" level. This cannot be accomplished in writeGrid since filesizes are already formatted for display there + wxString objectsViewLeft = numberToWxString(objectsOnLeftView); + GlobalFunctions::includeNumberSeparator(objectsViewLeft); + if (objectsOnLeftView == 1) + m_statusBar1->SetStatusText(wxString(_("1 item on left, ")) + FreeFileSync::formatFilesizeToShortString(mpz_class(filesizeLeftView)), 0); + else + m_statusBar1->SetStatusText(objectsViewLeft + _(" items on left, ") + FreeFileSync::formatFilesizeToShortString(mpz_class(filesizeLeftView)), 0); + + + wxString objectsTotal = numberToWxString(currentGridData.size()); + GlobalFunctions::includeNumberSeparator(objectsTotal); + wxString objectsView = numberToWxString(visibleGrid.size()); + GlobalFunctions::includeNumberSeparator(objectsView); + if (currentGridData.size() == 1) + m_statusBar1->SetStatusText(objectsView + _(" of ") + objectsTotal + _(" row in view"), 2); + else + m_statusBar1->SetStatusText(objectsView + _(" of ") + objectsTotal + _(" rows in view"), 2); + + + wxString objectsViewRight = numberToWxString(objectsOnRightView); + GlobalFunctions::includeNumberSeparator(objectsViewRight); + if (objectsOnRightView == 1) + m_statusBar1->SetStatusText(wxString(_("1 item on right, ")) + FreeFileSync::formatFilesizeToShortString(mpz_class(filesizeRightView)), 4); + else + m_statusBar1->SetStatusText(objectsViewRight + _(" items on right, ") + FreeFileSync::formatFilesizeToShortString(mpz_class(filesizeRightView)), 4); + + //----------------------------------------------------- + mpz_clear(filesizeLeftView); + mpz_clear(filesizeRightView); + mpz_clear(tmpInt); +} + + +void MainDialog::mapFileModelToUI(UI_Grid& output, const FileCompareResult& fileCmpResult) +{ + output.clear(); + + UI_GridLine gridline; + unsigned int currentRow = 0; + wxString fileSize; //tmp string + for (FileCompareResult::const_iterator i = fileCmpResult.begin(); i != fileCmpResult.end(); i++, currentRow++) + { + //process UI filter settings + switch (i->cmpResult) + { + case FileOnLeftSideOnly: + if (!leftOnlyFilesActive) continue; + break; + case FileOnRightSideOnly: + if (!rightOnlyFilesActive) continue; + break; + case RightFileNewer: + if (!rightNewerFilesActive) continue; + break; + case LeftFileNewer: + if (!leftNewerFilesActive) continue; + break; + case FilesDifferent: + if (!differentFilesActive) continue; + break; + case FilesEqual: + if (!equalFilesActive) continue; + break; + default: + assert (false); + } + + //hide filtered row, if corresponding option is set + if (hideFiltered && !i->selectedForSynchronization) + continue; + + if (i->fileDescrLeft.objType == IsDirectory) + { + gridline.leftFilename = wxEmptyString; + gridline.leftRelativePath = i->fileDescrLeft.relFilename; + gridline.leftSize = _("<Directory>"); + } + else + { + gridline.leftFilename = i->fileDescrLeft.relFilename.AfterLast('\\'); + gridline.leftRelativePath = i->fileDescrLeft.relFilename.BeforeLast('\\'); + gridline.leftSize = GlobalFunctions::includeNumberSeparator(fileSize = i->fileDescrLeft.fileSize); + } + gridline.leftDate = i->fileDescrLeft.lastWriteTime; + + gridline.cmpResult = evaluateCmpResult(i->cmpResult, i->selectedForSynchronization); + gridline.linkToCurrentGridData = currentRow; + + if (i->fileDescrRight.objType == IsDirectory) + { + gridline.rightFilename = wxEmptyString; + gridline.rightRelativePath = i->fileDescrRight.relFilename; + gridline.rightSize = _("<Directory>"); + } + else + { + gridline.rightFilename = i->fileDescrRight.relFilename.AfterLast('\\'); + gridline.rightRelativePath = i->fileDescrRight.relFilename.BeforeLast('\\'); + gridline.rightSize = GlobalFunctions::includeNumberSeparator(fileSize = i->fileDescrRight.fileSize); + } + gridline.rightDate = i->fileDescrRight.lastWriteTime; + + output.push_back(gridline); + } + + //sorting is expensive: ca. 50% bigger runtime for large grids; unsorted doesn't look too bad, so it's disabled + // sort(output.begin(), output.end(), cmpGridSmallerThan); +} +//######################################################################################################## + + +void updateUI_Now() +{ + //process UI events and prevent application from "not responding" -> NO performance issue! + while (wxTheApp->Pending()) + wxTheApp->Dispatch(); +} + + +bool updateUI_IsAllowed() +{ + static wxLongLong lastExec = 0; + + wxLongLong newExec = wxGetLocalTimeMillis(); + + if (newExec - lastExec > 100) //perform ui updates not more often than necessary, 100 seems to be a good value with only a minimal performance loss + { + lastExec = newExec; + return true; + } + return false; +} + +//######################################################################################################## + + +CompareStatusUpdater::CompareStatusUpdater(MainDialog* dlg, wxStatusBar* mainWindowBar) : + mainDialog(dlg), + statusBar(mainWindowBar), + suppressUI_Errormessages(false), + numberOfScannedObjects(0) +{ + //prevent user input during "compare", do not disable maindialog since abort-button would also be disabled + //it's not nice, but works - even has the advantage that certain actions are still possible: exit, about.. + mainDialog->m_radioBtnSizeDate->Disable(); + mainDialog->m_radioBtnContent->Disable(); + mainDialog->m_bpButtonFilter->Disable(); + mainDialog->m_hyperlinkCfgFilter->Disable(); + mainDialog->m_checkBoxHideFilt->Disable(); + mainDialog->m_bpButtonSync->Disable(); + mainDialog->m_dirPicker1->Disable(); + mainDialog->m_dirPicker2->Disable(); + mainDialog->m_bpButtonSwap->Disable(); + mainDialog->m_bpButton20->Disable(); + mainDialog->m_bpButton21->Disable(); + mainDialog->m_bpButton22->Disable(); + mainDialog->m_bpButton23->Disable(); + mainDialog->m_bpButton24->Disable(); + mainDialog->m_bpButton25->Disable(); + mainDialog->m_panel1->Disable(); + mainDialog->m_panel2->Disable(); + mainDialog->m_panel3->Disable(); + + //show abort button + mainDialog->m_buttonAbort->Show(true); + mainDialog->m_bpButtonCompare->Show(false); + mainDialog->Layout(); + mainDialog->Refresh(); +} + +CompareStatusUpdater::~CompareStatusUpdater() +{ + //reenable complete main dialog + mainDialog->m_radioBtnSizeDate->Enable(); + mainDialog->m_radioBtnContent->Enable(); + mainDialog->m_bpButtonFilter->Enable(); + mainDialog->m_hyperlinkCfgFilter->Enable(); + mainDialog->m_checkBoxHideFilt->Enable(); + //mainDialog->m_bpButtonSync->Enable(); don't enable this one, this is up to OnCompare to handle its status + mainDialog->m_dirPicker1->Enable(); + mainDialog->m_dirPicker2->Enable(); + mainDialog->m_bpButtonSwap->Enable(); + mainDialog->m_bpButton20->Enable(); + mainDialog->m_bpButton21->Enable(); + mainDialog->m_bpButton22->Enable(); + mainDialog->m_bpButton23->Enable(); + mainDialog->m_bpButton24->Enable(); + mainDialog->m_bpButton25->Enable(); + mainDialog->m_panel1->Enable(); + mainDialog->m_panel2->Enable(); + mainDialog->m_panel3->Enable(); + + if (abortionRequested) + mainDialog->m_statusBar1->SetStatusText(mainDialog->m_statusBar1->GetStatusText(2) + " - " + _("Aborted!"), 2); + + mainDialog->m_buttonAbort->Show(false); + mainDialog->m_bpButtonCompare->Show(true); + mainDialog->Layout(); + mainDialog->Refresh(); +} + +void CompareStatusUpdater::updateStatus(const wxString& text) +{ + //not relevant for "compare"; it's sufficient to display the number of scanned files/folders +} + +inline +void CompareStatusUpdater::updateProgressIndicator(double number) +{ + numberOfScannedObjects+= int(number); //conversion is harmless, since number == 1 in case of "compare" +} + +int CompareStatusUpdater::reportError(const wxString& text) +{ + if (suppressUI_Errormessages) + return StatusUpdater::Continue; + + wxString errorMessage = text + _("\n\nContinue with next object, retry or abort comparison?"); + + ErrorDlg* errorDlg = new ErrorDlg(errorMessage, suppressUI_Errormessages); + + int rv = errorDlg->ShowModal(); + errorDlg->Destroy(); + + switch (rv) + { + case ErrorDlg::ContinueButtonPressed: + return StatusUpdater::Continue; + case ErrorDlg::RetryButtonPressed: + return StatusUpdater::Retry; + case ErrorDlg::AbortButtonPressed: + { + abortionRequested = true; + throw AbortThisProcess(); + } + default: + assert (false); + } + + return StatusUpdater::Continue; //dummy return value +} + + +inline +void CompareStatusUpdater::triggerUI_Refresh() +{ + if (abortionRequested) throw AbortThisProcess(); //abort can be triggered by syncStatusFrame + + if (updateUI_IsAllowed()) //test if specific time span between ui updates is over + { + statusBar->SetStatusText(wxString(_("Scanning files/folders: ")) + numberToWxString(numberOfScannedObjects), 2); + updateUI_Now(); + } +} +//######################################################################################################## + + +SyncStatusUpdater::SyncStatusUpdater(wxWindow* dlg, double gaugeTotalElements) : + suppressUI_Errormessages(false) +{ + syncStatusFrame = new SyncStatus(this, gaugeTotalElements, dlg); + syncStatusFrame->Show(); + updateUI_Now(); +} + +SyncStatusUpdater::~SyncStatusUpdater() +{ + if (abortionRequested) + syncStatusFrame->processHasFinished(_("Aborted!")); //enable okay and close events + else + syncStatusFrame->processHasFinished(_("Completed")); + + //print the results list + unsigned int failedItems = unhandledErrors.GetCount(); + wxString result; + if (failedItems) + { + result = wxString(_("Warning: Synchronization failed for ")) + numberToWxString(failedItems) + _(" item(s):\n\n"); + for (unsigned int j = 0; j < failedItems; ++j) + result+= unhandledErrors[j] + "\n"; + } + syncStatusFrame->setStatusText_NoUpdate(result); + syncStatusFrame->updateStatusDialogNow(); +} + + +inline +void SyncStatusUpdater::updateStatus(const wxString& text) +{ + syncStatusFrame->setStatusText_NoUpdate(text); +} + + +inline +void SyncStatusUpdater::updateProgressIndicator(double number) +{ + syncStatusFrame->incProgressIndicator_NoUpdate(number); +} + + +int SyncStatusUpdater::reportError(const wxString& text) +{ + if (suppressUI_Errormessages) + { + unhandledErrors.Add(text); + return StatusUpdater::Continue; + } + + wxString errorMessage = text + _("\n\nContinue with next object, retry or abort synchronization?"); + + ErrorDlg* errorDlg = new ErrorDlg(errorMessage, suppressUI_Errormessages); + + int rv = errorDlg->ShowModal(); + errorDlg->Destroy(); + + switch (rv) + { + case ErrorDlg::ContinueButtonPressed: + unhandledErrors.Add(text); + return StatusUpdater::Continue; + case ErrorDlg::RetryButtonPressed: + return StatusUpdater::Retry; + case ErrorDlg::AbortButtonPressed: + { + unhandledErrors.Add(text); + abortionRequested = true; + throw AbortThisProcess(); + } + default: + assert (false); + } + + return StatusUpdater::Continue; //dummy return value +} + + +void SyncStatusUpdater::triggerUI_Refresh() +{ + if (abortionRequested) + throw AbortThisProcess(); //abort can be triggered by syncStatusFrame + + if (updateUI_IsAllowed()) //test if specific time span between ui updates is over + { + syncStatusFrame->updateStatusDialogNow(); + } +} + + diff --git a/ui/MainDialog.h b/ui/MainDialog.h new file mode 100644 index 00000000..4c2486b9 --- /dev/null +++ b/ui/MainDialog.h @@ -0,0 +1,220 @@ +/*************************************************************** + * Name: FreeFileSyncMain.h + * Purpose: Defines Application Frame + * Author: ZenJu (zhnmju123@gmx.de) + * Created: 2008-07-16 + * Copyright: ZenJu () + * License: + **************************************************************/ + +#ifndef MAINDIALOG_H +#define MAINDIALOG_H + +#include "..\library\wxWidgets.h" +#include "GUI_Generated.h" +#include "..\FreeFileSync.h" + +#include "SyncDialog.h" +#include "SmallDialogs.h" +#include "Resources.h" + +using namespace std; + +//configure filter dialog +const int OkayButtonPressed = 25; + +const wxString ConstFilteredOut = "(-)"; + +struct UI_GridLine +{ + wxString leftFilename; + wxString leftRelativePath; + wxString leftSize; + wxString leftDate; + + wxString cmpResult; + + wxString rightFilename; + wxString rightRelativePath; + wxString rightSize; + wxString rightDate; + + unsigned int linkToCurrentGridData; //rownumber of corresponding row in currentGridData +}; +typedef vector<UI_GridLine> UI_Grid; + +bool updateUI_IsAllowed(); //test if a specific amount of time is over +void updateUI_Now(); //do the updating + + +extern int leadingPanel; + +class CompareStatusUpdater; + +class MainDialog : public GUI_Generated +{ +public: + MainDialog(wxFrame* frame); + ~MainDialog(); + +private: + friend class SyncDialog; + friend class FilterDlg; + friend class CompareStatusUpdater; + friend class SyncStatusUpdater; + + void readConfigurationFromHD(const wxString& filename); + void writeConfigurationToHD(const wxString& filename); + + void loadResourceFiles(); + void unloadResourceFiles(); + + void updateViewFilterButtons(); + void updateFilterButton(); + + void synchronizeFolders(FileCompareResult& grid, const SyncConfiguration config); + + static wxString evaluateCmpResult(const CompareFilesResult result, const bool selectedForSynchronization); + + //main method for putting gridData on UI: maps data respecting current view settings + void writeGrid(const FileCompareResult& gridData, bool useUI_GridCache = false); + + void mapFileModelToUI(UI_Grid& output, const FileCompareResult& fileCmpResult); + void updateStatusInformation(const UI_Grid& output); + + void filterRangeManual(int begin, int end, int leadingRow); + + //Events + void onGrid1access(wxEvent& event); + void onGrid2access(wxEvent& event); + void onGrid3access(wxEvent& event); + + void onGrid1ButtonEvent(wxKeyEvent& event); + void onGrid2ButtonEvent(wxKeyEvent& event); + + void OnEnterLeftDir(wxCommandEvent& event); + void OnEnterRightDir(wxCommandEvent& event); + void OnDirChangedPanel1(wxFileDirPickerEvent& event); + void OnDirChangedPanel2(wxFileDirPickerEvent& event); + void onFilesDroppedPanel1(wxDropFilesEvent& event); + void onFilesDroppedPanel2(wxDropFilesEvent& event); + + void OnGrid3SelectCell(wxGridEvent& event); + void OnGrid3SelectRange(wxGridRangeSelectEvent& event); + void OnGrid3LeftMouseUp(wxEvent& event); + void OnIdleToFilterManually(wxEvent& event); + + void OnLeftGridDoubleClick( wxGridEvent& event); + void OnRightGridDoubleClick(wxGridEvent& event); + void OnSortLeftGrid( wxGridEvent& event); + void OnSortRightGrid( wxGridEvent& event); + + void OnLeftOnlyFiles( wxCommandEvent& event); + void OnLeftNewerFiles( wxCommandEvent& event); + void OnDifferentFiles( wxCommandEvent& event); + void OnRightNewerFiles( wxCommandEvent& event); + void OnRightOnlyFiles( wxCommandEvent& event); + void OnEqualFiles( wxCommandEvent& event); + + void OnAbortCompare( wxCommandEvent& event); + void OnFilterButton( wxCommandEvent& event); + void OnHideFilteredButton( wxCommandEvent& event); + void OnConfigureFilter( wxHyperlinkEvent& event); + void OnShowHelpDialog( wxCommandEvent& event); + void OnSwapDirs( wxCommandEvent& event); + void OnChangeCompareVariant(wxCommandEvent& event); + void OnCompare( wxCommandEvent& event); + void OnSync( wxCommandEvent& event); + void OnClose( wxCloseEvent& event); + void OnQuit( wxCommandEvent& event); + void OnAbout( wxCommandEvent& event); + +//*********************************************** + //global application variables are stored here: + + //technical representation of grid-data + FileCompareResult currentGridData; + + //UI view of currentGridData + UI_Grid currentUI_View; + + //Synchronisation settings + SyncConfiguration syncConfiguration; + + //Filter setting + wxString includeFilter; + wxString excludeFilter; + bool hideFiltered; + bool filterIsActive; + + //UI View Filter settings + bool leftOnlyFilesActive; + bool leftNewerFilesActive; + bool differentFilesActive; + bool equalFilesActive; + bool rightNewerFilesActive; + bool rightOnlyFilesActive; + + //other options + bool useRecycleBin; //use Recycle bin when deleting or overwriting files while synchronizing + +//*********************************************** + + wxFrame* parent; + + //variables for manual filtering of m_grid3 + int selectedRangeBegin; + int selectedRangeEnd; + int selectionLead; + bool filteringPending; + + CompareStatusUpdater* cmpStatusUpdaterTmp; //used only by the abort button when comparing +}; + +//###################################################################################### + +//classes handling sync and compare error as well as status information + +class CompareStatusUpdater : public StatusUpdater +{ +public: + CompareStatusUpdater(MainDialog* dlg, wxStatusBar* mainWindowBar); + ~CompareStatusUpdater(); + + void updateStatus(const wxString& text); + void updateProgressIndicator(double number); + int reportError(const wxString& text); + + void triggerUI_Refresh(); + +private: + MainDialog* mainDialog; + wxStatusBar* statusBar; + bool suppressUI_Errormessages; + + unsigned int numberOfScannedObjects; +}; + +class SyncStatus; + +class SyncStatusUpdater : public StatusUpdater +{ +public: + SyncStatusUpdater(wxWindow* dlg, double gaugeTotalElements); + ~SyncStatusUpdater(); + + void updateStatus(const wxString& text); + void updateProgressIndicator(double number); + int reportError(const wxString& text); + + void triggerUI_Refresh(); + +private: + SyncStatus* syncStatusFrame; + + bool suppressUI_Errormessages; + wxArrayString unhandledErrors; //list of non-resolved errors +}; + + +#endif // MAINDIALOG_H diff --git a/ui/Resources.cpp b/ui/Resources.cpp new file mode 100644 index 00000000..d4db282c --- /dev/null +++ b/ui/Resources.cpp @@ -0,0 +1,111 @@ +#include "Resources.h" +#include <wx/wfstream.h> +#include <wx/zipstrm.h> +#include <wx/image.h> +#include <stdexcept> //for std::runtime_error + +map<wxString, wxBitmap*> GlobalResources::bitmapResource; + +wxBitmap* GlobalResources::bitmapLeftArrow = 0; +wxBitmap* GlobalResources::bitmapStartSync = 0; +wxBitmap* GlobalResources::bitmapRightArrow = 0; +wxBitmap* GlobalResources::bitmapDelete = 0; +wxBitmap* GlobalResources::bitmapEmail = 0; +wxBitmap* GlobalResources::bitmapAbout = 0; +wxBitmap* GlobalResources::bitmapWebsite = 0; +wxBitmap* GlobalResources::bitmapExit = 0; +wxBitmap* GlobalResources::bitmapSync = 0; +wxBitmap* GlobalResources::bitmapCompare = 0; +wxBitmap* GlobalResources::bitmapSyncDisabled = 0; +wxBitmap* GlobalResources::bitmapSwap = 0; +wxBitmap* GlobalResources::bitmapHelp = 0; +wxBitmap* GlobalResources::bitmapLeftOnly = 0; +wxBitmap* GlobalResources::bitmapLeftNewer = 0; +wxBitmap* GlobalResources::bitmapDifferent = 0; +wxBitmap* GlobalResources::bitmapRightNewer = 0; +wxBitmap* GlobalResources::bitmapRightOnly = 0; +wxBitmap* GlobalResources::bitmapLeftOnlyDeact = 0; +wxBitmap* GlobalResources::bitmapLeftNewerDeact = 0; +wxBitmap* GlobalResources::bitmapDifferentDeact = 0; +wxBitmap* GlobalResources::bitmapRightNewerDeact = 0; +wxBitmap* GlobalResources::bitmapRightOnlyDeact = 0; +wxBitmap* GlobalResources::bitmapEqual = 0; +wxBitmap* GlobalResources::bitmapEqualDeact = 0; +wxBitmap* GlobalResources::bitmapInclude = 0; +wxBitmap* GlobalResources::bitmapExclude = 0; +wxBitmap* GlobalResources::bitmapFilterOn = 0; +wxBitmap* GlobalResources::bitmapFilterOff = 0; +wxBitmap* GlobalResources::bitmapWarning = 0; +wxBitmap* GlobalResources::bitmapSmallUp = 0; +wxBitmap* GlobalResources::bitmapSmallDown = 0; + +wxAnimation* GlobalResources::animationMoney = 0; + + +void GlobalResources::loadResourceFiles() +{ + //map, allocate and initialize pictures + bitmapResource["left arrow.png"] = (bitmapLeftArrow = new wxBitmap(wxNullBitmap)); + bitmapResource["start sync.png"] = (bitmapStartSync = new wxBitmap(wxNullBitmap)); + bitmapResource["right arrow.png"] = (bitmapRightArrow = new wxBitmap(wxNullBitmap)); + bitmapResource["delete.png"] = (bitmapDelete = new wxBitmap(wxNullBitmap)); + bitmapResource["email.png"] = (bitmapEmail = new wxBitmap(wxNullBitmap)); + bitmapResource["about.png"] = (bitmapAbout = new wxBitmap(wxNullBitmap)); + bitmapResource["website.png"] = (bitmapWebsite = new wxBitmap(wxNullBitmap)); + bitmapResource["exit.png"] = (bitmapExit = new wxBitmap(wxNullBitmap)); + bitmapResource["sync.png"] = (bitmapSync = new wxBitmap(wxNullBitmap)); + bitmapResource["compare.png"] = (bitmapCompare = new wxBitmap(wxNullBitmap)); + bitmapResource["sync disabled.png"] = (bitmapSyncDisabled = new wxBitmap(wxNullBitmap)); + bitmapResource["swap.png"] = (bitmapSwap = new wxBitmap(wxNullBitmap)); + bitmapResource["help.png"] = (bitmapHelp = new wxBitmap(wxNullBitmap)); + bitmapResource["leftOnly.png"] = (bitmapLeftOnly = new wxBitmap(wxNullBitmap)); + bitmapResource["leftNewer.png"] = (bitmapLeftNewer = new wxBitmap(wxNullBitmap)); + bitmapResource["different.png"] = (bitmapDifferent = new wxBitmap(wxNullBitmap)); + bitmapResource["rightNewer.png"] = (bitmapRightNewer = new wxBitmap(wxNullBitmap)); + bitmapResource["rightOnly.png"] = (bitmapRightOnly = new wxBitmap(wxNullBitmap)); + bitmapResource["leftOnlyDeact.png"] = (bitmapLeftOnlyDeact = new wxBitmap(wxNullBitmap)); + bitmapResource["leftNewerDeact.png"] = (bitmapLeftNewerDeact = new wxBitmap(wxNullBitmap)); + bitmapResource["differentDeact.png"] = (bitmapDifferentDeact = new wxBitmap(wxNullBitmap)); + bitmapResource["rightNewerDeact.png"] = (bitmapRightNewerDeact = new wxBitmap(wxNullBitmap)); + bitmapResource["rightOnlyDeact.png"] = (bitmapRightOnlyDeact = new wxBitmap(wxNullBitmap)); + bitmapResource["equal.png"] = (bitmapEqual = new wxBitmap(wxNullBitmap)); + bitmapResource["equalDeact.png"] = (bitmapEqualDeact = new wxBitmap(wxNullBitmap)); + bitmapResource["include.png"] = (bitmapInclude = new wxBitmap(wxNullBitmap)); + bitmapResource["exclude.png"] = (bitmapExclude = new wxBitmap(wxNullBitmap)); + bitmapResource["filter active.png"] = (bitmapFilterOn = new wxBitmap(wxNullBitmap)); + bitmapResource["filter not active.png"] = (bitmapFilterOff = new wxBitmap(wxNullBitmap)); + bitmapResource["Warning.png"] = (bitmapWarning = new wxBitmap(wxNullBitmap)); + bitmapResource["small arrow up.png"] = (bitmapSmallUp = new wxBitmap(wxNullBitmap)); + bitmapResource["small arrow down.png"] = (bitmapSmallDown = new wxBitmap(wxNullBitmap)); + + animationMoney = new wxAnimation(wxNullAnimation); + + wxFileInputStream input("Resources.dat"); + if (!input.IsOk()) throw runtime_error(_("Unable to load Resources.dat!")); + + wxZipInputStream resourceFile(input); + + wxZipEntry* entry; + map<wxString, wxBitmap*>::iterator bmp; + while (entry = resourceFile.GetNextEntry()) + { + wxString name = entry->GetName(); + + //just to be sure: search if entry is available in map + if ((bmp = bitmapResource.find(name)) != bitmapResource.end()) + *(bmp->second) = wxBitmap(wxImage(resourceFile, wxBITMAP_TYPE_PNG)); + } + + animationMoney->LoadFile("Resources.a01"); +} + + +void GlobalResources::unloadResourceFiles() +{ + //free bitmap resources + for (map<wxString, wxBitmap*>::iterator i = bitmapResource.begin(); i != bitmapResource.end(); ++i) + delete i->second; + + //free other resources + delete animationMoney; +} diff --git a/ui/Resources.h b/ui/Resources.h new file mode 100644 index 00000000..fba26f03 --- /dev/null +++ b/ui/Resources.h @@ -0,0 +1,59 @@ +#ifndef RESOURCES_H_INCLUDED +#define RESOURCES_H_INCLUDED + +#include <wx/bitmap.h> +#include <wx/animate.h> +#include <wx/string.h> +#include <map> + +using namespace std; + +class GlobalResources +{ +public: + + static void loadResourceFiles(); + static void unloadResourceFiles(); + + static wxBitmap* bitmapLeftArrow; + static wxBitmap* bitmapStartSync; + static wxBitmap* bitmapRightArrow; + static wxBitmap* bitmapDelete; + static wxBitmap* bitmapEmail; + static wxBitmap* bitmapAbout; + static wxBitmap* bitmapWebsite; + static wxBitmap* bitmapExit; + static wxBitmap* bitmapSync; + static wxBitmap* bitmapCompare; + static wxBitmap* bitmapSyncDisabled; + static wxBitmap* bitmapSwap; + static wxBitmap* bitmapHelp; + static wxBitmap* bitmapLeftOnly; + static wxBitmap* bitmapLeftNewer; + static wxBitmap* bitmapDifferent; + static wxBitmap* bitmapRightNewer; + static wxBitmap* bitmapRightOnly; + static wxBitmap* bitmapLeftOnlyDeact; + static wxBitmap* bitmapLeftNewerDeact; + static wxBitmap* bitmapDifferentDeact; + static wxBitmap* bitmapRightNewerDeact; + static wxBitmap* bitmapRightOnlyDeact; + static wxBitmap* bitmapEqual; + static wxBitmap* bitmapEqualDeact; + static wxBitmap* bitmapInclude; + static wxBitmap* bitmapExclude; + static wxBitmap* bitmapFilterOn; + static wxBitmap* bitmapFilterOff; + static wxBitmap* bitmapWarning; + static wxBitmap* bitmapSmallUp; + static wxBitmap* bitmapSmallDown; + + static wxAnimation* animationMoney; + +private: + //resource mapping + static map<wxString, wxBitmap*> bitmapResource; +}; + + +#endif // RESOURCES_H_INCLUDED diff --git a/ui/SmallDialogs.cpp b/ui/SmallDialogs.cpp new file mode 100644 index 00000000..f6d29864 --- /dev/null +++ b/ui/SmallDialogs.cpp @@ -0,0 +1,229 @@ +#include "SmallDialogs.h" +#include "..\library\globalFunctions.h" + +AboutDlg::AboutDlg(MainDialog* window) : AboutDlgGenerated(window) +{ + m_bitmap9->SetBitmap(*GlobalResources::bitmapWebsite); + m_bitmap10->SetBitmap(*GlobalResources::bitmapEmail); + + m_animationControl1->SetAnimation(*GlobalResources::animationMoney); + m_animationControl1->Play(); + + //build + wxString build = wxString(_("(Build: ")) + __TDATE__ + ")"; + m_build->SetLabel(build); +} + +AboutDlg::~AboutDlg() {} + +void AboutDlg::OnClose(wxCloseEvent& event) +{ + Destroy(); +} + +void AboutDlg::OnOK(wxCommandEvent& event) +{ + Destroy(); +} +//######################################################################################## + + +HelpDlg::HelpDlg(MainDialog* window) : HelpDlgGenerated(window) {} + +HelpDlg::~HelpDlg() {} + + +void HelpDlg::OnClose(wxCloseEvent& event) +{ + Destroy(); +} + + +void HelpDlg::OnOK(wxCommandEvent& event) +{ + Destroy(); +} +//######################################################################################## + + +FilterDlg::FilterDlg(MainDialog* window) : FilterDlgGenerated(window), mainDialog(window) +{ + + m_bitmap8->SetBitmap(*GlobalResources::bitmapInclude); + m_bitmap9->SetBitmap(*GlobalResources::bitmapExclude); + + m_textCtrlInclude->SetValue(mainDialog->includeFilter); + m_textCtrlExclude->SetValue(mainDialog->excludeFilter); +} + +FilterDlg::~FilterDlg() {} + +void FilterDlg::OnClose(wxCloseEvent& event) +{ + EndModal(0); +} + +void FilterDlg::OnOK(wxCommandEvent& event) +{ + //only if user presses ApplyFilter, he wants the changes to be committed + mainDialog->includeFilter = m_textCtrlInclude->GetValue(); + mainDialog->excludeFilter = m_textCtrlExclude->GetValue(); + + //when leaving dialog: filter and redraw grid, if filter is active + EndModal(OkayButtonPressed); +} + + +void FilterDlg::OnDefault(wxCommandEvent& event) +{ + m_textCtrlInclude->SetValue("*"); + m_textCtrlExclude->SetValue(""); + + //changes to mainDialog are only committed when the OK button is pressed + event.Skip(); +} +//######################################################################################## + + +ErrorDlg::ErrorDlg(const wxString messageText, bool& suppressErrormessages) : + ErrorDlgGenerated(0), + suppressErrors(suppressErrormessages) +{ + m_bitmap10->SetBitmap(*GlobalResources::bitmapWarning); + m_textCtrl8->SetValue(messageText); +} + +ErrorDlg::~ErrorDlg() {} + +void ErrorDlg::OnClose(wxCloseEvent& event) +{ + //suppressErrors = m_checkBoxSuppress->GetValue(); -> not needed here + EndModal(AbortButtonPressed); +} + +void ErrorDlg::OnContinue(wxCommandEvent& event) +{ + suppressErrors = m_checkBoxSuppress->GetValue(); + EndModal(ContinueButtonPressed); +} + +void ErrorDlg::OnRetry(wxCommandEvent& event) +{ + //suppressErrors = m_checkBoxSuppress->GetValue(); -> not needed here + EndModal(RetryButtonPressed); +} + +void ErrorDlg::OnAbort(wxCommandEvent& event) +{ + //suppressErrors = m_checkBoxSuppress->GetValue(); -> not needed here + EndModal(AbortButtonPressed); +} +//######################################################################################## + + +SyncStatus::SyncStatus(StatusUpdater* updater, double gaugeTotalElements, wxWindow* parentWindow) : + SyncStatusGenerated(parentWindow), + currentStatusUpdater(updater), + windowToDis(parentWindow), + currentProcessIsRunning(true), + numberOfProcessedObjects(0) +{ + //initialize gauge + m_gauge1->SetRange(50000); + m_gauge1->SetValue(0); + + resetGauge(gaugeTotalElements); + + if (windowToDis) //disable (main) window while this status dialog is shown + windowToDis->Enable(false); +} + + +SyncStatus::~SyncStatus() +{ + if (windowToDis) + windowToDis->Enable(true); +} + + +void SyncStatus::resetGauge(double totalNrOfElements) +{ + currentElements = 0; + totalElements = totalNrOfElements; + + if (totalElements != 0) + scalingFactor = 50000 / totalElements; //let's normalize to 50000 + else + scalingFactor = 0; +} + + +void SyncStatus::incProgressIndicator_NoUpdate(double number) +{ + currentElements+= number; + numberOfProcessedObjects++; +} + + +void SyncStatus::setStatusText_NoUpdate(const wxString& text) +{ + currentStatusText = text; +} + + +void SyncStatus::updateStatusDialogNow() +{ + //progress indicator + m_gauge1->SetValue(int(currentElements * scalingFactor)); + + //status text + m_textCtrlInfo->SetValue(currentStatusText); + + //processed objects + m_staticTextProcessedObj->SetLabel(GlobalFunctions::numberToWxString(numberOfProcessedObjects)); + + //remaining bytes left for copy + m_staticTextBytesCurrent->SetLabel(FreeFileSync::formatFilesizeToShortString(mpz_class(currentElements))); + + static double totalElementsLast = -1; + if (totalElementsLast != totalElements) + { + totalElementsLast = totalElements; + m_staticTextBytesTotal->SetLabel(FreeFileSync::formatFilesizeToShortString(mpz_class(totalElements))); + } + + //do the ui update + updateUI_Now(); +} + + +void SyncStatus::processHasFinished(const wxString& finalStatusText) //essential to call this in StatusUpdater derived class destructor +{ //at the LATEST(!) to prevent access to currentStatusUpdater + currentProcessIsRunning = false; //enable okay and close events + + m_staticTextStatus->SetLabel(finalStatusText); + m_buttonAbort->Hide(); + m_buttonOK->Show(); + + updateStatusDialogNow(); //keep this sequence to avoid display distortion, if e.g. only 1 item is sync'ed + Layout(); // +} + + +void SyncStatus::OnOkay(wxCommandEvent& event) +{ + if (!currentProcessIsRunning) Destroy(); +} + + +void SyncStatus::OnAbort(wxCommandEvent& event) +{ + if (currentProcessIsRunning) currentStatusUpdater->requestAbortion(); +} + + +void SyncStatus::OnClose(wxCloseEvent& event) +{ + if (!currentProcessIsRunning) Destroy(); +} + diff --git a/ui/SmallDialogs.h b/ui/SmallDialogs.h new file mode 100644 index 00000000..77da9eac --- /dev/null +++ b/ui/SmallDialogs.h @@ -0,0 +1,99 @@ +#ifndef SMALLDIALOGS_H_INCLUDED +#define SMALLDIALOGS_H_INCLUDED + +#include "MainDialog.h" + +class MainDialog; + +class AboutDlg : public AboutDlgGenerated +{ +public: + AboutDlg(MainDialog* window); + ~AboutDlg(); + +private: + void OnClose(wxCloseEvent& event); + void AboutDlg::OnOK(wxCommandEvent& event); +}; + + +class HelpDlg : public HelpDlgGenerated +{ +public: + HelpDlg(MainDialog* window); + ~HelpDlg(); + +private: + void OnClose(wxCloseEvent& event); + void OnOK(wxCommandEvent& event); +}; + + +class FilterDlg : public FilterDlgGenerated +{ +public: + FilterDlg(MainDialog* window); + ~FilterDlg(); + +private: + void OnDefault(wxCommandEvent& event); + void OnOK(wxCommandEvent& event); + void OnClose(wxCloseEvent& event); + + MainDialog* mainDialog; +}; + + +class ErrorDlg : public ErrorDlgGenerated +{ +public: + ErrorDlg(const wxString messageText, bool& suppressErrormessages); + ~ErrorDlg(); + + static const int ContinueButtonPressed = 35; + static const int RetryButtonPressed = 45; + static const int AbortButtonPressed = 55; + +private: + void OnClose(wxCloseEvent& event); + void OnContinue(wxCommandEvent& event); + void OnRetry(wxCommandEvent& event); + void OnAbort(wxCommandEvent& event); + + bool& suppressErrors; +}; + + +class SyncStatus : public SyncStatusGenerated +{ +public: + SyncStatus(StatusUpdater* updater, double gaugeTotalElements, wxWindow* parentWindow = 0); + ~SyncStatus(); + + void resetGauge(double totalNrOfElements); + void incProgressIndicator_NoUpdate(double number); + void setStatusText_NoUpdate(const wxString& text); + void updateStatusDialogNow(); + + void processHasFinished(const wxString& finalStatusText); //essential to call this in StatusUpdater derived class destructor at the LATEST(!) to prevent access to currentStatusUpdater + +private: + void OnOkay(wxCommandEvent& event); + void OnAbort(wxCommandEvent& event); + void OnClose(wxCloseEvent& event); + + StatusUpdater* currentStatusUpdater; + wxWindow* windowToDis; + bool currentProcessIsRunning; + + //gauge variables + double totalElements; //each element represents one byte for proper progress indicator scaling + double currentElements; + double scalingFactor; //nr of elements has to be normalized to smaller nr. because of range of int limitation + + wxString currentStatusText; + unsigned int numberOfProcessedObjects; +}; + + +#endif // SMALLDIALOGS_H_INCLUDED diff --git a/ui/SyncDialog.cpp b/ui/SyncDialog.cpp new file mode 100644 index 00000000..2353e313 --- /dev/null +++ b/ui/SyncDialog.cpp @@ -0,0 +1,250 @@ +#include "SyncDialog.h" +#include "..\library\globalfunctions.h" + +SyncDialog::SyncDialog(MainDialog* window) + : SyncDialogGenerated(window), mainDialog(window) +{ + //make working copy of mainDialog->syncConfiguration and recycler setting + localSyncConfiguration = mainDialog->syncConfiguration; + + m_checkBoxUseRecycler->SetValue(mainDialog->useRecycleBin); + + //set icons for this dialog + m_bpButton18->SetBitmapLabel(*GlobalResources::bitmapStartSync); + m_bitmap13->SetBitmap(*GlobalResources::bitmapLeftOnlyDeact); + m_bitmap14->SetBitmap(*GlobalResources::bitmapRightOnlyDeact); + m_bitmap15->SetBitmap(*GlobalResources::bitmapLeftNewerDeact); + m_bitmap16->SetBitmap(*GlobalResources::bitmapRightNewerDeact); + m_bitmap17->SetBitmap(*GlobalResources::bitmapDifferentDeact); + + //set sync config icons + updateConfigIcons(); + + //set radiobutton + if (localSyncConfiguration.exLeftSideOnly == SyncDirRight && + localSyncConfiguration.exRightSideOnly == SyncDirRight && + localSyncConfiguration.leftNewer == SyncDirRight && + localSyncConfiguration.rightNewer == SyncDirRight && + localSyncConfiguration.different == SyncDirRight) + m_radioBtn1->SetValue(true); //one way -> + + else if (localSyncConfiguration.exLeftSideOnly == SyncDirRight && + localSyncConfiguration.exRightSideOnly == SyncDirLeft && + localSyncConfiguration.leftNewer == SyncDirRight && + localSyncConfiguration.rightNewer == SyncDirLeft && + localSyncConfiguration.different == SyncDirNone) + m_radioBtn2->SetValue(true); //two way <-> + + else + m_radioBtn3->SetValue(true); //other +} + +//################################################################################################################# + +SyncDialog::~SyncDialog() {} + + +void SyncDialog::updateConfigIcons() +{ + if (localSyncConfiguration.exLeftSideOnly == SyncDirRight) + { + m_bpButton5->SetBitmapLabel(*GlobalResources::bitmapRightArrow); + m_bpButton5->SetToolTip(_("Copy from left to right")); + } + else if (localSyncConfiguration.exLeftSideOnly == SyncDirLeft) + { + m_bpButton5->SetBitmapLabel(*GlobalResources::bitmapDelete); + m_bpButton5->SetToolTip(_("Delete files existing on left side only")); + } + else if (localSyncConfiguration.exLeftSideOnly == SyncDirNone) + { + m_bpButton5->SetBitmapLabel(wxNullBitmap); + m_bpButton5->SetToolTip(_("Do nothing")); + } + + if (localSyncConfiguration.exRightSideOnly == SyncDirRight) + { + m_bpButton6->SetBitmapLabel(*GlobalResources::bitmapDelete); + m_bpButton6->SetToolTip(_("Delete files existing on right side only")); + } + else if (localSyncConfiguration.exRightSideOnly == SyncDirLeft) + { + m_bpButton6->SetBitmapLabel(*GlobalResources::bitmapLeftArrow); + m_bpButton6->SetToolTip(_("Copy from right to left")); + } + else if (localSyncConfiguration.exRightSideOnly == SyncDirNone) + { + m_bpButton6->SetBitmapLabel(wxNullBitmap); + m_bpButton6->SetToolTip(_("Do nothing")); + } + + if (localSyncConfiguration.leftNewer == SyncDirRight) + { + m_bpButton7->SetBitmapLabel(*GlobalResources::bitmapRightArrow); + m_bpButton7->SetToolTip(_("Copy from left to right overwriting")); + } + else if (localSyncConfiguration.leftNewer == SyncDirLeft) + { + m_bpButton7->SetBitmapLabel(*GlobalResources::bitmapLeftArrow); + m_bpButton7->SetToolTip(_("Copy from right to left overwriting")); + } + else if (localSyncConfiguration.leftNewer == SyncDirNone) + { + m_bpButton7->SetBitmapLabel(wxNullBitmap); + m_bpButton7->SetToolTip(_("Do nothing")); + } + + if (localSyncConfiguration.rightNewer == SyncDirRight) + { + m_bpButton8->SetBitmapLabel(*GlobalResources::bitmapRightArrow); + m_bpButton8->SetToolTip(_("Copy from left to right overwriting")); + } + else if (localSyncConfiguration.rightNewer == SyncDirLeft) + { + m_bpButton8->SetBitmapLabel(*GlobalResources::bitmapLeftArrow); + m_bpButton8->SetToolTip(_("Copy from right to left overwriting")); + } + else if (localSyncConfiguration.rightNewer == SyncDirNone) + { + m_bpButton8->SetBitmapLabel(wxNullBitmap); + m_bpButton8->SetToolTip(_("Do nothing")); + } + + if (localSyncConfiguration.different == SyncDirRight) + { + m_bpButton9->SetBitmapLabel(*GlobalResources::bitmapRightArrow); + m_bpButton9->SetToolTip(_("Copy from left to right overwriting")); + } + else if (localSyncConfiguration.different == SyncDirLeft) + { + m_bpButton9->SetBitmapLabel(*GlobalResources::bitmapLeftArrow); + m_bpButton9->SetToolTip(_("Copy from right to left overwriting")); + } + else if (localSyncConfiguration.different == SyncDirNone) + { + m_bpButton9->SetBitmapLabel(wxNullBitmap); + m_bpButton9->SetToolTip(_("Do nothing")); + } + + //update preview of bytes to be transferred: + m_textCtrl5->SetValue(FreeFileSync::formatFilesizeToShortString(FreeFileSync::calcTotalBytesToTransfer(mainDialog->currentGridData, localSyncConfiguration))); +} + + +void SyncDialog::OnClose(wxCloseEvent& event) +{ + EndModal(0); +} + +void SyncDialog::OnBack(wxCommandEvent& event) +{ + //write configuration to main dialog + mainDialog->syncConfiguration = localSyncConfiguration; + mainDialog->useRecycleBin = m_checkBoxUseRecycler->GetValue(); + + EndModal(0); +} + +void SyncDialog::OnStartSync(wxCommandEvent& event) +{ + //write configuration to main dialog + mainDialog->syncConfiguration = localSyncConfiguration; + mainDialog->useRecycleBin = m_checkBoxUseRecycler->GetValue(); + + EndModal(StartSynchronizationProcess); +} + + +void SyncDialog::OnSelectRecycleBin(wxCommandEvent& event) +{ + if (event.IsChecked()) + { + if (!FreeFileSync::recycleBinExists()) + { + wxMessageBox(_("It was not possible to gain access to Recycle Bin!\n\nIt's likely that you are not using Windows XP. (Probably Vista)\nIf you want this feature included, please contact the author. :)"), _("Error") , wxOK | wxICON_ERROR); + m_checkBoxUseRecycler->SetValue(false); + } + } +} + + +void SyncDialog::OnSyncLeftToRight( wxCommandEvent& event ) +{ + localSyncConfiguration.exLeftSideOnly = SyncDirRight; + localSyncConfiguration.exRightSideOnly = SyncDirRight; + localSyncConfiguration.leftNewer = SyncDirRight; + localSyncConfiguration.rightNewer = SyncDirRight; + localSyncConfiguration.different = SyncDirRight; + + updateConfigIcons(); + + //if event is triggered by button + m_radioBtn1->SetValue(true); +} + + +void SyncDialog::OnSyncBothSides( wxCommandEvent& event ) +{ + localSyncConfiguration.exLeftSideOnly = SyncDirRight; + localSyncConfiguration.exRightSideOnly = SyncDirLeft; + localSyncConfiguration.leftNewer = SyncDirRight; + localSyncConfiguration.rightNewer = SyncDirLeft; + localSyncConfiguration.different = SyncDirNone; + + updateConfigIcons(); + //if event is triggered by button + m_radioBtn2->SetValue(true); +} + + +void toggleSyncDirection(SyncDirection& current) +{ + if (current == SyncDirRight) + current = SyncDirLeft; + else if (current == SyncDirLeft) + current = SyncDirNone; + else if (current== SyncDirNone) + current = SyncDirRight; + else + assert (false); +} + +void SyncDialog::OnExLeftSideOnly( wxCommandEvent& event ) +{ + toggleSyncDirection(localSyncConfiguration.exLeftSideOnly); + updateConfigIcons(); + //set custom config button + m_radioBtn3->SetValue(true); +} + +void SyncDialog::OnExRightSideOnly( wxCommandEvent& event ) +{ + toggleSyncDirection(localSyncConfiguration.exRightSideOnly); + updateConfigIcons(); + //set custom config button + m_radioBtn3->SetValue(true); +} + +void SyncDialog::OnLeftNewer( wxCommandEvent& event ) +{ + toggleSyncDirection(localSyncConfiguration.leftNewer); + updateConfigIcons(); + //set custom config button + m_radioBtn3->SetValue(true); +} + +void SyncDialog::OnRightNewer( wxCommandEvent& event ) +{ + toggleSyncDirection(localSyncConfiguration.rightNewer); + updateConfigIcons(); + //set custom config button + m_radioBtn3->SetValue(true); +} + +void SyncDialog::OnDifferent( wxCommandEvent& event ) +{ + toggleSyncDirection(localSyncConfiguration.different); + updateConfigIcons(); + //set custom config button + m_radioBtn3->SetValue(true); +} diff --git a/ui/SyncDialog.h b/ui/SyncDialog.h new file mode 100644 index 00000000..a743279a --- /dev/null +++ b/ui/SyncDialog.h @@ -0,0 +1,40 @@ +#ifndef SYNCDIALOG_H_INCLUDED +#define SYNCDIALOG_H_INCLUDED + +#include "MainDialog.h" + +class MainDialog; + +class SyncDialog: public SyncDialogGenerated +{ +public: + SyncDialog(MainDialog* window); + ~SyncDialog(); + + static const int StartSynchronizationProcess = 15; + +private: + //temporal copy of maindialog->syncConfiguration + SyncConfiguration localSyncConfiguration; + + void updateConfigIcons(); + + void OnSyncLeftToRight( wxCommandEvent& event ); + void OnSyncBothSides( wxCommandEvent& event ); + + void OnExLeftSideOnly( wxCommandEvent& event ); + void OnExRightSideOnly( wxCommandEvent& event ); + void OnLeftNewer( wxCommandEvent& event ); + void OnRightNewer( wxCommandEvent& event ); + void OnDifferent( wxCommandEvent& event ); + + void OnStartSync(wxCommandEvent& event); + void OnClose(wxCloseEvent& event); + void OnBack(wxCommandEvent& event); + + void OnSelectRecycleBin(wxCommandEvent& event); + + MainDialog* mainDialog; +}; + +#endif // SYNCDIALOG_H_INCLUDED |