⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compressdialog.cpp

📁 7z一个高压缩比的压缩程序源代码,重要的是里面的算法值得学习
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  s += L" (*.*)";
  UString resPath;
  if (!MyGetOpenFileName(HWND(*this), title, fullFileName, s, resPath))
    return;
  m_ArchivePath.SetText(resPath);
}

// in ExtractDialog.cpp
extern void AddUniqueString(UStringVector &strings, const UString &srcString);

static bool IsAsciiString(const UString &s)
{
  for (int i = 0; i < s.Length(); i++)
  {
    wchar_t c = s[i];
    if (c < 0x20 || c > 0x7F)
      return false;
  }
  return true;
}

void CCompressDialog::OnOK()
{
  _password1Control.GetText(Info.Password);
  if (IsZipFormat())
  {
    if (!IsAsciiString(Info.Password))
    {
      ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII, 0x02000B11);
      return;
    }
    UString method = GetEncryptionMethodSpec();
    method.MakeUpper();
    if (method.Find(L"AES") == 0)
    {
      if (Info.Password.Length() > 99)
      {
        ShowErrorMessageHwndRes(*this, IDS_PASSWORD_IS_TOO_LONG, 0x02000B12);
        return;
      }
    }
  }
  if (!IsShowPasswordChecked())
  {
    UString password2;
    _password2Control.GetText(password2);
    if (password2 != Info.Password)
    {
      ShowErrorMessageHwndRes(*this, IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH, 0x02000B10);
      return;
    }
  }

  SaveOptionsInMem();
  UString s;
  m_ArchivePath.GetText(s);
  s.Trim();
  m_RegistryInfo.HistoryArchives.Clear();
  AddUniqueString(m_RegistryInfo.HistoryArchives, s);
  Info.ArchiveName = s;
  Info.UpdateMode = NCompressDialog::NUpdateMode::EEnum(m_UpdateMode.GetCurSel());

  Info.Level = GetLevelSpec();
  Info.Dictionary = GetDictionarySpec();
  Info.Order = GetOrderSpec();
  Info.OrderMode = GetOrderMode();
  Info.NumThreads = GetNumThreadsSpec();

  UInt32 solidLogSize = GetBlockSizeSpec();
  Info.SolidBlockSize = 0;
  if (solidLogSize > 0 && solidLogSize != (UInt32)-1)
    Info.SolidBlockSize = (solidLogSize >= 64) ? (UInt64)(Int64)-1 : ((UInt64)1 << solidLogSize);

  Info.Method = GetMethodSpec();
  Info.EncryptionMethod = GetEncryptionMethodSpec();
  Info.ArchiverInfoIndex = m_Format.GetCurSel();
  Info.SFXMode = IsSFX();
  Info.OpenShareForWrite = IsButtonCheckedBool(IDC_COMPRESS_SHARED);

  m_RegistryInfo.EncryptHeaders = Info.EncryptHeaders = IsButtonCheckedBool(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES);

  m_Params.GetText(Info.Options);
  UString volumeString;
  m_Volume.GetText(volumeString);
  volumeString.Trim();
  Info.VolumeSizes.Clear();
  if (!volumeString.IsEmpty())
  {
    if (!ParseVolumeSizes(volumeString, Info.VolumeSizes))
    {
      ShowErrorMessageHwndRes(*this, IDS_COMPRESS_INCORRECT_VOLUME_SIZE, 0x02000D41);
      return;
    }
    if (!Info.VolumeSizes.IsEmpty())
    {
      const UInt64 volumeSize = Info.VolumeSizes.Back();
      if (volumeSize < (100 << 10))
      {
        wchar_t s[32];
        ConvertUInt64ToString(volumeSize, s);
        if (::MessageBoxW(*this, MyFormatNew(IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE, 0x02000D42, s),
            L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION | MB_TASKMODAL) != IDYES)
          return;
      }
    }
  }

  for(int i = 0; i < m_ArchivePath.GetCount(); i++)
  {
    UString sTemp;
    m_ArchivePath.GetLBText(i, sTemp);
    sTemp.Trim();
    AddUniqueString(m_RegistryInfo.HistoryArchives, sTemp);
  }
  if (m_RegistryInfo.HistoryArchives.Size() > kHistorySize)
    m_RegistryInfo.HistoryArchives.DeleteBack();
  
  m_RegistryInfo.ArchiveType = m_ArchiverInfoList[Info.ArchiverInfoIndex].Name;
  m_RegistryInfo.ShowPassword = IsShowPasswordChecked();

  SaveCompressionInfo(m_RegistryInfo);
  
  CModalDialog::OnOK();
}

static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/add.htm";

void CCompressDialog::OnHelp()
{
  ShowHelpWindow(NULL, kHelpTopic);
}

bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
{
  if (code == CBN_SELCHANGE)
  {
    switch(itemID)
    {
      case IDC_COMPRESS_COMBO_FORMAT:
      {
        bool isSFX = IsSFX();
        SaveOptionsInMem();
        SetLevel();
        SetSolidBlockSize();
        SetNumThreads();
        SetParams();
        CheckControlsEnable();
        SetArchiveName2(isSFX);
        SetEncryptionMethod();
        SetMemoryUsage();
        return true;
      }
      case IDC_COMPRESS_COMBO_LEVEL:
      {
        const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
        int index = FindRegistryFormatAlways(ai.Name);
        NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
        fo.ResetForLevelChange();
        SetMethod();
        SetSolidBlockSize();
        SetNumThreads();
        CheckSFXNameChange();
        SetMemoryUsage();
        return true;
      }
      case IDC_COMPRESS_COMBO_METHOD:
      {
        SetDictionary();
        SetOrder();
        SetSolidBlockSize();
        SetNumThreads();
        CheckSFXNameChange();
        SetMemoryUsage();
        return true;
      }
      case IDC_COMPRESS_COMBO_DICTIONARY:
      case IDC_COMPRESS_COMBO_ORDER:
      {
        SetSolidBlockSize();
        SetMemoryUsage();
        return true;
      }
      case IDC_COMPRESS_COMBO_THREADS:
      {
        SetMemoryUsage();
        return true;
      }
    }
  }
  return CModalDialog::OnCommand(code, itemID, lParam);
}

void CCompressDialog::CheckSFXNameChange()
{
  bool isSFX = IsSFX();
  CheckSFXControlsEnable();
  if (isSFX != IsSFX())
    SetArchiveName2(isSFX);
}

void CCompressDialog::SetArchiveName2(bool prevWasSFX)
{
  UString fileName;
  m_ArchivePath.GetText(fileName);
  const CArcInfoEx &prevArchiverInfo = m_ArchiverInfoList[m_PrevFormat];
  if (prevArchiverInfo.KeepName || Info.KeepName)
  {
    UString prevExtension = prevArchiverInfo.GetMainExt();
    if (prevWasSFX)
      prevExtension = kExeExt;
    else
      prevExtension = UString('.') + prevExtension;
    const int prevExtensionLen = prevExtension.Length();
    if (fileName.Length() >= prevExtensionLen)
      if (fileName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0)
        fileName = fileName.Left(fileName.Length() - prevExtensionLen);
  }
  SetArchiveName(fileName);
}

// if type.KeepName then use OriginalFileName
// else if !KeepName remove extension
// add new extension

void CCompressDialog::SetArchiveName(const UString &name)
{
  UString fileName = name;
  Info.ArchiverInfoIndex = m_Format.GetCurSel();
  const CArcInfoEx &ai = m_ArchiverInfoList[Info.ArchiverInfoIndex];
  m_PrevFormat = Info.ArchiverInfoIndex;
  if (ai.KeepName)
  {
    fileName = OriginalFileName;
  }
  else
  {
    if (!Info.KeepName)
    {
      int dotPos = fileName.ReverseFind('.');
      int slashPos = MyMax(fileName.ReverseFind(WCHAR_PATH_SEPARATOR), fileName.ReverseFind('/'));
      if (dotPos >= 0 && dotPos > slashPos + 1)
        fileName = fileName.Left(dotPos);
    }
  }

  if (IsSFX())
    fileName += kExeExt;
  else
  {
    fileName += L'.';
    fileName += ai.GetMainExt();
  }
  m_ArchivePath.SetText(fileName);
}

int CCompressDialog::FindRegistryFormat(const UString &name)
{
  for (int i = 0; i < m_RegistryInfo.FormatOptionsVector.Size(); i++)
  {
    const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[i];
    if (GetUnicodeString(fo.FormatID) == name)
      return i;
  }
  return -1;
}

int CCompressDialog::FindRegistryFormatAlways(const UString &name)
{
  int index = FindRegistryFormat(name);
  if (index < 0)
  {
    NCompression::CFormatOptions fo;
    fo.FormatID = GetSystemString(name);
    index = m_RegistryInfo.FormatOptionsVector.Add(fo);
  }
  return index;
}

int CCompressDialog::GetStaticFormatIndex()
{
  int formatIndex = m_Format.GetCurSel();
  const CArcInfoEx &ai = m_ArchiverInfoList[formatIndex];
  for (int i = 0; i < MY_SIZE_OF_ARRAY(g_Formats); i++)
    if (ai.Name.CompareNoCase(g_Formats[i].Name) == 0)
      return i;
  return 0; // -1;
}

void CCompressDialog::SetNearestSelectComboBox(NControl::CComboBox &comboBox, UInt32 value)
{
  for (int i = comboBox.GetCount() - 1; i >= 0; i--)
    if ((UInt32)comboBox.GetItemData(i) <= value)
    {
      comboBox.SetCurSel(i);
      return;
    }
  if (comboBox.GetCount() > 0)
    comboBox.SetCurSel(0);
}

