Monthly Archives: October 2013

H5 Builder

At CIDC in September we showed a quick demo of an H5 enabled app.  For the details on what the H5 product is all about you can read this; https://clarionsharp.com/blog/clarion-h5/

At the conference I talked about our plans for H5:

H5 will be included with a future C9.x EE.  H5 will be our first Clarion Community open source project.  We’ll be posting the templates and classes onto GitHub so that Clarion developers from around the world can hack, enhance, branch, and generally share their ideas and expertise (working along side our core dev team).  At the conference quite a few of the Clarion devs present indicated they are looking forward to getting involved with the project, and I think there are many more who weren’t at the conference who will join in.

Currently we are refactoring the templates/classes to move each control into separate file(s).  This is a necessary first step to ensure its easy to work on files and get them checked back into the common repository while minimizing conflicting changes.  We expect to open the project on GitHub in approximately 2 weeks.

Template for creating a CLASS in an .App

At the CIDC conference we showed a template (that is already included with C9) for easily creating CLASSes within your APP.
The Help doesn’t yet cover it, (but will in the next update) and it’s very simple to use without any docs. Here are a few screenshots to get you going;

start by inserting a new procedure and then select “Source Class”
NewSourceClass

if you press the Actions button, you have the option to declare the module as a generic MEMBER() so you can share the class between Apps as needed.  (this option was actually added during the devcon based on feedback during the presentation)

SC_actions

the embed points are pretty much self-explanatory

SC_embeds

SC_props

You may have noticed the other new template Procedure “Generated UserControl Class”. As the name implies that template creates a ‘user control’ which is comprised of a Window and all the controls on it.  We’ll post separately about that one.

REPORTs in the new RTL

Clarion uses Windows metafiles to generate reports since the very first version of Clarion for Windows. A metafile is a sequence of records containing a list of GDI functions and parameters. Metafiles are created in memory and can be written to disk files. The RTL also uses metafiles to handle direct drawing operations like ARC() or PIE() in both WINDOWs and REPORTs. A metafile is a simple way to store drawing operations but there are several issues:

  1. Windows metafiles do not support all GDI functions used for drawing. For example, images with semi-transparent parts cannot be stored in Windows metafiles.
  2. Reports are sequences of bands and bands consist of controls and can be nested. Multiple drawing operations can be required to draw individual controls. For example, multiple lines and multiple strings must be drawn for LIST controls. Reports are best represented as a tree structure, and metafiles with their linear organization are not an easy/adequate way to represent them.
  3. The RTL must carefully track images, pens and fonts used in metafiles to avoid leaking of resources.

Problem (1) can be solved by use of Enhanced metafiles (EMF) instead of Windows metafiles (WMF). But other problems exist for both types of metafiles. The RTL must enumerate metafile records every time some delayed action needs to be executed, for example when processing widow/orphan settings to find end of page. The RTL inserts additional records into metafiles to mark logically related records and assist in enumeration and parsing both during report generation and during conversion metafiles to text/PDF/XML/HTML format.

ReportsTree

The new RTL won’t use metafiles for direct drawing operations or during report generation. Instead it will produce a dynamic tree structure matching the Report with a sequence of drawing operations. Every tree node is a class instance derived from the MetaNode class:
MetaNode       CLASS,TYPE
Next             &MetaNode
Bounds           LIKE(RECT)
Flags            ULONG
Custom1          LONG
Custom2          LONG
Draw             PROCEDURE (LONG context),VIRTUAL
END

ContainerNode  CLASS(MetaNode),TYPE
Nested           &MetaNode
END

PageNode       CLASS(ContainerNode),TYPE
Print            PROCEDURE (HDC, ULONG skipmask)
END

IndirectNode   CLASS(MetaNode),TYPE
Actual           &ContainerNode
END

