// Заполняем меню выбора таблиц символов void FillCodePagesVMenu(bool bShowUnicode, bool bShowUTF, bool bShowUTF7, bool bShowAutoDetect=false, bool bShowM2=false) { uintptr_t codePage = currentCodePage; if (CodePages->GetSelectPos()!=-1 && CodePages->GetSelectPos()<CodePages->GetItemCount()-normalCodePages) currentCodePage = GetMenuItemCodePage(); // Очищаем меню favoriteCodePages = normalCodePages = 0; CodePages->DeleteItems(); UnicodeString title = MSG(MGetCodePageTitle); if (Opt.CPMenuMode) title += L" *"; CodePages->SetTitle(title); // Добавляем таблицы символов AddCodePages(::OEM | ::ANSI | (bShowUTF ? ::UTF8 : 0) | (bShowUTF7 ? ::UTF7 : 0) | (bShowUnicode ? (::UTF16BE | ::UTF16LE) : 0) | (bShowAutoDetect ? ::Auto : 0) | (bShowM2 ? ::AllowM2 : 0) ); // Восстанавливаем оригинальню таблицу символов currentCodePage = codePage; // Позиционируем меню CodePages->SetPosition(-1, -1, 0, 0); // Показываем меню CodePages->Show(); }
// Заполняем меню выбора таблиц символов void FillCodePagesVMenu(bool bShowUnicode, bool bShowUTF, bool bShowUTF7) { UINT codePage = currentCodePage; if (CodePages->GetSelectPos()!=-1 && CodePages->GetSelectPos()<CodePages->GetItemCount()-normalCodePages) currentCodePage = GetMenuItemCodePage(); // Очищаем меню favoriteCodePages = normalCodePages = 0; CodePages->DeleteItems(); UnicodeString title = MSG(MGetCodePageTitle); if (Opt.CPMenuMode) title += L" *"; CodePages->SetTitle(title); // Добавляем таблицы символов // BUBUG: Когда добавится поддержка UTF7 параметр bShowUTF7 нужно убрать отовсюду AddCodePages(::DOS | ::ANSI | ::KOI8 | (bShowUTF ? ::UTF8 : 0) | (bShowUTF7 ? ::UTF7 : 0) | (bShowUnicode ? AllUtfBiggerThan8 : 0)); // Восстанавливаем оригинальню таблицу символов currentCodePage = codePage; // Позиционируем меню CodePages->SetPosition(-1, -1, 0, 0); // Показываем меню CodePages->Show(); }
uintptr_t SelectCodePage(uintptr_t nCurrent, bool bShowUnicode, bool bShowUTF, bool bShowUTF7, bool bShowAutoDetect) { CallbackCallSource = CodePageSelect; currentCodePage = nCurrent; // Создаём меню CodePages = new VMenu(L"", nullptr, 0, ScrY-4); CodePages->SetBottomTitle(MSG(!Opt.CPMenuMode?MGetCodePageBottomTitle:MGetCodePageBottomShortTitle)); CodePages->SetFlags(VMENU_WRAPMODE|VMENU_AUTOHIGHLIGHT); CodePages->SetHelp(L"CodePagesMenu"); // Добавляем таблицы символов FillCodePagesVMenu(bShowUnicode, bShowUTF, bShowUTF7, bShowAutoDetect); // Показываем меню CodePages->Show(); // Цикл обработки сообщений меню while (!CodePages->Done()) { switch (CodePages->ReadInput()) { // Обработка скрытия/показа системных таблиц символов case KEY_CTRLH: case KEY_RCTRLH: Opt.CPMenuMode = !Opt.CPMenuMode; CodePages->SetBottomTitle(MSG(!Opt.CPMenuMode?MGetCodePageBottomTitle:MGetCodePageBottomShortTitle)); FillCodePagesVMenu(bShowUnicode, bShowUTF, bShowUTF7, bShowAutoDetect); break; // Обработка удаления таблицы символов из списка выбранных case KEY_DEL: case KEY_NUMDEL: ProcessSelected(false); break; // Обработка добавления таблицы символов в список выбранных case KEY_INS: case KEY_NUMPAD0: ProcessSelected(true); break; // Редактируем имя таблицы символов case KEY_F4: EditCodePageName(); break; default: CodePages->ProcessInput(); break; } } // Получаем выбранную таблицу символов uintptr_t codePage = CodePages->Modal::GetExitCode() >= 0 ? static_cast<WORD>(GetMenuItemCodePage()) : (uintptr_t)-1; delete CodePages; CodePages = nullptr; return codePage; }
// Каллбак для диалога редактирования имени кодовой страницы intptr_t WINAPI EditDialogProc(HANDLE hDlg, intptr_t Msg, intptr_t Param1, void* Param2) { if (Msg==DN_CLOSE) { if (Param1==EDITCP_OK || Param1==EDITCP_RESET) { string strCodePageName; uintptr_t CodePage = GetMenuItemCodePage(); FormatString strCodePage; strCodePage<<CodePage; if (Param1==EDITCP_OK) { FarDialogItemData item = {sizeof(FarDialogItemData)}; item.PtrLength = SendDlgMessage(hDlg, DM_GETTEXT, EDITCP_EDIT, 0); item.PtrData = strCodePageName.GetBuffer(item.PtrLength+1); SendDlgMessage(hDlg, DM_GETTEXT, EDITCP_EDIT, &item); strCodePageName.ReleaseBuffer(); } // Если имя кодовой страницы пустое, то считаем, что имя не задано if (!strCodePageName.GetLength()) GeneralCfg->DeleteValue(NamesOfCodePagesKey, strCodePage); else GeneralCfg->SetValue(NamesOfCodePagesKey, strCodePage, strCodePageName); // Получаем информацию о кодовой странице CPINFOEX cpiex; if (GetCodePageInfo(CodePage, cpiex)) { // Формируем имя таблиц символов bool IsCodePageNameCustom = false; wchar_t *CodePageName = FormatCodePageName(CodePage, cpiex.CodePageName, sizeof(cpiex.CodePageName)/sizeof(wchar_t), IsCodePageNameCustom); // Формируем строку представления strCodePage.Clear(); FormatCodePageString(CodePage, CodePageName, strCodePage, IsCodePageNameCustom); // Обновляем имя кодовой страницы int Position = CodePages->GetSelectPos(); CodePages->DeleteItem(Position); MenuItemEx NewItem; NewItem.Clear(); NewItem.strName = strCodePage; NewItem.UserData = &CodePage; NewItem.UserDataSize = sizeof(CodePage); CodePages->AddItem(&NewItem, Position); CodePages->SetSelectPos(Position, 1); } } } return DefDlgProc(hDlg, Msg, Param1, Param2); }
// Каллбак для диалога редактирования имени кодовой страницы LONG_PTR WINAPI EditDialogProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) { if (Msg==DN_CLOSE) { if (Param1==EDITCP_OK || Param1==EDITCP_RESET) { FARString strCodePageName; UINT CodePage = GetMenuItemCodePage(); FormatString strCodePage; strCodePage<<CodePage; if (Param1==EDITCP_OK) { wchar_t *CodePageName = strCodePageName.GetBuffer(SendDlgMessage(hDlg, DM_GETTEXTPTR, EDITCP_EDIT, 0)+1); SendDlgMessage(hDlg, DM_GETTEXTPTR, EDITCP_EDIT, (LONG_PTR)CodePageName); strCodePageName.ReleaseBuffer(); } // Если имя кодовой страницы пустое, то считаем, что имя не задано if (!strCodePageName.GetLength()) DeleteRegValue(NamesOfCodePagesKey, strCodePage); else SetRegKey(NamesOfCodePagesKey, strCodePage, strCodePageName); // Получаем информацию о кодовой странице CPINFOEX cpiex; if (GetCodePageInfo(CodePage, cpiex)) { // Формируем имя таблиц символов bool IsCodePageNameCustom = false; wchar_t *CodePageName = FormatCodePageName(CodePage, cpiex.CodePageName, sizeof(cpiex.CodePageName)/sizeof(wchar_t), IsCodePageNameCustom); // Формируем строку представления strCodePage.Clear(); FormatCodePageString(CodePage, CodePageName, strCodePage, IsCodePageNameCustom); // Обновляем имя кодовой страницы int Position = CodePages->GetSelectPos(); CodePages->DeleteItem(Position); MenuItemEx NewItem; NewItem.Clear(); NewItem.strName = strCodePage; NewItem.UserData = (char *)(UINT_PTR)CodePage; NewItem.UserDataSize = sizeof(UINT); CodePages->AddItem(&NewItem, Position); CodePages->SetSelectPos(Position, 1); } } } return DefDlgProc(hDlg, Msg, Param1, Param2); }
// Получаем позицию для вставки таблицы с учётом сортировки по номеру кодовой страницы int GetCodePageInsertPosition(UINT codePage, int start, int length) { for (int position=start; position < start+length; position++) { UINT itemCodePage; if (CallbackCallSource == CodePageSelect) itemCodePage = GetMenuItemCodePage(position); else itemCodePage = GetListItemCodePage(position); if (itemCodePage >= codePage) return position; } return start+length; }
// Обработка добавления/удаления в/из список выбранных таблиц символов void ProcessSelected(bool select) { if (Opt.CPMenuMode && select) return; UINT itemPosition = CodePages->GetSelectPos(); UINT codePage = GetMenuItemCodePage(); if ((select && IsPositionFavorite(itemPosition)) || (!select && IsPositionNormal(itemPosition))) { // Преобразуем номер таблицы символов в строку FormatString strCPName; strCPName<<codePage; // Получаем текущее состояние флага в реестре int selectType = 0; GetRegKey(FavoriteCodePagesKey, strCPName, selectType, 0); // Удаляем/добавляем в ресестре информацию о выбранной кодовой странице if (select) SetRegKey(FavoriteCodePagesKey, strCPName, CPST_FAVORITE | (selectType & CPST_FIND ? CPST_FIND : 0)); else if (selectType & CPST_FIND) SetRegKey(FavoriteCodePagesKey, strCPName, CPST_FIND); else DeleteRegValue(FavoriteCodePagesKey, strCPName); // Создаём новый элемент меню MenuItemEx newItem; newItem.Clear(); newItem.strName = CodePages->GetItemPtr()->strName; newItem.UserData = (char *)(UINT_PTR)codePage; newItem.UserDataSize = sizeof(UINT); // Сохраняем позицию курсора int position=CodePages->GetSelectPos(); // Удаляем старый пункт меню CodePages->DeleteItem(CodePages->GetSelectPos()); // Добавляем пункт меню в новое место if (select) { // Добавляем разделитель, если выбранных кодовых страниц ещё не было // и после добавления останутся нормальные кодовые страницы if (!favoriteCodePages && normalCodePages>1) AddSeparator(MSG(MGetCodePageFavorites),CodePages->GetItemCount()-normalCodePages); // Ищем позицию, куда добавить элемент int newPosition = GetCodePageInsertPosition( codePage, CodePages->GetItemCount()-normalCodePages-favoriteCodePages, favoriteCodePages ); // Добавляем кодовою страницу в выбранные CodePages->AddItem(&newItem, newPosition); // Удаляем разделитель, если нет обыкновынных кодовых страниц if (normalCodePages==1) CodePages->DeleteItem(CodePages->GetItemCount()-1); // Изменяем счётчики нормальных и выбранных кодовых страниц favoriteCodePages++; normalCodePages--; position++; } else { // Удаляем разделитеь, если после удаления не останнется ни одной // выбранной таблицы символов if (favoriteCodePages==1 && normalCodePages>0) CodePages->DeleteItem(CodePages->GetItemCount()-normalCodePages-2); // Переносим элемент в нормальные таблицы, только если они показываются if (!Opt.CPMenuMode) { // Добавляем разделитель, если не было ни одной нормальной кодовой страницы if (!normalCodePages) AddSeparator(MSG(MGetCodePageOther)); // Добавляем кодовою страницу в нормальные CodePages->AddItem( &newItem, GetCodePageInsertPosition( codePage, CodePages->GetItemCount()-normalCodePages, normalCodePages ) ); normalCodePages++; } // Если в режиме скрытия нормальных таблиц мы удалили последнюю выбранную таблицу, то удаляем и разделитель else if (favoriteCodePages==1) CodePages->DeleteItem(CodePages->GetItemCount()-normalCodePages-1); favoriteCodePages--; if (position==CodePages->GetItemCount()-normalCodePages-1) position--; } // Устанавливаем позицию в меню CodePages->SetSelectPos(position>=CodePages->GetItemCount() ? CodePages->GetItemCount()-1 : position, 1); // Показываем меню if (Opt.CPMenuMode) CodePages->SetPosition(-1, -1, 0, 0); CodePages->Show(); } }
// Добавляем таблицу символов void AddCodePage(const wchar_t *codePageName, UINT codePage, int position, bool enabled, bool checked, bool IsCodePageNameCustom) { if (CallbackCallSource == CodePagesFill) { // Вычисляем позицию вставляемого элемента if (position==-1) { FarListInfo info; SendDlgMessage(dialog, DM_LISTINFO, control, (LONG_PTR)&info); position = info.ItemsNumber; } // Вставляем элемент FarListInsert item = {position, {}}; FormatString name; FormatCodePageString(codePage, codePageName, name, IsCodePageNameCustom); item.Item.Text = name; if (selectedCodePages && checked) { item.Item.Flags |= MIF_CHECKED; } if (!enabled) { item.Item.Flags |= MIF_GRAYED; } SendDlgMessage(dialog, DM_LISTINSERT, control, (LONG_PTR)&item); // Устанавливаем данные для элемента FarListItemData data; data.Index = position; data.Data = (void*)(DWORD_PTR)codePage; data.DataSize = sizeof(UINT); SendDlgMessage(dialog, DM_LISTSETDATA, control, (LONG_PTR)&data); } else { // Создаём новый элемент меню MenuItemEx item; item.Clear(); if (!enabled) item.Flags |= MIF_GRAYED; FormatString name; FormatCodePageString(codePage, codePageName, name, IsCodePageNameCustom); item.strName = name; item.UserData = (char *)(UINT_PTR)codePage; item.UserDataSize = sizeof(UINT); // Добавляем новый элемент в меню if (position>=0) CodePages->AddItem(&item, position); else CodePages->AddItem(&item); // Если надо позиционируем курсор на добавленный элемент if (currentCodePage==codePage) { if ((CodePages->GetSelectPos()==-1 || GetMenuItemCodePage()!=codePage)) { CodePages->SetSelectPos(position>=0?position:CodePages->GetItemCount()-1, 1); } } } }