Skip to content

Commit 91dc985

Browse files
committed
added Copy command into menu
1 parent 63d32fb commit 91dc985

File tree

3 files changed

+198
-21
lines changed

3 files changed

+198
-21
lines changed

languages.ini

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,10 @@ ctxmenu_add_new_line="&Add New Line Ctrl+I"
205205
; Result Docking Menu
206206
rdmenu_fold_all="Fold all"
207207
rdmenu_unfold_all="Unfold all"
208+
rdmenu_copy_std="&Copy Ctrl+C"
208209
rdmenu_copy_lines="Copy Selected Line(s)"
209210
rdmenu_copy_paths="Copy Selected Pathname(s)"
210-
rdmenu_select_all="Select All"
211+
rdmenu_select_all="Select All Ctrl+A"
211212
rdmenu_clear_all="Clear all"
212213
rdmenu_open_paths="Open Selected Pathname(s)"
213214
rdmenu_wrap="Word wrap long lines"
@@ -420,9 +421,10 @@ ctxmenu_add_new_line="Neue &Zeile einfügen Ctrl+I"
420421
; Result Docking Menu
421422
rdmenu_fold_all="Alles einklappen"
422423
rdmenu_unfold_all="Alles aufklappen"
424+
rdmenu_copy_std="&Kopieren Ctrl+C"
423425
rdmenu_copy_lines="Kopiere ausgewählte Zeile(n)"
424426
rdmenu_copy_paths="Gewählte(n) Pfadnamen kopieren"
425-
rdmenu_select_all="Alles auswählen"
427+
rdmenu_select_all="Alles auswählen Ctrl+A"
426428
rdmenu_clear_all="Alles löschen"
427429
rdmenu_open_paths="Gewählte(n) Pfadnamen öffnen"
428430
rdmenu_wrap="Zeilenumbruch bei langen Zeilen"
@@ -635,9 +637,10 @@ ctxmenu_add_new_line="&Nuova Riga Ctrl+I"
635637
; Result Docking Menu
636638
rdmenu_fold_all="Riduci tutto"
637639
rdmenu_unfold_all="Espandi tutto"
640+
rdmenu_copy_std="&Copia Ctrl+C"
638641
rdmenu_copy_lines="Copia righe selezionate"
639642
rdmenu_copy_paths="Copia i Percorsi Selezionati"
640-
rdmenu_select_all="Seleziona tutto"
643+
rdmenu_select_all="Seleziona t&utto Ctrl+A"
641644
rdmenu_clear_all="Pulisci tutto"
642645
rdmenu_open_paths="Apri i Percorsi Selezionati"
643646
rdmenu_wrap="Attiva il Ritorno a capo automatico"
@@ -841,7 +844,7 @@ ctxmenu_copy="&Másol Ctrl+C"
841844
ctxmenu_paste="Beille&szt Ctrl+V"
842845
ctxmenu_edit="Mező szerk&esztése"
843846
ctxmenu_delete="&Töröl Del"
844-
ctxmenu_select_all="&Összes kiválasztása Ctrl+A"
847+
ctxmenu_select_all="&Összes kijelölése Ctrl+A"
845848
ctxmenu_enable="En&gedélyez Alt+E"
846849
ctxmenu_disable="&Letilt Alt+D"
847850
ctxmenu_undo="Visszavo&n Ctrl+Z"
@@ -850,9 +853,10 @@ ctxmenu_add_new_line="&Új Sor Beszúrása Ctrl+I"
850853
; Result Docking Menu
851854
rdmenu_fold_all="Minden blokk összecsukása"
852855
rdmenu_unfold_all="Minden blokk kibontása"
856+
rdmenu_copy_std="&Másol Ctrl+C"
853857
rdmenu_copy_lines="Kijelölt sor(ok) másolása"
854858
rdmenu_copy_paths="A kijelölt elérési út/utak másolása"
855-
rdmenu_select_all="Az összes kijelölése"
859+
rdmenu_select_all="Az &összes kijelölése Ctrl+A"
856860
rdmenu_clear_all="Az összes eredmény eltávolítása"
857861
rdmenu_open_paths="A kijelölt elérési út/utak megnyitása"
858862
rdmenu_wrap="A hosszú sorok tördelése"
@@ -1066,9 +1070,10 @@ ctxmenu_add_new_line="Добавить &новую строку Ctrl+I"
10661070
; Result Docking Menu
10671071
rdmenu_fold_all="Свернуть все блоки"
10681072
rdmenu_unfold_all="Развернуть все блоки"
1073+
rdmenu_copy_std="&Скопировать Ctrl+C"
10691074
rdmenu_copy_lines="Копировать (выбранные строки)"
10701075
rdmenu_copy_paths="Путь и Имя выделенных файлов в буфер"
1071-
rdmenu_select_all="Выделить Всё"
1076+
rdmenu_select_all="Выде&лить Всё Ctrl+A"
10721077
rdmenu_clear_all="Очистить Окно Поиска"
10731078
rdmenu_open_paths="Открыть все выделенные файлы"
10741079
rdmenu_wrap="Перенос длинных строк"
@@ -1282,9 +1287,10 @@ ctxmenu_add_new_line="&Añadir Nueva Línea Ctrl+I"
12821287
; Result Docking Menu
12831288
rdmenu_fold_all="Contraer todo"
12841289
rdmenu_unfold_all="Expandir todo"
1290+
rdmenu_copy_std="&Copiar Ctrl+C"
12851291
rdmenu_copy_lines="Copiar línea(s) seleccionada(s)"
12861292
rdmenu_copy_paths="Copiar nombre(s) de ruta(s) seleccionada(s)"
1287-
rdmenu_select_all="Seleccionar todo"
1293+
rdmenu_select_all="Seleccionar &todo Ctrl+A"
12881294
rdmenu_clear_all="Limpiar todo"
12891295
rdmenu_open_paths="Abrir ruta(s) seleccionada(s)"
12901296
rdmenu_wrap="Ajustar longitud del texto"
@@ -1498,9 +1504,10 @@ ctxmenu_add_new_line="&Ajouter une nouvelle ligne Ctrl+I"
14981504
; Result Docking Menu
14991505
rdmenu_fold_all="Replier tout"
15001506
rdmenu_unfold_all="Déplier tout"
1507+
rdmenu_copy_std="&Copier Ctrl+C"
15011508
rdmenu_copy_lines="Copier la(les) ligne(s) sélectionnée(s)"
15021509
rdmenu_copy_paths="Copier le(s) chemin(s) sélectionné(s)"
1503-
rdmenu_select_all="Sélectionner tout"
1510+
rdmenu_select_all="Sélectio&nner tout Ctrl+A"
15041511
rdmenu_clear_all="Effacer tout"
15051512
rdmenu_open_paths="Ouvrir le(s) chemin(s) sélectionné(s)"
15061513
rdmenu_wrap="Retour à la ligne automatique"
@@ -1714,9 +1721,10 @@ ctxmenu_add_new_line="&Adicionar Nova Linha Ctrl+I"
17141721
; Result Docking Menu
17151722
rdmenu_fold_all="Recolher tudo"
17161723
rdmenu_unfold_all="Expandir tudo"
1724+
rdmenu_copy_std=&Copiar Ctrl+C"
17171725
rdmenu_copy_lines="Copiar linha(s) selecionada(s)"
17181726
rdmenu_copy_paths="Copiar nome do caminho selecionado(s)"
1719-
rdmenu_select_all="Selecionar tudo"
1727+
rdmenu_select_all="Selecionar &tudo Ctrl+A"
17201728
rdmenu_clear_all="Limpar tudo"
17211729
rdmenu_open_paths="Abrir nome do caminho selecionado(s)"
17221730
rdmenu_wrap="Quebra de linha em linhas longas"
@@ -1930,9 +1938,10 @@ ctxmenu_add_new_line="Indsæt &Ny Linje Ctrl+I"
19301938
; Result Docking Menu
19311939
rdmenu_fold_all="Sammenfold alle"
19321940
rdmenu_unfold_all="Udvid alle"
1941+
rdmenu_copy_std="&Kopiér Ctrl+C"
19331942
rdmenu_copy_lines="Kopiér valgte linie(r)"
19341943
rdmenu_copy_paths="Copy Selected Pathname(s)"
1935-
rdmenu_select_all="Markér alt"
1944+
rdmenu_select_all="Markér &alt Ctrl+A"
19361945
rdmenu_clear_all="Ryd alle"
19371946
rdmenu_open_paths="Open Selected Pathname(s)"
19381947
rdmenu_wrap="Ombryd lange linier"
@@ -2146,9 +2155,10 @@ ctxmenu_add_new_line="&Додати новий рядок Ctrl+I"
21462155
; Result Docking Menu
21472156
rdmenu_fold_all="Згорнути все"
21482157
rdmenu_unfold_all="Розгорнути все"
2158+
rdmenu_copy_std="Ско&піювати Ctrl+C"
21492159
rdmenu_copy_lines="Копіювати вибрані рядки"
21502160
rdmenu_copy_paths="Copy Selected Pathname(s)"
2151-
rdmenu_select_all="Вибрати все"
2161+
rdmenu_select_all="Вибрати &все Ctrl+A"
21522162
rdmenu_clear_all="Очистити все"
21532163
rdmenu_open_paths="Open Selected Pathname(s)"
21542164
rdmenu_wrap="Обтинати слова в довгих рядках"