There are 3 categories of nodes:

  1. Nodes with information to execute a direct draw operation or to draw a control. A Nodes’ classes have fields for all values required to perform both drawing and post-processing: fonts, colors, pen style and width, value of the EXTEND attribute, etc.
  2. Container nodes used for referencing a list of nested nodes.
  3. Indirect nodes referencing some Container node.

The container node class for a report page has a function to start drawing or printing. The call to this function initiates iteration of the page sub-tree and calls the Draw method for every node. This approach provides a very easy method to get a page in any required form:

  • If the HDC parameter is a handle to a screen device context (DC), the page contents are drawn on screen.
  • If the HDC parameter is a handle to a printer DC, the page contents are sent to the corresponding printer.
  • If the HDC parameter is a handle to an Enhanced metafile DC, an .EMF file with the page’s image is generated.
  • If the HDC parameter is a handle to a Windows metafile DC, a .WMF file with the page’s image is generated.

 

The skipmask parameter of PageNode.Print function is used to filter which nodes to print/draw. If the value of the expression

BAND (node.Flags, skipmask)

is not 0, the node (and all nested nodes for container) are not drawn.  Filtering nodes can be used in multiple ways, for example to exclude some pages from printing, or to show the document form at preview time but not print it without needing to re-generate the report. The program can set its own flags in high WORD of the node’s Flags field (low WORD is reserved for Clarion internal use). The program also can use node’s Custom1 and Custom2 fields to store any useful data associated with that node.

Position of nodes corresponding to bands (FORM, HEADER, FOOTER, DETAIL, BREAK) is calculated relative to the page origin. Position of controls is calculated relative to the origin of the band they belong to. This allows us to have “references to containers” implemented by indirect nodes. Upon drawing/printing an indirect node the RTL uses its position, flags, custom data and a list of nested nodes of the container it points to. Indirect nodes are used internally to handle the FORM band, which is shared by all report pages. But a program can use them in other ways, for example to merge several short reports to print them on the same page, or to print a number of copies of specific pages.

ReportsTree2

Benefits

The new internal organization for Reports retains complete backward compatibility with the current and prior versions of the RTL because WMF files can be easily generated for every page.  But it opens the door to numerous potential enhancements:

  1. Faster report generation by eliminating the need for repeated re-scanning of metafiles to merge them or to find the point of a page break.
  2. Easier conversion of reports to formats other than WMF and EMF by elimination of the need to parse the WMF file to reconstruct the structure of the report in another format.
  3. Easier after-generation modification of reports, for example placing the correct total number of pages to “Page n of N” text.
  4. The possibility to have report pages with multi-layered contents and then selecting the desired layers at preview time.

WINDOWs in the new RTL

To distinguish between Clarion WINDOW and APPLICATION structures, and Windows OS User objects, the following text uses upper-cased WINDOW for Clarion structures and a lower-case italic font for User objects: window.

Every window  has 2 logical areas:

  • Client area – rectangular part of window surface where window contents (controls) is drawing. The client area can be empty, e.g. for iconized windows.
  • Non-client area – part of the window’s surface outside the client area. The non-client area can be empty if the client area is equal in size to the entire window rectangle.

Windows uses the non-client area of a window to draw the border, caption, menubar and scrollbars, if any. Because modern window styles assume usage of additional informational and control elements, for example toolbars or status bars which can be created/destroyed at run time, Clarion uses 2 or more windows to implement WINDOW structures:

  • Non-client window (mandatory)
  • Client window (mandatory)
  • Toolbar (optional)
  • Site windows for dockable toolboxes (optional)
  • MDI Tab bar (in APPLICATIONs, optional)

 

The term non-client part indicates the non-client window of a WINDOW/APPLICATION structure, and the term client part to indicate the client window area.

Non-client part of WINDOW

Non-Client

The non-client part of WINDOW can contain:

  • Caption
  • Border
  • Menubar

All elements are optional depending on the actual WINDOW declaration.

The client area of non-client part of WINDOW can contain:

  • Toolbar
  • Status bar
  • MDI Tab bar (for frame WINDOWs)
  • Docking site spaces

