|Symmetry Group Introduction| |SLATE Introduction| |SLATE| |SLATE with Graphics| |SLATEUTL| |SCRIPT| |S_PRINT| |Supported Printers| |Compilers Supported| |License Agreements| |Terms and Conditions| |Price List and Ordering Information| |Support@SymmetryGroup.com|

Technical Support FAQs

As always, our Tech Support Department stands ready to help with any problem you may have with our products. Support@SymmetryGroup.com

|Message Handling System| |Justified Text| |Configuration| |D Group and Huge Model| |Stack Overflow| |Porting SLATE to Other Platforms| |Porting SLATE to Turbo Pascal|

Message Handling System

Below is described the process that SLATE uses to display messages and the requirements for a Replacement Message Display routine. It also describes how to intercept fatal errors. See the Message System appendix for more information.

Operation: When SLATE encounters a problem with the printer (printer busy, off line, out of paper, etc.) it sends an error message to the Message System such as Error - Printer Busy, A to abort, I to ignore. The message system displays the message and returns. SLATE starts a polling loop where it first tests the printer for errors and then tests the keyboard for an A or I.

If the printer error goes away, SLATE sends the message Printer OK. It then sends a null message (pointer to an empty string) to the message system and SLATE continues.

If an A is entered, the message Fatal Error - Aborting is sent. The Message System displays the message and calls the exit() routine unless fatal error trapping has been enabled.

If an I is entered, the output to the printer is turned off. SLATE continues but all printer output is ignored.

Critical Errors: The Printer error messages do not come from the Critical Error Handler. The su_seset() function installs the Symmetry Critical Error Handler. The Critical Error Handler traps critical errors caused by SLATE operations and forces DOS to return with an error code. SLATE then responds with error messages via the Message System if necessary.

Critical errors not caused by SLATE are passed through to the previous Critical Error Handler. See the Critical Error appendix for details.

Replacement Message Display Routine: If a screen handling system or GUI is being used, the Message System output must be routed to a Replacement Message Display routine provided by the developer. This routine is described in detail in the Message System appendix (su_mddef() and rep_mdsp()). A sample routine is shown in the examples at the end of the appendix.

NOTE: When Functions Pointers are passed to SLATE routines, the functions must use the C Calling Convention. (Use the cdecl and/or the C keyword.)

The Replacement Message Display routine must be designed to match the Screen Handler and the specific design of the screen. In general it should do the following:

Test for a message box (use a global or static flag). If the box is not displayed, create and display it.

If the Message is null (a pointer to an empty string), remove the message box. (A delay may need to be introduced to allow the user time to read the previous message.)

Otherwise, display the Prefix and the Message. If desired, the Message Type can be used to select the message color and send a beep.

If the type has the 0x80 or 0x100 bit set, the cursor may want to be displayed after the message to indicate to the user that data may be entered.

However, do not wait for keyboard input! The Message Display routine only displays messages. It must return immediately after displaying a message. Other processes take care of responses if necessary.

At the end of printing or aborting, remove the message box if it is still displayed.


Replacement Keyboard Response Routine: In most cases the Keyboard Response routine will not need to be replaced. Only those systems that need to allow mouse input or need to change the A or I control need to replace the Keyboard Response routine. The details of this operation are shown in the Message System appendix (su_mkdef() and rep_mkey()).

NOTE: When Functions Pointers are passed to SLATE routines, the functions must use the C Calling Convention. (Use the cdecl and/or the C keyword.)

The Replacement Keyboard Response routine should do the following:

Test for keyboard input. If a keyboard character is available, it should be retrieved. Do not wait for keyboard input! Other processes will continue to test for keyboard input.

In the simplest form, if a keyboard character was retrieved, it should be returned. Otherwise, zero should be returned.

For mouse systems, the Message Display routine should be modified to display a mouse target. After testing for a keyboard character, the mouse should be tested. If the proper mouse operation is detected, an A should be returned.

To cause an I to abort rather than retry, test for an I and if detected, return an A.

The Message System takes care of clearing the Keyboard Buffer before prompting for a response.

Trapping Fatal Errors: In most/all cases, the default exit on Fatal Error should be replaced. (If only to close SLATE and cleanup the application before exiting.) This is accomplished with the Set Message Longjump su_meset() function described in the Message System appendix. Most demo programs include this function. For more detailed information on the Longjump see setjmp() and longjmp() in the compiler library manual or in any good C programming text.

However, a few precautions need to be followed:

The su_meset() function only should be called in an if or switch statement. The code should not attempt to capture the return code and use it later. Compilers are only required to work with the if and switch operations. (See the ANSI C specifications.)

