Hello, world.
I'm having trouble with a program I'm trying to write. I have a record called 'Window' that contains data for a window, including a dynamic array for its contents and color information (You'll note that I have commented a static version of the arrays):
type
XYType = record
X,Y:byte;
end;
ContentType = array of array of string[1];
ContentColorType = array of array of byte;
WindowType = record
DoubleBorder:boolean;
Origin,Size:XYType;
// Content:array[1..80,1..25] of string[1];
// ContentColor:array[1..80,1..25] of byte;
Content:ContentType;
ContentColor:ContentColorType;
Title:string[MaxTitleLength];
end;
WindowListType = record
InUse:boolean;
Window:WindowType
end;
I have two procedures (rather a function and a procedure) called CreateWindow and DestroyWindow, and they're fighting with each other! I can successfully call CreateWindow and DestroyWindow once, and the next call to CreateWindow causes an access violation...but they work perfectly with the static version of the arrays.
(Be aware, that I have created empty arrays of size 1,1 called Content and ContentColor, and an empty window called NulWindow in the program's initialization)
function CreateWindow(w:WindowType):byte;
// modifies WindowList
var
AvailWindow,counter:byte;
begin
CreateWindow:=0;
w.Content:=copy(Content);
w.ContentColor:=copy(ContentColor);
with w do
begin
SetLength(Content, Size.X, Size.Y);
SetLength(ContentColor, Size.X, Size.Y);
end;
AvailWindow:=0;
counter:=1;
repeat
if not WindowList[counter].InUse then
begin
AvailWindow:=counter;
counter:=MaxWindows+1;
end
else
counter:=counter+1;
until counter=MaxWindows+1;
if AvailWindow=0 then
error('No Availiable Windows')
else
begin
WindowList[AvailWindow].InUse:=true;
// POTENTIAL ERROR HERE, WORKS ONCE
WindowList[AvailWindow].Window:=w;
ActiveWindow:=AvailWindow;
RedrawWindows;
CreateWindow:=AvailWindow;
end;
end;
procedure DestroyWindow(W:byte);
//modifies WindowList
var
counter:byte;
begin
if W=0 then
begin
for counter:=1 to MaxWindows do
begin
WindowList[counter].InUse:=false;
// POTENTIAL ERROR HERE
WindowList[counter].Window:=NulWindow;
// Possible solution below, Does NOT fix problem...
WindowList[counter].Window.Content:=copy(Content);
WindowList[counter].Window.ContentColor:=copy(ContentColor);
end;
DrawBG;
end
else
begin
if not WindowList[W].InUse then
error('DestroyWindow: Window not InUse');
WindowList[W].InUse:=false;
// POTENTIAL ERROR HERE
WindowList[W].Window:=NulWindow;
WindowList[W].Window.Content:=copy(Content);
WindowList[W].Window.ContentColor:=copy(ContentColor);
end;
counter:=MaxWindows;
repeat
if not WindowList[counter].InUse then counter:=counter-1;
until WindowList[counter].InUse or (counter<1);
ActiveWindow:=counter;
RedrawWindows;
end;
I'm aware that I cannot simply use := to copy the contents of a dynamic array, as that would just copy a pointer, not an array. So I've used 'copy' where I think I'm supposed to (with the static arrays, the 'copy' function calls wouldn't be used). However, there are places where I copy the entire record with := (I've put a comment just before each instance) and I think this must be what's causing the access violation.
I've been banging my head against this wall for a couple of days now. I could always go back to the static arrays, but 80x25 arrays for every window, including tiny ones, seems really wasteful, and totally against the grain for my goal of creating a tiny-footprint text-mode windowed UI for use with other projects.
Any advice would be greatly appreciated!
-McDoob