The non-client part is a parent window for the client-part.

The non-client part determines the position and dimensions of WINDOW:

  • Coordinates of the upper-left corner of the non-client part are position of WINDOW.
  • Width and height of the client part are the dimensions of WINDOW.

The Windows OS (not the RTL) deals with the non-client part to move, size, change position in Z-order, activate, maximize, restore, iconize and hide/unhide WINDOW.

Implementation of WINDOW structures in the RTL

Implementation of WINDOWs in the RTL follows their (user) declared structure. In both the current version (C9) of the RTL, and all previous versions, the RTL considers non-client and client parts as a united object.

schemaWindow

Schema of implementation of WINDOWs (APPLICATIONs have additional elements)

The Clarion RTL creates the entire WINDOW including window objects for non-client and client parts, toolbar and other elements in the thread where the program executes the CREATE statement for that WINDOW. Because Clarion does not allow creation of MDI child WINDOWs in the Frame’s thread, the RTL uses the CreateMDIWindow API function to create the non-client part of WINDOW. The CreateMDIWindow function has been listed as one of benefits of 32-bit Windows in comparison with earlier 16-bit Windows 3.x versions because it can create an MDI child window in a different thread other than one running the frame window. But the real life implementation of the MDI API in Windows OS is not thread safe. Therefore simultaneous activity of several MDI child windows running in their own threads will eventually cause an inconsistent state of the Windows OS internal structure containing MDI-related information and, consecutively, incorrect functioning of both the MDI frame and MDI child windows in multiple ways.

Since Clarion 6 was introduced and the problems with MDI were discovered huge efforts have been made to hide them for MDI child WINDOWs in Clarion. Unfortunately, there is no complete solution without changing of the internal structure of WINDOWs. The new Clarion RTL will use a new implementation of WINDOWs. The main change is that the non-client and client parts will be strictly separated.

schemaWindow2

Changes in the WINDOW structure provide several important benefits:

  1. The non-client part and the client part of the same WINDOW can be created in different threads. Specifically, the non-client part of an MDI child WINDOWs can be created in the Frame’s thread. This solves all the problems caused by the thread-unsafe implementation of MDI in Windows. All the code added to the RTL to work around these problems becomes unnecessary and can be removed. This makes the RTL far more manageable and extensible.
  2. The client part of WINDOWs with or without the MDI attribute is absolutely identical and is very close to the toolbar. There are a few minor differences, e.g., the client part of a WINDOW can be scrollable and setting focus to a toolbar’s controls is handled in special way.  This allows us to share most of the code for the client part and for the toolbar.
    1. The separate client part can be “glued” to any rectangular area within the bounds of the client area of the non-client part of any WINDOW, for example, to a TAB control. That means the client part can be used as a compound custom control. It can be created multiple times, and every copy can be “glued” to different places without the necessity to duplicate the code. Implementation of such user-defined control could be coded as a class with a method to declare a client-part-only WINDOW and run it’s ACCEPT loop and methods to set or query values of any USE variables.  Dockable toolboxes can be re-implemented in this same way.  Probably, a new keyword will be added to the language for declaring client-part-only WINDOWs. The host WINDOW would provide a simple interface to inform the “glued” object about events like resizing. The functionality of REGION controls could be extended for handling that implementation. Alternatively we could introduce another new keyword for areas where client-part-only WINDOWs can be “glued”.
    2. The common part of a WINDOW object is created upon entry to the scope where a WINDOW is declared is the same for WINDOWs with and without the MDI attribute. This allows the possibility to change the type of non-frame WINDOWs at run time before opening them.

 

Working with 64bit Signed and Unsigned integers

Clarion 9.x will introduce RTL support to work with 64-bit signed and unsigned integers.  The RTL has 19 functions (so far) which provide a means to assign values, add, subtract, multiply, divide, bit-shift, convert to/from decimals, and more.

