SCI: Rework the way SciGUIwindowMgr keeps track of windows/ports; remove the GUI heapmanager

svn-id: r44635
This commit is contained in:
Max Horn 2009-10-04 21:27:24 +00:00
parent f242266f6d
commit db2e5a4fb5
10 changed files with 88 additions and 586 deletions

View file

@ -100,8 +100,6 @@
<File RelativePath="..\..\engines\sci\gui\gui_gfx.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_gfx.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_gfx.h" /> <File RelativePath="..\..\engines\sci\gui\gui_gfx.h" />
<File RelativePath="..\..\engines\sci\gui\gui_helpers.h" /> <File RelativePath="..\..\engines\sci\gui\gui_helpers.h" />
<File RelativePath="..\..\engines\sci\gui\gui_memmgr.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_memmgr.h" />
<File RelativePath="..\..\engines\sci\gui\gui_picture.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_picture.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_picture.h" /> <File RelativePath="..\..\engines\sci\gui\gui_picture.h" />
<File RelativePath="..\..\engines\sci\gui\gui_screen.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_screen.cpp" />

View file

@ -101,8 +101,6 @@
<File RelativePath="..\..\engines\sci\gui\gui_gfx.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_gfx.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_gfx.h" /> <File RelativePath="..\..\engines\sci\gui\gui_gfx.h" />
<File RelativePath="..\..\engines\sci\gui\gui_helpers.h" /> <File RelativePath="..\..\engines\sci\gui\gui_helpers.h" />
<File RelativePath="..\..\engines\sci\gui\gui_memmgr.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_memmgr.h" />
<File RelativePath="..\..\engines\sci\gui\gui_picture.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_picture.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_picture.h" /> <File RelativePath="..\..\engines\sci\gui\gui_picture.h" />
<File RelativePath="..\..\engines\sci\gui\gui_screen.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_screen.cpp" />

View file

