Techtips

Practical Tips and Scripts

Here we share practical tips, instructions, and solutions for common questions about our software. Need a quick answer? You might already find it here.

Tech Tips Topics

Tech Tip of the Season

Starting debugging windows from the application To make the debugging windows appear from within an application, the following code is often used:
PREINPUT -1300; ESCAPE ! Opent het TRACE venster 
PREINPUT -1301; ESCAPE ! Opent het COMMAND venster 
PREINPUT -1302; ESCAPE ! Opent het WATCH venster 
PREINPUT -1303; ESCAPE ! Opent het BREAK venster


This code works only in a Windows ProvideX/Plus session – in a WindX environment these commands will not result in opening the corresponding debug window. Therefore, it is recommended to change this code to:

 


PRINT 'OPTION'("DebugWindow","Trace"),
PRINT 'OPTION'("DebugWindow","Command"), 
PRINT 'OPTION'("DebugWindow","Watch"), 
PRINT 'OPTION'("DebugWindow","Break"),

When using WindX, it is advisable to start the Trace, Watch, and Break windows so that they monitor the application on the server side. This can be done by placing the word “Host” before the name of the debug window, for example:
PRINT 'OPTION'("DebugWindow","Host Watch"),.

To connect a debug window to the server application after it has already been started, send:
PRINT 'OPTION'("DebugWindow","Host Trace Enable"),.

Variables to be monitored and break instructions can also be loaded into the debug windows using the ‘OPTION’ mnemonic. For example: PRINT 'OPTION'("DebugWindow","Host Watch Add A$"), will add the variable A$ to the Watch window, and PRINT 'OPTION'("DebugWindow","Break Add Test=LEN(A$)>0"), will load a break that stops the application as soon as the length of A$ is greater than 0.

For a complete overview of all possibilities regarding debugging windows, refer to the ProvideX Language Reference PDF (v9.10) under 5. Mnemonics / OPTION.

Note: To use the ProvideX/PxPlus debugging windows, the INI file in use (use PRINT ARG(-1) to see which file you are using) must contain a [Config] section with Debug=1 (without quotes).

Extreme Makeover Techtip

Want to quickly and easily give your application a new look? With “Themes” and “Visual Classes” you can. Themes are the former Templates. They determine the appearance of objects throughout an entire library. Therefore, they are set in the library defaults.

Visual classes apply to a single object. You have to set them individually for each object. In this example, we’ll work only with buttons, but other objects can be used as well.

We’ll take these buttons as an example:

Font: Arial, 20 points
Foreground: default
Background: default


We will now create a “Theme.”
To do this, start Nomads and choose in the menu: Options > Themes.

 

Choose the name “T1” and control type: Button.

You will see several extra options that are normally not available for a standard button.
For example, “Hover Border Color”.
The goal is to have a red border around the button when you hover the mouse over it. In this example, a few other colors are also shown.
This theme “T1” is linked to our library via Library Defaults.

Choose TAB ‘Font/Clr’ and select T1

Now, when we start the panel with buttons and move the mouse over them,
we mainly see that the buttons get a red border. You will also notice a different font size,
different colors, and sharper corners. All buttons in all panels now have this look.
Sometimes, however, you may want certain buttons to look different. That’s why we have Visual Classes.
Go back to the main screen, choose menu > Options > Visual Classes.
For the name, choose “BLUE”, theme: “T1”, control type: Button.
The same properties as in a theme will appear again.

Now, we want a flat, transparent button with a dark blue background and red text when it has focus,
and dark red text when you hover the mouse over it.

You will probably need to try several settings through trial and error.

Save these settings and then, in our panel, set this Visual Class “BLUE” for each button.
Choose the properties of your button, go to the Font/Clr tab, and select “BLUE” under Visual Class.
We will do this for the “auxiliary” and “parameter” buttons, but not yet for “exit”, to clearly see the difference.

Restart the panel.

When you hover the mouse over “parameter”, this is the result:

NomadsPlus Techtip

You are probably familiar with the difference between folder style and property sheets when editing in Nomads.
Some users prefer the first method, others the second.
Now there is a third option: Nomads+.

Nomads+ is essentially a combination of both.

How can you choose between ‘Nomads+’, ‘Folder style’, and ‘Property sheets’?
When editing a panel, go to the Utilities menu, and at the bottom of the dropdown you will find the three options.
So, we choose Nomads+.

As mentioned, there is a grid table with certain properties such as control name, text, position and size, tab stop, tab order, etc.
These properties can be edited in sequence directly within the grid.

All other options can be changed via a classic dialog window.
It can feel a bit cluttered on a small screen. The easiest solution is to use a second monitor, for example to park the screen with the Nomads+ toolbar, so your main screen is free to design a panel. Fortunately, it remembers its last position.

You can have multiple panels open at the same time. Each panel and toolbar has its own specific background color and ID number, so you won’t confuse which toolbar belongs to which panel.

In short, it’s worth trying a different editing style to see what works best for you.

IDE Techtip

Have you tried the new IDE yet?
IDE stands for Integrated Development Environment, and it’s extremely useful for developers. All the tools available in PxPLUS are conveniently gathered here in one place.

How to start IDE?
In console mode, type:

IDE

or via a shortcut:

E:\PvxPLUS12\pxplus.exe *ide/launcher

You will then see this screen:

