! *viewer/preview.pvc - Graphical Print Preview Object
! By Gord Davey
! (c) Copyright 2004-2005 Sage Software Canada Ltd.
! Version Info:
! Source Code File: $RCSfile: preview.pvs,v $   Version: $Revision: 1.78 $
!      Last Edited: $Date: 2006/03/02 21:30:45 $   Author: $Author: gordd $
!
! This object contains the logic to create and control the GUI Print Previewer
!
def class "*viewer/preview" create OnCreate required delete OnDelete required

    property Version$ = mid(mid("$Revision: 1.78 $",12), 1, len(mid("$Revision: 1.78 $",12)) - 2)
    precision 6

    local EventCounter
    local This
    local SaveFont$, SaveSTDFont$, SaveGraphicFont$
    local SaveIZ, SavePC, SaveTU, SaveTA
    local ViewerDir$
    local MessageLibrary, ParametersSoftware, ParametersUsers, WinAPI, Constants, Theme ! Internal Objects
    local BaseWHnd, Monitor  ! Window's Window Handle
    local BasePHnd, GotoPHnd, ZoomPHnd, BannerPHnd, AboutPHnd, FindPHnd ! ProvideX window Handles
    local ExtraVisualEffects
    local ImageLook$  ! "XP" or "2K"
    local ImageColour$ ! "256" or "16M"
    local ImageFlat$  ! "" or "F"
    local ImageSize$  ! "16" or "24" or "32"
    local CurrentWindowList$, Icon16$, Icon32$
    local ColGUs, RowGUs ! Column and Row Graphical Unit Size
    local VisiblePages$, ViewComplete
    local RenderErrorOnPages$
    local TimeVal

    local InitialPage
    local PrinterChan, IsPrinting, IsPrinted, CheckPrint, PrintingRange$, PrintingDPI
    local PrintingUnCollatedCopy, PrintingCollatedCopy, PrintingPage, PrintingTotalPages

    local SplashClass$, ReportClass$, WaterMarkClass$

    local IsWindows, IsUnix, IsWindX, IsJavX, IsWindX$
    local ForceRePaint

    local LastOpenPath$, LastOpenFile$
    local LastSaveAsPath$
    local IsSpooled, IsSpooling, CheckSpool

    local ViewPort
    local ViewPortWindow
    local ViewColumn, ViewRow
    local ViewColumns, ViewRows
    local WindowState, WinPlacementDone, HasWindowOverrides

    local BorderWidth, BorderHeight, FrameWidth, FrameHeight
    local ColourDlgWorkSpace$, ColourDlgBase$, Colour3DDark$, Colour3DLight$, ColourShadow$, \
          AboutBackgroundColour$, AboutTextColour$

    local StatusBar, StatusBarHeight, StatusBarRow
    local StatusBarSep0,  StatusBarSep1,  StatusBarSep2
    local StatusBarS1, StatusBarSection1, StatusBarS1Text$
    local StatusBarS2, StatusBarSection2, StatusBarS2Text$
    local StatusBarS3, StatusBarSection3, StatusBarS3Text$, StatusBarS3Tip$

    local ToolBar, ToolBar$, ToolBarExtra$, ToolBarFlatButtons, ToolBarHeight, ToolBarSize
    local ToolBarButtonHeight, ToolBarButtonWidth, ToolBarButtonRow
    local ToolBarRightClickMenu, ToolBarDropButton
    local ToolBarStart, ToolBarMenuX, ToolBarMenuY
    local ToolTips, IconSize
    local ToolBarCustomize

    local Menu$, DMenu, CurrentMenu$

    local objs$, cntls
    local FOpen, FClose, FSaveAs, FSaveAsPDF, FDelete, FPrint, FExit, FPauseSpool
    local EFind, EFindAgain, EFindPrev
    local SearchString$, SavedSearchStrings$, MatchCase, SearchDirection, SearchLastPage
    local VTop, VPrevious, VNext, VBottom, VGoto, VJump
    local VZoom, VZoomIn, VZoomOut, VZoomWidth, VZoomWindow, VZoomCustom
    local MZoomCustom, MGoto
    local VOne, VTwo, VFour, VBook, VLayout
    local VBanner
    local VToolBar, VStatusBar, VToolTip, VWaterMark
    local HContent, HIndex, HAbout
    local BOK, BCancel
    local IgnoreNextTab
    local DGotoJump, DGotoOK, DGotoCancel, DGotoQuit, DGotoTabKey, DGotoBackTabKey, DGotoFocus
    local DZoomCustom, DZoomOK, DZoomCancel, DZoomQuit, DZoomTabKey, DZoomBackTabKey, DZoomFocus
    local DBannerInfo, DBannerOK, DBannerQuit, DBannerTabKey, DBannerBackTabKey, DBannerFocus
    local DAboutQuit
    local DFindText, DFindMatch, DFindDir, DFindOK, DFindCancel, DFindQuit
    local DFindTabKey, DFindBackTabKey, DFindFocus

    local LastZoomLevel, CurrentZoom
    local ZoomLevel                  ! Current ZoomLevel -1=Fit To Width, -2=Fit to Window, Default=-1
    local ZoomLevels$                ! String of Zoom Levels, comma sep percentages (15, 20, 25, 35, 50, 75, 100, 125, 150, 200, 400, -1, -2)
    local ZoomLevels, VZoomLevels$

    local ScrollBars, BVScroll, BHScroll
    local VScrollMax, HScrollMax
    local VScrollLastMax, HScrollLastMax
    local VScrollCurPos, HScrollCurPos
    local VScrollLastPos, HScrollLastPos
    local VScrollSmallJump, HScrollSmallJump
    local VScrollBigJump, HScrollBigJump
    local VScrollSmallSize, HScrollSmallSize

    local BTop, BPrevious, BBlank, BNext, BBottom

    local TPage$,TPages$,TOf$,TLoading$,TZoom$,TPercent$,TSpooling$,TSpoolingPaused$

    ! Image Buttons
    local ImageButton1,ImageButton2,ImageButton3,ImageButton4
    local ImageButtonRight1,ImageButtonRight2,ImageButtonRight3,ImageButtonRight4
    local BorderButton1,BorderButton2,BorderButton3,BorderButton4
    local ShadowButton1,ShadowButton2,ShadowButton3,ShadowButton4

    ! Image Buffers
    local ImageBuffer, ImageBuffers, ImageBufferItems, LastAssignedBuffer
    local VisibleImage, VisibleImages, VisibleImageItems

    ! Events to Handle
    local EQuit, ReSize, TabKey, BackTabKey, HomeKey, EndKey
    local LeftMouseDown, RightMouseDown, LeftMouseUp, RightMouseUp
    local PgUpKey, PgDnKey, CurLeft, CurRight, CurUp, CurDown, CTLCurLeft, CtlCurRight
    local F3Key, ShiftF3Key

    local RefreshScreen ! set to 0 if you do not want intermediate drawing functions to update the screen

    local SplashImage$, Splash

    local Company$, CompanyInfo1$, CompanyInfo2$, CompanyInfo3$, CompanyInfo4$

    local WarningImage$, WarningTip$

    local SaveAsExtensions$, SaveAsExtensionsDefault$, SaveAsPDFExtensions$, \
          SaveAsPDFExtensionsDefault$, OpenExtensions$

    property Language$ = MessageLibrary'Language$   set SetLanguage

    property Report     object

    property Software$                  set err
    property SuppressSplashScreen        set err
    property SuppressStatusBar           set SetSuppressStatusBar
    property SuppressToolBar             set SetSuppressToolBar
    property SuppressToolTips            set SetSuppressToolTips
    property SuppressWaterMarks          set SetSuppressWaterMarks
    property SuppressBannerInfo          set SetSuppressBannerInfo ! 1=suppress info, 0=Allow user to query info
    property Caption$                   set SetCaption ! Window caption of viewer
    property Icon$                      set SetIcon ! Icon for upper left corner of viewer

    property Left                       ! Upper Left Location of primary Window X-Axis in pixels
    property Right                      ! Width of primary Window in pixels
    property Top                        ! Upper Left Location of primary Window Y-Axis in pixels
    property Bottom                     ! Height of primary Window in pixels

    property Column   get GetColumn  ! location of base window on current monitor
    property Row      get GetRow     !location of base window on current monitor
    property Columns  get GetColumns ! width of base window on current monitor
    property Rows     get GetRows    ! height of base window on current monitor

    property SetWindowStateOnCreate        set SetWindowStateOnCreate        ! 0 | 1
    property SetWindowStateOnSpoolStart    set SetWindowStateOnSpoolStart    ! 0 | 1
    property SetWindowStateOnFirstPage     set SetWindowStateOnFirstPage     ! 0 | 1
    property SetWindowStateOnSpoolComplete set SetWindowStateOnSpoolComplete ! 0 | 1

    ! LookAndFeel and ThemeName must be set prior to doing an 'Init() or changing it will have no effect
    property LookAndFeel                ! 0|1|2 = Auto Select, 3=3D, 4=4D
    property ThemeName$                 ! Use Specific ThemeName,

    property Visible                    set SetVisible ! 1=primary Window Visible / 0=Not Visible

    property Page                       set err ! Current Page
    property Pages                      set err ! Total Pages

    property View     set SetView       ! 0 = 1 page at a time, no page scrolling (Default)
                                        ! 1 = 2 pages at a time, no page scrolling (odd on left, even on Right)
                                        ! 2 = 2 pages at a time, odd on right, Even on Left (Book Style)
                                        ! 3 = 4 pages at a time

    property Zoom                       set SetZoom ! Current Zoom Percent

    property FileName$                  set err ! Disk Filename of report to view
    property DPIScreen                  ! Screen resolution, 0 = default of 120 dpi

!    property Security     How about some access restrictions stored in print file ?
!    perhaps a Callback for the user to check the security code stored in the viewer print file ?

    property Printer$                   set err ! Last Printer that was printed to.
    property PrinterDescription$        set err ! Description of Last Printer that was printed to.
    local PrinterSelectionCallBack$ ! Allow the developer to use their own Printer Selection Routine ! Name of a Program will be called with 2 args
!    property CloseAfterPrint          ! Force the viewer to close after the user selects Print
    property DisableSaveAs              set SetDisableSaveAs ! 1=Disable, 0=Allow
    property DisableDelete              set SetDisableDelete ! 1=Disable, 0=Allow
    property DisablePrint               set SetDisablePrint ! 1=Disable, 0=Allow
    property DisableSearch              set SetDisableSearch ! 1=Disable, 0=Allow
    property DisableWatermarks          set SetDisableWaterMarks ! 1=Disable, 0=Allow
    property DisableBanner              set SetDisableBanner ! 1=Disable, 0=Allow

    property Collate                    set SetCollate ! 0=No Collation, 1=Yes Collate (default)
    property Colour                     set SetColour ! 0=Monochrome, 1=Colour (default)
    property Color = Colour             set SetColour ! 0=Monochrome, 1=Colour (default)
    property Range$                     set SetRange ! "" or "ALL"=Default or value "StartPageNum:EndPageNum" or "Page,Page,FromPage:ToPage,Page"
    property Copies                     set SetCopies ! Number of copies to print, default of 1
    property DPIPrinter                 set SetDPIPrinter ! Printer Resolution, 0 = printer default

    property DefaultOpenPath$
    property DefaultSaveAsPath$
    property AlwaysUseDefaultOpenPath

    property DefaultPaperSize           set SetDefaultPaperSize ! Defaults to 0, which tells the Pages to use their default, which is letter
    property DefaultOrientation         set SetDefaultOrientation ! Default to 0, portrait
    property DefaultOrientation$        set SetDefaultOrientationString ! Default to "Portrait"
    property DefaultFixedFont$          set SetDefaultFixedFont ! Contains the name of the Fixed Width Font to use, Defaults to Courier New
    property DefaultFixedFontSize       set SetDefaultFixedFontSize ! Contains the point size of the Default Fixed Width Font to use. 0=Calc based on ReportColumns/Lines
    property MinimumColumns             set SetMinimumColumns ! Minimum number of columns for report ie: 132 columns
    property MinimumRows                set SetMinimumRows ! Minimum number of lines for report  ie: 66 lines
                                         ! 0=Auto Calc based on number of lines in first non-blank page
    property PaginationAt               set SetPaginationAt ! 0=Contains FormFeeds, >0 Line number to paginate at
    property ScaleToFit                 set SetScaleToFit ! 0=no, 1=Force report to fit the page

    property WaterMark object ! This is an Object to access the report's watermark
    property WaterMarkPages              set SetWaterMarkPages ! 0=None, 1=First Page, 2=All Pages
    property OutputEvenNumberOfPages    set SetOutputEvenNumberOfPages ! Forces all reports to product an even number of Pages in total
    property Banner                     set SetBanner ! Print Banner Page 0=No banner, 1=Banner before print job, 2=Banner before each copy

    property SuppressFirstBlankPage     set SetSuppressFirstBlankPage ! 1=Suppress leading blank pages (default), 0=No suppression
    property SuppressAllBlankPages      set SetSuppressAllBlankPages ! 1=Suppress blank pages (default), 0=No suppression

    property PageGutterVertical         set SetPageGutterVertical
    property PageGutterHorizontal       set SetPageGutterHorizontal

    function Print()                    PrintReport ! print whole report with user printer selection dialogue
    function Print(Printer$)            PrintReport ! print whole report to printer specified

    function Open()                     OpenFilePrompt
    function Open(FileName$)            OpenFileName
    function Open(ObjectHandle)         OpenFileHandle
    function Close()                    CloseFile

    function SaveAs()                   FileSaveAs ! Show a SaveAs Dialogue
    function SaveAs(FileName$)          FileSaveAs ! force a save as to a specific name
    function SaveAsPDF()                FileSaveAsPDF ! Show a SaveAs Dialogue
    function SaveAsPDF(FileName$)       FileSaveAsPDF ! force a save as to a specific name

    function Find()                       DialogueFindCreate ! show dialog to find some text
    function Find(String$)                SearchForText ! find some text
    function Find(String$, CaseSensitive) SearchForText ! find some text
    function FindNext()                   SearchForTextNext ! find next occurance of current search string
    function FindPrevious()               SearchForTextPrevious ! find previous occurance of current search string

    function Delete()                   DeleteFile
!    function Cancel()                   ! to cancel spooling

!    function Help()                     ! Displays Online Help
    property HelpFile$                  ! Filename of Helpfile
    property HelpIndex$                 ! Reference for Helpfile Index page
    property HelpContents$              ! Reference for the Helpfile Contents page
!    function Help(function$, Reference$) ! Sets help references for various Viewer functions
!    function Help(function$)            ! Returns help references for various Viewer functions

    property UsePrinter$                ! Name of default printer to output a print to
    property SuppressPrinterSelection   ! 1=No printer selection allowed use Printer$, 0=Allow user to select printer

!    property INIFile$                   ! Ini file to use when invoking the viewer

    function Init() Initialize          ! Creates viewer window

    function Quit()                     ! close and exit browser
        preinput EQuit

!    function Minimize()                 ! Minimize viewer window
!    function Maximize()                 ! Maximize Viewer window
!    function Restore()                  ! switch to a normal or restore state viewer window
!    function Hide()                     ! hide the viewer window (see Visible)

    function GotoPage()                 DialogueGotoPageCreate ! jump to top of page specified
    function GotoPage(Page%)            GotoPage ! jump to top of page specified
    function FirstPage()                FirstPage ! jump to top of first page of report
    function LastPage()                 LastPage ! jump to top of last page of report
    function NextPage()                 NextPage ! jump to top of next page of report
    function PreviousPage()             PreviousPage ! jump to top of previous page of report

    function ScrollUp()                 ScrollUp
    function ScrollUp(Amount)           ScrollUp
    function ScrollDown()               ScrollDown
    function ScrollDown(Amount)         ScrollDown
    function ScrollLeft()               ScrollLeft
    function ScrollLeft(Amount)         ScrollLeft
    function ScrollRight()              ScrollRight
    function ScrollRight(Amount)        ScrollRight

    function Zoom()                                 DialogueZoomCreate ! Zoom to specific level
    function Zoom(ZoomLevel%)                       SetZoom ! Zoom to specific level
    function Zoom(ZoomLevel%, ColumnPercent, RowPercent)          SetZoom ! Zoom to specific level center at percent of page
    function ZoomIn()                               ZoomIn  ! Zoom in one notch
    function ZoomIn(ColumnPercent, RowPercent)                    ZoomIn  ! Zoom in one notch center at point
    function ZoomOut()                              ZoomOut ! Zoom out one notch
    function ZoomOut(ColumnPercent, RowPercent)                   ZoomOut ! Zoom out one notch center at point

!    function NotifyOnEvent(EventName$,wHnd%,CTL%) ! register notification events

    function Event(Text$, ControlVal, EOM$, Mouse$, UseTimer%)   HandleEvent ! Handles Events
    function Process()  ProcessEvents

    function SetCallBack(EventName$, Routine$)      SetCallBack

    function local DisplayError$(Text$,Options$)    DisplayError
    function local DisplayError$(Text$)             DisplayError

    function local SetMessageLibrary()  SetMessageLibrary

    function local GetDefaultValues()   GetDefaultValues ! Gets any defaults for the viewer
    function local GetWindowsDefaults() GetWindowsDefaults ! Gets MS Window Default Values
    function local SaveStates()         SaveStates       ! Saves User Parameters for use next time
    function local CheckPlatform()      CheckPlatform    ! Ensures people are using the right OS etc.
    function local CheckVersion()       CheckVersion     ! Checks ProvideX and WindX version levels
    function local GetAccelerator$(string$)     GetAccelerator
    function local ResolveIcon(IconPath$, Reference$, Transparency$)       ResolveIcon

    function local CreateBaseWindow()   CreateBaseWindow ! Creates and locates the initial Base Window.

    function local CreateMenuBar()      CreateMenuBar
    function local AddMenuItem(MenuDef$, ControlNumber, AddImage, AddAccelerator)        AddMenuItem
    function local ChangeMenu(MenuGroup$)   ChangeMenu

    function local SetLookAndFeel()     SetLookAndFeel   ! Setup any Look and Feel

    function local GetWindowLocationAndSize()   GetWindowLocationAndSize

    function local LoadObjectInfo()             LoadObjectInfo
    function local LoadObject(Name$, Menu, Type$, Counter)    LoadObject

    function local DrawStatusBar()              DrawStatusBar
    function local SetStatusBarText(Part, Value$)   SetStatusBarText
    function local SetStatusBarText(Part, Value$, ToolTip$)   SetStatusBarText

    function local DrawToolBar()                DrawToolBar
    function local DeleteToolBar()              DeleteToolBar
    function local AddToolBarTips()             AddToolBarTips
    function local RemoveToolBarTips()          RemoveToolBarTips
    function local DisplayToolBarRightMenu()    DisplayToolBarRightMenu
    function local DisplayToolBarDropMenu()     DisplayToolBarDropMenu
    function local SetSuppressToolTips(OnOff)    SetSuppressToolTips
    function local SetSuppressBannerInfo(OnOff)  SetSuppressBannerInfo
    function local SetSuppressWaterMarks(OnOff)  SetSuppressWaterMarks

    function local DrawScrollBars()             DrawScrollBars
    function local DeleteScrollBars()           DeleteScrollBars
    function local AddScrollBarTips()           AddScrollBarTips
    function local RemoveScrollBarTips()        RemoveScrollBarTips

    function local CreateViewPort()             CreateViewPort
    function local DeleteViewPort()             DeleteViewPort
    function local Makevisible()                MakeVisible

    function local ImageBufferGet(PageNumber%)  ImageBufferGet

    function local ImageButtonsClear()          ImageButtonsClear
    function local ImageButtonsMarkDirty()      ImageButtonsMarkDirty
    function local ImageButtonsSetPageNumbers(PageNumber%)    ImageButtonsSetPageNumbers
    function local ImageButtonsSetSizeLocation()  ImageButtonsSetSizeLocation
    function local ImageButtonsSetSizeLocation(IsZoomOp, ColumnPercent, RowPercent)  ImageButtonsSetSizeLocation

    function local Size1WayView(IsZoomOperation, CenterOnXPercent, CenterOnYPercent)              Size1WayView
    function local Size2WayViewToWin()         Size2WayViewToWin
    function local Size4WayViewToWin()         Size4WayViewToWin

    function local VScrollBarSelect()                               VScrollBarSelect
    function local HScrollBarSelect()                               HScrollBarSelect
    function local ScrollHorizontal(Location)   ScrollHorizontal
    function local ScrollVertical(Location, Direction)     ScrollVertical
    function local ResetVerticalScrollBar()                ResetVerticalScrollBar

    function local JumpToPage()                 JumpToPage
    function local ZoomCustom()                 ZoomCustom
    function local View(ViewNumber, ColumnPercent, RowPercent)  SetView
    function View(ViewNumber)  SetView
    function local MoveView(ColumnPercent, RowPercent)  MoveView

    function local DrawPages()                  DrawPages

    function local SetNumPages()                SetNumPages

    function local DialogueBannerInfo()         DialogueBannerInfoCreate
    function local DialogueAbout()              DialogueAboutCreate
    function local DialogueFind()               DialogueFindCreate

    function local DialogueGotoPageDestroy()    DialogueGotoPageDestroy
    function local DialogueZoomDestroy()        DialogueZoomDestroy
    function local DialogueBannerInfoDestroy()  DialogueBannerInfoDestroy
    function local DialogueAboutDestroy()       DialogueAboutDestroy
    function local DialogueFindDestroy()        DialogueFindDestroy
    function local DialogueFindMove(Page, ColumnPercent, RowPercent)    DialogueFindMove

    function local BackGroundSpool(SetTimer)    BackGroundSpool
    function local BackGroundPrint(SetTimer)    BackGroundPrint

    function local OpenPrinter(Printer$, Desc$, Options$, IsGUI, DoCopies, DoCollate, DoRange$, DoColor, DoDPI) OpenPrinter
    function local ClosePrinter()               ClosePrinter
    function local UpdatePrintOptions(Options$, NewOptions$, Copies, Collate, DoRange$, DoColor, DoDPI) UpdatePrintOptions
    function local NextPageToPrint()            NextPageToPrint
    function local OutputBlankPage()            OutputBlankPage

    function local CopyFile(InputFile$, OutputFile$)    CopyFile
    function local ProcessUpgrade()             ProcessUpgrade

    function RePaint()                          RePaint
    function local RefreshPages()               RefreshPages
    function local RefreshPages(Page%)          RefreshPages

    function local CheckParametersVersion()     CheckParametersVersion

fnend
!
OnCreate:
    This = _obj
    ViewerDir$ = "*viewer/"
    RefreshScreen = 1
    IsPrinted = 1

    SaveIZ = prm('IZ')
    SavePC = prm('PC')
    SaveTU = prm('TU')
    SaveTA = prm('TA')
    setparam 'IZ', 'PC' = 20, 'TU', 'TA' = 10
    SaveFont$ = fin(0,"FONT")
    SaveSTDFont$ = fin(0,"STDFONT")
    SaveGraphicFont$ = fin(0,"GRAPHICFONT")
    if pos("SYSTEM," = ucs(SaveGraphicFont$)) = 1 \
        then SaveGraphicFont$ = "*SysFont"

    if not(This'SetMessageLibrary()) \
        then exit 12

    This'ProcessUpgrade()

    This'GetDefaultValues()

    if not(This'CheckPlatform()) \
        then exit 99

    if not(This'CheckVersion()) \
        then exit 97

    SuppressSplashScreen = 1 ! ********************* Remove This line when the 'OPTION'() Font setting works correctly and the window creation has been corrected to eliminate the compensation
    if not(SuppressSplashScreen) then \
    {   Splash = new(SplashClass$)
        Splash'Image$ = SplashImage$
        Splash'StatusFont$ = "MS Sans Serif, -8"
        Splash'Status$ = msg("Tinitializing")
        Splash'Visible = 1
    }

    WinAPI = new(IsWindX$+"*obj/winapi")
    Constants = new(IsWindX$ + "*obj/constants/constants")

    Theme = new(IsWindX$+"*obj/theme",err=*proceed)
    if Theme \
        then Theme'Save()

    This'GetWindowsDefaults()

    This'LoadObjectInfo()

    ! Timer interval, controls the speed of background page loading and page printing. The shorter
    ! the timer the fast the pages will load/print. I would not recommend less that .01 seconds.
    ! Note, can use 100th's of second on input timer, if running locally, or in WindX Client/Server modes
    TimeVal = 0.03

    ! Note, only 1/10th of a second resolution on input timer when running against telnet
    if IsUnix and mid(ucs(pth(0)), 1, 4) = "/dev" \
        then TimeVal = 0.10

    return
!
!
OnDelete:
    print 'cursor'(1),
    _obj'SetStatusBarText(2, msg("TShutdown"))

    This'SaveStates()
    if Splash \
        then Splash'Status$ = msg("Tclosing")

    if Report \
        then drop object Report

    if MessageLibrary \
        then drop object MessageLibrary

    if WinAPI \
        then drop object WinAPI
    if Constants \
        then drop object Constants

    if Theme then \
    {   Theme'Restore()
        drop object Theme
    }

    if ParametersUsers then \
        drop object ParametersUsers

    if ParametersSoftware then \
        drop object ParametersSoftware

    if Splash \
        then drop object Splash

    if ViewPort \
        then This'DeleteViewPort()

    if BasePHnd then \
    {
        print (0,err=*proceed) 'show'(-1), \
                               'drop'(BasePhnd), \
                               'option'("FONT",SaveFont$), \
                               'option'("STDFONT",SaveSTDFont$), \
                               'option'("GRAPHICFONT",SaveGraphicFont$),
        x$ = mse
    }

    if RefreshScreen = 0 \
        then print '+U',

    setparam 'IZ' = SaveIZ, 'PC' = SavePC, 'TU' = SaveTU, 'TA' = SaveTA

    print 'cursor'(0),

    return
!
!
Initialize: ! Returns 0 on sucess. >1 = Error
    print 'cursor'("off"),'cursor'(1),'-U',
    RefreshScreen = 0
    This'CreateBaseWindow()
    This'CreateMenuBar()
    CurrentMenu$="NOFILE"
    This'View = View
    This'Zoom(ZoomLevel)
    This'Repaint()

    if SetWindowStateOnCreate \
        then This'MakeVisible()
    if Visible and HasWindowOverrides = 0 \
        then This'MakeVisible()

    print '+U',
    RefreshScreen = 1
    if Splash then \
    {   wait 1
        drop object Splash
        Splash = 0
    }
    print 'cursor'(0),
    wait 0

    return 1
!
SetLanguage:
    enter (Value$)
    MessageLibrary'Language(Value$)
    return MessageLibrary'Language$
!
!
DisplayError:
    enter (Text$), (Options$), err=*next
    if Visible = 0 \
        then return "OK"

    if Options$ = "" \
        then Options$="!,^,OK"
    if Software$ = "" \
        then Software$ = "Report Viewer"
    msgbox Text$, Software$, Options$, answer$, err=*next
    return answer$
!
!
SetMessageLibrary:
    MessageLibrary = new("*viewer/messagelib", ViewerDir$ + "messages", err=*next);
        return 1
    This'DisplayError$("Files are Missing which are required by the Report Viewer."+$0d0a$+ \
                       "Message Library missing."+$0d0a$+ \
                       "Please check your installation.")
    return 0
!
!
GetDefaultValues:
    VisibleImages = 4, VisibleImageItems = 11
    ImageBuffers = 10, ImageBufferItems = 13
    dim VisibleImage[ 1:VisibleImages, 1:VisibleImageItems ]
    dim ImageBuffer[ 1:ImageBuffers, 1:ImageBufferItems ]

    ! Entries in the "software.prm" can be supplied by a developer to customize the
    ! look and feel of the viewer with their software.
    ParametersSoftware = new("*viewer/parameters", ViewerDir$ + "software.prm")
    ParametersUsers = new("*viewer/parameters", ViewerDir$ + "users.prm")

    ! Always add the basic entries, note 'AddVariable only adds if entry does not exist
    ! and will not update an existing entry
    ParametersSoftware'AddVariable("Viewer","Software","Software","S","","","",msg("Tsoftware"))
    ParametersSoftware'AddVariable("Viewer","Software","Caption","S","","","",msg("Tsoftware"))
    ParametersSoftware'AddVariable("Viewer","Software","Icon","S","","","","<WinSysDir>\shell32.dll@134,T")
    ParametersSoftware'AddVariable("Viewer","Software","SplashImage","S","","","",ViewerDir$+"splash.bmp")
    ParametersSoftware'AddVariable("Viewer","Software","LookAndFeel","N","0","4","","0")
    ParametersSoftware'AddVariable("Viewer","Software","ThemeName","S","","255","","")
    ParametersSoftware'AddVariable("Viewer","Software","AboutBackgroundColour","S","","","","RGB:1,102,74")
    ParametersSoftware'AddVariable("Viewer","Software","AboutTextColour","S","","","","RGB:0,0,0")
    ParametersSoftware'AddVariable("Viewer","Software","SplashClass","S","","","","*viewer/splashscreen")
    ParametersSoftware'AddVariable("Viewer","Software","ReportClass","S","","","","*viewer/report")
    ParametersSoftware'AddVariable("Viewer","Software","WaterMarkClass","S","","","","*viewer/watermark")
    ParametersSoftware'AddVariable("Viewer","Software","DefaultOpenPath","S","","","","")
    ParametersSoftware'AddVariable("Viewer","Software","DefaultSaveAsPath","S","","","","")
    ParametersSoftware'AddVariable("Viewer","Software","AlwaysUseDefaultOpenPath","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Software","DisableWaterMarks","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Software","WaterMarkPages","N","0","2","","2")
    ParametersSoftware'AddVariable("Viewer","Software","DisablePrint","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Software","DisableSearch","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Software","DisableSaveAs","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Software","DisableDelete","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Software","DisableBanner","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Software","Banner","N","0","2","","0")
    ParametersSoftware'AddVariable("Viewer","Software","PrinterSelectionCallBack","S","","","","")

    ParametersSoftware'AddVariable("Viewer","Help","HelpFile","S","","","","")
    ParametersSoftware'AddVariable("Viewer","Help","HelpIndex","S","","","","")
    ParametersSoftware'AddVariable("Viewer","Help","HelpContents","S","","","","")

    ParametersSoftware'AddVariable("Viewer","Company","Company","S","","","","")
    ParametersSoftware'AddVariable("Viewer","Company","CompanyInfo1","S","","","",msg("TCompInfo1"))
    ParametersSoftware'AddVariable("Viewer","Company","CompanyInfo2","S","","","",msg("TCompInfo2"))
    ParametersSoftware'AddVariable("Viewer","Company","CompanyInfo3","S","","","",msg("TCompInfo3"))
    ParametersSoftware'AddVariable("Viewer","Company","CompanyInfo4","S","","","",msg("TCompInfo4"))

    ParametersSoftware'AddVariable("Viewer","Suppress","SuppressStatusBar","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Suppress","SuppressToolBar","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Suppress","SuppressToolTips","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Suppress","SuppressWaterMarks","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Suppress","SuppressBannerInfo","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Suppress","SuppressFirstBlankPage","B","","","","1")
    ParametersSoftware'AddVariable("Viewer","Suppress","SuppressAllBlankPages","B","","","","1")
    ParametersSoftware'AddVariable("Viewer","Suppress","SuppressPrinterSelection","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","Suppress","SuppressSplashScreen","B","","","","0")

    ParametersSoftware'AddVariable("Viewer","ToolBar","ToolBarSize","N","0","2","","1")
    ParametersSoftware'AddVariable("Viewer","ToolBar","ToolBarFlatButtons","B","","","","1")
    ParametersSoftware'AddVariable("Viewer","ToolBar","ToolBar","S","","","", \
        "FOpen,FSaveAs,FSaveAsPDF,FPrint,EFind,," + \
        "VOne,VTwo,VBook,VFour,,VZoomWidth,VZoomWindow,,VJump,," + \
        "VZoomIn,VZoomCustom,VZoomOut,," + \
        "VBanner,FPauseSpool,")

    ParametersSoftware'AddVariable("Viewer","WindowInfo","DPIScreen","N","0","600","","120")
    ParametersSoftware'AddVariable("Viewer","WindowInfo","View","N","0","3","","0")
    ParametersSoftware'AddVariable("Viewer","WindowInfo","PageGutterVertical","N","0","4","","1")
    ParametersSoftware'AddVariable("Viewer","WindowInfo","PageGutterHorizontal","N","0","4","","1.5")
    ParametersSoftware'AddVariable("Viewer","WindowInfo","ColourShadow","S","","","","RGB:48,48,48")

    ParametersSoftware'AddVariable("Viewer","ZoomInfo","ZoomLevel","N","-2","400","","-1")
    ParametersSoftware'AddVariable("Viewer","ZoomInfo","ZoomLevels","S","","","","10,15,20,25,30,35,40,50,60,70,80,90,100,125,150,175,200,300,400,")

    ParametersSoftware'AddVariable("Viewer","ScrollInfo","VScrollSmallSize","N","1","1000","","5") ! Percent 1 to 100 of Page
    ParametersSoftware'AddVariable("Viewer","ScrollInfo","HScrollSmallSize","N","1","1000","","50") ! Number of Columns (x 100) 50 = .5 Columns

    ParametersSoftware'AddVariable("Viewer","PrintInfo","Copies","N","1","999","","1")
    ParametersSoftware'AddVariable("Viewer","PrintInfo","Collate","B","0","1","","1")
    ParametersSoftware'AddVariable("Viewer","PrintInfo","Colour","B","0","1","","1")
    ParametersSoftware'AddVariable("Viewer","PrintInfo","DPIPrinter","N","0","2400","","0")

    ParametersSoftware'AddVariable("Viewer","FontInfo","DefaultFixedFont","S","","","","Courier New")
    ParametersSoftware'AddVariable("Viewer","FontInfo","DefaultFixedFontSize","N","-72","72","","-12")

    ParametersSoftware'AddVariable("Viewer","PaperInfo","DefaultPaperSize","N","0","255","","0")
    ParametersSoftware'AddVariable("Viewer","PaperInfo","DefaultOrientation","N","0","1","","0")
    ParametersSoftware'AddVariable("Viewer","PaperInfo","MinimumColumns","N","0","255","","0")
    ParametersSoftware'AddVariable("Viewer","PaperInfo","MinimumRows","N","0","255","","0")
    ParametersSoftware'AddVariable("Viewer","PaperInfo","PaginationAt","N","0","255","","0")
    ParametersSoftware'AddVariable("Viewer","PaperInfo","ScaleToFit","B","","","","0")

    ParametersSoftware'AddVariable("Viewer","MnemonicInfo","SPCols","N","0","255","","0")
    ParametersSoftware'AddVariable("Viewer","MnemonicInfo","SPRows","N","0","255","","0")
    ParametersSoftware'AddVariable("Viewer","MnemonicInfo","CPCols","N","0","255","","0")
    ParametersSoftware'AddVariable("Viewer","MnemonicInfo","CPRows","N","0","255","","0")
    ParametersSoftware'AddVariable("Viewer","MnemonicInfo","EPCols","N","0","255","","0")
    ParametersSoftware'AddVariable("Viewer","MnemonicInfo","EPRows","N","0","255","","0")

    ParametersSoftware'AddVariable("Viewer","TabInfo","TabSize","N","0","12","","4")

    ParametersSoftware'AddVariable("Viewer","WindowStates","SetWindowStateOnCreate","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","WindowStates","SetWindowStateOnSpoolStart","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","WindowStates","SetWindowStateOnFirstPage","B","","","","0")
    ParametersSoftware'AddVariable("Viewer","WindowStates","SetWindowStateOnSpoolComplete","B","","","","0")

    ParametersSoftware'AddVariable("Viewer","FileExtensions","SaveAsExtensions","S","","","","")
    ParametersSoftware'AddVariable("Viewer","FileExtensions","SaveAsExtensionsDefault","S","","","","")
    ParametersSoftware'AddVariable("Viewer","FileExtensions","SaveAsPDFExtensions","S","","","","")
    ParametersSoftware'AddVariable("Viewer","FileExtensions","SaveAsPDFExtensionsDefault","S","","","","")
    ParametersSoftware'AddVariable("Viewer","FileExtensions","OpenExtensions","S","","","","")


    EQuit=-1999, \
    ReSize=-1105, \
    TabKey=-1015, \
    BackTabKey=-1016, \
    LeftMouseDown=-1080, \
    LeftMouseUp=-1081, \
    RightMouseDown=-1082, \
    RightMouseUp=-1083, \
    HomeKey=-1010, \
    EndKey=-1018, \
    F3Key=3, \
    ShiftF3Key=-7, \
    PgUpKey=-1013, \
    PgDnKey=-1014, \
    CurLeft=-1004, \
    CurRight=-1005, \
    CurUp=-1011, \
    CurDown=-1012, \
    CtlCurLeft=-1022, \
    CTLCurRight=-1021


    ToolBarStart=31000, \
    ToolBarDropButton=31001, \
    ToolBarRightClickMenu=31002

    DMenu=31003, \
    FOpen=31004, \
    FClose=31005, \
    FSaveAs=31006, \
    FSaveAsPDF=31056, \
    FPrint=31007, \
    FDelete=31008, \
    FExit=31009, \
    FPauseSpool=31057

    EFind=31010, \
    EFindAgain=31011, \
    EFindPrev=31012

    HContent=31014, \
    HIndex=31015, \
    HAbout=31016

    VTop=31017, \
    VPrevious=31018, \
    VNext=31019, \
    VBottom=31020, \
    VGoto=31021, \
    MGoto=31051, \
    VJump=31049

    VZoom=31022, \
    VZoomIn=31023, \
    VZoomOut=31024, \
    VZoomWidth=31025, \
    VZoomWindow=31026, \
    VZoomCustom=31048, \
    MZoomCustom=31050

    VLayout=31027, \
    VOne=31028, \
    VTwo=31029, \
    VBook=31047, \
    VFour=31030, \
    VBanner=31032, \
    VToolBar=31033, \
    VStatusBar=31034, \
    VToolTip=31035, \
    VWaterMark=31036

    BVScroll=31037, \
    BHScroll=31038, \
    BTop=31039, \
    BPrevious=31040, \
    BBlank=31041, \
    BNext=31042, \
    BBottom=31043, \
    BOK=31052, \
    BCancel=31053, \

    StatusBarSection1=31044, \
    StatusBarSection2=31045, \
    StatusBarSection3=31013, \
    CheckSpool=31046

    ImageButton1=31501, ImageButtonRight1=31551
    ImageButton2=31502, ImageButtonRight2=31552
    ImageButton3=31503, ImageButtonRight3=31553
    ImageButton4=31504, ImageButtonRight4=31554

    BorderButton1=31511, ShadowButton1=31521
    BorderButton2=31512, ShadowButton2=31522
    BorderButton3=31513, ShadowButton3=31523
    BorderButton4=31514, ShadowButton4=31524

    ! Dialogues
    DGotoJump=31058
    DGotoOK=31059
    DGotoCancel=31060
    DGotoQuit=31061
    DGotoTabKey=31062
    DGotoBackTabKey=31063

    DZoomCustom=31064
    DZoomOK=31065
    DZoomCancel=31066
    DZoomQuit=31067
    DZoomTabKey=31068
    DZoomBackTabKey=31069

    DBannerInfo=31070
    DBannerOK=31071
    DBannerQuit=31072
    DBannerTabKey=31073
    DBannerBackTabKey=31074

    DAboutQuit=31054

    DFindText=31075
    DFindMatch=31076
    DFindDir=31055
    DFindOK=31077
    DFindCancel=31078
    DFindQuit=31079
    DFindTabKey=31080
    DFindBackTabKey=31081

    CheckPrint = 31082
    ! Last Used CTL = 31082, Reuseable = <none>


    if not(ParametersUsers'ExistsReference("Viewer","WindowSize")) then \
    {   ParametersUsers'AddVariable("Viewer","WindowSize","Left","N","-65535","65536","","0")
        ParametersUsers'AddVariable("Viewer","WindowSize","Right","N","-65535","65536","","0")
        ParametersUsers'AddVariable("Viewer","WindowSize","Top","N","-65535","65536","","0")
        ParametersUsers'AddVariable("Viewer","WindowSize","Bottom","N","-65535","65536","","0")
    }

    ParametersSoftware'GetParameters("Viewer","Software")
    ParametersSoftware'GetParameters("Viewer","Help")
    ParametersSoftware'GetParameters("Viewer","Company")
    ParametersSoftware'GetParameters("Viewer","Suppress")
    ParametersSoftware'GetParameters("Viewer","ToolBar")
    ParametersSoftware'GetParameters("Viewer","WindowStates")
    ParametersSoftware'GetParameters("Viewer","ZoomInfo")
    ParametersSoftware'GetParameters("Viewer","ScrollInfo")
    ParametersSoftware'GetParameters("Viewer","WindowInfo")
    ParametersSoftware'GetParameters("Viewer","FontInfo")
    ParametersSoftware'GetParameters("Viewer","PaperInfo")
    ParametersSoftware'GetParameters("Viewer","PrintInfo")
    ParametersSoftware'GetParameters("Viewer","FileExtensions")

    ParametersUsers'AddVariable("Viewer","WindowInfo","View","N","0","4","",str(View))
    ParametersUsers'AddVariable("Viewer","WindowInfo","WindowState","N","0","4","","2")
    ParametersUsers'AddVariable("Viewer","ZoomInfo","ZoomLevel","N","-2","400","",str(ZoomLevel))
    ParametersUsers'AddVariable("Viewer","Suppress","SuppressStatusBar","B","","","",str(SuppressStatusBar))
    ParametersUsers'AddVariable("Viewer","Suppress","SuppressToolBar","B","","","",str(SuppressToolBar))
    ParametersUsers'AddVariable("Viewer","Suppress","SuppressToolTips","B","","","",str(SuppressToolTips))
    ParametersUsers'AddVariable("Viewer","Suppress","SuppressWaterMarks","B","","","",str(SuppressWaterMarks))
    ParametersUsers'AddVariable("Viewer","Suppress","SuppressFirstBlankPage","B","","","",str(SuppressFirstBlankPage))
    ParametersUsers'AddVariable("Viewer","Suppress","SuppressAllBlankPages","B","","","",str(SuppressAllBlankPages))
    ParametersUsers'AddVariable("Viewer","Software","LastOpenPath","S","","","","")
    ParametersUsers'AddVariable("Viewer","Software","LastSaveAsPath","S","","","","")
    ParametersUsers'AddVariable("Viewer","ToolBar","ToolBarSize","N","0","2","","1")

    ParametersUsers'GetParameters("Viewer","WindowSize")
    ParametersUsers'GetParameters("Viewer","WindowInfo")
    ParametersUsers'GetParameters("Viewer","ZoomInfo")
    ParametersUsers'GetParameters("Viewer","Suppress")
    ParametersUsers'GetParameters("Viewer","Software")
    ParametersUsers'GetParameters("Viewer","ToolBar")

    Software$ = tbl(Software$>"",msg("Tsoftware"),Software$)
    Caption$ = tbl(Caption$>"",Software$,Caption$)
    TPage$ = msg("Tpage")
    TPages$ = msg("Tpages")
    TOf$ = msg("Tof")
    TLoading$ = msg("Tloading")
    TZoom$ = msg("Tzoom")
    TPercent$ = msg("Tpercent")
    TSpooling$ = msg("TSpooling")
    TSpoolingPaused$ = msg("TSpoolingPaused")
    DefaultOrientation$ = tbl(DefaultOrientation > 0, "Portrait", "Landscape")

    if SaveAsExtensions$ = "" \
        then SaveAsExtensions$ = msg("TSaveAsExtensions")
    if SaveAsExtensionsDefault$ = "" \
        then SaveAsExtensionsDefault$ = msg("TSaveAsExtensionsDefault")
    if SaveAsPDFExtensions$ = "" \
        then SaveAsPDFExtensions$ = msg("TSaveAsPDFExtensions")
    if SaveAsPDFExtensionsDefault$ = "" \
        then SaveAsPDFExtensionsDefault$ = msg("TSaveAsPDFExtensionsDefault")
    if OpenExtensions$ = "" \
        then OpenExtensions$ = msg("TOpenExtensions")

    if SetWindowStateOnCreate \
        then HasWindowOverrides = 1
    if SetWindowStateOnSpoolStart \
        then HasWindowOverrides = 1
    if SetWindowStateOnFirstPage \
        then HasWindowOverrides = 1
    if SetWindowStateOnSpoolComplete \
        then HasWindowOverrides = 1

    for x = 1 to VisibleImages
        VisibleImage[x, 1] = vin(("ImageButton"+str(x)))
        VisibleImage[x, 10] = vin(("BorderButton"+str(x)))
        VisibleImage[x, 11] = vin(("ShadowButton"+str(x)))
    next x

    if ZoomLevels$ = "" \
        then ZoomLevels$ = "10,15,20,25,30,35,40,50,60,70,80,90,100,125,150,175,200,300,400,"
    if mid(ZoomLevels$,-1,1)<>"," \
        then ZoomLevels$ += ","
    ZoomLevels$ = sub(ZoomLevels$,"-1,","")
    ZoomLevels$ = sub(ZoomLevels$,"-2,","")
    ZoomLevels = pos("," = ZoomLevels$, 1, 0)
    VZoomLevels$ = ""
    dim ZoomLevels[1:ZoomLevels]
    read data from ZoomLevels$,sep="," to ZoomLevels{all}
    for x = 1 to ZoomLevels
        VZoomLevels$ += str(ZoomLevels[x]) + TPercent$ + ","
    next x

    if DisableWaterMarks \
        then SuppressWaterMarks = 1

    VScrollMax = 1, HScrollMax = 1
    VScrollLastMax = 1, HScrollLastMax = 1
    VScrollCurPos = 1, HScrollCurPos = 1
    VScrollLastPos = 1, HScrollLastPos = 1
    VScrollSmallJump = 1, HScrollSmallJump = 1
    VScrollBigJump = 1, HScrollBigJump = 1
    VScrollSmallSize = int(VScrollSmallSize)
    HScrollSmallSize = int(HScrollSmallSize)

    return 1
!
!
GetWindowsDefaults:

    BorderWidth = WinAPI'GetSystemMetrics(Constants'SystemMetric'SM_CXEDGE)
    BorderHeight = WinAPI'GetSystemMetrics(Constants'SystemMetric'SM_CYEDGE)
    FrameWidth = WinAPI'GetSystemMetrics(Constants'SystemMetric'SM_CXDLGFRAME)
    FrameHeight = WinAPI'GetSystemMetrics(Constants'SystemMetric'SM_CYDLGFRAME)

    if WinAPI'GetColourDepth() <= 8 \
        then ImageColour$ = "256" \
        else ImageColour$ = "16M"

    ColourDlgWorkSpace$ = WinAPI'GetSysColor$(Constants'SystemColor'COLOR_APPWORKSPACE)
    !if ImageColour$ = "256" \
    !    then ColourDlgBase$ = "RGB:192,192,192" \
    !    else ColourDlgBase$ = "RGB:224,224,224"
    ColourDlgBase$ = "Gray"
    Colour3DDark$ = WinAPI'GetSysColor$(Constants'SystemColor'COLOR_3DSHADOW)
    Colour3DLight$ = WinAPI'GetSysColor$(Constants'SystemColor'COLOR_3DHILIGHT)

    return 1
!
!
SaveStates:
    if WinAPI = 0 or BaseWHnd = 0 \
        then return

    if IsWindX \
        then call "[wdx]*winapi;GetWindowPlacementPixels",BaseWHnd,Left,Top,Right,Bottom \
        else WinAPI'GetWindowPlacement(BaseWHnd,Left,Top,Right,Bottom)
    mse$ = mse
    WindowState = dec(mid(mse$,31,1)) + 1

    if ParametersUsers then \
    {   if Visible then \
        {   ParametersUsers'SetParameters("Viewer","WindowSize")
            ParametersUsers'SetParameters("Viewer","WindowInfo")
        }
        ParametersUsers'SetParameters("Viewer","WindowStates")
        ParametersUsers'SetParameters("Viewer","ZoomInfo")
        ParametersUsers'SetParameters("Viewer","Suppress")
        ParametersUsers'SetParameters("Viewer","Software")
        ParametersUsers'SetParameters("Viewer","ToolBar")
    }
    return 1
!
!
CheckPlatform:
    if pos("WIN"=ucs(sys),1) \
        then IsWindows=1 \
        else IsUnix=1

    if tcb(88) \
        then IsWindX$="[WDX]";
             if ucs(mid(mse,32,1))="J" \
                 then IsJavX=tcb(88) \
                 else IsWindX=tcb(88)

    if IsJavX then \
    {   This'DisplayError$(msg("Enojavx", Software$))
        return 0
    }

    if IsUnix and not(IsWindX) then \
    {   This'DisplayError(msg("Enotgui", Software$))
        return 0
    }
    return 1
!
!
CheckVersion:
    if tcb(29)<6090000 then \
    {   This'DisplayError$(msg("Epvxtoold"))
        return 0
    }

    if tcb(32)<5 then \
    {   This'DisplayError$(msg("Eneed5act"))
        return 0
    }

    if IsWindX and IsWindX < 10 then \
    {   This'DisplayError$(msg("Eoldwindx"))
        return 0
    }
    return 1
!
!
CreateBaseWindow:
    ! If no saved location, then use the monitor the current window is on
    if Left = 0 and Top = 0 and Right = 0 and Bottom = 0 then \
    {    w = WinAPI'GetUltimateParent(0)
         if IsWindX \
            then call "[wdx]*winapi;GetWindowPlacementPixels",w,l,t,r,b \
            else WinAPI'GetWindowPlacement(w,l,t,r,b)
         if IsWindX \
            then call "[wdx]*Winapi;GetMonitorFromRect",l,t,r,b,Monitor \
            else Monitor = WinAPI'GetMonitorFromRect(l,t,r,b)
    } else \
    {    if IsWindX \
            then call "[wdx]*Winapi;GetMonitorFromRect",Left,Top,Right,Bottom,Monitor \
            else Monitor = WinAPI'GetMonitorFromRect(Left,Top,Right,Bottom)
    }
    if IsWindX \
        then call "[wdx]*winapi;GetMonitorInfo",Monitor,mLeft,mTop,mRight,mBottom,wLeft,wTop,wRight,wBottom \
        else WinAPI'GetMonitorInfo(Monitor,mLeft,mTop,mRight,mBottom,wLeft,wTop,wRight,wBottom)
    ! If the saved location and size is too big for monitor, then shrink to fit this monitor
    if Right - Left > wRight - wLeft then \
    {   x = wRight - wLeft
        Right = Left + x
    }
    if Bottom - Top > wBottom - wTop then \
    {   x = wBottom - wTop
        Bottom = Top + x
    }

    ! If the window is not on the current monitor, push it onto the current monitor
    ! retaining its current size
    if Right > wRight then \
    {   x = right - wRight
        right -= x
        Left -= x
    }
    if Bottom > wBottom then \
    {   x = Bottom - wBottom
        Bottom -= x
        Top -= x
    }
    if Left < wLeft then \
    {   x = Left - wLeft
        Right -= x
        Left -= x
    }
    if Top < wTop then \
    {   x = Top - wTop
        Bottom -= x
        Top -= x
    }

    ! Adjust for Windows ToolBar placement. GetWindowPlacement returns coords with ToolBars
    ! SetWindowPlacement sets coords without Windows Toolbars (silly, eh!)
    Left = Left - (wLeft - mLeft)
    Right = Right - (wLeft - mLeft)
    Top = Top - (wTop - mTop)
    Bottom = Bottom - (wTop - mTop)

    HiddenPHnd = hwn(0)
    print 'dialog'(-16000,-16000,20,10,HiddenPHnd,"Hidden Dialog",'cs',opt="c"),
    print '_white','black','df',
    This'SetLookAndFeel()

    This'ResolveIcon(Icon$,r$,t$)
    Icon32$ = Icon$+r$+"%32"+t$
    Icon16$ = Icon$+r$+"%16"+t$
    Icon$ = Icon16$

    BasePHnd = hwn(0)
    print 'dialog'(-16000,-16000,255,255,BasePHnd,Caption$,'_colour'(ColourDlgWorkSpace$)+'df'+'cs',opt="-mMsZ"),'sr',
    print (0,err=*proceed) 'option'("FONT","FixedSys,-9"), \
                           'option'("STDFONT","FixedSys, -9"), \
                           'option'("GRAPHICFONT","*GuiFont"), \
                           'option'("WDWICON",Icon32$), \
                           'option'("WDWICON",Icon16$), \
                           '-U',
    print 'drop'(HiddenPHnd),

    if ColGUs = 0 then \
    {   mse$ = mse
        ColGUs = dec($00$ + mse$(10, 1))
        RowGUs = dec($00$ + mse$(11, 1))
    }

    MaxColumns = int((wRight - wLeft) / ColGUs)
    MaxRows = int((wBottom - wTop) / RowGUs)

    print 'size'(MaxColumns,MaxRows),! 'MinSize'(20,8), no effect ?????????????????
    BaseWHnd = WinAPI'GetUltimateParent(0)

    ! If there is no saved location and size then make the window 2/3'rds the size of the screen
    if Left = Right and Bottom = Top then \
    {   w = int((wRight - wLeft) * .66)
        Left = int((wRight - wLeft - w) / 2) + wLeft
        Right = Left + w
        h = int((wBottom - wTop) * .66)
        Top = int((wBottom - wTop -h) / 2) + wTop
        Bottom = Top + h
    }

    print 'show'(-1),

    return
!
!
SetLookAndFeel:
    if BasePHnd \
        then return 0

    if Theme \
        then ExtraVisualEffects = Theme'ExtraVisualEffects()

    if ImageColour$ = "256" \
        then LookAndFeel = 3

    switch LookAndFeel
        case 3 ! 3D
            print '2d','3d',
            ThemeName$ = ""
            ImageLook$ = "2K"
            NoTheme = 1
            break

        case 4 ! 4D
            print '2d','4d',
            ImageLook$ = "XP"
            break

        default ! Auto Select
            AutoSelect = 1
            LookAndFeel = 4
            ImageLook$ = "XP"
            break
    esac

    if Theme = 0 or NoTheme then \
    {   print '2d','3d',
        ThemeName$ = ""
        ImageLook$ = "2K"
        return 1
    }

    ! If auto or no theme name, find the windows theme name
    if AutoSelect or ThemeName$ = "" then \
    {   if Theme'WindowsThemeActive() then \
        {   WindowsTheme$ = Theme'WindowsThemeName$()
        }
    }

    ! if auto and no theme name found, switch to 3D
    if AutoSelect and WindowsTheme$ = "" then \
    {   print '2d','3d',
        LookAndFeel = 3
        ImageLook$ = "2K"
        ThemeName$ = ""
        return 1
    }

    ! if passed a specific theme name, then try it first
    if ThemeName$>"" then \
    {   result = Theme'Load(ThemeName$)
        if result = 0 \
            then return 1
    }

    ! if no theme name provided or unsuccessful at loading name given fall back to windows
    result = Theme'Load(WindowsTheme$)
    if result = 0 then \
    {   ThemeName$ = WindowsTheme$
        return 1
    }

    ! if I cant load any, fall back to 3D
    print '2d','3d',
    ImageLook$ = "2K"
    ThemeName$ = ""
    return 1
!
!
! Gets Column, Row, Columns, Rows for the base Window
GetWindowLocationAndSize:
    local obj$
    print 'goto'(BasePHnd),
    obj$ = obj(0)
    Column = int(dec(mid(obj$,21,2)) / ColGUs)
    Row = int(dec(mid(obj$,23,2)) / RowGUs)
    Columns = dec($00$ + mid(obj$,33,2)) - 1
    Rows = dec($00$ + mid(obj$,35,2)) - 1
    return 1
!
GetColumn:
    This'GetWindowLocationAndSize()
    return Column
!
GetRow:
    This'GetWindowLocationAndSize()
    return Row
!
GetColumns:
    This'GetWindowLocationAndSize()
    return Columns
!
GetRows:
    This'GetWindowLocationAndSize()
    return Rows
!
!
LoadObjectInfo:
    dim objs$[1:99, 0:14],cntls[-32000:32000],Menu$[1:10,1:2]
    c = 1
    Menu$[1, 1] = msg("Menu.File")
    Menu$[1, 2] = This'GetAccelerator$(Menu$[1, 1])
    Menu$[2, 1] = msg("Menu.Edit")
    Menu$[2, 2] = This'GetAccelerator$(Menu$[2, 1])
    Menu$[3, 1] = msg("Menu.View")
    Menu$[3, 2] = This'GetAccelerator$(Menu$[3, 1])
    Menu$[4, 1] = msg("Menu.Help")
    Menu$[4, 2] = This'GetAccelerator$(Menu$[4, 1])
    Menu$[5, 1] = msg("C.VZoom.Menu")
    Menu$[5, 2] = Menu$[3, 2] + This'GetAccelerator$(Menu$[5, 1])
    Menu$[6, 1] = msg("C.VLayout.Menu")
    Menu$[6, 2] = Menu$[3, 2] + This'GetAccelerator$(Menu$[6, 1])

    WarningImage$ = msg("C.Warning.Image")
    if ucs(WarningImage$) = "C.WARNING.IMAGE:" \
        then WarningImage$ = "{*viewer/images/warning/warning.bmp,T}"

    WarningTip$ = msg("C.Warning.Tip")
    if ucs(WarningTip$) = "C.WARNING.TIP:" \
        then WarningTip$ = "Rendering errors have occurred on this page."

    This'LoadObject("FOpen", 1, "B", C++)
    This'LoadObject("FClose", 1, "B", C++)
    This'LoadObject("FSaveAs", 1, "B", C++)
    This'LoadObject("FSaveAsPDF", 1, "B", C++)
    This'LoadObject("FDelete", 1, "B", C++)
    This'LoadObject("FPrint", 1, "B", C++)
    This'LoadObject("FExit", 1, "B", C++)
    This'LoadObject("FPauseSpool", 1, "S", C++)

    This'LoadObject("EFind", 2, "B", C++)
    This'LoadObject("EFindAgain", 2, "B", C++)
    This'LoadObject("EFindPrev", 2, "B", C++)

    This'LoadObject("VTop", 3, "B", C++)
    This'LoadObject("VPrevious", 3, "B", C++)
    This'LoadObject("VNext", 3, "B", C++)
    This'LoadObject("VBottom", 3, "B", C++)
    This'LoadObject("VGoto", 3, "B", C++)
    This'LoadObject("MGoto", 3, "B", C++)
    This'LoadObject("VJump", 3, "M", C++)
    This'LoadObject("VZoom", 3, "B", C++)
    This'LoadObject("VZoomIn", 5, "B", C++)
    This'LoadObject("VZoomOut", 5, "B", C++)
    This'LoadObject("VZoomWidth", 5, "S", C++)
    This'LoadObject("VZoomWindow", 5, "S", C++)
    This'LoadObject("VZoomCustom", 5, "VD", C++)
    This'LoadObject("MZoomCustom", 5, "VD", C++)
    This'LoadObject("VLayout", 3, "B", C++)
    This'LoadObject("VOne", 6, "S", C++)
    This'LoadObject("VTwo", 6, "S", C++)
    This'LoadObject("VBook", 6, "S", C++)
    This'LoadObject("VFour", 6, "S", C++)
    This'LoadObject("VBanner", 3, "B", C++)
    This'LoadObject("VToolBar", 3, "B", C++)
    This'LoadObject("VStatusBar", 3, "B", C++)
    This'LoadObject("VToolTip", 3, "B", C++)
    This'LoadObject("VWaterMark", 3, "B", C++)

    This'LoadObject("HContent", 4, "B", C++)
    This'LoadObject("HIndex", 4, "B", C++)
    This'LoadObject("HAbout", 4, "B", C++)

    This'LoadObject("DGotoJump", 0, "M", C++)
    This'LoadObject("DGotoOK", 0, "B", C++)
    This'LoadObject("DGotoCancel", 0, "B", C++)
    This'LoadObject("DGotoQuit", 0, "B", C++)
    This'LoadObject("DGotoTabKey", 0, "B", C++)
    This'LoadObject("DGotoBackTabKey", 0, "B", C++)

    This'LoadObject("DZoomCustom", 0, "VD", C++)
    This'LoadObject("DZoomOK", 0, "B", C++)
    This'LoadObject("DZoomCancel", 0, "B", C++)
    This'LoadObject("DZoomQuit", 0, "B", C++)
    This'LoadObject("DZoomTabKey", 0, "B", C++)
    This'LoadObject("DZoomBackTabKey", 0, "B", C++)

    This'LoadObject("DBannerInfo", 0, "G", C++)
    This'LoadObject("DBannerOK", 0, "B", C++)
    This'LoadObject("DBannerQuit", 0, "B", C++)
    This'LoadObject("DBannerTabKey", 0, "B", C++)
    This'LoadObject("DBannerBackTabKey", 0, "B", C++)

    This'LoadObject("DFindText", 0, "VD", C++)
    This'LoadObject("DFindMatch", 0, "C", C++)
    This'LoadObject("DFindDir", 0, "C", C++)
    This'LoadObject("DFindOK", 0, "B", C++)
    This'LoadObject("DFindCancel", 0, "B", C++)
    This'LoadObject("DFindQuit", 0, "B", C++)
    This'LoadObject("DFindTabKey", 0, "B", C++)
    This'LoadObject("DFindBackTabKey", 0, "B", C++)

    return 1
!
!
! objs$[ Objects CTL Value, InfoIndeX ]
! Index 0 = Objects CTL Value
! Index 1 = Menu Entry Name
! Index 2 = Menu Accelerator
! Index 3 = Tool Tip
! Index 4 = Icon
! index 5 = Icon Reference
! Index 6 = Icon Transparency
! Index 7 = Help Reference ID
! Index 8 = Shortcut key
! Index 9 = Button Type, "B"=Standard Button, "S"=Sticky Button
! Index 10 = Menu Bar Accelerators to get to this item
! Index 11 = 4 Way Bitmap for Up State
! Index 12 = 4 way Bitmap for Down State
LoadObject:
    enter (Name$), (Menu), (Type$), (Counter)
    value = evn(Name$)
    if value = 0 \
        then return 0
    cntls[Value] = Counter
    objs$[Counter, 0] = str(Value)
    objs$[Counter, 1] = msg("C."+Name$+".Menu")
    objs$[Counter, 2] = This'GetAccelerator$(objs$[Counter, 1])
    objs$[Counter, 3] = msg("C."+Name$+".Tip")
    ThisIcon$ = msg("C."+Name$+".Icon")
    This'ResolveIcon(ThisIcon$,r$,t$)
    objs$[Counter, 4] = ThisIcon$
    objs$[Counter, 5] = r$
    objs$[Counter, 6] = t$
    objs$[Counter, 7] = msg("C."+Name$+".HelpRef")
    objs$[Counter, 8] = msg("C."+Name$+".ShortCut")
    objs$[Counter, 9] = Type$

    objs$[Counter, 11] = msg("C."+Name$+".ToolBarUp")
    objs$[Counter, 12] = msg("C."+Name$+".ToolBarDn")

    if mid(stp(objs$[Counter, 11], 2), -1) = ":" \
        then objs$[Counter, 11] = "{*viewer/images/TB/TB.BB<FL>Up.<LOOK><COLOUR><SIZE>.bmp,G}"

    if mid(stp(objs$[Counter, 12], 2), -1) = ":" \
        then objs$[Counter, 12] = "{*viewer/images/TB/TB.BB<FL>Dn.<LOOK><COLOUR><SIZE>.bmp,G}"

    if Menu > 0 and objs$[Counter, 2] > "" \
        then objs$[Counter,10] = Menu$[Menu, 2] + objs$[Counter, 2]
    return 1
!
!
CreateMenuBar:
! Index 0 = Objects CTL Value
! Index 1 = Menu Entry Name
! Index 2 = Menu Accelerator
! Index 3 = Tool Tip
! Index 4 = Icon
! index 5 = Icon Reference
! Index 6 = Icon Transparency
! Index 7 = Help Reference ID
! Index 8 = Shortcut key
! Index 9 = Button Type, "B"=Standard Button, "S"=Sticky Button, "M"=Multiline, "VD" = VarDropBox
! Index 10 = Menu Bar Accelerators to get to this item
    ! Base Menu Bar
    m$ = "-[" + menu$[1,1] + "," + menu$[2,1] + "," + menu$[3,1] + "," + \
                menu$[4,1] + "]"
    ! File Menu
    m$ += "," + menu$[1,2] + ":["
    This'AddMenuItem(m$, FOpen, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, FClose, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, FSaveAs, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, FSaveAsPDF, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, FDelete, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, FPauseSpool, 0, 1)
    m$ += ",,"
    This'AddMenuItem(m$, FPrint, 0, 1)
    m$ += ",,"
    This'AddMenuItem(m$, FExit, 0, 1)
    m$ +="]"

    ! Edit Menu
    m$ += "," + menu$[2,2] + ":["
    This'AddMenuItem(m$, EFind, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, EFindAgain, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, EFindPrev, 0, 1)
    m$ +="]"

    ! View Menu
    m$ += "," + menu$[3,2] + ":["
    This'AddMenuItem(m$, VToolBar, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VStatusBar, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VToolTip, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VWaterMark, 0, 1)
    m$ += ",,"
    This'AddMenuItem(m$, VTop, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VPrevious, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VNext, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VBottom, 0, 1)
    m$ += ",,"
    This'AddMenuItem(m$, MGoto, 0, 1)
    m$ += ",,"
    This'AddMenuItem(m$, VZoom, 0, 1)
    m$ += ",,"
    This'AddMenuItem(m$, VLayout, 0, 1)

    if SuppressBannerInfo = 0 then \
    {   m$ += ",,"
        This'AddMenuItem(m$, VBanner, 0, 1)
    }
    m$ +="]"

    ! Help Menu
    m$ += "," + menu$[4,2] + ":["
    This'AddMenuItem(m$, HContent, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, HIndex, 0, 1)
    m$ += ",,"
    This'AddMenuItem(m$, HAbout, 0, 1)
    m$ +="]"

    ! Zoom SubMenu
    m$ += "," + menu$[5,2] + ":["
    This'AddMenuItem(m$, VZoomIn, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VZoomOut, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VZoomWidth, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VZoomWindow, 0, 1)
    m$ += ",,"
    This'AddMenuItem(m$, MZoomCustom, 0, 1)
    m$ +="]"

    ! Layout SubMenu
    m$ += "," + menu$[6,2] + ":["
    This'AddMenuItem(m$, VOne, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VTwo, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VBook, 0, 1)
    m$ += ","
    This'AddMenuItem(m$, VFour, 0, 1)
    m$ +="]"

    menubar DMenu, m$, err=InvalidMenu

    if SuppressStatusBar = 0 \
        then menubar on objs$[cntls[VStatusBar],10]

    if SuppressToolBar = 0 \
        then menubar on objs$[cntls[VToolBar],10]

    if SuppressToolTips = 0 \
        then menubar on objs$[cntls[VToolTip],10]

    if SuppressWaterMarks = 0 \
        then menubar on objs$[cntls[VWaterMark],10]

    if WaterMarkPages = 0 \
        then menubar disable objs$[cntls[VWaterMark],10] \
        else menubar enable objs$[cntls[VWaterMark],10]

    return 1

    InValidMenu:
    msgbox "Menu is Invalid"+$0a$+m$
    return 0
!
AddMenuItem:
    enter Menu$, (Value), (AddImage), (AddAccelerator)
    if Value = 0 \
        then return 0
    c = cntls[Value]
    image$ = "{"+objs$[c,4]+objs$[c,5]+"%"+str(tbl(IconSize>0,16,IconSize))+objs$[c,6]+"}"
    if AddImage \
        then if objs$[c, 4] + objs$[c, 5] > "" \
             then Menu$ += image$

    Menu$ += objs$[c,1]

    if AddAccelerator \
        then if objs$[c, 8] > "" \
              then Menu$ += $09$ + objs$[c, 8]

    d$ = ""
    if value = FPauseSpool and IsSpooled = 1 \
        then d$ = "D"

    Menu$ += "=" + d$ + str(Value)
    return 1
!
!
ChangeMenu:
    enter (Value$)
    if Value$ = "" \
        then return 0
    m$=","
    print 'goto'(BasePHnd),
    switch ucs(Value$)
        case "NOFILE"
            m$ = "ENABLE:,FOpen,FExit,VToolBar,VStatusBar,VToolTip,HContent,HIndex,HAbout,"+ \
                 "DISABLE:,FClose,FSaveAs,FSaveAsPDF,FDelete,FPauseSpool,FPrint,EFind,EFindAgain,EFindPrev,"+ \
                 "VTop,VPrevious,VNext,VBottom,VGoto,VJump,VZoom,VZoomIn,VZoomOut,VZoomCustom,"+ \
                 "VZoomWidth,VZoomWindow,VOne,VTwo,VBook,VFour,VLayout,VBanner," + \
                 "BVScroll,BHScroll,Btop,BPrevious,BBlank,BNext,BBottom," + \
                 "OFF:,FPauseSpool,"
            CurrentMenu$ = Value$
            break
        case "FILEOPEN"
            m$ = "ENABLE:,FClose,FSaveAs,FSaveAsPDF,FDelete,FPauseSpool,FPrint,EFind,EFindAgain,EFindPrev,"+ \
                 "VTop,VPrevious,VNext,VBottom,VGoto,VJump,VZoom,VZoomIn,VZoomOut,VZoomCustom,"+ \
                 "VZoomWidth,VZoomWindow,VOne,VTwo,VBook,VFour,VLayout,VBanner," + \
                 "BVScroll,BHScroll,Btop,BPrevious,BNext,BBottom," + \
                 "OFF:,FPauseSpool,"
            CurrentMenu$ = Value$
            break
        case "SPOOLED"
            m$ = "DISABLE:,FPauseSpool,OFF:,FPauseSpool,"
            break
        case "PAUSESPOOL"
            m$ = "ENABLE:,FPauseSpool,ON:,FPauseSpool,"
            break
        case "SPOOLING"
            m$ = "ENABLE:,FPauseSpool,OFF:,FPauseSpool,"
            break
        case "VIEW0"
            m$ = "ON:,VOne,OFF:,VTwo,VBook,VFour,"
            if ZoomLevel = -1 \
                then m$ += "OFF:,VZoomWindow,ON:,VZoomWidth,"
            if ZoomLevel = -2 \
                then m$ += "ON:,VZoomWindow,OFF:,VZoomWidth,"
            break
        case "VIEW1"
            m$ = "ON:,VTwo,OFF:,VOne,VBook,VFour,OFF:,VZoomWindow,VZoomWidth,"
            break
        case "VIEW2"
            m$ = "ON:,VBook,OFF:,VOne,VTwo,VFour,OFF:,VZoomWindow,VZoomWidth,"
            break
        case "VIEW3"
            m$ = "ON:,VFour,OFF:,VOne,VTwo,VBook,OFF:,VZoomWindow,VZoomWidth,"
            break
        case "ZOOM"
            m$ = "OFF:,VZoomWindow,VZoomWidth,"
            break
        case "ZOOM-1"
            m$ = "OFF:,VZoomWindow,ON:,VZoomWidth,"
            break
        case "ZOOM-2"
            m$ = "ON:,VZoomWindow,OFF:,VZoomWidth,"
            break
        case "NOWATERMARKS"
            m$ = "DISABLE:,VWaterMark,"
            break
        case "WATERMARKS"
            m$ = "ENABLE:,VWaterMark,"
            break
        case "DISABLEPRINT"
            m$ = "DISABLE:,FPrint,"
            break
        case "ENABLEPRINT"
            m$ = "ENABLE:,FPrint,"
            break
        case "DISABLESAVEAS"
            m$ = "DISABLE:,FSaveAs,FSaveAsPDF"
            break
        case "ENABLESAVEAS"
            m$ = "ENABLE:,FSaveAs,FSaveAsPDF"
            break
        case "DISABLEDELETE"
            m$ = "DISABLE:,FDelete,"
            break
        case "ENABLEDELETE"
            m$ = "ENABLE:,FDelete,"
            break
        case "DISABLESEARCH"
            m$ = "DISABLE:,EFind,EFindAgain,EFindPrev,"
            break
        case "ENABLESEARCH"
            m$ = "ENABLE:,EFind,EFindAgain,EFindPrev,"
            break
        case "DISABLEBANNER"
            m$ = "DISABLE:,VBanner,"
            break
        case "ENABLEBANNER"
            m$ = "ENABLE:,VBanner,"
            break

    esac

    i = pos("," = m$, 1, 0)
    dim x$[1:i]
    read data from m$,sep="," to x${all}
    for x = 1 to i
        c = 0
        if x$[x] = "ENABLE:" then \
        {   state = 1
            continue
        }
        if x$[x] = "DISABLE:" then \
        {   state = 0
            continue
        }
        if x$[x] = "ON:" then \
        {   state = 2
            continue
        }
        if x$[x] = "OFF:" then \
        {   state = 3
            continue
        }
        ss = state

        c = vin(x$[x],err=*proceed)
        if c = 0 then continue

        if c = FPrint and DisablePrint and state = 1 \
            then state = 0

        if c = VWaterMark and DisableWaterMarks and state = 1 \
            then state = 0

        if (c = FSaveAs or c = FSaveAsPDF) and DisableSaveAs and state = 1 \
            then state = 0

        if c = FDelete and DisableDelete and state = 1 \
            then state = 0

        if (c = EFind or c = EFindAgain or c = EFindPrev) and DisableSearch and state = 1 \
            then state = 0

        if c = VBanner and DisableBanner and state = 1 \
            then state = 0

        switch state
            case 0
                menubar disable objs$[cntls[c],10],err=*proceed
                disable control c,err=*proceed
                break

            case 1
                menubar enable objs$[cntls[c],10],err=*proceed
                enable control c,err=*proceed
                break

            case 2
                menubar on objs$[cntls[c],10],err=*proceed
                if objs$[cntls[c],9] = "S" \
                    then checkbox write c,"1",err=*proceed
                break

            case 3
                menubar off objs$[cntls[c],10],err=*proceed
                if objs$[cntls[c],9] = "S" \
                    then checkbox write c,"0",err=*proceed
                break
        esac
        state = ss
    next x
    return 1
!
!
SetSuppressStatusBar:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    SuppressStatusBar = Value%
    This'RePaint()
    return Value%
!
!
SetSuppressToolBar:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    SuppressToolBar = Value%
    This'RePaint()
    return Value%
!
!
SetSuppressWaterMarks:
    enter (Value%)
    if Value%<> 0 \
        then Value% = 1
    if SuppressWaterMarks = Value% \
        then return SuppressWaterMarks
    SuppressWaterMarks = Value%
    if SuppressWaterMarks = 0 \
        then menubar on objs$[cntls[VWaterMark],10] \
        else menubar off objs$[cntls[VWaterMark],10]
    if WaterMarkPages = 0 \
        then menubar disable objs$[cntls[VWaterMark],10] \
        else menubar enable objs$[cntls[VWaterMark],10]
    This'RefreshPages()
    This'DrawPages()
    return Value%
!
!
SetDisableWaterMarks:
    enter (Value%)
    if Value%<>0 \
        then Value% = 1
    if DisableWaterMarks = Value% \
        then return DisableWaterMarks
    DisableWaterMarks = Value%
    switch DisableWaterMarks
        case 0
            This'ChangeMenu("WATERMARKS")
            break

        case 1
            if SuppressWaterMarks = 0 \
                This'SuppressWaterMarks(1)
            This'ChangeMenu("NOWATERMARKS")
            break
    esac
    return 1
!
!
SetDisablePrint:
    enter (Value%)
    if Value%<>0 \
        then Value% = 1
    if DisablePrint = Value% \
        then return DisablePrint
    DisablePrint = Value%
    switch DisablePrint
        case 0
            This'ChangeMenu("ENABLEPRINT")
            break

        case 1
            This'ChangeMenu("DISABLEPRINT")
            break
    esac
    return 1
!
!
SetDisableSaveAs:
    enter (Value%)
    if Value%<>0 \
        then Value% = 1
    if DisableSaveAs = Value% \
        then return DisableSaveAs
    DisableSaveAs = Value%
    switch DisableSaveAs
        case 0
            This'ChangeMenu("ENABLESAVEAS")
            break

        case 1
            This'ChangeMenu("DISABLESAVEAS")
            break
    esac
    return 1
!
!
SetDisableDelete:
    enter (Value%)
    if Value%<>0 \
        then Value% = 1
    if DisableDelete = Value% \
        then return DisableDelete
    DisableDelete = Value%
    switch DisableDelete
        case 0
            This'ChangeMenu("ENABLEDELETE")
            break

        case 1
            This'ChangeMenu("DISABLEDELETE")
            break
    esac
    return 1
!
!
SetDisableSearch:
    enter (Value%)
    if Value%<>0 \
        then Value% = 1
    if DisableSearch = Value% \
        then return DisableSearch
    DisableSearch = Value%
    switch DisableSearch
        case 0
            This'ChangeMenu("ENABLESEARCH")
            break

        case 1
            This'ChangeMenu("DISABLESEARCH")
            break
    esac
    return 1
!
!
SetDisableBanner:
    enter (Value%)
    if Value%<>0 \
        then Value% = 1
    if DisableBanner = Value% \
        then return DisableBanner
    DisableBanner = Value%
    switch DisableBanner
        case 0
            This'ChangeMenu("ENABLEBANNER")
            break

        case 1
            This'ChangeMenu("DISABLEBANNER")
            break
    esac
    return 1
!
!
SetSuppressFirstBlankPage:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    SuppressFirstBlankPage = Value%
    if Report \
        then Report'SuppressFirstBlankPage = Value%
    return Value%
!
!
SetSuppressAllBlankPages:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    SuppressAllBlankPages = Value%
    if Report \
        then Report'SuppressAllBlankPages = Value%
    return Value%
!
!
SetDefaultPaperSize:
    enter (Value%)
    if Value% < 0 \
        then Value% *= -1
    DefaultPaperSize = Value%
    if Report then \
    {   x = Report'Page(0)
        x'PaperSize = Value%
        DefaultPaperSize = x'PaperSize
        Value% = DefaultPaperSize
    }
    return Value%
!
!
SetDefaultOrientation:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    DefaultOrientation = Value%
    DefaultOrientation$ = tbl(DefaultOrientation > 0, "Portrait", "Landscape")
    if Report then \
    {   x = Report'Page(0)
        x'Orientation = Value%
    }
    return Value%
!
!
SetDefaultOrientationString:
    enter (Value$)
    switch ucs(Value$)
        case "LANDSCAPE"
            DefaultOrientation$ = "Landscape"
            DefaultOrientation = 1
            break

        default
            DefaultOrientation$ = "Portrait"
            DefaultOrientation = 0
            break
    esac
    if Report then \
    {   x = Report'Page(0)
        x'Orientation = DefaultOrientation
    }
    return Value$

!
!
SetDefaultFixedFont:
    enter (Value$)
    DefaultFixedFont$ = Value$
    if Report \
        then Report'DefaultFixedFont$ = DefaultFixedFont$
    return Value$
!
!
SetDefaultFixedFontSize:
    enter (Value%)
    DefaultFixedFontSize = Value%
    if Report \
        then Report'DefaultFixedFontSize = DefaultFixedFontSize
    return Value%
!
!
SetMinimumColumns:
    enter (Value%)
    if Value% < 0 \
        then Value% = 0
    MinimumColumns = Value%
    if Report \
        then Report'MinimumColumns = MinimumColumns
    return Value%
!
!
SetMinimumRows:
    enter (Value%)
    if Value% < 0 \
        then Value% = 0
    MinimumRows = Value%
    if Report \
        then Report'MinimumRows = MinimumRows
    return Value%
!
!
SetPaginationAt:
    enter (Value%)
    if Value% < 0 \
        then Value% = 0
    PaginationAt = Value%
    if Report \
        then Report'PaginationAt = PaginationAt
    return Value%
!
!
SetScaleToFit:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    ScaleToFit = Value%
    if Report \
        then Report'ScaleToFit = Value%
    return Value%
!
!
SetWindowStateOnCreate:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    SetWindowStateOnCreate = Value%
    HasWindowOverrides = 1
    return Value%
!
!
SetWindowStateOnSpoolStart:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    SetWindowStateOnSpoolStart = Value%
    HasWindowOverrides = 1
    return Value%
!
!
SetWindowStateOnFirstPage:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    SetWindowStateOnFirstPage = Value%
    HasWindowOverrides = 1
    return Value%
!
!
SetWindowStateOnSpoolComplete:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    SetWindowStateOnSpoolComplete = Value%
    HasWindowOverrides = 1
    return Value%
!
!
SetCollate:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    Collate = Value%
    if Report \
        then Report'Collate = Collate
    return Value%
!
!
SetColour:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    Colour = Value%
    if Report \
        then Report'Colour = Colour
    return Value%
!
!
SetCopies:
    enter (Value%)
    if Value% < 1 or Value% > 99 \
        then Value% = 1
    Copies = Value%
    if Report \
        then Report'Copies = Copies
    return Value%
!
!
SetDPIPrinter:
    enter (Value%)
    if Value% < 0 or Value% > 2400 \
        then Value% = 0
    DPIPrinter = Value%
    if Report \
        then Report'DPI = DPIPrinter
    return Value%
!
!
SetRange:
    enter (Value$)
    if Value$ = "" or ucs(Value$) = "ALL" then \
    {   Value$ = "All"
    } else \
    {   if pos("-" = Value$, 1) = 0 \
            then return Range$
        read data from Value$,sep=":" to x$,y$
        Value$ = ""
        s = abs(int(num(x$,err=*proceed)))
        e = abs(int(num(y$,err=*proceed)))
        if s < 1 \
            then s = 1
        if e < 0 \
            then e = 0
        if e < s \
            then s = 1, e = 0
        Value$ = str(s)+":"+str(e)
    }
    if Value$ = "1-0" \
        then Value$ = "All"

    Range$ = Value$
    if Report \
        then Report'Range$ = Range$
    return Range$
!
!
SetOutputEvenNumberOfPages: ! Forces all reports to product an even number of Pages in total
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    OutputEvenNumberOfPages = Value%
    return Value%
!
!
SetBanner: ! Print Banner Page 0=No banner, 1=Banner before print job, 2=Banner before each copy
    enter (Value%)
    if Value% < 0 or Value% > 2 \
        then Value% = 0
    Banner = Value%
    return Value%
!
!
! Clears, Resets, and Lays out Status Bar, Uses current Columns and Rows for Sizing
! Make sure a call to GetWindowLocationAndSize() occurs before doing this.
DrawStatusBar:
    print 'goto'(BasePHnd),
    menubar off objs$[cntls[VStatusBar],10]

    if SuppressStatusBar then \
    {   if StatusBar then \
        {   if StatusBarS1 then \
            {   StatusBarS1Text$ = StatusBarS1'Value$
                multiline remove StatusBarS1,err=*proceed
                StatusBarS1 = 0
            }
            if StatusBarS2 then \
            {   StatusBarS2Text$ = StatusBarS2'Value$
                multiline remove StatusBarS2,err=*proceed
                StatusBarS2 = 0
            }
            if StatusBarS3 then \
            {   StatusBarS3Text$ = StatusBarS3'Text$
                StatusBarS3Tip$ = StatusBarS3'Tip$
                button remove StatusBarS3,err=*proceed
                StatusBarS3 = 0
            }
            print 'image'(delete "StatusBar"),
            StatusBar = 0
        }
        return 1
    }

    print '-U',
    print 'image'(delete "StatusBar"),
    if StatusBarS1 then \
    {   StatusBarS1Text$ = StatusBarS1'Value$
        multiline remove StatusBarS1,err=*proceed
        StatusBarS1 = 0
    }
    if StatusBarS2 then \
    {   StatusBarS2Text$ = StatusBarS2'Value$
        multiline remove StatusBarS2,err=*proceed
        StatusBarS2 = 0
    }
    if StatusBarS3 then \
    {   StatusBarS3Text$ = StatusBarS3'Text$
        StatusBarS3Tip$ = StatusBarS3'Tip$
        button remove StatusBarS3,err=*proceed
        StatusBarS3 = 0
    }

    StatusBarHeight = 24 / RowGUs
    StatusBarRow = Rows + 1 - StatusBarHeight
    StatusBarSep0 = 0
    StatusBarSep1 = Columns * .50
    StatusBarSep2 = Columns * .90

    StatusBarS1 = StatusBarSection1
    StatusBarS2 = StatusBarSection2
    StatusBarS3 = StatusBarSection3

    print 'image'("StatusBar"),

    switch LookAndFeel
        case 3
            print 'pen'(0,1,0), ! No Pen = No Border
            print 'fill'(1,ColourDlgBase$),
            print 'rectangle'(@x(0),@y(StatusBarRow) + BorderHeight,@x(Columns + 1) + 2,@y(Rows + 1) + 2),

            print 'pen'(1,1,Colour3DLight$),
            print 'line'(@x(0),@y(StatusBarRow) + BorderHeight, \
                         @x(Columns + 1), @y(StatusBarRow) + BorderHeight),
            print 'line'(@x(0) + FrameWidth, @y(Rows + 1) - BorderHeight - FrameHeight, \
                         @x(StatusBarSep1), @y(Rows + 1) - BorderHeight - FrameHeight, \
                         @x(StatusBarSep1), @y(StatusBarRow) + BorderHeight + FrameHeight * 1),
            print 'line'(@x(StatusBarSep1) + BorderWidth + FrameWidth, @y(Rows + 1) - BorderHeight - FrameHeight, \
                         @x(StatusBarSep2), @y(Rows + 1) - BorderHeight - FrameHeight, \
                         @x(StatusBarSep2), @y(StatusBarRow) + BorderHeight + FrameHeight * 2),

            print 'pen'(1,1,Colour3DDark$),
            print 'line'(@x(0) + FrameWidth, @y(Rows + 1) - BorderHeight - FrameHeight, \
                         @x(0) + FrameWidth, @y(StatusBarRow) + BorderHeight + FrameHeight * 2, \
                         @x(StatusBarSep1), @y(StatusBarRow) + BorderHeight + FrameHeight * 2),
            print 'line'(@x(StatusBarSep1) + BorderWidth + FrameWidth, @y(Rows + 1) - BorderHeight - FrameHeight, \
                         @x(StatusBarSep1) + BorderWidth + FrameWidth, @y(StatusBarRow) + BorderHeight + FrameHeight * 2, \
                         @x(StatusBarSep2), @y(StatusBarRow) + BorderHeight + FrameHeight * 2),
            multiline StatusBarS1,@(.5, Rows + 1 - 1.2, StatusBarSep1 - .5, .95 ),opt="BL",mnu=-1000
            StatusBarS1'BackColour$ = ColourDlgBase$
            StatusBarS1'Value$ = StatusBarS1Text$
            multiline StatusBarS2,@(StatusBarSep1 + .7, Rows + 1 - 1.2, StatusBarSep2 - StatusBarSep1 - 1.8, .95 ),opt="BL",mnu=-1000
            StatusBarS2'BackColour$ = ColourDlgBase$
            StatusBarS2'Value$ = StatusBarS2Text$
            button StatusBarS3,@(StatusBarSep2 + .7, Rows + 1 - 1.15, 1.8, .95)="{}",opt="BfST"
            StatusBarS3'Text$ = StatusBarS3Text$
            StatusBarS3'Tip$ = StatusBarS3Tip$
            break

        case 4
            print 'pen'(0,1,0), ! No Pen = No Border
            print 'fill'(1,ColourDlgBase$),
            print 'rectangle'(@x(0),@y(StatusBarRow) + BorderHeight + FrameHeight,@x(Columns + 1) + 2,@y(Rows + 1) + BorderHeight),

            print 'fill'(3,"RGB:234,234,234",ColourDlgBase$),
            print 'rectangle'(@x(0),@y(StatusBarRow) + BorderHeight + FrameHeight,@x(Columns / 2),@y(Rows + 1) +  BorderHeight),

            print 'fill'(2,Colour3DDark$,Colour3DLight$), ! Gradient Top Dark grey to bottom light grey
            print 'rectangle'(@x(0),@y(StatusBarRow) + BorderHeight  + FrameHeight,@x(Columns + 1),@y(StatusBarRow) + FrameHeight + 10),

            print 'fill'(2,ColourDlgBase$,Colour3DDark$), ! Gradient Top light grey to bottom dark grey
            print 'rectangle'(@x(0),@y(Rows + 1)-12,@x(Columns + 1),@y(Rows + 1)),

            print 'pen'(1,1,Colour3DDark$), ! Solid Dark Grey
            print 'line'(@x(0),@y(StatusBarRow) + BorderHeight  + FrameHeight,@x(Columns + 1), @y(StatusBarRow) + BorderHeight  + FrameHeight),

            ! Next the separators
            print 'pen'(1,1,Colour3DDark$), ! dark grey  "RGB:199,195,177"
            print 'line'(@x(StatusBarSep1),@y(StatusBarRow) + BorderHeight + FrameHeight + 8,@x(StatusBarSep1),@y(Rows + 1) - 9),
            print 'line'(@x(StatusBarSep2),@y(StatusBarRow) + BorderHeight  + FrameHeight + 8,@x(StatusBarSep2),@y(Rows + 1) - 9),
            print 'pen'(1,1,Colour3DLight$), ! white
            print 'line'(@x(StatusBarSep1) + 2,@y(StatusBarRow) + BorderHeight  + FrameHeight + 9,@x(StatusBarSep1) + 2,@y(Rows + 1) - 8),
            print 'line'(@x(StatusBarSep2) + 2,@y(StatusBarRow) + BorderHeight  + FrameHeight + 9,@x(StatusBarSep2) + 2,@y(Rows + 1) - 8),
            multiline StatusBarS1,@(.5, Rows + 1 - 1.1, StatusBarSep1 - .5, .95 ),opt="BL",mnu=-1000
            StatusBarS1'BackColour$ = ColourDlgBase$
            StatusBarS1'Value$ = StatusBarS1Text$
            multiline StatusBarS2,@(StatusBarSep1 + .7, Rows + 1 - 1.1, StatusBarSep2 - StatusBarSep1 - 1.8, .95 ),opt="BL",mnu=-1000
            StatusBarS2'BackColour$ = ColourDlgBase$
            StatusBarS2'Value$ = StatusBarS2Text$
            button StatusBarS3,@(StatusBarSep2 + .7, Rows + 1 - 1.15, 1.8, .95)="{}",opt="BfST"
            StatusBarS3'Text$ = StatusBarS3Text$
            StatusBarS3'Tip$ = StatusBarS3Tip$
            break
    esac

    StatusBar = 1
    menubar on objs$[cntls[VStatusBar],10]

    print 'image'("BaseWindow"),

    if RefreshScreen \
        then print '+U',
    return 1
!
!
SetStatusBarText:
    enter Part, Value$, ToolTip$, err=*proceed
    switch Part
        case 1
            StatusBarS1Text$ = Value$
            if StatusBarS1 \
                then StatusBarS1'Value$ = Value$
            break
        case 2
            StatusBarS2Text$ = Value$
            if StatusBarS2 \
                then StatusBarS2'Value$ = Value$
            break
        case 3
            StatusBarS3Text$ = Value$
            if StatusBarS3 then \
            {   StatusBarS3'Text$ = Value$
                StatusBarS3'Tip$ = ToolTip$
            }
            break
    esac
    return 1

!
!
DeleteToolBar:
    if ToolBar = 0 \
        then return 0

    This'RemoveToolBarTips()
    i = pos("," = ToolBar$, 1, 0)
    dim x$[1:i]
    read data from ToolBar$,sep="," to x${all}
    for x = 1 to i
        c = 0
        c = vin(x$[x],err=*proceed)
        if c = 0 \
            then continue
        switch objs$[cntls[c], 9]
            case "S"; checkbox remove c,err=*proceed; break
            case "M"; multiline remove c,err=*proceed; break
            case "VD"; vardropbox remove c,err=*proceed; break
            default;  button remove c,err=*proceed; break
        esac
    next x
    button remove ToolBarStart,err=*proceed
    button remove ToolBarDropButton,err=*proceed
    print 'image'(delete "ToolBar"),
    ToolBar = 0
    menubar off objs$[cntls[VToolBar],10]
    return 1
!
!
SetSuppressToolTips:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    print 'goto'(BasePHnd),
    SuppressToolTips = Value%
    if SuppressToolTips = 1 then \
    {   This'RemoveToolBarTips()
        This'RemoveScrollBarTips()
        menubar off objs$[cntls[VToolTip],10]
        return Value%
    }
    menubar on objs$[cntls[VToolTip],10]
    This'AddToolBarTips()
    This'AddScrollBarTips()

    return Value%
!
!
AddToolBarTips:
    if ToolBar = 0 or ToolTips = 1 \
        then return 0

    t$ = ToolBar$
    if ToolBarExtra$ > "" \
        then t$ = t$(1, len(t$) - len(ToolBarExtra$))
    i = pos("," = t$, 1, 0)
    dim x$[1:i]
    read data from t$,sep="," to x${all}
    for x = 1 to i
        c = 0
        c = vin(x$[x],err=*proceed)
        if c = 0 then continue
        seterr ATBTCont
        c'tip$ = objs$[cntls[c],3]
        ATBTCont:
    next x
    ToolTips = 1
    return 1
!
!
RemoveToolBarTips:
    if ToolBar = 0 or ToolTips = 0 \
        then return 0

    t$ = ToolBar$
    if ToolBarExtra$ > "" \
        then t$ = t$(1, len(t$) - len(ToolBarExtra$))
    i = pos("," = t$, 1, 0)
    dim x$[1:i]
    read data from t$,sep="," to x${all}
    for x = 1 to i
        c = 0
        c = vin(x$[x],err=*proceed)
        if c = 0 then continue
        seterr RTBTCont
        c'tip$ = ""
         RTBTCont:
    next x
    ToolTips = 0
    return 1
!
!
DrawToolBar:
    print '-U',
    print 'goto'(BasePHnd),
    This'DeleteToolBar()

    if SuppressToolBar then \
    {   This'SuppressToolTips=SuppressToolTips
        print '+U',
        return 1
    }

    switch ToolBarSize
        case 2 ! 32 pixel images on button (large)
            ToolBarButtonHeight = 42 / RowGUs
            ToolBarButtonWidth = 42 / ColGUs
            ToolBarHeight = (48) / RowGUs
            IconSize = 32
            ImageSize$ = "32"
            break

        case 1 ! 24 pixel images on button (medium)
            ToolBarButtonHeight = 34 / RowGUs
            ToolBarButtonWidth = 34 / ColGUs
            ToolBarHeight = (40) / RowGUs
            IconSize = 24
            ImageSize$ = "24"
            break

        default ! 16 pixel images on button (small)
            ToolBarSize = 0
            ToolBarButtonHeight = 26 / RowGUs
            ToolBarButtonWidth = 26 / ColGUs
            ToolBarHeight = (32) / RowGUs
            IconSize = 16
            ImageSize$ = "16"
            break
    esac

    ToolBarButtonRow = (BorderHeight + 1)/ RowGUs

    print 'image'("ToolBar"),

    switch LookAndFeel
        case 3
            if ToolBarFlatButtons \
                then ImageFlat$ = "F"
            TBStartImage$ = ""
            print 'pen'(0,1,0), ! No Pen = No Border
            print 'fill'(1,ColourDlgBase$),
            print 'rectangle'(@x(0),@y(0),@x(Columns + 1) + 2,@y(ToolBarHeight)),

            print 'pen'(1, 1, Colour3DDark$),
            print 'line'(@x(0), @y(0), @x(Columns + 1), @y(0)),
            print 'line'(@x(0), @y(ToolBarHeight) - BorderHeight, @x(Columns + 1), @y(ToolBarHeight) - BorderHeight),
            print 'pen'(1, 1 ,Colour3DLight$),
            print 'line'(@x(0), @y(0) + BorderHeight, @x(Columns + 1), @y(0) + BorderHeight),
            print 'line'(@x(0), @y(ToolBarHeight), @x(Columns + 1), @y(ToolBarHeight)),
            break

        case 4
            ImageFlat$ = ""
            TBStartImage$ = "{*viewer/images/TB/TB.Leader.XP16M"+str(Iconsize)+".bmp,G}"
            print 'pen'(0,1,0), ! No Pen = No Border
            print 'fill'(1,ColourDlgBase$),
            print 'rectangle'(@x(0),@y(0),@x(Columns + 1) + 2,@y(ToolBarHeight)),

            print 'pen'(1, 1, Colour3DDark$), ! dark grey  "RGB:199,195,177"
            print 'line'(@x(0), @y(0), @x(Columns + 1), @y(0)),
            print 'line'(@x(0), @y(ToolBarHeight) - BorderHeight, @x(Columns + 1), @y(ToolBarHeight) - BorderHeight),
            print 'pen'(1, 1 ,Colour3DLight$),
            print 'line'(@x(0), @y(0) + BorderHeight, @x(Columns + 1), @y(0) + BorderHeight),
            print 'line'(@x(0), @y(ToolBarHeight), @x(Columns + 1), @y(ToolBarHeight)),
            break
    esac

    button ToolBarStart, @(0, ToolBarButtonRow, 1.3, ToolBarButtonHeight)=TBStartImage$, mnu=ToolBarRMenu,opt="fS"
    x = 1.3

    i = pos("," = ToolBar$, 1, 0)
    ToolBarExtra$ = ToolBar$
    for z = 1 to i
        y = pos("," = ToolBarExtra$)
        n$ = mid(ToolBarExtra$, 1, y - 1)

        if n$="VBanner" and SuppressBannerInfo then \
        {   ToolBarExtra$ = mid(ToolBarExtra$,y + 1)
            continue
        }

        if n$ > "" then \
        {   cn = vin(n$)
            c = cntls[cn]

            switch objs$[c, 9]
                case "B","S"; w = ToolBarButtonWidth; break
                case "M"
                    tw = txw(objs$[c, 1], 0, fnt="*GUIFont") / 16
                    w = .8 + tw + .1 + 6.2
                    break
                case "VD"
                    tw = txw(objs$[c, 1], 0, fnt="*GUIFont") / 16
                    w = .8 + tw + .2 + 7.05
                    break
            esac

            if x + w + ToolBarButtonWidth / 2 >= Columns \
                then break
        }

        ToolBarExtra$ = mid(ToolBarExtra$,y + 1)

        if n$ = "" then \
        {   if LookAndFeel = 3 then \
            {   print 'pen'(1,1,Colour3DDark$),
                print 'line'(@x(x + .65) - 1,@y(ToolBarButtonRow) + FrameHeight,@x(x + .65) - 1,@y(ToolBarButtonHeight) + FrameHeight),
                print 'pen'(1,1,Colour3DLight$), ! white
                print 'line'(@x(x + .65) + 1,@y(ToolBarButtonRow) + FrameHeight + BorderHeight,@x(x + .65) + 1,@y(ToolBarButtonHeight) + FrameHeight + BorderHeight),
            } else \
            {   print 'pen'(1,1,Colour3DDark$), ! dark grey  "RGB:199,195,177"
                print 'line'(@x(x + .65),@y(ToolBarButtonRow) + FrameHeight,@x(x + .65),@y(ToolBarButtonHeight) + FrameHeight),
            }
            x += 1.2
        } else \
        {   image$=""
            u$ = objs$[c, 11]
            u$ = sub(u$, "<FL>", ImageFlat$)
            u$ = sub(u$, "<LOOK>", ImageLook$)
            u$ = sub(u$, "<COLOUR>", ImageColour$)
            u$ = sub(u$, "<SIZE>", str(IconSize))

            d$ = objs$[c, 12]
            d$ = sub(d$, "<FL>", ImageFlat$)
            d$ = sub(d$, "<LOOK>", ImageLook$)
            d$ = sub(d$, "<COLOUR>", ImageColour$)
            d$ = sub(d$, "<SIZE>", str(IconSize))

            switch objs$[c, 9]
                case "S"
                    checkbox cn,@(x, ToolBarButtonRow, ToolBarButtonWidth, ToolBarButtonHeight)= mid(u$, 1, len(u$) - 1) + "|" + d$(2), opt="BSPT"
                    x += ToolBarButtonWidth
                    break

                case "B"
                    button cn,@(x, ToolBarButtonRow, ToolBarButtonWidth, ToolBarButtonHeight)= u$, opt="BT"
                    x += ToolBarButtonWidth
                    break

                case "M"
                    x += .8
                    print 'text'(@x(x),@y((ToolbarHeight - 1) / 2),objs$[c, 1],"&"),
                    x += tw
                    x -= .1
                    multiline cn,@(x,(ToolBarHeight - 1) / 2, 6.2, 1),opt="RT",len=7
                    cn'Key$ = objs$[c, 2]
                    x += 6.2
                    break

                case "VD"
                    x += .8
                    print 'text'(@x(x),@y((ToolbarHeight - 1) / 2),objs$[c, 1],"&"),
                    x += tw
                    x -= .2
                    vardropbox cn,@(x,(ToolBarHeight - 1) / 2, 6.6, 7),opt="T"
                    cn'Key$ = objs$[c, 2]
                    x += 7.05
                    break
            esac

        }
    next z

    if ToolBarExtra$ > "" then \
    {   if pos(","^ToolBarExtra$,1) \
            then button ToolBarDropButton,@(Columns + 1 - ToolBarButtonWidth / 2, \
                                            ToolBarButtonRow, ToolBarButtonWidth / 2, \
                                            ToolBarButtonHeight) \
                                            ="{*viewer/images/TB/TB.Chevron."+ImageLook$+ImageColour$+ \
                                            "32"+".bmp,G}",opt="BT",mnu=-1000
    }

    ToolBar = 1
    menubar on objs$[cntls[VToolBar],10]
    vardropbox load VZoomCustom,VZoomLevels$, err=*proceed

    This'SuppressToolTips=SuppressToolTips
    print 'image'("BaseWindow"),


    if RefreshScreen \
        then print '+U',
    return 1
!
!
DisplayToolBarDropMenu:
    t$ = ToolBarExtra$
    if mid(t$,1,1)="," \
        then t$ = t$(2);
             goto *same

    if len(t$) = 0 \
        then return 0

    m$ = "["
    i = pos("," = t$, 1, 0)
    dim x$[1:i]
    read data from t$,sep="," to x${all}
    for x = 1 to i
        c = 0
        c = vin(x$[x],err=*proceed)
        if c = VJump or c = VZoomCustom then continue
        if c = 0 and m$="[" then continue
        if c = 0 and x > 1 then m$ += ","; continue
        if m$ > "[" then m$ += ","
        This'AddMenuItem(m$, c, 0, 0)
    next x
    m$ += "]"
    popupmenu m$,selected,err=*next
    if selected \
        then preinput next selected
    setfocus 0
    return 1
!
!
DisplayToolBarRightMenu:
    oldToolBarSize = ToolBarSize
    m$ = "[" + msg("Menu.TBSmallIcons")  + "=" + tbl(IconSize=16,"","C") + "1," + \
               msg("Menu.TBMediumIcons") + "=" + tbl(IconSize=24,"","C") + "2," + \
               msg("Menu.TBLargeIcons")  + "=" + tbl(IconSize=32,"","C") + "3"  + \
               "]"
               ! "," + msg("Menu.Customize")     + "=" + "D" + str(ToolBarCustomize) + "]"

    popupmenu @(ToolBarMenuX, ToolBarMenuY),m$,selected
    if selected then \
    {   ToolBarSize = selected - 1
        if ToolBarSize <> OldToolBarSize then \
        {   ForceRePaint = 1
            This'RePaint()
        }
    }
    setfocus 0
    return 1
!
!
DeleteScrollBars:
    if ScrollBars = 0 \
        then return 0
    print 'image'(delete "ScrollBars"),
    vscrollbar remove BVScroll, err=*proceed
    hscrollbar remove BHScroll, err=*proceed
    button remove BTop, err=*proceed
    button remove BPrevious, err=*proceed
    button remove BBlank, err=*proceed
    button remove BNext, err=*proceed
    button remove BBottom, err=*proceed
    ScrollBars = 0
    return 1
!
!
DrawScrollBars:
    print '-U',
    print 'goto'(BasePHnd),
    This'DeleteScrollBars()

    w = 2.2
    c = Columns + 1 - w
    r = BorderHeight / RowGUs
    h = Rows + 1

    if ExtraVisualEffects \
        then ImageTemp$ = "XP", bw = 2.0 \
        else ImageTemp$ = "2K", bw = 2.2
    if ImageColour$ = "256" \
        then ImageTemp$ = "2K"
    bh = bw * ColGUs / RowGUs

    if ToolBar \
        then r += ToolBarHeight; h -= ToolBarHeight
    if StatusBar \
        then h -= StatusBarHeight

    h = h - (6 * bh)

    print 'image'("ScrollBars"),
    print 'pen'(0,1,0), ! No Pen = No Border
    print 'fill'(1,ColourDlgBase$),
    if StatusBar \
        then yy = @y(StatusBarRow) + BorderHeight + 2 \
        else yy = @y(Rows + 1) + 2
    print 'rectangle'(@x(c),@y(r) - 2,@x(Columns + 1) + 2, yy),

    vscrollbar BVScroll,@(c, r, w, h - .1)
    BVScroll'MaxValue = VScrollMax
    BVScroll'SmallJump = VScrollSmallJump
    BVScroll'BigJump = VScrollBigJump

    r += h

    switch ExtraVisualEffects
        case 1
            button BTop,@(c+.1, r-.1, bw, bh)="{*viewer/images/VSB/VSB.Top."+ImageTemp$+ImageColour$+".bmp,G}",opt="BT",tip=msg("C.BTop.Tip")
            r += bh
            button BPrevious,@(c+.1, r-.1, bw, bh)="{*viewer/images/VSB/VSB.Up."+ImageTemp$+ImageColour$+".bmp,G}",opt="BT",tip=msg("C.BPrevious.Tip")
            r += bh
            r += bh
            button BNext,@(c+.1, r+.05, bw, bh)="{*viewer/images/VSB/VSB.Down."+ImageTemp$+ImageColour$+".bmp,G}",opt="BT",tip=msg("C.BNext.Tip")
            r += bh
            button BBottom,@(c+.1, r, bw , bh )="{*viewer/images/VSB/VSB.Bottom."+ImageTemp$+ImageColour$+".bmp,G}",opt="BT",tip=msg("C.BBottom.Tip")
            break

        case 0
            button BTop,@(c, r-.15, bw, bh)="{*viewer/images/VSB/VSB.Top."+ImageTemp$+ImageColour$+".bmp,G}",opt="BT",tip=msg("C.BTop.Tip")
            r += bh
            button BPrevious,@(c, r-.2, bw, bh)="{*viewer/images/VSB/VSB.Up."+ImageTemp$+ImageColour$+".bmp,G}",opt="BT",tip=msg("C.BPrevious.Tip")
            r += bh
            r += bh
            button BNext,@(c, r, bw, bh)="{*viewer/images/VSB/VSB.Down."+ImageTemp$+ImageColour$+".bmp,G}",opt="BT",tip=msg("C.BNext.Tip")
            r += bh
            button BBottom,@(c, r, bw , bh )="{*viewer/images/VSB/VSB.Bottom."+ImageTemp$+ImageColour$+".bmp,G}",opt="BT",tip=msg("C.BBottom.Tip")
            break
    esac

    r += bh
    if ToolBar \
        then y1 = @y(ToolBarHeight)  \
        else y1 = 0
    if StatusBar \
        then y2 = @y(StatusBarRow) - (2.2 * RowGUs) - BorderHeight \
        else y2 = @y(Rows + 1) - (2.2 * RowGUs) - BorderHeight
    print 'pen'(1, 1 ,Colour3DLight$),
    print 'line'(@x(0), y1 + BorderHeight, @x(0), y2 + BorderHeight),
    print 'line'(@x(c) - BorderWidth * 2, y1 + BorderHeight, @x(c) - BorderWidth * 2, y2 + BorderHeight),
    print 'line'(@x(0), y2, @x(c) - BorderWidth * w, y2),

    if ToolBar = 0 then \
    {   print 'image'("ToolBar"),
        print 'pen'(1, 1 ,Colour3DLight$),
        print 'line'(@x(0), @y(0) + BorderHeight, @x(Columns -1.5), @y(0)+2),
    }

    print 'image'("ScrollBars"),

    if LookAndFeel = 4 \
        then print '2d','4d',

    hscrollbar BHScroll,@(0, r-.1, Columns + 1 - bw, bh)
    BHScroll'MaxValue = HScrollMax
    BHScroll'SmallJump = HScrollSmallJump
    BHScroll'BigJump = HScrollBigJump

    print 'image'("BaseWindow"),
    ScrollBars = 1

    if SuppressToolTips = 0 \
        then This'AddScrollBarTips()

    if RefreshScreen \
        then print '+U',

    return 1
!
AddScrollBarTips:
    if ScrollBars = 0 \
        then return 0
    BTop'Tip$=msg("C.BTop.Tip")
    BPrevious'Tip$=msg("C.BPrevious.Tip")
    BNext'Tip$=msg("C.BNext.Tip")
    BBottom'Tip$=msg("C.BBottom.Tip")
    return 0
!
RemoveScrollBarTips:
    if ScrollBars = 0 \
        then return 0
    BTop'Tip$=""
    BPrevious'Tip$=""
    BNext'Tip$=""
    BBottom'Tip$=""
    return 0
!
!
CreateViewPort:
    print '-U',
    if ViewPort \
        then This'DeleteViewPort()
    print 'goto'(BasePHnd),

    ViewColumn = 1
    ViewRow = 1
    ViewColumns = Columns - 4 + 1
    ViewRows = Rows + 1

    if ToolBar then \
    {   ViewRow = int(ToolBarHeight) + sgn(fpt(ToolBarHeight))
        ViewRows -= ViewRow - 1
    }

    if StatusBar then \
    {   ViewRows -= int(StatusBarHeight + .5)
    }

    if ScrollBars then \
    {   ViewRows -= 3
    }

    ! Create View port
    ViewPortWindow = hwn(0)
    print 'window'(ViewColumn, ViewRow, ViewColumns, ViewRows, ViewPortWindow, opt="c&"),
    print (0,err=*proceed) 'option'("FONT","FixedSys,-9"), \
                           'option'("GRAPHICFONT","*GuiFont"), \
                           'scroll'("OFF"), \
                           'wrap'("OFF"), \
                           '_colour'(ColourDlgWorkSpace$), \
                           'df','cs','sr', \
                           '-U',

    ViewPort = 1

    print '2d','3d',
    for x = 1 to VisibleImages
        c = VisibleImage[x, 1]
        b = VisibleImage[x, 10]
        s = VisibleImage[x, 11]
        if ImageButtonRight1 < 0 \
            then mc = ImageButtonRight1 + 1 - x \
            else mc = ImageButtonRight1 - 1 + x
        button c,@(0,0,0,0)="{}",mnu=mc,opt="SHBf"
        button b,@(0,0,0,0)="",opt="SHf"
        button s,@(0,0,0,0)="",opt="SHGf"
        c'ImageCount = 1
        c'BackColour$ = "White"
        b'BackColour$ = "Black"
        s'BackColour$ = ColourShadow$
    next x

    if LookAndFeel = 4 \
        then print '2d','4d',

    if RefreshScreen \
        then print '+U',
    return 1
!
!
DeleteViewPort:
    if ViewPortWindow then \
    {   print 'goto'(ViewPortWindow),
        for x = 1 to VisibleImages
            button remove VisibleImage[x,11],err=*proceed
            button remove VisibleImage[x,10],err=*proceed
            button remove VisibleImage[x,1],err=*proceed
            VisibleImage[x, 9] = 0
        next x

        print (0,err=*proceed) 'drop'(ViewPortWindow),
    }

    ViewPort = 0

    return
!
!
SetSuppressBannerInfo:
    enter (Value%)
    if Value% <> 0 \
        then Value% = 1
    if Value% = SuppressBannerInfo \
        then return Value%
    SuppressBannerInfo = Value%
    if SuppressBannerInfo = 1 then \
    {   This'CreateMenuBar()
        This'DrawToolBar()
        return Value%
    }
    This'CreateMenuBar()
    This'DrawToolBar()
    return Value%
!
!
GetAccelerator:
    enter value$
    x1 = pos("&"=value$,1)
    if x1 \
        then return ucs(mid(value$, x1 + 1, 1) ) \
        else return ""
!
!
ResolveIcon:
    enter path$, refer$, trans$
    refer$ = ""
    trans$ = ""
    x1 = pos("@" = path$, 1)
    x2 = pos("%" = path$, 1)
    x3 = pos("," = path$, 1)
    if x1 then path$(x1, 1)=";"
    if x2 then path$(x2, 1)=";"
    if x3 then path$(x3, 1)=";"
    path$ += ";"

    if x1 then refer$ = "@" + path$(x1 + 1, pos(";" = path$(x1 + 1),1) - 1)
    if x3 then trans$ = "," + path$(x3 + 1, pos(";" = path$(x3 + 1),1) - 1)

    x1 = pos("<" = path$, 1)
    x2 = pos(">" = path$, 1)

    if x1 and x2 then \
    {   p1$ = mid(path$, x1 + 1, x2 - x1 - 1)
        path$ = mid(path$, x2 + 1)
    }

    if ucs(p1$) = "WINSYSDIR" \
        then p1$ = WinAPI'GetFolderPath$(Constants'Folders'CSIDL_SYSTEM)

    if ucs(p1$) = "WINDIR" \
        then p1$ = WinAPI'GetFolderPath$(Constants'Folders'CSIDL_WINDOWS)

    path$ = mid(path$, 1, pos(";" = path$,1) - 1)
    path$ = p1$ + path$
    return 1
!
!
CloseFile:
    if IsPrinting then \
    {   answer$ = This'DisplayError$(msg("TCurrentlyPrinting"),"?,^,YESNO")
        if answer$ = "NO" \
            then return 0
    }

    if Report then \
    {   This'DialogueGotoPageDestroy()
        This'DialogueZoomDestroy()
        This'DialogueBannerInfoDestroy()
        This'DialogueAboutDestroy()
        This'DialogueFindDestroy()
        This'ImageButtonsClear()
        drop object Report
        drop object WaterMark
        Report = 0
        WaterMark = 0
        This'ChangeMenu("NOFILE")
        This'SetStatusBarText(1,"No File.")
        This'SetStatusBarText(2,"")
        This'SetStatusBarText(3,"","")
    }
    Page = 0
    Pages = 0
    IsSpooling = 0
    IsSpooled = 0
    IsPrinting = 0
    IsPrinted = 1
    RenderErrorOnPages$ = ""

    return 1
!
!
DeleteFile:
    if DisableDelete or Report = 0 \
        then return 0

    if IsPrinting then \
    {   answer$ = This'DisplayError$(msg("TCurrentlyPrinting"),"?,^,YESNO")
        if answer$ = "NO" \
            then return 0
    }

    answer$ = This'DisplayError$(msg("TConfirmDelete"),"?,^,YESNO")
    if answer$ = "NO" \
        then return 0

    if This'Close() = 0 \
        then return 0

    erase FileName$, err=DFCantErase
    return 1
    !
    DFCantErase:
    This'DisplayError$(msg("TUnableToDelete",msg(ret)))
    return 1
!
!
FileSaveAs:
    if not(IsSpooled) then \
    {   answer$ = This'DisplayError$(msg("TCurrentlySpooling"),"?,^,YESNO")
        if answer$ = "NO" \
            then return 0
    }

    enter SaveAsFile$, err=*proceed

    if LastSaveAsPath$ = "" and DefaultSaveAsPath$ > "" \
        then LastSaveAsPath$ = DefaultSaveAsPath$
    if LastSaveAsPath$ = "" \
        then LastSaveAsPath$ = lwd

    x = pos(dlm = FileName$, -1)
    if x \
        then CurrentFile$ = mid(FileName$, x + 1)

    x = pos("." = CurrentFile$, -1)
    if x \
        then CurrentFile$ = CurrentFile$(1, x - 1)

    x = pos(dlm = SaveAsFile$, -1)
    if SaveAsFile$ > "" and x = 0 then \
    {   LastSaveAsFile$ = LastSaveAsPath$ + dlm + SaveAsFile$(x + 1)
    }

    if LastSaveAsFile$ = "" \
        then LastSaveAsFile$ = LastSaveAsPath$ + dlm + CurrentFile$

    if SaveAsFile$ = "" \
        then getfilebox write LastSaveAsFile$, LastSaveAsPath$, Software$ + " - "+msg("TSaveAs"), SaveAsExtensions$, SaveAsExtensionsDefault$ \
        else LastSaveAsFile$ = SaveAsFile$

    if LastSaveAsFile$ > "" then \
    {   LastSaveAsPath$ = mid(LastSaveAsFile$, 1, pos(dlm = LastSaveAsFile$, -1) - 1)

        if IsWindows or pos("[WDX]" = LastSaveAsFile$) \
            then if ucs(LastSaveAsFile$) = ucs(Report'FileName$) \
                     then return 1 \
                 fi \
            else if LastSaveAsFile$ = Report'FileName$ \
                    then return 1

        if ucs(mid(LastSaveAsFile$, -4)) = ".PDF" then \
        {   This'SaveAsPDF(LastSaveAsFile$)
            return 1
        }

        This'SetStatusBarText(2,msg("TSaveCopy"))
        print 'cursor'(2),; wait 0
        This'CopyFile(Report'FileName$, LastSaveAsFile$)
        This'SetStatusBarText(2,msg("TSaveComplete"))
        print 'cursor'(0),; wait 0
        return 1
    }

    return 1
!
!
FileSaveAsPDF:
    if not(IsSpooled) then \
    {   answer$ = This'DisplayError$(msg("TCurrentlySpooling"),"?,^,YESNO")
        if answer$ = "NO" \
            then return 0
    }

    enter SaveAsFile$, err=*proceed

    if LastSaveAsPath$ = "" and DefaultSaveAsPath$ > "" \
        then LastSaveAsPath$ = DefaultSaveAsPath$
    if LastSaveAsPath$ = "" \
        then LastSaveAsPath$ = lwd

    x = pos(dlm = FileName$, -1)
    if x \
        then CurrentFile$ = mid(FileName$, x + 1)

    x = pos("." = CurrentFile$, -1)
    if x \
        then CurrentFile$ = CurrentFile$(1, x - 1)

    x = pos(dlm = SaveAsFile$, -1)
    if SaveAsFile$ > "" and x = 0 then \
    {   LastSaveAsFile$ = LastSaveAsPath$ + dlm + SaveAsFile$(x + 1)
    }

    if LastSaveAsFile$ = "" \
        then LastSaveAsFile$ = LastSaveAsPath$ + dlm + CurrentFile$

    if SaveAsFile$ = "" \
        then getfilebox write LastSaveAsFile$, LastSaveAsPath$, Software$ + " - "+msg("TSaveAsPDF"), SaveAsPDFExtensions$, SaveAsPDFExtensionsDefault$ \
        else LastSaveAsFile$ = SaveAsFile$

    if LastSaveAsFile$ > "" then \
    {   LastSaveAsPath$ = mid(LastSaveAsFile$, 1, pos(dlm = LastSaveAsFile$, -1) - 1)

        if ucs(mid(LastSaveAsFile$, -4)) <> "."+ucs(SaveAsPDFExtensionsDefault$) \
            then LastSaveAsFile$ = LastSaveAsFile$ + "." + SaveAsPDFExtensionsDefault$

        if ucs(mid(LastSaveAsFile$, 1, 5)) = "[WDX]" then\
        {   LastSaveAsFile$ = LastSaveAsFile$(6)
            IsWindXFile = 1
        }

        Report'Page = 0
        ThisPage = Report'Page(0)

        if IsWindXFile \
            then PDF$ = "[WDX]*pdf*" \
            else PDF$ = "*pdf*"

        PDF$ += ";File="+LastSaveAsFile$
        PDF$ += ";Overwrite"
        PDF$ += ";PaperSize="+str(ThisPage'PaperSize)
        PDF$ += ";Orientation="+str(ThisPage'Orientation$)
        PDF$ += ";Margins="+str(ThisPage'MarginLeft) + ":" + str(ThisPage'MarginTop) + ":" + \
                            str(ThisPage'MarginRight) + ":" + str(ThisPage'MarginBottom)
        if Report'Title$ > "" \
            then PDF$ += ";Title = "+Report'Title$

        This'Print(PDF$)

        return 1
    }

    return 0
!
!
! Returns 0 on successfull copy, else it errored
CopyFile:
    enter (InputFile$), (OutputFile$)

    if InputFile$ = "" or OutputFile$ = "" \
        then return 0
    open input(hfn, isz=1, err=CFErr) InputFile$
    iFile = lfo

    serial OutputFile$, err=*proceed
    open purge(hfn, isz=1, err=CFErr) OutputFile$
    oFile = lfo

    eof = 0
    while not(eof)
        eof = 1
        dat$ = ""
        read record(iFile, siz=16384, end=*next) dat$; eof = 0
        if dat$ > "" \
            then write record(oFile, err=*proceed)dat$
    wend

    close(iFile),(oFile)
    return 0
    !
    CFErr:
    if iFile \
        then close(iFile)
    if oFile \
        then close(oFile)
    return err
!
!
OpenFilePrompt: ! returns 0 on sucess else error code (-1 = error 0)
    if This'Close() = 0 \
        then return 0
    if AlwaysUseDefaultOpenPath and DefaultOpenPath$ > "" \
        then LastOpenPath$ = DefaultOpenPath$
    if LastOpenPath$ = "" and DefaultOpenPath$ > "" \
        then LastOpenPath$ = DefaultOpenPath$
    if LastOpenPath$ = "" \
        then LastOpenPath$ = lwd
    This'MakeVisible()

    getfilebox LastOpenFile$, LastOpenPath$, Software$, TOpenExtensions$
    if LastOpenFile$ > "" then \
    {   FileName$ = LastOpenFile$
        This'SetStatusBarText(1, FileName$)
        This'SetStatusBarText(2, msg("TWaitForReport"))
        if WaterMark = 0 \
            then WaterMark = new(WaterMarkClass$, ParametersSoftware, err=*proceed)
        Report = new(ReportClass$, FileName$, WaterMark, err=*proceed)
        This'SetStatusBarText(2, "")
        result = err
        if result = 0 \
            then result = -1
        if Report then \
        {   if SetWindowStateOnSpoolStart \
                then This'MakeVisible()
            x = pos(dlm = FileName$, -1)
            if x \
                then LastOpenPath$ = mid(FileName$, 1, x - 1)
            LastOpenFile$ = FileName$
            LastOpenPath$ = mid(LastOpenFile$, 1, pos(dlm = LastOpenFile$, -1) - 1)
            This'ChangeMenu("FILEOPEN")
            This'View = View
            This'Zoom(ZoomLevel)
            This'SetStatusBarText(2, TLoading$)

            Report'SuppressFirstBlankPage = SuppressFirstBlankPage
            Report'SuppressAllBlankPages = SuppressAllBlankPages
            Report'DefaultFixedFont$ = DefaultFixedFont$
            Report'DefaultFixedFontSize = DefaultFixedFontSize
            Report'MinimumColumns = MinimumColumns
            Report'MinimumRows = MinimumRows
            Report'PaginationAt = PaginationAt
            Report'ScaleToFit = ScaleToFit
            Report'Collate = Collate
            Report'Colour = Colour
            Report'Copies = Copies
            Report'DPI = DPIPrinter
            Report'Range$ = Range$

            x = Report'Page(0)
            x'PaperSize = DefaultPaperSize
            x'Orientation = DefaultOrientation

            if Visible then \
            {   preinput CheckSpool
                return 0
            }

            counter = 0
            while Report and not(Report'Spooled) and Report'Spool
                This'BackGroundSpool(UseTimer)
                if counter and counter | 5 = 0 \
                    then wait .2
                counter ++
            wend
            return 0
        }
    }
    return result
!
!
OpenFileName: ! returns 0 on sucess else error code
    if This'Close() = 0 \
        then return 0
    enter Value$

    This'SetStatusBarText(1, Value$)
    This'SetStatusBarText(2, msg("TWaitForReport"))
    if WaterMark = 0 \
        then WaterMark = new(WaterMarkClass$, ParametersSoftware, err=*proceed)
    Report = new(ReportClass$, Value$, WaterMark, err=OFNOpenErr)
    This'SetStatusBarText(2, "")
    result = err
    if result = 0 \
        then result = -1

    if Report then \
    {   if SetWindowStateOnSpoolStart \
            then This'MakeVisible()

        FileName$ = Value$
        This'ChangeMenu("FILEOPEN")
        This'View = View
        This'Zoom(ZoomLevel)
        This'SetStatusBarText(2, TLoading$)

        Report'SuppressFirstBlankPage = SuppressFirstBlankPage
        Report'SuppressAllBlankPages = SuppressAllBlankPages
        Report'DefaultFixedFont$ = DefaultFixedFont$
        Report'DefaultFixedFontSize = DefaultFixedFontSize
        Report'MinimumColumns = MinimumColumns
        Report'MinimumRows = MinimumRows
        Report'PaginationAt = PaginationAt
        Report'ScaleToFit = ScaleToFit
        Report'Collate = Collate
        Report'Colour = Colour
        Report'Copies = Copies
        Report'DPI = DPIPrinter
        Report'Range$ = Range$

        x = Report'Page(0)
        x'PaperSize = DefaultPaperSize
        x'Orientation = DefaultOrientation

        if Visible then \
        {   preinput CheckSpool
            return 0
        }

        counter = 0
        while Report and not(Report'Spooled) and Report'Spool
            This'BackGroundSpool(UseTimer)
            if counter and counter | 5 = 0 \
                then wait .2
            counter ++
        wend
        return 0
    }
    return result
!
OFNOpenErr:
    error = err
    This'SetStatusBarText(2, "")
    Answer$ = ""
    if error = 0 \
        then error = 256
    switch error
        case 256; Answer$ = This'DisplayError$(msg("EPermissions",Value$),"?,RETRYCANCEL"); break
        case 17; This'DisplayError$(msg("EInvalidFileType",Value$)); break
        case 12; This'DisplayError$(msg("EFileNotFound",Value$)); break
        default; This'DisplayError$(msg("EUnknownError",Value$,str(error))); break
    esac
    if Answer$ = "RETRY" \
        then retry
    return error
!
!
OpenFileHandle: ! returns 0 on sucess else error code (-1 = error 0)
    if This'Close() = 0 \
        then return 0

    enter Value%
    if Value% <= 0 \
        then return 0
    This'SetStatusBarText(1, msg("TFileObject",str(Value%)))
    This'SetStatusBarText(2, msg("TWaitForReport"))
    if WaterMark = 0 \
        then WaterMark = new(WaterMarkClass$, ParametersSoftware, err=*proceed)
    Report = new(ReportClass$, Value%, WaterMark, err=*next)
    This'SetStatusBarText(2, "")
    result = err
    if result = 0 \
        then result = -1
    if Report then \
    {   if SetWindowStateOnSpoolStart \
            then This'MakeVisible()
        This'ChangeMenu("FILEOPEN")
        This'View = View
        This'Zoom(ZoomLevel)
        This'SetStatusBarText(2, TLoading$)

        Report'SuppressFirstBlankPage = SuppressFirstBlankPage
        Report'SuppressAllBlankPages = SuppressAllBlankPages
        Report'DefaultFixedFont$ = DefaultFixedFont$
        Report'DefaultFixedFontSize = DefaultFixedFontSize
        Report'MinimumColumns = MinimumColumns
        Report'MinimumRows = MinimumRows
        Report'PaginationAt = PaginationAt
        Report'ScaleToFit = ScaleToFit
        Report'Collate = Collate
        Report'Colour = Colour
        Report'Copies = Copies
        Report'DPI = DPIPrinter
        Report'Range$ = Range$

        x = Report'Page(0)
        x'PaperSize = DefaultPaperSize
        x'Orientation = DefaultOrientation

        if Visible then \
        {   preinput CheckSpool
            return 0
        }

        counter = 0
        while Report and not(Report'Spooled) and Report'Spool
            This'BackGroundSpool(UseTimer)
            if counter and counter | 5 = 0 \
                then wait .2
            counter ++
        wend
        return 0
    }
    return result
!
!
VScrollBarSelect:
    if ScrollBars = 0 or Report = 0 \
        then return 0
    vscrollbar read BVScroll, Location, VScrollMax, VScrollBigJump, VScrollSmallJump
    Amount = VScrollCurPos - Location
    if Amount = 0 \
        then return 0

    if sgn(Amount) = -1 \
        then Direction = 2, Amount = abs(Amount) \
        else Direction = 1
    This'ScrollVertical(Amount, Direction)
    return 0
!
!
HScrollBarSelect:
    if ScrollBars = 0 or Report = 0 or HScrollMax = 1 \
        then return 0
    hscrollbar read BHScroll, Location, HScrollMax, HScrollBigJump, HScrollSmallJump
    This'ScrollHorizontal(Location)
    return 0
!
!
ScrollVertical:
    enter Amount, Direction

    if Direction = 1 \
        then amount *= -1

    ! What to do when in other "views"
    if VScrollSmallJump = VScrollBigJump then \
    {   if View = 1 or View = 2 \
            then amount *= 2
        if View = 3 \
            then amount *= 4
        This'GotoPage(Page + amount)
        return 0
    }

    ! What to do when we are scrolling more than 1 page
    if Amount < -100 or Amount > 100 then \
    {   location = VScrollCurPos + Amount
        newpage = int((location - 1) / 100) + 1
        newlocation = (location - 1) | 100 + 1
        newlocation *= sgn(newlocation)
        This'GotoPage(newpage)

        if VScrollSmallJump = VScrollBigJump then \
        {   Location = Page
        } else \
        {   PageLines = VisibleImage[1, 8]
            LinesPerIncrement = PageLines / 100
            PageLocLines = LinesPerIncrement * newlocation
            HalfViewArea = (ViewRows - 1) / 2
            TopOfPageLocation = HalfViewArea - PageLocLines
            BottomOfPageLocation = TopOfPageLocation + PageLines

            If TopOfPageLocation > 0 then \
            {   Adjustment = TopOfPageLocation
                TopOfPageLocation = 0
                BottomOfPageLocation -= Adjustment
                Location = Page * 100 - 100 + 1
            }

            if BottomOfPageLocation < ViewRows - 1 then \
            {   Adjustment = BottomOfPageLocation - (ViewRows - 1)
                TopOfPageLocation -= Adjustment
                BottomOfPageLocation = ViewRows - 1
                Location = Page * 100
            }

            VisibleImage[1, 6] = TopOfPageLocation
        }
        VScrollCurPos = Location

    } else \
    {   ! Scrolling Less than 1 page worth

        location = VScrollCurPos + amount

        PageLoc = VisibleImage[1, 6]
        PageLines = VisibleImage[1, 8]
        LinesPerIncrement = PageLines / 100

        ! If scrolling up and Page is already at y location of 0 then change pages unless were on page 1
        if Direction = 1 and PageLoc = 0 then \
        {   if VisibleImage[1, 2] <= 1 then \
            {   Amount = 0
                location = 1
            } else \
            {   This'GotoPage(VisibleImage[1, 2] - 1)
                if VScrollSmallJump = VScrollBigJump then \
                {   Amount = 0
                    location = Page
                    TopOfPageLocation = VisibleImage[1, 6]
                } else \
                {   Amount = 99
                    location = Page * 100
                }
            }
        }

        ! If scrolling down and Page is already displaying its bottom, then changes pages unless were on the last page
        if Direction = 2 and PageLoc + PageLines <= ViewRows - 1 then \
        {   if VisibleImage[1, 2] >= Report'Pages then \
            {   Amount = 99
                location = Page * 100
            } else \
            {   This'GotoPage(VisibleImage[1, 2] + 1)
                Amount = 0
                if VScrollSmallJump = VScrollBigJump then \
                {   Location = Page
                    TopOfPageLocation = VisibleImage[1, 6]
                } else \
                {   location = Page * 100 - 100 + 1
                }
            }
        }

        PageLoc = VisibleImage[1, 6]
        PageLines = VisibleImage[1, 8]
        LinesPerIncrement = PageLines / 100

        if Amount then \
        {   AmountToMove = LinesPerIncrement * Amount
            TopOfPageLocation = PageLoc - AmountToMove
            BottomOfPageLocation = TopOfPageLocation + PageLines

            If TopOfPageLocation >= 0 then \
            {   Adjustment = TopOfPageLocation
                TopOfPageLocation = 0
                BottomOfPageLocation -= Adjustment
                Location = Page * 100 - 100 + 1
            }

            if BottomOfPageLocation <= ViewRows - 1 then \
            {   Adjustment = BottomOfPageLocation - (ViewRows - 1)
                TopOfPageLocation -= Adjustment
                BottomOfPageLocation = ViewRows - 1
                Location = Page * 100
            }
        }

        VisibleImage[1, 6] = TopOfPageLocation
        VScrollCurPos = Location
    }

    vscrollbar write BVScroll, VScrollCurPos, VScrollMax
    This'DrawPages()

    return 0
!
!
ScrollHorizontal:
    enter Location
    VisibleImage[1, 5] = 0 - ((Location - 1) / 100)
    HScrollCurPos = Location
    HScrollLastPos = HScrollCurPos
    hscrollbar write BHScroll, HScrollCurPos, HScrollMax
    This'DrawPages()
    return 0
!
!
ScrollLeft:
    if Scrollbars = 0 or Report = 0 or HScrollMax = 1 or HScrollCurPos = 1 \
        then return 0
    enter Amount, err=*next ! Amount is in Columns
    if Amount = 0 \
        then Amount = HScrollSmallJump \
        else Amount = int(Amount * 100) + 1 ! Convert to Scrollbar Position
    NewPos = HScrollCurPos - Amount
    NewPos = max(1, NewPos)
    NewPos = min(NewPos, HScrollMax)
    This'ScrollHorizontal(NewPos)
    return 0
!
!
ScrollRight:
    if Scrollbars = 0 or Report = 0 or HScrollMax = 1 or HscrollCurPos >= HScrollMax \
        then return 0
    enter Amount, err=*next ! Amount is in Columns
    if Amount = 0 \
        then Amount = HScrollSmallJump \
        else Amount = int(Amount * 100)
    NewPos = HScrollCurPos + Amount
    NewPos = max(1, NewPos)
    NewPos = min(NewPos, HScrollMax)
    This'ScrollHorizontal(NewPos)
    return 0
!
!
ScrollUp:
    if ScrollBars = 0 or Report = 0 or VScrollMax = 0 or VScrollCurPos = 1 \
        then return 0
    enter Amount, err=*next ! Amount is in Pages (to 2 decimal places)

    if VScrollSmallJump = VScrollBigJump then \
    {   Amount = int(Amount)
        if Amount = 0 \
            then Amount = VScrollSmallJump
    } else \
    {   if Amount = 0 \
            then Amount = VScrollSmallJump \
            else Amount = int(Amount * 100)
    }

    This'ScrollVertical(Amount, 1) ! ! for Up
    return 0
!
!
ScrollDown:
    if ScrollBars = 0 or Report = 0 or VScrollMax = 0 or VScrollCurPos >= VScrollMax \
        then return 0
    enter Amount, err=*next ! Amount is in Pages (to 2 decimal places)

    if VScrollSmallJump = VScrollBigJump then \
    {   Amount = int(Amount)
        if Amount = 0 \
            then Amount = VScrollSmallJump
    } else \
    {   if Amount = 0 \
            then Amount = VScrollSmallJump \
            else Amount = int(Amount * 100)
    }

    This'ScrollVertical(Amount, 2) ! ! for Down
    return 0
!
!
SetCaption:
    enter Value$, err=*proceed
    if Value$ = "" \
        then return 0

    Caption$ = Value$

    if BasePHnd = 0 \
        then return 0

    print 'goto'(BasePHnd),'caption'(Caption$),

    return 0
!
!
SetIcon:
    enter Value$, err=*proceed
    if Value$ = "" \
        then return 0

    This'ResolveIcon(Value$,r$,t$)
    Icon32$ = Value$+r$+"%32"+t$
    Icon16$ = Value$+r$+"%16"+t$
    Icon$ = Icon16$

    if BasePHnd = 0 \
        then return 0

    print (0,err=*proceed)'option'("WDWICON",Icon32$), \
                          'option'("WDWICON",Icon16$),
    return 0
!
!
SetWaterMarkPages:
    enter Value%, err=*proceed
    if Value% < 0 or Value% > 2 \
        then Value% = 2

    if Value% = WaterMarkPages \
        then return 0

    WaterMarkPages = Value%

    if SuppressWaterMarks = 0 \
        then menubar on objs$[cntls[VWaterMark],10] \
        else menubar off objs$[cntls[VWaterMark],10]
    if WaterMarkPages = 0 \
        then menubar disable objs$[cntls[VWaterMark],10] \
        else menubar enable objs$[cntls[VWaterMark],10]

    if Report then \
    {   This'RefreshPages()
        This'DrawPages()
    }
    return 0
!
!
MakeVisible:
    if BasePHnd = 0 \
        then return 0

    if Visible = 0 \
        then return 0

    if WinPlacementDone = 0 then \
    {   WinAPI'SetWindowPlacement(BaseWHnd,Left,Top,Right,Bottom)
        WinPlacementDone = 1
    }

    if WindowState < 2 then \
        WindowState = 2

    print 'show'(WindowState - 1),
    ForceRePaint = 1
    This'RePaint()
    wait 0

    return 0

!
SetVisible:
    enter Value%, err=*proceed

    if Value% <> 0 \
        then Value% = 1

    if Value% = Visible \
        then return 0

    Visible = Value%

    if BasePHnd = 0 \
        then return 0

    if Visible = 0 then \
    {   print 'goto'(BasePHnd),'show'(-1),
        wait 0
        return 0
    }

    if HasWindowOverrides then \
    {   if SetWindowStateOnSpoolComplete and IsSpooled \
            then This'MakeVisible(); return 0
        if SetWindowStateOnFirstPage and BasePhnd and Report and (Page or Pages = 0) \
            then This'MakeVisible(); return 0
        if SetWindowStateOnSpoolStart and BasePhnd and Report and IsSpooled = 0 \
            then This'MakeVisible(); return 0
        if SetWindowStateOnCreate and BasePHnd \
            then This'MakeVisible(); return 0
        if IsSpooled = 0 \
            then return 0
    }

    This'MakeVisible()
    return 0
!
!
SetPageGutterVertical:
    enter Value, err=*proceed

    if Value < .25 \
        then Value = .25

    PageGutterVertical = Value
    return 0
!
!
SetPageGutterHorizontal:
    enter Value, err=*proceed

    if Value < .25 \
        then Value = .25

    PageGutterHorizontal = Value
    return 0
!
!
MoveView:
    enter (CenterX), (CenterY), err=*proceed

    if View > 0 or ZoomLevel = -2 then \
    {   This'DrawPages()
        return 1
    }
    if CenterX = 0 then CenterX = 0.000001
    if CenterY = 0 then CenterY = 0.000001
    This'ImageButtonsMarkDirty()
    This'ImageButtonsSetPageNumbers(Page)
    This'ImageButtonsSetSizeLocation(1, CenterX, CenterY)
    This'DrawPages()
    return 1
!
!
SetView: ! Sets the view mode
    enter Value%, CenterX, CenterY, err=*proceed

    if Value% < 0 or Value% > 3 \
        then Value% = 0

    if Report = 0 \
        then return 0

    if View = Value% then \
    {   This'ChangeMenu("VIEW"+str(View))
        return 0
    }

    View = Value%
    This'ImageButtonsMarkDirty()
    This'ImageButtonsSetPageNumbers(Page)

    if CenterX or CenterY \
        then This'ImageButtonsSetSizeLocation(1, CenterX, CenterY) \
        else This'ImageButtonsSetSizeLocation()

    This'ChangeMenu("VIEW"+str(View))
    This'DrawPages()

    return 1
!
!
SetZoom:
    enter Value%, CenterX, CenterY, err=*proceed
    if Value% < -2 or Value% > 400 \
        then return 41
    if Value% > -1 and Value% < 10 \
        then Value% = Zoom


    if Report = 0 or Page = 0 \
    {   if ZoomLevel < 0 then \
        {   This'ChangeMenu("ZOOM"+str(ZoomLevel))
        } else \
        {   LastZoomLevel = ZoomLevel
            This'ChangeMenu("ZOOM")
        }
        ZoomLevel = Value%
        return 0
    }

    ZoomLevel = Value%
    if ZoomLevel < 0 then \
    {   This'ChangeMenu("ZOOM"+str(ZoomLevel))
    } else \
    {   LastZoomLevel = ZoomLevel
        This'ChangeMenu("ZOOM")
    }

    if View > 0 \
    {   This'View(0, CenterX, CenterY)
        return 0
    }

    This'ImageButtonsMarkDirty()

    if ZoomLevel >= 0 \
        then This'ImageButtonsSetSizeLocation(1, CenterX, CenterY) \
        else This'ImageButtonsSetSizeLocation()
    This'DrawPages()
    return 0
!
!
ZoomIn: ! Makes things bigger
    enter CenterX, CenterY, err=*proceed
    if ZoomLevel = -1 or ZoomLevel = -2 or View > 0 then \
    {   if ZoomLevel = -1 or ZoomLevel = -2 \
            then ZoomLevel = CurrentZoom + 1;
                 goto ZoomInMore

        if ZoomLevel >= ZoomLevels[ZoomLevels] then \
        {   This'Zoom(ZoomLevels[ZoomLevels], CenterX, CenterY)
            return 0
        } else \
        {   This'Zoom(ZoomLevel, CenterX, CenterY)
            return 0
        }
    }

    ZoomInMore:
    if ZoomLevel >= ZoomLevels[ZoomLevels] then \
    {   ZoomLevel = ZoomLevels[ZoomLevels]
        return 0
    }

    for x = 1 to ZoomLevels
        if ZoomLevels[x] < ZoomLevel \
            then continue
        if ZoomLevels[x] > ZoomLevel \
            then break
    next x

    This'Zoom(ZoomLevels[x], CenterX, CenterY)
    return 0
!
!
ZoomOut: ! Makes things smaller
    enter CenterX, CenterY, err=*proceed
    if ZoomLevel = -1 or ZoomLevel = -2 or View > 0 then \
    {   if ZoomLevel = -1 or ZoomLevel = -2 \
            then ZoomLevel = LastZoomLevel
        if ZoomLevel <= ZoomLevels[1] then \
        {   This'Zoom(ZoomLevels[1], CenterX, CenterY)
            return 0
        } else \
        {   This'Zoom(ZoomLevel, CenterX, CenterY)
            return 0
        }
    }

    if ZoomLevel <= ZoomLevels[1] then \
    {   return 0
    }

    for x = ZoomLevels to 1 step -1
        if ZoomLevels[x] > ZoomLevel \
            then continue
        if ZoomLevels[x] < ZoomLevel \
            then break
    next x

    This'Zoom(ZoomLevels[x], CenterX, CenterY)
    return 0
!
!
ZoomCustom:
    vardropbox read VZoomCustom,value$,err=*proceed
    if report = 0 or len(value$) = 0 \
        then goto ZCInvalid

    x$ = ""
    for x = 1 to len(Value$)
        if Value$(x, 1) = TPercent$ \
            then break
        if Value$(x, 1) < "0" or Value$(x, 1) > "9" \
            then continue
        x$ += Value$(x, 1)
    next x
    status = 1
    x = int(num(x$, err=*proceed))
    if x < 10 or x > 400 then \
    {   status = 2
        goto ZCInvalid
    }
    vardropbox write VZoomCustom,str(x) + TPercent$,err=*proceed
    This'Zoom(x)
    return 0

    ZCInvalid:
    vardropbox write VZoomCustom,str(Zoom) + TPercent$,err=*proceed
    return status
!
!
JumpToPage:
    multiline read VJump,value$,err=*proceed
    if report = 0 or len(value$) = 0 \
        then goto JTPInvalid

    x$ = ""
    for x = 1 to len(Value$)
        if Value$(x, 1) < "0" or Value$(x, 1) > "9" \
            then continue
        x$ += Value$(x, 1)
    next x
    status = 1
    x = int(num(x$, err=*proceed))
    if x < 1 or x > Report'Pages then \
    {   status = 2
        goto JTPInvalid
    }
    multiline write VJump,str(x),err=*proceed
    This'GotoPage(x)
    return 0

    JTPInvalid:
    multiline write VJump,str(Page),err=*proceed
    return status
!
!
GotoPage: ! 0 = Sucess, Other = Error
    enter PageNum%
    if Report = 0 \
        then return 41
    p = Report'Pages
    if PageNum% < 1 \
        then PageNum% = 1
    if p = 0 \
        then InitialPage = PageNum%
    if PageNum% > p \
        then PageNum% = p
    if Page = PageNum% \
        then return 0

    Page = PageNum%
    This'ImageButtonsSetPageNumbers(PageNum%)
    This'ImageButtonsSetSizeLocation()
    This'DrawPages()
    return 0
!
!
FirstPage:
    This'GotoPage(1)
    return 0
!
!
LastPage:
    This'GotoPage(Report'Pages)
    return 0
!
!
NextPage:
    switch View
        case 0; x = 1; break
        case 1,2; x = 2; break
        case 3; x = 4; break
    esac

    This'GotoPage(Page + x)
    return 0
!
!
PreviousPage:
    switch View
        case 0; x = 1; break
        case 1,2; x = 2; break
        case 3; x = 4; break
    esac

    This'GotoPage(Page - x)
    return 0
!
!
RePaint:
    print 'goto'(BasePHnd),
    OrigColumns = Columns
    OrigRows = Rows
    This'GetWindowLocationAndSize()

    if Columns < 40 or Rows < 14 then \
    {   if Columns < 40 \
            then Columns = 40
        if Rows < 14 \
            then Rows = 14
        print 'size'(Columns + 1,Rows + 1),
        This'GetWindowLocationAndSize()
    }

    if RefreshScreen \
        then DoARefresh = 1

    if (Columns <> OrigColumns)  \
        or (Rows <> OrigRows) \
        or (SuppressStatusBar = StatusBar) \
        or (SuppressToolBar = ToolBar) \
        or (ForceRePaint) then \
    {   print 'cursor'(1),'-U',
        RefreshScreen = 0
        ForceRePaint = 0

        This'DrawToolBar()
        This'DrawStatusBar()
        This'DrawScrollBars()
        This'ChangeMenu(CurrentMenu$)
        if Report then \
        {
            if IsSpooled then \
                This'ChangeMenu("SPOOLED")
            if IsSpooling and IsSpooled = 0 then \
                This'ChangeMenu("SPOOLING")
            if IsSpooling = 0 and IsSpooled = 0 then \
                This'ChangeMenu("PAUSESPOOL")
        } else \
        {   This'ChangeMenu("SPOOLED")
        }
        This'ChangeMenu("VIEW"+str(View))
        This'CreateViewPort()
        if ZoomLevel < 0 \
            then This'ChangeMenu("ZOOM"+str(ZoomLevel)) \
            else This'ChangeMenu("ZOOM")
        if Report then \
        {   This'ImageButtonsMarkDirty()
            This'ImageButtonsSetSizeLocation()
            This'DrawPages()
        }

        if DoARefresh then \
        {   print '+U','cursor'(0),
            ReFreshScreen = 1
            DoARefresh = 0
        }

        !print 'goto'(BasePHnd),
        setfocus 0
    }

    wait 0
    return 1
!
!
ResetVerticalScrollBar:
    if Report = 0 \
        then return 0
    pagecount = Report'Pages
    if pagecount = 0 \
        then return 0

    switch View
        case 0 ! 1 Page View
            y = max(0, VisibleImage[1, 8] - (ViewRows - 1))
            if y = 0 then \
            {   ! Pages fit in window
                VScrollMax = pagecount, \
                VScrollCurPos = Page
            } else \
            {   ! Pages do NOT fit within the viewable window area
                VScrollMax = pagecount * 100
                PageLines = VisibleImage[1, 8], \
                LinesPerIncrement = PageLines / 100, \
                TopOfPageLocation = VisibleImage[1, 6], \
                BottomOfPageLocation = TopOfPageLocation + VisibleImage[1, 8], \
                VScrollCurPos = Page * 100 - 100 + 1 + int(((TopOfPageLocation * -1) / LinesPerIncrement))

                if TopOfPageLocation >= 0 \
                    then VScrollCurPos = Page * 100 - 100 + 1

                if BottomOfPageLocation <= ViewRows - 1 \
                    then VScrollCurPos = Page * 100
            }
            break

        case 1,2 ! 2 Page Views
            VScrollMax = pagecount / 2
            if fpt(VScrollMax) > 0 \
                then VScrollMax = int(VScrollMax) + 1
            if View = 2 and pagecount | 2 = 0 \
                then VScrollMax += 1
            break

        case 3 ! 4 Page View
            VScrollMax = pagecount / 4
            if fpt(VScrollMax) > 0 \
                then VScrollMax = int(VScrollMax) + 1
            break
    esac

    vscrollbar write BVScroll, VScrollCurPos, VScrollMax, err=*proceed
    return 0
!
!
RefreshPages:
    enter (JustPage), err=*proceed

    RefreshScreen = 0
    print '-U',
    for x = 1 to ImageBuffers
        if JustPage and ImageBuffer[x, 1] <> JustPage \
            then continue
        ImageBuffer[x, 8]=0
    next x

    RefreshScreen = 1
    print '+U',
    return 0
!
!
! Use this to get an image buffer for a page.
! Retrieves a buffer number, and notifies lets the page in the report know what buffer it is in
! Also sets up the buffer for the new page. However it does not render the image to the channel
! function local ImageBufferGet(PageNumber%)    ImageBufferGet
!  LastAssignedBuffer
ImageBufferGet:
    enter PageNum%

    ! first, see if the pagenumber is already buffered
    for x = 1 to ImageBuffers;
        if ImageBuffer[x, 1] = PageNum% \
            then break \
        fi;
    next x;
    if x <= ImageBuffers \
        then return x

    ! Clear a buffer that is not being used and return it
    for y = 1 + LastAssignedBuffer to ImageBuffers + LastAssignedBuffer;
        x = y;
        if x > ImageBuffers \
            then x-=ImageBuffers \
        fi;
        if ImageBuffer[x, 7] = 0 \
            then break \
        fi;
    next y;

    tmp=Report'Page(PageNum%)
    newwidth = tmp'PaperWidth, \
    newlength = tmp'PaperLength, \
    neworientation = tmp'Orientation, \
    newdpi = DPIScreen, \
    newmarginleft = tmp'MarginLeft, \
    newmarginright = tmp'MarginRight, \
    newmargintop = tmp'MarginTop, \
    newmarginbot = tmp'MarginBottom, \
    oldpage = ImageBuffer[x, 1], \
    oldchannel = ImageBuffer[x, 2], \
    oldwidth = ImageBuffer[x, 3], \
    oldlength = ImageBuffer[x, 4], \
    oldorientation = ImageBuffer[x, 5], \
    olddip = ImageBuffer[x, 6], \
    oldwdxchannel = ImageBuffer[x, 9], \
    oldmarginleft = ImageBuffer[x, 10], \
    oldmarginright = ImageBuffer[x, 11], \
    oldmargintop = ImageBuffer[x, 12], \
    oldmarginbot = ImageBuffer[x, 13]
    ImageBuffer[x, 1] = PageNum%

    if oldchannel and (newwidth <> oldwidth or newlength <> oldlength \
       or neworientation <> oldorientation or newdpi <> olddip \
       or newmarginleft <> oldmarginleft or newmarginright <> oldmarginright \
       or newmargintop <> oldmargintop or newmarginbot <> oldmarginbot ) \
        then close(oldchannel);
             oldchannel = 0

    if oldchannel = 0 \
        then oldchannel=hfn;
                o$ = "DPI="+str(newdpi)+ \
                ";Length="+str(newlength)+ \
                ";Width="+str(newwidth)+ \
                ";FORCE6X10=Yes" + \
                ";Margins="+str(newmarginleft)+":"+str(newmargintop)+":"+ \
                            str(newmarginright)+":"+str(newmarginbot);
             open(oldchannel,opt=o$,err=IMGCreateError)IsWindX$+"*BITMAP*";
             if IsWindX \
                then call "[wdx]*windx.utl;get_num","LFO",oldwdxchannel \
                else oldwdxchannel = oldchannel

    ImageBuffer[x, 2] = oldchannel, \
    ImageBuffer[x, 3] = newwidth, \
    ImageBuffer[x, 4] = newlength, \
    ImageBuffer[x, 5] = neworientation, \
    ImageBuffer[x, 6] = newdpi, \
    ImageBuffer[x, 8] = 0, \
    ImageBuffer[x, 9] = oldwdxchannel, \
    ImageBuffer[x, 10] = newmarginleft, \
    ImageBuffer[x, 11] = newmarginright, \
    ImageBuffer[x, 12] = newmargintop, \
    ImageBuffer[x, 13] = newmarginbot
    LastAssignedBuffer = x
    return x

    IMGCreateError:
    if newdpi > 120 then \
    {   newdpi -= 100
        if newdpi < 120 \
            then newdpi = 120
        retry
    }
    return x

!
!
! Use this only when starting a new report
! function local ImageButtonsClear()    ImageButtonsClear
ImageButtonsClear:
    for x = 1 to VisibleImages
        image = VisibleImage[x, 3]
        if image \
            then ImageBuffer[image, 7] = 0 ! Set image buffer to not in use

        for i = 2 to 9;
            VisibleImage[x, i] = 0;
        next i

        c = VisibleImage[x, 1], \
        b = VisibleImage[x, 10], \
        s = VisibleImage[x, 11], \
        s'Visible = 0, \
        b'Visible = 0, \
        c'Visible = 0
        c'col = 0, \
        c'line = 0, \
        c'cols = 0, \
        c'lines = 0, \
        c'text$ = ""
    next x
    for x = 1 to ImageBuffers
        if ImageBuffer[x, 2] > 0 \
            then close(ImageBuffer[x,2],err=*proceed)
        for i = 1 to ImageBufferItems;
            ImageBuffer[x, i] = 0;
        next i
    next x
    return 0
!
!
! Use this when you want to mark all Image Buttons as needing a resize
! Such as when a Zoom changes
! function local ImageButtonsMarkDirty()    ImageButtonsMarkDirty
ImageButtonsMarkDirty:
    for x = 1 to VisibleImages;
        if VisibleImage[x, 2] > 0 \
            then VisibleImage[x, 4] = 0 \
        fi;
    next x;
    return 0
!
!
! Use this when switching from one page to another
! Using View 0, Visible Page at index 1
! Using View 1,2 or 3, Visibles pages start at index 1 for 2 or 4 pages depending on view
! function local ImageButtonsSetPageNumbers(PageNumber%)    ImageButtonsSetPageNumbers
ImageButtonsSetPageNumbers:
    enter PageNum%

    pagecount = Report'Pages

    if PageNum% <= 0 \
        then PageNum% = 1

    odd = PageNum% | 2
    if View = 1 and not(odd) \
        then adjust = - 1
    if view = 2 and odd \
        then adjust = - 1
    if View = 3 \
        then adjust = -1 * (tbl(PageNum%|4,4,1,2,3) - 1)

    switch View
        case 0; vi=1; break
        case 1; vi=2; break
        case 2; vi=2; break
        case 3; vi=4; break
    esac

    ! Mark all image buffers as not in use
    for x = 1 to ImageBuffers;
        ImageBuffer[x, 7]=0;
    next x

    ViewComplete = 1

    for x = 1 to vi
        newpage = PageNum% + x - 1 + adjust, \
        oldpage = VisibleImage[x, 2], \
        oldimage = VisibleImage[x, 3]

        if newpage < 1 or newpage > pagecount then \
        {   if oldpage then \
            {   for y = 2 to 9;
                    VisibleImage[x, y] = 0;
                next y
            }
            ViewComplete = 0
            continue
        }

        ! if this button already contains this page then leave it alone, but mark it as in use.
        if newpage = oldpage \
            then ImageBuffer[oldimage, 7] = 1;
                 continue

        ! Set this button to this page, clear values and mark as dirty sizing
        VisibleImage[x, 2] = newpage;
        for y = 4 to 9;
            VisibleImage[x, y] = 0;
        next y

        VisibleImage[x, 3] = This'ImageBufferGet(newpage), \
        ImageBuffer[VisibleImage[x, 3], 7] = 1 ! set Image to be in use

    next x

    return 0
!
! Use this when the size or locations of a page must change
! like when zoom changes
! Only does calcs on VisibleImages which are marked as dirty
! Size is based on View and Zoom
! View=1 or 2, always fit to window, zoom to fit, work on VisibleImages in groups of 2
! View=3, always fit to window, zoom to fit, work on VisibleImages in groups of 4
! View=0, based on zoom, fit to width, fit to window
!         dirty Images or not, based on location of Visibleimage 1
! function local ImageButtonsSetSizeLocation()  ImageButtonsSetSizeLocation
ImageButtonsSetSizeLocation:
    IsZoomOp = 0
    enter IsZoomOp, CenterX, CenterY, err=*proceed

    pagecount = Report'Pages

    switch View
        case 0 ! 1 Page View
            if VisibleImage[1, 4] = 0 \
                then This'Size1WayView(IsZoomOp, CenterX, CenterY)
            CurrentZoom = Zoom

            HScrollMax = max(0, VisibleImage[1, 7] - (ViewColumns - 1)), \
            HScrollMax = int(HScrollMax * 100) + 1
            y = max(0, VisibleImage[1, 8] - (ViewRows - 1))
            if y = 0 then \
            {   ! Pages fit in window
                VScrollSmallJump = 1, \
                VScrollBigJump = 1, \
                VScrollMax = pagecount, \
                VScrollCurPos = Page

            } else \
            {   ! Pages do NOT fit within the viewable window area
                VScrollLastPos = VScrollCurPos, \
                VScrollLastMax = VScrollMax, \
                VScrollSmallJump = VScrollSmallSize, \
                VScrollBigJump = min(99, int((ViewRows - 1) / VisibleImage[1, 8] * 100)), \
                VScrollMax = pagecount * 100, \
                VScrollCurPos = Page * 100 - 100 + 1

                if IsZoomOp then \
                {   PageLines = VisibleImage[1, 8], \
                    LinesPerIncrement = PageLines / 100, \
                    TopOfPageLocation = VisibleImage[1, 6], \
                    BottomOfPageLocation = TopOfPageLocation + VisibleImage[1, 8], \
                    VScrollCurPos = Page * 100 - 100 + 1 + int(((TopOfPageLocation * -1) / LinesPerIncrement))

                    if TopOfPageLocation >= 0 \
                        then VScrollCurPos = Page * 100 - 100 + 1

                    if BottomOfPageLocation <= ViewRows - 1 \
                        then VScrollCurPos = Page * 100
                }
            }

            if HScrollMax > 1 then \
            {   if IsZoomOp then \
                {   HScrollCurPos = int(0 - VisibleImage[1, 5] * 100), \
                    HScrollLastPos = HScrollCurPos, \
                    HScrollLastMax = HScrollMax
                } else \
                {   if HScrollLastMax > 1 \
                        then percent = HScrollLastPos / HScrollLastMax, \
                             HScrollCurPos = max(1, int(HScrollMax * percent))
                    HScrollLastPos = HScrollCurPos, \
                    HScrollLastMax = HScrollMax, \
                    VisibleImage[1, 5] = 0 - ((HScrollCurPos - 1) / 100)
                }
            }


            if HScrollMax = 1 \
                then HScrollCurPos = 1

            break

        case 1,2 ! 2 Page Views
            HScrollCurPos = 1, \
            HScrollMax = 1, \
            VScrollSmallJump = 1, \
            VScrollBigJump = 1, \
            VScrollMax = pagecount / 2
            if fpt(VScrollMax) > 0 \
                then VScrollMax = int(VScrollMax) + 1
            if View = 2 and pagecount | 2 = 0 \
                then VScrollMax += 1

            if VisibleImage[1, 4] = 0 or \
               VisibleImage[2, 4] = 0 or \
                then This'Size2WayViewToWin()
            CurrentZoom = Zoom

            VScrollCurPos = Page / 2
            if fpt(VScrollCurPos) > 0 \
                then VScrollCurPos = int(VScrollCurPos) + 1
            if View = 2 and Page | 2 = 0 \
                then VScrollCurPos += 1
            break

        case 3 ! 4 Page View
            HScrollCurPos = 1, \
            HScrollMax = 1, \
            VScrollSmallJump = 1, \
            VScrollBigJump = 1, \
            VScrollMax = pagecount / 4
            if fpt(VScrollMax) > 0 \
                then VScrollMax = int(VScrollMax) + 1

            if VisibleImage[1, 4] = 0 or \
               VisibleImage[2, 4] = 0 or \
               VisibleImage[3, 4] = 0 or \
               VisibleImage[4, 4] = 0 or \
                then This'Size4WayViewToWin()
            CurrentZoom = Zoom

            VScrollCurPos = Page / 4
            if fpt(VScrollCurPos) > 0 \
                then VScrollCurPos = int(VScrollCurPos) + 1
            break
    esac

    if HScrollMax > 1 \
        then HScrollSmallJump = HScrollSmallSize, \
             HScrollBigJump = min(int((ViewColumns - 1) * 100), HScrollMax) \
        else HScrollSmallJump = 1, \
             HScrollBigJump = 1
    }
    hscrollbar write BHScroll, HScrollCurPos, HScrollMax, err=*proceed
    vscrollbar write BVScroll, VScrollCurPos, VScrollMax, err=*proceed
    return 0
!
!
Size1WayView:
    enter IsZoomOp, CenterX, CenterY

    if VisibleImage[1, 3] = 0 \
        then return 0

    origx = VisibleImage[1, 5], \
    origy = VisibleImage[1, 6], \
    origw = VisibleImage[1, 7], \
    origh = VisibleImage[1, 8]

    if origw = 0 and origh = 0 \
        then IsZoomOp = 0

    w = ImageBuffer[VisibleImage[1, 3], 3] * 120 / ColGUs, \
    h = ImageBuffer[VisibleImage[1, 3], 4] * 120 / RowGUs

    switch ZoomLevel
        case -1 ! Fit Page Width to Window Width
            z = (ViewColumns - 1 - .4) / w
            break

        case -2 ! Fit whole page in window
            z = min((ViewColumns - 1 - .4) / w, (ViewRows - 1) / h), \
            IsZoomOp = 0;
            break

        default
            z = ZoomLevel / 100;
            break
    esac

    w = prc(w * z, 3), \
    h = prc(h * z, 3), \
    Zoom = int(z * 100), \
    offx = 0, \
    offy = 0

    if IsZoomOp then \
    {
        if origh and h > ViewRows - 1 \
            then if CenterY = 0 \
                     then origph = ((ViewRows - 1) / 2 - origy) / origh \
                     else origph = CenterY \
            else origph = .50

        if origw and w > ViewColumns - 1 \
            then if CenterX = 0 \
                     then origpw = ((ViewColumns - 1) / 2 - origx) / origw \
                     else origpw = CenterX \
                 else origpw = .50

        offx = ((ViewColumns - 1) / 2) - (w * origpw), \
        offy = ((ViewRows - 1) / 2) - (h * origph)

        if offx > 0 then offx = 0
        if offy > 0 then offy = 0

        if w > ViewColumns - 1 and offx + w < ViewColumns - 1 \
            then offx = ViewColumns - 1 - w

        if h > ViewRows - 1 and offy + h < ViewRows - 1 \
            then offy = ViewRows - 1 - h
    }

    ! Deal with the X location - Center in Screen if it does not fill the width of the viewing area
    if w < ViewColumns \
        then offx = prc((ViewColumns - 1 - w) / 2, 2)

    ! Deal with the Y location - Center in Screen if it does not fill the height of the viewing area
    if h < ViewRows \
        then offy = prc((ViewRows - 1 - h) / 2, 2)

    VisibleImage[1, 4] = 1, \
    VisibleImage[1, 5] = offx, \
    VisibleImage[1, 6] = offy, \
    VisibleImage[1, 7] = w, \
    VisibleImage[1, 8] = h

    return 0
!
!
Size2WayViewToWin:
    dim w[1:2], h[1:2]

    if VisibleImage[1, 3] \
        then w[1] = ImageBuffer[VisibleImage[1, 3], 3] * 120 / ColGUs, \
             h[1] = ImageBuffer[VisibleImage[1, 3], 4] * 120 / RowGUs, \
             tp += 1

    if VisibleImage[2, 3] \
        then w[2] = ImageBuffer[VisibleImage[2, 3], 3] * 120 / ColGUs, \
             h[2] = ImageBuffer[VisibleImage[2, 3], 4] * 120 / RowGUs, \
             tp += 1

    if tp = 0 \
        then return 0

    if w[1] = 0 then w[1] = w[2]
    if w[2] = 0 then w[2] = w[1]

    if h[1] = 0 then h[1] = h[2]
    if h[2] = 0 then h[2] = h[1]

    w = w[1] + w[2], \
    h = max(h[1], h[2])

    if w = 0 or h = 0 \
        then return 0

    z1 = (ViewColumns - 1 - .4 - PageGutterHorizontal) / w, \
    z2 = (ViewRows - 1 - .4 - PageGutterVertical) / h, \
    z = min(z1, z2), \
    Zoom = int(z * 100)

    offx = (ViewColumns - 1 - .4 - w * z) / 2, \
    offy = (ViewRows - 1 - .4 - h * z) / 2, \
    gutv = PageGutterHorizontal / 2, \
    guth = PageGutterVertical / 2, \
    x = 0, \
    y = 0

    if VisibleImage[1, 3] \
        then VisibleImage[1, 4] = 1, \
             VisibleImage[1, 5] = offx - gutv, \
             VisibleImage[1, 6] = offy + (max(h[1],h[2]) - h[1]) * z / 2, \
             VisibleImage[1, 7] = w[1] * z, \
             VisibleImage[1, 8] = h[1] * z

    if VisibleImage[2, 3] \
        then VisibleImage[2, 4] = 1, \
             VisibleImage[2, 5] = offx + w[1] * z + gutv, \
             VisibleImage[2, 6] = offy + (max(h[1],h[2]) - h[2]) * z / 2, \
             VisibleImage[2, 7] = w[2] * z, \
             VisibleImage[2, 8] = h[2] * z

    return 0
!
!
Size4WayViewToWin:
    dim w[1:4], h[1:4]

    if VisibleImage[1, 3] \
        then w[1] = ImageBuffer[VisibleImage[1, 3], 3] * 120 / ColGUs, \
             h[1] = ImageBuffer[VisibleImage[1, 3], 4] * 120 / RowGUs, \
             tp += 1

    if VisibleImage[2, 3] \
        then w[2] = ImageBuffer[VisibleImage[2, 3], 3] * 120 / ColGUs, \
             h[2] = ImageBuffer[VisibleImage[2, 3], 4] * 120 / RowGUs, \
             tp += 1

    if VisibleImage[3, 3] \
        then w[3] = ImageBuffer[VisibleImage[3, 3], 3] * 120 / ColGUs, \
             h[3] = ImageBuffer[VisibleImage[3, 3], 4] * 120 / RowGUs, \
             tp += 1

    if VisibleImage[4, 3] \
        then w[4] = ImageBuffer[VisibleImage[4, 3], 3] * 120 / ColGUs, \
             h[4] = ImageBuffer[VisibleImage[4, 3], 4] * 120 / RowGUs, \
             tp += 1

    if tp = 0 \
        then return 0

    if w[1] = 0 then w[1] = w[3]
    if w[1] = 0 then w[1] = max(w[2], w[3], w[4])
    if w[2] = 0 then w[2] = w[4]
    if w[2] = 0 then w[2] = max(w[1], w[3], w[4])
    if w[3] = 0 then w[3] = w[1]
    if w[3] = 0 then w[3] = max(w[1], w[2], w[4])
    if w[4] = 0 then w[4] = w[2]
    if w[4] = 0 then w[4] = max(w[1], w[2], w[3])

    if h[1] = 0 then h[1] = h[2]
    if h[1] = 0 then h[1] = max(h[2], h[3], h[4])
    if h[2] = 0 then h[2] = h[1]
    if h[2] = 0 then h[2] = max(h[1], h[3], h[4])
    if h[3] = 0 then h[3] = h[4]
    if h[3] = 0 then h[3] = max(h[1], h[2], h[4])
    if h[4] = 0 then h[4] = h[3]
    if h[4] = 0 then h[4] = max(h[1], h[2], h[3])

    w = max(w[1], w[3]) + max(w[2], w[4]), \
    h = max(h[1], h[2]) + max(h[3], h[4])

    if w = 0 or h = 0 \
        then return 0

    z1 = (ViewColumns - 1 - .4 - PageGutterHorizontal) / w, \
    z2 = (ViewRows - 1 - .4 - PageGutterVertical) / h, \
    z = min(z1, z2), \
    Zoom = int(z * 100)

    offx = (ViewColumns - 1 - .4 - w * z) / 2, \
    offy = (ViewRows - 1 - .4 - h * z) / 2, \
    gutv = PageGutterHorizontal / 2, \
    guth = PageGutterVertical / 2, \
    x = 0, \
    y = 0

    if VisibleImage[1, 3] \
        then VisibleImage[1, 4] = 1, \
             VisibleImage[1, 5] = offx + (max(w[1],w[3]) - w[1]) * z / 2 - gutv, \
             VisibleImage[1, 6] = offy + (max(h[1],h[2]) - h[1]) * z / 2 - guth, \
             VisibleImage[1, 7] = w[1] * z, \
             VisibleImage[1, 8] = h[1] * z

    if VisibleImage[2, 3] \
        then VisibleImage[2, 4] = 1, \
             VisibleImage[2, 5] = offx + (w * z) - (max(w[2],w[4]) - w[2]) * z / 2 - (w[2] * z) + gutv, \
             VisibleImage[2, 6] = offy + (max(h[1],h[2]) - h[2]) * z / 2 - guth, \
             VisibleImage[2, 7] = w[2] * z, \
             VisibleImage[2, 8] = h[2] * z

    if VisibleImage[3, 3] \
        then VisibleImage[3, 4] = 1, \
             VisibleImage[3, 5] = offx + (max(w[1],w[3]) - w[3]) * z / 2 - gutv, \
             VisibleImage[3, 6] = offy + (h * z) - (max(h[3],h[4]) - h[3]) * z / 2 - (h[3] * z) + guth, \
             VisibleImage[3, 7] = w[3] * z, \
             VisibleImage[3, 8] = h[3] * z

    if VisibleImage[4, 3] \
        then VisibleImage[4, 4] = 1, \
             VisibleImage[4, 5] = offx + (w * z) - (max(w[2],w[4]) - w[4]) * z / 2 - (w[4] * z) + gutv, \
             VisibleImage[4, 6] = offy + (h * z) - (max(h[3],h[4]) - h[4]) * z / 2 - (h[4] * z) + guth, \
             VisibleImage[4, 7] = w[4] * z, \
             VisibleImage[4, 8] = h[4] * z

    return 0
!
!
!
!
! ImageBuffer Array. ImageBuffer[ 1:10, 1:8 ].
! Index 1 = Page Number
! Index 2 = *BITMAP* Channel to Button Image
! Index 3 = PaperWidth
! Index 4 = PaperLength
! Index 5 = PaperOrientation 0=Portrait 1=Landscape
! Index 6 = DPI (typically for the screen)
! Index 7 = Buffer in use 0|1
! Index 8 = Image has been rendered 0|1
! Index 9 - WindX's Channel number for the *BITMAP* file in index 2 (if applicable)
!
! VisibleImage Array. VisibleImage[ 1:4, 1:8]   [ primary, index ]
! Primary, 1:4 (4 buttons).
! Layout = 1 page, primary = 1 only
! Layout = 2 pages, primary = 1 and 2 only
! Layout = 4 pages, primary = 1,2,3 and 4
!
! Index 1 = Button ctl
! Index 2 = PageNum
! Index 3 = ImageBuffer Index
! Index 4 = Location and Size are Dirty.  Dirty=0, OK=1
! Index 5 = Column
! Index 6 = Line
! Index 7 = Columns
! Index 8 = Lines
! Index 9 = Button Content is Current 0|1
! Index 10 = Border Button ctl
! Index 11 = Shadow Button ctl
!
!
DrawPages:
    VisiblePages$ = ","
    if RenderErrorOnPages$ = "" \
        then RenderErrorOnPages$ = ","

    shadow = 2
    if Zoom > 20 then shadow+=1
    if Zoom > 50 then shadow+=1
    if Zoom > 100 then shadow+=1
    if Zoom > 200 then shadow+=1

    for x = 1 to VisibleImages
        c = VisibleImage[x, 1], \
        b = VisibleImage[x, 10], \
        s = VisibleImage[x, 11]

        if VisibleImage[x, 2] = 0 \
            then s'Visible = 0, \
                 b'Visible = 0, \
                 c'Visible = 0;
                 continue

        if (View = 0 and x = 1) or \
           (View = 1 and x >= 1 and x <= 2) or \
           (View = 2 and x >= 1 and x <= 2) or \
           (View = 3 and x >= 1) then \
        {   print '-U',
            s'Visible=0, b'visible=0

            c'_PropList$="text,col,line,cols,lines"
            c'_PropValues$="" + sep + \
                           str(VisibleImage[x, 5] + .2) + sep + \
                           str(VisibleImage[x, 6] + .24) + sep + \
                           str(VisibleImage[x, 7])+ sep + \
                           str(VisibleImage[x, 8])

            c'_PropList$="left,top,width,height"
            read data from c'_PropValues$ to l,t,w,h

            b'_PropList$="left,top,width,height"
            b'_PropValues$=str(l - 1) + sep + \
                           str(t - 1) + sep + \
                           str(w + 2) + sep + \
                           str(h + 2)

            s'_PropList$="left,top,cols,lines"
            s'_PropValues$=str(l + shadow) + sep + \
                           str(t + shadow) + sep + \
                           str(VisibleImage[x, 7]) + sep + \
                           str(VisibleImage[x, 8])

            i = VisibleImage[x, 3], \
            p = VisibleImage[x, 2]

            if i and p then \
            {   ch = ImageBuffer[i, 2]
                if ImageBuffer[i, 8] = 0 then \
                {   Report'Page = p
                    o = Report'Page(p)
                    print(ch,err=*proceed),'ff',
                    if not(SuppressWaterMarks = 1 or Report'SuppressWaterMarks = 1) then \
                    {   if (p = 1 and WaterMarkPages = 1) or \
                           (p > 0 and WaterMarkPages = 2) then \
                        {   WaterMark'RenderWaterMark(ch, p, o'PaperWidth, o'PaperLength, DPIScreen, \
                                                            o'MarginLeft, o'MarginTop, \
                                                            o'MarginRight, o'MarginBottom )
                        }
                    }
                    Result = Report'RenderPage(ch)

                    if Result then \
                    {   r = pos(","+str(p)+"," = RenderErrorOnPages$, 1)
                        if r = 0 \
                            then RenderErrorOnPages$ += str(p) + ","
                    }
                    ImageBuffer[i, 8] = 1, \
                    VisibleImage[x, 9] = 0
                }
            }
            c'text$ = "{#"+str(ImageBuffer[VisibleImage[x, 3], 9])+"}", \
            VisibleImage[x, 9] = 1, \
            VisiblePages$ += str(VisibleImage[x, 2]) + ","

            c'Visible = 1, \
            b'Visible = 1, \
            s'Visible = 1

        } else \
        {   s'Visible = 0, \
            b'Visible = 0, \
            c'Visible = 0
        }

    next x

    if Report and len(VisiblePages$) > 1 then \
    {   This'SetNumPages()
        Zoom = CurrentZoom
    }

    multiline write VJump,str(Page),err=*proceed
    vardropbox write VZoomCustom,str(CurrentZoom) + TPercent$, err=*proceed

    if RefreshScreen \
        then print '+U',

    return 0
!
!
DialogueGotoPageCreate:
    if Report = 0 \
        then return

    if pos(bin(GotoPHnd,1) = CurrentWindowList$, 1) \
        then print 'goto'(GotoPHnd),; return

    GotoPHnd = hwn(0)
    CurrentWindowList$ += bin(GotoPHnd,1)
    w = 22
    h = 5
    xcol = max(int((Columns - w) / 2),3) + This'Column + 1
    ycol = max(int((Rows - h) / 2),2) + This'Row + 1
    print 'dialog'(-16000,-16000,w,h,GotoPHnd,msg("TGotoPage"),'B?'+'df'+'cs',opt="c&M"),'sr',
    print (0,err=*proceed) 'option'("FONT","FixedSys,-9"), \
                           'option'("STDFONT","FixedSys, -9"), \
                           'option'("GRAPHICFONT","*GuiFont"), \
                           'option'("WDWICON",Icon32$), \
                           'option'("WDWICON",Icon16$),
    menubar remove
    defctl window EQuit = DGotoQuit
    defctl window TabKey = DGotoTabKey
    defctl window BackTabKey = DGotoBackTabKey
    defctl window $1B$ = DGotoQuit
    defctl window LeftMouseDown = -1000
    defctl window LeftMouseUp = -1000
    defctl window RightMouseDown = -1000
    defctl window RightMouseUp = -1000
    tw = txw(objs$[cntls[DGotoJump], 1], 0, fnt="*GUIFont") / 16
    x = (22 - tw - 1.5 - 6.2) / 2
    print 'text'(@x(x),@y(.8),objs$[cntls[DGotoJump], 1],"&"),
    multiline DGotoJump,@(x + tw, .8, 6.2, 1),opt="RT",len=5,fnt="*GUIFont"
    DGotoJump'Key$ = objs$[cntls[DGotoJump], 2]
    multiline write DGotoJump,str(Page)
    button DGotoOK,@(1.6, 2.7, 9, 1.5)=msg("BOK"),fnt="*GUIFont",opt="*"
    button DGotoCancel,@(11.5, 2.7, 9, 1.5)=msg("BCancel"),fnt="*GUIFont"
    DGotoFocus = DGotoJump
    setfocus DGotoJump

    print 'move'(xcol,ycol),
    return 0
!
!
DialogueGotoPageDestroy:
    if GotoPHnd = 0 \
        then return 0

    CurrentWindowList$ = sub(CurrentWindowList$, bin(GotoPHnd,1), "")
    print 'drop'(GotoPHnd),
    GotoPHnd = 0
    return 1
!
!
DialogueZoomCreate:
    if Report = 0 \
        then return 0

    if pos(bin(ZoomPHnd,1) = CurrentWindowList$, 1) \
        then print 'goto'(ZoomPHnd),; return

    ZoomPHnd = hwn(0)
    CurrentWindowList$ += bin(ZoomPHnd,1)
    w = 22
    h = 5
    xcol = max(int((Columns - w) / 2),3) + This'Column + 1
    ycol = max(int((Rows - h) / 2),2) + This'Row + 1
    print 'dialog'(-16000,-16000,w,h,ZoomPHnd,msg("TSelectZoomLevel"),'B?'+'df'+'cs',opt="c&M"),'sr',
    print (0,err=*proceed) 'option'("FONT","FixedSys,-9"), \
                           'option'("STDFONT","FixedSys, -9"), \
                           'option'("GRAPHICFONT","*GuiFont"), \
                           'option'("WDWICON",Icon32$), \
                           'option'("WDWICON",Icon16$),
    menubar remove
    defctl window EQuit = DZoomQuit
    defctl window TabKey = DZoomTabKey
    defctl window BackTabKey = DZoomBackTabKey
    defctl window $1B$ = DZoomQuit
    defctl window LeftMouseDown = -1000
    defctl window LeftMouseUp = -1000
    defctl window RightMouseDown = -1000
    defctl window RightMouseUp = -1000

    tw = txw(objs$[cntls[DZoomCustom], 1], 0, fnt="*GUIFont") / 16
    x = (22 - tw - 1.5 - 6.6) / 2
    print 'text'(@x(x),@y(.8),objs$[cntls[DZoomCustom], 1],"&"),
    vardropbox DZoomCustom,@(x + tw, .8, 6.6, 7),opt="T",fnt="*GUIFont"
    vardropbox load DZoomCustom,VZoomLevels$, err=*proceed
    DZoomCustom'Key$ = objs$[cntls[DZoomCustom], 2]
    vardropbox write DZoomCustom,str(Zoom) + TPercent$,err=*proceed

    button DZoomOK,@(1.6, 2.7, 9, 1.5)=msg("BOK"),fnt="*GUIFont",opt="*"
    button DZoomCancel,@(11.5, 2.7, 9, 1.5)=msg("BCancel"),fnt="*GUIFont"
    DZoomFocus = DZoomCustom
    setfocus DZoomCustom

    print 'move'(xcol,ycol),
    return 0
!
!
DialogueZoomDestroy:
    if ZoomPHnd = 0 \
        then return 0

    CurrentWindowList$ = sub(CurrentWindowList$, bin(ZoomPHnd,1), "")
    print 'drop'(ZoomPHnd),
    ZoomPHnd = 0
    return 1
!
!
DialogueBannerInfoCreate:
    if Report = 0 or SuppressBannerInfo = 1 \
        then return 0

    if pos(bin(BannerPHnd,1) = CurrentWindowList$, 1) \
        then print 'goto'(BannerPHnd),; return

    BannerPHnd = hwn(0)
    CurrentWindowList$ += bin(BannerPHnd,1)

    w = 62
    h = 22
    xcol = max(int((Columns - w) / 2),3) + This'Column + 1
    ycol = max(int((Rows - h) / 2),2) + This'Row + 1
    print 'dialog'(-16000,-16000,w,h,BannerPHnd,msg("TBannerInfo"),'B?'+'df'+'cs',opt="c&M"),'sr',
    print (0,err=*proceed) 'option'("FONT","FixedSys,-9"), \
                           'option'("STDFONT","FixedSys, -9"), \
                           'option'("GRAPHICFONT","*GuiFont"), \
                           'option'("WDWICON",Icon32$), \
                           'option'("WDWICON",Icon16$),
    menubar remove
    defctl window EQuit = DBannerQuit
    defctl window TabKey = DBannerTabKey
    defctl window BackTabKey = DBannerBackTabKey
    defctl window $1B$ = DBannerQuit
    defctl window $0D$ = DBannerQuit
    defctl window LeftMouseDown = -1000
    defctl window LeftMouseUp = -1000
    defctl window RightMouseDown = -1000
    defctl window RightMouseUp = -1000

    grid DBannerInfo,@(2,1,58.4,17.8),fnt="*GUIFont"
    DBannerInfo'Key$ = objs$[cntls[DBannerInfo], 2]
    DBannerInfo'ColumnsWide = 2
    InfoCount = Report'GetInfo()
    DBannerInfo'RowsHigh = InfoCount + 2

    DBannerInfo'Row = -1
    DBannerInfo'Column = 1
    DBannerInfo'Value$ = msg("TProperty")
    DBannerInfo'Column = 2
    DBannerInfo'Value$ = msg("TValue")

    DBannerInfo'Column = 0
    DBannerInfo'Row = 0
    DBannerInfo'Resizable = 0
    DBannerInfo'Lock = 1
    DBannerInfo'BackColour$ = "White"
    DBannerInfo'RowHiLight = 1
    DBannerInfo'SwapEnabled = 0
    DBannerInfo'EnterMode = 1

    DBannerInfo'Row = 0
    DBannerInfo'Column = -1
    DBannerInfo'ColumnWidth = 0
    DBannerInfo'Column = 1
    DBannerInfo'ColumnWidth = 16.37
    DBannerInfo'Column = 2
    DBannerInfo'ColumnWidth = 40

    na$ = msg("Tna")

    grid load DBannerInfo, 1, 1, msg("TTitle") + sep + tbl(Report'Title$ = "", Report'Title$, na$) + sep
    grid load DBannerInfo, 1, 2, msg("TFilename") + sep + tbl(Report'Filename$ = "", Report'Filename$, na$) + sep

    for r = 1 to InfoCount
        Report'GetInfo(r, n$, v$)
        if n$ = "" \
            then continue
        if v$ = "" \
            then v$ = na$
        grid load DBannerInfo, 1, r + 2, n$ + sep + v$ + sep
    next r

    button DBannerOK,@(51.2, 19.7, 9, 1.5)=msg("BOK"),fnt="*GUIFont",opt="*"
    DBannerFocus = DBannerInfo
    setfocus DBannerFocus
    print 'move'(xcol,ycol),
    return 0
!
!
DialogueBannerInfoDestroy:
    if BannerPHnd = 0 \
        then return 0

    CurrentWindowList$ = sub(CurrentWindowList$, bin(BannerPHnd,1), "")
    print 'drop'(BannerPHnd),
    BannerPHnd = 0
    return 1
!
!
DialogueAboutCreate:
    if pos(bin(AboutPHnd,1) = CurrentWindowList$, 1) \
        then print 'goto'(AboutPHnd),; return

    AboutPHnd = hwn(0)
    CurrentWindowList$ += bin(AboutPHnd,1)

    w = 55
    h = 1
    call IsWindX$ + "*picture;get_size", err=DialogueAboutNoPicture, SplashImage$, w, h

    w = int(w)
    h = int(h)

    DialogueAboutNoPicture:
    h += 3
    xcol = max(int((Columns - w) / 2),3) + This'Column + 1
    ycol = max(int((Rows - h) / 2),2) + This'Row + 1
    print 'image'("AboutBox"),
    print 'dialog'(-16000,-16000,w,h,AboutPHnd,msg("TAbout"),'B?'+'df'+'cs',opt="hc&M"),'sr',
    print (0,err=*proceed) 'option'("FONT","FixedSys,-9"), \
                           'option'("STDFONT","FixedSys, -9"), \
                           'option'("GRAPHICFONT","*GuiFont"), \
                           'option'("WDWICON",Icon32$), \
                           'option'("WDWICON",Icon16$),
    menubar remove
    defctl window $1B$ = DAboutQuit
    defctl window $0D$ = DAboutQuit
    defctl window $20$ = DAboutQuit
    defctl window LeftMouseDown = -1000
    defctl window LeftMouseUp = DAboutQuit
    defctl window RightMouseDown = -1000
    defctl window RightMouseUp = DAboutQuit
    print (0,err=*proceed) '_colour'(AboutBackgroundColour$), \
                            'colour'(AboutTextColour$), \
                            'cs',
    print (0,err=*proceed) 'picture'(0,0,@x(w),@y(h),SplashImage$,0),
    print (0,err=*proceed) 'white', 'text'(@x(2.8),@y(h - 7),Company$), \
                                    'text'(@x(2.8),@y(h - 6),CompanyInfo1$), \
                                    'text'(@x(2.8),@y(h - 5),CompanyInfo2$), \
                                    'text'(@x(2.8),@y(h - 4),CompanyInfo3$), \
                                    'text'(@x(2.8),@y(h - 3),CompanyInfo4$), \
                                    'text'(@x(2.8),@y(h - 2),Software$+" - "+msg("TVer")+": "+Version$),

    !setfocus 0
    print 'move'(xcol,ycol), \
          'image'("BaseWindow"),
    return 0
!
!
DialogueAboutDestroy:
    if AboutPHnd = 0 \
        then return 0

    CurrentWindowList$ = sub(CurrentWindowList$, bin(AboutPHnd,1), "")
    print 'drop'(AboutPHnd),
    AboutPHnd = 0
    return 1
!
!
DialogueFindCreate:
    if Report = 0 \
        then return 0

    if pos(bin(FindPHnd,1) = CurrentWindowList$, 1) \
        then print 'goto'(FindPHnd),; return

    FindPHnd = hwn(0)
    CurrentWindowList$ += bin(FindPHnd,1)

    w = 42
    h = 5
    xcol = max(int((Columns - w) / 2),3) + This'Column + 1
    ycol = max(int((Rows - h) / 2),2) + This'Row + 1
    print 'dialog'(-16000,-16000,w,h,FindPHnd,msg("TFind"),'B?'+'df'+'cs',opt="c&M"),'sr',
    print (0,err=*proceed) 'option'("FONT","FixedSys,-9"), \
                           'option'("STDFONT","FixedSys, -9"), \
                           'option'("GRAPHICFONT","*GuiFont"), \
                           'option'("WDWICON",Icon32$), \
                           'option'("WDWICON",Icon16$),

    menubar remove
    defctl window EQuit = DFindQuit
    defctl window TabKey = DFindTabKey
    defctl window BackTabKey = DFindBackTabKey
    defctl window $1B$ = DFindQuit
    defctl window $0D$ = DFindOK
    defctl window LeftMouseDown = -1000
    defctl window LeftMouseUp = -1000
    defctl window RightMouseDown = -1000
    defctl window RightMouseUp = -1000

    tw = txw(objs$[cntls[DFindText], 1], 0, fnt="*GUIFont") / 16
    print 'text'(@x(1.4),@y(1),objs$[cntls[DFindText], 1],"&"),
    if SuppressToolTips = 0 \
        then t$ = objs$[cntls[DFindText], 3]
    vardropbox DFindText,@(1.4 + tw, 1, 21, 10),len=255,opt="T",fnt="*GUIFont" !,tip=t$
    if SavedSearchStrings$ > "" \
        then vardropbox load DFindText,SavedSearchStrings$, err=*proceed
    DFindText'Key$ = objs$[cntls[DFindText], 2]
    if SearchString$ > "" \
        then vardropbox write DFindText,SearchString$,err=*proceed

    tw = txw(objs$[cntls[DFindMatch], 1], 0, fnt="*GUIFont") / 16
    twm = 5 + tw
    if SuppressToolTips = 0 \
        then t$ = objs$[cntls[DFindMatch], 3]
    checkbox DFindMatch,@(1.4, 3.2, 3 + tw, 1)=objs$[cntls[DFindMatch], 1],fnt="*GUIFont" !,tip=t$
    DFindMatch'Key$ = objs$[cntls[DFindMatch], 2]
    if MatchCase \
        then DFindMatch'Value$="1"

    tw = txw(objs$[cntls[DFindDir], 1], 0, fnt="*GUIFont") / 16
    if SuppressToolTips = 0 \
        then t$ = objs$[cntls[DFindDir], 3]
    checkbox DFindDir,@(w - 14 - tw, 3.2, 3 + tw, 1)=objs$[cntls[DFindDir], 1],fnt="*GUIFont" !,tip=t$
    DFindDir'Key$ = objs$[cntls[DFindDir], 2]
    if SearchDirection \
        then DFindDir'Value$="1"

    button DFindOK,@(w - 10.6, .8, 9, 1.5)=msg("BOK"),fnt="*GUIFont",opt="*"
    button DFindCancel,@(w - 10.6, 2.8, 9, 1.5)=msg("BCancel"),fnt="*GUIFont"
    DFindFocus = DFindText
    setfocus DFindFocus

    print 'move'(xcol,ycol),

    return 0
!
!
DialogueFindDestroy:
    if FindPHnd = 0 \
        then return 0

    CurrentWindowList$ = sub(CurrentWindowList$, bin(FindPHnd,1), "")
    print 'drop'(FindPHnd),
    FindPHnd = 0
    Report'Search = 0
    return 1
!
!
DialogueFindMove:
    if FindPHnd = 0 \
        then return 0

    enter (CurrentPage), (CenterX), (CenterY), err=*proceed
    if CenterX = 0 then CenterX = 0.000001
    if CenterY = 0 then CenterY = 0.000001

    o = Report'Page(CurrentPage)
    pl = o'PaperLength
    pw = o'PaperWidth
    ml = o'MarginLeft / 1000
    mt = o'MarginTop / 1000
    mr = o'MarginRight / 1000
    mb = o'MarginBottom / 1000

    ReportWidthPercent = (pw - ml - mr) / pw
    ReportLengthPercent = (pl - mt - mb) / pl

    print (0,err=*proceed)'-U',
    print (0,err=*proceed) 'goto'(ViewPortWindow),
    x$ = obj(0)
    ViewWinX = dec(mid(x$, 21, 2))
    ViewWinY = dec(mid(x$, 23, 2))
    ViewWinW = dec(mid(x$, 25, 2))
    ViewWinH = dec(mid(x$, 27, 2))

    print (0,err=*proceed) 'goto'(FindPHnd),
    x$ = obj(0)
    FindWinX = dec(mid(x$, 21, 2))
    FindWinY = dec(mid(x$, 23, 2))
    FindWinW = dec(mid(x$, 25, 2))
    FindWinH = dec(mid(x$, 27, 2))

    FindWinCol = prc((FindWinX-ViewWinX) / ColGus, 0)
    FindWinRow = prc((FindWinY-ViewWinY) / RowGus, 0)

    print (0,err=*proceed)'+U',

    ! If the Find window is outside of the main dialogue, we do not need to move it.
    if FindWinX + FindWinW <= ViewWinX \
        then return 1
    if FindWinX >= ViewWinX + ViewWinW \
        then return 1
    if FindWinY + FindWinH <= ViewWinY \
        then return 1
    if FindWinY >= ViewWinY + ViewWinH \
        then return 1

    for x = 1 to VisibleImages
        if VisibleImage[x, 2] = CurrentPage \
            then break
    next x

    ButtonOffsetX = int(VisibleImage[x, 5] * ColGus)
    ButtonOffsetY = int(VisibleImage[x, 6] * RowGus)
    ButtonWidth = int(VisibleImage[x, 7] * ColGus)
    ButtonHeight = int(VisibleImage[x, 8] * RowGus)

    ReportWidthPixels = int(ButtonWidth * ReportWidthPercent)
    ReportLengthPixels = int(ButtonHeight * ReportLengthPercent)

    MarginLeftPercent = (pw - ml) / pw
    MarginTopPercent = (pl - mt) / pl

    MarginLeftPixels = int(ButtonWidth * (1 - MarginLeftPercent))
    MarginTopPixels = int(ButtonHeight * (1 - MarginTopPercent))

    XinButt = int((ReportWidthPixels) * CenterX) + MarginLeftPixels
    YinButt = int((ReportLengthPixels) * CenterY) + MarginTopPixels

    XinViewPort = XinButt + ButtonOffsetX
    YinViewPort = YinButt + ButtonOffsetY

    ColInViewPort = XinViewPort / ColGus
    RowInViewPort = YinViewPort / RowGus

    RowsToMove = 0
    DFM_ReCheck:
    ! Area around find box, keep find out of this area
    RectX = FindWinCol - 8
    RectY = FindWinRow - 3 + RowsToMove
    RectW = RectX + (FindWinW / ColGus) + 16
    RectH = RectY + (FindWinH / RowGus) + 6

    if RowInViewPort < RectY or RowInViewPort > RectH \
        then goto DFM_Completed
    if ColInViewPort < RectX or ColInViewPort > RectW \
        then goto DFM_Completed

    if RowInViewPort <= (ViewRows - 1) / 2 \
        then FindMoveUp = 0 \
        else FindMoveUp = 1

    if FindMoveUp \
        then RowsToMove -= 1 \
        else RowsToMove += 1

    goto DFM_ReCheck

    DFM_Completed:
    if RowsToMove then \
    {   print(0,err=*proceed)'-U','move'(-15000,-15000),
        print (0,err=*proceed)'move'( prc(FindWinX / ColGus, 0), prc(FindWinY / RowGus, 0) + RowsToMove),'+U',
    }

    return 1
!
!
SearchForText:
    enter (TextToFind$), (CaseSensitive), err=*proceed
    if TextToFind$ = "" \
        then This'Find();
             return 0
    if len(TextToFind$) > 255 \
        then TextToFind$ = TextToFind$(1,255)

    SeachString$ = TextToFind$
    MatchCase = CaseSensitive

    SFTAgain:
    FP = Page
    Report'Search = 1

    oStat$ = StatusBarS2'Value$
    This'SetStatusBarText(2, msg("TSearching"))
    print 'cursor'(1),

    FoundIt = Report'Search(SearchString$, MatchCase, SearchDirection, FP, FX, FY)

    This'SetStatusBarText(2, oStat$)
    print 'cursor'(0),; wait 0

    if FoundIt then \
    {
        if FP > 0 and FP <= Pages and FP <> Page then \
        {   This'RefreshPages(SearchLastPage)
            This'RefreshPages(FP)
            This'GotoPage(FP)
            This'MoveView(FX, FY)
            This'DialogueFindMove(FP, FX, FY)
        } else \
        {   This'RefreshPages(FP)
            This'MoveView(FX, FY)
            This'DialogueFindMove(FP, FX, FY)
        }
        SearchLastPage = FP
    } else \
    {
        if SearchDirection then \
        {
            answer$ = This'DisplayError$(msg("FindHitTop"),"?,^,YESNO")
            if answer$ = "YES" then \
            {
                This'RefreshPages(SearchLastPage)
                Report'SearchReset()
                This'GotoPage(Pages)
                goto SFTAgain
            }
        } else \
        {
            answer$ = This'DisplayError$(msg("FindHitBottom"),"?,^,YESNO")
            if answer$ = "YES" then \
            {
                This'RefreshPages(SearchLastPage)
                Report'SearchReset()
                This'GotoPage(1)
                goto SFTAgain
            }
        }
    }
    return 0
!
!
SearchForTextNext:
    SearchDirection = 0
    if SearchString$ = "" then \
    {   This'Find()
        return 0
    }

    FP = Page
    Report'Search = 1

    oStat$ = StatusBarS2'Value$
    This'SetStatusBarText(2, msg("TSearching"))
    print 'cursor'(1),

    FoundIt = Report'Search(SearchString$, MatchCase, 0, FP, FX, FY)

    This'SetStatusBarText(2, oStat$)
    print 'cursor'(0),; wait 0

    if FoundIt then \
    {
        if FP > 0 and FP <= Pages and FP <> Page then \
        {   This'RefreshPages(SearchLastPage)
            This'RefreshPages(FP)
            This'GotoPage(FP)
            This'MoveView(FX, FY)
        } else \
        {   This'RefreshPages(FP)
            This'MoveView(FX, FY)
        }
        SearchLastPage = FP
    } else \
    {
        answer$ = This'DisplayError$(msg("FindHitBottom"),"?,^,YESNO")
        if answer$ = "YES" then \
        {
            This'RefreshPages(SearchLastPage)
            Report'SearchReset()
            This'GotoPage(1)
            goto SearchForTextNext
        }
    }
    return 0
!
!
SearchForTextPrevious:
    SearchDirection = 1
    if SearchString$ = "" then \
    {   This'Find()
        return 0
    }

    FP = Page
    Report'Search = 1

    oStat$ = StatusBarS2'Value$
    This'SetStatusBarText(2, msg("TSearching"))
    print 'cursor'(1),

    FoundIt = Report'Search(SearchString$, MatchCase, 1, FP, FX, FY)

    This'SetStatusBarText(2, oStat$)
    print 'cursor'(0),; wait 0

    if FoundIt then \
    {
        if FP > 0 and FP <= Pages and FP <> Page then \
        {   This'RefreshPages(SearchLastPage)
            This'RefreshPages(FP)
            This'GotoPage(FP)
            This'MoveView(FX, FY)
        } else \
        {   This'RefreshPages(FP)
            This'MoveView(FX, FY)
        }
        SearchLastPage = FP
    } else \
    {
        answer$ = This'DisplayError$(msg("FindHitTop"),"?,^,YESNO")
        if answer$ = "YES" then \
        {
            This'RefreshPages(SearchLastPage)
            Report'SearchReset()
            This'GotoPage(Pages)
            goto SearchForTextPrevious
        }
    }
    return 0
!
!
SetNumPages:
    x = pos("," = VisiblePages$, 1, 0)
    if IsSpooled = 0 and IsSpooling = 0 \
        then s$=" ("+TSpoolingPaused$+")"
    if IsSpooled = 0 and IsSpooling = 1 \
        then s$=" ("+TSpooling$+")"
    if SuppressToolBar \
        then z$ = " ("+TZoom$+str(Zoom)+TPercent$+")"
    if Report = 0 \
        then return 0

    if x > 1 then \
    {   vp$ = tbl(x > 2, TPage$, TPages$) + " " + mid(VisiblePages$, 2, len(VisiblePages$) - 2)
        This'SetStatusBarText(2,vp$+" "+Tof$+" "+str(Report'Pages) + s$ + z$)
    }

    dim vp[0 : 4]
    read data from VisiblePages$,sep="," to vp[all]
    for y = 1 to 4
        z = pos("," + str(vp[y]) + ","  = RenderErrorOnPages$, 1)
        if z then s = 1
    next y
    if s  \
        then This'SetStatusBarText(3, WarningImage$, WarningTip$) \
        else  This'SetStatusBarText(3, "", "")
    return 0
!
!
! 0 = More to Spool, 1 = DoneSpooling
BackGroundSpool:
    if Report = 0 or IsSpooled \
        then return 1

    enter SetTimer

    PageCount = Pages
    IsSpooled = Report'Spooled
    IsSpooling = Report'Spool

    if IsSpooled and PageCount = 0 \
        then This'SetStatusBarText(2, msg("TNoPages"))

    if IsSpooling = 0 \
        then return 1

    if IsSpooling and IsSpooled = 0 then \
    {   SetTimer = 1
        Report'Load()
        IsSpooled = Report'Spooled
        IsSpooling = Report'Spool
        if IsSpooling = 0 and IsSpooled = 0 \
            then This'ChangeMenu("PAUSESPOOL");
                 This'SetNumPages();
                 SetTimer = 0
        if IsSpooled \
            then This'ChangeMenu("SPOOLED");
                 This'SetNumPages();
                 SetTimer = 0
        if IsSpooled and SetWindowStateOnSpoolComplete \
            then This'MakeVisible()
    }

    Pages = Report'Pages
    x$ = Report'Title$
    if x$ = "" \
        then x$ = Report'Filename$
    This'SetStatusBarText(1, x$)

    if IsSpooled and Pages = 0 then \
    {   This'SetStatusBarText(2, msg("TEmptyReport"))
        This'ChangeMenu("NOFILE")
        This'MakeVisible()
    }

    if Page = 0 and Pages > 0 then \
    {   if Report'ScreenDPI > 0 \
            then DPIScreen = Report'ScreenDPI
        This'GotoPage(1)
        if SetWindowStateOnFirstPage \
            then This'MakeVisible()
    }

    if InitialPage and Pages >= InitialPage then \
    {   This'GotoPage(InitialPage)
        InitialPage = 0
        if SetWindowStateOnFirstPage \
            then This'MakeVisible()
    }

    if Pages > PageCount and Pages > 1 then \
    {   if ViewComplete = 0 then \
        {   This'ImageButtonsSetPageNumbers(Page)
            This'ImageButtonsSetSizeLocation()
            This'DrawPages()
        } else \
        {   This'SetNumPages()
            This'ResetVerticalScrollBar()
        }
    }

    return 0
!
!
!local PrinterChan, IsPrinting, IsPrinted, CheckPrint
!local PrintingUnCollatedCopy, PrintingCollatedCopy, PrintingPage, PrintingTotalPages
BackGroundPrint:
    if Report = 0 or IsPrinted \
        then return 1

    enter SetTimer

    Pages = Report'Pages
    PrintingDone = 0

    ! Figure out what page to print next
    ! 4 pages, 3 copies, Collated = 1,2,3,4,1,2,3,4,1,2,3,4
    ! 4 Pages, 3 copies, UnCollated = 1,1,1,2,2,2,3,3,3,4,4,4
    ! The following code expects us to deal with the Copies and Collation
    ! However, there is no current method to override what was set in the printer selection dialogue
    ! and therefore windows MAY do the copies and collation itself, which will
    ! cause us a problem, as you would end up getting COPIES * COPIES if we also output X number of copies
    ! So force Collate and Copies to 1 and let Windows deal with it, until such time as
    ! we can override items like this in ProvideX. (Perhaps V7)
    !if Collate = 1 then \
    !{   PrintingPage = This'NextPageToPrint()
    !    if PrintingPage > Pages \
    !        then PrintingCollatedCopy++; PrintingRange$ = Range$; PrintingPage = This'NextPageToPrint()
    !    if PrintingCollatedCopy > Copies \
    !        then PrintingDone = 1
    !} else \
    !{   if PrintingUnCollatedCopy = 0 \
    !        then PrintingPage = This'NextPageToPrint()
    !    PrintingUnCollatedCopy++
    !    if PrintingUnCollatedCopy > Copies \
    !        then PrintingRange$ = Range$; PrintingUnCollatedCopy = 0
    !    if PrintingPage > Pages \
    !        then PrintingDone = 1
    !}

    if (Range$ = "" or ucs(Range$)="ALL") and PrintingPage < Pages \
        then PrintingRange$ = str(PrintingPage + 1)+":"+str(Pages)

    PrintingPage = This'NextPageToPrint()

    if PrintingPage > Pages or PrintingPage = 0 \
        then PrintingDone = 1

    if PrintingDone then \
    {   This'ClosePrinter()
    } else \
    {   This'SetStatusBarText(2,msg("TBackgroundPrint",str(PrintingPage)))

        if PrintingTotalPages > 0 \
            then print(PrinterChan,err=*proceed)'ff',

        PrintingTotalPages++

        Report'Page = PrintingPage
        o = Report'Page(PrintingPage)

        if not(SuppressWaterMarks = 1 or Report'SuppressWaterMarks = 1) then \
        {   if (PrintingPage = 1 and WaterMarkPages = 1) or \
               (PrintingPage > 0 and WaterMarkPages = 2) then \
            {   WaterMark'RenderWaterMark(PrinterChan, PrintingPage, \
                                                o'PaperWidth, o'PaperLength, PrintingDPI, \
                                                o'MarginLeft, o'MarginTop, \
                                                o'MarginRight, o'MarginBottom )
            }
        }
        Result = Report'RenderPage(PrinterChan)
        SetTimer = 1
    }

    return 0
