Version 0.1.026 (released August 29th, 2016)
This release adds several nice refinements to the procedure editor, performance enhancements to the data sheet, and dozens of bug fixes, including resolving several long-standing issues. All known problems relating to hiding/showing database fields have been resolved. All known problems with single stepping and debug statements have been resolved.

- Undo in the Procedure editor window is now correctly linked to the database undo manager. This means that editing the procedure now makes the database “dirty”, and auto-save, etc. works correctly even if the only changes that have been made were to procedure code.

- Fixed debug breakpoints and single stepping.

- Added procedure context menu (right click in procedure), with items for looking up in Panorama Help, setting and jumping to marks, typing in fields, forms and procedure names. New in Panorama X you can open procedures in the same database without using the View menu – just right click, then choose from the Open Procedure submenu. Or if you select a procedure name, you can open it directly – just right click and choose Open from the menu (this option is only available if you have selected the name of an actual procedure in the database).

- Added Mark menu to procedure editor window. As it did in Panorama 6, this menu allows you to quickly jump to specific spots in a long procedure. Unlike in Panorama 6, when you ask it to create a new mark it doesn’t prompt you with a dialog, instead it creates an untitled mark that you can then type in whatever name you want. The Mark menu is also available in the procedure context menu (right click).

- Fixed problem that sometimes could cause a database to be saved without any open windows.

- Fixed problems (hang) that occurred when automatic calculations were performed if there are hidden fields in the data sheet.

- When hiding the current field, Panorama X now correctly keeps track of which field is the current field.

- Adding a field to the end of a data sheet is now nearly instantaneous, even if there are hundreds of fields.

- Deleting a field is now instantaneous, even if the database contains hundreds of fields.

- Inserting/rearranging fields is now 10x–100x faster for databases with large numbers of fields.

- Added new statements and functions that allow a program to perform automated editing of a procedure: ProcedureInsertText, ProcedureSetSelection, ProcedureSearch, ProcedureSearchExact. ProcedureSearchNext, ProcedureSearchNextExact, InsertNewProcedureMark, ProcedureInsertFieldName, info(“proceduretext”), info(“procedureselectedtext”), info(“procedureselectionstart”), info(“procedureselectionend”), and info(“procedureselectionlength”). Note: These statements and functions were used to create the procedure context menu.

