Skip to content

Commit 24ddb2b

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.
1 parent b135758 commit 24ddb2b

File tree

12 files changed

+86
-55
lines changed

12 files changed

+86
-55
lines changed

engine/src/aclip.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,10 @@ Exec_stat MCAudioClip::setprop(uint4 parid, Properties p, MCExecPoint &ep, Boole
244244
Boolean MCAudioClip::del()
245245
{
246246
getstack()->removeaclip(this);
247-
return True;
247+
248+
// MCObject now does things on del(), so we must make sure we finish by
249+
// calling its implementation.
250+
return MCObject::del();
248251
}
249252

250253
void MCAudioClip::paste(void)

engine/src/button.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,6 @@ MCButton::~MCButton()
365365
// particuarly if the button had icons.
366366
while (opened)
367367
close();
368-
369-
// MW-2008-10-28: [[ ParentScripts ]] Flush the parent scripts table if
370-
// tsub has the state flag marked.
371-
if (getstate(CS_IS_PARENTSCRIPT))
372-
MCParentScript::FlushObject(this);
373368

374369
delete icons;
375370
freemenu(True);
@@ -425,15 +420,7 @@ bool MCButton::visit(MCVisitStyle p_style, uint32_t p_part, MCObjectVisitor* p_v
425420

426421
void MCButton::open()
427422
{
428-
// MW-2008-10-28: [[ ParentScripts ]] We have to preserve the setting of the
429-
// CS_IS_PARENTSCRIPT state.
430-
if (!getstate(CS_IS_PARENTSCRIPT))
431-
MCControl::open();
432-
else
433-
{
434-
MCControl::open();
435-
setstate(True, CS_IS_PARENTSCRIPT);
436-
}
423+
MCControl::open();
437424

438425
// MW-2011-02-08: [[ Bug 9382 ]] Make sure we reset icons when opening and the state
439426
// 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
@@ -1253,7 +1253,10 @@ Boolean MCCard::del()
12531253
}
12541254
while (optr != objptrs);
12551255
}
1256-
return True;
1256+
1257+
// MCObject now does things on del(), so we must make sure we finish by
1258+
// calling its implementation.
1259+
return MCObject::del();
12571260
}
12581261

12591262
struct UpdateDataIdsVisitor: public MCObjectVisitor

engine/src/control.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ MCControl::~MCControl()
9696
{
9797
if (focused == this)
9898
focused = NULL;
99+
99100
MCscreen->stopmove(this, False);
100101

101102
// MW-2009-06-11: [[ Bitmap Effects ]] Destroy the bitmap effects
@@ -112,6 +113,7 @@ void MCControl::open()
112113
if (!getstate(CS_KEEP_LAYER))
113114
layer_resetattrs();
114115

116+
// Make sure we keep state which should be preserved across open.
115117
state = (state & (CS_NO_MESSAGES | CS_NO_FILE | CS_SELECTED)) | (state & CS_KEEP_LAYER);
116118
}
117119

@@ -756,15 +758,6 @@ Boolean MCControl::del()
756758
}
757759
}
758760

759-
// MW-2008-10-28: [[ ParentScripts ]] If the object is marked as being used
760-
// as a parentScript, flush the parentScript table so we don't get any
761-
// dangling pointers.
762-
if (getstate(CS_IS_PARENTSCRIPT) && gettype() == CT_BUTTON)
763-
{
764-
MCParentScript::FlushObject(this);
765-
setstate(False, CS_IS_PARENTSCRIPT);
766-
}
767-
768761
// IM-2012-05-16 [[ BZ 10212 ]] deleting the dragtarget control in response
769762
// to a 'dragdrop' message would leave these globals pointing to the deleted
770763
// object, leading to an infinite loop if the target was a field
@@ -777,7 +770,9 @@ Boolean MCControl::del()
777770
if (MCdragsource == this)
778771
MCdragsource = nil;
779772

780-
return True;
773+
// MCObject now does things on del(), so we must make sure we finish by
774+
// calling its implementation.
775+
return MCObject::del();
781776
}
782777

783778
void MCControl::paste(void)

engine/src/hndlrlst.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ Parse_stat MCHandlerlist::parse(MCObject *objptr, const char *script)
401401
// (for example 'getdefaultprinter()' on Linux) so don't indirect in this case.
402402
bool t_is_parent_script;
403403
if (objptr != NULL)
404-
t_is_parent_script = objptr -> getstate(CS_IS_PARENTSCRIPT) && objptr -> gettype() == CT_BUTTON;
404+
t_is_parent_script = objptr -> getisparentscript();
405405
else
406406
t_is_parent_script = false;
407407

engine/src/objdefs.h

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

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

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)
@@ -240,6 +243,10 @@ MCObject::MCObject(const MCObject &oref) : MCDLlist(oref)
240243

241244
// MW-2012-10-10: [[ IdCache ]]
242245
m_in_id_cache = false;
246+
247+
// Cloned objects have a different identifier so are not in the parentScript
248+
// table at the start.
249+
m_is_parent_script = false;
243250
}
244251

245252
MCObject::~MCObject()
@@ -290,6 +297,10 @@ MCObject::~MCObject()
290297
// all deletions vector through 'scheduledelete'.
291298
if (m_in_id_cache)
292299
getstack() -> uncacheobjectbyid(this);
300+
301+
// If this object is a parent-script make sure we flush it from the table.
302+
if (m_is_parent_script)
303+
MCParentScript::FlushObject(this);
293304
}
294305

295306
Chunk_term MCObject::gettype() const
@@ -805,8 +816,15 @@ void MCObject::deselect()
805816

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

