Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit c1b3edb

Browse files
committed
[[ StacksAsBehaviors ]] Behavior property expanded to allow stacks.
The behavior property can now be set to use either the script of a button, or the script of a stack. This is file-format-backwards-compatible change - referencing a stack will cause the behavior reference to be written out to the stackfile with id 0 which an accessible runtime object can never have an id of. When fetching the behavior property it might now either be a string of the form: button id <id> of stack <stack> or stack <stack> This might have implications on scripts which process the behavior property directly, rather than relying on chunk parsing. To extend behaviors to be able to reference any object we will need to extend the chunk syntax to allow object id <id> of stack <stack> This is because ids can uniquely identify cards, audio clips, video clips as well as controls. Conflicts: engine/src/object.h engine/src/objectprops.cpp
1 parent 89c6a07 commit c1b3edb

File tree

13 files changed

+105
-63
lines changed

13 files changed

+105
-63
lines changed

engine/src/aclip.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,10 @@ Exec_stat MCAudioClip::setprop_legacy(uint4 parid, Properties p, MCExecPoint &ep
268268
Boolean MCAudioClip::del()
269269
{
270270
getstack()->removeaclip(this);
271-
return True;
271+
272+
// MCObject now does things on del(), so we must make sure we finish by
273+
// calling its implementation.
274+
return MCObject::del();
272275
}
273276

274277
void MCAudioClip::paste(void)

engine/src/button.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -386,11 +386,6 @@ MCButton::~MCButton()
386386
// particuarly if the button had icons.
387387
while (opened)
388388
close();
389-
390-
// MW-2008-10-28: [[ ParentScripts ]] Flush the parent scripts table if
391-
// tsub has the state flag marked.
392-
if (getstate(CS_IS_PARENTSCRIPT))
393-
MCParentScript::FlushObject(this);
394389

395390
delete icons;
396391
freemenu(True);
@@ -446,15 +441,7 @@ bool MCButton::visit(MCVisitStyle p_style, uint32_t p_part, MCObjectVisitor* p_v
446441

447442
void MCButton::open()
448443
{
449-
// MW-2008-10-28: [[ ParentScripts ]] We have to preserve the setting of the
450-
// CS_IS_PARENTSCRIPT state.
451-
if (!getstate(CS_IS_PARENTSCRIPT))
452-
MCControl::open();
453-
else
454-
{
455-
MCControl::open();
456-
setstate(True, CS_IS_PARENTSCRIPT);
457-
}
444+
MCControl::open();
458445

459446
// MW-2011-02-08: [[ Bug 9382 ]] Make sure we reset icons when opening and the state
460447
// has changed (i.e. background transition has occured).

engine/src/card.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,10 @@ Boolean MCCard::del()
13421342
}
13431343
while (optr != objptrs);
13441344
}
1345-
return True;
1345+
1346+
// MCObject now does things on del(), so we must make sure we finish by
1347+
// calling its implementation.
1348+
return MCObject::del();
13461349
}
13471350

13481351
struct UpdateDataIdsVisitor: public MCObjectVisitor

engine/src/control.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ MCControl::~MCControl()
128128
{
129129
if (focused == this)
130130
focused = NULL;
131+
131132
MCscreen->stopmove(this, False);
132133

133134
// MW-2009-06-11: [[ Bitmap Effects ]] Destroy the bitmap effects
@@ -144,6 +145,7 @@ void MCControl::open()
144145
if (!getstate(CS_KEEP_LAYER))
145146
layer_resetattrs();
146147

148+
// Make sure we keep state which should be preserved across open.
147149
state = (state & (CS_NO_MESSAGES | CS_NO_FILE | CS_SELECTED)) | (state & CS_KEEP_LAYER);
148150
}
149151

@@ -789,15 +791,6 @@ Boolean MCControl::del()
789791
}
790792
}
791793

792-
// MW-2008-10-28: [[ ParentScripts ]] If the object is marked as being used
793-
// as a parentScript, flush the parentScript table so we don't get any
794-
// dangling pointers.
795-
if (getstate(CS_IS_PARENTSCRIPT) && gettype() == CT_BUTTON)
796-
{
797-
MCParentScript::FlushObject(this);
798-
setstate(False, CS_IS_PARENTSCRIPT);
799-
}
800-
801794
// IM-2012-05-16 [[ BZ 10212 ]] deleting the dragtarget control in response
802795
// to a 'dragdrop' message would leave these globals pointing to the deleted
803796
// object, leading to an infinite loop if the target was a field
@@ -810,7 +803,9 @@ Boolean MCControl::del()
810803
if (MCdragsource == this)
811804
MCdragsource = nil;
812805

813-
return True;
806+
// MCObject now does things on del(), so we must make sure we finish by
807+
// calling its implementation.
808+
return MCObject::del();
814809
}
815810

816811
void MCControl::paste(void)

