6386 lines
215 KiB
C++
6386 lines
215 KiB
C++
/*******************************************************************************
|
|
* pvengine.cpp
|
|
*
|
|
* This file implements Windows specific routines, WinMain, and message loops.
|
|
*
|
|
* Primary author: Christopher J. Cason.
|
|
*
|
|
* ---------------------------------------------------------------------------
|
|
* Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
|
|
* Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
|
|
*
|
|
* POV-Ray is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* POV-Ray 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 Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
* ---------------------------------------------------------------------------
|
|
* POV-Ray is based on the popular DKB raytracer version 2.12.
|
|
* DKBTrace was originally written by David K. Buck.
|
|
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
|
|
* ---------------------------------------------------------------------------
|
|
* $File: //depot/public/povray/3.x/windows/pvengine.cpp $
|
|
* $Revision: #1 $
|
|
* $Change: 6069 $
|
|
* $DateTime: 2013/11/06 11:59:40 $
|
|
* $Author: chrisc $
|
|
*******************************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
/* NOTICE */
|
|
/* */
|
|
/* Much of this source code (all of pvengine.exe) should be considered on */
|
|
/* its last legs. The base code was originally written back in early 1995 */
|
|
/* (with some of the code even predating that), and targeted at Win32s under */
|
|
/* Windows 3.1. An additional constraint was a desire for the code to be */
|
|
/* able to be compiled on a DEC Alpha under NT for the Alpha using only a */
|
|
/* 'C' compiler, and for it to be able to run with or without the editor. */
|
|
/* */
|
|
/* With the introduction of VFE in version 3.7, creating a new UI for POVWIN */
|
|
/* should be a lot less painful as almost all of the bindings with the core */
|
|
/* POV-Ray renderer have been abstracted into the above class library. */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
#define POVWIN_FILE
|
|
#define _WIN32_IE COMMONCTRL_VERSION
|
|
|
|
#if !defined( __BORLANDC__ ) && !defined( __DMC__ ) && !defined( __MINGW32__ )
|
|
#pragma comment(lib, "htmlhelp")
|
|
#pragma comment(lib, "winmm")
|
|
#endif
|
|
|
|
#define _CRT_RAND_S
|
|
#define PSAPI_VERSION 1
|
|
#pragma comment(lib, "psapi")
|
|
|
|
#include <windows.h>
|
|
#include <htmlhelp.h>
|
|
#include <shellapi.h>
|
|
#include <shlobj.h>
|
|
#include <shlwapi.h>
|
|
#include <mmsystem.h>
|
|
#include <commdlg.h>
|
|
#include <commctrl.h>
|
|
#include <crtdbg.h>
|
|
#include <psapi.h>
|
|
#include <dbghelp.h>
|
|
|
|
// #define DEVELOPMENT
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <tchar.h>
|
|
#include "pvengine.h"
|
|
#include "resource.h"
|
|
#include "pvdialog.h"
|
|
#include "pvguiext.h"
|
|
#include "pvedit.h"
|
|
#include "backend/control/benchmark.h"
|
|
#include "pvdisplay.h"
|
|
#include "syspovprotofrontend.h"
|
|
#include "povray.h"
|
|
|
|
#ifdef RTR_SUPPORT
|
|
#include "rtrsupport.h"
|
|
#endif
|
|
|
|
#if defined(USE_AVX_FMA4_FOR_NOISE)
|
|
#include "backend/texture/avxfma4check.h"
|
|
#endif
|
|
|
|
// this must be the last file included
|
|
#include "syspovdebug.h"
|
|
|
|
typedef HRESULT (CALLBACK* DLLGETVERSIONPROC) (DLLVERSIONINFO *);
|
|
typedef DWORD __stdcall shCopyType (HKEY, LPCTSTR, HKEY, DWORD) ;
|
|
|
|
#ifndef SM_CMONITORS
|
|
#define SM_XVIRTUALSCREEN 76
|
|
#define SM_YVIRTUALSCREEN 77
|
|
#define SM_CXVIRTUALSCREEN 78
|
|
#define SM_CYVIRTUALSCREEN 79
|
|
#define SM_CMONITORS 80
|
|
#endif
|
|
|
|
#ifndef PROCESS_MODE_BACKGROUND_BEGIN
|
|
#define PROCESS_MODE_BACKGROUND_BEGIN 0x00100000
|
|
#define PROCESS_MODE_BACKGROUND_END 0x00200000
|
|
#endif
|
|
|
|
#define CONFIRM_STOP_THRESHOLD 900
|
|
|
|
typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
|
|
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
|
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
|
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
|
|
);
|
|
|
|
char *WriteDump(struct _EXCEPTION_POINTERS *pExceptionInfo, bool full, long timestamp);
|
|
|
|
namespace pov_frontend
|
|
{
|
|
extern shared_ptr<Display> gDisplay;
|
|
}
|
|
|
|
namespace vfePlatform
|
|
{
|
|
extern bool GetCPUCount(unsigned int *TotAvailLogical, unsigned int *TotAvailCore, unsigned int *PhysicalNum);
|
|
}
|
|
|
|
using namespace pov;
|
|
using namespace pov_frontend;
|
|
|
|
void GenerateDumpMeta(bool brief);
|
|
|
|
namespace povwin
|
|
{
|
|
|
|
typedef struct
|
|
{
|
|
int id ;
|
|
HWND hwnd ;
|
|
SIZE size ;
|
|
} StatusPanelItem ;
|
|
|
|
bool rendering ;
|
|
bool stop_rendering ;
|
|
bool rendersleep ;
|
|
bool render_cooperate = false ;
|
|
bool InFrontend = false ;
|
|
bool ErrorNotified ;
|
|
bool ErrorOccurred ;
|
|
bool HideRenderWithMain ;
|
|
bool UseAlpha;
|
|
bool IsExpired;
|
|
bool BackendFailedFlag = false;
|
|
bool PreventSleep = true;
|
|
char DumpMeta[65536];
|
|
string ErrorMessage ;
|
|
string ErrorFilename ;
|
|
unsigned ErrorLine ;
|
|
unsigned ErrorCol ;
|
|
unsigned render_priority = CM_RENDERPRIORITY_NORMAL ;
|
|
unsigned Duty_Cycle = 9 ;
|
|
unsigned renderwin_8bits ;
|
|
|
|
extern int renderwin_xoffset ;
|
|
extern int renderwin_yoffset ;
|
|
extern int renderwin_left ;
|
|
extern int renderwin_top ;
|
|
extern char PovLegacyRenderWinClass [] ;
|
|
extern unsigned renderwin_max_width ;
|
|
extern unsigned renderwin_max_height ;
|
|
extern unsigned renderwin_flags ;
|
|
extern bool MakeRenderwinActive ;
|
|
|
|
int render_bitmap_depth ;
|
|
unsigned render_width ;
|
|
unsigned render_height ;
|
|
|
|
int alert_sound ;
|
|
int run_count ;
|
|
int render_anim_count ;
|
|
int argc ;
|
|
int io_restrictions ;
|
|
int tb_combo_sel ;
|
|
int povray_return_code ;
|
|
int PerformanceScale = 1 ;
|
|
int seconds_for_last_line = -1 ;
|
|
int delay_next_status ;
|
|
int screen_origin_x ;
|
|
int screen_origin_y ;
|
|
int virtual_screen_width ;
|
|
int virtual_screen_height ;
|
|
int LastRenderPercentage ;
|
|
int renderwin_transparency ;
|
|
int cb_expect_selchange ;
|
|
char command_line [_MAX_PATH * 3] ;
|
|
char old_command_line [_MAX_PATH * 3] ;
|
|
char *argv [MAX_ARGV] ;
|
|
char source_file_name [_MAX_PATH] ;
|
|
char modulePath [_MAX_PATH] ;
|
|
char engineHelpPath [_MAX_PATH] ;
|
|
char lastRenderName [_MAX_PATH] ;
|
|
char lastBitmapName [_MAX_PATH] ;
|
|
char lastRenderPath [_MAX_PATH] ;
|
|
char lastBitmapPath [_MAX_PATH] ;
|
|
char lastQueuePath [_MAX_PATH] ;
|
|
char lastSecondaryIniFilePath [_MAX_PATH] ;
|
|
char DefaultRenderIniFileName [_MAX_PATH] ;
|
|
char SecondaryRenderIniFileName [_MAX_PATH] ;
|
|
char SecondaryRenderIniFileSection [64] ;
|
|
char background_file [_MAX_PATH] ;
|
|
char EngineIniFileName[_MAX_PATH] ;
|
|
char BinariesPath [_MAX_PATH] ;
|
|
char DocumentsPath [_MAX_PATH] ;
|
|
char LastInferredHome [_MAX_PATH] ;
|
|
char ToolIniFileName [_MAX_PATH] ;
|
|
char tool_commands [MAX_TOOLCMD] [MAX_TOOLCMDTEXT] ;
|
|
char tool_help [MAX_TOOLCMD] [MAX_TOOLHELPTEXT] ;
|
|
char requested_render_file [_MAX_PATH] ;
|
|
char RegionStr [128] ;
|
|
char TempRegionStr [128] ;
|
|
char demo_file_name [_MAX_PATH] ;
|
|
char demo_ini_name [_MAX_PATH] ;
|
|
char status_buffer [1024] ;
|
|
char render_complete_sound [_MAX_PATH] ;
|
|
char parse_error_sound [_MAX_PATH] ;
|
|
char render_error_sound [_MAX_PATH] ;
|
|
char FontPath [_MAX_PATH] ;
|
|
char *EditDLLPath ;
|
|
bool render_complete_sound_enabled ;
|
|
bool parse_error_sound_enabled ;
|
|
bool render_error_sound_enabled ;
|
|
bool alert_on_completion ;
|
|
bool save_settings ;
|
|
bool IsW95UserInterface = true;
|
|
bool IsW98 ;
|
|
bool IsWNT ;
|
|
bool IsW2k ;
|
|
bool IsWXP ;
|
|
bool IsVista ;
|
|
bool running_demo ;
|
|
bool running_benchmark ;
|
|
bool benchmark_multithread ;
|
|
bool fast_scroll ;
|
|
bool no_shellout_wait ;
|
|
bool tile_background = false ;
|
|
bool debugging ;
|
|
bool no_palette_warn ;
|
|
bool render_lock_up ;
|
|
bool RenderwinIsChild = true ;
|
|
bool demo_mode ;
|
|
bool benchmark_mode;
|
|
bool ignore_auto_ini ;
|
|
bool newVersion ;
|
|
bool exit_after_render ;
|
|
bool system_noactive ;
|
|
bool one_instance = true ;
|
|
bool run_renderer ;
|
|
bool use_toolbar = true ;
|
|
bool use_tooltips = true ;
|
|
bool use_editors = true ;
|
|
bool editors_enabled = true;
|
|
bool resizing ;
|
|
bool drop_to_editor ;
|
|
bool restore_command_line ;
|
|
bool render_requested ;
|
|
bool render_auto_close ;
|
|
bool noexec ;
|
|
bool ExtensionsEnabled = true ;
|
|
bool use_taskbar = true ;
|
|
bool main_window_hidden ;
|
|
bool about_showing ;
|
|
bool NoRestore ;
|
|
bool IsComCtl5 = false ;
|
|
bool IsComCtl6 = false ;
|
|
bool allow_rw_source ;
|
|
bool no_shell_outs = true ;
|
|
bool hide_newuser_help ;
|
|
bool info_render_complete = false ;
|
|
bool no_status_output = false ;
|
|
bool temp_render_region = false ;
|
|
bool rendering_insert_menu = false ;
|
|
bool was_insert_render = false ;
|
|
bool rendering_animation = false ;
|
|
bool preserve_bitmap = false ;
|
|
bool first_frame = false ;
|
|
bool check_new_version ;
|
|
bool check_news ;
|
|
bool send_system_info ;
|
|
bool homeInferred = false ;
|
|
bool editSettingsCopied = false ;
|
|
bool FreshInstall = false;
|
|
bool output_to_file ;
|
|
bool UpdateCheckDone = false ;
|
|
bool AutoAppendPaths ;
|
|
HWND toolbar_window ;
|
|
HWND aux_toolbar_window ;
|
|
HWND window_list [MAX_WINDOWS] ;
|
|
HWND toolbar_combobox ;
|
|
HWND rebar_window ;
|
|
HWND StatusWindow ;
|
|
HWND StatusTooltip ;
|
|
HWND toolbar_cmdline ;
|
|
HWND tab_window ;
|
|
HICON ourIcon ;
|
|
HICON renderIcon ;
|
|
HFONT about_font ;
|
|
HANDLE hMainThread ;
|
|
string InputFileName ;
|
|
time_t SecondCountStart ;
|
|
time_t quit ;
|
|
HBITMAP hBmpBackground ;
|
|
HBITMAP hBmpRendering ;
|
|
HBITMAP hBmpIcon ;
|
|
HBITMAP hBmpAbout ;
|
|
__int64 PerformanceFrequency ;
|
|
__int64 PerformanceCounter1 ;
|
|
__int64 PerformanceCounter2 ;
|
|
__int64 KernelTimeStart ;
|
|
__int64 KernelTimeEnd ;
|
|
__int64 UserTimeStart ;
|
|
__int64 UserTimeEnd ;
|
|
__int64 KernelTimeTotal ;
|
|
__int64 UserTimeTotal ;
|
|
__int64 CPUTimeTotal ;
|
|
clock_t ClockTimeStart ;
|
|
clock_t ClockTimeEnd ;
|
|
clock_t ClockTimeTotal ;
|
|
clock_t SleepTimeStart ;
|
|
clock_t SleepTimeEnd ;
|
|
clock_t SleepTimeTotal ;
|
|
unsigned class_registered = 0 ;
|
|
unsigned currentX = 0 ;
|
|
unsigned currentY = 0 ;
|
|
unsigned screen_width ;
|
|
unsigned screen_height ;
|
|
unsigned screen_depth ;
|
|
unsigned background_width ;
|
|
unsigned background_height ;
|
|
unsigned seconds = 0 ;
|
|
unsigned toolheight = 0 ;
|
|
unsigned statusheight = 0 ;
|
|
unsigned on_completion = CM_COMPLETION_NOTHING ;
|
|
unsigned window_count = 0 ;
|
|
unsigned ThreadCount = 2 ;
|
|
unsigned NumberOfCPUs ;
|
|
unsigned NumLogicalCPUs ;
|
|
unsigned NumCPUCores ;
|
|
unsigned NumPhysicalCPUs ;
|
|
HPALETTE hPalApp ;
|
|
HPALETTE hPalBitmap ;
|
|
COLORREF background_colour ;
|
|
COLORREF text_colours [3] ;
|
|
COLORREF custom_colours [16] ;
|
|
COLORREF background_shade = RGB (1, 1, 1) ;
|
|
HINSTANCE hInstance ;
|
|
HH_AKLINK hh_aklink ;
|
|
OSVERSIONINFO version_info ;
|
|
StatusPanelItem StatusPanelItems [IDC_STATUS_ID_LAST + 1] ;
|
|
CRITICAL_SECTION critical_section ;
|
|
|
|
// key is the name of an included file (all lower case).
|
|
// content is the name of the most recent rendered file that caused it to be included.
|
|
map<string, string> IncludeToSourceMap;
|
|
map<string, bool> IncludeAlternateDecisionMap;
|
|
|
|
char queued_files [MAX_QUEUE] [_MAX_PATH] ;
|
|
char dir [_MAX_PATH] ;
|
|
unsigned queued_file_count = 0 ;
|
|
unsigned auto_render = true ;
|
|
unsigned timer_id ;
|
|
unsigned about_timer_id ;
|
|
unsigned timer_ticks;
|
|
|
|
unsigned panel_size ;
|
|
|
|
char PovMainWinClass [] = CLASSNAMEPREFIX "MainWinClass" ;
|
|
unsigned mainwin_xpos ;
|
|
unsigned mainwin_ypos ;
|
|
HWND main_window ;
|
|
HWND message_window ;
|
|
WINDOWPLACEMENT mainwin_placement ;
|
|
|
|
char PovAboutWinClass [] = CLASSNAMEPREFIX "AboutWinClass" ;
|
|
HWND about_window ;
|
|
HWND about_buttons [3] ;
|
|
WNDPROC about_button_wndproc ;
|
|
unsigned about_width ;
|
|
unsigned about_height ;
|
|
HPALETTE about_palette ;
|
|
|
|
HWND statuspanel ;
|
|
|
|
char PovMessageWinClass [] = CLASSNAMEPREFIX "MessageWinClass" ;
|
|
|
|
#define NUM_ABOUT_LINKS 7
|
|
RECT AboutLinks[NUM_ABOUT_LINKS] =
|
|
{
|
|
{ 23, 14, 188, 87 },
|
|
{ 104, 397, 184, 409 },
|
|
{ 185, 397, 262, 409 },
|
|
{ 263, 397, 370, 409 },
|
|
{ 371, 397, 480, 409 },
|
|
{ 481, 397, 560, 409 },
|
|
{ 32, 411, 154, 423 }
|
|
};
|
|
char *AboutURLs[NUM_ABOUT_LINKS] =
|
|
{
|
|
"http://www.povray.org/",
|
|
"http://www.digicert.com/",
|
|
"http://ntplx.net/",
|
|
"http://opensourcelaw.biz/",
|
|
"http://www.perforce.com/",
|
|
"http://softwarefreedom.org/",
|
|
"http://softwarefreedom.org/"
|
|
};
|
|
|
|
bool handle_main_command (WPARAM wParam, LPARAM lParam) ;
|
|
void SetStatusPanelItemText (int id, LPCSTR format, ...) ;
|
|
void ShowAboutBox (void);
|
|
|
|
extern int message_xchar ;
|
|
extern int message_ychar ;
|
|
extern int message_scroll_pos_x ;
|
|
extern int message_scroll_pos_y ;
|
|
extern int top_message_row ;
|
|
extern int message_count ;
|
|
extern int message_cols ;
|
|
extern int message_rows ;
|
|
extern int listbox_xchar ;
|
|
extern int listbox_ychar ;
|
|
extern int EditFileCount ;
|
|
extern int message_output_x ;
|
|
extern char message_font_name [256] ;
|
|
extern char *EditFiles [] ;
|
|
extern bool ListenMode ;
|
|
extern bool keep_messages ;
|
|
extern bool MenuBarDraw ;
|
|
extern bool TrackMem;
|
|
extern __int64 PeakMem;
|
|
extern unsigned message_font_size ;
|
|
extern unsigned message_font_weight ;
|
|
extern HFONT message_font ;
|
|
extern HFONT tab_font ;
|
|
extern HMENU hMenuBar ;
|
|
extern HMENU hMainMenu ;
|
|
extern HMENU hPopupMenus ;
|
|
extern HMENU hVidcapMenu ;
|
|
extern HACCEL hAccelerators ;
|
|
extern HINSTANCE hLibPovEdit ;
|
|
|
|
#define MAX_INSERT_MENU_SECTIONS 8192
|
|
|
|
typedef std::vector<int> InsMenuSecList;
|
|
|
|
int InsertMenuSection;
|
|
bool StartInsertRender;
|
|
InsMenuSecList InsertMenuSections;
|
|
|
|
typedef struct
|
|
{
|
|
WORD wVirtkey ;
|
|
int iMessage ;
|
|
WORD wRequest ;
|
|
} SCROLLKEYS ;
|
|
|
|
SCROLLKEYS key2scroll [] =
|
|
{
|
|
{ VK_END, WM_VSCROLL, SB_BOTTOM },
|
|
{ VK_PRIOR, WM_VSCROLL, SB_PAGEUP },
|
|
{ VK_NEXT, WM_VSCROLL, SB_PAGEDOWN },
|
|
{ VK_UP, WM_VSCROLL, SB_LINEUP },
|
|
{ VK_DOWN, WM_VSCROLL, SB_LINEDOWN },
|
|
{ VK_LEFT, WM_HSCROLL, SB_PAGEUP },
|
|
{ VK_RIGHT, WM_HSCROLL, SB_PAGEDOWN },
|
|
{ -1, -1, -1 }
|
|
} ;
|
|
|
|
string StripFilePath (const string& str)
|
|
{
|
|
string::size_type pos = str.find_last_of ("\\/") ;
|
|
if (pos == string::npos)
|
|
return (str) ;
|
|
return string (str, pos + 1) ;
|
|
}
|
|
|
|
bool StripPathComponent (char *path, int number)
|
|
{
|
|
if (number > 1)
|
|
if (!StripPathComponent (path, number - 1))
|
|
return (false) ;
|
|
char *s = path + strlen (path) - 1 ;
|
|
if (isPathSeparator(*s))
|
|
*s-- = '\0' ;
|
|
while (s > path && !isPathSeparator(*s))
|
|
s-- ;
|
|
*s = '\0' ;
|
|
return (path [0] != '\0') ;
|
|
}
|
|
|
|
void debug_output (const char *format, ...)
|
|
{
|
|
char str [2048] ;
|
|
va_list arg_ptr ;
|
|
FILE *f ;
|
|
|
|
if (format == NULL)
|
|
{
|
|
_unlink ("c:\\temp\\povdebug.txt") ;
|
|
return ;
|
|
}
|
|
|
|
va_start (arg_ptr, format) ;
|
|
vsprintf (str, format, arg_ptr) ;
|
|
va_end (arg_ptr) ;
|
|
OutputDebugString (str) ;
|
|
|
|
if ((f = fopen ("c:\\temp\\povdebug.txt", "a+t")) != NULL)
|
|
{
|
|
fprintf (f, sizeof(time_t) == 4 ? "%u: %s" : "%I64u: %s", time (NULL), str) ;
|
|
|
|
fclose (f) ;
|
|
}
|
|
}
|
|
|
|
// this function is declared in syspovconfig.h ... use pov::WIN32_DEBUG_OUTPUT() from
|
|
// anywhere in the POV-Ray source, core or otherwise
|
|
void WIN32_DEBUG_OUTPUT (const char *format,...)
|
|
{
|
|
char str [2048] ;
|
|
va_list arg_ptr ;
|
|
|
|
sprintf (str, "%5d ", GetCurrentThreadId());
|
|
va_start (arg_ptr, format) ;
|
|
vsprintf (str + 6, format, arg_ptr) ;
|
|
va_end (arg_ptr) ;
|
|
OutputDebugString (str) ;
|
|
}
|
|
|
|
// this function is declared in syspovconfig.h ... use pov::WIN32_DEBUG_FILE_OUTPUT() from
|
|
// anywhere in the POV-Ray source, core or otherwise. it's also thread-safe.
|
|
void WIN32_DEBUG_FILE_OUTPUT (const char *format,...)
|
|
{
|
|
va_list arg_ptr ;
|
|
static FILE *f ;
|
|
static boost::mutex mtx;
|
|
|
|
if (format == NULL)
|
|
{
|
|
if (f != NULL)
|
|
{
|
|
fclose (f) ;
|
|
f = NULL ;
|
|
}
|
|
return ;
|
|
}
|
|
|
|
if (f == NULL)
|
|
{
|
|
f = fopen ("c:\\temp\\povdebug.txt", "at") ;
|
|
if (f == NULL)
|
|
return ;
|
|
}
|
|
|
|
boost::mutex::scoped_lock l(mtx);
|
|
fprintf (f, "%u [%d]: ", GetTickCount (), GetCurrentThreadId ()) ;
|
|
va_start (arg_ptr, format) ;
|
|
vfprintf (f, format, arg_ptr) ;
|
|
va_end (arg_ptr) ;
|
|
fflush (f);
|
|
}
|
|
|
|
void SetCaption (LPCSTR str)
|
|
{
|
|
char buffer [1024] ;
|
|
static char lastStr [1024] ;
|
|
vfeSession& Session (GetSession());
|
|
|
|
if (str != NULL)
|
|
strcpy (lastStr, str) ;
|
|
else
|
|
str = lastStr ;
|
|
|
|
if (Session.BackendFailed())
|
|
{
|
|
SetWindowText (main_window, "Backend Failed") ;
|
|
return;
|
|
}
|
|
|
|
#ifndef DEVELOPMENT
|
|
if (Session.GetBackendState() == kRendering && InputFileName.size () > 0)
|
|
{
|
|
string filename = StripFilePath (InputFileName) ;
|
|
if (strstr (str, filename.c_str ()) != NULL)
|
|
{
|
|
// if the filename is in the caption already, we're probably rendering
|
|
// the current editor file (exception: if a file with the same name but
|
|
// a different path is being viewed).
|
|
sprintf (buffer, "%s [%s %d%%]", str, Session.GetBackendStateName(), Session.GetPercentComplete()) ;
|
|
}
|
|
else
|
|
{
|
|
// the render file name is not in the caption: in that case we are
|
|
// probably viewing another file or the message window.
|
|
sprintf (buffer, "%s [Rendering %s: %d%%]", str, filename.c_str (), Session.GetPercentComplete()) ;
|
|
}
|
|
}
|
|
else
|
|
sprintf (buffer, "%s [%s]", str, Session.GetBackendStateName ()) ;
|
|
SetWindowText (main_window, buffer) ;
|
|
#else
|
|
if (Session.GetBackendState() == kRendering && InputFileName.size () > 0)
|
|
{
|
|
string filename = StripFilePath (InputFileName) ;
|
|
if (strstr (str, filename.c_str ()) != NULL)
|
|
{
|
|
// if the filename is in the caption already, we're probably rendering
|
|
// the current editor file (exception: if a file with the same name but
|
|
// a different path is being viewed).
|
|
sprintf (buffer, CAPTIONPREFIX " %s [%s %d%%]", str, Session.GetBackendStateName(), Session.GetPercentComplete()) ;
|
|
}
|
|
else
|
|
{
|
|
// the render file name is not in the caption: in that case we are
|
|
// probably viewing another file or the message window.
|
|
sprintf (buffer, CAPTIONPREFIX " %s [Rendering %s:%d%%]", str, filename.c_str (), Session.GetPercentComplete()) ;
|
|
}
|
|
}
|
|
else
|
|
sprintf (buffer, CAPTIONPREFIX " %s [%s]", str, Session.GetBackendStateName()) ;
|
|
SetWindowText (main_window, buffer) ;
|
|
#endif
|
|
}
|
|
|
|
// returned value is in microseconds
|
|
__int64 GetCPUTime (bool Kernel = true, bool User = true)
|
|
{
|
|
__int64 kt ;
|
|
__int64 ut ;
|
|
__int64 total = 0 ;
|
|
FILETIME ct ;
|
|
FILETIME et ;
|
|
|
|
if (IsWNT)
|
|
{
|
|
if (!GetProcessTimes (GetCurrentProcess (), &ct, &et, (FILETIME *) &kt, (FILETIME *) &ut))
|
|
{
|
|
assert (false) ;
|
|
return (0) ;
|
|
}
|
|
if (Kernel)
|
|
total += kt ;
|
|
if (User)
|
|
total += ut ;
|
|
return (total / 10) ;
|
|
}
|
|
else
|
|
{
|
|
// have to simulate the results for now
|
|
// TODO: handle pause time
|
|
ut = clock () ;
|
|
if (User)
|
|
total += ut * 1000 ;
|
|
return (total) ;
|
|
}
|
|
}
|
|
|
|
char *PPS_String (unsigned pixels, unsigned renderseconds)
|
|
{
|
|
static char str [128] ;
|
|
|
|
if (rendersleep)
|
|
return ("PAUSED") ;
|
|
|
|
if (renderseconds == 0)
|
|
return ("??? PPS") ;
|
|
|
|
if (pixels / renderseconds < 5)
|
|
{
|
|
if (pixels * 60 / renderseconds < 5)
|
|
sprintf (str, "%u PPH", pixels * 3600 / renderseconds) ;
|
|
else
|
|
sprintf (str, "%u PPM", pixels * 60 / renderseconds) ;
|
|
}
|
|
else
|
|
sprintf (str, "%u PPS", pixels / renderseconds) ;
|
|
return (str) ;
|
|
}
|
|
|
|
void PrintRenderTimes (int Finished, int NormalCompletion)
|
|
{
|
|
int PixelsRendered = GetSession().GetPixelsRendered();
|
|
unsigned STT = SleepTimeTotal ;
|
|
|
|
if (rendersleep)
|
|
{
|
|
SleepTimeEnd = clock () ;
|
|
if (Finished)
|
|
{
|
|
SleepTimeTotal += SleepTimeEnd - SleepTimeStart ;
|
|
STT = SleepTimeTotal ;
|
|
rendersleep = false ;
|
|
}
|
|
else
|
|
STT += SleepTimeEnd - SleepTimeStart ;
|
|
}
|
|
KernelTimeEnd = GetCPUTime (true, false) ;
|
|
UserTimeEnd = GetCPUTime (false, true) ;
|
|
KernelTimeTotal = KernelTimeEnd - KernelTimeStart ;
|
|
UserTimeTotal = UserTimeEnd - UserTimeStart ;
|
|
CPUTimeTotal = UserTimeTotal + KernelTimeTotal ;
|
|
ClockTimeEnd = clock () ;
|
|
ClockTimeTotal = ClockTimeEnd - ClockTimeStart - STT ;
|
|
if (ClockTimeTotal >= CLOCKS_PER_SEC)
|
|
status_printf (StatusPPS, PPS_String (PixelsRendered, ClockTimeTotal / CLOCKS_PER_SEC)) ;
|
|
say_status_message (StatusRendertime, get_elapsed_time (ClockTimeTotal / CLOCKS_PER_SEC)) ;
|
|
if (IsWNT != 0 && Finished != 0)
|
|
{
|
|
message_printf ("CPU time used: kernel %.02f seconds, user %.02f seconds, total %.02f seconds.\n",
|
|
KernelTimeTotal / 1000000.0, UserTimeTotal / 1000000.0, CPUTimeTotal / 1000000.0) ;
|
|
message_printf ("Elapsed time %.02f seconds", (double) ClockTimeTotal / CLOCKS_PER_SEC) ;
|
|
if (NumberOfCPUs > 1 && ThreadCount > 1)
|
|
{
|
|
POV_ULONG cputotal = CPUTimeTotal * CLOCKS_PER_SEC / 1000000 ;
|
|
if (cputotal > ClockTimeTotal * 10 / 9)
|
|
message_printf (", CPU vs elapsed time ratio %.02f", (double) cputotal / ClockTimeTotal) ;
|
|
}
|
|
message_printf (".\n") ;
|
|
if (PixelsRendered > 0 && CPUTimeTotal > 0 && NormalCompletion)
|
|
{
|
|
message_printf ("Render averaged %.02f PPS (%.02f PPS CPU time) over %u pixels.\n",
|
|
(double) PixelsRendered * CLOCKS_PER_SEC / ClockTimeTotal, (double) PixelsRendered * 1000000 / CPUTimeTotal, PixelsRendered) ;
|
|
message_printf ("----------------------------------------------------------------------------\n") ;
|
|
#ifndef _DEBUG
|
|
char str [2048] ;
|
|
if (running_benchmark)
|
|
{
|
|
char *s = str;
|
|
s += sprintf(str, "CPU time used: kernel %.02f seconds, user %.02f seconds, total %.02f seconds.\n",
|
|
KernelTimeTotal / 1000000.0, UserTimeTotal / 1000000.0, CPUTimeTotal / 1000000.0) ;
|
|
s += sprintf(s, "Elapsed time %.02f seconds", (double) ClockTimeTotal / CLOCKS_PER_SEC) ;
|
|
if (NumberOfCPUs > 1 && ThreadCount > 1)
|
|
{
|
|
POV_ULONG cputotal = CPUTimeTotal * CLOCKS_PER_SEC / 1000000 ;
|
|
if (cputotal > ClockTimeTotal * 10 / 9)
|
|
s += sprintf(s, ", CPU vs elapsed time ratio %.02f", (double) cputotal / ClockTimeTotal) ;
|
|
}
|
|
s += sprintf(s, ".\n") ;
|
|
s += sprintf (s, "Render averaged %.02f PPS (%.02f PPS CPU time) over %u pixels using %u thread(s).\n",
|
|
(double) PixelsRendered * CLOCKS_PER_SEC / ClockTimeTotal, (double) PixelsRendered * 1000000 / CPUTimeTotal, PixelsRendered, ThreadCount) ;
|
|
copy_text_to_clipboard(str);
|
|
if (benchmark_mode)
|
|
{
|
|
// special case: we are running the benchmark because of a command-line request.
|
|
char fn[_MAX_PATH];
|
|
char ts[256];
|
|
time_t t = time(NULL);
|
|
|
|
strftime(ts, sizeof(ts), "%Y%m%d.%H%M%S", gmtime(&t));
|
|
sprintf(fn, "%sbenchmark-%s.txt", DocumentsPath, ts);
|
|
FILE *f = fopen(fn, "wt");
|
|
if (f != NULL)
|
|
{
|
|
int n = Get_Benchmark_Version();
|
|
|
|
fprintf(f, "%s", str);
|
|
strftime(str, sizeof(str), "%#c", gmtime(&t));
|
|
fprintf(f, "\nRender of benchmark version %x.%02x completed at %s UTC.\n", n / 256, n % 256, str);
|
|
fprintf(f, "----------------------------------------------------------------------------\n");
|
|
GenerateDumpMeta(true);
|
|
fwrite(DumpMeta, strlen(DumpMeta), 1, f);
|
|
fprintf(f, "povversion=%s\n", POV_RAY_VERSION) ;
|
|
fprintf(f, "compilerversion=%s\n", COMPILER_VER) ;
|
|
fprintf(f, "platformversion=%s\n", PVENGINE_VER) ;
|
|
fclose(f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strcat(str, "\nThese results have been placed in the clipboard.\n");
|
|
MessageBox (main_window, str, "Benchmark Complete.", MB_OK) ;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
message_printf ("----------------------------------------------------------------------------\n") ;
|
|
}
|
|
}
|
|
|
|
bool OkToStopRendering (void)
|
|
{
|
|
if (GetSession().BackendFailed())
|
|
return (true);
|
|
if (time (NULL) - SecondCountStart < CONFIRM_STOP_THRESHOLD)
|
|
return (true) ;
|
|
if (GetSession().GetRealTimeRaytracing() == true)
|
|
return (true);
|
|
if (MessageBox (main_window, "You've been running this render for quite a while - really cancel ?", "Stop rendering ?", MB_ICONQUESTION | MB_YESNO) == IDYES)
|
|
return (true) ;
|
|
return (false) ;
|
|
}
|
|
|
|
void menuhelp (UINT idCommand)
|
|
{
|
|
switch (idCommand)
|
|
{
|
|
case CM_FILEMENUHELP :
|
|
hh_aklink.pszKeywords = "File Menu" ;
|
|
break ;
|
|
|
|
case CM_EDITMENUHELP :
|
|
hh_aklink.pszKeywords = "Edit Menu" ;
|
|
break ;
|
|
|
|
case CM_SEARCHMENUHELP :
|
|
hh_aklink.pszKeywords = "Search Menu" ;
|
|
break ;
|
|
|
|
case CM_TEXTMENUHELP :
|
|
hh_aklink.pszKeywords = "Text Menu" ;
|
|
break ;
|
|
|
|
case CM_EDITORMENUHELP :
|
|
hh_aklink.pszKeywords = "Editor Menu" ;
|
|
break ;
|
|
|
|
case CM_RENDERMENUHELP :
|
|
hh_aklink.pszKeywords = "Render Menu" ;
|
|
break ;
|
|
|
|
case CM_OPTIONSMENUHELP :
|
|
hh_aklink.pszKeywords = "Options Menu" ;
|
|
break ;
|
|
|
|
case CM_TOOLSMENUHELP :
|
|
hh_aklink.pszKeywords = "Tools Menu" ;
|
|
break ;
|
|
|
|
case CM_WINDOWMENUHELP :
|
|
hh_aklink.pszKeywords = "Window Menu" ;
|
|
break ;
|
|
|
|
case CM_RENDERWINMENUHELP :
|
|
hh_aklink.pszKeywords = "Render Window Menu" ;
|
|
break ;
|
|
|
|
case CM_MESSAGEWINMENUHELP :
|
|
hh_aklink.pszKeywords = "Message Window Menu" ;
|
|
break ;
|
|
|
|
default :
|
|
hh_aklink.pszKeywords = NULL ;
|
|
break ;
|
|
}
|
|
if (hh_aklink.pszKeywords != NULL)
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
}
|
|
|
|
// example taken from MSDN documentation
|
|
DWORD GetDllVersion (LPCTSTR lpszDllName)
|
|
{
|
|
HINSTANCE hinstDll;
|
|
DWORD dwVersion = 0;
|
|
|
|
hinstDll = LoadLibrary(lpszDllName) ;
|
|
|
|
if (hinstDll)
|
|
{
|
|
DLLGETVERSIONPROC pDllGetVersion;
|
|
|
|
pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress (hinstDll, "DllGetVersion");
|
|
|
|
if (pDllGetVersion)
|
|
{
|
|
DLLVERSIONINFO dvi;
|
|
HRESULT hr;
|
|
|
|
ZeroMemory(&dvi, sizeof (dvi));
|
|
dvi.cbSize = sizeof (dvi);
|
|
|
|
hr = (*pDllGetVersion) (&dvi);
|
|
|
|
if (SUCCEEDED (hr))
|
|
dwVersion = MAKELONG (dvi.dwMajorVersion, dvi.dwMinorVersion);
|
|
}
|
|
|
|
FreeLibrary (hinstDll);
|
|
}
|
|
return dwVersion;
|
|
}
|
|
|
|
void getvars (ExternalVarStruct *v)
|
|
{
|
|
strcpy (v->command_line, command_line) ;
|
|
strcpy (v->source_file_name, source_file_name) ;
|
|
strcpy (v->lastRenderName, lastRenderName) ;
|
|
strcpy (v->lastRenderPath, lastRenderPath) ;
|
|
strcpy (v->lastQueuePath, lastQueuePath) ;
|
|
strcpy (v->lastSecondaryIniFilePath, lastSecondaryIniFilePath) ;
|
|
strcpy (v->DefaultRenderIniFileName, DefaultRenderIniFileName) ;
|
|
strcpy (v->SecondaryRenderIniFileName, SecondaryRenderIniFileName) ;
|
|
strcpy (v->SecondaryRenderIniFileSection, SecondaryRenderIniFileSection) ;
|
|
strcpy (v->ourPath, modulePath) ;
|
|
strcpy (v->engineHelpPath, engineHelpPath) ;
|
|
strcpy (v->rendererHelpPath, "") ;
|
|
strcpy (v->BinariesPath, BinariesPath) ;
|
|
strcpy (v->EngineIniFileName, EngineIniFileName) ;
|
|
strcpy (v->ToolIniFileName, ToolIniFileName) ;
|
|
memcpy (v->queued_files, queued_files, sizeof (v->queued_files)) ;
|
|
v->loadRerun = false ;
|
|
v->continueRerun = false ;
|
|
v->povray_return_code = povray_return_code ;
|
|
v->rendering = rendering ;
|
|
v->IsWin32 = true ;
|
|
v->IsW95UserInterface = IsW95UserInterface ;
|
|
v->running_demo = running_demo ;
|
|
v->debugging = debugging ;
|
|
v->isMaxiMinimized = false ;
|
|
v->newVersion = newVersion ;
|
|
v->use_threads = true ;
|
|
v->use_toolbar = use_toolbar ;
|
|
v->use_tooltips = use_tooltips ;
|
|
v->use_editors = use_editors ;
|
|
v->drop_to_editor = drop_to_editor ;
|
|
v->rendersleep = rendersleep ;
|
|
v->ExtensionsEnabled = ExtensionsEnabled ;
|
|
v->queued_file_count = queued_file_count > OLD_MAX_QUEUE ? OLD_MAX_QUEUE : queued_file_count ;
|
|
v->auto_render = auto_render ;
|
|
}
|
|
|
|
void setvars (ExternalVarStruct *v)
|
|
{
|
|
strncpy (command_line, v->command_line, sizeof (command_line) - 1) ;
|
|
SendMessage (toolbar_cmdline, WM_SETTEXT, 0, (LPARAM) command_line) ;
|
|
strncpy (source_file_name, v->source_file_name, sizeof (source_file_name) - 1) ;
|
|
strncpy (lastRenderName, v->lastRenderName, sizeof (lastRenderName) - 1) ;
|
|
strncpy (lastRenderPath, v->lastRenderPath, sizeof (lastRenderPath) - 1) ;
|
|
strncpy (lastQueuePath, v->lastQueuePath, sizeof (lastQueuePath) - 1) ;
|
|
strncpy (lastSecondaryIniFilePath, v->lastSecondaryIniFilePath, sizeof (lastSecondaryIniFilePath) - 1) ;
|
|
strncpy (DefaultRenderIniFileName, v->DefaultRenderIniFileName, sizeof (DefaultRenderIniFileName) - 1) ;
|
|
strncpy (SecondaryRenderIniFileName, v->SecondaryRenderIniFileName, sizeof (SecondaryRenderIniFileName) - 1) ;
|
|
strncpy (SecondaryRenderIniFileSection, v->SecondaryRenderIniFileSection, sizeof (SecondaryRenderIniFileSection) - 1) ;
|
|
}
|
|
|
|
bool HaveWin95OrLater (void)
|
|
{
|
|
return (version_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) ;
|
|
}
|
|
|
|
bool HaveWin98OrLater (void)
|
|
{
|
|
if (version_info.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
|
|
return (false) ;
|
|
if (version_info.dwMajorVersion < 4)
|
|
return (false) ;
|
|
if (version_info.dwMajorVersion > 4)
|
|
return (true) ;
|
|
return (version_info.dwMinorVersion > 0) ;
|
|
}
|
|
|
|
bool HaveNT4OrLater (void)
|
|
{
|
|
return (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT && version_info.dwMajorVersion >= 4) ;
|
|
}
|
|
|
|
bool HaveWin2kOrLater (void)
|
|
{
|
|
return (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT && version_info.dwMajorVersion >= 5) ;
|
|
}
|
|
|
|
bool HaveWinXPOrLater (void)
|
|
{
|
|
if (version_info.dwPlatformId != VER_PLATFORM_WIN32_NT || version_info.dwMajorVersion < 5)
|
|
return (false) ;
|
|
return (version_info.dwMajorVersion > 5 || (version_info.dwMajorVersion == 5 && version_info.dwMinorVersion > 0)) ;
|
|
}
|
|
|
|
bool HaveVistaOrLater (void)
|
|
{
|
|
return version_info.dwPlatformId == VER_PLATFORM_WIN32_NT && version_info.dwMajorVersion > 5;
|
|
}
|
|
|
|
void set_render_priority (unsigned priority)
|
|
{
|
|
switch (priority)
|
|
{
|
|
case CM_RENDERPRIORITY_BACKGROUND :
|
|
SetPriorityClass (GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN) ;
|
|
break ;
|
|
|
|
case CM_RENDERPRIORITY_LOW :
|
|
if (IsVista)
|
|
SetPriorityClass (GetCurrentProcess(), PROCESS_MODE_BACKGROUND_END);
|
|
SetPriorityClass (GetCurrentProcess(), IDLE_PRIORITY_CLASS) ;
|
|
break ;
|
|
|
|
case CM_RENDERPRIORITY_NORMAL :
|
|
if (IsVista)
|
|
SetPriorityClass (GetCurrentProcess(), PROCESS_MODE_BACKGROUND_END);
|
|
SetPriorityClass (GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS) ;
|
|
break ;
|
|
|
|
case CM_RENDERPRIORITY_HIGH :
|
|
if (IsVista)
|
|
SetPriorityClass (GetCurrentProcess(), PROCESS_MODE_BACKGROUND_END);
|
|
SetPriorityClass (GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS) ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
// we can't allow LoadBitmap to load our background bitmaps 'cause if we're running
|
|
// a 256-colour mode, it will map the incoming resource to 16 colours ...
|
|
// LoadImage () doesn't exist under Win32s, either. sigh.
|
|
HBITMAP NonBogusLoadBitmap (HINSTANCE hInst, LPSTR lpszBitmap)
|
|
{
|
|
void *p ;
|
|
HRSRC hres ;
|
|
HGLOBAL hg ;
|
|
HBITMAP hBitmap ;
|
|
|
|
if ((hres = FindResource (hInst, lpszBitmap, RT_BITMAP)) == NULL)
|
|
return (NULL) ;
|
|
if ((hg = LoadResource (hInst, hres)) == NULL)
|
|
return (NULL) ;
|
|
if ((p = LockResource (hg)) == NULL)
|
|
{
|
|
FreeResource (hg) ;
|
|
return (NULL) ;
|
|
}
|
|
hBitmap = lpDIBToBitmap (p, hPalApp) ;
|
|
FreeResource (hg) ;
|
|
return (hBitmap) ;
|
|
}
|
|
|
|
HBITMAP NonBogusLoadBitmapAndPalette (HINSTANCE hInst, LPSTR lpszBitmap)
|
|
{
|
|
void *p ;
|
|
HRSRC hres ;
|
|
HGLOBAL hg ;
|
|
HBITMAP hBitmap ;
|
|
|
|
if ((hres = FindResource (hInst, lpszBitmap, RT_BITMAP)) == NULL)
|
|
return (NULL) ;
|
|
if ((hg = LoadResource (hInst, hres)) == NULL)
|
|
return (NULL) ;
|
|
if ((p = LockResource (hg)) == NULL)
|
|
{
|
|
FreeResource (hg) ;
|
|
return (NULL) ;
|
|
}
|
|
hBitmap = lpDIBToBitmapAndPalette (p) ;
|
|
FreeResource (hg) ;
|
|
return (hBitmap) ;
|
|
}
|
|
|
|
// finds fist separator character in a path
|
|
char *findFirstPathSeparator (char *s)
|
|
{
|
|
size_t pos = strcspn(s, "\\/");
|
|
|
|
return pos >= strlen(s) ? NULL : s + pos;
|
|
}
|
|
|
|
// finds last separator character in a path
|
|
char *findLastPathSeparator (char *s)
|
|
{
|
|
char *s1 = strrchr (s, '\\');
|
|
char *s2 = strrchr (s1 ? s1 : s, '/');
|
|
|
|
return s2 ? s2 : s1;
|
|
}
|
|
|
|
// append separator character to a path, if not present already
|
|
// does not append to empty strings.
|
|
// does append to solitary drive letters; this isn't quite legit but as we don't
|
|
// support the use of drive references without a path (i.e. references that rely
|
|
// on the uniquely-DOS/Windows concept of a CWD for *each* mounted device), it
|
|
// doesn't really matter.
|
|
void appendPathSeparator (char *str)
|
|
{
|
|
if (str[0] != '\0') // only append to non-empty strings
|
|
if (!hasTrailingPathSeparator(str))
|
|
strcat(str, "\\");
|
|
}
|
|
|
|
// tests if path has trailing separator character
|
|
// does not return true if path is a solitary drive letter (e.g. "C:").
|
|
// the same consideration applies regarding relative drive references as
|
|
// mentioned in appendPathSeparator.
|
|
bool hasTrailingPathSeparator (const char *str)
|
|
{
|
|
return isPathSeparator(str[strlen (str) - 1]);
|
|
}
|
|
|
|
// strips trailing separator character from path
|
|
// will strip a trailing separator right after drive letter (e.g. "C:\").
|
|
// calling functions must be careful not to let this trip them up if they
|
|
// are passed any user-specified input.
|
|
void trimTrailingPathSeparator (char *str)
|
|
{
|
|
char *s = str + strlen (str) - 1 ;
|
|
if (isPathSeparator(*s))
|
|
*s = '\0' ;
|
|
}
|
|
|
|
// strips leading and trailing double-quotes from a string.
|
|
// does not check that both are present, just removes them
|
|
// if they are there. returns new start of string.
|
|
char *trimDoubleQuotes (char *str)
|
|
{
|
|
if (str[0] == '"')
|
|
str++;
|
|
char *s = str + strlen (str) - 1 ;
|
|
if (*s == '"')
|
|
*s = '\0' ;
|
|
return str;
|
|
}
|
|
|
|
// strips trailing separator character from path
|
|
void validatePath (char *s)
|
|
{
|
|
if (s [1] == ':' && strlen (s) < 4)
|
|
return ; // make sure we don't trim a trailing separator right after a drive letter (e.g. "C:\")
|
|
trimTrailingPathSeparator (s);
|
|
}
|
|
|
|
int joinPath (char *out, const char *path, const char *name)
|
|
{
|
|
strcpy (out, path) ;
|
|
appendPathSeparator (out);
|
|
strcat (out, name) ;
|
|
return ((int) strlen (out)) ;
|
|
}
|
|
|
|
bool reg_printf (bool useHKCU, char *keyName, char *valName, char *format, ...)
|
|
{
|
|
char str [2048] ;
|
|
HKEY hKey ;
|
|
va_list arg_ptr ;
|
|
|
|
if (strlen (format) > sizeof (str) - 256)
|
|
return (false) ;
|
|
if (RegCreateKeyEx (useHKCU ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
va_start (arg_ptr, format) ;
|
|
vsprintf (str, format, arg_ptr) ;
|
|
va_end (arg_ptr) ;
|
|
RegSetValueEx (hKey, valName, 0, REG_SZ, (BYTE *) str, (int) strlen (str) + 1) ;
|
|
RegCloseKey (hKey) ;
|
|
return (true) ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
// conditional version of reg_printf
|
|
bool cond_reg_printf (char *keyName, char *valName, char *format, ...)
|
|
{
|
|
char str [2048] ;
|
|
DWORD len = sizeof (str) ;
|
|
HKEY hKey ;
|
|
va_list arg_ptr ;
|
|
|
|
if (strlen (format) > sizeof (str) - 256)
|
|
return (false) ;
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, keyName, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
if (RegQueryValueEx (hKey, valName, 0, NULL, (BYTE *) str, &len) == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey (hKey) ;
|
|
// it already exists - if it doesn't have zero length we don't update it
|
|
if (str [0])
|
|
return (true) ;
|
|
}
|
|
else
|
|
RegCloseKey (hKey) ;
|
|
}
|
|
if (RegCreateKeyEx (HKEY_CURRENT_USER, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
va_start (arg_ptr, format) ;
|
|
vsprintf (str, format, arg_ptr) ;
|
|
va_end (arg_ptr) ;
|
|
RegSetValueEx (hKey, valName, 0, REG_SZ, (BYTE *) str, (int) strlen (str) + 1) ;
|
|
RegCloseKey (hKey) ;
|
|
return (true) ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
static bool reg_dword (char *keyName, char *valName, DWORD value)
|
|
{
|
|
HKEY hKey ;
|
|
|
|
if (RegCreateKeyEx (HKEY_CURRENT_USER, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
RegSetValueEx (hKey, valName, 0, REG_DWORD, (BYTE *) &value, 4) ;
|
|
RegCloseKey (hKey) ;
|
|
return (true) ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
char *GetInstallTime (void)
|
|
{
|
|
HKEY key ;
|
|
DWORD len ;
|
|
static char str [64] ;
|
|
|
|
len = sizeof (str) ;
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY, 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
if (RegQueryValueEx (key, INSTALLTIMEKEY, 0, NULL, (BYTE *) str, &len) == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey (key) ;
|
|
return (str) ;
|
|
}
|
|
RegCloseKey (key) ;
|
|
}
|
|
return (NULL) ;
|
|
}
|
|
|
|
bool checkRegKey (void)
|
|
{
|
|
char str [_MAX_PATH] ;
|
|
HKEY key ;
|
|
DWORD val;
|
|
DWORD len = sizeof (str) ;
|
|
FILETIME file_time ;
|
|
SYSTEMTIME system_time ;
|
|
|
|
if (GetInstallTime () == NULL)
|
|
{
|
|
GetSystemTime (&system_time) ;
|
|
if (SystemTimeToFileTime (&system_time, &file_time))
|
|
reg_printf (true, "Software\\" REGKEY, INSTALLTIMEKEY, "%I64u", ((__int64) file_time.dwHighDateTime << 32) | file_time.dwLowDateTime) ;
|
|
}
|
|
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
if (RegQueryValueEx (key, "Home", 0, NULL, (BYTE *) str, &len) != 0)
|
|
str[0] = '\0';
|
|
if (str [0] == '\0')
|
|
{
|
|
RegCloseKey (key) ;
|
|
return (false) ;
|
|
}
|
|
len = sizeof(val);
|
|
if (RegQueryValueEx (key, "FreshInstall", 0, NULL, (BYTE *) &val, &len) == 0)
|
|
{
|
|
FreshInstall = val != 0;
|
|
RegCloseKey (key) ;
|
|
if (FreshInstall && RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", 0, KEY_READ | KEY_SET_VALUE, &key) == ERROR_SUCCESS)
|
|
{
|
|
RegDeleteValue(key, "FreshInstall");
|
|
RegCloseKey (key) ;
|
|
}
|
|
}
|
|
else
|
|
RegCloseKey (key) ;
|
|
}
|
|
else
|
|
return (false) ;
|
|
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\CurrentVersion\\Windows", 0, KEY_READ | KEY_WRITE, &key) == ERROR_SUCCESS)
|
|
{
|
|
len = sizeof (str) ;
|
|
if (RegQueryValueEx (key, VERSIONVAL, 0, NULL, (BYTE *) str, &len) != 0 || strcmp (str, POV_RAY_VERSION) != 0)
|
|
RegSetValueEx (key, VERSIONVAL, 0, REG_SZ, (BYTE *) POV_RAY_VERSION, (int) strlen (POV_RAY_VERSION) + 1) ;
|
|
RegCloseKey (key) ;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool getHome (void)
|
|
{
|
|
HKEY key ;
|
|
DWORD len ;
|
|
|
|
if (debugging)
|
|
debug_output ("querying registry\n") ;
|
|
DocumentsPath [0] = BinariesPath [0] = '\0' ;
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
len = sizeof (LastInferredHome) ;
|
|
RegQueryValueEx (key, "LastInferredHome", 0, NULL, (BYTE *) LastInferredHome, &len) ;
|
|
|
|
len = sizeof (BinariesPath) ;
|
|
RegQueryValueEx (key, "Home", 0, NULL, (BYTE *) BinariesPath, &len) ;
|
|
if (debugging && BinariesPath[0] != '\0')
|
|
debug_output("Win32 getHome() succeeded (HKCU::Home), BinariesPath is '%s'\n", BinariesPath) ;
|
|
|
|
len = sizeof (DocumentsPath) ;
|
|
RegQueryValueEx (key, "DocPath", 0, NULL, (BYTE *) DocumentsPath, &len) ;
|
|
if (debugging && DocumentsPath[0] != '\0')
|
|
debug_output("Win32 getHome() succeeded (HKCU::DocPath), DocumentsPath is '%s'\n", DocumentsPath) ;
|
|
|
|
RegCloseKey (key) ;
|
|
return (BinariesPath[0] != '\0') ;
|
|
}
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
len = sizeof (BinariesPath) ;
|
|
RegQueryValueEx (key, "Home", 0, NULL, (BYTE *) BinariesPath, &len) ;
|
|
RegCloseKey (key) ;
|
|
if (debugging && BinariesPath[0] != '\0')
|
|
debug_output("Win32 getHome() succeeded (HKLM::Home), BinariesPath is '%s'\n", BinariesPath) ;
|
|
return (BinariesPath[0] != '\0') ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
bool inferHome (void)
|
|
{
|
|
char exePath [_MAX_PATH] ;
|
|
char *s ;
|
|
|
|
if (GetModuleFileName (NULL, exePath, _MAX_PATH) == 0)
|
|
return (false) ;
|
|
|
|
// find path component
|
|
if ((s = findLastPathSeparator (exePath)) == NULL)
|
|
return (false) ;
|
|
*s = '\0' ;
|
|
|
|
// now step up one directory
|
|
if ((s = findLastPathSeparator (exePath)) == NULL)
|
|
return (false) ;
|
|
*++s = '\0' ;
|
|
|
|
// now look for some standard directories
|
|
strcpy (s, "help") ;
|
|
if (!dirExists (exePath))
|
|
{
|
|
strcpy (s, "sounds") ;
|
|
if (!dirExists (exePath))
|
|
{
|
|
strcpy (s, "tiles") ;
|
|
if (!dirExists (exePath))
|
|
return (false) ;
|
|
}
|
|
}
|
|
|
|
*s = '\0' ;
|
|
strcpy (BinariesPath, exePath) ;
|
|
homeInferred = true ;
|
|
return (true) ;
|
|
}
|
|
|
|
string get36Home(void)
|
|
{
|
|
char str[_MAX_PATH];
|
|
HKEY key ;
|
|
DWORD len = sizeof(str);
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\" REGKEY "\\v3.6\\Windows", 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
if (RegQueryValueEx (key, "Home", 0, NULL, (BYTE *) str, &len) == 0)
|
|
{
|
|
RegCloseKey (key) ;
|
|
appendPathSeparator(str);
|
|
return string(str);
|
|
}
|
|
RegCloseKey (key) ;
|
|
}
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\v3.6\\Windows", 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
if (RegQueryValueEx (key, "Home", 0, NULL, (BYTE *) str, &len) == 0)
|
|
{
|
|
RegCloseKey (key) ;
|
|
appendPathSeparator(str);
|
|
return string(str);
|
|
}
|
|
RegCloseKey (key) ;
|
|
}
|
|
return string();
|
|
}
|
|
|
|
bool copy36EditSettings(void)
|
|
{
|
|
HKEY hKeySrc ;
|
|
HKEY hKeyDst ;
|
|
DWORD result ;
|
|
HINSTANCE hLib ;
|
|
shCopyType *shCopyKey ;
|
|
|
|
if ((hLib = LoadLibrary ("shlwapi.dll")) == NULL)
|
|
return (false) ;
|
|
shCopyKey = (shCopyType *) GetProcAddress (hLib, "SHCopyKeyA") ;
|
|
if (shCopyKey == NULL)
|
|
{
|
|
FreeLibrary (hLib) ;
|
|
return (false) ;
|
|
}
|
|
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\v3.6", 0, KEY_READ, &hKeySrc) != ERROR_SUCCESS)
|
|
{
|
|
FreeLibrary (hLib) ;
|
|
return (false) ;
|
|
}
|
|
|
|
if (RegCreateKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit", 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKeyDst, NULL) != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey (hKeySrc) ;
|
|
FreeLibrary (hLib) ;
|
|
return (false) ;
|
|
}
|
|
|
|
result = shCopyKey (hKeySrc, "POV-Edit", hKeyDst, NULL) ;
|
|
RegCloseKey (hKeySrc) ;
|
|
RegCloseKey (hKeyDst) ;
|
|
FreeLibrary (hLib) ;
|
|
|
|
return (result == ERROR_SUCCESS) ;
|
|
}
|
|
|
|
bool checkEditKey36 (void)
|
|
{
|
|
HKEY key ;
|
|
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\v3.6\\POV-Edit", 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey (key) ;
|
|
return (true) ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
bool checkEditKey37 (void)
|
|
{
|
|
HKEY key ;
|
|
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit", 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey (key) ;
|
|
return (true) ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
// called if either our registry entries don't seem to be set up, or if they do exist and
|
|
// the FreshInstall option is set in the registry.
|
|
bool CloneOptions (void)
|
|
{
|
|
if (debugging)
|
|
debug_output("attempting to create registry entries\n") ;
|
|
|
|
// don't do this if we're being called as a result of the FreshInstall registry setting
|
|
if (!FreshInstall)
|
|
{
|
|
if (!reg_printf (true, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", "Home", "%s", BinariesPath))
|
|
return (false) ;
|
|
if (!homeInferred)
|
|
reg_printf (true, "Software\\" REGKEY "\\CurrentVersion\\Windows", "Home", "%s", BinariesPath) ;
|
|
}
|
|
|
|
reg_printf (true, "Software\\" REGKEY "\\CurrentVersion\\Windows", VERSIONVAL, "%s", POV_RAY_VERSION) ;
|
|
|
|
cond_reg_printf ("Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit\\Open", "Open0", "%sChanges.txt,1,1,0,0,8,2", DocumentsPath) ;
|
|
cond_reg_printf ("Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit\\Recent", "Recent0", "%sChanges.txt,1,1,0,0,8,2", DocumentsPath) ;
|
|
cond_reg_printf ("Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit\\Open", "Open1", "%sRevision.txt,1,1,0,0,8,2", DocumentsPath) ;
|
|
cond_reg_printf ("Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit\\Recent", "Recent1", "%sRevision.txt,1,1,0,0,8,2", DocumentsPath) ;
|
|
cond_reg_printf ("Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit\\Open", "Open2", "%sscenes\\advanced\\biscuit.pov,1,1,0,6,8,2", DocumentsPath) ;
|
|
cond_reg_printf ("Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit\\Recent", "Recent2", "%sscenes\\advanced\\biscuit.pov,1,1,0,6,8,2", DocumentsPath) ;
|
|
cond_reg_printf ("Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit\\Open", "Open3", "%sscenes\\advanced\\woodbox.pov,1,1,0,6,8,2", DocumentsPath) ;
|
|
cond_reg_printf ("Software\\" REGKEY "\\" REGVERKEY "\\POV-Edit\\Recent", "Recent3", "%sscenes\\advanced\\woodbox.pov,1,1,0,6,8,2", DocumentsPath) ;
|
|
|
|
return (true) ;
|
|
}
|
|
|
|
int parse_commandline (char *s)
|
|
{
|
|
char *prevWord = NULL ;
|
|
char inQuote = '\0' ;
|
|
static char str [_MAX_PATH * 3] ;
|
|
static char filename [_MAX_PATH] ;
|
|
|
|
argc = 0 ;
|
|
GetModuleFileName (hInstance, filename, sizeof (filename) - 1) ;
|
|
argv [argc++] = filename ;
|
|
s = strncpy (str, s, sizeof (str) - 1) ;
|
|
while (*s)
|
|
{
|
|
switch (*s)
|
|
{
|
|
case '"' :
|
|
case '\'' :
|
|
if (inQuote)
|
|
{
|
|
if (*s == inQuote)
|
|
inQuote = 0 ;
|
|
}
|
|
else
|
|
{
|
|
inQuote = *s ;
|
|
if (prevWord == NULL)
|
|
prevWord = s ;
|
|
}
|
|
break ;
|
|
|
|
case ' ' :
|
|
case '\t' :
|
|
if (!inQuote)
|
|
{
|
|
if (prevWord != NULL)
|
|
{
|
|
*s = '\0' ;
|
|
argv [argc++] = prevWord ;
|
|
prevWord = NULL ;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
default :
|
|
if (prevWord == NULL)
|
|
prevWord = s ;
|
|
break ;
|
|
}
|
|
if (argc >= MAX_ARGV - 1)
|
|
break ;
|
|
s++ ;
|
|
}
|
|
if (prevWord != NULL && argc < MAX_ARGV - 1)
|
|
argv [argc++] = prevWord ;
|
|
argv [argc] = NULL ;
|
|
return (argc) ;
|
|
}
|
|
|
|
int InstallSettings (char *binpath, char *docpath, bool quiet)
|
|
{
|
|
char base [_MAX_PATH] ;
|
|
char str [_MAX_PATH] ;
|
|
char *s ;
|
|
|
|
// we attempt to infer the install dir if it's not supplied
|
|
if (binpath == NULL)
|
|
{
|
|
if (_getcwd (base, sizeof (base) - 1) == NULL)
|
|
{
|
|
if (!quiet)
|
|
MessageBox (NULL, "Could not get current directory - cannot infer home path. Please supply it on the command-line",
|
|
"POV-Ray for Windows - running INSTALL option", MB_OK | MB_ICONSTOP) ;
|
|
return 5 ;
|
|
}
|
|
if (strlen (base) < 3 || (strlen (base) == 3 && base [1] == ':' && isPathSeparator(base [2])))
|
|
{
|
|
if (!quiet)
|
|
{
|
|
sprintf (str, "Current dir '%s' is root - cannot infer home path. Please supply it on the command-line.", base) ;
|
|
MessageBox (NULL, str, "POV-Ray for Windows - running INSTALL option", MB_OK | MB_ICONSTOP) ;
|
|
}
|
|
return 10 ;
|
|
}
|
|
// the strlen test covers the case where base is "\\" (i.e. a network path) or a bare drive (e.g. "c:").
|
|
if (!StripPathComponent (base, 1) || strlen(base) < 3)
|
|
{
|
|
if (!quiet)
|
|
MessageBox (NULL, "Cannot infer home path. Please supply it on the command-line.",
|
|
"POV-Ray for Windows - running INSTALL option", MB_OK | MB_ICONSTOP) ;
|
|
return 15 ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strcpy (str, binpath) ;
|
|
s = trimDoubleQuotes(str);
|
|
validatePath (s) ;
|
|
if (GetFullPathName (s, sizeof (base), base, NULL) == 0)
|
|
{
|
|
sprintf (str, "GetFullPathName() for '%s' failed [0x%08x]", s, GetLastError ()) ;
|
|
MessageBox (NULL, str, "POV-Ray for Windows - running INSTALL option", MB_OK | MB_ICONSTOP) ;
|
|
}
|
|
}
|
|
if (!dirExists (base))
|
|
{
|
|
if (!quiet)
|
|
{
|
|
sprintf (str, "Could not stat directory '%s'", base) ;
|
|
MessageBox (NULL, str, "POV-Ray for Windows - running INSTALL option", MB_OK | MB_ICONSTOP) ;
|
|
}
|
|
return 20 ;
|
|
}
|
|
|
|
if (docpath != NULL)
|
|
{
|
|
if (!dirExists(docpath))
|
|
{
|
|
// if the path doesn't exist and quiet is selected, we continue, assuming that
|
|
// by the time povray is ready to be used, it will either exist or be able to be
|
|
// created. note that we do auto-create the path if possible (i.e. the parent
|
|
// directory exists and is writable by the user who launches POV-Ray).
|
|
if (!quiet)
|
|
if (MessageBox (NULL, "Could not verify supplied user files path: use it anyway?\n(Selecting NO will exit.)", "POV-Ray for Windows - running INSTALL option", MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
|
|
return 30;
|
|
}
|
|
reg_printf (true, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", "DocPath", "%s\\", docpath);
|
|
}
|
|
|
|
if (!reg_printf (true, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", "Home", "%s\\", base))
|
|
{
|
|
if (!quiet)
|
|
MessageBox (NULL, "Failed to write to HKCU in registry", "POV-Ray for Windows - running INSTALL option", MB_OK | MB_ICONSTOP) ;
|
|
return 35 ;
|
|
}
|
|
|
|
// it's ok for this to fail as they may not have administrative rights
|
|
reg_printf (false, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", "Home", "%s\\", base) ;
|
|
|
|
if (!quiet)
|
|
{
|
|
sprintf (str, "[Home path is %s]\n\nSuccess!", base) ;
|
|
MessageBox (NULL, str, "POV-Ray for Windows - running INSTALL option", MB_OK | MB_ICONINFORMATION) ;
|
|
}
|
|
return (0) ;
|
|
}
|
|
|
|
char *GetExceptionDescription (DWORD code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case EXCEPTION_ACCESS_VIOLATION :
|
|
return ("a memory access violation") ;
|
|
|
|
case EXCEPTION_DATATYPE_MISALIGNMENT :
|
|
return ("a datatype misalignment") ;
|
|
|
|
case EXCEPTION_FLT_DENORMAL_OPERAND :
|
|
return ("a denormal floating point operand") ;
|
|
|
|
case EXCEPTION_FLT_DIVIDE_BY_ZERO :
|
|
return ("a floating point divide by zero") ;
|
|
|
|
case EXCEPTION_FLT_INEXACT_RESULT :
|
|
return ("an inexact floating-point result") ;
|
|
|
|
case EXCEPTION_FLT_INVALID_OPERATION :
|
|
return ("an invalid floating-point operation") ;
|
|
|
|
case EXCEPTION_FLT_OVERFLOW :
|
|
return ("a floating-point overflow") ;
|
|
|
|
case EXCEPTION_FLT_STACK_CHECK :
|
|
return ("a floating-point stack over/underflow") ;
|
|
|
|
case EXCEPTION_FLT_UNDERFLOW :
|
|
return ("a floating-point underflow") ;
|
|
|
|
case EXCEPTION_INT_DIVIDE_BY_ZERO :
|
|
return ("an integer divide by zero") ;
|
|
|
|
case EXCEPTION_INT_OVERFLOW :
|
|
return ("an integer overflow") ;
|
|
|
|
case EXCEPTION_PRIV_INSTRUCTION :
|
|
return ("the execution of a privileged instruction") ;
|
|
|
|
case EXCEPTION_IN_PAGE_ERROR :
|
|
return ("a page error") ;
|
|
|
|
case EXCEPTION_ILLEGAL_INSTRUCTION :
|
|
return ("the execution of an illegal instruction") ;
|
|
|
|
case EXCEPTION_NONCONTINUABLE_EXCEPTION :
|
|
return ("a continuation after a noncontinuable exception") ;
|
|
|
|
case EXCEPTION_STACK_OVERFLOW :
|
|
return ("a stack overflow") ;
|
|
|
|
case EXCEPTION_INVALID_DISPOSITION :
|
|
return ("an invalid disposition") ;
|
|
|
|
case EXCEPTION_GUARD_PAGE :
|
|
return ("a guard page exception") ;
|
|
|
|
case EXCEPTION_INVALID_HANDLE :
|
|
return ("an invalid handle exception") ;
|
|
|
|
default :
|
|
return NULL ;
|
|
}
|
|
}
|
|
|
|
#if POV_RAY_IS_OFFICIAL == 1
|
|
// this pulls in the code for update checks and crash dump submission.
|
|
// it is only used in official releases made by the POV-Ray developers,
|
|
// so the source is not included in the public distribution.
|
|
#include "official.h"
|
|
#else
|
|
LONG WINAPI ExceptionHandler(struct _EXCEPTION_POINTERS* ExceptionInfo)
|
|
{
|
|
char *s;
|
|
long timestamp = _time32(NULL);
|
|
PCONTEXT c ;
|
|
static char str[2048] ;
|
|
static boost::mutex mtx;
|
|
boost::mutex::scoped_lock l(mtx);
|
|
|
|
c = ExceptionInfo->ContextRecord ;
|
|
const char *desc = GetExceptionDescription(ExceptionInfo->ExceptionRecord->ExceptionCode);
|
|
if (desc == NULL)
|
|
desc = "an" ;
|
|
sprintf (str,
|
|
"Unfortunately, it appears that %s at address 0x%p has caused this unofficial POV-Ray build to crash. "
|
|
"This dialog will allow you to choose whether or not a dump file (useful for diagnostics) is written.\n\n"
|
|
"NOTE: If you were running a render, you should be able to recover the part that had already been generated. "
|
|
"See the 'Continue' (+c) option in the documentation for more information about this.\n\n"
|
|
"Would you like to write a dump file?",
|
|
desc,
|
|
#ifdef _WIN64
|
|
c->Rip);
|
|
#else
|
|
c->Eip);
|
|
#endif
|
|
DWORD result = MessageBox (NULL, str, "POV-Ray for Windows", MB_ICONSTOP | MB_TOPMOST | MB_TASKMODAL | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND) ;
|
|
if (result == IDYES)
|
|
{
|
|
// write a full dump first, then a minidump. it's no big deal if the full dump write fails.
|
|
WriteDump(ExceptionInfo, true, timestamp);
|
|
if ((s = WriteDump(ExceptionInfo, false, timestamp)) != NULL)
|
|
{
|
|
MessageBox (main_window, "The dump was successfully saved.", "POV-Ray for Windows", MB_OK) ;
|
|
sprintf(str, "/select,%s", s);
|
|
ShellExecute (NULL, NULL, "explorer.exe", str, NULL, SW_SHOWNORMAL) ;
|
|
ExitProcess (1) ;
|
|
}
|
|
}
|
|
else
|
|
MessageBox (main_window, "POV-Ray will now exit.", "POV-Ray for Windows", MB_OK) ;
|
|
ExitProcess (1) ;
|
|
return (EXCEPTION_CONTINUE_SEARCH) ; // make compiler happy
|
|
}
|
|
#endif // POV_RAY_IS_OFFICIAL
|
|
|
|
int execute_tool (char *s)
|
|
{
|
|
int error ;
|
|
STARTUPINFO startupInfo ;
|
|
PROCESS_INFORMATION procInfo ;
|
|
|
|
if (strlen (s) == 0)
|
|
{
|
|
PovMessageBox ("No command to run!", "Tool Error") ;
|
|
return (0) ;
|
|
}
|
|
|
|
if (*s == '$')
|
|
{
|
|
switch (toupper (s[1]))
|
|
{
|
|
case 'S' :
|
|
s += 2 ;
|
|
while (*s == ' ')
|
|
s++ ;
|
|
if (strlen (s) == 0)
|
|
{
|
|
PovMessageBox ("No file to open!", "Tool Error") ;
|
|
return (0) ;
|
|
}
|
|
if ((error = PtrToInt (ShellExecute (main_window, "open", s, NULL, NULL, SW_SHOWNORMAL))) <= 32)
|
|
PovMessageBox ("ShellExecute failed", "Tool Error") ;
|
|
return (error) ;
|
|
|
|
case 'E' :
|
|
s += 2 ;
|
|
while (*s == ' ')
|
|
s++ ;
|
|
if (strlen (s) == 0)
|
|
{
|
|
PovMessageBox ("No file to open!", "Tool Error") ;
|
|
return (0) ;
|
|
}
|
|
return EditOpenFile(s) ? 0 : 1;
|
|
}
|
|
}
|
|
|
|
startupInfo.cb = sizeof (STARTUPINFO) ;
|
|
startupInfo.lpReserved = 0 ;
|
|
startupInfo.lpDesktop = NULL ;
|
|
startupInfo.lpTitle = NULL ;
|
|
startupInfo.dwX = 0 ;
|
|
startupInfo.dwY = 0 ;
|
|
startupInfo.dwXSize = 0 ;
|
|
startupInfo.dwYSize = 0 ;
|
|
startupInfo.dwXCountChars = 0 ;
|
|
startupInfo.dwYCountChars = 0 ;
|
|
startupInfo.dwFillAttribute = 0 ;
|
|
startupInfo.dwFlags = STARTF_USESHOWWINDOW ;
|
|
startupInfo.wShowWindow = SW_SHOW ;
|
|
startupInfo.cbReserved2 = 0 ;
|
|
startupInfo.lpReserved2 = 0 ;
|
|
|
|
if (CreateProcess (NULL, s, NULL, NULL, false, 0, NULL, NULL, &startupInfo, &procInfo) == false)
|
|
{
|
|
error = GetLastError () ;
|
|
PovMessageBox ("Could not run program", "Tool Error") ;
|
|
return (error) ;
|
|
}
|
|
|
|
// clean up
|
|
CloseHandle (procInfo.hProcess) ;
|
|
CloseHandle (procInfo.hThread) ;
|
|
|
|
return (0) ;
|
|
}
|
|
|
|
void RenderInsertMenu (void)
|
|
{
|
|
int val ;
|
|
char str [_MAX_PATH] ;
|
|
char *s1 ;
|
|
char *s2 ;
|
|
FILE *f ;
|
|
|
|
stop_rendering = false ;
|
|
sprintf (str, "%sInsert Menu\\Images.ini", DocumentsPath) ;
|
|
if ((f = fopen (str, "rt")) == NULL)
|
|
{
|
|
MessageBox (main_window, "Cannot open 'Images.ini' in Insert Menu directory", "Insert Menu Images", MB_OK | MB_ICONEXCLAMATION) ;
|
|
return ;
|
|
}
|
|
InsertMenuSection = 0 ;
|
|
InsertMenuSections.clear();
|
|
while (fgets (str, sizeof (str), f) != NULL)
|
|
{
|
|
s1 = clean (str) ;
|
|
if (*s1 == '[')
|
|
{
|
|
if ((s2 = strchr (s1, ']')) != NULL)
|
|
{
|
|
*s2 = '\0' ;
|
|
val = atoi (++s1) ;
|
|
if (val == 0)
|
|
continue ;
|
|
InsertMenuSections.push_back(val);
|
|
if (InsertMenuSections.size() == MAX_INSERT_MENU_SECTIONS)
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
fclose (f) ;
|
|
if (InsertMenuSections.empty())
|
|
{
|
|
MessageBox (main_window, "No insert menu sections found in 'Images.ini'", "Insert Menu Images", MB_OK | MB_ICONSTOP) ;
|
|
return ;
|
|
}
|
|
sprintf (str, "There are %u insert menu images to render. Press OK to start rendering these now.\n\n"
|
|
"Once the render has started you can press the 'Stop Rendering' button to cancel the render job.", (unsigned int) InsertMenuSections.size()) ;
|
|
if (MessageBox (main_window, str, "Insert Menu Images", MB_OKCANCEL | MB_ICONINFORMATION) == IDCANCEL)
|
|
return ;
|
|
PVEnableMenuItem (CM_RENDERSHOW, MF_GRAYED) ;
|
|
update_menu_for_render (true) ;
|
|
rendering_insert_menu = was_insert_render = no_status_output = true ;
|
|
EditShowMessages (true) ;
|
|
CalculateClientWindows (true) ;
|
|
ShowWindow (message_window, SW_SHOW) ;
|
|
sprintf (str, "%sInsert Menu", DocumentsPath) ;
|
|
SetCurrentDirectory (str) ;
|
|
StartInsertRender = true ;
|
|
}
|
|
|
|
int GetUCS2String(POVMSObjectPtr object, POVMSType key, char *result, int *maxlen)
|
|
{
|
|
UCS2 *str = new UCS2 [*maxlen] ;
|
|
int err = POVMSUtil_GetUCS2String (object, key, str, maxlen) ;
|
|
if (err == kNoErr)
|
|
{
|
|
string abc = UCS2toASCIIString (str) ;
|
|
strcpy (result, abc.c_str ()) ;
|
|
}
|
|
delete str ;
|
|
return err ;
|
|
}
|
|
|
|
void ShowIsPaused(void)
|
|
{
|
|
if (GetSession().BackendFailed() == false && rendersleep == false)
|
|
{
|
|
SleepTimeStart = clock () ;
|
|
status_printf (StatusPPS, PPS_String (GetSession().GetPixelsRendered(), ClockTimeTotal / CLOCKS_PER_SEC)) ;
|
|
say_status_message (StatusPPS, "PAUSED") ;
|
|
rendersleep = true ;
|
|
SendMessage (toolbar_window, TB_CHECKBUTTON, (WPARAM) CM_RENDERSLEEP, MAKELONG (1, 0)) ;
|
|
}
|
|
}
|
|
|
|
char *getCommandLine (void)
|
|
{
|
|
HKEY key ;
|
|
static char str [2048] ;
|
|
DWORD len = sizeof (str) ;
|
|
|
|
str [0] = '\0' ;
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
RegQueryValueEx (key, "Command Line", 0, NULL, (BYTE *) str, &len) ;
|
|
RegCloseKey (key) ;
|
|
}
|
|
return (str) ;
|
|
}
|
|
|
|
void setRunOnce (void)
|
|
{
|
|
#ifndef NOSETRUNONCE
|
|
char str [_MAX_PATH] ;
|
|
HKEY key ;
|
|
DWORD result ;
|
|
|
|
if (RegCreateKeyEx (HKEY_CURRENT_USER,
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
|
|
0,
|
|
"",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&key,
|
|
&result) == ERROR_SUCCESS)
|
|
{
|
|
GetModuleFileName (hInstance, str, sizeof (str)) ;
|
|
RegSetValueEx (key, "POV-Ray for Windows", 0, REG_SZ, (BYTE *) str, (int) strlen (str) + 1) ;
|
|
RegCloseKey (key) ;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void display_cleanup (bool unconditional)
|
|
{
|
|
if (unconditional)
|
|
{
|
|
gDisplay.reset();
|
|
return;
|
|
}
|
|
Display *d = gDisplay.get();
|
|
if (d == NULL)
|
|
return;
|
|
WinDisplay *wd = dynamic_cast<WinDisplay *>(d);
|
|
if (wd == NULL)
|
|
return;
|
|
if (wd->GetWidth() != render_width || wd->GetHeight() != render_height)
|
|
{
|
|
gDisplay.reset();
|
|
return;
|
|
}
|
|
wd->Clear();
|
|
}
|
|
|
|
void cancel_render (void)
|
|
{
|
|
stop_rendering = true ;
|
|
if (GetSession().BackendFailed())
|
|
{
|
|
render_stopped() ;
|
|
return;
|
|
}
|
|
if (GetSession().CancelRender() == vfeNotRunning)
|
|
{
|
|
// we possibly have an anamolous situation
|
|
MessageBox (NULL, "Warning: had to force state to stopped", "Cancel Render", MB_OK | MB_ICONEXCLAMATION) ;
|
|
render_stopped() ;
|
|
}
|
|
}
|
|
|
|
// TODO: we have a problem here - if the parse completes very quickly, it's
|
|
// possible for the VFE code to process the change to rendering mode before
|
|
// we exit start_rendering() [note that the VFE worker thread runs at a higher
|
|
// priority than the main UI thread]. as a result, on occasion, the VFE code
|
|
// will call the display's Show() method at the same time as we are executing
|
|
// display_cleanup(). display_cleanup() can cause the value of the pointer in
|
|
// gDisplay to change, and potentially destroy the old one ...
|
|
bool start_rendering (bool ignore_source_file)
|
|
{
|
|
int threadCount = ThreadCount ;
|
|
char str [sizeof (command_line)] ;
|
|
char path [_MAX_PATH] ;
|
|
char file [_MAX_PATH] ;
|
|
vfeSession& Session (GetSession());
|
|
|
|
if (Session.BackendFailed())
|
|
{
|
|
MessageBox (main_window, "The render backend has shut down due to an error: please re-start POV-Ray", "Error", MB_OK | MB_ICONSTOP) ;
|
|
return false;
|
|
}
|
|
|
|
Session.Clear();
|
|
Session.ClearOptions();
|
|
if (!keep_messages)
|
|
clear_messages(false);
|
|
|
|
if (running_benchmark)
|
|
threadCount = benchmark_mode || benchmark_multithread ? ThreadCount : 1 ;
|
|
|
|
ErrorOccurred = ErrorNotified = false ;
|
|
ErrorMessage.clear() ;
|
|
ErrorFilename.clear() ;
|
|
status_buffer [0] = '\0' ;
|
|
povray_return_code = 0 ;
|
|
rendersleep = false ;
|
|
SleepTimeTotal = 0 ;
|
|
render_anim_count = 0 ;
|
|
rendering_animation = false ;
|
|
stop_rendering = false ;
|
|
was_insert_render = false ;
|
|
first_frame = true ;
|
|
render_width = render_height = 0 ;
|
|
KernelTimeStart = GetCPUTime (true, false) ;
|
|
UserTimeStart = GetCPUTime (false, true) ;
|
|
CPUTimeTotal = KernelTimeTotal = UserTimeTotal = 0 ;
|
|
ClockTimeStart = clock () ;
|
|
SecondCountStart = time (NULL) ;
|
|
SleepTimeTotal = ClockTimeTotal = 0 ;
|
|
status_printf (StatusPPS, "") ;
|
|
say_status_message (StatusRendertime, "") ;
|
|
output_to_file = false ;
|
|
InputFileName.clear();
|
|
LastRenderPercentage = 0;
|
|
|
|
SendMessage (StatusPanelItems [IDC_STATUS_PROGRESS].hwnd, PBM_SETPOS, 0, 0) ;
|
|
|
|
say_status_message (StatusMessage, "") ;
|
|
|
|
PVEnableMenuItem (CM_RENDERSHOW, MF_GRAYED) ;
|
|
update_menu_for_render (true) ;
|
|
SendMessage (toolbar_combobox, CB_GETLBTEXT, SendMessage (toolbar_combobox, CB_GETCURSEL, 0, 0), (LPARAM) SecondaryRenderIniFileSection) ;
|
|
|
|
if (!StartInsertRender)
|
|
{
|
|
if (!temp_render_region)
|
|
if (RegionStr [0] != '\0' && strstr (command_line, RegionStr + 1) == NULL)
|
|
RegionStr [0] = '\0' ;
|
|
}
|
|
|
|
if (save_settings)
|
|
{
|
|
if (restore_command_line)
|
|
{
|
|
strcpy (str, command_line) ;
|
|
strcpy (command_line, old_command_line) ;
|
|
}
|
|
write_INI_settings (true) ;
|
|
if (restore_command_line)
|
|
strcpy (command_line, str) ;
|
|
EditSaveState () ;
|
|
}
|
|
|
|
try
|
|
{
|
|
// set up render options
|
|
vfeRenderOptions opts ;
|
|
|
|
opts.SetThreadCount (threadCount);
|
|
opts.AddINI (DefaultRenderIniFileName) ;
|
|
|
|
if (AutoAppendPaths || homeInferred)
|
|
{
|
|
sprintf (str, "%sinclude", DocumentsPath) ;
|
|
opts.AddLibraryPath (str);
|
|
opts.AddLibraryPath (FontPath);
|
|
}
|
|
|
|
if (!StartInsertRender)
|
|
{
|
|
if (running_demo == 0)
|
|
{
|
|
if (SecondaryRenderIniFileName [0] != '\0')
|
|
{
|
|
if (!hasTrailingPathSeparator(SecondaryRenderIniFileName))
|
|
{
|
|
splitpath (SecondaryRenderIniFileName, NULL, str) ;
|
|
if (str [0] != '\0')
|
|
{
|
|
if (SecondaryRenderIniFileSection [0] == '\0')
|
|
wrapped_printf ("Preset INI file is '%s'.", SecondaryRenderIniFileName) ;
|
|
else
|
|
wrapped_printf ("Preset INI file is '%s', section is '%s'.", SecondaryRenderIniFileName, SecondaryRenderIniFileSection) ;
|
|
sprintf (str, "%s%s", SecondaryRenderIniFileName, SecondaryRenderIniFileSection) ;
|
|
opts.AddINI (str);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!ignore_source_file && strlen (source_file_name) != 0)
|
|
{
|
|
wrapped_printf ("Preset source file is '%s'.", source_file_name) ;
|
|
splitpath (source_file_name, dir, NULL) ;
|
|
SetCurrentDirectory (dir) ;
|
|
sprintf (str, "%s\\povray.ini", dir) ;
|
|
if (fileExists (str))
|
|
{
|
|
wrapped_printf ("File '%s' exists - merging it.", str) ;
|
|
opts.AddINI (str);
|
|
}
|
|
switch (get_file_type (source_file_name))
|
|
{
|
|
case filePOV :
|
|
case fileINC :
|
|
opts.SetSourceFile (source_file_name);
|
|
break ;
|
|
|
|
case fileINI :
|
|
opts.AddINI (source_file_name);
|
|
break ;
|
|
|
|
default :
|
|
message_printf ("POV-Ray for Windows doesn't recognize this file type ; assuming POV source.\n") ;
|
|
opts.SetSourceFile (source_file_name);
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (running_benchmark)
|
|
{
|
|
opts.AddINI (demo_ini_name) ;
|
|
opts.SetSourceFile (demo_file_name) ;
|
|
if (strlen (demo_file_name) != 0)
|
|
{
|
|
splitpath (demo_file_name, dir, NULL) ;
|
|
SetCurrentDirectory (dir) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RegionStr [0] != 0)
|
|
{
|
|
if (strstr (command_line, RegionStr) == NULL && strstr (command_line, RegionStr + 1) == NULL)
|
|
{
|
|
if (!running_demo)
|
|
message_printf ("Selected render region is '%s'.\n", RegionStr + 1) ;
|
|
opts.AddCommand (RegionStr);
|
|
}
|
|
}
|
|
|
|
if (strlen (command_line))
|
|
{
|
|
if (!running_demo)
|
|
wrapped_printf ("Rendering using command line '%s'.", command_line) ;
|
|
opts.AddCommand (command_line);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// we are rendering the insert menu
|
|
if (InsertMenuSection >= InsertMenuSections.size())
|
|
throw POV_EXCEPTION_STRING("Insert menu render error - we should be stopped already!");
|
|
int section = InsertMenuSections [InsertMenuSection] ;
|
|
sprintf (str, "Images.ini[%d]", section) ;
|
|
opts.AddINI (str);
|
|
}
|
|
|
|
int result = Session.SetOptions (opts) ;
|
|
if (result == vfeNoInputFile)
|
|
throw POV_EXCEPTION_STRING("No source file specified, either directly or via an INI file.");
|
|
else if (result != vfeNoError)
|
|
throw POV_EXCEPTION_STRING (Session.GetErrorString());
|
|
|
|
// TODO FIXME - magic values
|
|
if (opts.GetOptions().TryGetInt(kPOVAttrib_RenderBlockSize, 32) < 4)
|
|
throw POV_EXCEPTION (kParseErr, "Minimum permitted render block size is 4 (+BS4 or Render_Block_Size=4)") ;
|
|
|
|
InputFileName = UCS2toASCIIString (Session.GetInputFilename());
|
|
output_to_file = opts.GetOptions().TryGetBool(kPOVAttrib_OutputToFile, true) ;
|
|
render_width = Session.GetRenderWidth();
|
|
render_height = Session.GetRenderHeight();
|
|
PutHKCU("LastRender", "SceneFile", "") ;
|
|
PutHKCU("LastRender", "OutputFile", "") ;
|
|
PutHKCU("LastRender", "IniOutputFile", "") ;
|
|
PutHKCU("LastRender", "IniOutputFile", "") ;
|
|
|
|
UseAlpha = Session.GetBoolOption("Output_Alpha", false);
|
|
if (Session.GetBoolOption("Display", true) == false)
|
|
display_cleanup(true);
|
|
|
|
if (StartInsertRender)
|
|
status_printf (StatusMessage, "Rendering Insert Menu entry %d of %d", InsertMenuSection + 1, (unsigned int) InsertMenuSections.size()) ;
|
|
else
|
|
status_printf (StatusMessage, "Parsing %s", InputFileName.c_str()) ;
|
|
|
|
if (!running_demo && !demo_mode && !benchmark_mode)
|
|
{
|
|
GetCurrentDirectory (sizeof (dir), dir) ;
|
|
PutHKCU("LastRender", "CurrentDirectory", dir) ;
|
|
splitpath ((char *) InputFileName.c_str (), path, file) ;
|
|
PutHKCU("LastRender", "SourceFile", get_full_name (file)) ;
|
|
splitfn (str, NULL, file, NULL) ;
|
|
PutHKCU("LastRender", "SceneFile", file) ;
|
|
}
|
|
|
|
result = Session.StartRender();
|
|
if (result < 0)
|
|
throw POV_EXCEPTION_CODE (result);
|
|
else if (result > 0)
|
|
throw POV_EXCEPTION_STRING (Session.GetErrorString());
|
|
}
|
|
catch (std::exception& e)
|
|
{
|
|
int errorCode = 0 ;
|
|
if (dynamic_cast<pov_base::Exception *> (&e) != NULL)
|
|
{
|
|
errorCode = dynamic_cast<pov_base::Exception *> (&e)->code() ;
|
|
povray_return_code = errorCode ;
|
|
}
|
|
if (povray_return_code == 0)
|
|
povray_return_code = -1 ;
|
|
ErrorOccurred = true ;
|
|
PVEnableMenuItem (CM_RENDERSHOW, MF_ENABLED) ;
|
|
update_menu_for_render (false) ;
|
|
if (restore_command_line)
|
|
{
|
|
strcpy (command_line, old_command_line) ;
|
|
SendMessage (toolbar_cmdline, WM_SETTEXT, 0, (UINT_PTR) command_line) ;
|
|
restore_command_line = false ;
|
|
}
|
|
|
|
// make sure any outstanding messages are processed
|
|
ProcessSession();
|
|
|
|
EditShowMessages (true) ;
|
|
|
|
if (ErrorNotified == false)
|
|
{
|
|
sprintf (str, "Failed to start render: %s", e.what()) ;
|
|
say_status_message (StatusMessage, str) ;
|
|
message_printf ("%s\n", str) ;
|
|
}
|
|
if (errorCode != kCannotOpenFileErr && errorCode != kParseErr && errorCode != kOutOfMemoryErr)
|
|
{
|
|
sprintf (str, "Failed to set render options (%s).\nSee message pane for more details.", e.what()) ;
|
|
MessageBox (main_window, str, "Error", MB_OK | MB_ICONSTOP) ;
|
|
}
|
|
|
|
if (ErrorFilename.empty() == false)
|
|
EditShowParseError (ErrorFilename.c_str(), ErrorMessage.c_str(), ErrorLine, ErrorCol) ;
|
|
if (parse_error_sound_enabled)
|
|
{
|
|
PlaySound (parse_error_sound, NULL, SND_NOWAIT | SND_ASYNC | SND_NODEFAULT) ;
|
|
if (!running_demo && !demo_mode && !benchmark_mode)
|
|
FeatureNotify ("ParserErrorSound",
|
|
"POV-Ray - Parse Error Sound",
|
|
"You can change the sound played upon parse errors "
|
|
"from the Render Menu.\n\n"
|
|
"Click Help for more information.",
|
|
"sounds", false) ;
|
|
}
|
|
buffer_message (mDivider, "\n") ;
|
|
EditShowMessages (true) ;
|
|
|
|
return (false) ;
|
|
}
|
|
|
|
if (!StartInsertRender)
|
|
{
|
|
if (MenuBarDraw)
|
|
{
|
|
DrawMenuBar (main_window) ;
|
|
MenuBarDraw = false ;
|
|
}
|
|
bool show = EditShowMessages (true) ;
|
|
CalculateClientWindows (true) ;
|
|
if (show)
|
|
ShowWindow (message_window, SW_SHOW) ;
|
|
PutHKCU ("Info", "Rendering", 1) ;
|
|
display_cleanup (false) ;
|
|
}
|
|
|
|
currentX = seconds_for_last_line = -1 ;
|
|
message_printf ("Rendering with %d thread%s.\n", threadCount, threadCount > 1 ? "s" : "") ;
|
|
|
|
if (GetRenderWindow())
|
|
GetRenderWindow()->SetRenderState (true);
|
|
|
|
ExternalEvent (EventStartRendering, 0) ;
|
|
|
|
set_render_priority (render_priority) ;
|
|
|
|
// FIXME - ought to wait for the render to start here
|
|
rendering = true ;
|
|
// StartProfile () ;
|
|
|
|
return (true) ;
|
|
}
|
|
|
|
void render_stopped (void)
|
|
{
|
|
char *s ;
|
|
char str [4096] ;
|
|
vfeWinSession& Session (GetSession());
|
|
|
|
run_renderer = false ;
|
|
rendering = false ;
|
|
status_buffer[0] = '\0' ;
|
|
delay_next_status = 0 ;
|
|
SetStatusPanelItemText (IDC_STATUS_DATA_FRAME, "N/A") ;
|
|
SendMessage (StatusPanelItems [IDC_STATUS_PROGRESS].hwnd, PBM_SETPOS, 0, 0) ;
|
|
bool success = Session.Succeeded();
|
|
|
|
if (message_output_x > 0)
|
|
buffer_message (mIDE, "\n") ;
|
|
|
|
s = EditGetFilename(true) ;
|
|
if (s != NULL && *s != '\0')
|
|
{
|
|
sprintf (str, "POV-Ray - %s", s) ;
|
|
SetCaption (str) ;
|
|
}
|
|
else
|
|
SetCaption ("POV-Ray for Windows") ;
|
|
|
|
if ((!success || ErrorOccurred) && povray_return_code == 0)
|
|
povray_return_code = -1 ;
|
|
PrintRenderTimes (true, !ErrorOccurred && !stop_rendering) ;
|
|
ExternalEvent (EventStopRendering, povray_return_code) ;
|
|
|
|
// EndProfile () ;
|
|
|
|
if (restore_command_line && !rendering_insert_menu)
|
|
{
|
|
strcpy (command_line, old_command_line) ;
|
|
SendMessage (toolbar_cmdline, WM_SETTEXT, 0, (LPARAM) command_line) ;
|
|
restore_command_line = false ;
|
|
}
|
|
|
|
if (rendering_insert_menu)
|
|
{
|
|
if (InsertMenuSection < InsertMenuSections.size() - 1 && !(stop_rendering || quit))
|
|
{
|
|
wrapped_printf ("Completed rendering Insert Menu section %d. result = %d", InsertMenuSections [InsertMenuSection++], povray_return_code) ;
|
|
StartInsertRender = true ;
|
|
return ;
|
|
}
|
|
StartInsertRender = rendering_insert_menu = no_status_output = false ;
|
|
was_insert_render = true ;
|
|
}
|
|
else if (running_benchmark || running_demo)
|
|
{
|
|
if (running_benchmark == false)
|
|
{
|
|
strcpy (command_line, old_command_line) ;
|
|
restore_command_line = false ;
|
|
}
|
|
_unlink (demo_file_name) ;
|
|
_unlink (demo_ini_name) ;
|
|
running_benchmark = running_demo = false ;
|
|
if (benchmark_mode) // only applies to benchmarks started from the command-line
|
|
PostQuitMessage (0) ;
|
|
if (demo_mode)
|
|
{
|
|
PovMessageBox ("Demonstration completed. POV-Ray will now exit.", "Finished test run") ;
|
|
PostQuitMessage (0) ;
|
|
}
|
|
}
|
|
|
|
PutHKCU("Info", "Rendering", 0U) ;
|
|
set_render_priority (CM_RENDERPRIORITY_NORMAL) ;
|
|
|
|
if (quit != 0 || exit_after_render)
|
|
{
|
|
DestroyWindow (main_window) ;
|
|
return ;
|
|
}
|
|
|
|
WinDisplay *rw = GetRenderWindow();
|
|
if (rw != NULL)
|
|
{
|
|
rw->SetCaption ("POV-Ray Render Window");
|
|
rw->SetRenderState (false);
|
|
if (render_auto_close)
|
|
rw->Hide();
|
|
}
|
|
if (main_window_hidden)
|
|
TaskBarModifyIcon (main_window, 0, "POV-Ray (Restore: DblClk ; Menu: Mouse2)") ;
|
|
InvalidateRect (statuspanel, NULL, false) ;
|
|
|
|
if (success == true && ErrorOccurred == false)
|
|
{
|
|
if (render_complete_sound_enabled)
|
|
{
|
|
PlaySound (render_complete_sound, NULL, SND_ASYNC | SND_NODEFAULT) ;
|
|
if (!running_demo && !demo_mode && !benchmark_mode)
|
|
FeatureNotify ("RenderCompleteSound",
|
|
"POV-Ray - Render Complete Sound",
|
|
"You can change the sound played upon completion of rendering "
|
|
"from the Render Menu.\n\nIt is also possible to tell POV-Ray "
|
|
"for Windows to do other things when a render stops (such as "
|
|
"display a message or exit.)",
|
|
"sounds", false) ;
|
|
}
|
|
say_status_message (StatusMessage, "") ;
|
|
EditShowMessages (false) ;
|
|
CalculateClientWindows (false) ;
|
|
switch (on_completion)
|
|
{
|
|
case CM_COMPLETION_EXIT :
|
|
DestroyWindow (main_window) ;
|
|
break ;
|
|
|
|
case CM_COMPLETION_MESSAGE :
|
|
PovMessageBox ("Render completed", "Message from POV-Ray for Windows") ;
|
|
break ;
|
|
}
|
|
if (!running_demo && !demo_mode && !benchmark_mode && !rendering_insert_menu && !running_benchmark && !was_insert_render)
|
|
{
|
|
string ofn = UCS2toASCIIString (Session.GetOutputFilename());
|
|
if (output_to_file && ofn.size () != 0)
|
|
{
|
|
sprintf (str, "Output -> '%s'", ofn.c_str ()) ;
|
|
say_status_message (StatusMessage, str) ;
|
|
//buffer_stream_message (mIDE, str) ;
|
|
sprintf (str, "Your output file has been written to the following location:\n\n"
|
|
" %s\n\n"
|
|
"Press F1 to learn more about how to control where files are written.",
|
|
ofn.c_str ()) ;
|
|
FeatureNotify ("OutputFileLocation", "POV-Ray - Output File Notification", str, "Output_File_Name", false) ;
|
|
PutHKCU("LastRender", "OutputFile", ofn.c_str ()) ;
|
|
}
|
|
else
|
|
{
|
|
if (!running_benchmark)
|
|
{
|
|
FeatureNotify ("OutputFileOff",
|
|
"POV-Ray - No Output File",
|
|
"A render has completed but file output was turned off. No file "
|
|
"was written.\n\nPress F1 for help on output file control.",
|
|
"Output_To_File",
|
|
false) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ErrorNotified == false && ErrorMessage.empty() == false)
|
|
say_status_message (StatusMessage, ErrorMessage.c_str()) ;
|
|
else if (stop_rendering)
|
|
say_status_message (StatusMessage, "Render cancelled by user") ;
|
|
else
|
|
say_status_message (StatusMessage, "Render failed") ;
|
|
if (ErrorFilename.empty() == false)
|
|
EditShowParseError (ErrorFilename.c_str(), ErrorMessage.c_str(), ErrorLine, ErrorCol) ;
|
|
if (stop_rendering)
|
|
{
|
|
if (render_error_sound_enabled)
|
|
{
|
|
PlaySound (render_error_sound, NULL, SND_ASYNC | SND_NODEFAULT) ;
|
|
if (!running_demo && !demo_mode && !benchmark_mode)
|
|
FeatureNotify ("RenderErrorSound",
|
|
"POV-Ray - Render Stopped Sound",
|
|
"You can change the sound played upon render errors/cancellation "
|
|
"from the Render Menu.",
|
|
"sounds", false) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (parse_error_sound_enabled)
|
|
{
|
|
PlaySound (parse_error_sound, NULL, SND_NOWAIT | SND_ASYNC | SND_NODEFAULT) ;
|
|
if (!running_demo && !demo_mode && !benchmark_mode)
|
|
FeatureNotify ("ParserErrorSound",
|
|
"POV-Ray - Parse Error Sound",
|
|
"You can change the sound played upon parse errors "
|
|
"from the Render Menu.\n\n"
|
|
"Click Help for more information.",
|
|
"sounds", false) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// update the mapping of included files to source files
|
|
const set<string>& rf = Session.GetReadFiles();
|
|
for (set<string>::const_iterator it = rf.begin(); it != rf.end(); it++)
|
|
{
|
|
if (_stricmp(it->c_str(), InputFileName.c_str()) == 0)
|
|
continue;
|
|
if (is_non_primary_file(it->c_str()))
|
|
{
|
|
FileType ft = get_file_type(it->c_str());
|
|
if (ft < fileFirstImageType || ft > fileLastImageType)
|
|
{
|
|
pair<map<string, string>::iterator, bool> result = IncludeToSourceMap.insert(pair<string, string> (*it, InputFileName));
|
|
if (result.second == false)
|
|
result.first->second = InputFileName;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
UINT WINAPI ofn_hook_fn (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG :
|
|
SetupExplorerDialog (hwnd) ;
|
|
break ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
void init_ofn (OPENFILENAME *ofn, HWND hWnd, char *title, char *name, int maxlen, char *lastPath, char *defaultExt)
|
|
{
|
|
ofn->lStructSize = sizeof (OPENFILENAME) ;
|
|
ofn->hwndOwner = hWnd ;
|
|
ofn->hInstance = hInstance ;
|
|
ofn->lpstrCustomFilter = NULL ;
|
|
ofn->nMaxCustFilter = 0 ;
|
|
ofn->nFilterIndex = 1 ;
|
|
ofn->lpstrTitle = title ;
|
|
ofn->lpstrFile = name ;
|
|
ofn->nMaxFile = maxlen ;
|
|
ofn->lpstrFileTitle = NULL ;
|
|
ofn->nMaxFileTitle = 0 ;
|
|
ofn->lpstrInitialDir = lastPath ;
|
|
ofn->Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR ;
|
|
if (IsW95UserInterface)
|
|
ofn->Flags |= OFN_EXPLORER ;
|
|
ofn->nFileOffset = 0 ;
|
|
ofn->nFileExtension = 0 ;
|
|
ofn->lpstrDefExt = defaultExt ;
|
|
ofn->lCustData = 0L ;
|
|
ofn->lpfnHook = NULL ;
|
|
ofn->lpTemplateName = NULL ;
|
|
}
|
|
|
|
char *file_open (HWND hWnd)
|
|
{
|
|
int result ;
|
|
OPENFILENAME ofnTemp ;
|
|
static char name [_MAX_PATH] ;
|
|
|
|
strcpy (name, lastRenderName) ;
|
|
validatePath (lastRenderPath) ;
|
|
init_ofn (&ofnTemp, hWnd, "Render File", name, sizeof (name), lastRenderPath, "pov") ;
|
|
ofnTemp.lpstrFilter = "POV source and INI (*.pov;*.ini)\0*.pov;*.ini\0POV files (*.pov)\0*.pov\0INI files (*.ini)\0*.ini\0Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0" ;
|
|
if ((result = GetOpenFileName (&ofnTemp)) != 0)
|
|
{
|
|
strcpy (lastRenderPath, name) ;
|
|
// this removes the name AND the trailing '\' [which is what we want]
|
|
lastRenderPath [ofnTemp.nFileOffset - 1] = '\0' ;
|
|
validatePath (lastRenderPath) ;
|
|
strcpy (lastRenderName, name + ofnTemp.nFileOffset) ;
|
|
}
|
|
return (result ? name : NULL) ;
|
|
}
|
|
|
|
char *get_background_file (HWND hWnd)
|
|
{
|
|
int result ;
|
|
OPENFILENAME ofnTemp ;
|
|
static char name [_MAX_PATH] ;
|
|
|
|
strcpy (name, lastBitmapName) ;
|
|
validatePath (lastBitmapPath) ;
|
|
init_ofn (&ofnTemp, hWnd, "Tile Bitmap File", name, sizeof (name), lastBitmapPath, "bmp") ;
|
|
ofnTemp.lpstrFilter = "BMP files (*.bmp)\0*.bmp\0" ;
|
|
if ((result = GetOpenFileName (&ofnTemp)) != 0)
|
|
{
|
|
strcpy (lastBitmapPath, name) ;
|
|
lastBitmapPath [ofnTemp.nFileOffset - 1] = '\0' ;
|
|
strcpy (lastBitmapName, name + ofnTemp.nFileOffset) ;
|
|
}
|
|
return (result ? name : NULL) ;
|
|
}
|
|
|
|
void get_font (void)
|
|
{
|
|
HDC hdc ;
|
|
HFONT hfont ;
|
|
HFONT hfontOld ;
|
|
LOGFONT lf ;
|
|
CHOOSEFONT cf ;
|
|
TEXTMETRIC tm ;
|
|
|
|
hdc = GetDC (message_window) ;
|
|
memset(&cf, 0, sizeof (CHOOSEFONT)) ;
|
|
cf.lStructSize = sizeof (CHOOSEFONT) ;
|
|
cf.hwndOwner = main_window ;
|
|
cf.lpLogFont = &lf ;
|
|
cf.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT ;
|
|
cf.nFontType = SCREEN_FONTTYPE ;
|
|
get_logfont (hdc, &lf) ;
|
|
if (ChooseFont (&cf))
|
|
{
|
|
if ((hfont = CreateFontIndirect (&lf)) == NULL)
|
|
{
|
|
PovMessageBox ("Failed to create message font", "Cannot change to selected font") ;
|
|
ReleaseDC (message_window, hdc) ;
|
|
return ;
|
|
}
|
|
hfontOld = (HFONT)SelectObject (hdc, hfont) ;
|
|
GetTextMetrics (hdc, &tm) ;
|
|
message_xchar = tm.tmAveCharWidth ;
|
|
message_ychar = tm.tmHeight + tm.tmExternalLeading ;
|
|
SelectObject (hdc, hfontOld) ;
|
|
DeleteObject (message_font) ;
|
|
message_font = hfont ;
|
|
PovInvalidateRect (message_window, NULL, true) ;
|
|
message_font_size = -MulDiv (lf.lfHeight, 72, GetDeviceCaps (hdc, LOGPIXELSY)) ;
|
|
message_font_weight = lf.lfWeight ;
|
|
strncpy (message_font_name, lf.lfFaceName, sizeof (message_font_name) - 1) ;
|
|
}
|
|
ReleaseDC (message_window, hdc) ;
|
|
}
|
|
|
|
void DragFunction (HDROP handle)
|
|
{
|
|
int cFiles ;
|
|
int i ;
|
|
char szFile [_MAX_PATH] ;
|
|
HDIB hDIB ;
|
|
bool calc = 0 ;
|
|
BITMAP bm ;
|
|
|
|
cFiles = DragQueryFile (handle, -1, NULL, 0) ;
|
|
if (rendering)
|
|
message_printf ("\n") ;
|
|
for (i = 0 ; i < cFiles ; i++)
|
|
{
|
|
DragQueryFile (handle, i, szFile, sizeof (szFile)) ;
|
|
switch (get_file_type (szFile))
|
|
{
|
|
case filePOV :
|
|
case fileINI :
|
|
case fileINC :
|
|
if (!use_editors || !drop_to_editor)
|
|
break ;
|
|
if ((EditGetFlags () & EDIT_CAN_OPEN) == 0)
|
|
{
|
|
say_status_message (StatusMessage, "Cannot open dropped file - max editor count reached") ;
|
|
message_printf ("Cannot open dropped file - max editor count reached\n") ;
|
|
}
|
|
else
|
|
EditOpenFile (szFile) ;
|
|
continue ;
|
|
|
|
case fileBMP :
|
|
if (screen_depth < 8)
|
|
{
|
|
PovMessageBox ("Tiled bitmaps not supported in this color depth", "File ignored") ;
|
|
continue ;
|
|
}
|
|
if ((hDIB = LoadDIB (szFile)) != NULL)
|
|
{
|
|
strcpy (background_file, szFile) ;
|
|
DeleteObject (hBmpBackground) ;
|
|
hBmpBackground = DIBToBitmap (hDIB, hPalApp) ;
|
|
DeleteObject (hDIB) ;
|
|
GetObject (hBmpBackground, sizeof (BITMAP), (LPSTR) &bm) ;
|
|
background_width = bm.bmWidth ;
|
|
background_height = bm.bmHeight ;
|
|
tile_background = true ;
|
|
PovInvalidateRect (message_window, NULL, true) ;
|
|
}
|
|
else
|
|
PovMessageBox ("Failed to load bitmap file", "Error") ;
|
|
continue ;
|
|
|
|
default :
|
|
if (!ExternalDragFunction (szFile, dfRealDrop))
|
|
{
|
|
if (!use_editors || !drop_to_editor)
|
|
{
|
|
say_status_message (StatusMessage, "Dropped file ignored (must be .POV, .INC, or .INI if destination is renderer)") ;
|
|
wrapped_printf ("Dropped file '%s' ignored (must be .POV, .INC, or .INI if destination is renderer).", szFile) ;
|
|
}
|
|
else
|
|
{
|
|
if ((EditGetFlags () & EDIT_CAN_OPEN) == 0)
|
|
{
|
|
say_status_message (StatusMessage, "Cannot open dropped file - max editor count reached") ;
|
|
message_printf ("Cannot open dropped file - max editor count reached\n") ;
|
|
}
|
|
else
|
|
EditOpenFile (szFile) ;
|
|
}
|
|
}
|
|
continue ;
|
|
}
|
|
if (queued_file_count < MAX_QUEUE)
|
|
{
|
|
strcpy (queued_files [queued_file_count++], szFile) ;
|
|
wrapped_printf ("File '%s' dropped as queue entry %d.", szFile, queued_file_count) ;
|
|
}
|
|
else
|
|
wrapped_printf ("render queue full ; file '%s' ignored.", szFile) ;
|
|
}
|
|
if (rendering)
|
|
message_printf ("\n") ;
|
|
DragFinish (handle) ;
|
|
update_queue_status (true) ;
|
|
if (calc)
|
|
CalculateClientWindows (true) ;
|
|
FeatureNotify ("DropFiles",
|
|
"POV-Ray - Drag and Drop",
|
|
"POV-Ray can do one of several things when you drop files onto it, "
|
|
"depending on the state of the 'Drop to Editor' option and the type "
|
|
"of file dropped. For example if the file is a .POV or .INI you can "
|
|
"chose whether POV-Ray opens it or renders it.\n\nPress F1 for more "
|
|
"information.",
|
|
"drag and drop",
|
|
true) ;
|
|
}
|
|
|
|
void WIN_Debug_Log (unsigned int from, const char *msg)
|
|
{
|
|
if (debugging)
|
|
OutputDebugString (msg) ;
|
|
}
|
|
|
|
#if POV_RAY_IS_OFFICIAL != 1
|
|
void WIN_PrintOtherCredits (void)
|
|
{
|
|
char *s = DISTRIBUTION_MESSAGE_2 ;
|
|
|
|
while (*s == ' ' || *s == '\t')
|
|
s++ ;
|
|
message_printf ("This is an UNSUPPORTED UNOFFICIAL COMPILE by %s.\n", s) ;
|
|
}
|
|
#endif
|
|
|
|
void PovMessageBox (const char *message, char *title)
|
|
{
|
|
MessageBox (main_window, message, title, MB_ICONEXCLAMATION) ;
|
|
}
|
|
|
|
void detect_graphics_config (void)
|
|
{
|
|
HDC hdc ;
|
|
|
|
hdc = GetDC (NULL) ;
|
|
screen_depth = GetDeviceCaps (hdc, BITSPIXEL) ;
|
|
render_bitmap_depth = (GetDeviceCaps (hdc, BITSPIXEL) > 8 && renderwin_8bits == 0) ? 24 : 8 ;
|
|
screen_width = GetDeviceCaps (hdc, HORZRES) ;
|
|
screen_height = GetDeviceCaps (hdc, VERTRES) ;
|
|
if (GetSystemMetrics (SM_CMONITORS) > 1)
|
|
{
|
|
screen_origin_x = GetSystemMetrics (SM_XVIRTUALSCREEN) ;
|
|
screen_origin_y = GetSystemMetrics (SM_YVIRTUALSCREEN) ;
|
|
virtual_screen_width = GetSystemMetrics (SM_CXVIRTUALSCREEN) ;
|
|
virtual_screen_height = GetSystemMetrics (SM_CYVIRTUALSCREEN) ;
|
|
}
|
|
else
|
|
{
|
|
screen_origin_x = screen_origin_y = 0 ;
|
|
virtual_screen_width = screen_width ;
|
|
virtual_screen_height = screen_height ;
|
|
}
|
|
ReleaseDC (NULL, hdc) ;
|
|
}
|
|
|
|
// Clear the system palette when we start to ensure an identity palette mapping
|
|
void clear_system_palette (void)
|
|
{
|
|
int Counter ;
|
|
HDC ScreenDC ;
|
|
LogPal Palette = { 0x300, 256 } ;
|
|
HPALETTE ScreenPalette ;
|
|
|
|
// Reset everything in the system palette to black
|
|
for (Counter = 0 ; Counter < 256 ; Counter++)
|
|
{
|
|
Palette.pe [Counter].peRed = 0 ;
|
|
Palette.pe [Counter].peGreen = 0 ;
|
|
Palette.pe [Counter].peBlue = 0 ;
|
|
Palette.pe [Counter].peFlags = PC_NOCOLLAPSE ;
|
|
}
|
|
|
|
// Create, select, realize, deselect, and delete the palette
|
|
ScreenDC = GetDC (NULL) ;
|
|
ScreenPalette = CreatePalette ((LOGPALETTE *) &Palette) ;
|
|
if (ScreenPalette)
|
|
{
|
|
ScreenPalette = SelectPalette (ScreenDC, ScreenPalette, false) ;
|
|
RealizePalette (ScreenDC) ;
|
|
ScreenPalette = SelectPalette (ScreenDC, ScreenPalette, false) ;
|
|
DeleteObject (ScreenPalette) ;
|
|
}
|
|
ReleaseDC (NULL, ScreenDC) ;
|
|
}
|
|
|
|
void create_about_font (void)
|
|
{
|
|
LOGFONT lf ;
|
|
|
|
HDC hdc = GetDC (NULL) ;
|
|
memset (&lf, 0, sizeof (LOGFONT)) ;
|
|
lf.lfHeight = -12 ;
|
|
lf.lfWeight = FW_REGULAR ;
|
|
lf.lfPitchAndFamily = VARIABLE_PITCH ;
|
|
lf.lfCharSet = DEFAULT_CHARSET ;
|
|
lf.lfQuality = PROOF_QUALITY ;
|
|
strcpy (lf.lfFaceName, "Trebuchet MS") ;
|
|
if ((about_font = CreateFontIndirect (&lf)) == NULL)
|
|
{
|
|
strcpy (lf.lfFaceName, "Arial") ;
|
|
about_font = CreateFontIndirect (&lf) ;
|
|
}
|
|
ReleaseDC (NULL, hdc) ;
|
|
}
|
|
|
|
void CalculateClientWindows (bool redraw)
|
|
{
|
|
RECT rect ;
|
|
|
|
GetClientRect (main_window, &rect) ;
|
|
rect.bottom -= toolheight + statusheight ;
|
|
if (!use_editors)
|
|
MoveWindow (message_window, 0, toolheight, rect.right, rect.bottom, redraw) ;
|
|
else
|
|
SetEditorPosition (0, toolheight, rect.right, rect.bottom) ;
|
|
}
|
|
|
|
// handle a WM_CHAR message destined for the toolbar commandline edit control.
|
|
// return true if the message is to be discarded.
|
|
bool handle_toolbar_cmdline (UINT wParam, UINT lParam)
|
|
{
|
|
if (wParam == VK_RETURN)
|
|
{
|
|
SendMessage (main_window, WM_COMMAND, CM_FILERENDER, 0) ;
|
|
return (true) ;
|
|
}
|
|
if (wParam == VK_ESCAPE)
|
|
{
|
|
EditSetFocus () ;
|
|
return (true) ;
|
|
}
|
|
if (wParam == 0x01) // ctrl-a
|
|
{
|
|
SendMessage(toolbar_cmdline, EM_SETSEL, 0, -1);
|
|
return (true) ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
void SetupStatusPanel (HWND hDlg)
|
|
{
|
|
int max = 0 ;
|
|
int ypos = 0;
|
|
char str [256] ;
|
|
RECT rect ;
|
|
StatusPanelItem item ;
|
|
|
|
GetWindowRect (hDlg, &rect) ;
|
|
int x = rect.left ;
|
|
int y = rect.top ;
|
|
int width = rect.right - rect.left + 1 ;
|
|
int height = rect.bottom - rect.top + 1 ;
|
|
for (int id = IDC_STATUS_LABEL_FIRST ; id <= IDC_STATUS_ID_LAST ; id++)
|
|
{
|
|
item.id = id ;
|
|
item.hwnd = GetDlgItem (hDlg, id) ;
|
|
if (item.hwnd == NULL)
|
|
continue ;
|
|
if (id <= IDC_STATUS_DATA_LAST)
|
|
{
|
|
GetWindowText (item.hwnd, str, sizeof (str)) ;
|
|
HDC hdc = GetDC (item.hwnd) ;
|
|
HFONT hFont = (HFONT) SendMessage (item.hwnd, WM_GETFONT, 0, 0) ;
|
|
HFONT oldFont = (HFONT) SelectObject (hdc, hFont) ;
|
|
GetTextExtentPoint32 (hdc, str, (int) strlen (str), &item.size) ;
|
|
SelectObject (hdc, oldFont) ;
|
|
ReleaseDC (GetDlgItem (hDlg, id), hdc) ;
|
|
if (id <= IDC_STATUS_LABEL_LAST)
|
|
if (item.size.cx > max)
|
|
max = item.size.cx ;
|
|
}
|
|
else
|
|
{
|
|
GetClientRect (item.hwnd, &rect) ;
|
|
item.size.cx = rect.right ;
|
|
item.size.cy = rect.bottom ;
|
|
}
|
|
StatusPanelItems [id] = item ;
|
|
}
|
|
for (int id = IDC_STATUS_LABEL_FIRST; id <= IDC_STATUS_LABEL_LAST ; id++)
|
|
{
|
|
item = StatusPanelItems [id] ;
|
|
if (item.hwnd == NULL)
|
|
continue ;
|
|
MoveWindow (item.hwnd, 2, ypos, max + 2, item.size.cy, false) ;
|
|
item = StatusPanelItems [id + IDC_STATUS_DATA_FIRST] ;
|
|
MoveWindow (item.hwnd, max + 7, ypos, width - max - 8, item.size.cy, false) ;
|
|
if (id >= IDC_STATUS_DATA_FIRST)
|
|
SetWindowText (item.hwnd, "") ;
|
|
ypos += item.size.cy ;
|
|
}
|
|
item = StatusPanelItems [IDC_STATUS_PROGRESS] ;
|
|
|
|
if (height - ypos > 6)
|
|
{
|
|
// there's at least six rows available, so we show the progress bar
|
|
item.size.cy = height - ypos - 1;
|
|
MoveWindow (item.hwnd, 2, ypos + 1, width - 2, item.size.cy, false) ;
|
|
}
|
|
else
|
|
{
|
|
// not enough room for progress bar: hide it
|
|
ShowWindow(item.hwnd, SW_HIDE);
|
|
}
|
|
}
|
|
|
|
void SetStatusPanelItemText (int id, LPCSTR format, ...)
|
|
{
|
|
char str [2048] ;
|
|
va_list arg_ptr ;
|
|
|
|
va_start (arg_ptr, format) ;
|
|
vsprintf (str, format, arg_ptr) ;
|
|
va_end (arg_ptr) ;
|
|
SetWindowText (StatusPanelItems [id].hwnd, str) ;
|
|
}
|
|
|
|
/**************************************************************************************/
|
|
/* WINDOW PROCEDURES */
|
|
/**************************************************************************************/
|
|
|
|
/*
|
|
* Return true if we are to return 0 to Windows, false if we are to continue.
|
|
*/
|
|
bool handle_main_command (WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int n ;
|
|
char *s ;
|
|
char filename [_MAX_PATH] ;
|
|
HDIB hDIB ;
|
|
RECT rect ;
|
|
BITMAP bm ;
|
|
HBITMAP hBMP ;
|
|
CHOOSECOLOR cc ;
|
|
struct stat st ;
|
|
static char str [8192] ;
|
|
vfeWinSession& Session(GetSession());
|
|
|
|
if (process_toggles (wParam))
|
|
return (true) ;
|
|
|
|
if (LOWORD (wParam) >= CM_FIRSTTOOL && LOWORD (wParam) <= CM_LASTTOOL)
|
|
{
|
|
s = parse_tool_command (tool_commands [LOWORD (wParam) - CM_FIRSTTOOL]) ;
|
|
if (GetHKCU("General", "Debug", 0))
|
|
message_printf ("Tool request - in '%s', out '%s'\n", tool_commands [LOWORD (wParam) - CM_FIRSTTOOL], s) ;
|
|
else
|
|
execute_tool (s) ;
|
|
return (true) ;
|
|
}
|
|
|
|
if (LOWORD (wParam) >= CM_FIRSTMENUHELP && LOWORD (wParam) <= CM_LASTMENUHELP)
|
|
{
|
|
menuhelp (LOWORD (wParam)) ;
|
|
return (true) ;
|
|
}
|
|
|
|
if (LOWORD (wParam) >= CM_DUTYCYCLE_10 && LOWORD (wParam) <= CM_DUTYCYCLE_100)
|
|
{
|
|
PVCheckMenuRadioItem (CM_DUTYCYCLE_10, CM_DUTYCYCLE_100, LOWORD (wParam)) ;
|
|
Duty_Cycle = LOWORD (wParam) - CM_DUTYCYCLE_10 ;
|
|
return (true) ;
|
|
}
|
|
|
|
#ifdef RTR_SUPPORT
|
|
if (LOWORD (wParam) >= CM_FIRSTVIDEOSOURCE && LOWORD (wParam) <= CM_LASTVIDEOSOURCE)
|
|
{
|
|
char str [256] ;
|
|
MENUITEMINFO mi ;
|
|
|
|
mi.cbSize = sizeof (MENUITEMINFO) ;
|
|
mi.fMask = MIIM_TYPE ;
|
|
mi.dwTypeData = str ;
|
|
mi.cch = sizeof (str) ;
|
|
if (GetMenuItemInfo(hVidcapMenu, LOWORD (wParam), false, &mi))
|
|
{
|
|
PVCheckMenuRadioItem (CM_FIRSTVIDEOSOURCE, CM_LASTVIDEOSOURCE, LOWORD (wParam)) ;
|
|
status_printf (StatusMessage, "Selected video source '%s'", str) ;
|
|
SetVideoSourceName(str);
|
|
}
|
|
return (true) ;
|
|
}
|
|
#endif
|
|
|
|
if (LOWORD (wParam) >= CM_FIRSTEDITNOTIFY && LOWORD (wParam) <= CM_LASTEDITNOTIFY)
|
|
{
|
|
switch (LOWORD (wParam) - CM_FIRSTEDITNOTIFY)
|
|
{
|
|
case NotifyTabChange :
|
|
if ((lParam & EDIT_MSG_SELECTED) == 0)
|
|
{
|
|
build_editor_menu (hMainMenu) ;
|
|
PVEnableMenuItem (CM_FILESAVE, (lParam & EDIT_CURRENT_MODIFIED) ? MF_ENABLED : MF_GRAYED) ;
|
|
PVEnableMenuItem (CM_FILECLOSE, MF_ENABLED) ;
|
|
s = EditGetFilename(true) ;
|
|
if (s != NULL && *s != '\0')
|
|
{
|
|
sprintf (str, rendersleep ? "POV-Ray (paused) - %s" : "POV-Ray - %s", s) ;
|
|
SetCaption (str) ;
|
|
}
|
|
else
|
|
SetCaption (rendersleep ? "POV-Ray for Windows (paused)" : "POV-Ray for Windows") ;
|
|
}
|
|
else
|
|
{
|
|
build_main_menu (hMainMenu, true) ;
|
|
PVEnableMenuItem (CM_FILESAVE, MF_GRAYED) ;
|
|
PVEnableMenuItem (CM_FILECLOSE, MF_GRAYED) ;
|
|
SetCaption (rendersleep ? "POV-Ray for Windows (paused)" : "POV-Ray for Windows") ;
|
|
}
|
|
break ;
|
|
|
|
case NotifyModifiedChange :
|
|
PVEnableMenuItem (CM_FILESAVE, lParam ? MF_ENABLED : MF_GRAYED) ;
|
|
s = EditGetFilename(true) ;
|
|
if (s != NULL && *s != '\0')
|
|
{
|
|
sprintf (str, rendersleep ? "POV-Ray (paused) - %s" : "POV-Ray - %s", s) ;
|
|
SetCaption (str) ;
|
|
}
|
|
else
|
|
SetCaption (rendersleep ? "POV-Ray for Windows (paused)" : "POV-Ray for Windows") ;
|
|
break ;
|
|
|
|
case NotifyFocusSaveModified :
|
|
FeatureNotify ("FocusSaveModified",
|
|
"POV-Ray - Modified Files Auto-Saved",
|
|
"Your modified files were automatically saved when you switched to another "
|
|
"application. This is necessary for the Auto-Reload feature to work. If you "
|
|
"do not want this to happen, turn auto-reload off via the Editor menu.\n\n"
|
|
"Click Help for more information.",
|
|
"auto-reload", false) ;
|
|
break ;
|
|
|
|
case NotifyExitRequest :
|
|
handle_main_command (CM_FILEEXIT, 0) ;
|
|
break ;
|
|
}
|
|
return (true) ;
|
|
}
|
|
|
|
switch (LOWORD (wParam))
|
|
{
|
|
case CM_HIDENEWUSERHELP :
|
|
set_newuser_menus (hide_newuser_help) ;
|
|
return (0) ;
|
|
|
|
case CM_IO_NO_RESTRICTIONS :
|
|
case CM_IO_RESTRICT_WRITE :
|
|
case CM_IO_RESTRICT_READWRITE :
|
|
io_restrictions = LOWORD (wParam) - CM_IO_NO_RESTRICTIONS ;
|
|
PVCheckMenuRadioItem (CM_IO_NO_RESTRICTIONS, CM_IO_RESTRICT_READWRITE, LOWORD (wParam)) ;
|
|
PutHKCU ("Scripting", "IO Restrictions", io_restrictions) ;
|
|
SetupFrontend();
|
|
return (0) ;
|
|
|
|
case CM_SHOWMAINWINDOW :
|
|
if (main_window_hidden)
|
|
{
|
|
if (ListenMode)
|
|
{
|
|
char *s = "POV-Ray is in network listen mode. Press OK to continue listening or "
|
|
"CANCEL to shut down and exit." ;
|
|
if (MessageBox (main_window, s, "POV-Ray - Network Listen Mode", MB_OKCANCEL) == IDOK)
|
|
return (0) ;
|
|
TaskBarDeleteIcon (main_window, 0) ;
|
|
DestroyWindow (main_window) ;
|
|
return (0) ;
|
|
}
|
|
ShowWindow (main_window, SW_SHOW) ;
|
|
ShowWindow (main_window, SW_RESTORE) ;
|
|
if (RenderwinIsChild == false && HideRenderWithMain == true)
|
|
if (GetRenderWindow() != NULL)
|
|
GetRenderWindow()->Show();
|
|
PVModifyMenu (CM_SHOWMAINWINDOW, MF_STRING, CM_SHOWMAINWINDOW, "Minimize to System &Tray\tAlt+W") ;
|
|
main_window_hidden = 0 ;
|
|
TaskBarDeleteIcon (main_window, 0) ;
|
|
}
|
|
else
|
|
{
|
|
if (use_taskbar)
|
|
{
|
|
char *s = "POV-Ray (Restore: DblClk ; Menu: Mouse Btn 2)" ;
|
|
if (ListenMode)
|
|
s = "POV-Ray: Network Listen Mode - DblClick for Options" ;
|
|
if (TaskBarAddIcon (main_window, 0, ourIcon, s))
|
|
{
|
|
ShowWindow (main_window, SW_MINIMIZE) ;
|
|
ShowWindow (main_window, SW_HIDE) ;
|
|
if (RenderwinIsChild == false && HideRenderWithMain == true)
|
|
if (GetRenderWindow() != NULL)
|
|
GetRenderWindow()->Hide();
|
|
PVModifyMenu (CM_SHOWMAINWINDOW, MF_STRING, CM_SHOWMAINWINDOW, "Restore &Main Window from System Tray") ;
|
|
main_window_hidden = true ;
|
|
}
|
|
}
|
|
}
|
|
return (0) ;
|
|
|
|
case CM_FILENEW :
|
|
EditOpenFile (NULL) ;
|
|
return (0) ;
|
|
|
|
case CM_FILEOPEN :
|
|
EditBrowseFile (true) ;
|
|
return (0) ;
|
|
|
|
case CM_FILESAVE :
|
|
EditSaveFile (NULL) ;
|
|
return (0) ;
|
|
|
|
case CM_FILECLOSE :
|
|
EditCloseFile (NULL) ;
|
|
return (0) ;
|
|
|
|
case CM_RENDERSLEEP :
|
|
if (Session.BackendFailed())
|
|
break ;
|
|
if (!Session.IsPausable())
|
|
break ;
|
|
if (Session.Paused())
|
|
{
|
|
if (Session.Resume())
|
|
{
|
|
SetCaption ("POV-Ray for Windows") ;
|
|
FlashWindow (main_window, 0) ;
|
|
SleepTimeEnd = clock () ;
|
|
SleepTimeTotal += SleepTimeEnd - SleepTimeStart ;
|
|
say_status_message (StatusPPS, "") ;
|
|
rendersleep = false ;
|
|
SendMessage (toolbar_window, TB_CHECKBUTTON, (WPARAM) CM_RENDERSLEEP, 0) ;
|
|
}
|
|
else
|
|
SendMessage (toolbar_window, TB_CHECKBUTTON, (WPARAM) CM_RENDERSLEEP, MAKELONG (1, 0)) ;
|
|
}
|
|
else
|
|
if (Session.Pause () == false)
|
|
SendMessage (toolbar_window, TB_CHECKBUTTON, (WPARAM) CM_RENDERSLEEP, 0) ;
|
|
break ;
|
|
|
|
case CM_DROPEDITOR :
|
|
case CM_DROPRENDERER :
|
|
PVCheckMenuItem (CM_DROPEDITOR, LOWORD (wParam) == CM_DROPEDITOR ? MF_CHECKED : MF_UNCHECKED) ;
|
|
PVCheckMenuItem (CM_DROPRENDERER, LOWORD (wParam) == CM_DROPRENDERER ? MF_CHECKED : MF_UNCHECKED) ;
|
|
drop_to_editor = LOWORD (wParam) == CM_DROPEDITOR ;
|
|
break ;
|
|
|
|
case CM_RENDERPRIORITY_BACKGROUND :
|
|
case CM_RENDERPRIORITY_LOW :
|
|
case CM_RENDERPRIORITY_NORMAL :
|
|
case CM_RENDERPRIORITY_HIGH :
|
|
render_priority = LOWORD (wParam) ;
|
|
PVCheckMenuRadioItem (CM_RENDERPRIORITY_BACKGROUND, CM_RENDERPRIORITY_HIGH, render_priority) ;
|
|
// only change process priority when the renderer is running
|
|
if (rendering)
|
|
set_render_priority (render_priority) ;
|
|
return (true) ;
|
|
|
|
case CM_COMPLETION_EXIT :
|
|
case CM_COMPLETION_NOTHING :
|
|
case CM_COMPLETION_MESSAGE :
|
|
PVCheckMenuItem (on_completion, MF_UNCHECKED) ;
|
|
on_completion = LOWORD (wParam) ;
|
|
PVCheckMenuItem (on_completion, MF_CHECKED) ;
|
|
return (true) ;
|
|
|
|
case CM_PREVWINDOW :
|
|
EditNextTab (false) ;
|
|
return (true) ;
|
|
|
|
case CM_NEXTWINDOW :
|
|
EditNextTab (true) ;
|
|
return (true) ;
|
|
|
|
case CM_USETOOLBAR :
|
|
if (rebar_window == NULL)
|
|
return (true) ;
|
|
ShowWindow (rebar_window, use_toolbar ? SW_SHOW : SW_HIDE) ;
|
|
// this seems to be needed to get the rebar to redraw properly with v4.72 of comctrl32.dll.
|
|
InvalidateRect (main_window, NULL, true) ;
|
|
toolheight = 0 ;
|
|
GetClientRect (main_window, &rect) ;
|
|
SendMessage (main_window, WM_SIZE, SIZE_RESTORED, MAKELPARAM (rect.right, rect.bottom)) ;
|
|
return (true) ;
|
|
|
|
case CM_SINGLEINSTANCE :
|
|
PutHKCU ("General", "OneInstance", one_instance) ;
|
|
return (true) ;
|
|
|
|
case CM_FILEEXIT :
|
|
if (rendering)
|
|
{
|
|
if (MessageBox (main_window,
|
|
"POV-Ray is currently rendering - do you want to stop ?",
|
|
"Stop rendering ?",
|
|
MB_ICONQUESTION | MB_YESNO) == IDYES)
|
|
{
|
|
if (!EditCanClose (true))
|
|
return (true) ;
|
|
if (!quit)
|
|
quit = time (NULL) ;
|
|
cancel_render () ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!EditCanClose (true))
|
|
return (true) ;
|
|
DestroyWindow (main_window) ;
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_FILERENDER :
|
|
case CM_STOPRENDER :
|
|
if (Session.BackendFailed())
|
|
return (true) ;
|
|
if (!rendering)
|
|
{
|
|
if (EditSaveModified (NULL) == 0)
|
|
return (true) ;
|
|
// EDIT_MSG_SELECTED is only ever set if use_editors == true
|
|
if ((EditGetFlags () & EDIT_MSG_SELECTED) == 0)
|
|
{
|
|
if ((s = EditGetFilename(false)) == NULL)
|
|
{
|
|
PovMessageBox ("No file to render in current editor tab!", "Cannot render") ;
|
|
return (true) ;
|
|
}
|
|
n = get_file_type (s) ;
|
|
if (n == filePOV || n == fileINI || !ExternalDragFunction (s, dfRenderEditor))
|
|
PostMessage (main_window, EDITOR_RENDER_MESSAGE, 0, (LPARAM) s) ;
|
|
return (true) ;
|
|
}
|
|
SetForegroundWindow (main_window) ;
|
|
if (!ExternalDragFunction (source_file_name, dfRenderMessage))
|
|
start_rendering (false) ;
|
|
}
|
|
else
|
|
{
|
|
if (Session.GetBackendState () >= kStopping)
|
|
return (true) ;
|
|
if (OkToStopRendering ())
|
|
{
|
|
if (rendersleep)
|
|
{
|
|
SleepTimeEnd = clock () ;
|
|
SleepTimeTotal += SleepTimeEnd - SleepTimeStart ;
|
|
rendersleep = false ;
|
|
}
|
|
stop_rendering = true ;
|
|
cancel_render () ;
|
|
}
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_SAVE_SETTINGS :
|
|
PutHKCU ("General", "SaveSettingsOnExit", save_settings) ;
|
|
return (true) ;
|
|
|
|
case CM_DUMPPANE :
|
|
dump_pane_to_clipboard () ;
|
|
return (true) ;
|
|
|
|
case CM_CLEARMESSAGES :
|
|
clear_messages () ;
|
|
PovInvalidateRect (message_window, NULL, false) ;
|
|
UpdateWindow (message_window) ;
|
|
return (true) ;
|
|
|
|
case CM_FORCE8BITS :
|
|
detect_graphics_config () ;
|
|
if (hPalApp)
|
|
DeleteObject (hPalApp) ;
|
|
hPalApp = WinLegacyDisplay::CreatePalette (NULL, 0, render_bitmap_depth != 24) ;
|
|
buffer_message (mIDE, render_bitmap_depth == 24 ? "Using 24-bit internal bitmap\n" :
|
|
renderwin_8bits ? "Using 8-bit dithered internal bitmap (menu setting)\n" :
|
|
"Using 8-bit dithered internal bitmap (4 or 8-bit video mode)\n") ;
|
|
return (true) ;
|
|
|
|
case CM_RENDERABOVEMAIN :
|
|
// TODO FIXME CJC
|
|
#if 0
|
|
// simply re-parenting doesn't seem to have the desired effect. sigh.
|
|
WinDisplay *rw = GetRenderWindow();
|
|
if (rw != NULL)
|
|
{
|
|
oldHwnd = render_window ;
|
|
render_window = NULL ;
|
|
ShowWindow (oldHwnd, SW_HIDE) ;
|
|
SetForegroundWindow (main_window) ;
|
|
DestroyWindow (oldHwnd) ;
|
|
renderwin_manually_closed = false ;
|
|
create_render_window (true) ;
|
|
ShowWindow (render_window, SW_SHOW) ;
|
|
}
|
|
#endif
|
|
PVEnableMenuItem (CM_RENDERHIDE, RenderwinIsChild ? MF_GRAYED : MF_ENABLED) ;
|
|
PVEnableMenuItem (CM_RENDERACTIVE, RenderwinIsChild ? MF_GRAYED : MF_ENABLED) ;
|
|
return (true) ;
|
|
|
|
case CM_USEEDITOR :
|
|
editors_enabled = !editors_enabled;
|
|
PutHKCU ("General", "UseEditors", editors_enabled) ;
|
|
PVCheckMenuItem (CM_USEEDITOR, editors_enabled ? MF_CHECKED : MF_UNCHECKED) ;
|
|
if (editors_enabled == use_editors)
|
|
return true;
|
|
if (MessageBox (main_window,
|
|
"POV-Ray for Windows needs to re-start for this to take effect immediately.\n\n"
|
|
"Re-start POV-Ray ?",
|
|
"Re-start POV-Ray for Windows ?",
|
|
MB_ICONEXCLAMATION | MB_YESNO) == IDYES)
|
|
{
|
|
GetModuleFileName (hInstance, filename, sizeof (filename) - 1) ;
|
|
if (save_settings)
|
|
{
|
|
SendMessage (toolbar_combobox,
|
|
CB_GETLBTEXT,
|
|
SendMessage (toolbar_combobox, CB_GETCURSEL, 0, 0),
|
|
(LPARAM) SecondaryRenderIniFileSection) ;
|
|
if (restore_command_line)
|
|
{
|
|
strcpy (command_line, old_command_line) ;
|
|
SendMessage (toolbar_cmdline, WM_SETTEXT, 0, (LPARAM) command_line) ;
|
|
restore_command_line = false ;
|
|
}
|
|
write_INI_settings () ;
|
|
EditSaveState () ;
|
|
}
|
|
DestroyWindow (main_window) ;
|
|
execute_tool (filename) ;
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_HELPABOUT :
|
|
ShowAboutBox () ;
|
|
return (true) ;
|
|
|
|
case CM_TOOLBARCMDLINE :
|
|
if (!rendering)
|
|
{
|
|
SetFocus (toolbar_cmdline) ;
|
|
SendMessage (toolbar_cmdline, EM_SETSEL, 0, -1) ;
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_RENDERINSERT :
|
|
if (!rendering)
|
|
RenderInsertMenu () ;
|
|
return (true) ;
|
|
|
|
case CM_COMMANDLINE :
|
|
if (!rendering)
|
|
{
|
|
if (DialogBoxParam (hInstance,
|
|
MAKEINTRESOURCE (IDD_COMMANDLINE),
|
|
main_window,
|
|
(DLGPROC) PovCommandLineDialogProc,
|
|
(LPARAM) main_window))
|
|
{
|
|
if (!ExternalDragFunction (source_file_name, dfRenderCommandLine))
|
|
start_rendering (false) ;
|
|
}
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_TILEDBACKGROUND :
|
|
PVModifyMenu (CM_TILEDBACKGROUND, MF_STRING, CM_TILEDBACKGROUND, tile_background ? "&Use Plain Background" : "&Use Tiled Background") ;
|
|
if (tile_background && hBmpBackground == NULL)
|
|
{
|
|
if ((hBmpBackground = NonBogusLoadBitmap (hInstance, MAKEINTRESOURCE (BMP_BACKGROUND00))) != NULL)
|
|
{
|
|
GetObject (hBmpBackground, sizeof (BITMAP), (LPSTR) &bm) ;
|
|
background_width = bm.bmWidth ;
|
|
background_height = bm.bmHeight ;
|
|
tile_background = true ;
|
|
PovInvalidateRect (message_window, NULL, true) ;
|
|
}
|
|
else
|
|
{
|
|
tile_background = false ;
|
|
// make sure this messagebox is AFTER we set tile_background to false !
|
|
PovMessageBox ("Failed to load internal bitmap", "Error") ;
|
|
PVModifyMenu (CM_TILEDBACKGROUND, MF_STRING, CM_TILEDBACKGROUND, "&Select Tiled Background") ;
|
|
background_file [0] = '\0' ;
|
|
}
|
|
return (true) ;
|
|
}
|
|
else
|
|
PovInvalidateRect (message_window, NULL, true) ;
|
|
return (true) ;
|
|
|
|
case CM_BACKGROUNDCOLOUR :
|
|
memset (&cc, 0, sizeof (CHOOSECOLOR)) ;
|
|
cc.lStructSize = sizeof (CHOOSECOLOR) ;
|
|
cc.hwndOwner = main_window ;
|
|
cc.rgbResult = background_colour ;
|
|
cc.Flags = CC_RGBINIT | CC_FULLOPEN ;
|
|
cc.lpCustColors = custom_colours ;
|
|
if (ChooseColor (&cc))
|
|
{
|
|
background_colour = cc.rgbResult ;
|
|
PovInvalidateRect (message_window, NULL, true) ;
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_BACKGROUNDBITMAP :
|
|
if ((s = get_background_file (main_window)) != NULL)
|
|
{
|
|
if ((hDIB = LoadDIB (s)) != NULL)
|
|
{
|
|
strcpy (background_file, s) ;
|
|
DeleteObject (hBmpBackground) ;
|
|
hBmpBackground = DIBToBitmap (hDIB, hPalApp) ;
|
|
DeleteObject (hDIB) ;
|
|
GetObject (hBmpBackground, sizeof (BITMAP), (LPSTR) &bm) ;
|
|
background_width = bm.bmWidth ;
|
|
background_height = bm.bmHeight ;
|
|
tile_background = true ;
|
|
PVModifyMenu (CM_TILEDBACKGROUND, MF_STRING, CM_TILEDBACKGROUND, "&Select Plain Background") ;
|
|
background_shade = RGB (1, 1, 1) ;
|
|
PovInvalidateRect (message_window, NULL, true) ;
|
|
}
|
|
else
|
|
PovMessageBox ("Failed to load bitmap file", "Error") ;
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_BACKGROUNDSTD + 0 :
|
|
case CM_BACKGROUNDSTD + 1 :
|
|
case CM_BACKGROUNDSTD + 2 :
|
|
case CM_BACKGROUNDSTD + 3 :
|
|
case CM_BACKGROUNDSTD + 4 :
|
|
case CM_BACKGROUNDSTD + 5 :
|
|
case CM_BACKGROUNDSTD + 6 :
|
|
case CM_BACKGROUNDSTD + 7 :
|
|
case CM_BACKGROUNDSTD + 8 :
|
|
case CM_BACKGROUNDSTD + 9 :
|
|
if ((hBMP = NonBogusLoadBitmap (hInstance, MAKEINTRESOURCE (BMP_BACKGROUND00 + (LOWORD (wParam) - CM_BACKGROUNDSTD)))) != NULL)
|
|
{
|
|
DeleteObject (hBmpBackground) ;
|
|
hBmpBackground = hBMP ;
|
|
if (GetObject (hBmpBackground, sizeof (BITMAP), (LPVOID) &bm) == 0)
|
|
{
|
|
PovMessageBox ("Failed to load internal bitmap", "Error") ;
|
|
tile_background = false ;
|
|
return (true) ;
|
|
}
|
|
background_width = bm.bmWidth ;
|
|
background_height = bm.bmHeight ;
|
|
background_file [0] = '0' + (char) (LOWORD (wParam) - CM_BACKGROUNDSTD) ;
|
|
background_file [1] = '\0' ;
|
|
switch (LOWORD (wParam))
|
|
{
|
|
case CM_BACKGROUNDSTD + 0 :
|
|
background_shade = RGB (1, 1, 1) ;
|
|
if (lParam != 1)
|
|
text_colours[0] = RGB (255, 255, 255) ;
|
|
break ;
|
|
|
|
case CM_BACKGROUNDSTD + 1 :
|
|
background_shade = RGB (0, 0, 0) ;
|
|
if (lParam != 1)
|
|
text_colours[0] = RGB (255, 255, 255) ;
|
|
break ;
|
|
|
|
case CM_BACKGROUNDSTD + 2 :
|
|
background_shade = RGB (1, 1, 1) ;
|
|
if (lParam != 1)
|
|
text_colours[0] = RGB (255, 255, 255) ;
|
|
break ;
|
|
|
|
case CM_BACKGROUNDSTD + 3 :
|
|
background_shade = RGB (1, 1, 1) ;
|
|
if (lParam != 1)
|
|
text_colours[0] = RGB (255, 255, 255) ;
|
|
break ;
|
|
|
|
case CM_BACKGROUNDSTD + 4 :
|
|
background_shade = RGB (1, 1, 1) ;
|
|
if (lParam != 1)
|
|
text_colours[0] = RGB (255, 255, 255) ;
|
|
break ;
|
|
|
|
case CM_BACKGROUNDSTD + 5 :
|
|
background_shade = RGB (1, 1, 1) ;
|
|
if (lParam != 1)
|
|
text_colours[0] = RGB (0, 0, 0) ;
|
|
break ;
|
|
}
|
|
tile_background = true ;
|
|
PVModifyMenu (CM_TILEDBACKGROUND, MF_STRING, CM_TILEDBACKGROUND, "&Select Plain Background") ;
|
|
PovInvalidateRect (message_window, NULL, true) ;
|
|
}
|
|
else
|
|
PovMessageBox ("Failed to load internal bitmap", "Error") ;
|
|
return (true) ;
|
|
|
|
case CM_TEXTCOLOUR_NORMAL :
|
|
case CM_TEXTCOLOUR_WARNING :
|
|
case CM_TEXTCOLOUR_ERROR :
|
|
memset (&cc, 0, sizeof (CHOOSECOLOR)) ;
|
|
cc.lStructSize = sizeof (CHOOSECOLOR) ;
|
|
cc.hwndOwner = main_window ;
|
|
cc.rgbResult = text_colours[LOWORD (wParam) - CM_TEXTCOLOUR_FIRST] ;
|
|
cc.Flags = CC_RGBINIT | CC_FULLOPEN ;
|
|
cc.lpCustColors = custom_colours ;
|
|
if (ChooseColor (&cc))
|
|
{
|
|
text_colours[LOWORD (wParam) - CM_TEXTCOLOUR_FIRST] = cc.rgbResult ;
|
|
PovInvalidateRect (message_window, NULL, true) ;
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_FONT :
|
|
get_font () ;
|
|
return (true) ;
|
|
|
|
case CM_RENDERSHOW :
|
|
if (GetRenderWindow() != NULL)
|
|
{
|
|
GetRenderWindow()->Show();
|
|
PVEnableMenuItem (CM_RENDERSHOW, MF_GRAYED) ;
|
|
PVEnableMenuItem (CM_RENDERCLOSE, MF_ENABLED) ;
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_RENDERCLOSE :
|
|
if (GetRenderWindow() != NULL)
|
|
{
|
|
if (GetForegroundWindow () == GetRenderwinHandle())
|
|
if (RenderwinIsChild)
|
|
SetForegroundWindow (main_window) ;
|
|
GetRenderWindow()->Hide();
|
|
PVEnableMenuItem (CM_RENDERSHOW, MF_ENABLED) ;
|
|
PVEnableMenuItem (CM_RENDERCLOSE, MF_GRAYED) ;
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_RENDERDESTROY :
|
|
if (GetForegroundWindow () == (HWND) lParam)
|
|
SetForegroundWindow (main_window) ;
|
|
DestroyWindow ((HWND) lParam) ;
|
|
return (true) ;
|
|
|
|
case CM_CLEARQUEUE :
|
|
queued_file_count = 0 ;
|
|
update_queue_status (true) ;
|
|
return (true) ;
|
|
|
|
case CM_FILEQUEUE :
|
|
DialogBoxParam (hInstance, MAKEINTRESOURCE (IDD_FILEQUEUE), main_window, (DLGPROC) PovFileQueueDialogProc, (LPARAM) main_window) ;
|
|
return (true) ;
|
|
|
|
case CM_SOURCEFILE :
|
|
if (!rendering)
|
|
{
|
|
if ((s = file_open (main_window)) != NULL)
|
|
{
|
|
strcpy (source_file_name, s) ;
|
|
splitpath (source_file_name, lastRenderPath, lastRenderName) ;
|
|
validatePath (lastRenderPath) ;
|
|
if (!ExternalDragFunction (source_file_name, dfRenderSourceFile))
|
|
start_rendering (false) ;
|
|
}
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_RENDERSOUNDS :
|
|
hh_aklink.pszKeywords = "sounds" ;
|
|
DialogBoxParam (hInstance, MAKEINTRESOURCE (IDD_SOUNDS), main_window, (DLGPROC) PovSoundsDialogProc, (LPARAM) main_window) ;
|
|
return (true) ;
|
|
|
|
case CM_RENDERTHREADCOUNT :
|
|
hh_aklink.pszKeywords = "thread count" ; // TODO
|
|
DialogBoxParam (hInstance, MAKEINTRESOURCE (IDD_THREADS), main_window, (DLGPROC) PovThreadCountDialogProc, (LPARAM) main_window) ;
|
|
return (true) ;
|
|
|
|
case CM_DEMO :
|
|
if (!rendering && !running_demo)
|
|
{
|
|
if (save_demo_file (demo_file_name, demo_ini_name) != NULL)
|
|
{
|
|
if (!demo_mode)
|
|
{
|
|
running_demo = true ;
|
|
if (DialogBoxParam (hInstance, MAKEINTRESOURCE (IDD_SHORTCOMMANDLINE), main_window, (DLGPROC) PovShortCommandLineDialogProc, (LPARAM) main_window))
|
|
{
|
|
if (!restore_command_line)
|
|
strcpy (old_command_line, command_line) ;
|
|
restore_command_line = true ;
|
|
sprintf (command_line, "Include_Ini='%s' Input_File_Name='%s' ", demo_ini_name, demo_file_name) ;
|
|
_strupr (command_line) ;
|
|
strcat (command_line, old_command_line) ;
|
|
ignore_auto_ini = true ;
|
|
start_rendering (true) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!restore_command_line)
|
|
strcpy (old_command_line, command_line) ;
|
|
restore_command_line = true ;
|
|
sprintf (command_line, "Include_Ini='%s' Input_File_Name='%s' ", demo_ini_name, demo_file_name) ;
|
|
running_demo = true ;
|
|
start_rendering (true) ;
|
|
}
|
|
}
|
|
}
|
|
return (true) ;
|
|
|
|
case CM_BENCHMARK :
|
|
case CM_BENCHMARKONETHREAD :
|
|
if (rendering)
|
|
return (0) ;
|
|
if (!benchmark_mode)
|
|
{
|
|
n = Get_Benchmark_Version () ;
|
|
hh_aklink.pszKeywords = "Run Benchmark" ;
|
|
sprintf (str, "This command will run the standard POV-Ray benchmark version %x.%02x.\n", n / 256, n % 256) ;
|
|
strcat (str, "This will take some time, and there will be no display or file output.\n\n") ;
|
|
strcat (str, "Note that the benchmark has changed since v3.6 and cannot be compared with it.\n\n") ;
|
|
if (LOWORD (wParam) == CM_BENCHMARK)
|
|
{
|
|
sprintf(str + strlen(str), "The benchmark will be rendered using %d threads. Continue?", ThreadCount) ;
|
|
benchmark_multithread = true ;
|
|
}
|
|
else
|
|
{
|
|
strcat (str, "The benchmark will be rendered using a single thread. Continue?") ;
|
|
benchmark_multithread = false ;
|
|
}
|
|
if (MessageBox (main_window, str, "Standard Benchmark", MB_YESNO | MB_ICONINFORMATION | MB_HELP) == IDNO)
|
|
return (0) ;
|
|
}
|
|
GetTempPath (_MAX_PATH - 16, demo_file_name) ;
|
|
appendPathSeparator(demo_file_name) ;
|
|
strcpy (demo_ini_name, demo_file_name) ;
|
|
strcat (demo_file_name, "POVBENCH.$$1") ;
|
|
strcat (demo_ini_name, "POVBENCH.$$2") ;
|
|
if (Write_Benchmark_File (demo_file_name, demo_ini_name))
|
|
{
|
|
running_benchmark = running_demo = true ;
|
|
int threadCount = benchmark_mode || benchmark_multithread ? ThreadCount : 1 ;
|
|
message_printf ("Running standard POV-Ray benchmark version %x.%02x using %d thread%s\n", n / 256, n % 256, threadCount, threadCount > 1 ? "s" : "") ;
|
|
buffer_message (mDivider, "\n") ;
|
|
status_printf (0, "Running standard POV-Ray benchmark version %x.%02x\n", n / 256, n % 256) ;
|
|
start_rendering (true) ;
|
|
}
|
|
else
|
|
PovMessageBox ("Failed to write temporary files", "Benchmark Failed") ;
|
|
return (true) ;
|
|
|
|
case CM_LOADTOOLMENU :
|
|
ExternalEvent (EventLoadToolMenu, 0) ;
|
|
load_tool_menu (ToolIniFileName) ;
|
|
break ;
|
|
|
|
case CM_HELPLOOKUP :
|
|
if (GetFocus () == GetRenderwinHandle ())
|
|
{
|
|
hh_aklink.pszKeywords = "Render Window" ;
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
return (true) ;
|
|
}
|
|
if (GetFocus () == toolbar_cmdline)
|
|
{
|
|
hh_aklink.pszKeywords = "Toolbar Command Line" ;
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
return (true) ;
|
|
}
|
|
if (GetFocus () == toolbar_combobox)
|
|
{
|
|
hh_aklink.pszKeywords = "Preset Rendering Options" ;
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
return (true) ;
|
|
}
|
|
if ((EditGetFlags () & EDIT_MSG_SELECTED) != 0)
|
|
HtmlHelp (NULL, engineHelpPath, HH_DISPLAY_TOC, 0) ;
|
|
else
|
|
EditContextHelp () ;
|
|
return (true) ;
|
|
|
|
case CM_HELPPOVWIN :
|
|
hh_aklink.pszKeywords = "welcome" ;
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
return (true) ;
|
|
|
|
case CM_HELPSCENE :
|
|
hh_aklink.pszKeywords = "Scene Description Language" ;
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
return (true) ;
|
|
|
|
case CM_GOPOVRAYORG :
|
|
ShellExecute (NULL, NULL, "http://www.povray.org/", NULL, NULL, SW_SHOWNORMAL) ;
|
|
return (true) ;
|
|
|
|
case CM_HELPBUGS :
|
|
hh_aklink.pszKeywords = "Bug Reports" ;
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
return (true) ;
|
|
|
|
case CM_POVLEGAL :
|
|
if (stat (engineHelpPath, &st) == 0)
|
|
{
|
|
hh_aklink.pszKeywords = "POV-Ray License" ;
|
|
if (HtmlHelp (main_window, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink))
|
|
return (true) ;
|
|
}
|
|
DialogBoxParam (hInstance, MAKEINTRESOURCE (IDD_VIEW), main_window, (DLGPROC) PovLegalDialogProc, (LPARAM) main_window) ;
|
|
return (true) ;
|
|
|
|
case CM_CHECKUPDATENOW:
|
|
#if POV_RAY_IS_OFFICIAL == 1
|
|
ManualUpdateCheck();
|
|
#endif
|
|
return true;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
LRESULT CALLBACK PovMainWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int i ;
|
|
char *s ;
|
|
char str [4096] ;
|
|
bool f ;
|
|
HDC hdc ;
|
|
RECT rect ;
|
|
POINT pt ;
|
|
NMHDR *nmh ;
|
|
DWORD result = 0 ;
|
|
HPALETTE oldPalette ;
|
|
TOOLTIPTEXT *t ;
|
|
COPYDATASTRUCT *cd ;
|
|
vfeSession& Session (GetSession());
|
|
|
|
PROCESS_MEMORY_COUNTERS memInfo;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_COPYDATA :
|
|
cd = (COPYDATASTRUCT *) lParam ;
|
|
if (cd->dwData == EDIT_FILE)
|
|
{
|
|
strncpy (str, (char *) cd->lpData, sizeof (str) - 1) ;
|
|
str [sizeof (str) - 1] = '\0' ;
|
|
if (EditGetFlags () & EDIT_CAN_OPEN)
|
|
EditOpenFile (str) ;
|
|
return (0) ;
|
|
}
|
|
if (cd->dwData == RENDER_FILE)
|
|
{
|
|
strncpy (str, (char *) cd->lpData, sizeof (str) - 1) ;
|
|
str [sizeof (str) - 1] = '\0' ;
|
|
if (rendering)
|
|
return (0) ;
|
|
strcpy (source_file_name, str) ;
|
|
start_rendering (false) ;
|
|
return (0) ;
|
|
}
|
|
return (1) ;
|
|
|
|
case COPY_COMMANDLINE_MESSAGE :
|
|
command_line [sizeof (command_line) - 1] = '\0' ;
|
|
strncpy (command_line, (LPCSTR) lParam, sizeof (command_line) - 1) ;
|
|
SendMessage (toolbar_cmdline, WM_SETTEXT, 0, (LPARAM) command_line) ;
|
|
SendMessage (toolbar_cmdline, EM_SETSEL, 0, strlen (command_line)) ;
|
|
SetFocus (toolbar_cmdline) ;
|
|
return (true) ;
|
|
|
|
case WM_HELP :
|
|
// we expect that whatever routine caused the WM_HELP would have set up the keyword
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
return (true) ;
|
|
|
|
case KEYWORD_LOOKUP_MESSAGE :
|
|
hh_aklink.pszKeywords = (LPCSTR) lParam ;
|
|
if (strncmp (hh_aklink.pszKeywords, "oooo", 4) == 0)
|
|
hh_aklink.pszKeywords = "" ;
|
|
if (strncmp (hh_aklink.pszKeywords, "//", 2) == 0)
|
|
hh_aklink.pszKeywords = "" ;
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
return (true) ;
|
|
|
|
case TASKBAR_NOTIFY_MESSAGE :
|
|
if (lParam == WM_LBUTTONDBLCLK)
|
|
{
|
|
if (ListenMode)
|
|
{
|
|
char *s = "POV-Ray is in network listen mode. Press OK to continue listening or "
|
|
"CANCEL to shut down and exit." ;
|
|
if (MessageBox (main_window, s, "POV-Ray - Network Listen Mode", MB_OKCANCEL | MB_SYSTEMMODAL) == IDOK)
|
|
return (0) ;
|
|
TaskBarDeleteIcon (main_window, 0) ;
|
|
DestroyWindow (main_window) ;
|
|
return (0) ;
|
|
}
|
|
ShowWindow (main_window, SW_SHOW) ;
|
|
ShowWindow (main_window, SW_RESTORE) ;
|
|
if (RenderwinIsChild == false && HideRenderWithMain == true)
|
|
if (GetRenderWindow() != NULL)
|
|
GetRenderWindow()->Show();
|
|
PVModifyMenu (CM_SHOWMAINWINDOW, MF_STRING, CM_SHOWMAINWINDOW, "Minimize to System &Tray\tAlt+W") ;
|
|
main_window_hidden = 0 ;
|
|
TaskBarDeleteIcon (main_window, 0) ;
|
|
return (0) ;
|
|
}
|
|
if (lParam == WM_RBUTTONDOWN)
|
|
{
|
|
if (ListenMode)
|
|
return (0) ;
|
|
if (hPopupMenus != NULL)
|
|
{
|
|
GetCursorPos (&pt) ;
|
|
SetForegroundWindow (main_window) ;
|
|
TrackPopupMenu (GetSubMenu (hPopupMenus, 0), TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, main_window, NULL) ;
|
|
return (0) ;
|
|
}
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_ENTERSIZEMOVE :
|
|
if (!IsW95UserInterface)
|
|
break ;
|
|
resizing = true ;
|
|
break ;
|
|
|
|
case WM_EXITSIZEMOVE :
|
|
if (!IsW95UserInterface)
|
|
break ;
|
|
resizing = false ;
|
|
InvalidateRect (message_window, NULL, true) ;
|
|
break ;
|
|
|
|
case WM_SETFOCUS :
|
|
// After a dialog has been displayed, Windows will give the focus
|
|
// back to our main window. We need to farm the focus off to whatever
|
|
// window should have it. EditSetFocus () will handle this for us.
|
|
EditSetFocus () ;
|
|
return (0) ;
|
|
|
|
case EDITOR_RENDER_MESSAGE :
|
|
if (rendering)
|
|
{
|
|
if (OkToStopRendering ())
|
|
{
|
|
stop_rendering = true ;
|
|
cancel_render () ;
|
|
}
|
|
return (0) ;
|
|
}
|
|
strcpy (source_file_name, (char *) lParam) ;
|
|
if (is_non_primary_file(source_file_name))
|
|
{
|
|
char fn[_MAX_PATH + 1];
|
|
|
|
strcpy(fn, source_file_name);
|
|
_strlwr(fn);
|
|
|
|
// see if we have a previous decision recorded for this file.
|
|
map<string, bool>::const_iterator altit = IncludeAlternateDecisionMap.find(fn);
|
|
if (altit == IncludeAlternateDecisionMap.end() || altit->second == true)
|
|
{
|
|
// either there is no decision recorded, or the decision was 'yes'
|
|
// in either case we need to find the alternate filename
|
|
map<string, string>::const_iterator it = IncludeToSourceMap.find(fn);
|
|
if (it != IncludeToSourceMap.end())
|
|
{
|
|
// we've found the alternate filename. do we need to ask the user about it?
|
|
if (altit == IncludeAlternateDecisionMap.end())
|
|
{
|
|
// yes we do.
|
|
switch (DialogBoxParam (hInstance, MAKEINTRESOURCE (IDD_RENDERALTERNATEFILE), main_window, (DLGPROC) RenderAlternativeFileDialogProc, (LPARAM) it->second.c_str()))
|
|
{
|
|
case IDYES:
|
|
// record the decision
|
|
IncludeAlternateDecisionMap.insert(pair<string, bool>(fn, true));
|
|
strcpy(source_file_name, it->second.c_str());
|
|
break;
|
|
|
|
case IDOK:
|
|
// we don't record this decision
|
|
strcpy(source_file_name, it->second.c_str());
|
|
break;
|
|
|
|
case IDNO:
|
|
// record the decision
|
|
IncludeAlternateDecisionMap.insert(pair<string, bool>(fn, false));
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
return (0) ;
|
|
}
|
|
}
|
|
else
|
|
strcpy(source_file_name, it->second.c_str());
|
|
}
|
|
}
|
|
}
|
|
splitpath (source_file_name, lastRenderPath, lastRenderName) ;
|
|
if (!ExternalDragFunction (source_file_name, dfRenderEditor))
|
|
start_rendering (false) ;
|
|
return (0) ;
|
|
|
|
case CREATE_RENDERWIN_MESSAGE :
|
|
if (dynamic_cast<WinDisplay *>(reinterpret_cast<WinDisplay *>(lParam)) != NULL)
|
|
return (dynamic_cast<WinDisplay *>(reinterpret_cast<WinDisplay *>(lParam))->CreateRenderWindow());
|
|
return (0) ;
|
|
|
|
case GUIEXT_CREATE_EDITOR :
|
|
if (wParam == 0)
|
|
{
|
|
message_printf ("External application or GUIEXT sent zero-length wParam for GUIEXT_CREATE_EDITOR\n") ;
|
|
return (0) ;
|
|
}
|
|
if (IsBadReadPtr ((void *) lParam, wParam + 1))
|
|
{
|
|
message_printf ("External application or GUIEXT sent bad paramstr address for GUIEXT_CREATE_EDITOR\n") ;
|
|
return (0) ;
|
|
}
|
|
if (((char *) lParam) [wParam] != '\0')
|
|
{
|
|
message_printf ("External application or GUIEXT sent non-NULL terminated paramstr for GUIEXT_CREATE_EDITOR\n") ;
|
|
return (0) ;
|
|
}
|
|
return (EditExternalOpenFile ((char *) lParam)) ;
|
|
|
|
case WM_NOTIFY :
|
|
nmh = (NMHDR *) lParam ;
|
|
if (nmh->hwndFrom == tab_window)
|
|
{
|
|
EditPassOnMessage (hwnd, message, wParam, lParam, &result) ;
|
|
break ;
|
|
}
|
|
if (nmh->hwndFrom == rebar_window)
|
|
{
|
|
switch (nmh->code)
|
|
{
|
|
case RBN_HEIGHTCHANGE :
|
|
if (!use_toolbar)
|
|
break ;
|
|
GetClientRect (rebar_window, &rect) ;
|
|
|
|
// under XP with comctrl v6 it has been noticed that this event will occur
|
|
// when the main window is minimized, before the parent's WM_SIZE message
|
|
// is received, and that the return value from GetClientRect () seems to
|
|
// be rather strange (e.g. 0,0,202,0 where the actual height is about 75.)
|
|
if (rect.right == rect.left)
|
|
break ;
|
|
|
|
toolheight = rect.bottom ;
|
|
CalculateClientWindows (true) ;
|
|
|
|
// need this due to an issue with Windows 95
|
|
if (top_message_row)
|
|
{
|
|
ShowScrollBar (message_window, SB_VERT, false) ;
|
|
ShowScrollBar (message_window, SB_VERT, true) ;
|
|
}
|
|
if (need_hscroll ())
|
|
{
|
|
ShowScrollBar (message_window, SB_HORZ, false) ;
|
|
ShowScrollBar (message_window, SB_HORZ, true) ;
|
|
}
|
|
break ;
|
|
}
|
|
break ;
|
|
}
|
|
if (nmh->hwndFrom == StatusTooltip)
|
|
{
|
|
if (HandleStatusTooltip(nmh))
|
|
return 0;
|
|
break;
|
|
}
|
|
switch (nmh->code)
|
|
{
|
|
case TTN_NEEDTEXT :
|
|
t = (TOOLTIPTEXT *) lParam ;
|
|
if (use_tooltips == 0)
|
|
{
|
|
t->lpszText = NULL ;
|
|
t->hinst = 0 ;
|
|
break ;
|
|
}
|
|
t->hinst = hInstance ;
|
|
t->lpszText = MAKEINTRESOURCE (t->hdr.idFrom) ;
|
|
return (0) ;
|
|
}
|
|
break ;
|
|
|
|
case RENDER_MESSAGE :
|
|
s = getCommandLine () ;
|
|
if (rendering && (strlen (s) || wParam))
|
|
{
|
|
PovMessageBox ("Cannot accept new command - already rendering", "Warning") ;
|
|
return (0) ;
|
|
}
|
|
if (main_window_hidden)
|
|
{
|
|
ShowWindow (main_window, SW_SHOW) ;
|
|
ShowWindow (main_window, SW_RESTORE) ;
|
|
if (RenderwinIsChild == false && HideRenderWithMain == true)
|
|
if (GetRenderWindow() != NULL)
|
|
GetRenderWindow()->Show();
|
|
PVModifyMenu (CM_SHOWMAINWINDOW, MF_STRING, CM_SHOWMAINWINDOW, "Minimize to System &Tray\tAlt+W") ;
|
|
main_window_hidden = 0 ;
|
|
TaskBarDeleteIcon (main_window, 0) ;
|
|
return (0) ;
|
|
}
|
|
if (wParam == 0)
|
|
{
|
|
if (strlen (s) == 0)
|
|
return (0) ;
|
|
if (!restore_command_line)
|
|
strcpy (old_command_line, command_line) ;
|
|
restore_command_line = true ;
|
|
strcpy (command_line, s) ;
|
|
start_rendering (true) ;
|
|
strcpy (command_line, old_command_line) ;
|
|
SendMessage (toolbar_cmdline, WM_SETTEXT, 0, (LPARAM) command_line) ;
|
|
restore_command_line = false ;
|
|
}
|
|
else
|
|
handle_main_command (CM_DEMO, 0) ;
|
|
return (0) ;
|
|
|
|
case WM_CREATE :
|
|
main_window = hwnd ;
|
|
hMainMenu = CreateMenu () ;
|
|
build_main_menu (hMainMenu, false) ;
|
|
SetMenu (main_window, hMainMenu) ;
|
|
break ;
|
|
|
|
case WM_QUERYENDSESSION :
|
|
if (rendering)
|
|
{
|
|
if (MessageBox (main_window, "POV-Ray is currently rendering - do you want to stop ?", "Stop rendering ?", MB_ICONQUESTION | MB_YESNO) != IDYES)
|
|
return (false) ;
|
|
if (!EditCanClose (true))
|
|
return (false) ;
|
|
if (!quit)
|
|
quit = time (NULL) ;
|
|
cancel_render () ;
|
|
return (true) ;
|
|
}
|
|
return (EditCanClose (true)) ;
|
|
|
|
case WM_ENDSESSION :
|
|
if (wParam != 0)
|
|
{
|
|
setRunOnce () ;
|
|
if (save_settings)
|
|
{
|
|
SendMessage (toolbar_combobox, CB_GETLBTEXT, SendMessage (toolbar_combobox, CB_GETCURSEL, 0, 0), (LPARAM) SecondaryRenderIniFileSection) ;
|
|
if (restore_command_line)
|
|
{
|
|
strcpy (command_line, old_command_line) ;
|
|
SendMessage (toolbar_cmdline, WM_SETTEXT, 0, (LPARAM) command_line) ;
|
|
restore_command_line = false ;
|
|
}
|
|
write_INI_settings () ;
|
|
EditSaveState () ;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
case WM_COMMAND :
|
|
if ((HANDLE) lParam == toolbar_cmdline)
|
|
{
|
|
// need to use EN_CHANGE rather than EN_KILLFOCUS as the command-line dialog
|
|
// will grab and possibly modify command_line before focus is lost, should it
|
|
// be activated while the edit control has focus.
|
|
if (HIWORD (wParam) == EN_CHANGE)
|
|
{
|
|
SendMessage (toolbar_cmdline, WM_GETTEXT, sizeof (command_line) - 1, (LPARAM) command_line) ;
|
|
return (0) ;
|
|
}
|
|
}
|
|
if ((HANDLE) lParam == toolbar_combobox)
|
|
{
|
|
if (HIWORD (wParam) == CBN_CLOSEUP)
|
|
{
|
|
cb_expect_selchange++ ;
|
|
return (0) ;
|
|
}
|
|
if (HIWORD (wParam) == CBN_SELCHANGE)
|
|
{
|
|
i = SendMessage (toolbar_combobox, CB_GETCURSEL, 0, 0) ;
|
|
if (i == SendMessage (toolbar_combobox, CB_GETCOUNT, 0, 0) - 1)
|
|
{
|
|
SendMessage (toolbar_combobox, CB_SETCURSEL, tb_combo_sel, 0) ;
|
|
if (cb_expect_selchange)
|
|
{
|
|
hh_aklink.pszKeywords = "Adding New Resolutions" ;
|
|
HtmlHelp (NULL, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink) ;
|
|
}
|
|
}
|
|
else
|
|
tb_combo_sel = i ;
|
|
cb_expect_selchange = 0 ;
|
|
return (0) ;
|
|
}
|
|
}
|
|
if (EditPassOnMessage (hwnd, message, wParam, lParam, &result))
|
|
return (result) ;
|
|
if (ExtensionsEnabled)
|
|
if (LOWORD (wParam) >= CM_FIRSTGUIEXT && LOWORD (wParam) <= CM_LASTGUIEXT)
|
|
return (ExternalMenuSelect (LOWORD (wParam))) ;
|
|
if (handle_main_command (wParam, lParam))
|
|
return (0) ;
|
|
break ;
|
|
|
|
case WM_INITMENU :
|
|
EditUpdateMenus ((HMENU) wParam) ;
|
|
EditPassOnMessage (hwnd, message, wParam, lParam, &result) ;
|
|
break ;
|
|
|
|
case WM_ACTIVATEAPP :
|
|
EditPassOnMessage (hwnd, message, wParam, lParam, &result) ;
|
|
break ;
|
|
|
|
case WM_TIMER :
|
|
if (!BackendFailedFlag && Session.BackendFailed())
|
|
{
|
|
BackendFailedFlag = true;
|
|
if (rendering)
|
|
{
|
|
rendering = false;
|
|
update_menu_for_render (false) ;
|
|
PVEnableMenuItem (CM_FILERENDER, MF_DISABLED) ;
|
|
PVEnableMenuItem (CM_STOPRENDER, MF_DISABLED) ;
|
|
SendMessage (toolbar_window, TB_HIDEBUTTON, (WPARAM) CM_FILERENDER, MAKELONG (0, 0)) ;
|
|
SendMessage (toolbar_window, TB_HIDEBUTTON, (WPARAM) CM_STOPRENDER, MAKELONG (0, 0)) ;
|
|
status_buffer [0] = '\0' ;
|
|
say_status_message (StatusMessage, "Render backend Failed - please re-start POV-Ray");
|
|
delay_next_status = 2500;
|
|
buffer_message (mFatal, "Render backend Failed - please re-start POV-Ray\n") ;
|
|
if (render_complete_sound_enabled)
|
|
PlaySound (render_error_sound, NULL, SND_ASYNC | SND_NODEFAULT) ;
|
|
}
|
|
}
|
|
if (rendering && !Session.BackendFailed() && Session.GetPercentComplete() != LastRenderPercentage)
|
|
{
|
|
LastRenderPercentage = Session.GetPercentComplete();
|
|
if (GetRenderWindow() != NULL)
|
|
{
|
|
sprintf (str, "%d%% complete", LastRenderPercentage) ;
|
|
GetRenderWindow()->SetCaption(str);
|
|
}
|
|
if (main_window_hidden)
|
|
{
|
|
sprintf (str, "POV-Ray [%d%% complete] (Restore: DblClk ; Menu: Mouse2)", LastRenderPercentage) ;
|
|
TaskBarModifyIcon (main_window, 0, str) ;
|
|
}
|
|
SendMessage (StatusPanelItems [IDC_STATUS_PROGRESS].hwnd, PBM_SETPOS, (WPARAM) LastRenderPercentage, 0) ;
|
|
SetCaption (NULL) ;
|
|
}
|
|
if (delay_next_status)
|
|
{
|
|
delay_next_status -= 250 ;
|
|
if (delay_next_status < 0)
|
|
delay_next_status = 0 ;
|
|
}
|
|
if (status_buffer [0] != '\0' && delay_next_status == 0)
|
|
{
|
|
say_status_message (StatusMessage, status_buffer) ;
|
|
status_buffer [0] = '\0' ;
|
|
}
|
|
|
|
memInfo.cb = sizeof(memInfo);
|
|
GetProcessMemoryInfo(GetCurrentProcess(), &memInfo, sizeof(memInfo));
|
|
status_printf(StatusMem, "\t%uMB", (unsigned int) (memInfo.WorkingSetSize / 1048576));
|
|
if (TrackMem && memInfo.WorkingSetSize > PeakMem)
|
|
PeakMem = memInfo.WorkingSetSize;
|
|
|
|
// NOTE: if we ever change the timer rate, we need to update the editor code too.
|
|
EditPassOnMessage (hwnd, message, wParam, lParam, &result) ;
|
|
if (timer_ticks++ % 4 != 3)
|
|
break ;
|
|
seconds++ ;
|
|
|
|
#if POV_RAY_IS_OFFICIAL == 1
|
|
if (seconds % 600 == 0)
|
|
DoUpdateCheck () ;
|
|
#endif
|
|
|
|
ExternalEvent (EventTimer, seconds) ;
|
|
if (MenuBarDraw)
|
|
{
|
|
DrawMenuBar (main_window) ;
|
|
MenuBarDraw = false ;
|
|
}
|
|
if (!rendering)
|
|
{
|
|
if (auto_render)
|
|
{
|
|
if (queued_file_count)
|
|
{
|
|
queued_file_count-- ;
|
|
update_queue_status (true) ;
|
|
strcpy (source_file_name, queued_files [0]) ;
|
|
memcpy (queued_files [0], queued_files [1], sizeof (queued_files) - sizeof (queued_files [0])) ;
|
|
splitpath (source_file_name, dir, NULL) ;
|
|
SetCurrentDirectory (dir) ;
|
|
if (seconds < 60 && GetHKCU("Info", "Rendering", 0) != 0)
|
|
{
|
|
// don't run the file if we were rendering when POV exited.
|
|
// [Rendering should only be set if there was an abnormal exit.]
|
|
PutHKCU ("Info", "Rendering", 0U) ;
|
|
message_printf ("Skipping queued file '%s' (possible abnormal exit)\n", source_file_name) ;
|
|
buffer_message (mDivider, "\n") ;
|
|
}
|
|
else
|
|
if (!ExternalDragFunction (source_file_name, dfRenderFileQueue))
|
|
start_rendering (false) ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PrintRenderTimes (false, false) ;
|
|
if (seconds % 10 == 0)
|
|
{
|
|
if (PreventSleep && !rendersleep)
|
|
SetThreadExecutionState(ES_AWAYMODE_REQUIRED | ES_SYSTEM_REQUIRED);
|
|
if (rendersleep)
|
|
FlashWindow (main_window, true) ;
|
|
}
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_PALETTECHANGED :
|
|
// make sure it wasn't us who changed the palette, otherwise we can get into an infinite loop.
|
|
if ((HWND) wParam == main_window)
|
|
return (0) ;
|
|
// FALL THROUGH to WM_QUERYNEWPALETTE
|
|
|
|
case WM_QUERYNEWPALETTE :
|
|
if (hPalApp)
|
|
{
|
|
hdc = GetDC (main_window) ;
|
|
oldPalette = SelectPalette (hdc, hPalApp, false) ;
|
|
f = (RealizePalette (hdc) != 0);
|
|
SelectPalette (hdc, oldPalette, false) ;
|
|
ReleaseDC (main_window, hdc) ;
|
|
if (f)
|
|
{
|
|
PovInvalidateRect (hwnd, NULL, true) ;
|
|
if ((EditGetFlags () & EDIT_MSG_SELECTED) == 0)
|
|
PovInvalidateRect (message_window, NULL, true) ;
|
|
if (GetRenderwinHandle() != NULL)
|
|
PovInvalidateRect (GetRenderwinHandle(), NULL, true) ;
|
|
}
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_SIZE :
|
|
if (main_window_hidden)
|
|
{
|
|
// perhaps another process has sent us a SIZE_RESTORED or something
|
|
if (GetRenderWindow() != NULL)
|
|
if (RenderwinIsChild == false && HideRenderWithMain == true)
|
|
GetRenderWindow()->Show();
|
|
PVModifyMenu (CM_SHOWMAINWINDOW, MF_STRING, CM_SHOWMAINWINDOW, "Minimize to System &Tray\tAlt+W") ;
|
|
main_window_hidden = 0 ;
|
|
TaskBarDeleteIcon (main_window, 0) ;
|
|
}
|
|
mainwin_placement.length = sizeof (WINDOWPLACEMENT) ;
|
|
GetWindowPlacement (main_window, &mainwin_placement) ;
|
|
SendMessage (rebar_window, WM_SIZE, wParam, lParam) ;
|
|
SendMessage (StatusWindow, WM_SIZE, wParam, lParam) ;
|
|
ResizeStatusBar (StatusWindow) ;
|
|
switch (wParam)
|
|
{
|
|
case SIZE_MINIMIZED :
|
|
SetCaption (rendersleep ? "POV-Ray for Windows (paused)" : "POV-Ray for Windows") ;
|
|
if (GetRenderWindow() != NULL)
|
|
if (RenderwinIsChild == false && HideRenderWithMain == true)
|
|
GetRenderWindow()->Hide();
|
|
ExternalEvent (EventSize, wParam) ;
|
|
return (0) ;
|
|
|
|
case SIZE_RESTORED :
|
|
SendMessage (StatusWindow, WM_SIZE, wParam, lParam) ;
|
|
s = EditGetFilename(true) ;
|
|
if (s != NULL && *s != '\0')
|
|
{
|
|
sprintf (str, rendersleep ? "POV-Ray (paused) - %s" : "POV-Ray - %s", s) ;
|
|
SetCaption (str) ;
|
|
}
|
|
else
|
|
SetCaption (rendersleep ? "POV-Ray for Windows (paused)" : "POV-Ray for Windows") ;
|
|
// ***** fall through *****
|
|
|
|
case SIZE_MAXIMIZED :
|
|
if (GetRenderwinHandle() != NULL)
|
|
if (RenderwinIsChild == false && HideRenderWithMain == true)
|
|
ShowWindow (GetRenderwinHandle(), MakeRenderwinActive ? SW_SHOW : SW_SHOWNA) ;
|
|
SendMessage (toolbar_window, TB_AUTOSIZE, 0, 0) ;
|
|
if (use_toolbar && rebar_window != NULL)
|
|
{
|
|
GetClientRect (rebar_window, &rect) ;
|
|
toolheight = rect.bottom ;
|
|
}
|
|
CalculateClientWindows (true) ;
|
|
|
|
// need this due to an issue with Windows 95
|
|
if (top_message_row)
|
|
{
|
|
ShowScrollBar (message_window, SB_VERT, false) ;
|
|
ShowScrollBar (message_window, SB_VERT, true) ;
|
|
}
|
|
if (need_hscroll ())
|
|
{
|
|
ShowScrollBar (message_window, SB_HORZ, false) ;
|
|
ShowScrollBar (message_window, SB_HORZ, true) ;
|
|
}
|
|
ExternalEvent (EventSize, wParam) ;
|
|
break ;
|
|
|
|
case SIZE_MAXHIDE :
|
|
case SIZE_MAXSHOW :
|
|
default :
|
|
ExternalEvent (EventSize, wParam) ;
|
|
return (0) ;
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_MOVE :
|
|
mainwin_placement.length = sizeof (WINDOWPLACEMENT) ;
|
|
GetWindowPlacement (main_window, &mainwin_placement) ;
|
|
ExternalEvent (EventMove, lParam) ;
|
|
return (0) ;
|
|
|
|
case WM_ERASEBKGND :
|
|
if (IsIconic (main_window))
|
|
{
|
|
BitBlt ((HDC) wParam, 0, 0, 36, 36, NULL, 0, 0, BLACKNESS) ;
|
|
return (1) ;
|
|
}
|
|
break ;
|
|
|
|
case WM_DROPFILES :
|
|
DragFunction ((HDROP) wParam) ;
|
|
return (0) ;
|
|
|
|
case WM_CHAR :
|
|
switch ((char) wParam)
|
|
{
|
|
case 0x0f : // ctrl-o
|
|
EditBrowseFile (true) ;
|
|
return (0) ;
|
|
|
|
case 0x0e : // ctrl-n (close enough to shift-ctrl-n ;)
|
|
EditOpenFile (NULL) ;
|
|
return (0) ;
|
|
}
|
|
if (EditPassOnMessage (hwnd, message, wParam, lParam, &result))
|
|
return (0) ;
|
|
break ;
|
|
|
|
case WM_KEYDOWN :
|
|
for (i = 0 ; key2scroll [i].wVirtkey != 0xffff ; i++)
|
|
{
|
|
if (wParam == key2scroll [i].wVirtkey)
|
|
{
|
|
SendMessage (message_window, key2scroll [i].iMessage, key2scroll [i].wRequest, 0L) ;
|
|
return (0) ;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
case WM_MENUSELECT :
|
|
if (EditPassOnMessage (hwnd, message, wParam, lParam, &result))
|
|
return (result) ;
|
|
handle_menu_select (wParam, lParam) ;
|
|
return (0) ;
|
|
|
|
case WM_SHOWWINDOW :
|
|
break ;
|
|
|
|
case WM_CLOSE :
|
|
if (debugging)
|
|
message_printf ("Close requested, rendering is %d, quit is %u\n", rendering, quit) ;
|
|
if (rendering && !quit)
|
|
{
|
|
if (MessageBox (main_window,
|
|
"POV-Ray is currently rendering - do you want to stop ?",
|
|
"Stop rendering",
|
|
MB_ICONQUESTION | MB_YESNO) == IDNO)
|
|
{
|
|
if (debugging)
|
|
message_printf ("User tells us we can't close\n") ;
|
|
return (0) ;
|
|
}
|
|
}
|
|
if (!EditCanClose (true))
|
|
{
|
|
if (debugging)
|
|
message_printf ("Editor tells us we can't close\n") ;
|
|
return (0) ;
|
|
}
|
|
ExternalEvent (EventClose, 0) ;
|
|
if (timer_id != 0)
|
|
KillTimer (main_window, timer_id) ;
|
|
DragAcceptFiles (main_window, false) ;
|
|
if (!rendering || quit)
|
|
{
|
|
DestroyWindow (main_window) ;
|
|
}
|
|
else
|
|
{
|
|
if (!quit)
|
|
quit = time (NULL) ;
|
|
cancel_render () ;
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_DESTROY :
|
|
if (debugging)
|
|
message_printf ("Destroy requested, rendering is %d, quit is %u\n", rendering, quit) ;
|
|
if (!quit)
|
|
{
|
|
quit = time (NULL) ;
|
|
if (rendering)
|
|
cancel_render () ;
|
|
}
|
|
ExternalEvent (EventDestroy, 0) ;
|
|
if (save_settings)
|
|
{
|
|
SendMessage (toolbar_combobox, CB_GETLBTEXT, SendMessage (toolbar_combobox, CB_GETCURSEL, 0, 0), (LPARAM) SecondaryRenderIniFileSection) ;
|
|
if (restore_command_line)
|
|
{
|
|
strcpy (command_line, old_command_line) ;
|
|
SendMessage (toolbar_cmdline, WM_SETTEXT, 0, (LPARAM) command_line) ;
|
|
restore_command_line = false ;
|
|
}
|
|
write_INI_settings () ;
|
|
EditSaveState () ;
|
|
}
|
|
PostQuitMessage (0) ;
|
|
return (0) ;
|
|
}
|
|
|
|
return (DefWindowProc (hwnd, message, wParam, lParam)) ;
|
|
}
|
|
|
|
LRESULT CALLBACK PovMessageWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int nhs ;
|
|
int msg ;
|
|
int mousewheel ;
|
|
HDC hdc ;
|
|
RECT rect ;
|
|
POINT pt ;
|
|
PAINTSTRUCT ps ;
|
|
static bool captured = false ;
|
|
static POINT mbdownPoint ;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_MOUSEWHEEL :
|
|
mousewheel = (short) (wParam >> 16) / WHEEL_DELTA ;
|
|
if ((LOWORD (wParam) & (MK_MBUTTON | MK_CONTROL)) == 0)
|
|
{
|
|
msg = mousewheel < 0 ? SB_LINEDOWN : SB_LINEUP ;
|
|
mousewheel *= 3 ;
|
|
}
|
|
else
|
|
msg = mousewheel < 0 ? SB_PAGEDOWN : SB_PAGEUP ;
|
|
mousewheel = abs (mousewheel) ;
|
|
while (mousewheel--)
|
|
PovMessageWndProc (hwnd, WM_VSCROLL, msg, 0) ;
|
|
return (0) ;
|
|
|
|
case WM_KEYDOWN :
|
|
PostMessage (main_window, message, wParam, lParam) ;
|
|
return (0) ;
|
|
|
|
case WM_LBUTTONDOWN :
|
|
SetCapture (hwnd) ;
|
|
captured = true ;
|
|
GetCursorPos (&mbdownPoint) ;
|
|
return (0) ;
|
|
|
|
case WM_LBUTTONUP :
|
|
if (!captured)
|
|
return (0) ;
|
|
ReleaseCapture () ;
|
|
captured = false ;
|
|
GetCursorPos (&pt) ;
|
|
GetWindowRect (hwnd, &rect) ;
|
|
if (pt.x < rect.left || pt.y < rect.top || pt.x > rect.right || pt.y > rect.bottom)
|
|
return (0) ;
|
|
if (abs (mbdownPoint.x - pt.x) > 3 || abs (mbdownPoint.y - pt.y) > 3)
|
|
{
|
|
hh_aklink.pszKeywords = "text streams" ;
|
|
MessageBox (hwnd,
|
|
"You may use the Edit menu to copy the contents of this message pane to the clipboard\n\n"
|
|
"Press Help to learn how to direct the POV-Ray text output streams to a file",
|
|
"Text Selection Not Supported In This Window",
|
|
MB_OK | MB_ICONINFORMATION | MB_HELP) ;
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_RBUTTONDOWN :
|
|
if (hPopupMenus != NULL)
|
|
{
|
|
pt.x = LOWORD (lParam) ;
|
|
pt.y = HIWORD (lParam) ;
|
|
ClientToScreen (hwnd, &pt) ;
|
|
TrackPopupMenu (GetSubMenu (hPopupMenus, 0),
|
|
TPM_LEFTALIGN | TPM_RIGHTBUTTON,
|
|
pt.x,
|
|
pt.y,
|
|
0,
|
|
main_window,
|
|
NULL) ;
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_ERASEBKGND :
|
|
return (1) ;
|
|
|
|
case WM_PAINT :
|
|
hdc = BeginPaint (hwnd, &ps) ;
|
|
if (hPalApp)
|
|
{
|
|
SelectPalette (hdc, hPalApp, false) ;
|
|
RealizePalette (hdc) ;
|
|
}
|
|
paint_display_window (hdc) ;
|
|
EndPaint (hwnd, &ps) ;
|
|
return (0) ;
|
|
|
|
case WM_SIZE :
|
|
if (message_count)
|
|
{
|
|
GetClientRect (hwnd, &rect) ;
|
|
message_scroll_pos_x = 0 ;
|
|
message_scroll_pos_y = message_count - rect.bottom / message_ychar ;
|
|
if (message_scroll_pos_y < 0)
|
|
message_scroll_pos_y = 0 ;
|
|
}
|
|
update_message_display (None) ;
|
|
PovInvalidateRect (hwnd, NULL, true) ;
|
|
return (0) ;
|
|
|
|
case WM_VSCROLL :
|
|
switch (LOWORD (wParam))
|
|
{
|
|
case SB_LINEDOWN :
|
|
if (message_scroll_pos_y < message_count - message_rows)
|
|
{
|
|
message_scroll_pos_y++ ;
|
|
ScrollWindow (hwnd, 0, -message_ychar, NULL, NULL) ;
|
|
update_message_display (None) ;
|
|
UpdateWindow (hwnd) ;
|
|
}
|
|
break ;
|
|
|
|
case SB_LINEUP :
|
|
if (message_scroll_pos_y > 0)
|
|
{
|
|
message_scroll_pos_y-- ;
|
|
ScrollWindow (hwnd, 0, message_ychar, NULL, NULL) ;
|
|
update_message_display (None) ;
|
|
UpdateWindow (hwnd) ;
|
|
}
|
|
break ;
|
|
|
|
case SB_PAGEDOWN :
|
|
if (message_scroll_pos_y < message_count - message_rows)
|
|
{
|
|
message_scroll_pos_y += message_rows ;
|
|
if (message_scroll_pos_y > message_count - message_rows)
|
|
message_scroll_pos_y = message_count - message_rows ;
|
|
PovInvalidateRect (hwnd, NULL, true) ;
|
|
update_message_display (None) ;
|
|
}
|
|
break ;
|
|
|
|
case SB_PAGEUP :
|
|
if (message_scroll_pos_y > 0)
|
|
{
|
|
message_scroll_pos_y -= message_rows ;
|
|
if (message_scroll_pos_y < 0)
|
|
message_scroll_pos_y = 0 ;
|
|
PovInvalidateRect (hwnd, NULL, true) ;
|
|
update_message_display (None) ;
|
|
}
|
|
break ;
|
|
|
|
case SB_THUMBPOSITION :
|
|
case SB_THUMBTRACK :
|
|
message_scroll_pos_y = HIWORD (wParam) ;
|
|
PovInvalidateRect (hwnd, NULL, true) ;
|
|
update_message_display (None) ;
|
|
break ;
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_HSCROLL :
|
|
nhs = need_hscroll () ;
|
|
switch (LOWORD (wParam))
|
|
{
|
|
case SB_LINERIGHT :
|
|
if (message_scroll_pos_x < nhs)
|
|
{
|
|
message_scroll_pos_x++ ;
|
|
ScrollWindow (hwnd, -message_xchar, 0, NULL, NULL) ;
|
|
update_message_display (None) ;
|
|
UpdateWindow (hwnd) ;
|
|
}
|
|
break ;
|
|
|
|
case SB_LINELEFT :
|
|
if (message_scroll_pos_x > 0)
|
|
{
|
|
message_scroll_pos_x-- ;
|
|
ScrollWindow (hwnd, message_xchar, 0, NULL, NULL) ;
|
|
update_message_display (None) ;
|
|
UpdateWindow (hwnd) ;
|
|
}
|
|
break ;
|
|
|
|
case SB_PAGERIGHT :
|
|
if (message_scroll_pos_x < nhs)
|
|
{
|
|
message_scroll_pos_x += message_cols ;
|
|
if (message_scroll_pos_x > nhs)
|
|
message_scroll_pos_x = nhs ;
|
|
PovInvalidateRect (hwnd, NULL, true) ;
|
|
update_message_display (None) ;
|
|
}
|
|
break ;
|
|
|
|
case SB_PAGELEFT :
|
|
if (message_scroll_pos_x > 0)
|
|
{
|
|
message_scroll_pos_x -= message_cols ;
|
|
if (message_scroll_pos_x < 0)
|
|
message_scroll_pos_x = 0 ;
|
|
PovInvalidateRect (hwnd, NULL, true) ;
|
|
update_message_display (None) ;
|
|
}
|
|
break ;
|
|
|
|
case SB_THUMBPOSITION :
|
|
case SB_THUMBTRACK :
|
|
message_scroll_pos_x = HIWORD (wParam) ;
|
|
PovInvalidateRect (hwnd, NULL, true) ;
|
|
update_message_display (None) ;
|
|
break ;
|
|
}
|
|
return (0) ;
|
|
}
|
|
return (DefWindowProc (hwnd, message, wParam, lParam)) ;
|
|
}
|
|
|
|
INT_PTR CALLBACK PovStatusPanelDialogProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG :
|
|
MoveWindow (hDlg, 0, 0, 204, 41, false) ;
|
|
SetupStatusPanel (hDlg) ;
|
|
SetStatusPanelItemText (IDC_STATUS_DATA_FRAME, "N/A") ;
|
|
return (false) ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
LRESULT CALLBACK PovAboutWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int button;
|
|
int offset = 0;
|
|
int i;
|
|
HDC hdc ;
|
|
HDC hdcMemory ;
|
|
bool f ;
|
|
DWORD threadId = 0 ;
|
|
DWORD threadParam = 0 ;
|
|
POINT pt;
|
|
HBITMAP oldBmp ;
|
|
HPALETTE oldPalette ;
|
|
PAINTSTRUCT ps ;
|
|
struct stat st ;
|
|
LPDRAWITEMSTRUCT lpdis ;
|
|
static char *url = NULL;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_CREATE :
|
|
about_showing = true ;
|
|
url = NULL;
|
|
break ;
|
|
|
|
case WM_DESTROY :
|
|
about_showing = false ;
|
|
EnableWindow (main_window, TRUE) ;
|
|
DeleteObject (hBmpAbout) ;
|
|
if (about_palette)
|
|
{
|
|
DeleteObject (about_palette) ;
|
|
about_palette = NULL ;
|
|
}
|
|
hBmpAbout = NULL ;
|
|
break ;
|
|
|
|
case WM_MOUSEMOVE:
|
|
pt.x = LOWORD (lParam);
|
|
pt.y = HIWORD (lParam);
|
|
for (i = 0; i < NUM_ABOUT_LINKS; i++)
|
|
{
|
|
if (PtInRect(AboutLinks + i, pt))
|
|
{
|
|
SetCursor(LoadCursor(NULL, IDC_HAND));
|
|
url = AboutURLs[i];
|
|
return 0;
|
|
}
|
|
}
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
url = NULL;
|
|
return 0;
|
|
|
|
case WM_SETCURSOR:
|
|
return 1;
|
|
|
|
case WM_LBUTTONUP:
|
|
if (url != NULL)
|
|
{
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT)); // will get changed on next mouse move
|
|
ShellExecute (NULL, NULL, url, NULL, NULL, SW_SHOWNORMAL) ;
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_COMMAND :
|
|
if (HIWORD (wParam) != BN_CLICKED)
|
|
return (false) ;
|
|
for (button = 0 ; button < 3 ; button++)
|
|
if (about_buttons [button] == (HWND) lParam)
|
|
break ;
|
|
if (button == 3)
|
|
break ;
|
|
switch (button)
|
|
{
|
|
case 0 :
|
|
// if help file is missing or something, default to internal viewer
|
|
if (stat (engineHelpPath, &st) == 0)
|
|
{
|
|
hh_aklink.pszKeywords = "POV-Ray License" ;
|
|
if (HtmlHelp (main_window, engineHelpPath, HH_KEYWORD_LOOKUP, (DWORD_PTR) &hh_aklink))
|
|
return (0) ;
|
|
}
|
|
DialogBoxParam (hInstance, MAKEINTRESOURCE (IDD_VIEW), main_window, (DLGPROC) PovLegalDialogProc, (LPARAM) main_window) ;
|
|
break ;
|
|
|
|
case 1 :
|
|
save_povlegal () ;
|
|
break ;
|
|
|
|
case 2 :
|
|
about_showing = false ;
|
|
EnableWindow (main_window, TRUE) ;
|
|
SetFocus (main_window) ;
|
|
DestroyWindow (hwnd) ;
|
|
break ;
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_DRAWITEM :
|
|
lpdis = (LPDRAWITEMSTRUCT) lParam ;
|
|
for (button = 0 ; button < 3 ; button++)
|
|
if (about_buttons [button] == lpdis->hwndItem)
|
|
break ;
|
|
if (button == 3)
|
|
return (0) ;
|
|
if ((lpdis->itemState & ODS_SELECTED) != 0)
|
|
offset = 400;
|
|
else if (GetWindowLongPtr(lpdis->hwndItem, GWLP_USERDATA) != 0)
|
|
offset = 200;
|
|
hdc = lpdis->hDC ;
|
|
if (about_palette)
|
|
SelectPalette (hdc, about_palette, true) ;
|
|
hdcMemory = CreateCompatibleDC (hdc) ;
|
|
oldBmp = (HBITMAP) SelectObject (hdcMemory, hBmpAbout) ;
|
|
BitBlt (hdc, 0, 0, 165, 30, hdcMemory, offset, button * 30 + about_height, SRCCOPY) ;
|
|
SelectObject (hdcMemory, oldBmp) ;
|
|
DeleteDC (hdcMemory) ;
|
|
return (1) ;
|
|
|
|
case WM_KEYDOWN :
|
|
if (wParam == VK_RETURN || wParam == VK_ESCAPE || wParam == VK_SPACE)
|
|
{
|
|
EnableWindow (main_window, TRUE) ;
|
|
SetFocus (main_window) ;
|
|
DestroyWindow (hwnd) ;
|
|
return (0) ;
|
|
}
|
|
return (0) ;
|
|
|
|
case WM_PAINT :
|
|
hdc = BeginPaint (hwnd, &ps) ;
|
|
if (about_palette)
|
|
{
|
|
SelectPalette (hdc, about_palette, false) ;
|
|
RealizePalette (hdc) ;
|
|
}
|
|
hdcMemory = CreateCompatibleDC (hdc) ;
|
|
oldBmp = (HBITMAP) SelectObject (hdcMemory, hBmpAbout) ;
|
|
BitBlt (hdc, 0, 0, about_width, about_height, hdcMemory, 0, 0, SRCCOPY) ;
|
|
SelectObject (hdcMemory, oldBmp) ;
|
|
DeleteDC (hdcMemory) ;
|
|
EndPaint (hwnd, &ps) ;
|
|
return (0) ;
|
|
|
|
case WM_PALETTECHANGED :
|
|
// make sure it wasn't us who changed the palette, otherwise we can get into an infinite loop.
|
|
if ((HWND) wParam == hwnd)
|
|
return (0) ;
|
|
// FALL THROUGH to WM_QUERYNEWPALETTE
|
|
|
|
case WM_QUERYNEWPALETTE :
|
|
if (about_palette)
|
|
{
|
|
hdc = GetDC (hwnd) ;
|
|
oldPalette = SelectPalette (hdc, about_palette, false) ;
|
|
f = (RealizePalette (hdc) != 0);
|
|
SelectPalette (hdc, oldPalette, false) ;
|
|
ReleaseDC (hwnd, hdc) ;
|
|
if (f)
|
|
PovInvalidateRect (hwnd, NULL, true) ;
|
|
}
|
|
return (0) ;
|
|
}
|
|
return (DefWindowProc (hwnd, message, wParam, lParam)) ;
|
|
}
|
|
|
|
LRESULT CALLBACK PovAboutButtonWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
TRACKMOUSEEVENT tme;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_MOUSEMOVE:
|
|
if (GetWindowLongPtr(hwnd, GWLP_USERDATA) != 0)
|
|
break;
|
|
tme.cbSize = sizeof(tme);
|
|
tme.dwFlags = TME_LEAVE;
|
|
tme.dwHoverTime = 0;
|
|
tme.hwndTrack = hwnd;
|
|
TrackMouseEvent(&tme);
|
|
InvalidateRect (hwnd, NULL, false);
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, 1);
|
|
break;
|
|
|
|
case WM_MOUSELEAVE:
|
|
InvalidateRect (hwnd, NULL, false);
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
if (wParam != VK_ESCAPE)
|
|
break;
|
|
EnableWindow (main_window, TRUE) ;
|
|
SetFocus (main_window) ;
|
|
DestroyWindow (about_window) ;
|
|
return (0) ;
|
|
}
|
|
return (CallWindowProc (about_button_wndproc, hwnd, message, wParam, lParam)) ;
|
|
}
|
|
|
|
void ShowAboutBox (void)
|
|
{
|
|
int oldMode ;
|
|
MSG msg ;
|
|
HDC hdcMemory ;
|
|
char *s = POV_RAY_VERSION COMPILER_VER SSE2_INCLUDED "." PVENGINE_VER ;
|
|
SIZE size ;
|
|
HFONT oldFont ;
|
|
BITMAP bm ;
|
|
HBITMAP oldBmp ;
|
|
COLORREF oldColour ;
|
|
|
|
if ((hBmpAbout = NonBogusLoadBitmapAndPalette (hInstance, MAKEINTRESOURCE (BMP_ABOUT))) != NULL)
|
|
{
|
|
GetObject (hBmpAbout, sizeof (BITMAP), (LPSTR) &bm) ;
|
|
about_width = bm.bmWidth ;
|
|
about_height = bm.bmHeight - 180 ;
|
|
about_palette = hPalBitmap ;
|
|
|
|
if (about_font == NULL)
|
|
create_about_font () ;
|
|
|
|
hdcMemory = CreateCompatibleDC (NULL) ;
|
|
oldFont = (HFONT) SelectObject (hdcMemory, about_font) ;
|
|
oldMode = SetBkMode (hdcMemory, TRANSPARENT) ;
|
|
oldColour = SetTextColor (hdcMemory, RGB (0x96, 0xD3, 0xFF)) ;
|
|
oldBmp = (HBITMAP) SelectObject (hdcMemory, hBmpAbout) ;
|
|
GetTextExtentPoint (hdcMemory, s, (int) strlen (s), &size) ;
|
|
ExtTextOut (hdcMemory, 387, 14, 0, NULL, s, (int) strlen (s), NULL) ;
|
|
SetTextColor (hdcMemory, oldColour) ;
|
|
SetBkMode (hdcMemory, oldMode) ;
|
|
SelectObject (hdcMemory, oldFont) ;
|
|
SelectObject (hdcMemory, oldBmp) ;
|
|
DeleteDC (hdcMemory) ;
|
|
|
|
about_window = CreateWindowEx (0,//WS_EX_TOOLWINDOW,
|
|
PovAboutWinClass,
|
|
"POV-Ray",
|
|
WS_POPUP,
|
|
(screen_width - about_width) / 2,
|
|
(screen_height - about_height) / 2,
|
|
about_width,
|
|
about_height,
|
|
main_window,
|
|
NULL,
|
|
hInstance,
|
|
NULL) ;
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
about_buttons[i] = CreateWindow ("BUTTON", "", WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, i * 184 + 27, 451, 165, 30, about_window, NULL, hInstance, NULL) ;
|
|
about_button_wndproc = (WNDPROC) (ULONG_PTR) SetWindowLongPtr (about_buttons[i], GWLP_WNDPROC, (ULONG_PTR) PovAboutButtonWndProc) ;
|
|
}
|
|
CenterWindowRelative (main_window, about_window, false, true) ;
|
|
ShowWindow (about_window, SW_SHOWNORMAL) ;
|
|
SetFocus (about_window) ;
|
|
EnableWindow (main_window, FALSE) ;
|
|
while (about_showing && GetMessage (&msg, NULL, 0, 0) != 0 && quit == 0)
|
|
{
|
|
if (!TranslateAccelerator (main_window, hAccelerators, &msg))
|
|
{
|
|
TranslateMessage (&msg) ;
|
|
DispatchMessage (&msg) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************************************************************/
|
|
/* END OF WINDOW PROCEDURES */
|
|
/**************************************************************************************/
|
|
|
|
int register_classes (void)
|
|
{
|
|
WNDCLASSEX wc ;
|
|
|
|
// the parameter to RegisterClass is considered CONST, so we
|
|
// can assume that the structure is not changed by the calls.
|
|
wc.cbSize = sizeof (wc) ;
|
|
wc.hIconSm = NULL ;
|
|
wc.cbClsExtra = 0 ;
|
|
wc.cbWndExtra = 0 ;
|
|
wc.hInstance = hInstance ;
|
|
wc.lpszMenuName = NULL ;
|
|
wc.hbrBackground = NULL ;
|
|
|
|
// Register the main window class.
|
|
wc.style = CS_BYTEALIGNCLIENT ;
|
|
wc.lpfnWndProc = PovMainWndProc ;
|
|
wc.hIcon = ourIcon ;
|
|
wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
|
|
wc.lpszClassName = PovMainWinClass ;
|
|
if (RegisterClassEx (&wc) == false)
|
|
return (false) ;
|
|
|
|
// Register the message window class.
|
|
wc.style = CS_BYTEALIGNCLIENT ;
|
|
wc.lpfnWndProc = PovMessageWndProc ;
|
|
wc.hIcon = NULL ;
|
|
wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
|
|
wc.lpszClassName = PovMessageWinClass ;
|
|
if (RegisterClassEx (&wc) == false)
|
|
return (false) ;
|
|
|
|
// Register the about window class.
|
|
wc.style = CS_BYTEALIGNCLIENT ;
|
|
wc.lpfnWndProc = PovAboutWndProc ;
|
|
wc.hIcon = ourIcon ;
|
|
wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
|
|
wc.lpszClassName = PovAboutWinClass ;
|
|
if (RegisterClassEx (&wc) == false)
|
|
return (false) ;
|
|
|
|
// Register the render window classes
|
|
wc.style = CS_BYTEALIGNCLIENT ;
|
|
wc.lpfnWndProc = WinLegacyDisplay::StaticWindowProc ;
|
|
wc.hIcon = renderIcon ;
|
|
wc.hCursor = LoadCursor (NULL, IDC_CROSS) ;
|
|
wc.hbrBackground = NULL ;
|
|
wc.lpszClassName = PovLegacyRenderWinClass ;
|
|
wc.cbWndExtra = 8 ;
|
|
if (RegisterClassEx (&wc) == false)
|
|
return (false) ;
|
|
|
|
return (true) ;
|
|
}
|
|
|
|
void cleanup_all (void)
|
|
{
|
|
// TODO: nuke any render threads still running
|
|
ExternalCleanupAll () ;
|
|
EditUnload () ;
|
|
if (use_taskbar)
|
|
TaskBarDeleteIcon (main_window, 0) ;
|
|
clear_messages (false) ;
|
|
clear_dir_restrictions () ;
|
|
DeleteCriticalSection (&critical_section) ;
|
|
display_cleanup (true) ;
|
|
if (hBmpBackground != NULL)
|
|
DeleteObject (hBmpBackground) ;
|
|
if (hBmpRendering != NULL)
|
|
DeleteObject (hBmpRendering) ;
|
|
if (hBmpIcon != NULL)
|
|
DeleteObject (hBmpIcon) ;
|
|
if (hMenuBar)
|
|
DestroyMenu (hMenuBar) ;
|
|
if (hMainMenu)
|
|
DestroyMenu (hMainMenu) ;
|
|
if (hPopupMenus)
|
|
DestroyMenu (hPopupMenus) ;
|
|
if (hPalApp)
|
|
DeleteObject (hPalApp) ;
|
|
if (message_font)
|
|
DeleteObject (message_font) ;
|
|
if (about_font)
|
|
DeleteObject (about_font) ;
|
|
if (tab_font)
|
|
DeleteObject (tab_font) ;
|
|
if (ourIcon)
|
|
DestroyIcon (ourIcon) ;
|
|
if (renderIcon)
|
|
DestroyIcon (renderIcon) ;
|
|
|
|
UnregisterClass (PovLegacyRenderWinClass, hInstance) ;
|
|
UnregisterClass (PovMessageWinClass, hInstance) ;
|
|
UnregisterClass (PovMainWinClass, hInstance) ;
|
|
}
|
|
|
|
#ifdef _MSC_VER
|
|
void LZTimerOn (void)
|
|
{
|
|
if (!QueryPerformanceCounter ((LARGE_INTEGER *) &PerformanceCounter1))
|
|
PerformanceCounter1 = 0 ;
|
|
}
|
|
|
|
void LZTimerOff (void)
|
|
{
|
|
if (!QueryPerformanceCounter ((LARGE_INTEGER *) &PerformanceCounter2))
|
|
PerformanceCounter2 = 0 ;
|
|
}
|
|
|
|
ulong LZTimerCount (void)
|
|
{
|
|
if (PerformanceCounter1 == 0 || PerformanceCounter2 < PerformanceCounter1)
|
|
return (0) ;
|
|
return ((ulong) ((PerformanceCounter2 - PerformanceCounter1) / PerformanceScale)) ;
|
|
}
|
|
|
|
__int64 LZTimerRawCount (void)
|
|
{
|
|
if (PerformanceCounter1 == 0 || PerformanceCounter2 < PerformanceCounter1)
|
|
return (0) ;
|
|
return (PerformanceCounter2 - PerformanceCounter1) ;
|
|
}
|
|
#endif // #ifdef _MSC_VER
|
|
|
|
}
|
|
|
|
static void __cdecl newhandler (void)
|
|
{
|
|
throw std::bad_alloc () ;
|
|
}
|
|
|
|
using namespace povwin ;
|
|
|
|
void GenerateDumpMeta(bool brief)
|
|
{
|
|
char str[128];
|
|
char *s = DumpMeta;
|
|
char *InstalledOn ;
|
|
HDC hdc ;
|
|
HKEY key ;
|
|
DWORD len;
|
|
DWORD header = 0 ;
|
|
DWORD n ;
|
|
FILETIME file_time ;
|
|
SYSTEMTIME system_time ;
|
|
SYSTEM_INFO sysinfo ;
|
|
OSVERSIONINFO version_info ;
|
|
MEMORYSTATUSEX mem_status ;
|
|
|
|
GetNativeSystemInfo(&sysinfo) ;
|
|
if (!brief)
|
|
{
|
|
if ((InstalledOn = GetInstallTime()) == NULL)
|
|
{
|
|
GetSystemTime (&system_time) ;
|
|
if (SystemTimeToFileTime (&system_time, &file_time))
|
|
reg_printf (true, "Software\\POV-Ray", INSTALLTIMEKEY, "%I64u", ((__int64) file_time.dwHighDateTime << 32) | file_time.dwLowDateTime) ;
|
|
if ((InstalledOn = GetInstallTime ()) == NULL)
|
|
InstalledOn = "Unknown" ;
|
|
}
|
|
s += sprintf(s, "installdate=%s\n", InstalledOn) ;
|
|
}
|
|
s += sprintf(s, "cpuarchitecture=%u\n", (DWORD) sysinfo.wProcessorArchitecture) ;
|
|
s += sprintf(s, "numberofcpus=%u\n", sysinfo.dwNumberOfProcessors) ;
|
|
s += sprintf(s, "processortype=%u\n", sysinfo.dwProcessorType) ;
|
|
s += sprintf(s, "processorlevel=%u\n", (DWORD) sysinfo.wProcessorLevel) ;
|
|
s += sprintf(s, "processorrevision=%u\n", (DWORD) sysinfo.wProcessorRevision) ;
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\Description\\System\\CentralProcessor\\0", 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
len = sizeof (n) ;
|
|
if (RegQueryValueEx (key, "~MHZ", 0, NULL, (BYTE *) &n, &len) == ERROR_SUCCESS)
|
|
s += sprintf(s, "cpufrequency=%u\n", n) ;
|
|
|
|
len = sizeof (n) ;
|
|
if (RegQueryValueEx (key, "FeatureSet", 0, NULL, (BYTE *) &n, &len) == ERROR_SUCCESS)
|
|
s += sprintf(s, "cpufeatureset=%u\n", n) ;
|
|
|
|
len = sizeof (str) ;
|
|
if (RegQueryValueEx (key, "ProcessorNameString", 0, NULL, (BYTE *) str, &len) == ERROR_SUCCESS)
|
|
s += sprintf(s, "cpuname=%s\n", str) ;
|
|
|
|
len = sizeof (str) ;
|
|
if (RegQueryValueEx (key, "Identifier", 0, NULL, (BYTE *) str, &len) == ERROR_SUCCESS)
|
|
s += sprintf(s, "cpuidentifier=%s\n", str) ;
|
|
|
|
len = sizeof (str) ;
|
|
if (RegQueryValueEx (key, "VendorIdentifier", 0, NULL, (BYTE *) str, &len) == ERROR_SUCCESS)
|
|
s += sprintf(s, "cpuvendoridentifier=%s\n", str) ;
|
|
|
|
RegCloseKey (key) ;
|
|
}
|
|
|
|
version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO) ;
|
|
GetVersionEx (&version_info) ;
|
|
s += sprintf(s, "osversion=%u.%u\n", version_info.dwMajorVersion, version_info.dwMinorVersion) ;
|
|
s += sprintf(s, "osbuild=%u\n", version_info.dwBuildNumber) ;
|
|
s += sprintf(s, "csdversion=%s\n", version_info.szCSDVersion) ;
|
|
|
|
if (!brief)
|
|
{
|
|
hdc = GetDC (NULL) ;
|
|
s += sprintf(s, "bitsperpixel=%u\n", GetDeviceCaps (hdc, BITSPIXEL)) ;
|
|
s += sprintf(s, "horzres=%u\n", GetDeviceCaps (hdc, HORZRES)) ;
|
|
s += sprintf(s, "vertres=%u\n", GetDeviceCaps (hdc, VERTRES)) ;
|
|
ReleaseDC (NULL, hdc) ;
|
|
}
|
|
|
|
mem_status.dwLength = sizeof (MEMORYSTATUSEX) ;
|
|
GlobalMemoryStatusEx(&mem_status) ;
|
|
s += sprintf(s, "physicalmemory=%I64u\n", mem_status.ullTotalPhys) ;
|
|
}
|
|
|
|
bool WriteDumpMeta(struct _EXCEPTION_POINTERS *ExceptionInfo, const char *filename)
|
|
{
|
|
FILE *f;
|
|
PCONTEXT c = ExceptionInfo->ContextRecord ;
|
|
static char fn[_MAX_PATH];
|
|
|
|
strcpy(fn, filename);
|
|
strcat(fn, ".metadata");
|
|
|
|
if ((f = fopen(fn, "wt")) == NULL)
|
|
return false;
|
|
fwrite(DumpMeta, strlen(DumpMeta), 1, f);
|
|
fprintf(f, "faulttype=%u\n", ExceptionInfo->ExceptionRecord->ExceptionCode);
|
|
#ifdef _WIN64
|
|
fprintf(f, "faultaddress=%I64u\n", ExceptionInfo->ContextRecord->Rip);
|
|
fprintf(f, "faultplatform=win64\n");
|
|
#else
|
|
fprintf(f, "faultaddress=%u\n", ExceptionInfo->ContextRecord->Eip);
|
|
fprintf(f, "faultplatform=win32\n");
|
|
#endif
|
|
fprintf(f, "povversion=%s\n", POV_RAY_VERSION) ;
|
|
fprintf(f, "compilerversion=%s\n", COMPILER_VER) ;
|
|
fprintf(f, "platformversion=%s\n", PVENGINE_VER) ;
|
|
fprintf(f, "remotesession=%u\n", GetSystemMetrics(SM_REMOTESESSION)) ;
|
|
fclose(f);
|
|
return true;
|
|
}
|
|
|
|
// TODO: re-write this!!!
|
|
char *WriteDump(struct _EXCEPTION_POINTERS *pExceptionInfo, bool full, long timestamp)
|
|
{
|
|
// firstly see if dbghelp.dll is around and has the function we need
|
|
// look next to the EXE first, as the one in System32 might be old
|
|
// (e.g. Windows 2000)
|
|
HMODULE hDll = NULL;
|
|
static char szDbgHelpPath[_MAX_PATH];
|
|
|
|
if (GetModuleFileName(NULL, szDbgHelpPath, _MAX_PATH ))
|
|
{
|
|
char *pSlash = findLastPathSeparator( szDbgHelpPath );
|
|
if (pSlash)
|
|
{
|
|
strcpy( pSlash+1, "DBGHELP.DLL" );
|
|
hDll = ::LoadLibrary( szDbgHelpPath );
|
|
}
|
|
}
|
|
|
|
if (hDll==NULL)
|
|
{
|
|
// load any version we can
|
|
hDll = ::LoadLibrary( "DBGHELP.DLL" );
|
|
}
|
|
|
|
LPCTSTR szResult = NULL;
|
|
|
|
if (hDll)
|
|
{
|
|
MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" );
|
|
if (pDump)
|
|
{
|
|
char szScratch [_MAX_PATH];
|
|
static char szDumpPath[_MAX_PATH];
|
|
|
|
if (full)
|
|
sprintf(szScratch, "POV-Ray-" POV_RAY_VERSION COMPILER_VER SSE2_INCLUDED "." PVENGINE_VER "-%08X.dmp", timestamp);
|
|
else
|
|
sprintf(szScratch, "POV-Ray-" POV_RAY_VERSION COMPILER_VER SSE2_INCLUDED "." PVENGINE_VER "-%08X.minidump", timestamp);
|
|
|
|
// work out a good place for the dump file
|
|
if (!GetTempPath( _MAX_PATH - 64, szDumpPath))
|
|
_tcscpy( szDumpPath, "c:\\" );
|
|
|
|
_tcscat( szDumpPath, szScratch );
|
|
|
|
// create the file
|
|
HANDLE hFile = ::CreateFile( szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
|
|
if (hFile!=INVALID_HANDLE_VALUE)
|
|
{
|
|
_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
|
|
|
|
ExInfo.ThreadId = ::GetCurrentThreadId();
|
|
ExInfo.ExceptionPointers = pExceptionInfo;
|
|
ExInfo.ClientPointers = NULL;
|
|
|
|
// write the dump
|
|
BOOL bOK = pDump(GetCurrentProcess(),
|
|
GetCurrentProcessId(),
|
|
hFile,
|
|
full ? MiniDumpWithFullMemory :
|
|
(MINIDUMP_TYPE)(MiniDumpWithDataSegs|MiniDumpWithHandleData|MiniDumpWithIndirectlyReferencedMemory), &ExInfo, NULL, NULL );
|
|
::CloseHandle(hFile);
|
|
if (bOK)
|
|
{
|
|
if (!WriteDumpMeta(pExceptionInfo, szDumpPath))
|
|
{
|
|
MessageBox (main_window, "Failed to save dump metadata file", "POV-Ray for Windows", MB_OK | MB_ICONEXCLAMATION);
|
|
return NULL;
|
|
}
|
|
return szDumpPath;
|
|
}
|
|
sprintf( szScratch, "Failed to save dump file to '%s' (error %d)", szDumpPath, GetLastError() );
|
|
MessageBox (main_window, szScratch, "POV-Ray for Windows", MB_OK | MB_ICONEXCLAMATION);
|
|
return NULL;
|
|
}
|
|
sprintf( szScratch, "Failed to create dump file '%s' (error %d)", szDumpPath, GetLastError() );
|
|
MessageBox (main_window, szScratch, "POV-Ray for Windows", MB_OK | MB_ICONEXCLAMATION);
|
|
return NULL;
|
|
}
|
|
MessageBox (main_window, "Sorry, DBGHELP.DLL is too old - cannot create dump.", "POV-Ray for Windows", MB_OK | MB_ICONEXCLAMATION);
|
|
return NULL;
|
|
}
|
|
MessageBox (main_window, "Sorry, we can't locate DBGHELP.DLL - cannot create dump.", "POV-Ray for Windows", MB_OK | MB_ICONEXCLAMATION);
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef BUILD_SSE2
|
|
void NoSSE2 (void)
|
|
{
|
|
MessageBox (NULL,
|
|
"This build of POV-Ray requires that your processor provides SSE2 support.\n"
|
|
"Please use the standard non-SSE2 version of POV-Ray on this computer.",
|
|
"POV-Ray for Windows",
|
|
MB_ICONSTOP | MB_OK) ;
|
|
exit (-1) ;
|
|
}
|
|
|
|
inline int TestSSE2 (void)
|
|
{
|
|
__try
|
|
{
|
|
__asm { movapd xmm0,xmm1 }
|
|
}
|
|
__except(NoSSE2(),1)
|
|
{
|
|
}
|
|
return (0) ;
|
|
}
|
|
#endif
|
|
|
|
void InvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
|
|
{
|
|
throw POV_EXCEPTION(kParamErr, "Run-Time Library Invalid Parameter Handler invoked");
|
|
}
|
|
|
|
int PASCAL WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
|
|
{
|
|
#ifdef BUILD_SSE2
|
|
TestSSE2 () ;
|
|
#endif
|
|
|
|
int show_state ;
|
|
int i ;
|
|
int id = 0 ;
|
|
int w, h ;
|
|
char str [_MAX_PATH * 2] ;
|
|
char *s = szCmdLine ;
|
|
bool exit_loop = false ;
|
|
bool have_cpu_info = false;
|
|
unsigned n ;
|
|
MSG msg ;
|
|
HDC hDC ;
|
|
HDIB hDIB ;
|
|
RECT rect ;
|
|
HWND hwnd ;
|
|
DWORD help_cookie ;
|
|
DWORD threadId = 0 ;
|
|
DWORD threadParam = 0 ;
|
|
BITMAP bm ;
|
|
HBITMAP hBMP ;
|
|
struct stat statbuf ;
|
|
SYSTEM_INFO sysinfo ;
|
|
WINDOWPLACEMENT placement ;
|
|
|
|
// REMINDER: don't try to write to the message pane until initialise_message_display() has been called.
|
|
|
|
_set_invalid_parameter_handler(InvalidParameterHandler);
|
|
|
|
#ifdef _DEBUG
|
|
_unlink ("c:\\temp\\povdebug.txt") ;
|
|
_unlink ("c:\\temp\\povmem.txt") ;
|
|
#endif
|
|
|
|
GenerateDumpMeta(false);
|
|
set_new_handler(newhandler) ;
|
|
SetUnhandledExceptionFilter(ExceptionHandler);
|
|
|
|
// need this now to set virtual_screen_width etc., in case we display a dialog
|
|
// before the main setup (we call it again once we've read the INI file).
|
|
detect_graphics_config () ;
|
|
|
|
try
|
|
{
|
|
CreateFrontend();
|
|
}
|
|
catch (pov_base::Exception& e)
|
|
{
|
|
sprintf (str, "Failed to initialize frontend: %s", e.what()) ;
|
|
MessageBox (NULL, str, "POV-Ray Critical Error", MB_ICONSTOP) ;
|
|
return (1) ;
|
|
}
|
|
|
|
hInstance = hInst ;
|
|
hMainThread = GetCurrentThread () ;
|
|
|
|
GetSystemInfo (&sysinfo) ;
|
|
ThreadCount = sysinfo.dwNumberOfProcessors ;
|
|
NumberOfCPUs = sysinfo.dwNumberOfProcessors ;
|
|
|
|
if (GetCPUCount(&NumLogicalCPUs, &NumCPUCores, &NumPhysicalCPUs) && NumLogicalCPUs > 1)
|
|
{
|
|
have_cpu_info = true;
|
|
ThreadCount = NumLogicalCPUs ;
|
|
NumberOfCPUs = NumCPUCores ;
|
|
}
|
|
|
|
while (*s == ' ' || *s == '\t')
|
|
s++ ;
|
|
if (_stricmp (s, "/install") == 0 || _strnicmp (s, "/install ", 9) == 0 || _stricmp (s, "/qinstall") == 0 || _strnicmp (s, "/qinstall ", 10) == 0)
|
|
{
|
|
bool quiet = s [1] == 'q' || s [1] == 'Q' ;
|
|
while (*s && *s != ' ')
|
|
s++ ;
|
|
argv[1] = argv[2] = NULL;
|
|
parse_commandline(s);
|
|
return (InstallSettings (argv[1], argv[2], quiet)) ;
|
|
}
|
|
|
|
getHome () ;
|
|
if (BinariesPath [0] == '\0')
|
|
{
|
|
inferHome () ;
|
|
if (BinariesPath [0] == '\0')
|
|
{
|
|
MessageBox (NULL,
|
|
"ERROR : Cannot find Home entry in registry (and cannot infer it).\n\n"
|
|
"This entry should have been set by the installation program.\n\n"
|
|
"POV-Ray can usually infer the installation path but that requires a\n"
|
|
"standard layout of directories, which also seems to be absent.\n\n"
|
|
"If you did not install using the correct installation procedure, please\n"
|
|
"do this before running POV-Ray for Windows. You can also try running\n"
|
|
"with the '/INSTALL' or '/INSTALL <bindir> [<docdir>]' option.",
|
|
"Critical Error",
|
|
MB_ICONSTOP) ;
|
|
return (1) ;
|
|
}
|
|
}
|
|
appendPathSeparator(BinariesPath) ;
|
|
if (DocumentsPath[0] == '\0')
|
|
{
|
|
if (SHGetFolderPath (NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, DocumentsPath) != S_OK)
|
|
{
|
|
MessageBox (NULL,
|
|
"ERROR : Cannot find DocPath entry in registry (and cannot infer it).\n\n"
|
|
"This entry should have been set by the installation program.\n\n"
|
|
"POV-Ray can usually infer the installation path but that requires a\n"
|
|
"standard layout of directories, which also seems to be absent.\n\n"
|
|
"If you did not install using the correct installation procedure, please\n"
|
|
"do this before running POV-Ray for Windows. You can also try running\n"
|
|
"with the '/INSTALL' or '/INSTALL <bindir> <docdir>' option.",
|
|
"Critical Error",
|
|
MB_ICONSTOP) ;
|
|
}
|
|
strcat(DocumentsPath, "\\" REGKEY);
|
|
if (!dirExists(DocumentsPath))
|
|
CreateDirectory(DocumentsPath, NULL);
|
|
strcat(DocumentsPath, "\\" REGVERKEY);
|
|
if (!dirExists(DocumentsPath))
|
|
CreateDirectory(DocumentsPath, NULL);
|
|
}
|
|
appendPathSeparator(DocumentsPath) ;
|
|
sprintf(str, "%sini", DocumentsPath);
|
|
if (!dirExists(str))
|
|
CreateDirectory(str, NULL);
|
|
sprintf(ToolIniFileName, "%sini\\pvtools.ini", DocumentsPath);
|
|
sprintf(EngineIniFileName, "%sini\\pvengine.ini", DocumentsPath);
|
|
|
|
if (checkEditKey37() == false && checkEditKey36() == true)
|
|
copy36EditSettings();
|
|
|
|
if (checkRegKey () == false || FreshInstall == true)
|
|
if (!CloneOptions())
|
|
MessageBox (NULL, "ERROR : Could not clone options - POV-Ray may not work correctly for this user.", "Critical Error", MB_ICONERROR) ;
|
|
|
|
#ifdef POVRAY_IS_BETA
|
|
if (FreshInstall)
|
|
{
|
|
// on installing a new beta, we always turn on check new version now that we no longer
|
|
// implement a short timeout. the user may switch it off if they like; we will not perform
|
|
// an automatic version check in this session since FreshInstall is set, in order to give
|
|
// them a chance to do it.
|
|
check_new_version = true;
|
|
PutHKCU("General", "CheckNewVersion", true);
|
|
}
|
|
#endif
|
|
|
|
#ifndef MAP_INI_TO_REGISTRY
|
|
if (!fileExists(EngineIniFileName))
|
|
{
|
|
// no INI file: see if we can copy the 3.6 INI options, should they exist
|
|
if (debugging)
|
|
debug_output("no pvengine.ini: seeing if there is a v3.6 ini\n") ;
|
|
|
|
string str(get36Home());
|
|
if (str.empty() == false)
|
|
{
|
|
string oldINIpath = str + "ini\\pvengine.ini";
|
|
if (fileExists(oldINIpath.c_str()))
|
|
{
|
|
if (debugging)
|
|
debug_output("cloning INI file %s to %s\n", oldINIpath.c_str(), EngineIniFileName) ;
|
|
cloneOldIni(str, DocumentsPath);
|
|
}
|
|
else
|
|
{
|
|
if (debugging)
|
|
debug_output("creating default INI file %s\n", EngineIniFileName) ;
|
|
cloneOldIni("", DocumentsPath);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (debugging)
|
|
debug_output("creating default INI file %s\n", EngineIniFileName) ;
|
|
cloneOldIni("", DocumentsPath);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (homeInferred)
|
|
{
|
|
if (_stricmp (LastInferredHome, BinariesPath) != 0)
|
|
{
|
|
sprintf (str, "POV-Ray for Windows did not find the expected registry entries present.\n"
|
|
"This typically means that it has not been installed via the installation program.\n"
|
|
"You can correct this by running with the '/INSTALL' or '/INSTALL <installdir>' option.\n\n"
|
|
"POV-Ray has inferred the installation path to be the following:\n\n"
|
|
"\t%s\n\n"
|
|
"This message will be displayed each time the inferred path changes.",
|
|
BinariesPath) ;
|
|
MessageBox (NULL, str, "Warning", MB_ICONINFORMATION) ;
|
|
}
|
|
reg_printf (true, "Software\\" REGKEY "\\" REGVERKEY "\\Windows", "LastInferredHome", "%s", BinariesPath) ;
|
|
}
|
|
|
|
sprintf(ToolIniFileName, "%sini\\pvtools.ini", DocumentsPath);
|
|
sprintf (DefaultRenderIniFileName, "%sini\\povray.ini", DocumentsPath) ;
|
|
GetModuleFileName (hInst, str, sizeof (str) - 1) ;
|
|
splitpath (str, modulePath, NULL) ;
|
|
validatePath (modulePath) ;
|
|
|
|
sprintf (engineHelpPath, "%shelp\\povray37.chm", BinariesPath) ;
|
|
HtmlHelp (NULL, NULL, HH_INITIALIZE, (DWORD_PTR) &help_cookie) ;
|
|
memset (&hh_aklink, 0, sizeof (hh_aklink)) ;
|
|
hh_aklink.cbStruct = sizeof (hh_aklink) ;
|
|
hh_aklink.fIndexOnFail = true ;
|
|
hh_aklink.pszWindow = "POV-Ray Help" ;
|
|
|
|
SHGetFolderPath (NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, FontPath) ;
|
|
|
|
one_instance = GetHKCU("General", "OneInstance", 1) != 0 ;
|
|
if ((hwnd = FindWindow (PovMainWinClass, NULL)) != NULL)
|
|
{
|
|
if (one_instance)
|
|
{
|
|
if (IsIconic (hwnd))
|
|
ShowWindow (hwnd, SW_RESTORE) ;
|
|
SetForegroundWindow (hwnd) ;
|
|
FeatureNotify ("OneInstanceSet",
|
|
"POV-Ray - 'Keep Single Instance' Feature",
|
|
"You have started POV-Ray for Windows while another copy is running, "
|
|
"and the 'Keep Single Instance' option is turned on (see Options menu). "
|
|
"In this case the other copy is activated rather than starting a new "
|
|
"instance of the program.\n\nClick &Help for information on this feature.",
|
|
"Keep Single Instance",
|
|
false) ;
|
|
|
|
// special case: there's a chance we're being called as a result of a windows file association
|
|
// default, which allows users to associate POV-Ray with arbitrary files. in this case, no
|
|
// /EDIT or /RENDER verb will be present; just the filename. what we do here is see if the
|
|
// passed string is a real file by calling fileExists(). if it is, then we assume /EDIT is
|
|
// desired.
|
|
n = strlen(szCmdLine);
|
|
if (n < _MAX_PATH && n > 2 && szCmdLine[0] == '"' && szCmdLine[n - 1] == '"')
|
|
{
|
|
memcpy(str, szCmdLine + 1, n - 2);
|
|
str[n - 2] = '\0';
|
|
if (fileExists(str))
|
|
{
|
|
FeatureNotify ("EditByDefault",
|
|
"POV-Ray - Filename passed on command-line",
|
|
"Quoted filenames which are the sole command-line parameter are now "
|
|
"opened in the editor by default. If you wish to render them instead "
|
|
"please pass the /RENDER switch, provide more than one parameter, or "
|
|
"use single quotes around the path.\n\n"
|
|
"Click &Help for more information.",
|
|
"associations", false) ;
|
|
add_edit_file(str);
|
|
szCmdLine = "";
|
|
}
|
|
}
|
|
|
|
SetForegroundWindow (hwnd) ;
|
|
if ((s = preparse_instance_commandline (szCmdLine)) != NULL)
|
|
{
|
|
parse_commandline(s);
|
|
if (argc > 1)
|
|
{
|
|
PovMessageBox ("Only /EDIT and /RENDER may be passed to previous instance", "Commandline processing error") ;
|
|
return (1) ;
|
|
}
|
|
COPYDATASTRUCT cd ;
|
|
cd.dwData = EDIT_FILE ;
|
|
for (i = 0 ; i < EditFileCount ; i++)
|
|
{
|
|
s = EditFiles [i] ;
|
|
if ((isalpha (s [0]) && s [1] == ':') || (isPathSeparator(s [0]) && isPathSeparator(s [1])))
|
|
{
|
|
cd.cbData = (int) strlen (s) + 1 ;
|
|
cd.lpData = s ;
|
|
}
|
|
else
|
|
{
|
|
GetCurrentDirectory (sizeof (str), str) ;
|
|
if (!isPathSeparator(s [0]))
|
|
{
|
|
strcat (str, "\\") ;
|
|
strcat (str, s) ;
|
|
}
|
|
else
|
|
strcpy (str + 2, s) ;
|
|
cd.cbData = (int) strlen (str) + 1 ;
|
|
cd.lpData = str ;
|
|
}
|
|
SendMessage (hwnd, WM_COPYDATA, NULL, (LPARAM) &cd) ;
|
|
free (EditFiles [i]) ;
|
|
EditFiles [i] = NULL ;
|
|
}
|
|
EditFileCount = 0 ;
|
|
if (render_requested)
|
|
{
|
|
cd.dwData = RENDER_FILE ;
|
|
s = requested_render_file ;
|
|
if ((isalpha (s [0]) && s [1] == ':') || (isPathSeparator(s [0]) && isPathSeparator(s [1])))
|
|
{
|
|
cd.cbData = (int) strlen (s) + 1 ;
|
|
cd.lpData = s ;
|
|
}
|
|
else
|
|
{
|
|
GetCurrentDirectory (sizeof (str), str) ;
|
|
if (!isPathSeparator(s [0]))
|
|
{
|
|
strcat (str, "\\") ;
|
|
strcat (str, s) ;
|
|
}
|
|
else
|
|
strcpy (str + 2, s) ;
|
|
cd.cbData = (int) strlen (str) + 1 ;
|
|
cd.lpData = str ;
|
|
}
|
|
SendMessage (hwnd, WM_COPYDATA, NULL, (LPARAM) &cd) ;
|
|
}
|
|
SetForegroundWindow (hwnd) ;
|
|
}
|
|
else
|
|
return (1) ;
|
|
return (0) ;
|
|
}
|
|
else
|
|
{
|
|
// one_instance isn't set. we should continue as per normal.
|
|
// however see if we need to notify the user about this.
|
|
FeatureNotify ("OneInstanceUnset",
|
|
"POV-Ray - 'Keep Single Instance' Feature",
|
|
"You have started POV-Ray for Windows while another copy is running, "
|
|
"and the 'Keep Single Instance' option is turned off (see Options menu). "
|
|
"In this case a new instance of the program is started rather than "
|
|
"activating the existing instance of the program.\n\nClick &Help for more "
|
|
"information on this feature.",
|
|
"Keep Single Instance",
|
|
false) ;
|
|
}
|
|
}
|
|
|
|
if (_strnicmp (szCmdLine, "/DEBUG", 6) == 0)
|
|
{
|
|
debugging = true ;
|
|
debug_output(NULL) ;
|
|
}
|
|
|
|
SetThreadPriority (hMainThread, THREAD_PRIORITY_ABOVE_NORMAL) ;
|
|
version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO) ;
|
|
GetVersionEx (&version_info) ;
|
|
use_editors = editors_enabled ;
|
|
|
|
IsW98 = HaveWin98OrLater () ;
|
|
IsWNT = HaveNT4OrLater () ;
|
|
IsW2k = HaveWin2kOrLater () ;
|
|
IsWXP = HaveWinXPOrLater () ;
|
|
IsVista = HaveVistaOrLater () ;
|
|
|
|
// yes, we actually used to support the windows 3.1 UI ...
|
|
IsW95UserInterface = true ;
|
|
|
|
ourIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IsWXP ? IDI_PVENGINE_XP : IDI_PVENGINE)) ;
|
|
renderIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IsWXP ? IDI_RENDERWINDOW_XP : IDI_RENDERWINDOW)) ;
|
|
|
|
if (hPrev == NULL)
|
|
if (register_classes () == false)
|
|
MessageBox (NULL, "ERROR : Could not register classes", "Error", MB_ICONSTOP) ;
|
|
|
|
IsComCtl5 = GetDllVersion (TEXT ("comctl32.dll")) >= MAKELONG (5,0) ;
|
|
IsComCtl6 = GetDllVersion (TEXT ("comctl32.dll")) >= MAKELONG (6,0) ;
|
|
|
|
// need to init menus before we read INI settings
|
|
init_menus () ;
|
|
|
|
// need to do this before we detect the graphics config
|
|
read_INI_settings () ;
|
|
|
|
detect_graphics_config () ;
|
|
clear_system_palette () ;
|
|
hPalApp = WinLegacyDisplay::CreatePalette (NULL, 0, render_bitmap_depth != 24) ;
|
|
|
|
if (!QueryPerformanceFrequency ((LARGE_INTEGER *) &PerformanceFrequency))
|
|
PerformanceFrequency = 0 ;
|
|
if (PerformanceFrequency > 1999999)
|
|
PerformanceScale = PerformanceFrequency / 1000000 ;
|
|
|
|
// 'IsW95UserInterface' dates from when Windows 95 and NT4 were introduced
|
|
// (at that time we still supported the old Windows 3.1 UI)
|
|
// IsW95UserInterface = GetHKCU("General", "UseW95UserInterface", 1) != 0 ;
|
|
IsW95UserInterface = true;
|
|
info_render_complete = GetHKCU("Info", "RenderCompleteSound", 0) != 0 ;
|
|
|
|
SetupFrontend();
|
|
|
|
if (!IsW95UserInterface)
|
|
{
|
|
PVEnableMenuItem (CM_SHOWMAINWINDOW, MF_GRAYED) ;
|
|
use_taskbar = false ;
|
|
}
|
|
|
|
create_about_font () ;
|
|
|
|
InitializeCriticalSection (&critical_section) ;
|
|
|
|
GetHKCU("General", "CommandLine", "", old_command_line, sizeof (old_command_line)) ;
|
|
strcpy (command_line, old_command_line) ;
|
|
|
|
// special case: POV may get associated with an arbitrary file type by the user.
|
|
// in such cases we won't be given any verbs to indicate what to do with the file,
|
|
// and in many instances our default action (which is to assume the file is either
|
|
// SDL or INI) is not appropriate. so we make an exception here for such cases.
|
|
//
|
|
// if the sole command-line parameter is a QUOTED filename referring to a file which
|
|
// exists, we assume /EDIT is desired (this may break some scripts that assume the
|
|
// default; in such cases the script should explicitly pass /RENDER). the shell
|
|
// always quotes files passed in this way; by testing for the quotes we can
|
|
// eliminate some unnecessary tests.
|
|
n = strlen(szCmdLine);
|
|
if (n < _MAX_PATH && n > 2 && szCmdLine[0] == '"' && szCmdLine[n - 1] == '"')
|
|
{
|
|
memcpy(str, szCmdLine + 1, n - 2);
|
|
str[n - 2] = '\0';
|
|
if (fileExists(str))
|
|
{
|
|
FeatureNotify ("EditByDefault",
|
|
"POV-Ray - Filename passed on command-line",
|
|
"Quoted filenames which are the sole command-line parameter are now "
|
|
"opened in the editor by default. If you wish to render them instead "
|
|
"please pass the /RENDER switch (or provide more than one parameter).\n\n"
|
|
"Click &Help for more information.",
|
|
"associations", false) ;
|
|
add_edit_file(str);
|
|
szCmdLine = "";
|
|
}
|
|
}
|
|
|
|
if ((szCmdLine = preparse_commandline (szCmdLine)) != NULL)
|
|
{
|
|
if (benchmark_mode)
|
|
demo_mode = false;
|
|
if (parse_commandline (szCmdLine) > 1 && !demo_mode && !benchmark_mode)
|
|
{
|
|
restore_command_line = true ;
|
|
strncpy (command_line, szCmdLine, sizeof (command_line) - 1) ;
|
|
}
|
|
}
|
|
|
|
if (debugging)
|
|
if (_getcwd (str, sizeof (str) - 1) != NULL)
|
|
debug_output("CWD is %s\n", str) ;
|
|
|
|
if (editors_enabled)
|
|
{
|
|
if (EditDLLPath != NULL)
|
|
{
|
|
sprintf (str, "%s" EDITDLLNAME, EditDLLPath) ;
|
|
if (!LoadEditorDLL (str, false))
|
|
use_editors = false ;
|
|
}
|
|
else
|
|
{
|
|
sprintf (str, "%s\\" EDITDLLNAME, modulePath) ;
|
|
if (!LoadEditorDLL (str, true))
|
|
{
|
|
sprintf (str, "%sbin\\" EDITDLLNAME, BinariesPath) ;
|
|
if (!LoadEditorDLL (str, false))
|
|
use_editors = false ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
use_editors = false;
|
|
|
|
GetHKCU("General", VERSIONVAL, "[unknown]", str, (DWORD) strlen (str)) ;
|
|
if (debugging)
|
|
debug_output("Registry records version %s, and we are %s\n", str, POV_RAY_VERSION COMPILER_VER SSE2_INCLUDED "." PVENGINE_VER) ;
|
|
|
|
if (strcmp (str, POV_RAY_VERSION COMPILER_VER "." PVENGINE_VER) != 0)
|
|
{
|
|
// we don't want to set the newVersion flag if the only thing that changed
|
|
// was the compiler used to generate the binary. in this case we add an
|
|
// explicit check for the intel, msvc, and watcom versions.
|
|
if ((s = strstr (str, ".icl")) != NULL)
|
|
strcpy (s, s + 4) ;
|
|
else if ((s = strstr (str, ".msvc")) != NULL)
|
|
strcpy (s, s + 5) ;
|
|
else if ((s = strstr (str, ".watcom")) != NULL)
|
|
strcpy (s, s + 7) ;
|
|
// strip off any trailing digits from the compiler version
|
|
if (s)
|
|
while (isdigit (*s))
|
|
strcpy (s, s + 1) ;
|
|
if (strcmp (str, POV_RAY_VERSION "." PVENGINE_VER) != 0)
|
|
newVersion = true ;
|
|
}
|
|
|
|
if ((run_count = GetHKCU("General", "RunCount", 0)) == 0 || newVersion)
|
|
{
|
|
if (screen_depth < 8)
|
|
{
|
|
MessageBox (NULL,
|
|
"NOTE : POV-Ray for Windows was not designed to run in 16-color mode. "
|
|
"While the program will operate, it is recommended that you use a minimum "
|
|
"graphics mode of 800x600x256.",
|
|
"Warning - running in 16-color mode",
|
|
MB_ICONEXCLAMATION) ;
|
|
tile_background = false ;
|
|
}
|
|
if (screen_width < 800)
|
|
{
|
|
MessageBox (NULL,
|
|
"NOTE : POV-Ray for Windows was not designed to run at less than 800x600.\n\n"
|
|
"While the program will operate, it is recommended that you use a minimum "
|
|
"graphics mode of 800x600x256.",
|
|
"Warning - running at less than 800x600",
|
|
MB_ICONEXCLAMATION) ;
|
|
}
|
|
}
|
|
PutHKCU ("General", "RunCount", ++run_count) ;
|
|
|
|
if (screen_depth < 8)
|
|
tile_background = false ;
|
|
|
|
/* Create the main window */
|
|
placement = mainwin_placement ;
|
|
placement.length = sizeof (WINDOWPLACEMENT) ;
|
|
w = mainwin_placement.rcNormalPosition.right - mainwin_placement.rcNormalPosition.left ;
|
|
h = mainwin_placement.rcNormalPosition.bottom - mainwin_placement.rcNormalPosition.top ;
|
|
if (w <= 128)
|
|
w = 700 ;
|
|
if (h <= 128)
|
|
h = screen_height - 75 ;
|
|
main_window = CreateWindowEx (0,
|
|
PovMainWinClass,
|
|
"POV-Ray for Windows",
|
|
WS_OVERLAPPEDWINDOW,
|
|
mainwin_placement.rcNormalPosition.left,
|
|
mainwin_placement.rcNormalPosition.top,
|
|
w,
|
|
h,
|
|
NULL,
|
|
NULL,
|
|
hInst,
|
|
NULL) ;
|
|
|
|
if (main_window == NULL)
|
|
{
|
|
MessageBox (NULL, "ERROR : Could not create main window.", "Critical Error", MB_ICONSTOP) ;
|
|
cleanup_all () ;
|
|
return (1) ;
|
|
}
|
|
|
|
EditSetNotifyBase (main_window, CM_FIRSTEDITNOTIFY) ;
|
|
|
|
if ((StatusWindow = CreateStatusbar (main_window)) == NULL)
|
|
{
|
|
MessageBox (main_window, "ERROR : Could not create statusbar", "Critical Error", MB_ICONSTOP) ;
|
|
cleanup_all () ;
|
|
return (1) ;
|
|
}
|
|
|
|
if (tile_background && background_file [1])
|
|
{
|
|
if ((hDIB = LoadDIB (background_file)) != NULL)
|
|
{
|
|
hBmpBackground = DIBToBitmap (hDIB, hPalApp) ;
|
|
DeleteObject (hDIB) ;
|
|
GetObject (hBmpBackground, sizeof (BITMAP), (LPSTR) &bm) ;
|
|
background_width = bm.bmWidth ;
|
|
background_height = bm.bmHeight ;
|
|
}
|
|
else
|
|
{
|
|
PovMessageBox ("Failed to load bitmap file", "Error") ;
|
|
strcpy (background_file, "0") ;
|
|
}
|
|
}
|
|
|
|
if (tile_background && hBmpBackground == NULL && screen_depth >= 8)
|
|
{
|
|
if (isdigit (background_file [0]) && background_file [1] == '\0')
|
|
id = background_file [0] - '0' ;
|
|
SendMessage (main_window, WM_COMMAND, CM_BACKGROUNDSTD + id, 1L) ;
|
|
}
|
|
|
|
if ((hBMP = LoadBitmap (hInstance, MAKEINTRESOURCE (BMP_ICON))) != NULL)
|
|
hBmpIcon = hBMP ;
|
|
|
|
if (lastBitmapPath [0] == '\0')
|
|
sprintf (lastBitmapPath, "%sTiles", BinariesPath) ;
|
|
if (lastRenderPath [0] == '\0')
|
|
{
|
|
sprintf (lastRenderPath, "%sScenes\\Advanced", DocumentsPath) ;
|
|
strcpy (lastRenderName, "Biscuit.pov") ;
|
|
}
|
|
if (lastQueuePath [0] == '\0')
|
|
sprintf (lastQueuePath, "%sScenes", DocumentsPath) ;
|
|
GetHKCU("Editor", "LastPath", "", str, sizeof (str)) ;
|
|
validatePath (lastRenderPath) ;
|
|
if (str [0] == '\0')
|
|
PutHKCU("Editor", "LastPath", lastRenderPath) ;
|
|
if (lastRenderName [0] != '\0' && !demo_mode && !benchmark_mode)
|
|
joinPath (source_file_name, lastRenderPath, lastRenderName) ;
|
|
|
|
if (use_editors)
|
|
if ((tab_window = InitialiseEditor (main_window, StatusWindow, BinariesPath, DocumentsPath)) == NULL)
|
|
use_editors = false ;
|
|
|
|
message_window = CreateWindowEx (WS_EX_CLIENTEDGE,
|
|
PovMessageWinClass,
|
|
"",
|
|
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
use_editors ? tab_window : main_window,
|
|
NULL,
|
|
hInst,
|
|
NULL) ;
|
|
if (message_window == NULL)
|
|
{
|
|
MessageBox (NULL, "ERROR : Could not create message window.", "Critical Error", MB_ICONSTOP) ;
|
|
cleanup_all () ;
|
|
return (1) ;
|
|
}
|
|
|
|
if (initialise_message_display ())
|
|
{
|
|
cleanup_all () ;
|
|
return (1) ;
|
|
}
|
|
EditSetMessageWindow (message_window) ;
|
|
|
|
if ((rebar_window = create_rebar (main_window)) == NULL)
|
|
{
|
|
MessageBox (main_window, "ERROR : Could not create internal window #1", "Critical Error", MB_ICONSTOP) ;
|
|
cleanup_all () ;
|
|
return (1) ;
|
|
}
|
|
if ((toolbar_window = create_toolbar (rebar_window)) == NULL)
|
|
{
|
|
MessageBox (main_window, "ERROR : Could not create internal window #2", "Critical Error", MB_ICONSTOP) ;
|
|
cleanup_all () ;
|
|
return (1) ;
|
|
}
|
|
if (!use_toolbar)
|
|
{
|
|
ShowWindow (rebar_window, SW_HIDE) ;
|
|
toolheight = 0 ;
|
|
}
|
|
extract_ini_sections_ex (SecondaryRenderIniFileName, toolbar_combobox) ;
|
|
SendMessage (toolbar_combobox, CB_ADDSTRING, 0, (LPARAM) "More Resolutions ...") ;
|
|
tb_combo_sel = select_combo_item_ex (toolbar_combobox, SecondaryRenderIniFileSection) ;
|
|
if (tb_combo_sel == -1)
|
|
tb_combo_sel = 0 ;
|
|
|
|
setup_menus (use_editors) ;
|
|
build_main_menu (hMainMenu, use_editors) ;
|
|
|
|
set_toggles () ;
|
|
|
|
if (!use_editors)
|
|
{
|
|
SendMessage (toolbar_window, TB_ENABLEBUTTON, CM_FILENEW, 0L) ;
|
|
SendMessage (toolbar_window, TB_ENABLEBUTTON, CM_FILEOPEN, 0L) ;
|
|
SendMessage (toolbar_window, TB_ENABLEBUTTON, CM_FILESAVE, 0L) ;
|
|
}
|
|
else
|
|
EditRestoreState (!NoRestore) ;
|
|
|
|
if (editors_enabled)
|
|
PVCheckMenuItem (CM_USEEDITOR, MF_CHECKED) ;
|
|
PVEnableMenuItem (CM_RENDERHIDE, RenderwinIsChild ? MF_GRAYED : MF_ENABLED) ;
|
|
PVEnableMenuItem (CM_RENDERACTIVE, RenderwinIsChild ? MF_GRAYED : MF_ENABLED) ;
|
|
PVCheckMenuItem (on_completion, MF_CHECKED) ;
|
|
PVEnableMenuItem (CM_RENDERSHOW, MF_GRAYED) ;
|
|
PVEnableMenuItem (CM_RENDERSLEEP, MF_GRAYED) ;
|
|
|
|
PVCheckMenuRadioItem (CM_RENDERPRIORITY_BACKGROUND, CM_RENDERPRIORITY_HIGH, render_priority) ;
|
|
|
|
PVCheckMenuItem (drop_to_editor ? CM_DROPEDITOR : CM_DROPRENDERER, MF_CHECKED) ;
|
|
|
|
PVEnableMenuItem (CM_RENDERSHOW, MF_GRAYED) ;
|
|
PVEnableMenuItem (CM_RENDERCLOSE, MF_GRAYED) ;
|
|
PVModifyMenu (CM_TILEDBACKGROUND,
|
|
MF_STRING,
|
|
CM_TILEDBACKGROUND,
|
|
tile_background ? "&Select Plain Background" : "&Select Tiled Background") ;
|
|
PVCheckMenuRadioItem (CM_DUTYCYCLE_10, CM_DUTYCYCLE_100, CM_DUTYCYCLE_10 + Duty_Cycle) ;
|
|
if (screen_depth < 8)
|
|
{
|
|
PVEnableMenuItem (CM_TILEDBACKGROUND, MF_GRAYED) ;
|
|
PVEnableMenuItem (CM_BACKGROUNDBITMAP, MF_GRAYED) ;
|
|
for (i = 0 ; i < 16 ; i++)
|
|
PVEnableMenuItem (CM_BACKGROUNDSTD + i, MF_GRAYED) ;
|
|
}
|
|
set_newuser_menus (hide_newuser_help) ;
|
|
|
|
if (ThreadCount == 1)
|
|
{
|
|
PVDeleteMenuItem (CM_BENCHMARK) ;
|
|
PVModifyMenu (CM_BENCHMARKONETHREAD, MF_STRING, CM_BENCHMARKONETHREAD, "Run &Benchmark") ;
|
|
}
|
|
|
|
switch (placement.showCmd)
|
|
{
|
|
case SW_SHOWNORMAL :
|
|
show_state = SW_SHOW ;
|
|
break ;
|
|
|
|
case SW_SHOWMINIMIZED :
|
|
// show_state = SW_SHOWMINNOACTIVE ;
|
|
show_state = SW_SHOW ;
|
|
break ;
|
|
|
|
case SW_SHOWMAXIMIZED :
|
|
show_state = SW_SHOWMAXIMIZED ;
|
|
break ;
|
|
|
|
default :
|
|
show_state = SW_SHOW ;
|
|
break ;
|
|
}
|
|
|
|
if (ListenMode)
|
|
show_state = SW_HIDE ;
|
|
|
|
placement.showCmd = show_state ;
|
|
placement.flags = (placement.ptMinPosition.x == -1 && placement.ptMinPosition.y == -1) ? 0 : WPF_SETMINPOSITION ;
|
|
if (placement.rcNormalPosition.right <= 0 || placement.rcNormalPosition.bottom <= 0)
|
|
{
|
|
placement.rcNormalPosition.right = placement.rcNormalPosition.left + message_xchar * 115 ;
|
|
placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + message_ychar * 75 ;
|
|
}
|
|
|
|
placement.length = sizeof (WINDOWPLACEMENT) ;
|
|
SetWindowPlacement (main_window, &placement) ;
|
|
if (show_state != SW_SHOWMAXIMIZED)
|
|
FitWindowInWindow (NULL, main_window) ;
|
|
|
|
if ((timer_id = SetTimer (main_window, 1, 250, NULL)) != 0)
|
|
DragAcceptFiles (main_window, true) ;
|
|
|
|
// only needed for earlier versions of common control DLL ...
|
|
if (use_toolbar && !IsComCtl5)
|
|
{
|
|
hDC = GetDC (toolbar_window) ;
|
|
GetClientRect (toolbar_window, &rect) ;
|
|
FillRect (hDC, &rect, (HBRUSH) GetStockObject (LTGRAY_BRUSH)) ;
|
|
ReleaseDC (toolbar_window, hDC) ;
|
|
}
|
|
|
|
// fixes visual glitch with ComCtl6
|
|
if (use_toolbar && IsComCtl6)
|
|
{
|
|
hDC = GetDC (main_window) ;
|
|
GetClientRect (rebar_window, &rect) ;
|
|
FillRect (hDC, &rect, (HBRUSH) GetStockObject (LTGRAY_BRUSH)) ;
|
|
ReleaseDC (main_window, hDC) ;
|
|
}
|
|
|
|
if (ExtensionsEnabled)
|
|
LoadGUIExtensions () ;
|
|
|
|
if (renderwin_left < 0 || renderwin_left > screen_width - 32 || renderwin_top < 0 || renderwin_top > screen_height - 32)
|
|
{
|
|
MONITORINFO mi;
|
|
mi.cbSize = sizeof(MONITORINFO);
|
|
if (GetMonitorInfo(MonitorFromWindow(main_window, MONITOR_DEFAULTTOPRIMARY), &mi))
|
|
{
|
|
// apply the principle of least astonishment: otherwise the render window could
|
|
// turn up on a monitor which may be switched off or otherwise not being paid
|
|
// attention to, with no (obvious) way for the user to move it. we make one
|
|
// exception: if the render window is placed on the primary display, we won't
|
|
// move it to the current display, since it's assumed the primary display is
|
|
// always going to be visible.
|
|
if (renderwin_left < mi.rcWork.left)
|
|
renderwin_left = mi.rcWork.left ;
|
|
if (renderwin_top < mi.rcWork.top)
|
|
renderwin_top = mi.rcWork.top ;
|
|
if (renderwin_left > mi.rcWork.right - 128)
|
|
renderwin_left = mi.rcWork.right - 128 ;
|
|
if (renderwin_top > mi.rcWork.bottom - 128)
|
|
renderwin_top = mi.rcWork.bottom - 128 ;
|
|
}
|
|
}
|
|
|
|
buffer_message (mIDE, "Persistence of Vision Raytracer(tm) for Windows.\n") ;
|
|
buffer_message (mIDE, "POV-Ray for Windows is part of the POV-Ray(tm) suite of programs.\n") ;
|
|
buffer_message (mIDE, " This is version " POV_RAY_VERSION COMPILER_VER SSE2_INCLUDED "." PVENGINE_VER ".\n") ;
|
|
buffer_message (mIDE, "Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.\n") ;
|
|
buffer_message (mIDE, " " DISCLAIMER_MESSAGE_1 "\n") ;
|
|
buffer_message (mIDE, " " DISCLAIMER_MESSAGE_2 "\n") ;
|
|
buffer_message (mIDE, " Select Help|About (or press Alt+B) for more information and a copy of the license.\n") ;
|
|
buffer_message (mIDE, "The terms POV-Ray and Persistence of Vision Raytracer are trademarks of\n") ;
|
|
buffer_message (mIDE, " Persistence of Vision Raytracer Pty. Ltd.\n") ;
|
|
if (render_bitmap_depth != 24)
|
|
{
|
|
buffer_message (mIDE, "\n") ;
|
|
buffer_message (mIDE, renderwin_8bits ? "Using 8-bit dithered internal bitmap (menu setting)\n" :
|
|
"Using 8-bit dithered internal bitmap (4 or 8-bit video mode)\n") ;
|
|
}
|
|
|
|
buffer_message (mIDE, "\n") ;
|
|
strcpy (tool_commands [0], "notepad.exe \"%ipovray.ini\"") ;
|
|
|
|
#if POV_RAY_IS_OFFICIAL != 1
|
|
WIN_PrintOtherCredits () ;
|
|
buffer_message (mIDE, "This unofficial build is derived from the POV-Ray for Windows source code.\n") ;
|
|
#endif
|
|
buffer_message (mDivider, "\n") ;
|
|
|
|
#if defined(USE_AVX_FMA4_FOR_NOISE)
|
|
// technically we should ask the backend what it's using, but given this is not a remoted version
|
|
// of POVWIN, we just call the test here.
|
|
if (CPU_FMA4_DETECT() != 0)
|
|
{
|
|
buffer_message (mIDE, "FMA4 instruction support detected: using FMA4-optimized noise functions.\n") ;
|
|
buffer_message (mDivider, "\n") ;
|
|
}
|
|
#endif
|
|
|
|
load_tool_menu (ToolIniFileName) ;
|
|
if (GetHKCU("FileQueue", "ReloadOnStartup", 0))
|
|
{
|
|
queued_file_count = GetHKCU("FileQueue", "QueueCount", 0) ;
|
|
if (queued_file_count > MAX_QUEUE)
|
|
queued_file_count = MAX_QUEUE ;
|
|
for (i = 0 ; i < queued_file_count ; i++)
|
|
{
|
|
sprintf (str, "QueuedFile%d", i) ;
|
|
GetHKCU("FileQueue", str, "", queued_files [i], sizeof (queued_files [0])) ;
|
|
}
|
|
if (queued_file_count != 0)
|
|
message_printf ("Loaded %d entr%s into file queue\n", queued_file_count, queued_file_count == 1 ? "y" : "ies") ;
|
|
update_queue_status (false) ;
|
|
}
|
|
|
|
if (have_cpu_info)
|
|
message_printf("Detected %u CPU%s providing %u physical core%s and %u logical one%s.\n",
|
|
NumPhysicalCPUs, NumPhysicalCPUs > 1 ? "'s" : "",
|
|
NumCPUCores, NumCPUCores > 1 ? "s" : "",
|
|
NumLogicalCPUs, NumLogicalCPUs > 1 ? "s" : "");
|
|
|
|
buffer_message (mDivider, "\n") ;
|
|
|
|
if (GetHKCU("General", "CheckColorsInc", 1) == 1)
|
|
{
|
|
sprintf (str, "%sinclude\\colors.inc", DocumentsPath) ;
|
|
if (stat (str, &statbuf) != 0)
|
|
{
|
|
char temp[2048];
|
|
sprintf(temp,
|
|
"WARNING : Cannot find COLORS.INC in expected location:\n\n%s\n\n"
|
|
"This file is important for the normal operation of POV-Ray. It is included "
|
|
"with the POV-Ray for Windows distribution. If you did not install using the "
|
|
"correct installation procedure please attend to this before running POV-Ray "
|
|
"for Windows.\n\nIf, however, you have chosen to change the location of this file "
|
|
"or do not need it, you may ignore this warning as long as you have updated "
|
|
"POVRAY.INI to the new path, or do not use any standard scenes that require it.\n\n"
|
|
"Do you want to see this warning again ?",
|
|
str);
|
|
if (MessageBox (NULL, temp, "Warning - COLORS.INC is missing", MB_ICONEXCLAMATION | MB_YESNO) == IDNO)
|
|
PutHKCU ("General", "CheckColorsInc", 0U) ;
|
|
}
|
|
}
|
|
|
|
if (demo_mode)
|
|
{
|
|
message_printf ("Running demonstration\n") ;
|
|
argc = 0 ;
|
|
handle_main_command (CM_DEMO, 0) ;
|
|
}
|
|
|
|
if (benchmark_mode)
|
|
{
|
|
message_printf ("Running benchmark\n") ;
|
|
argc = 0 ;
|
|
handle_main_command (CM_BENCHMARK, 0) ;
|
|
}
|
|
|
|
SendMessage (toolbar_cmdline, WM_SETTEXT, 0, (LPARAM) command_line) ;
|
|
|
|
if (debugging)
|
|
{
|
|
message_printf ("My window handle is %p\n", main_window) ;
|
|
|
|
if (HaveWin95OrLater ())
|
|
message_printf ("Win95 or later detected\n") ;
|
|
if (HaveWin98OrLater ())
|
|
message_printf ("Win98 or later detected\n") ;
|
|
if (HaveNT4OrLater ())
|
|
message_printf ("WinNT or later detected\n") ;
|
|
if (HaveWin2kOrLater ())
|
|
message_printf ("Win2k or later detected\n") ;
|
|
if (HaveWinXPOrLater ())
|
|
message_printf ("WinXP or later detected\n") ;
|
|
if (IsW95UserInterface)
|
|
message_printf ("Windows 95 user interface flag is set\n") ;
|
|
}
|
|
|
|
for (i = 0 ; i < EditFileCount ; i++)
|
|
{
|
|
if (EditGetFlags () & EDIT_CAN_OPEN)
|
|
EditOpenFile (EditFiles [i]) ;
|
|
free (EditFiles [i]) ;
|
|
EditFiles [i] = NULL ;
|
|
}
|
|
EditFileCount = 0 ;
|
|
|
|
if (newVersion || FreshInstall)
|
|
{
|
|
if (EditGetFlags() & EDIT_CAN_OPEN)
|
|
{
|
|
sprintf(str, "%srevision.txt", DocumentsPath);
|
|
if (fileExists(str))
|
|
EditOpenFile(str) ;
|
|
if (EditGetFlags() & EDIT_CAN_OPEN)
|
|
{
|
|
sprintf(str, "%schanges.txt", DocumentsPath);
|
|
if (fileExists(str))
|
|
EditOpenFile(str) ;
|
|
}
|
|
}
|
|
|
|
// TODO: remove this after a few betas
|
|
tile_background = false;
|
|
text_colours[0] = RGB (255, 255, 255);
|
|
text_colours[1] = RGB (255, 255, 0);
|
|
text_colours[2] = RGB (0, 255, 255);
|
|
background_colour = RGB (31, 0, 63);
|
|
}
|
|
|
|
if (run_count > 1 && !demo_mode && !benchmark_mode)
|
|
{
|
|
n = GetHKCU("General", "ItsAboutTime", 0) ;
|
|
if (_time32 (NULL) > n /*|| newVersion*/)
|
|
{
|
|
ShowAboutBox () ;
|
|
PutHKCU ("General", "ItsAboutTime", n ? _time32 (NULL) + DAYS(14) : _time32 (NULL) + DAYS(1)) ;
|
|
}
|
|
}
|
|
|
|
#if POV_RAY_IS_OFFICIAL == 1
|
|
DoUpdateCheck () ;
|
|
#endif
|
|
|
|
// automatically call the rendering engine if there were any parameters on the command line
|
|
if (!rendering && (argc > 1 || render_requested))
|
|
{
|
|
if (render_requested)
|
|
{
|
|
wrapped_printf ("Requested render file is '%s'", requested_render_file) ;
|
|
strcpy (source_file_name, requested_render_file) ;
|
|
}
|
|
if (argc > 1)
|
|
wrapped_printf ("Calling rendering engine with parameters '%s'", command_line) ;
|
|
start_rendering (!render_requested) ;
|
|
}
|
|
|
|
if (homeInferred)
|
|
message_printf ("Warning: running with inferred home path due to missing registry entry.\n\n") ;
|
|
|
|
#ifdef _DEBUG
|
|
if (sizeof (ExternalVarStruct) != 0x9350)
|
|
PovMessageBox ("Compatibility problem - ExternalVarStruct has changed size", "Warning") ;
|
|
#endif
|
|
|
|
if (ListenMode)
|
|
handle_main_command (CM_SHOWMAINWINDOW, 0) ;
|
|
|
|
if (debugging)
|
|
debug_output("Entering GetMessage loop\n") ;
|
|
|
|
try
|
|
{
|
|
while (!exit_loop)
|
|
{
|
|
// since the render thread can really slow things down for the UI (this becomes
|
|
// a problem if the user sets the render priority to high and then finds the
|
|
// UI unresponsive when attempting to change it back), we only sleep here if
|
|
// there's no events in the queue that we feel the need to handle immediately.
|
|
// (if one of these messages turns up while we're sleeping we'll get woken).
|
|
// N.B. longer wait times resulted in complaints from some testers, apparently
|
|
// there's some machines out there that don't exit the wait for some types of
|
|
// input.
|
|
MsgWaitForMultipleObjects (0, NULL, FALSE, 10, QS_ALLINPUT) ;
|
|
// MsgWaitForMultipleObjects (0, NULL, FALSE, 10, QS_HOTKEY | QS_KEY | QS_MOUSEBUTTON) ;
|
|
|
|
if (StartInsertRender)
|
|
{
|
|
if (!rendering)
|
|
start_rendering (false) ;
|
|
StartInsertRender = false ;
|
|
}
|
|
|
|
if (quit != 0)
|
|
if (quit + 15 < time (NULL))
|
|
break ;
|
|
|
|
ProcessSession();
|
|
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
if (msg.message == WM_QUIT)
|
|
{
|
|
exit_loop = true ;
|
|
break ;
|
|
}
|
|
|
|
// we have to disable all these calls because HTML Help has a bug (on some
|
|
// platforms - I can't work out the exact conditions that trigger it) which
|
|
// will cause the cursor to flash between normal and the busy state (normally
|
|
// an hourglass) several times a second, continually (even if help isn't open).
|
|
// See job #124.
|
|
#ifdef HTMLHELP_FIXED
|
|
if (HtmlHelp (NULL, NULL, HH_PRETRANSLATEMESSAGE, (DWORD) &msg))
|
|
continue ;
|
|
#else
|
|
// we need to pass on these messages, otherwise help navigation messages
|
|
// will go to us instead of the help window
|
|
if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
|
|
if (!IsChild (main_window, msg.hwnd))
|
|
if (HtmlHelp (NULL, NULL, HH_PRETRANSLATEMESSAGE, (DWORD_PTR) &msg))
|
|
continue ;
|
|
#endif
|
|
if (!TranslateAccelerator (main_window, hAccelerators, &msg))
|
|
{
|
|
TranslateMessage (&msg) ;
|
|
if (msg.hwnd == toolbar_cmdline)
|
|
{
|
|
if (msg.message == WM_CHAR)
|
|
if (handle_toolbar_cmdline (msg.wParam, msg.lParam))
|
|
continue ;
|
|
}
|
|
DispatchMessage (&msg) ;
|
|
}
|
|
ProcessSession();
|
|
}
|
|
}
|
|
}
|
|
catch(std::exception& e)
|
|
{
|
|
sprintf (str, "Caught exception: %s", e.what()) ;
|
|
if (debugging)
|
|
debug_output ("%s\n", str) ;
|
|
MessageBox (NULL, str, "POV-Ray Critical Error", MB_ICONSTOP) ;
|
|
exit(1);
|
|
}
|
|
|
|
if (debugging)
|
|
debug_output ("Dropping out of message loop\n") ;
|
|
|
|
try
|
|
{
|
|
DeleteFrontend();
|
|
cleanup_all () ;
|
|
}
|
|
catch(pov_base::Exception& e)
|
|
{
|
|
// don't do much about POV exceptions here: often, they will relate to the front end
|
|
// not cleaning up fast enough (i.e. due to a lot of memory de-allocation)
|
|
if (debugging)
|
|
debug_output ("Caught exception: %s\n", e.what()) ;
|
|
}
|
|
catch(std::exception& e)
|
|
{
|
|
sprintf (str, "Caught exception: %s", e.what()) ;
|
|
if (debugging)
|
|
debug_output ("%s\n", str) ;
|
|
MessageBox (NULL, str, "POV-Ray Critical Error", MB_ICONSTOP) ;
|
|
}
|
|
|
|
_fcloseall () ;
|
|
#ifndef _WIN64
|
|
// win64 - get exception during HH_UNINITIALIZE
|
|
HtmlHelp (NULL, NULL, HH_UNINITIALIZE, (DWORD) help_cookie) ;
|
|
#endif
|
|
|
|
if (debugging)
|
|
debug_output ("exiting WinMain()\n") ;
|
|
return (0) ;
|
|
}
|