/*----------------------------------------------------------*/
/*                                                          */
/*   Turbo Vision 1.0                                       */
/*   Copyright (c) 1991 by Borland International            */
/*                                                          */
/*   Turbo Vision TVEDIT source file                        */
/*----------------------------------------------------------*/

// That's the first include because is used to configure the editor.
#include "ceditint.h"

#define Uses_TApplication
#define Uses_TMenuBar
#define Uses_TRect
#define Uses_TSubMenu
#define Uses_TMenuItem
#define Uses_TStatusLine
#define Uses_TStatusItem
#define Uses_TStatusDef
#define Uses_TPoint
#define Uses_MsgBox
#define Uses_TFileDialog
#define Uses_TDeskTop
#define Uses_TStringCollection
#define Uses_TEditor
#define Uses_fpstream
#define Uses_TSortedListBox
#include <tv.h>

#include "tkeys.h"

#define Uses_TCEditor
#define Uses_TCEditWindow
#include "ceditor.h"

#include "setconst.h"

#ifdef RHIDE
#define Uses_TEditorApp
#include "tvedit.h"
#else
#include "tvedit2.h"
#endif

#include <stdlib.h>
#include <stdarg.h>
#include <strstream.h>
#include <iomanip.h>
#include <stdio.h>
#ifdef __GNUC__
#include <errno.h>
#endif

#if defined(STANDALONE)
#include "inf.h"
#endif

#if defined(STANDALONE) || defined(RHIDE)
int SelectFunctionToJump(char *b, unsigned l);
#endif


TMenuBar *TEditorApp::initMenuBar( TRect r )
{

      TSubMenu& sub1 = *new TSubMenu( _("~F~ile"), kbAltF ) +
        *new TMenuItem( _("~O~pen"), cmOpen, kbF3 ) +
        *new TMenuItem( _("~N~ew"), cmNew, kbNoKey ) +
        *new TMenuItem( _("~S~ave"), cmSave, kbF2, hcNoContext, "F2" ) +
        *new TMenuItem( _("S~a~ve as..."), cmSaveAs, kbNoKey ) +
        *new TMenuItem( _("S~a~ve as UNIX..."), cmcSaveAsUNIX, kbNoKey ) +
               newLine() +
        *new TMenuItem( _("~C~hange dir..."), cmChangeDrct, kbNoKey ) +
        *new TMenuItem( _("~D~OS shell"), cmDosShell, kbNoKey ) +
        *new TMenuItem( _("E~x~it"), cmQuit, kbAltX, hcNoContext, "Alt-X" );

      TSubMenu& sub2 = *new TSubMenu( _("~E~dit"), kbAltE ) +
        *new TMenuItem( _("~U~ndo"), cmcUndo, kbAltBack, hcNoContext, "Alt+BackSpace" ) +
        *new TMenuItem( _("~R~edo"), cmcRedo, kbNoKey ) +
               newLine() +
        *new TMenuItem( _("Cu~t~"), cmcCut, kbShiftDel, hcNoContext, "Shift-Del" ) +
        *new TMenuItem( _("~C~opy"), cmcCopy, kbCtrlIns, hcNoContext, "Ctrl-Ins" ) +
        *new TMenuItem( _("~P~aste"), cmcPaste, kbShiftIns, hcNoContext, "Shift-Ins" ) +
        *new TMenuItem( _("~S~how clipboard"), cmShowClip, kbNoKey ) +
               newLine() +
        *new TMenuItem( _("~C~lear"), cmcClear, kbCtrlDel, hcNoContext, "Ctrl-Del" ) +
               newLine() +
        *new TMenuItem( _("S~e~t Local"), cmcSetLocalOptions, kbAltL, hcNoContext, "Alt-L" ) +
        *new TMenuItem( _("Set ~G~lobal"), cmcSetGlobalOptions, kbAltG, hcNoContext, "Alt-G" ) +
               newLine() +
        *new TMenuItem( _("E~x~pand all tabs"), cmcExpandAllTabs, kbNoKey ) +
        *new TMenuItem( _("C~o~mpact text"), cmcCompactBuffer, kbNoKey ) +
               newLine() +
        *new TMenuItem( _("~J~ump to function"), cmcJumpToFunction, kbNoKey ) +
        *new TMenuItem( _("~P~rofile Editor"), cmcProfileEditor, kbNoKey );

      TSubMenu& sub3 = *new TSubMenu( _("~S~earch"), kbAltS ) +
        *new TMenuItem( _("~F~ind..."), cmcFind, kbNoKey ) +
        *new TMenuItem( _("~R~eplace..."), cmcReplace, kbNoKey ) +
        *new TMenuItem( _("~S~earch again"), cmcSearchAgain, kbNoKey );

      TSubMenu& sub4 = *new TSubMenu( _("~M~acro"), kbAltM ) +
        *new TMenuItem( _("~R~ecord"), cmcRecordMacro, kbAltR, hcNoContext, "Alt-R" ) +
        *new TMenuItem( _("~S~top"), cmcStopMacro, kbAltT, hcNoContext, "Alt-T" ) +
        *new TMenuItem( _("~P~lay"), cmcPlayMacro, kbAltP, hcNoContext, "Alt-P" );

      TSubMenu& sub5 = *new TSubMenu( _("Re~c~tangle"), kbAltR ) +
        *new TMenuItem( _("~S~tart"), cmcSelRectStart, kbNoKey ) +
        *new TMenuItem( _("~E~nd"),   cmcSelRectEnd,   kbNoKey ) +
        *new TMenuItem( _("~H~ide"), cmcSelRectHide,   kbNoKey ) +
               newLine() +
        *new TMenuItem( _("~C~opy"),  cmcSelRectCopy,  kbNoKey ) +
        *new TMenuItem( _("~P~aste"), cmcSelRectPaste, kbNoKey ) +
        *new TMenuItem( _("Cu~t~"),   cmcSelRectCut,   kbNoKey ) +
        *new TMenuItem( _("C~l~ear"), cmcSelRectDel,   kbNoKey ) +
        *new TMenuItem( _("~M~ove"),  cmcSelRectMove,  kbNoKey );

      TSubMenu& sub6 = *new TSubMenu( _("~W~indows"), kbAltW ) +
        *new TMenuItem( _("~S~ize/move"),cmResize, kbCtrlF5, hcNoContext, "Ctrl-F5" ) +
        *new TMenuItem( _("~Z~oom"), cmZoom, kbF5, hcNoContext, "F5" ) +
        *new TMenuItem( _("~T~ile"), cmTile, kbNoKey ) +
        *new TMenuItem( _("C~a~scade"), cmCascade, kbNoKey ) +
        *new TMenuItem( _("~N~ext"), cmNext, kbF6, hcNoContext, "F6" ) +
        *new TMenuItem( _("~P~revious"), cmPrev, kbShiftF6, hcNoContext, "Shift-F6" ) +
        *new TMenuItem( _("~C~lose"), cmClose, kbAltF3, hcNoContext, "Alt-F3" )
#ifdef STANDALONE
        +
        *new TMenuItem( _("~L~ist"), cmListWin, kbAlt0, hcNoContext, "Alt-0" ) +
        *new TMenuItem( _("~U~ser Screen"), cmUserScreen, kbAltF5, hcNoContext, "Alt-F5" );
#else
        ;
#endif

#ifdef STANDALONE
      TSubMenu& sub7 = *new TSubMenu( "~H~elp", kbAltH ) +
        *new TMenuItem( "~I~NF View", cmInfView, kbF1, hcNoContext, "F1" );

      TSubMenu& sub8 = *new TSubMenu( "~V~arious", kbAltH ) +
        *new TMenuItem( "~C~alculator", cmCalculator, kbF9, hcNoContext, "F9" );

    r.b.y = r.a.y+1;
    return new TMenuBar( r, sub1 + sub2 + sub3 + sub4 + sub5 + sub6 + sub7 + sub8 );
#else
    r.b.y = r.a.y+1;
    return new TMenuBar( r, sub1 + sub2 + sub3 + sub4 + sub5 + sub6 );
#endif
}

