           Ŀ
            Paradox, Interbase and the Peer-to-Peer Network 
            =========== by Gary M. Mugford ================ 
           
  Borland's Paradox for Windows and Interbase is a natural fit that Borland
and the Santa Cruz Operation are pushing with their Client-Server combo.
Unfortunately, not everybody can operate in a Windows environment as the
DOS product, 4.5, still holds sway at a large number of companies. For some
of those companies, the limitations of DOS are leading to an investigation of
a Client-Server solution.
  Up until now, if the company used a peer-to-peer network, the answer included
"Change your operating system." Borland, for legal reasons, has never supported
Paradox on peer-to-peer networks, while offering as much help as possible
within that "Not officially supported" framework. In fact, Paradox applications
on Lantastic networks undoubtedly make up a fair percentage of the network
installations of Paradox.
  The upgrade path to Interbase, smooth under Windows, even on a peer-to-peer
network, has not been successfully managed with Paradox for DOS.
  Until now.
  A small data processing company in Mississauga ON Canada (about 30 miles NW
of Toronto) has put together a successful solution. Upper Canada Data Processing
specializes in data entry and analysis applications that run up into the 250
megabyte territory that is the upper limit of Paradox for DOS's capabilities.
  Since the company's main client would exceed the real Paradox for DOS limit
of 256 megabytes of information during this calendar year, a team was
assembled late in 1993 to prepare for an upgrade to Interbase. The lead
programmer for the team was Gary Mugford of Mugford Info Services of Bramalea
ON, who had done all of the company's programming since its inception and had
done most of the system work until the arrival of system administrator
Richard Beaini. Completing the trio of problem solvers was renowned Paradox
expert Henrik Bechmann of Toronto's Elect Software. Henrik's job was to
provide the SQL programming and produce the Windows bits that would be the
start of moving the application in question towards a Windows environment in
the future.
  While Gary worked on version 10 of the software to accomodate the changes
working partially in Interbase and in DOS and partially in Windows, Richard
and Henrik worked at the setting up of the inter-process communications that
allowed for the successful marriage of the technologies. It was Richard and
Henrik that pulled off this first for Upper Canada, getting help from other
sources, including Rob Schieck of Borland Canada and Charlie Russel of
Oakland CA. The latter source was invaluable in setting up TCP stack protocols
and for warning which wrong roads to avoid travelling in that effort.
  What follows is the various setup files Richard used in the final solution.
His comments are sprinkled liberally throughout the sections and the various
files are presented verbatim. The result is a working system at Upper Canada.
Identical setups should also work elsewhere. But ...

Ŀ
 A complete SET-UP guide to the Borland Paradox and Interbase Installation 
 ==================== by Richard Beaini ================================== 


To start the installation, I am going to list the following software
  packages needed to reach our goal :

* SCO UNIX Release 3.2v4.2 Open Server Network
* Borland Interbase 3.3D for SCO UNIX
* Artisoft Lantastic 5.0
* Artisoft NDIS drivers ( Downloaded from Artisoft BBS )
* FTP Inc. PC/TCP ( Dos and Windows TCP/IP product )
* Borland Paradox 4.5 for Dos
* Borland Paradox 4.5 for Windows
* Borland Interbase SQL link for Dos
* Borland Interbase SQL link for Windows

Other packages in use for our system:

* Quarterdeck's QEMM 7.03 (in the C:\Q6 directory)
* Sony's CD-ROM Drive with the PowerSCSI software
* Eagle, Robin Rowe's Paradox Unexpected Condition DeCoder software
* POCO, a TSR Address/Postal Code lookup program for Canada
* Archive Tape Software

============================================
FTP INC.  ------------>  PC/TCP INSTALLATION
============================================

 The installation of PCTCP package is easy and straight forward. Some
modifications were being made to the Autoexec.bat, Config.sys, and
Protocol.ini files. There is a new file to look for in this
implementation and that is PCTCP.INI . In the PC/TCP installation manual,
they will tell you how to use an NDIS driver with the Generic Kernel. And
now let us take a look at the respective files.

==================
AUTOEXEC.BAT FILE
==================

@echo off
SET X=XXXXXXXX
SET PRNTR=NET
SET PCTCP=C:\PCTCP\PCTCP.INI
SET LAN_CFG=C:\LANTASTI
SET COMSPEC=C:\COMMAND.COM
VERIFY OFF
PATH C:\PCTCP;C:\;C:\U;C:\DOS;C:\LANTASTI;C:\Q6;C:\WINDOWS
SET TEMP=C:\TEMP
C:\Q6\LOADHI /R:3 C:\WINDOWS\SMARTDRV.EXE /L
SHARE.EXE /L:700 /F:4096
DOSKEY
C:\Q6\LOADHI /R:2 C:\Q6\FILES=60
C:\Q6\LOADHI /R:1 C:\Q6\LASTDRIVE=Z
C:\Q6\LOADHI /R:4 C:\Q6\FCBS=16,8
PROMPT $P$G
C:\Q6\LOADHI /R:3 C:\LANTASTI\AI-NDIS BIND_TO=AEXNDIS_NIF
C:\Q6\LOADHI /R:4 /RES=20000 /SQT=FE00-FEFF C:\LANTASTI\AILANBIO VERBOSE
C:\Q6\LOADHI /R:3 C:\LANTASTI\REDIR GINA LOGINS=10
C:\PWRSCSI!\MSCDEX /D:MSCD000 /M:10

NET USER/DISABLE GINA
ECHO OFF
CLS
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ECHO.
ECHO                 GENERAL LOGIN PROCEDURE ...
ECHO.
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ECHO.
NET LOGIN \\GENERAL RICHARD ^"Please Enter Password : "

: TESTPASS
SET NAME=AAAAA
NET STRING/LEFT=1/RIGHT=1 NAME !"LOGIN=GENERAL"
IF %NAME%==T GOTO ISOK
ECHO.
NET LOGIN \\GENERAL ?"USER NAME ---> " ^"  PASSWORD? : "
GOTO TESTPASS

:ISOK

NET STRING/LEFT=1/RIGHT=8 X !"MACHINEID"

NET USE F: \\GENERAL\C-DRIVE
NET USE M: \\GENERAL\M-DRIVE

path M:\;m:\u;%Path%

CD\
M:
CD\
MENU.BAT

:END

ͻ
             
  Comments:  
             
ͼ

* AI-NDIS IS THE NDIS PROTOCOL DRIVER and is binded to the NDIS MAC
    DRIVER ( AEXNDIS.DOS )

================
CONFIG.SYS FILE
================

DEVICE=C:\TSCSI\MA13B.SYS /I5               ; Archive Tape Drive Driver
DEVICE=C:\Q6\DOSDATA.SYS
DEVICE=C:\Q6\QEMM386.SYS RAM ARAM=C980-C9FF ST:M X=C100-C1FF X=C800-C9FF
         X=F400-F4FF X=FE00-FFFF R:2
DEVICE=C:\Q6\DOS-UP.SYS @C:\Q6\DOS-UP.DAT
DEVICE=C:\Q6\LOADHI.SYS /R:1 /SIZE=8592 C:\Q6\QDPMI.SYS SWAPFILE=DPMI.SWP
         SWAPSIZE=1024
DEVICE=C:\Q6\LOADHI.SYS /R:1 /SIZE=28848 C:\MOUSE\MOUSE.SYS
FILES=40
BUFFERS=40
SHELL=C:\Q6\LOADHI.COM /R:3 C:\COMMAND.COM /P /E:1000
STACKS=9,256
DOS=HIGH
FCBS=10,8
DEVICE=C:\Q6\LOADHI.SYS /R:4 /RES=32768 /SQT=FE00-FEFF /SIZE=39760 C:\BIN
                \FDCD.SYS /D:MSCD000
DEVICE=C:\Q6\LOADHI.SYS /R:1 /SIZE=13648 C:\LANTASTI\PROTMAN.DOS /I: C:\
                LANTASTI
DEVICE=C:\Q6\LOADHI.SYS /R:1 /SIZE=6608 C:\LANTASTI\AEXNDIS.DOS
DEVICE=C:\Q6\LOADHI.SYS /R:4 /SIZE=5248 C:\PCTCP\DIS_PKT.GUP

ͻ
             
  Comments:  
             
ͼ

* PROTMAN.DOS IS THE PROTOCOL MANAGER
* AEXNDIS.DOS IS THE NDIS MAC DRIVER and is connected to the NDIS
                protocol driver in the AUTOEXEC.BAT file
*DIS_PKT.GUP IS THE FTP CONVERSION MODULE to use with NDIS drivers
*The line in the config.sys file that has the PROTMAN.DOS will look in the
                lantasti sub-directory for the PROTOCOL.INI file.

=================
PROTOCOL.INI FILE
=================

[PROTMAN]
DRIVERNAME=PROTMAN$
DYNAMIC=YES

[AEXNDIS_NIF]                 ; for the Artisoft Ethernet Adapter
DRIVERNAME=AEXNDS$
IOBASE=0X300                  ; This Must be the address of Your Network CARD.
INTERRUPT=10                  ; This Must be the interrupt of Your Network CARD.

[PKTDRV]
DRIVERNAME=PKTDRV$            ; PCTCP driver
BINDINGS=AEXNDIS_NIF          ; Binded to Lantastic NDIS Driver
INTVEC=0X60                   ; Interrupt Vector at which to load the converter
                              ;             module.

ͻ
             
  Comments:  
             
ͼ

The PROTOCOL.INI and PROTMAN.DOS files should be in the LANTASTI sub-directory
  If you have NON-Artisoft Ethernet Adaptor, the [AEXNDIS_NIF] Section must
  be replaced with the corresponding NDIS Driver. For example if you have
  a novell NE2000 card you should use the following settings :

  [NE2000]
  DRIVERNAME=MS2000$          ; NE2000 NDIS Driver
  IOBASE=0X300
  INTERRUPT=10

Also don't forget to Substitute the line in the Config.sys (AEXNDIS.Dos) with
  NE2000.DOS and in the Autoexec.bat (AI-NDIS) with NEX000.

===============
SYSTEM.INI FILE
================

[boot]           
network.drv=C:\PCTCP\PCTCPNET.DRV         ; This line will be added by install
shell=progman.exe
mouse.drv=aw5mouse.drv
language.dll=
sound.drv=mmsound.drv
comm.drv=comm.drv
keyboard.drv=aw5kbd.drv
system.drv=system.drv
386grabber=vga.3gr
oemfonts.fon=vgaoem.fon
286grabber=vgacolor.2gr
fixedfon.fon=vgafix.fon
fonts.fon=vgasys.fon
display.drv=aw5vga.drv
drivers=mmsystem.dll

[keyboard]
subtype=
type=4
keyboard.dll=
oemansi.bin=

[boot.description]
network.drv="FTP Software's PC/TCP Interdrive"       ; Added by Install
keyboard.typ=Enhanced 101 or 102 key US and Non US keyboards
mouse.drv=Microsoft, or IBM PS/2
language.dll=English (American)
system.drv=MS-DOS System
codepage=437
woafont.fon=English (437)
aspect=100,96,96
display.drv=VGA
;network.drv=Artisoft LANtastic (versions 4.X)       ; Commented by Install