@ -31,7 +31,6 @@
#include "sci/gui/gui_screen.h" #include "sci/gui/gui_screen.h"
#include "sci/gui/gui_gfx.h" #include "sci/gui/gui_gfx.h"
#include "sci/gui/gui_windowmgr.h" #include "sci/gui/gui_windowmgr.h"
#include "sci/gui/gui_memmgr.h"
#include "sci/gui/gui_view.h" #include "sci/gui/gui_view.h"
#include "sci/gfx/operations.h" #include "sci/gfx/operations.h"
@ -71,10 +70,14 @@ void SciGUI::wait(int16 ticks) {
void SciGUI::setPort(uint16 portPtr) { void SciGUI::setPort(uint16 portPtr) {
switch (portPtr) { switch (portPtr) {
case 0: _gfx->SetPort(_windowMgr->_wmgrPort); break; case 0:
case 0xFFFF: _gfx->SetPort(_gfx->_menuPort); break; _gfx->SetPort(_windowMgr->_wmgrPort);
default: break;
_gfx->SetPort((GUIPort *)heap2Ptr(portPtr)); case 0xFFFF:
_gfx->SetPort(_gfx->_menuPort);
break;
default:
_gfx->SetPort(_windowMgr->getPortById(portPtr));
}; };
} }
@ -87,7 +90,7 @@ void SciGUI::setPortPic(Common::Rect rect, int16 picTop, int16 picLeft) {
} }
reg_t SciGUI::getPort() { reg_t SciGUI::getPort() {
return make_reg(0, ptr2heap((byte *)_gfx->GetPort())); return make_reg(0, _gfx->GetPort()->id);
} }
void SciGUI::globalToLocal(int16 *x, int16 *y) { void SciGUI::globalToLocal(int16 *x, int16 *y) {
@ -112,23 +115,25 @@ reg_t SciGUI::newWindow(Common::Rect dims, Common::Rect restoreRect, uint16 styl
wnd->penClr = colorPen; wnd->penClr = colorPen;
wnd->backClr = colorBack; wnd->backClr = colorBack;
_windowMgr->DrawWindow(wnd); _windowMgr->DrawWindow(wnd);
return make_reg(0, ptr2heap((byte *)wnd));
return make_reg(0, wnd->id);
} }
void SciGUI::disposeWindow(uint16 windowPtr, int16 arg2) { void SciGUI::disposeWindow(uint16 windowPtr, int16 arg2) {
GUIWindow *wnd = (GUIWindow *)heap2Ptr(windowPtr); GUIWindow *wnd = (GUIWindow *)_windowMgr->getPortById(windowPtr);
_windowMgr->DisposeWindow(wnd, arg2); _windowMgr->DisposeWindow(wnd, arg2);
} }
void SciGUI::display(const char *text, int argc, reg_t *argv) { void SciGUI::display(const char *text, int argc, reg_t *argv) {
int displayArg; int displayArg;
GUIPort oldPort;
int16 align = 0; int16 align = 0;
int16 bgcolor = -1, width = -1, bRedraw = 1; int16 bgcolor = -1, width = -1, bRedraw = 1;
byte bSaveUnder = false; byte bSaveUnder = false;
Common::Rect rect, *orect = &((GUIWindow *)_gfx->GetPort())->dims; Common::Rect rect, *orect = &((GUIWindow *)_gfx->GetPort())->dims;
memcpy(&oldPort, _gfx->GetPort(), sizeof(GUIPort)); // Make a "backup" of the port settings
GUIPort oldPort = *_gfx->GetPort();
// setting defaults // setting defaults
_gfx->PenMode(0); _gfx->PenMode(0);
_gfx->PenColor(0); _gfx->PenColor(0);
@ -203,7 +208,7 @@ void SciGUI::display(const char *text, int argc, reg_t *argv) {
GUIPort *currport = _gfx->GetPort(); GUIPort *currport = _gfx->GetPort();
uint16 tTop = currport->curTop; uint16 tTop = currport->curTop;
uint16 tLeft = currport->curLeft; uint16 tLeft = currport->curLeft;
memcpy(currport, &oldPort, sizeof(GUIPort)); *currport = oldPort;
currport->curTop = tTop; currport->curTop = tTop;
currport->curLeft = tLeft; currport->curLeft = tLeft;

View file

@ -365,7 +365,7 @@ void SciGUIgfx::OpenPort(GUIPort *port) {
port->penClr = 0; port->penClr = 0;
port->backClr = 0xFF; port->backClr = 0xFF;
port->penMode = 0; port->penMode = 0;
memcpy(&port->rect, &_bounds, sizeof(_bounds)); port->rect = _bounds;
} }
void SciGUIgfx::PenColor(int16 color) { void SciGUIgfx::PenColor(int16 color) {

View file

@ -39,6 +39,7 @@ typedef int16 GUIViewCellNo;
typedef uint16 GUIHandle; typedef uint16 GUIHandle;
struct GUIPort { struct GUIPort {
uint16 id;
int16 top, left; int16 top, left;
Common::Rect rect; Common::Rect rect;
int16 curTop, curLeft; int16 curTop, curLeft;
@ -46,6 +47,12 @@ struct GUIPort {
GUIResourceId fontId; GUIResourceId fontId;
int16 textFace, penClr, backClr; int16 textFace, penClr, backClr;
int16 penMode; int16 penMode;
GUIPort(uint16 theId) : id(theId), top(0), left(0),
curTop(0), curLeft(0),
fontHeight(0), fontId(0), textFace(0),
penClr(0), backClr(0xFF), penMode(0) {
}
}; };
struct GUIWindow : public GUIPort { struct GUIWindow : public GUIPort {
@ -55,8 +62,14 @@ struct GUIWindow : public GUIPort {
uint16 uSaveFlag; uint16 uSaveFlag;
reg_t hSaved1; reg_t hSaved1;
reg_t hSaved2; reg_t hSaved2;
GUIHandle hTitle; Common::String title;
bool bDrawn; bool bDrawn;
GUIWindow(uint16 theId) : GUIPort(theId),
wndStyle(0), uSaveFlag(0),
hSaved1(NULL_REG), hSaved2(NULL_REG),
bDrawn(false) {
}
}; };
struct GUICast { struct GUICast {

View file

@ -1,373 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "sci/sci.h"
#include "sci/gui/gui_helpers.h"
#include "sci/gui/gui_memmgr.h"
namespace Sci {
static tagHandle *pHandles = 0;
static int16 nHandles = 0;
static byte *_heap = 0;
SCIHANDLE _firstfree = 0;
Common::HashMap<HEAPHANDLE, tagHeapInfo> heapInfo;
#define HEAP_BOTTOM 1000
//----------------------
void FreeMem(void) {
// deleting handles
if (pHandles) {
for (uint16 i = 0; i < nHandles; i++)
hunkDisposeHandle(i);
delete[] pHandles;
pHandles = 0;
}
// deleting heap
if (_heap) {
delete[] _heap;
_heap = 0;
}
}
//----------------------
bool InitMem(int16 max_handles) {
// heap
_heap = new byte[HEAP_SIZE];
memset(_heap, 0x55, HEAP_SIZE);
_firstfree = HEAP_START;
heapSetBlockSize(_firstfree, HEAP_SIZE - 1 - HEAP_START);
heapSetBlockNext(_firstfree, (SCIHANDLE)(HEAP_SIZE - 1));
//hunk
pHandles = new tagHandle[max_handles];
if (pHandles) {
nHandles = max_handles;
memset(pHandles, 0, sizeof(tagHandle) * max_handles); // zerofy all
return 1;
}
return 0;
}
//----------------------
SCIHANDLE hunkNeedHandle(uint16 size, uint32 resId) {
SCIHANDLE newh = 0;
// see if there is an empty handle available
for (int16 i = 1; i < nHandles; i++)
if (pHandles[i].ptr == 0) {
newh = i;
break;
}
// if unused handle was found - allocate memory and return it
if (newh == nHandles)
return 0;
pHandles[newh].ptr = (byte*)malloc(size);
assert(pHandles[newh].ptr);
if (pHandles[newh].ptr) {
pHandles[newh].size = size;
pHandles[newh].resId = resId;
debug(
5,
" MemMgr: Requested %6db for res %08X, allocated handle %04X",
size, resId, newh);
return newh;
}
return 0;
}
//----------------------
void hunkDisposeHandle(SCIHANDLE handle) {
// if (handle > 0 && handle < nHandles && pHandles[handle].ptr) {
// debug(
// 5,
// " MemMgr: disposing handle 0x%04X, size=%8db, associated res %08X",
// handle, pHandles[handle].size, pHandles[handle].resId);
// free(pHandles[handle].ptr);
// pHandles[handle].ptr = 0;
// // deleting associated resource handler
// // Check that this don't fail on delete as ResGetLoaded could return 0;
// if (pHandles[handle].resId != 0xFFFFFFFF)
// delete g_sci->ResMgr.ResGetLoaded(pHandles[handle].resId);
// }
}
//----------------------
byte *hunk2Ptr(SCIHANDLE handle) {
if (handle > 0 && handle < nHandles && pHandles[handle].ptr)
return (byte *)pHandles[handle].ptr;
return 0;
}
//----------------------
SCIHANDLE ptr2hunk(byte *ptr) {
for (int i = 0; i < nHandles; i++) {
if (ptr >= pHandles[i].ptr && ptr <= pHandles[i].ptr + pHandles[i].size)
return i;
}
return 0;
}
//----------------------
uint32 hunkHandleSize(SCIHANDLE handle) {
if (handle > 0 && handle < nHandles && pHandles[handle].ptr)
return pHandles[handle].size;
return 0;
}
//----------------------
// int16 hunkResourceNum(SCIHANDLE handle) {
// if (handle > 0 && handle < nHandles && pHandles[handle].ptr)
// return RES_ID2NUM(pHandles[handle].resId);
// return -1;
// }
//----------------------
void hunkDump() {
debug("\nMemMgr: Hunk dump:");
uint32 size = 0;
for (int i = 0; i < nHandles; i++)
if (pHandles[i].ptr) {
debug(" %04X, size=%8db, associated res %08X", i,
pHandles[i].size, pHandles[i].resId);
size += pHandles[i].size;
}
debug("Total memory allocated: %db", size);
debug("End dump");
}
uint32 hunkUsed() {
uint32 size = 0;
for (int i = 0; i < nHandles; i++)
if (pHandles[i].ptr)
size += pHandles[i].size;
return size;
}
//----------------------
// HEAP
//----------------------
//---------------------------------------------
// TODO : make sure that STRING, STACK and SCRIPT DATA is never allocated below HEAP_BOTTOM=1000
// otherwise it will cause problems with kernel string fuctions that assumes that anything below 1000 is res number
HEAPHANDLE heapNewPtr(uint16 size, kDataType type, const char *info) {
if (size == 0)
warning("Zero Heap Allocation Request!");
HEAPHANDLE ptr, prev, next;
ptr = prev = _firstfree;
// 2 bytes block header header + block size must be odd
size += 2 + (size & 1);
// looking for an empty block to use
uint16 blocksize;
bool bBottomSafe = !(type == kDataString || type == kDataUnknown);
while (ptr < HEAP_SIZE - 1) {
blocksize = heapGetBlockSize(ptr);
next = heapGetBlockNext(ptr);
if (blocksize >= size) {
if (bBottomSafe || (!bBottomSafe && ptr > HEAP_BOTTOM)) {
if (blocksize <= size + 4) { // use all block
size = blocksize;
heapSetBlockNext(prev, next);
} else { // split block in 2 blocks
HEAPHANDLE newblock = ptr + size;
heapSetBlockNext(prev, newblock);
heapSetBlockSize(newblock, blocksize - size);
heapSetBlockNext(newblock, next);
next = newblock;
}
// setting allocated block
heapSetBlockSize(ptr, size);
// updating firstfree pointer
if (ptr == _firstfree)
_firstfree = next;
setHeapInfo(ptr, type, info);
return ptr;
} //if (bBottomSafe || (!bBottomSafe && ptr>HEAP_BOTTOM))
else { // !bottomsafe && ptr < HEAP_BOTTOM
if (blocksize + ptr - HEAP_BOTTOM >= size) {
// splitting the block into 3 parts
// [2][ptr...999] [2][1002...1000+size-1] [2][1002+size...ptr+blocksize]
// free returned free
heapSetBlockSize(ptr, HEAP_BOTTOM-ptr + 2);
heapSetBlockSize(HEAP_BOTTOM+2, size);
heapSetBlockSize(HEAP_BOTTOM+2 + size, blocksize - size
- (HEAP_BOTTOM-ptr + 2));
heapSetBlockNext(HEAP_BOTTOM+2 + size, next);
heapSetBlockNext(ptr, HEAP_BOTTOM+2 + size);
setHeapInfo(HEAP_BOTTOM+2, type, info);
return HEAP_BOTTOM + 2;
}
}
} // if (blocksize >= size)
// block too small - moving to next one
prev = ptr;
ptr = next;
}
// allocation error - out of heap
warning("Out of heap space");
return 0;
}
//--------------------------------------------
void heapDisposePtr(HEAPHANDLE handle) {
HEAPHANDLE prev, next;
prev = next = _firstfree;
// searching for prev and next free blocks (before & after deleted block)
while (next < handle) {
prev = next;
next = heapGetBlockNext(prev);
}
// if deleted block is before 1st free space then it'll be 1st free space
if (handle < _firstfree) {
next = _firstfree;
_firstfree = handle;
} else
heapSetBlockNext(prev, handle);
heapSetBlockNext(handle, next);
//Try to merge with previous
if (prev + heapGetBlockSize(prev) == handle) {
heapSetBlockSize(prev, heapGetBlockSize(prev)
+ heapGetBlockSize(handle));
heapSetBlockNext(prev, next);
handle = prev;
}
//Try to merge with next
if (handle + heapGetBlockSize(handle) == next && next != (HEAP_SIZE - 1)) {
heapSetBlockSize(handle, heapGetBlockSize(handle) + heapGetBlockSize(
next));
heapSetBlockNext(handle, heapGetBlockNext(next));
}
}
//-------------------------------------
uint16 heapFreeSize() {
HEAPHANDLE free = _firstfree;
uint16 szFree = 0;
while (free < HEAP_SIZE - 1) {
int size = heapGetBlockSize(free);
free = heapGetBlockNext(free);
szFree += size;
}
return szFree;
}
//-------------------------------------
uint16 heapLargestFreeSize() {
HEAPHANDLE free = _firstfree;
uint16 maxFree = 0;
while (free < HEAP_SIZE - 1) {
int size = heapGetBlockSize(free);
free = heapGetBlockNext(free);
if (size > maxFree)
maxFree = size;
}
return maxFree ? maxFree - 2 : 0;
}
//-------------------------------------
void heapDump() {
debug("\nMemMgr:Heap dump:");
HEAPHANDLE ptr = HEAP_START;
HEAPHANDLE free = _firstfree;
uint16 szFree = 0, szUsed = 0;
while (ptr < HEAP_SIZE - 1) {
int size = heapGetBlockSize(ptr);
if (ptr == free) {
free = heapGetBlockNext(free);
debug(" %04X %6u size:%6d FREE next=%04X", ptr, ptr,
heapGetDataSize(ptr), free);
szFree += size;
} else {
debug(" %04X %6u size:%6d USED", ptr, ptr, heapGetDataSize(ptr));
szUsed += size;
}
ptr += size;
}
debug("Total %db used, %db free\nEnd Dump", szUsed, szFree);
}
//----------------------------
byte *heap2Ptr(HEAPHANDLE ptr) {
return (ptr >= HEAP_START) ? (byte *)(_heap + ptr) : NULL;
}
//----------------------------
HEAPHANDLE ptr2heap(byte *ptr) {
return ptr > _heap && ptr < (_heap + HEAP_SIZE) ? (HEAPHANDLE)(ptr - _heap)
: 0;
}
//----------------------------
uint16 heapGetBlockSize(HEAPHANDLE ptr) {
return READ_UINT16(_heap + ptr - 2);
}
//----------------------------
uint16 heapGetDataSize(HEAPHANDLE ptr) {
return heapGetBlockSize(ptr) - 2;
}
//----------------------------
void heapFillPtr(HEAPHANDLE ptr, byte filler) {
memset(heap2Ptr(ptr), filler, heapGetDataSize(ptr));
}
//----------------------------
void heapClearPtr(HEAPHANDLE ptr) {
heapFillPtr(ptr, 0);
}
//----------------------------
void heapSetBlockSize(HEAPHANDLE ptr, uint16 nbytes) {
WRITE_UINT16(_heap + ptr - 2, nbytes);
}
//----------------------------
HEAPHANDLE heapGetBlockNext(HEAPHANDLE ptr) {
return READ_UINT16(_heap + ptr);
}
//----------------------------
void heapSetBlockNext(HEAPHANDLE ptr, SCIHANDLE next) {
WRITE_UINT16(_heap + ptr, next);
}
//----------------------------
void heapDisposePtr(byte *ptr) {
heapDisposePtr(ptr - _heap);
}
//---------------------------------------------
//
//
void setHeapInfo(HEAPHANDLE hnd, kDataType type, const char *szinfo) {
tagHeapInfo info = { kDataUnknown, { 0 } };
info.type = type;
if (szinfo)
strncpy(info.info, szinfo, 20);
heapInfo.setVal(hnd, info);
}
//--------------------------------
bool saveMemState(Common::OutSaveFile *pFile) {
pFile->writeString("MEMORY\n");
// saving heap
pFile->write(_heap, HEAP_SIZE);
pFile->writeUint16LE(_firstfree);
// TODO : process and write hunk handles
//pFile->writeString("HUNK\n");
return true;
}
//--------------------------------
bool restoreMemState(Common::InSaveFile *pFile) {
if (pFile->readLine() != "MEMORY")
return false;
pFile->read(_heap, HEAP_SIZE);
_firstfree = pFile->readUint16LE();
return true;
}
//-------------------------------
}// End of namespace SCI

View file

@ -1,123 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef SCI_GUI_MEMMGR_H
#define SCI_GUI_MEMMGR_H
#include "common/savefile.h"
#include "common/endian.h"
#include "common/hashmap.h"
/*
Memory management functions for SCI engine;
All fuctions are simplified as there is no 16-bit limitations as in
original SCI. Although it may cause problems.
SCI Heap functionality.
Heap size is limited to 65535 bytes to be consistent with SCI scripts
Free block header is [wBlockSize][wNextFree]
Used block header is [wBlockSize][data.....]
^-----returned HEAPHANDLE
*/
namespace Sci {
typedef uint16 SCIHANDLE;
typedef uint16 HEAPHANDLE;
enum {
HEAP_SIZE = 0x10000l,
HEAP_START = 2
};
struct tagHandle {
byte *ptr; // data pointer
uint32 size; // memory block size
uint32 resId; // associated resource
};
//---------------------------------------------
// for debugger
enum kDataType {
kDataUnknown = 0,
kDataClass,
kDataObject,
kDataRect,
kDataWindow,
kDataPort,
kDataString,
kDataListHdr,
kDataListNode,
kDataCast,
kDataPalette,
kDataScript,
kDataFile
};
struct tagHeapInfo {
kDataType type;
char info[21];
};
void setHeapInfo(HEAPHANDLE hnd, kDataType type, const char *info = 0);
bool InitMem(int16 max_handles);
void FreeMem(void);
// hunk functions
SCIHANDLE hunkNeedHandle(uint16 size, uint32 resId = 0xFFFFFFFF);
void hunkDisposeHandle(SCIHANDLE handle);
byte *hunk2Ptr(SCIHANDLE handle);
SCIHANDLE ptr2hunk(byte *ptr);
uint32 hunkHandleSize(SCIHANDLE handle);
int16 hunkResourceNum(SCIHANDLE handle);
void hunkDump();
uint32 hunkUsed();
// heap functions
HEAPHANDLE heapNewPtr(uint16 size, kDataType type/*=kDataUnknown*/,
const char *info = 0);
void heapDisposePtr(HEAPHANDLE handle);
void heapDisposePtr(byte *ptr);
byte *heap2Ptr(HEAPHANDLE ptr);
HEAPHANDLE ptr2heap(byte *ptr);
uint16 heapGetBlockSize(HEAPHANDLE ptr);
uint16 heapGetDataSize(HEAPHANDLE ptr);
void heapFillPtr(HEAPHANDLE ptr, byte filler);
void heapClearPtr(HEAPHANDLE ptr);
void heapDump();
uint16 heapFreeSize();
uint16 heapLargestFreeSize();
void heapSetBlockSize(HEAPHANDLE ptr, uint16 nbytes);
HEAPHANDLE heapGetBlockNext(HEAPHANDLE ptr);
void heapSetBlockNext(HEAPHANDLE ptr, SCIHANDLE next);
bool saveMemState(Common::OutSaveFile *pFile);
bool restoreMemState(Common::InSaveFile *pFile);
} // End of namespace SCI
#endif

View file

@ -23,7 +23,6 @@
* *
*/ */
#include "common/algorithm.h" // for Common::find()
#include "common/util.h" #include "common/util.h"
#include "sci/sci.h" #include "sci/sci.h"
@ -31,14 +30,9 @@
#include "sci/tools.h" #include "sci/tools.h"
#include "sci/gui/gui_gfx.h" #include "sci/gui/gui_gfx.h"
#include "sci/gui/gui_windowmgr.h" #include "sci/gui/gui_windowmgr.h"
#include "sci/gui/gui_memmgr.h"
namespace Sci { namespace Sci {
namespace {
const Common::Rect s_picRect(0, 10, 320, 200);
} // end of anonymous namespace
// window styles // window styles
enum { enum {
kTransparent = (1 << 0), kTransparent = (1 << 0),
@ -51,12 +45,10 @@ enum {
SciGUIwindowMgr::SciGUIwindowMgr(EngineState *state, SciGUIgfx *gfx) SciGUIwindowMgr::SciGUIwindowMgr(EngineState *state, SciGUIgfx *gfx)
: _s(state), _gfx(gfx) { : _s(state), _gfx(gfx) {
// FIXME: remove memmgr _wmgrPort = new GUIPort(1);
InitMem(0x320); _windowsById.resize(2);
_windowsById[0] = 0;
HEAPHANDLE wmgrPortH = heapNewPtr(sizeof(GUIPort), kDataPort, "wmgrPort"); _windowsById[1] = _wmgrPort;
heapClearPtr(wmgrPortH);
_wmgrPort = (GUIPort *)heap2Ptr(wmgrPortH);
int16 offTop = 20; int16 offTop = 20;
@ -69,75 +61,71 @@ SciGUIwindowMgr::SciGUIwindowMgr(EngineState *state, SciGUIgfx *gfx)
_wmgrPort->curTop = 0; _wmgrPort->curTop = 0;
_wmgrPort->curLeft = 0; _wmgrPort->curLeft = 0;
windowList.push_front(wmgrPortH); _windowList.push_front(_wmgrPort);
_picWind = NewWindow(s_picRect, 0, 0, kTransparent | kNoFrame, 0, 1); _picWind = NewWindow(Common::Rect(0, 10, 320, 200), 0, 0, kTransparent | kNoFrame, 0, 1);
} }
SciGUIwindowMgr::~SciGUIwindowMgr() { SciGUIwindowMgr::~SciGUIwindowMgr() {
// TODO: Clear _windowList and delete all stuff in it?
} }
int16 SciGUIwindowMgr::isFrontWindow(GUIWindow *pWnd) { int16 SciGUIwindowMgr::isFrontWindow(GUIWindow *pWnd) {
if (heap2Ptr(windowList.back()) == (byte *)pWnd) return _windowList.back() == pWnd;
return 1;
return 0;
}
void SciGUIwindowMgr::SelectWindow(HEAPHANDLE hh) {
GUIPort *port = (GUIPort *)heap2Ptr(hh);
_gfx->SetPort(port);
if (hh != windowList.back()) { // selecting not topmost window
Common::List<HEAPHANDLE>::iterator curWindowIterator = Common::find(windowList.begin(), windowList.end(), hh);
Common::List<HEAPHANDLE>::iterator prevWindowIterator = --curWindowIterator;
curWindowIterator++; // restore iterator position
GUIWindow *prevwnd = (GUIWindow *)heap2Ptr(*prevWindowIterator);
BeginUpdate(prevwnd);
windowList.erase(curWindowIterator);
windowList.push_back(hh);
EndUpdate(prevwnd);
}
_gfx->SetPort(port);
} }
void SciGUIwindowMgr::BeginUpdate(GUIWindow *wnd) { void SciGUIwindowMgr::BeginUpdate(GUIWindow *wnd) {
GUIPort *oldPort = _gfx->SetPort(_wmgrPort); GUIPort *oldPort = _gfx->SetPort(_wmgrPort);
Common::List<HEAPHANDLE>::iterator curWindowIterator = windowList.end(); PortList::iterator it = _windowList.reverse_begin();
GUIWindow *node = (GUIWindow *)heap2Ptr(*curWindowIterator); const PortList::iterator end = Common::find(_windowList.begin(), _windowList.end(), wnd);
while (node != wnd) { while (it != end) {
UpdateWindow(node); // FIXME: We also store GUIPort objects in the window list.
curWindowIterator--; // previous node // We should add a check that we really only pass windows here...
node = (GUIWindow *)heap2Ptr(*curWindowIterator); UpdateWindow((GUIWindow *)*it);
--it;
} }
_gfx->SetPort(oldPort); _gfx->SetPort(oldPort);
} }
void SciGUIwindowMgr::EndUpdate(GUIWindow *wnd) { void SciGUIwindowMgr::EndUpdate(GUIWindow *wnd) {
GUIPort *oldPort = _gfx->SetPort(_wmgrPort); GUIPort *oldPort = _gfx->SetPort(_wmgrPort);
Common::List<HEAPHANDLE>::iterator curWindowIterator = windowList.end(); const PortList::iterator end = _windowList.end();
GUIWindow *last = (GUIWindow *)heap2Ptr(*curWindowIterator); PortList::iterator it = Common::find(_windowList.begin(), end, wnd);
while (wnd != last) { while (it != end) {
curWindowIterator++; // next node ++it;
wnd = (GUIWindow *)heap2Ptr(*curWindowIterator); // FIXME: We also store GUIPort objects in the window list.
UpdateWindow(wnd); // We should add a check that we really only pass windows here...
UpdateWindow((GUIWindow *)*it);
} }
_gfx->SetPort(oldPort); _gfx->SetPort(oldPort);
} }
GUIWindow *SciGUIwindowMgr::NewWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, uint16 arg8, uint16 argA) { GUIWindow *SciGUIwindowMgr::NewWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, uint16 arg8, uint16 argA) {
HEAPHANDLE hWnd = heapNewPtr(sizeof(GUIWindow), kDataWindow, title); // Find an unused window/port id
uint id = 1;
while (id < _windowsById.size() && _windowsById[id]) {
++id;
}
if (id == _windowsById.size())
_windowsById.push_back(0);
assert(0 < id && id < 0xFFFF);
GUIWindow *pwnd = new GUIWindow(id);
Common::Rect r; Common::Rect r;
if (!hWnd) { if (!pwnd) {
warning("Can't open window!"); warning("Can't open window!");
return 0; return 0;
} }
heapClearPtr(hWnd);
_windowsById[id] = pwnd;
if (style & kTopmost) if (style & kTopmost)
windowList.push_front(hWnd); _windowList.push_front(pwnd);
else else
windowList.push_back(hWnd); _windowList.push_back(pwnd);
GUIWindow *pwnd = (GUIWindow *)heap2Ptr(hWnd); _gfx->OpenPort(pwnd);
_gfx->OpenPort((GUIPort *)pwnd);
r = dims; r = dims;
pwnd->rect = dims; pwnd->rect = dims;
if (restoreRect) if (restoreRect)
@ -150,13 +138,7 @@ GUIWindow *SciGUIwindowMgr::NewWindow(const Common::Rect &dims, const Common::Re
pwnd->uSaveFlag = (arg8 == 0xFFFF ? 1 : 3); pwnd->uSaveFlag = (arg8 == 0xFFFF ? 1 : 3);
if (title && (style & kTitle)) { if (title && (style & kTitle)) {
HEAPHANDLE hTitle = heapNewPtr((uint16)strlen(title) + 1, kDataString, title); pwnd->title = title;
if (!hTitle) {
warning("Can't open window!");
return 0;
}
pwnd->hTitle = hTitle;
strcpy((char *)heap2Ptr(hTitle), title);
} }
r = dims; r = dims;
@ -229,10 +211,10 @@ void SciGUIwindowMgr::DrawWindow(GUIWindow *pWnd) {
_gfx->FrameRect(r); _gfx->FrameRect(r);
r.grow(-1); r.grow(-1);
_gfx->FillRect(r, 1, 0); _gfx->FillRect(r, 1, 0);
if (pWnd->hTitle) { if (!pWnd->title.empty()) {
int16 oldcolor = _gfx->GetPort()->penClr; int16 oldcolor = _gfx->GetPort()->penClr;
_gfx->PenColor(255); _gfx->PenColor(255);
_gfx->TextBox((char *)heap2Ptr(pWnd->hTitle), 1, r, 1, 0); _gfx->TextBox(pWnd->title.c_str(), 1, r, 1, 0);
_gfx->PenColor(oldcolor); _gfx->PenColor(oldcolor);
} }
@ -258,12 +240,10 @@ void SciGUIwindowMgr::DisposeWindow(GUIWindow *pWnd, int16 arg2) {
_gfx->ShowBits(pWnd->restoreRect, 1); _gfx->ShowBits(pWnd->restoreRect, 1);
// else // else
// g_sci->ReAnimate(&pwnd->dims); // g_sci->ReAnimate(&pwnd->dims);
HEAPHANDLE hh = ptr2heap((byte *)pWnd); _windowList.remove(pWnd);
windowList.remove(hh); _gfx->SetPort(_windowList.back());
SelectWindow(windowList.back()); _windowsById[pWnd->id] = 0;
if (pWnd->hTitle) delete pWnd;
heapDisposePtr(pWnd->hTitle);
heapDisposePtr(hh);
} }
void SciGUIwindowMgr::UpdateWindow(GUIWindow *wnd) { void SciGUIwindowMgr::UpdateWindow(GUIWindow *wnd) {

View file

@ -27,19 +27,16 @@
#define SCI_GUI_WINDOWMGR_H #define SCI_GUI_WINDOWMGR_H
#include "common/list.h" #include "common/list.h"
#include "common/array.h"
namespace Sci { namespace Sci {
// TODO: remove HEAPHANDLE and make a list of GUIWindow pointers instead
typedef uint16 HEAPHANDLE;
class SciGUIwindowMgr { class SciGUIwindowMgr {
public: public:
SciGUIwindowMgr(EngineState *state, SciGUIgfx *gfx); SciGUIwindowMgr(EngineState *state, SciGUIgfx *gfx);
~SciGUIwindowMgr(); ~SciGUIwindowMgr();
int16 isFrontWindow(GUIWindow *wnd); int16 isFrontWindow(GUIWindow *wnd);
void SelectWindow(HEAPHANDLE hh);
void BeginUpdate(GUIWindow *wnd); void BeginUpdate(GUIWindow *wnd);
void EndUpdate(GUIWindow *wnd); void EndUpdate(GUIWindow *wnd);
GUIWindow *NewWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, uint16 arg8, uint16 argA); GUIWindow *NewWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, uint16 arg8, uint16 argA);
@ -47,14 +44,22 @@ public:
void DisposeWindow(GUIWindow *pWnd, int16 arg2); void DisposeWindow(GUIWindow *pWnd, int16 arg2);
void UpdateWindow(GUIWindow *wnd); void UpdateWindow(GUIWindow *wnd);
GUIPort *getPortById(uint16 id) const { return _windowsById[id]; }
GUIPort *_wmgrPort; GUIPort *_wmgrPort;
GUIWindow *_picWind; GUIWindow *_picWind;
private: private:
typedef Common::List<GUIPort *> PortList;
EngineState *_s; EngineState *_s;
SciGUIgfx *_gfx; SciGUIgfx *_gfx;
Common::List<HEAPHANDLE> windowList; /** The list of open 'windows' (and ports), in visual order. */
PortList _windowList;
/** The list of all open 'windows' (and ports), ordered by their id. */
Common::Array<GUIPort *> _windowsById;
}; };
} // End of namespace Sci } // End of namespace Sci

View file

@ -58,7 +58,6 @@ MODULE_OBJS = \
gui/gui.o \ gui/gui.o \
gui/gui_font.o \ gui/gui_font.o \
gui/gui_gfx.o \ gui/gui_gfx.o \
gui/gui_memmgr.o \
gui/gui_picture.o \ gui/gui_picture.o \
gui/gui_screen.o \ gui/gui_screen.o \
gui/gui_view.o \ gui/gui_view.o \