src/ResultDock.cpp

Lines changed: 168 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,13 @@ LRESULT CALLBACK ResultDock::sciSubclassProc(HWND hwnd, UINT msg, WPARAM wp, LPA
11001100
::SendMessage(nppData._nppHandle, NPPM_DMMHIDE, 0, (LPARAM)ResultDock::instance()._hDock);
11011101
return TRUE;
11021102

1103+
case WM_KEYDOWN:
1104+
if (wp == VK_DELETE) {
1105+
deleteSelectedItems(hwnd);
1106+
return 0; // eat the key
1107+
}
1108+
break;
1109+
11031110
case WM_NCDESTROY:
11041111
s_prevSciProc = nullptr;
11051112
break;
@@ -1121,12 +1128,17 @@ LRESULT CALLBACK ResultDock::sciSubclassProc(HWND hwnd, UINT msg, WPARAM wp, LPA
11211128
::AppendMenuW(hMenu, flags, id, txt.c_str());
11221129
};
11231130

1131+
const bool hasSel =
1132+
::SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0) !=
1133+
::SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0);
1134+
11241135
// -------- exact order & separators (matches screenshot) ----------------
11251136

11261137
add(IDM_RD_FOLD_ALL, L"rdmenu_fold_all");
11271138
add(IDM_RD_UNFOLD_ALL, L"rdmenu_unfold_all");
11281139
::AppendMenuW(hMenu, MF_SEPARATOR, 0, nullptr);
1129-
1140+
UINT copyFlags = MF_STRING | (hasSel ? 0 : MF_GRAYED);
1141+
add(IDM_RD_COPY_STD, L"rdmenu_copy_std", copyFlags);
11301142
add(IDM_RD_COPY_LINES, L"rdmenu_copy_lines");
11311143
add(IDM_RD_COPY_PATHS, L"rdmenu_copy_paths");
11321144
add(IDM_RD_SELECT_ALL, L"rdmenu_select_all");
@@ -1161,6 +1173,10 @@ LRESULT CALLBACK ResultDock::sciSubclassProc(HWND hwnd, UINT msg, WPARAM wp, LPA
11611173
::SendMessage(hwnd, SCI_FOLDALL, SC_FOLDACTION_EXPAND, 0);
11621174
break;
11631175

1176+
case IDM_RD_COPY_STD:
1177+
::SendMessage(hwnd, SCI_COPY, 0, 0);
1178+
break;
1179+
11641180
// ── select / clear ────────────────────────────
11651181
case IDM_RD_SELECT_ALL:
11661182
::SendMessage(hwnd, SCI_SELECTALL, 0, 0);
@@ -1286,7 +1302,6 @@ namespace {
12861302
} // anonymous namespace
12871303

12881304

1289-
12901305
// ==========================================================================
12911306
// copySelectedLines (IDM_RD_COPY_LINES)
12921307
// ==========================================================================
@@ -1459,7 +1474,6 @@ void ResultDock::copySelectedPaths(HWND hSci) {
14591474
}
14601475

14611476

1462-
14631477
// --------------------------------------------------------------------------
14641478
// openSelectedPaths – helper for IDM_RD_OPEN_PATHS
14651479
// --------------------------------------------------------------------------
@@ -1496,3 +1510,154 @@ void ResultDock::openSelectedPaths(HWND hSci) {
14961510
}
14971511
}
14981512
}
1513+
1514+
// --------------------------------------------------------------------------
1515+
// deleteSelectedItems – remove selected lines incl. subordinate hierarchy
1516+
// --------------------------------------------------------------------------
1517+
void ResultDock::deleteSelectedItems(HWND hSci)
1518+
{
1519+
auto& dock = ResultDock::instance();
1520+
1521+
// ------------------------------------------------------------------
1522+
// Determine anchor / caret lines
1523+
// ------------------------------------------------------------------
1524+
Sci_Position a = ::SendMessage(hSci, SCI_GETSELECTIONNANCHOR, 0, 0);
1525+
Sci_Position c = ::SendMessage(hSci, SCI_GETCURRENTPOS, 0, 0);
1526+
if (a > c) std::swap(a, c);
1527+
1528+
int firstLine = (int)::SendMessage(hSci, SCI_LINEFROMPOSITION, a, 0);
1529+
int lastLine = (int)::SendMessage(hSci, SCI_LINEFROMPOSITION, c, 0);
1530+
bool hasSel = (a != c);
1531+
1532+
// ------------------------------------------------------------------
1533+
// Build list of display‑line ranges that must be deleted
1534+
// ------------------------------------------------------------------
1535+
struct DelRange { int first; int last; };
1536+
std::vector<DelRange> ranges;
1537+
1538+
auto subtreeEnd = [&](int fromLine, int minIndent) -> int
1539+
{
1540+
int total = (int)::SendMessage(hSci, SCI_GETLINECOUNT, 0, 0);
1541+
for (int l = fromLine; l < total; ++l)
1542+
{
1543+
int len = (int)::SendMessage(hSci, SCI_LINELENGTH, l, 0);
1544+
std::string raw(len, '\0');
1545+
::SendMessage(hSci, SCI_GETLINE, l, (LPARAM)raw.data());
1546+
raw.resize(strnlen(raw.c_str(), len));
1547+
1548+
int indent = ResultDock::leadingSpaces(raw.c_str(), (int)raw.size());
1549+
if (indent <= minIndent && classify(raw) != LineKind::HitLine)
1550+
return l - 1; // previous line ends subtree
1551+
}
1552+
return (int)::SendMessage(hSci, SCI_GETLINECOUNT, 0, 0) - 1; // EOF
1553+
};
1554+
1555+
auto pushRange = [&](int first, int last)
1556+
{
1557+
if (ranges.empty() || first > ranges.back().last + 1)
1558+
ranges.push_back({ first, last });
1559+
else
1560+
ranges.back().last = (std::max)(ranges.back().last, last);
1561+
};
1562+
1563+
// ------------------------------------------------------------------
1564+
// Selection mode: collect every header / hit and expand hierarchy
1565+
// ------------------------------------------------------------------
1566+
if (hasSel)
1567+
{
1568+
for (int l = firstLine; l <= lastLine; ++l)
1569+
{
1570+
// skip lines already included by previous pushRange
1571+
if (!ranges.empty() && l <= ranges.back().last) continue;
1572+
1573+
int len = (int)::SendMessage(hSci, SCI_LINELENGTH, l, 0);
1574+
std::string raw(len, '\0');
1575+
::SendMessage(hSci, SCI_GETLINE, l, (LPARAM)raw.data());
1576+
raw.resize(strnlen(raw.c_str(), len));
1577+
1578+
LineKind kind = classify(raw);
1579+
int endLine = l; // default: only this line
1580+
1581+
switch (kind)
1582+
{
1583+
case LineKind::HitLine: endLine = l; break;
1584+
case LineKind::CritHdr: endLine = subtreeEnd(l + 1, 8); break;
1585+
case LineKind::FileHdr: endLine = subtreeEnd(l + 1, 4); break;
1586+
case LineKind::SearchHdr: endLine = subtreeEnd(l + 1, 0); break;
1587+
default: continue; // ignore blanks
1588+
}
1589+
pushRange(l, endLine);
1590+
}
1591+
}
1592+
else
1593+
{
1594+
// ------------------------------------------------------------------
1595+
// Caret‑only mode: single logical block
1596+
// ------------------------------------------------------------------
1597+
int len = (int)::SendMessage(hSci, SCI_LINELENGTH, firstLine, 0);
1598+
std::string raw(len, '\0');
1599+
::SendMessage(hSci, SCI_GETLINE, firstLine, (LPARAM)raw.data());
1600+
raw.resize(strnlen(raw.c_str(), len));
1601+
1602+
LineKind kind = classify(raw);
1603+
int endLine = firstLine;
1604+
1605+
switch (kind)
1606+
{
1607+
case LineKind::HitLine: endLine = firstLine; break;
1608+
case LineKind::CritHdr: endLine = subtreeEnd(firstLine + 1, 8); break;
1609+
case LineKind::FileHdr: endLine = subtreeEnd(firstLine + 1, 4); break;
1610+
case LineKind::SearchHdr: endLine = subtreeEnd(firstLine + 1, 0); break;
1611+
default: return; // nothing deletable on this line
1612+
}
1613+
ranges.push_back({ firstLine, endLine });
1614+
}
1615+
1616+
if (ranges.empty())
1617+
return;
1618+
1619+
// ------------------------------------------------------------------
1620+
// Delete ranges bottom‑up and update _hits offsets
1621+
// ------------------------------------------------------------------
1622+
::SendMessage(hSci, SCI_SETREADONLY, FALSE, 0);
1623+
1624+
for (auto it = ranges.rbegin(); it != ranges.rend(); ++it)
1625+
{
1626+
int fLine = it->first;
1627+
int lLine = it->last;
1628+
1629+
Sci_Position start = ::SendMessage(hSci, SCI_POSITIONFROMLINE, fLine, 0);
1630+
Sci_Position end = (lLine + 1 < ::SendMessage(hSci, SCI_GETLINECOUNT, 0, 0))
1631+
? ::SendMessage(hSci, SCI_POSITIONFROMLINE, lLine + 1, 0)
1632+
: ::SendMessage(hSci, SCI_GETLENGTH, 0, 0);
1633+
1634+
Sci_Position delta = end - start;
1635+
if (delta <= 0) continue;
1636+
1637+
// ---- remove from Scintilla buffer
1638+
::SendMessage(hSci, SCI_DELETERANGE, start, delta);
1639+
1640+
// ---- sync internal hit list
1641+
for (auto h = dock._hits.begin(); h != dock._hits.end(); )
1642+
{
1643+
if (h->displayLineStart >= start && h->displayLineStart < end)
1644+
{
1645+
h = dock._hits.erase(h); // entry deleted
1646+
}
1647+
else
1648+
{
1649+
if (h->displayLineStart >= end)
1650+
h->displayLineStart -= (int)delta; // shift left
1651+
++h;
1652+
}
1653+
}
1654+
}
1655+
1656+
::SendMessage(hSci, SCI_SETREADONLY, TRUE, 0);
1657+
1658+
// ------------------------------------------------------------------
1659+
// Re‑fold and re‑style remaining lines
1660+
// ------------------------------------------------------------------
1661+
dock.rebuildFolding();
1662+
dock.applyStyling();
1663+
}

