// Plugin.cpp #include "StdAfx.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/PropVariantConv.h" #include "../Common/PropIDUtils.h" #include "FarUtils.h" #include "Messages.h" #include "Plugin.h" using namespace NWindows; using namespace NFile; using namespace NDir; using namespace NFar; // This function is used by CAgentFolder int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2); int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2) { return MyStringCompareNoCase(s1, s2); } CPlugin::CPlugin(const FString &fileName, CAgent *agent, UString archiveTypeName): _agent(agent), m_FileName(fileName), _archiveTypeName(archiveTypeName), PasswordIsDefined(false) { m_ArchiveHandler = agent; if (!m_FileInfo.Find(m_FileName)) throw "error"; m_ArchiveHandler->BindToRootFolder(&_folder); } CPlugin::~CPlugin() {} static void MyGetFileTime(IFolderFolder *folder, UInt32 itemIndex, PROPID propID, FILETIME &fileTime) { NCOM::CPropVariant prop; if (folder->GetProperty(itemIndex, propID, &prop) != S_OK) throw 271932; if (prop.vt == VT_EMPTY) { fileTime.dwHighDateTime = 0; fileTime.dwLowDateTime = 0; } else { if (prop.vt != VT_FILETIME) throw 4191730; fileTime = prop.filetime; } } #define kDotsReplaceString "[[..]]" #define kDotsReplaceStringU L"[[..]]" static void CopyStrLimited(char *dest, const AString &src, unsigned len) { len--; if (src.Len() < len) len = src.Len(); memcpy(dest, src, sizeof(dest[0]) * len); dest[len] = 0; } #define COPY_STR_LIMITED(dest, src) CopyStrLimited(dest, src, Z7_ARRAY_SIZE(dest)) void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex) { NCOM::CPropVariant prop; if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK) throw 271932; if (prop.vt != VT_BSTR) throw 272340; AString oemString (UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP)); if (oemString == "..") oemString = kDotsReplaceString; COPY_STR_LIMITED(panelItem.FindData.cFileName, oemString); panelItem.FindData.cAlternateFileName[0] = 0; if (_folder->GetProperty(itemIndex, kpidAttrib, &prop) != S_OK) throw 271932; if (prop.vt == VT_UI4) panelItem.FindData.dwFileAttributes = prop.ulVal; else if (prop.vt == VT_EMPTY) panelItem.FindData.dwFileAttributes = m_FileInfo.Attrib; else throw 21631; if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK) throw 271932; if (prop.vt == VT_BOOL) { if (VARIANT_BOOLToBool(prop.boolVal)) panelItem.FindData.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; } else if (prop.vt != VT_EMPTY) throw 21632; if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK) throw 271932; UInt64 length = 0; ConvertPropVariantToUInt64(prop, length); panelItem.FindData.nFileSizeLow = (UInt32)length; panelItem.FindData.nFileSizeHigh = (UInt32)(length >> 32); MyGetFileTime(_folder, itemIndex, kpidCTime, panelItem.FindData.ftCreationTime); MyGetFileTime(_folder, itemIndex, kpidATime, panelItem.FindData.ftLastAccessTime); MyGetFileTime(_folder, itemIndex, kpidMTime, panelItem.FindData.ftLastWriteTime); if (panelItem.FindData.ftLastWriteTime.dwHighDateTime == 0 && panelItem.FindData.ftLastWriteTime.dwLowDateTime == 0) panelItem.FindData.ftLastWriteTime = m_FileInfo.MTime; if (_folder->GetProperty(itemIndex, kpidPackSize, &prop) != S_OK) throw 271932; length = 0; ConvertPropVariantToUInt64(prop, length); panelItem.PackSize = UInt32(length); panelItem.PackSizeHigh = UInt32(length >> 32); panelItem.Flags = 0; panelItem.NumberOfLinks = 0; panelItem.Description = NULL; panelItem.Owner = NULL; panelItem.CustomColumnData = NULL; panelItem.CustomColumnNumber = 0; panelItem.CRC32 = 0; panelItem.Reserved[0] = 0; panelItem.Reserved[1] = 0; } int CPlugin::GetFindData(PluginPanelItem **panelItems, int *itemsNumber, int opMode) { // CScreenRestorer screenRestorer; if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0) { /* screenRestorer.Save(); const char *msgItems[]= { g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), g_StartupInfo.GetMsgString(NMessageID::kReadingList) }; g_StartupInfo.ShowMessage(0, NULL, msgItems, Z7_ARRAY_SIZE(msgItems), 0); */ } UInt32 numItems; _folder->GetNumberOfItems(&numItems); *panelItems = new PluginPanelItem[numItems]; try { for (UInt32 i = 0; i < numItems; i++) { PluginPanelItem &panelItem = (*panelItems)[i]; ReadPluginPanelItem(panelItem, i); panelItem.UserData = i; } } catch(...) { delete [](*panelItems); throw; } *itemsNumber = (int)numItems; return(TRUE); } void CPlugin::FreeFindData(struct PluginPanelItem *panelItems, int itemsNumber) { for (int i = 0; i < itemsNumber; i++) if (panelItems[i].Description != NULL) delete []panelItems[i].Description; delete []panelItems; } void CPlugin::EnterToDirectory(const UString &dirName) { CMyComPtr newFolder; UString s = dirName; if (dirName == kDotsReplaceStringU) s = ".."; _folder->BindToFolder(s, &newFolder); if (!newFolder) { if (dirName.IsEmpty()) return; else throw 40325; } _folder = newFolder; } int CPlugin::SetDirectory(const char *aszDir, int /* opMode */) { UString path = MultiByteToUnicodeString(aszDir, CP_OEMCP); if (path == WSTRING_PATH_SEPARATOR) { _folder.Release(); m_ArchiveHandler->BindToRootFolder(&_folder); } else if (path == L"..") { CMyComPtr newFolder; _folder->BindToParentFolder(&newFolder); if (!newFolder) throw 40312; _folder = newFolder; } else if (path.IsEmpty()) EnterToDirectory(path); else { if (path[0] == WCHAR_PATH_SEPARATOR) { _folder.Release(); m_ArchiveHandler->BindToRootFolder(&_folder); path.DeleteFrontal(1); } UStringVector pathParts; SplitPathToParts(path, pathParts); FOR_VECTOR (i, pathParts) EnterToDirectory(pathParts[i]); } SetCurrentDirVar(); return TRUE; } void CPlugin::GetPathParts(UStringVector &pathParts) { pathParts.Clear(); CMyComPtr folderItem = _folder; for (;;) { CMyComPtr newFolder; folderItem->BindToParentFolder(&newFolder); if (!newFolder) break; NCOM::CPropVariant prop; if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK) if (prop.vt == VT_BSTR) pathParts.Insert(0, (const wchar_t *)prop.bstrVal); folderItem = newFolder; } } void CPlugin::SetCurrentDirVar() { m_CurrentDir.Empty(); /* // kpidPath path has tail slash, but we don't need it for compatibility with default FAR style NCOM::CPropVariant prop; if (_folder->GetFolderProperty(kpidPath, &prop) == S_OK) if (prop.vt == VT_BSTR) { m_CurrentDir = (wchar_t *)prop.bstrVal; // if (!m_CurrentDir.IsEmpty()) } m_CurrentDir.InsertAtFront(WCHAR_PATH_SEPARATOR); */ UStringVector pathParts; GetPathParts(pathParts); FOR_VECTOR (i, pathParts) { m_CurrentDir.Add_PathSepar(); m_CurrentDir += pathParts[i]; } } static const char * const kPluginFormatName = "7-ZIP"; static int FindPropNameID(PROPID propID) { if (propID > NMessageID::k_Last_PropId_supported_by_plugin) return -1; return NMessageID::kNoProperty + (int)propID; } /* struct CPropertyIDInfo { PROPID PropID; const char *FarID; int Width; // char CharID; }; static CPropertyIDInfo kPropertyIDInfos[] = { { kpidName, "N", 0}, { kpidSize, "S", 8}, { kpidPackSize, "P", 8}, { kpidAttrib, "A", 0}, { kpidCTime, "DC", 14}, { kpidATime, "DA", 14}, { kpidMTime, "DM", 14}, { kpidSolid, NULL, 0, 'S'}, { kpidEncrypted, NULL, 0, 'P'}, { kpidDictionarySize, IDS_PROPERTY_DICTIONARY_SIZE }, { kpidSplitBefore, NULL, 'B'}, { kpidSplitAfter, NULL, 'A'}, { kpidComment, NULL, 'C'}, { kpidCRC, IDS_PROPERTY_CRC } // { kpidType, L"Type" } }; static const int kNumPropertyIDInfos = Z7_ARRAY_SIZE(kPropertyIDInfos); static int FindPropertyInfo(PROPID propID) { for (int i = 0; i < kNumPropertyIDInfos; i++) if (kPropertyIDInfos[i].PropID == propID) return i; return -1; } */ // char *g_Titles[] = { "a", "f", "v" }; /* static void SmartAddToString(AString &destString, const char *srcString) { if (!destString.IsEmpty()) destString += ','; destString += srcString; } */ /* void CPlugin::AddColumn(PROPID propID) { int index = FindPropertyInfo(propID); if (index >= 0) { for (int i = 0; i < m_ProxyHandler->m_InternalProperties.Size(); i++) { const CArchiveItemProperty &aHandlerProperty = m_ProxyHandler->m_InternalProperties[i]; if (aHandlerProperty.ID == propID) break; } if (i == m_ProxyHandler->m_InternalProperties.Size()) return; const CPropertyIDInfo &propertyIDInfo = kPropertyIDInfos[index]; SmartAddToString(PanelModeColumnTypes, propertyIDInfo.FarID); char tmp[32]; itoa(propertyIDInfo.Width, tmp, 10); SmartAddToString(PanelModeColumnWidths, tmp); return; } } */ static AString GetNameOfProp(PROPID propID, const wchar_t *name) { int farID = FindPropNameID(propID); if (farID >= 0) return (AString)g_StartupInfo.GetMsgString(farID); if (name) return UnicodeStringToMultiByte(name, CP_OEMCP); char s[16]; ConvertUInt32ToString(propID, s); return (AString)s; } static AString GetNameOfProp2(PROPID propID, const wchar_t *name) { AString s (GetNameOfProp(propID, name)); if (s.Len() > (kInfoPanelLineSize - 1)) s.DeleteFrom(kInfoPanelLineSize - 1); return s; } static AString ConvertSizeToString(UInt64 value) { char s[32]; ConvertUInt64ToString(value, s); unsigned i = MyStringLen(s); unsigned pos = Z7_ARRAY_SIZE(s); s[--pos] = 0; while (i > 3) { s[--pos] = s[--i]; s[--pos] = s[--i]; s[--pos] = s[--i]; s[--pos] = ' '; } while (i > 0) s[--pos] = s[--i]; return (AString)(s + pos); } static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) { if (prop.vt == VT_BSTR) { AString s (UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP)); s.Replace((char)0xA, ' '); s.Replace((char)0xD, ' '); return s; } if (prop.vt == VT_BOOL) { int messageID = VARIANT_BOOLToBool(prop.boolVal) ? NMessageID::kYes : NMessageID::kNo; return (AString)g_StartupInfo.GetMsgString(messageID); } if (prop.vt != VT_EMPTY) { if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && ( propID == kpidSize || propID == kpidPackSize || propID == kpidNumSubDirs || propID == kpidNumSubFiles || propID == kpidNumBlocks || propID == kpidPhySize || propID == kpidHeadersSize || propID == kpidClusterSize || propID == kpidUnpackSize )) { UInt64 v = 0; ConvertPropVariantToUInt64(prop, v); return ConvertSizeToString(v); } { char sz[64]; ConvertPropertyToShortString2(sz, prop, propID); return (AString)sz; } } return AString(); } static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID) { AString s (PropToString(prop, propID)); if (s.Len() > (kInfoPanelLineSize - 1)) s.DeleteFrom(kInfoPanelLineSize - 1); return s; } static void AddPropertyString(InfoPanelLine *lines, unsigned &numItems, PROPID propID, const wchar_t *name, const NCOM::CPropVariant &prop) { if (prop.vt != VT_EMPTY) { AString val (PropToString2(prop, propID)); if (!val.IsEmpty()) { InfoPanelLine &item = lines[numItems++]; COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name)); COPY_STR_LIMITED(item.Data, val); } } } static void InsertSeparator(InfoPanelLine *lines, unsigned &numItems) { if (numItems < kNumInfoLinesMax) { InfoPanelLine &item = lines[numItems++]; *item.Text = 0; *item.Data = 0; item.Separator = TRUE; } } void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) { info->StructSize = sizeof(*info); info->Flags = OPIF_USEFILTER | OPIF_USESORTGROUPS | OPIF_USEHIGHLIGHTING | OPIF_ADDDOTS | OPIF_COMPAREFATTIME; COPY_STR_LIMITED(m_FileNameBuffer, UnicodeStringToMultiByte(fs2us(m_FileName), CP_OEMCP)); info->HostFile = m_FileNameBuffer; // test it it is not static COPY_STR_LIMITED(m_CurrentDirBuffer, UnicodeStringToMultiByte(m_CurrentDir, CP_OEMCP)); info->CurDir = m_CurrentDirBuffer; info->Format = kPluginFormatName; { UString name; { FString dirPrefix, fileName; GetFullPathAndSplit(m_FileName, dirPrefix, fileName); name = fs2us(fileName); } m_PannelTitle = ' '; m_PannelTitle += _archiveTypeName; m_PannelTitle.Add_Colon(); m_PannelTitle += name; m_PannelTitle.Add_Space(); if (!m_CurrentDir.IsEmpty()) { // m_PannelTitle += '\\'; m_PannelTitle += m_CurrentDir; } COPY_STR_LIMITED(m_PannelTitleBuffer, UnicodeStringToMultiByte(m_PannelTitle, CP_OEMCP)); info->PanelTitle = m_PannelTitleBuffer; } memset(m_InfoLines, 0, sizeof(m_InfoLines)); m_InfoLines[0].Text[0] = 0; m_InfoLines[0].Separator = TRUE; MyStringCopy(m_InfoLines[1].Text, g_StartupInfo.GetMsgString(NMessageID::kArchiveType)); MyStringCopy(m_InfoLines[1].Data, (const char *)UnicodeStringToMultiByte(_archiveTypeName, CP_OEMCP)); unsigned numItems = 2; { CMyComPtr folderProperties; _folder.QueryInterface(IID_IFolderProperties, &folderProperties); if (folderProperties) { UInt32 numProps; if (folderProperties->GetNumberOfFolderProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps && numItems < kNumInfoLinesMax; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (folderProperties->GetFolderPropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (_folder->GetFolderProperty(propID, &prop) != S_OK || prop.vt == VT_EMPTY) continue; InfoPanelLine &item = m_InfoLines[numItems++]; COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name)); COPY_STR_LIMITED(item.Data, PropToString2(prop, propID)); } } } } /* if (numItems < kNumInfoLinesMax) { InsertSeparator(m_InfoLines, numItems); } */ { CMyComPtr getFolderArcProps; _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); if (getFolderArcProps) { CMyComPtr getProps; getFolderArcProps->GetFolderArcProps(&getProps); if (getProps) { UInt32 numLevels; if (getProps->GetArcNumLevels(&numLevels) != S_OK) numLevels = 0; for (UInt32 level2 = 0; level2 < numLevels; level2++) { { UInt32 level = numLevels - 1 - level2; UInt32 numProps; if (getProps->GetArcNumProps(level, &numProps) == S_OK) { InsertSeparator(m_InfoLines, numItems); for (Int32 i = -3; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; switch (i) { case -3: propID = kpidPath; break; case -2: propID = kpidType; break; case -1: propID = kpidError; break; default: if (getProps->GetArcPropInfo(level, (UInt32)i, &name, &propID, &vt) != S_OK) continue; } NCOM::CPropVariant prop; if (getProps->GetArcProp(level, propID, &prop) != S_OK) continue; AddPropertyString(m_InfoLines, numItems, propID, name, prop); } } } if (level2 != numLevels - 1) { UInt32 level = numLevels - 1 - level2; UInt32 numProps; if (getProps->GetArcNumProps2(level, &numProps) == S_OK) { InsertSeparator(m_InfoLines, numItems); for (Int32 i = 0; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (getProps->GetArcPropInfo2(level, (UInt32)i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (getProps->GetArcProp2(level, propID, &prop) != S_OK) continue; AddPropertyString(m_InfoLines, numItems, propID, name, prop); } } } } } } } //m_InfoLines[1].Separator = 0; info->InfoLines = m_InfoLines; info->InfoLinesNumber = (int)numItems; info->DescrFiles = NULL; info->DescrFilesNumber = 0; PanelModeColumnTypes.Empty(); PanelModeColumnWidths.Empty(); /* AddColumn(kpidName); AddColumn(kpidSize); AddColumn(kpidPackSize); AddColumn(kpidMTime); AddColumn(kpidCTime); AddColumn(kpidATime); AddColumn(kpidAttrib); _panelMode.ColumnTypes = (char *)(const char *)PanelModeColumnTypes; _panelMode.ColumnWidths = (char *)(const char *)PanelModeColumnWidths; _panelMode.ColumnTitles = NULL; _panelMode.FullScreen = TRUE; _panelMode.DetailedStatus = FALSE; _panelMode.AlignExtensions = FALSE; _panelMode.CaseConversion = FALSE; _panelMode.StatusColumnTypes = "N"; _panelMode.StatusColumnWidths = "0"; _panelMode.Reserved[0] = 0; _panelMode.Reserved[1] = 0; info->PanelModesArray = &_panelMode; info->PanelModesNumber = 1; */ info->PanelModesArray = NULL; info->PanelModesNumber = 0; info->StartPanelMode = 0; info->StartSortMode = 0; info->KeyBar = NULL; info->ShortcutData = NULL; } struct CArchiveItemProperty { AString Name; PROPID ID; VARTYPE Type; }; static inline char GetHex_A_minus10(unsigned v, unsigned a10) { return (char)(v < 10 ? v + '0' : v + a10); } HRESULT CPlugin::ShowAttributesWindow() { PluginPanelItem pluginPanelItem; if (!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem)) return S_FALSE; if (strcmp(pluginPanelItem.FindData.cFileName, "..") == 0 && NFind::NAttributes::IsDir(pluginPanelItem.FindData.dwFileAttributes)) return S_FALSE; const UInt32 itemIndex = (UInt32)pluginPanelItem.UserData; CObjectVector properties; UInt32 numProps; RINOK(_folder->GetNumberOfProperties(&numProps)) unsigned i; for (i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(_folder->GetPropertyInfo(i, &name, &propID, &vt)) CArchiveItemProperty prop; prop.Type = vt; prop.ID = propID; if (prop.ID == kpidPath) prop.ID = kpidName; prop.Name = GetNameOfProp(propID, name); properties.Add(prop); } int size = 2; CRecordVector initDialogItems; int xSize = 70; { const CInitDialogItem idi = { DI_DOUBLEBOX, 3, 1, xSize - 4, size - 2, false, false, 0, false, NMessageID::kProperties, NULL, NULL }; initDialogItems.Add(idi); } AStringVector values; const int kStartY = 3; for (i = 0; i < properties.Size(); i++) { const CArchiveItemProperty &property = properties[i]; const int startY = kStartY + (int)values.Size(); { CInitDialogItem idi = { DI_TEXT, 5, startY, 0, 0, false, false, 0, false, 0, NULL, NULL }; idi.DataMessageId = FindPropNameID(property.ID); if (idi.DataMessageId < 0) idi.DataString = property.Name; initDialogItems.Add(idi); } NCOM::CPropVariant prop; RINOK(_folder->GetProperty(itemIndex, property.ID, &prop)) values.Add(PropToString(prop, property.ID)); { const CInitDialogItem idi = { DI_TEXT, 30, startY, 0, 0, false, false, 0, false, -1, NULL, NULL }; initDialogItems.Add(idi); } } CMyComPtr _folderRawProps; _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps); CObjectVector properties2; if (_folderRawProps) { _folderRawProps->GetNumRawProps(&numProps); for (i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; if (_folderRawProps->GetRawPropInfo(i, &name, &propID) != S_OK) continue; CArchiveItemProperty prop; prop.Type = VT_EMPTY; prop.ID = propID; if (prop.ID == kpidPath) prop.ID = kpidName; prop.Name = GetNameOfProp(propID, name); properties2.Add(prop); } for (i = 0; i < properties2.Size(); i++) { const CArchiveItemProperty &property = properties2[i]; CMyComBSTR name; const void *data; UInt32 dataSize; UInt32 propType; if (_folderRawProps->GetRawProp(itemIndex, property.ID, &data, &dataSize, &propType) != S_OK) continue; if (dataSize != 0) { AString s; if (property.ID == kpidNtSecure) ConvertNtSecureToString((const Byte *)data, dataSize, s); else { const UInt32 kMaxDataSize = 64; if (dataSize > kMaxDataSize) { s += "data:"; s.Add_UInt32(dataSize); } else { const unsigned a = dataSize <= 8 && (property.ID == kpidCRC || property.ID == kpidChecksum) ? 'A' - 10 : 'a' - 10; for (UInt32 k = 0; k < dataSize; k++) { const unsigned b = ((const Byte *)data)[k]; s += GetHex_A_minus10(b >> 4, a); s += GetHex_A_minus10(b & 15, a); } } } const int startY = kStartY + (int)values.Size(); { CInitDialogItem idi = { DI_TEXT, 5, startY, 0, 0, false, false, 0, false, 0, NULL, NULL }; idi.DataMessageId = FindPropNameID(property.ID); if (idi.DataMessageId < 0) idi.DataString = property.Name; initDialogItems.Add(idi); } values.Add(s); { const CInitDialogItem idi = { DI_TEXT, 30, startY, 0, 0, false, false, 0, false, -1, NULL, NULL }; initDialogItems.Add(idi); } } } } const unsigned numLines = values.Size(); for (i = 0; i < numLines; i++) { CInitDialogItem &idi = initDialogItems[1 + i * 2 + 1]; idi.DataString = values[i]; } const unsigned numDialogItems = initDialogItems.Size(); CObjArray dialogItems(numDialogItems); g_StartupInfo.InitDialogItems(initDialogItems.ConstData(), dialogItems, numDialogItems); unsigned maxLen = 0; for (i = 0; i < numLines; i++) { FarDialogItem &dialogItem = dialogItems[1 + i * 2]; unsigned len = (unsigned)strlen(dialogItem.Data); if (len > maxLen) maxLen = len; } unsigned maxLen2 = 0; const unsigned kSpace = 10; for (i = 0; i < numLines; i++) { FarDialogItem &dialogItem = dialogItems[1 + i * 2 + 1]; const unsigned len = (unsigned)strlen(dialogItem.Data); if (len > maxLen2) maxLen2 = len; dialogItem.X1 = (int)(maxLen + kSpace); } size = (int)numLines + 6; xSize = (int)(maxLen + kSpace + maxLen2 + 5); FarDialogItem &firstDialogItem = dialogItems[0]; firstDialogItem.Y2 = size - 2; firstDialogItem.X2 = xSize - 4; /* int askCode = */ g_StartupInfo.ShowDialog(xSize, size, NULL, dialogItems, numDialogItems); return S_OK; } int CPlugin::ProcessKey(int key, unsigned controlState) { if (key == VK_F7 && controlState == 0) { CreateFolder(); return TRUE; } if (controlState == PKF_CONTROL && key == 'A') { HRESULT result = ShowAttributesWindow(); if (result == S_OK) return TRUE; if (result == S_FALSE) return FALSE; throw "Error"; } if ((controlState & PKF_ALT) != 0 && key == VK_F6) { FString folderPath; if (!GetOnlyDirPrefix(m_FileName, folderPath)) return FALSE; PanelInfo panelInfo; g_StartupInfo.ControlGetActivePanelInfo(panelInfo); GetFilesReal(panelInfo.SelectedItems, (unsigned)panelInfo.SelectedItemsNumber, FALSE, UnicodeStringToMultiByte(fs2us(folderPath), CP_OEMCP), OPM_SILENT, true); g_StartupInfo.Control(this, FCTL_UPDATEPANEL, NULL); g_StartupInfo.Control(this, FCTL_REDRAWPANEL, NULL); g_StartupInfo.Control(this, FCTL_UPDATEANOTHERPANEL, NULL); g_StartupInfo.Control(this, FCTL_REDRAWANOTHERPANEL, NULL); return TRUE; } return FALSE; }