/* 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); }