Merge 'dev' branch into stable

This commit is contained in:
Anton Kochkov 2024-02-24 08:15:30 +08:00
commit e612dcdf33
32 changed files with 212 additions and 177 deletions

View File

@ -1,4 +1,4 @@
version: '2.3.2-git-{build}' version: '2.2.0-git-{build}'
image: 'Visual Studio 2017' image: 'Visual Studio 2017'
clone_depth: 1 clone_depth: 1

View File

@ -36,8 +36,8 @@ if(NOT CUTTER_ENABLE_PYTHON)
endif() endif()
set(CUTTER_VERSION_MAJOR 2) set(CUTTER_VERSION_MAJOR 2)
set(CUTTER_VERSION_MINOR 3) set(CUTTER_VERSION_MINOR 2)
set(CUTTER_VERSION_PATCH 2) set(CUTTER_VERSION_PATCH 0)
set(CUTTER_VERSION "${CUTTER_VERSION_MAJOR}.${CUTTER_VERSION_MINOR}.${CUTTER_VERSION_PATCH}") set(CUTTER_VERSION "${CUTTER_VERSION_MAJOR}.${CUTTER_VERSION_MINOR}.${CUTTER_VERSION_PATCH}")

View File

@ -57,7 +57,7 @@ endif()
# TODO: This version number should be fetched automatically # TODO: This version number should be fetched automatically
# instead of being hardcoded. # instead of being hardcoded.
set (Rizin_VERSION 0.6) set (Rizin_VERSION 0.7)
set (RZ_LIBS rz_core rz_config rz_cons rz_io rz_util rz_flag rz_asm rz_debug set (RZ_LIBS rz_core rz_config rz_cons rz_io rz_util rz_flag rz_asm rz_debug
rz_hash rz_bin rz_lang rz_il rz_analysis rz_parse rz_bp rz_egg rz_reg rz_hash rz_bin rz_lang rz_il rz_analysis rz_parse rz_bp rz_egg rz_reg

View File

@ -1,5 +1,6 @@
set(TS_FILES set(TS_FILES
translations/ar/cutter_ar.ts translations/ar/cutter_ar.ts
translations/bn/cutter_bn.ts
translations/ca/cutter_ca.ts translations/ca/cutter_ca.ts
translations/de/cutter_de.ts translations/de/cutter_de.ts
translations/es-ES/cutter_es.ts translations/es-ES/cutter_es.ts
@ -8,6 +9,7 @@ set(TS_FILES
translations/he/cutter_he.ts translations/he/cutter_he.ts
translations/hi/cutter_hi.ts translations/hi/cutter_hi.ts
translations/it/cutter_it.ts translations/it/cutter_it.ts
translations/ko/cutter_ko.ts
translations/ja/cutter_ja.ts translations/ja/cutter_ja.ts
translations/nl/cutter_nl.ts translations/nl/cutter_nl.ts
translations/pt-PT/cutter_pt.ts translations/pt-PT/cutter_pt.ts
@ -15,9 +17,10 @@ set(TS_FILES
translations/ru/cutter_ru.ts translations/ru/cutter_ru.ts
translations/tr/cutter_tr.ts translations/tr/cutter_tr.ts
translations/uk/cutter_uk.ts translations/uk/cutter_uk.ts
translations/ur-PK/cutter_ur.ts
translations/zh-CN/cutter_zh.ts translations/zh-CN/cutter_zh.ts
translations/vi/cutter_vi.ts
) )
# translations/ko/cutter_ko.ts problems with fonts
# translations/pt-BR/cutter_pt.ts #2321 handling multiple versions of a language # translations/pt-BR/cutter_pt.ts #2321 handling multiple versions of a language
set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/translations) set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/translations)

4
dist/CMakeLists.txt vendored
View File

@ -188,9 +188,9 @@ if(CUTTER_PACKAGE_RZ_GHIDRA)
# installed Cutter. # installed Cutter.
ExternalProject_Add(rz-ghidra ExternalProject_Add(rz-ghidra
GIT_REPOSITORY https://github.com/rizinorg/rz-ghidra GIT_REPOSITORY https://github.com/rizinorg/rz-ghidra
GIT_TAG v0.6.0 #GIT_TAG v0.3.0
#GIT_TAG c7a50a2e7c0a95cd52b167c9ee0fa1805223f08e #GIT_TAG c7a50a2e7c0a95cd52b167c9ee0fa1805223f08e
#GIT_TAG dev GIT_TAG dev
#GIT_SHALLOW ON # disable this line when using commit hash #GIT_SHALLOW ON # disable this line when using commit hash
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""

View File

@ -2,10 +2,10 @@ $dist = $args[0]
$python = Split-Path((Get-Command python.exe).Path) $python = Split-Path((Get-Command python.exe).Path)
if (-not (Test-Path -Path 'jsdec' -PathType Container)) { if (-not (Test-Path -Path 'jsdec' -PathType Container)) {
git clone https://github.com/rizinorg/jsdec.git --depth 1 --branch "v0.6.0" git clone https://github.com/rizinorg/jsdec.git --depth 1 --branch "v0.7.0"
} }
cd jsdec cd jsdec
& meson.exe --buildtype=release -Dc_args=-DDUK_USE_DATE_NOW_WINDOWS -Djsc_folder=".." --prefix="$dist" p build & meson.exe --buildtype=release --prefix="$dist" build
ninja -C build install ninja -C build install
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
$pathdll = "$dist\lib\rizin\plugins\core_pdd.dll" $pathdll = "$dist\lib\rizin\plugins\core_pdd.dll"

View File

@ -85,8 +85,14 @@ On Arch-based Linux distributions:
:: ::
# When building with CUTTER_ENABLE_KSYNTAXHIGHLIGHTING (Default)
sudo pacman -Syu --needed syntax-highlighting
# When building with CUTTER_ENABLE_GRAPHVIZ (Default)
sudo pacman -Syu --needed graphviz
sudo pacman -Syu --needed base-devel cmake meson qt5-base qt5-svg qt5-tools sudo pacman -Syu --needed base-devel cmake meson qt5-base qt5-svg qt5-tools
On dnf/yum based distributions: On dnf/yum based distributions:
:: ::

View File

@ -24,9 +24,9 @@ copyright = '2020, The Cutter Developers'
author = 'The Cutter Developers' author = 'The Cutter Developers'
# The short X.Y version # The short X.Y version
version = '2.3' version = '2.2'
# The full version, including a2lpha/beta/rc tags # The full version, including a2lpha/beta/rc tags
release = '2.3.2' release = '2.2.0'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------

2
rizin

@ -1 +1 @@
Subproject commit 18b1243435df428b58bcefc4ec37aef558aab96e Subproject commit 78d4043afb39a56fe91ea7ab03c83da613319cc3

View File

@ -6,14 +6,15 @@ SCRIPTPATH=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
cd "$SCRIPTPATH/.." cd "$SCRIPTPATH/.."
if [[ ! -d jsdec ]]; then if [ ! -d jsdec ]; then
git clone https://github.com/rizinorg/jsdec.git --depth 1 --branch "v0.6.0" git clone https://github.com/rizinorg/jsdec.git --depth 1 --branch "v0.7.0"
fi fi
cd jsdec cd jsdec
rm -rf build if [ -d build ]; then
mkdir build && cd build rm -rf build
meson --buildtype=release -Djsc_folder="../" "$@" ../p fi
ninja meson --buildtype=release "$@" build
ninja install ninja -C build
ninja -C build install

View File

@ -429,33 +429,7 @@ if(CUTTER_ENABLE_PYTHON_BINDINGS)
include_directories("${BINDINGS_BUILD_DIR}/CutterBindings") include_directories("${BINDINGS_BUILD_DIR}/CutterBindings")
set(SHIBOKEN_INCLUDE_DIRS "")
if(APPLE AND _qt6Core_install_prefix)
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt6Core_install_prefix}/include")
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt6Core_install_prefix}/include/QtCore")
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt6Core_install_prefix}/include/QtGui")
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt6Core_install_prefix}/include/QtWidgets")
endif()
if (CUTTER_QT6)
list(APPEND SHIBOKEN_INCLUDE_DIRS ${Qt6Core_INCLUDE_DIRS} ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Gui_INCLUDE_DIRS})
else()
list(APPEND SHIBOKEN_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS})
endif()
foreach(_dir ${CUTTER_INCLUDE_DIRECTORIES})
list(APPEND SHIBOKEN_INCLUDE_DIRS
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${_dir}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cutter/${_dir}>
)
endforeach()
list(APPEND SHIBOKEN_INCLUDE_DIRS ${Rizin_INCLUDE_DIRS})
if (NOT WIN32)
string(REPLACE ";" ":" SHIBOKEN_INCLUDE_DIRS "${SHIBOKEN_INCLUDE_DIRS}")
endif()
set(SHIBOKEN_OPTIONS) set(SHIBOKEN_OPTIONS)
list(APPEND SHIBOKEN_OPTIONS --include-paths="${SHIBOKEN_INCLUDE_DIRS}")
if (WIN32) if (WIN32)
list(APPEND SHIBOKEN_OPTIONS --avoid-protected-hack) list(APPEND SHIBOKEN_OPTIONS --avoid-protected-hack)
endif() endif()
@ -558,11 +532,16 @@ if(CUTTER_ENABLE_PYTHON)
endif() endif()
endforeach() endforeach()
if(APPLE AND _qt5Core_install_prefix) set(BINDINGS_INCLUDE_DIR_LINES "")
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include") if(APPLE)
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtCore") if (_qt5Core_install_prefix)
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtGui") list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include")
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtWidgets") list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtCore")
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtGui")
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtWidgets")
elseif(CUTTER_QT6)
string(APPEND BINDINGS_INCLUDE_DIR_LINES "framework-include-path=${QT6_INSTALL_PREFIX}/${QT6_INSTALL_LIBS}\n")
endif()
endif() endif()
if (CUTTER_QT6) if (CUTTER_QT6)
list(APPEND BINDINGS_INCLUDE_DIRS ${Qt6Core_INCLUDE_DIRS} ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Gui_INCLUDE_DIRS}) list(APPEND BINDINGS_INCLUDE_DIRS ${Qt6Core_INCLUDE_DIRS} ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Gui_INCLUDE_DIRS})
@ -571,9 +550,12 @@ if(CUTTER_ENABLE_PYTHON)
endif() endif()
list(APPEND BINDINGS_INCLUDE_DIRS ${Rizin_INCLUDE_DIRS}) list(APPEND BINDINGS_INCLUDE_DIRS ${Rizin_INCLUDE_DIRS})
list(APPEND BINDINGS_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") list(APPEND BINDINGS_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
if (NOT WIN32)
string(REPLACE ";" ":" BINDINGS_INCLUDE_DIRS "${BINDINGS_INCLUDE_DIRS}") foreach(_dir ${BINDINGS_INCLUDE_DIRS})
endif() if (NOT "${_dir}" STREQUAL "")
string(APPEND BINDINGS_INCLUDE_DIR_LINES "include-path = ${_dir}\n")
endif()
endforeach()
configure_file("${BINDINGS_SRC_DIR}/bindings.txt.in" "${BINDINGS_BUILD_DIR}/bindings.txt") configure_file("${BINDINGS_SRC_DIR}/bindings.txt.in" "${BINDINGS_BUILD_DIR}/bindings.txt")
add_definitions(-DWIN32_LEAN_AND_MEAN) add_definitions(-DWIN32_LEAN_AND_MEAN)

View File

@ -7,7 +7,7 @@ typesystem-file = ${BINDINGS_BUILD_DIR}/bindings.xml
output-directory = ${BINDINGS_BUILD_DIR} output-directory = ${BINDINGS_BUILD_DIR}
include-path = ${BINDINGS_INCLUDE_DIRS} ${BINDINGS_INCLUDE_DIR_LINES}
typesystem-paths = ${PYSIDE_TYPESYSTEMS} typesystem-paths = ${PYSIDE_TYPESYSTEMS}

View File

@ -14,6 +14,7 @@
<enum-type name="ContextMenuType" /> <enum-type name="ContextMenuType" />
</object-type> </object-type>
<object-type name="BasicBlockHighlighter" /> <object-type name="BasicBlockHighlighter" />
<object-type name="BasicInstructionHighlighter" />
<object-type name="AddressableItemContextMenu" /> <object-type name="AddressableItemContextMenu" />
<object-type name="CutterDockWidget" /> <object-type name="CutterDockWidget" />

View File

@ -2,8 +2,7 @@
#include "CommandTask.h" #include "CommandTask.h"
#include "TempConfig.h" #include "TempConfig.h"
CommandTask::CommandTask(const QString &cmd, ColorMode colorMode, bool outFormatHtml) CommandTask::CommandTask(const QString &cmd, ColorMode colorMode) : cmd(cmd), colorMode(colorMode)
: cmd(cmd), colorMode(colorMode), outFormatHtml(outFormatHtml)
{ {
} }
@ -12,8 +11,5 @@ void CommandTask::runTask()
TempConfig tempConfig; TempConfig tempConfig;
tempConfig.set("scr.color", colorMode); tempConfig.set("scr.color", colorMode);
auto res = Core()->cmdTask(cmd); auto res = Core()->cmdTask(cmd);
if (outFormatHtml) {
res = CutterCore::ansiEscapeToHtml(res);
}
emit finished(res); emit finished(res);
} }

