void MCDebuggingGetTraceStack(MCExecContext& ctxt, MCStringRef& r_value) { if (MCtracestackptr == nil) { r_value = (MCStringRef)MCValueRetain(kMCEmptyString); return; } MCAutoValueRef t_value; if (MCtracestackptr -> names(P_NAME, &t_value)) if (ctxt.ConvertToString(*t_value, r_value)) return; ctxt . Throw(); }
void MCAdExecCreateAd(MCExecContext& ctxt, const char *p_name, MCAdType p_type, MCAdTopLeft p_top_left, MCVariableValue *p_meta_data) { bool t_success; t_success = true; if (s_inneractive_ad_key == nil || MCCStringLength(s_inneractive_ad_key) == 0) { ctxt.SetTheResultToStaticCString("not registered with ad service"); t_success = false;; } MCAd *t_ad; t_ad = nil; if (t_success) if (MCAd::FindByNameOrId(p_name, t_ad)) { ctxt.SetTheResultToStaticCString("ad already exists"); t_success = false; } if (t_success) { uint32_t t_timeout; if (t_success) { t_timeout = 0; if (p_meta_data != nil && p_meta_data->fetch_element_if_exists(ctxt.GetEP(), "refresh", false)) t_timeout = ctxt.GetEP().getint4(); if (p_type == kMCAdTypeFullscreen) t_timeout = 0; else if (t_timeout < 30 || t_timeout > 500) t_timeout = 120; } if (t_success) t_success = MCSystemInneractiveAdCreate(ctxt, t_ad, p_type, p_top_left, t_timeout, p_meta_data); if (t_success) t_success = t_ad->Create(); if (t_success) { t_ad->SetNext(s_ads); t_ad->SetName(p_name); t_ad->SetOwner(ctxt.GetObjectHandle()); s_ads = t_ad; } else if (t_ad != nil) t_ad->Release(); } if (!t_success) ctxt.SetTheResultToStaticCString("could not create ad"); }
bool MCArraysCopyMatrix(MCExecContext& ctxt, MCArrayRef self, matrix_t*& r_matrix) { MCAutoArray<array_extent_t> t_extents; if (!MCArraysCopyExtents(self, t_extents.PtrRef(), t_extents.SizeRef()) || t_extents.Size() != 2) return false; integer_t t_rows = extent_size(t_extents[0]); integer_t t_cols = extent_size(t_extents[1]); integer_t t_row_offset = t_extents[0].min; integer_t t_col_offset = t_extents[1].min; if (MCArrayGetCount(self) != t_rows * t_cols) return false; MCAutoPointer<matrix_t> t_matrix; if (!MCMatrixNew(t_rows, t_cols, t_row_offset, t_col_offset, &t_matrix)) return false; for (integer_t row = 0; row < t_rows; row++) { for (integer_t col = 0; col < t_cols; col++) { MCAutoStringRef t_string; MCNewAutoNameRef t_name; MCValueRef t_value; if (!MCStringFormat(&t_string, "%d,%d", row + t_row_offset, col + t_col_offset) || !MCNameCreate(*t_string, &t_name) || !MCArrayFetchValue(self, true, *t_name, t_value) || !ctxt.ConvertToReal(t_value, MCMatrixEntry(*t_matrix, row, col))) return false; } } t_matrix.Take(r_matrix); return true; }
void MCDebuggingExecDebugDo(MCExecContext& ctxt, MCStringRef p_script, uinteger_t p_line, uinteger_t p_pos) { Boolean added = False; if (MCnexecutioncontexts < MAX_CONTEXTS) { ctxt.SetLineAndPos(p_line, p_pos); MCexecutioncontexts[MCnexecutioncontexts++] = &ctxt; added = True; } if (MCdebugcontext >= MCnexecutioncontexts) MCdebugcontext = MCnexecutioncontexts - 1; MCExecContext *t_ctxt_ptr; t_ctxt_ptr = MCexecutioncontexts[MCdebugcontext]; t_ctxt_ptr->GetHandler()->doscript(*t_ctxt_ptr, p_script, p_line, p_pos); // AL-2014-03-21: [[ Bug 11940 ]] Ensure the debug context is not permanently in a state of error. t_ctxt_ptr -> IgnoreLastError(); if (added) MCnexecutioncontexts--; }
void MCLicenseSetRevLicenseLimits(MCExecContext& ctxt, MCArrayRef p_settings) { if(!MCenvironmentactive) return; bool t_case_sensitive = ctxt . GetCaseSensitive(); MCValueRef t_value; MCStringRef t_string; if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("token"), t_value) && ctxt . ConvertToString(t_value, t_string)) { MCValueRelease(MClicenseparameters . license_token); MClicenseparameters . license_token = t_string; } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("name"), t_value) && ctxt . ConvertToString(t_value, t_string)) { MCValueRelease(MClicenseparameters . license_name); MClicenseparameters . license_name = t_string; } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("organization"), t_value) && ctxt . ConvertToString(t_value, t_string)) { MCValueRelease( MClicenseparameters . license_organization); MClicenseparameters . license_organization = t_string; } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("class"), t_value)) { MCAutoStringRef t_class; MCLicenseClass t_license_class; if (ctxt . ConvertToString(t_value, &t_class) && MCStringToLicenseClass(*t_class, t_license_class)) { MClicenseparameters . license_class = t_license_class; } else MClicenseparameters . license_class = kMCLicenseClassNone; } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("multiplicity"), t_value)) { MCAutoNumberRef t_number; if (ctxt.ConvertToNumber(t_value, &t_number)) { MClicenseparameters . license_multiplicity = MCNumberFetchAsUnsignedInteger(*t_number); } } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("scriptlimit"), t_value)) { MCAutoNumberRef t_number; if (ctxt.ConvertToNumber(t_value, &t_number)) { integer_t t_limit; t_limit = MCNumberFetchAsInteger(*t_number); MClicenseparameters . script_limit = t_limit <= 0 ? 0 : t_limit; } } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("dolimit"), t_value)) { MCAutoNumberRef t_number; if (ctxt.ConvertToNumber(t_value, &t_number)) { integer_t t_limit; t_limit = MCNumberFetchAsInteger(*t_number); MClicenseparameters . do_limit = t_limit <= 0 ? 0 : t_limit; } } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("usinglimit"), t_value)) { MCAutoNumberRef t_number; if (ctxt.ConvertToNumber(t_value, &t_number)) { integer_t t_limit; t_limit = MCNumberFetchAsInteger(*t_number); MClicenseparameters . using_limit = t_limit <= 0 ? 0 : t_limit; } } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("insertlimit"), t_value)) { MCAutoNumberRef t_number; if (ctxt.ConvertToNumber(t_value, &t_number)) { integer_t t_limit; t_limit = MCNumberFetchAsInteger(*t_number); MClicenseparameters . insert_limit = t_limit <= 0 ? 0 : t_limit; } } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("deploy"), t_value)) { static struct { const char *tag; uint32_t value; } s_deploy_map[] = { { "windows", kMCLicenseDeployToWindows }, { "macosx", kMCLicenseDeployToMacOSX }, { "linux", kMCLicenseDeployToLinux }, { "ios", kMCLicenseDeployToIOS }, { "android", kMCLicenseDeployToAndroid }, { "winmobile", kMCLicenseDeployToWinMobile }, { "meego", kMCLicenseDeployToLinuxMobile }, { "server", kMCLicenseDeployToServer }, { "ios-embedded", kMCLicenseDeployToIOSEmbedded }, { "android-embedded", kMCLicenseDeployToIOSEmbedded }, { "html5", kMCLicenseDeployToHTML5 }, { "filemaker", kMCLicenseDeployToFileMaker }, }; MClicenseparameters . deploy_targets = 0; MCAutoStringRef t_params; if (ctxt . ConvertToString(t_value, &t_params)) { MCAutoArrayRef t_split_strings; MCValueRef t_fetched_string; if (MCStringSplit(*t_params, MCSTR(","), nil, kMCCompareExact, &t_split_strings)) { for(uint32_t i = 0; i < MCArrayGetCount(*t_split_strings); i++) { // Fetch the string value created with MCStringSplit MCArrayFetchValueAtIndex(*t_split_strings, i+1, t_fetched_string); for(uint32_t j = 0; j < sizeof(s_deploy_map) / sizeof(s_deploy_map[0]); j++) if (MCStringIsEqualToCString((MCStringRef)t_fetched_string, s_deploy_map[j] . tag, kMCStringOptionCompareCaseless)) { MClicenseparameters . deploy_targets |= s_deploy_map[j] . value; break; } } } } } if (MCArrayFetchValue(p_settings, t_case_sensitive, MCNAME("addons"), t_value) && MCValueIsArray(t_value)) { MCValueRelease(MClicenseparameters . addons); MCArrayCopy((MCArrayRef)t_value, MClicenseparameters . addons); } }
// SN-2014-09-01: [[ Bug 13297 ]] Combining by column deserves its own function as it is too // different from combining by row void MCArraysExecCombineByColumn(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef &r_string) { MCStringRef t_row_delimiter, t_col_delimiter; t_row_delimiter = ctxt . GetRowDelimiter(); t_col_delimiter = ctxt . GetColumnDelimiter(); MCAutoListRef t_list; MCListCreateMutable(t_row_delimiter, &t_list); uindex_t t_count = MCArrayGetCount(p_array); combine_int_indexed_array_t t_lisctxt; bool t_success; t_lisctxt . elements = nil; t_lisctxt . index = 0; t_lisctxt . converter = &ctxt; t_success = MCMemoryNewArray(t_count, t_lisctxt . elements); if (t_success) { if (MCArrayApply(p_array, list_int_indexed_array_elements, &t_lisctxt)) { bool t_valid_keys; qsort(t_lisctxt . elements, t_count, sizeof(array_element_t), compare_int_indexed_elements); // Combine by row/column is only valid if all the indices are consecutive numbers // Otherwise, an empty string is returned - no error index_t t_last_index; t_valid_keys = true; t_last_index = 0; for (int i = 0; i < t_count && t_valid_keys; ++i) { if (!t_last_index) t_last_index = t_lisctxt . elements[i] . key; else t_valid_keys = ++t_last_index == t_lisctxt . elements[i] . key; } if (t_valid_keys) { // SN-2014-09-01: [[ Bug 13297 ]] // We need to store the converted strings in a array, to be able to iterate through the elements by one row-delimitated // at a time MCStringRef* t_strings; uindex_t *t_next_row_indices; t_strings = NULL; t_next_row_indices = NULL; /* UNCHECKED */ MCMemoryNewArray(t_count, t_strings); // MCMemoryNewArray initialises all t_next_row_indices elements to 0. /* UNCHECKED */ MCMemoryNewArray(t_count, t_next_row_indices); for (int i = 0; i < t_count && t_success; ++i) { if (t_lisctxt . elements[i] . key == 0) // The index 0 is ignored continue; t_success = ctxt . ConvertToString(t_lisctxt . elements[i] . value, t_strings[i]); } // SN-2014-09-01: [[ Bug 13297 ]] Added a missed part in column-combining: // only combining row-by-row the array elements. if (t_success) { uindex_t t_elements_over; t_elements_over = 0; // We iterate as long as one element still has uncombined rows while (t_success && t_elements_over != t_count) { MCAutoListRef t_row; t_success = MCListCreateMutable(t_col_delimiter, &t_row); t_elements_over = 0; // Iterate through all the elements of the array for (int i = 0; i < t_count && t_success; ++i) { // Only consider this element if it has any uncombined rows remaining if (t_next_row_indices[i] < MCStringGetLength(t_strings[i])) { MCRange t_cell_range; if (MCStringFind(t_strings[i], MCRangeMake(t_next_row_indices[i], UINDEX_MAX), t_row_delimiter, ctxt.GetStringComparisonType(), &t_cell_range)) { // We found a row delimiter, so we stop the copy range before it and update the next index from which to look t_success = MCListAppendSubstring(*t_row, t_strings[i], MCRangeMake(t_next_row_indices[i], t_cell_range . offset - t_next_row_indices[i])); t_next_row_indices[i] = t_cell_range . offset + t_cell_range . length; } else { // No row delimiter: we copy the remaining part of the string and mark the element // as wholly combined by setting the next index to the length of the element t_success = MCListAppendSubstring(*t_row, t_strings[i], MCRangeMake(t_next_row_indices[i], UINDEX_MAX)); t_next_row_indices[i] = MCStringGetLength(t_strings[i]); } } else { // Everything has been combined in this element t_elements_over++; MCListAppend(*t_row, kMCEmptyString); } } // One more row has been combined - doing it anyway mimics the previous behaviour of having an empty row // added in the end when combining by columns if (t_elements_over != t_count) MCListAppend(*t_list, *t_row); } } MCMemoryDeleteArray(t_next_row_indices); MCMemoryDeleteArray(t_strings); } } MCMemoryDeleteArray(t_lisctxt . elements); } if (t_success && MCListCopyAsString(*t_list, r_string)) return; ctxt . Throw(); }
void MCArraysEvalTransposeMatrix(MCExecContext& ctxt, MCArrayRef p_matrix, MCArrayRef& r_result) { if (!MCArraysCopyTransposed(p_matrix, r_result)) ctxt.LegacyThrow(EE_TRANSPOSE_MISMATCH); }
void MCArraysEvalIsAmongTheKeysOf(MCExecContext& ctxt, MCNameRef p_key, MCArrayRef p_array, bool& r_result) { MCValueRef t_value; r_result = MCArrayFetchValue(p_array, ctxt.GetCaseSensitive(), p_key, t_value); }
void MCSetOp::exec_ctxt(MCExecContext &ctxt) { // ARRAYEVAL MCAutoValueRef t_src; if (!ctxt . EvalExprAsValueRef(*source, EE_ARRAYOP_BADEXP, &t_src)) return; MCAutoValueRef t_dst; MCContainer t_container; if (!is_into) { if (!destvar -> evalcontainer(ctxt, t_container)) { ctxt . LegacyThrow(EE_ARRAYOP_BADEXP); return; } if (!t_container.eval(ctxt, &t_dst)) return; } else { if (!ctxt.EvalExprAsValueRef(*destexpr, EE_ARRAYOP_BADEXP, &t_dst)) { return; } } MCAutoValueRef t_dst_value; switch(op) { case kOpIntersect: MCArraysExecIntersect(ctxt, *t_dst, *t_src, &t_dst_value); break; case kOpIntersectRecursively: MCArraysExecIntersectRecursively(ctxt, *t_dst, *t_src, &t_dst_value); break; case kOpUnion: MCArraysExecUnion(ctxt, *t_dst, *t_src, &t_dst_value); break; case kOpUnionRecursively: MCArraysExecUnionRecursively(ctxt, *t_dst, *t_src, &t_dst_value); break; case kOpDifference: MCArraysExecDifference(ctxt, *t_dst, *t_src, &t_dst_value); break; case kOpSymmetricDifference: MCArraysExecSymmetricDifference(ctxt, *t_dst, *t_src, &t_dst_value); break; case kOpNone: MCUnreachable(); break; } if (!ctxt . HasError()) { if (!is_into) t_container.set(ctxt, *t_dst_value); else destvar->set(ctxt, *t_dst_value); } }
// MW-2007-07-03: [[ Bug 5123 ]] - Strict array checking modification // Here the source can be an array or number so we use 'tona'. void MCAdd::exec_ctxt(MCExecContext &ctxt) { MCExecValue t_src; if (!ctxt . EvaluateExpression(source, EE_ADD_BADSOURCE, t_src) || !ctxt . ConvertToNumberOrArray(t_src)) { ctxt.LegacyThrow(EE_ADD_BADSOURCE); return; } MCExecValue t_dst; MCContainer t_dst_container; if (destvar != nil) { if (!destvar->evalcontainer(ctxt, t_dst_container) || !t_dst_container.eval_ctxt(ctxt, t_dst)) { ctxt . LegacyThrow(EE_ADD_BADDEST); MCExecTypeRelease(t_src); return; } } else { if (!ctxt . EvaluateExpression(dest, EE_ADD_BADDEST, t_dst)) { MCExecTypeRelease(t_src); return; } } if (!ctxt . ConvertToNumberOrArray(t_dst)) { MCExecTypeRelease(t_src); MCExecTypeRelease(t_dst); ctxt.LegacyThrow(EE_ADD_BADDEST); return; } MCExecValue t_result; t_result . type = t_dst . type; if (t_src . type == kMCExecValueTypeArrayRef) { if (t_dst . type == kMCExecValueTypeArrayRef) MCMathExecAddArrayToArray(ctxt, t_src . arrayref_value, t_dst . arrayref_value, t_result . arrayref_value); else { ctxt . LegacyThrow(EE_ADD_MISMATCH); return; } } else { if (t_dst . type == kMCExecValueTypeArrayRef) MCMathExecAddNumberToArray(ctxt, t_src . double_value, t_dst . arrayref_value, t_result . arrayref_value); else MCMathExecAddNumberToNumber(ctxt, t_src . double_value, t_dst . double_value, t_result . double_value); } MCExecTypeRelease(t_src); MCExecTypeRelease(t_dst); if (!ctxt . HasError()) { if (destvar != nil) { if (!t_dst_container.give_value(ctxt, t_result)) ctxt . Throw(); } else { if (dest->set(ctxt, PT_INTO, t_result)) return; ctxt . LegacyThrow(EE_ADD_CANTSET); } } }
void MCArrayOp::exec_ctxt(MCExecContext &ctxt) { MCAutoStringRef t_element_del; MCAutoStringRef t_key_del; uint4 chunk; chunk = mode; switch(chunk) { case TYPE_USER: if (element != NULL) { if (!ctxt . EvalExprAsStringRef(element, EE_ARRAYOP_BADEXP, &t_element_del)) return; if (!ctxt . EvalOptionalExprAsNullableStringRef(key, EE_ARRAYOP_BADEXP, &t_key_del)) return; } break; case TYPE_ROW: t_element_del = ctxt.GetRowDelimiter(); break; case TYPE_COLUMN: t_element_del = ctxt.GetColumnDelimiter(); break; case TYPE_LINE: t_element_del = ctxt.GetLineDelimiter(); break; case TYPE_ITEM: t_element_del = ctxt.GetItemDelimiter(); break; case TYPE_WORD: case TYPE_TOKEN: case TYPE_CHARACTER: default: ctxt . Throw(); return; } MCContainer t_container; MCAutoValueRef t_container_value; if (!destvar -> evalcontainer(ctxt, t_container)) { ctxt . LegacyThrow(EE_ARRAYOP_BADEXP); return; } if (!t_container.eval(ctxt, &t_container_value)) { ctxt . Throw(); return; } if (is_combine) { MCAutoArrayRef t_array; if (!ctxt . ConvertToArray(*t_container_value, &t_array)) return; MCAutoStringRef t_string; if (form == FORM_NONE) { // SN-2014-09-01: [[ Bug 13297 ]] Combining by column deserves its own function as it is too // different from combining by row if (chunk == TYPE_ROW) MCArraysExecCombineByRow(ctxt, *t_array, &t_string); else if (chunk == TYPE_COLUMN) MCArraysExecCombineByColumn(ctxt, *t_array, &t_string); else MCArraysExecCombine(ctxt, *t_array, *t_element_del, *t_key_del, &t_string); } else if (form == FORM_SET) MCArraysExecCombineAsSet(ctxt, *t_array, *t_element_del, &t_string); if (!ctxt . HasError()) t_container.set(ctxt, *t_string); } else { MCAutoStringRef t_string; if (!ctxt . ConvertToString(*t_container_value, &t_string)) return; MCAutoArrayRef t_array; if (form == FORM_NONE) { if (chunk == TYPE_COLUMN) MCArraysExecSplitByColumn(ctxt, *t_string, &t_array); else MCArraysExecSplit(ctxt, *t_string, *t_element_del, *t_key_del, &t_array); } else if (form == FORM_SET) MCArraysExecSplitAsSet(ctxt, *t_string, *t_element_del, &t_array); if (!ctxt . HasError()) t_container.set(ctxt, *t_array); } }
void MCKeywordsExecTry(MCExecContext& ctxt, MCStatement *trystatements, MCStatement *catchstatements, MCStatement *finallystatements, MCVarref *errorvar, uint2 line, uint2 pos) { Try_state state = TS_TRY; MCStatement *tspr = trystatements; Exec_stat stat; Exec_stat retcode = ES_NORMAL; MCtrylock++; while (tspr != NULL) { if (MCtrace || MCnbreakpoints) { MCB_trace(ctxt, tspr->getline(), tspr->getpos()); if (MCexitall) break; } ctxt . SetLineAndPos(tspr->getline(), tspr->getpos()); //stat = tspr->exec(ctxt . GetEP()); tspr->exec_ctxt(ctxt); stat = ctxt . GetExecStat(); ctxt . IgnoreLastError(); MCActionsRunAll(); switch(stat) { case ES_NORMAL: tspr = tspr->getnext(); if (MCexitall) { retcode = ES_NORMAL; tspr = NULL; } if (tspr == NULL && state != TS_FINALLY) { // Everything has executed normally but there may have been an // error added on another event. The trylock needs refactoring to // ensure a trylock on one event can't cause issues in another // event. MCeerror->clear(); tspr = finallystatements; state = TS_FINALLY; } break; case ES_ERROR: if ((MCtrace || MCnbreakpoints) && state != TS_TRY) do { if (MCB_error(ctxt, tspr->getline(), tspr->getpos(), EE_TRY_BADSTATEMENT)) break; ctxt.IgnoreLastError(); tspr->exec_ctxt(ctxt); } while(MCtrace && (stat = ctxt . GetExecStat()) != ES_NORMAL); if (stat == ES_ERROR) { if (MCexitall) { retcode = ES_NORMAL; tspr = NULL; } else if (state != TS_TRY) { MCtrylock--; return; } else { if (errorvar != NULL) { MCAutoStringRef t_error; MCeerror -> copyasstringref(&t_error); errorvar->set(ctxt, *t_error); } // MW-2007-09-04: At this point we need to clear the execution error // stack so that errors inside the catch statements are reported // correctly. MCeerror->clear(); MCperror->clear(); tspr = catchstatements; state = TS_CATCH; // MW-2007-07-03: [[ Bug 3029 ]] - If there is no catch clause // we end up skipping the finally as the loop terminates // before a state transition is made, thus we force it here. if (catchstatements == NULL) { MCeerror -> clear(); tspr = finallystatements; state = TS_FINALLY; } } } else tspr = tspr->getnext(); break; case ES_PASS: if (state == TS_CATCH) { MCAutoValueRef t_value; MCAutoStringRef t_string; if ((errorvar->eval(ctxt, &t_value), !ctxt.HasError()) && ctxt . ConvertToString(*t_value, &t_string)) { MCeerror->copystringref(*t_string, False); } MCeerror->add(EE_TRY_BADSTATEMENT, line, pos); stat = ES_ERROR; } default: if (state == TS_FINALLY) { MCeerror->clear(); retcode = ES_NORMAL; tspr = NULL; } else { retcode = stat; tspr = finallystatements; state = TS_FINALLY; } } } if (state == TS_CATCH) MCeerror->clear(); MCtrylock--; ctxt . SetExecStat(retcode); }
extern "C" MC_DLLEXPORT_DEF MCStringRef MCWidgetExecPopupMenuAtLocation(MCStringRef p_menu, MCCanvasPointRef p_at) { if (!MCWidgetEnsureCurrentWidget()) return nil; MCButton *t_button; t_button = nil; t_button = (MCButton*)MCtemplatebutton->clone(True, OP_NONE, true); if (t_button == nil) { MCErrorThrowOutOfMemory(); return nil; } MCPopupMenuHandler t_handler; MCExecContext ctxt; t_button->setmenuhandler(&t_handler); t_button->SetStyle(ctxt, F_MENU); t_button->SetMenuMode(ctxt, WM_POPUP); t_button->SetText(ctxt, p_menu); MCPoint t_at; MCPoint *t_at_ptr; t_at_ptr = nil; if (p_at != nil) { MCGPoint t_point; MCCanvasPointGetMCGPoint(p_at, t_point); t_at = MCGPointToMCPoint(MCWidgetMapPointToGlobal(MCcurrentwidget, t_point)); t_at_ptr = &t_at; } MCInterfaceExecPopupButton(ctxt, t_button, t_at_ptr); while (t_button->menuisopen() && !MCquit) { MCU_resetprops(True); // MW-2011-09-08: [[ Redraw ]] Make sure we flush any updates. MCRedrawUpdateScreen(); MCscreen->siguser(); MCscreen->wait(REFRESH_INTERVAL, True, True); } t_button->SetVisible(ctxt, 0, false); MCerrorlock++; if (t_button->del(false)) t_button->scheduledelete(); MCerrorlock--; MCAutoStringRef t_string; if (t_handler.GetPick() != nil) ctxt.ConvertToString(t_handler.GetPick(), &t_string); return t_string.Take(); }
void MCPickExecPickOptionByIndex(MCExecContext &ctxt, int p_chunk_type, MCStringRef *p_option_lists, uindex_t p_option_list_count, uindex_t *p_initial_indices, uindex_t p_indices_count, bool p_use_hilite_type, bool p_use_picker, bool p_use_cancel, bool p_use_done, MCRectangle p_button_rect) { MCAutoArray<MCPickList> t_pick_lists; char_t t_delimiter; switch ((MCChunkType)p_chunk_type) { // No access to the line/item delimiter set in the handler from the mobile-specific functions/commands // so following the old engine default values for them case kMCChunkTypeItem: t_delimiter = ','; break; case kMCChunkTypeWord: case kMCChunkTypeLine: t_delimiter = '\n'; break; default: MCUnreachable(); } uindex_t t_old_offset = 0; uindex_t t_new_offset = 0; bool t_success; t_success = true; for (uindex_t i = 0; i < p_option_list_count; i++) { MCStringRef t_option; MCPickList t_pick_list; MCAutoArray<MCStringRef> t_options; t_old_offset = 0; while (t_success && MCStringFirstIndexOfChar(p_option_lists[i], t_delimiter, t_old_offset, kMCCompareCaseless, t_new_offset)) { t_success = MCStringCopySubstring(p_option_lists[i], MCRangeMakeMinMax(t_old_offset, t_new_offset), t_option); if (t_success) t_options . Push(t_option); t_old_offset = t_new_offset + 1; } // Append the remaining part of the options t_success = MCStringCopySubstring(p_option_lists[i], MCRangeMakeMinMax(t_old_offset, MCStringGetLength(p_option_lists[i])), t_option); if (t_success) t_options . Push(t_option); t_options . Take(t_pick_list . options, t_pick_list . option_count); t_pick_list . initial = p_initial_indices[i]; t_pick_lists . Push(t_pick_list); } bool t_cancelled; uindex_t *t_result; uindex_t t_result_count = 0; // Open the picker and allow the user to select the options if (t_success) t_success = MCSystemPickOption(t_pick_lists . Ptr(), t_pick_lists . Size(), t_result, t_result_count, p_use_hilite_type, p_use_picker, p_use_cancel, p_use_done, t_cancelled, p_button_rect); ctxt.SetTheResultToEmpty(); if (t_success) { if (t_cancelled) { // HC-2012-02-15 [[ BUG 9999 ]] Picker should return 0 if cancel was selected. ctxt . SetTheResultToNumber(0); } else { MCAutoListRef t_indices; t_success = MCListCreateMutable(',', &t_indices); for (uindex_t i = 0; i < t_result_count && t_success; i++) { MCAutoStringRef t_index; t_success = MCStringFormat(&t_index, "%u", t_result[i]); if (t_success) t_success = MCListAppend(*t_indices, *t_index); } MCAutoStringRef t_string; /* UNCHECKED */ MCListCopyAsString(*t_indices, &t_string); ctxt . SetTheResultToValue(*t_string); } } // Free memory for (uindex_t i = 0; i < t_pick_lists . Size(); i++) for (uindex_t j = 0; j < t_pick_lists[i] . option_count; j++) MCValueRelease(t_pick_lists[i] . options[j]); }
void MCPickDoPickDateTime(MCExecContext& ctxt, MCStringRef p_current, MCStringRef p_start, MCStringRef p_end, int32_t *p_step, MCPickButtonType p_buttons, MCRectangle p_button_rect, int p_which) { MCDateTime t_current; MCDateTime *t_current_ptr; t_current_ptr = nil; // PM-2015-09-01: [[ Bug 15844 ]] Allow calling mobilePickDate with empty [, current] [, start] [, end] parameters // i.e. mobilePickDate "time",,,,10 if (!MCStringIsEmpty(p_current)) { if (!MCD_convert_to_datetime(ctxt, p_current, CF_UNDEFINED, CF_UNDEFINED, t_current)) return; t_current_ptr = &t_current; } MCDateTime t_start; MCDateTime *t_start_ptr; t_start_ptr = nil; if (!MCStringIsEmpty(p_start)) { if (!MCD_convert_to_datetime(ctxt, p_start, CF_UNDEFINED, CF_UNDEFINED, t_start)) return; t_start_ptr = &t_start; } MCDateTime t_end; MCDateTime *t_end_ptr; t_end_ptr = nil; if (!MCStringIsEmpty(p_end)) { if (!MCD_convert_to_datetime(ctxt, p_end, CF_UNDEFINED, CF_UNDEFINED, t_end)) return; t_end_ptr = &t_end; } int32_t t_step; if (p_step != nil) t_step = *p_step; else t_step = 1; bool t_cancel_button, t_done_button; t_cancel_button = false; t_done_button = false; switch (p_buttons) { case kMCPickButtonCancel: t_cancel_button = true; break; case kMCPickButtonDone: t_done_button = true; break; case kMCPickButtonCancelAndDone: t_cancel_button = true; t_done_button = true; break; case kMCPickButtonNone: default: break; } MCDateTime t_result; bool t_cancelled; t_cancelled = false; bool t_success; t_success = true; MCAutoValueRef t_result_string; // SN-2014-12-03: [[ Bug 14120 ]] If the picker has been cancelled, we should not try to convert the uninitialised t_result. switch (p_which) { case kMCPickDate: t_success = (MCSystemPickDate(t_current_ptr, t_start_ptr, t_end_ptr, t_cancel_button, t_done_button, &t_result, t_cancelled, p_button_rect) && (t_cancelled || MCD_convert_from_datetime(ctxt, t_result, CF_DATE, CF_UNDEFINED, &t_result_string))); break; case kMCPickTime: t_success = (MCSystemPickTime(t_current_ptr, t_start_ptr, t_end_ptr, t_step, t_cancel_button, t_done_button, &t_result, t_cancelled, p_button_rect) && (t_cancelled || MCD_convert_from_datetime(ctxt, t_result, CF_TIME, CF_UNDEFINED, &t_result_string))); break; case kMCPickDateAndTime: t_success = (MCSystemPickDateAndTime(t_current_ptr, t_start_ptr, t_end_ptr, t_step, t_cancel_button, t_done_button, &t_result, t_cancelled, p_button_rect) && (t_cancelled || MCD_convert_from_datetime(ctxt, t_result, CF_DATE, CF_TIME, &t_result_string))); break; default: MCUnreachable(); } if (t_success) { if (t_cancelled) ctxt.SetTheResultToStaticCString("cancel"); else ctxt . SetTheResultToValue(*t_result_string); return; } ctxt . SetTheResultToEmpty(); }