/* 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 "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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
if (object == NULL)
MCInterfaceExecFocusOnNothing(ctxt);
else
{
MCObject *optr;
uint4 parid;
if (!object->getobj(ctxt, optr, parid, True) ||
!MCChunkTermIsControl(optr -> gettype()))
{
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)
{
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)
{
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();
}
}
Parse_stat MCMessage::parse(MCScriptPoint &sp)
{
initpoint(sp);
MCScriptPoint oldsp(sp);
if (send && sp.skip_token(SP_FACTOR, TT_PROPERTY, P_SCRIPT) == PS_NORMAL)
{
MCerrorlock++;
if (sp.parseexp(False, True, &(&message)) != PS_NORMAL)
{
sp = oldsp;
}
else
{
script = True;
}
MCerrorlock--;
}
if (!script && 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;
}
if (script && sp.skip_eol() != PS_NORMAL)
{
MCperror->add(PE_SEND_SCRIPTINTIME, sp);
return PS_ERROR;
}
return gettime(sp, &(&in), units);
}
return PS_NORMAL;
}
void MCMessage::exec_ctxt(MCExecContext &ctxt)
{
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 (!script)
{
if (!send)
MCEngineExecCall(ctxt, *t_message, t_target_ptr);
else
MCEngineExecSend(ctxt, *t_message, t_target_ptr);
}
else
{
MCEngineExecSendScript(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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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);
}