Note that packages or options that are not accessible are marked with a small red minus sign, such as in the example above on the right — ‘myTiles Tile Creator’.

You’ll also see “Projects” at the top. Here you can create multiple projects. Logically, you can group categories per directory. For example: Accounting, Invoicing, Payroll Administration, etc.

At EDIAS, each customer has their own directory. For each customer, a project is created and linked to that directory.

If we now start Nomads from the project of customer X, the correct directory is automatically active.

The ‘Tasks’ Screen
(Enable ‘display tasks’ at the bottom of the main screen.)
This screen has two tabs: History and Project.

History shows the list of recent tasks you have performed — even from other projects. The list updates automatically when you edit a program in IT, edit a panel in Nomads, and so on.

Project shows all panels, reports, programs, etc., belonging to the active project.

Adding Panels, Reports, and Programs to a Project
In many tools, you will now find a ‘Projects’ menu item.

For example, in Nomads, you can choose whether to add only the selected panels or all panels to a project.

Also try selecting an option from the list of applications in the main window and enabling ‘Display Help’. You will then see the correct contextual help for the selected module.

Changes in IT (Program Editor)
In IT, the former “workspaces” are now called “projects.”
Here, too, all items from all projects are available — including Nomads panels and more.

Summary:
It’s worth exploring this new IDE method. It can save you a lot of time as a developer.

PxPlus Version 2014 (v12) Windows activation

Starting with this version, the ACTIVATE.PVX file is placed in a "PXPKEYS" directory, located one level higher than the PxPlus installation directory.
For example, if PxPlus is installed in the default directory: C:\PVX Plus Technologies\PxPlus 2014 then the activation file will be placed in: C:\PVX Plus Technologies\PxpKeys.
This means the activation is no longer tied to a specific PxPlus version, allowing different PxPlus versions (whether installed simultaneously or not) to use the same activation.

You can always refer to a specific activation by using: ActivationKey=path_to_directory_with_activate.pvx inside the [Config] block of the INI file, for example: [Config] ActivationKey=D:\PxPlus\pxpkeys
If you upgrade an existing Windows PxPlus installation to v2014 and a lib\keys directory from an older installation already exists, v2014 will continue to use that activation and will not create a pxpkeys directory.

Similarly, Unix and Linux v2014 versions will continue to use the activation in the lib directory (regardless of whether it was an upgrade or a fresh installation).

Logfile

Starting with PxPlus Windows version 11, you can add a LOGFILE= entry in the [CONFIG] section of the INI file. LOGFILE= should point to an existing path, for example: LOGFILE=D:\tmp\logv11.txt

The path D:\tmp must already exist; the text file logv11.txt will be created if it does not yet exist. If PxPlus encounters an internal error, it will write one or more entries to the log file. Additionally, if PxPlus is terminated by the operating system (for example, by accessing a memory location outside PxPlus memory space, resulting in the well-known "PxPlus has stopped working" message), this will also be recorded in the log file. This allows you, in the event of a PxPlus crash, to determine the exact point in the application where the issue occurred.
Each log file entry follows this structure: Date Time [Program:line] Description of the problem

Example:


Aug 13 16:52 [D:\pxplus\pxp7\misc\zip_format.pgm:160] *OUT OF MEMORY* - Global Alloc failed
Aug 13 16:52 [D:\pxplus\pxp7\misc\zip_format.pgm:160] *OUT OF MEMORY* Unable to allocate 
  1760559116 bytes
Aug 14 13:40 [*plus/web/request:120] [TCP][Winsock]Error status:10035(796:)
Aug 19 09:44 [D:\pxplus\pvxplus11\misc\blobtest.pgm:200] Fatal exception error code 
  c0000005 occurred
Aug 19 09:44 [D:\pxplus\pvxplus11\misc\blobtest.pgm:200] - ERR=0 CTL=0 RET=258 LFA=1 LFO=1
Aug 19 09:44 [D:\pxplus\pvxplus11\misc\blobtest.pgm:200] - Last path used: [MySQL]mysql;
Aug 19 09:44 [D:\pxplus\pvxplus11\misc\blobtest.pgm:200] - Program stack follows:
Sep 18 09:59 [*winlist:5193] *MEMORY LIMIT HIT* - About to report an error 31
Dec 17 09:17 [webreq:12240] SSL Chkerror socket 488 sts 0 yields 5
Dec 17 09:17 [webreq:12240] [TCP][Winsock]Error status:10035 (488:)
Jan 13 09:12 [*ezweb/server:444] * Error:404 Not Found Request:/favicon.ico
Jan 13 09:12 [*plus/winutl/winqry:1615] Skipping ref to control 0 (Disable) at 
  1615:D:\PxPLUS\PvxPlus11.5\lib\_plus\winutl\winqry (255:D:\PxPLUS\PvxPlus11.5\lib\_winlist)
Jan 13 09:14 [*ezweb/server:36] Shutting down *ezweb/server

You can also create entries in the log file directly from your application by using SETTRACE RECORD.
For example: SETTRACE RECORD "OOPS" in console mode will result in the following entry:
Jan 20 13:37 [:0] OOPS

Starting with PxPlus 2014 v.12, this functionality is also available in Unix and Linux PxPlus versions. To activate the log file in Unix/Linux, create a file named pvxtrace.log in the PxPlus directory. If PxPlus v.12 detects that this text file exists, it will automatically use it to store internal messages.