Within the subroutine where su_meset() is called, do not return until printing has completed, SLATE is closed, and su_meclr() has been called! The su_meset() function (or setjmp()) saves the machine state (segment registers, program counter, stack pointer, and other registers). The su_mejmp() function (or longjmp()) restores the machine state.

If the subroutine that calls su_meset() returns, the stack will no longer contain a valid return address. If su_mejmp() is subsequently called by SLATE, control will transfer to the point where su_meset() was called. However, when the that subroutine returns, the stack will no long contain a valid return address and control will be lost.

In an overlayed application, additional precautions must be observed. They are completely described in the Overlays section of this chapter.

These precautions should cause little difficulty. The su_meset() function is usually called at the subroutine level where printing is selected. If a fatal error is detected, SLATE should be closed with sl_close() or sl_abort(). Usually internal operations should be cleaned up, a message indicating that printing was aborted should be displayed, and a new menu displayed.

Justified Text

This explains how to generate fully justified (both right and left) text with SLATE. It also addresses some of the more complex issues in building a robust justification program.

NOTE: The demo programs with SLATE show how to right justifiy words or short strings. They also demonstrate building full lines without full justification.

Simple Justification:

This discussion assumes that the text is available from an input stream. It further assumes that it is to be printed with a single font.

First determine the printed width of the text. In most cases, set the right and left margins to the starting and ending positions.

Build a line of text by getting the input text a word at a time. Test to see that the length of the text is less than the printed width. Use sl_stst() to test the width.

Output the first word with no following space. Use sl_sprn().

Now start a loop.

Determine the length of the remaining text with sl_stst(), the available space with sl_hsget(), and the number of word spaces (the same as the remaining words). Divide to get the target word space. (Be sure to take into account the spaces in the string.)

Output the word space with sl_hsprn(), and the next word.

Return to the beginning of the loop if there is more to print.

Continue with the next line.

The rather complex loop is required because the positioning increment is finite. If a single calculation of the word space is done, the positioning errors are likely to accumulate to cause an unsightly raggedness on the right.

Refinements:

When calculating the word space, truncate to an actual width using sl_higet(). This will prevent the last word from extending too far.

There is probably some limit beyond which the word space should not be adjusted. Rather, the nominal word space should be used.

The last line of a paragraph may not want to be adjusted.

Some provision for sentence spaces must be made. This also complicates the line building function. It may be better to save the line as an array of words.

