@@ -739,6 +739,75 @@ void EditorApp::clear_bookmarks() {
739739 tabs_[active_tab_].bookmarks .clear ();
740740}
741741
742+ // ============================================================================
743+ // Code Folding
744+ // ============================================================================
745+ void EditorApp::toggle_fold (int line) {
746+ if (active_tab_ < 0 || active_tab_ >= (int )tabs_.size ()) return ;
747+ auto & folds = tabs_[active_tab_].folds ;
748+
749+ // Check if there's already a fold starting at this line
750+ for (auto it = folds.begin (); it != folds.end (); ++it) {
751+ if (it->first == line) {
752+ folds.erase (it);
753+ return ;
754+ }
755+ }
756+
757+ // Find matching closing brace
758+ auto & editor = *tabs_[active_tab_].editor ;
759+ int total_lines = editor.GetTotalLines ();
760+ int brace_count = 0 ;
761+ int end_line = line;
762+
763+ for (int i = line; i < total_lines; i++) {
764+ std::string text = editor.GetTextLines ()[i];
765+ for (char c : text) {
766+ if (c == ' {' ) brace_count++;
767+ else if (c == ' }' ) brace_count--;
768+ }
769+ if (brace_count <= 0 && i > line) {
770+ end_line = i;
771+ break ;
772+ }
773+ }
774+
775+ if (end_line > line) {
776+ folds.push_back ({line, end_line});
777+ }
778+ }
779+
780+ void EditorApp::fold_all () {
781+ if (active_tab_ < 0 || active_tab_ >= (int )tabs_.size ()) return ;
782+ auto & tab = tabs_[active_tab_];
783+ tab.folds .clear ();
784+
785+ auto & editor = *tab.editor ;
786+ auto & lines = editor.GetTextLines ();
787+ int brace_count = 0 ;
788+ int fold_start = -1 ;
789+
790+ for (int i = 0 ; i < (int )lines.size (); i++) {
791+ for (char c : lines[i]) {
792+ if (c == ' {' ) {
793+ if (brace_count == 0 ) fold_start = i;
794+ brace_count++;
795+ } else if (c == ' }' ) {
796+ brace_count--;
797+ if (brace_count == 0 && fold_start >= 0 && i > fold_start) {
798+ tab.folds .push_back ({fold_start, i});
799+ fold_start = -1 ;
800+ }
801+ }
802+ }
803+ }
804+ }
805+
806+ void EditorApp::unfold_all () {
807+ if (active_tab_ < 0 || active_tab_ >= (int )tabs_.size ()) return ;
808+ tabs_[active_tab_].folds .clear ();
809+ }
810+
742811// ============================================================================
743812// Change History
744813// ============================================================================
@@ -773,10 +842,10 @@ void EditorApp::load_fonts() {
773842
774843 ImFont* font = nullptr ;
775844
776- // Try to load user-selected font
845+ // Try to load user-selected font (prefer .ttf for better compatibility)
777846 if (!settings_.font_name .empty ()) {
778847 #ifdef _WIN32
779- std::vector<std::string> exts = {" .ttc " , " .ttf " , " .otf " };
848+ std::vector<std::string> exts = {" .ttf " , " .otf " , " .ttc " }; // Try ttf first
780849 for (const auto & ext : exts) {
781850 std::string path = " C:/Windows/Fonts/" + settings_.font_name + ext;
782851 font = io.Fonts ->AddFontFromFileTTF (path.c_str (), (float )settings_.font_size );
@@ -785,7 +854,7 @@ void EditorApp::load_fonts() {
785854 #endif
786855 }
787856
788- // Fallback to default
857+ // Fallback to built-in default (not system font)
789858 if (!font) {
790859 font = io.Fonts ->AddFontDefault ();
791860 // Clear font name since we couldn't load the requested one
@@ -810,10 +879,10 @@ void EditorApp::rebuild_fonts() {
810879
811880 ImFont* font = nullptr ;
812881
813- // Try to load user-selected font
882+ // Try to load user-selected font (prefer .ttf for better compatibility)
814883 if (!font_name_temp_.empty ()) {
815884 #ifdef _WIN32
816- std::vector<std::string> exts = {" .ttc " , " .ttf " , " .otf " };
885+ std::vector<std::string> exts = {" .ttf " , " .otf " , " .ttc " };
817886 for (const auto & ext : exts) {
818887 std::string path = " C:/Windows/Fonts/" + font_name_temp_ + ext;
819888 font = io.Fonts ->AddFontFromFileTTF (path.c_str (), (float )settings_.font_size );
@@ -826,7 +895,7 @@ void EditorApp::rebuild_fonts() {
826895 #endif
827896 }
828897
829- // Fallback to default if couldn't load
898+ // Fallback to built-in default if couldn't load
830899 if (!font) {
831900 font = io.Fonts ->AddFontDefault ();
832901 // Clear - couldn't load the requested font
@@ -1076,17 +1145,29 @@ void EditorApp::render_menu_view() {
10761145 if (ImGui::MenuItem (" Line Numbers" , nullptr , &ln)) toggle_line_numbers ();
10771146 bool sp = settings_.show_spaces ;
10781147 if (ImGui::MenuItem (" Show Spaces" , nullptr , &sp)) toggle_spaces ();
1079- ImGui::Separator ();
1148+ ImGui::Separator ();
10801149 if (ImGui::BeginMenu (" Spaces" )) {
10811150 if (ImGui::MenuItem (" 2 Spaces" , nullptr , settings_.tab_size == 2 )) set_tab_size (2 );
10821151 if (ImGui::MenuItem (" 4 Spaces" , nullptr , settings_.tab_size == 4 )) set_tab_size (4 );
10831152 if (ImGui::MenuItem (" 8 Spaces" , nullptr , settings_.tab_size == 8 )) set_tab_size (8 );
1084- if (ImGui::MenuItem (" Custom..." )) { show_spaces_ = true ; tab_size_temp_ = settings_.tab_size ; }
1153+ if (ImGui::MenuItem (" Custom..." )) { show_spaces_dialog_ = true ; tab_size_temp_ = settings_.tab_size ; }
1154+ ImGui::EndMenu ();
1155+ }
1156+ ImGui::Separator ();
1157+ if (ImGui::BeginMenu (" Code Folding" )) {
1158+ if (ImGui::MenuItem (" Fold All" , " Ctrl+Shift+[" )) fold_all ();
1159+ if (ImGui::MenuItem (" Unfold All" , " Ctrl+Shift+]" )) unfold_all ();
1160+ if (ImGui::MenuItem (" Toggle Fold" , " Ctrl+[" )) {
1161+ if (active_tab_ >= 0 && active_tab_ < (int )tabs_.size ()) {
1162+ auto pos = tabs_[active_tab_].editor ->GetCursorPosition ();
1163+ toggle_fold (pos.mLine );
1164+ }
1165+ }
10851166 ImGui::EndMenu ();
10861167 }
10871168 ImGui::Separator ();
10881169 if (ImGui::MenuItem (settings_.dark_theme ? " Light Theme" : " Dark Theme" )) toggle_theme ();
1089- ImGui::EndMenu ();
1170+ ImGui::EndMenu ();
10901171 }
10911172}
10921173
0 commit comments