PxPLUS simple Client/Server

PxPLUS has developed an alternative to *NThost/NTslave.
The advantage is that the host only needs one TCP socket.
This is particularly useful when using the Internet, as you only need to open one port in your firewall.
PxPLUS uses 4093 as the default port. This port has been officially assigned to them by IANA (Internet Assigned Numbers Authority).

Starting the host
Save the following script as /usr/local/bin/starthost on your Unix machine:

#!/bin/sh
PVXLIB=/pxplus/lib
PVXFLMAP=\\/
export PVXLIB  PVXFLMAP
umask 0
cd /pxplus
{su username}
/pxplus/pxplus -dr=/pxplus/ *plus/cs/host -arg 4093 {forced program} >/dev/null &1
and change the permissions with chmod 777

Add the following line to /etc/inittab on the Unix machine:

pxp1:2345:respawn:/usr/local/bin/starthost /dev/null 2>&1

Note for SCO OpenServer 5 users:
– Insert this line right below the r3 line.
– If the kernel is rebuilt or relinked, SCO will remove this line from /etc/inittab!

Run telinit -q. The PxPLUS host will then start.
On some Unix machines, it may be necessary to reboot the system so it recognizes the updated /etc/inittab.

If you are using a Linux OS, you will see that the inittab file is no longer used.
To still have the script start automatically when the machine boots, do the following:

There is a /etc/init.d/boot.local script.

Add the following line to this script:

sudo -uuser /usr/local/bin/starthost &

There is a /etc/rc.d/rc.local script.

Add the following line to this script:

su user -c /usr/local/bin/starthost &

(user is the name of a user who can log in and run PxPLUS)

If you want the host to start automatically under Windows, use *plus/cs/service.
The program will then ask for the starting directory, which port to use, and which program to run.
Afterwards, you will need to change the startup setting for the service from manual to automatic.
Starting the Client

Create the following shortcut in Windows to establish a WindX connection:

Target:

C:\pxplus\pxplus.exe *plus/cs/client -id=Txx -arg xxx.xxx.xxx.xxx[;ssss] [progname]

Start in:

C:\pxplus

Run: Minimized

xxx.xxx.xxx.xxx is the IP address of the host machine.

ssss is the socket number of the task on the host. Default = 4093.

-id=Txx is the FID(0) value of PxPLUS on the host computer.

progname is the name of the program that will start as soon as the connection is made. If left blank, PxPLUS will start in “console mode.”

If you want to start multiple tasks from within a program, do not use the START command, but instead use the utility specifically made for this:

*windx.utl

with the label spawn.
Example:

CALL "*WINDX.UTL;SPAWN" [,programname]

ODBC 64 / 32 bit drivers

The PxPLUS ODBC driver supports two types of connections:

a) A simple connection, where the ODBC driver runs on the workstation and only has access to local files or files accessible via a shared drive.

b) A server connection, where the ODBC driver connects to the ODBC file server on another computer, receiving data from that file server.

There are workstation ODBC drivers available in both 32-bit and 64-bit versions.
The 32-bit driver can be installed and used on both 32-bit and 64-bit Windows systems.
The 64-bit driver can only be installed on a 64-bit Windows system.

The 32-bit driver can only be used by a 32-bit application, and the 64-bit driver can only be used by a 64-bit application.
Example: If you have Office 64-bit, this product can only retrieve data from a 64-bit ODBC driver.
PS: Microsoft still recommends using the 32-bit version of Office on both 32-bit and 64-bit Windows systems.
See:
Microsoft Office 2010 FAQ

The standard Windows "ODBC Data Source Administrator" program only recognizes ODBC drivers of the same type as the Windows OS.
In other words, the Data Source Administrator on a 64-bit OS only uses 64-bit ODBC drivers.
To configure 32-bit ODBC drivers on a 64-bit OS, you must run the ODBCAD32.EXE program (found in \Windows\SysWOW64\).
PS: We automatically create a link to the correct configurator for the user.

When establishing a connection between an ODBC driver and an ODBC file server ("b" in item 1 above), the driver type (32-bit or 64-bit) is irrelevant to the file server type.
All communication between driver and server takes place over TCP/IP.
In short, a 32-bit ODBC driver can connect to a 64-bit ODBC file server and vice versa.

Window’s Printer Mapping to a PxPLUS Device Driver

A new feature has been added in PxPLUS v6.10, where a Windows Printer may be defined on a PC so that it appears in the Windows Printer Selection Dialogue, and if that printer is selected from within a PxPLUS session, then PxPLUS attempts to re-route the printer to a device driver.

This allows Developers to create Windows Printer’s on workstations for items such as the Preview, PDF, or HTMLoutput from PxPLUS.

