Beispiel #1
0
DataType& CFreeList<DataType>::AddItem( Int32* id )
{
	DebugAssert( m_NextFree != -1 );

	Int32 tmpId = m_NextFree;
	ConstructObject( &m_Array[ m_NextFree ].Data, DataType );

	m_Array[ m_NextFree ].Free = FALSE;
	m_ItemCount++;
	m_NextFree = FindNextFree( m_NextFree+1 );

	if( id )
		*id = tmpId;

	ConstructObject( &m_Array[tmpId].Data, DataType );

	return m_Array[ tmpId ].Data;
}
Beispiel #2
0
DARKSDK_DLL int LoadDBOEx ( LPSTR pFilename, sObject** ppObject )
{
	DWORD dwBlockSize = 0;
	DWORD* pDBOBlock = NULL;

	if ( !DBOLoadBlockFile ( pFilename, (DWORD*)&pDBOBlock, &dwBlockSize ) )
		return -1;

	if ( !ConstructObject ( ppObject, (LPSTR*)&pDBOBlock ) )
		return -2;

	return 1;
}
Beispiel #3
0
void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject *pParent, const std::vector<std::pair<CStr, CStr> >& NameSubst, boost::unordered_set<VfsPath>& Paths)
{
	ENSURE(pParent);
	int i;

	// Our object we are going to create
	IGUIObject *object = NULL;

	XMBAttributeList attributes = Element.GetAttributes();

	// Well first of all we need to determine the type
	CStr type (attributes.GetNamedItem(pFile->GetAttributeID("type")));
	if (type.empty())
		type = "empty";

	// Construct object from specified type
	//  henceforth, we need to do a rollback before aborting.
	//  i.e. releasing this object
	object = ConstructObject(type);

	if (!object)
	{
		// Report error that object was unsuccessfully loaded
		LOGERROR(L"GUI: Unrecognized object type \"%hs\"", type.c_str());
		return;
	}

	// Cache some IDs for element attribute names, to avoid string comparisons
	#define ELMT(x) int elmt_##x = pFile->GetElementID(#x)
	#define ATTR(x) int attr_##x = pFile->GetAttributeID(#x)
	ELMT(object);
	ELMT(action);
	ELMT(repeat);
	ATTR(style);
	ATTR(type);
	ATTR(name);
	ATTR(hotkey);
	ATTR(z);
	ATTR(on);
	ATTR(file);

	//
	//	Read Style and set defaults
	//
	//	If the setting "style" is set, try loading that setting.
	//
	//	Always load default (if it's available) first!
	//
	CStr argStyle (attributes.GetNamedItem(attr_style));

	if (m_Styles.count("default") == 1)
		object->LoadStyle(*this, "default");

	if (! argStyle.empty())
	{
		// additional check
		if (m_Styles.count(argStyle) == 0)
		{
			LOGERROR(L"GUI: Trying to use style '%hs' that doesn't exist.", argStyle.c_str());
		}
		else object->LoadStyle(*this, argStyle);
	}
	

	//
	//	Read Attributes
	//

	bool NameSet = false;
	bool ManuallySetZ = false; // if z has been manually set, this turn true

	CStr hotkeyTag;

	// Now we can iterate all attributes and store
	for (i=0; i<attributes.Count; ++i)
	{
		XMBAttribute attr = attributes.Item(i);

		// If value is "null", then it is equivalent as never being entered
		if (CStr(attr.Value) == "null")
			continue;

		// Ignore "type" and "style", we've already checked it
		if (attr.Name == attr_type || attr.Name == attr_style)
			continue;

		// Also the name needs some special attention
		if (attr.Name == attr_name)
		{
			CStr name (attr.Value);

			// Apply the requested substitutions
			for (size_t j = 0; j < NameSubst.size(); ++j)
				name.Replace(NameSubst[j].first, NameSubst[j].second);

			object->SetName(name);
			NameSet = true;
			continue;
		}

		// Wire up the hotkey tag, if it has one
		if (attr.Name == attr_hotkey)
			hotkeyTag = attr.Value;

		if (attr.Name == attr_z)
			ManuallySetZ = true;

		// Try setting the value
		if (object->SetSetting(pFile->GetAttributeString(attr.Name), attr.Value.FromUTF8(), true) != PSRETURN_OK)
		{
			LOGERROR(L"GUI: (object: %hs) Can't set \"%hs\" to \"%ls\"", object->GetPresentableName().c_str(), pFile->GetAttributeString(attr.Name).c_str(), attr.Value.FromUTF8().c_str());

			// This is not a fatal error
		}
	}

	// Check if name isn't set, generate an internal name in that case.
	if (!NameSet)
	{
		object->SetName("__internal(" + CStr::FromInt(m_InternalNameNumber) + ")");
		++m_InternalNameNumber;
	}

	// Attempt to register the hotkey tag, if one was provided
	if (! hotkeyTag.empty())
		m_HotkeyObjects[hotkeyTag].push_back(object);

	CStrW caption (Element.GetText().FromUTF8());
	if (! caption.empty())
	{
		// Set the setting caption to this
		object->SetSetting("caption", caption, true);

		// There is no harm if the object didn't have a "caption"
	}


	//
	//	Read Children
	//

	// Iterate children
	XMBElementList children = Element.GetChildNodes();

	for (i=0; i<children.Count; ++i)
	{
		// Get node
		XMBElement child = children.Item(i);

		// Check what name the elements got
		int element_name = child.GetNodeName();

		if (element_name == elmt_object)
		{
			// Call this function on the child
			Xeromyces_ReadObject(child, pFile, object, NameSubst, Paths);
		}
		else if (element_name == elmt_action)
		{
			// Scripted <action> element

			// Check for a 'file' parameter
			CStrW filename (child.GetAttributes().GetNamedItem(attr_file).FromUTF8());

			CStr code;

			// If there is a file, open it and use it as the code
			if (! filename.empty())
			{
				Paths.insert(filename);
				CVFSFile scriptfile;
				if (scriptfile.Load(g_VFS, filename) != PSRETURN_OK)
				{
					LOGERROR(L"Error opening GUI script action file '%ls'", filename.c_str());
					throw PSERROR_GUI_JSOpenFailed();
				}

				code = scriptfile.DecodeUTF8(); // assume it's UTF-8
			}

			// Read the inline code (concatenating to the file code, if both are specified)
			code += CStr(child.GetText());

			CStr action = CStr(child.GetAttributes().GetNamedItem(attr_on));
			
			// We need to set the GUI this object belongs to because RegisterScriptHandler requires an associated GUI.
			object->SetGUI(this);
			object->RegisterScriptHandler(action.LowerCase(), code, this);
		}
		else if (element_name == elmt_repeat)
		{
			Xeromyces_ReadRepeat(child, pFile, object, Paths);
		}
		else
		{
			// Try making the object read the tag.
			if (!object->HandleAdditionalChildren(child, pFile))
			{
				LOGERROR(L"GUI: (object: %hs) Reading unknown children for its type", object->GetPresentableName().c_str());
			}
		}
	} 

	//
	//	Check if Z wasn't manually set
	//
	if (!ManuallySetZ)
	{
		// Set it automatically to 10 plus its parents
		bool absolute;
		GUI<bool>::GetSetting(object, "absolute", absolute);

		// If the object is absolute, we'll have to get the parent's Z buffered,
		//  and add to that!
		if (absolute)
		{
			GUI<float>::SetSetting(object, "z", pParent->GetBufferedZ() + 10.f, true);
		}
		else
		// If the object is relative, then we'll just store Z as "10"
		{
			GUI<float>::SetSetting(object, "z", 10.f, true);
		}
	}


	//
	//	Input Child
	//

	try
	{
		if (pParent == m_BaseObject)
			AddObject(object);
		else
			pParent->AddChild(object);
	}
	catch (PSERROR_GUI& e)
	{
		LOGERROR(L"GUI error: %hs", e.what());
	}
}
Beispiel #4
0
long DoCommand( HWND hWindow, WPARAM wParam, LPARAM lParam )
/***********************************************************************/
{
FNAME szFileName;
LPFRAME lpFrame;
LPOBJECT lpObject, lpBase;
RECT rect, rMask, rTemp, rAll;
HWND hWnd;
STRING szString;
int i, idFileType, x, y, dx, dy;
BOOL fDoZoom, bPrint, fHasZoom;
LPSTR lpszCmdLine;
HGLOBAL hMem;
ITEMID idDataType;
DWORD dwReturn;
int NewShape;
UINT wID;

SoundStartID( wParam, NO/*bLoop*/, NULL/*hInstance*/ );
/*
	WIN16:	ID          = wParam
			ctrl handle = LOWORD(lParam)
			notify code = HIWORD(lParam)

	WIN32:	ID          = LOWORD(wParam)
			ctrl handle = lParam
			notify code = HIWORD(wParam)
*/

#ifdef WIN32
	wID = LOWORD(wParam);
#else
	wID = wParam;
#endif

switch (wID)
	{
	case IDM_EXIT:
	DeactivateTool();
	PostMessage( hWndAstral, WM_CLOSE, 0, 0L);
    Delay (750);
	break;

	case IDM_CLOSE:
	DeactivateTool();
	/* Check to see if the image needs to be saved */
	if ( !ConfirmClose(NO,NO) )
		break;
	CloseImage( NO, lpImage ); // Close the active image
	break;

	case IDM_ABOUT:
	/* Bring up the modal 'About' dialog box */
	AstralDlg( NO|2, hInstAstral, hWindow, IDD_ABOUT, DlgAboutProc);
	break;

	case IDM_NEXTPAGE:
	if ( !lpImage )
		break;
	DeactivateTool();
	SendMessage( lpImage->hWnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0L );
	break;

	case IDM_NEW:
	DeactivateTool();
	SoundStartResource( "magic01", NO, NULL );
	AstralCursor( IDC_WAIT );
	New( Control.NewWidth, Control.NewHeight, Control.NewResolution,
		Control.NewDepth );
	AstralCursor( NULL );
	break;

	case IDM_OPEN:
	DeactivateTool();
	/* Bring up the modal 'File Open' box */
	if ( !(dwReturn = DoOpenDlg( hWindow, IDD_OPEN,
		Save.FileType, szFileName, NO )) )
		break;
	idFileType = LOWORD( dwReturn );
	Save.FileType = idFileType;
	PutDefaultInt( "FileType", idFileType - IDN_TIFF );
	AstralImageLoad( idFileType, szFileName, MAYBE, YES );
	break;

	case IDM_ALTOPEN:
	DeactivateTool();
	// Command line sent from a second instance prior to it closing
	/* If the caller passed in a file name, try to load it or print it */
	if ( !(lpszCmdLine = (LPSTR)lParam) )
		break;
	HandleCommandLine( hWindow, lpszCmdLine, &bPrint );
	break;

	case IDM_SAVE:
	DeactivateTool();
	HandleSaveCommand(hWindow, wID, YES);
	break;

	case IDM_SAVEAS:
	DeactivateTool();
	HandleSaveCommand(hWindow, wID, YES);
	break;

	case IDM_SAVESPECIAL:
	DeactivateTool();
	HandleSaveCommand(hWindow, wID, YES);
	break;

	case IDM_SAVEWALLPAPER:
	DeactivateTool();
	SaveWallpaper( "CRAYOLA", NO/*fTiled*/ );
	break;

	case IDM_REVERT:
	if ( !lpImage )
		break;
	DeactivateTool();
	if ( lpImage->fUntitled ) // If the picture doesn't have a name, get out
		break;
	if ( ImgChanged(lpImage) )
		{
		/* Check to see if its OK to trash changes */
		if ( AstralOKCancel(IDS_OKTOREVERT,
				(LPSTR)lpImage->CurFile) == IDCANCEL )
			break;
		}
	lstrcpy( szFileName, lpImage->CurFile );
	idFileType = lpImage->FileType;
	fDoZoom = IsZoomed(lpImage->hWnd);
	fHasZoom = Window.fHasZoom;
	CloseImage( NO, lpImage ); // Close the active image
	if ( !AstralImageLoad( idFileType, szFileName, fDoZoom, YES ) )
		break;
	break;

	case IDM_RECALLIMAGE0:
	case IDM_RECALLIMAGE1:
	case IDM_RECALLIMAGE2:
	case IDM_RECALLIMAGE3:
	case IDM_RECALLIMAGE4:
	case IDM_RECALLIMAGE5:
	case IDM_RECALLIMAGE6:
	case IDM_RECALLIMAGE7:
	case IDM_RECALLIMAGE8:
	case IDM_RECALLIMAGE9:
	DeactivateTool();
	GetMenuString( GetMenu(hWindow), wID,
		szFileName, sizeof(szFileName), MF_BYCOMMAND );
	i = 0;
	while ( szFileName[i] && szFileName[i] != ' ' )
		i++; // Skip over the numeric id in the string (3. junk.tif)
	lstrcpy(szString, &szFileName[i+1]);
	GetRecallFileName(szString);
	AstralImageLoad( NULL, szString, MAYBE, YES );
	break;

	case IDM_PRINT:
	if ( !lpImage )
		break;
	DeactivateTool();
	AstralCursor( IDC_WAIT );
	DoPrintSizeInits();
	SoundStartResource( "print", YES, NULL );
	PrintFile( hWindow, filename(lpImage->CurFile), YES, lpImage, NULL );
	SoundStop();
	AstralCursor( NULL );
	break;

	case IDM_PRINTSETUP:
	/* Bring up the setup dialog box for the active printer */
	AstralDlg( NO|2, hInstAstral, hWindow, IDD_PRINTSETUP,
		DlgPrintSetupProc);
	break;

	case IDC_SOUND:
	SoundToggle();
	break;

	case IDM_UNDO:
	if ( !lpImage )
		break;
	DeactivateTool();
	ImgEditUndo(lpImage, YES, NO);
	break;

	case IDM_CUT:
	case IDM_COPY:
	if ( !lpImage )
		break;
	DeactivateTool();

	// Create the clipboard files from the image
	ProgressBegin(1, IDS_PROGCOPY);
	if ( !ImgWriteClipOut( lpImage, NULL, NULL, &rMask, lpImage->DataType ) )
		{
		ProgressEnd();
		Message(IDS_EMEMALLOC);
		break;
		}
	ProgressEnd();

	OpenClipboard(hWindow);
	EmptyClipboard();

	// Passing a NULL data handle in SetClipboardData() means that
	// the data will be requested in a WM_RENDERFORMAT message
	hMem = ConstructObject( lpImage,
		IsRectEmpty(&rMask)? (LPRECT)NULL : (LPRECT)&rMask );
	if ( pOLE )
		{ // Any data put on before Native will become staticly copied
		SetClipboardData( pOLE->cfNative, NULL );
		SetClipboardData( pOLE->cfOwnerLink, hMem );
		}
	SetClipboardData( CF_DIB, NULL );
	if ( Control.DoPicture )
		SetClipboardData( CF_METAFILEPICT, NULL );
	if ( Control.DoBitmap )
		SetClipboardData( CF_BITMAP, NULL );
	SetClipboardData( CF_PALETTE, NULL );
	SetClipboardData( Control.cfImage, NULL );
	if ( pOLE && wID == IDM_COPY && !lpImage->fUntitled )
		{ // ObjectLink is retrieved during a Paste Link...
		SetClipboardData( pOLE->cfObjectLink, hMem );
		}
	CloseClipboard();
	if ( wID == IDM_COPY )
		break;

	// else fall through to IDM_DELETE

	case IDM_DELETE:
	if ( !lpImage )
		break;
	{
	COLORINFO ColorInfo;

	DeactivateTool();
	ColorInfo.gray   = 255;
	SetColorInfo( &ColorInfo, &ColorInfo, CS_GRAY );
	TintFill( lpImage, &ColorInfo, 255, MM_NORMAL,
		wID == IDM_CUT ? IDS_UNDOCUT : IDS_UNDODELETE );
	}
	break;

	case IDM_PASTE:
	if ( !lpImage )
		break;

	case IDM_PASTEASNEW:
	if ( !OpenClipboard(hWndAstral) )
		{
		Message( IDS_ECLIPOPEN );
		break;
		}
	if ( !IsClipboardFormatAvailable(CF_DIB) &&
	     !IsClipboardFormatAvailable(CF_BITMAP) &&
	     !IsClipboardFormatAvailable(Control.cfImage) )
		{
		Message( IDS_ECLIPOPEN );
		CloseClipboard();
		break;
		}
	CloseClipboard();

	DeactivateTool();
	// First put clipboard contents into a file(s)
	AstralCursor(IDC_WAIT);
	if ( !PasteFromClipboard( hWindow, (wID == IDM_PASTE) /*fNeedMask*/ ) )
		{
		AstralCursor(NULL);
		Message(IDS_EMEMALLOC);
		break;
		}
	if ( wID == IDM_PASTE )
		{
		ProgressBegin(1, IDS_PROGPASTECLIP);
		TransformObjectsStart( YES/*fNewObject*/ );
        if ( ImgCreateClipInObject( lpImage, NO ) )
			;
		ProgressEnd();
		}
	else
	if ( wID == IDM_PASTEASNEW )
		{
		if ( lpFrame = AstralFrameLoad( Names.PasteImageFile, -1,
			 &idDataType, &idFileType) )
			{
			if ( NewImageWindow(
				NULL,			// lpOldFrame
				NULL,			// Name
				lpFrame, 		// lpNewFrame
				idFileType,		// lpImage->FileType
				idDataType,		// lpImage->DataType
				FALSE,			// New view?
				IMG_DOCUMENT,	// lpImage->DocumentType
				NULL,			// lpImage->ImageName
				MAYBE
				) )
					lpImage->fChanged = YES;
			}
		}
	break;

	case IDM_ESCAPE:
	if (!lpImage)
		break;
	if (lpImage->hWnd == hZoomWindow)
		break;
	if ( Tool.bActive && Tool.lpToolProc )
		DestroyProc( lpImage->hWnd, 1L );
	break;

	case IDM_SIZEUP:
	case IDM_SIZEDOWN:
	if (!Retouch.hBrush)
		break;				 
	SetFocus( hWindow ); // Take focus away from any controls
	if ( Retouch.BrushShape == IDC_BRUSHCUSTOM )
		break;
	if ( wID == IDM_SIZEUP )
    {
    	if( bHexBrush && ( Retouch.BrushSize % 2 == 0 ) && ( Retouch.BrushSize > 6 ))
    		Retouch.BrushSize += 2;
        else        
    		Retouch.BrushSize++;
    }
	else	
    {
    	if( bHexBrush && ( Retouch.BrushSize % 2 == 0 ) && ( Retouch.BrushSize > 6 )) 
    		Retouch.BrushSize -= 2;
        else        
    		Retouch.BrushSize--;
    }
	if ( Retouch.BrushSize < 1 || Retouch.BrushSize > MAX_BRUSH_SIZE )
		{
		Retouch.BrushSize = bound( Retouch.BrushSize, 1,MAX_BRUSH_SIZE);
		MessageBeep(0);
		break;
		}
	if (lpImage)
		DisplayBrush(0, 0, 0, OFF);
	SetMgxBrushSize(Retouch.hBrush, Retouch.BrushSize);
	if (lpImage && Window.hCursor == Window.hNullCursor)
		DisplayBrush(lpImage->hWnd, 32767, 32767, ON);
	if ( Tool.hRibbon )
		SetSlide( Tool.hRibbon, IDC_BRUSHSIZE, Retouch.BrushSize );
	break;

	case IDM_SHAPEUP:
	case IDM_SHAPEDOWN:
	if (!Retouch.hBrush)
		break;
	SetFocus( hWindow ); // Take focus away from any controls
	NewShape = Retouch.BrushShape;
	if ( wID == IDM_SHAPEUP )
		NewShape++;
	else	NewShape--;
	if ( NewShape > IDC_BRUSHCUSTOM )
		NewShape = IDC_BRUSHCIRCLE;
	if ( NewShape < IDC_BRUSHCIRCLE )
		NewShape = IDC_BRUSHCUSTOM;
	if (lpImage)
	 	DisplayBrush(0, 0, 0, OFF);
	if (!SetMgxBrushShape(Retouch.hBrush, NewShape, Names.CustomBrush))
		{
		NewShape = IDC_BRUSHCIRCLE;
		SetMgxBrushShape(Retouch.hBrush, NewShape, Names.CustomBrush);
		}
	Retouch.BrushShape = NewShape;
	if (lpImage && Window.hCursor == Window.hNullCursor)
	 	DisplayBrush(lpImage->hWnd, 32767, 32767, ON);
	if ( Tool.hRibbon )
		{
		CheckComboItem( Tool.hRibbon, IDC_BRUSHSHAPE, IDC_BRUSHCIRCLE,
			IDC_BRUSHCUSTOMNEW, Retouch.BrushShape );
		SendMessage( Tool.hRibbon, WM_CONTROLENABLE, 0, 0L );
		}
	break;

	case IDM_MOVEUP:
	case IDM_MOVEDOWN:
	case IDM_MOVELEFT:
	case IDM_MOVERIGHT:
	if (!lpImage)
		break;
	lpBase = ImgGetBase(lpImage);
	if (ImgGetSelObject(lpImage, NULL) == lpBase)
		break;
	dx = dy = 0;
	if (wID == IDM_MOVEUP)
		--dy;
	if (wID == IDM_MOVEDOWN)
		++dy;
	if (wID == IDM_MOVELEFT)
		--dx;
	if (wID == IDM_MOVERIGHT)
		++dx;
	lpObject = NULL;
	while (lpObject = ImgGetSelObject(lpImage, lpObject))
		{
		rect = lpObject->rObject;
		OffsetRect(&rect, dx, dy);
		if (!AstralIntersectRect(&rTemp, &lpBase->rObject, &rect))
			break;
		}
	if (lpObject)
		break;
	AstralSetRectEmpty(&rAll);
	lpObject = NULL;
	while (lpObject = ImgGetSelObject(lpImage, lpObject))
		{
		rect = lpObject->rObject;
		OffsetRect(&lpObject->rObject, dx, dy);
		AstralUnionRect(&rAll, &rAll, &lpObject->rObject);
		if (!lpObject->Pixmap.fNewFrame &&
				EqualRect(&rect, &lpObject->rUndoObject))
			lpObject->rUndoObject = lpObject->rObject;
		UpdateImage(&rect, TRUE);
		UpdateImage(&lpObject->rObject, TRUE);
		}
	if (wID == IDM_MOVEUP)
		{
		x = (rAll.left + rAll.right)/2;
		y = rAll.top;
		}
	else
	if (wID == IDM_MOVEDOWN)
		{
		x = (rAll.left + rAll.right)/2;
		y = rAll.bottom;
		}
	else
	if (wID == IDM_MOVELEFT)
		{
		x = rAll.left;
		y = (rAll.top + rAll.bottom)/2;
		}
	else
	if (wID == IDM_MOVERIGHT)
		{
		x = rAll.right;
		y = (rAll.top + rAll.bottom)/2;
		}
	File2Display(&x, &y);
	AutoScroll(lpImage->hWnd, x, y);
	AstralUpdateWindow(lpImage->hWnd);
	DisplayInfo(-1, &rAll);
	break;

	case IDM_LASTTOOL:
	DeactivateTool();
	if ( Tool.idLast && (hWnd = AstralDlgGet(IDD_MAIN)) )
		SendMessage( hWnd, WM_COMMAND, Tool.idLast, 2L);
	break;

	case IDM_PREF:
	// prevent problems if running animations and they change
	// the wave mix dll setting in preferences
	StopAnimation();
	AstralDlg( NO|2, hInstAstral, hWindow, IDD_PREF, DlgPrefProc );
	break;

	case IDC_VIEWLAST: // duplicate of function in the view ribbon
	if ( !lpImage )
		break;
	RevertLastView();
	break;

//	case IDC_VIEWFULL: // duplicate of function in the view ribbon
//	if ( !lpImage )
//		break;
//	AstralDlg( NO, hInstAstral, hWindow, IDD_VIEWFULL, DlgFullScreenViewProc );
//	break;

	case IDC_VIEWALL: // duplicate of function in the view ribbon
	if ( !lpImage )
		break;
	ViewAll();
	break;

	case IDC_ZOOMIN: // duplicate of function in the view ribbon
	if ( !lpImage )
		break;

	if (!lpImage->lpDisplay)
		break;

	if (!lpImage->lpDisplay->ViewPercentage)
		break;

	x = ( lpImage->lpDisplay->FileRect.left
			+ lpImage->lpDisplay->FileRect.right ) / 2;
	y = ( lpImage->lpDisplay->FileRect.top
			+ lpImage->lpDisplay->FileRect.bottom ) / 2;
	SaveLastView();
	Zoom(x,y, +100, YES, ( View.ZoomWindow ^ CONTROL ) );
	break;

	case IDC_ZOOMOUT: // duplicate of function in the view ribbon
	if ( !lpImage )
		break;

	if (!lpImage->lpDisplay)
		break;

	if (!lpImage->lpDisplay->ViewPercentage)
		break;

	x = ( lpImage->lpDisplay->FileRect.left
			+ lpImage->lpDisplay->FileRect.right ) / 2;
	y = ( lpImage->lpDisplay->FileRect.top
			+ lpImage->lpDisplay->FileRect.bottom ) / 2;
	SaveLastView();
	Zoom(x,y, -100, YES,( View.ZoomWindow ^ CONTROL ) );
	break;

	case IDM_HELP:
	Control.Hints = !Control.Hints;
	PutDefInt (Control.Hints,Control.Hints);
	break;

	default:
	return( FALSE );
	}

return( TRUE );
}
Beispiel #5
0
void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject* pParent, std::vector<std::pair<CStr, CStr> >& NameSubst, boost::unordered_set<VfsPath>& Paths, u32 nesting_depth)
{
	ENSURE(pParent);

	XMBAttributeList attributes = Element.GetAttributes();

	CStr type(attributes.GetNamedItem(pFile->GetAttributeID("type")));
	if (type.empty())
		type = "empty";

	// Construct object from specified type
	//  henceforth, we need to do a rollback before aborting.
	//  i.e. releasing this object
	IGUIObject* object = ConstructObject(type);

	if (!object)
	{
		LOGERROR("GUI: Unrecognized object type \"%s\"", type.c_str());
		return;
	}

	// Cache some IDs for element attribute names, to avoid string comparisons
	#define ELMT(x) int elmt_##x = pFile->GetElementID(#x)
	#define ATTR(x) int attr_##x = pFile->GetAttributeID(#x)
	ELMT(object);
	ELMT(action);
	ELMT(repeat);
	ELMT(translatableAttribute);
	ELMT(translate);
	ELMT(attribute);
	ELMT(keep);
	ELMT(include);
	ATTR(style);
	ATTR(type);
	ATTR(name);
	ATTR(hotkey);
	ATTR(z);
	ATTR(on);
	ATTR(file);
	ATTR(directory);
	ATTR(id);
	ATTR(context);

	//
	//	Read Style and set defaults
	//
	//	If the setting "style" is set, try loading that setting.
	//
	//	Always load default (if it's available) first!
	//
	CStr argStyle(attributes.GetNamedItem(attr_style));

	if (m_Styles.count("default") == 1)
		object->LoadStyle(*this, "default");

	if (!argStyle.empty())
	{
		if (m_Styles.count(argStyle) == 0)
			LOGERROR("GUI: Trying to use style '%s' that doesn't exist.", argStyle.c_str());
		else
			object->LoadStyle(*this, argStyle);
	}

	bool NameSet = false;
	bool ManuallySetZ = false;

	CStrW inclusionPath;
	CStr hotkeyTag;

	for (XMBAttribute attr : attributes)
	{
		// If value is "null", then it is equivalent as never being entered
		if (CStr(attr.Value) == "null")
			continue;

		// Ignore "type" and "style", we've already checked it
		if (attr.Name == attr_type || attr.Name == attr_style)
			continue;

		if (attr.Name == attr_name)
		{
			CStr name(attr.Value);

			for (const std::pair<CStr, CStr>& sub : NameSubst)
				name.Replace(sub.first, sub.second);

			object->SetName(name);
			NameSet = true;
			continue;
		}

		if (attr.Name == attr_hotkey)
			hotkeyTag = attr.Value;

		if (attr.Name == attr_z)
			ManuallySetZ = true;

		if (object->SetSetting(pFile->GetAttributeString(attr.Name), attr.Value.FromUTF8(), true) != PSRETURN_OK)
			LOGERROR("GUI: (object: %s) Can't set \"%s\" to \"%s\"", object->GetPresentableName(), pFile->GetAttributeString(attr.Name), attr.Value);
	}

	// Check if name isn't set, generate an internal name in that case.
	if (!NameSet)
	{
		object->SetName("__internal(" + CStr::FromInt(m_InternalNameNumber) + ")");
		++m_InternalNameNumber;
	}

	if (!hotkeyTag.empty())
		m_HotkeyObjects[hotkeyTag].push_back(object);

	CStrW caption(Element.GetText().FromUTF8());
	if (!caption.empty())
		object->SetSetting("caption", caption, true);

	for (XMBElement child : Element.GetChildNodes())
	{
		// Check what name the elements got
		int element_name = child.GetNodeName();

		if (element_name == elmt_object)
		{
			// Call this function on the child
			Xeromyces_ReadObject(child, pFile, object, NameSubst, Paths, nesting_depth);
		}
		else if (element_name == elmt_action)
		{
			// Scripted <action> element

			// Check for a 'file' parameter
			CStrW filename(child.GetAttributes().GetNamedItem(attr_file).FromUTF8());

			CStr code;

			// If there is a file, open it and use it as the code
			if (!filename.empty())
			{
				Paths.insert(filename);
				CVFSFile scriptfile;
				if (scriptfile.Load(g_VFS, filename) != PSRETURN_OK)
				{
					LOGERROR("Error opening GUI script action file '%s'", utf8_from_wstring(filename));
					throw PSERROR_GUI_JSOpenFailed();
				}

				code = scriptfile.DecodeUTF8(); // assume it's UTF-8
			}

			XMBElementList grandchildren = child.GetChildNodes();
			if (!grandchildren.empty()) // The <action> element contains <keep> and <translate> tags.
				for (XMBElement grandchild : grandchildren)
				{
					if (grandchild.GetNodeName() == elmt_translate)
						code += g_L10n.Translate(grandchild.GetText());
					else if (grandchild.GetNodeName() == elmt_keep)
						code += grandchild.GetText();
				}
			else // It’s pure JavaScript code.
				// Read the inline code (concatenating to the file code, if both are specified)
				code += CStr(child.GetText());

			CStr action = CStr(child.GetAttributes().GetNamedItem(attr_on));

			// We need to set the GUI this object belongs to because RegisterScriptHandler requires an associated GUI.
			object->SetGUI(this);
			object->RegisterScriptHandler(action.LowerCase(), code, this);
		}
		else if (element_name == elmt_repeat)
		{
			Xeromyces_ReadRepeat(child, pFile, object, NameSubst, Paths, nesting_depth);
		}
		else if (element_name == elmt_translatableAttribute)
		{
			// This is an element in the form “<translatableAttribute id="attributeName">attributeValue</translatableAttribute>”.
			CStr attributeName(child.GetAttributes().GetNamedItem(attr_id)); // Read the attribute name.
			if (attributeName.empty())
			{
				LOGERROR("GUI: ‘translatableAttribute’ XML element with empty ‘id’ XML attribute found. (object: %s)", object->GetPresentableName().c_str());
				continue;
			}

			CStr value(child.GetText());
			if (value.empty())
				continue;

			CStr context(child.GetAttributes().GetNamedItem(attr_context)); // Read the context if any.
			if (!context.empty())
			{
				CStr translatedValue(g_L10n.TranslateWithContext(context, value));
				object->SetSetting(attributeName, translatedValue.FromUTF8(), true);
			}
			else
			{
				CStr translatedValue(g_L10n.Translate(value));
				object->SetSetting(attributeName, translatedValue.FromUTF8(), true);
			}
		}
		else if (element_name == elmt_attribute)
		{
			// This is an element in the form “<attribute id="attributeName"><keep>Don’t translate this part
			// </keep><translate>but translate this one.</translate></attribute>”.
			CStr attributeName(child.GetAttributes().GetNamedItem(attr_id)); // Read the attribute name.
			if (attributeName.empty())
			{
				LOGERROR("GUI: ‘attribute’ XML element with empty ‘id’ XML attribute found. (object: %s)", object->GetPresentableName().c_str());
				continue;
			}

			CStr translatedValue;

			for (XMBElement grandchild : child.GetChildNodes())
			{
				if (grandchild.GetNodeName() == elmt_translate)
					translatedValue += g_L10n.Translate(grandchild.GetText());
				else if (grandchild.GetNodeName() == elmt_keep)
					translatedValue += grandchild.GetText();
			}
			object->SetSetting(attributeName, translatedValue.FromUTF8(), true);
		}
		else if (element_name == elmt_include)
		{
			CStrW filename(child.GetAttributes().GetNamedItem(attr_file).FromUTF8());
			CStrW directory(child.GetAttributes().GetNamedItem(attr_directory).FromUTF8());
			if (!filename.empty())
			{
				if (!directory.empty())
					LOGWARNING("GUI: Include element found with file name (%s) and directory name (%s). Only the file will be processed.", utf8_from_wstring(filename), utf8_from_wstring(directory));

				Paths.insert(filename);

				CXeromyces XeroIncluded;
				if (XeroIncluded.Load(g_VFS, filename, "gui") != PSRETURN_OK)
				{
					LOGERROR("GUI: Error reading included XML: '%s'", utf8_from_wstring(filename));
					continue;
				}

				XMBElement node = XeroIncluded.GetRoot();
				if (node.GetNodeName() != XeroIncluded.GetElementID("object"))
				{
					LOGERROR("GUI: Error reading included XML: '%s', root element must have be of type 'object'.", utf8_from_wstring(filename));
					continue;
				}

				if (nesting_depth+1 >= MAX_OBJECT_DEPTH)
				{
					LOGERROR("GUI: Too many nested GUI includes. Probably caused by a recursive include attribute. Abort rendering '%s'.", utf8_from_wstring(filename));
					continue;
				}

				Xeromyces_ReadObject(node, &XeroIncluded, object, NameSubst, Paths, nesting_depth+1);
			}
			else if (!directory.empty())
			{
				if (nesting_depth+1 >= MAX_OBJECT_DEPTH)
				{
					LOGERROR("GUI: Too many nested GUI includes. Probably caused by a recursive include attribute. Abort rendering '%s'.", utf8_from_wstring(directory));
					continue;
				}

				VfsPaths pathnames;
				vfs::GetPathnames(g_VFS, directory, L"*.xml", pathnames);
				for (const VfsPath& path : pathnames)
				{
					// as opposed to loading scripts, don't care if it's loaded before
					// one might use the same parts of the GUI in different situations
					Paths.insert(path);
					CXeromyces XeroIncluded;
					if (XeroIncluded.Load(g_VFS, path, "gui") != PSRETURN_OK)
					{
						LOGERROR("GUI: Error reading included XML: '%s'", path.string8());
						continue;
					}

					XMBElement node = XeroIncluded.GetRoot();
					if (node.GetNodeName() != XeroIncluded.GetElementID("object"))
					{
						LOGERROR("GUI: Error reading included XML: '%s', root element must have be of type 'object'.", path.string8());
						continue;
					}
					Xeromyces_ReadObject(node, &XeroIncluded, object, NameSubst, Paths, nesting_depth+1);
				}

			}
			else
				LOGERROR("GUI: 'include' XML element must have valid 'file' or 'directory' attribute found. (object %s)", object->GetPresentableName().c_str());
		}
		else
		{
			// Try making the object read the tag.
			if (!object->HandleAdditionalChildren(child, pFile))
				LOGERROR("GUI: (object: %s) Reading unknown children for its type", object->GetPresentableName().c_str());
		}
	}

	if (!ManuallySetZ)
	{
		// Set it automatically to 10 plus its parents
		bool absolute;
		GUI<bool>::GetSetting(object, "absolute", absolute);

		if (absolute)
			// If the object is absolute, we'll have to get the parent's Z buffered,
			// and add to that!
			GUI<float>::SetSetting(object, "z", pParent->GetBufferedZ() + 10.f, true);
		else
			// If the object is relative, then we'll just store Z as "10"
			GUI<float>::SetSetting(object, "z", 10.f, true);
	}

	try
	{
		if (pParent == m_BaseObject)
			AddObject(object);
		else
			pParent->AddChild(object);
	}
	catch (PSERROR_GUI& e)
	{
		LOGERROR("GUI error: %s", e.what());
	}
}