// aexecupd.cc - implements autoexec.bat update class, autoexec_update.
//    Copyright (C) 2000, 2001 Laurynas Biveinis <lauras@softhome.net>
//
//    This program is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "global.h"

#define Uses_MsgBox
#define Uses_TButton
#define Uses_TDeskTop
#define Uses_TDialog
#define Uses_TFileEditor
#define Uses_TLabel
#define Uses_TProgram
#define Uses_TRect
#define Uses_TScrollBar
#include <rhtvision/tv.h>

#include <fstream.h>
#include <stdio.h>

#include "aexecupd.h"

const unsigned cmSaveChanges  = 10000;
const unsigned cmSaveAsBackup = 10001;

// This format string assumes that DJGPP installation dir ends with slash.
const char update_text[] =
    "\n"
    "REM Following two lines were added by KITE, the DJGPP installer\n"
    "SET PATH=%sbin;%%PATH%%\n"
    "SET DJGPP=%sdjgpp.env\n";

static void write_block (ofstream & stream, char * buf, unsigned len);

autoexec_update::autoexec_update(void) :
    TDialog(TProgram::deskTop->getExtent(), "Update autoexec.bat"),
    TWindowInit(&TDialog::initFrame)
{
    TRect dialog_size = TProgram::deskTop->getExtent();
    unsigned width = dialog_size.b.x - dialog_size.a.x;
    old_h_sb = new TScrollBar(TRect(1, dialog_size.b.y - 5, width / 2 - 2,
                                    dialog_size.b.y - 4));
    insert(old_h_sb);
    old_v_sb = new TScrollBar(TRect(width / 2 - 2, 3, width / 2 - 1,
                                    dialog_size.b.y - 5));
    insert(old_v_sb);
    old_editor = new TFileEditor(TRect(1, 3, width / 2 - 2,
                                       dialog_size.b.y - 5),
                                 old_h_sb, old_v_sb, NULL, "C:/autoexec.bat");
    old_editor->options |= ofFramed;
    old_editor->options &= ~ofSelectable;
    insert(old_editor);
    insert(new TLabel(TRect(1, 1, width / 2 - 1, 2), "Your current autoexec.bat file:", old_editor));
    new_h_sb = new TScrollBar(TRect(width / 2 + 1, dialog_size.b.y - 5,
                                    width - 2, dialog_size.b.y - 4));
    insert(new_h_sb);
    new_v_sb = new TScrollBar(TRect(width - 2, 3, width - 1,
                                    dialog_size.b.y - 5));
    insert(new_v_sb);
    new_editor = new TFileEditor(TRect(width / 2 + 1, 3,
                                       width - 2, dialog_size.b.y - 5),
                                 new_h_sb, new_v_sb, NULL, "C:/autoexec.bat");
    new_editor->options |= ofFramed;
    insert(new_editor);
    insert(new TStaticText(TRect(width / 2 + 1, 1, width - 1, 2),
                           "Proposed autoexec.bat file:"));
    insert(new TButton(TRect(width / 4 - 10, dialog_size.b.y - 3,
                             width / 4 + 10, dialog_size.b.y - 1),
                       "~S~ave changes", cmSaveChanges, bfDefault));
    insert(new TButton(TRect(width / 2 - 10, dialog_size.b.y - 3,
                             width / 2 + 10, dialog_size.b.y - 1),
                       "Save as ~b~ackup", cmSaveAsBackup, bfNormal));
    insert(new TButton(TRect(width / 4 * 3 - 10, dialog_size.b.y - 3,
                             width / 4 * 3 + 10, dialog_size.b.y - 1),
                       "~E~xit", cmCancel, bfNormal));
    selectNext(False);
}

void autoexec_update::handleEvent(TEvent & event)
{
    TDialog::handleEvent(event);
    switch (event.what)
    {
       case evBroadcast:
          if ((event.message.command == cmScrollBarChanged) ||
              (event.message.command == cmScrollBarClicked))
          {
             int32 pos;
             if (event.message.infoPtr == new_h_sb)
             {
                pos = new_h_sb->value;
                old_h_sb->setValue(pos);
                message(old_editor, evBroadcast, cmScrollBarChanged, old_h_sb);
                message(new_editor, evBroadcast, cmScrollBarChanged, new_h_sb);
             }
             else if (event.message.infoPtr == old_h_sb)
             {
                pos = old_h_sb->value;
                new_h_sb->setValue(pos);
                message(old_editor, evBroadcast, cmScrollBarChanged, old_h_sb);
                message(new_editor, evBroadcast, cmScrollBarChanged, new_h_sb);
             }
             else if (event.message.infoPtr == old_v_sb)
             {
                pos = old_v_sb->value;
                new_v_sb->setValue(pos);
                message(old_editor, evBroadcast, cmScrollBarChanged, old_v_sb);
                message(new_editor, evBroadcast, cmScrollBarChanged, new_v_sb);
             }
             else if (event.message.infoPtr == new_v_sb)
             {
                pos = new_v_sb->value;
                old_v_sb->setValue(pos);
                message(old_editor, evBroadcast, cmScrollBarChanged, old_v_sb);
                message(new_editor, evBroadcast, cmScrollBarChanged, new_v_sb);
             }
          }
          break;
       case evCommand:
          switch (event.message.command)
          {
             case cmSaveChanges:
                save_editor(*old_editor, "c:/autoexec.lbi");
                save_editor(*new_editor, "c:/autoexec.bat");
                messageBox("Changes have been saved to autoexec.bat. "
                  "Your old autoexec.bat file is saved as autoexec.lbi ",
                  mfInformation | mfOKButton);
                endModal(cmSaveChanges);
                break;
             case cmSaveAsBackup:
                save_editor(*new_editor, "c:/autoexec.lbi");
                messageBox("Changes have been saved to autoexec.lbi. "
                           "Your old autoexec.bat is left unaltered.",
                mfInformation | mfOKButton);
                endModal(cmSaveAsBackup);
                break;
          }
    }
}

void autoexec_update::save_editor(const TEditor & editor,
                                  const char * file_name)
{
   ofstream output_file(file_name, std::ios::out | std::ios::binary);
   write_block(output_file, editor.buffer, editor.curPtr);
   write_block(output_file, editor.buffer + editor.curPtr + editor.gapLen,
               editor.bufLen - editor.curPtr);
   output_file.close();
}

int autoexec_update::update(const char * dir)
{
    char buf[700];
    message(new_editor, evCommand, cmTextEnd, this);
    sprintf(buf, update_text, dir, dir);
    new_editor->insertText(buf, strlen(buf), False);
    return TProgram::deskTop->execView(this);
}

Boolean autoexec_update::valid(ushort command)
{
   if ((command == cmSaveChanges) || (command == cmSaveAsBackup))
      return True;
   return TDialog::valid(command);
}

void write_block(ofstream & stream, char * buf, unsigned len)
{
    int l;
    while (len > 0)
    {
       l = len < INT_MAX ? len : INT_MAX;
       stream.write(buf, l);
       buf += l;
       len -= l;
    }
}