Spaces between letters may also want to be adjusted using sl_hlset(). (Use this with care, it usually doesn't look very good.)

Changing the Font within the line complicates things. This probably requires storing the individual words, their Font, and their width (in that Font).

To do a good job, particularly on short lines, some sort of hyphenation needs to be available. Special care needs to be taken with hyphenated words to put a hyphen at the end of the line and the start of the next line.

Paragraph indentation also can cause some difficulty.

Configuration

Did you know that operation of the slate and sl_test programs as well as many other SLATE features are controlled by the setup strings section of the printer database?

Setup strings were introduced in SLATE 2.2 to provide a simple way to configure a number of SLATE features to match your application. The details are in the SLATE Reference Manual in the Setup Strings section of the Editing Tables chapter.

To view the current setup strings, run the slate program. If the Main Menu screen is not displayed, you have just experienced a setup string configuration. Exit the program and restart it with the -D option.

When you get the Main Menu, select Add/Edit Tables to get the Tables Menu. Select Setup Strings to get the Setup Strings List.

You will see a number of setup strings that control default behavior. If you had to use the -D option to get to the main menu, you will see that the SLATE Defaults has -D set. In the slate program description, you will see that the -D option causes the program to start in the Device List screen rather than in Main Menu. The additional -D that you added toggled this feature back off.

You will want to review each of these strings to make sure that they are appropriate for your application. Note that there are setup strings to set search paths for several types of files, set the default behavior of the slate and sl_test programs, set the default paper size, and set the developer name displayed by the slate program.

The sl_tsget() function allows the application to access these strings. The sl_tsset() function (available in SLATE 2.2.7) allows the application to override the values in the printer database.

D Group and Huge Model

In the large data models, most C compilers keep all data variables in a single segment (DGROUP). It is not difficult to exceed the 64K segment limit. There are several solutions to the DGROUP exceeds 64K error:

Where available, the huge memory model can be used. While this may be easy, it is often not the best solution. Because extra code must be generated to load the segment registers and to test for arrays that exceed 64K, the code size will increase and the speed may decrease.

Often the best solution is to move a few of the larger data arrays and structures out of DGROUP with the far option in both their definition and declarations.

If text strings are the major contributor to DGROUP overflow, some compilers provide an option to move text strings to the code segment.

Many compilers have an option to move data items larger than a specified limit out of DGROUP. This is usually a bad idea. Unless every module (including each module in every library) is compiled with the same limit, it is possible for data to be in located in far memory and to be addressed in near (DGROUP) memory. This is a rich source of memory overwrite errors.

Stack Overflow

If your SLATE application hangs or prints incorrectly when a particular printer is selected, the printer becomes busy, a particular output mode is selected, or a new version of SLATE is linked, you could be experiencing a stack overflow.

The SLATE library has been compiled with stack checking turned off to reduce the size and improve the speed. As a result, exceeding the stack space can overwrite SLATE variables without any warning. This can result in strange behavior or even hanging.

SLATE needs about 4K of stack space in addition to any stack used when SLATE routines are called. The default for some compilers is only about 2K. Many linkers allow the stack size to be specified with the /ST:n command. Some compilers require a global variable to be set to change the stack size.

If you suspect that the stack is overflowing, add 4K to the stack size and try again. You can also use the debugger to initialize the upper part of the stack space and look later to see exactly how much stack has been used.

Porting SLATE to Other Platforms

Libraries: SLATE is provided in three or four libraries. The slate.lib library is written almost entirely in C. The only exceptions are some functions used to access the Parallel and Serial ports via BIOS. This library uses no special tricks and should port rather easily.

The optional slategph.lib library is written almost entirely in C. A few routines are provided in both C and Assembler. The Assembler versions are optimized to make graphic printing faster. This library uses no special tricks and should port rather easily.

The sutil.lib library is a collection of general purpose functions. It is written in both C and Assembly. Additionally, there are many modules in the library that are not used by SLATE. A link map from a DOS version of the application will show the modules that will need to be ported. In most cases, the assembly routines interface with DOS or BIOS. They can usually be replaced with C library functions.

The SMEM system is a special case. It will be discussed later.

The sfile.lib library is the Database that is used by SLATE to store Printer specifications.It is written entirely in C. However, it will not port without some significant work. It will be discussed later.

Source Code: Each source code module has a text header that describes the operation of each function in the module, the calling parameters, and the returned data. Complex functions may have additional information or literature references.

In most cases, the Assembly routines can be rewritten from the header data. The actual assembly language code can usually be ignored.

Version: The latest version of the source code should be obtained before attempting a port. It may also be useful to discuss the port with Tech Support to make sure that no significant changes are in process.
Areas of Special Concern: There are several areas of special concern.

SFILE: The SFILE system is a special purpose hierarchical database. It has a rather complex file structure to support the owner to member structure of the data. In addition, all data transfer is controlled by a file access table.
The difficulty in porting comes from loading C structures directly with disk reads (and writing structures directly to disk). The current system assumes byte alignment and Intel data ordering (little endian). Many platforms require word or double word alignment in C structures. Additionally, they may store multi byte data with the most significant byte first (big endian).
These platforms will require modification to include information about the contents of C structures in addition to their location that is now stored in the file access table. This will allow the disk data to be loaded into the structure properly.
The organization of the SFILE system is described in the SFILE Reference Manual. This is available upon request to source code licensees of the SLATE System.
SMEM: The SMEM Memory Management System may also provide some difficulty. It is a general purpose Memory Management System that allocates and accesses memory in much the same way as files are allocated and accessed. It comes with support for malloc, direct DOS allocation, EMS, and Disk Buffering. Additional support can be handled.
The Text Mode SLATE system can be supported quite nicely with the malloc system. Only small amounts of memory are required. Speed is not a big issue. It should be able to be ported with all changes done in C.
SLATE with Graphics may need to allocate large amounts of memory. Additionally, the speed is quite critical. Some assembly will probably be required to provide adequate performance. Some ports may need to handle the segmented memory for large data allocations. (There is adequate space in the data structures for 32 bit memory systems, however.)

Porting SLATE to Turbo Pascal

SLATE is written in C. It is compatible with all Borland C and C++ products.

However, Turbo Pascal does not allow the use of industry standard libraries. In addition, it has different subroutine calling conventions.

This will require that the entire SLATE package (about 200 modules) to be compiled with the Pascal Flags. The assembly routines will need to be forced to follow the Pascal calling convention. The resulting object files must be individually converted and put into a Pascal Unit.

SLATE uses some C library functions. These library functions will need to be replaced.

In some cases, the SLATE functions are actually C Macros. These will need to be replaced with Pascal Macros or functions.

Finally, the Pascal equivalent of an include file will need to be created to allow access to the SLATE functions and their parameters.

Due to the complexity of the project, we cannot recommend SLATE for use by Turbo Pascal users.