View File

@ -17,8 +17,7 @@ public:
MODE_16M = COLOR_MODE_16M MODE_16M = COLOR_MODE_16M
}; };
CommandTask(const QString &cmd, ColorMode colorMode = ColorMode::DISABLED, CommandTask(const QString &cmd, ColorMode colorMode = ColorMode::DISABLED);
bool outFormatHtml = false);
QString getTitle() override { return tr("Running Command"); } QString getTitle() override { return tr("Running Command"); }
@ -31,7 +30,6 @@ protected:
private: private:
QString cmd; QString cmd;
ColorMode colorMode; ColorMode colorMode;
bool outFormatHtml;
}; };
#endif // COMMANDTASK_H #endif // COMMANDTASK_H

View File

@ -16,7 +16,7 @@ static char *jsonToStrdup(const CutterJson &str)
if (!j || j->type != RZ_JSON_STRING) { if (!j || j->type != RZ_JSON_STRING) {
return NULL; return NULL;
} }
return rz_str_new(j->str_value); return rz_str_dup(j->str_value);
} }
static RzAnnotatedCode *parseJsonCode(CutterJson &json) static RzAnnotatedCode *parseJsonCode(CutterJson &json)

View File

@ -7,6 +7,7 @@
#include <QColor> #include <QColor>
#include <QTextCursor> #include <QTextCursor>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QRegularExpression>
QList<QTextEdit::ExtraSelection> createSameWordsSelections(QPlainTextEdit *textEdit, QList<QTextEdit::ExtraSelection> createSameWordsSelections(QPlainTextEdit *textEdit,
const QString &word) const QString &word)
@ -21,6 +22,42 @@ QList<QTextEdit::ExtraSelection> createSameWordsSelections(QPlainTextEdit *textE
} }
highlightSelection.cursor = textEdit->textCursor(); highlightSelection.cursor = textEdit->textCursor();
if (word == "{" || word == "}") {
int val;
if (word == "{") {
val = 0;
} else {
val = 1;
}
selections.append(highlightSelection);
while (!highlightSelection.cursor.isNull() && !highlightSelection.cursor.atEnd()) {
if (word == "{") {
highlightSelection.cursor =
document->find(QRegularExpression("{|}"), highlightSelection.cursor);
} else {
highlightSelection.cursor =
document->find(QRegularExpression("{|}"), highlightSelection.cursor,
QTextDocument::FindBackward);
}
if (!highlightSelection.cursor.isNull()) {
if (highlightSelection.cursor.selectedText() == word) {
val++;
} else {
val--;
}
if (val == 0) {
highlightSelection.format.setBackground(highlightWordColor);
selections.append(highlightSelection);
break;
}
}
}
return selections;
}
highlightSelection.cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor); highlightSelection.cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
while (!highlightSelection.cursor.isNull() && !highlightSelection.cursor.atEnd()) { while (!highlightSelection.cursor.isNull() && !highlightSelection.cursor.atEnd()) {

View File

@ -722,11 +722,10 @@ PRzAnalysisBytes CutterCore::getRzAnalysisBytesSingle(RVA addr)
rz_io_read_at(core->io, addr, buf, sizeof(buf)); rz_io_read_at(core->io, addr, buf, sizeof(buf));
auto seek = seekTemp(addr); auto seek = seekTemp(addr);
auto vec = fromOwned(rz_core_analysis_bytes(core, buf, sizeof(buf), 1)); auto abiter = fromOwned(rz_core_analysis_bytes(core, addr, buf, sizeof(buf), 1));
auto ab =
abiter ? reinterpret_cast<RzAnalysisBytes *>(rz_iterator_next(abiter.get())) : nullptr;
auto ab = vec && rz_pvector_len(vec.get()) > 0
? reinterpret_cast<RzAnalysisBytes *>(rz_pvector_pop_front(vec.get()))
: nullptr;
return { ab, rz_analysis_bytes_free }; return { ab, rz_analysis_bytes_free };
} }
@ -1027,18 +1026,10 @@ RVA CutterCore::nextOpAddr(RVA startAddr, int count)
{ {
CORE_LOCK(); CORE_LOCK();
auto seek = seekTemp(startAddr); auto seek = seekTemp(startAddr);
auto vec = auto consumed =
fromOwned(rz_core_analysis_bytes(core, core->block, (int)core->blocksize, count + 1)); rz_core_analysis_ops_size(core, core->offset, core->block, (int)core->blocksize, count);
RVA addr = startAddr + 1; RVA addr = startAddr + consumed;
if (!vec) {
return addr;
}
auto ab = reinterpret_cast<RzAnalysisBytes *>(rz_pvector_tail(vec.get()));
if (!(ab && ab->op)) {
return addr;
}
addr = ab->op->addr;
return addr; return addr;
} }
@ -1666,7 +1657,7 @@ QVector<Chunk> CutterCore::getHeapChunks(RVA arena_addr)
rz_list_free(arenas); rz_list_free(arenas);
return chunks_vector; return chunks_vector;
} }
m_arena = ((RzArenaListItem *)arenas->head->data)->addr; m_arena = ((RzArenaListItem *)rz_list_get_head_data(arenas))->addr;
rz_list_free(arenas); rz_list_free(arenas);
} else { } else {
m_arena = arena_addr; m_arena = arena_addr;
@ -2372,7 +2363,9 @@ void CutterCore::continueUntilSyscall()
} else { } else {
if (!asyncTask( if (!asyncTask(
[](RzCore *core) { [](RzCore *core) {
rz_cons_break_push(reinterpret_cast<RzConsBreak>(rz_debug_stop), core->dbg); rz_cons_break_push(
[](void *x) { rz_debug_stop(reinterpret_cast<RzDebug *>(x)); },
core->dbg);
rz_reg_arena_swap(core->dbg->reg, true); rz_reg_arena_swap(core->dbg->reg, true);
rz_debug_continue_syscalls(core->dbg, NULL, 0); rz_debug_continue_syscalls(core->dbg, NULL, 0);
rz_cons_break_pop(); rz_cons_break_pop();
@ -2681,8 +2674,8 @@ void CutterCore::addBreakpoint(const BreakpointDescription &config)
moduleNameData = config.positionExpression.toUtf8(); moduleNameData = config.positionExpression.toUtf8();
module = moduleNameData.data(); module = moduleNameData.data();
} }
breakpoint = rz_debug_bp_add(core->dbg, address, (config.hw && watchpoint_prot == 0), breakpoint = rz_debug_bp_add(core->dbg, address, config.size, config.hw, (watchpoint_prot != 0),
watchpoint_prot, watchpoint_prot, module, config.moduleDelta); watchpoint_prot, module, config.moduleDelta);
if (!breakpoint) { if (!breakpoint) {
QMessageBox::critical(nullptr, tr("Breakpoint error"), tr("Failed to create breakpoint")); QMessageBox::critical(nullptr, tr("Breakpoint error"), tr("Failed to create breakpoint"));
return; return;
@ -2791,7 +2784,7 @@ int CutterCore::breakpointIndexAt(RVA addr)
BreakpointDescription CutterCore::getBreakpointAt(RVA addr) BreakpointDescription CutterCore::getBreakpointAt(RVA addr)
{ {
CORE_LOCK(); CORE_LOCK();
int index = breakpointIndexAt(addr); int index = rz_bp_get_index_at(core->dbg->bp, addr);
auto bp = rz_bp_get_index(core->dbg->bp, index); auto bp = rz_bp_get_index(core->dbg->bp, index);
if (bp) { if (bp) {
return breakpointDescriptionFromRizin(index, bp); return breakpointDescriptionFromRizin(index, bp);
@ -3107,16 +3100,14 @@ QList<ImportDescription> CutterCore::getAllImports()
if (!bf) { if (!bf) {
return {}; return {};
} }
const RzList *imports = rz_bin_object_get_imports(bf->o); const RzPVector *imports = rz_bin_object_get_imports(bf->o);
if (!imports) { if (!imports) {
return {}; return {};
} }
QList<ImportDescription> qList; QList<ImportDescription> qList;
RzBinImport *import;
RzListIter *iter;
bool va = core->io->va || core->bin->is_debugger; bool va = core->io->va || core->bin->is_debugger;
CutterRzListForeach (imports, iter, RzBinImport, import) { for (const auto &import : CutterPVector<RzBinImport>(imports)) {
if (RZ_STR_ISEMPTY(import->name)) { if (RZ_STR_ISEMPTY(import->name)) {
continue; continue;
} }
@ -3153,7 +3144,8 @@ QList<ExportDescription> CutterCore::getAllExports()
if (!bf) { if (!bf) {
return {}; return {};
} }
const RzList *symbols = rz_bin_object_get_symbols(bf->o);
const RzPVector *symbols = rz_bin_object_get_symbols(bf->o);
if (!symbols) { if (!symbols) {
return {}; return {};
} }
@ -3162,7 +3154,7 @@ QList<ExportDescription> CutterCore::getAllExports()
bool demangle = rz_config_get_b(core->config, "bin.demangle"); bool demangle = rz_config_get_b(core->config, "bin.demangle");
QList<ExportDescription> ret; QList<ExportDescription> ret;
for (const auto &symbol : CutterRzList<RzBinSymbol>(symbols)) { for (const auto &symbol : CutterPVector<RzBinSymbol>(symbols)) {
if (!(symbol->name && rz_core_sym_is_export(symbol))) { if (!(symbol->name && rz_core_sym_is_export(symbol))) {
continue; continue;
} }
@ -3187,13 +3179,15 @@ QList<ExportDescription> CutterCore::getAllExports()
QList<SymbolDescription> CutterCore::getAllSymbols() QList<SymbolDescription> CutterCore::getAllSymbols()
{ {
CORE_LOCK(); CORE_LOCK();
RzListIter *it; RzBinFile *bf = rz_bin_cur(core->bin);
if (!bf) {
return {};
}
QList<SymbolDescription> ret; QList<SymbolDescription> ret;
const RzPVector *symbols = rz_bin_object_get_symbols(bf->o);
RzBinSymbol *bs; if (symbols) {
if (core && core->bin && core->bin->cur && core->bin->cur->o) { for (const auto &bs : CutterPVector<RzBinSymbol>(symbols)) {
CutterRzListForeach (core->bin->cur->o->symbols, it, RzBinSymbol, bs) {
QString type = QString(bs->bind) + " " + QString(bs->type); QString type = QString(bs->bind) + " " + QString(bs->type);
SymbolDescription symbol; SymbolDescription symbol;
symbol.vaddr = bs->vaddr; symbol.vaddr = bs->vaddr;
@ -3202,11 +3196,13 @@ QList<SymbolDescription> CutterCore::getAllSymbols()
symbol.type = QString(bs->type); symbol.type = QString(bs->type);
ret << symbol; ret << symbol;
} }
}
const RzList *entries = rz_bin_object_get_entries(bf->o);
if (entries) {
/* list entrypoints as symbols too */ /* list entrypoints as symbols too */
int n = 0; int n = 0;
RzBinAddr *entry; for (const auto &entry : CutterRzList<RzBinSymbol>(entries)) {
CutterRzListForeach (core->bin->cur->o->entries, it, RzBinAddr, entry) {
SymbolDescription symbol; SymbolDescription symbol;
symbol.vaddr = entry->vaddr; symbol.vaddr = entry->vaddr;
symbol.name = QString("entry") + QString::number(n++); symbol.name = QString("entry") + QString::number(n++);
@ -3226,15 +3222,12 @@ QList<HeaderDescription> CutterCore::getAllHeaders()
if (!bf) { if (!bf) {
return {}; return {};
} }
const RzList *fields = rz_bin_object_get_fields(bf->o); const RzPVector *fields = rz_bin_object_get_fields(bf->o);
if (!fields) { if (!fields) {
return {}; return {};
} }
RzListIter *iter;
RzBinField *field;
QList<HeaderDescription> ret; QList<HeaderDescription> ret;
for (auto field : CutterPVector<RzBinField>(fields)) {
CutterRzListForeach (fields, iter, RzBinField, field) {
HeaderDescription header; HeaderDescription header;
header.vaddr = field->vaddr; header.vaddr = field->vaddr;
header.paddr = field->paddr; header.paddr = field->paddr;
@ -3242,7 +3235,6 @@ QList<HeaderDescription> CutterCore::getAllHeaders()
header.name = field->name; header.name = field->name;
ret << header; ret << header;
} }
return ret; return ret;
} }
@ -3345,8 +3337,9 @@ QList<StringDescription> CutterCore::getAllStrings()
if (!obj) { if (!obj) {
return {}; return {};
} }
RzList *l = rz_core_bin_whole_strings(core, bf);
if (!l) { RzPVector *strings = rz_core_bin_whole_strings(core, bf);
if (!strings) {
return {}; return {};
} }
@ -3357,7 +3350,7 @@ QList<StringDescription> CutterCore::getAllStrings()
opt.esc_double_quotes = true; opt.esc_double_quotes = true;
QList<StringDescription> ret; QList<StringDescription> ret;
for (const auto &str : CutterRzList<RzBinString>(l)) { for (const auto &str : CutterPVector<RzBinString>(strings)) {
auto section = obj ? rz_bin_get_section_at(obj, str->paddr, 0) : NULL; auto section = obj ? rz_bin_get_section_at(obj, str->paddr, 0) : NULL;
StringDescription string; StringDescription string;
@ -3420,7 +3413,7 @@ QList<SectionDescription> CutterCore::getAllSections()
return sections; return sections;
} }
RzList *sects = rz_bin_object_get_sections(o); RzPVector *sects = rz_bin_object_get_sections(o);
if (!sects) { if (!sects) {
return sections; return sections;
} }
@ -3428,10 +3421,8 @@ QList<SectionDescription> CutterCore::getAllSections()
if (!hashnames) { if (!hashnames) {
return sections; return sections;
} }
rz_list_push(hashnames, rz_str_new("entropy")); rz_list_push(hashnames, rz_str_dup("entropy"));
RzListIter *it; for (const auto &sect : CutterPVector<RzBinSection>(sects)) {
RzBinSection *sect;
CutterRzListForeach (sects, it, RzBinSection, sect) {
if (RZ_STR_ISEMPTY(sect->name)) if (RZ_STR_ISEMPTY(sect->name))
continue; continue;
@ -3454,7 +3445,7 @@ QList<SectionDescription> CutterCore::getAllSections()
sections << section; sections << section;
} }
rz_list_free(sects); rz_pvector_free(sects);
return sections; return sections;
} }
@ -3468,15 +3459,14 @@ QStringList CutterCore::getSectionList()
return ret; return ret;
} }
RzList *sects = rz_bin_object_get_sections(o); RzPVector *sects = rz_bin_object_get_sections(o);
if (!sects) { if (!sects) {
return ret; return ret;
} }
RzListIter *it; for (const auto &sect : CutterPVector<RzBinSection>(sects)) {
RzBinSection *sect;
CutterRzListForeach (sects, it, RzBinSection, sect) {
ret << sect->name; ret << sect->name;
} }
rz_pvector_free(sects);
return ret; return ret;
} }
@ -3492,15 +3482,13 @@ QList<SegmentDescription> CutterCore::getAllSegments()
if (!bf) { if (!bf) {
return {}; return {};
} }
RzList *segments = rz_bin_object_get_segments(bf->o); RzPVector *segments = rz_bin_object_get_segments(bf->o);
if (!segments) { if (!segments) {
return {}; return {};
} }
RzBinSection *segment;
RzListIter *iter;
QList<SegmentDescription> ret; QList<SegmentDescription> ret;
CutterRzListForeach (segments, iter, RzBinSection, segment) { for (const auto &segment : CutterPVector<RzBinSection>(segments)) {
SegmentDescription segDesc; SegmentDescription segDesc;
segDesc.name = segment->name; segDesc.name = segment->name;
segDesc.vaddr = segment->vaddr; segDesc.vaddr = segment->vaddr;
@ -3510,7 +3498,7 @@ QList<SegmentDescription> CutterCore::getAllSegments()
segDesc.perm = perms_str(segment->perm); segDesc.perm = perms_str(segment->perm);
ret << segDesc; ret << segDesc;
} }
rz_list_free(segments); rz_pvector_free(segments);
return ret; return ret;
} }
@ -3557,17 +3545,16 @@ QList<BinClassDescription> CutterCore::getAllClassesFromBin()
return {}; return {};
} }
const RzList *cs = rz_bin_object_get_classes(bf->o); const RzPVector *cs = rz_bin_object_get_classes(bf->o);
if (!cs) { if (!cs) {
return {}; return {};
} }
QList<BinClassDescription> qList; QList<BinClassDescription> qList;
RzListIter *iter, *iter2, *iter3; RzListIter *iter2, *iter3;
RzBinClass *c;
RzBinSymbol *sym; RzBinSymbol *sym;
RzBinClassField *f; RzBinClassField *f;
CutterRzListForeach (cs, iter, RzBinClass, c) { for (const auto &c : CutterPVector<RzBinClass>(cs)) {
BinClassDescription classDescription; BinClassDescription classDescription;
classDescription.name = c->name; classDescription.name = c->name;
classDescription.addr = c->addr; classDescription.addr = c->addr;
@ -3782,8 +3769,8 @@ void CutterCore::setAnalysisMethod(const QString &className, const AnalysisMetho
{ {
CORE_LOCK(); CORE_LOCK();
RzAnalysisMethod analysisMeth; RzAnalysisMethod analysisMeth;
analysisMeth.name = rz_str_new(meth.name.toUtf8().constData()); analysisMeth.name = rz_str_dup(meth.name.toUtf8().constData());
analysisMeth.real_name = rz_str_new(meth.realName.toUtf8().constData()); analysisMeth.real_name = rz_str_dup(meth.realName.toUtf8().constData());
analysisMeth.addr = meth.addr; analysisMeth.addr = meth.addr;
analysisMeth.vtable_offset = meth.vtableOffset; analysisMeth.vtable_offset = meth.vtableOffset;
rz_analysis_class_method_set(core->analysis, className.toUtf8().constData(), &analysisMeth); rz_analysis_class_method_set(core->analysis, className.toUtf8().constData(), &analysisMeth);
@ -3806,19 +3793,22 @@ QList<ResourcesDescription> CutterCore::getAllResources()
if (!bf) { if (!bf) {
return {}; return {};
} }
const RzList *resources = rz_bin_object_get_resources(bf->o); const RzPVector *resources = rz_bin_object_get_resources(bf->o);
if (!resources) {
return {};
}
QList<ResourcesDescription> resourcesDescriptions; QList<ResourcesDescription> resourcesDescriptions;
RzBinResource *r; for (const auto &resource : CutterPVector<RzBinResource>(resources)) {
RzListIter *it;
CutterRzListForeach (resources, it, RzBinResource, r) {
ResourcesDescription description; ResourcesDescription description;
description.name = r->name; description.name = resource->name;
description.vaddr = r->vaddr; description.vaddr = resource->vaddr;
description.index = r->index; description.index = resource->index;
description.type = r->type; description.type = resource->type;
description.size = r->size; description.size = resource->size;
description.lang = r->language; description.lang = resource->language;
resourcesDescriptions << description; resourcesDescriptions << description;
} }
@ -4449,11 +4439,13 @@ bool CutterCore::setColor(const QString &key, const QString &color)
QString CutterCore::ansiEscapeToHtml(const QString &text) QString CutterCore::ansiEscapeToHtml(const QString &text)
{ {
int len; int len;
char *html = rz_cons_html_filter(text.toUtf8().constData(), &len); QString r = text;
r.replace("\t", " ");
char *html = rz_cons_html_filter(r.toUtf8().constData(), &len);
if (!html) { if (!html) {
return {}; return {};
} }
QString r = QString::fromUtf8(html, len); r = QString::fromUtf8(html, len);
rz_mem_free(html); rz_mem_free(html);
return r; return r;
} }

View File

@ -51,11 +51,17 @@ static inline auto fromOwned(RZ_OWN RzList *data) -> UniquePtrCP<decltype(data),
return { data, {} }; return { data, {} };
} }
static inline auto fromOwned(RZ_OWN RzIterator *data)
-> UniquePtrCP<decltype(data), &rz_iterator_free>
{
return { data, {} };
}
// Rizin list iteration macros // Rizin list iteration macros
// deprecated, prefer using CutterPVector and CutterRzList instead // deprecated, prefer using CutterPVector and CutterRzList instead
#define CutterRzListForeach(list, it, type, x) \ #define CutterRzListForeach(list, it, type, x) \
if (list) \ if (list) \
for (it = list->head; it && ((x = static_cast<type *>(it->data))); it = it->n) for (it = list->head; it && ((x = static_cast<type *>(it->elem))); it = it->next)
#define CutterRzVectorForeach(vec, it, type) \ #define CutterRzVectorForeach(vec, it, type) \
if ((vec) && (vec)->a) \ if ((vec) && (vec)->a) \
@ -133,7 +139,7 @@ public:
if (!iter) { if (!iter) {
return *this; return *this;
} }
iter = iter->n; iter = iter->next;
return *this; return *this;
} }
iterator operator++(int) iterator operator++(int)
@ -149,7 +155,7 @@ public:
if (!iter) { if (!iter) {
return nullptr; return nullptr;
} }
return reinterpret_cast<T *>(iter->data); return reinterpret_cast<T *>(iter->elem);
} }
}; };

View File

@ -38,7 +38,7 @@ AnalysisOptionsWidget::AnalysisOptionsWidget(PreferencesDialog *dialog)
QString val = confCheckbox.config; QString val = confCheckbox.config;
QCheckBox &cb = *confCheckbox.checkBox; QCheckBox &cb = *confCheckbox.checkBox;
connect(confCheckbox.checkBox, &QCheckBox::stateChanged, this, connect(confCheckbox.checkBox, &QCheckBox::stateChanged, this,
[this, val, &cb]() { checkboxEnabler(&cb, val); }); [val, &cb]() { checkboxEnabler(&cb, val); });
} }
ui->analyzePushButton->setToolTip("Analyze the program using Rizin's \"aaa\" command"); ui->analyzePushButton->setToolTip("Analyze the program using Rizin's \"aaa\" command");

View File

@ -31,6 +31,7 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
actionEditBytes(this), actionEditBytes(this),
actionCopy(this), actionCopy(this),
actionCopyAddr(this), actionCopyAddr(this),
actionCopyInstrBytes(this),
actionAddComment(this), actionAddComment(this),
actionAnalyzeFunction(this), actionAnalyzeFunction(this),
actionEditFunction(this), actionEditFunction(this),
@ -76,6 +77,10 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
getCopyAddressSequence()); getCopyAddressSequence());
addAction(&actionCopyAddr); addAction(&actionCopyAddr);
initAction(&actionCopyInstrBytes, tr("Copy instruction bytes"),
SLOT(on_actionCopyInstrBytes_triggered()), getCopyInstrBytesSequence());
addAction(&actionCopyInstrBytes);
initAction(&showInSubmenu, tr("Show in"), nullptr); initAction(&showInSubmenu, tr("Show in"), nullptr);
addAction(&showInSubmenu); addAction(&showInSubmenu);
@ -643,6 +648,11 @@ QKeySequence DisassemblyContextMenu::getCopyAddressSequence() const
return { Qt::CTRL | Qt::SHIFT | Qt::Key_C }; return { Qt::CTRL | Qt::SHIFT | Qt::Key_C };
} }
QKeySequence DisassemblyContextMenu::getCopyInstrBytesSequence() const
{
return { Qt::CTRL | Qt::ALT | Qt::Key_C };
}
QKeySequence DisassemblyContextMenu::getSetToCodeSequence() const QKeySequence DisassemblyContextMenu::getSetToCodeSequence() const
{ {
return { Qt::Key_C }; return { Qt::Key_C };
@ -793,6 +803,12 @@ void DisassemblyContextMenu::on_actionCopyAddr_triggered()
clipboard->setText(RzAddressString(offset)); clipboard->setText(RzAddressString(offset));
} }
void DisassemblyContextMenu::on_actionCopyInstrBytes_triggered()
{
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(Core()->getInstructionBytes(offset));
}
void DisassemblyContextMenu::on_actionAddBreakpoint_triggered() void DisassemblyContextMenu::on_actionAddBreakpoint_triggered()
{ {
Core()->toggleBreakpoint(offset); Core()->toggleBreakpoint(offset);

View File

@ -42,6 +42,7 @@ private slots:
void on_actionCopy_triggered(); void on_actionCopy_triggered();
void on_actionCopyAddr_triggered(); void on_actionCopyAddr_triggered();
void on_actionCopyInstrBytes_triggered();
void on_actionAddComment_triggered(); void on_actionAddComment_triggered();
void on_actionAnalyzeFunction_triggered(); void on_actionAnalyzeFunction_triggered();
void on_actionRename_triggered(); void on_actionRename_triggered();
@ -79,6 +80,7 @@ private:
QKeySequence getCopySequence() const; QKeySequence getCopySequence() const;
QKeySequence getCommentSequence() const; QKeySequence getCommentSequence() const;
QKeySequence getCopyAddressSequence() const; QKeySequence getCopyAddressSequence() const;
QKeySequence getCopyInstrBytesSequence() const;
QKeySequence getGlobalVarSequence() const; QKeySequence getGlobalVarSequence() const;
QKeySequence getSetToCodeSequence() const; QKeySequence getSetToCodeSequence() const;
QKeySequence getSetAsStringSequence() const; QKeySequence getSetAsStringSequence() const;
@ -111,6 +113,7 @@ private:
QAction actionCopy; QAction actionCopy;
QAction *copySeparator; QAction *copySeparator;
QAction actionCopyAddr; QAction actionCopyAddr;
QAction actionCopyInstrBytes;
QAction actionAddComment; QAction actionAddComment;
QAction actionAnalyzeFunction; QAction actionAnalyzeFunction;

View File

@ -25,10 +25,6 @@
<update_contact>xarkes</update_contact> <update_contact>xarkes</update_contact>
<releases> <releases>
<release version="2.3.2" date="2023-09-14" />
<release version="2.3.1" date="2023-08-20" />
<release version="2.3.0" date="2023-08-05" />
<release version="2.2.1" date="2023-05-15" />
<release version="2.2.0" date="2023-02-22" /> <release version="2.2.0" date="2023-02-22" />
<release version="2.1.2" date="2022-09-11" /> <release version="2.1.2" date="2022-09-11" />
<release version="2.1.1" date="2022-09-10" /> <release version="2.1.1" date="2022-09-10" />

@ -1 +1 @@
Subproject commit 0c92dc939a0aa74e6b5c8770bf50aa5719e4de2b Subproject commit 8358f174d519bbf0d6cf4e1ccbe586308c009f85

View File

@ -286,7 +286,6 @@ void ColorPicker::startPickingFromScreen()
{ {
if (!pickingFromScreen) { if (!pickingFromScreen) {
setMouseTracking(true); setMouseTracking(true);
grabMouse(Qt::CursorShape::CrossCursor);
pickingFromScreen = true; pickingFromScreen = true;
bufferColor = currColor; bufferColor = currColor;
} }
@ -298,7 +297,6 @@ void ColorPicker::mouseReleaseEvent(QMouseEvent *event)
setColor(getColorAtMouse()); setColor(getColorAtMouse());
pickingFromScreen = false; pickingFromScreen = false;
setMouseTracking(false); setMouseTracking(false);
releaseMouse();
} }
QWidget::mouseReleaseEvent(event); QWidget::mouseReleaseEvent(event);
} }