TStatusLine *TEditorApp::initStatusLine( TRect r )
{
    r.a.y = r.b.y-1;
    return new TStatusLine( r,
        *new TStatusDef( 0, 255 ) +
            *new TStatusItem( _("~F2~ Save"), kbF2, cmSave ) +
            *new TStatusItem( _("~F3~ Open"), kbF3, cmOpen ) +
            *new TStatusItem( _("~Alt-F3~ Close"), kbAltF3, cmClose ) +
            *new TStatusItem( _("~F5~ Zoom"), kbF5, cmZoom ) +
            *new TStatusItem( _("~F6~ Next"), kbF6, cmNext ) +
            *new TStatusItem( _("~F10~ Menu"), kbF10, cmMenu ) +
            *new TStatusItem( 0, kbCtrlF5, cmResize )
#ifdef STANDALONE
            +
            *new TStatusItem( 0, kbAltF1, cmLastHelp )
        +
        *new TStatusDef( hcInfView, hcInfView+5 ) +
            *new TStatusItem("~Alt-F1~ Back", kbAltF1, cmInfBack ) +
            *new TStatusItem("~Alt-F10~ Control", kbAltF10, cmInfControl ) +
            *new TStatusItem("~^H~ Help", kbCtrlH, cmInfHelp ) +
            *new TStatusItem("~ESC~ Close", kbEsc, cmClose ) +
            *new TStatusItem("~Alt-I~ Include", kbAltI, cmInfPasteIn ) +
            *new TStatusItem("~Alt-B~ Bookmark", kbAltB, cmInfBookM ) +
            *new TStatusItem( 0, kbF5, cmZoom )
        +
        *new TStatusDef( hcListWin, hcListWin+5 ) +
            *new TStatusItem("~Del~ Close", kbDel, cmDelete )
#endif
            );

}