- Subroutine parameters now work reliably with fileglobal variables and fields, even if the active database has changed. To make this work, parameters are now evaluated immediately in call statement, instead of waiting until parameter( function is used (this is the same way Panorama 6 worked).

- When opening a database, Panorama X will now always open with at least the data sheet, no matter what (even if a database was saved with no windows open). Now the only way a database can open with no windows is if you use the opensecret statement.

- Panorama now correctly auto-senses UTF–16 when importing text.

- Fixed problems that occurred when deleting the last (rightmost) field in a database.

- Implemented the DropFromFinder and DropImagesFromFinder statements.

- Fixed Drag Receiver object so that it correctly allows all file types to be dropped on object if the Extensions option is empty.

- Fixed problems relating to pasting styled text into a procedure.

- Fixed low level routine that did not always handle unselected records properly. This could have caused an unselected record to become the current record. It may have caused erratic behavior or even crashes, though I was not able to duplicate that.

- Fixed formulafill so that it works correctly with numeric fields and zero values.

- When convering a Panorama 6 Scrolling List object to a Panorama X Text List object, it now correctly converts a scan database of `<Current Database>` to `~`.

- The fileexists( function now correctly recognizes that a package is a file, not a directory. This includes Panorama X databases, applications, etc. (Though it will also be recognized as a folder by the folderexists( function.)

- Fixed the crtolf( function (it was incorrectly converting to carriage returns instead of linefeeds).

- Fixed the cardvalidate statement (the function already worked correctly).

- Fixed the DictionaryValueExists statement, it didn’t have the right number of parameters declared, and wasn’t returning the result into the correct parameter.

- The Formula Workshop can now be called with a parameter for the initial formula, for example `openwizard "Formula Workshop","2+2"`. This feature is used by the procedure context menu.

- The Open View dialog can now optionally be called with a parameter that specifies the initial search text. This is used by the procedure context menu.

- Improved address and phone number checks in the Site License wizard (to cut down false negatives).

- Hundreds of documentations corrections (this time, the majority came from Michael Kellock – thanks Michael!)

- Fixed Panorama Help MarkDown generation so that page links will work no matter what combination of upper and lower case is used, for example RectangleTweak( is now ok. This one change fixed hundreds of broken links in the documentation.

Brand new features implemented in this release (features that were not included in Panorama 6):

- info("procedureselectedtext") -- The info("procedureselectedtext") function returns the selected source code in the current procedure window.
- info("procedureselectionend") -- The info("procedureselectionend") function returns the ending position of the selected source code in the current procedure window.
- info("procedureselectionlength") -- The info("procedureselectionlength") function returns the length of the selected source code in the current procedure window.
- info("procedureselectionstart") -- The info("procedureselectionstart") function returns the starting position of the selected source code in the current procedure window.
- info("proceduretext") -- The info("proceduretext") function returns the source code in the current procedure window.
- procedureinsertfieldname -- The procedureinsertfieldname statement inserts a field name into a procedure, adding chevrons if necessary.
- procedureinserttext -- The procedureinserttext statement inserts text into the current procedure.
- proceduresearch -- The proceduresearch statement searches for text in a procedure.
- proceduresearchexact -- The proceduresearchexact statement searches for text in a procedure.
- proceduresearchnext -- The proceduresearchnext statement searches for text in a procedure, starting from the current location.
- proceduresearchnextexact -- The proceduresearchnextexact statement searches for text in a procedure, starting from the current location.
- proceduresetselection -- The proceduresetselection statement changes the text selection in the current procedure editor window.

Features implemented in this release that work differently than they did in Panorama 6.

- dropfromfinder -- The dropfromfinder statement processes any files or folders that have been dropped on a form from the finder.
- dropimagesfromfinder -- The dropimagesfromfinder statement processes images that have been dropped on a form from the Finder. The images may be added to new records in the database or put in the current record.

Features implemented in this release that work exactly the same as they did in Panorama 6.

ALL features that were added or changed in this release:

- ?( -- The ?( function allows a formula to make a true/false, yes/no decision.
- ^ -- The ^ operator raises a number to a power.
- + -- The + operator works differently depending on the type of operands used with it. If both operands are numeric, it does numerical addition. If either operand is text the + operator concatenates (joins together) the two operands.
- < -- The < operator compares two values to see if the first value is less than the second value.
- addlines -- The addlines statement adds a specified number of records to the end of a database.
- alert -- The alert statement displays a modal alert window with a message and one or more buttons.
- alertcanceldelete -- The alertcanceldelete statement displays a modal alert window with a message and two buttons: Cancel and Delete.
- alertcancelok -- The alertcancelok statement displays a modal alert window with a message and two buttons: Cancel and Ok.
- alertmodal -- The alertmodal statement displays a modal alert sheet (not attached to any window) with a message and one or more buttons.
- and -- The and operator returns true if both operands are true.
- append -- The append statement appends a text string to a field or variable.
- appendline -- The appendline statement appends a text string to a field or variable on a new line.
- applescript( -- The applescript( function executes AppleScript source code and returns the result.
- applescriptconstant( -- The applescriptconstant( function converts an expression into an AppleScript literal.
- applescriptstring( -- The applescriptstring( function converts text into an AppleScript string literal.
- arccosh( -- The arccosh( function calculates the inverse hyperbolic cosine of a numeric value.
- archivecontents( -- The archivecontents( function lists the contents of a compressed archive in *.zip*, *.tar.gz* or *.tar.bz2* format.
- arctanh( -- The arctanh( function calculates the inverse hyperbolic tangent of a numeric value.
- arraycolumn( -- The arraycolumn( function extracts a column from a two dimensional array.
- arraydeduplicate( -- The arraydeduplicate( function removes duplicate elements from a text array (see Text Arrays).
- arraydeduplicate -- The arraydeduplicate statement removes duplicate elements from an array (see Text Arrays).
- arrayhack( -- The arrayhack( function hacks an array by adding, replacing or removing array elements
- arrayinsert( -- The arrayinsert( function inserts one or more empty elements into the middle of a text array (see [Text Arrays]).
- arrayintegersort -- The arrayintegersort statement sorts all the numeric elements of a text array in proper numeric order.
- arraylast( -- The arraylast( function extracts the last element of an array.
- arraylefttrim( -- The arraylefttrim( function removes one or more elements from the beginning of an array.
- arraymenuitems( -- The arraymenuitems( function converts a carriage return delimited array into a series of menu items.
- arraymerge( -- The arraymerge( function merges two text arrays together (see [Text Arrays]).
- arraynumericsort( -- The arraynumericsort( function sorts a text array in numeric order (see Text Arrays).
- arraynumericsort -- The arraynumericsort statement sorts all the numeric elements of a text array in proper numeric order.
- arraynumerictotal( -- The arraynumerictotal( function totals all the numeric elements of a text array.
- arraynumerictotal -- The arraynumerictotal statement totals all the numeric elements of a text array.
- arrayrandomize( -- The arrayrandomize( function reorders an array in random order.
- arrayrandomize -- The arrayrandomize statement reorders an array in random order.
- arrayselectedbuild( -- The arrayselectedbuild( function builds an array by scanning a database and creating an array element for every visible (selected) record in the database (see Text Arrays).
- arrayselectedbuild -- The arrayselectedbuild statement builds an array by scanning a database and creating an array element for every visible (selected) record in the database (see Text Arrays).
- arraysort( -- The arraysort( function alphabetizes (A-Z) the elements in a text array (see [Text Arrays]).
- arraysort -- The arraysort statement sorts the elements in an array (see Text Arrays).
- arraytableceiling( -- The arraytableceiling( function looks up a value in a double column table, similar to the table( function but from an array instead of a database.
- arraytablefloor( -- The arraytablefloor( function looks up a value in a double column table, similar to the table( function but from an array instead of a database.
- arraytoggle -- The arraytoggle statement "toggles" a value within an array.
- arraytopythonlist( -- The arraytopythonlist( function converts a Panorama array into a Python list.
- arrayunpropagate( -- The arrayunpropagate( function scans an array from top to bottom, removing duplicate values in a row.
- asc( -- The asc( function converts the first character of a text string into a number from 0 to 65535 based on Unicode encoding.
- assign( -- The assign( function assigns a value to a field or variable, also returning the value.
- assignfield -- The assignfield statement performs an assignment, much like an equals sign or the assign statement. However, the assignfield statement only performs the assignment to a database field, not to any variable.
- assignglobal -- The assignglobal statement performs an assignment, much like an equals sign or the assign statement. However, the assignglobal statement only performs the assignment to a global variable.
- average -- The average statement calculates averages and sub-averages for the selected records in the current field.
- beep -- The beep statement makes the computer speaker beep once.
- beginswith -- The beginswith operator returns true if the value on the left starts with the value on the right, false if it doesn't.
- bigendianbinaryvalue( -- The bigendianbinaryvalue( function converts big endian binary data (a byte, word, or longword) into an unsigned number (see Binary Data).
- binarytotext( -- The binarytotext( function converts binary data into text, optionally using a specified encoding.
- binaryvalue( -- The binaryvalue( function converts binary data (a byte, word, longword, or longlongword) into a number (see Binary Data).
- bonjour( -- The bonjour( function returns a list of available hosts.
- bundleresourcepath( -- The bundleresourcepath( function returns the file path and name of a specified item in the Panorama application bundle.
- byte( -- The byte( function converts a number into a single byte of binary data (see Binary Data).
- cache( -- The cache( function stores a value in a temporary variable.
- calendarday( -- The calendarday( function helps in creating monthly calendars.
- call( -- The call( function allows a procedure to be called as a subroutine within a formula and return a result.
- callwithin -- The callwithin statement allows a procedure to call a mini-procedure within a separate procedure within the current database as a subroutine.
- callwithindatabase( -- The callwithindatabase( function returns true if the current procedure was called by another procedure in the same database, false if it was called by a procedure in another database.
- cardtype( -- The cardtype( function returns the credit card type (American Express, Visa, MasterCard or Discover).
- case -- The case statement allows multiple decisions to be chained together (also see the elseif statement).
- catcherror( -- The catcherror( function evaluates an expression, but suppresses any error generated by that expression.
- ceil( -- The ceil( function converts a number to an integer, truncating toward positive infinity.
- cell -- The cell statement enters a value into the currently active field (i.e. cell).
- cginavlink( -- The cginavlink( function creates a domain-independent navigation link for the current record in this database.
- cginavlinknewwindow( -- The cginavlinknewwindow( function creates a domain-independent navigation link (to a new browser window) for the current record in this database.
- changeobject -- The changeobject statement modifies the properties of one object in a form.
- changetimer -- The changetimer statement modifies a repeating task that will be performed periodically when Panorama is not otherwise busy.
- channelinformation( -- The channelinformation( function returns information about a specified channel.
- channelinformation -- The channelinformation statement returns information about a specified channel.
- characterfilter( -- The characterfilter( function scans and filters text on a character by character basis.
- characterfilter -- The characterfilter statement scans and filters text on a character by character basis.
- chararray( -- The chararray( function extracts a single character from text.
- checkedmenuitem( -- The checkedmenuitem( function creates a single menu item with an optional checkmark.
- choosefolderdialog -- The choosefolderdialog statement pauses and displays the standard “choose folder” dialog.
- city( -- The city( function looks up the name of a city associated with a US zip code.
- cityzip( -- The cityzip( function returns the lowest zip code associated with a city.
- cityzips( -- The cityzips( function returns a list of zip codes associated with a city.
- cloneform -- The cloneform statement copies all of the objects in a form (optionally, with modifications) into the active form.
- commalist( -- The commalist( function converts a text array (see Text Arrays) into an English list, with items separated by a comma and a space, except for the last two items which are separated by the word and and spaces.
- commastr( -- The commastr( function converts a number to text, with a comma every third digit. The number is converted as an integer, with no decimal point.
- Comments -- A comment is a note inside a program.
- commonpath( -- The commonpath( function returns the path for common folders (desktop, library, documents, pictures, etc.).
- comparedictprocedures -- The comparedictprocedures statement compares all the procedures from a dictionary with the procedures in a specified database.
- completedatestr( -- The completedatestr( function converts a date to text, spelling out the month and including the day of the week.
- constructmailinglabel -- The constructmailinglabel statement creates the form elements for printing mailing labels.
- copy -- The copy statement copies the contents of the current field onto the clipboard.
- copycell -- The copycell statement copies the contents of the current field onto the clipboard, replacing anything previously on the clipboard.
- cosh( -- The cosh( function calculates the hyperbolic cosine of a numeric value.
- custompluralpattern( -- The custompluralpattern( function converts a number to text using a pattern, making customizable adjustments for pluralization.
- customstatementdatabase( -- The customstatementdatabase( function returns the name of the library database that defines a custom statement.
- datamode -- The datamode statement switches a form from graphics mode into data mode.
- datatype( -- The datatype( function determines what kind of data is in a field or variable: text, number, etc.
- dbfolder( -- The dbfolder( function returns the folder path of the folder the current database is located in.
- dbsubfolder( -- The dbsubfolder( function returns the path of a subfolder within the same folder as the current database.
- decrypt( -- The decrypt( function decrypts data.
- deletechildren -- The deletechildren statement deletes all the records in another database that have a value in the key field that is equal to the key value.
- deletefield -- The deletefield statement deletes the current field from the database.
- deleteformcustompreference -- The deleteformcustompreference statement deletes a form custom preference.
- deleterecord -- The deleterecord statement deletes the currently selected record.
- deleterecordandchildren -- The deleterecordandchildren statement This deletes the current record from the active database and all the records in another database that have a value in the key field that is equal to the key value.
- dropfromfinder -- The dropfromfinder statement processes any files or folders that have been dropped on a form from the finder.
- dropimagesfromfinder -- The dropimagesfromfinder statement processes images that have been dropped on a form from the Finder. The images may be added to new records in the database or put in the current record.
- Duplicating Objects -- to make copies of one or more objects.
- editfieldname -- The editfieldname statement opens the data sheet window's field properties inspector and selects the field name.
- else -- The else statement works together with the if statement to specify statements that will be executed for both the true and false cases.
- emptyfill -- The emptyfill statement fills every empty visible cell in the active field with the specified value.
- Error Handling -- Techniques for trapping runtime errors instead of letting them abort the program.
- eulersconstant( -- The eulersconstant( function returns the value of Euler's constant.
- eurodatestr( -- The eurodatestr( function converts a date to text in European format.
- exp( -- The exp( function raises e to a power.
- expand -- The expand statement reveals the next level of collapsed detail records associated with the currently active summary record.
- expandall -- The expandall statement reveals all collapsed detail records associated with the currently active summary record.
- export -- The export statement exports the selected rows in the current database into a text file.
- exportallprocedures -- The exportallprocedures statement saves all the procedures in an editable text format.
- exportform( -- The exportform( function exports a form and the form's meta data as a binary object that can be imported with the importform statement.
- exportlinenotabs( -- The exportlinenotabs( function generates a tab delimited line of data containing all the fields in the current record. Any tabs within individual fields will be removed.
- exportlinevisiblecells( -- The exportlinevisiblecells( function generates a tab delimited line of data containing all the visible (non hidden) fields in the current record.
- fact( -- The fact( function computes the factorial of a value.
- field -- The field statement tells Panorama to move to the specified field for the current record.
- filefolder( -- The filefolder( function returns the folder ID of the folder that contains the specified file.
- fileglobal -- The fileglobal statement creates one or more fileglobal variables.
- fileloadpartial( -- The fileloadpartial( function reads a portion of the contents of any file on disk.
- fill -- The fill statement fills every visible cell in the active field with the specified value.
- find -- The find statement locates the first visible record in the active database for which the specified condition is true.
- findid -- The findid statement locates a record in the active database by its ID number (see info("serverrecordid").
- foldercontains( -- The foldercontains( function checks to see if a folder contains a specified file. See also the pathcontains( function.
- foldercontents( -- The foldercontents( function returns a list of all of the contents of a folder.
- folderexists( -- The folderexists( function returns true if a folder exists, false if it does not.
- for -- The for statement is used at the beginning of a loop that loops a fixed number of times.
- formatphone( -- The formatphone( function formats a US phone number using the standard *(aaa) nnn-nnnn* format.
- formblueprint -- The formblueprint statement creates blueprint code for the specified form.
- formulacalc -- The formulacalc statement allows you to evaluate a formula that you were not able to code into the procedure when it was being written.
- formulafill -- The formulafill statement fills every visible cell in the active field with the result of the specified formula.
- fullpath( -- The fullpath( function converts a filename or relative path (starting with the : or / symbol) into a full HFS path, including the disk name.
- fv( -- The fv( function (short for future value) calculates the future value of an investment.
- getbutton -- The getbutton statement retrieves the coordinates of the last button that was pressed (in global screen co-ordinates).
- getfieldproperties -- The getfieldproperties statement returns a dictionary that contains all of the properties of the specified field.
- info("procedureselectionend") -- The info("procedureselectionend") function returns the ending position of the selected source code in the current procedure window.
- info("procedureselectionlength") -- The info("procedureselectionlength") function returns the length of the selected source code in the current procedure window.
- info("procedureselectionstart") -- The info("procedureselectionstart") function returns the starting position of the selected source code in the current procedure window.
- info("proceduretext") -- The info("proceduretext") function returns the source code in the current procedure window.
- procedureinserttext -- The procedureinserttext statement inserts text into the current procedure.
- proceduresetselection -- The proceduresetselection statement changes the text selection in the current procedure editor window.

See Also

- Version 0.1.001 (released July 7th, 2012) -- Summary of Version 0.1.001 (released 7/7/2012)
- Version 0.1.002 (released August 12th, 2012) -- Summary of Version 0.1.002 (released 8/12/2012)
- Version 0.1.003 (released December 2nd, 2012) -- Summary of Version 0.1.003 (released 12/2/2012)
- Version 0.1.004 (released December 10th, 2012) -- Summary of Version 0.1.004 (released 12/10/2012)
- Version 0.1.005 (released December 21st, 2012) -- Summary of Version 0.1.005 (released 12/21/2012)
- Version 0.1.006 (released December 26th, 2012) -- Summary of Version 0.1.006 (released 12/26/2012)
- Version 0.1.007 (released May 1st, 2013) -- Summary of Version 0.1.007 (released 5/1/2013)
- Version 0.1.008 (released May 22nd, 2013) -- Summary of Version 0.1.008 (released 5/22/2013)
- Version 0.1.009 (released July 9th, 2013) -- Summary of Version 0.1.009 (released 7/9/2013)
- Version 0.1.010 (released October 14th, 2013) -- Summary of Version 0.1.010 (released 10/14/2013)
- Version 0.1.011 (released December 6th, 2013) -- Summary of Version 0.1.011 (released 12/6/2013)
- Version 0.1.012 (released August 29th, 2015) -- Summary of Version 0.1.012 (released 8/29/2015)
- Version 0.1.013 (released September 6th, 2015) -- Summary of Version 0.1.013 (released 9/6/2015)
- Version 0.1.014 (released September 14th, 2015) -- Summary of Version 0.1.014 (released 9/14/2015)
- Version 0.1.015 (released September 29th, 2015) -- Summary of Version 0.1.015 (released 9/29/2015)
- Version 0.1.016 (released October 12th, 2015) -- Summary of Version 0.1.016 (released 10/12/2015)
- Version 0.1.017 (released November 11th, 2015) -- Summary of Version 0.1.017 (released 11/11/2015)
- Version 0.1.018 (released December 7th, 2015) -- Summary of Version 0.1.018 (released 12/7/2015)
- Version 0.1.019 (released January 28th, 2016) -- Summary of Version 0.1.019 (released 1/28/2016)
- Version 0.1.020 (released February 15th, 2016) -- Summary of Version 0.1.020 (released 2/15/2016)
- Version 0.1.021 (released February 29th, 2016) -- Summary of Version 0.1.021 (released 2/29/2016)
- Version 0.1.022 (released March 1st, 2016) -- Summary of Version 0.1.022 (released 3/1/2016)
- Version 0.1.023 (released May 27th, 2016) -- Summary of Version 0.1.023 (released 5/27/2016)
- Version 0.1.024 (released June 12th, 2016) -- Summary of Version 0.1.024 (released 6/12/2016)
- Version 0.1.025 (released July 21st, 2016) -- Summary of Version 0.1.025 (released 7/21/2016)
- Version 0.1.027 (released September 18th, 2016) -- Summary of Version 0.1.027 (released 9/18/2016)
- Version 0.1.028 (released November 9th, 2016) -- Summary of Version 0.1.028 (released 11/9/2016)
- Version 0.1.029 (released December 31st, 2016) -- Summary of Version 0.1.029 (released 12/31/2016)
- Version 0.1.030 (released February 12th, 2017) -- Summary of Version 0.1.030 (released 2/12/2017)
- Version 0.1.031 (released March 3rd, 2017) -- Summary of Version 0.1.031 (released 3/3/2017)
- Version 0.1.032 (released April 3rd, 2017) -- Summary of Version 0.1.032 (released 4/3/2017)
- Version 0.9 (released May 15th, 2017) -- Summary of Version 0.9 (released 5/15/2017)
- Version 0.9.001 (released July 18th, 2017) -- Summary of Version 0.9.001 (released 7/18/2017)
- Version 0.9.002 (released July 27th, 2017) -- Summary of Version 0.9.002 (released 7/27/2017)
- Version 0.9.003 (released September 10th, 2017) -- Summary of Version 0.9.003 (released 9/10/2017)
- Version 0.9.004 (released September 14th, 2017) -- Summary of Version 0.9.004 (released 9/14/2017)
- Version 0.9.005 (released September 19th, 2017) -- Summary of Version 0.9.005 (released 9/19/2017)
- Version 0.9.006 (released September 27th, 2017) -- Summary of Version 0.9.006 (released 9/27/2017)
- Version 0.9.007 (released October 3rd, 2017) -- Summary of Version 0.9.007 (released 10/3/2017)
- Version 0.9.008 (released October 12th, 2017) -- Summary of Version 0.9.008 (released 10/12/2017)
- Version 10.0.0 (released October 18th, 2017) -- Summary of Version 10.0.0 (released 10/18/2017)
- Version 10.0.01 (released December 10th, 2017) -- Summary of Version 10.0.01 (released 12/10/2017)
- Version 10.1 (released August 6th, 2018) -- Summary of Version 10.1 (released 8/6/2018)
- Version 10.1.1 (released August 30th, 2018) -- Summary of Version 10.1.1 (released 8/30/2018)
- Version 10.1.2 (released November 15th, 2018) -- Summary of Version 10.1.2 (released 11/15/2018)
- Version 10.2 (released October 7th, 2021) -- Summary of Version 10.2 (released 10/7/2021)