How to define (applicable for FILE structures or variables):
! Declarations of INT64 and UINT64 types used in prototypes
!
! INT64    GROUP,TYPE
! lo         ULONG
! hi         LONG
!          END
!
! UINT64   GROUP,TYPE
! lo         ULONG
! hi         ULONG
!          END

List of functions:
i64Sign – return the sign
i64Negate – change the sign like the unary operator for numbers
i64ABS – equivalent to ABS()
i64Is0 – check for equality to 0
is32Bit – check the high half of number to be equal to 0
i64Assign – equivalent to the = assignment operator
i64To32 – take the lower 32 bits of the value
i64FromDecimal – direct DECIMAL to 64-bit integer conversion
i64ToDecimal – direct 64-bit integer to DECIMAL conversion
i64Shift – equivalent to BSHIFT (value, n)
i64LShift – equivalent to BSHIFT (value, n) if n is positive
i64RShift – equivalent to BSHIFT (value, -n) if n is positive
i64Add – equivalent to binary + operator
i64Sub – equivalent to binary – operator
i64Mult2 – equivalent to n*=2
i64Mult10 – equivalent to n=n*10+k
i64Mult – equivalent to * operator
i64Div10 – equivalent to x=n%10; n/=10
i64Div – equivalent to / operator

i64Div10 and i64Div for signed 64-bit integers assume that the define(compatible_modulus) pragma is set to “on”.

The i64.INC is self-documenting
MODULE(‘i64* family of RTL functions’)

!!! <summary>
!!! Returns sign of passed 64-bit signed integer
!!! </summary>
!!! <param name=”v”>Reference to 64-bit signed integer variable.</param>
!!! <returns>0 if passed value is 0, -1 if paased value is negative, +1 if passed value is positive.</returns>
i64Sign        PROCEDURE (*INT64 v),SIGNED,RAW,NAME(‘Cla$i64Sign’)

!!! <summary>
!!! Negates value of passed signed 64-bit signed integer variable
!!! </summary>
!!! <param name=”v”>Reference to 64-bit signed integer variable.</param>
!!! <returns>0 if operation successful, other value in case of overflow.</returns>
i64Negate      PROCEDURE (*INT64 v),UNSIGNED,PROC,RAW,NAME(‘Cla$i64Negate’)

!!! <summary>
!!! Negates value of passed signed 64 bit signed integer variable if it is
!!! negative
!!! </summary>
!!! <param name=”v”>Reference to 64-bit signed integer variable.</param>
!!! <returns>0 if operation successful, other value in case of overflow.</returns>
i64ABS         PROCEDURE (*INT64),UNSIGNED,PROC,RAW,NAME(‘Cla$i64ABS’)

!!! <summary>
!!! Compares value of passed 64-bit integer with 0
!!! </summary>
!!! <param name=”v”>Reference to 64-bit integer variable.</param>
!!! <returns>TRUE if passed value is 0.</returns>
i64Is0         PROCEDURE (*INT64 v),BOOL,RAW,NAME(‘Cla$i64is0’)
i64Is0         PROCEDURE (*UINT64 v),BOOL,RAW,NAME(‘Cla$i64is0’)

!!! <summary>
!!! Checks that value of passed 64-bit integer can be stored to 32-bit
!!! integer without truncating
!!! </summary>
!!! <param name=”v”>Reference to 64-bit integer variable.</param>
!!! <returns>TRUE if passed value has significant bits in lower ULONG only.</returns>
is32Bit        PROCEDURE (*INT64 v),BOOL,RAW,NAME(‘Cla$is32Bit’)
is32Bit        PROCEDURE (*UINT64 v),BOOL,RAW,NAME(‘Cla$is32BitU’)

!!! <summary>
!!! Assign 32-bit value to passed 64-bit integer variable
!!! </summary>
!!! <param name=”dest”>Variable to change.</param>
!!! <param name=”src”>Value to assign to destination variable.</param>
i64Assign      PROCEDURE (*INT64 dest, LONG src),RAW,NAME(‘Cla$i64AssignS’)
i64Assign      PROCEDURE (*UINT64 dest, ULONG src),RAW,NAME(‘Cla$i64AssignU’)