[386Enh]
SystemROMBreakPoint=false                            ; Added by Install
DEVICE=C:\PCTCP\VPCTCP.386                           ; Added by Install
mouse=*vmd
NetAsynchFallback=true
NetAsynchTimeout=50
NetHeapSize=64
PerVMFiles=0
EMMExclude=D800-DFFF
network=lantasti.386, *vnetbios
ebios=*ebios
woafont=dosapp.fon
display=*vddvga
EGA80WOA.FON=EGA80WOA.FON
EGA40WOA.FON=EGA40WOA.FON
CGA80WOA.FON=CGA80WOA.FON
CGA40WOA.FON=CGA40WOA.FON
keyboard=*vkd
device=vtdapi.386
device=*vpicd
device=*vtd
device=*reboot
device=*vdmad
device=*vsd
device=*v86mmgr
device=*pageswap
device=*dosmgr
device=*vmpoll
device=*wshell
device=*BLOCKDEV
device=*PAGEFILE
device=*vfd
device=*parity
device=*biosxlat
device=*vmcpd
device=*combuff
device=*cdpscsi
local=CON
FileSysChange=off
PermSwapDOSDrive=C
PermSwapSizeK=28645
MinTimeslice=20
WinTimeslice=100,50
WinExclusive=0
Com1AutoAssign=2
Com2AutoAssign=2
Com3AutoAssign=2
Com4AutoAssign=2
device=vpcaw5.386
TimerCriticalSection=500
device=aw5vcd.386

[standard]

[NonWindowsApp]
localtsrs=dosedit,ced
CommandEnvSize=512

[mci]
WaveAudio=mciwave.drv
Sequencer=mciseq.drv
CDAudio=mcicda.drv

[drivers]
timer=timer.drv
midimapper=midimap.drv

[vpctcp]
; These option settings may be added to SYSTEM.INI, in a
;   new section "[vpctcp]".
; The next line tells VPCTCP how much copy space memory to request.
;   It is in units of kilobytes (x1024).  This value is only a bid,
;   as Windows may choose to reduce your allocation arbitrarily.
;   This value should be increased if using Windows applications which
;   call the PC/TCP DLL from another DLL; suggested value in such
;   instances is at least 28.  
MinimumCopySpace=12

; The next line tells VPCTCP the segment (paragraph) number of the
;   beginning of memory reserved for devices, BIOS, and upper-
;   memory blocks (which could contain TSRs).  All calls below the
;   PSP of Windows or above this parameter are not processed by
;   the VxD but rather are passed-thru to the kernel untouched.
HiTSRFenceSegment=A000h
; eof

=============
WIN.INI FILE
=============

[windows]
spooler=yes
load=
run=
Beep=yes
NullPort=None
BorderWidth=3
CursorBlinkRate=530
DoubleClickSpeed=452
Programs=com exe bat pif
Documents=
DeviceNotSelectedTimeout=15
TransmissionRetryTimeout=45
KeyboardDelay=2
KeyboardSpeed=31
ScreenSaveActive=1
ScreenSaveTimeOut=600
DosPrint=no
device=HP LaserJet III,hppcl5a,LPT1.DOS  ; Set up in Windows OR it won't print
CoolSwitch=1

[Desktop]
Pattern=(None)
Wallpaper=(None)
GridGranularity=0
IconSpacing=75
TileWallPaper=1

[Extensions]
cal=calendar.exe ^.cal
crd=cardfile.exe ^.crd
trm=terminal.exe ^.trm
txt=notepad.exe ^.txt
ini=notepad.exe ^.ini
pcx=pbrush.exe ^.pcx
bmp=pbrush.exe ^.bmp
wri=write.exe ^.wri
rec=recorder.exe ^.rec
hlp=winhelp.exe ^.hlp
wb1=C:\QPW\qpw.exe ^.wb1
vsd=F:\VISIO\VISIO.EXE ^.vsd
vss=F:\VISIO\VISIO.EXE ^.vss
vst=F:\VISIO\VISIO.EXE ^.vst
vsw=F:\VISIO\VISIO.EXE ^.vsw
DB=C:\PDOXWIN\PDOXWIN.EXE ^.DB
DBF=C:\PDOXWIN\PDOXWIN.EXE ^.DBF
FDL=C:\PDOXWIN\PDOXWIN.EXE ^.FDL
FSL=C:\PDOXWIN\PDOXWIN.EXE ^.FSL
LSL=C:\PDOXWIN\PDOXWIN.EXE ^.LSL
RDL=C:\PDOXWIN\PDOXWIN.EXE ^.RDL
RSL=C:\PDOXWIN\PDOXWIN.EXE ^.RSL
SDL=C:\PDOXWIN\PDOXWIN.EXE ^.SDL
SSL=C:\PDOXWIN\PDOXWIN.EXE ^.SSL
QBE=C:\PDOXWIN\PDOXWIN.EXE ^.QBE
DMD=DMODELER.exe ^.DMD
DML=DMODELER.exe ^.DML
SC=notepad.exe ^.SC

[intl]
sLanguage=enu
sCountry=United States
iCountry=1
iDate=0
iTime=0
iTLZero=0
iCurrency=0
iCurrDigits=2
iNegCurr=0
iLzero=1
iDigits=2
iMeasure=1
s1159=AM
s2359=PM
sCurrency=$
sThousand=,
sDecimal=.
sDate=/
sTime=:
sList=,
sShortDate=M/d/yy
sLongDate=' 'd' 'MMMM' 'yyyy

[ports]
; A line with [filename].PRN followed by an equal sign causes
; [filename] to appear in the Control Panel's Printer Configuration dialog
; box. A printer connected to [filename] directs its output into this file.
LPT1:=
LPT2:=
LPT3:=
COM1:=9600,n,8,1,x
COM2:=9600,n,8,1,x
COM3:=9600,n,8,1,x
COM4:=9600,n,8,1,x
EPT:=
FILE:=
LPT1.DOS=
LPT2.DOS=

[FontSubstitutes]
Helv=MS Sans Serif
Tms Rmn=MS Serif
Times=Times New Roman
Helvetica=Arial

[TrueType]

[Sounds]
SystemDefault=ding.wav, Default Beep
SystemExclamation=chord.wav, Exclamation
SystemStart=tada.wav, Windows Start
SystemExit=chimes.wav, Windows Exit
SystemHand=chord.wav, Critical Stop
SystemQuestion=chord.wav, Question
SystemAsterisk=chord.wav, Asterisk

[mci extensions]
wav=waveaudio
mid=sequencer
rmi=sequencer

[Compatibility]
NOTSHELL=0x0001
CCMAIL=0x0008
AMIPRO=0x0010
REM=0x8022
PIXIE=0x0040
CP=0x0040
JW=0x42080
TME=0x0100
VB=0x0200
PACKRAT=0x0800
VISION=0x0040
MCOURIER=0x0800
_BNOTES=0x24000
MILESV3=0x1000
PM4=0x2000
DESIGNER=0x2000
PLANNER=0x2000
DRAW=0x2000
WINSIM=0x2000
CHARISMA=0x2000
PR2=0x2000
PLUS=0x1000
ED=0x00010000
APORIA=0x0100
EXCEL=0x1000
GUIDE=0x1000
NETSET2=0x0100
W4GL=0x4000
W4GLR=0x4000
TURBOTAX=0x00080000

[Microsoft Word 2.0]
HPDSKJET=+1

[fonts]
Arial (TrueType)=ARIAL.FOT
Arial Bold (TrueType)=ARIALBD.FOT
Arial Bold Italic (TrueType)=ARIALBI.FOT
Arial Italic (TrueType)=ARIALI.FOT
Courier New (TrueType)=COUR.FOT
Courier New Bold (TrueType)=COURBD.FOT
Courier New Bold Italic (TrueType)=COURBI.FOT
Courier New Italic (TrueType)=COURI.FOT
Times New Roman (TrueType)=TIMES.FOT
Times New Roman Bold (TrueType)=TIMESBD.FOT
Times New Roman Bold Italic (TrueType)=TIMESBI.FOT
Times New Roman Italic (TrueType)=TIMESI.FOT
WingDings (TrueType)=WINGDING.FOT
MS Sans Serif 8,10,12,14,18,24 (VGA res)=SSERIFE.FON
Courier 10,12,15 (VGA res)=COURE.FON
MS Serif 8,10,12,14,18,24 (VGA res)=SERIFE.FON
Symbol 8,10,12,14,18,24 (VGA res)=SYMBOLE.FON
Roman (Plotter)=ROMAN.FON
Script (Plotter)=SCRIPT.FON
Modern (Plotter)=MODERN.FON
Small Fonts (VGA res)=SMALLE.FON
Symbol (TrueType)=SYMBOL.FOT
VT220 (VGA res)=C:\LANTCP\TWG220V.FON
WP Phonetic (TrueType)=WPHV02N_.FOT
WP MathExtendedB (TrueType)=WPHV07NB.FOT
WP BoxDrawing (TrueType)=WPCO03N_.FOT
WP IconicSymbolsB (TrueType)=WPHV05NB.FOT
WP Greek Helve (TrueType)=WPHV08N_.FOT
WP MathExtendedA (TrueType)=WPHV07NA.FOT
WP CyrillicA (TrueType)=WPRO10NA.FOT
WP OverflowSet (TrueType)=WPROXXN_.FOT
WP Japanese (TrueType)=WPHV11N_.FOT
WP MathB (TrueType)=WPHV06NB.FOT
WP IconicSymbolsA (TrueType)=WPHV05NA.FOT
WP Arabic Sihafa (TrueType)=WPSI13N_.FOT
WP MultinationalA Roman (TrueType)=WPRO01NA.FOT
WP CyrillicB (TrueType)=WPRO10NB.FOT
WP MultinationalB Roman (TrueType)=WPRO01NB.FOT
WP Greek Courier (TrueType)=WPCO08N_.FOT
WP MathA (TrueType)=WPHV06NA.FOT
WP ArabicScript Sihafa (TrueType)=WPSI14N_.FOT
WP Greek Century (TrueType)=WPCE08N_.FOT
WP TypographicSymbols (TrueType)=WPHV04N_.FOT
WP Hebrew David (TrueType)=WPDV09N_.FOT
Ribbon 131 Bold BT (TrueType)=TT0208M_.FOT
Humanist 521 Light BT (TrueType)=TT0288M_.FOT
Humanist 521 Light Italic BT (TrueType)=TT0289M_.FOT
Geometric Slabserif 703 Light BT (TrueType)=TT0306M_.FOT
Geometric Slabserif 703 Light Italic BT (TrueType)=TT0307M_.FOT
Swiss 721 Black Extended BT (TrueType)=TT0374M_.FOT
Humanist 521 Condensed BT (TrueType)=TT0495M_.FOT
Humanist 521 Bold Condensed BT (TrueType)=TT0496M_.FOT
Onyx BT (TrueType)=TT0519M_.FOT
Caslon Openface BT (TrueType)=TT0581M_.FOT
Engravers' Gothic BT (TrueType)=TT0586M_.FOT
Shelley Volante BT (TrueType)=TT0595M_.FOT
Bernhard Modern BT (TrueType)=TT0607M_.FOT
Brush 738 BT (TrueType)=TT0806M_.FOT
Bernhard Modern Italic BT (TrueType)=TT0837M_.FOT
Bernhard Modern Bold BT (TrueType)=TT0838M_.FOT
Bernhard Modern Bold Italic BT (TrueType)=TT0839M_.FOT
Blackletter 686 BT (TrueType)=TT1044M_.FOT
Bitstream Arrus BT (TrueType)=TT1145M_.FOT
Bitstream Arrus Italic BT (TrueType)=TT1146M_.FOT
Bitstream Arrus Bold BT (TrueType)=TT1147M_.FOT
Bitstream Arrus Bold Italic BT (TrueType)=TT1148M_.FOT
Bitstream Arrus Black BT (TrueType)=TT1149M_.FOT
Bitstream Arrus Black Italic BT (TrueType)=TT1150M_.FOT
Oz Handicraft BT (TrueType)=TT1178M_.FOT

