mirror of
https://github.com/leozide/leocad
synced 2024-11-17 07:47:55 +01:00
496 lines
14 KiB
C++
496 lines
14 KiB
C++
#include "lc_global.h"
|
|
#include "LeoCAD.h"
|
|
|
|
#include "MainFrm.h"
|
|
#include "CADDoc.h"
|
|
#include "CADView.h"
|
|
#include <wininet.h>
|
|
#include <direct.h>
|
|
#include <process.h>
|
|
#include <dbghelp.h>
|
|
#include "project.h"
|
|
#include "globals.h"
|
|
#include "system.h"
|
|
#include "pieceinf.h"
|
|
#include "mainwnd.h"
|
|
#include "lc_library.h"
|
|
#include "keyboard.h"
|
|
#include "lc_application.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
static HANDLE __hStdOut = NULL;
|
|
|
|
// Use wprintf like TRACE0, TRACE1, ... (The arguments are the same as printf)
|
|
void wprintf(char *fmt, ...)
|
|
{
|
|
if(!__hStdOut)
|
|
{
|
|
AllocConsole();
|
|
SetConsoleTitle("Debug Window");
|
|
__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
COORD co = {80, 25};
|
|
SetConsoleScreenBufferSize(__hStdOut, co);
|
|
}
|
|
|
|
char s[300];
|
|
va_list argptr;
|
|
va_start(argptr, fmt);
|
|
vsprintf(s, fmt, argptr);
|
|
va_end(argptr);
|
|
strcat(s, "\n");
|
|
DWORD cCharsWritten;
|
|
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
|
|
}
|
|
#endif
|
|
|
|
// If Data is NULL this function will only display a message if there are updates.
|
|
static void CheckForUpdates(void* Data)
|
|
{
|
|
HINTERNET session = InternetOpen("LeoCAD", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0) ;
|
|
|
|
char szSizeBuffer[32];
|
|
DWORD dwLengthSizeBuffer = sizeof(szSizeBuffer);
|
|
DWORD dwFileSize;
|
|
DWORD dwBytesRead;
|
|
CString Contents;
|
|
|
|
HINTERNET hHttpFile = InternetOpenUrl(session, "http://www.leocad.org/updates.txt", NULL, 0, 0, 0);
|
|
|
|
if (hHttpFile)
|
|
{
|
|
if(HttpQueryInfo(hHttpFile,HTTP_QUERY_CONTENT_LENGTH, szSizeBuffer, &dwLengthSizeBuffer, NULL))
|
|
{
|
|
dwFileSize = atol(szSizeBuffer);
|
|
LPSTR szContents = Contents.GetBuffer(dwFileSize+1);
|
|
szContents[dwFileSize] = 0;
|
|
|
|
if (InternetReadFile(hHttpFile, szContents, dwFileSize, &dwBytesRead))
|
|
{
|
|
int MajorVersion, MinorVersion, PatchVersion;
|
|
int lib;
|
|
|
|
if (sscanf(szContents, "%d.%d.%d %d", &MajorVersion, &MinorVersion, &PatchVersion, &lib) == 4)
|
|
{
|
|
CString str;
|
|
bool Update = false;
|
|
|
|
if (MajorVersion > LC_VERSION_MAJOR)
|
|
Update = true;
|
|
else if (MajorVersion == LC_VERSION_MAJOR)
|
|
{
|
|
if (MinorVersion > LC_VERSION_MINOR)
|
|
Update = true;
|
|
else if (MinorVersion == LC_VERSION_MINOR)
|
|
{
|
|
if (PatchVersion > LC_VERSION_PATCH)
|
|
Update = true;
|
|
}
|
|
}
|
|
|
|
if (Update)
|
|
str.Format("There's a newer version of LeoCAD available for download (%d.%d.%d).\n", MajorVersion, MinorVersion, PatchVersion);
|
|
else
|
|
str = "You are using the latest version of LeoCAD.\n";
|
|
|
|
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
|
if (Library->mNumOfficialPieces)
|
|
{
|
|
if (lib > Library->mNumOfficialPieces)
|
|
{
|
|
str += "There are new pieces available.\n\n";
|
|
Update = true;
|
|
}
|
|
else
|
|
str += "There are no new pieces available at this time.\n";
|
|
}
|
|
|
|
if (Data || Update)
|
|
{
|
|
if (Update)
|
|
{
|
|
str += "Would you like to visit the LeoCAD website now?\n";
|
|
|
|
if (AfxMessageBox(str, MB_YESNO | MB_ICONQUESTION) == IDYES)
|
|
{
|
|
ShellExecute(::GetDesktopWindow(), _T("open"), _T("http://www.leocad.org"), NULL, NULL, SW_NORMAL);
|
|
}
|
|
}
|
|
else
|
|
AfxMessageBox(str, MB_OK | MB_ICONINFORMATION);
|
|
}
|
|
}
|
|
else if (Data != NULL)
|
|
AfxMessageBox("Unknown file information.");
|
|
}
|
|
InternetCloseHandle(hHttpFile);
|
|
}
|
|
else if (Data != NULL)
|
|
AfxMessageBox("Could not connect.");
|
|
}
|
|
else if (Data != NULL)
|
|
AfxMessageBox("Could not connect.");
|
|
|
|
InternetCloseHandle(session);
|
|
}
|
|
|
|
static char MinidumpPath[MAX_PATH];
|
|
|
|
LONG WINAPI SehHandler(PEXCEPTION_POINTERS pExceptionPtrs)
|
|
{
|
|
if (IsDebuggerPresent())
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
|
|
HMODULE hDbgHelp = LoadLibrary("dbghelp.dll");
|
|
|
|
if (hDbgHelp == NULL)
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
|
|
HANDLE hFile = CreateFile(MinidumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
|
|
typedef BOOL (WINAPI *LPMINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserEncoderParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
|
|
LPMINIDUMPWRITEDUMP pfnMiniDumpWriteDump = (LPMINIDUMPWRITEDUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
|
|
if (!pfnMiniDumpWriteDump)
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
|
|
MINIDUMP_EXCEPTION_INFORMATION mei;
|
|
|
|
mei.ThreadId = GetCurrentThreadId();
|
|
mei.ExceptionPointers = pExceptionPtrs;
|
|
mei.ClientPointers = TRUE;
|
|
|
|
BOOL bWriteDump = pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, pExceptionPtrs ? &mei : NULL, NULL, NULL);
|
|
|
|
CloseHandle(hFile);
|
|
FreeLibrary(hDbgHelp);
|
|
|
|
if (bWriteDump)
|
|
{
|
|
char Message[256];
|
|
sprintf(Message, "LeoCAD just crashed. Crash information was saved to the file '%s', please send it to the developers for debugging.", MinidumpPath);
|
|
|
|
MessageBox(NULL, Message, "LeoCAD", MB_OK);
|
|
}
|
|
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CCADApp
|
|
|
|
BEGIN_MESSAGE_MAP(CCADApp, CWinAppEx)
|
|
//{{AFX_MSG_MAP(CCADApp)
|
|
ON_COMMAND(ID_HELP_CHECKFORUPDATES, OnHelpUpdates)
|
|
ON_COMMAND(ID_HELP_LEOCADHOMEPAGE, OnHelpHomePage)
|
|
ON_COMMAND(ID_HELP_SENDEMAIL, OnHelpEmail)
|
|
//}}AFX_MSG_MAP
|
|
// Standard print setup command
|
|
ON_UPDATE_COMMAND_UI(ID_FILE_MRU_FILE1, OnUpdateRecentFileMenu)
|
|
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinAppEx::OnFilePrintSetup)
|
|
END_MESSAGE_MAP()
|
|
|
|
CCADApp::CCADApp()
|
|
{
|
|
}
|
|
|
|
CCADApp theApp;
|
|
|
|
BOOL CCADApp::InitInstance()
|
|
{
|
|
if (SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, MinidumpPath) == S_OK)
|
|
{
|
|
PathAppend(MinidumpPath, "LeoCAD\\");
|
|
_mkdir(MinidumpPath);
|
|
_snprintf(MinidumpPath + strlen(MinidumpPath), MAX_PATH, "%s", "minidump.dmp");
|
|
}
|
|
|
|
SetUnhandledExceptionFilter(SehHandler);
|
|
|
|
// InitCommonControlsEx() is required on Windows XP if an application
|
|
// manifest specifies use of ComCtl32.dll version 6 or later to enable
|
|
// visual styles. Otherwise, any window creation will fail.
|
|
INITCOMMONCONTROLSEX InitCtrls;
|
|
InitCtrls.dwSize = sizeof(InitCtrls);
|
|
// Set this to include all the common control classes you want to use
|
|
// in your application.
|
|
InitCtrls.dwICC = ICC_WIN95_CLASSES;
|
|
InitCommonControlsEx(&InitCtrls);
|
|
|
|
CWinAppEx::InitInstance();
|
|
|
|
SetRegistryKey(_T("BT Software"));
|
|
LoadStdProfileSettings();
|
|
|
|
InitContextMenuManager();
|
|
InitShellManager();
|
|
InitKeyboardManager();
|
|
InitTooltipManager();
|
|
CMFCToolTipInfo ttParams;
|
|
ttParams.m_bVislManagerTheme = TRUE;
|
|
theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL, RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
|
|
|
|
InitKeyboardShortcuts();
|
|
|
|
char ApplicationPath[LC_MAXPATH], *ptr;
|
|
GetModuleFileName (NULL, ApplicationPath, LC_MAXPATH);
|
|
ptr = strrchr(ApplicationPath,'\\');
|
|
if (ptr)
|
|
*(++ptr) = 0;
|
|
|
|
char CacheFilePath[LC_MAXPATH];
|
|
if (SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, CacheFilePath) == S_OK)
|
|
{
|
|
PathAppend(CacheFilePath, "LeoCAD\\");
|
|
_mkdir(CacheFilePath);
|
|
}
|
|
else
|
|
CacheFilePath[0] = 0;
|
|
|
|
g_App = new lcApplication();
|
|
main_window = new MainWnd();
|
|
|
|
if (!g_App->Initialize(__argc, __targv, ApplicationPath, CacheFilePath))
|
|
return false;
|
|
|
|
// Register the application's document templates. Document templates
|
|
// serve as the connection between documents, frame windows and views.
|
|
CSingleDocTemplate* pDocTemplate;
|
|
pDocTemplate = new CSingleDocTemplate(
|
|
IDR_MAINFRAME,
|
|
RUNTIME_CLASS(CCADDoc),
|
|
RUNTIME_CLASS(CMainFrame), // main SDI frame window
|
|
RUNTIME_CLASS(CCADView));
|
|
AddDocTemplate(pDocTemplate);
|
|
|
|
EnableShellOpen();
|
|
RegisterLeoCADShellFileTypes();
|
|
|
|
UINT cmdshow = m_nCmdShow;
|
|
m_nCmdShow = SW_HIDE;
|
|
pDocTemplate->OpenDocumentFile(NULL);
|
|
|
|
GL_EnableVertexBufferObject();
|
|
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
|
|
|
if (lcGetActiveProject()->m_pPieces)
|
|
{
|
|
for (int PieceIdx = 0; PieceIdx < Library->mPieces.GetSize(); PieceIdx++)
|
|
{
|
|
lcMesh* Mesh = Library->mPieces[PieceIdx]->mMesh;
|
|
|
|
if (Mesh)
|
|
Mesh->UpdateBuffers();
|
|
}
|
|
}
|
|
|
|
CMainFrame* MainFrame = (CMainFrame*)AfxGetMainWnd();
|
|
MainFrame->UpdateMenuAccelerators();
|
|
|
|
// Show something in the piece preview window.
|
|
PieceInfo* Info = Library->FindPiece("3005", false);
|
|
if (!Info && Library->mPieces.GetSize())
|
|
Info = Library->mPieces[0];
|
|
|
|
if (Info)
|
|
{
|
|
lcGetActiveProject()->SetCurrentPiece(Info);
|
|
MainFrame->m_wndPiecesBar.m_wndPiecePreview.SetPieceInfo(Info);
|
|
MainFrame->m_wndPiecesBar.m_wndPiecePreview.PostMessage(WM_PAINT);
|
|
}
|
|
|
|
/*
|
|
char out[_MAX_PATH];
|
|
GetTempPath (_MAX_PATH, out);
|
|
strcat (out, "~LC*.lcd");
|
|
|
|
WIN32_FIND_DATA fd;
|
|
HANDLE fh = FindFirstFile(out, &fd);
|
|
if (fh != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (char *ptr = strrchr (out, '\\')) *(ptr+1) = 0;
|
|
strcat (out, fd.cFileName);
|
|
if (AfxMessageBox (_T("LeoCAD found a file that was being edited while the program exited unexpectdly. Do you want to load it ?"), MB_YESNO) == IDNO)
|
|
{
|
|
if (AfxMessageBox (_T("Delete file ?"), MB_YESNO) == IDYES)
|
|
DeleteFile (out);
|
|
}
|
|
else
|
|
{
|
|
cmdInfo.m_nShellCommand = CCommandLineInfo::FileOpen;
|
|
cmdInfo.m_strFileName = out;
|
|
}
|
|
}
|
|
|
|
// if (cmdInfo.m_strFileName.IsEmpty())
|
|
// ParseCommandLine(cmdInfo);
|
|
*/
|
|
|
|
// The one and only window has been initialized, so show and update it.
|
|
m_pMainWnd->ShowWindow(cmdshow);
|
|
m_pMainWnd->UpdateWindow();
|
|
lcGetActiveProject()->HandleNotify(LC_ACTIVATE, 1);
|
|
lcGetActiveProject()->UpdateInterface();
|
|
|
|
main_window->UpdateMRU ();
|
|
|
|
// Enable drag/drop open
|
|
m_pMainWnd->DragAcceptFiles();
|
|
|
|
lcGetActiveProject()->UpdateAllViews();
|
|
|
|
int CheckUpdates = AfxGetApp()->GetProfileInt("Settings", "CheckUpdates", 1);
|
|
if (CheckUpdates)
|
|
{
|
|
struct tm When;
|
|
__time64_t Now, Next;
|
|
|
|
if (CheckUpdates == 2)
|
|
CheckUpdates = 7;
|
|
|
|
memset(&When, 0, sizeof(When));
|
|
CString LastCheck = GetProfileString("Settings", "LastUpdate", NULL);
|
|
sscanf(LastCheck, "%d %d %d", &When.tm_mday, &When.tm_mon, &When.tm_year);
|
|
When.tm_mday = When.tm_mday + CheckUpdates;
|
|
Next = _mktime64(&When);
|
|
|
|
_time64(&Now);
|
|
|
|
if (Next < Now)
|
|
{
|
|
When = *_localtime64(&Now);
|
|
_beginthread(CheckForUpdates, 0, NULL);
|
|
LastCheck.Format("%d %d %d", When.tm_mday, When.tm_mon, When.tm_year);
|
|
WriteProfileString("Settings", "LastUpdate", LastCheck);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int CCADApp::ExitInstance()
|
|
{
|
|
delete main_window;
|
|
main_window = NULL;
|
|
|
|
g_App->Shutdown();
|
|
|
|
delete g_App;
|
|
g_App = NULL;
|
|
|
|
#ifdef _DEBUG
|
|
if (__hStdOut != NULL)
|
|
FreeConsole();
|
|
#endif
|
|
|
|
return CWinAppEx::ExitInstance();
|
|
}
|
|
|
|
void CCADApp::UpdateMRU(char names[4][MAX_PATH])
|
|
{
|
|
if (m_pRecentFileList)
|
|
{
|
|
for (int iMRU = 0; iMRU < m_pRecentFileList->m_nSize; iMRU++)
|
|
m_pRecentFileList->m_arrNames[iMRU] = names[iMRU];
|
|
}
|
|
}
|
|
|
|
static BOOL SetRegKey(LPCTSTR lpszKey, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL)
|
|
{
|
|
if (lpszValueName == NULL)
|
|
{
|
|
if (AfxRegSetValue(HKEY_CLASSES_ROOT, lpszKey, REG_SZ, lpszValue, lstrlen(lpszValue) * sizeof(TCHAR)) != ERROR_SUCCESS)
|
|
{
|
|
TRACE(traceAppMsg, 0, _T("Warning: registration database update failed for key '%s'.\n"), lpszKey);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
HKEY hKey;
|
|
|
|
if (AfxRegCreateKey(HKEY_CLASSES_ROOT, lpszKey, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
LONG lResult = ::RegSetValueEx(hKey, lpszValueName, 0, REG_SZ, (CONST BYTE*)lpszValue, (lstrlen(lpszValue) + 1) * sizeof(TCHAR));
|
|
|
|
if (::RegCloseKey(hKey) == ERROR_SUCCESS && lResult == ERROR_SUCCESS)
|
|
return TRUE;
|
|
}
|
|
TRACE(traceAppMsg, 0, _T("Warning: registration database update failed for key '%s'.\n"), lpszKey);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
void CCADApp::RegisterLeoCADShellFileTypes()
|
|
{
|
|
CString strPathName, strTemp;
|
|
|
|
AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName);
|
|
|
|
// first register the type ID of our server
|
|
if (!SetRegKey(_T("LeoCAD.Project"), _T("LeoCAD Project")))
|
|
return;
|
|
|
|
// path\DefaultIcon = path,0
|
|
CString strDefaultIconCommandLine = strPathName;
|
|
strDefaultIconCommandLine += _T(",0");
|
|
if (!SetRegKey(_T("LeoCAD.Project\\DefaultIcon"), strDefaultIconCommandLine))
|
|
return;
|
|
|
|
// path\shell\open\command = path filename
|
|
CString strOpenCommandLine = strPathName;
|
|
strOpenCommandLine += _T(" \"%1\"");
|
|
if (!SetRegKey(_T("LeoCAD.Project\\shell\\open\\command"), strOpenCommandLine))
|
|
return;
|
|
|
|
// path\shell\print\command = path /p filename
|
|
CString strPrintCommandLine = strPathName;
|
|
strPrintCommandLine += _T(" /p \"%1\"");
|
|
if (!SetRegKey(_T("LeoCAD.Project\\shell\\print\\command"), strPrintCommandLine))
|
|
return;
|
|
|
|
// path\shell\printto\command = path /pt filename printer driver port
|
|
CString strPrintToCommandLine = strPathName;
|
|
strPrintToCommandLine += _T(" /pt \"%1\" \"%2\" \"%3\" \"%4\"");
|
|
if (!SetRegKey(_T("LeoCAD.Project\\shell\\printto\\command"), strPrintToCommandLine))
|
|
return;
|
|
|
|
LONG lSize = _MAX_PATH * 2;
|
|
LONG lResult = AfxRegQueryValue(HKEY_CLASSES_ROOT, _T(".lcd"), strTemp.GetBuffer(lSize), &lSize);
|
|
strTemp.ReleaseBuffer();
|
|
|
|
if (lResult != ERROR_SUCCESS || strTemp.IsEmpty() || strTemp == _T("LeoCAD.Project"))
|
|
{
|
|
// no association for that suffix
|
|
if (!SetRegKey(_T(".lcd"), _T("LeoCAD.Project")))
|
|
return;
|
|
|
|
SetRegKey(_T(".lcd\\ShellNew"), _T(""), _T("NullFile"));
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CCADApp commands
|
|
|
|
void CCADApp::OnHelpUpdates()
|
|
{
|
|
CheckForUpdates(this);
|
|
}
|
|
|
|
void CCADApp::OnHelpHomePage()
|
|
{
|
|
ShellExecute(::GetDesktopWindow(), _T("open"), _T("http://www.leocad.org"), NULL, NULL, SW_NORMAL);
|
|
}
|
|
|
|
void CCADApp::OnHelpEmail()
|
|
{
|
|
ShellExecute(::GetDesktopWindow(), _T("open"), _T("mailto:leozide@gmail.com?subject=LeoCAD"), NULL, NULL, SW_NORMAL);
|
|
}
|