/*-- AutoRev header do NOT      edit!
*
*   Program         :   Main.c
*   Copyright       :   Copyright © 1991-92 Jaba Development
*   Author          :   Jan van den Baard
*   Creation Date   :   04-Apr-92
*   Current version :   2.0
*   Translator      :   Dice v2.06.40
*
*   REVISION HISTORY
*
*   Date          Version         Comment
*   ---------     -------         ------------------------------------------
*   04-Apr-92     2.0             Main program. (rewrite)
*
*-- REV_END --*/

#include "View.h"

struct WBStartup                *WBenchMsg      = NULL;

UBYTE                           *CX_PRIORITY        = "CX_PRIORITY";
UBYTE                           *CX_POPWINDOW       = "CX_POPUP";
UBYTE                           *CX_VIEW            = "VIEW";
UBYTE                           *CX_FLUSH           = "FLUSH";
UBYTE                           *CX_QUIT            = "QUIT";

WORD                             CX_DEF_PRIORITY    =   0;
UBYTE                           *CX_DEF_POPWINDOW   =   "YES";
UBYTE                           *CX_DEF_VIEW        =   "lalt lcommand v";
UBYTE                           *CX_DEF_FLUSH       =   "lalt lcommand f";
UBYTE                           *CX_DEF_QUIT        =   "lalt lcommand q";

UBYTE                           *vwVersion          =   "\0$VER: " CX_NAME " 37.45 (16.4.92)";

struct MsgPort                  *vwCxPort           =   NULL;
struct MsgPort                  *vwIdPort           =   NULL;

ULONG                            vwCxMask           =   NULL;
ULONG                            vwIdMask           =   NULL;

UBYTE                            vwDopen            =   FALSE;
UBYTE                            vwIsOpen           =   FALSE;
UBYTE                            vwFsu              =   TRUE;
UBYTE                            vwCustom           =   FALSE;

UWORD                            vwTabSize;

CxObj                           *vwBroker           =   NULL;

UBYTE                           *vwQuitStr, *vwFlushStr, *vwViewStr;

struct NewBroker                 vwNewBroker = {
    NB_VERSION, CX_NAME, CX_TITLE, CX_DESCRIPTION,
    NBU_NOTIFY | NBU_UNIQUE, COF_SHOW_HIDE, NULL, 0
};

struct Window                   *vwWindow           =   NULL;
struct Screen                   *vwScreen           =   NULL;
struct AsciiText                *vwText             =   NULL;
struct RastPort                 *vwRPort;
struct TextFont                 *vwFont;
struct Line                     *vwFirst;
struct Line                     *vwLast;
struct Process                  *vwProc;
struct StringScan                vwSearch;
struct TextBlock                 vwBlocks[ 10 ];
APTR                             vwWdPtr;

#ifdef __DETACH
ULONG                           *vwArgs;
ULONG                            vwWBArgs[14]       =   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
UBYTE                           *_procname          =   "ViewD2.0";
UBYTE                           *_template          =   "Name,CX_PRIORITY/K/N,CX_POPUP/K,VIEW/K,FLUSH/K,QUIT/K,LACE/S,SUPER/S,PRODUCTIVITY/S,A2024TENHZ/S,A2024FIFTEENHZ/S,NOPOINTER/S,SCROLL/S,TABS/K/N";
UBYTE                           *_exthelp           =   NULL;
LONG                             _stack             =   4096L;
LONG                             _priority          =   NULL;
LONG                             _BackGroundIO      =   NULL;
#else
ULONG                            vwArgs[14]         =   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
struct RDArgs                    vwIArgs            =   { { 0, 0, 0}, 0, 0, 0, 0, 0 };
struct RDArgs                   *vwFArgs            =   NULL;
UBYTE                           *Template           =   "Name,CX_PRIORITY/K/N,CX_POPUP/K,VIEW/K,FLUSH/K,QUIT/K,LACE/S,SUPER/S,PRODUCTIVITY/S,A2024TENHZ/S,A2024FIFTEENHZ/S,NOPOINTER/S,SCROLL/S,TABS/K/N";
#endif

UBYTE                            vwFound            =   FALSE;
UBYTE                            vwPrinting         =   FALSE;
UBYTE                            vwErr              =   FALSE;

ULONG                            vwSignal, vwShown, vwNum, vwId;
UWORD                            vwYMax, vwMode, vwPMode, vwMaxLin, vwPMark;

UWORD                            vwDriPens          =   ~0;

