/* Copyright (C) 2003-2015 LiveCode Ltd.
This file is part of LiveCode.
LiveCode is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License v3 as published by the Free
Software Foundation.
LiveCode 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 LiveCode. If not see . */
#include "prefix.h"
#include "globdefs.h"
#include "objdefs.h"
#include "parsedef.h"
#include "filedefs.h"
#include "mcio.h"
#include "dispatch.h"
#include "object.h"
#include "stack.h"
#include "card.h"
#include "aclip.h"
#include "vclip.h"
#include "player.h"
#include "group.h"
#include "scriptpt.h"
//#include "execpt.h"
#include "handler.h"
#include "cmds.h"
#include "mcerror.h"
#include "chunk.h"
#include "param.h"
#include "util.h"
#include "date.h"
#include "debug.h"
#include "printer.h"
#include "variable.h"
#include "securemode.h"
#include "osspec.h"
#include "image.h"
#include "font.h"
#include "hndlrlst.h"
#include "globals.h"
#include "license.h"
#include "socket.h"
#include "exec.h"
#include "syntax.h"
MCAccept::~MCAccept()
{
delete port;
delete message;
}
Parse_stat MCAccept::parse(MCScriptPoint &sp)
{
initpoint(sp);
if (sp.skip_token(SP_ACCEPT, TT_UNDEFINED, AC_SECURE) == PS_NORMAL)
secure = True;
else if (sp.skip_token(SP_ACCEPT, TT_UNDEFINED, AC_DATAGRAM) == PS_NORMAL)
datagram = True;
sp.skip_token(SP_ACCEPT, TT_UNDEFINED, AC_UNDEFINED); // connections
sp.skip_token(SP_ACCEPT, TT_UNDEFINED, AC_UNDEFINED); // on
sp.skip_token(SP_ACCEPT, TT_UNDEFINED, AC_UNDEFINED); // port
if (sp.parseexp(False, True, &port) != PS_NORMAL)
{
MCperror->add(PE_ACCEPT_BADEXP, sp);
return PS_ERROR;
}
sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH); // with
sp.skip_token(SP_SUGAR, TT_CHUNK, CT_UNDEFINED); // message
if (sp.parseexp(False, True, &message) != PS_NORMAL)
{
MCperror->add(PE_ACCEPT_BADEXP, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL
&& sp.skip_token(SP_SSL, TT_STATEMENT, SSL_VERIFICATION) != PS_NORMAL)
{
//make error
MCperror->add(PE_OPEN_BADMESSAGE, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_SUGAR, TT_PREP, PT_WITHOUT) == PS_NORMAL
&& sp.skip_token(SP_SSL, TT_STATEMENT, SSL_VERIFICATION) == PS_NORMAL)
secureverify = False;
return PS_NORMAL;
}
void MCAccept::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCAccept */ LEGACY_EXEC
// MW-2005-01-28: Fix bug 2412 - accept doesn't clear the result.
MCresult -> clear(False);
if (MCsecuremode & MC_SECUREMODE_NETWORK)
{
MCeerror->add(EE_NETWORK_NOPERM, line, pos);
return ES_ERROR;
}
if (port->eval(ep) != ES_NORMAL || ep.ton() != ES_NORMAL)
{
MCeerror->add(EE_ACCEPT_BADEXP, line, pos);
return ES_ERROR;
}
uint2 port = ep.getuint2();
if (message->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_ACCEPT_BADEXP, line, pos);
return ES_ERROR;
}
MCAutoNameRef t_message_name;
/* UNCHECKED */ ep . copyasnameref(t_message_name);
MCSocket *s = MCS_accept(port, ep.getobj(), t_message_name, datagram, secure, secureverify, NULL);
if (s != NULL)
{
MCU_realloc((char **)&MCsockets, MCnsockets,
MCnsockets + 1, sizeof(MCSocket *));
MCsockets[MCnsockets++] = s;
}
return ES_NORMAL;
#endif /* MCAccept */
uinteger_t t_port;
if (!ctxt . EvalExprAsUInt(port, EE_ACCEPT_BADEXP, t_port))
return;
MCNewAutoNameRef t_message;
if (!ctxt . EvalExprAsNameRef(message, EE_ACCEPT_BADEXP, &t_message))
return;
if (datagram)
MCNetworkExecAcceptDatagramConnectionsOnPort(ctxt, t_port, *t_message);
else if (secure)
MCNetworkExecAcceptSecureConnectionsOnPort(ctxt, t_port, *t_message, secureverify == True);
else
MCNetworkExecAcceptConnectionsOnPort(ctxt, t_port, *t_message);
}
void MCAccept::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
port -> compile(ctxt);
message -> compile(ctxt);
if (datagram)
MCSyntaxFactoryExecMethod(ctxt, kMCNetworkExecAcceptDatagramConnectionsOnPortMethodInfo);
else if (secure)
{
MCSyntaxFactoryEvalConstantBool(ctxt, secureverify == True);
MCSyntaxFactoryExecMethod(ctxt, kMCNetworkExecAcceptSecureConnectionsOnPortMethodInfo);
}
else
MCSyntaxFactoryExecMethod(ctxt, kMCNetworkExecAcceptConnectionsOnPortMethodInfo);
MCSyntaxFactoryEndStatement(ctxt);
}
MCBeep::~MCBeep()
{
delete times;
}
Parse_stat MCBeep::parse(MCScriptPoint &sp)
{
initpoint(sp);
MCScriptPoint oldsp(sp);
MCerrorlock++;
if (sp.parseexp(False, True, ×) != PS_NORMAL)
{
sp = oldsp;
delete times;
times = NULL;
}
MCerrorlock--;
return PS_NORMAL;
}
void MCBeep::exec_ctxt(MCExecContext& ctxt)
{
#ifdef /* MCBeep */ LEGACY_EXEC
uint4 i = 1;
if (times != NULL)
{
if (times->eval(ep) != ES_NORMAL || ep.ton() != ES_NORMAL)
{
MCeerror->add(EE_BEEP_BADEXP, line, pos);
return ES_ERROR;
}
i = ep.getuint4();
}
while (i--)
{
MCscreen->beep();
// MW-2010-01-08: [[ Bug 1690 ]] We need a break on all beeps but the last
if (i >= 1)
{
// MW-2008-03-17: [[ Bug 6098 ]] Make sure we check for an abort from wait
if (MCscreen->wait(BEEP_INTERVAL, False, False))
{
MCeerror -> add(EE_WAIT_ABORT, line, pos);
return ES_ERROR;
}
}
}
return ES_NORMAL;
#endif /* MCBeep */
uinteger_t t_count;
if (!ctxt . EvalOptionalExprAsUInt(times, 1, EE_BEEP_BADEXP, t_count))
return;
MCInterfaceExecBeep(ctxt, t_count);
}
void MCBeep::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
if (times != nil)
times -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantUInt(ctxt, 1);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecBeepMethodInfo);
MCSyntaxFactoryEndStatement(ctxt);
}
void MCBreakPoint::exec_ctxt(MCExecContext& ctxt)
{
#ifdef /* MCBreakPoint */ LEGACY_EXEC
MCB_break(ep, getline(), getpos());
return ES_NORMAL;
#endif /* MCBreakPoint */
MCDebuggingExecBreakpoint(ctxt, line, pos);
}
void MCBreakPoint::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
MCSyntaxFactoryEvalConstantUInt(ctxt, line);
MCSyntaxFactoryEvalConstantUInt(ctxt, pos);
MCSyntaxFactoryExecMethod(ctxt, kMCDebuggingExecBreakpointMethodInfo);
MCSyntaxFactoryEndStatement(ctxt);
}
MCCancel::~MCCancel()
{
delete m_id;
}
Parse_stat MCCancel::parse(MCScriptPoint &sp)
{
initpoint(sp);
if (sp . skip_token(SP_RESET, TT_UNDEFINED, RT_PRINTING) == PS_NORMAL)
{
m_id = NULL;
}
else if (sp.parseexp(False, True, &m_id) != PS_NORMAL)
{
MCperror->add(PE_CANCEL_BADEXP, sp);
return PS_ERROR;
}
return PS_NORMAL;
}
void MCCancel::exec_ctxt(MCExecContext& ctxt)
{
#ifdef /* MCCancel */ LEGACY_EXEC
if (id == NULL)
{
MCprinter -> Cancel();
if (MCprinter != MCsystemprinter)
{
delete MCprinter;
MCprinter = MCsystemprinter;
}
return ES_NORMAL;
}
if (id->eval(ep) != ES_NORMAL || ep.ton() != ES_NORMAL)
{
MCeerror->add(EE_CANCEL_IDNAN, line, pos);
return ES_ERROR;
}
if (ep.getuint4() != 0)
MCscreen->cancelmessageid(ep.getuint4());
return ES_NORMAL;
#endif /* MCCancel */
if (m_id == NULL)
MCPrintingExecCancelPrinting(ctxt);
else
{
integer_t t_id;
if (!ctxt . EvalExprAsInt(m_id, EE_CANCEL_IDNAN, t_id))
return;
MCEngineExecCancelMessage(ctxt, t_id);
}
}
void MCCancel::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
if (m_id == nil)
MCSyntaxFactoryExecMethod(ctxt, kMCPrintingExecCancelPrintingMethodInfo);
else
{
m_id -> compile(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCEngineExecCancelMessageMethodInfo);
}
MCSyntaxFactoryEndStatement(ctxt);
}
MCClickCmd::~MCClickCmd()
{
delete button;
delete location;
}
Parse_stat MCClickCmd::parse(MCScriptPoint &sp)
{
initpoint(sp);
sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH);
if (sp.skip_token(SP_FACTOR, TT_CHUNK, CT_BUTTON) == PS_NORMAL)
{
if (sp.parseexp(False, True, &button) != PS_NORMAL)
{
MCperror->add(PE_CLICK_BADBUTTONEXP, sp);
return PS_ERROR;
}
}
if (sp.skip_token(SP_FACTOR, TT_PREP, PT_AT) != PS_NORMAL)
{
MCperror->add(PE_CLICK_NOAT, sp);
return PS_ERROR;
}
if (sp.parseexp(False, True, &location) != PS_NORMAL)
{
MCperror->add(PE_CLICK_BADLOCATIONEXP, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL)
return getmods(sp, mstate);
return PS_NORMAL;
}
void MCClickCmd::exec_ctxt(MCExecContext& ctxt)
{
#ifdef /* MCClickCmd */ LEGACY_EXEC
if (button != NULL)
{
if (button->eval(ep) != ES_NORMAL || ep.ton() != ES_NORMAL)
{
MCeerror->add(EE_CLICK_BADBUTTON, line, pos);
return ES_ERROR;
}
which = ep.getuint2();
}
if (location->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_CLICK_BADLOCATION, line, pos);
return ES_ERROR;
}
MCPoint t_clickloc;
if (!MCU_stoi2x2(ep.getsvalue(), t_clickloc.x, t_clickloc.y))
{
MCeerror->add(EE_CLICK_NAP, line, pos, ep.getsvalue());
return ES_ERROR;
}
if (!MCdefaultstackptr->getopened()
|| !MCdefaultstackptr->haswindow())
{
MCeerror->add(EE_CLICK_STACKNOTOPEN, line, pos, ep.getsvalue());
return ES_ERROR;
}
// IM-2013-09-23: [[ FullscreenMode ]] get / set mouseloc & clickloc in view coords
MCPoint t_view_clickloc;
// IM-2014-01-06: [[ Bug 11624 ]] Use MCStack::stacktowindowloc to account for stack scroll
t_view_clickloc = MCdefaultstackptr->stacktowindowloc(t_clickloc);
uint2 oldmstate = MCmodifierstate;
uint2 oldbstate = MCbuttonstate;
MCStack *t_old_mousestack;
MCPoint t_old_mouseloc;
MCscreen->getmouseloc(t_old_mousestack, t_old_mouseloc);
MCscreen->setmouseloc(MCdefaultstackptr, t_view_clickloc);
MCmodifierstate = mstate;
MCbuttonstate |= 0x1L << (which - 1);
MCdispatcher->wmfocus_stack(MCdefaultstackptr, t_view_clickloc.x, t_view_clickloc.y);
MCmodifierstate = mstate;
MCbuttonstate |= 0x1L << (which - 1);
MCdispatcher->wmdown_stack(MCdefaultstackptr, which);
// **** NULL POINTER FIX
if (MCmousestackptr != NULL)
MCscreen->sync(MCmousestackptr->getw());
Boolean abort = MCscreen->wait(CLICK_INTERVAL, False, False);
MCscreen->setclickloc(MCdefaultstackptr, t_view_clickloc);
MCmodifierstate = mstate;
MCbuttonstate &= ~(0x1L << (which - 1));
MCdispatcher->wmup_stack(MCdefaultstackptr, which);
MCmodifierstate = oldmstate;
MCbuttonstate = oldbstate;
MCControl *mfocused = MCdefaultstackptr->getcard()->getmfocused();
if (mfocused != NULL
&& (mfocused->gettype() == CT_GRAPHIC
&& mfocused->getstate(CS_CREATE_POINTS)
|| (mfocused->gettype() == CT_IMAGE && mfocused->getstate(CS_DRAW)
&& MCdefaultstackptr->gettool(mfocused) == T_POLYGON)))
mfocused->doubleup(1); // cancel polygon create
if (t_old_mousestack == NULL || t_old_mousestack->getmode() != 0)
{
MCscreen->setmouseloc(t_old_mousestack, t_old_mouseloc);
if (t_old_mousestack != NULL)
MCdispatcher->wmfocus_stack(t_old_mousestack, t_old_mouseloc.x, t_old_mouseloc.y);
}
if (abort)
{
MCeerror->add(EE_CLICK_ABORT, line, pos);
return ES_ERROR;
}
return ES_NORMAL;
#endif /* MCClickCmd */
uinteger_t t_which;
if (!ctxt . EvalOptionalExprAsUInt(button, which, EE_CLICK_BADBUTTON, t_which))
return;
which = t_which;
MCPoint t_location;
if (!ctxt . EvalExprAsPoint(location, EE_CLICK_BADLOCATION, t_location))
return;
MCInterfaceExecClickCmd(ctxt, which, t_location, mstate);
}
void MCClickCmd::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
if (button != nil)
button -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantUInt(ctxt, which);
location -> compile(ctxt);
MCSyntaxFactoryEvalConstantUInt(ctxt, mstate);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecClickCmdMethodInfo);
MCSyntaxFactoryEndStatement(ctxt);
}
MCDrag::~MCDrag()
{
delete button;
delete startloc;
delete endloc;
}
Parse_stat MCDrag::parse(MCScriptPoint &sp)
{
initpoint(sp);
sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH);
if (sp.skip_token(SP_FACTOR, TT_CHUNK, CT_BUTTON) == PS_NORMAL)
{
if (sp.parseexp(False, True, &button) != PS_NORMAL)
{
MCperror->add(PE_DRAG_BADBUTTONEXP, sp);
return PS_ERROR;
}
}
if (sp.skip_token(SP_FACTOR, TT_FROM, PT_FROM) != PS_NORMAL)
{
MCperror->add(PE_DRAG_NOFROM, sp);
return PS_ERROR;
}
if (sp.parseexp(False, True, &startloc) != PS_NORMAL)
{
MCperror->add(PE_DRAG_BADSTARTLOCEXP, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_FACTOR, TT_TO, PT_TO) != PS_NORMAL)
{
MCperror->add(PE_DRAG_NOTO, sp);
return PS_ERROR;
}
if (sp.parseexp(False, True, &endloc) != PS_NORMAL)
{
MCperror->add(PE_DRAG_BADENDLOCEXP, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL)
return getmods(sp, mstate);
return PS_NORMAL;
}
void MCDrag::exec_ctxt(MCExecContext& ctxt)
{
#ifdef /* MCDrag */ LEGACY_EXEC
if (button != NULL)
{
if (button->eval(ep) != ES_NORMAL || ep.ton() != ES_NORMAL)
{
MCeerror->add(EE_DRAG_BADBUTTON, line, pos);
return ES_ERROR;
}
which = ep.getuint2();
}
if (startloc->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_DRAG_BADSTARTLOC, line, pos);
return ES_ERROR;
}
int2 sx, sy;
if (!MCU_stoi2x2(ep.getsvalue(), sx, sy))
{
MCeerror->add(EE_DRAG_STARTNAP, line, pos, ep.getsvalue());
return ES_ERROR;
}
if (endloc->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_DRAG_BADENDLOC, line, pos);
return ES_ERROR;
}
int2 ex, ey;
if (!MCU_stoi2x2(ep.getsvalue(), ex, ey))
{
MCeerror->add(EE_DRAG_ENDNAP, line, pos, ep.getsvalue());
return ES_ERROR;
}
uint2 oldmstate = MCmodifierstate;
uint2 oldbstate = MCbuttonstate;
int2 oldx = MCmousex;
int2 oldy = MCmousey;
MCmodifierstate = mstate;
MCbuttonstate = 0x1 << (which - 1);
MCmousex = sx;
MCmousey = sy;
//MCdragging = True;
MCscreen->setlockmods(True);
MCdefaultstackptr->mfocus(sx, sy);
MCdefaultstackptr->mdown(which);
if (MCdragspeed == 0)
{
MCmousex = ex;
MCmousey = ey;
MCdefaultstackptr->mfocus(ex, ey);
MCdefaultstackptr->mup(which, false);
MCscreen->setlockmods(False);
MCmodifierstate = oldmstate;
MCbuttonstate = oldbstate;
MCmousex = oldx;
MCmousey = oldy;
return ES_NORMAL;
}
MCscreen->sync(MCdefaultstackptr->getw());
real8 dx = MCU_abs(ex - sx);
real8 dy = MCU_abs(ey - sy);
real8 ix = 0.0;
if (dx != 0.0)
ix = dx / (ex - sx);
real8 iy = 0.0;
if (dy != 0.0)
iy = dy / (ey - sy);
real8 starttime = MCS_time();
real8 curtime = starttime;
real8 duration = 0.0;
if (MCdragspeed != 0)
duration = sqrt((double)(dx * dx + dy * dy)) / (real8)MCdragspeed;
real8 endtime = starttime + duration;
Boolean abort = False;
MCdragging = True;
int2 x = sx;
int2 y = sy;
while (x != ex || y != ey)
{
int2 oldx = x;
int2 oldy = y;
x = sx + (int2)(ix * (dx * (curtime - starttime) / duration));
y = sy + (int2)(iy * (dy * (curtime - starttime) / duration));
if (MCscreen->wait((real8)MCsyncrate / 1000.0, False, True))
{
abort = True;
break;
}
curtime = MCS_time();
if (curtime >= endtime)
{
x = ex;
y = ey;
curtime = endtime;
}
if (x != oldx || y != oldy)
MCdefaultstackptr->mfocus(x, y);
}
MCdefaultstackptr->mup(which, false);
MCmodifierstate = oldmstate;
MCbuttonstate = oldbstate;
MCmousex = oldx;
MCmousey = oldy;
MCscreen->setlockmods(False);
MCdragging = False;
if (abort)
{
MCeerror->add(EE_DRAG_ABORT, line, pos);
return ES_ERROR;
}
return ES_NORMAL;
#endif /* MCDrag */
uinteger_t t_which;
if (!ctxt . EvalOptionalExprAsUInt(button, which, EE_DRAG_BADBUTTON, t_which))
return;
which = t_which;
MCPoint t_start;
if (!ctxt . EvalExprAsPoint(startloc, EE_DRAG_BADSTARTLOC, t_start))
return;
MCPoint t_end;
if (!ctxt . EvalExprAsPoint(endloc, EE_DRAG_BADENDLOC, t_end))
return;
MCInterfaceExecDrag(ctxt, which, t_start, t_end, mstate);
}
void MCDrag::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
if (button != nil)
button -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantUInt(ctxt, which);
startloc -> compile(ctxt);
endloc -> compile(ctxt);
MCSyntaxFactoryEvalConstantUInt(ctxt, mstate);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecDragMethodInfo);
MCSyntaxFactoryEndStatement(ctxt);
}
MCFocus::~MCFocus()
{
delete object;
}
Parse_stat MCFocus::parse(MCScriptPoint &sp)
{
initpoint(sp);
sp.skip_token(SP_FACTOR, TT_OF, PT_ON);
// MW-2008-01-30: [[ Bug 5676 ]] Add "focus on nothing" to allow unfocusing
// all objects on a card.
if (sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_NOTHING) == PS_NORMAL)
object = NULL;
else
{
object = new MCChunk(False);
if (object->parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_FOCUS_BADOBJECT, sp);
return PS_ERROR;
}
}
return PS_NORMAL;
}
void MCFocus::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCFocus */ LEGACY_EXEC
MCObject *optr;
uint4 parid;
if (object == NULL)
{
if (MCfocusedstackptr != NULL && MCfocusedstackptr -> getcard() != NULL)
MCfocusedstackptr -> getcard() -> kunfocus();
#ifdef _MOBILE
// Make sure the IME is forced closed if explicitly asked to be.
MCscreen -> closeIME();
#endif
}
else
{
if (object->getobj(ep, optr, parid, True) != ES_NORMAL
|| optr->gettype() < CT_BUTTON || !optr->getflag(F_TRAVERSAL_ON))
{
MCeerror->add(EE_FOCUS_BADOBJECT, line, pos);
return ES_ERROR;
}
optr->getstack()->kfocusset((MCControl *)optr);
}
return ES_NORMAL;
#endif /* MCFocus */
if (object == NULL)
MCInterfaceExecFocusOnNothing(ctxt);
else
{
MCObject *optr;
uint4 parid;
if (!object->getobj(ctxt, optr, parid, True)
|| optr->gettype() < CT_FIRST_CONTROL
|| optr->gettype() > CT_LAST_CONTROL)
{
ctxt . LegacyThrow(EE_FOCUS_BADOBJECT);
return;
}
MCInterfaceExecFocusOn(ctxt, optr);
}
}
void MCFocus::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
if (object == nil)
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecFocusOnNothingMethodInfo);
else
{
object -> compile_object_ptr(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecFocusOnMethodInfo);
}
MCSyntaxFactoryEndStatement(ctxt);
}
MCInsert::~MCInsert()
{
delete target;
}
Parse_stat MCInsert::parse(MCScriptPoint &sp)
{
Symbol_type type;
const LT *te;
initpoint(sp);
sp.skip_token(SP_FACTOR, TT_THE);
if (sp.skip_token(SP_FACTOR, TT_PROPERTY, P_SCRIPT) != PS_NORMAL
|| sp.skip_token(SP_FACTOR, TT_OF) != PS_NORMAL)
{
MCperror->add(PE_INSERT_NOSCRIPT, sp);
return PS_ERROR;
}
target = new MCChunk(False);
if (target->parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_INSERT_BADOBJECT, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_FACTOR, TT_PREP, PT_INTO) != PS_NORMAL)
{
MCperror->add(PE_INSERT_NOINTO, sp);
return PS_ERROR;
}
if (sp.next(type) != PS_NORMAL
|| sp.lookup(SP_INSERT, te) != PS_NORMAL)
{
MCperror->add(PE_INSERT_NOPLACE, sp);
return PS_ERROR;
}
where = (Insert_point)te->which;
return PS_NORMAL;
}
void MCInsert::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCInsert */ LEGACY_EXEC
MCObject *optr;
uint4 parid;
if (target->getobj(ep, optr, parid, True) != ES_NORMAL
|| !optr->parsescript(True))
{
MCeerror->add(EE_INSERT_BADTARGET, line, pos);
return ES_ERROR;
}
MCObjectList *&listptr = where == IP_FRONT ? MCfrontscripts : MCbackscripts;
optr->removefrom(listptr);
uint4 count = 0;
if (listptr != NULL)
{
MCObjectList *olptr = listptr;
do
{
if (!olptr->getremoved())
count++;
olptr = olptr->next();
}
while (olptr != listptr);
}
if (MClicenseparameters . insert_limit > 0 && count >= MClicenseparameters . insert_limit)
{
MCeerror->add(EE_INSERT_NOTLICENSED, line, pos);
return ES_ERROR;
}
MCObjectList *olptr = new MCObjectList(optr);
olptr->insertto(listptr);
return ES_NORMAL;
#endif /* MCInsert */
MCObject *optr;
uint4 parid;
if (!target->getobj(ctxt, optr, parid, True))
{
ctxt . LegacyThrow(EE_INSERT_BADTARGET);
return;
}
MCEngineExecInsertScriptOfObjectInto(ctxt, optr, where == IP_FRONT);
}
void MCInsert::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
target -> compile_object_ptr(ctxt);
MCSyntaxFactoryEvalConstantBool(ctxt, where == IP_FRONT);
MCSyntaxFactoryExecMethod(ctxt, kMCEngineExecInsertScriptOfObjectIntoMethodInfo);
MCSyntaxFactoryEndStatement(ctxt);
}
// MW-2008-11-05: [[ Dispatch Command ]] Implementation for the dispatch command.
MCDispatchCmd::~MCDispatchCmd(void)
{
while(params != NULL)
{
MCParameter *t_param;
t_param = params;
params = params -> getnext();
delete t_param;
}
delete target;
delete message;
}
// Syntax is:
// dispatch [ command | function ] [ with ]
// dispatch [ command | function ] [ to ] [ with ]
Parse_stat MCDispatchCmd::parse(MCScriptPoint& sp)
{
initpoint(sp);
// MW-2009-09-11: Added support for command/function specification
if (sp . skip_token(SP_HANDLER, TT_HANDLER, HT_FUNCTION) == PS_NORMAL)
is_function = true;
else
sp . skip_token(SP_HANDLER, TT_HANDLER, HT_MESSAGE);
if (sp . parseexp(False, True, &message) != PS_NORMAL)
{
MCperror->add(PE_DISPATCH_BADMESSAGE, sp);
return PS_ERROR;
}
// MW-2008-12-04: Added 'to ' form to the syntax
if (sp.skip_token(SP_FACTOR, TT_TO) == PS_NORMAL)
{
target = new MCChunk(False);
if (target -> parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_DISPATCH_BADTARGET, sp);
return PS_ERROR;
}
}
if (sp . skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL)
{
if (getparams(sp, ¶ms) != PS_NORMAL)
{
MCperror -> add(PE_DISPATCH_BADPARAMS, sp);
return PS_ERROR;
}
}
return PS_NORMAL;
}
// This method follows along the same lines as MCComref::exec
void MCDispatchCmd::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCDispatchCmd */ LEGACY_EXEC
if (MCscreen->abortkey())
{
MCeerror->add(EE_HANDLER_ABORT, line, pos);
return ES_ERROR;
}
if (message -> eval(ep) != ES_NORMAL)
{
MCeerror -> add(EE_DISPATCH_BADMESSAGEEXP, line, pos);
return ES_ERROR;
}
MCAutoNameRef t_message;
/* UNCHECKED */ ep . copyasnameref(t_message);
// Evaluate the target object (if we parsed a 'target' chunk).
MCObject *t_object;
uint4 t_object_part_id;
if (target == NULL)
t_object = ep.getobj();
else if (target->getobj(ep, t_object, t_object_part_id, True) != ES_NORMAL)
{
MCeerror->add(EE_DISPATCH_BADTARGET, line, pos);
return ES_ERROR;
}
// Evaluate the parameter list
Exec_stat stat;
MCParameter *tptr = params;
while (tptr != NULL)
{
// Get the pointer to the variable this parameter maps to or NULL
// if it is an expression.
MCVariable* t_var;
t_var = tptr -> evalvar(ep);
if (t_var == NULL)
{
tptr -> clear_argument();
while ((stat = tptr->eval(ep)) != ES_NORMAL && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
if (!MCB_error(ep, line, pos, EE_STATEMENT_BADPARAM))
break;
if (stat != ES_NORMAL)
{
MCeerror->add(EE_STATEMENT_BADPARAM, line, pos);
return ES_ERROR;
}
tptr->set_argument(ep);
}
else
tptr->set_argument_var(t_var);
tptr = tptr->getnext();
}
// Fetch current default stack and target settings
MCStack *t_old_stack;
t_old_stack = MCdefaultstackptr;
MCObject *t_old_target;
t_old_target = MCtargetptr;
// Cache the current 'this stack' (used to see if we should switch back
// the default stack).
MCStack *t_this_stack;
t_this_stack = t_object -> getstack();
// Retarget this stack and the target to be relative to the target object
MCdefaultstackptr = t_this_stack;
MCtargetptr = t_object;
// MW-2012-10-30: [[ Bug 10478 ]] Turn off lockMessages before dispatch.
Boolean t_old_lock;
t_old_lock = MClockmessages;
MClockmessages = False;
// Add a new entry in the execution contexts
MCExecPoint *oldep = MCEPptr;
MCEPptr = &ep;
stat = ES_NOT_HANDLED;
Boolean added = False;
if (MCnexecutioncontexts < MAX_CONTEXTS)
{
ep.setline(line);
MCexecutioncontexts[MCnexecutioncontexts++] = &ep;
added = True;
}
// Dispatch the message
stat = MCU_dofrontscripts(is_function ? HT_FUNCTION : HT_MESSAGE, t_message, params);
Boolean olddynamic = MCdynamicpath;
MCdynamicpath = MCdynamiccard != NULL;
if (stat == ES_PASS || stat == ES_NOT_HANDLED)
switch(stat = t_object->handle(is_function ? HT_FUNCTION : HT_MESSAGE, t_message, params, t_object))
{
case ES_ERROR:
MCeerror -> add(EE_DISPATCH_BADCOMMAND, line, pos, t_message);
break;
default:
break;
}
// Set 'it' appropriately
switch(stat)
{
case ES_NOT_HANDLED:
case ES_NOT_FOUND:
ep.getit() -> sets(MCString("unhandled"));
stat = ES_NORMAL;
break;
case ES_PASS:
ep.getit() -> sets(MCString("passed"));
stat = ES_NORMAL;
break;
case ES_EXIT_HANDLER:
case ES_NORMAL:
ep.getit() -> sets(MCString("handled"));
stat = ES_NORMAL;
break;
default:
ep.getit() -> clear();
break;
}
// Reset the default stack pointer and target - note that we use 'send'esque
// semantics here. i.e. If the default stack has been changed, the change sticks.
if (MCdefaultstackptr == t_this_stack)
MCdefaultstackptr = t_old_stack;
// Reset target pointer
MCtargetptr = t_old_target;
MCdynamicpath = olddynamic;
// MW-2012-10-30: [[ Bug 10478 ]] Restore lockMessages.
MClockmessages = t_old_lock;
// Remove our entry from the contexts list
MCEPptr = oldep;
if (added)
MCnexecutioncontexts--;
return stat;
#endif /* MCDispatchCmd */
MCNewAutoNameRef t_message;
if (!ctxt . EvalExprAsNameRef(message, EE_DISPATCH_BADMESSAGEEXP, &t_message))
return;
// Evaluate the target object (if we parsed a 'target' chunk).
MCObjectPtr t_target;
MCObjectPtr *t_target_ptr;
if (target != nil)
{
if (!target->getobj(ctxt, t_target, True))
{
ctxt . LegacyThrow(EE_DISPATCH_BADTARGET);
return;
}
t_target_ptr = &t_target;
}
else
t_target_ptr = nil;
// Evaluate the parameter list
bool t_success, t_can_debug;
MCParameter *tptr = params;
while (tptr != NULL)
{
// AL-2014-08-20: [[ ArrayElementRefParams ]] Use containers for potential reference parameters
MCContainer *t_container;
if (tptr -> evalcontainer(ctxt, t_container))
tptr -> set_argument_container(t_container);
else
{
MCExecValue t_value;
tptr -> clear_argument();
do
{
if (!(t_success = tptr->eval_ctxt(ctxt, t_value)))
t_can_debug = MCB_error(ctxt, line, pos, EE_STATEMENT_BADPARAM);
ctxt.IgnoreLastError();
}
while (!t_success && t_can_debug && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors);
if (!t_success)
{
ctxt . LegacyThrow(EE_STATEMENT_BADPARAM);
return;
}
tptr->give_exec_argument(t_value);
}
tptr = tptr->getnext();
}
ctxt . SetLineAndPos(line, pos);
MCEngineExecDispatch(ctxt, is_function ? HT_FUNCTION : HT_MESSAGE, *t_message, t_target_ptr, params);
// AL-2014-09-17: [[ Bug 13465 ]] Clear parameters after executing dispatch
tptr = params;
while (tptr != NULL)
{
tptr -> clear_argument();
tptr = tptr->getnext();
}
}
MCMessage::~MCMessage()
{
delete message;
delete eventtype;
delete target;
delete in;
}
Parse_stat MCMessage::parse(MCScriptPoint &sp)
{
initpoint(sp);
if (sp.parseexp(False, True, &message) != PS_NORMAL)
{
MCperror->add(PE_SEND_BADEXP, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_FACTOR, TT_TO) != PS_NORMAL
&& sp.skip_token(SP_FACTOR, TT_OF) != PS_NORMAL)
return PS_NORMAL;
if (sp.skip_token(SP_ASK, TT_UNDEFINED, AT_PROGRAM) == PS_NORMAL)
{
program = True;
if (sp.parseexp(False, True, &in) != PS_NORMAL)
{
MCperror->add(PE_SEND_BADTARGET, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL
&& sp.skip_token(SP_COMMAND, TT_STATEMENT, S_REPLY) != PS_NORMAL)
if (sp.parseexp(False, True, &eventtype) != PS_NORMAL)
{
MCperror->add(PE_SEND_BADEVENTTYPE, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_SUGAR, TT_PREP, PT_WITHOUT) == PS_NORMAL)
{
sp.skip_token(SP_COMMAND, TT_STATEMENT, S_REPLY);
sp.skip_token(SP_MOVE, TT_UNDEFINED, MM_WAITING);
reply = False;
}
}
else
{
target = new MCChunk(False);
if (target->parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_SEND_BADTARGET, sp);
return PS_ERROR;
}
return gettime(sp, &in, units);
}
return PS_NORMAL;
}
void MCMessage::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCMessage */ LEGACY_EXEC
if (program)
{
if (MCsecuremode & MC_SECUREMODE_PROCESS)
{
MCeerror->add(EE_PROCESS_NOPERM, line, pos);
return ES_ERROR;
}
if (in->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_SEND_BADPROGRAMEXP, line, pos);
return ES_ERROR;
}
char *pname = ep.getsvalue().clone();
char *etstring = NULL;
if (eventtype != NULL)
{
if (eventtype->eval(ep) != ES_NORMAL || ep.getsvalue().getlength() != 8)
{
MCeerror->add(EE_SEND_BADEXP, line, pos);
return ES_ERROR;
}
etstring = ep.getsvalue().clone();
}
if (message->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_SEND_BADEXP, line, pos);
delete pname;
delete etstring;
return ES_ERROR;
}
MCS_send(ep.getsvalue(), pname, etstring, reply);
delete pname;
delete etstring;
return ES_NORMAL;
}
MCObject *optr;
uint4 parid;
if (target == NULL)
optr = ep.getobj();
else
if (target->getobj(ep, optr, parid, True) != ES_NORMAL)
{
MCeerror->add(EE_SEND_BADTARGET, line, pos);
return ES_ERROR;
}
real8 delay = 0.0;
if (in != NULL)
{
if (in->eval(ep) != ES_NORMAL || ep.ton() != ES_NORMAL)
{
MCeerror->add(EE_SEND_BADINEXP, line, pos);
return ES_ERROR;
}
delay = ep.getnvalue();
switch (units)
{
case F_MILLISECS:
delay /= 1000.0;
break;
case F_TICKS:
delay /= 60.0;
break;
default:
break;
}
}
if (message->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_SEND_BADEXP, line, pos);
return ES_ERROR;
}
char *mptr = ep.getsvalue().clone();
MCParameter *params = NULL;
MCParameter *tparam = NULL;
char *sptr = mptr;
while (*sptr && !isspace((uint1)*sptr))
sptr++;
MCerrorlock++;
if (*sptr)
{
*sptr++ = '\0';
char *startptr = sptr;
while (*startptr)
{
while (*sptr && *sptr != ',')
if (*sptr == '"')
{
sptr++;
while (*sptr && *sptr++ != '"')
;
}
else
sptr++;
if (*sptr)
*sptr++ = '\0';
MCString pdata = startptr;
ep.setsvalue(pdata);
MCParameter *newparam = new MCParameter;
// MW-2011-08-11: [[ Bug 9668 ]] Make sure we copy 'pdata' if we use it, since
// mptr (into which it points) only lasts as long as this method call.
// MW-2013-11-15: [[ Bug 11277 ]] Refactor MCHandler::eval
Exec_stat t_stat;
t_stat = ep . eval(ep);
if (t_stat == ES_NORMAL)
newparam->set_argument(ep);
else
newparam->copysvalue_argument(pdata);
if (tparam == NULL)
params = tparam = newparam;
else
{
tparam->setnext(newparam);
tparam = newparam;
}
startptr = sptr;
}
}
MCerrorlock--;
// Convert the message c-string to a name
MCAutoNameRef t_mptr_as_name;
/* UNCHECKED */ t_mptr_as_name . CreateWithCString(mptr);
if (in == NULL)
{
Boolean oldlock = MClockmessages;
MClockmessages = False;
Exec_stat stat;
Boolean added = False;
if (MCnexecutioncontexts < MAX_CONTEXTS)
{
ep.setline(line);
MCexecutioncontexts[MCnexecutioncontexts++] = &ep;
added = True;
}
if ((stat = optr->message(t_mptr_as_name, params, send, True)) == ES_NOT_HANDLED)
{
MCHandler *t_handler;
t_handler = optr -> findhandler(HT_MESSAGE, t_mptr_as_name);
if (t_handler != NULL && t_handler -> isprivate())
MCeerror -> add(EE_SEND_BADEXP, line, pos, mptr);
else
{
char *tptr = mptr;
if (params != NULL)
{
params->eval(ep);
char *p = ep.getsvalue().clone();
tptr = new char[strlen(mptr) + ep.getsvalue().getlength() + 2];
sprintf(tptr, "%s %s", mptr, p);
delete p;
}
if ((stat = optr->domess(tptr)) == ES_ERROR)
MCeerror->add(EE_STATEMENT_BADCOMMAND, line, pos, mptr);
if (tptr != mptr)
delete tptr;
}
}
else if (stat == ES_PASS)
stat = ES_NORMAL;
else if (stat == ES_ERROR)
MCeerror->add(EE_SEND_BADEXP, line, pos, mptr);
while (params != NULL)
{
MCParameter *tmp = params;
params = params->getnext();
delete tmp;
}
delete mptr;
if (added)
MCnexecutioncontexts--;
MClockmessages = oldlock;
return stat;
}
else
{
delete mptr;
// MW-2014-05-28: [[ Bug 12463 ]] If we cannot add the pending message, then throw an
// error.
if (!MCscreen->addusermessage(optr, t_mptr_as_name, MCS_time() + delay, params))
{
MCeerror -> add(EE_SEND_TOOMANYPENDING, line, pos, t_mptr_as_name);
return ES_ERROR;
}
}
return ES_NORMAL;
#endif /* MCMessage */
if (program)
{
MCAutoStringRef t_message;
if (!ctxt . EvalExprAsStringRef(message, EE_SEND_BADEXP, &t_message))
return;
MCAutoStringRef t_program;
if (!ctxt . EvalExprAsStringRef(in, EE_SEND_BADPROGRAMEXP, &t_program))
return;
MCAutoStringRef t_event_type;
if (!ctxt . EvalOptionalExprAsNullableStringRef(eventtype, EE_SEND_BADEXP, &t_event_type))
return;
MCScriptingExecSendToProgram(ctxt, *t_message, *t_program, *t_event_type, reply == True);
}
else
{
MCAutoStringRef t_message;
if (!ctxt . EvalExprAsStringRef(message, EE_SEND_BADEXP, &t_message))
return;
MCObjectPtr t_target;
MCObjectPtr *t_target_ptr;
if (target != nil)
{
if (!target -> getobj(ctxt, t_target, True))
{
ctxt . LegacyThrow(EE_SEND_BADTARGET);
return;
}
t_target_ptr = &t_target;
}
else
t_target_ptr = nil;
if (in != nil)
{
double t_delay;
if (!ctxt . EvalExprAsDouble(in, EE_SEND_BADINEXP, t_delay))
return;
MCEngineExecSendInTime(ctxt, *t_message, t_target, t_delay, units);
}
else
{
ctxt . SetLineAndPos(line, pos);
if (!send)
MCEngineExecCall(ctxt, *t_message, t_target_ptr);
else
MCEngineExecSend(ctxt, *t_message, t_target_ptr);
}
}
}
void MCMessage::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
if (program)
{
message -> compile(ctxt);
in -> compile(ctxt);
if (eventtype != nil)
eventtype -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantNil(ctxt);
MCSyntaxFactoryEvalConstantBool(ctxt, reply == True);
MCSyntaxFactoryExecMethod(ctxt, kMCScriptingExecSendToProgramMethodInfo);
}
else
{
message -> compile(ctxt);
if (target != nil)
target -> compile_object_ptr(ctxt);
else
MCSyntaxFactoryEvalConstantNil(ctxt);
if (in != nil)
{
in -> compile(ctxt);
MCSyntaxFactoryEvalConstantInt(ctxt, units);
MCSyntaxFactoryExecMethod(ctxt, kMCEngineExecSendInTimeMethodInfo);
}
else
{
if (!send)
MCSyntaxFactoryExecMethod(ctxt, kMCEngineExecCallMethodInfo);
else
MCSyntaxFactoryExecMethod(ctxt, kMCEngineExecSendMethodInfo);
}
}
MCSyntaxFactoryEndStatement(ctxt);
}
MCMove::~MCMove()
{
delete object;
delete startloc;
delete endloc;
delete durationexp;
}
Parse_stat MCMove::parse(MCScriptPoint &sp)
{
initpoint(sp);
object = new MCChunk(False);
if (object->parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_MOVE_BADOBJECT, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_FACTOR, TT_FROM, PT_FROM) == PS_NORMAL)
if (sp.parseexp(False, True, &startloc) != PS_NORMAL)
{
MCperror->add(PE_MOVE_BADSTARTLOCEXP, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_FACTOR, TT_TO, PT_TO) != PS_NORMAL)
{
if (sp.skip_token(SP_FACTOR, TT_TO, PT_RELATIVE) != PS_NORMAL)
{
MCperror->add(PE_MOVE_NOTO, sp);
return PS_ERROR;
}
relative = True;
}
if (sp.parseexp(False, True, &endloc) != PS_NORMAL)
{
MCperror->add(PE_MOVE_BADENDLOCEXP, sp);
return PS_ERROR;
}
if (gettime(sp, &durationexp, units) != PS_NORMAL)
return PS_ERROR;
if (sp.skip_token(SP_SUGAR, TT_PREP, PT_WITHOUT) == PS_NORMAL)
{
if (sp.skip_token(SP_MOVE, TT_UNDEFINED, MM_MESSAGES) == PS_NORMAL)
messages = False;
else
if (sp.skip_token(SP_MOVE, TT_UNDEFINED, MM_WAITING) == PS_NORMAL)
waiting = False;
else
{
MCperror->add(PE_MOVE_BADWITHOUT, sp);
return PS_ERROR;
}
}
return PS_NORMAL;
}
void MCMove::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCMove */ LEGACY_EXEC
MCObject *optr;
uint4 parid;
if (object->getobj(ep, optr, parid, True) != ES_NORMAL)
{
MCeerror->add(EE_MOVE_BADOBJECT, line, pos);
return ES_ERROR;
}
if (endloc->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_MOVE_BADENDLOC, line, pos);
return ES_ERROR;
}
MCPoint *pts;
uint2 npts;
if (startloc != NULL)
{
pts = new MCPoint[2];
npts = 2;
if (!MCU_stoi2x2(ep.getsvalue(), pts[1].x, pts[1].y))
{
MCeerror->add(EE_MOVE_ENDNAP, line, pos, ep.getsvalue());
delete pts;
return ES_ERROR;
}
if (startloc->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_MOVE_BADSTARTLOC, line, pos);
return ES_ERROR;
}
if (!MCU_stoi2x2(ep.getsvalue(), pts[0].x, pts[0].y))
{
MCeerror->add(EE_MOVE_STARTNAP, line, pos, ep.getsvalue());
return ES_ERROR;
}
}
else
{
MCPoint *tpts = NULL;
uint2 tnpts = 0;
if (!MCU_parsepoints(tpts, tnpts, ep.getsvalue()))
{
MCeerror->add(EE_MOVE_ENDNAP, line, pos, ep.getsvalue());
delete tpts;
return ES_ERROR;
}
if (tnpts == 1)
{
pts = new MCPoint[2];
npts = 2;
MCRectangle trect = optr->getrect();
pts[0].x = trect.x + (trect.width >> 1);
pts[0].y = trect.y + (trect.height >> 1);
pts[1] = tpts[0];
delete tpts;
if (relative)
{
pts[1].x += pts[0].x;
pts[1].y += pts[0].y;
}
}
else
{
pts = tpts;
npts = tnpts;
}
}
if (npts < 2)
return ES_NORMAL;
real8 duration = 0.0;
if (durationexp != NULL)
{
if (durationexp->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_MOVE_BADDURATION, line, pos);
return ES_ERROR;
}
if (ep.getreal8(duration, line, pos, EE_MOVE_DURATIONNAN) != ES_NORMAL)
return ES_ERROR;
switch (units)
{
case F_MILLISECS:
duration /= 1000.0;
break;
case F_TICKS:
duration /= 60.0;
break;
default:
break;
}
}
MCscreen->addmove(optr, pts, npts, duration, waiting);
if (waiting)
{
if (MCscreen->wait(duration, messages, False))
{
MCeerror->add(EE_MOVE_ABORT, line, pos);
return ES_ERROR;
}
MCscreen->stopmove(optr, True);
}
return ES_NORMAL;
#endif /* MCMove */
MCObject *optr;
uint4 parid;
if (!object->getobj(ctxt, optr, parid, True))
{
ctxt . LegacyThrow(EE_MOVE_BADOBJECT);
return;
}
real8 duration;
if (!ctxt . EvalOptionalExprAsDouble(durationexp, 0.0, EE_MOVE_BADDURATION, duration))
return;
if (startloc != NULL)
{
MCPoint t_to, t_from;
if (!ctxt . EvalExprAsPoint(endloc, EE_MOVE_BADENDLOC, t_to))
return;
if (!ctxt . EvalExprAsPoint(startloc, EE_MOVE_BADSTARTLOC, t_from))
return;
MCInterfaceExecMoveObjectBetween(ctxt, optr, t_from, t_to, duration, units, waiting == True, messages == True);
}
else
{
MCAutoArray t_points;
MCAutoStringRef t_motion;
if (!ctxt . EvalExprAsStringRef(endloc, EE_MOVE_BADENDLOC, &t_motion))
return;
if (!MCU_parsepoints(t_points.PtrRef(), t_points.SizeRef(), *t_motion))
{
ctxt . LegacyThrow(EE_MOVE_ENDNAP);
return;
}
MCInterfaceExecMoveObjectAlong(ctxt, optr, t_points.Ptr(), t_points.Size(), relative == True, duration, units, waiting == True, messages == True);
}
}
void MCMove::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
object -> compile_object_ptr(ctxt);
if (startloc != nil)
{
startloc -> compile(ctxt);
endloc -> compile(ctxt);
if (durationexp != nil)
durationexp -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantDouble(ctxt, 0);
MCSyntaxFactoryEvalConstantInt(ctxt, units);
MCSyntaxFactoryEvalConstantBool(ctxt, waiting == True);
MCSyntaxFactoryEvalConstantBool(ctxt, messages == True);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecMoveObjectBetweenMethodInfo);
}
else
{
endloc -> compile(ctxt);
MCSyntaxFactoryEvalConstantBool(ctxt, relative == True);
if (durationexp != nil)
durationexp -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantDouble(ctxt, 0);
MCSyntaxFactoryEvalConstantInt(ctxt, units);
MCSyntaxFactoryEvalConstantBool(ctxt, waiting == True);
MCSyntaxFactoryEvalConstantBool(ctxt, messages == True);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecMoveObjectAlongMethodInfo);
}
MCSyntaxFactoryEndStatement(ctxt);
}
MCMM::~MCMM()
{
delete clip;
delete stack;
delete tempo;
delete loc;
delete options;
}
Parse_stat MCMM::parse(MCScriptPoint &sp)
{
initpoint(sp);
if (prepare && sp.skip_token(SP_FACTOR, TT_CHUNK, CT_IMAGE) == PS_NORMAL)
{
if (sp . skip_token(SP_THERE, TT_UNDEFINED, TM_FILE) == PS_NORMAL)
{
if (sp.parseexp(False, True, &clip) != PS_NORMAL)
{
MCperror->add(PE_PLAY_BADCLIP, sp);
return PS_ERROR;
}
image_file = True;
return PS_NORMAL;
}
sp.backup();
stack = new MCChunk(False);
if (stack->parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_PLAY_BADSTACK, sp);
return PS_ERROR;
}
image = True;
return PS_NORMAL;
}
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_VIDEO) == PS_NORMAL)
{
if (sp.parseexp(False, True, &clip) != PS_NORMAL)
{
MCperror->add(PE_PLAY_BADCLIP, sp);
return PS_ERROR;
}
video = True;
return PS_NORMAL;
}
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_STEP) == PS_NORMAL)
{
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_FORWARD) == PS_NORMAL)
stepforward = True;
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_BACK) == PS_NORMAL)
stepback = True;
video = True;
}
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_PAUSE) == PS_NORMAL)
pause = True;
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_RESUME) == PS_NORMAL)
resume = True;
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_STOP) == PS_NORMAL)
stop = True;
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_AUDIO_CLIP) == PS_NORMAL)
audio = True;
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_VIDEO_CLIP) == PS_NORMAL)
video = True;
if (sp.skip_token(SP_SHOW, TT_UNDEFINED, SO_BACKGROUND) == PS_NORMAL)
ptype = CT_BACKGROUND;
if (sp.skip_token(SP_SHOW, TT_UNDEFINED, SO_CARD) == PS_NORMAL)
ptype = CT_CARD;
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_PLAYER) == PS_NORMAL)
player = True;
if (sp.skip_token(SP_FACTOR, TT_PROPERTY, P_ID) == PS_NORMAL)
etype = CT_ID;
if (stop && !video && !player)
{
audio = True;
return PS_NORMAL;
}
if (!audio && !video && !player)
audio = True;
sp.skip_token(SP_FACTOR, TT_CHUNK, CT_URL);
MCerrorlock++;
if (sp.parseexp(False, True, &clip) != PS_NORMAL)
{
MCerrorlock--;
if (stepback || stepforward || stop)
return PS_NORMAL;
MCperror->add(PE_PLAY_BADCLIP, sp);
return PS_ERROR;
}
MCerrorlock--;
if (sp.skip_token(SP_FACTOR, TT_OF) == PS_NORMAL)
{
stack = new MCChunk(False);
if (stack->parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_PLAY_BADSTACK, sp);
return PS_ERROR;
}
}
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_LOOPING) == PS_NORMAL)
looping = True;
if (video)
{
if (sp.skip_token(SP_FACTOR, TT_PREP, PT_AT) == PS_NORMAL)
{
if (sp.parseexp(False, True, &loc) != PS_NORMAL)
{
MCperror->add(PE_PLAY_BADLOC, sp);
return PS_ERROR;
}
}
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_OPTIONS) == PS_NORMAL)
{
if (sp.parseexp(False, True, &options) != PS_NORMAL)
{
MCperror->add(PE_PLAY_BADOPTIONS, sp);
return PS_ERROR;
}
}
}
else
{
if (sp.skip_token(SP_PLAY, TT_UNDEFINED, PP_TEMPO) == PS_NORMAL)
{
if (sp.parseexp(False, True, &tempo) != PS_NORMAL)
{
MCperror->add(PE_PLAY_BADTEMPO, sp);
return PS_ERROR;
}
}
MCScriptPoint notessp(sp);
MCerrorlock++;
if (sp.parseexp(False, True, &loc) != PS_NORMAL)
{
sp = notessp;
delete loc;
loc = NULL;
}
MCerrorlock--;
}
return PS_NORMAL;
}
void MCMM::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCMM */ LEGACY_EXEC
MCresult->clear(False);
if (prepare && image)
{
uint4 parid;
MCObject *t_object;
if (stack -> getobj(ep, t_object, parid, True) != ES_NORMAL ||
t_object -> gettype() != CT_IMAGE)
{
MCeerror->add(EE_PLAY_BADCLIP, line, pos);
return ES_ERROR;
}
static_cast(t_object) -> prepareimage();
return ES_NORMAL;
}
else if (prepare && image_file)
{
if (clip->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_PLAY_BADCLIP, line, pos);
return ES_ERROR;
}
// IM-2013-10-30: [[ FullscreenMode ]] Use refactored functions to fetch & prepare
// image rep using the scale of the current stack.
MCImageRep *t_rep;
t_rep = nil;
if (MCImageGetRepForReferenceWithStackContext(ep.getcstring(), MCdefaultstackptr, t_rep))
{
MCImagePrepareRepForDisplayAtDensity(t_rep, MCdefaultstackptr->getdevicescale());
t_rep->Release();
}
return ES_NORMAL;
}
if (audio)
MCU_play_stop();
if (stop)
{
#ifdef _MOBILE
extern bool MCSystemStopVideo();
if (!MCSystemStopVideo())
MCresult->sets("no video support");
return ES_NORMAL;
#endif
}
if (clip == NULL)
{
if (video && MCplayers != NULL)
if (stepforward)
MCplayers->playstepforward();
else if (stepback)
MCplayers->playstepback();
else if (pause)
MCplayers->playpause(True);
else if (stop)
if (MCplayers->isdisposable())
{
MCPlayer *tptr = MCplayers;
tptr->playstop();
}
else
MCplayers->playpause(True);
else if (!MCplayers->playpause(False))
{
MCPlayer *tptr = MCplayers;
tptr->playstop();
}
return ES_NORMAL;
}
MCStack *sptr = MCdefaultstackptr;
if (stack != NULL)
{
uint4 parid;
MCObject *optr = MCdefaultstackptr;
if (stack->getobj(ep, optr, parid, True) != ES_NORMAL)
{
MCeerror->add(EE_PLAY_BADCLIP, line, pos);
return ES_ERROR;
}
sptr = optr->getstack();
}
if (clip->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_PLAY_BADCLIP, line, pos);
return ES_ERROR;
}
if (video)
{
#ifdef _MOBILE
extern bool MCSystemPlayVideo(const char *p_filename);
MCExecPoint *t_old_ep;
t_old_ep = MCEPptr;
MCEPptr = &ep;
if (!MCSystemPlayVideo(ep.getcstring()))
MCresult->sets("no video support");
MCEPptr = t_old_ep;
return ES_NORMAL;
#endif
}
if (video || player)
{
IO_cleanprocesses();
MCPlayer *tptr;
if (player)
tptr = (MCPlayer *)sptr->getcard()->getchild(etype, ep.getsvalue(), CT_PLAYER, ptype);
else
{
// Lookup the name we are searching for. If it doesn't exist, then no object can
// have it as a name.
tptr = nil;
if (etype == CT_EXPRESSION)
{
MCNameRef t_obj_name;
t_obj_name = MCNameLookupWithOldString(ep.getsvalue(), kMCCompareCaseless);
if (t_obj_name != nil)
{
tptr = MCplayers;
while (tptr != NULL)
{
if (tptr -> hasname(t_obj_name))
break;
tptr = tptr->getnextplayer();
}
}
}
else if (etype == CT_ID)
{
tptr = MCplayers;
while (tptr != NULL)
{
if (tptr -> getaltid() == ep.getnvalue())
break;
tptr = tptr->getnextplayer();
}
}
if (tptr != nil && !prepare)
tptr->setflag(True, F_VISIBLE);
}
if (tptr != NULL)
{
if (pause)
tptr->playpause(True);
else if (stepforward)
tptr->playstepforward();
else if (stepback)
tptr->playstepback();
else if (stop)
if (tptr->isdisposable())
tptr->playstop();
else
tptr->playpause(True);
else if (!prepare)
if (!tptr->playpause(False))
tptr->playstop();
return ES_NORMAL;
}
if (pause || stop || stepforward || stepback)
{
MCresult->sets("videoClip is not playing");
return ES_NORMAL;
}
const char *vcname = NULL;
char *fname = NULL;
Boolean tmpfile = False;
MCVideoClip *vcptr;
real8 scale;
Boolean dontrefresh;
if ((vcptr = (MCVideoClip *)sptr->getAV(etype, ep.getsvalue(),
CT_VIDEO_CLIP)) == NULL
&& (vcptr = (MCVideoClip *)sptr->getobjname(CT_VIDEO_CLIP,
ep.getsvalue())) == NULL)
{
if (ep.getsvalue().getlength() < 4096)
{
fname = ep.getsvalue().clone();
vcname = fname;
if (!MCS_exists(fname, True))
{
delete fname;
fname = NULL;
MCU_geturl(ep);
if (ep.getsvalue().getlength() == 0)
{
MCresult->sets("no data in videoClip");
return ES_NORMAL;
}
}
}
if (fname == NULL)
{
fname = strclone(MCS_tmpnam());
IO_handle tstream;
if ((tstream = MCS_open(fname, IO_WRITE_MODE, False, False, 0)) == NULL)
{
delete fname;
MCresult->sets("error opening temp file");
return ES_NORMAL;
}
IO_stat stat = IO_write(ep.getsvalue().getstring(), sizeof(int1),
ep.getsvalue().getlength(), tstream);
MCS_close(tstream);
if (stat != IO_NORMAL)
{
MCS_unlink(fname);
delete fname;
MCresult->sets("error writing videoClip");
return ES_NORMAL;
}
tmpfile = True;
}
scale = MCtemplatevideo->getscale();
dontrefresh = MCtemplatevideo->getflag(F_DONT_REFRESH);
}
else
{
vcname = vcptr->getname_cstring();
fname = vcptr->getfile();
scale = vcptr->getscale();
dontrefresh = vcptr->getflag(F_DONT_REFRESH);
tmpfile = True;
}
tptr = (MCPlayer *)MCtemplateplayer->clone(False, OP_NONE, false);
tptr->setsprop(P_SHOW_BORDER, MCfalsemcstring);
tptr->setfilename(vcname, fname, tmpfile);
tptr->open();
if (prepare)
tptr->setflag(False, F_VISIBLE);
MCRectangle trect = tptr->getrect();
if (loc != NULL)
{
if (loc->eval(ep) != ES_NORMAL)
{
if (tptr->isdisposable())
delete tptr;
MCeerror->add(EE_PLAY_BADLOC, line, pos);
return ES_ERROR;
}
if (!MCU_stoi2x2(ep.getsvalue(), trect.x, trect.y))
{
if (tptr->isdisposable())
delete tptr;
MCeerror->add(EE_PLAY_BADLOC, line, pos, ep.getsvalue());
return ES_ERROR;
}
}
else
{
MCRectangle crect = tptr->getcard()->getrect();
trect.x = crect.width >> 1;
trect.y = crect.height >> 1;
}
trect.width = trect.height = 1;
tptr->setrect(trect);
tptr->setscale(scale);
tptr->setflag(dontrefresh, F_DONT_REFRESH);
char *optionstring;
if (options != NULL)
{
if (options->eval(ep) != ES_NORMAL)
{
if (tptr->isdisposable())
delete tptr;
MCeerror->add(EE_PLAY_BADOPTIONS, line, pos);
return ES_ERROR;
}
optionstring = ep.getsvalue().clone();
}
else
optionstring = strclone(MCnullstring);
if (looping)
tptr->setflag(True, F_LOOPING);
if (prepare && !tptr->prepare(optionstring)
|| !prepare && !tptr->playstart(optionstring))
{
if (tptr->isdisposable())
delete tptr;
delete optionstring;
return ES_NORMAL;
}
delete optionstring;
}
else
{
if (!MCtemplateaudio->issupported())
{
#ifdef _MOBILE
extern bool MCSystemPlaySound(const char *p_filename, bool p_looping);
if (!MCSystemPlaySound(ep.getcstring(), looping == True))
MCresult->sets("no sound support");
#endif
return ES_NORMAL;
}
if ((MCacptr = (MCAudioClip *)(sptr->getAV(etype, ep.getsvalue(),
CT_AUDIO_CLIP))) == NULL
&& (MCacptr = (MCAudioClip *)sptr->getobjname(CT_AUDIO_CLIP,
ep.getsvalue())) == NULL)
{
char *fname = ep.getsvalue().clone();
IO_handle stream;
if (!MCS_exists(fname, True)
|| (stream = MCS_open(fname, IO_READ_MODE, True, False, 0)) == NULL)
{
MCU_geturl(ep);
if (ep.getsvalue().getlength() == 0)
{
delete fname;
MCresult->sets("no data in audioClip");
return ES_NORMAL;
}
stream = MCS_fakeopen(ep.getsvalue());
}
MCacptr = new MCAudioClip;
MCacptr->setdisposable();
if (!MCacptr->import(fname, stream))
{
MCS_close(stream);
MCresult->sets("error reading audioClip");
delete fname;
delete MCacptr;
MCacptr = NULL;
return ES_ERROR;
}
MCS_close(stream);
delete fname;
}
MCacptr->setlooping(looping);
MCU_play();
#ifndef FEATURE_PLATFORM_AUDIO
if (MCacptr != NULL)
MCscreen->addtimer(MCacptr, MCM_internal, looping ? LOOP_RATE : PLAY_RATE);
#endif
}
return ES_NORMAL;
#endif /* MCMM */
ctxt . SetTheResultToEmpty();
if (prepare && image)
{
uint4 parid;
MCObject *t_object;
if (!stack -> getobj(ctxt, t_object, parid, True) ||
t_object -> gettype() != CT_IMAGE)
{
ctxt . LegacyThrow(EE_PLAY_BADCLIP);
return;
}
MCGraphicsExecPrepareImage(ctxt, static_cast(t_object));
}
else if (prepare && image_file)
{
MCAutoStringRef t_filename;
if (!ctxt . EvalExprAsStringRef(clip, EE_PLAY_BADCLIP, &t_filename))
return;
MCGraphicsExecPrepareImageFile(ctxt, *t_filename);
}
else if (clip == NULL)
{
if (video)
{
if (stepforward)
MCMultimediaExecPlayLastVideoOperation(ctxt, PP_FORWARD);
else if (stepback)
MCMultimediaExecPlayLastVideoOperation(ctxt, PP_BACK);
else if (pause)
MCMultimediaExecPlayLastVideoOperation(ctxt, PP_PAUSE);
else if (stop)
MCMultimediaExecPlayLastVideoOperation(ctxt, PP_STOP);
else if (resume)
MCMultimediaExecPlayLastVideoOperation(ctxt, PP_RESUME);
else
MCMultimediaExecPlayLastVideoOperation(ctxt, PP_UNDEFINED);
}
// AL-2014-09-12: [[ Bug 13428 ]] The only valid audio action without a clip is stop
else if (audio)
{
MCMultimediaExecStopPlaying(ctxt);
}
// PM-2015-09-23: [[ Bug 15994 ]] Calling 'play stop' on mobile should stop the currently played video
if (stop)
{
#ifdef _MOBILE
MCMultimediaExecPlayVideoOperation(ctxt, nil, etype, kMCEmptyString, PP_STOP);
#endif
}
}
else
{
MCObject *optr = nil;
if (stack != NULL)
{
uint4 parid;
if (!stack->getobj(ctxt, optr, parid, True) ||
optr -> gettype() != CT_STACK)
{
ctxt . LegacyThrow(EE_PLAY_BADCLIP);
return;
}
}
MCAutoStringRef t_clip_name;
if (!ctxt . EvalExprAsStringRef(clip, EE_PLAY_BADCLIP, &t_clip_name))
return;
if (player)
{
if (pause)
MCMultimediaExecPlayPlayerOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, ptype, PP_PAUSE);
else if (stepforward)
MCMultimediaExecPlayPlayerOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, ptype, PP_FORWARD);
else if (stepback)
MCMultimediaExecPlayPlayerOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, ptype, PP_BACK);
else if (stop)
MCMultimediaExecPlayPlayerOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, ptype, PP_STOP);
else if (resume)
MCMultimediaExecPlayPlayerOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, ptype, PP_RESUME);
else
MCMultimediaExecPlayPlayerOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, ptype, PP_UNDEFINED);
}
else if (video)
{
if (pause)
MCMultimediaExecPlayVideoOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, PP_PAUSE);
else if (stepforward)
MCMultimediaExecPlayVideoOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, PP_FORWARD);
else if (stepback)
MCMultimediaExecPlayVideoOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, PP_BACK);
else if (stop)
MCMultimediaExecPlayVideoOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, PP_STOP);
else if (resume)
MCMultimediaExecPlayVideoOperation(ctxt, (MCStack *)optr, etype, *t_clip_name, PP_RESUME);
else
{
MCPoint t_loc;
MCPoint *t_loc_ptr = &t_loc;
if (!ctxt . EvalOptionalExprAsPoint(loc, nil, EE_PLAY_BADLOC, t_loc_ptr))
return;
MCAutoStringRef t_options;
if (!ctxt . EvalOptionalExprAsNullableStringRef(options, EE_PLAY_BADOPTIONS, &t_options))
return;
if (!prepare)
MCMultimediaExecPlayVideoClip(ctxt, (MCStack *)optr, etype, *t_clip_name, looping == True, t_loc_ptr, *t_options);
else
MCMultimediaExecPrepareVideoClip(ctxt, (MCStack *)optr, etype, *t_clip_name, looping == True, t_loc_ptr, *t_options);
}
}
else
MCMultimediaExecPlayAudioClip(ctxt, (MCStack *)optr, etype, *t_clip_name, looping == True);
}
}
void MCMM::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
if (prepare && image)
{
stack -> compile_object_ptr(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCGraphicsExecPrepareImageMethodInfo);
}
else if (prepare && image_file)
{
clip -> compile(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCGraphicsExecPrepareImageFileMethodInfo);
}
else if (clip == NULL)
{
if (video)
{
if (stepforward)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_FORWARD);
else if (stepback)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_BACK);
else if (pause)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_PAUSE);
else if (stop)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_STOP);
else if (resume)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_RESUME);
else
MCSyntaxFactoryEvalConstantInt(ctxt, PP_UNDEFINED);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPlayLastVideoOperationMethodInfo);
}
}
else
{
if (stack != nil)
stack -> compile_object_ptr(ctxt);
else
MCSyntaxFactoryEvalConstantNil(ctxt);
MCSyntaxFactoryEvalConstantInt(ctxt, etype);
clip -> compile(ctxt);
if (player)
{
MCSyntaxFactoryEvalConstantInt(ctxt, ptype);
if (stepforward)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_FORWARD);
else if (stepback)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_BACK);
else if (pause)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_PAUSE);
else if (stop)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_STOP);
else if (resume)
MCSyntaxFactoryEvalConstantInt(ctxt, PP_RESUME);
else
MCSyntaxFactoryEvalConstantInt(ctxt, PP_UNDEFINED);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPlayPlayerOperationMethodInfo);
}
else if (video)
{
if (stepforward)
{
MCSyntaxFactoryEvalConstantInt(ctxt, PP_FORWARD);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPlayVideoOperationMethodInfo);
}
else if (stepback)
{
MCSyntaxFactoryEvalConstantInt(ctxt, PP_BACK);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPlayVideoOperationMethodInfo);
}
else if (pause)
{
MCSyntaxFactoryEvalConstantInt(ctxt, PP_PAUSE);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPlayVideoOperationMethodInfo);
}
else if (stop)
{
MCSyntaxFactoryEvalConstantInt(ctxt, PP_STOP);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPlayVideoOperationMethodInfo);
}
else if (resume)
{
MCSyntaxFactoryEvalConstantInt(ctxt, PP_RESUME);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPlayVideoOperationMethodInfo);
}
else
{
MCSyntaxFactoryEvalConstantBool(ctxt, looping == True);
if (loc != nil)
loc -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantNil(ctxt);
if (options != nil)
options -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantNil(ctxt);
if (!prepare)
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPlayVideoClipMethodInfo);
else
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPrepareVideoClipMethodInfo);
}
}
else
{
MCSyntaxFactoryEvalConstantBool(ctxt, looping == True);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecPlayAudioClipMethodInfo);
}
}
MCSyntaxFactoryEndStatement(ctxt);
}
MCReply::~MCReply()
{
delete message;
delete keyword;
}
Parse_stat MCReply::parse(MCScriptPoint &sp)
{
initpoint(sp);
if (sp.skip_token(SP_LOCK, TT_UNDEFINED, LC_ERRORS) == PS_NORMAL)
error = True;
if (sp.parseexp(False, True, &message) != PS_NORMAL)
{
MCperror->add(PE_REPLY_BADEXP, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL)
{
sp.skip_token(SP_SUGAR, TT_CHUNK, CT_UNDEFINED);
if (sp.parseexp(True, False, &keyword) != PS_NORMAL)
{
MCperror->add(PE_REPLY_BADKEYWORD, sp);
return PS_ERROR;
}
}
return PS_NORMAL;
}
void MCReply::exec_ctxt(MCExecContext& ctxt)
{
#ifdef /* MCReply */ LEGACY_EXEC
char *k = NULL;
if (keyword != NULL)
{
if (message->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_REPLY_BADKEYWORDEXP, line, pos);
return ES_ERROR;
}
k = ep.getsvalue().clone();
}
if (message->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_REPLY_BADMESSAGEEXP, line, pos);
delete k;
return ES_ERROR;
}
MCS_reply(ep.getsvalue(), k, error);
delete k;
return ES_NORMAL;
#endif /* MCReply */
MCAutoStringRef t_message;
if (!ctxt . EvalExprAsStringRef(message, EE_REPLY_BADMESSAGEEXP, &t_message))
return;
MCAutoStringRef t_keyword;
if (!error)
{
if (!ctxt . EvalOptionalExprAsNullableStringRef(keyword, EE_REPLY_BADKEYWORDEXP, &t_keyword))
return;
}
if (!error)
MCScriptingExecReply(ctxt, *t_message, *t_keyword);
else
MCScriptingExecReplyError(ctxt, *t_message);
}
void MCReply::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
message -> compile(ctxt);
if (!error)
{
if (keyword != nil)
keyword -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantNil(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCScriptingExecReplyMethodInfo);
}
else
MCSyntaxFactoryExecMethod(ctxt, kMCScriptingExecReplyErrorMethodInfo);
MCSyntaxFactoryEndStatement(ctxt);
}
MCRequest::~MCRequest()
{
delete message;
delete program;
}
Parse_stat MCRequest::parse(MCScriptPoint &sp)
{
initpoint(sp);
if (sp.skip_token(SP_AE, TT_UNDEFINED, AE_AE) == PS_NORMAL)
{
Symbol_type type;
const LT *te;
if (sp.next(type) != PS_NORMAL)
{
MCperror->add(PE_REQUEST_NOTYPE, sp);
return PS_ERROR;
}
if (sp.lookup(SP_AE, te) != PS_NORMAL)
{
MCperror->add(PE_REQUEST_NOTTYPE, sp);
return PS_ERROR;
}
ae = (Apple_event)te->which;
if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL)
{
sp.skip_token(SP_SUGAR, TT_CHUNK, CT_UNDEFINED);
if (sp.parseexp(False, True, &program) != PS_NORMAL)
{
MCperror->add(PE_REQUEST_BADEXP, sp);
return PS_ERROR;
}
}
}
else
{
if (sp.parseexp(False, True, &message) != PS_NORMAL)
{
MCperror->add(PE_REQUEST_BADEXP, sp);
return PS_ERROR;
}
sp.skip_token(SP_FACTOR, TT_FROM, PT_FROM);
sp.skip_token(SP_FACTOR, TT_OF, PT_OF);
sp.skip_token(SP_ASK, TT_UNDEFINED, AT_PROGRAM);
if (sp.parseexp(False, True, &program) != PS_NORMAL)
{
MCperror->add(PE_REQUEST_BADPROGRAM, sp);
return PS_ERROR;
}
}
return PS_NORMAL;
}
void MCRequest::exec_ctxt(MCExecContext& ctxt)
{
#ifdef /* MCRequest */ LEGACY_EXEC
if (MCsecuremode & MC_SECUREMODE_PROCESS)
{
MCeerror->add(EE_REQUEST_NOPERM, line, pos);
return ES_ERROR;
}
char *result = NULL;
if (ae != AE_UNDEFINED)
{
if (program == NULL)
ep.clear();
else
if (program->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_REQUEST_BADKEYWORDEXP, line, pos);
return ES_ERROR;
}
result = MCS_request_ae(ep.getsvalue(), ae);
}
else
{
if (program->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_REQUEST_BADPROGRAMEXP, line, pos);
return ES_ERROR;
}
char *p = ep.getsvalue().clone();
if (message->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_REQUEST_BADMESSAGEEXP, line, pos);
delete p;
return ES_ERROR;
}
result = MCS_request_program(ep.getsvalue(), p);
delete p;
}
if (result == NULL)
ep.clear();
else
{
ep.copysvalue(result, strlen(result));
delete result;
}
ep.getit()->set(ep);
return ES_NORMAL;
#endif /* MCRequest */
if (ae != AE_UNDEFINED)
{
MCAutoStringRef t_program;
if (!ctxt . EvalOptionalExprAsNullableStringRef(program, EE_REQUEST_BADKEYWORDEXP, &t_program))
return;
MCScriptingExecRequestAppleEvent(ctxt, ae, *t_program);
}
else
{
MCAutoStringRef t_message;
if (!ctxt . EvalExprAsStringRef(message, EE_REQUEST_BADMESSAGEEXP, &t_message))
return;
MCAutoStringRef t_program;
if (!ctxt . EvalExprAsStringRef(program, EE_REQUEST_BADPROGRAMEXP, &t_program))
return;
MCScriptingExecRequestFromProgram(ctxt, *t_message, *t_program);
}
}
void MCRequest::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
if (ae != AE_UNDEFINED)
{
MCSyntaxFactoryEvalConstantInt(ctxt, ae);
if (program != nil)
program -> compile(ctxt);
else
MCSyntaxFactoryEvalConstantNil(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCScriptingExecRequestAppleEventMethodInfo);
}
else
{
message -> compile(ctxt);
program -> compile(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCScriptingExecRequestFromProgramMethodInfo);
}
MCSyntaxFactoryEndStatement(ctxt);
}
MCStart::~MCStart()
{
delete target;
delete stack;
delete font;
}
Parse_stat MCStart::parse(MCScriptPoint &sp)
{
Symbol_type type;
const LT *te;
initpoint(sp);
if (mode == SC_UNDEFINED)
{
if (sp.next(type) != PS_NORMAL)
{
MCperror->add(PE_START_NOTYPE, sp);
return PS_ERROR;
}
if (sp.lookup(SP_START, te) != PS_NORMAL)
{
MCperror->add(PE_START_NOTTYPE, sp);
return PS_ERROR;
}
mode = (Start_constants)te->which;
}
if (mode == SC_USING)
{
if (sp.skip_token(SP_FACTOR, TT_CHUNK, CT_STACK) == PS_NORMAL
|| sp.skip_token(SP_FACTOR, TT_CHUNK, CT_THIS) == PS_NORMAL)
{
sp.backup();
target = new MCChunk(False);
if (target->parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_START_BADCHUNK, sp);
return PS_ERROR;
}
}
// TD-2013-06-12: [[ DynamicFonts ]] Look for font
else if (sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_FONT) == PS_NORMAL)
{
if (sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_FILE) != PS_NORMAL)
{
MCperror->add(PE_START_BADCHUNK, sp);
return PS_ERROR;
}
if (sp . parseexp(False, True, &font) != PS_NORMAL)
{
MCperror->add(PE_START_BADCHUNK, sp);
return PS_ERROR;
}
is_globally = (sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_GLOBALLY) == PS_NORMAL);
}
else
{
if (sp.parseexp(False, True, &stack) != PS_NORMAL)
{
MCperror->add(PE_START_BADCHUNK, sp);
return PS_ERROR;
}
}
}
else if (mode == SC_SESSION)
{
return PS_NORMAL;
}
else
{
if (mode == SC_PLAYER)
sp.backup();
target = new MCChunk(False);
if (target->parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_START_BADCHUNK, sp);
return PS_ERROR;
}
}
return PS_NORMAL;
}
bool MCServerStartSession();
void MCStart::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCStart */ LEGACY_EXEC
if (mode == SC_USING)
{
// TD-2013-06-12: [[ DynamicFonts ]] Look for font.
if (font != NULL)
{
if (MCsecuremode & MC_SECUREMODE_DISK)
{
MCeerror->add(EE_DISK_NOPERM, line, pos);
return ES_ERROR;
}
// MERG-2013-08-14: [[ DynamicFonts ]] Refactored to use MCFontLoad
if (font->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_FONT_BADFILEEXP, line, pos);
return ES_ERROR;
}
MCAutoPointer t_resolved_path;
t_resolved_path = MCS_resolvepath(ep . getcstring());
if (MCFontLoad(ep, *t_resolved_path , is_globally) != ES_NORMAL)
MCresult -> sets("can't load font file");
else
MCresult -> clear();
}
else
{
MCStack *sptr = NULL;
if (target != NULL)
{
MCObject *optr;
uint4 parid;
if (target->getobj(ep, optr, parid, True) != ES_NORMAL
|| optr->gettype() != CT_STACK)
{
MCeerror->add(EE_START_BADTARGET, line, pos);
return ES_ERROR;
}
sptr = (MCStack *)optr;
}
else
{
if (stack->eval(ep) != ES_NORMAL
|| (sptr = MCdefaultstackptr->findstackname(ep.getsvalue())) == NULL
|| !sptr->parsescript(True))
{
MCeerror->add(EE_START_BADTARGET, line, pos);
return ES_ERROR;
}
}
uint2 i = MCnusing;
while (i--)
if (MCusing[i] == sptr)
{
MCnusing--;
while (i < MCnusing)
{
MCusing[i] = MCusing[i + 1];
i++;
}
break;
}
if (MClicenseparameters . using_limit > 0 && MCnusing >= MClicenseparameters . using_limit)
{
MCeerror->add(EE_START_NOTLICENSED, line, pos);
return ES_ERROR;
}
MCU_realloc((char **)&MCusing, MCnusing, MCnusing + 1, sizeof(MCStack *));
MCusing[MCnusing++] = sptr;
if (sptr->message(MCM_library_stack) == ES_ERROR)
return ES_ERROR;
}
}
else if (mode == SC_SESSION)
{
#ifdef _SERVER
if (!MCServerStartSession())
{
MCeerror->add(EE_UNDEFINED, line, pos);
return ES_ERROR;
}
#else
MCeerror->add(EE_SESSION_BADCONTEXT, line, pos);
return ES_ERROR;
#endif
}
else
{
MCObject *optr;
uint4 parid;
if (target->getobj(ep, optr, parid, True) != ES_NORMAL)
{
MCeerror->add(EE_START_BADTARGET, line, pos);
return ES_ERROR;
}
if (optr->gettype() == CT_PLAYER)
{
MCPlayer *pptr = (MCPlayer *)optr;
pptr->playstart(NULL);
}
else
{
if (optr->gettype() != CT_GROUP)
{
MCeerror->add(EE_START_NOTABACKGROUND, line, pos);
return ES_ERROR;
}
if (optr->getstack()->islocked())
{
MCeerror->add(EE_START_LOCKED, line, pos);
return ES_ERROR;
}
MCGroup *gptr = (MCGroup *)optr;
gptr->getstack()->startedit(gptr);
}
}
return ES_NORMAL;
#endif /* MCStart */
if (mode == SC_USING)
{
// TD-2013-06-12: [[ DynamicFonts ]] Look for font.
if (font != NULL)
{
if (MCsecuremode & MC_SECUREMODE_DISK)
{
ctxt . LegacyThrow(EE_DISK_NOPERM);
return;
}
MCAutoStringRef t_font;
if (!ctxt . EvalExprAsStringRef(font, EE_FONT_BADFILEEXP, &t_font))
return;
MCTextExecStartUsingFont(ctxt, *t_font, is_globally);
}
else if (target != NULL)
{
MCObject *optr;
uint4 parid;
if (!target->getobj(ctxt, optr, parid, True)
|| optr->gettype() != CT_STACK)
{
ctxt . LegacyThrow(EE_START_BADTARGET);
return;
}
MCEngineExecStartUsingStack(ctxt, (MCStack *)optr);
}
else
{
MCAutoStringRef t_name;
if (!ctxt . EvalExprAsStringRef(stack, EE_START_BADTARGET, &t_name))
return;
MCEngineExecStartUsingStackByName(ctxt, *t_name);
}
}
else if (mode == SC_SESSION)
{
#ifdef _SERVER
MCServerExecStartSession(ctxt);
#else
ctxt . LegacyThrow(EE_SESSION_BADCONTEXT);
return;
#endif
}
else
{
MCObject *optr;
uint4 parid;
if (!target->getobj(ctxt, optr, parid, True))
{
ctxt . LegacyThrow(EE_START_BADTARGET);
return;
}
if (optr->gettype() == CT_PLAYER)
{
MCMultimediaExecStartPlayer(ctxt, (MCPlayer *)optr);
}
else
{
if (optr->gettype() != CT_GROUP)
{
ctxt . LegacyThrow(EE_START_NOTABACKGROUND);
return;
}
MCInterfaceExecStartEditingGroup(ctxt, (MCGroup *)optr);
}
}
}
void MCStart::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
if (mode == SC_USING)
{
if (font != nil)
{
font -> compile(ctxt);
MCSyntaxFactoryEvalConstantBool(ctxt, is_globally);
MCSyntaxFactoryExecMethod(ctxt, kMCTextExecStartUsingFontMethodInfo);
}
else if (target != nil)
{
target -> compile_object_ptr(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCEngineExecStartUsingStackMethodInfo);
}
else
{
stack -> compile(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCEngineExecStartUsingStackByNameMethodInfo);
}
}
else if (mode == SC_SESSION)
{
#ifdef _SERVER
MCSyntaxFactoryExecMethod(ctxt, kMCServerExecStartSessionMethodInfo);
#endif
}
else
{
target -> compile(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecStartPlayerMethodInfo);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecStartEditingGroupMethodInfo);
}
MCSyntaxFactoryEndStatement(ctxt);
}
MCStop::~MCStop()
{
delete target;
delete stack;
delete font;
}
Parse_stat MCStop::parse(MCScriptPoint &sp)
{
Symbol_type type;
const LT *te;
initpoint(sp);
if (sp.next(type) != PS_NORMAL)
{
MCperror->add(PE_STOP_NOTYPE, sp);
return PS_ERROR;
}
if (sp.lookup(SP_START, te) != PS_NORMAL)
{
MCperror->add(PE_STOP_NOTTYPE, sp);
return PS_ERROR;
}
mode = (Start_constants)te->which;
if (mode == SC_RECORDING)
return PS_NORMAL;
if (mode == SC_SESSION)
return PS_NORMAL;
if (mode == SC_USING)
{
if (sp.skip_token(SP_FACTOR, TT_CHUNK, CT_STACK) == PS_NORMAL
|| sp.skip_token(SP_FACTOR, TT_CHUNK, CT_THIS) == PS_NORMAL)
{
sp.backup();
target = new MCChunk(False);
if (target->parse(sp, False) != PS_NORMAL)
{
MCperror->add(PE_START_BADCHUNK, sp);
return PS_ERROR;
}
}
// TD-2013-06-20: [[ DynamicFonts ]] Look for font
else if (sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_FONT) == PS_NORMAL)
{
if (sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_FILE) != PS_NORMAL)
{
MCperror->add(PE_START_BADCHUNK, sp);
return PS_ERROR;
}
if (sp . parseexp(False, True, &font) != PS_NORMAL)
{
MCperror->add(PE_START_BADCHUNK, sp);
return PS_ERROR;
}
}
else
if (sp.parseexp(False, True, &stack) != PS_NORMAL)
{
MCperror->add(PE_START_BADCHUNK, sp);
return PS_ERROR;
}
}
else
{
if (mode == SC_PLAYER)
sp.backup();
target = new MCChunk(False);
MCScriptPoint oldsp(sp);
MCerrorlock++;
if (target->parse(sp, False) != PS_NORMAL)
{
MCerrorlock--;
if (mode == SC_EDITING)
{
delete target;
target = NULL;
sp = oldsp;
return PS_NORMAL;
}
else
{
MCperror->add(PE_STOP_BADCHUNK, sp);
return PS_ERROR;
}
}
MCerrorlock--;
}
return PS_NORMAL;
}
bool MCServerStopSession();
void MCStop::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCStop */ LEGACY_EXEC
MCObject *optr = NULL;
uint4 parid;
if (target != NULL)
if (target->getobj(ep, optr, parid, True) != ES_NORMAL
|| optr == NULL && mode != SC_EDITING)
{
MCeerror->add(EE_STOP_BADTARGET, line, pos);
return ES_ERROR;
}
switch (mode)
{
case SC_EDITING:
if (optr != NULL)
{
if (optr->gettype() != CT_GROUP)
{
MCeerror->add(EE_STOP_NOTABACKGROUND, line, pos);
return ES_ERROR;
}
MCGroup *gptr = (MCGroup *)optr;
gptr->getstack()->stopedit();
}
else
MCdefaultstackptr->stopedit();
break;
case SC_MOVING:
MCscreen->stopmove(optr, False);
break;
case SC_PLAYER:
case SC_PLAYING:
if (optr == NULL)
MCU_play_stop();
else
if (optr->gettype() == CT_PLAYER)
{
MCPlayer *player = (MCPlayer *)optr;
if (player->isdisposable())
player->playstop();
else
player->playpause(True);
}
else
MCU_play_stop();
break;
case SC_RECORDING:
#ifdef FEATURE_PLATFORM_RECORDER
extern MCPlatformSoundRecorderRef MCrecorder;
if (MCrecorder == nil)
break;
MCPlatformSoundRecorderStop(MCrecorder);
#else
extern void MCQTStopRecording(void);
MCQTStopRecording();
#endif
break;
case SC_USING:
{
// TD-2013-06-12: [[ DynamicFonts ]] Look for font.
if (font != NULL)
{
// MERG-2013-08-14: [[ DynamicFonts ]] Refactored to use MCFontUnload
if (font->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_FONT_BADFILEEXP, line, pos);
return ES_ERROR;
}
MCAutoPointer t_resolved_path;
t_resolved_path = MCS_resolvepath(ep . getcstring());
if (MCFontUnload(ep, *t_resolved_path) != ES_NORMAL)
MCresult -> sets("can't unload font file");
else
MCresult -> clear();
}
else
{
MCStack *sptr = NULL;
if (target != NULL)
{
MCObject *optr;
uint4 parid;
if (target->getobj(ep, optr, parid, True) != ES_NORMAL
|| optr->gettype() != CT_STACK)
{
MCeerror->add(EE_STOP_BADTARGET, line, pos);
return ES_ERROR;
}
sptr = (MCStack *)optr;
}
else
if (stack->eval(ep) != ES_NORMAL
|| (sptr = MCdefaultstackptr->findstackname(ep.getsvalue())) == NULL)
{
MCeerror->add(EE_STOP_BADTARGET, line, pos);
return ES_ERROR;
}
uint2 i = MCnusing;
while (i--)
if (MCusing[i] == sptr)
{
MCnusing--;
while (i < MCnusing)
{
MCusing[i] = MCusing[i + 1];
i++;
}
break;
}
sptr->message(MCM_release_stack);
}
}
break;
case SC_SESSION:
{
#ifdef _SERVER
if (!MCServerStopSession())
{
MCeerror->add(EE_UNDEFINED, line, pos);
return ES_ERROR;
}
#else
MCeerror->add(EE_SESSION_BADCONTEXT, line, pos);
return ES_ERROR;
#endif
}
default:
break;
}
return ES_NORMAL;
#endif /* MCStop */
MCObject *optr = NULL;
uint4 parid;
if (target != NULL)
if (!target->getobj(ctxt, optr, parid, True)
|| (optr == NULL && mode != SC_EDITING))
{
ctxt . LegacyThrow(EE_STOP_BADTARGET);
return;
}
switch (mode)
{
case SC_EDITING:
if (optr != NULL)
{
if (optr->gettype() != CT_GROUP)
{
ctxt . LegacyThrow(EE_STOP_NOTABACKGROUND);
return;
}
MCInterfaceExecStopEditingGroup(ctxt, (MCGroup *)optr);
}
else
MCInterfaceExecStopEditingDefaultStack(ctxt);
break;
case SC_MOVING:
MCInterfaceExecStopMovingObject(ctxt, optr);
break;
case SC_PLAYER:
case SC_PLAYING:
if (optr == NULL)
MCMultimediaExecStopPlaying(ctxt);
else
MCMultimediaExecStopPlayingObject(ctxt, optr);
break;
case SC_RECORDING:
MCMultimediaExecStopRecording(ctxt);
break;
case SC_USING:
{
// TD-2013-06-12: [[ DynamicFonts ]] Look for font.
if (font != NULL)
{
MCAutoStringRef t_font;
if (!ctxt . EvalExprAsStringRef(font, EE_FONT_BADFILEEXP, &t_font))
return;
MCTextExecStopUsingFont(ctxt, *t_font);
}
else if (target != NULL)
{
MCObject *optr;
uint4 parid;
if (!target->getobj(ctxt, optr, parid, True)
|| optr->gettype() != CT_STACK)
{
ctxt . LegacyThrow(EE_STOP_BADTARGET);
return;
}
MCEngineExecStopUsingStack(ctxt, (MCStack *)optr);
}
else
{
MCAutoStringRef t_name;
if (!ctxt . EvalExprAsStringRef(stack, EE_STOP_BADTARGET, &t_name))
return;
MCEngineExecStopUsingStackByName(ctxt, *t_name);
}
}
break;
case SC_SESSION:
{
#ifdef _SERVER
MCServerExecStopSession(ctxt);
#else
ctxt . LegacyThrow(EE_SESSION_BADCONTEXT);
return;
#endif
}
default:
break;
}
}
void MCStop::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
switch (mode)
{
case SC_EDITING:
if (target != nil)
{
target -> compile_object_ptr(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecStopEditingGroupMethodInfo);
}
else
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecStopEditingDefaultStackMethodInfo);
break;
case SC_MOVING:
target -> compile_object_ptr(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecStopMovingObjectMethodInfo);
break;
case SC_PLAYER:
case SC_PLAYING:
if (target == nil)
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecStopPlayingMethodInfo);
else
{
target -> compile_object_ptr(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecStopPlayingObjectMethodInfo);
}
break;
case SC_RECORDING:
MCSyntaxFactoryExecMethod(ctxt, kMCMultimediaExecStopRecordingMethodInfo);
break;
case SC_USING:
if (font != nil)
{
font -> compile(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCTextExecStopUsingFontMethodInfo);
}
else if (target != nil)
{
target -> compile_object_ptr(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCEngineExecStopUsingStackMethodInfo);
}
else
{
stack -> compile(ctxt);
MCSyntaxFactoryExecMethod(ctxt, kMCEngineExecStopUsingStackByNameMethodInfo);
}
break;
case SC_SESSION:
#ifdef _SERVER
MCSyntaxFactoryExecMethod(ctxt, kMCServerExecStopSessionMethodInfo);
#endif
break;
default:
break;
}
MCSyntaxFactoryEndStatement(ctxt);
}
MCType::~MCType()
{
delete message;
}
Parse_stat MCType::parse(MCScriptPoint &sp)
{
initpoint(sp);
if (sp.parseexp(False, True, &message) != PS_NORMAL)
{
MCperror->add(PE_TYPE_BADEXP, sp);
return PS_ERROR;
}
if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL)
return getmods(sp, mstate);
return PS_NORMAL;
}
void MCType::exec_ctxt(MCExecContext &ctxt)
{
#ifdef /* MCType */ LEGACY_EXEC
if (message->eval(ep) != ES_NORMAL)
{
MCeerror->add(EE_TYPE_BADSTRINGEXP, line, pos);
return ES_ERROR;
}
uint2 oldstate = MCmodifierstate;
MCmodifierstate = mstate;
MCdefaultstackptr->kfocus();
const char *sptr = ep.getsvalue().getstring();
uint2 length = ep.getsvalue().getlength();
uint2 i;
char string[2];
string[1] = '\0';
real8 nexttime = MCS_time();
for (i = 0 ; i < length ; i++)
{
KeySym keysym = (unsigned char)sptr[i];
if (keysym < 0x20 || keysym == 0xFF)
{
if (keysym == 0x0A)
keysym = 0x0D;
keysym |= 0xFF00;
string[0] = '\0';
}
else
string[0] = sptr[i];
MCdefaultstackptr->kdown(string, keysym);
MCdefaultstackptr->kup(string, keysym);
nexttime += (real8)MCtyperate / 1000.0;
real8 delay = nexttime - MCS_time();
if (MCscreen->wait(delay, False, False))
{
MCmodifierstate = oldstate;
MCeerror->add(EE_TYPE_ABORT, line, pos);
return ES_ERROR;
}
}
MCmodifierstate = oldstate;
return ES_NORMAL;
#endif /* MCType */
MCAutoStringRef t_typing;
if (!ctxt . EvalExprAsStringRef(message, EE_TYPE_BADSTRINGEXP, &t_typing))
return;
MCInterfaceExecType(ctxt, *t_typing, mstate);
}
void MCType::compile(MCSyntaxFactoryRef ctxt)
{
MCSyntaxFactoryBeginStatement(ctxt, line, pos);
message -> compile(ctxt);
MCSyntaxFactoryEvalConstantUInt(ctxt, mstate);
MCSyntaxFactoryExecMethod(ctxt, kMCInterfaceExecTypeMethodInfo);
MCSyntaxFactoryEndStatement(ctxt);
}