void TEditorApp::outOfMemory()
{
    messageBox(_("Not enough memory for this operation."), mfError | mfOKButton );
}

typedef char *_charPtr;
typedef TPoint *PPoint;

void ApplyBroadcast(TView *p, void *e)
{
 p->handleEvent(*(TEvent *)e);
}


#pragma warn -rvl

ushort doEditDialog( int dialog, ... )
{
    va_list arg;

    char buf[256]; // 80 is not enough
    ostrstream os( buf, sizeof( buf ) );
    switch( dialog )
        {
        case edOutOfMemory:
            return messageBox( _("Not enough memory for this operation"),
                               mfError | mfOKButton );
        case edReadError:
            {
            char *fname;
            va_start( arg, dialog );
            fname = va_arg(arg,_charPtr);
            va_end(arg);
            return messageBox(mfError|mfOKButton,"%s %s. %s(%d)",
                  _("Error reading file "),fname,strerror(errno),errno);
            }
        case edWriteError:
            {
            va_start( arg, dialog );
            os << _("Error writing file ") << va_arg( arg,_charPtr )
               << "." << ends;
            va_end( arg );
            return messageBox( buf, mfError | mfOKButton );
            }
        case edCreateError:
            {
            va_start( arg, dialog );
            os << _("Error creating file ") << va_arg( arg, _charPtr )
               << "." << ends;
            va_end( arg );
            return messageBox( buf, mfError | mfOKButton );
            }
        case edSaveModify:
            {
            va_start( arg, dialog );
            os << va_arg( arg, _charPtr )
               << _(" has been modified. Save?") << ends;
            va_end( arg );
            return messageBox( buf, mfInformation | mfYesNoCancel );
            }
        case edSaveUntitled:
            return messageBox( _("Save untitled file?"),
                               mfInformation | mfYesNoCancel );
        case edSaveAs:
            {
            va_start( arg, dialog );
            return execDialog( new TFileDialog( "*.*",
                                                _("Save file as"),
                                                _("~N~ame"),
                                                fdOKButton,
                                                101 ), va_arg( arg, _charPtr ) );
            }

        case edFind:
            {
            va_start( arg, dialog );
            return execDialog( createFindDialog(), va_arg( arg, _charPtr ) );
            }

        case edSearchFailed:
            return messageBox( _("Search string not found."),
                               mfError | mfOKButton );
        case edReplace:
            {
            va_start( arg, dialog );
            return execDialog( createReplaceDialog(), va_arg( arg, _charPtr ) );
            }

        case edReplacePrompt:
            {
            //  Avoid placing the dialog on the same line as the cursor
            TRect r( 0, 1, 40, 8 );
            r.move( (TProgram::deskTop->size.x-r.b.x)/2, 0 );
            TPoint t = TProgram::deskTop->makeGlobal( r.b );
            t.y++;
            va_start( arg, dialog );
            TPoint *pt = va_arg( arg, PPoint );
            if( pt->y <= t.y )
                r.move( 0, TProgram::deskTop->size.y - r.b.y - 2 );
            va_end( arg );
            return messageBoxRect( r, _("Replace this occurence?"),
                                   mfYesNoCancel | mfInformation );
            }

        case edLineLenght:
            {
             va_start( arg, dialog );
             os << va_arg(arg,uint32) << _(" bytes selected") << ends;
             return messageBox(buf,mfInformation | mfOKButton);
            }

        case edGotoLine:
            {
             int *p;

             va_start( arg, dialog );
             p=va_arg(arg,int *);
             os << *p << ends;

             if (execDialog( createGotoLineDialog(), buf ) == cmOK)
               {
                sscanf(buf,"%d",p);
                return 1;
               }
             return 0;
            }

#if defined(STANDALONE) || defined(RHIDE)
        case edJumpToFunction:
            {
             int *p;
             char *bu;
             unsigned l;

             va_start( arg, dialog );
             p=va_arg(arg,int *);
             bu=va_arg(arg,char *);
             l=va_arg(arg,unsigned);

             *p=SelectFunctionToJump(bu,l);

             return (*p!=-1);
            }
#endif

        case edSetLocalOptions:
            {
             void *p;
             va_start( arg, dialog );
             p=va_arg(arg,void *);
             return (execDialog( createSetLocalOptions(), p ) == cmOK);
            }

        case edSetGlobalOptions:
            {
             void *p;
             va_start( arg, dialog );
             p=va_arg(arg,void *);
             ushort ret=execDialog( createSetGlobalOptions(), p );
             if (ret==cmApplyAll)
               {
                TEvent event;
                event.what = evBroadcast;
                event.message.command = cmcSetGlobalOptions;
                event.message.infoPtr = p;
                TEditorApp::deskTop->forEach(ApplyBroadcast,&event);
               }
             return (ret==cmApplyAll) || (ret==cmOK);
            }

        case edLineOverflow:
            return messageBox( _("Line too long, cut it?"),
                               mfError | mfYesButton | mfNoButton);
        }
 return 0;
}

#pragma warn .rvl