!
!
ClosePrinter:
    This'SetStatusBarText(2,msg("TBackgroundPrintDone"))

    if OutputEvenNumberOfPages and PrintingTotalPages > 0 and PrintingTotalPages | 2 then \
    {   print(PrinterChan,err=*proceed)'ff',
        This'OutputBlankPage()
    }

    IsPrinting = 0
    IsPrinted = 1
    close(PrinterChan)

    PrinterChan = 0
    PrintingUnCollatedCopy = 0
    PrintingCollatedCopy = 0
    PrintingPage = 0
    PrintingTotalPages = 0
    return 0
!
!
OutputBlankPage:
    Report'Page = Report'Pages
    o = Report'Page(Report'Pages)
    PrintingTotalPages++

    if not(SuppressWaterMarks = 1 or Report'SuppressWaterMarks = 1) then \
    {   if WaterMarkPages = 2 then \
            {   WaterMark'RenderWaterMark(PrinterChan, PrintingTotalPages, \
                                                o'PaperWidth, o'PaperLength, PrintingDPI, \
                                                o'MarginLeft, o'MarginTop, \
                                                o'MarginRight, o'MarginBottom )
        }
    }

    Report'RenderBlankPage(PrinterChan)
    return 0
!
!
!NextPageToPrint()
! Returns the next page in the range to print, or the 0 for no more pages
NextPageToPrint:
    p = 0
    x = pos("," = PrintingRange$+",", 1)
    x$ = mid(PrintingRange$,1, x - 1)
    PrintingRange$ = mid(PrintingRange$,x + 1)

    x = pos(":" = x$, 1)
    if x then \
    {   read data from x$,sep=":" to x1, x2
        p = x1
        x1 += 1
        if x1 <= x2 \
            then PrintingRange$ = str(x1)+":"+str(x2)+","+PrintingRange$
    } else \
    {   p = num(x$, err=*proceed)
    }
    return p