src/ResultDock.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,14 @@ class ResultDock final
150150
enum : UINT {
151151
IDM_RD_FOLD_ALL = 60001,
152152
IDM_RD_UNFOLD_ALL = 60002,
153-
IDM_RD_SELECT_ALL = 60003,
154-
IDM_RD_CLEAR_ALL = 60004,
155-
IDM_RD_COPY_LINES = 60005,
156-
IDM_RD_COPY_PATHS = 60006,
157-
IDM_RD_OPEN_PATHS = 60007,
158-
IDM_RD_TOGGLE_WRAP = 60008,
159-
IDM_RD_TOGGLE_PURGE = 60009
153+
IDM_RD_COPY_STD = 60003,
154+
IDM_RD_SELECT_ALL = 60004,
155+
IDM_RD_CLEAR_ALL = 60005,
156+
IDM_RD_COPY_LINES = 60006,
157+
IDM_RD_COPY_PATHS = 60007,
158+
IDM_RD_OPEN_PATHS = 60008,
159+
IDM_RD_TOGGLE_WRAP = 60009,
160+
IDM_RD_TOGGLE_PURGE = 60010
160161
};
161162

162163
// ------------------- Construction & State -----------------
@@ -173,6 +174,7 @@ class ResultDock final
173174
static void copySelectedPaths(HWND hSci);
174175
static void openSelectedPaths(HWND hSci);
175176
static void copyTextToClipboard(HWND owner, const std::wstring& w);
177+
static void deleteSelectedItems(HWND hSci);
176178

177179
// ‑‑‑ persistent UI flags ‑‑‑
178180
static bool _wrapEnabled;

0 commit comments

Comments
 (0)