//=======================================================================
//	videCmdw.cpp:	Source for videCmdwindow class
//=======================================================================

#include <v/vnotice.h>	// for vNoticeDialog
#include <v/vkeys.h>	// to map keys
#include <v/vfilesel.h>
#include <v/vfontsel.h>
#include <v/vutil.h>
#include <v/vynreply.h>
#include <v/vreply.h>
#include <v/vicon.h>

#include "videapp.h"	// main header for some global defs

#include "videcmdw.h"	// our header

#include "vrundlg.h"
#include "vseeci.h"	// command interp for See

//	Start defines for the main window with 100

//@V@:BeginIDs
    enum {
	m_FirstCmd = 100, 		// Dummy Command
	m_Options,			// set options
        m_View,				// view a file R/O
        m_SaveClose,
        m_EditHelp,
        m_Make,
        m_MakeAll,
        m_MakeClean,
        m_MakeDebug,
        m_MakeArgs,
        m_StopMake,
        m_SelectMake,

	m_Project,           // Project menu
	m_ProjectNew,        // ProjectDialog menu
	m_ProjectOpen, 	     // ProjectDialog menu
	m_ProjectEdit,
	m_ProjectSave,
	m_ProjectClose,

        m_Tools,
        m_RunVgen,
        m_RunViconed,
        m_RunCmd,
        m_RunShell,

        lblMkFile,
	lblLineCol,			// Status Bar
	lblIns,
	lblSBlank,
	lblEMsg,
        lblStatTitle,
	blkLast				// Last item
      };
//@V@:EndIDs