812830
void MCObject::paste(void)
@@ -3610,20 +3628,26 @@ bool MCObject::resolveparentscript(void)
36103628
t_stack = getstack() -> findstackname(MCNameGetOldString(t_script -> GetObjectStack()));
36113629

36123630
// Next search for the control we need.
3613-
MCControl *t_control;
3614-
t_control = NULL;
3631+
MCObject *t_object;
3632+
t_object = NULL;
36153633
if (t_stack != NULL)
3616-
t_control = t_stack -> getcontrolid(CT_BUTTON, t_script -> GetObjectId(), true);
3634+
{
3635+
if (t_script -> GetObjectId() != 0)
3636+
t_object = t_stack -> getcontrolid(CT_BUTTON, t_script -> GetObjectId(), true);
3637+
else
3638+
t_object = t_stack;
3639+
}
36173640

36183641
// If we found a control, resolve the parent script. Otherwise block it.
3619-
if (t_control != NULL)
3642+
if (t_object != NULL &&
3643+
t_object != this)
36203644
{
3621-
t_script -> Resolve(t_control);
3645+
t_script -> Resolve(t_object);
36223646

36233647
// MW-2015-05-30: [[ InheritedPscripts ]] Next we must ensure the
36243648
// existence of the inheritence hierarchy, so resolve the parentScript's
36253649
// parentScript.
3626-
if (!t_control -> resolveparentscript())
3650+
if (!t_object -> resolveparentscript())
36273651
return false;
36283652

36293653
// 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
@@ -216,6 +216,9 @@ class MCObject : public MCDLlist
216216

217217
// IM-2013-04-16: [[ BZ 10848 ]] // flag to record encrypted state of object script
218218
bool m_script_encrypted : 1;
219+
220+
// If this is true, then this object is in the parentScript resolution table.
221+
bool m_is_parent_script : 1;
219222

220223
char *tooltip;
221224

@@ -697,6 +700,16 @@ class MCObject : public MCDLlist
697700
{
698701
return m_in_id_cache;
699702
}
703+
704+
void setisparentscript(bool p_value)
705+
{
706+
m_is_parent_script = p_value;
707+
}
708+
709+
bool getisparentscript(void)
710+
{
711+
return m_is_parent_script;
712+
}
700713

701714
// IM-2013-02-11 image change notification (used by button icons, field images, etc.)
702715
// returns true if the referenced image is still in use by this object

engine/src/objectprops.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,13 @@ Exec_stat MCObject::getprop(uint4 parid, Properties which, MCExecPoint &ep, Bool
326326
MCParentScript *t_parent;
327327
t_parent = parent_script -> GetParent();
328328

329-
ep . setstringf("button id %d of stack \"%s\"",
330-
t_parent -> GetObjectId(),
331-
MCNameGetCString(t_parent -> GetObjectStack()));
329+
if (t_parent -> GetObjectId() != 0)
330+
ep . setstringf("button id %d of stack \"%s\"",
331+
t_parent -> GetObjectId(),
332+
MCNameGetCString(t_parent -> GetObjectStack()));
333+
else
334+
ep . setstringf("stack \"%s\"",
335+
MCNameGetCString(t_parent -> GetObjectStack()));
332336
}
333337
}
334338
break;
@@ -967,11 +971,13 @@ Exec_stat MCObject::setparentscriptprop(MCExecPoint& ep)
967971
uint32_t t_part_id;
968972
if (t_stat == ES_NORMAL)
969973
t_stat = t_chunk -> getobj(ep2, t_object, t_part_id, False);
970-
971-
// Check that the object is a button
972-
if (t_stat == ES_NORMAL && t_object -> gettype() != CT_BUTTON)
973-
t_stat = ES_ERROR;
974974

975+
// Check that the object is a button or a stack.
976+
if (t_stat == ES_NORMAL &&
977+
t_object -> gettype() != CT_BUTTON &&
978+
t_object -> gettype() != CT_STACK)
979+
t_stat = ES_ERROR;
980+
975981
// MW-2013-07-18: [[ Bug 11037 ]] Make sure the object isn't in the hierarchy
976982
// of the parentScript.
977983
bool t_is_cyclic;
@@ -1048,7 +1054,7 @@ Exec_stat MCObject::setparentscriptprop(MCExecPoint& ep)
10481054
// is because the inheritence hierarchy has been updated and so the
10491055
// super_use chains need to be remade.
10501056
MCParentScript *t_this_parent;
1051-
if (getstate(CS_IS_PARENTSCRIPT))
1057+
if (m_is_parent_script)
10521058
{
10531059
t_this_parent = MCParentScript::Lookup(this);
10541060
if (t_this_parent != nil)

engine/src/parentscript.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -366,9 +366,8 @@ void MCParentScript::Resolve(MCObject *p_object)
366366
// Unblock this
367367
m_blocked = false;
368368

369-
// Mark the object as being used as a parent script - note that this is a
370-
// button state flag since we currently restrict parentScripts to buttons.
371-
m_object -> setstate(True, CS_IS_PARENTSCRIPT);
369+
// Mark the object as being used as a parent script.
370+
m_object -> setisparentscript(true);
372371

373372
// Mark the object's stack as having an object which is a parent script.
374373
MCStack *t_stack;
@@ -621,7 +620,7 @@ void MCParentScript::Detach(MCParentScriptUse *p_use)
621620
// Unset the object's IS_PARENTSCRIPT state as it is no longer being used as
622621
// one.
623622
if (m_object != NULL)
624-
m_object -> setstate(False, CS_IS_PARENTSCRIPT);
623+
m_object -> setisparentscript(false);
625624

626625
// Now delete our state
627626
delete this;

0 commit comments

Comments
 (0)