!!! <summary>
!!! Assign 64-bit value to passed 64-bit integer variable
!!! </summary>
!!! <param name=”dest”>Variable to change.</param>
!!! <param name=”src”>Value to assign to destination variable.</param>
!!! <returns>0 if operation successful, other value in case of overflow or truncation.</returns>
i64Assign      PROCEDURE (*INT64 dest,  *INT64  src),UNSIGNED,PROC,RAW,NAME(‘Cla$i64AssignSS’)
i64Assign      PROCEDURE (*INT64 dest,  *UINT64 src),UNSIGNED,PROC,RAW,NAME(‘Cla$i64AssignSU’)
i64Assign      PROCEDURE (*UINT64 dest, *INT64  src),UNSIGNED,PROC,RAW,NAME(‘Cla$i64AssignUS’)
i64Assign      PROCEDURE (*UINT64 dest, *UINT64 src),UNSIGNED,PROC,RAW,NAME(‘Cla$i64AssignUU’)

!!! <summary>
!!! Store 64-bit integer value to 32-bit integer variable
!!! </summary>
!!! <param name=”src”>64-bit integer variable.</param>
!!! <param name=”dest”>32-bit integer variable.</param>
!!! <returns>0 if operation successful, other value in case of truncation</returns>
i64To32        PROCEDURE (*INT64 src, *LONG dest),UNSIGNED,PROC,RAW,NAME(‘Cla$i64To32’)
i64To32        PROCEDURE (*UINT64 src, *ULONG dest),UNSIGNED,PROC,RAW,NAME(‘Cla$i64To32U’)

!!! <summary>
!!! Store DECIMAL value to 64-bit integer variable
!!! </summary>
!!! <param name=”dest”>64-bit integer variable.</param>
!!! <param name=”src”>DECIMAL value to assign to 64-bit integer variable.</param>
i64FromDecimal PROCEDURE (*INT64  dest, *DECIMAL src),RAW,NAME(‘Cla$i64FromDecS’)
i64FromDecimal PROCEDURE (*UINT64 dest, *DECIMAL src),RAW,NAME(‘Cla$i64FromDecU’)

!!! <summary>
!!! Store 64-bit integer value to DECIMAL variable.
!!! </summary>
!!! <param name=”dest”>DECIMAL variable.</param>
!!! <param name=”src”>64-bit integer value to store to DECIMAL variable.</param>
i64ToDecimal   PROCEDURE (*DECIMAL dest, *INT64  src),RAW,NAME(‘Cla$i64ToDecS’)
i64ToDecimal   PROCEDURE (*DECIMAL dest, *UINT64 src),RAW,NAME(‘Cla$i64ToDecU’)

!!! <summary>
!!! Shift value of 64-bit integer value to given number of bits to left or
!!! to right and store result to another 64-bit integer variable. Shift is
!!! to right if shift count value is negative, and is to left if shift count
!!! value is positive. The same variable can be passed both as a source value
!!! and as a destination variable.
!!! </summary>
!!! <param name=”src”>64-bit integer value to shift.</param>
!!! <param name=”cnt”>Number of bits to shift.</param>
!!! <param name=”dest”>64-bit integer variable to store result to.</param>
i64Shift       PROCEDURE (*INT64  src, SIGNED cnt, *INT64  dest),RAW,NAME(‘Cla$i64Shift’)
i64Shift       PROCEDURE (*UINT64 src, SIGNED cnt, *UINT64 dest),RAW,NAME(‘Cla$i64ShiftU’)

