From 73106d63a35f24e75ea7bb2e9e9eb38ea14335f3 Mon Sep 17 00:00:00 2001 From: Peter TB Brett Date: Thu, 20 Apr 2017 11:39:56 +0100 Subject: [PATCH 0001/2459] system: Add support for accessing system error information. Add the following LCB syntax: - `reset system error`: Reset system code to "none" (i.e. 0) - `the system error code`: The current numerical error code - `the system error message`: A string describing the current error code. --- docs/lcb/notes/feature-system_error.md | 15 ++++ libfoundation/include/foundation-system.h | 3 +- libfoundation/include/system-error.h | 39 ++++++++ libfoundation/libfoundation.gyp | 2 + libfoundation/src/system-error.cpp | 105 ++++++++++++++++++++++ libscript/src/module-system.cpp | 18 +++- libscript/src/system.lcb | 76 +++++++++++++++- 7 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 docs/lcb/notes/feature-system_error.md create mode 100644 libfoundation/include/system-error.h create mode 100644 libfoundation/src/system-error.cpp diff --git a/docs/lcb/notes/feature-system_error.md b/docs/lcb/notes/feature-system_error.md new file mode 100644 index 00000000000..e13fbcd477e --- /dev/null +++ b/docs/lcb/notes/feature-system_error.md @@ -0,0 +1,15 @@ +# LiveCode Builder Standard Library +## System error information + +* Two new expressions have been added for accessing platform-specific + system error status: + + * `the system error code` evaluates to the current numerical system + error code + + * `the system error message` evaluates to a string describing the + current system error + +* The new `reset system error` statement clears the current system + error. + \ No newline at end of file diff --git a/libfoundation/include/foundation-system.h b/libfoundation/include/foundation-system.h index 20bee6dd7e6..30a24ab64f5 100644 --- a/libfoundation/include/foundation-system.h +++ b/libfoundation/include/foundation-system.h @@ -1,5 +1,5 @@ /* -*-c++-*- -Copyright (C) 2015 LiveCode Ltd. +Copyright (C) 2015-2016 LiveCode Ltd. This file is part of LiveCode. @@ -33,6 +33,7 @@ extern "C" { #include #include #include +#include } diff --git a/libfoundation/include/system-error.h b/libfoundation/include/system-error.h new file mode 100644 index 00000000000..0bf6ac8ef95 --- /dev/null +++ b/libfoundation/include/system-error.h @@ -0,0 +1,39 @@ +/* -*-c++-*- +Copyright (C) 2016 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 . */ + +#if !defined(__MCS_SYSTEM_H_INSIDE__) +# error "Only can be included directly" +#endif + +/* ================================================================ + * System error handling + * ================================================================ */ + +/* The MCSError library provides an API for accessing and resetting + * the system error status. This is to support standardized use of + * the POSIX and Win32 APIs. + */ + +/* Reset or clear the current system error state. */ +MC_DLLEXPORT void MCSErrorReset (void); + +/* Get the platform-dependent numeric code corresponding to the + * current system error. */ +MC_DLLEXPORT uint32_t MCSErrorGetCode (void); + +/* Get a platform-dependent string describing a system error code. */ +MC_DLLEXPORT bool MCSErrorGetDescription (uint32_t p_code, MCStringRef& r_description); diff --git a/libfoundation/libfoundation.gyp b/libfoundation/libfoundation.gyp index b831b67be26..212ab00a449 100644 --- a/libfoundation/libfoundation.gyp +++ b/libfoundation/libfoundation.gyp @@ -66,6 +66,7 @@ 'include/foundation-text.h', 'include/foundation-unicode.h', 'include/system-commandline.h', + 'include/system-error.h', 'include/system-file.h', 'include/system-init.h', 'include/system-library.h', @@ -112,6 +113,7 @@ 'src/foundation-objc.mm', 'src/foundation-ffi-js.cpp', 'src/system-commandline.cpp', + 'src/system-error.cpp', 'src/system-file.cpp', 'src/system-file-posix.cpp', 'src/system-file-w32.cpp', diff --git a/libfoundation/src/system-error.cpp b/libfoundation/src/system-error.cpp new file mode 100644 index 00000000000..a7094c5ec84 --- /dev/null +++ b/libfoundation/src/system-error.cpp @@ -0,0 +1,105 @@ +/* -*-c++-*- +Copyright (C) 2016 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 "system-private.h" + +#include + +#if defined(__WINDOWS__) +/* ================================================================ + * Windows implementations + * ================================================================ */ +# include + +MC_DLLEXPORT_DEF void +MCSErrorReset () +{ + SetLastError (0); +} + +MC_DLLEXPORT_DEF uint32_t +MCSErrorGetCode () +{ + return GetLastError (); +} + +MC_DLLEXPORT_DEF bool +MCSErrorGetDescription (uint32_t p_code, + MCStringRef& r_description) +{ + DWORD t_code = GetLastError (); + + /* No error has been recorded */ + if (0 == t_code) + { + return MCStringCopy (kMCEmptyString, r_description); + } + + LPWSTR t_message_buffer = nil; + + DWORD t_message_len = FormatMessageW ( + (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS), /* dwFlags */ + nil, /* lpSource */ + t_code, /* dwMessageId */ + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* dwLanguageId */ + reinterpret_cast(&t_message_buffer), /* lpBuffer */ + 0, /* nSize */ + nil); /* arguments... */ + + bool t_success = true; + MCAutoStringRef t_description; + + if (t_success) + t_success = MCStringCreateWithChars(t_message_buffer, + t_message_len, + &t_description); + + LocalFree(t_message_buffer); + + return MCStringCopy(*t_description, r_description); +} + +#else /* !__WINDOWS__ */ +/* ================================================================ + * POSIX implementations + * ================================================================ */ + +#include + +MC_DLLEXPORT_DEF void +MCSErrorReset () +{ + errno = 0; +} + +MC_DLLEXPORT_DEF uint32_t +MCSErrorGetCode () +{ + return errno; +} + +MC_DLLEXPORT_DEF bool +MCSErrorGetDescription (uint32_t p_code, + MCStringRef& r_description) +{ + return MCStringCreateWithCString(strerror(p_code), + r_description); +} + +#endif /* !__WINDOWS__ */ diff --git a/libscript/src/module-system.cpp b/libscript/src/module-system.cpp index 57a90c922e1..a9784131b16 100644 --- a/libscript/src/module-system.cpp +++ b/libscript/src/module-system.cpp @@ -1,5 +1,5 @@ /* -*-c++-*- -Copyright (C) 2015 LiveCode Ltd. +Copyright (C) 2015-2016 LiveCode Ltd. This file is part of LiveCode. @@ -62,6 +62,22 @@ MCSystemExecGetCommandArguments (MCProperListRef & r_list) /* UNCHECKED */ MCSCommandLineGetArguments (r_list); } +/* ================================================================ + * System error information + * ================================================================ */ + +extern "C" MC_DLLEXPORT_DEF void +MCSystemEvalErrorCode (uint32_t & r_code) +{ + r_code = MCSErrorGetCode (); +} + +extern "C" MC_DLLEXPORT_DEF void +MCSystemEvalErrorDescription (MCStringRef & r_string) +{ + /* UNCHECKED */ MCSErrorGetDescription (MCSErrorGetCode (), r_string); +} + //////////////////////////////////////////////////////////////// extern "C" bool com_livecode_system_Initialize (void) diff --git a/libscript/src/system.lcb b/libscript/src/system.lcb index a1628e7df8a..a3c9bd68126 100644 --- a/libscript/src/system.lcb +++ b/libscript/src/system.lcb @@ -1,5 +1,5 @@ /* -Copyright (C) 2015 LiveCode Ltd. +Copyright (C) 2015-2016 LiveCode Ltd. This file is part of LiveCode. @@ -161,6 +161,80 @@ begin MCSystemExecGetCommandArguments(output) end syntax +---------------------------------------------------------------- +-- System error information +---------------------------------------------------------------- + +public foreign handler MCSErrorReset() returns nothing binds to "" +public foreign handler MCSystemEvalErrorCode(out Code as UInt32) returns nothing binds to "" +public foreign handler MCSystemEvalErrorDescription(out Description as String) returns nothing binds to "" + + +/** +Summary: Clear the system error code. + +Description: + +Reset the system error code to its platform-dependent default ("no +error") value. + +Tags: System +*/ +syntax ResetSystemError is statement + "reset" "system" "error" +begin + MCSErrorReset() +end syntax + +/** +Summary: The system error code. + +Description: + +Evaluates to the current platform-dependent system error code. + +- On Windows, returns the result of `GetLastError()`. + +- On other platforms, returns the current value of `errno`. + +> **Note:** The system error code may be modified or cleared by any +> syntax that interacts with the operating system (e.g. by performing +> input or output). You should check the system error code as soon as +> possible after any platform operation that might fail. + +Related: SystemErrorDescription + +Tags: System +*/ +syntax SystemErrorCode is expression + "the" "system" "error" "code" +begin + MCSystemEvalErrorCode(output) +end syntax + +/** +Summary: The system error description. + +Description: + +Evaluates to a string describing the current platform-dependent system +error code. + +> **Note:** The system error code may be modified or cleared by any +> syntax that interacts with the operating system (e.g. by performing +> input or output). You should check the system error code as soon as +> possible after any platform operation that might fail. + +Related: SystemErrorCode + +Tags: System +*/ +syntax SystemErrorDescription is expression + "the" "system" "error" "message" +begin + MCSystemEvalErrorDescription(output) +end syntax + -- end module From 710c259e91cbb19ef863d0aa14161fdca74cd266 Mon Sep 17 00:00:00 2001 From: Peter TB Brett Date: Fri, 17 Feb 2017 16:58:01 +0000 Subject: [PATCH 0002/2459] Tidy bitmap effect setters/getters to prevent maybe-uninitialized Move the bitmap effect property lookup into the block where it is actually used. This is both cleaner and prevents `-Wmaybe-uninitialized` warnings. --- engine/src/bitmapeffect.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/engine/src/bitmapeffect.cpp b/engine/src/bitmapeffect.cpp index 48d454646fa..36d9294c529 100644 --- a/engine/src/bitmapeffect.cpp +++ b/engine/src/bitmapeffect.cpp @@ -678,10 +678,6 @@ bool MCBitmapEffectsGetProperty(MCExecContext& ctxt, MCBitmapEffectsRef& self, M t_effect = &self -> effects[t_type]; else t_effect = nil; - - MCBitmapEffectProperty t_prop; - if (!MCNameIsEmpty(p_index) && MCBitmapEffectLookupProperty(t_type, p_index, t_prop) != ES_NORMAL) - return false; if (t_is_array) { @@ -716,6 +712,10 @@ bool MCBitmapEffectsGetProperty(MCExecContext& ctxt, MCBitmapEffectsRef& self, M } else { + MCBitmapEffectProperty t_prop; + if (MCBitmapEffectLookupProperty(t_type, p_index, + t_prop) != ES_NORMAL) + return false; MCBitmapEffectFetchProperty(ctxt, t_effect, t_prop, r_value); return true; } @@ -983,7 +983,6 @@ bool MCBitmapEffectsSetProperty(MCExecContext& ctxt, MCBitmapEffectsRef& self, M return true; } - MCBitmapEffectProperty t_prop; MCBitmapEffect effect; bool t_dirty; @@ -1003,10 +1002,6 @@ bool MCBitmapEffectsSetProperty(MCExecContext& ctxt, MCBitmapEffectsRef& self, M t_dirty = true; } - // Lookup the property and ensure it is appropriate for our type. - if (!MCNameIsEmpty(p_index) && MCBitmapEffectLookupProperty(t_type, p_index, t_prop) != ES_NORMAL) - return false; - if (t_is_array) { bool t_dirty_array; @@ -1037,8 +1032,15 @@ bool MCBitmapEffectsSetProperty(MCExecContext& ctxt, MCBitmapEffectsRef& self, M } else + { + MCBitmapEffectProperty t_prop; + if (MCBitmapEffectLookupProperty(t_type, p_index, + t_prop) != ES_NORMAL) + return false; + MCBitmapEffectStoreProperty(ctxt, effect, t_prop, p_value, t_dirty); - + } + if (t_dirty) { // If we are currently empty, then allocate a new object From 503aeba188db1878b5ff978f4dec59d703db5653 Mon Sep 17 00:00:00 2001 From: Peter TB Brett Date: Mon, 20 Feb 2017 15:26:44 +0000 Subject: [PATCH 0003/2459] MCGraphicsContext: Use managed pointers for temporary arrays Using managed pointers for temporary arrays prevents any possibility of dereferencing an uninitialised pointer on memory allocation failure. --- engine/src/graphicscontext.cpp | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/engine/src/graphicscontext.cpp b/engine/src/graphicscontext.cpp index 28e26342076..de2eb291409 100644 --- a/engine/src/graphicscontext.cpp +++ b/engine/src/graphicscontext.cpp @@ -782,10 +782,10 @@ void MCGraphicsContext::setgradient(MCGradientFill *p_gradient) break; } - MCGFloat *t_stops; - /* UNCHECKED */ MCMemoryNewArray(p_gradient -> ramp_length, t_stops); - MCGColor *t_colors; - /* UNCHECKED */ MCMemoryNewArray(p_gradient -> ramp_length, t_colors); + /* UNCHECKED */ MCAutoPointer t_stops = + new MCGFloat[p_gradient->ramp_length](); + /* UNCHECKED */ MCAutoPointer t_colors = + new MCGColor[p_gradient->ramp_length](); for (uint32_t i = 0; i < p_gradient -> ramp_length; i++) { t_stops[i] = (MCGFloat) p_gradient -> ramp[i] . offset / STOP_INT_MAX; @@ -800,11 +800,8 @@ void MCGraphicsContext::setgradient(MCGradientFill *p_gradient) t_transform . tx = p_gradient -> origin . x; t_transform . ty = p_gradient -> origin . y; - MCGContextSetFillGradient(m_gcontext, t_function, t_stops, t_colors, p_gradient -> ramp_length, p_gradient -> mirror, p_gradient -> wrap, p_gradient -> repeat, t_transform, t_filter); - MCGContextSetStrokeGradient(m_gcontext, t_function, t_stops, t_colors, p_gradient -> ramp_length, p_gradient -> mirror, p_gradient -> wrap, p_gradient -> repeat, t_transform, t_filter); - - MCMemoryDeleteArray(t_stops); - MCMemoryDeleteArray(t_colors); + MCGContextSetFillGradient(m_gcontext, t_function, t_stops.Get(), t_colors.Get(), p_gradient -> ramp_length, p_gradient -> mirror, p_gradient -> wrap, p_gradient -> repeat, t_transform, t_filter); + MCGContextSetStrokeGradient(m_gcontext, t_function, t_stops.Get(), t_colors.Get(), p_gradient -> ramp_length, p_gradient -> mirror, p_gradient -> wrap, p_gradient -> repeat, t_transform, t_filter); } } @@ -1011,19 +1008,17 @@ void MCGraphicsContext::drawlines(MCPoint *points, uint2 npoints, bool p_closed) else { // MM-2013-11-14: [[ Bug 11457 ]] Adjust lines and polygons to make sure antialiased lines don't draw across pixels. - MCGPoint *t_points; - /* UNCHECKED */ MCMemoryNewArray(npoints, t_points); + /* UNCHECKED */ MCAutoPointer t_points = + new MCGPoint[npoints](); for (uint32_t i = 0; i < npoints; i++) t_points[i] = MCPointToMCGPoint(points[i], 0.5f); MCGContextBeginPath(m_gcontext); if (p_closed) - MCGContextAddPolygon(m_gcontext, t_points, npoints); + MCGContextAddPolygon(m_gcontext, t_points.Get(), npoints); else - MCGContextAddPolyline(m_gcontext, t_points, npoints); + MCGContextAddPolyline(m_gcontext, t_points.Get(), npoints); MCGContextStroke(m_gcontext); - - MCMemoryDeleteArray(t_points); } } @@ -1031,16 +1026,14 @@ void MCGraphicsContext::fillpolygon(MCPoint *points, uint2 npoints) { // MM-2013-11-26: [[ Bug 11501 ]] Adjust lines and polygons to make sure antialiased lines don't draw across pixels. // Here the adjust is 0.25 - not the same path as draw lines but appears to solve the issue where the fill interfers with the stroke. - MCGPoint *t_points; - /* UNCHECKED */ MCMemoryNewArray(npoints, t_points); + /* UNCHECKED */ MCAutoPointer t_points = + new MCGPoint[npoints](); for (uint32_t i = 0; i < npoints; i++) t_points[i] = MCPointToMCGPoint(points[i], 0.25f); MCGContextBeginPath(m_gcontext); - MCGContextAddPolygon(m_gcontext, t_points, npoints); + MCGContextAddPolygon(m_gcontext, t_points.Get(), npoints); MCGContextFill(m_gcontext); - - MCMemoryDeleteArray(t_points); } static MCGRectangle MCGRectangleInset(const MCGRectangle &p_rect, MCGFloat p_inset) From 74728f43fb3d46c1eed99a18117242b303ebe78b Mon Sep 17 00:00:00 2001 From: Peter TB Brett Date: Fri, 17 Feb 2017 16:58:01 +0000 Subject: [PATCH 0004/2459] -Wmaybe-uninitialized fixes --- config/linux-settings.gypi | 1 - engine/src/block.cpp | 2 +- engine/src/buttondraw.cpp | 2 +- engine/src/deploy.cpp | 2 +- engine/src/deploy_linux.cpp | 21 ++++++++------------- engine/src/field.cpp | 2 +- engine/src/fields.cpp | 4 ++-- engine/src/hc.cpp | 6 +++--- engine/src/ibmp.cpp | 5 +++-- engine/src/idraw.cpp | 6 ++++-- engine/src/igif.cpp | 2 +- engine/src/image.cpp | 2 +- engine/src/imagelist.cpp | 4 ++-- engine/src/opensslsocket.cpp | 4 ++-- engine/src/scriptpt.cpp | 4 ++-- engine/src/variable.cpp | 2 +- libfoundation/src/foundation-locale.cpp | 2 +- 17 files changed, 34 insertions(+), 37 deletions(-) diff --git a/config/linux-settings.gypi b/config/linux-settings.gypi index 17712e03c22..75ffc2cd491 100644 --- a/config/linux-settings.gypi +++ b/config/linux-settings.gypi @@ -71,7 +71,6 @@ '-Wno-unused-parameter', # Just contributes build noise '-Werror=return-type', '-Werror=uninitialized', - '-Wno-error=maybe-uninitialized', '-Werror=conversion-null', '-Werror=empty-body', ], diff --git a/engine/src/block.cpp b/engine/src/block.cpp index 13972f74cfd..3d087822953 100755 --- a/engine/src/block.cpp +++ b/engine/src/block.cpp @@ -169,7 +169,7 @@ IO_stat MCBlock::load(IO_handle stream, uint32_t version, bool is_ext) // MW-2012-03-04: [[ StackFile5500 ]] If this is an extended block, then work out // where to skip to when all the attrs currently recognized have been read. - int64_t t_attr_end; + int64_t t_attr_end = 0; if (is_ext) { // Read the size. diff --git a/engine/src/buttondraw.cpp b/engine/src/buttondraw.cpp index 31e6edfef62..7f23bd15b4b 100644 --- a/engine/src/buttondraw.cpp +++ b/engine/src/buttondraw.cpp @@ -377,7 +377,7 @@ void MCButton::draw(MCDC *dc, const MCRectangle& p_dirty, bool p_isolated, bool // MW-2009-06-14: We will assume (perhaps unwisely) that is 'opaque' is set // then the background is now, completely opaque. - bool t_was_opaque; + bool t_was_opaque = false; if (getflag(F_OPAQUE)) t_was_opaque = dc -> changeopaque(true); diff --git a/engine/src/deploy.cpp b/engine/src/deploy.cpp index 6a65dd58c5c..d10500c0498 100644 --- a/engine/src/deploy.cpp +++ b/engine/src/deploy.cpp @@ -858,7 +858,7 @@ void MCIdeDeploy::exec_ctxt(MCExecContext& ctxt) t_has_error = true; } - uint32_t t_platform; + uint32_t t_platform = PLATFORM_NONE; switch(m_platform) { case PLATFORM_MACOSX: diff --git a/engine/src/deploy_linux.cpp b/engine/src/deploy_linux.cpp index c3e2c7b3ce2..419a497173d 100644 --- a/engine/src/deploy_linux.cpp +++ b/engine/src/deploy_linux.cpp @@ -548,8 +548,7 @@ static bool MCDeployToLinuxReadProgramHeaders(MCDeployFileRef p_file, typename T template static bool MCDeployToLinuxReadString(MCDeployFileRef p_file, typename T::Shdr& p_string_header, uint32_t p_index, char*& r_string) { - bool t_success; - t_success = true; + bool t_success = true; // First check that the index is valid if (p_index >= p_string_header . sh_size) @@ -558,11 +557,9 @@ static bool MCDeployToLinuxReadString(MCDeployFileRef p_file, typename T::Shdr& // As the string table does not contain any string lengths and they are // just NUL terminated, we must gradually load portions until a NUL is // reached. - char *t_buffer; - uint32_t t_length; - t_buffer = NULL; - t_length = 0; - + char *t_buffer = nullptr; + uint32_t t_length = 0; + while(t_success) { // Compute how much data to read - this is either the fixed chunk @@ -688,17 +685,15 @@ Exec_stat MCDeployToELF(const MCDeployParameters& p_params, bool p_is_android) t_payload_section = NULL; for(uint32_t i = 0; t_success && i < t_header . e_shnum && t_project_section == NULL; i++) { - char *t_section_name; - t_success = MCDeployToLinuxReadString(t_engine, t_section_headers[t_header . e_shstrndx], t_section_headers[i] . sh_name, t_section_name); + MCAutoPointer t_section_name; + t_success = MCDeployToLinuxReadString(t_engine, t_section_headers[t_header . e_shstrndx], t_section_headers[i] . sh_name, &t_section_name); // Notice that we compare 9 bytes, this is to ensure we match .project // only and not .project (i.e. we match the NUL char). - if (t_success && memcmp(t_section_name, ".project", 9) == 0) + if (t_success && memcmp(*t_section_name, ".project", 9) == 0) t_project_section = &t_section_headers[i]; - if (t_success && memcmp(t_section_name, ".payload", 9) == 0) + if (t_success && memcmp(*t_section_name, ".payload", 9) == 0) t_payload_section = &t_section_headers[i]; - - delete t_section_name; } if (t_success && t_project_section == NULL) diff --git a/engine/src/field.cpp b/engine/src/field.cpp index 94b687036d2..c6e8afbd626 100644 --- a/engine/src/field.cpp +++ b/engine/src/field.cpp @@ -2522,7 +2522,7 @@ void MCField::draw(MCDC *dc, const MCRectangle& p_dirty, bool p_isolated, bool p // MW-2009-06-14: If the field is opaque, then render the contents with that // marked. - bool t_was_opaque; + bool t_was_opaque = false; if (getflag(F_OPAQUE)) t_was_opaque = dc -> changeopaque(true); drawrect(dc, dirty); diff --git a/engine/src/fields.cpp b/engine/src/fields.cpp index 9a3b23a212b..92f77750664 100644 --- a/engine/src/fields.cpp +++ b/engine/src/fields.cpp @@ -701,7 +701,7 @@ Exec_stat MCField::settextindex(uint4 parid, findex_t si, findex_t ei, MCStringR MCParagraph *t_initial_pgptr; t_initial_pgptr = pgptr; - int32_t t_initial_height; + int32_t t_initial_height = 0; if (opened && fptr == fdata) t_initial_height = t_initial_pgptr -> getheight(fixedheight); @@ -780,7 +780,7 @@ Exec_stat MCField::settextindex(uint4 parid, findex_t si, findex_t ei, MCStringR // MM-2014-04-09: [[ Bug 12088 ]] Get the width of the paragraph before insertion and layout. // If as a result of the update the width of the field has changed, we need to recompute. // MW-2014-06-06: [[ Bug 12385 ]] Don't do anything layout related if not open. - int2 t_initial_width; + int2 t_initial_width = 0; if (opened != 0) t_initial_width = pgptr -> getwidth(); diff --git a/engine/src/hc.cpp b/engine/src/hc.cpp index 08ca6ed61b4..85c149b00c6 100644 --- a/engine/src/hc.cpp +++ b/engine/src/hc.cpp @@ -674,9 +674,9 @@ MCCdata *MCHctext::buildf(MCHcstak *hcsptr, MCField *parent) string = MCU_empty(); char *eptr = string; MCParagraph *paragraphs = NULL; - const char *tname; - uint2 tsize; - uint2 tstyle; + const char *tname = nullptr; + uint2 tsize = 0; + uint2 tstyle = 0; uint2 aindex = 2; uint2 aoffset = 0; uint2 alength = 0; diff --git a/engine/src/ibmp.cpp b/engine/src/ibmp.cpp index addb7d33caf..c14cc4ea5d7 100644 --- a/engine/src/ibmp.cpp +++ b/engine/src/ibmp.cpp @@ -633,7 +633,8 @@ bool bmp_read_rle4_image(IO_handle p_stream, uindex_t &x_bytes_read, MCImageBitm else { // absolute mode - uint8_t t_byte, t_upper, t_lower; + uint8_t t_byte, t_upper; + uint8_t t_lower = 0; uint8_t t_run_buffer[128]; uint32_t t_run_bytes; @@ -1556,7 +1557,7 @@ bool MCNetPBMImageLoader::LoadFrames(MCBitmapFrame *&r_frames, uint32_t &r_count uindex_t t_token_size; bool t_binary; - uindex_t t_depth; + uindex_t t_depth = 1; uindex_t t_channel_count = 1; uindex_t t_stride; diff --git a/engine/src/idraw.cpp b/engine/src/idraw.cpp index 2d134d72a81..7a72657dfa1 100644 --- a/engine/src/idraw.cpp +++ b/engine/src/idraw.cpp @@ -285,8 +285,10 @@ void MCImage::drawwithgravity(MCDC *dc, MCRectangle r, MCGravity p_gravity) t_old_opacity = dc -> getopacity(); dc -> setopacity(blendlevel * 255 / 100); - int2 dx, dy; - uint2 dw, dh; + int2 dx = 0; + int2 dy = 0; + uint2 dw = 0; + uint2 dh = 0; switch(p_gravity) { diff --git a/engine/src/igif.cpp b/engine/src/igif.cpp index a87d47f9769..19fc1d4c739 100644 --- a/engine/src/igif.cpp +++ b/engine/src/igif.cpp @@ -288,7 +288,7 @@ bool MCGIFImageLoader::LoadFrames(MCBitmapFrame *&r_frames, uint32_t &r_count) // restoration info MCImageBitmap *t_restore_image = nil; int t_disposal_mode = DISPOSAL_UNSPECIFIED; - MCRectangle t_disposal_region; + MCRectangle t_disposal_region = kMCEmptyRectangle; // The list of frames. MCBitmapFrame *t_frames = nil; diff --git a/engine/src/image.cpp b/engine/src/image.cpp index 262e4980711..eb415dbdac6 100644 --- a/engine/src/image.cpp +++ b/engine/src/image.cpp @@ -845,7 +845,7 @@ void MCImage::draw(MCDC *dc, const MCRectangle& p_dirty, bool p_isolated, bool p } } - bool t_need_group; + bool t_need_group = false; if (!p_isolated) { // MW-2009-06-10: [[ Bitmap Effects ]] diff --git a/engine/src/imagelist.cpp b/engine/src/imagelist.cpp index dff05f01e1d..c6224ae1629 100644 --- a/engine/src/imagelist.cpp +++ b/engine/src/imagelist.cpp @@ -371,7 +371,7 @@ MCPatternRef MCImageList::allocpat(uint4 id, MCObject *optr) if (newim == nil) return nil; - MCPatternRef pat; + MCPatternRef pat = nullptr; MCImageListNode *tptr = images; if (tptr != nil) do @@ -384,7 +384,7 @@ MCPatternRef MCImageList::allocpat(uint4 id, MCObject *optr) /* UNCHECKED */ tptr = new (nothrow) MCImageListNode(newim); tptr->appendto(images); - tptr->allocimage(newim, pat); + /* UNCHECKED */ tptr->allocimage(newim, pat); return pat; } diff --git a/engine/src/opensslsocket.cpp b/engine/src/opensslsocket.cpp index eb107b6fb07..18259da6f87 100644 --- a/engine/src/opensslsocket.cpp +++ b/engine/src/opensslsocket.cpp @@ -868,8 +868,8 @@ MCSocket *MCS_open_socket(MCNameRef name, MCNameRef from, Boolean datagram, MCOb } else { - MCOpenSocketCallbackInfo *t_info; - MCMemoryNew(t_info); + MCOpenSocketCallbackInfo *t_info = nullptr; + /* UNCHECKED */ MCMemoryNew(t_info); t_info->m_socket = s; s->resolve_state = kMCSocketStateResolving; if (!MCS_name_to_sockaddr(MCNameGetString(s->name), &t_info->m_sockaddr, open_socket_resolve_callback, t_info)) diff --git a/engine/src/scriptpt.cpp b/engine/src/scriptpt.cpp index 13455c63af4..ff5e61c42ea 100644 --- a/engine/src/scriptpt.cpp +++ b/engine/src/scriptpt.cpp @@ -609,7 +609,7 @@ Parse_stat MCScriptPoint::next(Symbol_type &type) in_tag = True; // Stores the length of the Date: Mon, 15 May 2017 11:17:16 +0100 Subject: [PATCH 0005/2459] [[ Maybe Uninitialized ]] Clean up MCVarref::resolve --- engine/src/variable.cpp | 106 ++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/engine/src/variable.cpp b/engine/src/variable.cpp index fa7f2c2ec38..08481c85e5b 100644 --- a/engine/src/variable.cpp +++ b/engine/src/variable.cpp @@ -1487,71 +1487,71 @@ bool MCVarref::resolve(MCExecContext& ctxt, MCContainer& r_container) // AL-2014-08-20: [[ ArrayElementRefParams ]] If the Varref refers to a container then // resolving the path requires appending the new dimensions to the old path - - MCNameRef *t_path; MCSpan t_old_path = getpath(ctxt); - uindex_t t_path_length = t_old_path.size(); - - uindex_t t_new_dimension_count; - t_new_dimension_count = dimensions + t_path_length; - - /* UNCHECKED */ MCMemoryNewArray(t_new_dimension_count, t_path, t_new_dimension_count); + MCAutoNameRefArray t_path; + if (!t_path . New(t_old_path.size())) + return false; - for (uindex_t i = 0; i < t_path_length; i++) + for (uindex_t i = 0; i < t_old_path.size(); i++) t_path[i] = MCValueRetain(t_old_path[i]); - for(uindex_t i = 0; i < dimensions && !ctxt . HasError(); i++) + auto t_push_value_as_name = [&](MCValueRef p_value) { + MCNewAutoNameRef t_key; + if (!ctxt . ConvertToName(p_value, &t_key)) + { + ctxt . LegacyThrow(EE_VARIABLE_BADINDEX); + return false; + } + + if (!t_path.Push(*t_key)) + return false; + + MCValueRetain(*t_key); + return true; + }; + + for(uindex_t i = 0; i < dimensions; i++) { MCAutoValueRef t_value; - if (ctxt . EvalExprAsValueRef(t_dimensions[i], EE_VARIABLE_BADINDEX, &t_value)) + if (!ctxt . EvalExprAsValueRef(t_dimensions[i], EE_VARIABLE_BADINDEX, &t_value)) + return false; + + MCAutoArrayRef t_array; + if (ctxt . ConvertToArray(*t_value, &t_array) + && !MCArrayIsEmpty(*t_array)) { - MCAutoArrayRef t_array; - - if (ctxt . ConvertToArray(*t_value, &t_array) - && !MCArrayIsEmpty(*t_array)) + if (!MCArrayIsSequence(*t_array)) { - if (!MCArrayIsSequence(*t_array)) - ctxt . LegacyThrow(EE_VARIABLE_BADINDEX); - else - { - uindex_t t_length; - t_length = MCArrayGetCount(*t_array); - - /* UNCHECKED */ MCMemoryResizeArray(t_new_dimension_count + t_length, t_path, t_new_dimension_count); - - for(uindex_t t_index = 1; t_index <= t_length; t_index += 1) - { - MCValueRef t_value_fetched; - /* UNCHECKED */ MCArrayFetchValueAtIndex(*t_array, t_index, t_value_fetched); - - if (!ctxt . ConvertToName(t_value_fetched, t_path[t_path_length++])) - { - ctxt . LegacyThrow(EE_VARIABLE_BADINDEX); - break; - } - } - } - } - else if (!ctxt . ConvertToName(*t_value, t_path[t_path_length++])) ctxt . LegacyThrow(EE_VARIABLE_BADINDEX); - } - } + return false; + } - if (!ctxt . HasError()) - { - if (isparam) - return MCContainer::copywithpath(fetchcontainer(ctxt), t_path, t_path_length, r_container); + uindex_t t_length = MCArrayGetCount(*t_array); + for(uindex_t t_index = 1; t_index <= t_length; t_index += 1) + { + MCValueRef t_value_fetched; + if (!MCArrayFetchValueAtIndex(*t_array, t_index, t_value_fetched)) + return false; + + if (!t_push_value_as_name(t_value_fetched)) + return false; + } + } else - return MCContainer::createwithpath(fetchvar(ctxt), t_path, t_path_length, r_container); - } - else - { - for(uindex_t i = 0; i < t_path_length; i++) - MCValueRelease(t_path[i]); - MCMemoryDeleteArray(t_path); + { + if (!t_push_value_as_name(*t_value)) + return false; + } + } - return false; - } + MCNameRef *t_path_values = nullptr; + uindex_t t_count = 0; + t_path . Take(t_path_values, t_count); + + if (isparam) + return MCContainer::copywithpath(fetchcontainer(ctxt), t_path_values, t_count, r_container); + else + return MCContainer::createwithpath(fetchvar(ctxt), t_path_values, t_count, r_container); } MCSpan MCVarref::getpath(MCExecContext& ctxt) From 0e5e638d4727989953a763cfbaade721269c3eac Mon Sep 17 00:00:00 2001 From: livecodeali Date: Wed, 31 May 2017 11:50:25 +0100 Subject: [PATCH 0006/2459] [[ Travis ]] Use JDK 1.8 on Travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 469454fbc57..d3bb80341bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,7 +37,7 @@ env: - CXX_STD: "c++11" jdk: - - openjdk6 + - openjdk8 # Build using clang on mac and gcc on linux matrix: From 3ca6b1e8c6a212714d29e0593c846dbf14faded5 Mon Sep 17 00:00:00 2001 From: Devin Asay Date: Fri, 1 Sep 2017 16:22:45 -0600 Subject: [PATCH 0007/2459] [[ Docs ]] Fixes to stackFiles.lcdoc - Various minor formatting fixes. - Changed file extensions in code examples to .livecode. - Repaired mis-labeled reference entries. --- docs/dictionary/property/stackFiles.lcdoc | 34 +++++++++++------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/docs/dictionary/property/stackFiles.lcdoc b/docs/dictionary/property/stackFiles.lcdoc index 5bc6ae82154..75f3abc65ad 100644 --- a/docs/dictionary/property/stackFiles.lcdoc +++ b/docs/dictionary/property/stackFiles.lcdoc @@ -17,7 +17,7 @@ OS: mac, windows, linux, ios, android Platforms: desktop, server, mobile Example: -set the stackFiles of this stack to "My Dialog,Custom Dialogs.rev" +set the stackFiles of this stack to "My Dialog,Custom Dialogs.livecode" Value: The of a is a list of stack references, one per @@ -47,31 +47,30 @@ For example, if your stack contains a statement like this, the stack "Customers" must either be loaded into memory, or be listed in the , in order for LiveCode to know where it is: -```get the width of field "Text" of card "Data" of stack "Customers"``` + get the width of field "Text" of card "Data" of stack "Customers" In this example, if the "Customers" stack is not open and isn't in the , the must refer to it by its full , including its : -``` get the width of field "Text" of card "Data" of stack "Customers" \ - - of stack "/Volumes/Data/Business.rev" ``` + get the width of field "Text" of card "Data" of stack "Customers" \ + of stack "/Volumes/Data/Business.livecode" Using the lets you simply specify the name, instead of including its everywhere you refer to an in the . -The of a
is inherited by its : if +The of a
is inherited by its : if a in a refers to a that's not , LiveCode checks the of both the and its
. >*Important:* in the > start from the that the is in, rather -> than starting from the as with other path|relative paths> in . +> than starting from the as with other +> in . Placing a stack in the lets in your refer to in the referenced , but does @@ -81,16 +80,15 @@ To use a as a , allowing your to call the , use the or . -References: stacks (function), mainStacks (function), object (glossary), -substack (glossary), start using (glossary), call (glossary), -property (glossary), loaded into memory (glossary), load (glossary), -file path (glossary), command (glossary), statement (glossary), -LiveCode (glossary), main stack (glossary), relative file path (glossary), -folder (glossary), script (glossary), handler (glossary), long (keyword), -line (keyword), insert script (library), library (library), -stack (object), substacks (property), properties (property), -mainStack (property), defaultFolder (property), name (property), -filename of stack (property) +References: call (glossary), command (glossary), +defaultFolder (property), file path (glossary), +filename of stack (property), folder (glossary), handler (glossary), insert script (command), library (library), line (keyword), +LiveCode (glossary), load (glossary), loaded into memory (glossary), long (keyword), main stack (glossary), mainStack (property), +mainStacks (function), name (property), object (glossary), +properties (property), property (glossary), +relative file path (glossary), script (glossary), stack (object), +stacks (function), start using (command), statement (glossary), +substack (glossary), substacks (property) Tags: file system From 9f05b202a67c7de2399e147192656dbf382a2fcd Mon Sep 17 00:00:00 2001 From: livecodeali Date: Wed, 27 Sep 2017 16:19:15 +0100 Subject: [PATCH 0008/2459] [[ Bug 20478 ]] Fix crash on exit after using the commandName - Fix the missing retain when fetching the commandName - Fix a memory leak in the MCCommandArguments class - Refactor the MCCommandArguments and MCCommandName classes so that their functionality is implemented in the engine module - Add test for crash --- docs/notes/bugfix-20478.md | 1 + engine/src/exec-engine.cpp | 27 ++++++++++++++ engine/src/exec.h | 8 +++++ engine/src/funcs.cpp | 26 ++++++-------- engine/src/funcs.h | 7 ++-- tests/lcs/core/engine/_commandname.lc | 3 ++ .../core/engine/_commandname.livecodescript | 5 +++ .../core/engine/commandargs.livecodescript | 35 +++++++++++++++++++ 8 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 docs/notes/bugfix-20478.md create mode 100755 tests/lcs/core/engine/_commandname.lc create mode 100755 tests/lcs/core/engine/_commandname.livecodescript create mode 100644 tests/lcs/core/engine/commandargs.livecodescript diff --git a/docs/notes/bugfix-20478.md b/docs/notes/bugfix-20478.md new file mode 100644 index 00000000000..ed6394e4b5f --- /dev/null +++ b/docs/notes/bugfix-20478.md @@ -0,0 +1 @@ +# Prevent crash on quit when using the commandName diff --git a/engine/src/exec-engine.cpp b/engine/src/exec-engine.cpp index c7491f076ae..02a3bc08486 100644 --- a/engine/src/exec-engine.cpp +++ b/engine/src/exec-engine.cpp @@ -169,6 +169,10 @@ MC_EXEC_DEFINE_EVAL_METHOD(Engine, TargetAsObject, 1) MC_EXEC_DEFINE_EVAL_METHOD(Engine, ErrorObjectAsObject, 1) MC_EXEC_DEFINE_EVAL_METHOD(Engine, FontfilesInUse, 1) +MC_EXEC_DEFINE_EVAL_METHOD(Engine, CommandName, 1) +MC_EXEC_DEFINE_EVAL_METHOD(Engine, CommandArguments, 1) +MC_EXEC_DEFINE_EVAL_METHOD(Engine, CommandArgumentAtIndex, 2) + //////////////////////////////////////////////////////////////////////////////// struct MCEngineNumberFormat @@ -2170,3 +2174,26 @@ void MCEngineEvalIsNotStrictlyAnArray(MCExecContext& ctxt, MCValueRef value, boo } //////////////////////////////////////////////////////////////////////////////// + +void MCEngineEvalCommandName(MCExecContext& ctxt, MCStringRef& r_result) +{ + if (MCcommandname != nullptr) + r_result = MCValueRetain(MCcommandname); + else + r_result = MCValueRetain(kMCEmptyString); +} + +void MCEngineEvalCommandArguments(MCExecContext& ctxt, MCArrayRef& r_result) +{ + r_result = MCValueRetain(MCcommandarguments); +} + +void MCEngineEvalCommandArgumentAtIndex(MCExecContext& ctxt, uinteger_t t_index, MCStringRef& r_result) +{ + MCStringRef t_result = nullptr; + // If the index is wrong (< 0 or > argument count) then we return empty + if (!MCArrayFetchValueAtIndex(MCcommandarguments, t_index, (MCValueRef&)t_result)) + t_result = kMCEmptyString; + + r_result = MCValueRetain(t_result); +} diff --git a/engine/src/exec.h b/engine/src/exec.h index 568a9ea86ea..49336747c7a 100644 --- a/engine/src/exec.h +++ b/engine/src/exec.h @@ -3847,6 +3847,10 @@ extern MCExecMethodInfo *kMCEngineGetAddressMethodInfo; extern MCExecMethodInfo *kMCEngineGetStacksInUseMethodInfo; extern MCExecMethodInfo *kMCEngineGetEditionTypeMethodInfo; +extern MCExecMethodInfo *kMCEngineEvalCommandNameMethodInfo; +extern MCExecMethodInfo *kMCEngineEvalCommandArgumentsMethodInfo; +extern MCExecMethodInfo *kMCEngineEvalCommandArgumentAtIndexMethodInfo; + void MCEngineEvalVersion(MCExecContext& ctxt, MCNameRef& r_name); void MCEngineEvalBuildNumber(MCExecContext& ctxt, integer_t& r_build_number); void MCEngineEvalPlatform(MCExecContext& ctxt, MCNameRef& r_name); @@ -4020,6 +4024,10 @@ void MCEngineEvalIsNotStrictlyABinaryString(MCExecContext& ctxt, MCValueRef valu void MCEngineEvalIsStrictlyAnArray(MCExecContext& ctxt, MCValueRef value, bool& r_result); void MCEngineEvalIsNotStrictlyAnArray(MCExecContext& ctxt, MCValueRef value, bool& r_result); +void MCEngineEvalCommandName(MCExecContext& ctxt, MCStringRef& r_result); +void MCEngineEvalCommandArguments(MCExecContext& ctxt, MCArrayRef& r_result); +void MCEngineEvalCommandArgumentAtIndex(MCExecContext& ctxt, uinteger_t t_index, MCStringRef& r_result); + /////////// extern MCExecMethodInfo *kMCFilesEvalDirectoriesMethodInfo; diff --git a/engine/src/funcs.cpp b/engine/src/funcs.cpp index 06284eef5c6..10c38a3f1b1 100644 --- a/engine/src/funcs.cpp +++ b/engine/src/funcs.cpp @@ -583,7 +583,7 @@ void MCChunkOffset::compile(MCSyntaxFactoryRef ctxt) Parse_stat MCCommandArguments::parse(MCScriptPoint &sp, Boolean the) { - if (!get0or1param(sp, &argument_index, the)) + if (!get0or1param(sp, &(&argument_index), the)) { MCperror -> add(PE_FACTOR_BADPARAM, line, pos); return PS_ERROR; @@ -596,32 +596,26 @@ void MCCommandArguments::eval_ctxt(MCExecContext& ctxt, MCExecValue& r_value) { // If no parameter has been provided, then we return the list of parameters // as an array. - if (argument_index == NULL) + if (*argument_index == nullptr) { - MCExecValueTraits::set(r_value, MCValueRetain(MCcommandarguments)); - return; + MCEngineEvalCommandArguments(ctxt, r_value.arrayref_value); + r_value.type = kMCExecValueTypeArrayRef; } else { - integer_t t_index; - if (!ctxt . EvalExprAsInt(argument_index, EE_COMMANDARGUMENTS_BADPARAM, t_index)) + uinteger_t t_index; + if (!ctxt . EvalExprAsUInt(*argument_index, EE_COMMANDARGUMENTS_BADPARAM, t_index)) return; - MCStringRef t_value; - // If the index is wrong (< 0 or > argument count) then we return empty - if (!MCArrayFetchValueAtIndex(MCcommandarguments, t_index, (MCValueRef&)t_value)) - t_value = kMCEmptyString; - - MCExecValueTraits::set(r_value, MCValueRetain(t_value)); + MCEngineEvalCommandArgumentAtIndex(ctxt, t_index, r_value . stringref_value); + r_value.type = kMCExecValueTypeStringRef; } } void MCCommandName::eval_ctxt(MCExecContext& ctxt, MCExecValue& r_value) { - if (MCcommandname != NULL) - MCExecValueTraits::set(r_value, MCcommandname); - else - MCExecValueTraits::set(r_value, kMCEmptyString); + MCEngineEvalCommandName(ctxt, r_value.stringref_value); + r_value.type = kMCExecValueTypeStringRef; } MCDirectories::~MCDirectories() diff --git a/engine/src/funcs.h b/engine/src/funcs.h index 3558e824cb2..3a3d7111629 100644 --- a/engine/src/funcs.h +++ b/engine/src/funcs.h @@ -507,9 +507,12 @@ class MCClickLine : public MCConstantFunctionCtxt argument_index; public: - MCCommandArguments() { argument_index = NULL; } + MCCommandArguments() : + argument_index(nullptr) + { + } virtual Parse_stat parse(MCScriptPoint &sp, Boolean the); virtual void eval_ctxt(MCExecContext& ctxt, MCExecValue& r_value); }; diff --git a/tests/lcs/core/engine/_commandname.lc b/tests/lcs/core/engine/_commandname.lc new file mode 100755 index 00000000000..57802ef6364 --- /dev/null +++ b/tests/lcs/core/engine/_commandname.lc @@ -0,0 +1,3 @@ +#! +get the commandName +quit 0 \ No newline at end of file diff --git a/tests/lcs/core/engine/_commandname.livecodescript b/tests/lcs/core/engine/_commandname.livecodescript new file mode 100755 index 00000000000..ac12eb49d56 --- /dev/null +++ b/tests/lcs/core/engine/_commandname.livecodescript @@ -0,0 +1,5 @@ +script "_commandName" +on startup + get the commandName + quit 0 +end startup \ No newline at end of file diff --git a/tests/lcs/core/engine/commandargs.livecodescript b/tests/lcs/core/engine/commandargs.livecodescript new file mode 100644 index 00000000000..05eb2915e62 --- /dev/null +++ b/tests/lcs/core/engine/commandargs.livecodescript @@ -0,0 +1,35 @@ +script "CoreEngineCommandArgs" +/* +Copyright (C) 2017 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 . */ + +on TestCommandName + -- Bug 20478: run a subprocess in which we get the commandName and + -- then quit, to test that it no longer crashes + local tStackToRun, tOptions + put the effective filename of me into tStackToRun + set the itemdelimiter to slash + if the environment is "server" then + put "_commandname.lc" into item -1 of tStackToRun + else + put "_commandname.livecodescript" into item -1 of tStackToRun + if the environment contains "command line" then + put "-ui" into tOptions + end if + end if + TestRunStack tOptions, tStackToRun + TestAssert "command name does not crash on quit", the result is empty +end TestCommandName From 8b78b681d3a4e7ca117145fa901d3cf07ce07867 Mon Sep 17 00:00:00 2001 From: Brian Milby Date: Thu, 5 Oct 2017 12:25:42 -0500 Subject: [PATCH 0009/2459] [[Bug 20515]] Segmented control widget highlights off `hintLower` handler should not subtract 0.5 from pBound. This was resulting in an un-highlighted line one pixel wide at the right/bottom side of a cell depending on how the rounding went. --- extensions/widgets/segmented/segmented.lcb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/widgets/segmented/segmented.lcb b/extensions/widgets/segmented/segmented.lcb index 43a8d308412..70acbb6f6d3 100644 --- a/extensions/widgets/segmented/segmented.lcb +++ b/extensions/widgets/segmented/segmented.lcb @@ -379,7 +379,7 @@ end handler -- vertical pixel span to a whole number of pixels, in such a way that -- the input span is always fully contained within the output span. handler hintLower(in pBound as Number) returns Number - return the floor of (pBound - 0.5) + return the floor of (pBound) end handler handler hintUpper(in pBound as Number) returns Number return the floor of (pBound + 0.5) From 6fb14a772975e8a3e2cddc9713515f683ccd4f3a Mon Sep 17 00:00:00 2001 From: Brian Milby Date: Fri, 6 Oct 2017 11:49:11 -0500 Subject: [PATCH 0010/2459] [[Bug 20515]] Add note Prevent segmented control fill from ending one pixel to the left/bottom of segment. --- extensions/widgets/segmented/notes/20515.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 extensions/widgets/segmented/notes/20515.md diff --git a/extensions/widgets/segmented/notes/20515.md b/extensions/widgets/segmented/notes/20515.md new file mode 100644 index 00000000000..b75d5899eee --- /dev/null +++ b/extensions/widgets/segmented/notes/20515.md @@ -0,0 +1 @@ +# [20515] Prevent segmented control fill from ending one pixel to the left/bottom of segment. From 475590a0c8a460247c3b7790f88f0a0a2b56db04 Mon Sep 17 00:00:00 2001 From: livecodepanos Date: Tue, 10 Oct 2017 20:27:55 +0100 Subject: [PATCH 0011/2459] [Bug 20538] Ensure flushEvents("all") works on Mac --- engine/src/desktop-dc.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/engine/src/desktop-dc.cpp b/engine/src/desktop-dc.cpp index fd3186c9309..77d324206fd 100644 --- a/engine/src/desktop-dc.cpp +++ b/engine/src/desktop-dc.cpp @@ -911,9 +911,10 @@ void MCScreenDC::flushevents(uint2 e) t_mask = kMCPlatformEventKeyDown; else if (e == FE_KEYUP) t_mask = kMCPlatformEventKeyUp; - - if (t_mask != 0) - MCPlatformFlushEvents(t_mask); + else if (e == FE_ALL) + t_mask = kMCPlatformEventMouseDown + kMCPlatformEventMouseUp + kMCPlatformEventKeyDown + kMCPlatformEventKeyUp; + + MCPlatformFlushEvents(t_mask); } //////////////////////////////////////////////////////////////////////////////// From c837b122107eefd3985992249097b531d0f2301d Mon Sep 17 00:00:00 2001 From: livecodepanos Date: Tue, 10 Oct 2017 20:29:42 +0100 Subject: [PATCH 0012/2459] [20538] Added bugfix note --- docs/notes/bugfix-20538.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/notes/bugfix-20538.md diff --git a/docs/notes/bugfix-20538.md b/docs/notes/bugfix-20538.md new file mode 100644 index 00000000000..e38afbcc83a --- /dev/null +++ b/docs/notes/bugfix-20538.md @@ -0,0 +1 @@ +# Ensure flushEvents("all") works on MacOS From 550d82d98729e57db68147b89134b14d62b2a070 Mon Sep 17 00:00:00 2001 From: Monte Goulding Date: Wed, 11 Oct 2017 17:00:54 +1100 Subject: [PATCH 0013/2459] [[ Bug 19851 ]] Add support for property modifiers to lcb get property This patch adds support for long, abbreviated and short for id, name owner properties of script objects. to the `get property of` syntax. --- engine/src/module-engine.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/engine/src/module-engine.cpp b/engine/src/module-engine.cpp index dce1f496081..c8fe26367cb 100644 --- a/engine/src/module-engine.cpp +++ b/engine/src/module-engine.cpp @@ -224,10 +224,28 @@ static Properties parse_property_name(MCStringRef p_name) const LT *t_literal; if (t_sp . next(t_type) && t_sp . lookup(SP_FACTOR, t_literal) == PS_NORMAL && - t_literal -> type == TT_PROPERTY && - t_sp . next(t_type) == PS_EOF) - return (Properties)t_literal -> which; - + t_literal -> type == TT_PROPERTY) + { + Properties t_which = (Properties)t_literal -> which; + + // check for object property modifiers + if (t_which == P_SHORT || t_which == P_LONG || t_which == P_ABBREVIATE) + { + if (t_sp . next(t_type) && + t_sp . lookup(SP_FACTOR, t_literal) == PS_NORMAL && + t_literal -> type == TT_PROPERTY) + { + if (t_literal->which == P_ID || t_literal->which == P_NAME || t_literal->which == P_OWNER) + { + t_which = (Properties)(t_literal->which + t_which - P_SHORT + 1); + } + } + } + + if (t_sp . next(t_type) == PS_EOF) + return t_which; + } + return P_CUSTOM; } From 5fad4e6793402c56af016df54266487267187644 Mon Sep 17 00:00:00 2001 From: Monte Goulding Date: Wed, 11 Oct 2017 17:03:52 +1100 Subject: [PATCH 0014/2459] [[ Bug 19851 ]] Implement object repository library This patch implements an object repository library to be used by the IDE for storing references to objects where the long ID might mutate. --- Installer/package.txt | 2 + extensions/extensions.gyp | 1 + .../libraries/objectrepository/notes/19851.md | 1 + .../objectrepository/objectrepository.lcb | 147 ++++++++++++++++++ .../tests/objectrepository.livecodescript | 55 +++++++ 5 files changed, 206 insertions(+) create mode 100644 extensions/libraries/objectrepository/notes/19851.md create mode 100644 extensions/libraries/objectrepository/objectrepository.lcb create mode 100644 extensions/libraries/objectrepository/tests/objectrepository.livecodescript diff --git a/Installer/package.txt b/Installer/package.txt index 5149ff462c1..230d8e35e4a 100644 --- a/Installer/package.txt +++ b/Installer/package.txt @@ -435,6 +435,8 @@ component Extensions rfolder macosx:packaged_extensions/com.livecode.library.widgetutils into [[ToolsFolder]]/Extensions place rfolder macosx:packaged_extensions/com.livecode.widget.tile + into [[ToolsFolder]]/Extensions place + rfolder macosx:packaged_extensions/com.livecode.library.objectrepository component Toolchain.MacOSX into [[ToolsFolder]]/Toolchain place diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index 5fc99b821e5..a173ff2b634 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp @@ -23,6 +23,7 @@ 'libraries/canvas/canvas.lcb', 'libraries/iconsvg/iconsvg.lcb', 'libraries/json/json.lcb', + 'libraries/objectrepository/objectrepository.lcb', 'widgets/browser/browser.lcb', #’widgets/chart/chart.lcb', diff --git a/extensions/libraries/objectrepository/notes/19851.md b/extensions/libraries/objectrepository/notes/19851.md new file mode 100644 index 00000000000..3477d65110c --- /dev/null +++ b/extensions/libraries/objectrepository/notes/19851.md @@ -0,0 +1 @@ +# [19851] Implement object repository to store object references that might mutate diff --git a/extensions/libraries/objectrepository/objectrepository.lcb b/extensions/libraries/objectrepository/objectrepository.lcb new file mode 100644 index 00000000000..e3f95f49d09 --- /dev/null +++ b/extensions/libraries/objectrepository/objectrepository.lcb @@ -0,0 +1,147 @@ +/* +Copyright (C) 2017 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 . */ + +/** +This library provides support persistent object references within a session +*/ + +library com.livecode.library.objectrepository + +use com.livecode.engine + +metadata version is "1.0.0" +metadata author is "LiveCode" +metadata title is "Object Repository Library" +metadata userVisible is "false" + +variable mSequence as Integer + +variable mObjects as Array + +/** + +Store an object in the object repository and get its ID + +Description: +As long ID of an object may mutate during a session the IDE needs an +object reference that can handle that mutation. + +Parameters: +pObject (String): An object long ID + +Returns: +An object repository ID which can be used to get the current long id of +the object + +*/ +public handler objectRepositoryStore(in pObject as String) returns String + variable tID as String + repeat for each key tID in mObjects + if mObjects[tID] exists then + get property "long id" of mObjects[tID] + if the result is pObject then + return tID + end if + end if + end repeat + + variable tObject as ScriptObject + resolve script object pObject + put the result into tObject + + if tObject exists then + add 1 to mSequence + put mSequence formatted as string into tID + put tObject into mObjects[tID] + else + throw "object does not exist" + end if + + return tID +end handler + +/** + +Retrieve an object long id from the object repository + +Description: +As long ID of an object may mutate during a session the IDE needs an +object reference that can handle that mutation. + +Parameters: +pObject (String): An object repository ID + +Returns: +An object long ID or empty if the object is not in the repository or +no longer exists + +*/ +public handler objectRepositoryRetrieve(in pID as String) returns String + variable tObject as String + + if pID is among the keys of mObjects then + if not (mObjects[pID] exists) then + delete mObjects[pID] + else + get property "long id" of mObjects[pID] + put the result into tObject + end if + end if + + return tObject +end handler + +/** + +Remove and object from the object repository + +Description: +As long ID of an object may mutate during a session the IDE needs an +object reference that can handle that mutation. + +Parameters: +pObject (String): An object repository ID + +*/ +public handler objectRepositoryRemove(in pID as String) returns nothing + if pID is among the keys of mObjects then + delete mObjects[pID] + end if +end handler + +/** + +Flush deleted objects from the repository + +Description: +As long ID of an object may mutate during a session the IDE needs an +object reference that can handle that mutation. + +*/ +public handler objectRepositoryFlush() returns nothing + variable tIDs as List + put the keys of mObjects into tIDs + + variable tID as String + repeat for each element tID in tIDs + if not (mObjects[tID] exists) then + delete mObjects[tID] + end if + end repeat +end handler + +end library diff --git a/extensions/libraries/objectrepository/tests/objectrepository.livecodescript b/extensions/libraries/objectrepository/tests/objectrepository.livecodescript new file mode 100644 index 00000000000..56f3910289d --- /dev/null +++ b/extensions/libraries/objectrepository/tests/objectrepository.livecodescript @@ -0,0 +1,55 @@ +script "ObjectRepositoryLibrary" +/* +Copyright (C) 2017 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 . */ + +on TestSetup + TestLoadExtension "com.livecode.library.objectrepository" +end TestSetup + +on TestObjectRepository + local tObject + create stack uuid() + put it into tObject + + local tID + put objectRepositoryStore(tObject) into tID + TestAssert "object stored in repository", tID is an integer + TestAssert "object stored in repository once", tID is objectRepositoryStore(tObject) + + local tRetrieved + put objectRepositoryRetrieve(tID) into tRetrieved + TestAssert "object retrieved from repository", tRetrieved is tObject + + local tObject2 + put uuid() into tObject2 + set the name of tObject to tObject2 + put objectRepositoryRetrieve(tID) into tRetrieved + TestAssert "mutated object retrieved from repository", \ + tRetrieved is not empty and \ + exists(tRetrieved) and \ + not exists(tObject) + put tRetrieved into tObject + + objectRepositoryRemove tID + TestAssert "object removed from repository", objectRepositoryRetrieve(tID) is empty + + put objectRepositoryStore(tObject) into tID + delete tObject + TestAssert "deleted object removed from repository", objectRepositoryRetrieve(tID) is empty + + -- because of the behavior of objectRepositoryRetrieve it's not possible to test objectRepositoryFlush +end TestObjectRepository From 963d7730c4cd725b1ffc14475856eabbf3308ad3 Mon Sep 17 00:00:00 2001 From: livecodesam Date: Thu, 12 Oct 2017 13:10:21 +0100 Subject: [PATCH 0015/2459] [Dictionary] Various changes --- docs/dictionary/command/create-alias.lcdoc | 3 --- docs/dictionary/command/create-card.lcdoc | 5 ++--- docs/dictionary/command/crop.lcdoc | 5 +++-- docs/dictionary/function/compress.lcdoc | 4 ++-- docs/dictionary/function/cos.lcdoc | 12 +++++------- docs/dictionary/message/copyKey.lcdoc | 4 ++-- docs/dictionary/message/currentTimeChanged.lcdoc | 10 +++++----- docs/dictionary/property/convertOctals.lcdoc | 6 +++--- docs/dictionary/property/customKeys.lcdoc | 12 ++++++------ 9 files changed, 28 insertions(+), 33 deletions(-) diff --git a/docs/dictionary/command/create-alias.lcdoc b/docs/dictionary/command/create-alias.lcdoc index de5916562d4..a9a86b97731 100644 --- a/docs/dictionary/command/create-alias.lcdoc +++ b/docs/dictionary/command/create-alias.lcdoc @@ -33,9 +33,6 @@ The aliasPath specifies the name and location of the alias to be created. If you specify a name but not a location, the alias is created in the defaultFolder. -originalFilePath: - - orginalFolderPath: originalFilePath/originalFolderPath: The name and location of the file/folder you want to make an alias to. If you specify a name but not diff --git a/docs/dictionary/command/create-card.lcdoc b/docs/dictionary/command/create-card.lcdoc index 8998d01589e..d6f3661186b 100644 --- a/docs/dictionary/command/create-card.lcdoc +++ b/docs/dictionary/command/create-card.lcdoc @@ -34,8 +34,8 @@ The places the of the newly created in the . Description: -Use the to add a new to the . +Use the to add a new to the +. The new card is placed after the current card in the defaultStack. When the is created, you go to the new . @@ -45,7 +45,6 @@ will be placed on the newly-created automatically. >*Tip:* To create a in a specific , first set the > to the where you want to create the new -> : References: clone (command), create (command), place (command), create stack (command), property (glossary), current card (glossary), diff --git a/docs/dictionary/command/crop.lcdoc b/docs/dictionary/command/crop.lcdoc index fb900129fb4..cbfce9dc4f2 100644 --- a/docs/dictionary/command/crop.lcdoc +++ b/docs/dictionary/command/crop.lcdoc @@ -55,8 +55,9 @@ If the rectangle is larger than the original , blank are added to one or more edges of the . ->*Important:* The cannot be used on a control|referenced image>. Doing so will cause an . +>*Important:* The cannot be used on a +> . Doing so will cause an +> . References: flip (command), rotate (command), property (glossary), referenced control (glossary), command (glossary), diff --git a/docs/dictionary/function/compress.lcdoc b/docs/dictionary/function/compress.lcdoc index 6d6537abd21..7d34c07ad23 100644 --- a/docs/dictionary/function/compress.lcdoc +++ b/docs/dictionary/function/compress.lcdoc @@ -26,8 +26,8 @@ data (string): A string of binary data of any length. Returns: -The a of . +The a of +. Description: Use the to data to a smaller size for diff --git a/docs/dictionary/function/cos.lcdoc b/docs/dictionary/function/cos.lcdoc index ae33246a4c3..41341ac1d4d 100644 --- a/docs/dictionary/function/cos.lcdoc +++ b/docs/dictionary/function/cos.lcdoc @@ -35,18 +35,16 @@ The a number between -1 and 1. Description: Use the to find the cosine of an angle. -The repeats every 2*pi : cos(x) = cos(x - -+ 2 * pi), for any value of x. +The repeats every 2*pi : cos(x) = +cos(x + 2 * pi), for any value of x. The requires its input to be in . To -provide an angle in , use the following : +provide an angle in , use the following +: function cosInDegrees angleInDegrees - return cos(angleInDegrees * pi / 180) - + return cos(angleInDegrees * pi / 180) end cosInDegrees diff --git a/docs/dictionary/message/copyKey.lcdoc b/docs/dictionary/message/copyKey.lcdoc index 26a28cb9468..5488a0766a3 100644 --- a/docs/dictionary/message/copyKey.lcdoc +++ b/docs/dictionary/message/copyKey.lcdoc @@ -32,8 +32,8 @@ unless "Suspend LiveCode UI" is turned on in the Development menu. This means that the is not received by a if it's running in the . -The is sent when the user presses Command-C (on ), Control-C (on ), +The is sent when the user presses Command-C (on +), Control-C (on ), Control-Insert (on ), or the keyboard Copy key. The message is sent to the active (focused) control, or to the current diff --git a/docs/dictionary/message/currentTimeChanged.lcdoc b/docs/dictionary/message/currentTimeChanged.lcdoc index 70ae8cffe25..7144d4896ee 100644 --- a/docs/dictionary/message/currentTimeChanged.lcdoc +++ b/docs/dictionary/message/currentTimeChanged.lcdoc @@ -36,18 +36,18 @@ The user can change the current time by: - clicking the play button in the controller bar, - clicking in the controller bar, - dragging the controller bar scroller thumb, -- using the arrow keys when the player is the active (focused)control, +- using the arrow keys when the player is the active (focused) control, - using the scrubber control in the controller bar. (which is revealed by clicking the arrow buttons in the controller bar while holding the shift key down.) -Changing the player's property by script does not trigger the sending of the . +Changing the player's property by script does not trigger the sending of the . -Changing the player's property by script does -not trigger the sending of the . +Changing the player's property by script does +not trigger the sending of the . Starting the player by script does trigger the sending of the - once it is playing. + once it is playing. The number of intervals per second is specified by the player's timeScale . The total number of intervals is given in the diff --git a/docs/dictionary/property/convertOctals.lcdoc b/docs/dictionary/property/convertOctals.lcdoc index 9eca9588f22..0762641e573 100644 --- a/docs/dictionary/property/convertOctals.lcdoc +++ b/docs/dictionary/property/convertOctals.lcdoc @@ -27,9 +27,9 @@ Use the to make it easier to work with If the is set to true, numbers that start with a zero are treated as (base 8) numbers, instead of - (base 10). If the is false, all numbers +decimal (base 10). If the is false, all numbers (except numbers, which start with 0x) are treated as -. +decimal. Since the is a , its value is to false when the current finishes . It @@ -39,7 +39,7 @@ retains its value only for the current , and setting it in one References: reset (command), baseConvert (function), property (glossary), call (glossary), handler (glossary), execute (glossary), octal (glossary), -local property (glossary), hexadecimal (glossary), decimal (glossary) +local property (glossary), hexadecimal (glossary) Tags: math diff --git a/docs/dictionary/property/customKeys.lcdoc b/docs/dictionary/property/customKeys.lcdoc index 91163907c7b..1d293181745 100644 --- a/docs/dictionary/property/customKeys.lcdoc +++ b/docs/dictionary/property/customKeys.lcdoc @@ -31,15 +31,15 @@ The of an is a list of that Description: Use the to find out what an has, and to create or delete . +properties> an has, and to create or delete +. The lists the names of in the current . If the has more than one , you must switch to the desired property set before checking the . The following example -displays the in a called "Francois" : +displays the in a + called "Francois" : set the customPropertySet of button "My Button" to "Francois" answer the customKeys of button "My Button" -- in "Francois" set @@ -59,8 +59,8 @@ value of a newly-created custom property is empty. If you set the of an and do not include the name of an existing , that is -deleted. Setting the to empty deletes all in the current custom property set. +deleted. Setting the to empty deletes all + in the current custom property set. References: undefine (command), object (glossary), property (glossary), custom property (glossary), customPropertySet (glossary), From 92f4de4e6a502be57dcfc8cc60d8bde230c9524e Mon Sep 17 00:00:00 2001 From: Ali Lloyd Date: Thu, 12 Oct 2017 13:48:50 +0100 Subject: [PATCH 0016/2459] [[ Docs ]] Fix a few issues with docs generation - Make sure Name element maps to name property - Always give entries a display name at parse time - Allow various fields of library entries to be overridden - Allow library Summary element --- ide-support/revdocsparser.livecodescript | 138 ++++++++++++----------- 1 file changed, 73 insertions(+), 65 deletions(-) diff --git a/ide-support/revdocsparser.livecodescript b/ide-support/revdocsparser.livecodescript index e24beecd466..111e2e2aa2f 100644 --- a/ide-support/revdocsparser.livecodescript +++ b/ide-support/revdocsparser.livecodescript @@ -1061,6 +1061,7 @@ private command __nameToKeyAndType pName, @rKey, @rType case "Introduced" case "Deprecated" case "Edition" + case "Name" put "standard" into rType break case "Example" @@ -1095,10 +1096,6 @@ private command __nameToKeyAndType pName, @rKey, @rType put "tags" into rKey put "items" into rType break - case "Name" - put "display name" into rKey - put "standard" into rType - break case "Parameters" put "parameters" into rType break @@ -1219,6 +1216,9 @@ function revDocsParseElements pExtractedA, pBlocksA, pFilename if tParsedA[tItem] is empty then put pBlocksA[tItem] into tParsedA[tItem] end if + if tParsedA["display name"] is empty then + put tParsedA["name"] into tParsedA["display name"] + end if end repeat return tParsedA @@ -1256,14 +1256,10 @@ function revDocsParseDocFileToLibraryArray pFile, pLibraryName, pAuthor end revDocsParseDocFileToLibraryArray function revDocsParseDocTextToLibraryArray pFile, pText, pLibraryName, pAuthor - local tLibraryA - put revDocsParseDocText(pText, pFile) into tLibraryA - if pLibraryName is not empty then - put pLibraryName into tLibraryA["display name"] - put revDocsModifyForUrl(pLibraryName) into tLIbraryA["name"] - end if - put pAuthor into tLibraryA["author"] - return tLibraryA + local tOverridesA + put pLibraryName into tOverridesA["display name"] + put pAuthor into tOverridesA["author"] + return revDocsParseDocText(pText, pFile, "", tOverridesA) end revDocsParseDocTextToLibraryArray function revDocsParseDocFile pFile @@ -1319,7 +1315,7 @@ function revDocsGroupElements pElementsA end revDocsGroupElements -function revDocsParseDocText pText, pFilename, pDefaults +function revDocsParseDocText pText, pFilename, pDefaults, pOverrides local tElementsA put revDocsExtractElements(pText) into tElementsA @@ -1343,6 +1339,7 @@ function revDocsParseDocText pText, pFilename, pDefaults put tElementsA[tStartNum]["content"] into tParsedA["name"] add 1 to tStartNum break + case "Summary" case "Description" case "Author" case "Type" @@ -1418,24 +1415,36 @@ function revDocsParseDocText pText, pFilename, pDefaults end if end repeat - // Add a library entry - local tLibraryElements - local tCount - put 1 into tCount - add 1 to tEntryCount - - repeat for each item tItem in "name,description,author,type,example,references,edition" - if tParsedA[tItem] is not empty then - put tItem into tEntriesA[tEntryCount]["elements"][tCount]["name"] - put tParsedA[tItem] into tEntriesA[tEntryCount]["elements"][tCount]["content"] - add 1 to tCount - end if - end repeat + // Add a library entry, if there was one + local tHasLibraryEntry + put tParsedA["name"] is not empty into tHasLibraryEntry + if tHasLibraryEntry then + local tLibraryElements + local tCount + put 1 into tCount + add 1 to tEntryCount + + // Use overrides if specified + repeat for each item tItem in "name,description,author,type,example,references,edition,associations" + if tParsedA[tItem] is not empty then + put tItem into tEntriesA[tEntryCount]["elements"][tCount]["name"] + put tParsedA[tItem] into tEntriesA[tEntryCount]["elements"][tCount]["content"] + add 1 to tCount + end if + end repeat + end if repeat for each key tKey in tEntriesA put revDocsParseElements(tEntriesA[tKey]["elements"], tEntriesA[tKey], pFilename) into tParsedA["doc"][tKey] end repeat + if tHasLibraryEntry then + repeat for each key tKey in pOverrides + put pOverrides[tKey] into tParsedA["doc"][tEntryCount][tKey] + put pOverrides[tKey] into tParsedA[tKey] + end repeat + end if + return tParsedA end revDocsParseDocText @@ -1895,17 +1904,18 @@ private function __tabs pNum return tOutput end __tabs -function revDocsFormatLibraryDocArrayAsJSON pLibraryName, pDocA - local tCount - put the number of elements in pDocA into tCount +function revDocsFormatLibraryDocArrayAsJSON pLibraryA + local tCount, tDocA + put pLibraryA["doc"] into tDocA + put the number of elements in tDocA into tCount local tJSON if tCount is not 0 then repeat with tIndex = 1 to tCount local tDoc, tId - put pDocA[tIndex] into tDoc - put pLibraryName & "-" & tIndex into tId - put revDocsFormatLibraryDataAsJSON(tId, tDoc, pLibraryName) & comma after tJSON + put tDocA[tIndex] into tDoc + put pLibraryA["name"] & "-" & tIndex into tId + put revDocsFormatLibraryDataAsJSON(tId, tDoc, pLibraryA) & comma after tJSON end repeat delete the last char of tJSON end if @@ -2221,92 +2231,90 @@ end __revDocsFormatCustomArrayAsJSON Format the library array data as a JSON array as needed by the docs viewer */ -function revDocsFormatLibraryDataAsJSON pID, pLibraryDataA, pAPIName +function revDocsFormatLibraryDataAsJSON pID, pDocDataA, pLibraryDataA local tJSON put "{" & return into tJSON - if pLibraryDataA["display name"] is empty then - put pLibraryDataA["name"] into pLibraryDataA["display name"] - else if pLibraryDataA["name"] is empty then - put pLibraryDataA["display name"] into pLibraryDataA["name"] - else - throw "No name parsed" + if pDocDataA["name"] is empty then + throw "no name parsed" end if + # The 'name' should be urlencoded - put revDocsModifyForURL(pLibraryDataA["name"]) into pLibraryDataA["name"] + put revDocsModifyForURL(pDocDataA["name"]) into pDocDataA["name"] # ID put outputElement("id", pID, 3) after tJSON # Name - put outputArrayElement("name", pLibraryDataA, 3) after tJSON + put outputArrayElement("name", pDocDataA, 3) after tJSON # Display Name - put outputArrayElement("display name", pLibraryDataA, 3) after tJSON + put outputArrayElement("display name", pDocDataA, 3) after tJSON - put outputElement("library", pAPIName, 3) after tJSON + # Library Name + put outputElement("library", pLibraryDataA["name"], 3) after tJSON # Type - put outputArrayElement("type", pLibraryDataA, 3, true) after tJSON + put outputArrayElement("type", pDocDataA, 3, true) after tJSON # Syntax - put __revDocsFormatCustomArrayAsJSON("syntax", pLibraryDataA) after tJSON + put __revDocsFormatCustomArrayAsJSON("syntax", pDocDataA) after tJSON # Display syntax - if pLibraryDataA["syntax"] is not empty then - put line 1 of pLibraryDataA["syntax"][1] into pLibraryDataA["display syntax"][1] + if pDocDataA["syntax"] is not empty then + put line 1 of pDocDataA["syntax"][1] into pDocDataA["display syntax"][1] else - put pLibraryDataA["display name"] into pLibraryDataA["display syntax"][1] + put pDocDataA["display name"] into pDocDataA["display syntax"][1] end if - put __revDocsFormatCustomArrayAsJSON("display syntax", pLibraryDataA) after tJSON + put __revDocsFormatCustomArrayAsJSON("display syntax", pDocDataA) after tJSON # Synonyms - put revDocsItemListToJSONArray(pLibraryDataA, "synonyms") after tJSON + put revDocsItemListToJSONArray(pDocDataA, "synonyms") after tJSON # Associations - put revDocsItemListToJSONArray(pLibraryDataA, "associations") after tJSON + put revDocsItemListToJSONArray(pDocDataA, "associations") after tJSON # Summary - put outputElementIfExists("summary", pLibraryDataA, 3) after tJSON + put outputElementIfExists("summary", pDocDataA, 3) after tJSON # Edition - put outputElementIfExists("edition", pLibraryDataA, 3) after tJSON + put outputElementIfExists("edition", pDocDataA, 3) after tJSON # Introduced - put outputElementIfExists("introduced", pLibraryDataA, 3) after tJSON + put outputElementIfExists("introduced", pDocDataA, 3) after tJSON # Deprecated - put outputElementIfExists("deprecated", pLibraryDataA, 3) after tJSON + put outputElementIfExists("deprecated", pDocDataA, 3) after tJSON # OS - put revDocsItemListToJSONArray(pLibraryDataA, "OS") after tJSON + put revDocsItemListToJSONArray(pDocDataA, "OS") after tJSON # Platforms - put revDocsItemListToJSONArray(pLibraryDataA, "platforms") after tJSON + put revDocsItemListToJSONArray(pDocDataA, "platforms") after tJSON # Security - put revDocsItemListToJSONArray(pLibraryDataA, "security") after tJSON + put revDocsItemListToJSONArray(pDocDataA, "security") after tJSON # Parameters - put __revDocsFormatCustomArrayAsJSON("params", pLibraryDataA) after tJSON + put __revDocsFormatCustomArrayAsJSON("params", pDocDataA) after tJSON # Example - put __revDocsFormatCustomArrayAsJSON("example", pLibraryDataA) after tJSON + put __revDocsFormatCustomArrayAsJSON("example", pDocDataA) after tJSON # Value - put __revDocsFormatCustomArrayAsJSON("value", pLibraryDataA) after tJSON + put __revDocsFormatCustomArrayAsJSON("value", pDocDataA) after tJSON # Description - put outputElementIfExists("description", pLibraryDataA, 3) after tJSON + put outputElementIfExists("description", pDocDataA, 3) after tJSON # References - put __revDocsFormatReferencesArrayAsJSON(pLibraryDataA["references"]) after tJSON + put __revDocsFormatReferencesArrayAsJSON(pDocDataA["references"]) after tJSON # Tags - put revDocsItemListToJSONArray(pLibraryDataA, "tags") after tJSON + put revDocsItemListToJSONArray(pDocDataA, "tags") after tJSON # Changes - put outputElementIfExists("changes", pLibraryDataA, 3) after tJSON + put outputElementIfExists("changes", pDocDataA, 3) after tJSON delete char -2 to -1 of tJSON put return & tab & tab & "}" after tJSON From 15f751756fa2437706bb623dc67b0e6a4e4bfd77 Mon Sep 17 00:00:00 2001 From: Mikey Date: Thu, 12 Oct 2017 21:13:20 -0400 Subject: [PATCH 0017/2459] Dropbox doesn't like the way LC posts "" instead of null. Gerard in the original library got around this by actually sending the word "null", which works for some reason. Note that none of the other commands that take a null post are bothered by LC's POST "" technique. --- extensions/script-libraries/dropbox/dropbox.livecodescript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/script-libraries/dropbox/dropbox.livecodescript b/extensions/script-libraries/dropbox/dropbox.livecodescript index faa24f3dcb7..d09972fe3ac 100644 --- a/extensions/script-libraries/dropbox/dropbox.livecodescript +++ b/extensions/script-libraries/dropbox/dropbox.livecodescript @@ -4970,7 +4970,7 @@ private function __get_current_account_POST /* No parameters. */ - return "" + return "null" end __get_current_account_POST private function __get_space_usage_POST From 860e3fa513cc1db42a60002bb4cdb52ec37d248e Mon Sep 17 00:00:00 2001 From: livecodesam Date: Fri, 13 Oct 2017 10:42:50 +0100 Subject: [PATCH 0018/2459] Update currentTimeChanged.lcdoc --- docs/dictionary/message/currentTimeChanged.lcdoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/dictionary/message/currentTimeChanged.lcdoc b/docs/dictionary/message/currentTimeChanged.lcdoc index 7144d4896ee..b609598607a 100644 --- a/docs/dictionary/message/currentTimeChanged.lcdoc +++ b/docs/dictionary/message/currentTimeChanged.lcdoc @@ -41,7 +41,8 @@ The user can change the current time by: (which is revealed by clicking the arrow buttons in the controller bar while holding the shift key down.) -Changing the player's property by script does not trigger the sending of the . +Changing the player's property by script does not trigger +the sending of the . Changing the player's property by script does not trigger the sending of the . From 5f1917e35be0b18ae13b8e1554aad54146bb18ca Mon Sep 17 00:00:00 2001 From: livecodesam Date: Fri, 13 Oct 2017 10:44:07 +0100 Subject: [PATCH 0019/2459] Update create-alias.lcdoc --- docs/dictionary/command/create-alias.lcdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/dictionary/command/create-alias.lcdoc b/docs/dictionary/command/create-alias.lcdoc index a9a86b97731..fdf9d1974db 100644 --- a/docs/dictionary/command/create-alias.lcdoc +++ b/docs/dictionary/command/create-alias.lcdoc @@ -4,7 +4,7 @@ Synonyms: new alias Type: command -Syntax: create alias to {file | folder } +Syntax: create alias to {file | folder} Summary: Makes a new , , or to the specified @@ -34,7 +34,7 @@ created. If you specify a name but not a location, the alias is created in the defaultFolder. orginalFolderPath: -originalFilePath/originalFolderPath: The name and location of the +The name and location of the file/folder you want to make an alias to. If you specify a name but not a location, LiveCode assumes the file is in the defaultFolder. From 5adec7d24877680884a12fffd931b2456b1c2d0f Mon Sep 17 00:00:00 2001 From: livecodesam Date: Fri, 13 Oct 2017 12:20:45 +0100 Subject: [PATCH 0020/2459] Edit per suggestions --- docs/dictionary/command/create-alias.lcdoc | 2 +- docs/dictionary/function/cos.lcdoc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/dictionary/command/create-alias.lcdoc b/docs/dictionary/command/create-alias.lcdoc index fdf9d1974db..69921c241b3 100644 --- a/docs/dictionary/command/create-alias.lcdoc +++ b/docs/dictionary/command/create-alias.lcdoc @@ -33,7 +33,7 @@ The aliasPath specifies the name and location of the alias to be created. If you specify a name but not a location, the alias is created in the defaultFolder. -orginalFolderPath: +orginalPath: The name and location of the file/folder you want to make an alias to. If you specify a name but not a location, LiveCode assumes the file is in the defaultFolder. diff --git a/docs/dictionary/function/cos.lcdoc b/docs/dictionary/function/cos.lcdoc index 41341ac1d4d..60698a1114f 100644 --- a/docs/dictionary/function/cos.lcdoc +++ b/docs/dictionary/function/cos.lcdoc @@ -35,8 +35,8 @@ The a number between -1 and 1. Description: Use the to find the cosine of an angle. -The repeats every 2*pi : cos(x) = -cos(x + 2 * pi), for any value of x. +The repeats every `2 * pi` : +`cos(x) = cos(x + 2 * pi)`, for any value of `x`. The requires its input to be in . To From 79cef3c037d339032776b61a493ea4bfbe553aec Mon Sep 17 00:00:00 2001 From: James Hale Date: Fri, 6 Oct 2017 02:15:59 +1100 Subject: [PATCH 0021/2459] [[Dictionary]] correct malformed code code block not indented. --- .../command/mobileComposeUnicodeMail.lcdoc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/dictionary/command/mobileComposeUnicodeMail.lcdoc b/docs/dictionary/command/mobileComposeUnicodeMail.lcdoc index fb723255e48..fe2d1e08339 100644 --- a/docs/dictionary/command/mobileComposeUnicodeMail.lcdoc +++ b/docs/dictionary/command/mobileComposeUnicodeMail.lcdoc @@ -81,13 +81,13 @@ from disk when the file is needed. Therefore, using large amounts of data to an e-mail. For example, sending multiple attachments may be done like this: -put "Hello World!" into tAttachments[1]["data"] -put "text/plain" into tAttachments[1]["type"] -put "Greetings.txt" into tAttachments[1]["name"] -put "Goodbye World!" into tAttachments[2]["data"] -put "text/plain" into tAttachments[2]["type"] -put "Farewell.txt" into tAttachments[2]["name"] -mobileComposeUnicodeMail tSubject, tTo, tCCs, tBCCs, tBody, tAttachments + put "Hello World!" into tAttachments[1]["data"] + put "text/plain" into tAttachments[1]["type"] + put "Greetings.txt" into tAttachments[1]["name"] + put "Goodbye World!" into tAttachments[2]["data"] + put "text/plain" into tAttachments[2]["type"] + put "Farewell.txt" into tAttachments[2]["name"] + mobileComposeUnicodeMail tSubject, tTo, tCCs, tBCCs, tBody, tAttachments Some devices are not configured with e-mail sending capability. To determine if the current device is, use the From 958688d5f9b0cc5d27a4bce93360e26377c86c48 Mon Sep 17 00:00:00 2001 From: Ian Macphail Date: Tue, 17 Oct 2017 18:58:06 +0100 Subject: [PATCH 0022/2459] [[ EmscriptenWindows ]] Initial implementation of multiple emscripten windows using html5 canvas elements --- engine/engine-sources.gypi | 11 ++- engine/engine.gyp | 2 + engine/src/em-dc.cpp | 92 +++++++++++++----- engine/src/em-dc.h | 19 ++++ engine/src/em-dc.js | 191 +++++++++++++++++++++++++++++++++++++ engine/src/em-stack.cpp | 16 ++-- engine/src/em-surface.cpp | 18 ++-- engine/src/em-surface.h | 3 +- engine/src/em-surface.js | 7 +- 9 files changed, 312 insertions(+), 47 deletions(-) create mode 100644 engine/src/em-dc.js diff --git a/engine/engine-sources.gypi b/engine/engine-sources.gypi index eab98f941e0..b3c34c64f29 100644 --- a/engine/engine-sources.gypi +++ b/engine/engine-sources.gypi @@ -761,9 +761,12 @@ # Group "Desktop - Emscripten" 'src/em-async.h', 'src/em-async.js', + 'src/em-clipboard.h', + 'src/em-clipboard.cpp', 'src/em-dc-mainloop.cpp', 'src/em-dc.h', 'src/em-dc.cpp', + 'src/em-dc.js', 'src/em-dialog.js', 'src/em-event.h', 'src/em-event.cpp', @@ -772,9 +775,13 @@ 'src/em-filehandle.cpp', 'src/em-fontlist.h', 'src/em-fontlist.cpp', + 'src/em-liburl.h', + 'src/em-liburl.cpp', + 'src/em-liburl.js', 'src/em-main.cpp', 'src/em-osspec-misc.cpp', 'src/em-osspec-network.cpp', + 'src/em-preamble-overlay.js', 'src/em-preamble.js', 'src/em-resolution.cpp', 'src/em-stack.cpp', @@ -783,6 +790,7 @@ 'src/em-standalone.js', 'src/em-surface.h', 'src/em-surface.cpp', + 'src/em-surface.js', 'src/em-system.h', 'src/em-system.cpp', 'src/em-system.js', @@ -793,9 +801,6 @@ 'src/em-util.js', 'src/em-view.h', 'src/em-view.cpp', - 'src/em-liburl.h', - 'src/em-liburl.cpp', - 'src/em-liburl.js', ], # Sources that need to be compiled separately for each mode diff --git a/engine/engine.gyp b/engine/engine.gyp index d5fabc08431..a193e481ca0 100755 --- a/engine/engine.gyp +++ b/engine/engine.gyp @@ -996,6 +996,7 @@ 'src/em-url.js', 'src/em-standalone.js', 'src/em-liburl.js', + 'src/em-dc.js', ], 'outputs': @@ -1029,6 +1030,7 @@ 'src/em-url.js', 'src/em-standalone.js', 'src/em-liburl.js', + 'src/em-dc.js', ], }, ], diff --git a/engine/src/em-dc.cpp b/engine/src/em-dc.cpp index f215f39a3bc..06a33a5dc07 100644 --- a/engine/src/em-dc.cpp +++ b/engine/src/em-dc.cpp @@ -30,6 +30,40 @@ along with LiveCode. If not see . */ #include "redraw.h" #include "dispatch.h" #include "globals.h" +#include "graphics_util.h" + +/* ================================================================ + * Helper Functions + * ================================================================ */ + +MCRectangle MCEmscriptenGetWindowRect(uint32_t p_window_id) +{ + uint32_t t_left, t_top, t_right, t_bottom; + MCEmscriptenGetWindowRect(p_window_id, &t_left, &t_top, &t_right, &t_bottom); + + return MCRectangleMake(t_left, t_top, t_right - t_left, t_bottom - t_top); +} + +void MCEmscriptenSetWindowRect(uint32_t p_window_id, const MCRectangle &p_rect) +{ + MCEmscriptenSetWindowRect(p_window_id, p_rect.x, p_rect.y, p_rect.x + p_rect.width, p_rect.y + p_rect.height); +} + +/* ================================================================ + * Initialization / Finalization + * ================================================================ */ + +extern "C" bool MCEmscriptenDCInitializeJS(); +bool MCEmscriptenDCInitialize() +{ + return MCEmscriptenDCInitializeJS(); +} + +extern "C" void MCEmscriptenDCFinalizeJS(); +void MCEmscriptenDCFinalize() +{ + MCEmscriptenDCFinalizeJS(); +} /* ================================================================ * Construction/Destruction @@ -78,13 +112,15 @@ MCScreenDC::open() return MCEmscriptenEventInitialize() && MCEmscriptenViewInitialize() && - MCEmscriptenLibUrlInitialize(); + MCEmscriptenLibUrlInitialize() && + MCEmscriptenDCInitialize(); } Boolean MCScreenDC::close(Boolean force) { + MCEmscriptenDCFinalize(); MCEmscriptenViewFinalize(); MCEmscriptenEventFinalize(); MCEmscriptenLibUrlFinalize(); @@ -100,35 +136,28 @@ void MCScreenDC::openwindow(Window p_window, Boolean override) { - /* FIXME Implement multiple windows */ - - if (nil != m_main_window) - { - if (m_main_window == p_window) { - return; - } - else - { - MCEmscriptenNotImplemented(); - } - } - - m_main_window = p_window; + uint32_t t_window = reinterpret_cast(p_window); + MCLog("set window visible"); + MCEmscriptenSetWindowVisible(t_window, true); + MCLog("find stack"); MCStack *t_stack = MCdispatcher->findstackd(p_window); /* Enable drawing */ + MCLog("activate tilecache"); t_stack->view_activatetilecache(); t_stack->setextendedstate(false, ECS_DONTDRAW); /* Set mouse & keyboard focus */ - UpdateFocus(); +// MCLog("update focus"); +// UpdateFocus(); /* Set up view to match window, as far as possible */ /* FIXME Implement HiDPI support */ - MCEmscriptenViewSetBounds(t_stack->view_getrect()); + MCRectangle t_rect = t_stack->view_getrect(); + MCEmscriptenSetWindowRect(t_window, t_rect.x, t_rect.y, t_rect.x + t_rect.width, t_rect.y + t_rect.height); t_stack->view_configure(true); t_stack->view_dirty_all(); @@ -137,31 +166,42 @@ MCScreenDC::openwindow(Window p_window, void MCScreenDC::closewindow(Window p_window) { - /* FIXME Implement multiple windows */ - MCAssert(p_window); - if (p_window != m_main_window) - { - return; - } - - m_main_window = nil; + uint32_t t_window = reinterpret_cast(p_window); + MCEmscriptenSetWindowVisible(t_window, false); } void MCScreenDC::destroywindow(Window & x_window) { + uint32_t t_window = reinterpret_cast(x_window); + MCEmscriptenDestroyWindow(t_window); + x_window = nil; } +uintptr_t +MCScreenDC::dtouint(Drawable p_window) +{ + return reinterpret_cast(p_window); +} + +Boolean +MCScreenDC::uinttowindow(uintptr_t p_uint, Window &r_window) +{ + r_window = reinterpret_cast(p_uint); + return True; +} + bool MCScreenDC::platform_getwindowgeometry(Window p_window, MCRectangle & r_rect) { /* FIXME Implement HiDPI support */ - r_rect = MCEmscriptenViewGetBounds(); + uint32_t t_window = reinterpret_cast(p_window); + r_rect = MCEmscriptenGetWindowRect(t_window); return true; } diff --git a/engine/src/em-dc.h b/engine/src/em-dc.h index 9c1559a7d5b..ce6cc8a2cd9 100644 --- a/engine/src/em-dc.h +++ b/engine/src/em-dc.h @@ -31,9 +31,24 @@ along with LiveCode. If not see . */ MCUIDC *MCCreateScreenDC(void); +extern bool MCEmscriptenDCInitialize(); +extern void MCEmscriptenDCFinalize(); + extern "C" MCStack *MCEmscriptenGetCurrentStack(void); extern "C" bool MCEmscriptenHandleMousePress(MCStack *p_stack, uint32_t p_time, uint32_t p_modifiers, MCMousePressState p_state, int32_t p_button); +extern "C" uint32_t MCEmscriptenCreateWindow(); +extern "C" void MCEmscriptenDestroyWindow(uint32_t p_window_id); +extern "C" void MCEmscriptenSetWindowRect(uint32_t p_window_id, uint32_t p_left, uint32_t p_top, uint32_t p_right, uint32_t p_bottom); +extern "C" void MCEmscriptenGetWindowRect(uint32_t p_window_id, uint32_t *r_left, uint32_t *r_top, uint32_t *r_right, uint32_t *r_bottom); +extern "C" void MCEmscriptenSetWindowVisible(uint32_t p_window_id, bool p_visible); +extern "C" bool MCEmscriptenGetWindowVisible(uint32_t p_window_id); + +/* ---------------------------------------------------------------- */ + +MCRectangle MCEmscriptenGetWindowRect(uint32_t p_window_id); +void MCEmscriptenSetWindowRect(uint32_t p_window_id, const MCRectangle &p_rect); + /* ---------------------------------------------------------------- */ class MCScreenDC: public MCUIDC @@ -52,6 +67,10 @@ class MCScreenDC: public MCUIDC virtual bool platform_getwindowgeometry(Window p_window, MCRectangle & r_rect); + uintptr_t dtouint(Drawable d); + Boolean uinttowindow(uintptr_t, Window &w); + + /* ---------- Event loop */ virtual Boolean wait(real64_t p_duration, Boolean p_allow_dispatch, diff --git a/engine/src/em-dc.js b/engine/src/em-dc.js new file mode 100644 index 00000000000..4448a92f5e5 --- /dev/null +++ b/engine/src/em-dc.js @@ -0,0 +1,191 @@ +/* -*-Javascript-*- + + Copyright (C) 2017 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 . */ + +mergeInto(LibraryManager.library, { + // $LiveCodeDC__deps: ['$LiveCodeAsync'], + $LiveCodeDC: { + // true if ensureInit() has ever been run + _initialised: false, + + initialize: function() { + // Make sure this only ever gets run once + if (LiveCodeDC._initialised) { + return; + } + + LiveCodeDC._windowList = {}; + LiveCodeDC._assignedMainWindow = false; + LiveCodeDC._maxWindowID = 0; + + LiveCodeDC._initialised = true; + }, + + finalize: function() { + if (!LiveCodeDC._initialised) { + return; + } + + LiveCodeDC._initialised = false; + }, + + // Windows are backed by an html canvas within a floating div + createWindow: function() { + var canvas; + var rect; + if (!LiveCodeDC._assignedMainWindow) + { + canvas = Module['canvas']; + rect = canvas.getBoundingClientRect(); + LiveCodeDC._assignedMainWindow = true; + } + else + { + canvas = document.createElement('canvas'); + canvas.style.position = 'absolute'; + document.appendChild(canvas); + + rect = {'left':0, 'top':0, 'right':0, 'bottom':0}; + } + + LiveCodeDC._maxWindowID += 1; + LiveCodeDC._windowList[LiveCodeDC._maxWindowID] = { + 'canvas': canvas, + 'rect': rect, + 'visible':false, + }; + + return LiveCodeDC._maxWindowID; + }, + + destroyWindow: function(pID) { + var window = LiveCodeDC._windowList[pID]; + if (window) + { + if (window.canvas == Module['canvas']) + { + // TODO - handle cleanup of embedded canvas + LiveCodeDC._assignedMainWindow = false; + } + else + { + document.removeChild(window.canvas); + } + LiveCodeDC._windowList[pID] = null; + } + }, + + setWindowRect: function(pID, pLeft, pTop, pRight, pBottom) { + var window = LiveCodeDC._windowList[pID]; + if (window) + { + window.rect = {'left':pLeft, 'top':pTop, 'right':pRight, 'bottom':pBottom}; + window.canvas.style.left = pLeft + 'px'; + window.canvas.style.top = pLeft + 'px'; + window.canvas.style.right = pRight + 'px'; + window.canvas.style.bottom = pBottom + 'px'; + } + }, + + getWindowRect: function(pID) { + var window = LiveCodeDC._windowList[pID]; + if (window) + return window.rect; + + return null; + }, + + setWindowVisible: function(pID, pVisible) { + var window = LiveCodeDC._windowList[pID]; + if (window) + { + window.visible = pVisible; + if (pVisible) + window.canvas.style.visibility = 'visible'; + else + window.canvas.style.visibility = 'hidden'; + } + }, + + getWindowVisible: function(pID) { + var window = LiveCodeDC._windowList[pID]; + if (window) + { + return window.visible; + } + + return false; + }, + + getWindowCanvas: function(pID) { + var window = LiveCodeDC._windowList[pID]; + if (window) + { + return window.canvas; + } + + return null; + }, + }, + + MCEmscriptenDCInitializeJS__deps: ['$LiveCodeDC'], + MCEmscriptenDCInitializeJS: function() { + LiveCodeDC.initialize(); + return true; + }, + + MCEmscriptenDCFinalizeJS__deps: ['$LiveCodeDC'], + MCEmscriptenDCFinalizeJS: function() { + LiveCodeDC.finalize(); + }, + + MCEmscriptenCreateWindow__deps: ['$LiveCodeDC'], + MCEmscriptenCreateWindow: function() { + var window = LiveCodeDC.createWindow(); + console.debug("Created window: " + window); + return window; + }, + + MCEmscriptenDestroyWindow__deps: ['$LiveCodeDC'], + MCEmscriptenDestroyWindow: function(pWindowID) { + LiveCodeDC.destroyWindow(pWindowID); + }, + + MCEmscriptenSetWindowRect__deps: ['$LiveCodeDC'], + MCEmscriptenSetWindowRect: function(pWindowID, pLeft, pTop, pRight, pBottom) { + LiveCodeDC.setWindowRect(pWindowID, pLeft, pTop, pRight, pBottom); + }, + + MCEmscriptenGetWindowRect__deps: ['$LiveCodeDC'], + MCEmscriptenGetWindowRect: function(pWindowID, rLeft, rTop, rRight, rBottom) { + var rect = LiveCodeDC.getWindowRect(pWindowID); + {{{ makeSetValue('rLeft', '0', 'rect.left', 'i32') }}}; + {{{ makeSetValue('rTop', '0', 'rect.top', 'i32') }}}; + {{{ makeSetValue('rRight', '0', 'rect.right', 'i32') }}}; + {{{ makeSetValue('rBottom', '0', 'rect.bottom', 'i32') }}}; + }, + + MCEmscriptenSetWindowVisible__deps: ['$LiveCodeDC'], + MCEmscriptenSetWindowVisible: function(pWindowID, pVisible) { + LiveCodeDC.setWindowVisible(pWindowID, pVisible); + }, + + MCEmscriptenGetWindowVisible__deps: ['$LiveCodeDC'], + MCEmscriptenGetWindowVisible: function(pWindowID) { + return LiveCodeDC.getWindowVisible(pWindowID); + }, +}); diff --git a/engine/src/em-stack.cpp b/engine/src/em-stack.cpp index 7922f49bed7..38c08690185 100644 --- a/engine/src/em-stack.cpp +++ b/engine/src/em-stack.cpp @@ -43,8 +43,8 @@ MCStack::realize() start_externals(); - /* Use the MCStack pointer as the window handle */ - window = reinterpret_cast(this); + uint32_t t_window = MCEmscriptenCreateWindow(); + window = reinterpret_cast(t_window); /* By default, don't draw anything */ setextendedstate(true, ECS_DONTDRAW); @@ -118,22 +118,26 @@ MCStack::view_platform_updatewindow(MCRegionRef p_dirty_region) * for the first time will result in an update region being too * big. Restrict to a valid region. */ + uint32_t t_window = reinterpret_cast(window); + MCGRegionRef t_region = MCGRegionRef(p_dirty_region); - MCRectangle t_valid = MCEmscriptenViewGetBounds(); + MCRectangle t_valid = MCEmscriptenGetWindowRect(t_window); MCGRegionIntersectRect(t_region, MCRectangleToMCGIntegerRectangle(t_valid)); MCGIntegerRectangle t_rect = MCGRegionGetBounds(t_region); - MCHtmlCanvasStackSurface t_surface(t_rect); + MCHtmlCanvasStackSurface t_surface(t_window, t_rect); view_surface_redrawwindow(&t_surface, t_region); } MCRectangle MCStack::view_platform_setgeom(const MCRectangle &p_rect) { - MCRectangle t_old = MCEmscriptenViewGetBounds(); - /* UNCHECKED */ MCEmscriptenViewSetBounds(p_rect); + uint32_t t_window = reinterpret_cast(window); + + MCRectangle t_old = MCEmscriptenGetWindowRect(t_window); + MCEmscriptenSetWindowRect(t_window, p_rect); return t_old; } diff --git a/engine/src/em-surface.cpp b/engine/src/em-surface.cpp index fb1900c2537..3a17fa55fa5 100644 --- a/engine/src/em-surface.cpp +++ b/engine/src/em-surface.cpp @@ -26,11 +26,12 @@ along with LiveCode. If not see . */ * ================================================================ */ -extern "C" void MCEmscriptenBlitToMainCanvas(const uint8_t* p_rgba_buffer, - uint32_t p_dest_x, - uint32_t p_dest_y, - uint32_t p_width, - uint32_t p_height); +extern "C" void MCEmscriptenBlitToWindowCanvas(uint32_t p_window_id, + const uint8_t* p_rgba_buffer, + uint32_t p_dest_x, + uint32_t p_dest_y, + uint32_t p_width, + uint32_t p_height); /* ================================================================ @@ -184,8 +185,9 @@ MCAbstractRasterStackSurface::Composite(MCGRectangle p_dest_rect, * HTML canvas surface * ================================================================ */ -MCHtmlCanvasStackSurface::MCHtmlCanvasStackSurface(const MCGIntegerRectangle& p_rect) - : m_surface(nil), +MCHtmlCanvasStackSurface::MCHtmlCanvasStackSurface(uint32_t p_window_id, const MCGIntegerRectangle& p_rect) + : m_window_id(p_window_id), + m_surface(nil), m_region(nil), m_rect(p_rect) { @@ -218,7 +220,7 @@ void MCHtmlCanvasStackSurface::Unlock() { // This is implemented in JavaScript - MCEmscriptenBlitToMainCanvas(m_surface, m_rect.origin.x, m_rect.origin.y, m_rect.size.width, m_rect.size.height); + MCEmscriptenBlitToWindowCanvas(m_window_id, m_surface, m_rect.origin.x, m_rect.origin.y, m_rect.size.width, m_rect.size.height); } MCGRegionRef diff --git a/engine/src/em-surface.h b/engine/src/em-surface.h index 155029bcc98..db405f15d30 100644 --- a/engine/src/em-surface.h +++ b/engine/src/em-surface.h @@ -83,7 +83,7 @@ class MCAbstractRasterStackSurface : public MCStackSurface class MCHtmlCanvasStackSurface : public MCAbstractRasterStackSurface { public: - MCHtmlCanvasStackSurface(const MCGIntegerRectangle& p_rect); + MCHtmlCanvasStackSurface(uint32_t p_window_id, const MCGIntegerRectangle& p_rect); virtual ~MCHtmlCanvasStackSurface(); /* Lock and unlock the surface. */ @@ -96,6 +96,7 @@ class MCHtmlCanvasStackSurface : public MCAbstractRasterStackSurface virtual MCGRasterFormat GetFormat(); virtual void *GetPixelBuffer(MCGIntegerRectangle p_area); + uint32_t m_window_id; uint8_t *m_surface; MCGRegionRef m_region; MCGIntegerRectangle m_rect; diff --git a/engine/src/em-surface.js b/engine/src/em-surface.js index 25ce6c3e478..e3d0fb92fdd 100644 --- a/engine/src/em-surface.js +++ b/engine/src/em-surface.js @@ -21,9 +21,10 @@ mergeInto(LibraryManager.library, { // Blits the contents of the given RGBA buffer to the specified // location on the main HTML5 canvas - MCEmscriptenBlitToMainCanvas: function(p_rgba_buffer, p_x, p_y, p_w, p_h) { - // Get the main canvas - var canvas = Module['canvas']; + MCEmscriptenBlitToWindowCanvas__deps: ['$LiveCodeDC'], + MCEmscriptenBlitToWindowCanvas: function(p_window_id, p_rgba_buffer, p_x, p_y, p_w, p_h) { + // Get the window canvas + var canvas = LiveCodeDC.getWindowCanvas(p_window_id); // Create and get a 2D rendering context for the canvas var context = canvas.getContext('2d'); From 88d11c16ea836669a415ff7e7f42edb2332abafc Mon Sep 17 00:00:00 2001 From: Monte Goulding Date: Wed, 18 Oct 2017 13:15:30 +1100 Subject: [PATCH 0023/2459] [[ Cleanup ]] Add missing field initializer --- lcidlc/src/InterfaceGenerate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcidlc/src/InterfaceGenerate.cpp b/lcidlc/src/InterfaceGenerate.cpp index 846f5707f38..029f0541b92 100644 --- a/lcidlc/src/InterfaceGenerate.cpp +++ b/lcidlc/src/InterfaceGenerate.cpp @@ -1709,7 +1709,7 @@ static bool InterfaceGenerateExports(InterfaceRef self, CoderRef p_coder) NameGetCString(t_handler -> name), NameGetCString(t_handler -> name)); } - CoderWriteLine(p_coder, "\t{ 0 }\n};"); + CoderWriteLine(p_coder, "\t{ 0, nullptr, nullptr }\n};"); CoderWriteLine(p_coder, ""); From 25a3721f3cc8af47ddce17bfe6f522a145cbc0df Mon Sep 17 00:00:00 2001 From: livecodepanos Date: Wed, 18 Oct 2017 22:30:51 +0100 Subject: [PATCH 0024/2459] Updated ide submodule ptr --- ide | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ide b/ide index 55b89bb9b4b..4de7b661e37 160000 --- a/ide +++ b/ide @@ -1 +1 @@ -Subproject commit 55b89bb9b4b2ee32cec573ab0836f60c3977ffab +Subproject commit 4de7b661e37fd3d5a68cdfd0bc994725781a957f From 6713663ccadef0665edaeb85fa13e3321aed019c Mon Sep 17 00:00:00 2001 From: Ian Macphail Date: Thu, 19 Oct 2017 17:54:35 +0100 Subject: [PATCH 0025/2459] [[ EmscriptenWindows ]] Implement event handling for multiple windows, and embed canvases in div elements --- engine/src/em-dc.cpp | 34 +++---------- engine/src/em-dc.h | 6 +-- engine/src/em-dc.js | 61 ++++++++++++++++++----- engine/src/em-event.js | 69 +++++++++++++------------- engine/src/em-stack.cpp | 1 + libfoundation/src/foundation-debug.cpp | 2 +- 6 files changed, 94 insertions(+), 79 deletions(-) diff --git a/engine/src/em-dc.cpp b/engine/src/em-dc.cpp index 06a33a5dc07..7e33784199c 100644 --- a/engine/src/em-dc.cpp +++ b/engine/src/em-dc.cpp @@ -76,13 +76,13 @@ MCCreateScreenDC() } MC_DLLEXPORT_DEF MCStack * -MCEmscriptenGetCurrentStack() +MCEmscriptenGetStackForWindow(Window p_window) { if (MCnoui) return nil; - - MCScreenDC *t_dc = static_cast(MCscreen); - - return t_dc->GetCurrentStack(); + + MCStack *t_stack = MCdispatcher->findstackd(p_window); + + return t_stack; } MC_DLLEXPORT_DEF @@ -150,14 +150,13 @@ MCScreenDC::openwindow(Window p_window, t_stack->setextendedstate(false, ECS_DONTDRAW); /* Set mouse & keyboard focus */ -// MCLog("update focus"); -// UpdateFocus(); + MCEventQueuePostMouseFocus(t_stack, 0, true); + MCEventQueuePostKeyFocus(t_stack, true); /* Set up view to match window, as far as possible */ /* FIXME Implement HiDPI support */ - MCRectangle t_rect = t_stack->view_getrect(); - MCEmscriptenSetWindowRect(t_window, t_rect.x, t_rect.y, t_rect.x + t_rect.width, t_rect.y + t_rect.height); + MCEmscriptenSetWindowRect(t_window, t_stack->view_getrect()); t_stack->view_configure(true); t_stack->view_dirty_all(); @@ -205,23 +204,6 @@ MCScreenDC::platform_getwindowgeometry(Window p_window, return true; } -void -MCScreenDC::UpdateFocus() -{ - MCAssert(nil != m_main_window); - - MCStack *t_stack = GetCurrentStack(); - - MCEventQueuePostMouseFocus(t_stack, 0, true); - MCEventQueuePostKeyFocus(t_stack, true); -} - -MCStack * -MCScreenDC::GetCurrentStack() -{ - return MCdispatcher->findstackd(m_main_window); -} - /* ================================================================ * Event loop * ================================================================ */ diff --git a/engine/src/em-dc.h b/engine/src/em-dc.h index ce6cc8a2cd9..c4fd1200ef4 100644 --- a/engine/src/em-dc.h +++ b/engine/src/em-dc.h @@ -34,7 +34,7 @@ MCUIDC *MCCreateScreenDC(void); extern bool MCEmscriptenDCInitialize(); extern void MCEmscriptenDCFinalize(); -extern "C" MCStack *MCEmscriptenGetCurrentStack(void); +extern "C" MCStack *MCEmscriptenGetStackForWindow(Window p_window); extern "C" bool MCEmscriptenHandleMousePress(MCStack *p_stack, uint32_t p_time, uint32_t p_modifiers, MCMousePressState p_state, int32_t p_button); extern "C" uint32_t MCEmscriptenCreateWindow(); @@ -78,9 +78,6 @@ class MCScreenDC: public MCUIDC /* ---------- Extra stuff */ - /* Get the stack being shown in the default canvas. */ - MCStack *GetCurrentStack(); - /* Pops up simple ask/answer dialogues */ virtual int32_t popupanswerdialog(MCStringRef *p_buttons, uint32_t p_button_count, uint32_t p_type, MCStringRef p_title, MCStringRef p_message, bool p_blocking); virtual bool popupaskdialog(uint32_t p_type, MCStringRef p_title, MCStringRef p_message, MCStringRef p_initial, bool p_hint, MCStringRef& r_result); @@ -91,7 +88,6 @@ class MCScreenDC: public MCUIDC virtual void platform_querymouse(int16_t& r_x, int16_t& r_y); protected: - void UpdateFocus(); void FitWindow(); private: diff --git a/engine/src/em-dc.js b/engine/src/em-dc.js index 4448a92f5e5..1c8e2ec0a2b 100644 --- a/engine/src/em-dc.js +++ b/engine/src/em-dc.js @@ -17,7 +17,7 @@ along with LiveCode. If not see . */ mergeInto(LibraryManager.library, { - // $LiveCodeDC__deps: ['$LiveCodeAsync'], + $LiveCodeDC__deps: ['$LiveCodeEvents'], $LiveCodeDC: { // true if ensureInit() has ever been run _initialised: false, @@ -45,6 +45,7 @@ mergeInto(LibraryManager.library, { // Windows are backed by an html canvas within a floating div createWindow: function() { + var div; var canvas; var rect; if (!LiveCodeDC._assignedMainWindow) @@ -55,15 +56,21 @@ mergeInto(LibraryManager.library, { } else { + div = document.createElement('div'); + div.style.display = 'none'; + div.style.position = 'fixed'; + div.style.zIndex = 1; canvas = document.createElement('canvas'); - canvas.style.position = 'absolute'; - document.appendChild(canvas); + div.appendChild(canvas); + document.body.appendChild(div); rect = {'left':0, 'top':0, 'right':0, 'bottom':0}; } + LiveCodeEvents.addEventListeners(canvas); LiveCodeDC._maxWindowID += 1; LiveCodeDC._windowList[LiveCodeDC._maxWindowID] = { + 'div': div, 'canvas': canvas, 'rect': rect, 'visible':false, @@ -83,9 +90,9 @@ mergeInto(LibraryManager.library, { } else { - document.removeChild(window.canvas); + document.body.removeChild(window.div); } - LiveCodeDC._windowList[pID] = null; + delete LiveCodeDC._windowList[pID]; } }, @@ -93,11 +100,18 @@ mergeInto(LibraryManager.library, { var window = LiveCodeDC._windowList[pID]; if (window) { + var width = pRight - pLeft; + var height = pBottom - pTop; window.rect = {'left':pLeft, 'top':pTop, 'right':pRight, 'bottom':pBottom}; - window.canvas.style.left = pLeft + 'px'; - window.canvas.style.top = pLeft + 'px'; - window.canvas.style.right = pRight + 'px'; - window.canvas.style.bottom = pBottom + 'px'; + window.canvas.width = width; + window.canvas.height = height; + if (window.div) + { + window.div.style.setProperty('left', pLeft + 'px', 'important'); + window.div.style.setProperty('top', pTop + 'px', 'important'); + window.div.style.setProperty('width', width + 'px', 'important'); + window.div.style.setProperty('height', height + 'px', 'important'); + } } }, @@ -114,10 +128,20 @@ mergeInto(LibraryManager.library, { if (window) { window.visible = pVisible; - if (pVisible) - window.canvas.style.visibility = 'visible'; + if (window.div) + { + if (pVisible) + window.div.style.display = 'block'; + else + window.div.style.display = 'none'; + } else - window.canvas.style.visibility = 'hidden'; + { + if (pVisible) + window.canvas.style.visibility = 'visible'; + else + window.canvas.style.visibility = 'hidden'; + } } }, @@ -140,6 +164,19 @@ mergeInto(LibraryManager.library, { return null; }, + + getWindowIDForCanvas: function(pCanvas) { + for (var tID in LiveCodeDC._windowList) { + if (LiveCodeDC._windowList.hasOwnProperty(tID)) { + if (pCanvas == LiveCodeDC._windowList[tID].canvas) { + console.debug("canvas found: " + tID); + return tID; + } + } + } + console.debug("canvas not found: " + pCanvas); + return 0; + } }, MCEmscriptenDCInitializeJS__deps: ['$LiveCodeDC'], diff --git a/engine/src/em-event.js b/engine/src/em-event.js index c2946f1f4e0..da5b1de60bd 100644 --- a/engine/src/em-event.js +++ b/engine/src/em-event.js @@ -18,7 +18,7 @@ along with LiveCode. If not see . */ mergeInto(LibraryManager.library, { - $LiveCodeEvents__deps: ['$LiveCodeAsync'], + $LiveCodeEvents__deps: ['$LiveCodeAsync', '$LiveCodeDC'], $LiveCodeEvents: { // true if ensureInit() has ever been run @@ -64,30 +64,38 @@ mergeInto(LibraryManager.library, { } }, - initialize: function() { - // Make sure this only ever gets run once - if (LiveCodeEvents._initialised) { - return; - } - - var target = LiveCodeEvents._getTarget(); - - // Add all of the event handlers - LiveCodeEvents._eventForEach(function (type, handler) { - target.addEventListener(type, handler, true); + addEventListeners: function(pElement) + { + LiveCodeEvents._eventForEach(function(type, handler) { + pElement.addEventListener(type, handler, true); }); // Make sure the canvas is treated as focusable... - target.tabIndex = 0; + pElement.tabIndex = 0; // Make it a target for text input events - target.setAttribute('contentEditable', 'true'); + pElement.setAttribute('contentEditable', 'true'); // Force the canvas to use a normal mouse cursor by // default - target.style.cursor = 'default'; + pElement.style.cursor = 'default'; + }, + + removeEventListeners: function(pElement) + { + // Remove all of the event handlers + LiveCodeEvents._eventForEach(function (type, handler) { + pElement.removeEventListener(type, handler, true); + }); + }, + + initialize: function() { + // Make sure this only ever gets run once + if (LiveCodeEvents._initialised) { + return; + } - LiveCodeEvents._initialised = false; + LiveCodeEvents._initialised = true; }, finalize: function() { @@ -95,23 +103,14 @@ mergeInto(LibraryManager.library, { return; } - var target = LiveCodeEvents._getTarget(); - - // Remove all of the event handlers - LiveCodeEvents._eventForEach(function (type, handler) { - target.removeEventListener(type, handler, true); - }); - LiveCodeEvents._initialised = false;; }, - _getTarget: function() { - // Handlers are attached to the default canvas - return Module['canvas']; - }, - - _getStack: function() { - return Module.ccall('MCEmscriptenGetCurrentStack', 'number', [], []); + _getStackForCanvas: function(pCanvas) { + var window = LiveCodeDC.getWindowIDForCanvas(pCanvas); + return Module.ccall('MCEmscriptenGetStackForWindow', 'number', + ['number'], + [window]); }, _encodeModifiers: function(uiEvent) { @@ -136,7 +135,7 @@ mergeInto(LibraryManager.library, { _handleFocusEvent: function(e) { LiveCodeAsync.delay(function() { - var stack = LiveCodeEvents._getStack(); + var stack = LiveCodeEvents._getStackForCanvas(e.target); switch (e.type) { case 'focus': @@ -494,7 +493,7 @@ mergeInto(LibraryManager.library, { _handleKeyboardEvent: function(e) { LiveCodeAsync.delay(function() { - var stack = LiveCodeEvents._getStack(); + var stack = LiveCodeEvents._getStackForCanvas(e.target); var mods = LiveCodeEvents._encodeModifiers(e); switch (e.type) { @@ -557,7 +556,7 @@ mergeInto(LibraryManager.library, { _handleComposition: function(compositionEvent) { LiveCodeAsync.delay(function() { // Stack that we're targeting - var stack = LiveCodeEvents._getStack(); + var stack = LiveCodeEvents._getStackForCanvas(compositionEvent.target); var encodedString; var chars, length; @@ -658,7 +657,7 @@ mergeInto(LibraryManager.library, { _handleMouseEvent: function(e) { LiveCodeAsync.delay(function () { - var stack = LiveCodeEvents._getStack(); + var stack = LiveCodeEvents._getStackForCanvas(e.target); var mods = LiveCodeEvents._encodeModifiers(e); var pos = LiveCodeEvents._encodeMouseCoordinates(e); @@ -673,7 +672,7 @@ mergeInto(LibraryManager.library, { case 'mousedown': // In the case of mouse down, specifically request // keyboard focus - LiveCodeEvents._getTarget().focus(); + e.target.focus(); // Intentionally fall through to 'mouseup' case. case 'mouseup': diff --git a/engine/src/em-stack.cpp b/engine/src/em-stack.cpp index 38c08690185..846b53603ef 100644 --- a/engine/src/em-stack.cpp +++ b/engine/src/em-stack.cpp @@ -122,6 +122,7 @@ MCStack::view_platform_updatewindow(MCRegionRef p_dirty_region) MCGRegionRef t_region = MCGRegionRef(p_dirty_region); MCRectangle t_valid = MCEmscriptenGetWindowRect(t_window); + t_valid.x = t_valid.y = 0; MCGRegionIntersectRect(t_region, MCRectangleToMCGIntegerRectangle(t_valid)); diff --git a/libfoundation/src/foundation-debug.cpp b/libfoundation/src/foundation-debug.cpp index 31ff490e6d5..4c9cc40f25f 100644 --- a/libfoundation/src/foundation-debug.cpp +++ b/libfoundation/src/foundation-debug.cpp @@ -213,7 +213,7 @@ void __MCUnreachable(void) void __MCAssert(const char *p_file, uint32_t p_line, const char *p_message) { - fprintf(stderr, "MCAssert failed: %s:%u \"%s\"", p_file, p_line, p_message); + fprintf(stderr, "MCAssert failed: %s:%u \"%s\"\n", p_file, p_line, p_message); abort(); } From c932a233dec8131699aa2897504ba93e47eef4be Mon Sep 17 00:00:00 2001 From: livecodesam Date: Fri, 20 Oct 2017 12:49:05 +0100 Subject: [PATCH 0026/2459] Various dictionary entry changes --- docs/dictionary/command/delete-URL.lcdoc | 9 ++-- docs/dictionary/control_st/after.lcdoc | 6 --- docs/dictionary/control_st/before.lcdoc | 6 --- docs/dictionary/message/cutKey.lcdoc | 4 +- docs/dictionary/message/deleteGraphic.lcdoc | 5 +-- docs/dictionary/message/deleteImage.lcdoc | 5 +-- docs/dictionary/message/deleteKey.lcdoc | 21 +++++---- docs/dictionary/message/deletePlayer.lcdoc | 5 +-- docs/dictionary/message/deleteStack.lcdoc | 12 ++--- docs/dictionary/property/cursor.lcdoc | 45 +++++++++---------- .../property/customProperties.lcdoc | 4 +- docs/dictionary/property/decorations.lcdoc | 26 +++++------ docs/dictionary/property/defaultCursor.lcdoc | 16 +++---- docs/dictionary/property/defaultFolder.lcdoc | 10 ++--- 14 files changed, 78 insertions(+), 96 deletions(-) diff --git a/docs/dictionary/command/delete-URL.lcdoc b/docs/dictionary/command/delete-URL.lcdoc index a5248a7c22c..8bb2155f14c 100644 --- a/docs/dictionary/command/delete-URL.lcdoc +++ b/docs/dictionary/command/delete-URL.lcdoc @@ -39,7 +39,8 @@ to delete, in the form of a URL. The result: If the file or directory is successfully deleted, the result is set to empty. Otherwise, the returns an error -message. >*Important:* If a operation involving a +message. +>*Important:* If a operation involving a (using the to a , the , the , or a that gets an or ) is going on, no other operation can start @@ -66,7 +67,7 @@ name and password is valid, you will almost always need a user name and password to use the . >*Note:* When used with an or , the -> is : that is, the pauses until LiveCode +> is : that is, the pauses until LiveCode > is finished deleting the . Since deleting a file from a server > may take some time due to network lag, the may > take long enough to be noticeable to the user. @@ -90,10 +91,10 @@ delete file (command), delete folder (command), function (control structure), result (function), LiveCode custom library (glossary), application (glossary), standalone application (glossary), statement (glossary), -delete folder (glossary), blocking (glossary), +blocking (glossary), Standalone Application Settings (glossary), command (glossary), expression (glossary), main stack (glossary), group (glossary), -delete file (glossary), local file (glossary), server (glossary), +local file (glossary), server (glossary), upload (glossary), folder (glossary), message (glossary), handler (glossary), binfile (keyword), ftp (keyword), file (keyword), URL (keyword), http (keyword), put (library), library (library), diff --git a/docs/dictionary/control_st/after.lcdoc b/docs/dictionary/control_st/after.lcdoc index 7861839d4be..5f3917b5a69 100644 --- a/docs/dictionary/control_st/after.lcdoc +++ b/docs/dictionary/control_st/after.lcdoc @@ -40,16 +40,10 @@ path. It gets to an object with a behavior script: 1. The engine looks at the behavior script of the target object - If a before mouseDown handler is present, it executes it. - - 2. The engine next looks at the object script - If an on mouseDown handler is present, it executes it. - - 3. The engine now looks at the behavior script - If an mouseDown handler is present, it executes it. - - 4. The engine finally looks at the object script - If a pass mouseDown or no mouseDown handler is present, it moves on to the parent object. diff --git a/docs/dictionary/control_st/before.lcdoc b/docs/dictionary/control_st/before.lcdoc index 5026c58ff92..598d2e8f7e8 100644 --- a/docs/dictionary/control_st/before.lcdoc +++ b/docs/dictionary/control_st/before.lcdoc @@ -40,16 +40,10 @@ path. It gets to an object with a behavior script: 1. The engine looks at the behavior script of the target object - If a mouseDown handler is present, it executes it. - - 2. The engine next looks at the object script - If an on mouseDown handler is present, it executes it. - - 3. The engine now looks at the behavior script - If an after mouseDown handler is present, it executes it. - - 4. The engine finally looks at the object script - If a pass mouseDown or no mouseDown handler is present, it moves on to the parent object. diff --git a/docs/dictionary/message/cutKey.lcdoc b/docs/dictionary/message/cutKey.lcdoc index 0a54662acae..659392fa1ce 100644 --- a/docs/dictionary/message/cutKey.lcdoc +++ b/docs/dictionary/message/cutKey.lcdoc @@ -33,8 +33,8 @@ means that the is not received by a if it's running in the , To test a , choose Development → Suspend Development Tools from the menubar. - is sent when the user presses Command-X (on ), Control-X (on ), + is sent when the user presses Command-X (on +), Control-X (on ), Shift-Delete (on ), or the keyboard Cut key. The message is sent to the active (focused) control, or to the current diff --git a/docs/dictionary/message/deleteGraphic.lcdoc b/docs/dictionary/message/deleteGraphic.lcdoc index 607320416e0..ad39ff2dba4 100644 --- a/docs/dictionary/message/deleteGraphic.lcdoc +++ b/docs/dictionary/message/deleteGraphic.lcdoc @@ -35,9 +35,8 @@ stack - -### Engine download - -The engine is quite a large JavaScript file, so it's downloaded asynchronously in order to let the rest of the page finish loading and start being displayed. - -Quite straightforwardly: - - - -Make sure to replace `` as appropriate. - -### Bringing it all together - -Here's the complete skeleton web page for an HTML5 standalone: - - - -
- -
- - - - - - -## Advanced: Speeding up engine download - -Currently, the engine files are almost 30 MB, which is a lot to download before the engine can start. It is possible to speed up the download by enabling deflate compression in the web server configuration. - -Enabling deflate compression reduces the total download size to around 6.3 MB. It's recommended to pre-compress the engine with `gzip`, and then configure your web server to serve the pre-compressed files. - -* For the Apache web server, configure `mod_deflate` to serve [pre-compressed content](https://httpd.apache.org/docs/2.4/mod/mod_deflate.html#precompressed) -* For the NGINX web server, add [`gzip_static on;`](https://www.nginx.com/resources/admin-guide/compression-and-decompression/#send) to your configuration. - -## Advanced: Customizing the Module object - -There are a number of LiveCode-specific `Module` attributes that you can modify to affect how the engine behaves: - -* `Module.livecodeStandalone`: the filename of the standalone archive (default `standalone.zip`) -* `Module.livecodeStandalonePrefixURL`: Prepended to the standalone archive filename to construct its full URL (default empty) -* `Module.livecodeStandaloneRequest`: If you assign a network request to this attribute (before the engine runs), then it will use that request for the standalone archive instead of automatically starting a download for you. This means that you can, in your HTML, fire off a request for the standalone before the engine script actually arrives. For this to work, the network request should be an `XMLHttpRequest` with its `responseType` set to `arraybuffer`. - -See also Emscripten's [Module object documentation](https://kripken.github.io/emscripten-site/docs/api_reference/module.html). diff --git a/docs/guides/Mac Deployment.md b/docs/guides/Mac Deployment.md deleted file mode 100644 index c43b415d991..00000000000 --- a/docs/guides/Mac Deployment.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -group: deployment ---- - -# Mac Deployment - -## Introduction - -LiveCode 8.0 DP15 introduced the ability to build 64-bit standalones for -MacOSX after a successful sponsorship campaign on the LiveCode Feature -Exchange. - -## 64-bit engine features - -The 64-bit Mac engines should work exactly the same as the 32-bit -engines, with the following exceptions: - -* QuickTime is not available as it has been deprecated by Apple -* Sound recording is not available as it depends on QuickTime -* The revvideograbber external is not available as it depends on QuickTime - -Some other features may differ in minor ways not affecting -functionality, for example: - -* Printing progress dialogs are not shown as the necessary API was removed by Apple - -## The IDE - -The LiveCode IDE runs in 32-bit mode by default for maximum -compatibility. If you'd like to run it in 64-bit mode, right-click on -the app bundle, select "Get Info" and deselect the "Open in 32-bit mode" -option. In future, we will add a menu item in the IDE that re-launches -the IDE in either 32-bit or 64-bit mode, as appropriate. - -## How to deploy a 64-bit Mac standalone - -### Building - -The MacOS pane of the Standalone Settings includes two checkboxes to -indicate what engines you'd like to include in the standalone. The -current default is 32-bit only but this can be changed to 64-bit only or -32-bit/64-bit Universal binary. If both engines are included, only one -app bundle is produced containing both engines. The app will then run in -64-bit mode on 64-bit machines or 32-bit mode otherwise. - -### Testing - -If you have built a 32-bit only or 64-bit only standalone, the app will -always run in that mode. If you have a Universal standalone containing -both, you can force the app to run in 32-bit mode on 64-bit machines by -right-clicking the app bundle, selecting "Get Info" and then enabling -the "Open in 32-bit mode" option. - -## Reporting bugs - -Please report bugs to the -[LiveCode Quality Centre](http://quality.livecode.com/). Make sure you -select the correct engine type when prompted - 32-bit or 64-bit. \ No newline at end of file From 6c56b0c1e96aef4c07449096c9b362b997f48807 Mon Sep 17 00:00:00 2001 From: livecodepanos Date: Mon, 6 May 2019 10:32:41 +0300 Subject: [PATCH 1708/2459] Updated ide submodule ptr --- ide | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ide b/ide index 701f0ef80b2..1750c11ad53 160000 --- a/ide +++ b/ide @@ -1 +1 @@ -Subproject commit 701f0ef80b28dc9100f38c985c1405400a6e79d3 +Subproject commit 1750c11ad5350ebc29461ae7f60218156c7884d4 From 989a541563e8a65367b2bfe4230b5fb898ac2931 Mon Sep 17 00:00:00 2001 From: Ali Lloyd Date: Wed, 1 May 2019 22:44:02 +0100 Subject: [PATCH 1709/2459] [[ Math ]] Add tests for stats functions, errors and infinity handling This patch adds three new sets of tests: Firstly it adds tests for the stats functions which were previously untested. Secondly it adds tests for all the possible domain and range errors that can be caused by math function computations, and finally it adds tests for all types of computations involving infinity which neither throw an error nor return NaN. --- tests/_testlib.livecodescript | 20 +- .../math/arithmetic-commands.livecodescript | 20 +- tests/lcs/core/math/errors.livecodescript | 346 ++++++++++++++++++ tests/lcs/core/math/infinity.livecodescript | 180 ++++++++- tests/lcs/core/math/math.livecodescript | 39 +- tests/lcs/core/math/stats.livecodescript | 211 +++++++++++ 6 files changed, 749 insertions(+), 67 deletions(-) create mode 100644 tests/lcs/core/math/errors.livecodescript create mode 100644 tests/lcs/core/math/stats.livecodescript diff --git a/tests/_testlib.livecodescript b/tests/_testlib.livecodescript index de34591a5d7..1ffe5a2b064 100644 --- a/tests/_testlib.livecodescript +++ b/tests/_testlib.livecodescript @@ -222,6 +222,12 @@ function TestBuildErrorMap pErrorFile, pErrorPrefix, pZerothError if tCode is empty then throw "no error code found for" && tError end if + if tError begins with (pErrorPrefix & "_UNUSED_") then + if tError is not (pErrorPrefix & "_UNUSED_" & tCode) then + throw "unused error name" && tError && "does not match code" \ + && tCode && "change to" && pErrorPrefix & "_UNUSED_" & tCode + end if + end if if tErrorMap[tCode] is not empty then throw "duplicate error code" && tCode && "found for" && tError && \ "change to" && the number of elements of tErrorMap + 1 @@ -244,19 +250,19 @@ private command __TestEnsureExecErrorMap if sExecErrorMap is not empty then exit __TestEnsureExecErrorMap end if - + put TestBuildErrorMap("executionerrors.h", "EE", "UNDEFINED") \ into sExecErrorMap end __TestEnsureExecErrorMap -private function __TestErrorMatches pError, pCode +function TestErrorMatches pError, pCode __TestEnsureExecErrorMap - + local tErrorNumber put format("%04d", item 1 of line 1 of pError) into tErrorNumber - + return sExecErrorMap[tErrorNumber] is pCode -end __TestErrorMatches +end TestErrorMatches ---------------------------------------------------------------- -- Unit test library functions @@ -316,7 +322,7 @@ function _TestHandlerThrows pHandler, pTarget, pErrorCodes, pParam local tSuccess put true into tSuccess repeat for each item tErrorCode in pErrorCodes - put tSuccess and __TestErrorMatches(tError, tErrorCode) into tSuccess + put tSuccess and TestErrorMatches(tError, tErrorCode) into tSuccess delete the first line of tError end repeat return tSuccess @@ -351,7 +357,7 @@ end ErrorDialog on TestAssertErrorDialog pDescription, pErrorCode wait for messages - TestAssert pDescription, __TestErrorMatches(sError, pErrorCode) + TestAssert pDescription, TestErrorMatches(sError, pErrorCode) put empty into sError end TestAssertErrorDialog diff --git a/tests/lcs/core/math/arithmetic-commands.livecodescript b/tests/lcs/core/math/arithmetic-commands.livecodescript index b3db238e4fd..5722b65d9ee 100644 --- a/tests/lcs/core/math/arithmetic-commands.livecodescript +++ b/tests/lcs/core/math/arithmetic-commands.livecodescript @@ -19,11 +19,11 @@ along with LiveCode. If not see . */ ---------- private function MapError pError, pSrcErr, pDstErr - if item 1 of pError is pSrcErr then + if TestErrorMatches(pError, pSrcErr) then return "src" end if - if item 1 of pError is pDstErr then + if TestErrorMatches(pError, pDstErr) then return "dst" end if @@ -32,8 +32,8 @@ end MapError ---------- -constant kAddSrcError = 10 -constant kAddDstError = 9 +constant kAddSrcError = "EE_ADD_BADSOURCE" +constant kAddDstError = "EE_ADD_BADDEST" private function DoAdd pSrc, pDst try @@ -53,8 +53,8 @@ end TestAdd ---------- -constant kSubtractSrcError = 579 -constant kSubtractDstError = 578 +constant kSubtractSrcError = "EE_SUBTRACT_BADSOURCE" +constant kSubtractDstError = "EE_SUBTRACT_BADDEST" private function DoSubtract pSrc, pDst try @@ -74,8 +74,8 @@ end TestSubtract ---------- -constant kMultiplySrcError = 334 -constant kMultiplyDstError = 333 +constant kMultiplySrcError = "EE_MULTIPLY_BADSOURCE" +constant kMultiplyDstError = "EE_MULTIPLY_BADDEST" private function DoMultiply pSrc, pDst try @@ -95,8 +95,8 @@ end TestMultiply ---------- -constant kDivideSrcError = 149 -constant kDivideDstError = 148 +constant kDivideSrcError = "EE_DIVIDE_BADSOURCE" +constant kDivideDstError = "EE_DIVIDE_BADDEST" private function DoDivide pSrc, pDst try diff --git a/tests/lcs/core/math/errors.livecodescript b/tests/lcs/core/math/errors.livecodescript new file mode 100644 index 00000000000..0c74ae908d7 --- /dev/null +++ b/tests/lcs/core/math/errors.livecodescript @@ -0,0 +1,346 @@ +script "CoreMathErrors" +/* +Copyright (C) 2019 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 . */ + +command DoSin pParam + get sin(pParam) +end DoSin + +command DoCos pParam + get cos(pParam) +end DoCos + +command DoTan pParam + get tan(pParam) +end DoTan + +command DoAcos pParam + get acos(pParam) +end DoAcos + +on TestAcosError + TestAssertThrow "acos throws on invalid domain", "DoAcos", \ + the long id of me, "EE_MATH_DOMAIN", 2 +end TestAcosError + +command DoAsin pParam + get asin(pParam) +end DoAsin + +on TestAsinError + TestAssertThrow "asin throws on invalid domain", "DoAsin", \ + the long id of me, "EE_MATH_DOMAIN", 2 +end TestAsinError + +command DoAtan pParam + get atan(pParam) +end DoAtan + +command DoExp pParam + get exp(pParam) +end DoExp + +command DoExp1 pParam + get exp1(pParam) +end DoExp1 + +command DoExp2 pParam + get exp2(pParam) +end DoExp2 + +command DoExp10 pParam + get exp10(pParam) +end DoExp10 + +on TestExpErrors + local tParam + put GetVeryLargeInteger() into tParam + repeat for each item tItem in "exp,exp1,exp2,exp10" + TestAssertThrow tItem && "overflow throws", "Do" & tItem, \ + the long id of me, "EE_MATH_RANGE", tParam + end repeat +end TestExpErrors + +command DoLn pParam + get ln(pParam) +end DoLn + +on TestLnError + TestAssertThrow "ln throws with negative input", "DoLn", \ + the long id of me, "EE_MATH_DOMAIN", -1 + + TestAssertThrow "ln throws with -inf result", "DoLn", \ + the long id of me, "EE_MATH_ZERO", 0 +end TestLnError + +command DoLn1 pParam + get ln1(pParam) +end DoLn1 + +on TestLn1Error + TestAssertThrow "ln1 throws with input < -1", "DoLn1", \ + the long id of me, "EE_MATH_DOMAIN", -2 + + TestAssertThrow "ln1 throws with -inf result", "DoLn1", \ + the long id of me, "EE_MATH_ZERO", -1 +end TestLn1Error + +command DoLog2 pParam + get log2(pParam) +end DoLog2 + +on TestLog2Error + TestAssertThrow "log2 throws with negative input", "DoLog2", \ + the long id of me, "EE_MATH_DOMAIN", -1 + + TestAssertThrow "log2 throws with -inf result", "DoLog2", \ + the long id of me, "EE_MATH_ZERO", 0 +end TestLog2Error + +command DoLog10 pParam + get log10(pParam) +end DoLog10 + +on TestLog10Error + TestAssertThrow "log10 throws with negative input", "DoLog10", \ + the long id of me, "EE_MATH_DOMAIN", -1 + + TestAssertThrow "log10 throws with -inf result", "DoLog10", \ + the long id of me, "EE_MATH_ZERO", 0 +end TestLog10Error + +command DoSqrt pParam + get sqrt(pParam) +end DoSqrt + +on TestSqrtError + TestAssertThrow "sqrt throws with negative input", "DoSqrt", \ + the long id of me, "EE_MATH_DOMAIN", -1 +end TestSqrtError + +command DoAtan2 pParam + get atan2(pParam["left"], pParam["right"]) +end DoAtan2 + +command DoDiv pParam + get pParam["left"] div pParam["right"] +end DoDiv + +on TestDivError + local tParam + put 10 into tParam["left"] + put 0 into tParam["right"] + TestAssertThrow "div throws with 0 denominator", "DoDiv", \ + the long id of me, "EE_MATH_ZERO", tParam +end TestDivError + +command DoMod pParam + get pParam["left"] mod pParam["right"] +end DoMod + +on TestModError + local tParam + put 10 into tParam["left"] + put 0 into tParam["right"] + TestAssertThrow "mod 0 throws", "DoMod", \ + the long id of me, "EE_MATH_ZERO", tParam +end TestModError + +command DoWrap pParam + get pParam["left"] wrap pParam["right"] +end DoWrap + +on TestWrapError + local tParam + put 10 into tParam["left"] + put 0 into tParam["right"] + TestAssertThrow "wrap 0 throws", "DoWrap", \ + the long id of me, "EE_MATH_ZERO", tParam +end TestWrapError + +// Returns an integer large enough to cause overflow when added to itself +private function GetVeryLargeInteger pNegative + if pNegative then + return -(10^308) + end if + return 10^308 +end GetVeryLargeInteger + +command DoPlus pParam + get pParam["left"] + pParam["right"] +end DoPlus + +on TestPlusError + local tParam + put GetVeryLargeInteger() into tParam["left"] + put GetVeryLargeInteger() into tParam["right"] + TestAssertThrow "plus overflow throws", "DoPlus", \ + the long id of me, "EE_MATH_RANGE", tParam +end TestPlusError + +command DoMultiply pParam + get pParam["left"] * pParam["right"] +end DoMultiply + +on TestMultiplyError + local tParam + put GetVeryLargeInteger() into tParam["left"] + put 10 into tParam["right"] + TestAssertThrow "multiply overflow throws", "DoMultiply", \ + the long id of me, "EE_MATH_RANGE", tParam +end TestMultiplyError + +command DoMinus pParam + get pParam["left"] - pParam["right"] +end DoMinus + +on TestMinusError + local tParam + put GetVeryLargeInteger(true) into tParam["left"] + put GetVeryLargeInteger() into tParam["right"] + TestAssertThrow "minus overflow throws", "DoMinus", \ + the long id of me, "EE_MATH_RANGE", tParam +end TestMinusError + +command DoOver pParam + get pParam["left"] / pParam["right"] +end DoOver + +on TestOverError + local tParam + put 10 into tParam["left"] + put 0 into tParam["right"] + TestAssertThrow "/ throws with 0 denominator", "DoOver", \ + the long id of me, "EE_MATH_ZERO", tParam +end TestOverError + +command DoPow pParam + get pParam["left"] ^ pParam["right"] +end DoPow + +on TestPowError + local tParam + put -1 into tParam["left"] + put 0.5 into tParam["right"] + TestAssertThrow "negative^(abs < 1) throws", "DoPow", \ + the long id of me, "EE_MATH_DOMAIN", tParam + + put -1 into tParam["left"] + put -0.5 into tParam["right"] + TestAssertThrow "negative^(-1 < x < 0) throws", "DoPow", \ + the long id of me, "EE_MATH_DOMAIN", tParam + + put 0 into tParam["left"] + put -2 into tParam["right"] + TestAssertThrow "zero^(-ve) throws", "DoPow", \ + the long id of me, "EE_MATH_ZERO", tParam +end TestPowError + +command DoAnnuity pParam + get annuity(pParam["left"], pParam["right"]) +end DoAnnuity + +on TestAnnuityError + // Divide by zero + local tParam + put -1 into tParam["left"] + put 2 into tParam["right"] + TestAssertThrow "annuity(-1, +ve) throws", "DoAnnuity", \ + the long id of me, "EE_MATH_ZERO", tParam + + // Sqrt -1 + put -2 into tParam["left"] + put -0.5 into tParam["right"] + TestAssertThrow "annuity(-ve, -1 < x < 0) throws", "DoAnnuity", \ + the long id of me, "EE_MATH_DOMAIN", tParam + + put -2 into tParam["left"] + put 0.5 into tParam["right"] + TestAssertThrow "annuity(-ve, 0 < x < 1) throws", "DoAnnuity", \ + the long id of me, "EE_MATH_DOMAIN", tParam +end TestAnnuityError + +command DoCompound pParam + get compound(pParam["left"], pParam["right"]) +end DoCompound + +on TestCompoundError + // Divide by zero + local tParam + put -1 into tParam["left"] + put -1 into tParam["right"] + TestAssertThrow "compound(-1, -ve) throws", "DoCompound", \ + the long id of me, "EE_MATH_ZERO", tParam + + // Sqrt -1 + put -2 into tParam["left"] + put 0.5 into tParam["right"] + TestAssertThrow "compound(-ve, abs < 1) throws", "DoCompound", \ + the long id of me, "EE_MATH_DOMAIN", tParam +end TestCompoundError + +on TestNaryOverflowErrors + local tParam + put GetVeryLargeInteger() into tParam["args"][1] + put GetVeryLargeInteger() into tParam["args"][2] + repeat for each item tItem in "sum,average,median,avgdev,stddev,pop_stddev,pop_variance,variance" + put tItem into tParam["which"] + TestAssertThrow tItem && "overflow throws", "DoNaryFunction", \ + the long id of me, "EE_MATH_RANGE", tParam + end repeat +end TestNaryOverflowErrors + +command DoGeoMean pParam + get geometricMean(pParam[1], pParam[2]) +end DoGeoMean + +on TestGeoMeanError + local tParam + put -1 into tParam[1] + put 1 into tParam[2] + TestAssertThrow "geometric mean with negative number throws domain error", "DoGeoMean", \ + the long id of me, "EE_MATH_DOMAIN", tParam +end TestGeoMeanError + +command DoNaryFunction pParams + switch pParams["which"] + case "sum" + get sum(pParams["args"]) + break + case "average" + get avg(pParams["args"]) + break + case "median" + get median(pParams["args"]) + break + case "avgdev" + get averageDeviation(pParams["args"]) + break + case "pop_stddev" + get populationStandardDeviation(pParams["args"]) + break + case "pop_variance" + get populationVariance(pParams["args"]) + break + case "stddev" + get sampleStandardDeviation(pParams["args"]) + break + case "variance" + get sampleVariance(pParams["args"]) + break + end switch +end DoNaryFunction diff --git a/tests/lcs/core/math/infinity.livecodescript b/tests/lcs/core/math/infinity.livecodescript index b74f44f435c..d901e4fdc52 100644 --- a/tests/lcs/core/math/infinity.livecodescript +++ b/tests/lcs/core/math/infinity.livecodescript @@ -16,26 +16,170 @@ for more details. You should have received a copy of the GNU General Public License along with LiveCode. If not see . */ -on TestInfinityDivOperator - TestAssert "Infinity is unchanged by div operator", inf div 2 is inf -end TestInfinityDivOperator +private command _TestBinaryOperator pLeft, pRight, pOperator, pExpected + local tResult, tExpr + switch pOperator + case "plus" + put pLeft + pRight into tResult + break + case "minus" + put pLeft - pRight into tResult + break + case "times" + put pLeft * pRight into tResult + break + case "over" + put pLeft / pRight into tResult + break + case "to the power of" + put pLeft ^ pRight into tResult + break + case "added to" + add pLeft to pRight + put pRight into tResult + break + case "subtracted from" + subtract pLeft from pRight + put pRight into tResult + break + case "multiplied by" + multiply pLeft by pRight + put pLeft into tResult + break + case "divided by" + divide pLeft by pRight + put pLeft into tResult + break + case "div" + put pLeft div pRight into tResult + break + case "mod" + put pLeft mod pRight into tResult + break + case "wrap" + put pLeft wrap pRight into tResult + break + default + put pOperator & "(" & pLeft & "," & pRight & ")" into tExpr + put value(tExpr) into tResult + break + end switch + if tExpr is empty then + TestAssert "Result of" && pLeft && pOperator && pRight && "is" && pExpected, \ + tResult is pExpected + else + TestAssert "Result of" && tExpr && "is" && pExpected, \ + tResult is pExpected + end if +end _TestBinaryOperator -on TestInfinitySubtractOperator - TestAssert "Infinity is unchanged by subtract operator", inf - 1 is inf -end TestInfinitySubtractOperator +on TestInfinityBinaryOperators + _TestBinaryOperator "inf", 1, "plus", "inf" + _TestBinaryOperator "-inf", 1, "plus", "-inf" -on TestInfinityOverOperator - TestAssert "Infinity is unchanged by over operator", inf / 2 is inf -end TestInfinityOverOperator + _TestBinaryOperator "inf", 1, "minus", "inf" + _TestBinaryOperator "-inf", 1, "minus", "-inf" + _TestBinaryOperator 1, "inf", "minus", "-inf" + _TestBinaryOperator 1, "-inf", "minus", "inf" -on TestInfinityAddOperator - TestAssert "Infinity is unchanged by add operator", inf + 1 is inf -end TestInfinityAddOperator + _TestBinaryOperator "inf", 2, "times", "inf" + _TestBinaryOperator "-inf", 2, "times", "-inf" -on TestInfinityMultiplyOperator - TestAssert "Infinity is unchanged by multiply operator", inf * 2 is inf -end TestInfinityMultiplyOperator + _TestBinaryOperator "inf", 2, "over", "inf" + _TestBinaryOperator "-inf", 2, "over", "-inf" + _TestBinaryOperator 2, "inf", "over", 0 + _TestBinaryOperator 2, "-inf", "over", 0 -on TestInfinityPowerOperator - TestAssert "Infinity is unchanged by powwe operator", inf ^ 2 is inf -end TestInfinityPowerOperator + _TestBinaryOperator "inf", 2, "to the power of", "inf" + _TestBinaryOperator "-inf", 2, "to the power of", "inf" + _TestBinaryOperator "-inf", 3, "to the power of", "-inf" + _TestBinaryOperator 2, "inf", "to the power of", "inf" + _TestBinaryOperator 2, "-inf", "to the power of", 0 + + _TestBinaryOperator "inf", 1, "added to", "inf" + _TestBinaryOperator "-inf", 1, "added to", "-inf" + _TestBinaryOperator 1, "inf", "added to", "inf" + _TestBinaryOperator 1, "-inf", "added to", "-inf" + + _TestBinaryOperator 1, "inf", "subtracted from", "inf" + _TestBinaryOperator 1, "-inf", "subtracted from", "-inf" + _TestBinaryOperator "inf", 1, "subtracted from", "-inf" + _TestBinaryOperator "-inf", 1, "subtracted from", "inf" + + _TestBinaryOperator "inf", 2, "multiplied by", "inf" + _TestBinaryOperator "-inf", 2, "multiplied by", "-inf" + _TestBinaryOperator 2, "inf", "multiplied by", "inf" + _TestBinaryOperator 2, "-inf", "multiplied by", "-inf" + + _TestBinaryOperator "inf", 2, "divided by", "inf" + _TestBinaryOperator "-inf", 2, "divided by", "-inf" + _TestBinaryOperator 2, "inf", "divided by", 0 + _TestBinaryOperator 2, "-inf", "divided by", 0 + + _TestBinaryOperator "inf", 2, "div", "inf" + _TestBinaryOperator "-inf", 2, "div", "-inf" + _TestBinaryOperator 2, "inf", "div", 0 + _TestBinaryOperator 2, "-inf", "div", 0 + + _TestBinaryOperator 2, "inf", "mod", 2 + _TestBinaryOperator 2, "-inf", "mod", 2 + + _TestBinaryOperator 2, "inf", "wrap", 2 + _TestBinaryOperator 2, "-inf", "wrap", 2 + + _TestBinaryOperator 1, "inf", "atan2", 0 + _TestBinaryOperator "inf", 1, "atan2", pi/2 + _TestBinaryOperator "inf", "inf", "atan2", pi/4 + _TestBinaryOperator 1, "-inf", "atan2", pi + _TestBinaryOperator "-inf", 1, "atan2", -pi/2 + _TestBinaryOperator "-inf", "-inf", "atan2", -3*pi/4 +end TestInfinityBinaryOperators + +private command _TestUnaryOperator pOperator, pOperand, pExpected + local tResult, tExpr + put pOperator & "(" & pOperand & ")" into tExpr + put value(tExpr) into tResult + TestAssert tExpr && "is" && pExpected, \ + tResult is pExpected +end _TestUnaryOperator + +on TestInfinityUnaryOperators + _TestUnaryOperator "atan", "inf", pi/2 + _TestUnaryOperator "atan", "-inf", -pi/2 + + _TestUnaryOperator "exp", "inf", "inf" + _TestUnaryOperator "exp", "-inf", 0 + _TestUnaryOperator "exp1", "inf", "inf" + _TestUnaryOperator "exp1", "-inf", -1 + _TestUnaryOperator "exp2", "inf", "inf" + _TestUnaryOperator "exp2", "-inf", 0 + _TestUnaryOperator "exp10", "inf", "inf" + _TestUnaryOperator "exp10", "-inf", 0 + + _TestUnaryOperator "ln", "inf", "inf" + _TestUnaryOperator "ln1", "inf", "inf" + _TestUnaryOperator "log2", "inf", "inf" + _TestUnaryOperator "log10", "inf", "inf" + + _TestUnaryOperator "sqrt", "inf", "inf" +end TestInfinityUnaryOperators + +on TestInfinityNaryOperators + repeat for each item tItem in "sum,min,max,avg,median" + _TestUnaryOperator tItem, "inf", "inf" + if the platform is "win32" then + TestSkip tItem & "(-inf) is -inf", "Bug 22038" + else + _TestUnaryOperator tItem, "-inf", "-inf" + end if + end repeat + + _TestBinaryOperator 2, "inf", "min", 2 + _TestBinaryOperator 2, "-inf", "min", "-inf" + + _TestBinaryOperator 2, "inf", "max", "inf" + _TestBinaryOperator 2, "-inf", "max", 2 + + TestAssert "Result of median(2,inf,inf) is inf", median(2,"inf","inf") is "inf" + TestAssert "Result of median(2,-inf,-inf) is -inf", median(2,"-inf","-inf") is "-inf" +end TestInfinityNaryOperators diff --git a/tests/lcs/core/math/math.livecodescript b/tests/lcs/core/math/math.livecodescript index 07161374197..7da6fda46e0 100644 --- a/tests/lcs/core/math/math.livecodescript +++ b/tests/lcs/core/math/math.livecodescript @@ -97,12 +97,16 @@ repeat with i = 1 to 10 end repeat end TestMathArrayPlusArray -on TestMath3 +on TestAnnuity + TestAssert "test annuity formula", annuity(0.02, 25) is ( 1 - ( 1 + 0.02 ) ^ ( - 25 ) ) / 0.02 + TestAssert "test annuity zero rate", annuity(0, 25) is 25 +end TestAnnuity -TestAssert "test", annuity(0.02, 25) is ( 1 - ( 1 + 0.02 ) ^ ( - 25 ) ) / 0.02 +on TestCompound + TestAssert "test compound formula", compound(0.02, 25) is (1 + 0.02) ^ 25 +end TestCompound -end TestMath3 on TestMath4 @@ -131,21 +135,6 @@ TestAssert "test", atan2(-1, 0) is -pi / 2 TestAssert "test", atan2(-1, 1) is -pi / 4 end TestMath5 -on TestMath6 - - -TestAssert "test", average() is 0 -TestAssert "test", average(1.23) is 1.23 -TestAssert "test", average("1, 2, 3, 4, 5") is 3 -TestAssert "test", average(1, 2, 3, 4, 5) is 3 - -local tArray -repeat with i = 1 to 5 - put i into tArray[i] -end repeat -TestAssert "test", average(tArray) is 3 - -end TestMath6 on TestMath7 @@ -730,21 +719,7 @@ repeat with i = 1 to 10 step 0.1 end repeat end TestMath31 -on TestMathStdDev - - -TestAssert "test", stddev() is 0 -TestAssert "test", stddev("1, 2, 3") is 1 -TestAssert "test", stddev(1,2,3) is 1 -TestAssert "test", stddev(0.5,1,1.5) is 0.5 - -local tArray -repeat with i = 1 to 5 - put 6 - i into tArray[i] -end repeat -TestAssert "test", stddev(tArray) is stddev(1,2,3,4,5) -end TestMathStdDev on TestMathNumberMinusNumber diff --git a/tests/lcs/core/math/stats.livecodescript b/tests/lcs/core/math/stats.livecodescript new file mode 100644 index 00000000000..001951c02d6 --- /dev/null +++ b/tests/lcs/core/math/stats.livecodescript @@ -0,0 +1,211 @@ +script "CoreMathStats" +/* +Copyright (C) 2019 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 . */ + +private function ComputeAverage pMeanKind + local tTotal, tCount, tParams + put char 1 to -2 of item 2 to -1 of the params into tParams + put 0 into tTotal + put the number of items in tParams into tCount + if tCount is 0 then + return tTotal + end if + repeat for each item tItem in tParams + local tValue + // Strip quotes + put char 2 to -2 of tItem into tValue + switch pMeanKind + case "arithmetic" + add tValue to tTotal + break + case "harmonic" + add (1 / tValue) to tTotal + break + case "geometric" + if tTotal is 0 then + put 1 into tTotal + end if + multiply tTotal by (tValue ^ (1 / tCount)) + break + end switch + end repeat + + switch pMeanKind + case "arithmetic" + return tTotal / tCount + case "harmonic" + return tCount / tTotal + case "geometric" + return tTotal + break + end switch +end ComputeAverage + +on TestAverage + TestAssert "test arithmetic mean no params", average() is ComputeAverage("arithmetic") + TestAssert "test arithmetic mean one param", average(1.23) is ComputeAverage("arithmetic", 1.23) + TestAssert "test arithmetic mean string param", average("1, 2, 3, 4, 5") is ComputeAverage("arithmetic", 1, 2, 3, 4, 5) + TestAssert "test arithmetic mean numeric params", average(1, 2, 3, 4, 5) is ComputeAverage("arithmetic", 1, 2, 3, 4, 5) + + local tArray + repeat with i = 1 to 5 + put i into tArray[i] + end repeat + TestAssert "test arithmetic mean array param", average(tArray) is ComputeAverage("arithmetic", 1, 2, 3, 4, 5) + TestDiagnostic average(tArray) +end TestAverage + +on TestHarmonicMean + TestAssert "test harmonic mean no params", harmonicMean() is ComputeAverage("harmonic") + TestAssert "test harmonic mean one param", harmonicMean(1.23) is ComputeAverage("harmonic", 1.23) + TestAssert "test harmonic mean string param", harmonicMean("1, 2, 3, 4, 5") is ComputeAverage("harmonic", 1, 2, 3, 4, 5) + TestAssert "test harmonic mean numeric params", harmonicMean(1, 2, 3, 4, 5) is ComputeAverage("harmonic", 1, 2, 3, 4, 5) + + local tArray + repeat with i = 1 to 5 + put i into tArray[i] + end repeat + TestAssert "test arithmetic mean array param", harmonicMean(tArray) is ComputeAverage("harmonic", 1, 2, 3, 4, 5) +end TestHarmonicMean + +on TestGeometricMean + TestAssert "test geometric mean no params", geometricMean() is ComputeAverage("geometric") + TestAssert "test geometric mean one param", geometricMean(1.23) is ComputeAverage("geometric", 1.23) + TestAssert "test geometric mean string param", geometricMean("1, 2, 3, 4, 5") is ComputeAverage("geometric", 1, 2, 3, 4, 5) + TestAssert "test geometric mean numeric params", geometricMean(1, 2, 3, 4, 5) is ComputeAverage("geometric", 1, 2, 3, 4, 5) + + local tArray + repeat with i = 1 to 5 + put i into tArray[i] + end repeat + TestAssert "test geometric mean array param", geometricMean(tArray) is ComputeAverage("geometric", 1, 2, 3, 4, 5) +end TestGeometricMean + +private function ComputeStats pFunction + local tTotal, tCount, tParams, tMean + put char 1 to -2 of item 2 to -1 of the params into tParams + put 0 into tTotal + put the number of items in tParams into tCount + if tCount is 0 then + return tTotal + end if + + if (pFunction is "sampleStandardDeviation" or pFunction is "sampleVariance") \ + and tCount is 1 then + return 0 + end if + + local tParamArray + repeat with x = 1 to the number of items in tParams + // Strip quotes + put char 2 to -2 of item x of tParams into tParamArray[x] + end repeat + put average(tParamArray) into tMean + + repeat for each element tValue in tParamArray + subtract tMean from tValue + switch pFunction + case "averageDeviation" + add abs(tValue) to tTotal + break + case "populationStandardDeviation" + case "populationVariance" + case "sampleStandardDeviation" + case "sampleVariance" + add tValue^2 to tTotal + break + end switch + end repeat + + switch pFunction + case "averageDeviation" + return tTotal / tCount + case "populationStandardDeviation" + return sqrt(tTotal / tCount) + case "populationVariance" + return tTotal / tCount + case "sampleStandardDeviation" + return sqrt(tTotal / (tCount - 1)) + case "sampleVariance" + return tTotal / (tCount - 1) + end switch +end ComputeStats + +on TestAverageDeviation + TestAssert "test average deviation no params", averageDeviation() is ComputeStats("averageDeviation") + TestAssert "test average deviation one param", averageDeviation(1.23) is ComputeStats("averageDeviation", 1.23) + TestAssert "test average deviation string param", averageDeviation("1, 2, 3, 4, 5") is ComputeStats("averageDeviation", 1, 2, 3, 4, 5) + TestAssert "test average deviation numeric params", averageDeviation(1, 2, 3, 4, 5) is ComputeStats("averageDeviation", 1, 2, 3, 4, 5) + + local tArray + repeat with i = 1 to 5 + put i into tArray[i] + end repeat + TestAssert "test average deviation array param", averageDeviation(tArray) is ComputeStats("averageDeviation", 1, 2, 3, 4, 5) +end TestAverageDeviation + +on TestPopulationStandardDeviation + TestAssert "test population standard deviation no params", populationStandardDeviation() is ComputeStats("populationStandardDeviation") + TestAssert "test population standard deviation one param", populationStandardDeviation(1.23) is ComputeStats("populationStandardDeviation", 1.23) + TestAssert "test population standard deviation string param", populationStandardDeviation("1, 2, 3, 4, 5") is ComputeStats("populationStandardDeviation", 1, 2, 3, 4, 5) + TestAssert "test population standard deviation numeric params", populationStandardDeviation(1, 2, 3, 4, 5) is ComputeStats("populationStandardDeviation", 1, 2, 3, 4, 5) + + local tArray + repeat with i = 1 to 5 + put i into tArray[i] + end repeat + TestAssert "test population standard deviation array param", populationStandardDeviation(tArray) is ComputeStats("populationStandardDeviation", 1, 2, 3, 4, 5) +end TestPopulationStandardDeviation + +on TestPopulationVariance + TestAssert "test population variance no params", populationVariance() is ComputeStats("populationVariance") + TestAssert "test population variance one param", populationVariance(1.23) is ComputeStats("populationVariance", 1.23) + TestAssert "test population variance string param", populationVariance("1, 2, 3, 4, 5") is ComputeStats("populationVariance", 1, 2, 3, 4, 5) + TestAssert "test population variance numeric params", populationVariance(1, 2, 3, 4, 5) is ComputeStats("populationVariance", 1, 2, 3, 4, 5) + + local tArray + repeat with i = 1 to 5 + put i into tArray[i] + end repeat + TestAssert "test population variance array param", populationVariance(tArray) is ComputeStats("populationVariance", 1, 2, 3, 4, 5) +end TestPopulationVariance + +on TestSampleStandardDeviation + TestAssert "test sample standard deviation no params", sampleStandardDeviation() is ComputeStats("sampleStandardDeviation") + TestAssert "test sample standard deviation one param", sampleStandardDeviation(1.23) is ComputeStats("sampleStandardDeviation", 1.23) + TestAssert "test sample standard deviation string param", sampleStandardDeviation("1, 2, 3, 4, 5") is ComputeStats("sampleStandardDeviation", 1, 2, 3, 4, 5) + TestAssert "test sample standard deviation numeric params", sampleStandardDeviation(1, 2, 3, 4, 5) is ComputeStats("sampleStandardDeviation", 1, 2, 3, 4, 5) + + local tArray + repeat with i = 1 to 5 + put i into tArray[i] + end repeat + TestAssert "test sample standard deviation array param", sampleStandardDeviation(tArray) is ComputeStats("sampleStandardDeviation", 1, 2, 3, 4, 5) +end TestSampleStandardDeviation + +on TestSampleVariance + TestAssert "test sample variance no params", sampleVariance() is ComputeStats("sampleVariance") + TestAssert "test sample variance one param", sampleVariance(1.23) is ComputeStats("sampleVariance", 1.23) + TestAssert "test sample variance string param", sampleVariance("1, 2, 3, 4, 5") is ComputeStats("sampleVariance", 1, 2, 3, 4, 5) + TestAssert "test sample variance numeric params", sampleVariance(1, 2, 3, 4, 5) is ComputeStats("sampleVariance", 1, 2, 3, 4, 5) + + local tArray + repeat with i = 1 to 5 + put i into tArray[i] + end repeat + TestAssert "test sample variance array param", sampleVariance(tArray) is ComputeStats("sampleVariance", 1, 2, 3, 4, 5) +end TestSampleVariance From 18818ec7ca80d8062302028fa83a006d1b9147db Mon Sep 17 00:00:00 2001 From: Ian Macphail Date: Tue, 7 May 2019 23:40:08 +0100 Subject: [PATCH 1710/2459] [[ Prebuilt ]] Build thirdparty prebuilts for windows platform --- prebuilt/build-all-libs.bat | 2 +- prebuilt/scripts/build-thirdparty.bat | 104 ++++++++++++++++++++++++++ prebuilt/scripts/lib_versions.bat | 2 + 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 prebuilt/scripts/build-thirdparty.bat diff --git a/prebuilt/build-all-libs.bat b/prebuilt/build-all-libs.bat index 5377cc06334..4b580ac0f80 100644 --- a/prebuilt/build-all-libs.bat +++ b/prebuilt/build-all-libs.bat @@ -22,7 +22,7 @@ IF "%2"=="" ( SET ARCH=%2 ) -SET PREBUILT_LIBS=openssl curl icu cef +SET PREBUILT_LIBS=OpenSSL Curl ICU CEF thirdparty ECHO Building Libs %PREBUILT_LIBS% diff --git a/prebuilt/scripts/build-thirdparty.bat b/prebuilt/scripts/build-thirdparty.bat new file mode 100644 index 00000000000..50af72d3102 --- /dev/null +++ b/prebuilt/scripts/build-thirdparty.bat @@ -0,0 +1,104 @@ +@ECHO OFF +SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION + +REM ############################################################################ +REM # +REM # BUILD THIRDPARTY LIBS +REM # + +ECHO Build Thirdparty Libs for %BUILDTRIPLE% + +SET THIRDPARTY_BIN=%_ROOT_DIR%\thirdparty-%Thirdparty_VERSION%-%BUILDTRIPLE%-bin +SET THIRDPARTY_BUILD_LOG=%_ROOT_DIR%\thirdparty-%Thirdparty_VERSION%-%BUILDTRIPLE%.log + +IF DEFINED Thirdparty_BUILDREVISION ( + SET THIRDPARTY_TAR=%_PACKAGE_DIR%\Thirdparty-%Thirdparty_VERSION%-%BUILDTRIPLE%-%Thirdparty_BUILDREVISION%.tar +) ELSE ( + SET THIRDPARTY_TAR=%_PACKAGE_DIR%\Thirdparty-%Thirdparty_VERSION%-%BUILDTRIPLE%.tar +) + +if not defined BUILD_PLATFORM set BUILD_PLATFORM=win-%ARCH% + +IF "%1"=="prepare" ( + EXIT /B 0 +) + +ECHO Unpacking OpenSSL headers for %BUILDTRIPLE% +ECHO ========== UNPACKING OPENSSL HEADERS ========== >%THIRDPARTY_BUILD_LOG% + +IF DEFINED OpenSSL_BUILDREVISION ( + SET OPENSSL_TAR=%_PACKAGE_DIR%\OpenSSL-%OpenSSL_VERSION%-%BUILDTRIPLE%-%OpenSSL_BUILDREVISION%.tar.bz2 +) ELSE ( + SET OPENSSL_TAR=%_PACKAGE_DIR%\OpenSSL-%OpenSSL_VERSION%-%BUILDTRIPLE%.tar.bz2 +) +FOR /F "usebackq tokens=*" %%x IN (`cygpath.exe -u %OPENSSL_TAR%`) DO SET OPENSSL_TAR_CYG=%%x + +SET OPENSSL_UNPACK_DIR=%_TOOLS_DIR%\unpacked\OpenSSL +FOR /F "usebackq tokens=*" %%x IN (`cygpath.exe -u %OPENSSL_UNPACK_DIR%`) DO SET OPENSSL_UNPACK_DIR_CYG=%%x + +IF NOT EXIST "%_TOOLS_DIR%\unpacked" MKDIR "%_TOOLS_DIR%\unpacked" +IF NOT EXIST "%_TOOLS_DIR%\unpacked\OpenSSL" MKDIR "%_TOOLS_DIR%\unpacked\OpenSSL" + +bash -c "bunzip2 --stdout %OPENSSL_TAR_CYG% | tar x -C %OPENSSL_UNPACK_DIR_CYG%" >>%THIRDPARTY_BUILD_LOG% 2>>&1 +IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% + +ECHO Configuring Thirdparty for %BUILDTRIPLE% +ECHO ========== CONFIGURING ========== >%THIRDPARTY_BUILD_LOG% + +REM Generate project files +cd %_TOOLS_DIR%.. +python config.py --platform %BUILD_PLATFORM% >>%THIRDPARTY_BUILD_LOG% 2>>&1 +IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% + +REM Set build project +set BUILD_PROJECT=build-%BUILD_PLATFORM%\livecode\livecode.sln + +REM Set MSBUILD Platform +if /I "%ARCH%"=="x86_64" ( + set MSBUILD_PLATFORM=x64 +) +if /I "%ARCH%"=="x86" ( + set MSBUILD_PLATFORM=Win32 +) + +ECHO Building Thirdparty for %BUILDTRIPLE% +ECHO ========== BUILDING ========== >>%THIRDPARTY_BUILD_LOG% + +msbuild %BUILD_PROJECT% /fl /flp:Verbosity=normal /nologo /m:1 /t:thirdparty-prebuilts /p:Configuration=%MODE% /p:Platform=%MSBUILD_PLATFORM% >>%THIRDPARTY_BUILD_LOG% 2>>&1 +IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% + +ECHO Packaging Thirdparty for %BUILDTRIPLE% +ECHO ========== PACKAGING ========== >>%THIRDPARTY_BUILD_LOG% + +IF NOT EXIST "%THIRDPARTY_BIN%" MKDIR "%THIRDPARTY_BIN%" +IF NOT EXIST "%THIRDPARTY_BIN%\lib" MKDIR "%THIRDPARTY_BIN%\lib" + +SET THIRDPARTY_LIB_DIR=build-%BUILD_PLATFORM%\livecode\%MODE%\lib + +SET SKIA_LIBS=skia skia_opt_arm skia_opt_avx skia_opt_hsw skia_opt_none skia_opt_sse2 skia_opt_sse3 skia_opt_sse41 skia_opt_sse42 +SET THIRDPARTY_LIBS=cairo ffi gif jpeg mysql pcre png pq sqlite xml xslt z zip %SKIA_LIBS% + +SET THIRDPARTY_FILES= + +FOR %%L IN (%THIRDPARTY_LIBS%) DO ( + SET THIRDPARTY_LIB=%%L + SET THIRDPARTY_LIB_FILE=lib!THIRDPARTY_LIB!.lib + COPY /Y "%THIRDPARTY_LIB_DIR%\!THIRDPARTY_LIB_FILE!" "%THIRDPARTY_BIN%\lib\!THIRDPARTY_LIB_FILE!" >>%THIRDPARTY_BUILD_LOG% 2>>&1 + IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% + SET THIRDPARTY_FILES=!THIRDPARTY_FILES! lib/!THIRDPARTY_LIB_FILE! +) + +REM Build the prebuilt archives + +cd "%THIRDPARTY_BIN%" +FOR /F "usebackq tokens=*" %%x IN (`cygpath.exe -u %THIRDPARTY_TAR%`) DO SET THIRDPARTY_TAR_CYG=%%x + +ECHO Archiving Thirdparty for %BUILDTRIPLE% +ECHO ========== ARCHIVING ========== >>%THIRDPARTY_BUILD_LOG% +bash -c "tar --create --file=%THIRDPARTY_TAR_CYG% --transform='flags=r;s|^|%BUILDTRIPLE%/|' %THIRDPARTY_FILES%" >>%THIRDPARTY_BUILD_LOG% 2>>&1 +IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% + +ECHO Compressing Thirdparty for %BUILDTRIPLE% +ECHO ========== COMPRESSING ========== >>%THIRDPARTY_BUILD_LOG% +bash -c "bzip2 --force %THIRDPARTY_TAR_CYG%" >>%THIRDPARTY_BUILD_LOG% 2>>&1 +IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% diff --git a/prebuilt/scripts/lib_versions.bat b/prebuilt/scripts/lib_versions.bat index cb9b9e20e96..47f7860d8ab 100644 --- a/prebuilt/scripts/lib_versions.bat +++ b/prebuilt/scripts/lib_versions.bat @@ -7,3 +7,5 @@ FOR %%L in (OpenSSL ICU CEF Curl) DO ( SET /P !PREBUILT_LIB!_BUILDREVISION= Date: Thu, 25 Apr 2019 15:31:26 +0100 Subject: [PATCH 1711/2459] [[ Prebuilt ]] Add thirdparty prebuilt project file Add gyp target to link prebuilt thirdparty libraries into compiled executables --- engine/kernel-development.gyp | 2 +- engine/kernel-installer.gyp | 2 +- engine/kernel-server.gyp | 6 +- engine/kernel.gyp | 17 +- libfoundation/libfoundation.gyp | 2 +- libgraphics/libgraphics.gyp | 17 +- prebuilt/fetch-libraries.sh | 12 +- prebuilt/thirdparty.gyp | 316 ++++++++++++++++++++++++++++++++ revdb/revdb.gyp | 4 +- revxml/revxml.gyp | 4 +- 10 files changed, 333 insertions(+), 49 deletions(-) create mode 100644 prebuilt/thirdparty.gyp diff --git a/engine/kernel-development.gyp b/engine/kernel-development.gyp index 8bdf8b41e55..36eda715249 100644 --- a/engine/kernel-development.gyp +++ b/engine/kernel-development.gyp @@ -50,7 +50,7 @@ 'kernel.gyp:kernel', '../thirdparty/libopenssl/libopenssl.gyp:libopenssl_stubs', - '../thirdparty/libz/libz.gyp:libz', + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', ], 'sources': diff --git a/engine/kernel-installer.gyp b/engine/kernel-installer.gyp index 7fa5398014c..6d70e9e8e84 100644 --- a/engine/kernel-installer.gyp +++ b/engine/kernel-installer.gyp @@ -38,7 +38,7 @@ [ 'kernel.gyp:kernel', - '../thirdparty/libz/libz.gyp:libz', + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', ], 'includes': diff --git a/engine/kernel-server.gyp b/engine/kernel-server.gyp index 7749284bfaf..6c6d56a513b 100644 --- a/engine/kernel-server.gyp +++ b/engine/kernel-server.gyp @@ -57,11 +57,7 @@ '../prebuilt/libcurl.gyp:libcurl', '../prebuilt/libopenssl.gyp:libopenssl', - '../thirdparty/libgif/libgif.gyp:libgif', - '../thirdparty/libjpeg/libjpeg.gyp:libjpeg', - '../thirdparty/libpcre/libpcre.gyp:libpcre', - '../thirdparty/libpng/libpng.gyp:libpng', - '../thirdparty/libz/libz.gyp:libz', + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', 'engine-common.gyp:quicktime_stubs', diff --git a/engine/kernel.gyp b/engine/kernel.gyp index 833edc2a28c..d6f8965e61f 100644 --- a/engine/kernel.gyp +++ b/engine/kernel.gyp @@ -20,15 +20,12 @@ '../libbrowser/libbrowser.gyp:libbrowser', - '../thirdparty/libgif/libgif.gyp:libgif', - '../thirdparty/libjpeg/libjpeg.gyp:libjpeg', '../thirdparty/libopenssl/libopenssl.gyp:libopenssl_stubs', - '../thirdparty/libpcre/libpcre.gyp:libpcre', - '../thirdparty/libpng/libpng.gyp:libpng', - '../thirdparty/libz/libz.gyp:libz', '../prebuilt/libopenssl.gyp:libopenssl_headers', + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', + 'engine-common.gyp:encode_version', 'engine-common.gyp:quicktime_stubs', ], @@ -68,12 +65,6 @@ [ 'OS == "android"', { - 'dependencies': - [ - '../thirdparty/libfreetype/libfreetype.gyp:libfreetype', - '../thirdparty/libskia/libskia.gyp:libskia', - ], - 'sources!': [ # Not yet supported on Android @@ -100,10 +91,6 @@ [ 'OS == "emscripten"', { - 'dependencies': - [ - '../thirdparty/libskia/libskia.gyp:libskia', - ], 'sources': [ '<@(engine_minizip_source_files)', diff --git a/libfoundation/libfoundation.gyp b/libfoundation/libfoundation.gyp index c8dfb8013f1..09ba89362ef 100644 --- a/libfoundation/libfoundation.gyp +++ b/libfoundation/libfoundation.gyp @@ -45,10 +45,10 @@ 'dependencies': [ + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', '../prebuilt/libicu.gyp:libicu', '../prebuilt/libicu.gyp:encode_minimal_icu_data', '../thirdparty/libffi/libffi.gyp:libffi', - '../thirdparty/libz/libz.gyp:libz', ], 'include_dirs': diff --git a/libgraphics/libgraphics.gyp b/libgraphics/libgraphics.gyp index 620a8482def..9876e5e3d3e 100644 --- a/libgraphics/libgraphics.gyp +++ b/libgraphics/libgraphics.gyp @@ -14,8 +14,8 @@ 'dependencies': [ + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', '../libfoundation/libfoundation.gyp:libFoundation', - '../thirdparty/libskia/libskia.gyp:libskia', ], 'include_dirs': @@ -48,21 +48,6 @@ 'src/drawing.cpp', ], - 'conditions': - [ - [ - 'OS in ("emscripten", "android")', - { - 'dependencies': - [ - '../prebuilt/libicu.gyp:libicu', - '../thirdparty/libfreetype/libfreetype.gyp:libfreetype', - '../thirdparty/libharfbuzz/libharfbuzz.gyp:libharfbuzz', - ], - }, - ], - ], - 'target_conditions': [ [ diff --git a/prebuilt/fetch-libraries.sh b/prebuilt/fetch-libraries.sh index f075eb6fa84..7aa472d59de 100755 --- a/prebuilt/fetch-libraries.sh +++ b/prebuilt/fetch-libraries.sh @@ -8,12 +8,12 @@ ARCHS_ios=( Universal ) ARCHS_win32=( x86 x86_64 ) ARCHS_linux=( i386 x86_64 ) ARCHS_emscripten=( js ) -LIBS_android=( OpenSSL ICU ) -LIBS_mac=( OpenSSL ICU ) -LIBS_ios=( OpenSSL ICU ) -LIBS_win32=( OpenSSL Curl ICU CEF ) -LIBS_linux=( OpenSSL Curl ICU CEF ) -LIBS_emscripten=( ICU ) +LIBS_android=( Thirdparty OpenSSL ICU ) +LIBS_mac=( Thirdparty OpenSSL ICU ) +LIBS_ios=( Thirdparty OpenSSL ICU ) +LIBS_win32=( Thirdparty OpenSSL Curl ICU CEF ) +LIBS_linux=( Thirdparty OpenSSL Curl ICU CEF ) +LIBS_emscripten=( Thirdparty ICU ) SUBPLATFORMS_ios=(iPhoneSimulator8.2 iPhoneSimulator9.2 iPhoneSimulator10.2 iPhoneSimulator11.2 iPhoneSimulator12.1 iPhoneOS9.2 iPhoneOS10.2 iPhoneOS11.2 iPhoneOS12.1) SUBPLATFORMS_win32=(v141_static_debug v141_static_release) diff --git a/prebuilt/thirdparty.gyp b/prebuilt/thirdparty.gyp new file mode 100644 index 00000000000..c5715296bcb --- /dev/null +++ b/prebuilt/thirdparty.gyp @@ -0,0 +1,316 @@ +{ + 'includes': + [ + '../common.gypi', + ], + + 'targets': + [ + { + 'target_name': 'thirdparty_prebuilt', + 'type': 'none', + + 'toolsets': ['host','target'], + + 'dependencies': + [ + 'fetch.gyp:fetch', + ], + + 'direct_dependent_settings': + { + 'defines': + [ + 'PCRE_STATIC=1', + ], + + 'include_dirs': + [ + '../thirdparty/libexpat', + '../thirdparty/libexpat/lib', + '../thirdparty/libgif/include', + '../thirdparty/libharfbuzz/src', + '../thirdparty/libjpeg/include', + '../thirdparty/libpcre/include', + '../thirdparty/libpng/include', + '../thirdparty/libz/include', + '../thirdparty/libskia/include/config', + '../thirdparty/libskia/include/core', + '../thirdparty/libskia/include/device', + '../thirdparty/libskia/include/effects', + '../thirdparty/libskia/include/images', + '../thirdparty/libskia/include/pathops', + '../thirdparty/libskia/include/pdf', + '../thirdparty/libskia/include/pipe', + '../thirdparty/libskia/include/ports', + '../thirdparty/libskia/include/svg', + '../thirdparty/libskia/include/text', + '../thirdparty/libskia/include/utils', + # Needed for some legacy methods + '../thirdparty/libskia/src/core', + # Needed for directwrite text rendering on Windows + '../thirdparty/libskia/src/ports', + '../thirdparty/libskia/include/private', + '../thirdparty/libskia/src/utils/win', + + '../thirdparty/libfreetype/include', + ], + }, + + 'all_dependent_settings': + { + 'defines': + [ + # Disable Skia debugging + 'SK_RELEASE', + + # We use deprecated Skia features + 'SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT', + 'SK_SUPPORT_LEGACY_GETTOPDEVICE', + 'SK_SUPPORT_LEGACY_ACCESSBITMAP', + 'SK_SUPPORT_LEGACY_CLIP_REGIONOPS', + 'SK_SUPPORT_LEGACY_GETDEVICE', + + # Disable GPU support + 'SK_SUPPORT_GPU=0', + ], + }, + + 'link_settings': + { + 'target_conditions': + [ + [ + 'toolset_os == "mac"', + { + 'conditions': + [ + [ + 'GENERATOR == "xcode"', + { + 'libraries': + [ + 'lib/mac/libpcre.a', + # libskia depends on libgif, libjpeg, libpng, libz + 'lib/mac/libskia.a', + 'lib/mac/libskia_opt_none.a', + 'lib/mac/libskia_opt_arm.a', + 'lib/mac/libskia_opt_sse2.a', + 'lib/mac/libskia_opt_sse3.a', + 'lib/mac/libskia_opt_sse41.a', + 'lib/mac/libskia_opt_sse42.a', + 'lib/mac/libskia_opt_avx.a', + 'lib/mac/libskia_opt_hsw.a', + 'lib/mac/libgif.a', + 'lib/mac/libjpeg.a', + # libpng depends on libz + 'lib/mac/libpng.a', + 'lib/mac/libz.a', + ], + }, + { + 'library_dirs': + [ + 'lib/mac', + ], + + 'libraries': + [ + '-lpcre', + # libskia depends on libgif, libjpeg, libpng, libz + '-lskia', + '-lskia_opt_none', + '-lskia_opt_arm', + '-lskia_opt_sse2', + '-lskia_opt_sse3', + '-lskia_opt_sse41', + '-lskia_opt_sse42', + '-lskia_opt_avx', + '-lskia_opt_hsw', + '-lgif', + '-ljpeg', + # libpng depends on libz + '-lpng', + '-lz', + ], + }, + ], + ], + }, + ], + [ + 'toolset_os == "ios"', + { + 'libraries': + [ + 'lib/ios/$(SDK_NAME)/libpcre.a', + 'lib/ios/$(SDK_NAME)/libskia.a', + # libskia depends on libgif, libjpeg, libpng, libz + 'lib/ios/$(SDK_NAME)/libskia.a', + 'lib/ios/$(SDK_NAME)/libskia_opt_none.a', + 'lib/ios/$(SDK_NAME)/libskia_opt_arm.a', + 'lib/ios/$(SDK_NAME)/libskia_opt_sse2.a', + 'lib/ios/$(SDK_NAME)/libskia_opt_sse3.a', + 'lib/ios/$(SDK_NAME)/libskia_opt_sse41.a', + 'lib/ios/$(SDK_NAME)/libskia_opt_sse42.a', + 'lib/ios/$(SDK_NAME)/libskia_opt_avx.a', + 'lib/ios/$(SDK_NAME)/libskia_opt_hsw.a', + 'lib/ios/$(SDK_NAME)/libgif.a', + 'lib/ios/$(SDK_NAME)/libjpeg.a', + # libpng depends on libz + 'lib/ios/$(SDK_NAME)/libpng.a', + 'lib/ios/$(SDK_NAME)/libz.a', + ], + }, + ], + [ + 'toolset_os == "linux"', + { + # Gyp doesn't seem to handle non-absolute paths here properly... + 'library_dirs': + [ + 'lib/linux/>(toolset_arch)', + ], + + 'libraries': + [ + '-lpcre', + # libskia depends on libgif, libjpeg, libpng, libz + '-lskia', + '-lskia_opt_none', + '-lskia_opt_arm', + '-lskia_opt_sse2', + '-lskia_opt_sse3', + '-lskia_opt_sse41', + '-lskia_opt_sse42', + '-lskia_opt_avx', + '-lskia_opt_hsw', + '-lgif', + '-ljpeg', + # libpng depends on libz + '-lpng', + '-lz', + + #'-lGL', + '-lfreetype', + '-lfontconfig', + ], + }, + ], + [ + 'toolset_os == "android"', + { + # Gyp doesn't seem to handle non-absolute paths here properly... + 'conditions': + [ + [ + 'OS == "android"', + { + 'library_dirs': + [ + 'lib/android/<(target_arch)/<(android_subplatform)', + ], + + 'libraries': + [ + # *ANDROID* libharfbuzz depends on libicu + '-lharfbuzz', + '-lpcre', + # *ANDROID* libskia depends on libexpat, libfreetype + # libskia depends on libgif, libjpeg, libpng, libz + '-lskia', + '-lskia_opt_none', + '-lskia_opt_arm', + '-lskia_opt_sse2', + '-lskia_opt_sse3', + '-lskia_opt_sse41', + '-lskia_opt_sse42', + '-lskia_opt_avx', + '-lskia_opt_hsw', + '-lexpat', + # libfreetype depends on libz + '-lfreetype', + '-lgif', + '-ljpeg', + # libpng depends on libz + '-lpng', + '-lz', + + #'-lEGL', + #'-lGLESv2', + ], + }, + ], + ], + }, + ], + [ + 'toolset_os == "win"', + { + 'library_dirs': + [ + 'unpacked/Thirdparty/<(uniform_arch)-win32-$(PlatformToolset)_static_$(ConfigurationName)/lib', + ], + + 'libraries': + [ + '-llibpcre', + # libskia depends on libgif, libjpeg, libpng, libz + '-llibskia', + '-llibskia_opt_none', + '-llibskia_opt_arm', + '-llibskia_opt_sse2', + '-llibskia_opt_sse3', + '-llibskia_opt_sse41', + '-llibskia_opt_sse42', + '-llibskia_opt_avx', + '-llibskia_opt_hsw', + '-llibgif', + '-llibjpeg', + # libpng depends on libz + '-llibpng', + '-llibz', + + #'-lOpenGL32.lib' + ], + }, + ], + [ + 'OS == "emscripten"', + { + 'library_dirs': + [ + 'lib/emscripten/js', + ], + + 'libraries': + [ + # *EMSCRIPTEN* libharfbuzz depends on libicu + '-lharfbuzz', + '-lpcre', + # *EMSCRIPTEN* libskia depends on libfreetype + # libskia depends on libgif, libjpeg, libpng, libz + '-lskia', + '-lskia_opt_none', + '-lskia_opt_arm', + '-lskia_opt_sse2', + '-lskia_opt_sse3', + '-lskia_opt_sse41', + '-lskia_opt_sse42', + '-lskia_opt_avx', + '-lskia_opt_hsw', + # libfreetype depends on libz + '-lfreetype', + '-lgif', + '-ljpeg', + # libpng depends on libz + '-lpng', + '-lz', + ], + }, + ], + ], + }, + }, + ], +} diff --git a/revdb/revdb.gyp b/revdb/revdb.gyp index 65a06f7726a..1b061b302a0 100644 --- a/revdb/revdb.gyp +++ b/revdb/revdb.gyp @@ -100,7 +100,7 @@ '../libexternal/libexternal.gyp:libExternal', '../thirdparty/libmysql/libmysql.gyp:libmysql', '../thirdparty/libopenssl/libopenssl.gyp:libopenssl_stubs', - '../thirdparty/libz/libz.gyp:libz', + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', ], 'include_dirs': @@ -159,7 +159,7 @@ '../libexternal/libexternal.gyp:libExternal', '../thirdparty/libmysql/libmysql.gyp:libmysql', '../thirdparty/libopenssl/libopenssl.gyp:libopenssl_stubs', - '../thirdparty/libz/libz.gyp:libz', + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', ], 'include_dirs': diff --git a/revxml/revxml.gyp b/revxml/revxml.gyp index 00fda8d9b04..b0ae5743f2f 100644 --- a/revxml/revxml.gyp +++ b/revxml/revxml.gyp @@ -32,7 +32,7 @@ '../libexternal/libexternal.gyp:libExternal-symbol-exports', '../thirdparty/libxml/libxml.gyp:libxml', '../thirdparty/libxslt/libxslt.gyp:libxslt', - '../thirdparty/libz/libz.gyp:libz', + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', ], 'include_dirs': @@ -82,7 +82,7 @@ '../libexternal/libexternal.gyp:libExternal-symbol-exports', '../thirdparty/libxml/libxml.gyp:libxml', '../thirdparty/libxslt/libxslt.gyp:libxslt', - '../thirdparty/libz/libz.gyp:libz', + '../prebuilt/thirdparty.gyp:thirdparty_prebuilt', ], 'include_dirs': From 1d45a3b8849acd539380f45505962d57baa0bf2c Mon Sep 17 00:00:00 2001 From: Ian Macphail Date: Tue, 30 Apr 2019 12:13:29 +0100 Subject: [PATCH 1712/2459] [[ Prebuilt ]] Resolve issue of libharfbuzz depending on libicu prebuilt This patch modifies the targets of libicu to split the linking & includes settings off from the fetch target. This allows libharfbuzz to be built during the prebuilt build step as it no longer attempts to fetch the prebuilts before they have been compiled and packaged. --- prebuilt/libicu.gyp | 22 ++++++++++++++++++---- thirdparty | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/prebuilt/libicu.gyp b/prebuilt/libicu.gyp index 1dc9f96c848..2b52c648298 100755 --- a/prebuilt/libicu.gyp +++ b/prebuilt/libicu.gyp @@ -61,13 +61,21 @@ { 'target_name': 'libicu', 'type': 'none', - - 'toolsets': ['host','target'], - + + 'toolsets': ['host', 'target'], + 'dependencies': [ 'fetch.gyp:fetch', + 'libicu_include', + 'libicu_link', ], + }, + { + 'target_name': 'libicu_include', + 'type': 'none', + + 'toolsets': ['host','target'], # Needs to be all dependents as used by the HarfBuzz public headers 'all_dependent_settings': @@ -100,7 +108,13 @@ ], ], }, - + }, + { + 'target_name': 'libicu_link', + 'type': 'none', + + 'toolsets': ['host','target'], + 'link_settings': { 'target_conditions': diff --git a/thirdparty b/thirdparty index abd69c083e4..da340667339 160000 --- a/thirdparty +++ b/thirdparty @@ -1 +1 @@ -Subproject commit abd69c083e4e8b0fa4f8fa670c296d1c226373b5 +Subproject commit da3406673397272f65f4e19d0c8c75a3839ab238 From 04be442f8dd922c58acaca32ae6fb79bc37f0aee Mon Sep 17 00:00:00 2001 From: Monte Goulding Date: Wed, 8 May 2019 11:08:24 +1000 Subject: [PATCH 1713/2459] Update ide submodule pointer --- ide | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ide b/ide index fbb41598705..3f402c7c55e 160000 --- a/ide +++ b/ide @@ -1 +1 @@ -Subproject commit fbb41598705d53f64e4b4398433a17570cefaeb4 +Subproject commit 3f402c7c55e967bf9f8ec34a662b5c038dd8bece From f8667cff0c69e66f62a86e984329404db4c4e57d Mon Sep 17 00:00:00 2001 From: Ali Lloyd Date: Wed, 8 May 2019 10:16:34 +0100 Subject: [PATCH 1714/2459] [[ Math ]] Clarify new math op error behavior in documentation This patch adds a reference to a new math operation glossary entry for each math operation in the dictionary, in which the rules for determining what execution error is thrown (if any) are described. --- docs/dictionary/command/add.lcdoc | 6 +++- docs/dictionary/command/divide.lcdoc | 6 ++-- docs/dictionary/command/multiply.lcdoc | 8 +++-- docs/dictionary/command/subtract.lcdoc | 6 +++- docs/dictionary/function/acos.lcdoc | 5 ++- docs/dictionary/function/annuity.lcdoc | 6 +++- docs/dictionary/function/asin.lcdoc | 5 ++- docs/dictionary/function/atan.lcdoc | 8 +++-- docs/dictionary/function/atan2.lcdoc | 6 +++- docs/dictionary/function/average.lcdoc | 6 +++- .../function/averageDeviation.lcdoc | 6 +++- docs/dictionary/function/compound.lcdoc | 6 +++- docs/dictionary/function/exp.lcdoc | 6 +++- docs/dictionary/function/exp1.lcdoc | 7 ++++- docs/dictionary/function/exp10.lcdoc | 6 +++- docs/dictionary/function/exp2.lcdoc | 7 ++++- docs/dictionary/function/geometricMean.lcdoc | 8 +++-- docs/dictionary/function/harmonicMean.lcdoc | 8 +++-- docs/dictionary/function/ln.lcdoc | 5 ++- docs/dictionary/function/ln1.lcdoc | 7 ++++- docs/dictionary/function/log10.lcdoc | 6 +++- docs/dictionary/function/log2.lcdoc | 6 +++- docs/dictionary/function/median.lcdoc | 6 +++- .../populationStandardDeviation.lcdoc | 6 +++- .../function/populationVariance.lcdoc | 6 +++- docs/dictionary/function/sqrt.lcdoc | 6 +++- .../function/standardDeviation.lcdoc | 6 +++- docs/dictionary/function/sum.lcdoc | 6 +++- docs/dictionary/function/variance.lcdoc | 6 +++- docs/dictionary/operator/asterisk.lcdoc | 6 +++- docs/dictionary/operator/caret.lcdoc | 6 +++- docs/dictionary/operator/div.lcdoc | 6 ++-- docs/dictionary/operator/mod.lcdoc | 6 ++-- docs/dictionary/operator/plus.lcdoc | 6 +++- docs/dictionary/operator/slash.lcdoc | 11 ++++--- docs/dictionary/operator/wrap.lcdoc | 6 +++- docs/glossary/m/math-operation.lcdoc | 31 +++++++++++++++++++ 37 files changed, 213 insertions(+), 47 deletions(-) create mode 100644 docs/glossary/m/math-operation.lcdoc diff --git a/docs/dictionary/command/add.lcdoc b/docs/dictionary/command/add.lcdoc index 30513143d3f..43375fbfc0d 100644 --- a/docs/dictionary/command/add.lcdoc +++ b/docs/dictionary/command/add.lcdoc @@ -80,12 +80,16 @@ empty, the treats its contents as zero. If is a or