569 lines
17 KiB
C++
569 lines
17 KiB
C++
/*******************************************************************************
|
|
* pvedit.cpp
|
|
*
|
|
* This file contains editor support code.
|
|
*
|
|
* 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/pvedit.cpp $
|
|
* $Revision: #1 $
|
|
* $Change: 6069 $
|
|
* $DateTime: 2013/11/06 11:59:40 $
|
|
* $Author: chrisc $
|
|
*******************************************************************************/
|
|
|
|
#define POVWIN_FILE
|
|
#define _WIN32_IE COMMONCTRL_VERSION
|
|
|
|
#include <windows.h>
|
|
#include <shellapi.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include "pvengine.h"
|
|
#include "pvedit.h"
|
|
#include "backend/parser/reswords.h"
|
|
|
|
// this must be the last file included
|
|
#include "syspovdebug.h"
|
|
|
|
namespace pov_frontend
|
|
{
|
|
extern struct ProcessOptions::INI_Parser_Table RenderOptions_INI_Table[];
|
|
}
|
|
|
|
namespace povwin
|
|
{
|
|
|
|
using namespace pov;
|
|
|
|
HINSTANCE hLibPovEdit ;
|
|
|
|
extern bool debugging ;
|
|
extern HWND main_window ;
|
|
extern bool use_editors;
|
|
extern bool editors_enabled;
|
|
|
|
static HWND (*CreateTabWindow) (HWND ParentWindow, HWND StatusWindow, const char *BinariesPath, const char *DocumentsPath) ;
|
|
static DWORD (*GetDLLVersion) (void) ;
|
|
static void (*SetWindowPosition) (int x, int y, int w, int h) ;
|
|
static void (*SetMessageWindow) (HWND MessageWindow) ;
|
|
static void (*RestoreState) (int RestoreFiles) ;
|
|
static void (*SaveState) (void) ;
|
|
static bool (*SelectFile) (char *FileName) ;
|
|
static bool (*BrowseFile) (bool CreateNewWindow) ;
|
|
static bool (*LoadFile) (char *FileName) ;
|
|
static bool (*CloseFile) (char *FileName) ;
|
|
static bool (*SaveFile) (char *FileName) ;
|
|
static bool (*ExternalLoadFile) (char *ParamString) ;
|
|
static DWORD (*GetTab) (void) ;
|
|
static DWORD (*GetFlags) (void) ;
|
|
static char *(*GetFilename) (void) ;
|
|
static void (*NextTab) (bool Forward) ;
|
|
static bool (*CanClose) (bool AllFiles) ;
|
|
static bool (*SaveModified) (char *FileName) ;
|
|
static bool (*ShowMessages) (bool on) ;
|
|
static void (*DispatchMenuId) (DWORD id) ;
|
|
static HMENU (*GetMenuHandle) (int which) ;
|
|
static void (*SetNotifyBase) (HWND WindowHandle, int MessageBase) ;
|
|
static void (*UpdateMenus) (HMENU MenuHandle) ;
|
|
static void (*GetContextHelp) (void) ;
|
|
static void (*SetTabFocus) (void) ;
|
|
static bool (*ShowParseError) (const char *FileName, const char *Message, int Line, int Col) ;
|
|
static bool (*PassOnMessage) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, DWORD *rVal) ;
|
|
static void (*SetKeywords) (LPCSTR SDLKeywordList, LPCSTR INIKeywords) ;
|
|
static const char **(*GetWindowList) (void);
|
|
|
|
void **FunctionPtrs [] =
|
|
{
|
|
(void **) &GetWindowList,
|
|
(void **) &SetWindowPosition,
|
|
(void **) &SetMessageWindow,
|
|
(void **) &RestoreState,
|
|
(void **) &SaveState,
|
|
(void **) &SelectFile,
|
|
(void **) &BrowseFile,
|
|
(void **) &LoadFile,
|
|
(void **) &CloseFile,
|
|
(void **) &SaveFile,
|
|
(void **) &ExternalLoadFile,
|
|
(void **) &GetTab,
|
|
(void **) &GetFlags,
|
|
(void **) &GetFilename,
|
|
(void **) &NextTab,
|
|
(void **) &CanClose,
|
|
(void **) &SaveModified,
|
|
(void **) &ShowMessages,
|
|
(void **) &DispatchMenuId,
|
|
(void **) &GetMenuHandle,
|
|
(void **) &SetNotifyBase,
|
|
(void **) &UpdateMenus,
|
|
(void **) &GetContextHelp,
|
|
(void **) &SetTabFocus,
|
|
(void **) &ShowParseError,
|
|
(void **) &PassOnMessage,
|
|
(void **) &SetKeywords,
|
|
(void **) &CreateTabWindow,
|
|
NULL
|
|
} ;
|
|
|
|
char *FunctionNames [] =
|
|
{
|
|
"GetWindowList",
|
|
"SetWindowPosition",
|
|
"SetMessageWindow",
|
|
"RestoreState",
|
|
"SaveState",
|
|
"SelectFile",
|
|
"BrowseFile",
|
|
"LoadFile",
|
|
"CloseFile",
|
|
"SaveFile",
|
|
"ExternalLoadFile",
|
|
"GetTab",
|
|
"GetFlags",
|
|
"GetFilename",
|
|
"NextTab",
|
|
"CanClose",
|
|
"SaveModified",
|
|
"ShowMessages",
|
|
"DispatchMenuId",
|
|
"GetMenuHandle",
|
|
"SetNotifyBase",
|
|
"UpdateMenus",
|
|
"GetContextHelp",
|
|
"SetTabFocus",
|
|
"ShowParseError",
|
|
"PassOnMessage",
|
|
"SetKeywords",
|
|
"CreateTabWindow",
|
|
NULL
|
|
} ;
|
|
|
|
bool LoadEditorDLL (char *path, bool errorOK)
|
|
{
|
|
int DllVersion ;
|
|
int err ;
|
|
char str [2048] ;
|
|
char **s ;
|
|
void ***f ;
|
|
struct stat statbuf ;
|
|
|
|
if (!editors_enabled)
|
|
return (false) ;
|
|
if (debugging)
|
|
debug_output ("Trying to load editor DLL from '%s' [%s]\n", path, stat (path, &statbuf) != 0 ? "missing" : "found") ;
|
|
if (hLibPovEdit != NULL)
|
|
FreeLibrary(hLibPovEdit);
|
|
if ((hLibPovEdit = LoadLibraryEx (path, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL)
|
|
{
|
|
err = GetLastError () ;
|
|
if (debugging)
|
|
debug_output ("Could not load editor DLL '%s', error code is %08lx\n", path, err) ;
|
|
if (!errorOK)
|
|
{
|
|
#ifdef _DEBUG
|
|
sprintf (str,
|
|
"Editor DLL initialisation failed [LoadLibrary failed, code is %08lx]\n\n"
|
|
"Debug build: if you have renamed cmedit as cmeditd, keep in mind that it "
|
|
"will still look for povcmax.dll, not povcmaxd.dll. Also, for debug builds "
|
|
"the build output directory is checked for the DLL's before the install dir.\n\n"
|
|
"Check the README in the source for instructions on how to copy the DLL's from "
|
|
"the official distribution to the naming convention used by debug builds.",
|
|
err) ;
|
|
PovMessageBox (str, "POV-Ray Editor error") ;
|
|
PovMessageBox ("See the 'Internal Editor Reference' section in the help file for\n"
|
|
"instructions on how to correct this or turn editor loading off.", "Important!") ;
|
|
#else
|
|
if (MessageBox (main_window,
|
|
"POV-Ray could not load its internal editor. This is to be expected "
|
|
"if you installed the AGPL-licenced distribution, as the editor DLL "
|
|
"is not included. If you do not wish to use the editor you can turn "
|
|
"it off (and stop this message appearing) by unchecking 'Use Editor' "
|
|
"under the 'Other Settings' sub-menu of the Options menu.\n\n"
|
|
"If you wish to enable the editor, clicking 'Yes' below will take "
|
|
"you to its download page.",
|
|
"Could not load internal editor - download it?",
|
|
MB_ICONQUESTION | MB_YESNO) == IDYES)
|
|
ShellExecute (NULL, NULL, "http://www.povray.org/download/wineditdll/" POV_RAY_VERSION COMPILER_VER "." PVENGINE_VER, NULL, NULL, SW_SHOWNORMAL) ;
|
|
#endif
|
|
}
|
|
return (false) ;
|
|
}
|
|
|
|
GetDLLVersion = (DWORD (*) (void)) GetProcAddress (hLibPovEdit, "GetDLLVersion") ;
|
|
if (GetDLLVersion == NULL)
|
|
{
|
|
if (debugging)
|
|
debug_output ("Could not resolve GetDLLVersion, error code is %08lx\n", GetLastError ()) ;
|
|
if (!errorOK)
|
|
PovMessageBox ("Editor DLL initialization failed [could not resolve GetDLLVersion]\n\n"
|
|
"See the 'Built-In Editors' section in the help file",
|
|
"POV-Ray Editor Error") ;
|
|
return (false) ;
|
|
}
|
|
if ((DllVersion = GetDLLVersion ()) != EDITDLLVERSION)
|
|
{
|
|
sprintf (str, "ERROR : Wrong editor DLL version [expected %04x, got %04x].", EDITDLLVERSION, DllVersion) ;
|
|
if (debugging)
|
|
debug_output ("%s\n", str) ;
|
|
if (!errorOK)
|
|
{
|
|
MessageBox (NULL, str, "POV-Ray Editor Error", MB_ICONSTOP) ;
|
|
PovMessageBox ("Editor switched off.\n\nSee the 'Built-In Editors' section in the help file", "Important!") ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
for (s = FunctionNames, f = FunctionPtrs ; *s ; s++, f++)
|
|
{
|
|
**f = (void *) GetProcAddress (hLibPovEdit, *s) ;
|
|
if (**f == NULL)
|
|
{
|
|
if (debugging)
|
|
debug_output ("Could not get address of '%s', error code is %08lx\n", *s, GetLastError ()) ;
|
|
if (!errorOK)
|
|
{
|
|
sprintf (str, "Editor DLL initialization failed:\nCould not resolve %s.", *s) ;
|
|
PovMessageBox (str, "Editor Error") ;
|
|
PovMessageBox ("See the 'Built-In Editors' section in the help file", "Important!") ;
|
|
}
|
|
return (false) ;
|
|
}
|
|
}
|
|
if (debugging)
|
|
debug_output ("Loaded editor DLL '%s'\n", path) ;
|
|
return (true) ;
|
|
}
|
|
|
|
char *Get_Reserved_Words (const char *additional_words)
|
|
{
|
|
int length = 0 ;
|
|
int i ;
|
|
|
|
for (i = 0; i < LAST_TOKEN; i++)
|
|
{
|
|
if (!isalpha (Reserved_Words [i].Token_Name [0]))
|
|
continue ;
|
|
if (strchr (Reserved_Words [i].Token_Name, ' ') != NULL)
|
|
continue ;
|
|
length += (int)strlen (Reserved_Words[i].Token_Name) + 1 ;
|
|
}
|
|
|
|
length += (int)strlen (additional_words) + 2;
|
|
|
|
char *result = (char *) malloc (++length) ;
|
|
strcpy (result, additional_words) ;
|
|
strcat (result, "#\n");
|
|
char *s = result + strlen (additional_words) + 2;
|
|
|
|
for (i = 0 ; i < LAST_TOKEN ; i++)
|
|
{
|
|
if (!isalpha (Reserved_Words [i].Token_Name [0]))
|
|
continue ;
|
|
if (strchr (Reserved_Words [i].Token_Name, ' ') != NULL)
|
|
continue ;
|
|
s += sprintf (s, "%s\n", Reserved_Words[i].Token_Name) ;
|
|
}
|
|
*--s = '\0' ;
|
|
|
|
return (result) ;
|
|
}
|
|
|
|
char *Get_INI_Keywords(void)
|
|
{
|
|
int length = 0 ;
|
|
|
|
for (struct pov_base::ProcessOptions::INI_Parser_Table *op = pov_frontend::RenderOptions_INI_Table; op->keyword != NULL; op++)
|
|
length += strlen(op->keyword) + 1;
|
|
char *result = (char *) malloc (++length) ;
|
|
char *s = result;
|
|
for (struct pov_base::ProcessOptions::INI_Parser_Table *op = pov_frontend::RenderOptions_INI_Table; op->keyword != NULL; op++)
|
|
s += sprintf (s, "%s\n", op->keyword) ;
|
|
*--s = '\0' ;
|
|
return (result) ;
|
|
}
|
|
|
|
char *Get_User_Keywords(const char *DocumentsPath)
|
|
{
|
|
char str[_MAX_PATH];
|
|
char *s;
|
|
FILE *f;
|
|
string result;
|
|
|
|
sprintf(str, "%sini\\user-keywords.txt", DocumentsPath);
|
|
if ((f = fopen(str, "rt")) == NULL)
|
|
return _strdup("");
|
|
while (fgets(str, sizeof (str), f) != NULL)
|
|
{
|
|
s = clean(str);
|
|
if (*s != '\0' && *s != '#')
|
|
{
|
|
// don't allow any words with spaces
|
|
if (strchr(s, ' ') != NULL)
|
|
continue;
|
|
result += s;
|
|
result += '\n';
|
|
}
|
|
}
|
|
fclose (f) ;
|
|
return _strdup(result.c_str());
|
|
}
|
|
|
|
HWND InitialiseEditor (HWND ParentWindow, HWND StatusWindow, const char *BinariesPath, const char *DocumentsPath)
|
|
{
|
|
HWND hwnd ;
|
|
|
|
if (!editors_enabled || !use_editors)
|
|
return (NULL) ;
|
|
|
|
char *s1 = Get_User_Keywords(DocumentsPath);
|
|
char *s2 = Get_Reserved_Words(s1) ;
|
|
char *s3 = Get_INI_Keywords() ;
|
|
EditSetKeywords (s2, s3) ;
|
|
free(s1) ;
|
|
free(s2);
|
|
free(s3);
|
|
if ((hwnd = CreateTabWindow (ParentWindow, StatusWindow, BinariesPath, DocumentsPath)) == NULL)
|
|
{
|
|
PovMessageBox ("TabWindow error: see the 'Built-In Editors' section in the help file", "Important!") ;
|
|
return (NULL) ;
|
|
}
|
|
return (hwnd) ;
|
|
}
|
|
|
|
void SetEditorPosition (int x, int y, int w, int h)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
SetWindowPosition (x, y, w, h) ;
|
|
}
|
|
|
|
void EditSetMessageWindow (HWND MessageWindow)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
SetMessageWindow (MessageWindow) ;
|
|
}
|
|
|
|
void EditRestoreState (int RestoreFiles)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
RestoreState (RestoreFiles) ;
|
|
}
|
|
|
|
void EditSaveState (void)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
SaveState () ;
|
|
}
|
|
|
|
bool EditSelectFile (char *FileName)
|
|
{
|
|
if (!use_editors)
|
|
return (false) ;
|
|
return (SelectFile (FileName)) ;
|
|
}
|
|
|
|
bool EditBrowseFile (bool CreateNewWindow)
|
|
{
|
|
if (!use_editors)
|
|
return (false) ;
|
|
return (BrowseFile (CreateNewWindow)) ;
|
|
}
|
|
|
|
// NULL means create a new, untitled, editor window.
|
|
bool EditOpenFile (char *FileName)
|
|
{
|
|
if (!use_editors)
|
|
return (false) ;
|
|
return (LoadFile (FileName)) ;
|
|
}
|
|
|
|
// NULL means currently selected file
|
|
bool EditCloseFile (char *FileName)
|
|
{
|
|
if (!use_editors)
|
|
return (false) ;
|
|
return (CloseFile (FileName)) ;
|
|
}
|
|
|
|
// NULL means currently selected file
|
|
bool EditSaveFile (char *FileName)
|
|
{
|
|
if (!use_editors)
|
|
return (false) ;
|
|
return (SaveFile (FileName)) ;
|
|
}
|
|
|
|
bool EditExternalOpenFile (char *ParamString)
|
|
{
|
|
if (!use_editors)
|
|
return (false) ;
|
|
return (ExternalLoadFile (ParamString)) ;
|
|
}
|
|
|
|
DWORD EditGetTab (void)
|
|
{
|
|
if (!use_editors)
|
|
return (0) ;
|
|
return (GetTab ()) ;
|
|
}
|
|
|
|
DWORD EditGetFlags (void)
|
|
{
|
|
if (!use_editors)
|
|
return (EDIT_MSG_SELECTED) ;
|
|
return (GetFlags ()) ;
|
|
}
|
|
|
|
char *EditGetFilename (bool IncludeModifiedIndicator)
|
|
{
|
|
char *s;
|
|
static char str [_MAX_PATH + 2] ;
|
|
|
|
if (!use_editors)
|
|
return (NULL) ;
|
|
s = GetFilename();
|
|
if (IncludeModifiedIndicator == false || s == NULL || *s == '\0')
|
|
return s;
|
|
if ((GetFlags() & EDIT_CURRENT_MODIFIED) == 0)
|
|
return s;
|
|
strcpy(str, s);
|
|
strcat(str, "*");
|
|
return str;
|
|
}
|
|
|
|
void EditNextTab (bool Forward)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
NextTab (Forward) ;
|
|
}
|
|
|
|
bool EditCanClose (bool AllFiles)
|
|
{
|
|
if (!use_editors)
|
|
return (true) ;
|
|
return (CanClose (AllFiles)) ;
|
|
}
|
|
|
|
bool EditSaveModified (char *FileName)
|
|
{
|
|
if (!use_editors)
|
|
return (true) ;
|
|
return (SaveModified (FileName)) ;
|
|
}
|
|
|
|
bool EditShowMessages (bool on)
|
|
{
|
|
// return true if the caller should show the message window themselves
|
|
if (!use_editors)
|
|
return (true) ;
|
|
return (ShowMessages (on)) ;
|
|
}
|
|
|
|
void EditDispatchMenuId (DWORD id)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
DispatchMenuId (id) ;
|
|
}
|
|
|
|
void EditUpdateMenus (HMENU MenuHandle)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
UpdateMenus (MenuHandle) ;
|
|
}
|
|
|
|
void EditSetFocus (void)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
SetTabFocus () ;
|
|
}
|
|
|
|
HMENU EditGetMenu (int which)
|
|
{
|
|
if (!use_editors)
|
|
return (NULL) ;
|
|
return (GetMenuHandle (which)) ;
|
|
}
|
|
|
|
void EditSetNotifyBase (HWND WindowHandle, int MessageBase)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
SetNotifyBase (WindowHandle, MessageBase) ;
|
|
}
|
|
|
|
void EditContextHelp (void)
|
|
{
|
|
if (!use_editors)
|
|
return ;
|
|
GetContextHelp () ;
|
|
}
|
|
|
|
bool EditShowParseError (const char *FileName, const char *Message, int Line, int Col)
|
|
{
|
|
if (!use_editors)
|
|
return (false) ;
|
|
return (ShowParseError (FileName, Message, Line, Col)) ;
|
|
}
|
|
|
|
bool EditPassOnMessage (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, DWORD *rVal)
|
|
{
|
|
if (!use_editors)
|
|
return (false) ;
|
|
return (PassOnMessage (hwnd, message, wParam, lParam, rVal)) ;
|
|
}
|
|
|
|
void EditUnload (void)
|
|
{
|
|
}
|
|
|
|
bool EditEnabled (void)
|
|
{
|
|
return (use_editors) ;
|
|
}
|
|
|
|
void EditSetState (bool on)
|
|
{
|
|
use_editors = on ;
|
|
}
|
|
|
|
void EditSetKeywords (LPCSTR SDLKeywordList, LPCSTR INIKeywordList)
|
|
{
|
|
SetKeywords (SDLKeywordList, INIKeywordList) ;
|
|
}
|
|
|
|
const char **EditGetWindowList (void)
|
|
{
|
|
if (!use_editors)
|
|
return NULL;
|
|
return GetWindowList();
|
|
}
|
|
|
|
}
|