!!! <summary>
!!! Shift value of 64-bit variable to left to given number of bits and store
!!! result to another 64-bit integer variable. The same variable can be passed
!!! both as a source value and as a destination variable.
!!! </summary>
!!! <param name=”src”>64-bit integer value to shift.</param>
!!! <param name=”cnt”>Number of bits to shift.</param>
!!! <param name=”dest”>64-bit integer variable to store result to.</param>
i64LShift      PROCEDURE (*INT64  src, UNSIGNED cnt, *INT64  dest),RAW,NAME(‘Cla$i64LShift’)
i64LShift      PROCEDURE (*UINT64 src, UNSIGNED cnt, *UINT64 dest),RAW,NAME(‘Cla$i64LShiftU’)

!!! <summary>
!!! Shift value of 64-bit variable to right to given number of bits and store
!!! result to another 64-bit integer variable. The same variable can be passed
!!! both as a source value and as a destination variable.
!!! </summary>
!!! <param name=”src”>64-bit integer value to shift.</param>
!!! <param name=”cnt”>Number of bits to shift.</param>
!!! <param name=”dest”>64-bit integer variable to store result to.</param>
i64RShift      PROCEDURE (*INT64  src, UNSIGNED cnt, *INT64  dest),RAW,NAME(‘Cla$i64RShift’)
i64RShift      PROCEDURE (*UINT64 src, UNSIGNED cnt, *UINT64 dest),RAW,NAME(‘Cla$i64RShiftU’)

!!! <summary>
!!! Add value of one 64-bit integer variable to another one. Possible overflow
!!! is ignored.
!!! </summary>
!!! <param name=”dest”>64-bit integer variable to increase by value of another variabke.</param>
!!! <param name=”src”>64-bit integer value to add to value of destination variable.</param>
i64Add         PROCEDURE (*INT64 dest,  *INT64 src),RAW,NAME(‘Cla$i64Add’)
i64Add         PROCEDURE (*UINT64 dest, *UINT64 src),RAW,NAME(‘Cla$i64Add’)

!!! <summary>
!!! Subtract value of one 64-bit integer variable from another one. Possible
!!! overflow is ignored.
!!! </summary>
!!! <param name=”dest”>64-bit integer variable to increase by value of another variabke.</param>
!!! <param name=”src”>64-bit integer value to add to value of destination variable.</param>
i64Sub         PROCEDURE (*INT64 dest,  *INT64 src),RAW,NAME(‘Cla$i64Sub’)
i64Sub         PROCEDURE (*UINT64 dest, *UINT64 src),RAW,NAME(‘Cla$i64Sub’)

!!! <summary>
!!! Assign sum of two 64-bit integer values to passed 64-bit integer variable.
!!! The same variable can be passed as one of operands and as a destination.
!!! Possible overflow is ignored.
!!! </summary>
!!! <param name=”op1″>First 64-bit integer operand.</param>
!!! <param name=”op2″>Second 64-bit integer operand.</param>
!!! <param name=”dest”>Variable to store the result.</param>
i64Add         PROCEDURE (*INT64  op1, *INT64  op2, *INT64  dest),RAW,NAME(‘Cla$i64Add3’)
i64Add         PROCEDURE (*UINT64 op1, *UINT64 op2, *UINT64 dest),RAW,NAME(‘Cla$i64Add3U’)

!!! <summary>
!!! Assign result of subtraction of two 64-bit integer values to passed 64-bit
!!! integer variable. The same variable can be passed as one of operands and
!!! as a destination. Possible overflow is ignored.
!!! </summary>
!!! <param name=”op1″>First 64-bit integer operand of subtraction.</param>
!!! <param name=”op2″>Second 64-bit integer operand of subtraction.</param>
!!! <param name=”dest”>Variable to store the result.</param>
i64Sub         PROCEDURE (*INT64  op1, *INT64  op2, *INT64  dest),RAW,NAME(‘Cla$i64Sub3’)
i64Sub         PROCEDURE (*UINT64 op1, *UINT64 op2, *UINT64 dest),RAW,NAME(‘Cla$i64Sub3U’)