This feature works based on the name and properties of the printer.

 

  • The printer must have an output port of “NUL:”
  • The second word in the Printer’s Name, will be parsed out and an underscore will be added to the beginning and end of the name. The PxPLUS LIB directory will be scanned for a device driver that matches this name. If the device driver is not found, then the printer will not be mapped anywhere, and will simply output to NUL. EXAMPLE:
    Printer Name:   “PxPLUS Viewer”
    A search of the PxPLUS Lib Directory for “_viewer_” will be made.EXAMPLE:
    Printer Name:   “PxPLUS PDF”
    A search of the PxPLUS Lib Directory for “_pdf_” will be made.Follow the next steps to add such a Printer to a Windows XP Workstation:
  1. Go to Window’s Printer’s and Faxes.
  2. Select “Add a printer”.
  3. Select “Local printer”.
  4. Check the “Use the following port” for an entry of “NUL:”.
    if “NUL:” exists, select it and go to Step 8.
  5. Select “Create a New Port”.
  6. Set the “Type of Port” = “Local Port”.
  7. For “Port Name” enter “NUL:” (without the quotes).
  8. From the manufacturer / printers dialogue, select “Generic” for a manufacturer and “Generic/Text Only” for the printer.
  9. Select “Keep existing driver”
  10. Enter a name for your printer, keep in mind, that the 2nd word in the name is what must match the device driver.
    For this “Printer Name”, enter “PxPLUS Viewer”
  11. For the “Set as default printer”, select “No”.
  12. For “Sharing”, select “No”.
  13. For “Print a test page ?”, select “No”.
  14. Check your settings and Select “Finish”.

You should now have a printer named “PxPLUS Viewer” as one of this workstation’s printers. From within any PxPLUS application, you will see this printer in the *WINPRT* printer selection dialogue. Whenever this printer is selected, PxPLUS will re-route the printer to the specific device driver.

In the case of our example, we have created a printer named “PxPLUS Viewer” which is connected to “NUL:”. If selected from Printer Selection, PxPLUS will automatically close “*WINPRT*” and open the file “*VIEWER*” instead.

NOTE: This will ONLY work in PxPLUS applications!
If the user selects one of these special PxPLUS mapped printers from another application (Word, Notepad, etc.), they will get NO output.

How PxPLUS searches for and finds your files and programs

First, let's go over the commands, functions and parameters related to finding files.

'CD' parameter.
The 'CD' parameter is set to 'OFF' by default, which means that the current directory will only be searched after the directories in the PREFIX list.
If the parameter is 'ON', PxPLUS will first look in the current directory, and only then in the PREFIX list.
(see also 'Search Rules')

To check the content of the parameter: PRINT PRM ( 'CD' )
and to change the parameter: SET PARAM 'CD' = 1 (or 0)

PREFIX
You can compare the PREFIX command to the PATH variable in MS-DOS or UNIX.
Use the PREFIX command to specify a series of search paths where PxPLUS should look when you perform an OPEN / LOAD / RUN / CALL / PERFORM on a file or program without a full path name.
Example:
PREFIX “/usr/mydir/data/ /usr/mydir/prog/ /usr/mydir/sub/ D:/other/data/”

In other words, if you open a file with a full path name, the search rules do not apply.

The names in the PREFIX must be separated by a space.
As you can see, the drive letter may be added to the path name in order to search on a drive other than the one made active with the SETDRIVE command.

You can specify 10 different PREFIXes, namely PREFIX (0) to PREFIX (9).
Example:
PREFIX (0) “/usr/mydir/data/”
PREFIX (1)”/usr/mydir/prog/ /usr/mydir/sub/”
PREFIX (2)”D:/other/data/”

The advantage is that you can DISABLE and ENABLE a specific PREFIX.
e.g.: DISABLE 2, and you stop searching in D:/other/data/.

PREFIX (0) ” … ” is the same as PREFIX ” … ”

If there are path names that already contain a space, you must enclose that path name in quotation marks.
Example:
PREFIX “C:/Tmp/ C:/usr/ “”C:/Program Files/”””

PRINT PFX or PRINT PFX (n) shows the content of PREFIX.

' = ' sign for special search operations.
The '=' sign in the PREFIX has a special meaning. Each '=' sign corresponds to a letter (or digit) of the file name and is replaced by it. The first '=' sign is replaced by the first letter of the file name, the second '=' by the second letter of the file name, and so on.
The idea is to divide large directories into smaller ones for faster access and better management.

Example:
Suppose your application consists of several modules. From the name of a program, you can already see to which module it belongs.
e.g. BH001 BH002 BH003 belong to the accounting module and LN001 LN002 LN… belong to the payroll module. You can then split your (large) directory into several smaller directories. The name of these subdirectories must match the first letters of the module names. In this case BH and LN.
If PxPLUS now searches for a program or file, it evaluates the first matching letter(s) and uses them to look in the correct directory.
Example:
PREFIX “/myapp/==/”
OPEN (1)”BHHIST”
PxPLUS evaluates the file name BHHIST and turns it into ‘/ myapp / BH / BHHIST’ (1), and thus tries to open the file.

Asterisks as PREFIX wild-cards.(2)
You can use '*' and '**' as wildcard characters in PREFIX to support (new) file name extensions without having to change your programs.
This extension was introduced in version 4.20 mainly to be Windows 2000 certified. To be Windows 2000 certified, your files and programs must have an extension. With the wildcard characters in PREFIX you can give your files a specific extension without having to change your programs.

A single asterisk (*):
If your PREFIX command contains an asterisk followed by an extension, PxPLUS will replace this asterisk with the file name you are trying to open.
With the result, PxPLUS will then try to find the file, and if not found, it will still try to open the file without an extension.
Example:

PREFIX (5) “*.dat”
OPEN(1)”customer”
PxPLUS scans the directory for ‘customer.dat’ and opens the file. If ‘customer.dat’ is not found, PxPLUS continues searching for ‘customer’. If found, PxPLUS opens the file; if not, PxPLUS generates an ERROR 12.