UBYTE                            vwPath[ 256 ];
UBYTE                            vwPatt[ 32  ];
UBYTE                            vwFile[ 32  ];
UBYTE                            vwName[ 512 ];
UBYTE                            vwFBuf[ 256 ];

extern struct IntuitionBase     *IntuitionBase;
extern struct GfxBase           *GfxBase;
extern struct GadToolsBase      *GadToolsBase;
extern struct UtilityBase       *UtilityBase;

extern UBYTE                     StdStr[];
extern UBYTE                     ClearStr[];
extern UBYTE                     MoveStr[];
extern UBYTE                     ScrUpStr[];
extern UBYTE                     ScrDnStr[];
extern UBYTE                     ResStr[];

extern ULONG                     vwClass;
extern UWORD                     vwCode, vwQualifier;

extern __far struct Custom       custom;

struct CxBase                   *CxBase             =   NULL;
struct IconBase                 *IconBase           =   NULL;
struct NoFragBase               *NoFragBase         =   NULL;
struct PPBase                   *PPBase             =   NULL;
struct ReqToolsBase             *ReqToolsBase       =   NULL;

Prototype void OpenLibraries( void );
Prototype void CloseLibraries( void );
Prototype void Quit( long );
Prototype void OpenDisplay( void );
Prototype void CloseDisplay( void );
Prototype void QuitCommodity( void );
Prototype void myMain( long );
Prototype void MainLoop( void );
Prototype void SetupCustom( void );
Prototype void QuitCommodity( void );
Prototype void SetupCommodity( void );
Prototype void CheckDirExtension( UBYTE * );
Prototype void LoadFile( long );
Prototype void DisplayText( void );
Prototype void MoveTo( UBYTE c, UBYTE r );
Prototype void LineDown( void );
Prototype void LineUp( void );
Prototype void Top( void );
Prototype void Bottom( void );
Prototype void PageDown( void );
Prototype void PageUp( void );
Prototype void Percentage( void );
Prototype void BytesShown( void );
Prototype void InfoLine( void );
Prototype void ErrorLine( UBYTE * );
Prototype void Error( UBYTE * );
Prototype long IsAsciiChar( UBYTE );
Prototype long CheckAscii( UBYTE * );
Prototype void PrintFound( UWORD );
Prototype long CheckPP( void );
Prototype long CountEsc( struct Line *, long );
Prototype long ParseName( void );
Prototype long IsItADir( void );
Prototype void _waitwbmsg( void );

void OpenLibraries( void )
{
    NoFragBase   = ( struct NoFragBase * )   OpenLibrary( "nofrag.library", NOFRAG_VERSION );
    CxBase       = ( struct CxBase * )       OpenLibrary( "commodities.library", 37L );
    IconBase     = ( struct IconBase * )     OpenLibrary( "icon.library", 36L );
    PPBase       = ( struct PPBase * )       OpenLibrary( "powerpacker.library", 34L );
    ReqToolsBase = ( struct ReqToolsBase * ) OpenLibrary( REQTOOLSNAME, REQTOOLSVERSION );

    if ( ! NoFragBase || ! CxBase || ! IconBase || ! ReqToolsBase )
        Quit( 20L );
}

void CloseLibraries( void )
{
    if ( ReqToolsBase )         CloseLibrary(( struct Library * )ReqToolsBase );
    if ( PPBase )               CloseLibrary(( struct Library * )PPBase );
    if ( IconBase )             CloseLibrary( IconBase );
    if ( CxBase )               CloseLibrary( CxBase );
    if ( NoFragBase )           CloseLibrary( NoFragBase );
}