!
!
! Returns PrinterChannel or 0 if not opened.
! Returns Desc$, which is a human readable description of the printer (if any)
! If a SpecifiedPrinter$ is given, then the OPEN should only try to open that printer, and not
! give the user a choice of others.
OpenPrinter:
    if Report = 0 \
        then return 0
    if IsPrinting or PrinterChan \
        then return 0 ! Currently Printing a report

    enter (SpecifiedPrinter$), Desc$, Options$, (IsGUI), DoCopies, DoCollate, DoRange$, DoColor, DoDPI, err=*next
    Desc$ = ""
    PrinterChan = 0

    t$ = Report'Title$
    if t$ = "" \
        then t$ = Software$+": "+msg("TUnamedReport") \
        else t$ = Software$+": "+t$

    if PrinterSelectionCallBack$ > "" then \
    {   call PrinterSelectCallBack$,err=SPPSCFailed, PrinterChan, SpecifiedPrinter$, Desc$, Options$, IsGUI, t$
        if PrinterChan = 0 \
            then goto SPPSCFailed

        goto OpenPrinterContinued

        SPPSCFailed:
        PrintChan = 0
        Desc$ = ""
        return 0
    }

    if Report'Title$ > "" then \
    {   TitleWin = hwn(0)
        print '-U','dialogue'(Column + 2,Row + 1,40,20,TitleWin,t$,'show'(-1), opt="c"),'+U',
    }

    if ucs(SpecifiedPrinter$) = "DEFAULT" \
        then SpecifiedPrinter$ = IsWindX$ + "*winprt*;Default"

    if ucs(SpecifiedPrinter$) = "ASIS" \
        then SpecifiedPrinter$ = IsWindX$ + "*winprt*;Asis"

    if SpecifiedPrinter$ = "" \
        then SpecifiedPrinter$ = IsWindX$ + "*winprt*;Normal"

    if pos(";" = SpecifiedPrinter$, 1, 0) < 1 \
        then Options$ = ";" + Options$

    tmp$ = SpecifiedPrinter$+Options$+";FORCE6X10=Yes"
    x = pos(";" = tmp$, 1)
    if x then \
    {   p$ = tmp$(1, x - 1)
        o$ = tmp$(x + 1)
    } else \
    {   p$ = tmp$
        o$ = ""
    }
    open (hfn, opt=o$, err=SPOpenFail) p$
    PrinterChan = LFO
    if TitleWin \
        then print 'drop'(TitleWin),
    goto OpenPrinterContinued
    !
    SPOpenFail:
    if TitleWin \
        then print 'drop'(TitleWin),
    return 0
    !
    OpenPrinterContinued:
    P$ = pth(PrinterChan)
    w = pos("[WDX]" = ucs(P$), 1)
    wp = pos("*WINPRT*" = ucs(P$), 1)

    x$ = ""
    if Desc$ = "" then \
    {   if w = 0 and wp = 1 \
            then winprtsetup server read x$
        if w = 1 and (wp = 1 or wp = 6) \
            then winprtsetup read x$

        if x$ > "" \
            then x = pos(" ON " = ucs(x$), 1)
        if x$ > "" and x \
            then x$ = x$(1, x - 1)
        if x$ > "" \
            then Desc$ = x$ \
            else Desc$ = SpecifiedPrinter$

    }

    ! This program will deal with Copies itself, just make sure Windows doesn't do it too.
    ! The following code does not work, there needs to be a way to adjust printing properties
    ! on-the-fly for each, perhaps for V7 - Until then this code can remain as a reminder
    if wp = 1 or wp = 6 then \
    {   NewOptions$ = ""
        if w = 1 then \
        {   winprtsetup read properties NewOptions$, err=*proceed
    !        winprtsetup write properties "Copies=1;Collate=no;Range=All", err=*proceed
        } else \
        {   winprtsetup read properties NewOptions$, err=*proceed                       ! Server
    !        winprtsetup write properties "Copies=1;Collate=no;Range=All", err=*proceed ! Server
        }
        This'UpdatePrintOptions(Options$, NewOptions$, DoCopies, DoCollate, DoRange$, DoColor, DoDPI)

    }

    PrintingCollatedCopy=1
    PrintingUnCollatedCopy=0
    PrintingPage = 0
    PrintingTotalPages = 0

    return PrinterChan
