Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6eb240a0c4 | |||
| 4c402f5ef3 | |||
| a8abda4b87 | |||
| 7347556aa2 | |||
| 289e155c98 | |||
| 147a52f3d4 | |||
| dda7541e2f | |||
| 2408f5494c | |||
| 2542690eca | |||
| cc0c187481 | |||
| a8dcfbec58 | |||
| 65705e3354 | |||
| e1f9a9eb6a |
3
.idea/editor.xml
generated
3
.idea/editor.xml
generated
@@ -19,7 +19,7 @@
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
@@ -58,6 +58,7 @@
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefinitionsOrder/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
|
||||
2
.idea/kte.iml
generated
2
.idea/kte.iml
generated
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4">
|
||||
<module classpath="CIDR" type="CPP_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="Python" name="Python facet">
|
||||
<configuration sdkName="" />
|
||||
|
||||
@@ -4,7 +4,7 @@ project(kte)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(KTE_VERSION "1.5.2")
|
||||
set(KTE_VERSION "1.5.8")
|
||||
|
||||
# Default to terminal-only build to avoid SDL/OpenGL dependency by default.
|
||||
# Enable with -DBUILD_GUI=ON when SDL2/OpenGL/Freetype are available.
|
||||
@@ -63,7 +63,7 @@ endif ()
|
||||
|
||||
message(STATUS "Build system: ${CMAKE_HOST_SYSTEM_NAME}")
|
||||
|
||||
if (${BUILD_GUI})
|
||||
if (BUILD_GUI)
|
||||
include(cmake/imgui.cmake)
|
||||
endif ()
|
||||
|
||||
@@ -208,6 +208,7 @@ set(FONT_HEADERS
|
||||
fonts/Syne.h
|
||||
fonts/Triplicate.h
|
||||
fonts/Unispace.h
|
||||
fonts/BerkeleyMono.h
|
||||
)
|
||||
|
||||
set(COMMON_HEADERS
|
||||
@@ -255,6 +256,7 @@ if (BUILD_GUI)
|
||||
ImGuiFrontend.h
|
||||
ImGuiInputHandler.h
|
||||
ImGuiRenderer.h
|
||||
fonts/BerkeleyMono.h
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
@@ -324,7 +326,7 @@ if (BUILD_TESTS)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (${BUILD_GUI})
|
||||
if (BUILD_GUI)
|
||||
# ImGui::CreateContext();
|
||||
# ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
@@ -379,12 +381,18 @@ if (${BUILD_GUI})
|
||||
${CMAKE_CURRENT_BINARY_DIR}/kge-Info.plist
|
||||
@ONLY)
|
||||
|
||||
# Ensure proper macOS bundle properties and RPATH so our bundled
|
||||
# frameworks are preferred over system/Homebrew ones.
|
||||
set_target_properties(kge PROPERTIES
|
||||
MACOSX_BUNDLE TRUE
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER ${KGE_BUNDLE_ID}
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "kge"
|
||||
MACOSX_BUNDLE_ICON_FILE ${MACOSX_BUNDLE_ICON_FILE}
|
||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/kge-Info.plist")
|
||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/kge-Info.plist"
|
||||
# Prefer the app's bundled frameworks at runtime
|
||||
INSTALL_RPATH "@executable_path/../Frameworks"
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
|
||||
add_dependencies(kge kte)
|
||||
add_custom_command(TARGET kge POST_BUILD
|
||||
@@ -408,4 +416,20 @@ if (${BUILD_GUI})
|
||||
# Install kge man page only when GUI is built
|
||||
install(FILES docs/kge.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
||||
install(FILES kge.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons)
|
||||
|
||||
# Optional post-build bundle fixup (can also be run from scripts).
|
||||
# This provides a CMake target to run BundleUtilities' fixup_bundle on the
|
||||
# built app, useful after macdeployqt to ensure non-Qt dylibs are internalized.
|
||||
if (APPLE AND TARGET kge)
|
||||
get_target_property(IS_BUNDLE kge MACOSX_BUNDLE)
|
||||
if (IS_BUNDLE)
|
||||
add_custom_target(kge_fixup_bundle ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DAPP_BUNDLE=${CMAKE_CURRENT_BINARY_DIR}/$<TARGET_PROPERTY:kge,MACOSX_BUNDLE_BUNDLE_NAME>.app
|
||||
-P ${CMAKE_CURRENT_LIST_DIR}/cmake/fix_bundle.cmake
|
||||
COMMENT "Running fixup_bundle on kge.app to internalize non-Qt dylibs"
|
||||
VERBATIM)
|
||||
add_dependencies(kge_fixup_bundle kge)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
24
Command.cc
24
Command.cc
@@ -2350,7 +2350,8 @@ cmd_newline(CommandContext &ctx)
|
||||
}
|
||||
// Insert replacement if provided
|
||||
if (!with.empty()) {
|
||||
buf->insert_text(static_cast<int>(y), static_cast<int>(p), std::string_view(with));
|
||||
buf->insert_text(static_cast<int>(y), static_cast<int>(p),
|
||||
std::string_view(with));
|
||||
if (u) {
|
||||
buf->SetCursor(p, y);
|
||||
u->Begin(UndoType::Insert);
|
||||
@@ -2405,6 +2406,8 @@ cmd_newline(CommandContext &ctx)
|
||||
ctx.editor.SetStatus(err.empty() ? std::string("Failed to open ") + value : err);
|
||||
} else {
|
||||
ctx.editor.SetStatus(std::string("Opened ") + value);
|
||||
// Center the view on the cursor (e.g. if the buffer restored a cursor position)
|
||||
cmd_center_on_cursor(ctx);
|
||||
// Close the prompt so subsequent typing edits the buffer, not the prompt
|
||||
ctx.editor.CancelPrompt();
|
||||
}
|
||||
@@ -4202,7 +4205,8 @@ cmd_reflow_paragraph(CommandContext &ctx)
|
||||
// Replace paragraph lines via PieceTable-backed operations
|
||||
for (std::size_t i = para_end; i + 1 > para_start; --i) {
|
||||
buf->delete_row(static_cast<int>(i));
|
||||
if (i == 0) break; // prevent wrap on size_t
|
||||
if (i == 0)
|
||||
break; // prevent wrap on size_t
|
||||
}
|
||||
// Insert new lines starting at para_start
|
||||
std::size_t insert_y = para_start;
|
||||
@@ -4227,6 +4231,9 @@ cmd_reload_buffer(CommandContext &ctx)
|
||||
Buffer *buf = ctx.editor.CurrentBuffer();
|
||||
if (!buf)
|
||||
return false;
|
||||
// Remember the current cursor position so we can attempt to restore it
|
||||
const std::size_t old_x = buf->Curx();
|
||||
const std::size_t old_y = buf->Cury();
|
||||
const std::string &filename = buf->Filename();
|
||||
if (filename.empty()) {
|
||||
ctx.editor.SetStatus("Cannot reload unnamed buffer");
|
||||
@@ -4237,6 +4244,19 @@ cmd_reload_buffer(CommandContext &ctx)
|
||||
ctx.editor.SetStatus(std::string("Reload failed: ") + err);
|
||||
return false;
|
||||
}
|
||||
// Try to restore the cursor to its previous position if still valid; otherwise clamp
|
||||
{
|
||||
auto &rows = buf->Rows();
|
||||
const std::size_t nrows = rows.size();
|
||||
if (nrows == 0) {
|
||||
buf->SetCursor(0, 0);
|
||||
} else {
|
||||
const std::size_t new_y = old_y < nrows ? old_y : (nrows - 1);
|
||||
const std::size_t line_len = rows[new_y].size();
|
||||
const std::size_t new_x = old_x < line_len ? old_x : line_len;
|
||||
buf->SetCursor(new_x, new_y);
|
||||
}
|
||||
}
|
||||
ctx.editor.SetStatus(std::string("Reloaded ") + filename);
|
||||
ensure_cursor_visible(ctx.editor, *buf);
|
||||
return true;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "GUITheme.h"
|
||||
#include "fonts/Font.h" // embedded default font (DefaultFont)
|
||||
#include "fonts/FontRegistry.h"
|
||||
#include "fonts/IosevkaExtended.h"
|
||||
#include "syntax/HighlighterRegistry.h"
|
||||
#include "syntax/NullHighlighter.h"
|
||||
|
||||
@@ -262,10 +263,10 @@ GUIFrontend::Step(Editor &ed, bool &running)
|
||||
// Update editor logical rows/cols using current ImGui metrics and display size
|
||||
{
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
float line_h = ImGui::GetTextLineHeightWithSpacing();
|
||||
float row_h = ImGui::GetTextLineHeightWithSpacing();
|
||||
float ch_w = ImGui::CalcTextSize("M").x;
|
||||
if (line_h <= 0.0f)
|
||||
line_h = 16.0f;
|
||||
if (row_h <= 0.0f)
|
||||
row_h = 16.0f;
|
||||
if (ch_w <= 0.0f)
|
||||
ch_w = 8.0f;
|
||||
// Prefer ImGui IO display size; fall back to cached SDL window size
|
||||
@@ -273,20 +274,20 @@ GUIFrontend::Step(Editor &ed, bool &running)
|
||||
float disp_h = io.DisplaySize.y > 0 ? io.DisplaySize.y : static_cast<float>(height_);
|
||||
|
||||
// Account for the GUI window padding and the status bar height used in ImGuiRenderer.
|
||||
// ImGuiRenderer pushes WindowPadding = (6,6) every frame, so use the same constants here
|
||||
// to avoid mismatches that would cause premature scrolling.
|
||||
const float pad_x = 6.0f;
|
||||
const float pad_y = 6.0f;
|
||||
// Status bar reserves one frame height (with spacing) inside the window
|
||||
float status_h = ImGui::GetFrameHeightWithSpacing();
|
||||
|
||||
float avail_w = std::max(0.0f, disp_w - 2.0f * pad_x);
|
||||
float avail_h = std::max(0.0f, disp_h - 2.0f * pad_y - status_h);
|
||||
// Use the same logic as ImGuiRenderer for available height and status bar reservation.
|
||||
float wanted_bar_h = ImGui::GetFrameHeight();
|
||||
float total_avail_h = std::max(0.0f, disp_h - 2.0f * pad_y);
|
||||
float actual_avail_h = std::floor((total_avail_h - wanted_bar_h) / row_h) * row_h;
|
||||
|
||||
// Visible content rows inside the scroll child
|
||||
auto content_rows = static_cast<std::size_t>(std::floor(avail_h / line_h));
|
||||
auto content_rows = static_cast<std::size_t>(std::max(0.0f, std::floor(actual_avail_h / row_h)));
|
||||
// Editor::Rows includes the status line; add 1 back for it.
|
||||
std::size_t rows = std::max<std::size_t>(1, content_rows + 1);
|
||||
std::size_t rows = content_rows + 1;
|
||||
|
||||
float avail_w = std::max(0.0f, disp_w - 2.0f * pad_x);
|
||||
std::size_t cols = static_cast<std::size_t>(std::max(1.0f, std::floor(avail_w / ch_w)));
|
||||
|
||||
// Only update if changed to avoid churn
|
||||
@@ -357,14 +358,32 @@ GUIFrontend::LoadGuiFont_(const char * /*path*/, const float size_px)
|
||||
{
|
||||
const ImGuiIO &io = ImGui::GetIO();
|
||||
io.Fonts->Clear();
|
||||
const ImFont *font = io.Fonts->AddFontFromMemoryCompressedTTF(
|
||||
|
||||
ImFontConfig config;
|
||||
config.MergeMode = false;
|
||||
|
||||
// Load Basic Latin + Latin Supplement
|
||||
io.Fonts->AddFontFromMemoryCompressedTTF(
|
||||
kte::Fonts::DefaultFontData,
|
||||
kte::Fonts::DefaultFontSize,
|
||||
size_px);
|
||||
if (!font) {
|
||||
font = io.Fonts->AddFontDefault();
|
||||
}
|
||||
(void) font;
|
||||
size_px,
|
||||
&config,
|
||||
io.Fonts->GetGlyphRangesDefault());
|
||||
|
||||
// Merge Greek and Mathematical symbols from IosevkaExtended
|
||||
config.MergeMode = true;
|
||||
static const ImWchar extended_ranges[] = {
|
||||
0x0370, 0x03FF, // Greek and Coptic
|
||||
0x2200, 0x22FF, // Mathematical Operators
|
||||
0,
|
||||
};
|
||||
io.Fonts->AddFontFromMemoryCompressedTTF(
|
||||
kte::Fonts::IosevkaExtended::DefaultFontRegularCompressedData,
|
||||
kte::Fonts::IosevkaExtended::DefaultFontRegularCompressedSize,
|
||||
size_px,
|
||||
&config,
|
||||
extended_ranges);
|
||||
|
||||
io.Fonts->Build();
|
||||
return true;
|
||||
}
|
||||
@@ -158,8 +158,9 @@ map_key(const SDL_Keycode key,
|
||||
ascii_key = static_cast<int>(key);
|
||||
}
|
||||
bool ctrl2 = (mod & KMOD_CTRL) != 0;
|
||||
// If user typed a literal 'C' (or '^') as a control qualifier, keep k-prefix active
|
||||
if (ascii_key == 'C' || ascii_key == 'c' || ascii_key == '^') {
|
||||
// If user typed a literal 'C' (uppercase) or '^' as a control qualifier, keep k-prefix active
|
||||
// Do NOT treat lowercase 'c' as a qualifier; 'c' is a valid k-command (BufferClose).
|
||||
if (ascii_key == 'C' || ascii_key == '^') {
|
||||
k_ctrl_pending = true;
|
||||
// Keep waiting for the next suffix; show status and suppress ensuing TEXTINPUT
|
||||
if (ed)
|
||||
@@ -472,8 +473,8 @@ ImGuiInputHandler::ProcessSDLEvent(const SDL_Event &e)
|
||||
ascii_key = static_cast<int>(c0);
|
||||
}
|
||||
if (ascii_key != 0) {
|
||||
// Qualifier via TEXTINPUT: 'C' or '^'
|
||||
if (ascii_key == 'C' || ascii_key == 'c' || ascii_key == '^') {
|
||||
// Qualifier via TEXTINPUT: uppercase 'C' or '^' only
|
||||
if (ascii_key == 'C' || ascii_key == '^') {
|
||||
k_ctrl_pending_ = true;
|
||||
if (ed_)
|
||||
ed_->SetStatus("C-k C _");
|
||||
|
||||
215
ImGuiRenderer.cc
215
ImGuiRenderer.cc
@@ -94,8 +94,17 @@ ImGuiRenderer::Draw(Editor &ed)
|
||||
ImGui::SetNextWindowScroll(ImVec2(target_x, target_y));
|
||||
}
|
||||
|
||||
// Reserve space for status bar at bottom
|
||||
ImGui::BeginChild("scroll", ImVec2(0, -ImGui::GetFrameHeightWithSpacing()), false,
|
||||
// Reserve space for status bar at bottom.
|
||||
// We calculate a height that is an exact multiple of the line height
|
||||
// to avoid partial lines and "scroll past end" jitter.
|
||||
float total_avail_h = ImGui::GetContentRegionAvail().y;
|
||||
float wanted_bar_h = ImGui::GetFrameHeight();
|
||||
float child_h_plan = std::max(0.0f, std::floor((total_avail_h - wanted_bar_h) / row_h) * row_h);
|
||||
float real_bar_h = total_avail_h - child_h_plan;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
|
||||
ImGui::BeginChild("scroll", ImVec2(0, child_h_plan), false,
|
||||
ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||
|
||||
// Get child window position and scroll for click handling
|
||||
@@ -138,90 +147,6 @@ ImGuiRenderer::Draw(Editor &ed)
|
||||
}
|
||||
prev_buf_rowoffs = buf_rowoffs;
|
||||
prev_buf_coloffs = buf_coloffs;
|
||||
|
||||
// Synchronize cursor and scrolling.
|
||||
// Ensure the cursor is visible, but avoid aggressive centering so that
|
||||
// the same lines remain visible until the cursor actually goes off-screen.
|
||||
{
|
||||
// Compute visible row range using the child window height
|
||||
float child_h = ImGui::GetWindowHeight();
|
||||
long first_row = static_cast<long>(scroll_y / row_h);
|
||||
long vis_rows = static_cast<long>(child_h / row_h);
|
||||
if (vis_rows < 1)
|
||||
vis_rows = 1;
|
||||
long last_row = first_row + vis_rows - 1;
|
||||
|
||||
long cyr = static_cast<long>(cy);
|
||||
if (cyr < first_row) {
|
||||
// Scroll just enough to bring the cursor line to the top
|
||||
float target = static_cast<float>(cyr) * row_h;
|
||||
if (target < 0.f)
|
||||
target = 0.f;
|
||||
float max_y = ImGui::GetScrollMaxY();
|
||||
if (max_y >= 0.f && target > max_y)
|
||||
target = max_y;
|
||||
ImGui::SetScrollY(target);
|
||||
scroll_y = ImGui::GetScrollY();
|
||||
first_row = static_cast<long>(scroll_y / row_h);
|
||||
last_row = first_row + vis_rows - 1;
|
||||
} else if (cyr > last_row) {
|
||||
// Scroll just enough to bring the cursor line to the bottom
|
||||
long new_first = cyr - vis_rows + 1;
|
||||
if (new_first < 0)
|
||||
new_first = 0;
|
||||
float target = static_cast<float>(new_first) * row_h;
|
||||
float max_y = ImGui::GetScrollMaxY();
|
||||
if (target < 0.f)
|
||||
target = 0.f;
|
||||
if (max_y >= 0.f && target > max_y)
|
||||
target = max_y;
|
||||
ImGui::SetScrollY(target);
|
||||
scroll_y = ImGui::GetScrollY();
|
||||
first_row = static_cast<long>(scroll_y / row_h);
|
||||
last_row = first_row + vis_rows - 1;
|
||||
}
|
||||
|
||||
// Horizontal scroll: ensure cursor column is visible
|
||||
float child_w = ImGui::GetWindowWidth();
|
||||
long vis_cols = static_cast<long>(child_w / space_w);
|
||||
if (vis_cols < 1)
|
||||
vis_cols = 1;
|
||||
long first_col = static_cast<long>(scroll_x / space_w);
|
||||
long last_col = first_col + vis_cols - 1;
|
||||
|
||||
// Compute cursor's rendered X position (accounting for tabs)
|
||||
std::size_t cursor_rx = 0;
|
||||
if (cy < lines.size()) {
|
||||
std::string cur_line = static_cast<std::string>(lines[cy]);
|
||||
const std::size_t tabw = 8;
|
||||
for (std::size_t i = 0; i < cx && i < cur_line.size(); ++i) {
|
||||
if (cur_line[i] == '\t') {
|
||||
cursor_rx += tabw - (cursor_rx % tabw);
|
||||
} else {
|
||||
cursor_rx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
long cxr = static_cast<long>(cursor_rx);
|
||||
if (cxr < first_col || cxr > last_col) {
|
||||
float target_x = static_cast<float>(cxr) * space_w;
|
||||
// Center horizontally if possible
|
||||
target_x -= (child_w / 2.0f);
|
||||
if (target_x < 0.f)
|
||||
target_x = 0.f;
|
||||
float max_x = ImGui::GetScrollMaxX();
|
||||
if (max_x >= 0.f && target_x > max_x)
|
||||
target_x = max_x;
|
||||
ImGui::SetScrollX(target_x);
|
||||
scroll_x = ImGui::GetScrollX();
|
||||
}
|
||||
// Phase 3: prefetch visible viewport highlights and warm around in background
|
||||
if (buf->SyntaxEnabled() && buf->Highlighter() && buf->Highlighter()->HasHighlighter()) {
|
||||
int fr = static_cast<int>(std::max(0L, first_row));
|
||||
int rc = static_cast<int>(std::max(1L, vis_rows));
|
||||
buf->Highlighter()->PrefetchViewport(*buf, fr, rc, buf->Version());
|
||||
}
|
||||
}
|
||||
// Cache current horizontal offset in rendered columns for click handling
|
||||
const std::size_t coloffs_now = buf->Coloffs();
|
||||
|
||||
@@ -489,23 +414,98 @@ ImGuiRenderer::Draw(Editor &ed)
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(p0, p1, col);
|
||||
}
|
||||
}
|
||||
// Synchronize cursor and scrolling after rendering all lines so content size is known.
|
||||
{
|
||||
float child_h_actual = ImGui::GetWindowHeight();
|
||||
float child_w_actual = ImGui::GetWindowWidth();
|
||||
float scroll_y_now = ImGui::GetScrollY();
|
||||
float scroll_x_now = ImGui::GetScrollX();
|
||||
|
||||
long first_row = static_cast<long>(scroll_y_now / row_h);
|
||||
long vis_rows = static_cast<long>(std::round(child_h_actual / row_h));
|
||||
if (vis_rows < 1)
|
||||
vis_rows = 1;
|
||||
long last_row = first_row + vis_rows - 1;
|
||||
|
||||
long cyr = static_cast<long>(cy);
|
||||
if (cyr < first_row) {
|
||||
float target = static_cast<float>(cyr) * row_h;
|
||||
if (target < 0.f)
|
||||
target = 0.f;
|
||||
float max_y = ImGui::GetScrollMaxY();
|
||||
if (max_y >= 0.f && target > max_y)
|
||||
target = max_y;
|
||||
ImGui::SetScrollY(target);
|
||||
first_row = static_cast<long>(target / row_h);
|
||||
last_row = first_row + vis_rows - 1;
|
||||
} else if (cyr > last_row) {
|
||||
long new_first = cyr - vis_rows + 1;
|
||||
if (new_first < 0)
|
||||
new_first = 0;
|
||||
float target = static_cast<float>(new_first) * row_h;
|
||||
float max_y = ImGui::GetScrollMaxY();
|
||||
if (target < 0.f)
|
||||
target = 0.f;
|
||||
if (max_y >= 0.f && target > max_y)
|
||||
target = max_y;
|
||||
ImGui::SetScrollY(target);
|
||||
first_row = static_cast<long>(target / row_h);
|
||||
last_row = first_row + vis_rows - 1;
|
||||
}
|
||||
|
||||
// Horizontal scroll: ensure cursor column is visible
|
||||
long vis_cols = static_cast<long>(std::round(child_w_actual / space_w));
|
||||
if (vis_cols < 1)
|
||||
vis_cols = 1;
|
||||
long first_col = static_cast<long>(scroll_x_now / space_w);
|
||||
long last_col = first_col + vis_cols - 1;
|
||||
|
||||
std::size_t cursor_rx = 0;
|
||||
if (cy < lines.size()) {
|
||||
std::string cur_line = static_cast<std::string>(lines[cy]);
|
||||
const std::size_t tabw = 8;
|
||||
for (std::size_t i = 0; i < cx && i < cur_line.size(); ++i) {
|
||||
if (cur_line[i] == '\t') {
|
||||
cursor_rx += tabw - (cursor_rx % tabw);
|
||||
} else {
|
||||
cursor_rx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
long cxr = static_cast<long>(cursor_rx);
|
||||
if (cxr < first_col || cxr > last_col) {
|
||||
float target_x = static_cast<float>(cxr) * space_w;
|
||||
target_x -= (child_w_actual / 2.0f);
|
||||
if (target_x < 0.f)
|
||||
target_x = 0.f;
|
||||
float max_x = ImGui::GetScrollMaxX();
|
||||
if (max_x >= 0.f && target_x > max_x)
|
||||
target_x = max_x;
|
||||
ImGui::SetScrollX(target_x);
|
||||
}
|
||||
|
||||
if (buf->SyntaxEnabled() && buf->Highlighter() && buf->Highlighter()->HasHighlighter()) {
|
||||
int fr = static_cast<int>(std::max(0L, first_row));
|
||||
int rc = static_cast<int>(std::max(1L, vis_rows));
|
||||
buf->Highlighter()->PrefetchViewport(*buf, fr, rc, buf->Version());
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleVar(2); // WindowPadding, ItemSpacing
|
||||
|
||||
// Status bar spanning full width
|
||||
ImGui::Separator();
|
||||
|
||||
// Compute full content width and draw a filled background rectangle
|
||||
// Status bar area starting right after the scroll child
|
||||
ImVec2 win_pos = ImGui::GetWindowPos();
|
||||
ImVec2 cr_min = ImGui::GetWindowContentRegionMin();
|
||||
ImVec2 cr_max = ImGui::GetWindowContentRegionMax();
|
||||
float x0 = win_pos.x + cr_min.x;
|
||||
float x1 = win_pos.x + cr_max.x;
|
||||
ImVec2 cursor = ImGui::GetCursorScreenPos();
|
||||
float bar_h = ImGui::GetFrameHeight();
|
||||
ImVec2 p0(x0, cursor.y);
|
||||
ImVec2 p1(x1, cursor.y + bar_h);
|
||||
ImVec2 win_sz = ImGui::GetWindowSize();
|
||||
float x0 = win_pos.x;
|
||||
float x1 = win_pos.x + win_sz.x;
|
||||
float y0 = ImGui::GetCursorScreenPos().y;
|
||||
float bar_h = real_bar_h;
|
||||
|
||||
ImVec2 p0(x0, y0);
|
||||
ImVec2 p1(x1, y0 + bar_h);
|
||||
ImU32 bg_col = ImGui::GetColorU32(ImGuiCol_HeaderActive);
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(p0, p1, bg_col);
|
||||
|
||||
// If a prompt is active, replace the entire status bar with the prompt text
|
||||
if (ed.PromptActive()) {
|
||||
std::string label = ed.PromptLabel();
|
||||
@@ -591,11 +591,9 @@ ImGuiRenderer::Draw(Editor &ed)
|
||||
|
||||
ImVec2 msg_sz = ImGui::CalcTextSize(final_msg.c_str());
|
||||
ImGui::PushClipRect(ImVec2(p0.x, p0.y), ImVec2(p1.x, p1.y), true);
|
||||
ImGui::SetCursorScreenPos(ImVec2(left_x, p0.y + (bar_h - msg_sz.y) * 0.5f));
|
||||
ImGui::SetCursorScreenPos(ImVec2(left_x, y0 + (bar_h - msg_sz.y) * 0.5f));
|
||||
ImGui::TextUnformatted(final_msg.c_str());
|
||||
ImGui::PopClipRect();
|
||||
// Advance cursor to after the bar to keep layout consistent
|
||||
ImGui::Dummy(ImVec2(x1 - x0, bar_h));
|
||||
} else {
|
||||
// Build left text
|
||||
std::string left;
|
||||
@@ -671,20 +669,21 @@ ImGuiRenderer::Draw(Editor &ed)
|
||||
float max_left = std::max(0.0f, right_x - left_x - pad);
|
||||
if (max_left < left_sz.x && max_left > 10.0f) {
|
||||
// Render a clipped left using a child region
|
||||
ImGui::SetCursorScreenPos(ImVec2(left_x, p0.y + (bar_h - left_sz.y) * 0.5f));
|
||||
ImGui::PushClipRect(ImVec2(left_x, p0.y), ImVec2(right_x - pad, p1.y), true);
|
||||
ImGui::SetCursorScreenPos(ImVec2(left_x, y0 + (bar_h - left_sz.y) * 0.5f));
|
||||
ImGui::PushClipRect(ImVec2(left_x, y0), ImVec2(right_x - pad, y0 + bar_h),
|
||||
true);
|
||||
ImGui::TextUnformatted(left.c_str());
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
} else {
|
||||
// Draw left normally
|
||||
ImGui::SetCursorScreenPos(ImVec2(left_x, p0.y + (bar_h - left_sz.y) * 0.5f));
|
||||
ImGui::SetCursorScreenPos(ImVec2(left_x, y0 + (bar_h - left_sz.y) * 0.5f));
|
||||
ImGui::TextUnformatted(left.c_str());
|
||||
}
|
||||
|
||||
// Draw right
|
||||
ImGui::SetCursorScreenPos(ImVec2(std::max(right_x, left_x),
|
||||
p0.y + (bar_h - right_sz.y) * 0.5f));
|
||||
y0 + (bar_h - right_sz.y) * 0.5f));
|
||||
ImGui::TextUnformatted(right.c_str());
|
||||
|
||||
// Draw middle message centered in remaining space
|
||||
@@ -696,14 +695,12 @@ ImGuiRenderer::Draw(Editor &ed)
|
||||
ImVec2 msg_sz = ImGui::CalcTextSize(msg.c_str());
|
||||
float msg_x = mid_left + std::max(0.0f, (mid_w - msg_sz.x) * 0.5f);
|
||||
// Clip to middle region
|
||||
ImGui::PushClipRect(ImVec2(mid_left, p0.y), ImVec2(mid_right, p1.y), true);
|
||||
ImGui::SetCursorScreenPos(ImVec2(msg_x, p0.y + (bar_h - msg_sz.y) * 0.5f));
|
||||
ImGui::PushClipRect(ImVec2(mid_left, y0), ImVec2(mid_right, y0 + bar_h), true);
|
||||
ImGui::SetCursorScreenPos(ImVec2(msg_x, y0 + (bar_h - msg_sz.y) * 0.5f));
|
||||
ImGui::TextUnformatted(msg.c_str());
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
}
|
||||
// Advance cursor to after the bar to keep layout consistent
|
||||
ImGui::Dummy(ImVec2(x1 - x0, bar_h));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ TerminalFrontend::Init(Editor &ed)
|
||||
have_old_sigint_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -178,8 +178,9 @@ map_key_to_command(const int ch,
|
||||
ctrl = true;
|
||||
ascii_key = 'a' + (ch - 1);
|
||||
}
|
||||
// If user typed literal 'C'/'c' or '^' as a qualifier, keep k-prefix and set pending
|
||||
if (ascii_key == 'C' || ascii_key == 'c' || ascii_key == '^') {
|
||||
// If user typed literal 'C' or '^' as a qualifier, keep k-prefix and set pending
|
||||
// Note: Do NOT treat lowercase 'c' as a qualifier, since 'c' is a valid C-k command (BufferClose).
|
||||
if (ascii_key == 'C' || ascii_key == '^') {
|
||||
k_ctrl_pending = true;
|
||||
if (ed)
|
||||
ed->SetStatus("C-k C _");
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#include <clocale>
|
||||
#define _XOPEN_SOURCE_EXTENDED 1
|
||||
#include <cwchar>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
@@ -177,15 +180,32 @@ TerminalRenderer::Draw(Editor &ed)
|
||||
}
|
||||
};
|
||||
while (written < cols) {
|
||||
char ch = ' ';
|
||||
bool from_src = false;
|
||||
wchar_t wch = L' ';
|
||||
int wch_len = 1;
|
||||
int disp_w = 1;
|
||||
|
||||
if (src_i < line.size()) {
|
||||
unsigned char c = static_cast<unsigned char>(line[src_i]);
|
||||
if (c == '\t') {
|
||||
// Decode UTF-8
|
||||
std::mbstate_t state = std::mbstate_t();
|
||||
size_t res = std::mbrtowc(
|
||||
&wch, &line[src_i], line.size() - src_i, &state);
|
||||
if (res == (size_t) -1 || res == (size_t) -2) {
|
||||
// Invalid or incomplete; treat as single byte
|
||||
wch = static_cast<unsigned char>(line[src_i]);
|
||||
wch_len = 1;
|
||||
} else if (res == 0) {
|
||||
wch = L'\0';
|
||||
wch_len = 1;
|
||||
} else {
|
||||
wch_len = static_cast<int>(res);
|
||||
}
|
||||
|
||||
if (wch == L'\t') {
|
||||
std::size_t next_tab = tabw - (render_col % tabw);
|
||||
if (render_col + next_tab <= coloffs) {
|
||||
render_col += next_tab;
|
||||
++src_i;
|
||||
src_i += wch_len;
|
||||
continue;
|
||||
}
|
||||
// Emit spaces for tab
|
||||
@@ -233,23 +253,34 @@ TerminalRenderer::Draw(Editor &ed)
|
||||
++render_col;
|
||||
--next_tab;
|
||||
}
|
||||
++src_i;
|
||||
src_i += wch_len;
|
||||
continue;
|
||||
} else {
|
||||
// normal char
|
||||
disp_w = wcwidth(wch);
|
||||
if (disp_w < 0)
|
||||
disp_w = 1; // non-printable or similar
|
||||
|
||||
if (render_col < coloffs) {
|
||||
++render_col;
|
||||
++src_i;
|
||||
render_col += disp_w;
|
||||
src_i += wch_len;
|
||||
continue;
|
||||
}
|
||||
ch = static_cast<char>(c);
|
||||
from_src = true;
|
||||
}
|
||||
} else {
|
||||
// beyond EOL, fill spaces
|
||||
ch = ' ';
|
||||
wch = L' ';
|
||||
wch_len = 1;
|
||||
disp_w = 1;
|
||||
from_src = false;
|
||||
}
|
||||
|
||||
if (written + disp_w > cols) {
|
||||
// would overflow, just break
|
||||
break;
|
||||
}
|
||||
|
||||
bool in_hl = search_mode && from_src && is_src_in_hl(src_i);
|
||||
bool in_cur =
|
||||
has_current && li == cur_my && from_src && src_i >= cur_mx && src_i <
|
||||
@@ -273,11 +304,20 @@ TerminalRenderer::Draw(Editor &ed)
|
||||
if (!in_hl && from_src) {
|
||||
apply_token_attr(token_at(src_i));
|
||||
}
|
||||
addch(static_cast<unsigned char>(ch));
|
||||
++written;
|
||||
++render_col;
|
||||
|
||||
if (from_src) {
|
||||
cchar_t cch;
|
||||
wchar_t warr[2] = {wch, L'\0'};
|
||||
setcchar(&cch, warr, A_NORMAL, 0, nullptr);
|
||||
add_wch(&cch);
|
||||
} else {
|
||||
addch(' ');
|
||||
}
|
||||
|
||||
written += disp_w;
|
||||
render_col += disp_w;
|
||||
if (from_src)
|
||||
++src_i;
|
||||
src_i += wch_len;
|
||||
if (src_i >= line.size() && written >= cols)
|
||||
break;
|
||||
}
|
||||
@@ -306,14 +346,26 @@ TerminalRenderer::Draw(Editor &ed)
|
||||
std::size_t src_i_cur = 0;
|
||||
std::size_t render_col_cur = 0;
|
||||
while (src_i_cur < line_for_cursor.size() && src_i_cur < cx) {
|
||||
unsigned char ccur = static_cast<unsigned char>(line_for_cursor[src_i_cur]);
|
||||
if (ccur == '\t') {
|
||||
std::mbstate_t state = std::mbstate_t();
|
||||
wchar_t wch;
|
||||
size_t res = std::mbrtowc(
|
||||
&wch, &line_for_cursor[src_i_cur], line_for_cursor.size() - src_i_cur,
|
||||
&state);
|
||||
|
||||
if (res == (size_t) -1 || res == (size_t) -2) {
|
||||
render_col_cur += 1;
|
||||
src_i_cur += 1;
|
||||
} else if (res == 0) {
|
||||
src_i_cur += 1;
|
||||
} else {
|
||||
if (wch == L'\t') {
|
||||
std::size_t next_tab = tabw - (render_col_cur % tabw);
|
||||
render_col_cur += next_tab;
|
||||
++src_i_cur;
|
||||
} else {
|
||||
++render_col_cur;
|
||||
++src_i_cur;
|
||||
int dw = wcwidth(wch);
|
||||
render_col_cur += (dw < 0) ? 1 : dw;
|
||||
}
|
||||
src_i_cur += res;
|
||||
}
|
||||
}
|
||||
rx_recomputed = render_col_cur;
|
||||
|
||||
78
cmake/fix_bundle.cmake
Normal file
78
cmake/fix_bundle.cmake
Normal file
@@ -0,0 +1,78 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
# Fix up a macOS .app bundle by copying non-Qt dylibs into
|
||||
# Contents/Frameworks and rewriting install names to use @rpath/@loader_path.
|
||||
#
|
||||
# Usage:
|
||||
# cmake -DAPP_BUNDLE=/path/to/kge.app -P cmake/fix_bundle.cmake
|
||||
|
||||
if (NOT APP_BUNDLE)
|
||||
message(FATAL_ERROR "APP_BUNDLE not set. Invoke with -DAPP_BUNDLE=/path/to/App.app")
|
||||
endif ()
|
||||
|
||||
get_filename_component(APP_DIR "${APP_BUNDLE}" ABSOLUTE)
|
||||
set(EXECUTABLE "${APP_DIR}/Contents/MacOS/kge")
|
||||
|
||||
if (NOT EXISTS "${EXECUTABLE}")
|
||||
message(FATAL_ERROR "Executable not found at: ${EXECUTABLE}")
|
||||
endif ()
|
||||
|
||||
include(BundleUtilities)
|
||||
|
||||
# Directories to search when resolving prerequisites. We include Homebrew so that
|
||||
# if any deps are currently resolved from there, fixup_bundle will copy them into
|
||||
# the bundle and rewrite install names to be self-contained.
|
||||
set(DIRS
|
||||
"/usr/local/lib"
|
||||
"/opt/homebrew/lib"
|
||||
"/opt/homebrew/opt"
|
||||
)
|
||||
|
||||
# Note: We pass empty plugin list so fixup_bundle scans the executable and all
|
||||
# libs it references recursively. Qt frameworks already live in the bundle after
|
||||
# macdeployqt; this step is primarily for non-Qt dylibs (glib, icu, pcre2, zstd,
|
||||
# dbus, etc.).
|
||||
# fixup_bundle often fails if copied libraries are read-only.
|
||||
# We also try to use the system install_name_tool and otool to avoid issues with Anaconda's version.
|
||||
# Note: BundleUtilities uses find_program(gp_otool "otool") internally, so we might need to set it differently.
|
||||
set(gp_otool "/usr/bin/otool")
|
||||
set(CMAKE_INSTALL_NAME_TOOL "/usr/bin/install_name_tool")
|
||||
set(CMAKE_OTOOL "/usr/bin/otool")
|
||||
set(ENV{PATH} "/usr/bin:/bin:/usr/sbin:/sbin")
|
||||
|
||||
execute_process(COMMAND chmod -R u+w "${APP_DIR}/Contents/Frameworks")
|
||||
|
||||
fixup_bundle("${APP_DIR}" "" "${DIRS}")
|
||||
|
||||
# On Apple Silicon (and modern macOS in general), modifications by fixup_bundle
|
||||
# invalidate code signatures. We must re-sign the bundle (at least ad-hoc)
|
||||
# for it to be allowed to run.
|
||||
# We sign deep, but sometimes explicit signing of components is more reliable.
|
||||
message(STATUS "Re-signing ${APP_DIR} after fixup...")
|
||||
|
||||
# 1. Sign dylibs in Frameworks
|
||||
file(GLOB_RECURSE DYLIBS "${APP_DIR}/Contents/Frameworks/*.dylib")
|
||||
foreach (DYLIB ${DYLIBS})
|
||||
message(STATUS "Signing ${DYLIB}...")
|
||||
execute_process(COMMAND /usr/bin/codesign --force --sign - "${DYLIB}")
|
||||
endforeach ()
|
||||
|
||||
# 2. Sign nested executables
|
||||
message(STATUS "Signing nested kte...")
|
||||
execute_process(COMMAND /usr/bin/codesign --force --sign - "${APP_DIR}/Contents/MacOS/kte")
|
||||
|
||||
# 3. Sign the main executable explicitly
|
||||
message(STATUS "Signing main kge...")
|
||||
execute_process(COMMAND /usr/bin/codesign --force --sign - "${APP_DIR}/Contents/MacOS/kge")
|
||||
|
||||
# 4. Sign the main bundle
|
||||
execute_process(
|
||||
COMMAND /usr/bin/codesign --force --deep --sign - "${APP_DIR}"
|
||||
RESULT_VARIABLE CODESIGN_RESULT
|
||||
)
|
||||
|
||||
if (NOT CODESIGN_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Codesign failed with error: ${CODESIGN_RESULT}")
|
||||
endif ()
|
||||
|
||||
message(STATUS "fix_bundle.cmake completed for ${APP_DIR}")
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
lib,
|
||||
pkgs ? import <nixpkgs> {},
|
||||
lib ? pkgs.lib,
|
||||
stdenv,
|
||||
cmake,
|
||||
ncurses,
|
||||
|
||||
5438
fonts/BerkeleyMono.h
Normal file
5438
fonts/BerkeleyMono.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
#include "Font.h"
|
||||
#include "IosevkaExtended.h"
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
@@ -8,16 +9,32 @@ Font::Load(const float size) const
|
||||
{
|
||||
const ImGuiIO &io = ImGui::GetIO();
|
||||
io.Fonts->Clear();
|
||||
const ImFont *font = io.Fonts->AddFontFromMemoryCompressedTTF(
|
||||
|
||||
ImFontConfig config;
|
||||
config.MergeMode = false;
|
||||
|
||||
// Load Basic Latin + Latin Supplement
|
||||
io.Fonts->AddFontFromMemoryCompressedTTF(
|
||||
this->data_,
|
||||
this->size_,
|
||||
size);
|
||||
size,
|
||||
&config,
|
||||
io.Fonts->GetGlyphRangesDefault());
|
||||
|
||||
if (!font) {
|
||||
font = io.Fonts->AddFontDefault();
|
||||
}
|
||||
// Merge Greek and Mathematical symbols from IosevkaExtended as fallback
|
||||
config.MergeMode = true;
|
||||
static const ImWchar extended_ranges[] = {
|
||||
0x0370, 0x03FF, // Greek and Coptic
|
||||
0x2200, 0x22FF, // Mathematical Operators
|
||||
0,
|
||||
};
|
||||
io.Fonts->AddFontFromMemoryCompressedTTF(
|
||||
kte::Fonts::IosevkaExtended::DefaultFontRegularCompressedData,
|
||||
kte::Fonts::IosevkaExtended::DefaultFontRegularCompressedSize,
|
||||
size,
|
||||
&config,
|
||||
extended_ranges);
|
||||
|
||||
(void) font;
|
||||
io.Fonts->Build();
|
||||
}
|
||||
} // namespace kte::Fonts
|
||||
@@ -3,12 +3,12 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "BrassMonoCode.h"
|
||||
#include "BerkeleyMono.h"
|
||||
|
||||
namespace kte::Fonts {
|
||||
// Provide default embedded font aliases used by GUIFrontend fallback loader
|
||||
inline const unsigned int DefaultFontSize = BrassMonoCode::DefaultFontBoldCompressedSize;
|
||||
inline const unsigned int *DefaultFontData = BrassMonoCode::DefaultFontBoldCompressedData;
|
||||
inline const unsigned int DefaultFontSize = BerkeleyMono::DefaultFontRegularCompressedSize;
|
||||
inline const unsigned int *DefaultFontData = BerkeleyMono::DefaultFontRegularCompressedData;
|
||||
|
||||
class Font {
|
||||
public:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "B612Mono.h"
|
||||
#include "BerkeleyMono.h"
|
||||
#include "BrassMono.h"
|
||||
#include "BrassMonoCode.h"
|
||||
#include "FiraCode.h"
|
||||
|
||||
@@ -7,14 +7,24 @@ InstallDefaultFonts()
|
||||
{
|
||||
FontRegistry::Instance().Register(std::make_unique<Font>(
|
||||
"default",
|
||||
BrassMono::DefaultFontBoldCompressedData,
|
||||
BrassMono::DefaultFontBoldCompressedSize
|
||||
BerkeleyMono::DefaultFontBoldCompressedData,
|
||||
BerkeleyMono::DefaultFontBoldCompressedSize
|
||||
));
|
||||
FontRegistry::Instance().Register(std::make_unique<Font>(
|
||||
"b612",
|
||||
B612Mono::DefaultFontRegularCompressedData,
|
||||
B612Mono::DefaultFontRegularCompressedSize
|
||||
));
|
||||
FontRegistry::Instance().Register(std::make_unique<Font>(
|
||||
"berkeley",
|
||||
BerkeleyMono::DefaultFontRegularCompressedData,
|
||||
BerkeleyMono::DefaultFontRegularCompressedSize
|
||||
));
|
||||
FontRegistry::Instance().Register(std::make_unique<Font>(
|
||||
"berkeley-bold",
|
||||
BerkeleyMono::DefaultFontBoldCompressedData,
|
||||
BerkeleyMono::DefaultFontBoldCompressedSize
|
||||
));
|
||||
FontRegistry::Instance().Register(std::make_unique<Font>(
|
||||
"brassmono",
|
||||
BrassMono::DefaultFontRegularCompressedData,
|
||||
|
||||
7
main.cc
7
main.cc
@@ -1,3 +1,4 @@
|
||||
#include <clocale>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
@@ -113,6 +114,8 @@ RunStressHighlighter(unsigned seconds)
|
||||
int
|
||||
main(int argc, const char *argv[])
|
||||
{
|
||||
std::setlocale(LC_ALL, "");
|
||||
|
||||
Editor editor;
|
||||
|
||||
// CLI parsing using getopt_long
|
||||
@@ -192,8 +195,6 @@ main(int argc, const char *argv[])
|
||||
} else if (req_term) {
|
||||
use_gui = false;
|
||||
} else {
|
||||
|
||||
|
||||
// Default depends on build target: kge defaults to GUI, kte to terminal
|
||||
#if defined(KTE_DEFAULT_GUI)
|
||||
use_gui = true;
|
||||
@@ -307,6 +308,8 @@ main(int argc, const char *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
Execute(editor, CommandId::CenterOnCursor);
|
||||
|
||||
bool running = true;
|
||||
while (running) {
|
||||
fe->Step(editor, running);
|
||||
|
||||
@@ -16,14 +16,18 @@ open .
|
||||
cd ..
|
||||
|
||||
mkdir -p cmake-build-release-qt
|
||||
cmake -S . -B cmake-build-release -DBUILD_GUI=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_ASAN=OFF
|
||||
cmake -S . -B cmake-build-release-qt -DBUILD_GUI=ON -DKTE_USE_QT=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_ASAN=OFF
|
||||
|
||||
cd cmake-build-release-qt
|
||||
make clean
|
||||
rm -fr kge.app* kge-qt.app*
|
||||
make
|
||||
mv kge.app kge-qt.app
|
||||
macdeployqt kge-qt.app -always-overwrite
|
||||
mv -f kge.app kge-qt.app
|
||||
# Use the same Qt's macdeployqt as used for building; ensure it overwrites in-bundle paths
|
||||
macdeployqt kge-qt.app -always-overwrite -verbose=3
|
||||
|
||||
# Run CMake BundleUtilities fixup to internalize non-Qt dylibs and rewrite install names
|
||||
cmake -DAPP_BUNDLE="$(pwd)/kge-qt.app" -P "${PWD%/*}/cmake/fix_bundle.cmake"
|
||||
zip -r kge-qt.app.zip kge-qt.app
|
||||
sha256sum kge-qt.app.zip
|
||||
open .
|
||||
|
||||
Reference in New Issue
Block a user