void OpenDisplay( void )
{
    struct DimensionInfo         disp;
    struct Screen               *lock;
    ULONG                        modes, id;
    UWORD                        width, height, depth = 2;

    if ( ! vwCustom ) {
        if ( lock = LockPubScreen( "Workbench" )) {

            width       = lock->Width;
            height      = lock->Height;
            modes       = lock->ViewPort.Modes;
            depth       = lock->BitMap.Depth;
            id          = GetVPModeID( &lock->ViewPort );

            if ( vwArgs[ 6 ] )
                id     |= LORESLACE_KEY;

            UnlockPubScreen( NULL, lock );
        } else
            Quit( 20L );
    } else
        id = vwId;

    GetDisplayInfoData( NULL, ( UBYTE * )&disp, sizeof( struct DimensionInfo ), DTAG_DIMS, id );

    width  = disp.TxtOScan.MaxX + 1;
    height = disp.TxtOScan.MaxY + 1;

    if ( ! ( vwScreen = OpenScreenTags( NULL, SA_Pens,          &vwDriPens,
                                              SA_DisplayID,     id,
                                              SA_Overscan,      OSCAN_TEXT,
                                              SA_Width,         width,
                                              SA_Height,        height,
                                              SA_Depth,         depth,
                                              TAG_DONE )))
        Quit( 20L );

    if ( ! ( vwWindow = OpenWindowTags( NULL, WA_RptQueue,      1,
                                              WA_Width,         width,
                                              WA_Height,        height,
                                              WA_IDCMP,         IDCMP_RAWKEY | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW,
                                              WA_Flags,         WFLG_ACTIVATE | WFLG_RMBTRAP | WFLG_SMART_REFRESH | WFLG_BORDERLESS | WFLG_BACKDROP,
                                              WA_CustomScreen,  vwScreen,
                                              TAG_DONE )))
        Quit( 20L );

    ShowTitle( vwScreen, FALSE );

    if ( vwArgs[ 11 ] ) OFF_SPRITE;

    vwIdPort                = vwWindow->UserPort;
    vwIdMask                = ( 1L << vwIdPort->mp_SigBit );
    vwWdPtr                 = vwProc->pr_WindowPtr;
    vwProc->pr_WindowPtr    = (APTR)vwWindow;
    vwRPort                 = vwWindow->RPort;
    vwFont                  = vwRPort->Font;
    vwMaxLin                = ( height / vwFont->tf_YSize ) - 1;

    sprintf(( char * )&StdStr[ 7 ], "%02.2ldy", vwFont->tf_YSize );

    if ( ! OpenConsole())
        Quit( 20L );

    vwIsOpen                = TRUE;

    if ( ! vwText ) {
        if ( vwFsu ) {
            if ( strlen( vwName )) {
                if ( ! ParseName()) LoadFile( TRUE );
                else                LoadFile( FALSE );
            } else
                LoadFile( TRUE );
        } else
            LoadFile( TRUE );
    }

    if ( vwText ) {
        DisplayText();
        BytesShown();
        InfoLine();
    } else
        InfoLine();

    vwFsu = FALSE;
}

long IsItADir( void )
{
    struct FileInfoBlock    *fib;
    BPTR                     lock;
    long                     ret = -1L;

    if( fib = ( struct FileInfoBlock * )AllocDosObjectTags( DOS_FIB, TAG_DONE )) {
        if( lock = Lock(( char * )vwName, ACCESS_READ )) {
            Examine( lock, fib );
            ret = fib->fib_DirEntryType;
            UnLock( lock );
        }
        FreeDosObject( DOS_FIB, fib );
    }
    return(ret);
}


long ParseName( void )
{
    char *str;
    long  len;

    if( strlen( vwName )) {
        if( str = PathPart( vwName )) {
            if ( IsItADir() < 0 ) {
                if ( *str == '/' ) str++;
                strcpy( vwFile, str );
                len = strlen( vwName ) - strlen( vwFile );
                strcpy( vwPath, vwName );
                vwPath[ len ] = 0;
            } else
                strcpy( vwPath, vwName );
        } else
            strcpy( vwFile, vwName );
    }
    return( strlen( vwFile ));
}

void CloseDisplay( void )
{
    CloseConsole();

    if ( vwArgs[ 11 ] ) ON_SPRITE;

    if ( vwWindow ) {
        vwProc->pr_WindowPtr = vwWdPtr;
        ClearMsgPort( vwIdPort );
        CloseWindow( vwWindow );
        vwWindow = NULL;
        vwIdPort = NULL;
        vwIdMask = NULL;
    }

    if ( vwScreen ) {
        CloseScreen( vwScreen );
        vwScreen = NULL;
    }

    vwIsOpen = FALSE;
}

void Quit( long code )
{
    ON_SPRITE;

    CloseDisplay();
    QuitCommodity();

    if ( vwText )       FreeAscii( vwText );

    CloseLibraries();

#ifndef __DETACH
    if ( vwFArgs )      FreeArgs( vwFArgs );
    _exit( code );
#else
    exit( code );
#endif
}

void SetupCommodity( void )
{
    CxObj               *tmp;
    struct WBArg        *wba;
    char                *pw, **ttypes;
    WORD                 pri;

    if ( WBenchMsg ) {
        ttypes = ArgArrayInit( NULL, ( UBYTE ** )WBenchMsg );

        pri         = ArgInt( ttypes, CX_PRIORITY, CX_DEF_PRIORITY );
        pw          = ArgString( ttypes, CX_POPWINDOW, CX_DEF_POPWINDOW );
        vwViewStr   = ArgString( ttypes, CX_VIEW, CX_DEF_VIEW );
        vwFlushStr  = ArgString( ttypes, CX_FLUSH, CX_DEF_FLUSH );
        vwQuitStr   = ArgString( ttypes, CX_QUIT, CX_DEF_QUIT );
        vwArgs[ 6 ] = ArgString( ttypes, "LACE", NULL );
        vwArgs[ 7 ] = ArgString( ttypes, "SUPER", NULL );
        vwArgs[ 8 ] = ArgString( ttypes, "PRODUCTIVITY", NULL );
        vwArgs[ 9 ] = ArgString( ttypes, "A2024TENHZ", NULL );
        vwArgs[ 10] = ArgString( ttypes, "A2024FIFTEENHZ", NULL );
        vwArgs[ 11] = ArgString( ttypes, "NOPOINTER", NULL );
        vwArgs[ 12] = ArgString( ttypes, "SCROLL", NULL );
        vwTabSize   = ArgInt( ttypes, "TABS", ANSITAB );

        wba = WBenchMsg->sm_ArgList;

        if ( WBenchMsg->sm_NumArgs > 1 ) {
            wba++;
            CurrentDir( wba->wa_Lock );
            if ( wba->wa_Name ) strcpy( vwName, ( char * )wba->wa_Name );
        }
    } else {
        if ( vwArgs[ 0 ] ) strcpy( vwName, (char *)vwArgs[ 0 ] );

        if ( vwArgs[ 1  ] )  pri        = vwArgs[ 1 ];
        else                 pri        = CX_DEF_PRIORITY;
        if ( vwArgs[ 2  ] )  pw         = ( char * )vwArgs[ 2 ];
        else                 pw         = CX_DEF_POPWINDOW;
        if ( vwArgs[ 3  ] )  vwViewStr  = ( char * )vwArgs[ 3 ];
        else                 vwViewStr  = CX_DEF_VIEW;
        if ( vwArgs[ 4  ] )  vwFlushStr = ( char * )vwArgs[ 4 ];
        else                 vwFlushStr = CX_DEF_FLUSH;
        if ( vwArgs[ 5  ] )  vwQuitStr  = ( char * )vwArgs[ 5 ];
        else                 vwQuitStr  = CX_DEF_QUIT;
        if ( vwArgs[ 13 ])   vwTabSize  = (UWORD)(*((ULONG *)vwArgs[ 13 ]));
        else                 vwTabSize  = ANSITAB;
    }

    SetupCustom();

    if ( ! Stricmp( pw, CX_DEF_POPWINDOW )) vwDopen = TRUE;
    else                                    vwDopen = FALSE;

    if ( ! ( vwCxPort = CreateMsgPort()))
        Quit( RETURN_FAIL );

    if ( vwTabSize < MINTAB )       vwTabSize = MINTAB;
    else if ( vwTabSize > MAXTAB )  vwTabSize = MAXTAB;

    vwNewBroker.nb_Pri  = pri;
    vwNewBroker.nb_Port = vwCxPort;

    vwCxMask            = ( 1L <<  vwCxPort->mp_SigBit );

    if ( ! ( vwBroker = CxBroker( &vwNewBroker, NULL )))
        Quit( RETURN_FAIL );

    if ( ! ( tmp = HotKey( vwQuitStr, vwCxPort, CXC_QUIT )))
        Quit( RETURN_FAIL );
    AttachCxObj( vwBroker, tmp );

    if ( ! ( tmp = HotKey( vwFlushStr, vwCxPort, CXC_FLUSH )))
        Quit( RETURN_FAIL );
    AttachCxObj( vwBroker, tmp );

    if ( ! ( tmp = HotKey( vwViewStr, vwCxPort, CXC_VIEW )))
        Quit( RETURN_FAIL );
    AttachCxObj( vwBroker, tmp );

    if( CxObjError( vwBroker ))
        Quit( RETURN_FAIL );

    if(WBenchMsg)
        ArgArrayDone();

    CxOn( vwBroker );
}

void SetupCustom( void )
{
    if ( vwArgs[ 7 ] && ! ModeNotAvailable( DEFAULT_MONITOR_ID | SUPER_KEY )) {
        vwId = DEFAULT_MONITOR_ID | SUPER_KEY;
        vwCustom = TRUE;
    } else if ( vwArgs[ 8 ] && ! ModeNotAvailable( DEFAULT_MONITOR_ID | VGAPRODUCT_KEY )) {
        vwId = DEFAULT_MONITOR_ID | VGAPRODUCT_KEY;
        vwCustom = TRUE;
    } else if ( vwArgs[ 9 ] && ! ModeNotAvailable( DEFAULT_MONITOR_ID | A2024TENHERTZ_KEY )) {
        vwId = DEFAULT_MONITOR_ID | A2024TENHERTZ_KEY;
        vwCustom = TRUE;
    } else if ( vwArgs[ 10 ] && ! ModeNotAvailable( DEFAULT_MONITOR_ID | A2024FIFTEENHERTZ_KEY )) {
        vwId = DEFAULT_MONITOR_ID | A2024FIFTEENHERTZ_KEY;
        vwCustom = TRUE;
    } else
        vwCustom = FALSE;

    if ( vwArgs[ 6 ] ) vwId |= LORESLACE_KEY;
}

void QuitCommodity( void )
{
    if ( vwBroker )     DeleteCxObjAll( vwBroker );

    if( vwCxPort ) {
        ClearMsgPort( vwCxPort );
        DeleteMsgPort( vwCxPort );
    }
}

void MainLoop( void )
{
    struct Message      *msg;
    struct IntuiMessage *imsg;
    ULONG                sig, type, id, class;
    BOOL                 running = TRUE;

    if ( vwDopen )    OpenDisplay();

    do {
        if ( vwIsOpen)   Percentage();

        sig = Wait( SIGBREAKF_CTRL_C | vwCxMask | vwIdMask );

        if (( sig & SIGBREAKF_CTRL_C ) == SIGBREAKF_CTRL_C ) {
            if ( ! vwPrinting ) running = FALSE;
        } else if (( sig & vwCxMask ) == vwCxMask ) {

            while (( msg = (struct Message *)GetMsg( vwCxPort ))) {

                id   = CxMsgID(( CxMsg * )msg );
                type = CxMsgType(( CxMsg * )msg );
                ReplyMsg( msg );

                switch( type ) {

                    case    CXM_IEVENT:

                        switch( id ) {

                            case    CXC_VIEW:
                                    if ( ! vwIsOpen )
                                        OpenDisplay();
                                    else {
                                        ScreenToFront( vwScreen );
                                        if( vwArgs[ 11 ] ) OFF_SPRITE;
                                    }
                                    break;

                            case    CXC_FLUSH:
                                    if ( ! vwIsOpen ) {
                                        if ( vwText ) FreeAscii( vwText );
                                        vwText = NULL;
                                    }
                                    break;

                            case    CXC_QUIT:
                                    if( ! vwIsOpen ) {
                                        if ( ! vwPrinting ) running = FALSE;
                                    }
                                    break;
                        }
                        break;

                    case    CXM_COMMAND:
                        switch( id ) {

                            case    CXCMD_KILL:
                                if ( ! vwPrinting ) running = FALSE;
                                break;

                            case    CXCMD_DISABLE:
                                CxOff( vwBroker );
                                break;

                            case    CXCMD_ENABLE:
                                CxOn( vwBroker );
                                break;

                            case    CXCMD_UNIQUE:
                            case    CXCMD_APPEAR:
                                if ( ! vwIsOpen )
                                    OpenDisplay();
                                else {
                                    ScreenToFront( vwScreen );
                                    if( vwArgs[ 11 ] ) OFF_SPRITE;
                                }
                                break;

                            case    CXCMD_DISAPPEAR:
                                if ( vwIsOpen )
                                    CloseDisplay();
                                break;
                        }
                        break;
                }
            }
        } else if ( vwIsOpen ) {
            if (( sig & vwIdMask ) == vwIdMask ) {

                while ( ReadMsgPort( vwWindow->UserPort )) {
                    Percentage();

                    switch( vwClass ) {
                        case IDCMP_RAWKEY:
                            HandleKeyboard( vwCode, vwQualifier );
                            break;

                        case IDCMP_ACTIVEWINDOW:
                            if ( vwArgs[ 11 ] ) OFF_SPRITE;
                            break;

                        case IDCMP_INACTIVEWINDOW:
                            if ( vwArgs[ 11 ] ) ON_SPRITE;
                            break;
                    }
                    if ( ! vwIsOpen ) break;
                }
            }
        }
    } while( running == TRUE );

    if( vwIsOpen )
        CloseDisplay();
    CxOff( vwBroker );
    Quit(NULL);
}

void CheckDirExtension( UBYTE *name )
{
    UWORD   len = strlen( name );

    if ( len ) {
        if ( name[ len - 1 ] != ':' && name[ len - 1 ] != '/' )
            strcat( name, "/" );
    }
}