[embedding]
SoundRec=Sound,Sound,SoundRec.exe,picture
Package=Package,Package,packager.exe,picture
PBrush=Paintbrush Picture,Paintbrush Picture,pbrush.exe,picture
ShapewareVISIO10=VISIO Drawing,VISIO Drawing,F:\VISIO\VISIO.EXE,picture
ImportServer=VISIO Graphics Import,VISIO Graphics Import,F:\VISIO\VISIOIMP.EXE,picture
QuattroProNotebook=Quattro Pro Notebook,Quattro Pro Notebook,C:\QPW\QPW.EXE,picture
QuattroProGraph=Quattro Pro Graph,Quattro Pro Graph,C:\QPW\QPW.EXE,picture
TEXTART=TextArt,TextArt,c:\wpwin60\textart.exe,picture
WPWin6.0=WordPerfect Document (6.0),WordPerfect Document (6.0),c:\wpwin60\wpwin.exe,picture
WPGraphic21=WP Graphic 2.1,WP Graphic 2.1,c:\wpwin60\wpdraw\wpdrwin.exe,picture
WPChart21=WP Chart 2.1,WP Chart 2.1,c:\wpwin60\wpdraw\wpdrwin.exe,picture
MPlayer=Media Clip,Media Clip,mplayer.exe,picture

[ODAPI]
CONFIGFILE=C:\WINDOWS\SYSTEM\ODAPI.CFG
CONFIGFILE01=C:\ODAPI\ODAPI.CFG

[DBD]
WORKDIR=C:\QPW
PRIVDIR=C:\QPW

[HPPCL5A,LPT1]
FontSummary=C:\WINDOWS\FS5LPT1.PCL
prtcaps2=3

[spooler]
window=22 22 614 386
netupdate=yes
netspool=no

[HPPCL5A,LPT2]
FontSummary=C:\WINDOWS\FS5LPT2.PCL
prtcaps2=3

[Windows Help]
M_WindowPosition=[275,0,364,479,0]
H_WindowPosition=[213,160,213,160,0]

[PDOXWIN]
SQLTDir=C:\PDOXWIN\EXAMPLES
USERNAME=Richard Beaini
COMPANY=Upper Canada Data Processing
WORKDIR=C:\develop\v9clone
PRIVDIR=C:\develop\privdir
WGDir=C:\PDOXWIN\WORKGRP
AddrDir=C:\PDOXWIN\ADDRBOOK

[MSWrite]
Backup=0

[DDE Servers]
DBD=C:\QPW\DBD
DMODELER=C:\QPW\DMODELER

[WPCorp]
spwin20=CE
thwin20=CE
BIFED20=CE
WPWin60CE=c:\wpwin60\

[Paradox Engine]
NetNamePath=c:\
NetType=2
ShareLocal=No
PX35LOCKING=No
UserName=PxEngine
MaxTables=5
MaxLocks=32
SwapSize=32
MaxFiles=10

[nsreqDPMI]
datalength=4096
views=8
tasks=2

[btrieve]
options=/m:32 /f:20 /p:1024

[brequest]
options=/r:20 /s:20 /d:532 /w:2

[WPCorp-Windows Printer Flags]
TTY=0x00000009
HPDSKJET=0x00000006
DESKJETC=0x00000006
LBPII=0x00000002
LBPIII=0x00000002
HPPCL5E=0x00000060
HPPCL=0x00000010
EPSON24=0x00000080

[WordPerfect]
MDI Frame Position (X)=-32768
MDI Frame Position (Y)=-32768
MDI Frame Position (CX)=-32768
MDI Frame Position (CY)=-32768
MDI Frame Position (ShowCmd)=3

[HPPCL5E,LPT1]
FontSummary=C:\WINDOWS\FS5ELPT1.PCL
prtcaps2=13779

[HP LaserJet 4/4M,LPT2.DOS]
paper=1
prtcaps=-5240
prtcaps2=13779

[PrinterPorts]
HP LaserJet 4/4M=HPPCL5E,LPT2.DOS,15,45
HP LaserJet III=hppcl5a,LPT1.DOS,15,45

[devices]
HP LaserJet 4/4M=HPPCL5E,LPT2.DOS
HP LaserJet III=hppcl5a,LPT1.DOS

[OBEX]
ObexDir=C:\OBEX

[AAPLAY Animation]
DualScreen=0
FullScreen=AAVGA.DLL
FullInstalled=1
ConfigTime=477187351
WaveAudio=x,0
Sequencer=x,0
CDAudio=x,0

[colors]
Background=255 255 232
AppWorkspace=255 255 255
Window=255 255 255
WindowText=0 0 0
Menu=255 255 255
MenuText=0 0 0
ActiveTitle=0 0 128
InactiveTitle=255 255 255
TitleText=255 255 255
ActiveBorder=192 192 192
InactiveBorder=192 192 192
WindowFrame=0 0 0
Scrollbar=192 192 192
ButtonFace=192 192 192
ButtonShadow=128 128 128
ButtonText=0 0 0
GrayText=192 192 192
Hilight=0 0 128
HilightText=255 255 255
InactiveTitleText=0 0 0
ButtonHilight=255 255 255

===============
PCTCP.INI FILE
===============

[pctcp general]
host-name=gina                                ; Workstation Name
domain=gina
user=RICHARD
full-name=RICHARD BEAINI
time-zone=EST
time-zone-offset=300
use-old-init-scheme=no

[pctcp kernel]
interface=ifcust 0                            ; will be defined later
serial-number=1990-1014-8201
authentication-key=2789-8471-9422
window=2048
low-window=0 
use-emm=no
host-table=c:\pctcp\hosts           ; Points to the HOSTS file ( IP Table )
kernel-int=0x61
ip-ttl=64
ip-precedence=routine
ip-precedence-matching=lax
ip-security=none
ip-delay=high
ip-reliability=low
ip-throughput=low
large-packets=5
small-packets=5
tcp-connections=6
udp-connections=6
router-discovery=no
mtu-discovery=yes

[pctcp ifcust 0]
io-addr=300                               ; Adrress of the Network Card
ip-address=128.197.231.73                 ; IP Address
irq=5                                     ; Interrupt of your network card
subnet-mask=255.255.255.0
dma=no
rcv-dma=0
xmt-dma=0

[pctcp lpr]
banner=yes

[pctcp print]
spool=c:\predir.spl

[pctcp idprint printer]
when=timeout
timer=30
mine=no
number=0 

[pctcp idrive] 
cache-tmo=30
lock-tmo=3
map-char=~
retry-x=3
stream=2
sym-lnk=no
umask=775
lock=no

[pctcp idrive NFS]
host=bluejay                                  ; SCO Server
path=/interb/test                             ; Network File System On bluejay
drive=N:
sec_key=PCNFS
sec_arg=richard
lock=no
reads=1024
writes=8192
timeout=30
umask=775
fat=no
tcp=no

[pctcp idrive-user]
richard=
gina=

[pctcp kerberos]
principal-is-userid=yes
always-encrypt-session=no
directory=c:\pctcp

[pctcp ip-security]
basic-classification=unclassified
matching=lax

[pctcp pd-pctcp]
default=ipx

[pctcp pd-pctcp ipx]
retain-header=0
protocol=UDP
type-port=0x8137,213

[pctcp netbios]
scope=

[pctcp vmail]
indent-reply="    "
new-mbox=yes
post=yes
ask-overwrite=no
print-nonprintable=no

[pctcp pcmail]
msglimit=0
max-sync-descs=0
net-time-out=5
repository-port=158

[pctcp pop3]
rpop=no
pop3-port=110
default-mbox=default
bboard=no
net-time-out=5
xmit=no
max-sync-descs=0

[pctcp pop2]
pop2-port=109
net-time-out=5
max-sync-descs=0

[pctcp nntp]
net-time-out=5
max-sync-descs=0
join-max-msgs=0

[pctcp tn]
ftpsrv=on
status=on
cmdline=-?
back-arrow-key=del
screen-saver=no
kerberos4-auth=on
kerberos4-only=off

[pctcp vt]
allow-vt220-8-bit=off
8-bit=off
wrap-line=on
answerback=FTP

[pctcp ftp]
ftpinit=ftp

[pctcp host]
umask=644

[pctcp wmsg]
protocol = TCP
save-protocol = yes
beep-on-msg = yes

[pctcp serial n]                        ; SETUP if your're using SLIP ( MODEM )
port=1
io-addr=0x03f8
irq=4
baud=2400
hardware-flow-control=on

[pctcp comscrpt hostname]
dialup=c:\pctcp\dialup.scr
hangup=c:\pctcp\hangup.scr
mru=1500
accm=0x000A0000
addr-ctrl-field-comp=on
prot-field-comp=on
local-ip-address=0.0.0.0
remote-ip-address=0.0.0.0

[pctcp time]
dst-begins=94
dst-ends=299

[pctcp install]
bindir=C:\PCTCP
etcdir=C:\PCTCP
kernel-name=ETHDRV.EXE                 ; Kernel Name Thet Supports NDIS Drivers
major-version=2
minor-version=2
patch-level=0
do-kappconf=yes
configure-driver=yes

[pctcp idrive-previous-printers]
\\MainSrv\@laser=LPT1:

[pctcp idrive-restore]
LPT2:=\\MainSrv\@laser lpr

[pctcp idrive-previous-drives]
\\MainSrv\@LASER=G:

=====================
BATCH FILES: GP45.BAT     ; Launch Paradox 4.5 without the Interbase connect
=====================

@echo off
cls
echo.
echo.
echo.
echo.
echo.
echo.
echo ============================================
echo    Just setting up right now ...
echo ============================================
set PP=%PATH%

:: Postal Code Lookup TSR
if not exist C:\poco\pocodos.exe goto NOPOCO
c:
cd \poco
pocodos -c5 -h2
cd \

: NOPOCO

net login \\MainSrv GENERICNAME SILLYNONSENSEPASSWORD

::                          Program
net use P: \\general\pdox45
::                          Data
net use I: \\MainSrv\45data
::                          40 Standard Access
net use J: \\general\40data
::                          45 Standard Access
net use K: \\MainSrv\45data
::                          MainSrvRoot
net use X: \\MainSrv\c-drive
::                          GeneralRoot (Borlnet Home)
net use Y: \\general\c-drive
::                          GeneralD    (Soon to be obsolete)
net use Z: \\general\d-drive

set PROMPT=[ PDX4_shell ] $P$G
REM set PATH=c:\pdx45prv;P:\;Y:\BORLNET;I:\;%PP%
set path=P:\;Y:\borlnet;I:\;%PP%