engine/src/exec-interface-object.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,9 +1596,20 @@ void MCObject::GetParentScript(MCExecContext& ctxt, MCStringRef& r_parent_script
15961596
MCParentScript *t_parent;
15971597
t_parent = parent_script -> GetParent();
15981598

1599-
if (MCStringFormat(r_parent_script, "button id %d of stack \"%@\"", t_parent -> GetObjectId(),
1600-
t_parent -> GetObjectStack()))
1601-
return;
1599+
if (t_parent -> GetObjectId() != 0)
1600+
{
1601+
if (MCStringFormat(r_parent_script, "button id %d of stack \"%@\"", t_parent -> GetObjectId(),
1602+
t_parent -> GetObjectStack()))
1603+
1604+
return;
1605+
}
1606+
else
1607+
{
1608+
if (MCStringFormat(r_parent_script, "stack \"%@\"",
1609+
t_parent -> GetObjectStack()))
1610+
1611+
return;
1612+
}
16021613

16031614
ctxt . Throw();
16041615
}
@@ -1648,10 +1659,6 @@ void MCObject::SetParentScript(MCExecContext& ctxt, MCStringRef new_parent_scrip
16481659
if (t_success)
16491660
t_success = t_chunk -> getobj(ctxt, t_object, t_part_id, False);
16501661

1651-
// Check that the object is a button
1652-
if (t_success)
1653-
t_success = t_object -> gettype() == CT_BUTTON;
1654-
16551662
// MW-2013-07-18: [[ Bug 11037 ]] Make sure the object isn't in the hierarchy
16561663
// of the parentScript.
16571664
bool t_is_cyclic;
@@ -1694,6 +1701,10 @@ void MCObject::SetParentScript(MCExecContext& ctxt, MCStringRef new_parent_scrip
16941701
uint32_t t_id;
16951702
t_id = t_object -> getid();
16961703

1704+
// If the object is a stack, then it has an id of zero.
1705+
if (t_object -> gettype() == CT_STACK)
1706+
t_id = 0;
1707+
16971708
MCNameRef t_stack;
16981709
t_stack = t_object -> getstack() -> getname();
16991710

@@ -1728,7 +1739,7 @@ void MCObject::SetParentScript(MCExecContext& ctxt, MCStringRef new_parent_scrip
17281739
// is because the inheritence hierarchy has been updated and so the
17291740
// super_use chains need to be remade.
17301741
MCParentScript *t_this_parent;
1731-
if (getstate(CS_IS_PARENTSCRIPT))
1742+
if (getisparentscript())
17321743
{
17331744
t_this_parent = MCParentScript::Lookup(this);
17341745
if (t_success && t_this_parent != nil)

engine/src/hndlrlst.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ Parse_stat MCHandlerlist::parse(MCObject *objptr, MCStringRef script)
427427
// (for example 'getdefaultprinter()' on Linux) so don't indirect in this case.
428428
bool t_is_parent_script;
429429
if (objptr != NULL)
430-
t_is_parent_script = objptr -> getstate(CS_IS_PARENTSCRIPT) && objptr -> gettype() == CT_BUTTON;
430+
t_is_parent_script = objptr -> getisparentscript();
431431
else
432432
t_is_parent_script = false;
433433

engine/src/objdefs.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,10 +401,6 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
401401
#define CS_MOUSE_UP_MENU (1UL << 21)
402402
#define CS_VISITED (1UL << 22)
403403

404-
// MW-2008-10-28: [[ ParentScripts ]] If this state flag is set it means that
405-
// the button is referenced as a parentScript.
406-
#define CS_IS_PARENTSCRIPT (1UL << 21)
407-
408404
// MCImage state
409405
#define CS_BEEN_MOVED (1UL << 13)
410406

engine/src/object.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,12 @@ MCObject::MCObject()
149149

150150
// MW-2012-10-10: [[ IdCache ]]
151151
m_in_id_cache = false;
152-
152+
153153
// IM-2013-04-16: Initialize to false;
154154
m_script_encrypted = false;
155+
156+
// Object's do not begin in the parentScript table.
157+
m_is_parent_script = false;
155158
}
156159

157160
MCObject::MCObject(const MCObject &oref) : MCDLlist(oref)
@@ -243,6 +246,10 @@ MCObject::MCObject(const MCObject &oref) : MCDLlist(oref)
243246

244247
// MW-2012-10-10: [[ IdCache ]]
245248
m_in_id_cache = false;
249+
250+
// Cloned objects have a different identifier so are not in the parentScript
251+
// table at the start.
252+
m_is_parent_script = false;
246253
}
247254

248255
MCObject::~MCObject()
@@ -295,6 +302,10 @@ MCObject::~MCObject()
295302
// all deletions vector through 'scheduledelete'.
296303
if (m_in_id_cache)
297304
getstack() -> uncacheobjectbyid(this);
305+
306+
// If this object is a parent-script make sure we flush it from the table.
307+
if (m_is_parent_script)
308+
MCParentScript::FlushObject(this);
298309
}
299310

300311
Chunk_term MCObject::gettype() const
@@ -806,8 +817,15 @@ void MCObject::deselect()
806817

807818
Boolean MCObject::del()
808819
{
809-
fprintf(stderr, "Object: ERROR tried to delete %s\n", getname_cstring());
810-
return False;
820+
// If the object is marked as being used as a parentScript, flush the parentScript
821+
// table so we don't get any dangling pointers.
822+
if (m_is_parent_script)
823+
{
824+
MCParentScript::FlushObject(this);
825+
m_is_parent_script = false;
826+
}
827+
828+
return True;
811829
}
812830

813831
void MCObject::paste(void)
@@ -3815,20 +3833,26 @@ bool MCObject::resolveparentscript(void)
38153833
t_stack = getstack() -> findstackname(t_script -> GetObjectStack());
38163834

38173835
// Next search for the control we need.
3818-
MCControl *t_control;
3819-
t_control = NULL;
3836+
MCObject *t_object;
3837+
t_object = NULL;
38203838
if (t_stack != NULL)
3821-
t_control = t_stack -> getcontrolid(CT_BUTTON, t_script -> GetObjectId(), true);
3839+
{
3840+
if (t_script -> GetObjectId() != 0)
3841+
t_object = t_stack -> getcontrolid(CT_BUTTON, t_script -> GetObjectId(), true);
3842+
else
3843+
t_object = t_stack;
3844+
}
38223845

38233846
// If we found a control, resolve the parent script. Otherwise block it.
3824-
if (t_control != NULL)
3847+
if (t_object != NULL &&
3848+
t_object != this)
38253849
{
3826-
t_script -> Resolve(t_control);
3850+
t_script -> Resolve(t_object);
38273851

38283852
// MW-2015-05-30: [[ InheritedPscripts ]] Next we must ensure the
38293853
// existence of the inheritence hierarchy, so resolve the parentScript's
38303854
// parentScript.
3831-
if (!t_control -> resolveparentscript())
3855+
if (!t_object -> resolveparentscript())
38323856
return false;
38333857

38343858
// MW-2015-05-30: [[ InheritedPscripts ]] And then make sure it creates its

engine/src/object.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,9 @@ class MCObject : public MCDLlist
231231

232232
// IM-2013-04-16: [[ BZ 10848 ]] // flag to record encrypted state of object script
233233
bool m_script_encrypted : 1;
234+
235+
// If this is true, then this object is in the parentScript resolution table.
236+
bool m_is_parent_script : 1;
234237

235238
MCStringRef tooltip;
236239

@@ -794,6 +797,16 @@ class MCObject : public MCDLlist
794797
return m_in_id_cache;
795798
}
796799

800+
void setisparentscript(bool p_value)
801+
{
802+
m_is_parent_script = p_value;
803+
}
804+
805+
bool getisparentscript(void)
806+
{
807+
return m_is_parent_script;
808+
}
809+
797810
MCRectangle measuretext(MCStringRef p_text, bool p_is_unicode);
798811

799812
// Currently non-functional: always returns false

engine/src/objectprops.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -581,9 +581,13 @@ Exec_stat MCObject::getprop_legacy(uint4 parid, Properties which, MCExecPoint &e
581581
MCParentScript *t_parent;
582582
t_parent = parent_script -> GetParent();
583583

584-
ep . setstringf("button id %d of stack \"%@\"",
585-
t_parent -> GetObjectId(),
586-
MCNameGetString(t_parent -> GetObjectStack()));
584+
if (t_parent -> GetObjectId() != 0)
585+
ep . setstringf("button id %d of stack \"%s\"",
586+
t_parent -> GetObjectId(),
587+
MCNameGetCString(t_parent -> GetObjectStack()));
588+
else
589+
ep . setstringf("stack \"%s\"",
590+
MCNameGetCString(t_parent -> GetObjectStack()));
587591
}
588592
}
589593
break;
@@ -1234,11 +1238,13 @@ Exec_stat MCObject::setparentscriptprop(MCExecPoint& ep)
12341238
uint32_t t_part_id;
12351239
if (t_stat == ES_NORMAL)
12361240
t_stat = t_chunk -> getobj(ep2, t_object, t_part_id, False);
1237-
1238-
// Check that the object is a button
1239-
if (t_stat == ES_NORMAL && t_object -> gettype() != CT_BUTTON)
1240-
t_stat = ES_ERROR;
12411241

1242+
// Check that the object is a button or a stack.
1243+
if (t_stat == ES_NORMAL &&
1244+
t_object -> gettype() != CT_BUTTON &&
1245+
t_object -> gettype() != CT_STACK)
1246+
t_stat = ES_ERROR;
1247+
12421248
// MW-2013-07-18: [[ Bug 11037 ]] Make sure the object isn't in the hierarchy
12431249
// of the parentScript.
12441250
bool t_is_cyclic;
@@ -1315,7 +1321,7 @@ Exec_stat MCObject::setparentscriptprop(MCExecPoint& ep)
13151321
// is because the inheritence hierarchy has been updated and so the
13161322
// super_use chains need to be remade.
13171323
MCParentScript *t_this_parent;
1318-
if (getstate(CS_IS_PARENTSCRIPT))
1324+
if (m_is_parent_script)
13191325
{
13201326
t_this_parent = MCParentScript::Lookup(this);
13211327
if (t_this_parent != nil)

0 commit comments

Comments
 (0)