Note!
KEYED “abcde”,5 will not create the file ‘abcde.dat’ but will create ‘abcde’, and
ERASE “abcde” will erase the file ‘abcde.dat’!

Double asterisks (**):
If your PREFIX contains two asterisks together with an extension, then the substitution described above will only occur if the file name in the OPEN command does not already have its own extension. If the name already has an extension, no automatic replacement will occur.
Example:
PREFIX “/mydir/**.dat”
OPEN(1)”journal”
OPEN(2)”journal.hist”
Since ‘OPEN (1)”journal”’ is a file without an extension, PxPLUS will first look for ‘/mydir/journal.dat’ and then for ‘/mydir/journal’.
Since ‘OPEN (2)”journal.hist”’ already has an extension (.hist), PxPLUS will not add ‘.dat’ and will simply look for the file ‘/mydir/journal.hist’.

PREFIX PROGRAM
Use the PREFIX PROGRAM format to define a search path specifically for programs. PxPLUS will first search in this path, and then possibly in the other PREFIXes, if you perform a LOAD, RUN, CALL, PERFORM, PROGRAM or SAVE.
Example:
PREFIX PROGRAM “/pvx/mydir/pgm/”

to see the content:
PRINT PFX(PGN)

PREFIX FILE
This is not the counterpart of PREFIX PROGRAM!

Use the PREFIX FILE format to perform dynamic conversions of file names. For example, you may have programmed an ‘OPEN(x)”customer”’, but actually want to open “//other_machine/customer”.

How does it work? You define a KEYED file with an external key and a variable record length. If the file does not meet these requirements, you will get an ERROR 17:Invalid file type or contents.
The key is the name as it appears in the program, e.g. “customer”.
The first field is the name of the replacement file, e.g. “//other_machine/customer”.
Then execute the command: PREFIX FILE “PFXFILE”

When opening, PxPLUS will first check this file to see if the file name you want to open exists as a key in this file. If so, the field is used as the file name and all search rules apply again.
Remember that the search mechanism only applies if a relative file name is given. File names with absolute paths are opened immediately without searching.

Example:
KEYED “pfxfile”,25
OPEN(1)”pfxfile”
WRITE (1,key=”customer”)”[odb]ACCESS;CUST;KEY=CUSTNO”
CLOSE(1)
……
PREFIX FILE “pfxfile”
OPEN(1)”customer” ! Internally becomes
>> OPEN(1)”[odb]ACCESS;CUST;KEY=CUSTNO”

As you can see, it is very easy if you want to switch databases. You only need to change the keyed file; your programs remain unchanged.

Since version 4.23, a second field has been added to the PREFIX FILE file.
This is an OPTIONS field. These options are added to the OPT= when opening the file. This was done because the length of the name has a limit of 256 bytes.

Example:
The PREFIX FILE file contains the following:
Key=”customer”, Field1=”[ODB]DSN;customer”, Field2=”KEY=cust_id”

OPEN(1)”customer”
internally becomes:
OPEN(1,OPT=”KEY=cust_id”)”[ODB]DSN;customer”
or …
OPEN(1,OPT=”REC=customer_name”)”customer”
internally becomes:
OPEN(1,OPT=”KEY=cust_id;REC=customer_name”)”[ODB]DSN;customer”

The content of OPT= is in fact appended to the name, resulting in:
OPEN(1)”[ODB]DSN;customer;KEY=cust_id;REC=customer_name”

PRINT PFX(-1) shows you the PREFIX FILE file.

SEARCH RULES
PxPLUS searches for a file or program in this order:

OPEN
1) PREFIX FILE, if used. (Replaces the path name and continues the sequence)
2) Current directory (if 'CD' parameter is on)
3) PREFIX 0 to 9
4) PROGRAM PREFIX, if used
5) Current directory (if 'CD' parameter is off)

LOAD / RUN / CALL / PERFORM / SAVE
1) PREFIX FILE, if used (Replaces the path name and continues the sequence)
2) Program Cache
3) Current Directory (if 'CD' parameter is on)
4) PREFIX PROGRAM, if used
5) PREFIX 0 to 9
6) Current Directory (if 'CD' parameter is off)

The PREFIX search rules apply not only to opening files but also to creating them. PxPLUS will create the file in the first path of the first PREFIX. If 'CD' parameter is on, files are created in the 'active' directory.
Note that once a program is in 'cache', and if you disable the PREFIX from which the program came, PxPLUS will still retrieve the program from cache when called again and will not generate error 12.

PERFORMANCE
What you should avoid is the drive letter at the start of the path name.
SETDRIVE “C:” ! usually this is the default value
PREFIX “C:/myapp/data/ C:/myapp/files/ D:/mydir/somedir/ C:/pvx/lib/”

Better is:
SETDRIVE “C:”
PREFIX “/myapp/data/ /myapp/files/ D:/mydir/somedir/”

Firstly, you do not need /pvx/lib in your search path. Any PxPLUS utility and any PxPLUS subdirectory can be called or found by prefixing with '*'.
e.g. CALL “*web/email” instead of CALL “\pvx\lib\_web\email”
Secondly, by omitting the drive letter, PxPLUS does not need to check whether the drive exists, saving time.
If possible, put the path with a different drive letter at the end of the search path.

ASCII files

PxPLUS and ASCII text files
PxPLUS can populate a file in 9 different ways.
There are 3 options to open a file:

OPEN (1) FILE$
OPEN (1,ISZ=1) FILE$
OPEN (1,ISZ=n) FILE$, waar n>1
And you have 3 commands to write:
OPEN (1) OPEN (1,ISZ=1) OPEN (1,ISZ=n) n>1
PRINT 0D0A 0D0A 0D0A000000…
WRITE 8A0D0A 8A 8A0000000000…
WRITE RECORD 0D0A NOTHING 000000… (tot LEN=n)
  • OPEN (1)

PxPLUS first tests the first record of a ‘serial’ file. If a character is found outside the range from a ” ” (space) to a “~” (tilde), PxPLUS considers the file a binary file and the rules of ‘OPEN (1,ISZ=1)’ apply.

You must LOCK the file if you want to write to it.
PxPLUS handles the file in a record-oriented way.
The IND() function gives you the current record.

  • WRITING

PxPLUS always appends $0D0A$ (1) at the end of a record.
In the case of a WRITE command, an extra field separator ($8A$) (2) will be added just before the record separator ($0D0A$)

  • READING

A ‘READ RECORD’ scans the data in the file for a $0D0A$ byte combination.
A ‘READ’ implies a ‘READ RECORD’. The data from the ‘READ RECORD’ is used to populate the variables, where $8A$ functions as a field separator.
A ‘READ (1,IND=n)’ reads the n+1th record.

1 record separator
PxPLUS for Windows: record separator is $0D0A$
PxPLUS for UNIX: record separator is $0A$
In my examples I have always used $0D0A$.

2 field separator
The default field separator is $8A$, but can be changed with the ‘FS’ parameter.


  • OPEN (1,ISZ=1)

If you open a file with ‘,ISZ=1’, you open the file in BINARY mode, even if it is a KEYED file.
To be compatible with other Business Basics, ‘ISZ=-1’ is allowed.
This type of OPEN implies a LOCK on the file.
PxPLUS handles the file in a byte-oriented way.
The IND() function gives you the byte pointer or, in other words, the number of bytes you have read.

  • WRITING

PRINT X$ writes X$+$0D0A$
WRITE X$ writes X$+$8A$
WRITE RECORD X$ writes X$ and adds nothing to the variable, but if the variable is empty a $00$ byte is added.

  • READING

Normally you read the file with READ RECORD(1,SIZ=nnn)X$
Otherwise, ‘SIZ=1’ is taken.
‘READ(1,IND=n)’ reads the n+1th byte.


  • OPEN (1,ISZ=n) where n>1

Be careful with this method of reading and writing.
Always check if the result matches what you intended.

  • WRITING

‘PRINT’ writes the variable(s) to the file. Each PRINT is terminated with $0D0A$.
Consecutive PRINTs can be performed. No field separator between two fields.
When the n number of bytes is reached, an ERROR #1 is generated.
If the n number of bytes is not reached, the rest of the n bytes is filled with $00$
‘WRITE’ writes the variable(s) to the file. A field separator ($8A$) is added after each field. The remaining n bytes are filled with $00$.
‘WRITE RECORD’ writes the data to the file without a separator. The remaining n bytes are always filled with $00$.

  • READING

A ‘READ’ implies a READ RECORD with n bytes. The variables are populated based on the record read.
A ‘READ RECORD’ reads n bytes (n = specified in the OPEN)
A ‘READ RECORD (1,SIZ=x)’ reads x bytes.

  • Tip: Do not mix PRINT, WRITE, and WRITE RECORD to fill a file unless you know exactly what you are doing.

Summary

  • If you want to fill a ‘serial’ file, intending to later use it to ‘MERGE’ something back:

WRITE PROCEDURE


SERIAL F$
OPEN LOCK (1) F$
PRINT (1)"10 REM"
PRINT (1)"20 BEGIN"
PRINT (1)"30 FOR I=1 to 10"
PRINT ...
PRINT (1)"9999 END"

READ PROCEDURE


CLOSE (1)
OPEN (1)F$
MERGE (1)
If you want full control over what you write:
For example: You need to create a file so that someone else can read it.
They impose a few rules: the record must be 128 bytes long and separated by a 'TAB' character ($09$).

WRITE PROCEDURE


SERIAL F$
OPEN (1,isz=1) F$
DIM X$(128)
X$(1)=SOME_CODE$
X$(25)=OTHER_STUFF$
...
X$=X$+$09$
WRITE RECORD (1)X$

READ PROCEDURE


OPEN(1,isz=1)F$
GET:
READ(1,siz=129,end=DONE)X$
GOTO GET
DONE:
If you want to write records with variables into a ‘serial’ file with the intention of reading them back later:

READ PROCEDURE


OPEN (1) F$
GET:
READ(1,end=DONE)X$,Y$,Z$
GOTO GET
DONE:

WRITE PROCEDURE


SERIAL F$
OPEN LOCK (1) F$
PUT:
A$= ... , B$= ... , C$= ...
WRITE (1)A$,B$,C$
GOTO PUT
Example:

0010 BEGIN ; PRINT 'CS','SB'
0020 FOR I=1 TO 2
0030 LET F$="c:\tmp\erase.me"; ERASE F$,ERR=*PROCEED; SERIAL F$
0050 !
0060 IF I=1 THEN OPEN LOCK (1)F$; PRINT "OPEN (1) "
0070 IF I=2 THEN OPEN LOCK (1,ISZ=1)F$; PRINT "OPEN(1,ISZ=1)"
0080 !
0090 PRINT (1)"111"
0100 WRITE (1)"222"
0110 WRITE RECORD (1)"333"
0130 PRINT (1)"444"
0140 WRITE (1)"555"
0150 WRITE RECORD (1)"666"
0160 !
0170 CLOSE (1); OPEN (1,ISZ=1) F$
0180 READ RECORD (1,SIZ=-1000) X$
0190 PRINT 'LF',"Binary file contents: ",'LF','LF','SF',HTA(X$),
0200 !
0330 CLOSE (1)
0331 PRINT 'SB','LF'
0340 NEXT I

Link files

What is a Link File?

A Link File is a PxPLUS file used to create an ‘ALIAS’ name for a specific ‘port’ or ‘file’ and to link a Device Driver to it.

A PxPLUS Link File is a small, simple file consisting of three parts.
– The ‘header’, which contains the type of Link File.
– The name of the ‘other’ port or ‘other’ file.
– The name of a Device Driver (CALL program) that will be executed after the ‘other’ file is opened. (see Device Driver below)

That’s really all there is to it… Link Files are small files in a directory like many others and follow the same rules as other files. Therefore, under UNIX you must pay attention to upper and lower case letters.

There are three different types of Link Files, indicated by the ‘header’ of the Link File: [Pvxlnk], [Pvxdev], and [Pvxapr]. Internally, PxPLUS handles them differently.

Let’s briefly talk about the ‘header’ of a file.

All PxPLUS files have a ‘header’. In ‘KEYED’ files you see [PVXKEY], and ‘INDEXED’ files have [PVXIND].

When PxPLUS opens a file—any file—it immediately reads the first 512 bytes (or less). It checks whether the ‘header’ starts with ‘[Pvx’, and thus instantly determines if it is one of its own files. Any other file is considered an ASCII file.

If it is a ‘keyed’ file, PxPLUS will process it appropriately. The interpreter knows the internal structure and can read the correct records.

If it is a Link File, PxPLUS knows to handle it differently from a ‘keyed’ file.

Since PxPLUS has already read the first 512 bytes, it has the entire Link File in memory. PxPLUS then analyses the rest.
From position 9, length 60: the name of the ‘other file’.
From position 69, length 12: the name of the ‘CALL’ or Device Driver.

Internally, PxPLUS closes the Link File. On the same channel, PxPLUS opens the ‘other file’ and ensures that the Link File name is shown when you execute PRINT FID(channel). Before the Device Driver name, ‘*dev’ is prefixed, which means Device Drivers are always located in ‘…../lib/_dev/’. Finally, the ‘CALL’ is executed.

How a Link File Works

You must ensure that:
1) The ‘other file’ must be openable in PxPLUS — correct permissions, correct path, correct name (case-sensitive).
2) The Device Driver must be loadable and executable using the command: CALL “*dev/<program>”.

There is, of course, a utility program to create Link Files, namely ‘*UCL’.

As mentioned, there are three types of Link Files. Their respective ‘headers’ are: [Pvxlnk], [Pvxdev], and [Pvxapr].
These ‘headers’ tell PxPLUS how to handle them differently.

[Pvxlnk] is used to link to another file without a Device Driver. For example, you could move the file ‘CUSTOMERS’ to another drive such as ‘F:\DATA\CUSTOMERS’ and create a Link File named CUSTOMERS. This way, you do not need to change your programs.

[Pvxdev] is probably the most used type. It opens another file or port and calls the Device Driver. This type is needed for printers and similar devices.

[Pvxapr] is a Link File for ‘slave’ printers—printers connected to the printer port of a terminal. PxPLUS opens the ‘other port’, executes the ‘CALL’ program, and sends the ‘PS’ mnemonic to the printer. When the channel is closed, PxPLUS sends the ‘PE’ mnemonic.

A few Examples :

The name of the Link File is entirely your choice. The name of "the other file or port" must be a name that can be opened in PxPLUS. So physical ports (LPT1), or spool queues (>lp -dxxx -s ..), or UNC names (\SERVER\PRINTER), or TCP/IP ports ([TCP]1000;), ODBC connections, and so on …

The Device Driver is a CALL program that must be located in the “*dev” directory. You are free to create one yourself.

What is a Device Driver?

A PxPLUS Device Driver is a ‘CALL’ program used to initialize and prepare a file or port once it has been opened.

Example:

OPEN(1)"LP"

This would be the same as:

OPEN(1)"/dev/lp0"
CALL "*dev/OKI"
SETFID (1)"LP"

'OKI' is just a PxPLUS program. You can put anything in it. You can open other files, prompt the user for input, execute other CALLs—anything you can do in a regular CALL can also be done here.

Take a look at a Device Driver such as HPLASER. For example: LOAD "*dev/hplaser".

At the start, there is a line beginning with DEFTTY (LFO) cols,rows or DEFPRT (LFO) cols,rows.

DEFTTY and DEFPRT tell PxPLUS whether this is a screen or a printer. Without this, PxPLUS will assume it’s a file. This is how PxPLUS knows to return FIN() in TERMINAL format if DEFTTY is used, or FIN() in PRINTER format if DEFPRT is used.

COLS and ROWS are also used by FIN() and functions such as MXC() and MXL().

LFO and LFA are two system variables, like DAY or SSN.
LFO = Last File Open, LFA = Last File Accessed.

A simple program such as "*dev/hplaser" shows you that you can create your own mnemonics. These mnemonics exist as long as the channel remains open and are therefore channel-specific.

With the MNM() function you can read the value of a mnemonic and reuse it for another channel.
Example: You define the ‘PS’ and ‘PE’ mnemonics for your screen.
In the Device Driver for your ‘slave’ printer, you can retrieve the ‘PE’ and ‘PS’ mnemonics from channel 0 (your screen) and apply them to your printer channel.

There are also mnemonics with special meanings.

‘*C’ is a mnemonic automatically sent when the channel is closed.
Usually it contains ‘reset’ codes to initialize the printer.

‘*R’ can contain an OS command that will be executed when the channel is closed. Example: ‘rm /tmp/lock_file’

And then there are ‘*I’ and ‘*O’. If you know UNIX ‘mapchan’, you understand what *I and *O can do.
‘*I’ is an input conversion table, and ‘*O’ is an output conversion table.
These let you change certain characters into others during input and/or output.
Example: MNEMONIC ‘*O’=$00 01 02 03.. .. ..1C 1D 1E 1F 2E 21 22 .. .. .. .. .. FE FF$
This table will display a space as a period. (Hex value of a space is $20$, replaced by $2E$, a period)

An example of a more complex Device Driver could be:
! My driver
PCHAN=LFO, PNAME$=FID(LFO)
CLOSE(PCHAN)

[code that checks for a lock file]
[if lock file exists, EXIT 14 so OPEN returns ERROR=14]
[code to create a lock file]
[code to create a temporary file: ‘MYOUTPUT’]
OPEN(PCHAN)"MYOUTPUT"

[call program with mnemonic definitions]

SETFID (PCHAN) PNAME$ (yes, SETFID works on files too!)
EXIT

An interesting PxPLUS function is OPT().

If you do OPEN(CHANNEL,OPT="hello")NAME$, then OPT(channel) returns ‘hello’. You can store anything in OPT= during OPEN and retrieve it in the Device Driver.

Example:

You have a Link File named ‘LP’, the ‘other port’ is ‘/dev/lp0’ and the Device Driver is ‘myprog’

OPEN(1,ERR=stmt,OPT="Check if the correct paper is loaded!") "LP"

<PxPLUS Internal>
[Reads ‘LP’ link file]
[Closes file ‘LP’]
[Opens ‘/dev/lp0’]
[Uses SETFID to rename ‘/dev/lp0’ to ‘LP’]
[Calls "*dev/myprog"]

<In ‘*dev/myprog’>
options$=OPT(LFO)
[options$ now contains "Check if the correct paper is loaded!"]
IF NOT(NUL(OPTIONS$)) MSGBOX OPTION$,"Message"
[call program EXITS]

<PxPLUS Internal>
[Passes any EXIT numval back to OPEN]

A lesser-known function is SETDEV TSK().

If you have worked with BBx, you might have used TSK() to list printers. PxPLUS can emulate this.
This command loads the TSK() so the TSK() function returns the expected content as if it were BBx. The only drawback is that you cannot clear a TSK().

SETDEV TSK() $0100$+"LP"+$00$+">lp -dq1 %COPIES% -s 2>/dev/null"+$00$
SETDEV TSK() $0100$+"P1"+$00$+"/dev/lp1"+$00$

You can retrieve the content with X1$=TSK(0) and X2$=TSK(1)

As you see, almost anything is possible in a Device Driver.

Take a look at ‘*dev/spool’. For ‘the other file’, a directory name is expected. The directory is closed, a temporary file is created in it, and the name is reset to what it was. All ‘prints’ go into this temporary file and, when the channel is closed, the OS command ‘>lp -d…’ is executed via the ‘*R’ mnemonic. You can put multiple commands in ‘*R’, separated by a ‘;’ like any OS command.

A special Device Driver is ‘*dev/windows’. This is used by ‘PxPLUS for Windows’.
It’s best not to modify this program! In fact, never modify a driver in ‘*dev’ because a new PxPLUS installation will overwrite your changes. You can, however, make copies under another name and modify those as needed. For customizations, use the ‘lib/_udev’ directory. (If it doesn’t exist, you may create it)
PxPLUS always checks this directory for a matching terminal driver. In this case, ‘WINDOWS’. If found, it will be executed.
Example: You want blue text on a white background.

Create a program ‘*udev/windows’
0010 ! Windows
0020 print ‘blue’,’_white’,’df’,’cs’,
0030 exit
>save"*udev/windows"
>start

It’s really just terminology. The whole concept of Link Files and Device Drivers is quite simple because… anything is possible. You can do anything you can imagine… because it’s ‘just’ a CALL program. Link Files are simply a way to assign an ALIAS name to a file or port or <fill in yourself>.


(Original text by Gord Davey, reworked and expanded by Tino Vanholst)

Tab Content

This is a basic text element.

Tab Content

This is a basic text element.

Missing information or have a technical question?

Need help or stuck on something? Our support team is ready to answer your questions and provide solutions. Whether it’s a technical challenge or advice, we are happy to help. Contact us and get the support you need quickly!
© 2025 Edias Software International. All rights reserved.