# ACF Plugin v1.7.8.4 Release Notes

Welcome to the latest release of the ACF Plugin, version 1.7.8.4. For the latest updates, refer to the version history.

## Key Improvements

- First version of Excel_PlaceChart implementation to place charts in Excel documents produced by the plugin. See documentation on https://horneks.no for details.

- Compiler now runs two-pass to allow declarations inside conditional structures. In the first pass, it collects all declarations, and initializes variables. In the second pass, it ignores declarations.

  - Variables declared inside loop structures are cleared for each iteration in the loop.

  - Even when we collect declarations in the first pass, they still need to be declared before use. Variables declared after they are used will generate an compiler error: Variable used before declaration.

  - Variables declared inside the body of conditional or loop structures, does not go out of scope before the function ends.

  - Declarations with assignments (i.e. `int a=5, b=6;` : The declaration is collected in the pre-parser stage and initialized to zero value in the top of the function, while the main parser stage assign the value where it is defined. Like:

        if ( false ) then    int a=5, b=6; end if

    In this construct, the variables are declared, but will never get their value as above.

  - All local variables are initialized to zero or empty value in the top of the functions.

  - Functions compiled with this version, are binary compatible with earlier versions, as long as features used are implemented in those versions. I.e. the runtime of 1.7.6.5 can still run code compiled with 1.7.7.2.

- Built-in translation functions for multilingual solutions.

- Creating Excel Spreadsheets in native XLSX format with the new Excel functions makes this task easier.

- Container variable type: compatible with FileMaker's Container field type.

- Included Macro definitions and invocation in the ACF language

## MacOS compatibility:

- Intel Mac: From MacOS 10.13 High Sierra (New Drag and drop requires 10.14)

- Arm (Silicon) Mac (M1, M2...) : From macOS 12.3 Monterey

- All architectures can run up to the current macOS 15 Sequoia and Tahoe

## FileMaker compatibility

- Tested on FileMaker Pro versions 17, 18, 19, 20, 21 and 22 (2025)

## Windows Compatibility:

- 64-bit Intel PC's with Windows 10 and Windows 11

- All 64-bit FileMaker versions.

## Version History

### 1.7.8.4

- BugFix: The plugin functions dsPD_Text2Hex and dsPD_Text2HexInv had a memory allocation issue that sometimes caused FileMaker to crash. The issue is Fixed.

### 1.7.8.3

- Linux version in Alpha

- New functions : Min_(mixed parameter list) and Max_(mixed parameter list). They returns the less or greatest value from the list. It can be discrete variables or constants of any type, and arrays. The return type is determined by the types of your parameters: Int, long or float. Strings is treated as Float, as they can contain float numbers. The parameters does not need to be the same type. The functions also works on TIME, DATE or TIMESTAMP variables or constants (as they contain unix-timestamps).

- BugFix: Functions returning a container, and used the FunctionID to make ACFU_Function_name - when called using the ACFU... it didn't return the container, while ACF_Run... did. Fixed.

- New Constants: `isLinux` , `isServer` - in additon to the `isMac`, `isWindows` that we had before.

- New System variables: `appVersion` returns the FileMaker application version, or server. Also `plugginVersion` that returns the version string for the plugin as dot-separated version number.

- NOTE: If you are using any of those new functions, variables or constants, it is required that all clients of your database update to this version. Otherwise, functions might fail due to lack of runtime support for the new functions.

- NOTE: Also install the new ACF-Compiler for syntax check from your IDE, as this have the new functions defined.

- Improved server-side functions for `Documents_directory()` to retun the path for the documents directory on the server, if executed from server. Also the same for `temporary_directory()`

- The built-in bootstrap ACF-library has been updated. The `GetFilenameFromPath(path)` , `GetDirectoriesFromPath`, `GetExtentionFromPath` has been improved to correctly handle all types of paths/plattforms. The functions that involves UI operations has been made server-safe, either returning a default value or empty if used on server.

- BugFix: In the function Excel_SetRowHeight - Sometimes thrown an error exception - Allocated space in the row-heigh list using a wrong variable. Errnously reported to invalid or negative row index. Fixed.

### 1.7.8.2

- Excel Chart implementation: Full support for "axes" in the JSON configuration object.

- Min/Max values in "axes": They are now rounded to two significant digits. Min values are rounded down, Max values are rounded up. This gives round figures on the axes.

- Fixed bug in JSON function: Key/Value pairs where the value is an array failed (sometimes). Bug fixed.

### 1.7.8.1

- First version of `Excel_PlaceChart` function implementation to add charts to Excel spreadsheets produced by the plugin.

- Small fix determining the position of the "INTO" part in SQL statements. It was not recognised if set on its own line and the arrays on the next line. Requirements to have the array list starting on the same line is now lifted. The INTO still need to start on a new line at the end of the SQL statement, to ensure it is not confused with INTO occuring elsewhere in the SQL statement, like field name, literal, etc.

- Date, time and timestamp, when called from a FM calculation, somtimes it did not get the correct value. Workaround was to declare as string and convert after. Now the logic is re-written.

### 1.7.7.4

- New functions for Drag & Drop files from Finder or Email into an area on the layout, to receive FilePaths dragged into it.

  - To start Drag and Drop handler: `Set Variable [$res;ACF_DefineDragAndDrop( $$coords; "DandDcallback";$$JSON_options)]`

  - To Remove the Drag and Drop handler: `Set Variable [$res;ACF_RemoveDragAndDrop( 1)]`

  - The $$Json_options are used to style the and specify what file extensions to accept for the drop. See an example here

### 1.7.7.3

- Parsing Macro defenitions created compiler errors (pre-parsing the macro parameter list). Issue introduced in 1.7.7.2; Fixed in this version.

### 1.7.7.2

- Made a pre-parsing stage in the compiler to collect declarations, to allow declarations inside conditional structures. See text in the top of this document.

- Some minor bugfixes

### 1.7.7.1

- Bugfix "SQL INTO PART" issue introduced in 1.7.7.0. If the INTO part span over several lines, only the first line was used, making mismatch with the number of columns and number of INTO arrays. -- Fixed

- When plugin run as "unlicensed", when the 30 minutes demo period is over, the user gets an dialog and a 2 minutes grace period instead of function throwing an error. This makes the function call still working. The grace period can be extended 5 times, or FileMaker can be restarted for new 30 min demo mode. New license can be bought at https://horneks.no/butikk

### 1.7.7.0

- New: “Configure…” in FileMaker ▸ Preferences ▸ Plug-ins ▸ HORNEKS ACF Plugin Opens a dialog showing license details (licensee, status, expiry, seats, plugin version) and an expandable list of loaded ACF packages with their functions. A bottom toggle switches the displayed prototypes between FM (as used in FileMaker calculations) and ACF (as called from other ACF functions).

- Improved: Timestamp converter — `timestamp(date_value, time_value)` now converts a Date and a Time into a Timestamp value.

### 1.7.6.5

- Update to ACF_RegisterPlugin to save license on local computer, and auto-register at next startup.

### 1.7.6.4

- Improved constant syntax - Implemented Scientific Long types: 1E6, instead of 1000000 or 10^6.

- Windows release 1.7.6.4 (Separate download)

### 1.7.6.3

- Bugfix: Boolean expression `>=` with mixed types did not work properly. The other expressions were OK. For the same type, it worked properly. For example, `if (intvar >= 100)` is OK, while `if (longvar >= 100)` fails.

### 1.7.6.2

- The plugin can now load translation files in both .po format and .mo format. The .mo format is a compiled language file, and the loading from the container is several times as fast.

### 1.7.6.1

- Added the same plugin functions as presented in 1.7.6.0, also in the ACF language. Both FM calculations and ACF functions can now use the new multilingual concept. Also released a new ACF-compiler to use with SublimeText.

### 1.7.6.0 - Combined release with DDR-parser 1.2.0

- DDRparser 1.2.0 adds automatic extraction of `_("…")` strings and generates a standard `messages.pot` under `…/TranslationFiles/`. ACF-Plugin 1.7.6.0 adds runtime translation functions:

  - `_( text {; arg…} )`, `_n( singular ; plural ; count {; arg…} )`

  - `ACF_Load_TranslationPO`, `ACF_Clear_Translation`, `ACF_UpdatePOT` Together they deliver a fast, professional i18n workflow for FileMaker: readable source, translator-friendly files, instant runtime results, and a one-click way to capture new strings into the POT.

### 1.7.5.6

- HTTPS certificate fix for Apple Silicon: Fixed an issue where HTTPS calls on native Apple Silicon Macs could fail with the error: `SSL peer certificate or SSH remote key was not OK`

  Cause: When the plugin is compiled with OpenSSL, it requires a CA certificate bundle to validate HTTPS connections. Unlike Rosetta/Intel mode (which may automatically locate a CA bundle), native Apple Silicon builds don’t automatically locate system-trusted certificates.

  Fix: The latest cacert.pem is embedded in the plugin and used by the curl library within the plugin.

### 1.7.5.5

- Improved functions to convert between string timestamps and timestamps, accepting more default formats, like locale format, SQL format JSON format. The same is also enhanced for date types.

- Added function "HTTP_PATCH", same parameters as HTTP_POST, just doing PATCH metohod instead. Used by some API's when updating existing data.

### 1.7.5.4

- Added function `ExtractCertChainBase64(cert, pass);`- returns a string array of certificates in Base64 format. Can be used in JWT to put an "x5c" tag in the header, containing certificates used for signing.

      xxxxxxxxxxheader ["x5c"] = ExtractCertChainBase64(cert, pass);

- modified the "now()" function to also accept one optional parameter: now(time_zone). Now(0) returns the timestamp in Zulu time. A construct like `long(now(0))` returns a Unix timestamp in Zulu time. While `long(now())` returns a Unix Timestamp in local time. The timezone parameter can be an integer or a float. This allows for a minute resolution. 5.5 will be 5 hours and 30 minutes.

### 1.7.5.3

- Added functions for signing with a certificate or with a secret:

  - SignWithCert ( string data-to-sign, container|string certificate, string|int return-format, string certificate-password) -> signature

  - SignWithSecret ( string data-to-sign, string secret, string|int returnFormat) -> signature

  - The function accepts both PKCS#12 and PEM format - Can be a container with the cert, a path to a cert or a PEM cert in a string variable. Return format can be "base64" or "base64url", or the option numbers 1 or 3, respectively. 3 = base64url.

  - The functions can be used to sign anything, for example, auth tokens, email content, documents, etc.

### 1.7.5.2

- Bug Fix: String literals enclosed in single apostrophes (`'...'`) that spanned multiple lines did not correctly update the source line counter. This led to compiler error messages referencing incorrect line numbers. This has now been fixed.

- Bug Fix: The `copy_file` function was intended to handle both files and directories. However, directory support was unintentionally left out during the transition from Objective-C to Boost libraries, which was done to make the source compatible with Windows. This has now been fixed.

- Improved Type Handling in Array Initialisers: Removed unnecessary warnings when initialising arrays with compatible numeric types. For example:

      xxxxxxxxxxarray float abc = {1, 2.5, 3};  // Previously gave warnings due to mixed int/float types

- New Built-in Functions:

  - `Atan2(y, x)` — Computes the angle between the x-axis and the point `(x, y)` (returns radians).

  - `URL_Encode(string)` — Percent-encodes a string for safe use in URLs.

  - `URL_Decode(string)` — Decodes a percent-encoded URL string.

- Sublime Text Auto-Completion Updated: Updated the completions list to reflect new functions and syntax improvements.

- New compatible version of the ACF compiler 1.7.5.2: separate download.

### 1.7.5.1

- Bugfix: When a `catch` block is invoked in a `try/catch/end try` structure, it incorrectly reset the local variable stack pointer to its initial value instead of preserving the current state. This could cause subsequent function calls to overwrite local variables with parameter values. A rare and subtle bug that went unnoticed since the `try/catch` mechanism was introduced in version 1.7.0.1.

### 1.7.5.0

- New Macro feature in the ACF language. Read a separate article about the concept in the manual.

  - Define local parameterised macros inside functions.

  - Invoke the Macros in a macro call style, where the macro body will be inserted into the code.

### 1.7.4.3

- The Excel style option: "Alignment", and the value: "Middle" did not work. The XML output to the workbook stylesheet used "middle" as vertical alignment, but should use "centred". Fixed.

- The command Excel_SetRowHeights has got a new variant: `Excel_SetRowHeights ( SheetID, FromRow, ToRow, Height);`

- Fixed bug in `Excel_SetRowHeights` variant with array. The command failed on start-row different from 1.

- Better error handling on conversion from date to string. The function does not throw an exception on invalid dates but returns 1.1.1970 as the string. This is to avoid erroneous data causing reports to be non-working.

### 1.7.4.2

- Bugfix: the function ABS rounded floating point numbers to whole numbers. The function used the C++ function "abs" which is not defined for floating numbers. Instead, when floating numbers it now uses "fabs". Fixed.

- Bugfix: Accessing JSON boolean values did not return any value. Like `{"success": true}` It now returns the string type "true" or "false." The bug made it difficult to evaluate the result of an operation that produces a JSON object containing such elements.

### 1.7.4.1

- New command: Excel_SheetProtection ( sheetID, new_password {, old_password {, spin_count}})

  - for unprotected sheets, no need to supply old_password (optional blank)

  - new password set to blank clears the sheet protection

  - The spin count is default 100 000;

  - Compatible with Excel hashing algorithm. Applying sheet protection can be unprotected in Excel specifying passwords.

- New Command Excel_DefineTable - See example: (This will be elaborated on in the documentation soon.) Ref and autofilterref

      xxxxxxxxxx// Define a table for the data...    Excel_DefineTable (s, JSON(      "name", "CustomTable",      "ref", Excel_Sheetaddress (3, 1, 20, 6),      "autoFilterRef", Excel_Sheetaddress (3, 1, 19, 6),      "filterButtons", JSONarray(1,1,1,0,0,0), // if not array, but single 1 or 0, means all on or all off.       "style", "TableStyleMedium2",      "options", JSONarray(        "totalsRowShown","showFirstColumn", "showRowStripes"      ),      "columnNames", JSONarray(        "Name","Position","Office","Age","Startdate","Salary"      ),      "totalsRowFunctions", JSONarray(        "count","", "", "average", "", "sum"      ),       "totalsRowStyle", "Num" // pick the number format from this regular style    ));

- Some minor debugging.

### 1.7.4.0

- New datatype: Container - Compatible with FileMaker's Container field type. You can declare variables or parameters as type `Container`- Functions can also return this type, or use it as a parameter in certain functions.

- New commands / Functions:

  - int ImgID = Excel_AddImage (string path | Container );

  - Excel_PlaceImage ( int SheetID, int ImgID, row, column, int/float width, int/float height, int/float offsetX, int float offsetY);

  - string content = Excel_ContainerGetData ( Container);

  - string FileName = Excel_ContainerGetFileName ( Container );

  - Container_LoadFile ( Container, string Path);

  - string Size = get_imagesize(String path | Container );

  - Excel_SetGridLines ( int sheetID, bool on ) // Fslse is off

  - Excel_SetRowHeights ( int sheetID, int fromRow, array float heights);

  - Excel_SetRowHeights ( int sheetID, int Row, float height);

### 1.7.3.9

- Added Date, Time and Timestamp literals to the ACF language for hard-coded values. The literals have these formats:

      xxxxxxxxxx!2025-03-12!    // Date literal 12 march 2025!12:34:29!      // Time literal!2025-03-12T14:30:00!   // Timestamp literal.

- Added Date, Time and Timestamp parameterized converters in addition to the string converters we had before.

  Prototypes:

      xxxxxxxxxxdate ( int mnd, int day, int year ) => Datetime ( int hour, int minutes{, int seconds}) => Timetimestamp (int mnd, int day, int year, int hour, int minutes{, int seconds}) => Timestamp

  See example:

      ​xdate dx = date(3, 25, 2025);time tx = time(22, 45,0); time t1x = time(now()); timestamp tsx = timestamp(3,25,2025,10,30,0); print format ("\nDate: %s, time: %s, now: %s, TimeStamp:%s\n", string(dx), string(tx), string(t1x), string(tsx));
      Output: Date: 25/03/2025, time: 22:45:00, now: 13:30:06, TimeStamp:25/03/2025 10:30:00

- Corrected bug: When opening a workbook with formulas referencing other sheets, inserting or removing rows/columns did not correctly update the references from other sheets in the workbook.

- Corrected bug: When inserting or deleting rows/columns in workbooks edited by Excel, Excel grouped formulas into shared formulas. The references section was not updated correctly for those.

### 1.7.3.8

- Corrected bug in Excel_Open: When opening workbooks containing more than nine sheets, an issue with sheetID sorting made the sheets be parsed in the incorrect order. The names of the tabs and the sheet contents did not correspond.

### 1.7.3.7

- Corrected bug in `Excel_SetColumnWidth` when called for a single column. Returned an exception about invalid sheetID.

- Improved the classification of styles concerning the NumFormaCodes to classify as DATE, TIME, and TIMESTAMP formatting. The complete list of all internal format codes used by Excel is used for classification. Make putting a date value into a cell with a style already configured to format dates, not creating a duplicate style.

#### Windows only and 1.7.3.7

- Same functionality as in the Mac version. This is a comprehensive update to the Windows version.

- I solved some Windows-only issues. Amongst date and time handling, the long datatype on Windows was 32bit, but it is now changed to 64bit to confirm with the Mac version.

- Solved a bug in date handling before 1960 that made the dates one-off when parsing dates, due to an issue with leap-year calculations with negative Unix timestamps. (Unix timestamp is used for the internal date format, and starts 1.1.1970, calculated in seconds). This issue is still present on the Mac version, the fix will be included in the next Mac release.

### 1.7.3.6

- Added new functions to do column insertion and deletion for a range of rows, as opposed to the Excel_InsertColumns and Excel_DeleteColumns that works for the whole spreadsheet.

      xxxxxxxxxx// Excel_ShiftRight ( sheetID, column, numberOfCols, fromRow, toRow); // Excel_ShiftLeft ( sheetID, column, numberOfCols, fromRow, toRow);

- Changed logic for updating formulas to care for interlinking when moving cells around.

- Revised handling of date, time and timestamp values in Excel_setCell and Excel_GetCell

- Automatic creation of styles when setting a date, time or timestamp value based on the style given in the Excel_setCell call, if the style does not have NumFormat to display date, time or timestamp. For example, If the style given is "myNum", having numformat "### ### ###.00", font 13pt Arial, fill color yellow. This style does not show date values well, so the style is duplicated, given name "myNum_Date", numformat is set to empty string, and numFormatCode is set to 14, which is the internal code for date values used by Excel. In this way, the date will be shown correctly, on a yellow background using 13pt Arial font. All this happens when using "Excel_SetCell", and using a date variable for its value.

- Corrected a crashing bug in the plugin. Enforced additional checks for array bounds and improved memory handling.

### 1.7.3.5

- Added new functions for manipulating Rows and Columns:

      xxxxxxxxxx// Default in number of row/column=1, insertabove=false, insertleft=false// Excel_InsertRows (int sheetID, int row {, int numberofrows {, bool insertabove}});// Excel_InsertColumns (int sheetID, int column {, int numberofcols {, bool insertleft}});// Excel_DeleteRows (int sheetID, int fromRow, int toRow ) // Excel_DeleteColumns (int sheetID, fromCol, toCol);

  See the manual page

- Revised the stylesheet operations, especially handling the defaults and using the styles reference count. Making the stylesheet cleaner and has improved compatibility with Excel-generated source documents.

### 1.7.3.4

- Improved compatibility when importing Excel Spreadsheets made in Excel, and saved to a new workbook. Better handling of font, fills, shared formulas, and number formats with internal format numbers defined by Excel.

- When Importing from Excel, as the names defined by us is not stored on the Excel file, the format uses style by index instead. All the styles imported get generic names "Style1, Style2, and so on". If you create a new style, it will try to match with one of the generic styles, and if found a match, this style is renamed instead.

- If opening and saving Excel files several times, the style table might contain styles not used. To get rid of those, a new command Excel_CleanUnusedStyles, has been developed.

### 1.7.3.3

- Improved the style handling for Excel_Open and Excel_SaveAsWorkbook, compatibility with Excel's style-attributes has been improved.

- New functions:

  - `Excel_GetGetStyleOptions ( wb, styleName)` => returning a JSON object describing the style. The object is compatible with `Excel_SetStyleOptions`.

  - `JSONarray(list of array ellements, any type)` => retuning a JSON object containing a JSON array.

- Improved JSON function, array objects.

- General debugging Excel functions.

### 1.7.3.2

- Added function WorbokRef = Excel_Open ( path, accessmode )

  - Accessmode must be "r" in this version. Changes will not be saved.

- The function import an existing excel document. The Excel_GetCell, Excel_GetColumns and Excel_GetRows can be used to extract content from the spreadsheet.

- An "Alpha-state" function called "Excel_SaveAsWorkbook (WorkbookRef, path )" is implemented mainly for debugg purposes, but this will be extended to full support with styles and everything in future release. The command export imported content to another spreadsheet.

### 1.7.3.1

- Added functions:

  - Excel_SetConditionalFormatting (sheetID, JSON config object)

  - Excel_Liststyles (WorkBook ID) => array string

  - Excel_mergeCells ( SheetID, row, column, rowSpan, colSpan)

  - Excel_GetCell (SheetID, row, column) => String

  - Excel_GetColumns ( Sheet_ID, row, FromCol, ToCol ) => array string

  - Excel_GetRows ( Sheet_ID, col, FromRow, ToRow ) => array string

  - excel_sheetaddress (row, column {, toRow, toColumn}) => string (i.e. A1:B6)

### 1.7.3.0

- Mac Beta of the new XLSX functions for creating Excel spreadsheets. Documentation is under way, follow our web-site for documentation.

### 1.7.2.4b

- Windows release only: Changed principle for SystemCommand to avoid a black window-command-prompt flashing up while executing the command.

### 1.7.2.4

- Added 3 more access modes for `open(<path>, <access mode>)`

  - rb - open binary file for read access. `read` only.

  - wb - open binary file for write access. `write` only

  - ab - open binary file for append access. `write` only.

  - r, w, wa is for text-based access modes, support both `read`, `write`, `readln`, `writtln`.

- fixed bug in `HTTP_POST`, not handling binary post data well.

- New commands `HTTP_PUT` and `HTTP_DELETE`, having the same parameters as HTTP_POST, by doing PUT and DELETE requests instead.

### 1.7.2.3

- Added function `SystemCommand` to execute OS commands. The function has two parameters: Command, and directory path to `cd` into before the command is applied.

- Added system variables HTTP_STATUS_CODE and HTTP_HEADERS, which can be used when working with APIs, to verify request went OK (200), and for the headers - it is now possible to extract cookies from the headers to be used with authentication protocols when working with web-services.

### 1.7.2.2

- Corrected issues with global variables that sometimes did not work correctly. Compiler issue.

### 1.7.2.1

- New function `SystemCommand` to execute operating system commands from within the ACF function. Parameters: `SystemCommand ("Command", "/path/to/directory/to/cd/into", environment); environment is default "/bin/bash" if this parameter is omitted. On Windows: "cmd"

### 1.7.2.0

- Fixed issue with JSON and XML implementation where there is no root object, and assignment a single tag.

- Fixed issues with the handling of SQL errors. Returned only "?" as the function result, and an error on the console. However, the error did not give enough insight to be able to debug the issue, especially when using placeholders one could not see the actual SQL statement that gave the error. This is now fixed with a print on the console showing the SQL statement. The function also returns the error instead of the "?".

- Fixed Escaping of SQL literal content. The literals use single apostrophes on each side, and single apostrophes inside the literal was escaped with `\'` - that was not correct for SQL. Correct escaping is two single apostrophes, like: `''` instead. Now fixed. The problem was most experienced when updating or inserting user content in the database.

### 1.7.1.8

- Fixed a compiler bug in the `Power (^)` function, which occurred when operands were non-float values. The incorrect return type caused calculation errors, such as `3*5^0` producing an erroneous result, while `3*5.0^0.0` returned the correct result.

- Added functions:

  - Log10 - Calculate Briggs logarithm of the argument

  - LogLn - Calculate the natural logarithm of the argument.

### 1.7.1.7

- Fixed bug in date and timestamp formatting functions, where on the Windows platform an invalid format string made Filemaker quit unexpectedly. The issue has never been seen on MacOS. The fix causes now a runtime error with a proper message in the function instead.

- Implemented math trigonometric functions `asin`, `acos`, and `atan` .

- Implemented check for curl CA-certificate environment variable `CURL_CA_BUNDLE`. If it exists and points to a certificate file containing the CA certificates, the plugin uses this when executing `HTTP_GET`, `HTTP_POST` and `SEND_EMAIL` functions when using the SSL protocol. This is usually not needed for MacOS, as it has such a file in its default location, but Windows uses a different system for CA certificates that makes downloading and installing such files in the system necessary to speak over the SSL protocol. For some special sites, it might be necessary to use a different CA file, and this is now possible.

- Break inside for-loop didn't pop the step variable, so the console received a warning about something left on the stack at return. Fixed.

### 1.7.1.6

- Fixed a bug in handling SQL placeholders in SQL statements. The ":" prefix of the variable names was also checked inside string literals making it impossible to update or insert literal values containing a colon.

### 1.7.1.5

- Added function "proper" which makes the title case of a given string as a parameter, (in the family of upper/lower functions). This is also a standard FileMaker function, but now also standard in ACF.

### 1.7.1.4

- Bugfix: The ACF functions `upper` and `lower` to convert a string to uppercase and lowercase did not check if the current locale was initialized. This caused a runtime exception if not initialized by other functions. Fixed in this version. Bug introduced in 1.7.1.3 as an optimization task to reduce the overhead of the startup of the ACF functions.

### 1.7.1.3

- Optimized code for ACF_run startup, delayed initialization of locale until needed. Removed 1.3mS from startup code, down to 0.1mS

### 1.7.1.2

- Added native TRIM functions to trim left, right and both sides of a text string. The function trims away white space including CR, LF, TAB, SPACE, and NBSP ( 0xC2 0xA0).

  - `TrimBoth` - Both sides

  - `TrimLeft` and `TrimRight` for either side.

  The functions are highly effective, trims a string in less than 2uS. (Tested with 200 char string and mix of white space on each side in a loop running 10.000 trim operations).

### 1.7.1.1

- In version 1.7.1.1, we've fixed a critical bug causing a 1-byte displacement in the binary output when referencing inter-package functions via the `USE` statement, which previously led to unloadable compiled packages. We've introduced an updated, more reliable method to prevent this issue, rolling out file format version 2 that retains compatibility with the original format. Format version 1 is deprecated and treated as version 0, excluding inter-package link tables. Users are encouraged to update to ensure compatibility and take advantage of these corrections. All packages compiled with 1.7.1.0 must be recompiled with this plugin version.

### 1.7.1.0

- Implemented "USE" statement to allow inter-package function calls. With the "use" statement, you tell the package that it can call functions in the other namespace (another package name). See an example in the article addressing this feature.

- Corrected some minor bugs: The "repeat-until" falsely reported a "left content on stack" warning.

### 1.7.0.20

- Discovered bug in date, time, and timestamp compare construct. Fixed.

- New functions: `open_zip` and `close_zip` functions and included all filesystem operations to work on paths inside ZIP archives, see article about ZIP file support here

### 1.7.0.19

- The functions `left`, `right`, `substr`, and `mid` handle UTF8 strings based on characters instead of bytes. for example `left("bæææ", 3)` returns `bææ` that represents 5 bytes. (each "æ" is two bytes: C3 A6). This change will ensure that multi-byte characters don't got cut.

- The functions `char` and `ascii` now use Unicode representation instead of pure ASCII values. For `ascii,` it means that if the first character in a string is a multibyte UTF8 character, it will return the unicode for that character instead of only the first byte. Also, char` - will produce a string with the UTF8 character based on the Unicode taken as a parameter.

- The functions `upper` and `lower` now use the currently active locale set by `set_locale` to handle locale-specific conversion to upper and lowercase strings.

- The function `length` now counts characters in a string, instead of bytes. This means that `length("bææ")`returns 3, instead of 5 bytes. This works well in most cases.

- The new function `bytes` return the actual number of bytes in the string.

- Some adjustments to the format function and UTF8 strings. s-format with length now fits with multi-byte UTF8 strings, so that the length is expanded with the extra number of bytes required to fit the string. For example, the format %-10s (left justified string, 10 char), and the string "Bodø" that is 5 bytes, will expand the format to %-11s, so that the 6-space padding makes the result 10 characters.

### 1.7.0.18

- Included `boost_locale` and the `ICU` libraries to improve the following functions about UTF-8 handling:

- ICU stands for "International Components for Unicode." It is a mature, widely used set of C/C++ and Java libraries that provide robust and full-featured Unicode and locale support. This includes functions for string comparison, normalization, conversion between different character encodings, date/time formatting, and language-sensitive text collation. ICU is extensively used in various applications and platforms for internationalization (i18n) to ensure that software can be used in multiple languages and cultural contexts.

  - New command: `set_locale`. See the reference on page: new locale command for the syntax and a list of often-used locale codes.

  - The `sort_array` command now uses the locale for the correct sorting of national characters.

  - The compare function can now use the correct locale when comparing strings with `if (string1<string2) then` statement.

  - The `regex` functions are improved and now use ICU for special UTF8 characters.

### 1.7.0.17

- new functions: encrypt and decrypt. See manual page: encryption/decrypt functions

- new function: sort_array - multi-array multi-level sorting function for sorting a single array or a group of arrays. See manual page sort_array function

### 1.7.0.16

- Two new ACF functions, `create_hash` and `create_hmac` for generating message digests for all the methods: MD5, SHA1, SHA256, SHA384, and SHA512. Documentation can be found on the following WEB-page: horneks.no/manuals/ACF/createhashfunction.html

### 1.7.0.15

- Implemented new language grammar features:

  - Conditional expressions (see Syntax differences, conditional expressions )

  - Case ... end case structures. (see Case structures)

  - `break` statement to exit loops and case constructs. A break that is placed inside an if-construct will break out of the loop surrounding it. Breaks inside case constructs break out of the case and continue execution after `end case`. The break statement exits any type of loop construct being for, while, or repeat until.

### 1.7.0.12

- The `send_email` function has been enhanced to encode display names in email addresses and the subject line, ensuring compliance with email standards. Additionally, we've refined the processing of lengthy subject lines by appropriately splitting them across multiple lines in the mail headers. For emails with numerous recipients in the "To" or "Cc" fields, our improved implementation now effectively splits these lines following RFC standards. The encoding utilized is UTF-8 with Quoted Printable. It's worth noting that the encoding of different body parts was already accurately implemented starting from version 1.7.0.9.

### 1.7.0.11

- Fixed bug in send_email where mail contained several inline images. The styling of the HTML mail was incorrect.

### 1.7.0.10

- Fixed a little bug in the `send_email` implementation. It did not recognize correctly the email addresses on the form `name <myemail@example.com>` , only the naked emails without the name in front.

- Updated the TextMate editor bundle to correctly handle indentation and added some new language functions. It is in the download DMG.

### 1.7.0.9

- Implemented send_email function, according to the web page at: https://horneks.no/manuals/ACF/sendane-mailfromtheacfplugin.html

### 1.7.0.8

- Resolved SSL issues on macOS Sonoma by updating the cURL and OpenSSL libraries. Previously, the plugin used cURL with LibreSSL, which was compatible with earlier macOS versions but not with Sonoma. The plugin now utilizes cURL with OpenSSL 3.0.9. This update is essential for the proper functioning of HTTP_GET, HTTP_POST, and document service functions.

### 1.7.0.7

- Plugin and installer dmg is now Notarized @ apple, so there should be no issues installing the plugin on newer MacOS releases. Tested with MacOS Sonomoa 14.2

- Minor adjustments to XML implementation for improved handling of intermediate XML documents. When attaching intermediate XMLs to a master document, if the intermediate document's root element is "intermediateRoot", only its child elements are attached. The function for adding key/value pair lists now encapsulates the list within an "intermediateRoot" element. Conversely, other ACF functions return XML nodes without this wrapper. This approach greatly facilitates the construction of complex XML structures, allowing for seamless assembly of disparate parts into a unified master document. This implementation strategy is essential due to XML's limitation of only allowing a single root element per document. Further details will be provided in the documentation.

### 1.7.0.6

- ##### Quality Assurance Enhancements

  - Our team has made substantial efforts in the quality assurance department to ensure the highest standards. The ACF compiler, integral to the plugin, now more accurately predicts stack usage for the runtime, focusing on data types involved in various operations.

  - We've implemented automated testing and detailed logging, leading to the identification and resolution of several critical issues. These efforts have significantly enhanced the overall stability and quality of the plugin.

  - New functions - Check the revision history below for details.

### 1.7.0.5

- Minor adjustments to JSON functionality for alignment with XML implementation.

### 1.7.0.4

- Enhanced debugging of XML functions.

### 1.7.0.3

- Introduction of XML support functions and data type.

- Seamless XML to JSON conversion capabilities.

### 1.7.0.2b

- Incorporation of JSON support as detailed at ACF JSON Data Type Documentation.

### 1.7.0.1

- Enhanced document service with one-time password security.

- Introduction of Confirm, Alert, and Request functions for exception handling.

- Robust TRY/CATCH/TRY AGAIN logic for exceptions.

### 1.7.0.0

- New HTTP_Get and HTTP_Post functions.

- Enhanced OTP functions for Two-factor authentication.

- Advanced SQL functionality with placeholders.

- Updated MySQL compatibility.

- Refined Document Service functions.

- New BASE64_ENCODE, BASE32_ENCODE, BASE64_DECODE, BASE32_DECODE functions.

## Bug Fixes

- Addressed issues with compiling nameless packages. Nameless packages are now labeled "STD".

- Overhauled document service for improved stability, particularly in handling unusual parameters.

- Implemented 'List_files', absent in version 1.6.2.

- Introduced 'Delete_directory', though usage advisories apply due to potential risks with incorrect path specifications.

## Documentation

For detailed information and guidance, visit our online documentation.

Additionally, an offline version of the documentation, as of 09.12.2023, is included in this download. Start with the `index.html` file at the top of the archive for offline reference.

Your feedback and suggestions are invaluable to us. If you have any thoughts or concerns, especially regarding features like 'Delete_directory', we welcome your input. Thank you for choosing the ACF Plugin!