!!! <summary>
!!! Multiply value of 64-bit integer variable by 2
!!! </summary>
!!! <param name=”v”>64-bit integer variable.</param>
!!! <returns>0 if operation successful, other value in case of overflow.</returns>
i64Mult2       PROCEDURE (*INT64 v),UNSIGNED,PROC,RAW,NAME(‘Cla$i64Mult2’)
i64Mult2       PROCEDURE (*UINT64 v),UNSIGNED,PROC,RAW,NAME(‘Cla$i64Mult2U’)

!!! <summary>
!!! Multiply value of 64-bit integer variable by 10, add passed 32-bit value
!!! and store result back to variable
!!! <param name=”v”>64-bit integer variable.</param>
!!! <param name=”inc”>32-bit integer increment value.</param>
!!! <returns>0 if operation successful, other value in case of overflow.</returns>
i64Mult10      PROCEDURE (*INT64  v, LONG  inc = 0),UNSIGNED,PROC,RAW,NAME(‘Cla$i64Mult10’)
i64Mult10      PROCEDURE (*UINT64 v, ULONG inc = 0),UNSIGNED,PROC,RAW,NAME(‘Cla$i64Mult10U’)

!!! <summary>
!!! Multiply two 64-bit integer values and store result to passed 64-bit
!!! integer variable. The same variable can be passed as one of parameters
!!! and as a destination. Possible overflow is ignored.
!!! <param name=”op1″>64-bit integer multiplier.</param>
!!! <param name=”op2″>64-bit integer multiplicand.</param>
!!! <param name=”dest”>Variable to store result.</param>
i64Mult        PROCEDURE (*INT64  op1, *INT64  op2, *INT64  dest),RAW,NAME(‘Cla$i64Mult’)
i64Mult        PROCEDURE (*UINT64 op1, *UINT64 op2, *UINT64 dest),RAW,NAME(‘Cla$i64MultU’)

!!! <summary>
!!! Divide value of 64-bit integer variable to 10 and store quotient back to
!!! variable. The remainder is stored to 32-bit integer variable. Value of
!!! remainder is positive always.
!!! </summary>
!!! <param name=”v”>64-bit integer variable.</param>
!!! <param name=”rem”>32-bit integer variable to store remainder.</param>
!!! <returns>0 if operation successful, other value in case of errors.</returns>
i64Div10       PROCEDURE (*INT64  v, *LONG rem),UNSIGNED,PROC,RAW,NAME(‘Cla$i64Div10’)
i64Div10       PROCEDURE (*UINT64 v, *LONG rem),UNSIGNED,PROC,RAW,NAME(‘Cla$i64Div10U’)

!!! <summary>
!!! Store result of division of two 64-bit signed integer values to passed
!!! 64-bit variable. The same variable can be passed as one of operands and
!!! as a destination variable.
!!!
!!! Result corresponds to value of define(compatible_modulus) pragma set to “on”
!!! </summary>
!!! <param name=”op1″>64-bit integer dividend.</param>
!!! <param name=”op2″>64-bit integer divisor.</param>
!!! <param name=”dest”>Variable to store quotient.</param>
!!! <returns>0 if operation successful, other value in case of errors.</returns>
i64Div         PROCEDURE (*INT64 op1, *INT64 op2, *INT64 dest),UNSIGNED,PROC,RAW,NAME(‘Cla$i64Div’)

!!! <summary>
!!! Store result of division of two 64-bit unsigned integer values to passed
!!! 64-bit variable. The same variable can be passed as one of operands and
!!! as a destination variable.
!!! </summary>
!!! <param name=”op1″>64-bit integer dividend.</param>
!!! <param name=”op2″>64-bit integer divisor.</param>
!!! <param name=”dest”>Variable to store quotient.</param>
!!! <returns>0 if operation successful, other value in case of errors.</returns>
i64Div         PROCEDURE (*UINT64 op1, *UINT64 op2, *UINT64 dest),UNSIGNED,PROC,RAW,NAME(‘Cla$i64DivU’)