//@V@:BeginPulldownMenu FileMenu
    static vMenu FileMenu[] =
      {
	{"&New", M_New, isSens, notChk, noKeyLbl, noKey, noSub},
	{"&Open...", M_Open, isSens, notChk, noKeyLbl, noKey, noSub},
        {"&View...", m_View, isSens, notChk, noKeyLbl, noKey, noSub},
	{"&Save", M_Save, isSens, notChk, noKeyLbl, noKey, noSub},
	{"Save &as...", M_SaveAs, isSens, notChk, noKeyLbl, noKey, noSub},
	{"&Close", M_CloseFile, isSens, notChk, noKeyLbl, noKey, noSub},
        {"Save and Close", M_SaveClose, isSens, notChk, noKeyLbl, noKey, noSub},
	{"-", M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
	{"E&xit", M_Exit, isSens, notChk, noKeyLbl, noKey, noSub},
	{NULL}
      };

//@V@:BeginPulldownMenu EditMenu
    static vMenu EditMenu[] =
      {
	{"Cut  ", M_Cut, notSens, notChk, "^X", noKey, noSub},
	{"Copy ", M_Copy, notSens, notChk, "^C", noKey, noSub},
	{"Paste", M_Paste, notSens, notChk, "^V", noKey, noSub},
	{"-", M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
	{"Find", edFind, isSens,notChk,noKeyLbl,noKey,noSub},
	{"Find Next", edFindNext, isSens,notChk,noKeyLbl,noKey,noSub},
	{"Find Matching Paren", edBalMatch, isSens,notChk,noKeyLbl,noKey,noSub},
	{"-", M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
        {"Edit Help", m_EditHelp, isSens, notChk, noKeyLbl, noKey, noSub},

	{NULL}
      };
//@V@:EndPulldownMenu

//@V@:BeginPulldownMenu OptMenu
    static vMenu OptMenu[] =
      {
	{"Font", M_Font,isSens,notChk,noKeyLbl,noKey,noSub},
	{NULL}
      };
//@V@:EndPulldownMenu

//@V@:BeginPulldownMenu MakeMenu
    static vMenu MakeMenu[] =
      {
 	{"Select Makefile", m_SelectMake, isSens, notChk, noKeyLbl, noKey, noSub},
        {"-", M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
        {"Make", m_MakeAll, isSens, notChk, noKeyLbl, noKey, noSub},
        {"Make Clean", m_MakeClean, isSens, notChk, noKeyLbl, noKey, noSub},
        {"Make <target>", m_MakeArgs, isSens, notChk, noKeyLbl, noKey, noSub},
        {"Make Debug", m_MakeDebug, notSens, notChk, noKeyLbl, noKey, noSub},
        {"-", M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
        {"Stop Make", m_StopMake, isSens, notChk, noKeyLbl, noKey, noSub},
        {NULL}
      };
//@V@:EndPulldownMenu

//@V@:BeginPulldownMenu ToolsMenu
    static vMenu ToolsMenu[] =
      {
        {"Run a program", m_RunCmd, isSens, notChk, noKeyLbl, noKey, noSub},
        {"Run OS Shell", m_RunShell, isSens, notChk, noKeyLbl, noKey, noSub},
        {"-", M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
        {"V App Gen", m_RunVgen, isSens, notChk, noKeyLbl, noKey, noSub},
        {"V Icon Editor", m_RunViconed, isSens, notChk, noKeyLbl, noKey, noSub},
        {NULL}
      };
//@V@:EndPulldownMenu

//@V@:BeginPulldownMenu ProjectMenu
    static vMenu ProjectMenu[] =
      {
	{"&Open", m_ProjectOpen, isSens, notChk, noKeyLbl, noKey, noSub},
	{"&Close", m_ProjectClose, isSens, notChk, noKeyLbl, noKey, noSub},
	{"&New", m_ProjectNew, isSens, notChk, noKeyLbl, noKey, noSub},
	{"&Edit", m_ProjectEdit, isSens, notChk, noKeyLbl, noKey, noSub},
	{"&Save", m_ProjectSave, isSens, notChk, noKeyLbl, noKey, noSub},
        {NULL}
      };
//@V@:EndPulldownMenu

//@V@:BeginMenu StandardMenu
    static vMenu StandardMenu[] =
      {
	{"&File", M_File, isSens, notUsed, notUsed, noKey, &FileMenu[0]},
	{"&Edit", M_Edit, isSens, notUsed, notUsed, noKey, &EditMenu[0]},
	{"&Make", m_Make, isSens, notUsed, notUsed, noKey, &MakeMenu[0]},
        {"&Project",m_Project,isSens,notUsed,notUsed,noKey,&ProjectMenu[0]},
        {"&Tools", m_Tools, isSens, notUsed, notUsed, noKey, &ToolsMenu[0]},
        {"&Options", m_Options, isSens, notUsed, notUsed, noKey, &OptMenu[0]},
	{NULL}
      };
//@V@:EndMenu

//vbm1
#define open_width 16
#define open_height 16
static unsigned char open_bits[] = {
 0x00,0x00,0x00,0x0e,0x00,0x51,0x00,0x60,0x00,0x70,0x1c,0x00,0xe2,0x07,0x02,
 0x04,0x02,0x04,0xc2,0x7f,0xa2,0x2a,0x52,0x15,0xaa,0x0a,0x56,0x05,0xfc,0x03,
 0x00,0x00};
    static vIcon openI(&open_bits[0],open_height,open_width);

//vbm1
#define find_width 16
#define find_height 16
static unsigned char find_bits[] = {
 0x00,0x00,0xf0,0x01,0x08,0x02,0x44,0x04,0xa2,0x08,0x12,0x09,0xf2,0x09,0x12,
 0x09,0x14,0x05,0x08,0x0e,0xf0,0x1d,0x00,0x38,0x00,0x70,0x00,0x60,0x00,0x00,
 0x00,0x00};
    static vIcon findI(&find_bits[0],find_height,find_width);

//vbm1
#define findagn_width 16
#define findagn_height 16
static unsigned char findagn_bits[] = {
 0x00,0x00,0xf0,0x01,0x08,0x02,0x44,0x04,0xa2,0x08,0x12,0x09,0xf2,0x09,0x12,
 0x09,0x14,0x05,0x08,0x0e,0xf0,0x1d,0x66,0x38,0xcc,0x70,0x98,0x61,0xcc,0x00,
 0x66,0x00};
    static vIcon findagnI(&findagn_bits[0],findagn_height,findagn_width);

//vbm1
#define openprj_depth 1
#define openprj_width 16
#define openprj_height 16
static unsigned char openprj_bits[] = {
 0x00,0x1e,0x00,0xa3,0xbc,0xc0,0x22,0xe0,0x21,0x00,0xe1,0x7f,0x01,0x40,0xdd,
 0x5d,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xdd,0x5d,0x01,0x40,
 0xff,0x7f};
    static vIcon openprjI(&openprj_bits[0],openprj_height,openprj_width);

//vbm1
#define selmake_depth 1
#define selmake_width 16
#define selmake_height 16
static unsigned char selmake_bits[] = {
 0xbd,0x57,0xa5,0x54,0xa5,0x54,0xa5,0x54,0xa5,0x54,0xbd,0x57,0x00,0x00,0xc0,
 0x03,0x7f,0x22,0x01,0x32,0x01,0xfa,0x01,0xfa,0x01,0x32,0x01,0x22,0x01,0x02,
 0xff,0x03};
    static vIcon selmakeI(&selmake_bits[0],selmake_height,selmake_width);

//vbm1
#define make_depth 1
#define make_width 16
#define make_height 16
static unsigned char make_bits[] = {
 0xc0,0x03,0x7f,0x12,0x01,0x32,0x01,0x22,0x01,0x22,0x01,0x32,0x01,0x12,0xff,
 0x13,0x00,0x10,0x00,0x7c,0x00,0x38,0x00,0x10,0x9d,0xeb,0x95,0xaa,0x95,0xaa,
 0x9d,0xeb};
    static vIcon makeI(&make_bits[0],make_height,make_width);


//vbm1
#define vrun_depth 1
#define vrun_width 16
#define vrun_height 16
static unsigned char vrun_bits[] = {
 0x00,0x00,0x80,0x1f,0xc0,0x0f,0xe0,0x07,0xf0,0x03,0xf8,0x1f,0xfc,0x1f,0xc0,
 0x0f,0xe0,0x07,0xf0,0x03,0xf8,0x0f,0x80,0x07,0xc0,0x03,0xe0,0x01,0x70,0x00,
 0x00,0x00};
    static vIcon vrunI(&vrun_bits[0],vrun_height,vrun_width);

//vbm1
#define vgen_depth 1
#define vgen_width 16
#define vgen_height 16
static unsigned char vgen_bits[] = {
 0xf0,0x01,0xd8,0x03,0x80,0x1f,0xc0,0x0c,0x60,0x04,0x30,0x00,0x18,0x00,0x8c,
 0xc1,0x86,0xc1,0x03,0x41,0x01,0x63,0x00,0x22,0x00,0x36,0x00,0x1c,0x00,0x1c,
 0x00,0x08};
    static vIcon vgenI(&vgen_bits[0],vgen_height,vgen_width);

//vbm1
#define icon_width 16
#define icon_height 16
static unsigned char icon_bits[] = {
 0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x6b,0x00,0x55,0x00,0x6b,0x80,0x57,0x50,
 0x68,0x38,0x50,0x3c,0x70,0x3e,0x10,0x20,0x10,0x40,0x08,0x80,0x07,0x00,0x00,
 0x00,0x00};
    static vIcon iconI(&icon_bits[0],icon_height,icon_width);

//@V@:BeginCmdPane ToolBar
    static CommandObject ToolBar[] =
      {
	{C_IconButton,M_Open,0,"Open",&openI,CA_None,isSens,NoFrame,0,0,0,"Open File"},
	{C_IconButton,m_ProjectOpen,0,"OpenPrj",&openprjI,CA_None,isSens,NoFrame,0,0,0,"Open Project"},
        {C_IconButton,m_SelectMake,0,"Sel Mk",&selmakeI,CA_None,isSens,NoFrame,0,0,0,
           "Select Makefile"},
	{C_Blank,99,0," ",NoList,CA_None,isSens,NoFrame,0,0},
	{C_IconButton,m_RunVgen,0,"V Gen",&vgenI,CA_None,isSens,NoFrame,0,0,0,"V App Gen"},
	{C_IconButton,m_RunViconed,0,"Icon Ed",&iconI,CA_None,isSens,NoFrame,0,0,0,"V Icon Editor"},
	{C_Blank,99,0," ",NoList,CA_None,isSens,NoFrame,0,0},
	{C_IconButton,edFind,0,"Find",&findI,CA_None,isSens,NoFrame,0,0,0,"Find"},
	{C_IconButton,edFindNext,0,"Find Next",&findagnI,CA_None,isSens,NoFrame,0,0,0,"Find Next"},
        {C_Blank,99,0," ",NoList,CA_None,isSens,NoFrame,0,0},
        {C_IconButton,m_MakeAll,0,"MAKE",&makeI,CA_None,isSens,NoFrame,0,0,0,"make all"},
	{C_IconButton,m_RunCmd,0,"Run a program",&vrunI,CA_None,isSens,NoFrame,0,0,0,"Run a program"},
  	{C_EndOfList,0,0,0,0,CA_None,0,0,0}
      };
//@V@:EndCmdPane

//@V@:BeginStatPane StatBar
    static vStatus StatBar[] =
      {
        {" V IDE ", lblStatTitle, CA_NoBorder, isSens, 0},
	{"1/1     ", lblLineCol, CA_None, isSens, 0},
	{"    Insert   ", lblIns, CA_None, isSens, 0},
	// handle messages up to 40 chars
	{"                                      ", lblEMsg, /* CA_NoBorder */ CA_None, isSens, 0},
	{0,0,0,0,0}
      };
//@V@:EndStatPane


    static int filterIndex = 0;
    static char* filter[] =
      {
        "*",
        "*.txt",
        "*.c;*.cpp;*.cxx;*.h;*.hxx",
        0
      };

    static char makebName[] = "make";

//====================>>> videCmdWindow::videCmdWindow <<<====================
  videCmdWindow::videCmdWindow(char* name, int width, int height) :
    vCmdWindow(name, width,  height)
  {
    UserDebug1(Constructor,"videCmdWindow::videCmdWindow(%s) Constructor\n",name)

    // local inits

    fileName[0] = 0;

    // The Menu Bar
    videMenu = new vMenuPane(StandardMenu);
    AddPane(videMenu);

    // The Command Pane
    videCmdPane = new vCommandPane(ToolBar);
    AddPane(videCmdPane);

    // The Canvas
    vedCanvas = new vedTextEditor(this);
    AddPane(vedCanvas);

    if (((videApp*)theApp)->GetEmulation() == See)
      {
        vedCI = (vTextEdCmdInterp*) new vSeeCI(vedCanvas, this); // override interp
    					// ed canvas will do delete at end
        vedCanvas->ChangeCmdInterp(vedCI);
      }
    else
        vedCI = 0;


    // The Status Bar
    videStatus = new vStatusPane(StatBar);
    AddPane(videStatus);

    // Associated dialogs

    // Other stuff

    ideMake = new videMake();

    // Show Window

    ShowWindow();

    vedFont = ((videApp*)theApp)->DefaultFont;

#ifdef XXXX
#ifdef V_VersionX
    vedFont.SetFontValues(vfFixed,12);	// use Courier rathern than default
#else
#ifdef DEVEL
    vedFont.SetFontValues(vfFixed,10,vfNormal,vfBold);	// use Courier rathern than default
#else
    vedFont.SetFontValues(vfFixed,10);	// use Courier rathern than default
#endif
#endif
#endif XXXX
    vedCanvas->SetFont(vedFont);
    vedCanvas->SetTextRowsCols(height,width);
    (vedCanvas->GetCmdInterp())->InitCmdInterp();

  }

//====================>>> videCmdWindow::~videCmdWindow <<<====================
  videCmdWindow::~videCmdWindow()
  {
    UserDebug(Destructor,"videCmdWindow::~videCmdWindow() destructor\n")

    // Now put a delete for each new in the constructor.

    delete videMenu;
    delete vedCanvas;
    delete videCmdPane;
    delete videStatus;
    delete ideMake;
  }

//====================>>> videCmdWindow::ChangeLoc <<<====================
  void videCmdWindow::ChangeLoc(long line, int col)
  {
    char buff[20];
    char colbuff[10];
    char outbuff[20];
    int ll;

    LongToStr(line,buff);

    IntToStr(col,colbuff);

    // center the line/col string

    int totalLen = strlen(buff) + strlen(colbuff) + 1;

    int add = (9 - totalLen) / 2;

    for (ll = 0 ; ll < add ; ++ll)
	outbuff[ll] = ' ';
    outbuff[ll] = 0;
    
    strcat(outbuff,buff); strcat(outbuff,"/");
    strcat(outbuff,colbuff);

    // pad with trailing blanks so X doesn't shift things

    for (ll = strlen(outbuff) ; ll < 9 ; ++ll)
	outbuff[ll] = ' ';
    outbuff[ll] = 0;
    SetString(lblLineCol,outbuff);

  }

//=========================>>> videCmdWindow::FindCmdWin <<<===========================
  videCmdWindow* videCmdWindow::FindCmdWin(char* fname)
  {
    // Find a command window by file name
    videCmdWindow* clist;
  
    // try to match full name first
    for (clist = (videCmdWindow*)GetCmdWinList() ;
         clist != 0 ; clist = (videCmdWindow*)clist->GetNextCmdWin())
      {
        char* fp = clist->GetFileName();
        if (strcmp(fname, fp) == 0)
            return clist;
      }

    // now just match file, not path
    for (clist = (videCmdWindow*)GetCmdWinList() ;
         clist != 0 ; clist = (videCmdWindow*)clist->GetNextCmdWin())
      {
        char* cp = strstr(clist->GetFileName(), fname);	// substring?
        if (cp != 0)
          {
            if (strcmp(cp,fname) == 0)			// substring match
                return clist;
          }
      }
    return 0;
  }

//====================>>> videCmdWindow::GotoErrorLine <<<====================
  void videCmdWindow::GotoErrorLine()
  {
    // Pick up the error from the selected line in the message window
    // and open that file, going to the error line

    // First, get pointer to the error message window
    videCmdWindow* cmdw = ((videApp*)theApp)->GetMsgWindow();

    char errLine[100];

    long curLine = (cmdw->vedCanvas)->GetCurLine();
    (void)(cmdw->vedCanvas)->getLine(errLine, 99, curLine);

    // error line in format "  ! filename.cpp:###:msg"

    char fileBase[100];
    char cLineNum[20];
    if (errLine[2] != '!')
      {
        vNoticeDialog note(this);       // for user notification
        note.Notice("Selected line is not a g++ error message.");
        return;
      }
    int ix;				// get base file name
    for (ix = 4 ; ix < 100 && errLine[ix] != ':' ; ++ix)
        fileBase[ix-4] = errLine[ix];
    fileBase[ix-4] = 0;

    char* np = &cLineNum[0];		// get the line number
    for ( ++ix ; ix < 100 && errLine[ix] != ':' ; ++ix)
        *np++ = errLine[ix];
    *np = 0;
    long lineNum = StrToLong(cLineNum);


    // start by seeing if file is in base directory
    char fullPath[maxFileNameSize];

    strcpy(fullPath,((videApp*)theApp)->GetMkFile());
    ix = strlen(fullPath);
    while (ix > 0)			// just that path
      {
        if (fullPath[ix] == '\\' || fullPath[ix] == '/')
          {
            fullPath[ix+1] = 0;		// keep the last /
            break;
          }
        --ix;
      }

    char* namePtr = fullPath;
    strcat(fullPath,fileBase);
    videCmdWindow* openw = FindCmdWin(fullPath);
    if (openw == 0)		// try just base name
      {
        openw = FindCmdWin(fileBase);
        namePtr = fileBase;	// just the base name
      }

    if (openw != 0)		// EASY, already open
      {
        (openw->GetTextEd())->EditCommand(edLineGoto, 12);
        (openw->GetTextEd())->EditCommand(edLineGoto, lineNum);
        openw->RaiseWindow();
        return;
      }

    // Not already open, so need to open a new window.

    openw = (videCmdWindow*)
                    theApp->NewAppWin(0,"V Text Editor", 90, 24);
    if (!openw)
        return;	       // should never happen...
    if (!openw->OpenFile(fullPath,0,0))
      {
      	// hmmm - the file doesn't exist on Makefile path
        // try something else
        vFileSelect fsel(this);     // make an instance
        strcpy(fullPath,fileBase);	// base only
        if (!fsel.FileSelect("Open file",fullPath,maxFileNameSize,
                     filter,filterIndex))
          {
            openw->CloseWin();
            return;
          }
        if (!openw->OpenFile(fullPath,0,0))
          {
              openw->CloseWin();
              return;
          }
        (openw->GetTextEd())->EditCommand(edLineGoto, 12);
        (openw->GetTextEd())->EditCommand(edLineGoto, lineNum);
      }
    else
      {
        (openw->GetTextEd())->EditCommand(edLineGoto, 12);
        (openw->GetTextEd())->EditCommand(edLineGoto, lineNum);
        openw->RaiseWindow();
      }
  }

//====================>>> videCmdWindow::ChangeInsMode <<<====================
  void videCmdWindow::ChangeInsMode(int IsInsMode, char* msg)
  {
    if (msg && *msg)
        SetString(lblIns,msg);
    else if ((vedCanvas->GetEdState()).readOnly)
        SetString(lblIns,"  View  ");
    else if (IsInsMode)
	SetString(lblIns," Insert ");
    else
	SetString(lblIns,"Overtype");
  }

//====================>>> videCmdWindow::SetRdOnly <<<====================
  void videCmdWindow::SetRdOnly(int ro)
  {
    vedCanvas->SetRdOnly(ro);
    vedCanvas->Verify();

    ChangeInsMode(1);
   }

//====================>>> videCmdWindow::StatusMessage <<<====================
  void videCmdWindow::StatusMessage(char *msg)
  {
    char lineout[42];
    int ix;

    // copy up to 40 chars
    for (ix = 0 ; ix < 40 && msg[ix] ; ++ix)
	lineout[ix] = msg[ix];

    // pad with trailing blanks
  //  for ( ; ix < 40 ; ++ix)
  //	lineout[ix] = ' ';

    lineout[ix] = 0;

    SetString(lblEMsg,lineout);
  }

//====================>>> videCmdWindow::ErrorMsg <<<====================
  void videCmdWindow::ErrorMsg(char *str)
  {
      StatusMessage(str);
  }

//====================>>> videCmdWindow::KeyIn <<<====================
  void videCmdWindow::KeyIn(vKey keysym, unsigned int shift)
  {
    StatusMessage(" ");
    if (!vedCanvas->EditKeyIn(keysym, shift))
	vCmdWindow::KeyIn(keysym, shift);
  }

//==============>>> videCmdWindow::CheckClose <<<================
  int videCmdWindow::CheckClose(int ask)
  {
    // Checks to see if the user wants to save changes, if changes have been
    // done, before it closes the application.
    // Return 1 if ok to close now, 0 to abort

    if (this ==((videApp*)theApp)->GetMsgWindow())
      {
         // we are the main message window...
         if (NumCmdWindows() > 1)
             return 0;
      }

    if (vedCanvas->Changed())    // changes have been made
      {
	if (ask)
	  {
	    vYNReplyDialog ynr(this);
	    int ans = ynr.AskYN("Save new or changed file?");
	    if (ans == 0)
	      {
		return 1;           // don't want to save
	      }
	    if (ans == -1)          // cancel
		return 0;
	  }

        // ok, want to save changed file
        if (*fileName)                    // have a name
          {
            if (!vedCanvas->SaveFile(fileName))        // Save in fileName
              {
                vNoticeDialog note(this);       // for user notification
                note.Notice("Unable to save file");
                return 0;
              }
          }
        else                            // need to request name
          {
            vFileSelect fsel(this);     // V file select dialog

            if (!fsel.FileSelectSave("Save file as",
                fileName,99,filter,filterIndex) || !*fileName)
            return 0;

            if (!vedCanvas->SaveFile(fileName))        // Save in fileName
              {
                vNoticeDialog note(this);       // for user notification
                note.Notice("Unable to save file");
                return 0;
              }
          }
      }
    return 1;
  }

//====================>>> videCmdWindow::WindowCommand <<<====================
  void videCmdWindow::WindowCommand(ItemVal id, ItemVal val, CmdType cType)
  {
    // Default: route menu and toolbar commands here

    UserDebug1(CmdEvents,"videCmdWindow:WindowCommand(%d)\n",id)

    StatusMessage(" ");
    switch (id)
      {
	//@V@:Case M_New
	case M_New:
	  {
            videCmdWindow* ncmdw = this;
            ncmdw = (videCmdWindow*) theApp->NewAppWin(0,"V Text Editor", 80 , 24);
            if (ncmdw)		// If a new window, raise it
                ncmdw->RaiseWindow();
	    break;
	  }	//@V@:EndCase

	//@V@:Case M_Open
        case m_View:
	case M_Open: 			// View/Open - always open a new window!
	  {
	    char name[maxFileNameSize+2] = ""; // start out with null name
	    vFileSelect fsel(this);     // make an instance

	    int oans = fsel.FileSelect("Open file",name,maxFileNameSize,
                     filter,filterIndex);

	    if (oans)
	      {
		videCmdWindow* openw = FindCmdWin(name);
		if (openw != 0)
		  {
		    vNoticeDialog note(this);       // for user notification
		    note.Notice("Sorry - you can only edit one copy of each file.");
		    return;		 // @@@ not twice
		  }
		videCmdWindow* cmdw = (videCmdWindow*)
		theApp->NewAppWin(0,"V Text Editor", 80, 24);
		if (!cmdw)
		    break;
		if (!cmdw->OpenFile(name))
		  {
		    vNoticeDialog note(this);
		    note.Notice("Unable to open specified file.");
		    if (cmdw != this)		// A new window?
			delete cmdw;
		    break;
		  }
		else
		  {
		    if (cmdw != this)		// If a new window, raise it
			cmdw->RaiseWindow();
		  }

		SetSyntaxType(cmdw,name,0);

		edState curState = cmdw->vedCanvas->GetEdState();
		if (id == m_View)
		  {
		    curState.readOnly = 1;
		  }

		cmdw->vedCanvas->SetEdState(curState);
		cmdw->vedCanvas->Verify();
		cmdw->ChangeInsMode(1);
	      }

	    break;
	  }	//@V@:EndCase

	//@V@:Case M_Save
	case M_Save:
	  {
	    CheckClose(0);
	    break;
	  }	//@V@:EndCase

	//@V@:Case M_SaveAs
	case M_SaveAs:
	  {
            vFileSelect fsel(this);     // V file select dialog

            if (!fsel.FileSelectSave("Save file as",
                fileName,99,filter,filterIndex) || !*fileName)
	        break;

            if (!vedCanvas->SaveFile(fileName))        // Save in fileName
              {
                vNoticeDialog note(this);       // for user notification
                note.Notice("Unable to save file");
              }
	    else
	      {
		SetTitle(fileName);
		SetSyntaxType(this, fileName,0);
	      }
	    break;
	  }	//@V@:EndCase

	//@V@:Case M_CloseFile
	case M_CloseFile:
	  {
	    if (!CheckClose(1))
		break;
	    CloseWin();
	    break;
	  }	//@V@:EndCase

	//@V@:Case m_SaveClose
	case M_SaveClose:
	  {
	    if (!CheckClose(0))
		break;
	    CloseWin();
	    break;
	  }	//@V@:EndCase


	//@V@:Case M_Exit
	case M_Exit:
	  {
	    theApp->Exit();
	    break;
	  }	//@V@:EndCase

        //@V@:Case btnDoMake
	case m_MakeAll:
	  {
	    theApp->SendWindowCommandAll(M_Save,1,C_Button);
            if (ideMake->DoMake(this, makebName))
	      {
	        if (ideMake->CheckMake(makebName))
		    ideMake->DoMake(this, makebName);
	      }
	    break;
	  }	//@V@:EndCase

         //@V@:Case m_MakeArgs
	case m_MakeArgs:
	  {
            static char target[80] = "";
            vReplyDialog rp(this);
            if (rp.Reply("Enter make target",target,79) == M_Cancel)
                break;
	    char cmd[100];
            strcpy(cmd,makebName); strcat(cmd," ");
            strcat(cmd,target);
	    theApp->SendWindowCommandAll(M_Save,1,C_Button);
            (void) ideMake->DoMake(this, cmd);
	    break;
	  }	//@V@:EndCase

        case m_MakeClean:
          {
            char cmd[100];
            strcpy(cmd,makebName); strcat(cmd," clean");
	    theApp->SendWindowCommandAll(M_Save,1,C_Button);
            (void) ideMake->DoMake(this, cmd);
	    break;
	  }	//@V@:EndCase

        case m_StopMake:
          {
            ideMake->StopMake();
	    break;
	  }	//@V@:EndCase

        case m_MakeDebug:
          {
             char cmd[100];
            strcpy(cmd,makebName); strcat(cmd," debug");
	    theApp->SendWindowCommandAll(M_Save,1,C_Button);
            if (ideMake->DoMake(this, cmd))
	      {
	        if (ideMake->CheckMake(cmd))
		    ideMake->DoMake(this, cmd);
	      }
	    break;
	  }	//@V@:EndCase


	//**************************************************
	// The Project Menu

	case m_ProjectClose:
	  {
	    if (prjName[0] != 0)
	      {
		mm.saveProject(prjName);	// save previous
	      }
	    strcpy(prjName,"");
	    mm.setDefaults();
            ((videApp*)theApp)->SetMkFile("");
	    break;
	  }

	case m_ProjectEdit:
	  {
	    if (prjName[0] == 0)
	      {
		//open prj file
		char MSDOSpath[256]= "";
		int fi = 0;
		static char* makeFilter[] = {"*.vpj", 0};
		vFileSelect fsel(this);

		int ans = fsel.FileSelect("Select a project file",
		    MSDOSpath ,255, makeFilter,fi);
		char uxfn[256]="";
		if (ans && *MSDOSpath) //filename picked
		    Dos2UxFName(MSDOSpath, prjName, 0);
		else
		    break;
		mm.loadProject(prjName);
	      }
	    projectDialog PDlg(mm,this);
	    if (!PDlg.editProject())	// edit an old one
		break;
	    mm.saveProject(prjName);

            ((videApp*)theApp)->SetMkFile(mm.makeName);

	    break;
	  }

	case m_ProjectNew:
	  {
	    char MSDOSpath[256]= "";
	    ItemVal dans, oans, rval;
	    int fi = 0;
	    static char* makeFilter[] = {"*.vpj", 0};
	    vFileSelect fsel(this);

	    if (prjName[0] != 0)
	      {
		mm.saveProject(prjName);	// save previous
	      }

	    //find where to save new project
	    oans = fsel.FileSelectSave("New Project file",
	    MSDOSpath , 255, makeFilter,fi);
	    if (oans && *MSDOSpath) //filename picked
		Dos2UxFName(MSDOSpath, prjName, 0);
	    else
		break;
	    mm.setDefaults();
	    projectDialog PDlg(mm,this);
	    if (!PDlg.editProject())	// edit an old one
		break;
	    mm.saveProject(prjName);
            ((videApp*)theApp)->SetMkFile(mm.makeName);
	    break;
	  }

	case m_ProjectSave:
	  {
	    char MSDOSpath[256]= "";
	    ItemVal dans, oans, rval;
	    int fi = 0;
	    static char* makeFilter[] = {"*.vpj", 0};
	    vFileSelect fsel(this);

	    if (prjName[0] == 0)
	      {
		//find where to save new project
		oans = fsel.FileSelectSave("New Project file",
		    MSDOSpath , 255, makeFilter,fi);
		if (oans && *MSDOSpath) //filename picked
		    Dos2UxFName(MSDOSpath, prjName, 0);
		else
		    break;
	      }
	    mm.saveProject(prjName);
            ((videApp*)theApp)->SetMkFile(mm.makeName);
	    break;		// done with new, edit, and save
	  }


	case m_ProjectOpen:
	  {
	    if (prjName[0] != 0)
	      {
		mm.saveProject(prjName);	// save previous
	      }

	    //open prj file
	    char MSDOSpath[256]= "";
	    int fi = 0;
	    static char* makeFilter[] = {"*.vpj", 0};
	    vFileSelect fsel(this);

	    int ans = fsel.FileSelect("Select a project file",
	        MSDOSpath ,255, makeFilter,fi);
	    char uxfn[256]="";
	    if (ans && *MSDOSpath) //filename picked
		Dos2UxFName(MSDOSpath, prjName, 0);
	    else
		break;
	    mm.loadProject(prjName);
            ((videApp*)theApp)->SetMkFile(mm.makeName);
	    mm.saveProject(prjName);
	    break;
	  }

        case m_RunVgen:
          {
            vOS vos;
#ifdef V_VersionX
            vos.vRunProcess("vgen", 0, 0, 0);
#else
            vos.vRunProcess("vgen.exe", 0, 0, 0);
#endif
            break;
          }

        case m_RunViconed:
          {
            vOS vos;
#ifdef V_VersionX
            vos.vRunProcess("viconed", 0, 0, 0);
#else
            vos.vRunProcess("viconed.exe", 0, 0, 0);
#endif
            break;
          }

        case m_RunShell:
          {
            vOS vos;
#ifdef V_VersionX
            vos.vRunProcess("rxvt", 0, 0, 0);
#endif
#ifdef V_VersionWindows
            vos.vRunProcess("command.com", 0, 0, 0);
#endif
#ifdef V_VersionOS2
            vos.vRunProcess("cmd.exe", 0, 0, 0);
#endif
            break;
          }

        case m_RunCmd:
          {
            vRunDialog run(this);      // make an instance

            (void)run.Run(mm.exeName);

            break;
          }

	//@V@:Case M_Font
	case M_Font:
	  {
	    vFontSelect fd(this);

	    (void) fd.FontSelect(vedFont);
            vedCanvas->SetFont(vedFont);
            vedCanvas->SetTextRowsCols(24,80);
	    break;
	  }	//@V@:EndCase


	//@V@:Case M_Cut
	case M_Cut:
	  {
	    vedCanvas->EditCommand(edCut,0);
	    break;
	  }	//@V@:EndCase

	//@V@:Case M_Copy
	case M_Copy:
	  {
	    vedCanvas->EditCommand(edCopy,0);
	    break;
	  }	//@V@:EndCase

	//@V@:Case M_Paste
	case M_Paste:
	  {
	    vedCanvas->EditCommand(edPaste,0);
	    break;
	  }	//@V@:EndCase

        case m_SelectMake:	// select makefile
          {
            static int filterIndex = 0;
            static char* filter[] =
              {
        	"Make*;make*;Make*.*;make*.*",
        	"*",
        	0
              };
            char fn[maxFileNameSize+2] = "Makefile";

            vFileSelect fsel(this);     // V file select dialog

            if (!fsel.FileSelect("Select Makefile",
                fn,maxFileNameSize,filter,filterIndex))
	        break;

            ((videApp*)theApp)->SetMkFile(fn);

            break;
          }

        case m_updateMkFile:	// fix up the label for cwd
          {
            char *mkname = ((videApp*)theApp)->GetMkFile();
            if (*mkname != 0)
		(((videApp*)theApp)->GetMsgWindow())->
                    SetTitle(mkname);
            else
		(((videApp*)theApp)->GetMsgWindow())->
                    SetTitle("No Makefile Specified");
            break;
          }

	default:	// route unhandled commands through editor
	  {
	    if (vedCanvas->EditCommand(id, 1) < 0)
		vCmdWindow::WindowCommand(id, val, cType);
	    break;
	  }
      }
  }

//====================>>> videCmdWindow::SetSyntaxType <<<====================
  void videCmdWindow::SetSyntaxType(videCmdWindow* cmdw, char* name, int RdOnly)
  {
    // Set syntax highlighting based on file name
    char* CExts[] = {".cpp", ".CPP", ".C", ".c", ".cxx", ".CXX",
               ".h", ".H", ".hpp", ".HPP", ""};

    edState curState = cmdw->vedCanvas->GetEdState();
    curState.ftype = Text;			// assume Text
    curState.readOnly = RdOnly;

    for (int ix = 0 ; *CExts[ix] ; ++ix)	// check C extensions
      {
        if (strstr(name,CExts[ix]) != 0)	// found one!
          {                                     // @@@ .h matches .html!!!!
            curState.ftype = CPP;
            break;
          }
      }
    cmdw->vedCanvas->SetEdState(curState);
  }

//====================>>> videCmdWindow::OpenFile <<<====================
  int videCmdWindow::OpenFile(char* name, int RdOnly, int notify)
  {
     if (!name || !*name)
	return 0;

    if (!vedCanvas->ReadFile(name,0))
      {
        if (!notify)
            return 0;
	vNoticeDialog note(this);       // for user notification
	note.Notice("Unable to open specified file");
	return 0;
      }

    SetTitle(name);
    strcpy(fileName,name);
    SetSyntaxType(this,name,RdOnly);
    vedCanvas->Verify();
    ChangeInsMode(1);
    return 1;
  }

//====================>>> videCmdWindow::SetViewWindow <<<====================
  int videCmdWindow::SetViewWindow(char *name)
  {
    SetTitle(name);
    strcpy(fileName,name);
    vedCanvas->resetBuff();
#ifdef V_VersionX
    vedFont.SetFontValues(vfFixed,12);	// use Courier rathern than default
#else
#ifdef DEVEL
    vedFont.SetFontValues(vfFixed,9,vfNormal,vfBold);	// use Courier rathern than default
#else
    vedFont.SetFontValues(vfFixed,10);	// use Courier rathern than default
#endif
#endif
    vedCanvas->SetFont(vedFont);

    vedCanvas->Verify();
    return 1;
  }

//====================>>> videCmdWindow::AddLine <<<====================
  int videCmdWindow::AddLine(char* line)
  {
    if (!vedCanvas->addLine(line))
        return 0;
    vedCanvas->displayBuff(99999,1);
    return 1;
  }