void CCompressDialog::SetLevel()
{
  m_Level.ResetContent();
  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
  const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
  int index = FindRegistryFormat(ai.Name);
  UInt32 level = kNormal;
  if (index >= 0)
  {
    const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
    if (fo.Level <= kUltra)
      level = fo.Level;
    else
      level = kUltra;
  }
  int i;
  for (i = 0; i <= kUltra; i++)
  {
    if ((fi.LevelsMask & (1 << i)) != 0)
    {
      const CLevelInfo &levelInfo = g_Levels[i];
      int index = (int)m_Level.AddString(LangString(levelInfo.ResourceID, levelInfo.LangID));
      m_Level.SetItemData(index, i);
    }
  }
  SetNearestSelectComboBox(m_Level, level);
  SetMethod();
}

void CCompressDialog::SetMethod()
{
  m_Method.ResetContent();
  UInt32 level = GetLevel();
  if (level == 0)
  {
    SetDictionary();
    SetOrder();
    return;
  }
  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
  const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
  int index = FindRegistryFormat(ai.Name);
  UString defaultMethod;
  if (index >= 0)
  {
    const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
    defaultMethod = fo.Method;
  }
  bool isSfx = IsSFX();
  for(int m = 0; m < fi.NumMethods; m++)
  {
    EMethodID methodID = fi.MathodIDs[m];
    if (isSfx)
      if (!IsMethodSupportedBySfx(methodID))
        continue;
    const LPCWSTR method = kMethodsNames[methodID];
    int itemIndex = (int)m_Method.AddString(GetSystemString(method));
    if (defaultMethod.CompareNoCase(method) == 0 || m == 0)
      m_Method.SetCurSel(itemIndex);
  }
  SetDictionary();
  SetOrder();
}

bool CCompressDialog::IsZipFormat()
{
  const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
  return (ai.Name.CompareNoCase(L"zip") == 0);
}

void CCompressDialog::SetEncryptionMethod()
{
  _encryptionMethod.ResetContent();
  const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
  if (ai.Name.CompareNoCase(L"7z") == 0)
  {
    _encryptionMethod.AddString(TEXT("AES-256"));
    _encryptionMethod.SetCurSel(0);
  }
  else if (ai.Name.CompareNoCase(L"zip") == 0)
  {
    int index = FindRegistryFormat(ai.Name);
    UString encryptionMethod;
    if (index >= 0)
    {
      const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
      encryptionMethod = fo.EncryptionMethod;
    }
    _encryptionMethod.AddString(TEXT("ZipCrypto"));
    _encryptionMethod.AddString(TEXT("AES-256"));
    _encryptionMethod.SetCurSel(encryptionMethod.Find(L"AES") == 0 ? 1 : 0);
  }
}

int CCompressDialog::GetMethodID()
{
  UString methodName;
  m_Method.GetText(methodName);
  for (int i = 0; i < MY_SIZE_OF_ARRAY(kMethodsNames); i++)
    if (methodName.CompareNoCase(kMethodsNames[i]) == 0)
      return i;
  return -1;
}

UString CCompressDialog::GetMethodSpec()
{
  if (m_Method.GetCount() <= 1)
    return UString();
  UString result;
  m_Method.GetText(result);
  return result;
}

UString CCompressDialog::GetEncryptionMethodSpec()
{
  if (_encryptionMethod.GetCount() <= 1)
    return UString();
  if (_encryptionMethod.GetCurSel() <= 0)
    return UString();
  UString result;
  _encryptionMethod.GetText(result);
  result.Replace(L"-", L"");
  return result;
}

int CCompressDialog::AddDictionarySize(UInt32 size, bool kilo, bool maga)
{
  UInt32 sizePrint = size;
  if (kilo)
    sizePrint >>= 10;
  else if (maga)
    sizePrint >>= 20;
  TCHAR s[40];
  ConvertUInt64ToString(sizePrint, s);
  if (kilo)
    lstrcat(s, TEXT(" K"));
  else if (maga)
    lstrcat(s, TEXT(" M"));
  else
    lstrcat(s, TEXT(" "));
  lstrcat(s, TEXT("B"));
  int index = (int)m_Dictionary.AddString(s);
  m_Dictionary.SetItemData(index, size);
  return index;
}

int CCompressDialog::AddDictionarySize(UInt32 size)
{
  if (size > 0)
  {
    if ((size & 0xFFFFF) == 0)
      return AddDictionarySize(size, false, true);
    if ((size & 0x3FF) == 0)
      return AddDictionarySize(size, true, false);
  }
  return AddDictionarySize(size, false, false);
}

void CCompressDialog::SetDictionary()
{
  m_Dictionary.ResetContent();
  const CArcInfoEx &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
  int index = FindRegistryFormat(ai.Name);
  UInt32 defaultDictionary = UInt32(-1);
  if (index >= 0)
  {
    const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
    if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)
      defaultDictionary = fo.Dictionary;
  }
  int methodID = GetMethodID();
  UInt32 level = GetLevel2();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -