//---------------------------------------------------------------------------
#include <shlobj.h>
#include <dir.h>

#pragma hdrstop

#include "SFXDialogs.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)

bool CALLBACK MainDialogProc(HWND DlgWin, UINT DlgMessage, WPARAM DlgWParam, LPARAM DlgLParam)
{
  switch(DlgMessage)
  {
    case WM_INITDIALOG:
    {
      // Assign to a global
      VH_MainWnd = DlgWin;
      InExtraction = false;
      VBool_Cancelled = false;
      // Set the program's icon may 11,2002: changed
      SendMessage(DlgWin, WM_SETICON, ICON_BIG,
                  reinterpret_cast<long>(LoadIcon(MInstance, "MNICON")));
      // add columns to the listview (name,path,size)
      AddFilesListViewCol(DlgWin, 0, LVC_Filename, LVCFMT_LEFT, 200);
      AddFilesListViewCol(DlgWin, 1, LVC_Filesize, LVCFMT_RIGHT, 70);
       // set image list
      SendDlgItemMessage(DlgWin, ID_LV_FILES, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
      SendDlgItemMessage(DlgWin, ID_LV_FILES, LVM_SETIMAGELIST, LVSIL_SMALL, VH_ShellImageList);
      HWND cm1 = GetDlgItem(DlgWin, ID_CB_RUN); // the run... checkbox
      if((VRec_SFXHeader.CmdLineSize == 0) || !(VRec_SFXHeader.Options & soAskCmdLine ))
            // Command Line
            DestroyWindow(cm1); //  no cmd-line, so hide the run... checkbox
      else
      {
            //## give the run... checkbox a title
        GetRunCheckBoxText(PathBuf);
        SetWindowText(cm1, PathBuf);
            //## check it by default
        SendMessage(cm1, BM_SETCHECK, 1, 0);
      }
      SetDlgItemText(DlgWin, ID_EDITBOX, VStr_ExtractPath);
          // Hilite string in Edit1 control
      SendMessage(GetDlgItem(DlgWin, ID_EDITBOX), EM_SETSEL, 0, 0x7FFF);
          // Set overwrite mode *)
      SendMessage(GetDlgItem(DlgWin, static_cast<int>(VRec_SFXHeader.DefOVW) +
                             ID_RB_OVERWRITE), BM_SETCHECK, 1, 0);
          // and calculate the command for the overwrite-mode
      int LIntSmaller = 0;
      if(VRec_SFXHeader.Options & soHideOverWriteBox)
      {       // if we do not want to select another overwrite-mode, destroy the controls
 	      LIntSmaller = 10;   // gave wrong dimension when resized  was = 23;
        DestroyWindow(GetDlgItem(DlgWin, ID_RB_OVERWRITE));
        DestroyWindow(GetDlgItem(DlgWin, ID_RB_SKIP));
        DestroyWindow(GetDlgItem(DlgWin, ID_RB_CONFIRM));
        DestroyWindow(GetDlgItem(DlgWin, ID_ST_OVWGROUP));
      }
      if(!(VRec_SFXHeader.Options & soAskCmdLine))
      {
        if(LIntSmaller) LIntSmaller += 5;
        LIntSmaller += 10;
      }
      if(LIntSmaller)
      {
        ResizeControl(DlgWin, false, - LIntSmaller);
        for(int i = 0; i < 6; ++i)
          ResizeControl(GetDlgItem(DlgWin, POS_CTRLS_HIDE[i]), true, -LIntSmaller);
      }
      SetWindowText(DlgWin, VStr_SFX_Caption);
      // Fill the list view and select all items
      FillListView(DlgWin);

      if(!(VRec_SFXHeader.Options & soInitiallyHideFiles))
            // show files listview
            SendMessage(DlgWin, WM_COMMAND, ID_BTN_SHOWFILES, 0);
      else if(VRec_SFXHeader.Options & soForceHideFiles)
            // no "show files" button
            DestroyWindow(GetDlgItem(DlgWin, ID_BTN_SHOWFILES));
      if(VRec_SFXHeader.Options & soAutoRun)
            // do the extraction automatically, if autorun = true
            SetTimer(DlgWin, 0, 20, NULL);
    }
    break;
    case WM_TIMER:
        KillTimer(DlgWin, 0);
        PostMessage(DlgWin, WM_COMMAND, ID_BTN_YES, 0);
    break;
    case WM_NOTIFY: // Handle button presses, etc.
      if((DlgWParam == ID_LV_FILES) && (((LPNMHDR)DlgLParam)->code == LVN_ITEMCHANGED))
        {
          if((VRec_SFXHeader.Options & soAskFiles) && !InExtraction)
            EnableWindow(GetDlgItem(DlgWin, ID_BTN_YES),
                    (SendDlgItemMessage(DlgWin, ID_LV_FILES, LVM_GETSELECTEDCOUNT,0,0) > 0));
        }
    break;
    case WM_SYSCOMMAND:
      switch(LOWORD(DlgWParam))
      {
        case SC_CLOSE:
          SfxExit(true, true);
        break;
      }
    break;
    case WM_COMMAND:
      switch(LOWORD(DlgWParam))
      {
        case ID_ST_FILES: // 09/18/2002 -> select the files list by pressing the "Files" shortcut key
          SetFocus(GetDlgItem(DlgWin, ID_LV_FILES));
        break;
        case ID_BTN_SHOWFILES:  // show files
          for(int i = 0; i < 2; ++i) ShowWindow(GetDlgItem(DlgWin, SHOW_CTRLS[i]), SW_SHOW);
          ResizeControl(DlgWin, false, 66);
          for(int i = 0; i < 10; ++i) ResizeControl(GetDlgItem(DlgWin, POS_CTRLS[i]), true, 66);
          SetFocus(GetDlgItem(DlgWin, ID_LV_FILES));
          DestroyWindow(GetDlgItem(DlgWin, ID_BTN_SHOWFILES));
        break;
          // added the ability to select a extract directory
        case ID_BTN_BROWSE:
          delete[] VStr_ExtractPath;
          VStr_ExtractPath = StrGetEditText(DlgWin);
          if(BrowseDirectory(DlgWin, VStr_ExtractPath))
                SetDlgItemText(DlgWin, ID_EDITBOX, VStr_ExtractPath);
        break;
        case ID_BTN_ABOUT: // show the copyright information
            MsgBox(DlgWin, Msg_About, Cap_About, MB_OK);
        break;
        case ID_RB_OVERWRITE:
            VRec_SFXHeader.DefOVW = somOverwrite;
        break;
        case ID_RB_SKIP:
            VRec_SFXHeader.DefOVW = somSkip;
        break;
        case ID_RB_CONFIRM:
            VRec_SFXHeader.DefOVW = somAsk;
        break;
        case ID_BTN_YES:
        {
              // if the user is not allowed to (de)select files from the archive, then
              //   select them all
          VBool_Cancelled = false;
          if(!(VRec_SFXHeader.Options & soAskFiles)) SelectAllInFilesListView(DlgWin);
          delete[] VStr_ExtractPath;
          VStr_ExtractPath = RemoveDirSeparator(StrGetEditText(DlgWin));
          if(!VStr_ExtractPath)
          {
            VStr_ExtractPath = GetCurDir();
            SetDlgItemText(DlgWin, ID_EDITBOX, VStr_ExtractPath);
          }
          EnableChildren(DlgWin, false);
              // re-enable close-button
          if(VRec_SFXHeader.Options & soCanBeCancelled)
                EnableWindow(GetDlgItem(DlgWin, ID_BTN_NO), true);
           // show progress bar
          for(int i = 0; i < 4; ++i)
          {
            int nCmdShow = (i) ? SW_HIDE : SW_SHOW;
            ShowWindow(GetDlgItem(DlgWin, SWAP_CTRLS[i]), nCmdShow);
          }
           // do extraction
          InExtraction = true;
          bool OK = Extract(DlgWin);
          InExtraction = false;
           // hide progress bar
           for(int i = 0; i < 4; ++i)
          {
            int nCmdShow = (i) ? SW_SHOW : SW_HIDE;
            ShowWindow(GetDlgItem(DlgWin, SWAP_CTRLS[i]), nCmdShow);
          }
              // enable controls
          EnableChildren(DlgWin, true);
          if(!OK)
          {
            if(VRec_SFXHeader.Options & soHideOverWriteBox)
                                VRec_SFXHeader.DefOVW = somAsk;
            if(!VBool_Cancelled)
            {
              if(IsWindow(GetDlgItem(DlgWin, ID_BTN_SHOWFILES)))
                // show files if something went wrong
                SendMessage(DlgWin, WM_COMMAND, ID_BTN_SHOWFILES, 0);
              if(VRec_SFXHeader.Options & soForceHideFiles)
                   ErrorMsgBox(DlgWin, Msg_SomeNotExtracted);
              else ErrorMsgBox(DlgWin, Msg_SelNotExtracted);
            }
          }
          else
          {
            if(!(VRec_SFXHeader.Options & soAutoRun) &&
               !(VRec_SFXHeader.Options & soNoSuccessMsg))
                    MsgBox(DlgWin,Msg_AllExtracted ,Cap_Finished , MB_OK);
            if(!(VRec_SFXHeader.Options & soAskCmdLine) ||
                   (SendMessage(GetDlgItem(DlgWin, ID_CB_RUN), BM_GETCHECK, 0, 0) == 1))
            {
              if(VStr_SFX_CmdLine && (ExecuteCMD() < 32))
              {
                 GetRunErrorMessage(PathBuf);
                 ErrorMsgBox(DlgWin, PathBuf);
              }
            }
            SfxExit(true, false);
            EndDialog(DlgWin, IDOK);
            if(VRec_SFXHeader.Options & soAutoRun)
                PostMessage(DlgWin, WM_COMMAND, ID_BTN_NO, 0);
          }
        }
        break;
        case ID_BTN_NO:
          if(!InExtraction)
          {
            delete[] VStr_ExtractPath;
            VStr_ExtractPath = StrGetEditText(DlgWin);
            if(DirectoryExists(VStr_ExtractPath)) chdir(VStr_ExtractPath);
            SfxExit(true, false);
            EndDialog(DlgWin, LOWORD(DlgWParam));
          }
          else
          {
            if((VRec_SFXHeader.Options & soCanBeCancelled) && VBool_Cancelled ||
                  (MsgBox(DlgWin, Msg_QueryCancel,
                  VStr_SFX_Caption, MB_YESNO | MB_ICONWARNING) == IDYES))
            {
              VBool_Cancelled = true;
              PostMessage(DlgWin, WM_CLOSE, DlgWParam, DlgLParam);
              InExtraction = false;
            }
          }
        break;
       }
    break;
  }
  return false;
}
//---------------------------------------------------------------------------
// browse for a directory using shell32 api
bool BrowseDirectory(HWND Parent, char* Path)
{
  BROWSEINFO Browseinfo = {0};
  Browseinfo.hwndOwner = Parent;
  Browseinfo.pidlRoot = NULL;
  Browseinfo.pszDisplayName = DisplayName;
  Browseinfo.lpszTitle = Cap_Browse;
  Browseinfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
  Browseinfo.lpfn = reinterpret_cast<BFFCALLBACK>(BrowseCBProc);
  Browseinfo.lParam = reinterpret_cast<long>(Path);
  LPITEMIDLIST ItemID =  SHBrowseForFolder(&Browseinfo);
  if(ItemID)
  {
    SHGetPathFromIDList(ItemID, Path);
    chdir(Path);
    return true;
  }
  return false;
}
//---------------------------------------------------------------------------
int CALLBACK BrowseCBProc(HWND HWindow, int Msg, LPARAM lParameter, LPARAM lpBrowseFolder)
{
  switch(Msg)
  {
   case BFFM_INITIALIZED:   // set the current path
   {
    SendMessage(HWindow, BFFM_SETSELECTIONA, 1, lpBrowseFolder);
    SetWindowText(HWindow, Cap_Browse);
   }
   break;
   case BFFM_SELCHANGED: // test if the currently selected path is a valid file-system path
     if(!SHGetPathFromIDList(reinterpret_cast<LPITEMIDLIST>(lParameter), DisplayName))
          EnableWindow(GetDlgItem(HWindow, IDOK), false);
   break;
  }
  return 0;
}
//---------------------------------------------------------------------------
bool CALLBACK FileExistsDialogProc(HWND DlgWin, UINT DlgMessage, WPARAM DlgWParam,
                                   LPARAM /*DlgLParam*/)
{
 switch(DlgMessage)
 {
  case WM_INITDIALOG:
  {
    ExtractFileName(VStr_CurrentFile, PathBuf);
    FormatStr(Msg_FileExists, PathBuf, TempBuf);
    SetDlgItemText(DlgWin, ID_EDITBOX, TempBuf);
    SetFocus(GetDlgItem(DlgWin, ID_BTN_YES));
  }
  break;
  case WM_COMMAND:
      switch(LOWORD(DlgWParam))
      {
        case ID_BTN_YES:
        case ID_BTN_NO:
          // No ask Overwrite again checked, show results in affected option buttons
          if(IsDlgButtonChecked(DlgWin, ID_CB_NOASK) == BST_CHECKED)
          {
            CheckRadioButton(VH_MainWnd, ID_RB_OVERWRITE, ID_RB_CONFIRM, ID_RB_OVERWRITE |
                (static_cast<int>(LOWORD(DlgWParam) == ID_BTN_NO)));
            VRec_SFXHeader.DefOVW = TSFXOverwriteMode(LOWORD(DlgWParam) == ID_BTN_NO);
          }
          EndDialog(DlgWin, LOWORD(DlgWParam));
          return false;
      }
  break;
 }
 return false;
}
//---------------------------------------------------------------------------
// PasswordQueryDialogProc --- Handle messages for password dialog.
bool CALLBACK PasswordQueryDialogProc(HWND DlgWin, UINT DlgMessage, WPARAM DlgWParam,
                                      LPARAM DlgLParam)
{
  switch(DlgMessage)
  {
    case WM_INITDIALOG:
    {
      // set the caption to reflect the current file
      ExtractFileName(VStr_CurrentFile, PathBuf);
      FormatStr(Cap_Password, PathBuf, TempBuf);
      SetWindowText(DlgWin, TempBuf);
      // Set input focus to the first edit field.
      SetFocus(GetDlgItem(DlgWin, ID_EDITBOX));
    }
    break;
    case WM_CLOSE:
      if(VStr_Password) VStr_Password[0] = '\0';
      EndDialog(DlgWin, IDCANCEL);
    break;
    case WM_COMMAND:
      switch(LOWORD(DlgWParam))
      {
        case ID_EDITBOX:
          if(HIWORD(DlgWParam) == EN_CHANGE)
             EnableWindow(GetDlgItem(DlgWin, ID_BTN_YES),
                          GetWindowTextLength(reinterpret_cast<HWND>(DlgLParam)) > 0);
        break;
        case ID_BTN_YES:
          if(VStr_Password) delete[] VStr_Password;
          VStr_Password = StrGetEditText(DlgWin);
          EndDialog(DlgWin, IDOK);
        break;
        case ID_BTN_NO:
          if(VStr_Password) VStr_Password[0] = '\0';
          EndDialog(DlgWin, IDCANCEL);
        break;
      }
    break;
  }
return false;
}