REM c:
REM cd \pdx45prv

P:
cd \

if %1!==! goto INTRACTIVE

: MENUCONTROL
paradox -share -diag -user %1 MENU
goto DAEAGLE

: INTRACTIVE
paradox -share -diag          MENU

: DAEAGLE
m:\u\eagle
@echo off
cls
echo.
echo.
echo.
echo.
echo.
echo.
echo ============================================
echo    Returning to the menu now ...
echo ============================================
cd \
m:
cd \
set PATH=%PP%
set PROMPT=$P$G
net unuse P:
net unuse J:
net unuse I:
net unuse Y:
net unuse Z:

if not exist C:\poco\pocodos.exe goto DAEND
c:
cd \poco
pocodos -u
cd \

: DAEND
net logout \\MainSrv
set PP=

=======================
BATCH FILES: GP45IB.BAT    ; Launch Paradox 4.5 with the Interbase connect
=======================

@echo off
cls
echo.
echo.
echo.
echo.
echo.
echo.
echo ============================================
echo    Just setting up right now ...
echo ============================================
set PP=%PATH%

:: FTP driver loading
ethdrv -m
:: Postal Code Lookup TSR
if not exist C:\poco\pocodos.exe goto NOPOCO
c:
cd \poco
pocodos -c5 -h2
cd \

: NOPOCO

net login \\MainSrv allenter nopassword

::                          Program
net use P: \\general\pdox45
::                          Data
net use I: \\MainSrv\45data
::                          40 Standard Access
net use J: \\general\40data
::                          45 Standard Access
net use K: \\MainSrv\45data
::                          MainSrvRoot
net use X: \\MainSrv\c-drive
::                          GeneralRoot (Borlnet Home)
net use Y: \\general\c-drive
::                          GeneralD    (Soon to be obsolete)
net use Z: \\general\d-drive

set PROMPT=[ PDX4IB_shell ] $P$G
set path=P:\;Y:\borlnet;I:\;%PP%

REM c:
REM cd \pdx45prv

P:
cd \

if %1!==! goto INTRACTIVE

: MENUCONTROL
paradox -share -diag -NOREALHEAP -user %1 MENU
goto DAEAGLE

: INTRACTIVE
paradox -share -diag -NOREALHEAP          MENU

: DAEAGLE
m:\u\eagle
@echo off
cls
echo.
echo.
echo.
echo.
echo.
echo.
echo ============================================
echo    Returning to the menu now ...
echo ============================================
cd \
m:
cd \
set PATH=%PP%
set PROMPT=$P$G
net unuse P:
net unuse J:
net unuse I:
net unuse Y:
net unuse Z:

if not exist C:\poco\pocodos.exe goto DAEND
c:
cd \poco
pocodos -u
cd \

inet unload

: DAEND
net logout \\MainSrv
set PP=

ͻ
 ͻ 
                          
   IMPORTANT COMMENTS :   
                          
 ͼ 
ͼ

* PC/TCP runs according to the values in the PCTCP.INI file.

*  You don't need the PC/TCP KERNEL loaded all the time ( MEMORY USAGE ), you
    can load it in the batch file that execute PARADOX by simply adding this
    line "ETHDRV" to the batch file. In PARADOX for Dos, You can load the
    KERNEL high in memory by using "ETHDRV -m" ( note m MUST be in lower
    case ). And when you exit paradox you can include this line at the end
    of the batch file to unload the kernel and save MEMORY --> "inet unload".
    In PARADOX for Windows you MUST load the KERNEL in lower memory by adding
    "ETHDRV" to the batch file that loads Windows. If the KERNEL is loaded in
    high memory, Windows PCTCP won't work and therefore PARADOX for Windows.

*  Create a Sub-directory called ETC, or the install program of PC/TCP will
    create it for you (to the best of my recollection), on your local drive
    and copy to it a file called SERVICES. This file must include, at the top
    of it, this line :
         gds_db    3050/tcp
    If the SERVICES file is not in the ETC sub-directory, NEITHER PARADOX for
    Dos Nor PARADOX for Windows will CONNECT to Interbase.
    The HOSTS file could be in either ETC or PCTCP sub-directory But you have
    to refer to its location in the PCTCP.INI file ( in the [pctcp kernel]
    section, host-table=c:\... )

** If you have any problems, Please feel free to call me at :
    VOICE ---> ( 905 ) 507-2092 ----->  9:00 AM  TO 5:00 PM  Eastern Time
    REMEMBER that you Australian guys are 14 HOURS ahead of us.

              Ŀ
               Interbase Interface: Scripts and Stuff 
               by Gary M. Mugford and Henrik Bechmann 
              
This next section is the generic script used by Henrik to communicate between
Paradox for DOS and Interbase. It very much concentrates on the most important
issue in the communication, the memo field issue. Upper Canada makes HEAVY use
of memo fields for auditing changes to records and their use was a stumbling
block. Interbase will use memo fields once the record is in Interbase format.
It won't bring over a memo as a memo, changing it into a pointer alpha field
instead. The solution, presented here, is Henrik's initial approach and he
continues to work on it. It works amazingly well.

; written by Henrik Bechmann Dec 15, 1993. 416-534-8176; cis 72701,3717
; modified by Henrik Bechmann April 25, 1994
; copyright (c) 1993, 1994 Elect Software International Inc. Toronto Canada.
; This source code may be used as long as the user indemnifies Elect
; from any liability. The author makes no claims or warranties whatsoever,
; including but not limited to the merchantibility or fitness of this code
; for any purpose whatsoever. The code may be distributed and copied as long
; as this notice is retained. The code may be modified if modifications are
; clearly annotated as to author and date.
;==========================================================================
;                       SQLLink  Description
;==========================================================================
; The code uses an object based programming approach (object.xxxxx).
; SQLLink is defined to handle certain SQL operations between PdoxDOS and
; InterBase.
; The approach uses Global variables (properties of SQLLink)
; Set parameters at end of script file to test.
;
; SQLLink is generic code which allows for upload and download of records
; that have memo fields.
; To download, SQLLink collects a list of blob pointers from interBase into
; a working table that has record keys and blob pointers. It then reads the
; memos one at a time and writes them to the memo fields of the local copy
; table.
; Therefore the approach needs not only a replica table but a local working
; copy of the table as well.
;
;==========================================================================
;                       SQLLink  Interface
;==========================================================================
; CREATION:
;  SQLLink.Constructor()
;  SQLLink.Destructor()
; UTILITIES:
;  SQLLink.ConnectToServer(ParameterBag)
;  SQLLink.DisconnectFromServer()
;  SQLLink.setmemoVarFromServer(BlobPointer)
;  SQLLink.addMemoBlobToServer() ; returns blobPointer
;  SQLLink.enumMemoPointers(KeyValue,PointerTable)
;  SQLLink.WriteMemoToClientRecord(KeyValue)
;  SQLLink.createUploadTable()
;  SQLLink.DownloadMemos(KeyValue)
;  SQLLink.uploadMemos()
;  SQLLink.addClientToServer(ClientTabSpec,ServerTabSpec)
; PROPERTIES:
;  SQLLink.memoVar ; the current memo
;  SQLLink.parameterBag[] ; Title, UserName, PassWord, Database
;  SQLLink.tableParmBag[] ; see "Test Mainline section at end of script"
;  SQLLink.memoFileName ; transient import/export file for memo
;  SQLLink.ClientKeyFieldList[2] ; for appendArray
;
;==========================================================================
;                       SQLLink  Implementation
;==========================================================================
;--------------------------------------------------------------------------
; create the global variables involved with processing a request to
; download and upload records that have memos...
;--------------------------------------------------------------------------
Proc SQLLink.constructor()
   SQLLink.memoVar = ""
   Dynarray SQLLink.parameterBag[] ; Title, UserName, PassWord, Database
      SQLLink.parameterBag["ErrorCode"] = 0
      SQLLink.parameterBag["SQLErrorCode"] = 0
      SQLLink.parameterBag["ErrorMessage"] = ""
   Dynarray SQLLink.tableParmBag[] ; see following list...
;      SQLLink.TableParmBag["BlobPointerTabSpec"]
;      SQLLink.TableParmBag["ServerTabSpec"]
;      SQLLink.TableParmBag["ServerKeyFieldName"]
;      SQLLink.TableParmBag["ServerMemoFieldName"]
;      SQLLink.TableParmBag["ClientTabSpec"]
;      SQLLink.TableParmBag["ClientKeyFieldName"]
;      SQLLink.TableParmBag["ClientMemoFieldName"]
   SQLLink.memoFileName = "memoblob.txt" ; transient import/export file
   Array SQLLink.ClientKeyFieldList[2] ; for appendArray
EndProc ; SQLLink.constructor

;--------------------------------------------------------------------------
; destroys the variables created by the constructor...
;--------------------------------------------------------------------------
Proc SQLLink.destructor()
   release vars
      SQLLink.memoVar,
      SQLLink.parameterBag,
      SQLLink.tableParmBag,
      SQLLink.memoFileName,
      SQLLink.ClientKeyFieldList
EndProc ; SQLLink.destructor

;--------------------------------------------------------------------------
; connects to the server based on data in a global parameter Bag
;--------------------------------------------------------------------------
Proc SQLLink.ConnectToServer(parameterBag)

   SQLSelectConnect
      Title parameterBag["Title"]
      Values
        parameterBag["UserName"],
        parameterBag["Password"],
        parameterBag["Database"]

   ;---------------------------------------------------------
   ; allow import/export of memo as blob...
   ;---------------------------------------------------------
   SQL
      :BLOBMODE BINARY
   EndSQL

endProc ; SQLLink.ConnectToServer

;--------------------------------------------------------------------------
; disconnects from the server...
;--------------------------------------------------------------------------
proc SQLLink.disconnectFromServer()
   SQLBreakConnect
endproc ; SQLLink.disconnectFromServer

;---------------------------------------------------------
; set the global memo variable (SQLLink.memoVar) from a
; blob in the Server database
;---------------------------------------------------------
Proc SQLLink.SetMemoVarFromServer(BlobPointer)
   private
      errorProc,
      isTransactionOK

   errorProc = "SQLLink.HandleError"
   isTransactionOK = True

   SQL
      :BLOBGET ~BlobPointer~,~SQLLink.memofilename~
   ENDSQL

   if isTransactionOK then
      fileread binary SQLLink.memoFileName to SQLLink.memoVar
   endif

   return isTransactionOK

endProc ; SQLLink.setMemoVarFromServer

;---------------------------------------------------------
; Write SQLLink.memoVar to server, and return blobPointer.
; Requires SQLLink.memoFileName and SQLLink.memoVar to be
; set.
;---------------------------------------------------------
Proc SQLLink.AddMemoBlobToServer()

   filewrite binary SQLLink.memoFileName from SQLLink.memoVar

   SQL
      :BLOBPUT ~SQLLink.memofilename~
   ENDSQL

   if isTransactionOK then

      View "Answer"
      blobpointer = [BlobId]
      ClearImage
      return blobpointer

   else

      return ""

   endif

endProc ; SQLLink.addMemoBlobToServer

;---------------------------------------------------------
; Assumes non-compound key.
; "ALL" brings pointers for all records.
; returns two column table named pointerTable: the first
;  field has the key values recovered, and the second
;  field has the memo pointers.
;---------------------------------------------------------
Proc SQLLink.EnumMemoPointers(KeyValue,pointerTable)
   if upper(keyvalue) = "ALL" then
      SQL
         Select All ~SQLLink.TableParmBag["ServerKeyFieldName"]~,
            ~SQLLink.TableParmBag["ServerMemoFieldName"]~ from
            ~SQLLink.TableParmBag["ServerTabSpec"]~
      endSQL
   else
      SQL
         Select All ~SQLLink.TableParmBag["ServerKeyFieldName"]~,
            ~SQLLink.TableParmBag["ServerMemoFieldName"]~ from
            ~SQLLink.TableParmBag["ServerTabSpec"]~
            where ~SQLLink.TableParmBag["ServerKeyFieldName"]~ = ~KeyValue~
      endSQL
   endif
   if upper(pointerTable) <> "ANSWER" then
      rename "Answer" pointerTable
   endif
endProc ; SQLLink.enumMemoPointers

;---------------------------------------------------------
; Locates KeyValue in ClientTabSpec, or adds a record
; for that keyValue, then sets the ClientMemoFieldName
; to the global SQLLink.MemoVar...
;---------------------------------------------------------
Proc SQLLink.WriteMemoToClientRecord(KeyValue)

   Moveto SQLLink.TableParmBag["ClientTabSpec"]
   moveto Field SQLLink.TableParmBag["ClientKeyFieldName"]
   Locate KeyValue
   CoEditKey ; anticipate appendarray
   if not retVal then
      SQLLink.ClientKeyFieldList[2] = KeyValue
      Appendarray SQLLink.ClientKeyFieldList
      if retval <> 1 then
         debug ; unable to add unique record
      endif
      locate keyValue
      if not retval then
         debug ; unable to find unique record
      endif
   endif
   moveto Field SQLLink.TableParmBag["ClientMemoFieldName"]
   [] = SQLLink.memoVar
   Do_It!
endproc ; SQLLink!WriteMemoToClientRecord

;---------------------------------------------------------------------------
; This proc creates a table that has a blank A255 field in place of the memo
;  field.
; Assumes that there is only one memo field in the ClientTabSpec, and that
;  the Client and Server tables have identical field orders (not necessarily
;  the same field names, but types much match)...
; See SQLLink.uploadMemos.
;---------------------------------------------------------------------------
proc SQLLink.createUploadTable(UploadTabSpec)
   private
      i
   create uploadTabSpec like SQLLink.TableParmBag["ServerTabSpec"]
   Menu {Ask} select SQLLink.tableParmBag["ClientTabSpec"]
   CtrlHome Right
   i = 1
   While rowno() = 1
      if upper(field()) <> upper(SQLLink.tableParmBag["ClientMemoFieldName"]) then
         example typein i
         i = i + 1
      endif
      right
   endWhile
   Menu {Ask} select uploadTabSpec
   CtrlHome "fast insert"
   Right
   i = 1
   While rowno() = 1
      if upper(field()) <> upper(SQLLink.tableParmBag["ServerMemoFieldName"]) then
         example typein i
         i = i + 1
      endif
      right
   endWhile
   do_it!
   moveto 1 clearImage
   moveto 1 clearImage
endProc ; SQLLink.createUploadTable

;---------------------------------------------------------------------------
; This proc laboriously (on a record basis) uploads memos from
; SQLLink.TableParmBag["ClientTabSpec"] to the server, and places the
; returned (temporary) blob pointer in uploadTabSpec (See
; SQLLink.createUploadTable). It then adds the resulting records to
; SQLLink.TableParmBagp"ServerTabSpec"].
;---------------------------------------------------------------------------
proc SQLLink.uploadmemos(uploadTabSpec)
   private
      keyValue,
      blobPointer,
      IsTransactionOK,
      errorProc
   errorProc = "SQLLink.HandleError"
   isTransactionOK = True
   sqlStartTrans
   view uploadTabSpec
   view SQLLink.TableParmBag["ClientTabSpec"]
   scan
      Moveto Field SQLLink.TableParmBag["ClientkeyFieldName"]
      keyValue = []
      Moveto Field SQLLink.TableParmBag["ClientmemoFieldName"]
      SQLLink.memoVar = []
      blobPointer = SQLLink.addMemoBlobToServer()
      if not isTransactionOK then
         quitloop
      endif
      Moveto uploadTabSpec
      Moveto Field SQLLink.TableParmBag["ServerKeyFieldName"]
      Locate KeyValue
      if not RetVal then
         debug ; cannot find upload record key
      endif
      Moveto Field SQLLink.TableParmBag["ServerMemoFieldName"]
      CoEditKey
      [] = blobPointer
      Do_It!
      Moveto SQLLink.TableParmBag["ClientTabSpec"]
   endScan
   if isTransactionOK then
      SQLLink.addClientToServer(
         uploadTabSpec,SQLLink.TableParmBag["ServerTabSpec"])
   endif
   moveto uploadTabSpec
   clearImage
   moveto SQLLink.TableParmBag["ClientTabSpec"]
   clearImage
   return isTransactionOK
endProc ; SQLLink.uploadmemos

proc SQLLink.HandleError()
   SQLLink.parameterBag["ErrorCode"] = errorCode()
   SQLLink.parameterBag["ErrorMessage"] = errorMessage()
   SQLLink.parameterBag["SQLErrorCode"] = SQLerrorCode()
   switch
      case errorCode() = 1000:
         switch
            case strVal(sqlerrorCode()) = "-501":
               isTransactionOK = false
               return 1
         endSwitch
      case errorCode() = 1002:
         isTransactionOK = false
         return 1
   endswitch
   return 2
endProc ; SQLHandleAddError

;---------------------------------------------------------------------------
; this proc simply adds a client table to a server table.
;---------------------------------------------------------------------------
proc SQLLink.addClientToServer(ClientTabSpec,ServerTabSpec)
   if isTable("keyviol") then
      delete "Keyviol"
   endif
   if isTable("problems") then
      delete "problems"
   endif
   add ClientTabSpec ServerTabSpec
   if isTable("Changed") then
      delete "Changed"
   endif
endProc ; SQLLink.addClientToServer

;---------------------------------------------------------------------------
; This proc creates a list of server table memo pointers, and then
; downloads those memos to SQLLink.TableParmBag["ClientTabSpec"]
;---------------------------------------------------------------------------
proc SQLLink.DownloadMemos(KeyValue)
   ;-----------------------------------------------------------------------
   ; collect a list of the blob pointers to be downloaded...
   ;-----------------------------------------------------------------------
   SQLLink.EnumMemoPointers(KeyValue,SQLLink.TableParmBag["BlobPointerTabSpec"])
   ;-----------------------------------------------------------------------
   ; initialize the workspace...
   ;-----------------------------------------------------------------------
   View SQLLink.TableParmBag["ClientTabSpec"]
   CtrlHome Right ; position on the key field
   View SQLLink.TableParmBag["BlobPointerTabSpec"]
   ;-----------------------------------------------------------------------
   ; for each record, get the memo blob and place it in the Client table,
   ; creating a new record for it if necessary...
   ;-----------------------------------------------------------------------
   if recno() > 0 then
      scan

         moveto Field SQLLink.TableParmBag["ServerMemoFieldName"]
         SQLLink.setMemoVarFromServer([])

         moveto Field SQLLink.TableParmBag["ServerKeyFieldName"]
         SQLLink.writeMemoToClientRecord([])

         moveto SQLLink.TableParmBag["BlobPointerTabSpec"]

      endScan
   endif
   ;-----------------------------------------------------------------------
   ; clear the pointer table off the workspace, so the Client table can be
   ; examined...
   ;-----------------------------------------------------------------------
   Moveto SQLLink.TableParmBag["ClientTabSpec"]
   ClearImage
   Moveto SQLLink.TableParmBag["BlobPointerTabSpec"]
   ClearImage
endProc ; SQLLink.DownloadMemos

writelib library_name.a
   SQLLink.Constructor,
   SQLLink.Destructor,
   SQLLink.ConnectToServer,
   SQLLink.DisconnectFromServer,
   SQLLink.setmemoVarFromServer,
   SQLLink.addMemoBlobToServer,
   SQLLink.enumMemoPointers,
   SQLLink.WriteMemoToClientRecord,
   SQLLink.createUploadTable,
   SQLLink.DownloadMemos,
   SQLLink.uploadMemos,
   SQLLink.addClientToServer,
   SQLLink.HandleError


release procs
   SQLLink.Constructor,
   SQLLink.Destructor,
   SQLLink.ConnectToServer,
   SQLLink.DisconnectFromServer,
   SQLLink.setmemoVarFromServer,
   SQLLink.addMemoBlobToServer,
   SQLLink.enumMemoPointers,
   SQLLink.WriteMemoToClientRecord,
   SQLLink.createUploadTable,
   SQLLink.DownloadMemos,
   SQLLink.uploadMemos,
   SQLLink.addClientToServer,
   SQLLink.HandleError

;;==========================================================================
;;                               TEST PROCS
;;==========================================================================
;
;proc testMemoUpload()
;   SQLLink.CreateUploadTable("$upload")
;   SQLLink.UploadMemos("$upload")
;endProc ; testmemoUpload
;
;proc testMemoDownLoad(KeyValue)
;   SQLLink.DownloadMemos(KeyValue)
;endProc
;
;;==========================================================================
;;                               TEST MAINLINE
;;==========================================================================
;
;echo normal
;
;;-----------------------------------------------------------------------
;; set up global variables...
;;-----------------------------------------------------------------------
;SQLLink.constructor()
;;-----------------------------------------------------------------------
;; Set parameters...
;;-----------------------------------------------------------------------
;
;SQLLink.parameterBag["Title"] = "aaaa"
;SQLLink.parameterBag["UserName"] = "bbbb"
;SQLLink.parameterBag["Password"] = "cccc"
;SQLLink.parameterBag["Database"] = "hostName:/path/database.gdb"
;
;SQLLink.TableParmBag["BlobPointerTabSpec"]      = "Answer"
;SQLLink.TableParmBag["ServerTabSpec"]           = "Test"
;SQLLink.TableParmBag["ServerKeyFieldName"]      = "TestKey"
;SQLLink.TableParmBag["ServerMemoFieldName"]     = "TestMemo"
;SQLLink.TableParmBag["ClientTabSpec"]           = "LocTest"
;SQLLink.TableParmBag["ClientKeyFieldName"]      = "TestKey"
;SQLLink.TableParmBag["ClientMemoFieldName"]     = "TestMemo"
;
;;-----------------------------------------------------------------------
;; End of set parameters.
;; set the name of the table for the appendArray array...
;;-----------------------------------------------------------------------
;SQLLink.ClientKeyFieldList[1] = SQLLink.TableParmBag["ClientTabSpec"]
;;-----------------------------------------------------------------------
;; connect to the Server server...
;;-----------------------------------------------------------------------
;SQLLink.ConnectToServer(SQLLink.ParameterBag)
;
;testMemoUpLoad("All")
;testMemoDownLoad()
;SQLLink.disconnectFromServer()
;SQLLink.destructor()

