summaryrefslogtreecommitdiff
path: root/win/System.cpp
diff options
context:
space:
mode:
authordocwhat1999-11-14 06:43:18 +0000
committerdocwhat1999-11-14 06:43:18 +0000
commitd71eec8062e852e56f03102ba4b4e87dc485821d (patch)
tree452368ad0e7e24627e517a0c88c2508d02cea6dc /win/System.cpp
parent2046090b7ce8dd901ce43e650be5acf44016d714 (diff)
Initial revision
git-svn-id: http://svn.leocad.org/trunk@2 c7d43263-9d01-0410-8a33-9dba5d9f93d6
Diffstat (limited to 'win/System.cpp')
-rw-r--r--win/System.cpp1608
1 files changed, 1608 insertions, 0 deletions
diff --git a/win/System.cpp b/win/System.cpp
new file mode 100644
index 0000000..a5b63b1
--- /dev/null
+++ b/win/System.cpp
@@ -0,0 +1,1608 @@
+// System user interface.
+//
+
+#include "stdafx.h"
+#include <dlgs.h>
+#include <direct.h>
+#include "leocad.h"
+#include "bmpmenu.h"
+#include "system.h"
+#include "defines.h"
+#include "camera.h"
+#include "tools.h"
+#include "file.h"
+#include "image.h"
+#include "PieceBar.h"
+#include "PropsSht.h"
+#include "PrefSht.h"
+#include "arraydlg.h"
+#include "imagedlg.h"
+#include "groupdlg.h"
+#include "figdlg.h"
+#include "seldlg.h"
+#include "htmldlg.h"
+#include "stepdlg.h"
+#include "povdlg.h"
+#include "terrdlg.h"
+#include "LibDlg.h"
+#include "EdGrpDlg.h"
+#include "AboutDlg.h"
+
+static CMenu menuPopups;
+static CStepDlg* StepModeless = NULL;
+static UINT ClipboardFormat = 0;
+
+/////////////////////////////////////////////////////////////////////////////
+// Static functions
+
+static void ShowLastError()
+{
+ LPVOID lpMsgBuf;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf, 0, NULL);
+
+ MessageBox( NULL, (char*)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
+ LocalFree( lpMsgBuf );
+}
+
+/*
+typedef void (APIENTRY * GLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (APIENTRY * GLUNLOCKARRAYSEXTPROC) ();
+
+// Compiled vertex array function pointers.
+static GLLOCKARRAYSEXTPROC glLockArraysEXT;
+static GLUNLOCKARRAYSEXTPROC glUnlockArraysEXT;
+
+char* extensions = (char*)glGetString(GL_EXTENSIONS);
+if (strstr(extensions, "GL_EXT_compiled_vertex_array") != NULL)
+{
+ glLockArraysEXT = (GLLOCKARRAYSEXTPROC)wglGetProcAddress("glLockArraysEXT");
+ glUnlockArraysEXT = (GLUNLOCKARRAYSEXTPROC)wglGetProcAddress("glUnlockArraysEXT");
+}
+*/
+
+static CMenu* GetMainMenu(int nIndex)
+{
+ CWnd* pFrame = AfxGetMainWnd();
+ if (pFrame == NULL)
+ return NULL;
+ CMenu* pMenu = pFrame->GetMenu();
+ return pMenu->GetSubMenu(nIndex);
+}
+
+UINT APIENTRY OFNOpenHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uiMsg)
+ {
+/*
+ case WM_HELP:
+ {
+ LPHELPINFO lphi = (LPHELPINFO)lParam;
+ if (lphi->iContextType == HELPINFO_WINDOW) // must be for a control
+ WinHelp ((HWND)lphi->hItemHandle, AfxGetApp()->m_pszHelpFilePath, HELP_WM_HELP, (DWORD)(LPVOID)HelpIDs);
+ return TRUE;
+ } break;
+
+ case WM_CONTEXTMENU:
+ {
+ WinHelp ((HWND)wParam, AfxGetApp()->m_pszHelpFilePath, HELP_CONTEXTMENU, (DWORD)(LPVOID)HelpIDs);
+ return TRUE;
+ } break;
+
+*/
+ case WM_INITDIALOG:
+ {
+ RECT rc1, rc2;
+ HWND h = GetParent(hdlg);
+ GetWindowRect(GetDlgItem(h, lst1), &rc1);
+ ScreenToClient(h, (LPPOINT)&rc1);
+ ScreenToClient(h, ((LPPOINT)&rc1)+1);
+ GetWindowRect(hdlg, &rc2);
+ SetWindowPos(hdlg, NULL, 0, 0, 122 + rc1.left, rc2.bottom - rc2.top, SWP_NOMOVE);
+ HBITMAP hbm = CreateColorBitmap(120, 100, GetSysColor(COLOR_BTNFACE));
+ SendDlgItemMessage(hdlg, IDC_OPENDLG_PREVIEW, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm);
+ GetWindowRect(GetDlgItem(hdlg, IDC_OPENDLG_PREVIEW), &rc1);
+ GetWindowRect(GetDlgItem(hdlg, IDC_OPENDLG_TEXT), &rc2);
+ SetWindowPos(GetDlgItem(hdlg, IDC_OPENDLG_TEXT), NULL, 0, 0, rc1.right - rc1.left, rc2.bottom - rc2.top, SWP_NOMOVE);
+ } break;
+
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pnmh = (LPNMHDR) lParam;
+ if (pnmh->code == CDN_FILEOK)
+ {
+// HBITMAP hbmold = (HBITMAP)SendDlgItemMessage(hdlg, IDC_OPENDLG_BITMAP, STM_GETIMAGE, IMAGE_BITMAP, 0);
+// if (hbmold)
+// DeleteObject(hbmold);
+
+ // This avoids an assert
+ _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
+ pThreadState->m_pAlternateWndInit = NULL;
+ return FALSE;
+ }
+
+ if (pnmh->code == CDN_SELCHANGE)
+ {
+ char filename[_MAX_PATH];
+ SendMessage(GetParent(hdlg), CDM_GETFILEPATH, _MAX_PATH, (LPARAM)filename);
+ HBITMAP hbm = NULL;
+ char *p = strrchr(filename, '.');
+
+ if ((p && (_stricmp (p+1, "lcd"))) ||
+ ((GetFileAttributes(filename) & FILE_ATTRIBUTE_DIRECTORY)))
+ {
+ hbm = CreateColorBitmap (120, 100, GetSysColor (COLOR_BTNFACE));
+ HBITMAP hbmold = (HBITMAP)SendDlgItemMessage(hdlg, IDC_OPENDLG_PREVIEW, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm);
+ if (hbmold)
+ DeleteObject(hbmold);
+ return FALSE;
+ }
+
+ float fv;
+ char id[32];
+ File file(false);
+ file.Open(filename, "rb");
+ file.Read(id, 32);
+ sscanf(strchr(id, ' '), "%f", &fv);
+
+ if (fv > 0.4f)
+ {
+ file.Read(&fv, 4);
+
+ if (fv > 0.7f)
+ {
+ unsigned long dwPosition;
+ file.Seek(-4, SEEK_END);
+ file.Read(&dwPosition, 4);
+ file.Seek(dwPosition, SEEK_SET);
+
+ if (dwPosition != 0)
+ {
+ if (fv < 1.0f)
+ {
+ BITMAPFILEHEADER bmfHeader;
+ file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader));
+ DWORD nPackedDIBLen = sizeof(BITMAPINFOHEADER) + 36000;
+ HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen);
+ file.Read((LPSTR)hDIB, nPackedDIBLen);
+ BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB;
+ BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB;
+ int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed : 1 << bmiHeader.biBitCount;
+ LPVOID lpDIBBits;
+ if (bmInfo.bmiHeader.biBitCount > 8)
+ lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) +
+ ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
+ else
+ lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
+
+ CClientDC dc(NULL);
+ hbm = CreateDIBitmap(dc.m_hDC, &bmiHeader, CBM_INIT, lpDIBBits, &bmInfo, DIB_RGB_COLORS);
+ ::GlobalFree(hDIB);
+ }
+ else
+ {
+ LC_IMAGE* image = OpenImage(&file, LC_IMAGE_GIF);
+
+ HWND hwndDesktop = GetDesktopWindow();
+ HDC hdcDesktop = GetDC(hwndDesktop);
+ HDC hdcMem = CreateCompatibleDC(hdcDesktop);
+ hbm = CreateCompatibleBitmap(hdcDesktop, 120, 100);
+ HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hbm);
+
+ for (int y = 0; y < 100; y++)
+ for (int x = 0; x < 120; x++)
+ {
+ unsigned char* b = (unsigned char*)image->bits + (y*120+x)*3;
+ SetPixelV(hdcMem, x, y, RGB(b[0], b[1], b[2]));
+ }
+
+ // Clean up
+ SelectObject(hdcMem, hbmOld);
+ DeleteDC(hdcMem);
+ ReleaseDC(hwndDesktop, hdcDesktop);
+
+ free(image);
+ }
+ }
+ }
+ }
+ file.Close();
+
+ if (!hbm)
+ hbm = CreateColorBitmap (120, 100, GetSysColor(COLOR_BTNFACE));
+
+ HBITMAP hbmold = (HBITMAP)SendDlgItemMessage(hdlg, IDC_OPENDLG_PREVIEW, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm);
+ if (hbmold)
+ DeleteObject(hbmold);
+
+ InvalidateRect(GetDlgItem(hdlg, IDC_OPENDLG_PREVIEW), NULL, TRUE);
+ }
+ } break;
+
+ case WM_DESTROY:
+ {
+ HBITMAP hbmold = (HBITMAP)SendDlgItemMessage(hdlg, IDC_OPENDLG_PREVIEW, STM_GETIMAGE, IMAGE_BITMAP, 0);
+ if (hbmold)
+ DeleteObject(hbmold);
+ } break;
+ }
+
+ return FALSE;
+}
+
+static UINT APIENTRY OFNSaveHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uiMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ int i = theApp.GetProfileInt ("Default", "Save Preview", 0);
+ if (i != 0)
+ CheckDlgButton(hdlg, IDC_SAVEDLG_PREVIEW, BST_CHECKED);
+ }
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pnmh = (LPNMHDR) lParam;
+ if (pnmh->code == CDN_FILEOK)
+ {
+ int i = 0;
+ if (IsDlgButtonChecked(hdlg, IDC_SAVEDLG_PREVIEW))
+ i = 1;
+ theApp.WriteProfileInt ("Default", "Save Preview", i);
+
+ // This avoids an assert
+ _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
+ pThreadState->m_pAlternateWndInit = NULL;
+ return FALSE;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static UINT APIENTRY OFNSavePictureHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uiMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ OPENFILENAME* ofn = (OPENFILENAME*)lParam;
+ SetWindowLong(hdlg, GWL_USERDATA, ofn->lCustData);
+ } break;
+
+ case WM_COMMAND:
+ {
+ if (wParam == IDC_SAVEPICTURE_OPTIONS)
+ {
+ LC_IMAGEDLG_OPTS* opts = (LC_IMAGEDLG_OPTS*)GetWindowLong(hdlg, GWL_USERDATA);
+ CImageDlg dlg(FALSE, opts);
+ dlg.DoModal();
+ }
+ } break;
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pnmh = (LPNMHDR) lParam;
+ if (pnmh->code == CDN_FILEOK)
+ {
+ // This avoids an assert
+ _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
+ pThreadState->m_pAlternateWndInit = NULL;
+ return FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Wait cursor
+
+static int g_nWaitCursorCount; // for wait cursor (>0 => waiting)
+static HCURSOR g_hcurWaitCursorRestore; // old cursor to restore after wait cursor
+
+// 0 => restore, 1=> begin, -1=> end
+void SystemDoWaitCursor(int nCode)
+{
+ g_nWaitCursorCount += nCode;
+ if (g_nWaitCursorCount > 0)
+ {
+ HCURSOR hcurWait = ::LoadCursor(NULL, IDC_WAIT);
+ HCURSOR hcurPrev = ::SetCursor(hcurWait);
+ if (nCode > 0 && g_nWaitCursorCount == 1)
+ g_hcurWaitCursorRestore = hcurPrev;
+ }
+ else
+ {
+ // turn everything off
+ g_nWaitCursorCount = 0; // prevent underflow
+ ::SetCursor(g_hcurWaitCursorRestore);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Profile Access
+
+// returns the store value or default
+int SystemGetProfileInt(const char* section, const char* entry, const int defaultvalue)
+{
+ return theApp.GetProfileInt(section, entry, defaultvalue);
+}
+
+// returns true if successful
+bool SystemSetProfileInt(const char* section, const char* entry, const int value)
+{
+ return theApp.WriteProfileInt(section, entry, value) ? true : false;
+}
+
+const char* SystemGetProfileString(const char* section, const char* entry, const char* defaultvalue)
+{
+ static CString str;
+ str = theApp.GetProfileString(section, entry, defaultvalue);
+ return (LPCSTR)str;
+}
+
+bool SystemSetProfileString(const char* section, const char* entry, const char* value)
+{
+ return theApp.WriteProfileString(section, entry, value) ? true : false;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// User Interface
+
+static HBITMAP hbmMenuDot;
+static const BYTE rgbDot[] =
+ { 0x6, 0xF, 0xF, 0xF, 0x6 }; // simple byte bitmap, 1=> bit on
+#define DOT_WIDTH 4
+#define DOT_HEIGHT 5
+
+void SystemFinish()
+{
+ DeleteObject(hbmMenuDot);
+}
+
+void SystemInit()
+{
+ ClipboardFormat = RegisterClipboardFormat(_T("LeoCAD_Data"));
+
+ // initialize wait cursor state
+ g_nWaitCursorCount = 0;
+ g_hcurWaitCursorRestore = NULL;
+
+ menuPopups.LoadMenu(IDR_POPUPS);
+
+ // attempt to load special bitmap, else default to arrow
+ CSize size = GetMenuCheckMarkDimensions();
+ ASSERT(size.cx > 4 && size.cy > 5); // not too small please
+ if (size.cx > 32)
+ size.cx = 32;
+ int iwRow = (size.cx + 15) >> 4; // # of WORDs per raster line
+ int nShift = (size.cx - DOT_WIDTH) / 2; // # of bits to shift over
+ nShift += ((iwRow * 16) - size.cx); // padding for word alignment
+ if (nShift > 16 - DOT_WIDTH)
+ nShift = 16 - DOT_WIDTH; // maximum shift for 1 word
+
+ if (size.cy > 32)
+ size.cy = 32;
+
+ // bitmap 2/4/4/4/2 pixels wide - centered (0 => black)
+ BYTE rgbBitmap[32 * 2 * sizeof(WORD)];
+ memset(rgbBitmap, 0xff, sizeof(rgbBitmap));
+
+ BYTE* pbOut = &rgbBitmap[iwRow * sizeof(WORD) *
+ ((size.cy - (DOT_HEIGHT+1)) >> 1)];
+ const BYTE* pbIn = rgbDot;
+ for (int y = 0; y < DOT_HEIGHT; y++)
+ {
+ WORD w = (WORD)~(((DWORD)*pbIn++) << nShift);
+ // bitmaps are always hi-lo
+ pbOut[0] = HIBYTE(w);
+ pbOut[1] = LOBYTE(w);
+ pbOut += iwRow * sizeof(WORD);
+ }
+
+ hbmMenuDot = CreateBitmap(size.cx, size.cy, 1, 1, (LPVOID)&rgbBitmap);
+ if (hbmMenuDot == NULL)
+ {
+ #define OBM_MNARROW 32739
+ hbmMenuDot = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_MNARROW));
+ }
+}
+
+// Viewport menu.
+void SystemUpdateViewport(int nNew, int nOld)
+{
+ CMenu* pMenu = GetMainMenu(3)->GetSubMenu(12);
+ pMenu->CheckMenuItem(nOld + ID_VIEWPORT01, MF_BYCOMMAND | MF_UNCHECKED);
+ pMenu->CheckMenuItem(nNew + ID_VIEWPORT01, MF_BYCOMMAND | MF_CHECKED);
+}
+
+// Action toolbar, popup menu and cursor.
+void SystemUpdateAction(int nNew, int nOld)
+{
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_TOOLS_BAR);
+ CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl();
+ CView* pView = pFrame->GetActiveView();
+
+ pCtrl->CheckButton(ID_ACTION_SELECT+nOld, FALSE);
+ pCtrl->CheckButton(ID_ACTION_SELECT+nNew, TRUE);
+
+ // TODO: make sure this works if loading a file from the cmd line.
+ if (pView)
+ pView->SendMessage(WM_LC_SET_CURSOR, nNew);
+
+ // TODO: update popup context menu
+ // TODO: disable lights if count > 8
+}
+
+// Current color in the listbox;
+void SystemUpdateColorList(int nNew)
+{
+ AfxGetMainWnd()->PostMessage (WM_LC_UPDATE_LIST, 0, nNew+1);
+}
+
+void SystemUpdateRenderingMode(bool bBackground, bool bFast)
+{
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR);
+ CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl();
+
+ if (bFast)
+ {
+ pCtrl->EnableButton(ID_RENDER_BACKGROUND, TRUE);
+ pCtrl->CheckButton(ID_RENDER_BACKGROUND, bBackground);
+ }
+ else
+ {
+ pCtrl->CheckButton(ID_RENDER_BACKGROUND, FALSE);
+ pCtrl->EnableButton(ID_RENDER_BACKGROUND, FALSE);
+ }
+
+ pCtrl->CheckButton(ID_RENDER_BOX, bFast);
+}
+
+void SystemUpdateUndoRedo(char* undo, char* redo)
+{
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR);
+ CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl();
+ CMenu* pMenu = GetMainMenu(1);
+ char txt[50];
+ UINT nState;
+
+ if (pMenu == NULL)
+ return;
+
+ strcpy(txt, "Undo ");
+ if (undo != NULL)
+ strcat(txt, undo);
+ strcat(txt, "\tCtrl+Z");
+
+ nState = pMenu->GetMenuState(ID_EDIT_UNDO, MF_BYCOMMAND);
+ nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR);
+ pMenu->ModifyMenu(ID_EDIT_UNDO, MF_BYCOMMAND |
+ MF_STRING | nState, ID_EDIT_UNDO, txt);
+
+ strcpy(txt, "Redo ");
+ if (redo != NULL)
+ strcat(txt, redo);
+ strcat(txt, "\tCtrl+Y");
+
+ nState = pMenu->GetMenuState(ID_EDIT_REDO, MF_BYCOMMAND);
+ nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR);
+ pMenu->ModifyMenu(ID_EDIT_REDO, MF_BYCOMMAND |
+ MF_STRING | nState, ID_EDIT_REDO, txt);
+
+ pMenu->EnableMenuItem(ID_EDIT_UNDO, MF_BYCOMMAND |
+ (undo ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_EDIT_REDO, MF_BYCOMMAND |
+ (redo ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+
+ pCtrl->EnableButton(ID_EDIT_UNDO, undo ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_EDIT_REDO, redo ? TRUE : FALSE);
+}
+
+// Snap menu & toolbar icon
+void SystemUpdateSnap(const unsigned long nSnap)
+{
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR);
+ CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl();
+ pCtrl->CheckButton(ID_SNAP_ANGLE, (nSnap & LC_DRAW_SNAP_A) != 0);
+
+ CMenu* pMenu = menuPopups.GetSubMenu(2);
+ pMenu->CheckMenuItem(ID_SNAP_SNAPX, MF_BYCOMMAND |
+ (nSnap & LC_DRAW_SNAP_X ? MF_CHECKED : MF_UNCHECKED));
+ pMenu->CheckMenuItem(ID_SNAP_SNAPY, MF_BYCOMMAND |
+ (nSnap & LC_DRAW_SNAP_Y ? MF_CHECKED : MF_UNCHECKED));
+ pMenu->CheckMenuItem(ID_SNAP_SNAPZ, MF_BYCOMMAND |
+ (nSnap & LC_DRAW_SNAP_Z ? MF_CHECKED : MF_UNCHECKED));
+
+ pMenu = menuPopups.GetSubMenu(8);
+ pMenu->CheckMenuItem(ID_LOCK_LOCKX, MF_BYCOMMAND |
+ (nSnap & LC_DRAW_LOCK_X ? MF_CHECKED : MF_UNCHECKED));
+ pMenu->CheckMenuItem(ID_LOCK_LOCKY, MF_BYCOMMAND |
+ (nSnap & LC_DRAW_LOCK_Y ? MF_CHECKED : MF_UNCHECKED));
+ pMenu->CheckMenuItem(ID_LOCK_LOCKZ, MF_BYCOMMAND |
+ (nSnap & LC_DRAW_LOCK_Z ? MF_CHECKED : MF_UNCHECKED));
+
+ SetMenuItemBitmaps(pMenu->m_hMenu, ID_LOCK_2BUTTONS, MF_BYCOMMAND, NULL, hbmMenuDot);
+ SetMenuItemBitmaps(pMenu->m_hMenu, ID_LOCK_3DMOVEMENT, MF_BYCOMMAND, NULL, hbmMenuDot);
+ pMenu->CheckMenuItem(ID_LOCK_2BUTTONS, MF_BYCOMMAND |
+ ((nSnap & LC_DRAW_3DMOUSE) == 0 ? MF_CHECKED : MF_UNCHECKED));
+ pMenu->CheckMenuItem(ID_LOCK_3DMOVEMENT, MF_BYCOMMAND |
+ (nSnap & LC_DRAW_3DMOUSE ? MF_CHECKED : MF_UNCHECKED));
+
+
+ // TODO: change Snap None & All (or maybe not ?)
+}
+
+void SystemUpdateSelected(unsigned long flags)
+{
+ CMenu* pMenu;
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR);
+ CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl();
+
+ // select all/none/invert/by name
+ pMenu = GetMainMenu(1);
+ if (flags & LC_SEL_NO_PIECES)
+ {
+ pMenu->EnableMenuItem(ID_EDIT_SELECTINVERT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ pMenu->EnableMenuItem(ID_EDIT_SELECTBYNAME, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ }
+ else
+ {
+ pMenu->EnableMenuItem(ID_EDIT_SELECTINVERT, MF_BYCOMMAND | MF_ENABLED);
+ pMenu->EnableMenuItem(ID_EDIT_SELECTBYNAME, MF_BYCOMMAND | MF_ENABLED);
+ }
+ pMenu->EnableMenuItem(ID_EDIT_SELECTNONE, MF_BYCOMMAND |
+ (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_EDIT_SELECTALL, MF_BYCOMMAND |
+ (flags & LC_SEL_UNSELECTED ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+
+ // cut, copy
+ pMenu->EnableMenuItem(ID_EDIT_CUT, MF_BYCOMMAND |
+ (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_EDIT_COPY, MF_BYCOMMAND |
+ (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pCtrl->EnableButton(ID_EDIT_CUT, flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_EDIT_COPY, flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? TRUE : FALSE);
+
+ // mirror/array, hide sel/unsel, unhideall
+ pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_TOOLS_BAR);
+ pCtrl = &pBar->GetToolBarCtrl();
+ pCtrl->EnableButton(ID_PIECE_ARRAY, flags & LC_SEL_PIECE ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_PIECE_MIRROR, flags & LC_SEL_PIECE ? TRUE : FALSE);
+ pMenu = GetMainMenu(2);
+ pMenu->EnableMenuItem(ID_PIECE_DELETE, MF_BYCOMMAND |
+ (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_COPYKEYS, MF_BYCOMMAND |
+ (flags & (LC_SEL_PIECE|LC_SEL_CAMERA|LC_SEL_LIGHT) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_ARRAY, MF_BYCOMMAND |
+ (flags & LC_SEL_PIECE ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_MIRROR, MF_BYCOMMAND |
+ (flags & LC_SEL_PIECE ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_UNHIDEALL, MF_BYCOMMAND |
+ (flags & LC_SEL_HIDDEN ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_HIDESELECTED, MF_BYCOMMAND |
+ (flags & LC_SEL_PIECE ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_HIDEUNSELECTED, MF_BYCOMMAND |
+ (flags & LC_SEL_UNSELECTED ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+
+ // group
+ pMenu->EnableMenuItem(ID_PIECE_GROUP, MF_BYCOMMAND |
+ (flags & LC_SEL_CANGROUP ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_UNGROUP, MF_BYCOMMAND |
+ (flags & LC_SEL_GROUP ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_ATTACH, MF_BYCOMMAND |
+ ((flags & (LC_SEL_GROUP|LC_SEL_FOCUSGROUP)) == (LC_SEL_GROUP) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_DETACH, MF_BYCOMMAND |
+ (flags & LC_SEL_FOCUSGROUP ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMenu->EnableMenuItem(ID_PIECE_EDITGROUPS, MF_BYCOMMAND |
+ ((flags & LC_SEL_NO_PIECES) == 0 ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+
+ pCtrl->EnableButton(ID_PIECE_PREVIOUS, flags & LC_SEL_PIECE ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_PIECE_NEXT, flags & LC_SEL_PIECE ? TRUE : FALSE);
+}
+
+// Changed current step/frame
+void SystemUpdateTime(bool bAnimation, int nTime, int nTotal)
+{
+ // Toolbar
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_ANIMATION_BAR);
+ CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl();
+
+ pCtrl->EnableButton(ID_VIEW_STEP_NEXT, nTime < nTotal ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_VIEW_STEP_PREVIOUS, nTime > 1 ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_VIEW_STEP_FIRST, nTime != 1 ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_VIEW_STEP_LAST, nTime != nTotal ? TRUE : FALSE);
+
+ // Main menu
+ CBMPMenu* pMainMenu = (CBMPMenu*)GetMainMenu(3)->GetSubMenu(14);
+
+ pMainMenu->EnableMenuItem(ID_VIEW_STEP_NEXT, MF_BYCOMMAND |
+ (nTime < nTotal ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMainMenu->EnableMenuItem(ID_VIEW_STEP_PREVIOUS, MF_BYCOMMAND |
+ (nTime > 1 ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMainMenu->EnableMenuItem(ID_VIEW_STEP_FIRST, MF_BYCOMMAND |
+ (nTime != 1 ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pMainMenu->EnableMenuItem(ID_VIEW_STEP_LAST, MF_BYCOMMAND |
+ (nTime != nTotal ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+
+ // Status bar
+ char szStep[11];
+ CStatusBar* pStatusBar = (CStatusBar*)pFrame->GetControlBar(AFX_IDW_STATUS_BAR);
+
+ if (bAnimation)
+ sprintf(szStep, "%i/%i", nTime, nTotal);
+ else
+ sprintf(szStep, " Step %i ", nTime);
+
+ pStatusBar->SetPaneText(pStatusBar->CommandToIndex(ID_INDICATOR_STEP), LPCSTR(szStep));
+
+ // Choose step dialog
+ if (StepModeless != NULL)
+ StepModeless->UpdateRange(nTime, nTotal);
+}
+
+void SystemUpdateMoveSnap(unsigned short nMoveSnap)
+{
+ // Status bar
+ char snap[11];
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CStatusBar* pStatusBar = (CStatusBar*)pFrame->GetControlBar(AFX_IDW_STATUS_BAR);
+
+ if (nMoveSnap)
+ wsprintf(snap, " Move x%i ", nMoveSnap);
+ else
+ strcpy (snap, " Move /2 ");
+
+ pStatusBar->SetPaneText(pStatusBar->CommandToIndex(ID_INDICATOR_SNAP), LPCSTR(snap));
+}
+
+void SystemUpdatePaste(bool enable)
+{
+ CMenu* pMenu = GetMainMenu(1);
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(AFX_IDW_TOOLBAR);
+ CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl();
+
+ pMenu->EnableMenuItem(ID_EDIT_PASTE, MF_BYCOMMAND |
+ (enable ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
+ pCtrl->EnableButton(ID_EDIT_PASTE, enable ? TRUE : FALSE);
+}
+
+void SystemUpdatePlay(bool play, bool stop)
+{
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_ANIMATION_BAR);
+ CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl();
+
+ pCtrl->EnableButton(ID_ANIMATOR_PLAY, play ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_ANIMATOR_STOP, stop ? TRUE : FALSE);
+}
+
+void SystemUpdateAnimation(bool bAnimation, bool bAddKeys)
+{
+ // Toolbar
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CToolBar* pBar = (CToolBar*)pFrame->GetControlBar(ID_VIEW_ANIMATION_BAR);
+ CToolBarCtrl* pCtrl = &pBar->GetToolBarCtrl();
+
+ pCtrl->CheckButton(ID_ANIMATOR_TOGGLE, bAnimation ? TRUE : FALSE);
+ pCtrl->CheckButton(ID_ANIMATOR_KEY, bAddKeys ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_ANIMATOR_PLAY, bAnimation ? TRUE : FALSE);
+ pCtrl->EnableButton(ID_ANIMATOR_STOP, FALSE);
+
+ // Menu
+ char* txt;
+ CMenu* pMenu = GetMainMenu(2);
+ UINT nState = pMenu->GetMenuState(ID_PIECE_COPYKEYS, MF_BYCOMMAND);
+ nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR);
+
+ if (bAnimation)
+ txt = "Copy Keys from Instructions";
+ else
+ txt = "Copy Keys from Animation";
+
+ pMenu->ModifyMenu(ID_PIECE_COPYKEYS, MF_BYCOMMAND |
+ MF_STRING | nState, ID_PIECE_COPYKEYS, txt);
+}
+
+void SystemUpdateCurrentCamera(Camera* pOld, Camera* pNew, Camera* pCamera)
+{
+ CBMPMenu* pMainMenu = (CBMPMenu*)GetMainMenu(3)->GetSubMenu(13);
+ CMenu* pPopupMenu = menuPopups.GetSubMenu(1)->GetSubMenu(3);
+ int i;
+
+ for (i = 0; pCamera; i++, pCamera = pCamera->m_pNext)
+ {
+ if (pOld == pCamera)
+ {
+ pPopupMenu->CheckMenuItem(i + ID_CAMERA_FIRST, MF_BYCOMMAND | MF_UNCHECKED);
+ pMainMenu->CheckMenuItem(i + ID_CAMERA_FIRST, MF_BYCOMMAND | MF_UNCHECKED);
+ }
+
+ if (pNew == pCamera)
+ {
+ pPopupMenu->CheckMenuItem(i + ID_CAMERA_FIRST, MF_BYCOMMAND | MF_CHECKED);
+ pMainMenu->CheckMenuItem(i + ID_CAMERA_FIRST, MF_BYCOMMAND | MF_CHECKED);
+ SetMenuItemBitmaps(pPopupMenu->m_hMenu, i + ID_CAMERA_FIRST, MF_BYCOMMAND, NULL, hbmMenuDot);
+ SetMenuItemBitmaps(pMainMenu->m_hMenu, i + ID_CAMERA_FIRST, MF_BYCOMMAND, NULL, hbmMenuDot);
+ }
+ }
+}
+
+// Update the list of cameras
+void SystemUpdateCameraMenu(Camera* pCamera)
+{
+ CBMPMenu* pMainMenu = (CBMPMenu*)GetMainMenu(3)->GetSubMenu(13);
+ CMenu* pPopupMenu = menuPopups.GetSubMenu(1)->GetSubMenu(3);
+ Camera* pFirst = pCamera;
+ char tmp[90];
+ const char* s = "FBTULRM";
+ int i;
+
+ while (pMainMenu->GetMenuItemCount())
+ pMainMenu->DeleteMenu(0, MF_BYPOSITION);
+ while (pPopupMenu->GetMenuItemCount())
+ pPopupMenu->DeleteMenu(0, MF_BYPOSITION);
+
+ for (i = 0; pCamera; i++, pCamera = pCamera->m_pNext)
+ if (i > 6)
+ {
+ pMainMenu->AppendODMenu(pCamera->GetName(), MF_ENABLED, i + ID_CAMERA_FIRST);
+ pPopupMenu->AppendMenu(MF_STRING, i + ID_CAMERA_FIRST, pCamera->GetName());
+ }
+
+ if (i > 7)
+ {
+ pMainMenu->AppendODMenu("", MF_SEPARATOR);
+ pPopupMenu->AppendMenu(MF_SEPARATOR);
+ }
+
+ pCamera = pFirst;
+ for (i = 0; pCamera && (i < 7); i++, pCamera = pCamera->m_pNext)
+ {
+ strcpy(tmp, pCamera->GetName());
+ strcat(tmp, "\t ");
+ tmp[strlen(tmp)-1] = s[i];
+
+ pMainMenu->AppendODMenu(tmp, MF_ENABLED, i + ID_CAMERA_FIRST);
+ pPopupMenu->AppendMenu(MF_STRING, i + ID_CAMERA_FIRST, tmp);
+ }
+
+ pMainMenu->AppendODMenu("", MF_SEPARATOR);
+ pPopupMenu->AppendMenu(MF_SEPARATOR);
+ pMainMenu->AppendODMenu("Reset", MF_ENABLED, ID_VIEW_CAMERAS_RESET);
+ pPopupMenu->AppendMenu(MF_STRING, ID_VIEW_CAMERAS_RESET, "Reset");
+// pMainMenu->AppendODMenu("Adjust...\t", MF_ENABLED, ID_VIEW_VIEWPOINT);
+// pPopupMenu->AppendODMenu("Adjust...\t", MF_ENABLED, ID_VIEW_VIEWPOINT);
+}
+
+extern UINT AFXAPI AfxGetFileTitle(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax);
+extern UINT AFXAPI AfxGetFileName(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax);
+
+/////////////////////////////////////////////////////////////////////////////
+// lpszCanon = C:\MYAPP\DEBUGS\C\TESWIN.C
+//
+// cchMax b Result
+// ------ - ---------
+// 1- 7 F <empty>
+// 1- 7 T TESWIN.C
+// 8-14 x TESWIN.C
+// 15-16 x C:\...\TESWIN.C
+// 17-23 x C:\...\C\TESWIN.C
+// 24-25 x C:\...\DEBUGS\C\TESWIN.C
+// 26+ x C:\MYAPP\DEBUGS\C\TESWIN.C
+
+#ifndef _MAC
+static void AbbreviateName(LPTSTR lpszCanon, int cchMax, BOOL bAtLeastName)
+{
+ int cchFullPath, cchFileName, cchVolName;
+ const TCHAR* lpszCur;
+ const TCHAR* lpszBase;
+ const TCHAR* lpszFileName;
+
+ lpszBase = lpszCanon;
+ cchFullPath = lstrlen(lpszCanon);
+
+ cchFileName = AfxGetFileName(lpszCanon, NULL, 0) - 1;
+ lpszFileName = lpszBase + (cchFullPath-cchFileName);
+
+ // If cchMax is more than enough to hold the full path name, we're done.
+ // This is probably a pretty common case, so we'll put it first.
+ if (cchMax >= cchFullPath)
+ return;
+
+ // If cchMax isn't enough to hold at least the basename, we're done
+ if (cchMax < cchFileName)
+ {
+ lstrcpy(lpszCanon, (bAtLeastName) ? lpszFileName : &afxChNil);
+ return;
+ }
+
+ // Calculate the length of the volume name. Normally, this is two characters
+ // (e.g., "C:", "D:", etc.), but for a UNC name, it could be more (e.g.,
+ // "\\server\share").
+ //
+ // If cchMax isn't enough to hold at least <volume_name>\...\<base_name>, the
+ // result is the base filename.
+
+ lpszCur = lpszBase + 2; // Skip "C:" or leading "\\"
+
+ if (lpszBase[0] == '\\' && lpszBase[1] == '\\') // UNC pathname
+ {
+ // First skip to the '\' between the server name and the share name,
+ while (*lpszCur != '\\')
+ {
+ lpszCur = _tcsinc(lpszCur);
+ ASSERT(*lpszCur != '\0');
+ }
+ }
+ // if a UNC get the share name, if a drive get at least one directory
+ ASSERT(*lpszCur == '\\');
+ // make sure there is another directory, not just c:\filename.ext
+ if (cchFullPath - cchFileName > 3)
+ {
+ lpszCur = _tcsinc(lpszCur);
+ while (*lpszCur != '\\')
+ {
+ lpszCur = _tcsinc(lpszCur);
+ ASSERT(*lpszCur != '\0');
+ }
+ }
+ ASSERT(*lpszCur == '\\');
+
+ cchVolName = lpszCur - lpszBase;
+ if (cchMax < cchVolName + 5 + cchFileName)
+ {
+ lstrcpy(lpszCanon, lpszFileName);
+ return;
+ }
+
+ // Now loop through the remaining directory components until something
+ // of the form <volume_name>\...\<one_or_more_dirs>\<base_name> fits.
+ //
+ // Assert that the whole filename doesn't fit -- this should have been
+ // handled earlier.
+
+ ASSERT(cchVolName + (int)lstrlen(lpszCur) > cchMax);
+ while (cchVolName + 4 + (int)lstrlen(lpszCur) > cchMax)
+ {
+ do
+ {
+ lpszCur = _tcsinc(lpszCur);
+ ASSERT(*lpszCur != '\0');
+ }
+ while (*lpszCur != '\\');
+ }
+
+ // Form the resultant string and we're done.
+ lpszCanon[cchVolName] = '\0';
+ lstrcat(lpszCanon, _T("\\..."));
+ lstrcat(lpszCanon, lpszCur);
+}
+#endif
+
+static BOOL GetDisplayName(char* filename, CString& strName, LPCTSTR lpszCurDir, int nCurDir, BOOL bAtLeastName)
+{
+ LPTSTR lpch = strName.GetBuffer(_MAX_PATH);
+#ifndef _MAC
+ lstrcpy(lpch, filename);
+ // nLenDir is the length of the directory part of the full path
+ int nLenDir = lstrlen(lpch) - (AfxGetFileName(lpch, NULL, 0) - 1);
+ BOOL bSameDir = FALSE;
+ if (nLenDir == nCurDir)
+ {
+ TCHAR chSave = lpch[nLenDir];
+ lpch[nCurDir] = 0; // terminate at same location as current dir
+ bSameDir = lstrcmpi(lpszCurDir, lpch) == 0;
+ lpch[nLenDir] = chSave;
+ }
+ // copy the full path, otherwise abbreviate the name
+ if (bSameDir)
+ {
+ // copy file name only since directories are same
+ char szTemp[_MAX_PATH];
+ AfxGetFileTitle(lpch+nCurDir, szTemp, sizeof(szTemp));
+ lstrcpyn(lpch, szTemp, _MAX_PATH);
+ }
+ else
+ {
+ // strip the extension if the system calls for it
+ char szTemp[_MAX_PATH];
+ AfxGetFileTitle(lpch+nLenDir, szTemp, sizeof(szTemp));
+ lstrcpyn(lpch+nLenDir, szTemp, _MAX_PATH-nLenDir);
+
+ // abbreviate name based on what will fit in limited space
+ AbbreviateName(lpch, 30, bAtLeastName);
+ }
+#else
+ // for Mac just show the file title name without path
+ AfxGetFileTitle(filename, lpch, _MAX_PATH);
+#endif
+ strName.ReleaseBuffer();
+ return TRUE;
+}
+
+void SystemUpdateRecentMenu(char names[4][LC_MAXPATH])
+{
+ CBMPMenu* pMenu = (CBMPMenu*)GetMainMenu(0);
+ UINT nState;
+
+ pMenu->DeleteMenu(ID_FILE_MRU_FILE2, MF_BYCOMMAND);
+ pMenu->DeleteMenu(ID_FILE_MRU_FILE3, MF_BYCOMMAND);
+ pMenu->DeleteMenu(ID_FILE_MRU_FILE4, MF_BYCOMMAND);
+
+ if (strlen(names[0]) == 0)
+ {
+ nState = pMenu->GetMenuState(ID_FILE_MRU_FILE1, MF_BYCOMMAND);
+ nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR);
+ pMenu->ModifyMenu(ID_FILE_MRU_FILE1, MF_BYCOMMAND |
+ MF_STRING | nState, ID_FILE_MRU_FILE1, "Recent File");
+ pMenu->EnableMenuItem(ID_FILE_MRU_FILE1, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ return;
+ }
+
+#ifndef _MAC
+ TCHAR szCurDir[_MAX_PATH];
+ GetCurrentDirectory(_MAX_PATH, szCurDir);
+ int nCurDir = lstrlen(szCurDir);
+ ASSERT(nCurDir >= 0);
+ szCurDir[nCurDir] = '\\';
+ szCurDir[++nCurDir] = '\0';
+#endif
+
+ CString strName;
+ CString strTemp;
+ for (int i = 0; i < 4; i++)
+ {
+ if (strlen(names[i]) == 0)
+ break;
+ if (!GetDisplayName(names[i], strName, szCurDir, nCurDir, TRUE))
+ break;
+
+ // double up any '&' characters so they are not underlined
+ LPCTSTR lpszSrc = strName;
+ LPTSTR lpszDest = strTemp.GetBuffer(strName.GetLength()*2);
+ while (*lpszSrc != 0)
+ {
+ if (*lpszSrc == '&')
+ *lpszDest++ = '&';
+ if (_istlead(*lpszSrc))
+ *lpszDest++ = *lpszSrc++;
+ *lpszDest++ = *lpszSrc++;
+ }
+ *lpszDest = 0;
+ strTemp.ReleaseBuffer();
+
+ // insert mnemonic + the file name
+ char buf[200];
+ sprintf(buf, "&%d %s", i+1, strTemp);
+
+ if (i != 0)
+ {
+ UINT x = pMenu->GetMenuItemCount() - 2;
+ pMenu->InsertMenu(x, MF_BYPOSITION|MF_STRING, ID_FILE_MRU_FILE1 + i, buf);
+ }
+ else
+ {
+ nState = pMenu->GetMenuState(ID_FILE_MRU_FILE1, MF_BYCOMMAND);
+ nState &= ~(MF_BITMAP|MF_OWNERDRAW|MF_SEPARATOR);
+ pMenu->ModifyMenu(ID_FILE_MRU_FILE1, MF_BYCOMMAND |
+ MF_STRING | nState, ID_FILE_MRU_FILE1 + i, buf);
+ pMenu->EnableMenuItem(ID_FILE_MRU_FILE1, MF_BYCOMMAND | MF_ENABLED);
+ }
+ }
+}
+
+// if x = -1, get cursor pos
+void SystemDoPopupMenu(int nMenu, int x, int y)
+{
+ CMenu* pPopup;
+ POINT pt;
+
+ if (x != -1)
+ {
+ pt.x = x;
+ pt.y = y;
+ }
+ else
+ GetCursorPos(&pt);
+
+ pPopup = menuPopups.GetSubMenu(nMenu);
+ pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, AfxGetMainWnd());
+}
+
+// Private MFC function only sets the title if it's different
+extern void AFXAPI AfxSetWindowText(HWND, LPCTSTR);
+
+void SystemSetWindowCaption(char* caption)
+{
+ AfxSetWindowText(AfxGetMainWnd()->m_hWnd, caption);
+}
+
+int SystemDoMessageBox(char* prompt, int nMode)
+{
+ return AfxMessageBox(prompt, nMode);
+}
+
+extern BOOL AFXAPI AfxFullPath(LPTSTR lpszPathOut, LPCTSTR lpszFileIn);
+
+bool SystemDoDialog(int nMode, void* param)
+{
+ switch (nMode)
+ {
+ case LC_DLG_FILE_OPEN:
+ {
+ char *defdir = (char*)param;
+ if (strlen(defdir))
+ _chdir(defdir);
+
+ CFileDialog dlg(TRUE, "*.lcd", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
+ "LeoCAD Projects (*.lcd)|*.lcd|LDraw Files (*.dat)|*.dat|All Files (*.*)|*.*||", AfxGetMainWnd());
+ dlg.m_ofn.Flags |= (OFN_ENABLETEMPLATE|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_ENABLEHOOK|OFN_EXPLORER);
+ dlg.m_ofn.hInstance = AfxGetInstanceHandle();
+ dlg.m_ofn.lpfnHook = OFNOpenHookProc;
+ dlg.m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OPENDLG_TEMPLATE);
+
+ if (dlg.DoModal() == IDOK)
+ {
+ char szFullPath[LC_MAXPATH];
+ AfxFullPath(szFullPath, dlg.GetPathName());
+ strcpy((char*)param, szFullPath);
+ return true;
+ }
+ } break;
+
+ case LC_DLG_FILE_SAVE:
+ {
+ CFileDialog dlg(FALSE, "*.lcd", (char*)param, OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE,
+ "LeoCAD Projects (*.lcd)|*.lcd|LDraw Files (*.dat)|*.dat|All Files (*.*)|*.*||");
+
+ dlg.m_ofn.lpfnHook = OFNSaveHookProc;
+ dlg.m_ofn.hInstance = AfxGetInstanceHandle();
+ dlg.m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SAVEDLG_TEMPLATE);
+
+ if (dlg.DoModal() == IDOK)
+ {
+ char szFullPath[LC_MAXPATH];
+ AfxFullPath(szFullPath, dlg.GetPathName());
+ strcpy((char*)param, szFullPath);
+ return true;
+ }
+ } break;
+
+ case LC_DLG_FILE_MERGE:
+ {
+ char *defdir = (char*)param;
+ if (strlen(defdir))
+ _chdir(defdir);
+
+ CFileDialog dlg(TRUE, "*.lcd", NULL, OFN_HIDEREADONLY|OFN_ENABLETEMPLATE|OFN_FILEMUSTEXIST|OFN_ENABLEHOOK|OFN_EXPLORER,
+ "LeoCAD Projects (*.lcd)|*.lcd|All Files (*.*)|*.*||", AfxGetMainWnd());
+
+ dlg.m_ofn.hInstance = AfxGetInstanceHandle();
+ dlg.m_ofn.lpfnHook = OFNOpenHookProc;
+ dlg.m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OPENDLG_TEMPLATE);
+ dlg.m_ofn.lpstrTitle = "Merge";
+
+ if (dlg.DoModal() == IDOK)
+ {
+ strcpy((char*)param, dlg.GetPathName());
+ return true;
+ }
+ } break;
+
+ case LC_DLG_PICTURE_SAVE:
+ {
+ CFileDialog dlg(FALSE, NULL, NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE|OFN_EXPLORER,
+ "GIF Files (*.gif)|*.gif|JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg|Bitmap Files (*.bmp)|*.bmp|AVI Files (*.avi)|*.avi|All Files (*.*)|*.*||");
+
+ DWORD dwImage = theApp.GetProfileInt ("Default", "Image Options", 1|LC_IMAGE_TRANSPARENT);
+ LC_IMAGEDLG_OPTS* opts = (LC_IMAGEDLG_OPTS*)param;
+ opts->width = theApp.GetProfileInt("Default", "Image Width", GetSystemMetrics(SM_CXSCREEN));
+ opts->height = theApp.GetProfileInt("Default", "Image Height", GetSystemMetrics(SM_CYSCREEN));
+ opts->imopts.quality = theApp.GetProfileInt("Default", "JPEG Quality", 70);
+ opts->imopts.interlaced = (dwImage & LC_IMAGE_PROGRESSIVE) != 0;
+ opts->imopts.transparent = (dwImage & LC_IMAGE_TRANSPARENT) != 0;
+ opts->imopts.truecolor = (dwImage & LC_IMAGE_HIGHCOLOR) != 0;
+ opts->imopts.pause = (float)theApp.GetProfileInt("Default", "AVI Pause", 100)/100;
+ opts->imopts.format = (unsigned char)(dwImage & ~(LC_IMAGE_MASK));
+
+ dlg.m_ofn.hInstance = AfxGetInstanceHandle();
+ dlg.m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SAVEPICTUREDLG_TEMPLATE);
+ dlg.m_ofn.lpfnHook = OFNSavePictureHookProc;
+ dlg.m_ofn.lCustData= (LONG)opts;
+
+ if (dlg.DoModal() == IDOK)
+ {
+ strcpy(opts->filename, (LPCSTR)dlg.GetPathName());
+ char ext[5];
+ if (strlen(opts->filename) == 0)
+ return false;
+ char *p = strrchr(opts->filename, '.');
+ if (p != NULL)
+ {
+ strcpy(ext, p+1);
+ strlwr(ext);
+
+ if ((strcmp(ext, "jpg") == 0) || (strcmp(ext, "jpeg") == 0) ||
+ (strcmp(ext, "bmp") == 0) || (strcmp(ext, "gif") == 0) ||
+ (strcmp(ext, "avi") == 0))
+ return true;
+ }
+ switch(opts->imopts.format)
+ {
+ case 0: strcat(opts->filename, ".bmp"); break;
+ case 1: strcat(opts->filename, ".gif"); break;
+ case 2: strcat(opts->filename, ".jpg"); break;
+ case 3: strcat(opts->filename, ".avi"); break;
+ }
+
+ return true;
+ }
+ } break;
+
+ case LC_DLG_HTML:
+ {
+ LC_HTMLDLG_OPTS* opts = (LC_HTMLDLG_OPTS*)param;
+ CHTMLDlg dlg(&opts->imdlg);
+
+ if (dlg.DoModal() == IDOK)
+ {
+ strcpy(opts->path, dlg.m_strFolder);
+ opts->singlepage = (dlg.m_nLayout == 0);
+ opts->index = dlg.m_bIndex == TRUE;
+ opts->images = dlg.m_bImages == TRUE;
+ opts->listend = dlg.m_bListEnd == TRUE;
+ opts->liststep = dlg.m_bListStep == TRUE;
+ opts->hilite = dlg.m_bHighlight == TRUE;
+ return true;
+ }
+ } break;
+
+ case LC_DLG_POVRAY:
+ {
+ CPOVDlg dlg;
+ if (dlg.DoModal() == IDOK)
+ {
+ LC_POVRAYDLG_OPTS* opts = (LC_POVRAYDLG_OPTS*)param;
+ opts->render = dlg.m_bRender != 0;
+ strcpy(opts->povpath, dlg.m_strPOV);
+ strcpy(opts->outpath, dlg.m_strOut);
+ strcpy(opts->libpath, dlg.m_strLGEO);
+
+ return true;
+ }
+ } break;
+
+ case LC_DLG_WAVEFRONT:
+ {
+ CFileDialog dlg(FALSE, "*.obj", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
+ "Wavefront Files (*.obj)|*.obj|All Files (*.*)|*.*||", AfxGetMainWnd());
+ if (dlg.DoModal() == IDOK)
+ {
+ strcpy((char*)param, dlg.GetPathName());
+ return true;
+ }
+ } break;
+
+ case LC_DLG_MINIFIG:
+ {
+ CMinifigDlg dlg(param);
+
+ if (dlg.DoModal() == IDOK)
+ return true;
+ } break;
+
+ case LC_DLG_ARRAY:
+ {
+ CArrayDlg dlg;
+ if (dlg.DoModal() == IDOK)
+ {
+ LC_ARRAYDLG_OPTS* opts = (LC_ARRAYDLG_OPTS*)param;
+
+ opts->n1DCount = dlg.m_n1DCount;
+ opts->n2DCount = dlg.m_n2DCount;
+ opts->n3DCount = dlg.m_n3DCount;
+ opts->f2D[0] = dlg.m_f2DX;
+ opts->f2D[1] = dlg.m_f2DY;
+ opts->f2D[2] = dlg.m_f2DZ;
+ opts->f3D[0] = dlg.m_f3DX;
+ opts->f3D[1] = dlg.m_f3DY;
+ opts->f3D[2] = dlg.m_f3DZ;
+ opts->fMove[0] = dlg.m_fMoveX;
+ opts->fMove[1] = dlg.m_fMoveY;
+ opts->fMove[2] = dlg.m_fMoveZ;
+ opts->fRotate[0] = dlg.m_fRotateX;
+ opts->fRotate[1] = dlg.m_fRotateY;
+ opts->fRotate[2] = dlg.m_fRotateZ;
+ opts->nArrayDimension = dlg.m_nArrayDimension;
+
+ return true;
+ }
+ } break;
+
+ case LC_DLG_PREFERENCES:
+ {
+ CPreferencesSheet ps;
+ LC_PREFERENCESDLG_OPTS* opts = (LC_PREFERENCESDLG_OPTS*)param;
+
+ ps.m_PageGeneral.SetOptions(opts->nSaveInterval, opts->nMouse, opts->strPath);
+ ps.m_PageDetail.SetOptions(opts->nDetail, opts->fLineWidth);
+ ps.m_PageDrawing.SetOptions(opts->nSnap, opts->nAngleSnap, opts->nGridSize);
+ ps.m_PageScene.SetOptions(opts->nScene, opts->fDensity, opts->strBackground, opts->fBackground, opts->fFog, opts->fAmbient, opts->fGrad1, opts->fGrad2);
+ ps.m_PagePrint.SetOptions(opts->strHeader, opts->strFooter);
+
+ if (ps.DoModal() == IDOK)
+ {
+ ps.m_PageGeneral.GetOptions(&opts->nSaveInterval, &opts->nMouse, opts->strPath);
+ ps.m_PageDetail.GetOptions(&opts->nDetail, &opts->fLineWidth);
+ ps.m_PageDrawing.GetOptions(&opts->nSnap, &opts->nAngleSnap, &opts->nGridSize);
+ ps.m_PageScene.GetOptions(&opts->nScene, &opts->fDensity, opts->strBackground, opts->fBackground, opts->fFog, opts->fAmbient, opts->fGrad1, opts->fGrad2);
+ ps.m_PagePrint.GetOptions(opts->strHeader, opts->strFooter);
+ AfxGetMainWnd()->PostMessage(WM_LC_UPDATE_SETTINGS);
+ AfxGetApp()->WriteProfileInt("Settings", "Autosave", opts->nSaveInterval);
+ AfxGetApp()->WriteProfileInt("Default", "Mouse", opts->nMouse);
+ AfxGetApp()->WriteProfileString("Default", "Projects", opts->strPath);
+
+ return true;
+ }
+ } break;
+
+ case LC_DLG_PROPERTIES:
+ {
+ CPropertiesSheet ps;
+ LC_PROPERTIESDLG_OPTS* opts = (LC_PROPERTIESDLG_OPTS*)param;
+
+ ps.SetTitle(opts->strTitle, PSH_PROPTITLE);
+ ps.m_PageSummary.m_strAuthor = opts->strAuthor;
+ ps.m_PageSummary.m_strDescription = opts->strDescription;
+ ps.m_PageSummary.m_strComments = opts->strComments;
+ ps.m_PageGeneral.m_strFilename = opts->strFilename;
+ ps.m_PagePieces.names = opts->names;
+ ps.m_PagePieces.count = opts->count;
+ ps.m_PagePieces.lines = opts->lines;
+
+ if (ps.DoModal() == IDOK)
+ {
+ strcpy(opts->strAuthor, ps.m_PageSummary.m_strAuthor);
+ strcpy(opts->strDescription, ps.m_PageSummary.m_strDescription);
+ strcpy(opts->strComments, ps.m_PageSummary.m_strComments);
+
+ return true;
+ }
+ } break;
+
+ case LC_DLG_TERRAIN:
+ {
+ CTerrainDlg dlg((Terrain*)param, false);
+ if (dlg.DoModal() == IDOK)
+ return true;
+ } break;
+
+ case LC_DLG_LIBRARY:
+ {
+ CLibraryDlg dlg;
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CPiecesBar* pBar = (CPiecesBar*)pFrame->GetControlBar(ID_VIEW_PIECES_BAR);
+
+ for (int i = 0; i < pBar->m_wndGroupsBar.m_ToolbarData.iButtons; i++)
+ {
+ strcpy (dlg.m_strGroups[i], pBar->m_GroupNames[i]);
+ dlg.m_nBitmaps[i] = pBar->m_wndGroupsBar.m_ToolbarData.ButtonData[i].iBitmap;
+ }
+ dlg.m_nMaxGroups = pBar->m_wndGroupsBar.m_ToolbarData.iButtons;
+ dlg.m_ImageList.Create(IDB_PIECEBAR, 16, 0, 0x00ff00ff);
+
+ if (dlg.DoModal() == IDOK)
+ {
+ pBar->CreateGroupsBar();
+ pBar->m_wndPiecesList.UpdateList();
+ RECT rc;
+ pBar->GetClientRect(&rc);
+ pBar->PostMessage(WM_SIZE, SIZE_RESTORED, MAKELPARAM(rc.right, rc.bottom));
+ }
+
+ return (dlg.m_bReload != FALSE);
+ } break;
+
+ case LC_DLG_SELECTBYNAME:
+ {
+ CSelectDlg dlg(param);
+ if (dlg.DoModal() == IDOK)
+ return true;
+ } break;
+
+ case LC_DLG_STEPCHOOSE:
+ {
+ if (StepModeless == NULL)
+ {
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CView* pView = pFrame->GetActiveView();
+ StepModeless = new CStepDlg(&StepModeless, pView);
+ StepModeless->Create(IDD_STEP, pView);
+
+ int t, l;
+ char buf[30];
+ strcpy (buf, theApp.GetProfileString("Settings", "Step Dialog"));
+ if (sscanf(buf, "%d, %d", &t, &l) == 2)
+ {
+ CRect rc;
+ StepModeless->GetWindowRect(&rc);
+ StepModeless->SetWindowPos(NULL,
+ min(l, GetSystemMetrics(SM_CXSCREEN)-rc.Width()),
+ min(t, GetSystemMetrics(SM_CYSCREEN)-rc.Height()),
+ 0, 0, SWP_NOZORDER|SWP_NOSIZE);
+ }
+ StepModeless->ShowWindow(SW_SHOW);
+ }
+ else
+ StepModeless->SetActiveWindow();
+ } break;
+
+ case LC_DLG_EDITGROUPS:
+ {
+ CEditGroupsDlg dlg((LC_GROUPEDITDLG_OPTS*)param);
+
+ if (dlg.DoModal() == IDOK)
+ return true;
+ } break;
+
+ case LC_DLG_GROUP:
+ {
+ CGroupDlg dlg;
+ dlg.m_strName = (char*)param;
+
+ if (dlg.DoModal() == IDOK)
+ {
+ strcpy((char*)param, dlg.m_strName);
+
+ return true;
+ }
+ } break;
+
+ case LC_DLG_ABOUT:
+ {
+ CAboutDlg dlg;
+ dlg.m_hViewDC = wglGetCurrentDC();
+ dlg.DoModal();
+ } break;
+ }
+
+ return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Memory rendering functions
+
+typedef struct
+{
+ HDC hdc;
+ HDC oldhdc;
+ HGLRC hrc;
+ HGLRC oldhrc;
+ HBITMAP hbm;
+ HBITMAP oldhbm;
+} LC_RENDER;
+
+void* SystemStartRender(int width, int height)
+{
+ LC_RENDER* render = (LC_RENDER*)malloc(sizeof(LC_RENDER));
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CView* pView = pFrame->GetActiveView();
+ CDC* pDC = pView->GetDC();
+ render->oldhdc = wglGetCurrentDC();
+ render->oldhrc = wglGetCurrentContext();
+ render->hdc = CreateCompatibleDC(pDC->m_hDC);
+
+ // Preparing bitmap header for DIB section
+ BITMAPINFO bi;
+ ZeroMemory(&bi, sizeof(BITMAPINFO));
+ bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bi.bmiHeader.biWidth = width;
+ bi.bmiHeader.biHeight = height;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 24;
+ bi.bmiHeader.biCompression = BI_RGB;
+ bi.bmiHeader.biSizeImage = width * height * 3;
+ bi.bmiHeader.biXPelsPerMeter = 2925;
+ bi.bmiHeader.biYPelsPerMeter = 2925;
+
+ // Creating a DIB surface
+ LPVOID lpBits;
+ render->hbm = CreateDIBSection(pDC->GetSafeHdc(), &bi, DIB_RGB_COLORS, (void**)&lpBits, NULL, (DWORD)0);
+ render->oldhbm = (HBITMAP)::SelectObject(render->hdc, render->hbm);
+
+ PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_BITMAP|PFD_SUPPORT_OPENGL,
+ PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,
+ 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 };
+
+ int pixelformat = ChoosePixelFormat(render->hdc, &pfd);
+ DescribePixelFormat(render->hdc, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+ SetPixelFormat(render->hdc, pixelformat, &pfd);
+ render->hrc = wglCreateContext(render->hdc);
+ wglMakeCurrent(render->hdc, render->hrc);
+
+ return render;
+}
+
+void SystemFinishRender(void* param)
+{
+ LC_RENDER* render = (LC_RENDER*)param;
+
+ wglMakeCurrent (render->oldhdc, render->oldhrc);
+ wglDeleteContext(render->hrc);
+ SelectObject(render->hdc, render->oldhbm);
+ DeleteObject(render->hbm);
+ DeleteDC(render->hdc);
+ free(render);
+}
+
+LC_IMAGE* SystemGetRenderImage(void* param)
+{
+ LC_RENDER* render = (LC_RENDER*)param;
+ HANDLE hdib;
+ HDC hdc;
+ BITMAP bitmap;
+ UINT wLineLen;
+ DWORD dwSize, wColSize;
+ LPBITMAPINFOHEADER lpbi;
+ LPBYTE lpBits;
+
+ glFinish();
+ GetObject(render->hbm, sizeof(BITMAP), &bitmap);
+
+ // DWORD align the width of the DIB
+ // Figure out the size of the colour table
+ // Calculate the size of the DIB
+ wLineLen = (bitmap.bmWidth*24+31)/32 * 4;
+ wColSize = sizeof(RGBQUAD)*((24 <= 8) ? 1 << 24 : 0);
+ dwSize = sizeof(BITMAPINFOHEADER) + wColSize +
+ (DWORD)(UINT)wLineLen*(DWORD)(UINT)bitmap.bmHeight;
+
+ // Allocate room for a DIB and set the LPBI fields
+ hdib = GlobalAlloc(GHND, dwSize);
+ if (!hdib)
+ return NULL;
+
+ lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
+ lpbi->biSize = sizeof(BITMAPINFOHEADER);
+ lpbi->biWidth = bitmap.bmWidth;
+ lpbi->biHeight = bitmap.bmHeight;
+ lpbi->biPlanes = 1;
+ lpbi->biBitCount = (WORD)24;
+ lpbi->biCompression = BI_RGB;
+ lpbi->biSizeImage = dwSize - sizeof(BITMAPINFOHEADER) - wColSize;
+ lpbi->biXPelsPerMeter = 0;
+ lpbi->biYPelsPerMeter = 0;
+ lpbi->biClrUsed = (24 <= 8) ? 1 << 24 : 0;
+ lpbi->biClrImportant = 0;
+
+ // Get the bits from the bitmap and stuff them after the LPBI
+ lpBits = (LPBYTE)(lpbi+1)+wColSize;
+ hdc = CreateCompatibleDC(NULL);
+ GetDIBits(hdc, render->hbm, 0, bitmap.bmHeight,
+ lpBits, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
+
+ // Fix this if GetDIBits messed it up....
+ lpbi->biClrUsed = (24 <= 8) ? 1 << 24 : 0;
+
+ DeleteDC(hdc);
+
+ LC_IMAGE* image = (LC_IMAGE*)malloc(bitmap.bmWidth*bitmap.bmHeight*3+sizeof(LC_IMAGE));
+ image->width = (unsigned short)bitmap.bmWidth;
+ image->height = (unsigned short)bitmap.bmHeight;
+ image->bits = (char*)image + sizeof(LC_IMAGE);
+
+ for (int i = 0; i < image->height; i++)
+ {
+ unsigned char* out = (unsigned char*)image->bits + (image->height-i-1)*image->width*3;
+ unsigned char* in = lpBits + i*wLineLen;
+ for (int j = 0; j < image->width*3; j += 3)
+ {
+ out[j] = in[j+2];
+ out[j+1] = in[j+1];
+ out[j+2] = in[j];
+ }
+ }
+
+ GlobalUnlock(hdib);
+ GlobalFree(hdib);
+
+ return image;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Main window functions
+
+void SystemRedrawView()
+{
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CView* pView = pFrame->GetActiveView();
+ pView->Invalidate(FALSE);
+}
+
+void SystemPieceComboAdd(char* name)
+{
+ CWnd* pWnd = AfxGetMainWnd();
+ if (pWnd != NULL)
+ pWnd->PostMessage(WM_LC_ADD_COMBO_STRING, (LPARAM)name);
+}
+
+void SystemCaptureMouse()
+{
+ CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
+ CView* pView = pFrame->GetActiveView();
+ pView->SetCapture();
+}
+
+void SystemReleaseMouse()
+{
+ ReleaseCapture();
+}
+
+// if (type == 255) -> don't change current type
+void SystemUpdateFocus(void* object, unsigned char type)
+{
+ CWnd* pFrame = AfxGetMainWnd();
+ if (pFrame != NULL)
+ pFrame->PostMessage(WM_LC_UPDATE_INFO, (WPARAM)object, type);
+}
+
+void SystemExportClipboard(File* clip)
+{
+ if (clip == NULL)
+ return;
+
+ HGLOBAL hData = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, clip->GetLength());
+ void* lpBuffer = GlobalLock(hData);
+ clip->Seek(0, SEEK_SET);
+ clip->Read(lpBuffer, clip->GetLength());
+ GlobalUnlock(hData);
+
+ if (OpenClipboard(NULL))
+ {
+ SetClipboardData(ClipboardFormat, hData);
+ CloseClipboard();
+ }
+// else
+// AfxMessageBox(IDS_CANNOT_OPEN_CLIPBOARD);
+}
+
+File* SystemImportClipboard()
+{
+ File* clip = NULL;
+
+ if (ClipboardFormat != 0)
+ if (OpenClipboard(NULL))
+ {
+ HANDLE hData = ::GetClipboardData(ClipboardFormat);
+ if (hData != NULL)
+ {
+ clip = new File(true);
+
+ BYTE* lpBuffer = (BYTE*)::GlobalLock(hData);
+ long nBufferSize = ::GlobalSize(hData);
+ clip->Write(lpBuffer, nBufferSize);
+ GlobalUnlock(hData);
+ }
+// else
+// AfxMessageBox(IDS_CANNOT_GET_CLIPBOARD_DATA);
+ CloseClipboard();
+ }
+// else
+// AfxMessageBox(IDS_CANNOT_OPEN_CLIPBOARD);
+
+ return clip;
+}