!
!
UpdatePrintOptions:
    enter O$, N$, DoCopies, DoCollate, DoRange$, DoColor, DoDPI

    origo$ = o$

    x = max( pos(";" = O$, 1, 0) + 1, pos(";" = N$, 1, 0) + 1)
    x += 2
    dim o1$[1:x], n1$[1:x]
    dim o2$[1:x, 1:2], n2$[1:x, 1:2]

    if pos(";DPI=" = ucs(o$), 1) = 0 and pos(";DPI=" = ucs(n$), 1) \
        then o$ += ";DPI=0"

    if pos(";QUALITY=" = ucs(o$), 1) = 0 and pos(";QUALITY=" = ucs(n$), 1) \
        then o$ += ";Quality=0"

    if pos(";RESOLUTION=" = ucs(o$), 1) = 0 and pos(";RESOLUTION=" = ucs(n$), 1) \
        then o$ += ";Resolution=0:0"

    read data from O$,sep=";" to o1${all}
    read data from N$,sep=";" to n1${all}

    for y = 1 to x
        read data from o1$[y],sep="=" to o2$[y,1],o2$[y,2]
        read data from n1$[y],sep="=" to n2$[y,1],n2$[y,2]
    next y

    for y = 1 to x
        for z = 1 to x
            n$ = ucs(n2$[y, 1])
            if n$ = "COLLATE" or n$ = "MARGINS" or \
               n$ = "SOURCE" or n$ = "PAPERSIZE" or \
               n$ = "ORIENTATION" or n$ = "MARGIN" \
                then continue ! Don't override certain things.

            if n$ = ucs(o2$[z, 1]) \
                then o2$[z, 2] = n2$[y, 2]
        next z
    next y

    O$ = ""
    for y = 1 to x
        if o2$[y, 1] = "" \
            then continue
        if o2$[y, 2] = "" \
            then o$ += ";" + o2$[y, 1]; continue
        o$ += ";" + o2$[y, 1] + "=" + o2$[y, 2]

        !DoCopies, DoCollate, DoRange$, DoColor
        switch ucs(o2$[y, 1])
            case "COPIES"
                DoCopies = num(o2$[y, 2], err=*proceed)
                break

            case "COLLATE"
                if ucs(o2$[y, 2]) = "YES" \
                    then DoCollate = 1 \
                    else DoCollate = 0
                break

            case "RANGE"
                DoRange$ = o2$[y, 2]
                break

            case "COLOR"
            case "COLOUR"
                if ucs(o2$[y, 2]) = "YES" \
                    then DoColor = 1 \
                    else DoColor = 0
                break

            case "QUALITY"
            case "DPI"
                DoDPI = num(o2$[y, 2], err=*proceed)
                break

            case "RESOLUTION"
                read data from o2$[y, 2],sep=":" to x1, x2
                DoDPI = x1
                break

        esac
    next y

    o$ = o$(2)
    return 0
!
!
! Returns 0 = Sucess, otherwise failure
PrintReport:
    if DisablePrint or Report = 0 or Report'Pages = 0 \
        then return 1

    if IsPrinting or PrinterChan \
        then return 1

    enter (Value$), err=*next

    if Report'ReportType = 3 \
        then IsGUI = 1 \
        else IsGUI = 0

    OrigPrinter$ = Printer$
    OrigPrinterDesc$ = PrinterDescription$

    Copies = Report'Copies
    Collate = Report'Collate
    Colour = Report'Colour
    Range$ = Report'Range$
    PrintingDPI = Report'DPI
    ReportPrinter$ = Report'Printer$
    p = Report'Page(0)

    Options$  = ";Copies="+str(Copies)
    Options$ += tbl(Collate = 1, ";Collate=no", ";Collate=yes")
    Options$ += tbl(Range$ > "", "", ";Range="+Range$)
    Options$ += tbl(PrintingDPI > 0, "", ";Quality="+str(DPIPrinter))
    Options$ += ";Margins="+str(p'MarginLeft)+":"+str(p'MarginTop)+":"+ \
                            str(p'MarginRight)+":"+str(p'MarginBottom);
    Options$ += ";Source="+str(p'PaperBin)
    Options$ += ";PaperSize="+str(p'PaperSize)
    Options$ += ";Orientation="+p'Orientation$
    Options$ += tbl(Colour = 1, ";Color=no", ";Color=yes")
    Options$ += ";Range=Query"

    ! If the report has a hard coded printer name in it.
    PROpenReportPrinter:
    if ReportPrinter$ > "" then \
    {   PrinterChan = This'OpenPrinter(ReportPrinter$, PrinterDescription$, Options$, IsGUI, Copies, Collate, Range$, Color, PrintingDPI)
        if PrinterChan then \
        {   Printer$ = ReportPrinter$
            goto DoPrintJob
        }
        if Visible then \
        {   result$ = This'DisplayError$(msg("E_OPEN_SPECIFIC_REPORT_PRINTER_NA", ReportPrinter$), "?,^,RETRYCANCEL")
            if result$ = "RETRY" \
                then goto PROpenReportPrinter
            Printer$ = OrigPrinter$
            PrinterDescription$ = OrigPrinterDescription$
            return 513
        }
    }

    ! If the report object has been told to use a specific printer
    PROpenUsePrinter:
    if UsePrinter$ > "" then \
    {   PrinterChan = This'OpenPrinter(UsePrinter$, PrinterDescription$, Options$, IsGUI, Copies, Collate, Range$, Color, PrintingDPI)
        if PrinterChan then \
        {   Printer$ = UsePrinter$
            goto DoPrintJob
        }
        if Visible then \
        {   result$ = This'DisplayError$(msg("E_OPEN_SPECIFIC_REPORT_PRINTER_NA", UsePrinter$), "?,^,RETRYCANCEL")
            if result$ = "RETRY" \
                then goto  PROpenUsePrinter
            Printer$ = OrigPrinter$
            PrinterDescription$ = OrigPrinterDescription$
            return 513 ! E_OPEN_SPECIFIC_REPORT_PRINTER_NA
        }
    }

    ! If the Print Command had a specific printer passed to it.
    if Value$ > "" then \
    {   PrinterChan = This'OpenPrinter(Value$, PrinterDescription$, Options$, IsGUI, Copies, Collate, Range$, Color, PrintingDPI)
        if PrinterChan then \
        {   Printer$ = Value$
            goto DoPrintJob
        }
        ! If we fail on this printer, allow it to fall through and give the user a printer selection
    }

    ! if we are not visible then get out, as the we cannot present the user with a dialogue while invisible
    if Visible = 0 \
        then return 514 ! E_NO_PRINTER_SPECIFIED

    PrinterChan = This'OpenPrinter("", PrinterDescription$, Options$, IsGUI, Copies, Collate, Range$, Color, PrintingDPI)
    if PrinterChan = 0 \
        then return 1

    Printer$ = pth(PrinterChan)

    if  PrinterDescription$ > "" and \
        (pos("*WINPRT*" = ucs(Printer$), 1) or pos("*WINDEV*" = ucs(Printer$), 1)) then \
    {   x = pos(";" = Printer$, 1, 1)
        if x then \
        {   if ucs(mid(Printer$, x, 7)) = ";NORMAL" \
                then Printer$ = Printer$(1, x) + PrinterDescription$ + Printer$(x + 7)
            if ucs(mid(Printer$, x, 6)) = ";SETUP" \
                then Printer$ = Printer$(1, x) + PrinterDescription$ + Printer$(x + 6)
            if ucs(mid(Printer$, x, 8)) = ";DEFAULT" \
                then Printer$ = Printer$(1, x) + PrinterDescription$ + Printer$(x + 8)
            if ucs(mid(Printer$, x, 5)) = ";ASIS" \
                then Printer$ = Printer$(1, x) + PrinterDescription$ + Printer$(x + 5)
        }

    }

    ! We have a selected and opened printer channel, lets get down to the printing business.
    DoPrintJob:

    IsPrinting = 1
    IsPrinted = 0

    if Range$ = "" or ucs(Range$)="ALL" \
        then PrintingRange$ = "1:"+str(Report'Pages) \
        else PrintingRange$ = Range$

    if Visible then \
    {   preinput CheckPrint
        return 0
    }

    counter = 0
    while Report and not(IsPrinted) and PrinterChan
        This'BackGroundPrint(UserTimer)
        if counter and counter | 5 = 0 \
            then wait .1
        counter++
    wend

    return 0
! Error Code Listing
! E_OPEN_SPECIFIC_REPORT_PRINTER_NA = 513 - From either the report file, or setting UsePrinter$
! E_NO_PRINTER_SPECIFIED = 514
! E_NOT_WHILE_INVISIBLE = 515
! E_NO_REPORT_LOADED = 516
!
!
ProcessEvents:
    setesc EscapeRoutine
    print 'cursor'("OFF"),
    ProcessEventsLoop:

    mse$ = "", \
    eom$ = "", \
    c = 0

    if UseTimer \
        then obtain (0,siz=1, tim=TimeVal, bsy=*next, err=ProcessEventsError)'me',Answer$,'mn',;
                 c = ctl, \
                 mse$ = mse, \
                 eom$ = eom \
        else obtain (0,siz=1, bsy=*next, err=ProcessEventsError)'me',Answer$,'mn',;
                 c = ctl, \
                 mse$ = mse, \
                 eom$ = eom

    Result = _obj'Event(Answer$, c, eom$, mse$, UseTimer)

!    if result = -1 \
!       then escape;
!             goto ProcessEventsLoop

    if result \
        then print 'cursor'("ON"),;
             return 1

    goto ProcessEventsLoop

    ProcessEventsError:
    error = err
    print 'cursor'("ON"),

    if error = 86 \
        then release 86

    return 1
!
!
HandleEvent: ! Returns 1 if terminate else 0 to continue
    enter (text$), (ctlval), (EOM$), (mouse$), UseTimer
    Terminate = 0
    UseTimer = 0
    lc = dec(mid(mouse$,20,2)) ! Last control with focus
    cc = dec(mid(mouse$,18,2)) ! Current control with focus

    ! Where's the mouse ?
    x = dec(mid(mouse$,14,2)) / ColGUs
    y = dec(mid(mouse$,16,2)) / RowGUs

!    settrace print Software$+" - Event: "+str(++EventCounter)+" CTL: "+str(ctlval)+"  Keystroke: "+quo+text$+quo+"  EOM: $"+hta(eom$)+"$"

    CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))

    if IgnoreNextTab and (ctlval = TabKey or ctlval = BackTabKey) \
        then ctlval = -1000, IgnoreNextTab = 0

    if CurrentWindow and ctlval = TabKey then \
    {
        switch CurrentWindow
            case GotoPHnd; ctlval = DGotoTabKey; break
            case ZoomPHnd; ctlval = DZoomTabKey; break
            case BannerPHnd; ctlval = DBannerTabKey; break
            case AboutPHnd; ctlval = DAboutQuit; break
            case FindPHnd; ctlval = DFindTabKey; break
            default; break
        esac
    }

    if CurrentWindow and ctlval = BackTabKey then \
    {
        switch CurrentWindow
            case GotoPHnd; ctlval = DGotoBackTabKey; break
            case ZoomPHnd; ctlval = DZoomBackTabKey; break
            case BannerPHnd; ctlval = DBannerBackTabKey; break
            case AboutPHnd; ctlval = DAboutQuit; break
            case FindPHnd; ctlval = DFindBackTabKey; break
            default; break
        esac
    }

    if ctlval = 5 then \
    {   ! Single Key entry, switch to an internal CTL
        switch text$
            case "+";   ctlval = VZoomIn; break
            case "-";   ctlval = VZoomOut; break
            case "G","g"
                if not(ToolBar) or pos("VJump," = ToolBarExtra$, 1) then \
                {   result = This'GotoPage()
                } else \
                {   setfocus VJump,err=*proceed
                }
                break

            case "Z","z"
                if not(ToolBar) or pos("VZoomCustom," = ToolBarExtra$, 1) then \
                {   result = This'Zoom()
                } else \
                {   setfocus VZoomCustom,err=*proceed
                }

                break

            case "F","f";   ctlval = VZoomWidth; break
            case "W","w";   ctlval = VZoomWindow; break
            case "B","b";   ctlval = VBanner; break
            case "p","P";   ctlval = FPauseSpool; break
            case "1";       ctlval = VOne; break
            case "2";       ctlval = VTwo; break
            case "3";       ctlval = VBook; break
            case "4";       ctlval = VFour; break
            case " "
                if CurrentWindow and CurrentWindow = AboutPHnd \
                    then ctlval = DAboutQuit
                break
        esac
    }

    if ctlval = 0 then \
    {   ! Key Entry without character, switch to internal CTL based on EOM
        switch eom$
            case $02$;      ctlval = VStatusBar; break
            case $04$;      ctlval = FSaveAsPDF; break
            case $05$;      ctlval = FClose; break
            case $06$;      ctlval = EFind; break
            case $07$;      ctlval = VToolTip; break
            case $0C$;      ctlval = FDelete; break
            case $0F$;      ctlval = FOpen; break
            case $10$;      ctlval = FPrint; break
            case $13$;      ctlval = FSaveAs; break
            case $14$;      ctlval = VToolBar; break
            case $17$;      ctlval = VWaterMark; break
            case $000221$;  ctlval = VPrevious; break ! CTRL-PgUp
            case $000222$;  ctlval = VNext; break ! CTRL-PgDn
            case $000125$;  ! Shift+Cursor Left, Pan left one screen full
                if HScrollCurPos > 1 then \
                {   This'ScrollHorizontal(max(1,HScrollCurPos - HScrollBigJump))
                    ctlval = -1000
                }
                break
            case $000225$;  ! CTL+Cursor Left, Jump to Left side of page
                if HScrollCurPos > 1 then \
                {   This'ScrollHorizontal(1)
                    ctlval = -1000
                }
                break
            case $000127$;  ! Shift+Cursor Right, Pan right one screen full
                if HScrollCurPos < HScrollMax then \
                {   This'ScrollHorizontal(min(HScrollCurPos + HScrollBigJump, HScrollMax))
                    ctlval = -1000
                }
                break
            case $000227$;  ! CTL+Cursor Right, Jump to Right side of page
                if HScrollCurPos < HScrollMax then \
                {   This'ScrollHorizontal(HScrollMax)
                    ctlval = -1000
                }
                break
            case $000126$;  ctlval = PgUpKey;   break ! Shift Cursor Up
            case $000128$;  ctlval = PgDnKey;   break ! Shift Cursor Down
            case $000226$;  ctlval = BPrevious; break ! CTL + Cursor Up
            case $000228$;  ctlval = BNext;     break ! CTL + Cursor Down
            case $000326$;  ctlval = HomeKey;   break ! CTL + Shift + Cursor Up
            case $000328$;  ctlval = EndKey;    break ! CTL + Shift + Cursor Down
            case $000070$;  ctlval = HContent;  break ! F1
            case $000170$;  ctlval = HIndex;    break ! Shift F1
        esac
    }

    switch ctlval
        case 0, CheckSpool, CheckPrint
            !
            ! Background Spooling
            if Report and not(IsSpooled) \
                then This'BackGroundSpool(UseTimer)

            ! Background Printing
            if Report and not(IsPrinted) and PrinterChan \
                then This'BackGroundPrint(UserTimer)

            break

        case 1, HContent
            if HelpFile$ > "" \
                then systemhelp HelpFile$,HelpContents$,err=*proceed \
                else This'DisplayError$(msg("TNoHelpContents"),"!,OK,^")
            break

        case -5, HIndex
            if HelpFile$ > "" \
                then systemhelp HelpFile$,HelpIndex$,err=*proceed \
                else This'DisplayError$(msg("TNoHelpIndex"),"!,OK,^")
            break

        case EQuit,FExit
            Terminate = 1
            if CurrentWindow then \
            {   Terminate = 0
                switch CurrentWindow
                    case GotoPHnd; preinput DGotoQuit; preinput EQuit; break
                    case ZoomPHnd; preinput DZoomQuit; preinput EQuit; break
                    case BannerPHnd; preinput DBannerQuit; preinput EQuit; break
                    case AboutPHnd; preinput DAboutQuit; preinput EQuit; break
                    case FindPHnd; preinput DFindQuit; preinput EQuit; break
                esac
            }
            break

        case ReSize;                    This'RePaint(); break
        case VToolBar;                  SuppressToolBar=not(SuppressToolBar); This'RePaint(); break
        case VStatusBar;                SuppressStatusBar=not(SuppressStatusBar); This'RePaint(); break
        case VToolTip;                  This'SetSuppressToolTips(not(SuppressToolTips)); break
        case VWaterMark;                This'SetSuppressWaterMarks(not(SuppressWaterMarks)); break
        case VBanner;                   This'DialogueBannerInfo(); break

        case VOne;                      This'View = 0; break
        case VTwo;                      This'View = 1; break
        case VBook;                     This'View = 2; break
        case VFour;                     This'View = 3; break
        case VTop,BTop,HomeKey;         This'FirstPage(); break
        case VBottom,BBottom,EndKey;    This'LastPage(); break
        case VNext,BNext;               This'NextPage(); break
        case VPrevious,BPrevious;       This'PreviousPage(); break
        case MGoto;                     preinput next "G",5; break

        case VJump
            result = This'JumpToPage()
            if result \
                then print 'rb',; setfocus VJump,err=*proceed \
                else setfocus 0
            break

        case MZoomCustom;               preinput next "Z",5; break

        case VZoomCustom
            result = This'ZoomCustom()
            if result \
                then print 'rb',; setfocus VZoomCustom,err=*proceed \
                else setfocus 0
            break

        case VZoomIn
            This'ZoomIn()
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case VZoomOut
            This'ZoomOut()
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case VZoomWidth
            if ZoomLevel = -1 \
                then This'Zoom(LastZoomLevel) \
                else This'Zoom(-1)
            break

        case VZoomWindow
            if ZoomLevel = -2 \
                then This'Zoom(LastZoomLevel) \
                else This'Zoom(-2)
            break

        case BVScroll;                   This'VScrollBarSelect(); break
        case BHScroll;                   This'HScrollBarSelect(); break
        case CurLeft;                    This'ScrollLeft(); break
        case CurRight;                   This'ScrollRight(); break
        case CurUp;                      This'ScrollUp(); break
        case CurDown;                    This'ScrollDown(); break
        case PgUpKey;                    This'ScrollUp(VScrollBigJump/100); break
        case PgDnKey;                    This'ScrollDown(VScrollBigJump/100); break

        case CTLCurLeft;  ! CTL+Cursor Left, Jump to Left side of page
            if HScrollCurPos > 1 \
                then This'ScrollHorizontal(1)
            break
        case CTLCurRight;  ! CTL+Cursor Right, Jump to Right side of page
            if HScrollCurPos < HScrollMax \
                then This'ScrollHorizontal(HScrollMax)
            break

        case FOpen
            This'Open()
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case FClose
            This'Close()
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case FDelete
            This'Delete()
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case FSaveAs
            This'SaveAs()
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case FSaveAsPDF
            This'SaveAsPDF()
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case FPrint
            This'Print()
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case FPauseSpool;
            if CurrentWindow = 0 \
                then setfocus 0
            if Report = 0 \
                then break
            if IsSpooled \
                then break
            IsSpooling = Report'Spool
            if IsSpooling then \
            {   Report'Spool = 0
                IsSpooling = 0
                This'ChangeMenu("PAUSESPOOL")
                UseTimer = 0
            } else \
            {   Report'Spool = 1
                IsSpooling = 1
                This'ChangeMenu("SPOOLING")
                Usetimer = 1
            }
            This'SetNumPages()
            break

        case HAbout;                    This'DialogueAbout(); break

        case EFindAgain, F3Key
            if Report = 0 \
                then break
            if FindPHnd \
                then break
            SearchDirection = 0
            if SearchString$ = "" then \
            {   Report'SearchReset()
                This'Find()
            } else \
            {   This'FindNext()
            }
            break

        case EFindPrev, ShiftF3Key
            if Report = 0 \
                then break
            if FindPhnd \
                then break
            SearchDirection = 1
            if SearchString$ = "" then \
            {   Report'SearchReset()
                This'Find()
            } else \
            {   This'FindPrevious()
            }
            break

        case EFind;
            if Report = 0 \
                then break
            if FindPHnd \
                then break
            SearchDirection = 0
            SearchString$ = ""
            This'Find()
            break

        case RightMouseUp
            if ToolBar then \
            {   if y < = ToolBarHeight then \
                {   preinput next ToolBarRightClickMenu
                    ToolBarMenuX = x
                    if y < 0 \
                        then y = 0
                    ToolBarMenuY = y
                }
            }
            break

        case ToolBarRightClickMenu
            This'DisplayToolBarRightMenu()
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case ToolBarDropButton;         This'DisplayToolBarDropMenu(); break

        case ImageButton1, ImageButton2, ImageButton3, ImageButton4
            i = abs(ctlval | tbl(ImageButton1 < 0, ImageButton1 - 1, ImageButton1 + 1))
            p = VisibleImage[i, 2] ! Page Clicked on
            if VisibleImage[i, 7] = 0 or VisibleImage[i, 8] = 0 \
                then break
            CenterX = x - ViewColumn - VisibleImage[i, 5] ! Column on page clicked on
            CenterY = y - ViewRow - VisibleImage[i, 6] ! Row on page clicked on
            CenterX = CenterX / VisibleImage[i, 7] ! Convert to % of page
            CenterY = CenterY / VisibleImage[i, 8] ! Convert to % of page
            Page = p
            This'ZoomIn(CenterX, CenterY)
            break

        case ImageButtonRight1, ImageButtonRight2, ImageButtonRight3, ImageButtonRight4
            i = abs(ctlval | tbl(ImageButtonRight1 < 0, ImageButtonRight1 - 1, ImageButtonRight1 + 1))
            p = VisibleImage[i, 2] ! Page Clicked on
            if VisibleImage[i, 7] = 0 or VisibleImage[i, 8] = 0 \
                then break
            CenterX = x - ViewColumn - VisibleImage[i, 5] ! Column on page clicked on
            CenterY = y - ViewRow - VisibleImage[i, 6] ! Row on page clicked on
            CenterX = CenterX / VisibleImage[i, 7] ! Convert to % of page
            CenterY = CenterY / VisibleImage[i, 8] ! Convert to % of page
            Page = p
            This'ZoomOut(CenterX, CenterY)
            break

        case DGotoQuit,DGotoCancel
            This'DialogueGotoPageDestroy()
            CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case DGotoJump,DGotoOK
            DGotoFocus = ctlval
            multiline read DGotoJump,value$,meom$,err=*proceed
            if len(value$) = 0 then \
            {   multiline write DGotoJump,str(Page),err=*proceed
                DGotoJump'SelectOffset = 0
                DGotoJump'SelectLength = 5
                IgnoreNextTab = 1
                break
            }

            x$ = ""
            for x = 1 to len(Value$)
                if Value$(x, 1) < "0" or Value$(x, 1) > "9" \
                    then continue
                x$ += Value$(x, 1)
            next x
            x = int(num(x$, err=*proceed))
            if x < 1 or x > Report'Pages then \
            {   multiline write DGotoJump,str(Page),err=*proceed
                DGotoJump'SelectOffset = 0
                DGotoJump'SelectLength = 5
                IgnoreNextTab = 1
                break
            }
            if ctlval = DGotoOK or meom$=$0D$ then \
            {   This'GotoPage(x)
                wait 0
                This'DialogueGotoPageDestroy()
                CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))
                if CurrentWindow = 0 \
                    then setfocus 0
            }
            break

        case DGotoTabKey
            switch DGotoFocus
                case DGotoJump; DGotoFocus = DGotoOK; break
                case DGotoOK; DGotoFocus = DGotoCancel; break
                case DGotoCancel; DGotoFocus = DGotoJump; break
            esac
            setfocus DGotoFocus
            break

        case DGotoBackTabKey
            switch DGotoFocus
                case DGotoJump; DGotoFocus = DGotoCancel; break
                case DGotoOK; DGotoFocus = DGotoJump; break
                case DGotoCancel; DGotoFocus = DGotoOK; break
            esac
            setfocus DGotoFocus
            break

        case DZoomQuit,DZoomCancel
            This'DialogueZoomDestroy()
            CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case DZoomCustom,DZoomOK
            vardropbox read DZoomCustom,value$,meom$,err=*proceed
            if len(value$) = 0 then \
            {   vardropbox write DZoomCustom,str(Zoom) + TPercent$,err=*proceed
                DZoomCustom'SelectOffset=0
                DZoomCustom'SelectLength=len(str(Zoom) + TPercent$)
                IgnoreNextTab = 1
                break
            }

            x$ = ""
            for x = 1 to len(Value$)
                if Value$(x, 1) = TPercent$ \
                    then break
                if Value$(x, 1) < "0" or Value$(x, 1) > "9" \
                    then continue
                x$ += Value$(x, 1)
            next x
            x = int(num(x$, err=*proceed))
            if x < 10 or x > 400 then \
            {   vardropbox write DZoomCustom,str(Zoom) + TPercent$,err=*proceed
                DZoomCustom'SelectOffset=0
                DZoomCustom'SelectLength=len(str(Zoom) + TPercent$)
                IgnoreNextTab = 1
                break
            }
            if ctlval = DZoomOK or meom$=$0D$ then \
            {   This'Zoom(x)
                wait 0
                This'DialogueZoomDestroy()
                CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))
                if CurrentWindow = 0 \
                    then setfocus 0
                }
            break

        case DZoomTabKey
            switch DZoomFocus
                case DZoomCustom; DZoomFocus = DZoomOK; break
                case DZoomOK; DZoomFocus = DZoomCancel; break
                case DZoomCancel; DZoomFocus = DZoomCustom; break
            esac
            setfocus DZoomFocus
            break

        case DZoomBackTabKey
            switch DZoomFocus
                case DZoomCustom; DZoomFocus = DZoomCancel; break
                case DZoomOK; DZoomFocus = DZoomCustom; break
                case DZoomCancel; DZoomFocus = DZoomOK; break
            esac
            setfocus DZoomFocus
            break

        case DBannerQuit,DBannerOK
            This'DialogueBannerInfoDestroy()
            CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case DBannerInfo
            grid read DBannerInfo, x, y, x$, e$
            if e$ = $0D$ or e$ = $20$ then \
            {   This'DialogueBannerInfoDestroy()
                CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))
                if CurrentWindow = 0 \
                    then setfocus 0
            }

            break

        case DBannerTabKey, DBannerBackTabKey
            switch DBannerFocus
                case DBannerInfo; DBannerFocus = DBannerOK; break
                case DBannerOK; DBannerFocus = DBannerInfo; break
            esac
            setfocus DBannerFocus
            break

        case DAboutQuit
            This'DialogueAboutDestroy()
            CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))
            if CurrentWindow = 0 \
                then setfocus 0
            break

        case DFindQuit, DFindCancel
            This'DialogueFindDestroy()
            CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))
            if CurrentWindow = 0 \
                then print(0,err=*proceed)'goto'(BasePHnd),;setfocus 0
            break

        case DFindMatch
            checkbox read DFindMatch,value$,meom$,err=*proceed
            MatchCase = num(value$)
            DFindFocus = DFindMatch
            break

        case DFindDir
            checkbox read DFindDir,value$,meom$,err=*proceed
            SearchDirection = num(value$)
            DFindFocus = DFindDir
            break

        case DFindOK, DFindText
            vardropbox read DFindText,value$,meom$,err=*proceed

            if len(value$) > 0 \
                then SearchString$ = Value$ \
                else SearchString$ = ""

            if SearchString$ > "" then \
            {   if pos(SearchString$+$01$ = SavedSearchStrings$,1) = 0 \
                    then SavedSearchStrings$ = SearchString$+$01$+SavedSearchStrings$

                x = pos($01$ = SavedSearchStrings$, 1, 10)
                if x \
                    then SavedSearchStrings$ = SavedSearchStrings$(1, x)
                vardropbox load DFindText,"",err=*proceed
                vardropbox load DFindText,SavedSearchStrings$,err=*proceed
                vardropbox write DFindText,SearchString$,err=*proceed
                DFindText'SelectOffset = 0
                DFindText'SelectLength = 256
            }

            if SearchString$ = "" then \
            {   This'DialogueFindDestroy()
                CurrentWindow = dec($00$ + mid(CurrentWindowList$, -1))
                if CurrentWindow = 0 \
                    then print(0,err=*proceed)'goto'(BasePHnd),;setfocus 0
                break
            }

            if ctlval=DFindOK or (ctlval=DFindText and meom$=$0D$) and SearchString$ > "" \
                then This'Find(SearchString$, MatchCase)

            break

        case DFindTabKey
            switch DFindFocus
                case DFindOK; DFindFocus = DFindCancel; break
                case DFindCancel; DFindFocus = DFindText; break
                case DFindText; DFindFocus = DFindMatch; break
                case DFindMatch; DFindFocus = DFindDir; break
                case DFindDir; DFindFocus = DFindOK; break
            esac
            setfocus DFindFocus
            break

        case DFindBackTabKey
            switch DFindFocus
                case DFindOK; DFindFocus = DFindDir; break
                case DFindCancel; DFindFocus = DFindOK; break
                case DFindText; DFindFocus = DFindCancel; break
                case DFindMatch; DFindFocus = DFindText; break
                case DFindDir; DFindFocus = DFindMatch; break
            esac
            setfocus DFindFocus
            break

!        case 4
!            if eom$=$1B$ \
!                then break
!            Terminate = -1
!            break ! ******* REMOVE THIS LATER *********
       !
        case -1 ! User Hit Refresh
            This'RefreshPages()
            This'DrawPages()
            break

    esac


    if Report and (IsSpooling or IsPrinting) \
        then UseTimer = 1

    return Terminate
!
!
EscapeRoutine:
    preinput FExit
    return
!
!
!
!   function SetCallBack(EventName$, Routine$)         SetCallBack
!   0 = Successful, 1 = Unsuccessfully set.
SetCallBack:
    enter EventName$, Routine$
    result = 0
    switch EventName$
        case "PRINTER";     PrinterSelectionCallBack$ = Routine$;   break
        default;            result = 1; break
    esac
    return result
!
! *************************************************
! Note to customers, if you want to ship a software.prm file with your own information for certain
! items, then you must include the "Viewer","Version","LastUpdateVersion" with some value > ""
! If you do not, then your software.prm file will get erased, as this routine will consider
! it to be an alpha or beta / early edition that needs some fairly radical changes.
CheckParametersVersion:
    ParametersSoftware = new("*viewer/parameters", ViewerDir$ + "software.prm")
    ParametersSoftware'AddVariable("Viewer","Version","LastUpdateVersion","S","","","","")
    ParametersSoftware'GetParameters("Viewer","Version")
    drop object ParametersSoftware
    ParametersSoftware = 0

    if LastUpdateVersion$ = Version$ \
        then return 0

    ! If not a known update version, then it may have been alpha or beta, clean up if it was.
    if LastUpdateVersion$ = "" then \
    {   erase ViewerDir$ + "software.prm", err=*next
        erase ViewerDir$ + "users.prm", err=*next
        goto ProcessUpgradeComplete
    }

    if LastUpdateVersion$ <= "1.72" then \
    {
        if ParametersSoftware = 0 \
            then ParametersSoftware = new("*viewer/parameters", ViewerDir$ + "software.prm")
        ParametersSoftware'RemoveVariable("Viewer","Company","Company","S")
        ParametersSoftware'RemoveVariable("Viewer","Software","AboutBackgroundColour","S")
        ParametersSoftware'RemoveVariable("Viewer","Software","AboutTextColour","S")
        drop object ParametersSoftware
        ParametersSoftware = 0
    }

    ProcessUpgradeComplete:
    LastUpdateVersion$ = Version$
    if ParametersSoftware = 0 \
        then ParametersSoftware = new("*viewer/parameters", ViewerDir$ + "software.prm")
    ParametersSoftware'AddVariable("Viewer","Version","LastUpdateVersion","S","","","",LastUpdateVersion$)
    ParametersSoftware'SetDefaultParameters("Viewer","Version")
    drop object ParametersSoftware
    ParametersSoftware = 0

    return 0
!
! *********************************************************
! The next section deals with doing upgrades from older to newer versions
!
ProcessUpgrade:
    This'CheckParametersVersion()
    return 0