A searching routine making use of the SQLlink.SC code was developed jointly
by Henrik and Gary. Obviously, some of the code is very specific to the app
that was the genesis of the Project 10 effort. Other parts of it should be
instructional as to the problems presented by the DOS/Interbase combo.

;ͻ
; Script Name: GSEARCH    Created:04/28/94      Author: Gary Mugford  
;Ķ
; Description: Example Group Search script meant to be incorporated into
;              V10-Reg. Base Code comes from V9, modified 1st by H.B.   
;Ķ
; Called By: NONE                                                       
;Ķ
; Libraries: NONE ?? SqlLink.SC code ??                                 
;Ķ
; Tables    ID      Reports  Forms     Procedures                   
;Ķ
;                   NONE               DO_GROUPSEARCH_V10           
;                                      groupSearch!initVars         
;                                      groupSearch!searchRemote     
;                                      groupSearch!isCriteriaOK     
;                                      groupSearch!cleanVar         
;                                      groupSearch!setPCvar         
;                                      groupSearch!prepDisplayResults
;                                      groupSearch!wait             
;                                      groupSearch!editRecord       
;                                      groupSearch!viewRecord       
;                                      groupSearch!cleanup          
;                                      DLG_GROUPSEARCH_V10          
;Ķ
;WORK TO DO:                                                            
; refine messages to users throughout.                                  
; allow >=M6K,<M6M type of searches, think about replacing ".." with   
;    >,< until version 4 of interbase allows wild card searches         
; Trap for control-Z (gary)                                            
; set up statistical db for limitation of search by most common names.  
; set up vxLegals table with passwords for interBase                    
; Criteria constraints for search:                                      
;   if appNum then blank out other criteria                            
;   strip out double dots, possibly replace with >,<                   
;    look for WaitTest() proc for ideas on dialog with user re criteria 
; Gary to add generic Followup field handler                            
; screen out alt-o's etc on wait statements                             
; for edit, check if user is danger crowd, and take copy of record      
;    before & after edit to danger table -- check with Gary about this  
; Allow cancel from edit                                               
;                                                                       
;Notes:                                                                 
; 1.3  Revised: 05/01/94 By: Henrik Bechmann                            
;      Added privtables for localreg and $answer                        
;      Added reset on cleanup to remove privtables                      
;      Added message in failure of query (no answer table)              
;      Added isCriteriaOK logic                                         
;      NOTE: logic for appendarray use in sqllink.sc is OK              
; 1.31 Revised: 05/02/94 By: Gary Mugford                               
;      Did a second version of the setPCvar function because the 1.3    
;       version tested for input characters ruled out by the valpix in  
;       the dialog accept statement (still might be a problem with a    
;       space in the fourth character NOT being followed by a char)     
;      Added find (search/zoom) and again buttons on the table browser  
;       during multi-records display                                    
; 1.32 Revised May 23 1994 by Henrik Bechmann                           
;      "Unlock all" statements commented out as redundant               
;      SetPCVar simplified.                                             
;      Added explicit reset after doing a copy LocalReg to privdir.     
; 1.4  Revised 6/20/94 by Gary Mugford                                  
;      Changed all references to v9Main to DB_MAIN.a (except hard-coded 
;       in the SQL line code 2 places both marked)                      
;      Changed the reference to v9CA to DB_CA.a                         
;      Changed the name of the calling function from MENU1_GROUPSEARCH  
;       to DO_GROUPSEARCH_V10 in order to be called by the original     
;       menu option                                                     
;      Changed the name of the dialog box proc to use the _V10 ending   
; 1.5  Revised 06-29-94 12:50pm by Gary Mugford                         
;      In the GroupSearch routines, have modified the speedbars in the  
;       KwikSearch screen and in the actual Edit and View modes. Have   
;       also put a view/edit mode indicator in the prompt as needed.    
;       Have added access to the KwikPrint functions that kick out a    
;       reprinted warranty on demand.                                   
;ͼ

; ## --------------------------------------------------------------------------
; proc: DO_GROUPSEARCH_V10   Function: Searchs the main database for a group of
;                                      files and then permits the editing of
;                                      particular file from that group
; -------------------------------------------------------------created 03-19-93
; modified by Henrik Bechmann, April 1994 to accomodate remote database...
proc DO_GROUPSEARCH_V10()
   private PROCNAME.a,
      ; query variables...
      APPNUM.q,
      BIZ_NAME.q,
      BIZ_CITY.q,
      BIZ_PC.q,
      CUS_NAME.q,
      CPC.q,
      MUFF_NUM.q,
      MAKE.q,
      MODEL.q,
      YEAR.q,
      ; control variables...
      FOUND.n,
      TEMP.l,
      ; workspace data...
      OUTKEY.a,
      EDIT_NUM.a,
      results_form.a,
      full_form.a,
      oldusername,
      groupsearch.record,
      WILD_CARD.q

   PROCNAME.a="DO_GROUPSEARCH_V10"

   message "Preparing for a Group Search"
   prompt ""
   echo off

   lock "localreg" FL
   while not retval
      lock "localreg" FL
   endwhile

   copy "localreg" privdir() + "localreg"

   unlock "localReg" FL

   reset

   privtables "localreg","$answer"

   groupSearch!initVars()

   ;-----------------------------------------------------------------------
   ; open remote database...
   ;-----------------------------------------------------------------------

   SQLLink.ConnectToServer(SQLLink.ParameterBag)

   ;-----------------------------------------------------------------------
   ; initialize local working tables
   ;-----------------------------------------------------------------------
   empty "localreg"

   ;-----------------------------------------------------------------------
   ; cycle throught the dialog box, to prevent unneccesary link and unlink
   ; to the database server. The only exit location for the loop is marked
   ; a few lines below.
   ;-----------------------------------------------------------------------
   while true
      ;-----------------------------------------------------------------------
      ; get criterion for search, exit if abandoned...
      ;-----------------------------------------------------------------------
      TEMP.l= DLG_GROUPSEARCH_V10()

      if TEMP.l=false then
         clearall
         ; unlock all
         quitloop ; <<<<<<<<<<<<<<< exit point ****************
      endif

      if not groupsearch!isCriteriaOK() then
         loop
      endif

      found.n = groupSearch!searchRemote()

      ;-----------------------------------------------------------------------
      ; allow user to see results of the search...
      ;-----------------------------------------------------------------------
      if FOUND.n>0 then

         message "Please be patient"

         groupSearch!prepDisplayResults()

         VIEW.l=true

         ;--------------------------------------------------------------------
         ; user can cycle through records or edit a record, after which the
         ; download table is abandoned. prepdisplayresults above renames the
         ; answer table to $answer
         ;--------------------------------------------------------------------
         while VIEW.l
            moveto "$answer"
            pickform RESULTS_FORM.a
            gmCLEAR_FRAME()

            groupSearch!wait()
            switch
               case OUTKEY.a="F8" :
                  if groupSearch!EditRecord() then
                     VIEW.l=false
                  endif
               case OUTKEY.a="F4" :
                  groupSearch!viewRecord()
               case OUTKEY.a="Esc":
                  VIEW.l=false
            endswitch
         endwhile
         delete "$answer"
         clear
      else
         if isTable("Answer") then
            delete "Answer"
         endif
         clear
      endif
   endWhile
   groupsearch!cleanup()

endproc

proc groupSearch!initVars()
   ;-----------------------------------------------------------------------
   ; initialize variables...
   ;-----------------------------------------------------------------------
   APPNUM.q     =""
   BIZ_NAME.q   =""
   BIZ_CITY.q   =""
   BIZ_PC.q     =""
   CUS_NAME.q   =""
   CPC.q        =""
   MUFF_NUM.q   =""
   MAKE.q       =""
   MODEL.q      =""
   YEAR.q       =""
   WILD_CARD.q  =""

   ;-----------------------------------------------------------------------
   ; initialize SQLLink code for up and down loading memos...
   ;-----------------------------------------------------------------------
   SQLLink.constructor()
   oldusername = Username()
   setUserName "User1"
   SQLLink.parameterBag["Title"] = "MainSrv_r"
   SQLLink.parameterBag["UserName"] = "User1"
   SQLLink.parameterBag["Password"] = "User1PW"
   SQLLink.parameterBag["Database"] = "bluejay:/interb/v10/v10main.gdb"

   SQLLink.TableParmBag["BlobPointerTabSpec"]      = "Answer"
   SQLLink.TableParmBag["ServerTabSpec"]           = DB_MAIN.a
   SQLLink.TableParmBag["ServerKeyFieldName"]      = "AppNum"
   SQLLink.TableParmBag["ServerMemoFieldName"]     = "Followup"
   SQLLink.TableParmBag["ClientTabSpec"]           = "localreg"
   SQLLink.TableParmBag["ClientKeyFieldName"]      = "AppNum"
   SQLLink.TableParmBag["ClientMemoFieldName"]     = "Followup"

   ; anticipate appendarray
   SQLLink.ClientKeyFieldList[1] = SQLLink.TableParmBag["ClientTabSpec"]

endProc

;-------------------------------------------------------------------------
; search the remote table based on criteria entered in dialog box...
; returns the number of found records
;-------------------------------------------------------------------------
proc groupSearch!searchRemote()
   private
      found.n
   ;-----------------------------------------------------------------------
   ; implement search on remote table...
   ;-----------------------------------------------------------------------
   if isTable("Answer") then
      delete "Answer"
   endif
   message "Executing search. Please be patient"
   menu {Ask} select DB_MAIN.a
      ctrlHome checkplus ; select all fields
      moveto [Appnum]  []=[]+APPNUM.q
      moveto [BName]   []=[]+BIZ_NAME.q
      moveto [BCity]   []=[]+BIZ_CITY.q
      moveto [BPC]     []=[]+BIZ_PC.q
      moveto [PartNum] []=[]+MUFF_NUM.q
      moveto [VMake]   []=[]+MAKE.q
      moveto [VModel]  []=[]+MODEL.q
      moveto [VYear]   []=[]+YEAR.q
      moveto [CName]   []=[]+CUS_NAME.q
      moveto [CPC]     []=[]+CPC.q

   do_it!

   if not isTable("Answer") then ; error in condition formulation...
;      message window()
      wild_card.q = window()
      found.n = 0
   else
      FOUND.n=nrecords("Answer")
      if found.n = 0 then
         wild_card.q = "Search unsuccessful"
      endif
   endif
   moveto 1 ClearImage
   return found.n
endProc