void LoadFile( long request )
{
    UBYTE           *ppdata, *fname;
    ULONG            pplen;
    BPTR             ppout;
    BOOL             pptemp = FALSE, ret = TRUE;
    LONG             pperr;
    struct BuffIO   *file = NULL;
    struct Line     *line;

    ErrorLine( CX_NAME " v" CX_VERSION " © 1991-92 Jaba Development" );

    if ( request ) {
        if ( vwArgs[ 11 ] ) ON_SPRITE;

        ret = FileRequest( vwWindow, "Select file to load...", vwFile, vwPath, vwPatt, FR_LOAD );

        if ( vwArgs[ 11 ] ) OFF_SPRITE;
    }

    if ( ret ) {
        if ( vwText ) {
            FreeAscii( vwText );
            vwText = NULL;
            ClrBlk();
        }

        Inform( ClearStr );
        Inform( StdStr );

        Busy();

        if ( CheckPP()) {
            if ( PPBase ) {
                ErrorLine( "Loading and decrunching file..." );
                if ( vwArgs[ 11 ] ) ON_SPRITE;
                if (( pperr = ppLoadData( vwName, DECR_POINTER, MEMF_PUBLIC, &ppdata, &pplen, NULL )) < 0 ) {
                    switch( pperr ) {
                        case    PP_OPENERR:
                            Error( "PPLib: Can't open the file." );
                            break;
                        case    PP_READERR:
                            Error("PPLIB: Read error.");
                            break;
                        case    PP_NOMEMORY:
                            Error("PPLIB: Out of memory.");
                            break;
                        case    PP_PASSERR:
                            Error("PPLIB: Incorrect password.");
                            break;
                        case    PP_UNKNOWNPP:
                            Error("PPLIB: Unknown PowerPacker version.");
                            break;
                    }
                    return;
                }

                if ( vwArgs[ 11 ] ) OFF_SPRITE;
                fname = "T:view.pp.tmp.v" CX_VERSION ".decrunched";
                if ( ppout = Open( fname, MODE_NEWFILE )) {
                    if ( Write( ppout, ppdata, pplen ) != pplen )
                        Error( "Error writing temporary file." );
                    else
                        pptemp = TRUE;
                    Close( ppout );
                } else
                    Error( "Can't open temporary file." );

                if ( ppdata ) FreeMem( ppdata, pplen );

                if ( ! pptemp ) goto ppCleanUp;
            } else
                Error( "Can't load powerpacker files\nwithout the powerpacker.library." );
        } else {
            ErrorLine( "Loading file..." );
            fname = vwName;
        }

        if ( CheckAscii( fname )) {
            if ( vwText = AllocAscii( vwTabSize, MaxCol() + 1, ATF_SkipEsc | ATF_TabConvert )) {
                if ( file = BOpen( fname, MODE_OLDFILE )) {
                    while( line = BGetS( file, vwText ))
                        AddTail(( struct List * )vwText, ( struct Node * )line );
                    switch( BIoErr( file )) {
                        case    ASE_READ:
                            Error( "Read error." );
                            goto CleanExit;
                        case    ASE_NOMEM:
                            Error( "Out of memory." );
                            goto CleanExit;
                    }

                    BClose( file );
                    vwFirst = vwText->First;
                    vwFound = FALSE;
                    DisplayText();
                    BytesShown();
                    InfoLine();
                    goto ppCleanUp;
                } else {
                    Error( "Could not open the file." );
                    goto CleanExit;
                }
            } else {
                Error( "Out of memory." );
                goto CleanExit;
            }
        } else {
            Error( "File contains binary." );
            goto CleanExit;
        }
    } else goto ppCleanUp;

CleanExit:
    if ( vwText ) {
        FreeAscii( vwText );
        vwText = NULL;
    }

    if ( file ) BClose( file );

ppCleanUp:
    ClearMsgPort( vwIdPort );
    Ready();
    if ( pptemp )   DeleteFile( fname );
}

void DisplayText( void )
{
    UWORD   y = 1, i = 0;

    if ( ! vwText )    return;

    for(  vwLast = vwFirst; i < vwMaxLin; i++, vwLast = vwLast->Next, y++ ) {
        if ( vwLast == vwText->Last->Next )  break;
        MoveTo( 1 , y );
        Display( vwLast );
        if ( vwFound && vwLast == vwSearch.Line ) PrintFound( y );
    }
    vwYMax = y - 1;
}

void MoveTo( UBYTE c, UBYTE r )
{
    sprintf((char *)&MoveStr[ 1 ], "%02ld;%02ldH", r, c );
    Inform( MoveStr );
}