View File

@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Color Picker</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<item> <item>

View File

@ -228,11 +228,11 @@ void ConsoleWidget::executeCommand(const QString &command)
addOutput(cmd_line); addOutput(cmd_line);
RVA oldOffset = Core()->getOffset(); RVA oldOffset = Core()->getOffset();
commandTask = QSharedPointer<CommandTask>( commandTask =
new CommandTask(command, CommandTask::ColorMode::MODE_256, true)); QSharedPointer<CommandTask>(new CommandTask(command, CommandTask::ColorMode::MODE_16M));
connect(commandTask.data(), &CommandTask::finished, this, connect(commandTask.data(), &CommandTask::finished, this,
[this, cmd_line, command, oldOffset](const QString &result) { [this, cmd_line, command, oldOffset](const QString &result) {
ui->outputTextEdit->appendHtml(result); ui->outputTextEdit->appendHtml(CutterCore::ansiEscapeToHtml(result));
scrollOutputToEnd(); scrollOutputToEnd();
historyAdd(command); historyAdd(command);
commandTask.clear(); commandTask.clear();

View File

@ -80,7 +80,7 @@ void Dashboard::updateContents()
int static_value = rz_bin_is_static(core->bin); int static_value = rz_bin_is_static(core->bin);
setPlainText(ui->staticEdit, tr(setBoolText(static_value))); setPlainText(ui->staticEdit, tr(setBoolText(static_value)));
RzList *hashes = bf ? rz_bin_file_compute_hashes(core->bin, bf, UT64_MAX) : nullptr; const RzPVector *hashes = bf ? rz_bin_file_compute_hashes(core->bin, bf, UT64_MAX) : nullptr;
// Delete hashesWidget if it isn't null to avoid duplicate components // Delete hashesWidget if it isn't null to avoid duplicate components
if (hashesWidget) { if (hashesWidget) {
@ -94,23 +94,23 @@ void Dashboard::updateContents()
ui->hashesVerticalLayout->addWidget(hashesWidget); ui->hashesVerticalLayout->addWidget(hashesWidget);
// Add hashes as a pair of Hash Name : Hash Value. // Add hashes as a pair of Hash Name : Hash Value.
RzListIter *iter; if (hashes != nullptr) {
RzBinFileHash *hash; for (const auto &hash : CutterPVector<RzBinFileHash>(hashes)) {
CutterRzListForeach (hashes, iter, RzBinFileHash, hash) { // Create a bold QString with the hash name uppercased
// Create a bold QString with the hash name uppercased QString label = QString("<b>%1:</b>").arg(QString(hash->type).toUpper());
QString label = QString("<b>%1:</b>").arg(QString(hash->type).toUpper());
// Define a Read-Only line edit to display the hash value // Define a Read-Only line edit to display the hash value
QLineEdit *hashLineEdit = new QLineEdit(); QLineEdit *hashLineEdit = new QLineEdit();
hashLineEdit->setReadOnly(true); hashLineEdit->setReadOnly(true);
hashLineEdit->setText(hash->hex); hashLineEdit->setText(hash->hex);
// Set cursor position to begining to avoid long hashes (e.g sha256) // Set cursor position to begining to avoid long hashes (e.g sha256)
// to look truncated at the begining // to look truncated at the begining
hashLineEdit->setCursorPosition(0); hashLineEdit->setCursorPosition(0);
// Add both controls to a form layout in a single row // Add both controls to a form layout in a single row
hashesLayout->addRow(new QLabel(label), hashLineEdit); hashesLayout->addRow(new QLabel(label), hashLineEdit);
}
} }
st64 fcns = rz_list_length(core->analysis->fcns); st64 fcns = rz_list_length(core->analysis->fcns);
@ -134,11 +134,11 @@ void Dashboard::updateContents()
setPlainText(ui->percentageLineEdit, QString::number(precentage) + "%"); setPlainText(ui->percentageLineEdit, QString::number(precentage) + "%");
ui->libraryList->setPlainText(""); ui->libraryList->setPlainText("");
const RzList *libs = bf ? rz_bin_object_get_libs(bf->o) : nullptr; const RzPVector *libs = bf ? rz_bin_object_get_libs(bf->o) : nullptr;
if (libs) { if (libs) {
QString libText; QString libText;
bool first = true; bool first = true;
for (const auto &lib : CutterRzList<char>(libs)) { for (const auto &lib : CutterPVector<char>(libs)) {
if (!first) { if (!first) {
libText.append("\n"); libText.append("\n");
} }

View File

@ -347,8 +347,10 @@ void DecompilerWidget::decompilationFinished(RzAnnotatedCode *codeDecompiled)
} }
} }
ui->textEdit->horizontalScrollBar()->setSliderPosition(scrollHistory[historyPos].first); if (!scrollHistory.empty()) {
ui->textEdit->verticalScrollBar()->setSliderPosition(scrollHistory[historyPos].second); ui->textEdit->horizontalScrollBar()->setSliderPosition(scrollHistory[historyPos].first);
ui->textEdit->verticalScrollBar()->setSliderPosition(scrollHistory[historyPos].second);
}
} }
void DecompilerWidget::setAnnotationsAtCursor(size_t pos) void DecompilerWidget::setAnnotationsAtCursor(size_t pos)

View File

@ -310,7 +310,7 @@ QVariant FunctionModel::headerData(int section, Qt::Orientation orientation, int
case SizeColumn: case SizeColumn:
return tr("Size"); return tr("Size");
case ImportColumn: case ImportColumn:
return tr("Imp."); return tr("Import");
case OffsetColumn: case OffsetColumn:
return tr("Offset"); return tr("Offset");
case NargsColumn: case NargsColumn:

View File

@ -159,7 +159,6 @@ void GraphView::beginMouseDrag(QMouseEvent *event)
scrollBase = event->pos(); scrollBase = event->pos();
scroll_mode = true; scroll_mode = true;
setCursor(Qt::ClosedHandCursor); setCursor(Qt::ClosedHandCursor);
viewport()->grabMouse();
} }
void GraphView::setViewOffset(QPoint offset) void GraphView::setViewOffset(QPoint offset)
@ -741,7 +740,6 @@ void GraphView::mouseReleaseEvent(QMouseEvent *event)
if (scroll_mode && (event->buttons() & (Qt::LeftButton | Qt::MiddleButton)) == 0) { if (scroll_mode && (event->buttons() & (Qt::LeftButton | Qt::MiddleButton)) == 0) {
scroll_mode = false; scroll_mode = false;
setCursor(Qt::ArrowCursor); setCursor(Qt::ArrowCursor);
viewport()->releaseMouse();
} }
} }

View File

@ -94,7 +94,7 @@ void GraphvizLayout::CalculateLayout(std::unordered_map<ut64, GraphBlock> &block
std::unordered_map<ut64, Agnode_t *> nodes; std::unordered_map<ut64, Agnode_t *> nodes;
for (const auto &block : blocks) { for (const auto &block : blocks) {
nodes[block.first] = agnode(g, nullptr, TRUE); nodes[block.first] = agnode(g, nullptr, true);
} }
std::vector<std::string> strc; std::vector<std::string> strc;
@ -143,7 +143,7 @@ void GraphvizLayout::CalculateLayout(std::unordered_map<ut64, GraphBlock> &block
if (v == nodes.end()) { if (v == nodes.end()) {
continue; continue;
} }
auto e = agedge(g, u, v->second, nullptr, TRUE); auto e = agedge(g, u, v->second, nullptr, true);
edges[{ blockIt.first, edge.target }] = e; edges[{ blockIt.first, edge.target }] = e;
if (loopEdges.find({ blockIt.first, edge.target }) != loopEdges.end()) { if (loopEdges.find({ blockIt.first, edge.target }) != loopEdges.end()) {
agxset(e, constraintAttr, STR("0")); agxset(e, constraintAttr, STR("0"));