;-------------------------------------------------------------------------
; make sure that groupsearch criteria will not lead to inordinately large
; answer...
; Rules applied: HB May 1, 1994...
; if the application number is set, then blank out all other criteria and
;     proceed
; if any criterion other than one of the postal codes has a wild card
;    character, disallow the search.
; if business or customer name, city and postal code are all blank, then
;    disallow the search.
; if postal codes have wild cards other than trailing ".." then disallow
;   the search.
; if postal codes are set in the absence of customer or business name or
;   city, and are only one character, then disallow the search.
; if postal codes have trailing ".." or are shorter than 7 characters, then
;   change the criterion to >=x,<x, with the second x right-padded with "Z"
;   to make the second x seven characters long.
;-------------------------------------------------------------------------
proc groupSearch!isCriteriaOK()
   private OK

   OK = true

   ;---------------------------------------------------------------------
   ; if the application number is specified then blank out any other
   ; criteria....
   ;---------------------------------------------------------------------
   if appNum.q <> "" then
      BIZ_NAME.q   =""
      BIZ_CITY.q   =""
      BIZ_PC.q     =""
      CUS_NAME.q   =""
      CPC.q        =""
      MUFF_NUM.q   =""
      MAKE.q       =""
      MODEL.q      =""
      YEAR.q       =""
   else
   ;---------------------------------------------------------------------
   ; clear out ".." and "@" from search strings...
   ;---------------------------------------------------------------------
      OK = groupSearch!cleanVar("appnum.q")
      if OK then
         OK = groupSearch!cleanVar("biz_name.q")
      endif
      if OK then
         OK = groupSearch!cleanVar("biz_city.q")
      endif
      if OK then
         OK = groupSearch!cleanVar("cus_name.q")
      endif
      if OK then
         OK = groupSearch!cleanVar("muff_num.q")
      endif
      if OK then
         OK = groupSearch!cleanVar("make.q")
      endif
      if OK then
         OK = groupSearch!cleanVar("model.q")
      endif
      if OK then
         OK = groupSearch!cleanVar("year.q")
      endif

      ;---------------------------------------------------------------------
      ; if the operator does not include specifics about the business or the
      ; customer then the search is too general and the process is aborted
      ;---------------------------------------------------------------------
      if OK and
         BIZ_NAME.q   ="" and
         BIZ_CITY.q   ="" and
         BIZ_PC.q     ="" and
         CUS_NAME.q   ="" and
         CPC.q        ="" then
;         message "Must include business or customer name, city or postal code"
         wild_card.q = "Must include names, city or PC"
         OK = false
      endif

      ;---------------------------------------------------------------------
      ; if the business and customer name are NOT included in the search
      ; criteria, then make sure that there is more than one character
      ; in at least one of their postal codes, so that the search result
      ; is likely to be manageably small.
      ;---------------------------------------------------------------------
      if OK and
         BIZ_NAME.q   ="" and
         BIZ_CITY.q   ="" and
         CUS_NAME.q   ="" then
         if (biz_pc.q = "" and len(cpc.q) = 1) or
            (cpc.q = "" and len(biz_pc.q) = 1) or
            (len(cpc.q) = 1 and len(biz_pc.q) = 1) then
;            message "need more information in postal code"
            wild_card.q = "Need more info in postal code"
            OK = false
         endif
      endif
      if OK then
         cpc.q = groupSearch!setPCVar(cpc.q)
         biz.q = groupSearch!setPCVar(biz_pc.q)
      endif
   endif
   return OK
endProc

proc groupSearch!cleanVar(VarString)
   private
      workVar
   workVar = varVal(varString)
   if workVar <> "" then
      workVar = strVal(workVar)
   endif
   if search("..",workVar) <> 0 or
      search("@",workVar) <> 0 then
;      message "Can only place wild cards in postal codes, not " + VarSTring
      wild_card.q = "wild cards in PC's only"
      return false
   endif
   return true
endProc ; groupSearch!CleanVar

;---------------------------------------------------------------------
; translate Postal Code variable into range version as equivalent to
; wildcard query.
; Wildcard to allow partial postal code entries, range operators
; added so that InterBase will use indexes (version 3.3 of InterBase
; drops indexes with wildcard searches, but retains them with range
; searches.)
;---------------------------------------------------------------------
proc groupSearch!setPCVar(PCVar)
  ; Value pictures in the accept statement of the box prevent use of illegal
  ;  and/or wildcard characters.
  private
     StringLgth
  stringLgth = len(PCVar)
  if stringLgth < 7 and stringLgth > 0 then ; wildcard need/replacement indicated
      PCVar = ">=" + PCVar + ",<" + PCVar + fill("Z",7-stringLgth)
  endif
  return PCVar
endProc ; groupSearch!setPCVar

proc groupSearch!prepDisplayResults()
   ;--------------------------------------------------------------------
   ; display the records found...
   ;--------------------------------------------------------------------
   RESULTS_FORM.a=iif(COLOUR.l,"7","6")
   full_form.a = iif(colour.l,"F","1")
   copyform "localreg" RESULTS_FORM.a "Answer" RESULTS_FORM.a
   copyform "localreg" full_FORM.a "Answer" full_FORM.a
   rename "Answer" "$answer"
   ANSWER.h=getwindow()
   message ""
   wild_card.q = ""

endProc

proc groupSearch!wait()
   ;-----------------------------------------------------------------
   ; allow user to search and view the found records...
   ; added extra speedbar keys GM 06-29-94 12:50pm
   ;-----------------------------------------------------------------
   speedbar "OUT:~ESC~"   :"Esc",
           "Edit:~F8~"    :"F8",
           "View:~F4~"    :"F4",
           "Next:~^PD~"   :-118,
           "Prev:~^PU~"   :-132,
           "Find:~^Z~"    :"Zoom",
           "Ag'n:~@Z~"    :"ZoomNext"
   prompt "FOUND: "+strval(FOUND.n)
   if isassigned(ECHO_OFF.l) then
      gmECHO_NORMAL()
   else
      echo normal
   endif

   ;-----------------------------------------------------------------
   ; wait for user input...
   ;-----------------------------------------------------------------
   wait table until "F8","Esc","F4" ; SHOULD HAVE OTHER DISALLOWABLES
   OUTKEY.a=retval
   prompt "SWITCHING views ... "
   clearspeedbar
   echo off
   prompt ""
endProc

proc groupSearch!editRecord()
   private
      Blobptr,
      allowPosting,
      doPosting
   ;-----------------------------------------------------------
   ; edit the record...
   ; get memo field...
   ;-----------------------------------------------------------

   EDIT_NUM.a=[AppNum]

   copyToArray groupSearch.record
   view "localreg"
   sqlautocommit No

   coEditKey

   appendArray groupSearch.record

   pickForm full_Form.a
   gmCLEAR_FRAME()
   blobPtr = [Followup]
   if not isBlank([Followup]) then
      if SQLLink.SetMemoVarFromServer([Followup]) then
         [Followup] = SQLLink.memoVar
      else
         do_it!
         empty "localreg"
         clearImage
         wild_card.q = SQLLink.parameterBag["Errormessage"]
         wild_card.q = "Record is out of date. Please try again."
         return False
      endif
   endif

   AllowPosting = false
   doPosting = false
   if groupsearch!attemptBlock() then
      if SQLLink.SetMemoVarFromServer(blobptr) then
         if groupSearch!checkUpToDate() then
            AllowPosting = True
         else
            wild_card.q = "Record is out of date. Please try again."
         endif
      else
         wild_card.q = "Record is out of date. Please try again."
      endif
   else
      wild_card.q = "Record is being edited by someone else."
   endif
   if AllowPosting then
      imagerights update
      [FollowUp]=THIS_DAY.a+": G/S edit- "+ENTERED_BY.a+"\n"+[FollowUp]
      moveto [BName]
      echo normal
      ;------------------------------------------------------------------
      ; Added a more extensive speedbar with calls to a Pal command print
      ; routine for direct printing of the warranties GM 06-29-94 12:44pm
      ;------------------------------------------------------------------
      speedbar  "Done:~F2~"         :"F2",
                "UnDo:~ESC~"        :"Esc",
                "KwikPrnReg:~F4~"   :"F4",
                "KwikPrnBiz:~F5~"   :"F5",
                "KwikPrnLbl:~F6~"   :"F6"
      prompt "EDIT MODE"
      doPostAnyway=false    ; Once an item has been saved with F2
                            ;  OR printed with a KwikPrint, must be
                            ;  posted despite an ESCAPE command
      while true
          wait record until "F2","F4","F5","F6","Esc"
          echo off
          OUTKEY.a=retval
          doPosting=false
          switch
            case OUTKEY.a="F2" : doPostAnyway=true
                                 doPosting=true
                                 if isfieldview() then fieldview endif
                                 quitloop
            case OUTKEY.a="Esc": if not doPostAnyway
                                  then undo
                                  else doPosting=true
                                 endif
                                 quitloop
            case OUTKEY.a="F4" : F4_DIRECT_PRINT()
                                 doPostAnyway=true
            case OUTKEY.a="F5" : F5_DIRECT_PRINT()
                                 doPostAnyway=true
            case OUTKEY.a="F6" : F6_DIRECT_PRINT()
                                 doPostAnyway=true
            otherwise          : beep
          endswitch
      endwhile
      clearspeedbar
      if doPosting
        then postrecord
      endif
      do_it!
      imagerights
      clearImage
      if doPosting then
         message "Storing changes ... "    
         ;-----------------------------------------------------------
         ; upload modified record...
         ;-----------------------------------------------------------
         SQLLink.parameterBag["ErrorCode"] = 0
         SQLLink.CreateUploadTable("$upload")
         SQLLink.UploadMemos("$upload")
         delete "$upload"
         if SQLLink.parameterBag["ErrorCode"] <> 0 then
            wild_card.q = SQLLink.parameterBag["Errormessage"]
         endif
         SQLCommit
      else
         SQLRollback
      endif
   else
      SQLRollback
      do_it!
   endif
   empty "localreg"
   sqlautocommit Yes
   message ""
   Return doPosting
endProc

;--------------------------------------------- v9Main reference here hard-coded

proc groupSearch!checkUpToDate()
   private
      theRecord,
      i
   if [Followup] <> SQLLink.memoVar then
      return false
   endif
   sql noFetch
      Select * from v9main where appnum = '~edit_num.a~'
   endSql

   SQLFetch theRecord
   SQLRelease

   for i from 2 to arraySize(theRecord)
      if theRecord[i] <> groupsearch.record[i] then
         return false
      endif
   endFor
   return true
endProc ; groupSearch!checkUpToDate

;--------------------------------------------- v9Main reference here hard-coded
proc groupSearch!attemptBlock()
   private
      errorProc,
      isTransactionOK
   errorProc = "SQLLink.handleError"
   isTransactionOK = True
   SQLStartTrans
   sql
      update V9MAIN set APPNUM = '~edit_num.a~' where APPNUM = '~edit_num.a~'
   endSql
   return isTransactionOK
endproc ; groupSearch!attemptBlock

proc groupSearch!viewRecord()
   EDIT_NUM.a=[AppNum]

   copyToArray groupSearch.record
   view "localreg"
   coEditKey

   appendArray groupSearch.record

   pickForm full_Form.a
   gmCLEAR_FRAME()

   if not isBlank([Followup]) then
      SQLLink.SetMemoVarFromServer([Followup])
      [Followup] = SQLLink.memoVar
   endif

   do_it!

   moveto [BName]
   echo normal
   ;---------------------------------------------------------------
   ; Added a much more substantial speedbar and warranty print keys
   ; to the viewing routine GM 06-29-94 12:48pm
   ;---------------------------------------------------------------
   speedbar  "Done:~F2~"         :"F2",
             "KwikPrnReg:~F4~"   :"F4",
             "KwikPrnBiz:~F5~"   :"F5",
             "KwikPrnLbl:~F6~"   :"F6"
   prompt "VIEW MODE"
   while true
       wait record until "F2","F4","F5","F6"
       OUTKEY.a=retval
       switch
         case OUTKEY.a="F2": quitloop
         case OUTKEY.a="F4": F4_DIRECT_PRINT()
         case OUTKEY.a="F5": F5_DIRECT_PRINT()
         case OUTKEY.a="F6": F6_DIRECT_PRINT()
         otherwise         : beep
       endswitch
   endwhile
   clearspeedbar
   if isFieldView() then
      FieldView
   endif
   echo off
   imagerights
   clearImage
   empty "localreg"