void LineDown( void )
{
    if ( ! vwText )    return;
    if ( vwLast == vwText->Last->Next ) return;

    vwFirst = vwFirst->Next;
    Inform( ScrUpStr );
    MoveTo( 1, vwYMax  );
    Display( vwLast );

    vwShown += vwLast->Size;

    if ( vwFound && vwLast == vwSearch.Line ) PrintFound( vwYMax );

    vwLast = vwLast->Next;
}

void LineUp( void )
{
    if ( ! vwText )    return;
    if ( vwFirst == vwText->First ) return;

    vwLast   = vwLast->Prev;
    vwShown -= vwLast->Size;
    vwFirst  = vwFirst->Prev;

    Inform( ScrDnStr );
    MoveTo( 1, 1 );
    Display( vwFirst );

    if ( vwFound && vwFirst == vwSearch.Line ) PrintFound( 1 );
}

void Top( void )
{
    if ( ! vwText ) return;
    if ( vwFirst == vwText->First ) return;

    vwFirst = vwText->First;

    Inform( ClearStr );
    DisplayText();
    BytesShown();
}

void Bottom( void )
{
    UWORD   i;

    if ( ! vwText )    return;
    if ( vwLast == vwText->Last->Next ) return;

    vwLast = vwFirst = vwText->Last;

    for( i = 1; i < vwMaxLin; i++ )
        vwFirst = vwFirst->Prev;

    vwShown = vwText->NumBytes;

    Inform( ClearStr );
    DisplayText();
}

void PageDown( void )
{
    UWORD   i;

    if ( ! vwText ) return;
    if ( vwLast == vwText->Last->Next ) return;

    if ( ! vwArgs[ 12 ] ) {
        for( i = 1; i < vwMaxLin; i++ ) {
            vwFirst  = vwFirst->Next;
            vwShown += vwLast->Size;
            if (( vwLast = vwLast->Next ) == vwText->Last->Next ) break;
        }
        Inform( ClearStr );
        DisplayText();
    } else {
        for ( i = 1; i < vwMaxLin; i++ ) {
            LineDown();
            Percentage();
        }
    }
}

void PageUp( void )
{
    UWORD   i;

    if ( ! vwText ) return;
    if ( vwFirst == vwText->First ) return;

    if ( ! vwArgs[ 12 ] ) {
        for( i = 1; i < vwMaxLin; i++ ) {
            vwLast   = vwLast->Prev;
            vwShown -= vwLast->Size;
            if (( vwFirst = vwFirst->Prev ) == vwText->First ) break;
        }
        Inform( ClearStr );
        DisplayText();
    } else {
        for ( i = 1; i < vwMaxLin; i++ ) {
            LineUp();
            Percentage();
        }
    }
}

void Percentage( void )
{
    ULONG   perc;
    char    pcbuf[5];

    if ( ! vwText )    return;

    perc = ( ULONG )( vwShown * 100 / vwText->NumBytes );

    if ( perc == 100 && ( vwLast != vwText->Last->Next )) perc = 99;

    vwNum = perc;

    sprintf(pcbuf,"%3ld%%",perc);

    SetAPen( vwRPort, 3 );
    SetBPen( vwRPort, 2 );
    SetDrMd( vwRPort, JAM2 );
    Move( vwRPort, 544, vwFont->tf_Baseline );
    Text( vwRPort, pcbuf, strlen( pcbuf ));
    SetAPen( vwRPort, 1 );
    Move(  vwRPort, 584, vwFont->tf_Baseline );
    Text( vwRPort, "Shown.", 6);
}

void BytesShown( void )
{
    struct Line *line;

    vwShown = 0L;

    for ( line = vwText->First; line != vwLast; line = line->Next )
        vwShown += line->Size;
}

void InfoLine( void )
{
    UBYTE   ibuf[100];

    ClrLin();

    vwErr = FALSE;

    SetAPen( vwRPort, 1 );
    SetDrMd( vwRPort, JAM1 );

    if ( vwText )
        sprintf( ibuf, "File : %-31.31ls %-6.6ld Lines, %-6.6ld Bytes.", &vwFile[0], vwText->NumLines - vwText->NumSplit, vwText->NumBytes );
    else
        strcpy( ibuf, "No text in memory (press 'l' to load a file)" );

    Move( vwRPort, 1, vwFont->tf_Baseline );
    Text( vwRPort, ibuf, strlen( ibuf ));
}

void ErrorLine( UBYTE *text )
{
    ClrLin();

    vwErr = TRUE;

    SetAPen( vwRPort, 1 );
    SetDrMd( vwRPort, JAM1 );
    Move( vwRPort, 1, vwFont->tf_Baseline );
    Text( vwRPort, text, strlen( text ));
}

void Error( UBYTE *error )
{
    rtEZRequestTags( error, "Continue", NULL, NULL,
                     RT_ReqPos,         REQPOS_CENTERSCR,
                     RT_WaitPointer,    TRUE,
                     RTEZ_ReqTitle,     CX_NAME " " CX_VERSION,
                     RTEZ_Flags,        EZREQF_CENTERTEXT,
                     TAG_DONE );

    ClearMsgPort( vwIdPort );
}

long IsAsciiChar( UBYTE chr )
{
    if ( chr > 0x00 && chr < 0x09 ) return( FALSE );
    if ( chr > 0x0d && chr < 0x1b ) return( FALSE );
    if ( chr > 0x1b && chr < 0x20 ) return( FALSE );
    if ( chr > 0x7f && chr < 0x9b ) return( FALSE );
    return( TRUE );
}

long CheckAscii( UBYTE *name )
{
    BPTR        file;
    UBYTE       memory[ 100 ];
    ULONG       cnt, ret = TRUE, len;

    if ( file = Open( name, MODE_OLDFILE )) {
        len = Read( file, memory, 100L );
        Close( file );
        if ( len ) {
            for ( cnt = 0; cnt < len; cnt++ ) {
                if ( ! IsAsciiChar( memory[ cnt ] )) {
                    ret = FALSE;
                    break;
                }
            }
        }
    }
    return( ret );
}

long CheckPP( void )
{
    BPTR    file;
    ULONG   ident;

    if ( ! ( file = Open( vwName, MODE_OLDFILE ))) {
        strcat( vwName, ".pp" );
        if ( ! ( file = Open( vwName, MODE_OLDFILE ))) {
            vwName[ strlen( vwName ) - 3 ] = 0;
            return FALSE;
        }
    }
    Read( file, &ident, 4L );
    Close( file );

    if( ident == 'PP20' || ident == 'PX20' ) return TRUE;
    return FALSE;
}

long CountEsc( struct Line *line, long off )
{
    UWORD   i;
    LONG    c = 0L;
    char   *ptr = line->Text, chr;

    for( i = 0; i <= off; i++ ) {
        if( *ptr == ESC || *ptr == CSI ) {
            while( 1 ) {
               c++;
               i++;
               chr = ( *ptr++ ) - ' ';
               if(( chr >= '?' && chr <= 'Z' ) || !chr ) break;
            }
        }
        else ptr++;
    }

    return(c);
}

void PrintFound( UWORD y )
{
    char wrd[256];

    setmem( &wrd[ 0 ], 256, 0 );

    Inform( "\033[32;43m" );
    strncpy( wrd, (char *)&vwSearch.Line->Text[ vwSearch.TextOffset ], vwSearch.StringSize );
    MoveTo( vwSearch.TextOffset - CountEsc( vwSearch.Line, vwSearch.TextOffset ) + 1, y );
    Inform( wrd );
    Inform( ResStr );
}

void myMain( long cli )
{
    OpenLibraries();

    vwFile[ 0 ] = vwName[ 0 ] = vwPath[ 0 ] = 0;

    strcpy( vwPatt, "~(#?.info)" );

#ifndef __DETACH
    if ( ! cli ) {
        if ( WBenchMsg->sm_ArgList->wa_Lock )
            CurrentDir( WBenchMsg->sm_ArgList->wa_Lock );
    }
#endif

    SetupCommodity();
    MainLoop();
    return;
}

#ifdef __DETACH
void main( long numargs, long *argarray )
{
    vwProc = ( struct Process * )FindTask( NULL );
    vwArgs = argarray;

    myMain( TRUE );
    return;

    atoi("");
}

void wbmain( struct WBStartup *su )
{
    vwArgs    = &vwWBArgs[ 0 ];
    WBenchMsg = su;
    myMain( FALSE );
    return;
}
#else
extern struct Library       *SysBase;
extern struct WBStartup     *_WBMsg;

void _main( void )
{
    vwProc = ( struct Process * )FindTask( NULL );

    if ( SysBase->lib_Version < 36 )
        _exit( RETURN_FAIL );

    if ( vwProc->pr_CLI ) {
        if ( vwFArgs = ReadArgs( Template, &vwArgs[ 0 ], &vwIArgs ))
            myMain( TRUE );
        return;
    } else {
        WBenchMsg = _WBMsg;
        myMain( FALSE );
        return;
    }

    _waitwbmsg();
    atoi("");
}
#endif
