// choosedr.cc - implements path input class - path_dialog.
//    Copyright (C) 2000 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"

#include "choosedr.h"

#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define Uses_MsgBox
#define Uses_TButton
#define Uses_TDeskTop
#define Uses_TDialog
#define Uses_TDirCollection
#define Uses_TDirEntry
#define Uses_THistory
#define Uses_TLabel
#define Uses_TProgram
#define Uses_TRect
#define Uses_TScreen
#define Uses_TScrollBar
#define Uses_TWindowInit
#include <rhtvision/tv.h>

#define HIST_ID 111

const int cmNewDir = 555;

choose_dir::choose_dir(const char * start_dir, const int new_button) :
    TDialog(TRect(0, 0, 50, 18), "Choose Directory"),
    TWindowInit(&TDialog::initFrame )
{
    const char * name = "Directory ~n~ame";
    const char * tree = "Directory ~t~ree";
    options |= ofCentered;
    dir_input = new TInputLine(TRect(3, 3, 30, 4), FILENAME_MAX);
    dir_input->setData(const_cast<char *>(start_dir));
    insert(dir_input);
    insert(new TLabel(TRect(2, 2, 3 + strlen(name), 3), name, dir_input));
    insert(new THistory(TRect(30, 3, 33, 4), dir_input, HIST_ID));
    TScrollBar *scroll_bar = new TScrollBar(TRect(32, 6, 33, 16));
    insert(scroll_bar);
    dir_list = new TDirListBox(TRect(3, 6, 32, 16), scroll_bar);
    int pos = strspn(start_dir, "\\/");
    int len = strlen(start_dir);
    if (pos == len)
       dir_list->newDirectory(getcwd(NULL, PATH_MAX));
    else
       dir_list->newDirectory(start_dir);
    insert(dir_list);
    insert(new TLabel(TRect(2, 5, 3 + strlen(tree), 6), tree, dir_list));
    int button_y = 6;
    insert(new TButton(TRect(35, button_y, 45, button_y + 2), "~O~K", cmOK,
                       bfNormal));
    button_y += 3;
    insert(new TButton(TRect(35, button_y, 45, button_y + 2), "~C~hange",
                       cmChangeDir, bfDefault));
    button_y += 3;
    if (new_button)
    {
       insert(new TButton(TRect(35, button_y, 45, button_y + 2), "~N~ew",
                          cmNewDir, bfNormal));
       button_y += 3;
    }
    insert(new TButton(TRect(35, button_y, 45, button_y + 2), "Cancel",
                       cmCancel, bfNormal));
    selectNext( False );
}

bool choose_dir::get_dir(char * directory)
{
    int exit_code = TProgram::deskTop->execView(this);
    if (exit_code == cmCancel)
       return false;
    dir_input->getData(directory);
    return true;
}

void choose_dir::shutDown(void)
{
    dir_list = NULL;
    dir_input = NULL;
    TDialog::shutDown();
}

void choose_dir::handleEvent(TEvent & event)
{
    TDialog::handleEvent(event);
    if (event.what == evCommand)
    {
       switch (event.message.command)
       {
          case cmNewDir:
          {
             char chosen_dir[PATH_MAX + 1];
             char message[PATH_MAX + 30];
             dir_input->getData(chosen_dir);
             if (access(chosen_dir, D_OK))
             {
                messageBox("Cannot create new subdirectory because "
                           "parent directory does not exist", mfError | mfOKButton);
                return;
             }
             sprintf(message, "Enter new subdirectory of '%s':", chosen_dir);
             unsigned width = min(strlen(message) + 3, (TScreen::getCols() - 2));
             TDialog * new_dir = new TDialog(TRect(0, 0, width, 8),
                                             "New Directory");
             new_dir->options |= ofCentered;
             TInputLine * new_dir_input = new TInputLine(TRect(2, 3, width - 2, 4),
                                                         PATH_MAX);
             new_dir->insert(new TLabel(TRect(1, 2, width - 2, 3), message,
                                        new_dir_input));
             new_dir->insert(new_dir_input);
             new_dir->insert(new TButton(TRect(width / 3 - 5, 5,
                                               width / 3 + 5, 7), "~O~K",
                                               cmOK, bfDefault));
             new_dir->insert(new TButton(TRect(width / 3 * 2 - 5, 5,
                                               width / 3 * 2 + 5, 7), "Cancel",
                                               cmCancel, bfNormal));
             new_dir->selectNext(False);
             int exit_code = TProgram::deskTop->execView(new_dir);
             if (exit_code == cmOK)
             {
                char new_subdir[PATH_MAX + 1];
                char dir[PATH_MAX + 1];
                new_dir->getData(new_subdir);
                strcpy(dir, chosen_dir);
                if (dir[strlen(dir) - 1] != DIRSEPARATOR)
                    strcat(dir, DIRSEPARATOR_ );
                strcat(dir, new_subdir);
                mkdir(dir, S_IWUSR);
                dir_list->newDirectory(chosen_dir);
                dir_list->select();
             }
             destroy(new_dir);
             break;
          }
          case cmChangeDir:
             char chosen_dir[PATH_MAX + 1];
             TDirEntry * dir = dir_list->list()->at(dir_list->focused);
             strcpy(chosen_dir, dir->dir());
             if (strcmp(chosen_dir, "Drives"))
             {
                if (driveValid(chosen_dir[0]))
                {
                   if (chosen_dir[strlen(chosen_dir) - 1] != DIRSEPARATOR)
                      strcat(chosen_dir, DIRSEPARATOR_ );
                }
                else
                   return;
             }
             dir_list->newDirectory(chosen_dir);
             int len = strlen(chosen_dir);
             if((len > 3) && (chosen_dir[len - 1] == DIRSEPARATOR))
                chosen_dir[len - 1] = EOS;
             dir_input->setData(chosen_dir);
             dir_input->drawView();
             dir_list->select();
             clearEvent(event);
             break;
       }
    }
}

Boolean choose_dir::valid(ushort command)
{
   if (command != cmOK)
      return True;
   char dir[PATH_MAX + 1];
   dir_input->getData(dir);
   if (access(dir, D_OK))
   {
      messageBox("Directory does not exist", mfError | mfOKButton);
      return False;
   }
   return True;
}