endProc

;-------------------------------------------------------------------------
; clean up environment after user requests exit from groupsearch facility
;-------------------------------------------------------------------------
proc groupsearch!cleanUp()
   ; unlock all
   clearall
   if isTable("$answer") then
      delete "$answer"
   endif
   delete "localreg" ; the privtables version! - HB
   ;-----------------------------------------------------------------------
   ; close remote database...
   ;-----------------------------------------------------------------------
   if sqlisConnect() then
      sqlLink.disconnectFromServer()
   endif
   sqlLink.destructor()
   reset ; to clear out privtables
   setUserName oldUserName
endProc

;--------------------------------------------------------------------------
PROC DLG_GROUPSEARCH_V10()
;--------------------------------------------------------------------------

private PaintPAL.OriginalPalette,
        CONFIRM.l,
     ;   WILD_CARD.q,
        USE_DATABASE.n,
        USE_DATABASE.a

; PaintPAL_Generated_Code_Begin(479837147)

CONFIRM.l=false

if WILD_CARD.q <> "" then
   beep beep beep
endif

USE_DATABASE.n=1
; init!vars()

; PaintPAL_Color_Setup_Begin
GETCOLORS TO PaintPAL.OriginalPalette
DYNARRAY PaintPAL.ColorDeviations[]
  PaintPAL.ColorDeviations[1031] =  48  ;Border Inactive
  PaintPAL.ColorDeviations[1032] =  63  ;Border Active
  PaintPAL.ColorDeviations[1033] =  58  ;Border Dragging/Icons
  PaintPAL.ColorDeviations[1036] =  56  ;Background Text
  PaintPAL.ColorDeviations[1037] =  48  ;Label Inactive
  PaintPAL.ColorDeviations[1038] =  63  ;Label Selected
  PaintPAL.ColorDeviations[1039] =  62  ;Label Shortcut
  PaintPAL.ColorDeviations[1040] =  32  ;Pushbutton normal
  PaintPAL.ColorDeviations[1041] =  46  ;Pushbutton default
  PaintPAL.ColorDeviations[1042] =  47  ;Pushbutton selected
  PaintPAL.ColorDeviations[1044] =  46  ;Pushbutton hotkey
  PaintPAL.ColorDeviations[1046] =  63  ;Cluster Normal
  PaintPAL.ColorDeviations[1047] =  63  ;Cluster Selected
  PaintPAL.ColorDeviations[1048] =  62  ;Cluster Shortcut
  PaintPAL.ColorDeviations[1049] =  75  ;Accept Line Normal
  PaintPAL.ColorDeviations[1050] =  31  ;Accept Line Selected
  PaintPAL.ColorDeviations[1051] =  78  ;Accept Line Arrows
SETCOLORS FROM PaintPAL.ColorDeviations
RELEASE VARS PaintPAL.ColorDeviations
; PaintPAL_Color_Setup_End

SHOWDIALOG "Record Requestor"
  @1,0 HEIGHT 23 WIDTH 79
  PAINTCANVAS ATTRIBUTE 48 0,0,20,23
; PaintPAL_Frame_Begin
  frame single from 1,25 to 8,48
  paintcanvas border attribute 48 1,25,8,48
; PaintPAL_Frame_End
; PaintPAL_Frame_Begin
  frame single from 10,25 to 19,48
  paintcanvas border attribute 48 10,25,19,48
; PaintPAL_Frame_End
; PaintPAL_Frame_Begin
  frame single from 1,50 to 8,75
  paintcanvas border attribute 48 1,50,8,75
; PaintPAL_Frame_End
; PaintPAL_Frame_Begin
  frame double from 0,23 to 20,23
  paintcanvas border attribute 59 0,23,20,23
; PaintPAL_Frame_End
; PaintPAL_Frame_Begin
  frame single from 2,1 to 2,21
  paintcanvas border attribute 59 2,1,2,21
; PaintPAL_Frame_End
; PaintPAL_Frame_Begin
  frame single from 10,50 to 13,75
  paintcanvas border attribute 56 10,50,13,75
; PaintPAL_Frame_End
; PaintPAL_Static_Text_Begin
  PAINTCANVAS FILL " " ATTRIBUTE 49 3,1,13,21
  @3,1    ?? "\7 Use this screen to"
  @4,1    ?? "search for a record"
  @5,1    ?? "or group of records."
  @6,1    ?? "\7 By filling in the"
  @7,1    ?? "blanks with as much"
  @8,1    ?? "(or as little) info"
  @9,1    ?? "as you have, you will"
  @10,1   ?? "be able to retrieve a"
  @11,1   ?? "set of records to"
  @12,1   ?? "examine (and/or edit)"
  @13,1   ?? "further."
  PAINTCANVAS ATTRIBUTE 49 3,1,13,21
; PaintPAL_Static_Text_End
; PaintPAL_Static_Text_Begin
  PAINTCANVAS FILL " " ATTRIBUTE 49 14,1,19,21
  @14,1   ?? "\7 Wild cards (..) are"
  @15,1   ?? "FORBIDDEN in v10.0,"
  @16,1   ?? "however you can get "
  @17,1   ?? "helpful range hint"
  @18,1   ?? "help by pressing the"
  @19,1   ?? "Range Helper key."
  PAINTCANVAS ATTRIBUTE 49 14,1,19,21
; PaintPAL_Static_Text_End
; PaintPAL_Static_Text_Begin
  PAINTCANVAS FILL " " ATTRIBUTE 49 1,1,1,21
  @1,1    ?? "        NOTES"
  PAINTCANVAS ATTRIBUTE 49 1,1,1,21
; PaintPAL_Static_Text_End
; PaintPAL_Static_Text_Begin
  PAINTCANVAS FILL " " ATTRIBUTE 49 20,25,20,74
  @20,26  ?? "HINTS \205\205\16 "+WILD_CARD.q
  PAINTCANVAS ATTRIBUTE 49 20,25,20,74
; PaintPAL_Static_Text_End
  accept @3,26 width 22
    "a10"
    picture "*!"
    tag "APPNUM.tag"
    to APPNUM.q
  label @2,26
    "~1~ App Number "
    for "APPNUM.tag"
  accept @5,26 width 22
    "A25"
    picture "&[#[&[ #[&[#]]]]]"
    tag "CPC.tag"
    to CPC.q
  label @4,26
    "~2~ Customer PC     "
    for "CPC.tag"
  accept @7,26 width 22
    "A25"
    picture "{>=*!,!*[{ ,.,(,;,}*{ ,.,(,:,}!,@]}"
    tag "CNAME.tag"
    to CUS_NAME.q
  label @6,26
    "~3~ Customer Last Name"
    for "CNAME.tag"
  accept @12,26 width 22
    "A25"
    picture "{>=*!,#####[#]}"
    tag "MUFF.tag"
    to MUFF_NUM.q
  label @11,26
    "~4~ Muffler PartNumber "
    for "MUFF.tag"
  accept @14,26 width 22
    "A25"
    picture "{>=*!,!*[{ ,.,(,;,}*{ ,.,(,:,}!,@]}"
    tag "VMAKE.tag"
    to MAKE.q
  label @13,26
    "~5~ Vehicle Make "
    for "VMAKE.tag"
  accept @16,26 width 22
    "A25"
    picture "{>=*!,!*[{ ,.,(,;,}*{ ,.,(,:,}!,@]}"
    tag "VMODEL.tag"
    to MODEL.q
  label @15,26
    "~6~ Vehicle Model"
    for "VMODEL.tag"
  accept @18,26 width 22
    "A25"
    picture "{>=*!,#[#][#]}"
    tag "VYEAR.tag"
    to YEAR.q
  label @17,26
    "~7~ Vehicle Year "
    for "VYEAR.tag"
  accept @3,51 width 24
    "A25"
    picture "{>=*!,!*[{ ,.,(,;,}*{ ,.,(,:,}!,@]}"
    tag "BNAME.tag"
    to BIZ_NAME.q
  label @2,51
    "~8~ Business Name "
    for "BNAME.tag"
  accept @5,51 width 24
    "A25"
    picture "{>=*!,!*[{ ,.,(,;,}*{ ,.,(,:,}!,@]}"
    tag "BCITY.tag"
    to BIZ_CITY.q
  label @4,51
    "~9~ Business City "
    for "BCITY.tag"
  accept @7,51 width 24
    "A25"
    picture "&[#[&[ #[&[#]]]]]"
    tag "BPC.tag"
    to BIZ_PC.q
  label @6,51
    "~A~ Business PC "
    for "BPC.tag"
  radiobuttons @12,51 height 1 width 24
    "Main",
    "ConvApps"
    tag "1"
    to USE_DATABASE.n
  label @11,51
    "~T~arget Database"
    for "1"
  pushbutton @16,50 width 7
    "~Y~es "
    ok
    value true
    tag "OK_BUTTON.tag"
    to CONFIRM.l
  pushbutton @16,58 width 7
    "~N~o!"
    cancel
    value false
    tag "NO_BUTTON.tag"
    to CONFIRM.l
  pushbutton @16,66 width 10
    "~H~ELPER"
    value DLG_WILD_CARD()
    tag "WILD.tag"
    to WILD_CARD.q
ENDDIALOG

if USE_DATABASE.n=2
  then USE_DATABASE.a=DB_CA.a
  else USE_DATABASE.a=DB_MAIN.a
endif

; For testing purposes until CA access is provided ...
USE_DATABASE.a=DB_MAIN.a

; PaintPAL_Color_Cleanup_Begin
  SETCOLORS FROM PaintPAL.OriginalPalette
  RELEASE VARS PaintPAL.OriginalPalette
; PaintPAL_Color_Cleanup_End

return CONFIRM.l
; PaintPAL_Generated_Code_End(479837147)
ENDPROC ; DLG_GROUPSEARCH_V10()

Ŀ
 CONTACT 


All of the parties will be more than happy to converse and share with others
interested in the processes described above. Please bear in mind that all are
busy with their disperate companies and help requests in moderation will be
appreciated.

The time zone Upper Canada is situated in is the Eastern Time Zone of North
America, so please confine phone calls to working hours on that basis. Gary
keeps programmer hours (11 am to 3 am), the others roughly obeying standard
office hours of 9 am to 5 pm. Richard is normally at Upper Canada four of five
weekdays and Henrik is in the Elect offices about two of each five weekdays.

Telephone contact is as follows: Upper Canada (905) 507-2092, Mugford Info
Services (905) 793-0219 and Elect Software (416) 534-8176.

Compuserv contact is limited to Gary and Henrik. Gary normally monitors the
Paradox for Dos forum while Henrik hangs out on the Interbase forum with the
occasional foray into Paradox for Windows. Both answer mail. Henrik is a daily
checker on CIS and a TeamB member. Gary checks in every other day (or so).

CIS addresses: Gary Mugford 70274,2254   Henrik Bechmann 72701,3717

In conclusion, hope this paper has been enough to help you out. THE END?
