From 1fb189ad484774738a75a79f51a94d8cc34adde7 Mon Sep 17 00:00:00 2001 From: kake26 Date: Wed, 30 Apr 2025 11:55:24 -0500 Subject: [PATCH] Remove GTK3 version and update README with GTK3 port reference --- README.md | 4 + kpadgtk3.pl | 515 ---------------------------------------------------- 2 files changed, 4 insertions(+), 515 deletions(-) delete mode 100644 kpadgtk3.pl diff --git a/README.md b/README.md index 31bf7b8..428853c 100755 --- a/README.md +++ b/README.md @@ -2,3 +2,7 @@ Original Perl version of kpad. Please note this code is very old. It requires Perl and Perl/Tk to run. Works on any platform that can support those. Version 5.2.1 + +# Notes + +Ported to GTK3 see the GTK3 branch \ No newline at end of file diff --git a/kpadgtk3.pl b/kpadgtk3.pl deleted file mode 100644 index cc20793..0000000 --- a/kpadgtk3.pl +++ /dev/null @@ -1,515 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; -use Gtk3 '-init'; -use Glib qw(TRUE FALSE); -use File::Glob; -use FileHandle; -use LWP::Simple; -use Gtk3::SourceView; - -# Declare global variables -our $textbuffer; # SourceView buffer for the editor -our $textview; # SourceView widget -our $statusbar; # Status bar for feedback -our $open; # Current file path -our $track = 'init'; # Tracks modifications - -# Base directory setup (reused from your code) -my ($ar) = @ARGV; -my $basedir; -if ($^O ne "Win32") { - if ($0 =~ /\//g) { - my @hd = split "/", $0; - pop @hd; # Remove filename - $basedir = join('/', @hd) || "."; - } else { - $basedir = "."; - } -} else { - $basedir = "."; -} - -# Main window -my $window = Gtk3::Window->new('toplevel'); -$window->set_title('KPad'); -$window->set_default_size(800, 600); -$window->signal_connect(destroy => sub { Gtk3->main_quit }); - -# Main layout -my $vbox = Gtk3::Box->new('vertical', 0); -$window->add($vbox); - -# Menu bar -my $menubar = Gtk3::MenuBar->new; -$vbox->pack_start($menubar, FALSE, FALSE, 0); - -# File menu -my $file_menu = Gtk3::Menu->new; -my $file_item = Gtk3::MenuItem->new_with_label('File'); -$file_item->set_submenu($file_menu); -$menubar->append($file_item); - -my $new_item = Gtk3::MenuItem->new_with_label('New'); -$new_item->signal_connect(activate => sub { - $textbuffer->set_text(''); - $statusbar->push(0, 'New file'); -}); -$file_menu->append($new_item); - -my $open_item = Gtk3::MenuItem->new_with_label('Open'); -$open_item->signal_connect(activate => \&open_file); -$file_menu->append($open_item); - -my $save_item = Gtk3::MenuItem->new_with_label('Save'); -$save_item->signal_connect(activate => \&save_file); -$file_menu->append($save_item); - -my $save_as_item = Gtk3::MenuItem->new_with_label('Save As'); -$save_as_item->signal_connect(activate => \&save_as_file); -$file_menu->append($save_as_item); - -my $exit_item = Gtk3::MenuItem->new_with_label('Exit'); -$exit_item->signal_connect(activate => \&tapp); -$file_menu->append($exit_item); - -# Edit menu -my $edit_menu = Gtk3::Menu->new; -my $edit_item = Gtk3::MenuItem->new_with_label('Edit'); -$edit_item->set_submenu($edit_menu); -$menubar->append($edit_item); - -my $undo_item = Gtk3::MenuItem->new_with_label('Undo'); -$undo_item->signal_connect(activate => sub { - $textbuffer->undo if $textbuffer->can_undo; - $statusbar->push(0, 'Undo'); -}); -$edit_menu->append($undo_item); - -my $redo_item = Gtk3::MenuItem->new_with_label('Redo'); -$redo_item->signal_connect(activate => sub { - $textbuffer->redo if $textbuffer->can_redo; - $statusbar->push(0, 'Redo'); -}); -$edit_menu->append($redo_item); - -my $cut_item = Gtk3::MenuItem->new_with_label('Cut'); -$cut_item->signal_connect(activate => sub { - $textbuffer->cut_clipboard(Gtk3::Clipboard::get('CLIPBOARD'), TRUE); -}); -$edit_menu->append($cut_item); - -my $copy_item = Gtk3::MenuItem->new_with_label('Copy'); -$copy_item->signal_connect(activate => sub { - $textbuffer->copy_clipboard(Gtk3::Clipboard::get('CLIPBOARD')); -}); -$edit_menu->append($copy_item); - -my $paste_item = Gtk3::MenuItem->new_with_label('Paste'); -$paste_item->signal_connect(activate => sub { - $textbuffer->paste_clipboard(Gtk3::Clipboard::get('CLIPBOARD'), undef, TRUE); -}); -$edit_menu->append($paste_item); - -my $select_all_item = Gtk3::MenuItem->new_with_label('Select All'); -$select_all_item->signal_connect(activate => sub { - $textbuffer->select_range($textbuffer->get_start_iter, $textbuffer->get_end_iter); -}); -$edit_menu->append($select_all_item); - -my $find_item = Gtk3::MenuItem->new_with_label('Find'); -$find_item->signal_connect(activate => sub { find_and_replace_dialog(1); }); -$edit_menu->append($find_item); - -my $replace_item = Gtk3::MenuItem->new_with_label('Find and Replace'); -$replace_item->signal_connect(activate => sub { find_and_replace_dialog(0); }); -$edit_menu->append($replace_item); - -# View menu (wrap options) -my $view_menu = Gtk3::Menu->new; -my $view_item = Gtk3::MenuItem->new_with_label('View'); -$view_item->set_submenu($view_menu); -$menubar->append($view_item); - -my $wrap_menu = Gtk3::Menu->new; -my $wrap_item = Gtk3::MenuItem->new_with_label('Wrap'); -$wrap_item->set_submenu($wrap_menu); -$view_menu->append($wrap_item); - -my $wrap_word = Gtk3::CheckMenuItem->new_with_label('Word'); -$wrap_word->signal_connect(toggled => sub { - $textview->set_wrap_mode($wrap_word->get_active ? 'word' : 'none'); -}); -$wrap_menu->append($wrap_word); - -my $wrap_char = Gtk3::CheckMenuItem->new_with_label('Char'); -$wrap_char->signal_connect(toggled => sub { - $textview->set_wrap_mode($wrap_char->get_active ? 'char' : 'none'); -}); -$wrap_menu->append($wrap_char); - -my $wrap_none = Gtk3::CheckMenuItem->new_with_label('None'); -$wrap_none->signal_connect(toggled => sub { - $textview->set_wrap_mode($wrap_none->get_active ? 'none' : 'none'); -}); -$wrap_menu->append($wrap_none); - -# Tools menu -my $tools_menu = Gtk3::Menu->new; -my $tools_item = Gtk3::MenuItem->new_with_label('Tools'); -$tools_item->set_submenu($tools_menu); -$menubar->append($tools_item); - -my $goto_line_item = Gtk3::MenuItem->new_with_label('Goto Line'); -$goto_line_item->signal_connect(activate => \&goto_line_dialog); -$tools_menu->append($goto_line_item); - -my $which_line_item = Gtk3::MenuItem->new_with_label('Which Line?'); -$which_line_item->signal_connect(activate => \&which_line_dialog); -$tools_menu->append($which_line_item); - -# HTML menu -my $html_menu = Gtk3::Menu->new; -my $html_item = Gtk3::MenuItem->new_with_label('HTML'); -$html_item->set_submenu($html_menu); -$menubar->append($html_item); - -my $fetch_item = Gtk3::MenuItem->new_with_label('Fetch a web resource...'); -$fetch_item->signal_connect(activate => \&fetch_html); -$html_menu->append($fetch_item); - -# Macros menu (plugins) -my $macros_menu = Gtk3::Menu->new; -my $macros_item = Gtk3::MenuItem->new_with_label('Macros'); -$macros_item->set_submenu($macros_menu); -$menubar->append($macros_item); - -my $exec_macro_item = Gtk3::MenuItem->new_with_label('Execute Macro'); -$exec_macro_item->signal_connect(activate => \&show_plugin_dialog); -$macros_menu->append($exec_macro_item); - -# Help menu -my $help_menu = Gtk3::Menu->new; -my $help_item = Gtk3::MenuItem->new_with_label('Help'); -$help_item->set_submenu($help_menu); -$menubar->append($help_item); - -my $help_topics_item = Gtk3::MenuItem->new_with_label('Help Topics...'); -$help_topics_item->signal_connect(activate => sub { - my $dialog = Gtk3::MessageDialog->new($window, 'modal', 'info', 'ok', - "Help topics for KPAD\nWell, this is a text/file editor mainly meant for scripting and programming use.\nLike notepad but made for the programmer."); - $dialog->run; - $dialog->destroy; -}); -$help_menu->append($help_topics_item); - -my $about_item = Gtk3::MenuItem->new_with_label('About KPAD...'); -$about_item->signal_connect(activate => sub { - my $dialog = Gtk3::MessageDialog->new($window, 'modal', 'info', 'ok', - "kPad\nby Paul Malcher\nVersion 6 Release\n"); - $dialog->run; - $dialog->destroy; -}); -$help_menu->append($about_item); - -# Text view with SourceView -my $scrolled = Gtk3::ScrolledWindow->new(undef, undef); -$vbox->pack_start($scrolled, TRUE, TRUE, 0); -$textview = Gtk3::SourceView::View->new; -$textview->set_wrap_mode('word'); -$textview->set_show_line_numbers(TRUE); -$textview->set_auto_indent(TRUE); -$scrolled->add($textview); -$textbuffer = $textview->get_buffer; -my $lang_manager = Gtk3::SourceView::LanguageManager->get_default; -my $language = $lang_manager->get_language('perl'); -$textbuffer->set_language($language) if $language; -$textbuffer->set_highlight_syntax(TRUE); - -# CSS styling for Kubuntu -my $provider = Gtk3::CssProvider->new; -$provider->load_from_data(' - textview { font-family: Monospace; font-size: 12pt; } - button { color: black; background: #d3d3d3; } -'); -Gtk3::StyleContext::add_provider_for_screen( - Gtk3::Gdk::Screen::get_default, - $provider, - Gtk3::STYLE_PROVIDER_PRIORITY_APPLICATION -); - -# Status bar -$statusbar = Gtk3::Statusbar->new; -$vbox->pack_start($statusbar, FALSE, FALSE, 0); -$textbuffer->signal_connect('mark-set' => sub { - my ($buf, $iter, $mark) = @_; - if ($mark->get_name eq 'insert') { - my $line = $iter->get_line + 1; - $statusbar->push(0, "Line: $line"); - } -}); - -# Track modifications -$textbuffer->signal_connect('modified-changed' => sub { - $track = $textbuffer->get_text($textbuffer->get_start_iter, $textbuffer->get_end_iter, TRUE); -}); - -# Load file from ARGV -if ($ar) { - if (open my $fh, '<', $ar) { - local $/; - $textbuffer->set_text(<$fh>); - close $fh; - $statusbar->push(0, "Opened $ar"); - $open = $ar; - } else { - $statusbar->push(0, "Failed to open $ar"); - } -} - -# Plugin system -my @plugins; -my @n; -my $pls = 0; -while (<*.kpd>) { - push @plugins, $_; - open my $pin, '<', $_ or next; - my @gn = split '::', <$pin>; - $n[$pls] = $gn[2] eq 'auto' ? 'auto' : $gn[1]; - $pls++; -} -my $nop = grep { $_ ne 'auto' } @n; - -# File handling -sub open_file { - my $dialog = Gtk3::FileChooserDialog->new( - 'Open File', $window, 'open', - 'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok' - ); - $dialog->add_filter(Gtk3::FileFilter->new)->add_pattern('*.pl'); - $dialog->add_filter(Gtk3::FileFilter->new)->add_pattern('*'); - if ($dialog->run eq 'ok') { - my $filename = $dialog->get_filename; - if (open my $fh, '<', $filename) { - local $/; - $textbuffer->set_text(<$fh>); - close $fh; - $statusbar->push(0, "Opened $filename"); - $open = $filename; - } else { - $statusbar->push(0, "Failed to open $filename"); - } - } - $dialog->destroy; -} - -sub save_file { - if ($open) { - my ($start, $end) = $textbuffer->get_bounds; - my $text = $textbuffer->get_text($start, $end, TRUE); - if (open my $fh, '>', $open) { - print $fh $text; - close $fh; - $statusbar->push(0, "Saved $open"); - } else { - $statusbar->push(0, "Failed to save $open"); - } - } else { - save_as_file(); - } -} - -sub save_as_file { - my $dialog = Gtk3::FileChooserDialog->new( - 'Save File', $window, 'save', - 'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok' - ); - $dialog->add_filter(Gtk3::FileFilter->new)->add_pattern('*.pl'); - $dialog->add_filter(Gtk3::FileFilter->new)->add_pattern('*'); - if ($dialog->run eq 'ok') { - my $filename = $dialog->get_filename; - my ($start, $end) = $textbuffer->get_bounds; - my $text = $textbuffer->get_text($start, $end, TRUE); - if (open my $fh, '>', $filename) { - print $fh $text; - close $fh; - $statusbar->push(0, "Saved $filename"); - $open = $filename; - } else { - $statusbar->push(0, "Failed to save $filename"); - } - } - $dialog->destroy; -} - -# Find and replace dialog -sub find_and_replace_dialog { - my ($find_only) = @_; - my $dialog = Gtk3::Dialog->new($find_only ? 'Find' : 'Find and Replace', $window, 'modal', - 'gtk-ok', 'ok', 'gtk-cancel', 'cancel'); - my $find_entry = Gtk3::Entry->new; - my $replace_entry = Gtk3::Entry->new; - my $find_label = Gtk3::Label->new('Find:'); - $dialog->get_content_area->pack_start($find_label, FALSE, FALSE, 0); - $dialog->get_content_area->pack_start($find_entry, FALSE, FALSE, 0); - unless ($find_only) { - my $replace_label = Gtk3::Label->new('Replace with:'); - $dialog->get_content_area->pack_start($replace_label, FALSE, FALSE, 0); - $dialog->get_content_area->pack_start($replace_entry, FALSE, FALSE, 0); - } - $dialog->show_all; - if ($dialog->run eq 'ok') { - my $search = $find_entry->get_text; - my $replace = $replace_entry->get_text; - my $search_context = Gtk3::SourceView::SearchContext->new($textbuffer); - $search_context->set_search_text($search, []); - my $iter = $textbuffer->get_start_iter; - if (my ($match_start, $match_end) = $search_context->forward($iter)) { - $textbuffer->select_range($match_start, $match_end); - unless ($find_only) { - $search_context->replace($match_start, $match_end, $replace, -1); - $statusbar->push(0, "Replaced '$search' with '$replace'"); - } else { - $statusbar->push(0, "Found '$search'"); - } - } else { - $statusbar->push(0, "Text not found"); - } - } - $dialog->destroy; -} - -# Goto line dialog -sub goto_line_dialog { - my $dialog = Gtk3::Dialog->new('Goto Line', $window, 'modal', 'gtk-ok', 'ok', 'gtk-cancel', 'cancel'); - my $entry = Gtk3::Entry->new; - $dialog->get_content_area->pack_start($entry, FALSE, FALSE, 0); - $dialog->show_all; - if ($dialog->run eq 'ok') { - my $line = $entry->get_text; - if ($line =~ /^\d+$/) { - my $iter = $textbuffer->get_iter_at_line($line - 1); - $textbuffer->place_cursor($iter); - $textview->scroll_to_iter($iter, 0, TRUE, 0, 0.5); - } - } - $dialog->destroy; -} - -# Which line dialog -sub which_line_dialog { - my $iter = $textbuffer->get_iter_at_mark($textbuffer->get_insert); - my $line = $iter->get_line + 1; - my $dialog = Gtk3::MessageDialog->new($window, 'modal', 'info', 'ok', "Current line: $line"); - $dialog->run; - $dialog->destroy; -} - -# HTML fetch -sub fetch_html { - my $dialog = Gtk3::Dialog->new('HTML Source Fetch', $window, 'modal', 'gtk-ok', 'ok', 'gtk-cancel', 'cancel'); - my $label = Gtk3::Label->new('Fetch what:'); - my $entry = Gtk3::Entry->new; - $entry->set_text('http://'); - $dialog->get_content_area->pack_start($label, FALSE, FALSE, 0); - $dialog->get_content_area->pack_start($entry, FALSE, FALSE, 0); - $dialog->show_all; - if ($dialog->run eq 'ok') { - my $url = $entry->get_text; - my $contents = get($url); - if ($contents) { - $textbuffer->set_text($contents); - $statusbar->push(0, "Fetched $url"); - } else { - $statusbar->push(0, "Failed to fetch $url"); - } - } - $dialog->destroy; -} - -# Plugin dialog -sub show_plugin_dialog { - my $dialog = Gtk3::Dialog->new('Macro Execution Menu', $window, 'modal', 'gtk-close', 'close'); - my $label = Gtk3::Label->new('Double Click To Execute Macro'); - my $listbox = Gtk3::ListBox->new; - $dialog->get_content_area->pack_start($label, FALSE, FALSE, 0); - $dialog->get_content_area->pack_start($listbox, TRUE, TRUE, 0); - foreach my $name (@n) { - next if $name eq 'auto'; - my $row = Gtk3::ListBoxRow->new; - my $lbl = Gtk3::Label->new($name); - $row->add($lbl); - $listbox->add($row); - } - $listbox->signal_connect(row_activated => sub { - my ($lb, $row) = @_; - my $name = $row->get_child->get_text; - eplugin($name); - }); - $dialog->show_all; - $dialog->run; - $dialog->destroy; -} - -# Plugin execution -sub eplugin { - my ($v) = @_; - my $fp = 0; - while ($n[$fp] ne $v) { $fp++; } - $v = $plugins[$fp]; - open my $pe, '<', "$basedir/$v" or return; - my $tdata = do { local $/; <$pe> }; - close $pe; - $tdata =~ s/.*?\n//; # Skip first line - eval $tdata; - if ($@) { - my $error = $@; - my $dialog = Gtk3::MessageDialog->new($window, 'modal', 'error', 'ok', "Error: $error"); - $dialog->run; - $dialog->destroy; - } -} - -# Auto plugin execution -sub aeplugin { - for my $i (0..$#n) { - next unless $n[$i] eq 'auto'; - my $v = $plugins[$i]; - open my $pe, '<', "$basedir/$v" or next; - my $tdata = do { local $/; <$pe> }; - close $pe; - $tdata =~ s/.*?\n//; - eval $tdata; - if ($@) { - my $error = $@; - my $dialog = Gtk3::MessageDialog->new($window, 'modal', 'error', 'ok', "Error: $error"); - $dialog->run; - $dialog->destroy; - } - } -} - -# Shutdown handler -sub tapp { - if ($track ne 'init') { - my $dialog = Gtk3::MessageDialog->new( - $window, 'modal', 'question', 'yes-no', 'File contents have changed, save now?!' - ); - my $response = $dialog->run; - $dialog->destroy; - if ($response eq 'yes') { - save_file(); - } - } - Gtk3->main_quit; -} - -# Run auto plugins -my $arun = 0; -if ($arun eq '0') { - aeplugin(); -} - -# Show and start -$window->show_all; -Gtk3->main; \ No newline at end of file