#!/usr/bin/perl # gPad TEXT-file editor ALPHA4 : raimo 20060318 -> 20072011.2 look *X # http://gpad.uhvo.org/ ################ Under construction, NOT SAFE YET! ################ # license, CC NC-SA: http://creativecommons.org/licenses/nc-sa/1.0/ # # 1. INSTALL REQUIRED LIBS: libgtk2-perl libgtk2-sourceview-perl libgnome2-print-perl # # sudo apt-get install libgtk2-perl libgtk2-sourceview-perl libgnome2-print-perl # # 2. INSTALL gPad: # wget -O ~/gpad.txt http://uhvo.org/sec/gpad.txt # sudo cp -i ~/gpad.txt /usr/bin/gpad # sudo chmod 755 /usr/bin/gpad # gpad # # RUN: gpad and SET SETTINGS, select from menu: Settings -> Preferencens # Set Gtk-settings (fonts and colors) with: Settings -> Gtk settings # Restart gPad after settings changed: Settings -> Restart gpad # # USER SETTINGS are in ~/.gpad/gpadrc file, look defaults in *0 # GTK SETTINGS are in ~/.gpad/gpad-gtkrc file, look defaults in *0 # Reset settings by removing both files and (re)starting gPad # # Usage: gpad [FILENAME] [ARGS] # Look help: gpad --help # # Auto-FTP is very highly supposed, please get it: # wget http://uhvo.org/sec/auto-ftp.txt # ################## DO NOT EDIT BELOW OF THIS LINE #################### my $license = "http://creativecommons.org/licenses/nc-sa/1.0/"; use strict; use Gtk2 "-init"; # libgtk2-perl use Gtk2::Gdk::Keysyms; use Gtk2::SourceView; # libgtk2-sourceview-perl libgnome2-print-perl use Encode; # for Gtk2 UTF-8 bugfix, look *6 use File::Copy; use HTML::Entities; sub open_file; # dev remove or add all *? 0105 my $user = $ENV{"USER"}; # dev remove my $home = $ENV{"HOME"}; my $pwd = $ENV{"PWD"}; my $name = $0; $name =~ s/^.*\///; my $vers = 20072011.2; my $url = "http://gpad.uhvo.org"; my $dir = "$home/.$name"; my $backup = "$home/$name-crash-backup~"; # auto-backup file my $ftpprf = "$home/.auto-ftp"; # auto-ftp profile dir my $set1file = "$dir/gpadrc"; # USER settings my $set2file = "$dir/gpad-gtkrc"; # GtkRC settings my $ftpready = 1; # Auto-FTP mark, do not change my $status = "not-done"; # auto-backup status mark, do not change my $forcelang = ""; # force highlight, do not use # dev remove my $transfer = 0; # auto-ftp message mark my $silent = 2; # message-level, over 2 = almost full silent my $autoftp = 0; # 0/1 automatic FTP with Ctrl+S OFF/ON by default # dev move these to def-settings our $dobackup = 1; # 0/1 create file~ backups before saving our $rmbackup = 1; # 0/1 remove backup files on close, *not in use yet our $tabwidth = 8; # TAB-width, marks our $smartkeys = 0; # 0/1 "smart" home and end keys our $tabtospace = 1; # 0/1 tabs to spaces our $wrap = "none"; # Word wrap, "none", "char" or "word" my $main = 1; # force normal main loop, (no auto-ftp or crash-backup) # dev remove our $menumode = "full-menu"; # View -> Highlight menu modes, "simple-menu" or "full-menu" my $globalresp; my ($entry, @files, @session, $lastkey, $profile, @langs, $ftpM); our ($browser, $terminal, $fm, $wdth, $hght, $mode, $lm, $rm, $nums, $margin, $markers, $autoindent, $highlight, $recent, $cftp, $commandline, $undolevel, $lastmem, $tabpos, $fullscreen, $menufont, $codefont, $style, %mimes); exit print &help if grep/^-h$|^--help$|^-v$|^--version$/, @ARGV; # INSTALLATION AND SETTINGS CHECK &install; # USER SETTINGS $dir/gpadrc eval do "$set1file" if -f "$set1file" && -s "$set1file" > 10; &fix_gtk; # fixing Gtk-font-size # GTK SETTINGS $dir/gpad-gtkrc eval do "$set2file" if -f "$set2file" && # look GtkRc -s "$set2file" > 10; $undolevel = 2 if $undolevel < 2; # dev remove my $about = < new("toplevel"); my $scroll = Gtk2::ScrolledWindow -> new(undef, undef); my $combo = Gtk2::Combo -> new; my $entry = $combo -> entry; my $hbox0 = Gtk2::HBox -> new; # commandlinebox my $tabs = Gtk2::Notebook -> new; $tabs -> signal_connect("switch-page", sub{&change_tab}); $tabs -> signal_connect("button-release-event" => sub{&pop_up}); #$tabs -> popup_enable; # disabled by own popup-menu #my $buffer = Gtk2::SourceView::Buffer -> new(undef); # dev remove #$buffer -> set_max_undo_levels($undolevel); # dev remove ## MAIN PLUGIN eval do "$dir/main-plugin" if -f "$dir/main-plugin"; ## CRASH-RESTORE-ENGINE (THIS THING is NOT crashing, but if crashed by USER) ;) if (-f $backup && $file ne "$backup.bu"){ &dialog("warning", "ok", "CRASH-BACKUP file found, opening in different window.."); copy $backup, "$backup.bu"; # FINAL-CHANGE-TO-RESTORE system("$0 $backup.bu --new &"); # CRASH-BACKUP auto-restore } $file = "untitled" if !$file && $file != 0; # WTF? 0105 # $buffer -> set_modified(0); # dev remove ## WINDOW ONE (and only) $window -> set_default_icon_name("gtk-edit"); $window -> set_title("$name: $file"); $window -> resize($wdth, $hght); $window -> set_resizable(1); $window -> set_keep_above(1) if grep/^--ontop$/, @ARGV; $window -> fullscreen if $fullscreen == 1; $window -> set_position("center"); # dev try center or center-on-parent, not center-always 0105 $window -> set_position("center-on-parent") if grep/^--new$/, @ARGV; # OK 0105 $window -> signal_connect(delete_event => sub{$globalresp = "none"; # fix 0107.2 &save_session; &quit}); $window -> signal_connect(destroy => \&quit); # dev fix this, missing window on out *! 0105 $window -> signal_connect("key-press-event" => \&check_keys); # main keys $window -> signal_connect("key-release-event" => sub{$lastkey = undef}); ## MAIN MENU my $main = Gtk2::MenuBar -> new; my $fileM = Gtk2::Menu -> new; # File menu my $editM = Gtk2::Menu -> new; # Edit menu my $toolM = Gtk2::Menu -> new; # Tools menu my $viewM = Gtk2::Menu -> new; # View menu my $settM = Gtk2::Menu -> new; # Settings menu my $helpM = Gtk2::Menu -> new; # Help menu my $menu0 = Gtk2::MenuItem -> new(" File"); my $menu1 = Gtk2::MenuItem -> new("Edit"); my $menu2 = Gtk2::MenuItem -> new("Tools"); my $menu3 = Gtk2::MenuItem -> new("Run"); my $menuV = Gtk2::MenuItem -> new("View"); my $menu4 = Gtk2::MenuItem -> new("Settings"); my $menu5 = Gtk2::MenuItem -> new(" Help "); ## TABS POPUP my $popup = Gtk2::Menu -> new; $popup -> append(my $popu1 = Gtk2::MenuItem -> new ("_New tab Ctrl+T")); $popup -> append(my $popu2 = Gtk2::MenuItem -> new ("_Copy tab")); $popup -> append(my $popu3 = Gtk2::MenuItem -> new("_Save tab Ctrl+S")); $popup -> append(Gtk2::SeparatorMenuItem -> new); $popup -> append(my $popu4 = Gtk2::MenuItem -> new("_Close tab Ctrl+W")); $popu1 -> signal_connect("activate" => sub{&new_tab("untitled")}); $popu2 -> signal_connect("activate" => sub{©_tab()}); $popu3 -> signal_connect("activate" => sub{&save_file($file)}); $popu4 -> signal_connect("activate" => sub{$globalresp = "none"; &close_tab}); $popup -> show_all; ## FILE MENU my $accel2 = Gtk2::AccelGroup -> new; $accel2 -> connect(116, ["control-mask"], ["visible"], sub {&new_tab("untitled")}); $accel2 -> connect(119, ["control-mask"], ["visible"], sub {&close_tab("untitled")}); $window -> add_accel_group($accel2); my $accel = Gtk2::AccelGroup -> new; $fileM -> append(Gtk2::TearoffMenuItem -> new); # cool! ;) $fileM -> append(my $menu00 = Gtk2::ImageMenuItem -> new_from_stock("gtk-new", $accel)); $fileM -> append(my $menu01 = Gtk2::MenuItem -> new(" New window ")); $fileM -> append(my $menu0D = Gtk2::MenuItem -> new(" Templates ")); #submenu $fileM -> append(Gtk2::SeparatorMenuItem -> new); $fileM -> append(my $menu0X = Gtk2::MenuItem -> new(" Close tab ")); $fileM -> append(Gtk2::SeparatorMenuItem -> new); $fileM -> append(my $menu02 = Gtk2::ImageMenuItem -> new_from_stock("gtk-open", $accel)); $fileM -> append(my $menu03 = Gtk2::MenuItem -> new(" Recent files ")); $fileM -> append(my $menu0A = Gtk2::MenuItem -> new(" Open Location ")); $fileM -> append(Gtk2::SeparatorMenuItem -> new); $fileM -> append(my $menu0B = Gtk2::MenuItem -> new(" Sessions ")); $fileM -> append(Gtk2::SeparatorMenuItem -> new); $fileM -> append(my $menu04 = Gtk2::ImageMenuItem -> new_from_stock("gtk-save", $accel)); $fileM -> append(my $menu05 = Gtk2::ImageMenuItem -> new_from_stock("gtk-save-as", $accel)); $fileM -> append(my $menu0C = Gtk2::MenuItem -> new("Save copy as")); $fileM -> append(my $menu06 = Gtk2::MenuItem -> new(" FTP-out ")); $fileM -> append(Gtk2::SeparatorMenuItem -> new); $fileM -> append(my $menu07 = Gtk2::ImageMenuItem -> new_from_stock("gtk-quit", $accel)); $menu00 -> signal_connect("activate" => sub{&new_tab("untitled")}); $menu0X -> signal_connect("activate" => sub{$globalresp = "none"; &close_tab}); $menu01 -> signal_connect("activate" => sub{system("$0 --new &")}); $menu02 -> signal_connect("activate" => sub{&file_dialog("open")}); $menu0A -> signal_connect("activate" => sub{&open_location}); $menu04 -> signal_connect("activate" => sub{&save_file($file)}); $menu0C -> signal_connect("activate" => sub{&file_dialog("save-copy")}); $menu05 -> signal_connect("activate" => sub{&file_dialog("save")}); $menu07 -> signal_connect("activate" => sub{$globalresp = "none"; &save_session; &quit}); ## SESSIONS SUBMENU my $sessM = &sessions_sub; ## EDIT MENU $editM -> append(my $menu11 = Gtk2::ImageMenuItem -> new_from_stock("gtk-undo", $accel)); $editM -> append(my $menu12 = Gtk2::ImageMenuItem -> new_from_stock("gtk-redo", $accel)); $editM -> append(Gtk2::SeparatorMenuItem -> new); $editM -> append(my $menu13 = Gtk2::ImageMenuItem -> new_from_stock("gtk-copy", $accel)); $editM -> append(my $menu14 = Gtk2::ImageMenuItem -> new_from_stock("gtk-paste", $accel)); $editM -> append(my $menu1A = Gtk2::MenuItem -> new("Paste to new")); $editM -> append(Gtk2::SeparatorMenuItem -> new); $editM -> append(my $menu15 = Gtk2::ImageMenuItem -> new_from_stock("gtk-cut", $accel)); $editM -> append(Gtk2::SeparatorMenuItem -> new); $editM -> append(my $menu1B = Gtk2::ImageMenuItem -> new_from_stock("gtk-find", $accel)); $editM -> append(my $menu16 = Gtk2::MenuItem -> new("Replace special")); # submenu $editM -> append(Gtk2::SeparatorMenuItem -> new); $editM -> append(my $menu17 = Gtk2::ImageMenuItem -> new_from_stock("gtk-select-all", $accel)); $editM -> append(Gtk2::SeparatorMenuItem -> new); $editM -> append(my $menu18 = Gtk2::ImageMenuItem -> new_from_stock("gtk-preferences", $accel)); $menu11 -> signal_connect("activate" => sub{&undo}); $menu12 -> signal_connect("activate" => sub{&redo}); $menu13 -> signal_connect("activate" => sub{&clipboard("copy")}); $menu14 -> signal_connect("activate" => sub{&clipboard("paste")}); $menu1A -> signal_connect("activate" => sub{&new_tab("untitled"); &clipboard("paste"); &get_buffer -> set_modified(1)}); $menu15 -> signal_connect("activate" => sub{&clipboard("cut")}); $menu1B -> signal_connect("activate" => sub{&find_dialog}); $menu17 -> signal_connect("activate" => sub{&select_all}); $menu18 -> signal_connect("activate" => sub{&open_file($set1file, "check")}); ## TOOLS MENU &tools_menu($toolM); # dev is this funny? why not $toolM = &tools_menu ? :) eval do "$dir/tools-menu.plugin" if -f "$dir/tools-menu.plugin"; ## RUN MENU my $runeM = &run_menu; eval do "$dir/run-menu.plugin" if -f "$dir/run-menu.plugin"; ## VIEW MENU $viewM -> append(my $menu7D = Gtk2::MenuItem -> new("Cursor")); $viewM -> append(my $menu7A = Gtk2::MenuItem -> new("Current info")); $viewM -> append(my $menu7B = Gtk2::MenuItem -> new("Highlight")); # submenu $viewM -> append(my $menu7C = Gtk2::MenuItem -> new("Tab position")); $viewM -> append(my $menu70 = Gtk2::CheckMenuItem -> new("Command-line ")); $viewM -> append(my $menu71 = Gtk2::ImageMenuItem -> new_from_stock("gtk-fullscreen", $accel)); $menu70 -> set_active(1) if $commandline == 1; $menu7D -> signal_connect("activate" => sub{&get_viewer -> place_cursor_onscreen if &get_viewer}); # TEST, dev remove $menu7A -> signal_connect("activate" => sub{&dialog("info", "ok", &view_info)}); $menu7C -> signal_connect("activate" => \&toggle_tabs); $menu70 -> signal_connect("activate" => \&show_hide_commandline); $menu71 -> signal_connect("activate" => sub{&toggle_fullscreen}); ## SETTINGS MENU $settM -> append(my $menu21 = Gtk2::ImageMenuItem -> new_from_stock("gtk-preferences", $accel)); $settM -> append(my $menu22 = Gtk2::MenuItem -> new(" Gtk settings ")); $settM -> append(Gtk2::SeparatorMenuItem -> new); $settM -> append(my $menu2B = Gtk2::MenuItem -> new(" Reset settings ")); $settM -> append(Gtk2::SeparatorMenuItem -> new); $settM -> append(my $menu23 = Gtk2::MenuItem -> new(" View \u$name source ")); $settM -> append(my $menu2A = Gtk2::MenuItem -> new(" Open ~/.$name dir ")); $settM -> append(Gtk2::SeparatorMenuItem -> new); $settM -> append(my $menu24 = Gtk2::MenuItem -> new(" Restart \u$name ")); $menu21 -> signal_connect("activate" => sub{&open_file($set1file, "check")}); $menu22 -> signal_connect("activate" => sub{&open_file($set2file, "check")}); $menu2A -> signal_connect("activate" => sub{&run("$fm $dir")}); $menu2B -> signal_connect("activate" => sub{&reset_settings}); $menu23 -> signal_connect("activate" => sub{&open_file("$0", "check")}); $menu24 -> signal_connect("activate" => sub{&save_session; &ask_save; system("$0 &"); $window -> destroy}); ## HELP MENU $helpM -> append(my $menu51 = Gtk2::MenuItem -> new(" Help ")); $helpM -> append(my $menu52 = Gtk2::MenuItem -> new(" Internet ")); $helpM -> append(my $menu53 = Gtk2::MenuItem -> new(" About ")); $menu51 -> signal_connect("activate" => sub{&dialog("info", "ok", &help)}); $menu52 -> signal_connect("activate" => sub{&run("$browser $url")}); $menu53 -> signal_connect("activate" => sub{&dialog("info", "ok", $about)}); ## SUBMENU STUFF $menu03 -> set_submenu(&recent_files("", "read")); # recent files submenu $menu0D -> set_submenu(&templates); # templates submenu $menu06 -> set_submenu(&ftp_profiles) if -e $ftpprf; # ftp profiles submenu $menu16 -> set_submenu(&replace); # replace submenu $menu0B -> set_submenu($sessM); # session submenu $menu7B -> set_submenu(&high_light($menumode)); # highlight submenu # ADD TO MAIN MENUBAR $menu0 -> set_submenu($fileM); $menu1 -> set_submenu($editM); $menu2 -> set_submenu($toolM); $menu3 -> set_submenu($runeM); $menuV -> set_submenu($viewM); $menu4 -> set_submenu($settM); $menu5 -> set_submenu($helpM); # ADD TO MAIN MENUBAR $main -> append($menu0); # File menu $main -> append($menu1); # Edit menu $main -> append($menu2); # Tools menu $main -> append($menu3); # Run menu $main -> append($menuV); # View menu $main -> append($menu4); # Settings menu $main -> append($menu5); # Help menu $scroll -> set_policy("automatic", "always"); # fixed 20061230 # $scroll -> signal_connect("" => sub{}); ## MENU PLUGIN THINGS eval do "$home/.gpad/main-menu-plugin" if -f "$home/.gpad/main-menu-plugin"; ## PACKING $window -> add(&package); #$vbox0 -> show; # speed-up? # check this *0 my $run = 1; # ready-to-rock-mark ## PUSH LAST SESSION UP if ($lastmem == 1 && @files){ while(<@files>){ next if !-f $_; &open_file($_, "no-check"); # dev check that "check" *! 0105 -> *OK 0107.3 } } ## ADD multiple files here *0107.4 -> test it *0108.1, fix to single-open if already open 0111 while(<@ARGV>){ &open_file($_, "check") if -f $_ && $_ !~ m/--/g; # 2nd not needed? *101 -T bug in Perl 0112.1 } # &open_file($ARGV[0], "check") if -f $ARGV[0]; # bugfix 0107.3, removed 0108.1 $window -> show_all; $hbox0 -> hide_all if ($commandline == 0); ## MAIN LOOP my $mem; # time-memory for loop my $counter = 0; # resource check counter, dev remove if((grep/^--main$/, @ARGV) || $main == 1){ # check this *0 warn "NORMAL LOOP\n"; Gtk2 -> main; }else{ warn "AUTO-LOOP\n"; Gtk2 -> main_iteration while(&loop == 1); #HAHA! Am I good or not? ;D *10 } Gtk2 -> main_quit; exit 0; ## SUB LOOP (main_iteration hoax-loop) sub loop{ # *10 my $time = time; $counter++; # dev remove if ($time > $mem + 5){ #my $xbuffer = &get_buffer; # dev check this *! FIX FIX FIX! 0105 $ftpready = 1 if !-f "$home/.auto-ftp.lock"; # Auto-FTP ready-to-rock-again mark if (-f "$home/.auto-ftp.msg" && $transfer == 1){ # show transfer status-message open FILE, "< $home/.auto-ftp.msg"; my @xinfo = ; close FILE; unlink "$home/.auto-ftp.msg"; print "MESSAGE FROM AUTO-FTP:\n@xinfo"; # dev remove &info("@xinfo"); # do not remove " -marks $transfer = 0; } #return $run if $buffer -> get_modified == 0 || # dev FIX this to local buffer *! 0105 # $status eq "done"; # no backup needed *! # &auto_backup($tview); # CHECK 0112 print "LOOP: $counter FILE: $file\n"; # dev remove $mem = $time; $counter = 0; # dev remove } return $run; # run while 1 } exit 0; ############################## SUBS ################################### ### POP UP sub pop_up{ my($widget, $event, undef) = @_; my $ear = $event -> button(); $popup -> popup(undef, undef, undef, undef, 0, 0) if $ear == 3; &close_tab if $ear == 2; } ### RUN (for cool internal commandline) sub run{ my $task = shift; return dialog("info", "ok", "Nothing to do?") if !$task; return dialog("warning", "ok", "Canceled, " . "NOT SAFE command:\n$task") if grep/^rm|^sudo|unlink/, $task; if ($task =~ m/^:/){ $task =~ s/^\://; &close_all if $task eq "close-all"; &close_tab if $task eq "close"; &new_tab if $task eq "new"; &file_dialog("open") if $task eq "open"; &save_file($file) if $task eq "save"; &file_dialog("save") if $task eq "save-as"; &quit if $task eq "quit" || $task eq "q"; } else { return &error("Not safe command $task") if grep/^sudo |rm |unlink /, $task; system("$task &"); } open FILE, "< $dir/run.list"; my @list = ; close FILE; if (!grep/$task/, @list){ open FILE, ">> $dir/run.list"; flock FILE, 2; print FILE "$task\n"; close FILE; } &read_run_list; # update combo return 0; } ### RUN_EX (for Run -> Execute ) sub run_ex{ copy $file, "$dir/filetmp.run"; chmod 0755, "$dir/filetmp.run"; open FILE, "> $dir/tmp.run"; flock FILE, 2; print FILE "#!/bin/sh\n\n"; print FILE "# $name run-file, this file can be removed at any time.\n\n"; print FILE "\$($dir/filetmp.run &)\n\n"; print FILE "echo Press Any Key to close shell\n\n"; print FILE "exit 0\n\n"; close FILE; system("sh $dir/tmp.run &"); $window -> activate; return 0; } ### MESSAGE DIALOG sub dialog{ my ($mode, $button, $msg) = @_; my $dialog = Gtk2::MessageDialog -> new($window, [qw/modal destroy-with-parent/], #$mode, $button, decode("utf8", $msg)); # removed 0328.2 $mode, $button, $msg); my $response = $dialog -> run; $dialog -> destroy; return $response; } ### FIND DIALOG sub find_dialog{ my $word = shift; my $dialog = Gtk2::Dialog -> new ("Find", $window, [qw/modal destroy-with-parent/], "gtk-cancel" => "cancel", "gtk-find" => 2); my $entry = Gtk2::Entry -> new(); $entry -> set_text($word) if !grep /HASH\(/, $word; $dialog -> vbox -> add ($entry); $dialog -> show_all; my $response = $dialog -> run; if ($response == 2){ &search_buffer($entry -> get_text, "next"); $dialog -> destroy; &find_dialog($entry-> get_text); } $dialog -> destroy; } ### SEARCH_BUFFER sub search_buffer { my($text, $direction) = shift; print $direction; my $cont = &get_buffer -> get_text(&get_buffer -> get_start_iter, &get_buffer -> get_end_iter, 0); my $start_index = 0; # if ($direction == 2){ print "JAHUU"; my $mark = &get_buffer -> get_selection_bound; my $iter = &get_buffer -> get_iter_at_mark($mark); print $iter -> get_offset, "\n"; $start_index = $iter -> get_offset; $start_index = $start_index + length $text; #} my $start = index ($cont, $text, $start_index); return if $start == -1; #print "start: $start\n"; my $start_iter = &get_buffer -> get_iter_at_offset($start); my $end_iter = &get_buffer -> get_iter_at_offset($start+length($text)); &get_buffer -> select_range($start_iter, $end_iter); #$textview->scroll_to_iter($start_iter, 0.4, 1, 0.0, 0.0); my $mark = &get_buffer -> create_mark("xxx", $start_iter, 1); &get_viewer -> scroll_to_mark($mark, 0.4, 1, 0.5, 0.5); } ### FILE DIALOG (open, save + sessions and templates) sub file_dialog{ my $mode = shift; my $tmpmode = $mode; $mode = "open" if $tmpmode eq "open-session"; $mode = "save" if $tmpmode =~ m/^save-.*$/g; print "MODE: $mode\n"; my $dialog = Gtk2::FileChooserDialog -> new("\u$mode file", $window, "$mode", "gtk-cancel" => "cancel", "gtk-ok" => "ok"); $dialog -> set_filename($file) if $mode ne "save" && -f $file; # dev fixed, check 0105 $dialog -> set_do_overwrite_confirmation(1) if $mode eq "save"; # dev fixed, look *203 $dialog -> set_select_multiple(0); # $dialog -> set_preview_widget_active(1); # $dialog -> set_show_hidden(1); # dev, think this *-1 if ($tmpmode eq "save-session" || $tmpmode eq "open-session"){ # dev, fixed FileChooser set_current_folder $dialog -> set_filename("$dir/sessions"); # bug in FC's file open mode *OK now, 0105 $dialog -> set_current_folder("$dir/sessions"); # This will crash to SegFault if set_filename is NOT first. } $dialog -> set_current_folder("$dir/templates") # no bugs in save mode here if $tmpmode eq "save-template"; my $response = $dialog -> run; my $xfile = $dialog -> get_filename if $dialog -> get_filename; $dialog -> destroy; return $response if $response ne "ok"; # Cancel pressed return $xfile if $tmpmode =~ m/-session$/; # Session open/save stuff return 0 if &is_open($xfile) ne "can-open"; # No dublicates 0107.2 $file = $xfile if $xfile && $tmpmode ne "save-copy"; &recent_files($file, 2); # fixed 0105, check *204 return &open_file($file, "check") if ($mode eq "open"); # Open file mode &check_uid(&basedir($file)); # Check is write allowed here return &save_file($xfile) if $tmpmode eq "save-copy"; # dev THIS 0105 -> 0107 &save_file($file); # Save file mode &set_tab($file); &recent_files($file, 2); # dev check and FIX this *0 -> 0105 *! -> OK? *204 $window -> activate; # dev check if not needed 0105 return 0; # $buffer -> set_modified(0); # CHECK return 0112.1 } ### SET LANG ## FIX HTML URGENT! sub set_lang{ # dev this sometime :) my ($mode, $xmode, $xfile) = @_; my @html = (qw/html shtml xhtml/); my @perl = (qw/pl pm/); my @php = (qw/php php3 php4 php5/); if ($forcelang){ # --lang from command-line $mode = $forcelang; $xmode = !$xmode; } ### fixed bug if path includes . mark 20072011 *8 my $ext = $xfile; $ext =~ s/.*\///; (my $trash, my $ext) = split/\./, $ext; if (!$xmode){ # dev remove this THING! print "LANG-AUTO $ext\n"; # stable remove $mode = "text/css" if $mode eq "css" || $ext eq "css"; $mode = "application/x-sh" if $mode eq "sh" || $ext eq "sh"; $mode = "text/html" if $mode eq "html" || (grep/^$ext$/, @html); # test 0112, not working -> *7 #$mode = "text/x-perl" if $mode eq "perl" || (grep/^$ext$/, @perl); 0326.2 $mode = "application/x-perl" if $mode eq "perl" || (grep/^$ext$/, @perl); # 0326.2 $mode = "text/x-python" if $mode eq "python"; # ***ked from Gnome 2603 :P ;D $mode = "application/x-c++src" if $mode eq "c" || (grep/gpadrc$|gpad-gtkrc$/, $xfile); $mode = "application/x-php" if $mode eq "php" || (grep/^$ext$/, @php); $mode = "text/xml" if $mode eq "xml" || $ext eq "xml"; $mode = "application/javascript" if $mode eq "js" || $ext eq "js"; $mode = "text/plain" if $mode eq "none" || $ext eq "txt";; } else { # dev remove this THING too! print "LANG-FORCE $mode\n"; # stable remove $mode = "text/css" if $mode eq "css"; $mode = "application/x-sh" if $mode eq "sh"; $mode = "text/html" if $mode eq "html"; $mode = "application/x-perl" if $mode eq "perl"; # fix 0326.2 $mode = "text/x-python" if $mode eq "python"; $mode = "text/x-c++src" if $mode eq "c"; $mode = "application/x-php" if $mode eq "php"; $mode = "text/xml" if $mode eq "xml"; $mode = "text/plain" if $mode eq "none"; } eval do "$dir/highlight.plugin" if -f "$dir/highlight.plugin"; # FORCE MIMES (text/x-*** is incoming default with full-menu) $mode = "text/x-adasrc" if $mode =~ m/text\/x-ada/; # fix 0326.2 $mode = "application/x-shellscript" if $mode =~ m/text\/x-sh/i; # fix 2603.2 $mode = "application/x-javascript" if $mode =~ m/javascript/; # fix 2603.2 $mode = "text/x-patch" if $mode =~ m/diff/; # fix 2603.2 $mode = "application/docbook+xml" if $mode =~ m/docbook/; # fix 2603.2 $mode = "text/x-gettext-translation" if $mode =~ m/text\/x-po/; # fix 2603.2 $mode = "text/x-rpm-spec" if $mode =~ m/text\/x-spec/; # fix 2603.2 $mode = "text/html" if $mode =~ m/html/i; $mode = "text/css" if $mode =~ m/css/i; $mode = "text/xml" if $mode =~ m/xml/i; $mode = "text/x-tex" if $mode =~ m/tex$/i; # LaTeX $mode = "text/x-dsrc" if $mode =~ m/x-d$/i; # D $mode = "application/x-gnome-app-info" if $mode =~ m/desktop/i; # Desktop $mode = "application/x-perl" if $mode =~ m/perl/i; # fix 0326.2 $mode = "application/x-php" if $mode =~ m/php/i; # fix 0326.2 $mode = "application/x-ruby" if $mode =~ m/ruby/i; # fix 0326.2 $mode = "text/x-c++src" if $mode =~ m/x-c/i; # fix 0326.2 $mode = "text/x-ini-file" if $mode =~ m/ini$/i; # INI $mode = "text/x-verilog-src" if $mode =~ m/verilog/i; # Verilog my $lm = Gtk2::SourceView::LanguagesManager -> new; my $lang = $lm -> get_language_from_mime_type($mode); # dev *1 speeding here with "if same" -memory @langs = $lm -> get_lang_files_dirs if !$langs[0]; # speed up, 0-path is used my $xbuffer = &get_buffer; my $test = $xbuffer -> set_highlight($lang) if $xbuffer; # dev FIX THIS!! *! 0104 print ":$test -> LANG-STR NOW: ", &get_langstr($xbuffer), "\n" if $run; # dev remove 0105 print "MIME SELECTED: $mode\n"; # dev remove return $lang; } ### GET TEXT sub get_text{ # MARK 0103 *? my $mode = shift; #my $xtab = $tabs -> get_nth_page($tabs -> get_current_page); #my $xbuffer = $xtab -> get_child -> get_buffer; my $xbuffer = &get_buffer; # dev check this *! my $xtext; $xtext = $xbuffer -> get_text($xbuffer -> get_iter_at_line(0), $xbuffer -> get_end_iter, 0); return $xtext; } # GET BUFFER sub get_buffer{ return if !$run; my $xtab = $tabs -> get_nth_page($tabs -> get_current_page); my $xbuffer = $xtab -> get_child -> get_buffer if $xtab; return $xbuffer; } # GET VIEWER sub get_viewer{ my $xtab = $tabs -> get_nth_page($tabs -> get_current_page); my $xviewer = $xtab -> get_child if $xtab; return $xviewer; } ### SET TITLE sub set_title{ my $xbuffer = shift; my $title = $window -> get_title; return "" if $title !~ m/\*/ && $xbuffer -> get_modified == 0; if ($xbuffer -> get_modified == 0){ $title =~ s/\*//; } else { $title = "$title *"; } $window -> set_title($title); return; } ### NEW BUFFER sub new_buffer{ my $xfile = shift; my $xbuffer; print "NEW BUFFER $xfile\n"; # dev remove my $lang = &set_lang("$forcelang", "", $xfile) if !grep/^--no-color$/, @ARGV; if ($lang){ $xbuffer = Gtk2::SourceView::Buffer -> new_with_language($lang); $xbuffer -> set_highlight(1); # dev check this 0105 print "COLORS ON\n"; # dev remove } else { $xbuffer = Gtk2::SourceView::Buffer -> new(undef); $xbuffer -> set_highlight(0); # dev check this 0105 print "NO COLORS\n"; # dev remove } # try modified-changed signal and remove *1136 $xbuffer -> signal_connect("modified-changed" => sub{set_title($xbuffer)}); # added 0108.1 check, fixed return $xbuffer; } ### COPY TAB # FIX highlighting *0108.1 sub copy_tab{ print "COPY TAB\n"; my $xtext = &get_text; # old text &new_tab; my $zbuffer = &get_buffer; # new buffer $zbuffer -> set_text($xtext); &set_tab; return 0; } ### NEW TAB (under construction, # NOT SAFE YET!) sub new_tab{ my $xfile = shift; my $xtabname = $xfile; $xtabname =~ s/^.*\///; $xtabname = "untitled" if !$xtabname; print "NEW-TAB $xfile\n"; my $xbuffer = &new_buffer($xfile); my $xview = Gtk2::SourceView::View -> new_with_buffer($xbuffer); my $xscroll = Gtk2::ScrolledWindow -> new(undef, undef); $xscroll -> set_policy("automatic", "always"); $xscroll -> add($xview); my $newtab = $tabs -> append_page($xscroll, Gtk2::Label -> new($xtabname)); $tabs -> set_tab_pos($tabpos); $tabs -> show_all; &set_editor($xview); $tabs -> set_current_page(-1); # last page my $cnt = $tabs -> get_current_page; $files[$cnt] = "untitled"; $file = "untitled"; $window -> set_focus(&get_viewer); # dev CHECK THIS 0106 *! return $newtab, $xbuffer; # check 0103 } ### CHANGE TAB # *OK 0108.2 sub change_tab{ my $tab = $_[2]; $tab = 0 if !$run; # fixed *16 my $page = $tabs -> get_nth_page($tab); # new page $files[$tab] = "untitled" if !-f $files[$tab]; $file = $files[$tab]; my $tmp = $file; $tmp = "$file *" if $page -> get_child -> get_buffer -> get_modified > 0; $window -> set_title("$name: $tmp"); return $tab; } ### SET_TAB # IS this needed at all 0108.2, look change_tab ?? sub set_tab{ my $xfile = shift; $xfile = "untitled" if !-f $xfile; $file = $xfile; my $filename = $xfile; $filename =~ s/^.*\///; $files[0] = $xfile if !$run; my $xscroll = $tabs -> get_nth_page($tabs -> get_current_page); $tabs -> set_tab_label($xscroll, Gtk2::Label -> new($filename)); $window -> set_title("$name: $file"); $files[$tabs -> get_current_page] = $xfile if $run; return 0; } ### CLOSE_TAB # *OK 0104 sub close_tab{ &ask_save if $globalresp ne "cancel"; return print "Canceled by You1\n" if $globalresp eq "cancel"; # added/bugfix 0107.2 my $cnt = $tabs -> get_current_page; return if $tabs -> get_n_pages < 0; #dev check *0 0103 -> fixed 0 0105 my $mem = $files[$cnt]; $tabs -> remove_page($cnt); $cnt = $tabs -> get_current_page; if ($cnt < @files){ for (my $i = $cnt + 1; $i < @files; $i++){ $files[$i] = $files[$i + 1] if $files[$i + 1]; } } pop @files; $files[0] = $file if grep/^$mem$/, @files; # dev check/fix *! WTFIT? 0108.1 -> 0108.2 $file = $files[$cnt]; } ### OPEN SESSION # *OK 0105 sub open_session{ my $xsess = &file_dialog("open-session"); return 0 if $xsess eq "cancel"; # bugfix 0107.2 &close_all; # fix 0326.3 open FILE, "< $xsess" or return dialog("error", "ok", "Can't open session file, $xsess"); my @data = split /\|/, ; close FILE; while (<@data>){ chomp(my $tmp = $_); next if !-f $tmp; &open_file($_, "check") if !grep/$tmp/, @files; } return 0; } ### STORE SESSION # *OK 0106 sub store_session{ my $xsess = &file_dialog("save-session"); return 0 if !$xsess; open FILE, "> $xsess" or return dialog("error", "ok", "Can't save to $xsess"); flock FILE, 2; print FILE join "|", @files; close FILE; return 0; } ### IS OPEN # *OK 0106 sub is_open{ my $xfile = shift; return dialog("info", "ok", # No dublicates allowed "File is already open\n$xfile") if grep/^$xfile$/, @files; return "can-open"; } ### OPEN FILE sub open_file{ my ($xfile, $mode) = @_; if ($mode eq "check"){ return 0 if &is_open ne "can-open"; } open FILE, "< $xfile" or return &error("Can't open $xfile"); (my $newtab, my $xbuffer) = &new_tab($xfile) if $run; $xbuffer -> begin_not_undoable_action(); $xbuffer -> set_text(""); $xbuffer -> insert($xbuffer -> get_end_iter(), decode("utf8", $_)) while (); #decode("utf8", $_)) while (); removed 0328.2 # *6 umlauts bug was here, putting decode back in 1120.1 $xbuffer -> end_not_undoable_action(); close FILE; $xbuffer -> place_cursor($xbuffer -> get_start_iter()); $xbuffer -> set_modified(0); $tabs -> set_current_page($newtab); &set_tab($xfile); &check_uid(&basedir($xfile)); # dev check if dublicate in file_dialog? 0105 return 0; } ### DIALOG EX sub dialog_ex{ my @stuff = @_; my $dialog = Gtk2::Dialog -> new; $dialog -> set_resizable(0); $dialog -> set_has_separator(0); $dialog -> set_position("center-on-parent"); my $vbox = $dialog -> vbox; my $lab1 = Gtk2::Label -> new(decode("utf8", $stuff[@stuff - 1])); my $hbox = Gtk2::HBox -> new; my $resp = "cancel"; $vbox -> pack_start($lab1, 10, 10, 10); foreach(@stuff){ my $ff = $_; last if $ff eq $stuff[@stuff - 1]; my $btn = Gtk2::Button -> new_from_stock("gtk-$ff"); $btn -> signal_connect("clicked" => sub{$resp = $ff; $dialog -> destroy}); $hbox -> pack_end($btn, 0, 0, 0); } $vbox -> pack_start($hbox, 0, 0, 0); $vbox -> show_all; $dialog -> run; $dialog -> destroy; print "$resp\n"; return $resp; } ### GET FILE sub get_file{ my $xfile = shift; open FILE, "< $xfile" or &error("$xfile $!"); my @data = ; close FILE; return @data; } ###OPEN LOCATION sub open_location{ my $url = shift; return &dialog("message", "ok", "Wget not found\n please isntall it first.") if !-x "/usr/bin/wget"; my @list; my @list2 = &get_file("$dir/urls.list"); foreach(@list2){ chomp $_; unshift(@list, $_); } my $dialog = Gtk2::Dialog -> new; $dialog -> set_has_separator(0); $dialog -> set_title("Open location (URL)"); my $vbox = $dialog -> vbox; my $hbox = Gtk2::HBox -> new; my $combo = Gtk2::Combo -> new; # Entry -> Combo $combo -> set_size_request(350, 20); $combo -> set_popdown_strings(@list); my $entry = $combo -> entry; # FIX 0108.3 # $entry -> signal_connect("key-release-event" => sub{&check_keys; # $dialog -> destroy if $lastkey == 13}); $entry -> set_text(""); my $button = Gtk2::Button -> new("Open"); $button -> signal_connect("clicked" => sub{$dialog -> destroy}); $hbox -> pack_start($combo, 0, 0, 0); $hbox -> pack_start($button, 0, 0, 0); $vbox -> pack_start($hbox, 0, 0, 0); $vbox -> show_all; my $resp = $dialog -> run; return 0 if $resp eq "delete-event"; my $url = $entry -> get_text; $dialog -> destroy; print "opening -> $url\n"; my $time = time; `wget -O $dir/temp/$time.tmp $url` if grep/^http:\/\/|^ftp:\/\//, $url; # check this 0107.2 &open_file("$dir/temp/$time.tmp", "no-check"); if (!grep/$url/, @list){ open FILE, ">> $dir/urls.list"; flock FILE, 2; print FILE "$url\n"; close FILE; } } ### BASEDIR sub basedir{ my $xfile = shift; my $base = $xfile; $base =~ s/^(.*)(.*\/)/$2/; # fixed 20061231 my @xpath = split/$base/, $xfile; return @xpath; } ### CHECK UID sub check_uid{ return 0 if $silent > 2; my $uid = $>; my $xdir = shift; $xdir = $pwd if !$xdir; dialog("warning", "ok", "WARNING! You are root!") if $uid == 0; dialog("warning", "ok", "User: $user, UID: $uid\n" . "You are not allowed to save " . "in $xdir directory.\n" . "Please, use sudo or save " . "files to the other directory.\n") if !-w $xdir; return 0; } ### SELECT ALL # *OK 0108.2 sub select_all{ my $xbuffer = &get_buffer; $xbuffer -> select_range($xbuffer -> get_start_iter, $xbuffer -> get_end_iter) if $xbuffer; return 0; } ### GET SELECTED # *OK 0108.2 sub get_selected{ my $xbuffer = &get_buffer; return error("No in-buffer") if !$xbuffer; # dev remove or change 0106 my ($start, $end) = $xbuffer -> get_selection_bounds; my $xtext = $xbuffer -> get_text($start, $end, 0) if $start; return $xtext; } ### SET SELECTED # *OK 0108.2 sub set_selected{ my $xtext = shift; my $xbuffer = &get_buffer; return error("No out-buffer") if !$xbuffer; # dev remove or change 0106 &create_backup; my ($start, $end) = $xbuffer -> get_selection_bounds; $xbuffer -> delete($start, $end); $xbuffer -> insert($start, $xtext); $xbuffer -> set_modified(1); return 0; } ### CLIPBOARD # *OK 0104 (but can it be done with buffer?) sub clipboard{ my $mode = shift; my $clip = Gtk2::Clipboard -> get(Gtk2::Gdk::Atom -> intern("CLIPBOARD", 0)); return &get_buffer -> copy_clipboard($clip) if $mode eq "copy"; return &get_buffer -> paste_clipboard($clip, undef, 1) if $mode eq "paste"; return &get_buffer -> cut_clipboard($clip, 1) if $mode eq "cut"; return 0; } ### UNDO # *OK 0108.2 sub undo{ my $xbuffer = &get_buffer; $xbuffer -> undo if $xbuffer -> can_undo && $xbuffer; return 0; } ### REDO # *OK 0108.2 sub redo{ my $xbuffer = &get_buffer; $xbuffer -> redo if $xbuffer -> can_redo && $xbuffer; return 0; } ### SAVE FILE sub save_file{ # dev UID-check here ? 0105 -> 0107 -> 0108 my $xfile = shift; my $xview = &get_viewer; # bugfix 0107.2 my $resp = &file_dialog("save") if $xfile eq "untitled"; return 0 if $resp eq "cancel"; # dev fixed, check 0105 -> *OK 0105 return &error("Can't save $xfile!") if $xfile eq "untitled" || $xfile eq ""; my $xtext = &get_text($xview); # getting buffer text return &error("Save canceled") if dialog("info", "yes-no", "Test version safety query!\n\n" . "Save to: $xfile ?\n\n" . " " . substr($xtext, 0, 100) . " ...") ne "yes"; copy $xfile, "$xfile~" if -f $xfile && $dobackup == 1; # added 0105, check open FILE, "> $xfile" or return &error("Save canceled!\nCan't write to $xfile"); flock FILE, 2; print FILE $xtext; close FILE; my $tmp = &get_buffer -> set_modified(0); return $tmp if !$profile && $autoftp == 1 && dialog("warning", "ok", "Can't transfer file.\n" . "Please, select FTP-profile first!"); return $tmp if $autoftp == 1 && $ftpready == 0 && dialog("info", "ok", "Old FTP-transfer is not ready yet,\n" . "please wait a second and try again."); &auto_ftp($xfile, $profile) if $autoftp == 1; # Automatic FTP transfer return $tmp; } ### ASK SAVE sub ask_save{ my $xbuffer = &get_buffer; return 0 if !$xbuffer; return 0 if $xbuffer -> get_modified == 0; my $resp = &dialog_ex("yes", "no", "cancel", " File not saved, save now?\n $file \n"); $globalresp = $resp; &save_file($file) if $resp eq "yes"; return $resp; } ### ERROR # *OK 0108.2 sub error{ my $msg = shift; print "$msg\n"; &dialog("error", "ok", $msg); } ### INFO # *OK 0108.2 sub info{ my $msg = shift; print "$msg\n"; &dialog("info", "ok", $msg); } ### CHANGE LANG # it would be nice if here is cursor pos memory but HOW to do it ? sub change_lang{ my $fg = shift; my $nbuffer = &new_buffer; my $lang = &set_lang($fg, $fg, $fg) if !grep/^--no-color$/, @ARGV; print "\nLANG: $lang\n"; if ($lang){ $nbuffer = Gtk2::SourceView::Buffer -> new_with_language($lang); $nbuffer -> set_highlight(1); print "COLORS ON\n"; # dev remove } else { $nbuffer = Gtk2::SourceView::Buffer -> new(undef); $nbuffer -> set_highlight(0); print "COLORS OFF\n"; # dev remove } # $nbuffer -> set_text(decode("utf8", &get_text)); # testing utf8 0107.3 # removed 0328.2 $nbuffer -> set_text(&get_text); # fix 0328.2 &get_viewer -> set_buffer($nbuffer); return 0; } ### HIGH LIGHT # dev fix this *0 sub high_light{ my $mode = shift; my $xbuffer = &get_buffer; return set_lang("none", "none", "none") if $mode eq "off"; if ($mode eq "full-menu" || $mode eq "simple-menu"){ my $i = 1; # submenu counter my @smenu; # submenus my $menuR = Gtk2::Menu -> new; # highlight mode-menu $menuR -> append($smenu[0] = Gtk2::MenuItem -> new("Highlight OFF ")); $smenu[0] -> signal_connect("activate" => sub{&high_light("off")}); $menuR -> append(Gtk2::SeparatorMenuItem -> new); # my FAST SIMPLE-MENU Set more %mimes in ~/.gpad/gpadrc OR ~/.gpad/simple-lang.menu if ($mode eq "simple-menu"){ print "SIMPLE-MENU\n"; eval do "$dir/simple-lang.menu" if -f "$dir/simple-lang.menu"; while(my($ff, $fg) = each(%mimes)){ $menuR -> append($smenu[$i] = Gtk2::MenuItem -> new($ff)); $smenu[$i] -> signal_connect("activate" => sub{&change_lang($fg)}); $i++; } } # mode: simple-menu # SLOW original FULL-MENU (SourceView)# fixed, *OK 0105 if ($mode eq "full-menu"){ set_lang(); print "FULL-MENU\n"; my $langdir = $langs[0]; # in Ubuntu: /usr/share/gtksourceview-1.0/language-specs while (<$langdir/*.lang>){ my $ff = $_; $ff =~ s/^.*\/(.*)\.lang$/$1/; $menuR -> append($smenu[$i] = Gtk2::MenuItem -> new($ff)); $smenu[$i] -> signal_connect("activate" => sub{&change_lang("text/x-$ff")}); $i++; } } # mode: full-menu return $menuR; } return 0; } ### CHECK KEYS (main-keys), ### this is NOT good, but can't do better.. yet :| sub check_keys{ my ($widget, $event, $parameter) = @_; my $keynum = $event -> keyval(); my $lock = 0; my $tmp = 0; foreach my $key (keys %Gtk2::Gdk::Keysyms){ my $keycomp = $Gtk2::Gdk::Keysyms{$key}; if($keycomp == $keynum){ if ($lastkey == 65507 || $lastkey == 65508){ # CTRL &save_file($file) if $keynum == 115; # Ctrl+S &quit if $keynum == 113; # Ctrl+Q &file_dialog("open") if $keynum == 111; # Ctrl+O &select_all if $keynum == 97; # Ctrl+A bf *22 &new_tab("untitled") if $keynum == 110; # Ctrl+N bf *22 $lock = 1; } # Ctrl $lastkey = 13 if $keynum == 65421 || $keynum == 65293; # Enter last; } } $lastkey = $keynum if $lastkey != 13; #$status = "not-done" #if &get_buffer -> get_modified > 0 && $lock == 0; # check 0108.2 return; } ### TOGGLE FULLSCREEN sub toggle_fullscreen{ if ($fullscreen == 1){ $window -> unfullscreen; $fullscreen = 0; }else{ $window -> fullscreen; $fullscreen = 1; } return 0; } ### SHOW/HIDE COMMANDLINE sub show_hide_commandline{ if ($commandline == 1){ $hbox0 -> hide_all; $commandline = 0; }else{ $hbox0 -> show_all; $commandline = 1; } return 0; } ### AUTO BACKUP file will be removed when program is ending normally ### look *10 sub auto_backup{ my $xtext = &get_text; my $time = localtime time; open FILE, "> $backup" or return $status = "not-done"; flock FILE, 2; print FILE "\n###\nTHIS IS AUTO-CREATED CRASH-BACKUP FILE!\n", "Backup created: $time\n", "Original filename is $file\n\n###\n"; print FILE $xtext; close FILE; $status = "done"; return $xtext; } ### AUTO FTP (starter) sub auto_ftp{ my ($xfile, $ff) = @_; return &error("Please install Auto-FTP") if !-x "/usr/bin/auto-ftp"; return &error("File not found, $xfile") if !-f $xfile; return info("Please, select profile first") if !$ff; unlink "$home/.auto-ftp.msg" if -f "$home/.auto-ftp.msg"; if ($cftp == 1){ return 0 if &dialog("info", "yes-no", "Transfer $xfile ->\n$ff ?") ne "yes"; } $profile = $ff; # global profile for $autoftp Ctrl+S -mode $menu06 -> set_submenu(&ftp_profiles); # updating menu $fileM -> show_all; $ftpready = 0; # mark, only one transfer can be alive at the time $transfer = 1; # mark for message-system, look main-loop system("auto-ftp -f $xfile -p $ff --force-auto &"); return 0; } ### REPLACE HTML sub replace_html{ # dev BUILD this 0104 -> 0105, check my $data = &get_selected; return &info("Please select code first.") if !$data; $data = HTML::Entities::encode($data); &set_selected($data); # check decode here 0107.3 return 0; } ### REPLACE (submenu $menu16) sub replace{ my @smenu; my $menuR = Gtk2::Menu -> new; # replace menu # $menuR -> append(Gtk2::TearoffMenuItem -> new); $menuR -> append($smenu[0] = Gtk2::MenuItem -> new("<&> -> HTML Entities")); $smenu[0] -> signal_connect("activate" => sub{&replace_html}); # $menuR -> append(Gtk2::SeparatorMenuItem -> new()); return $menuR; } ### TEMPLATES # *OK 0105 sub templates{ my $i = 1; # submenu counter my @smenu; my $menuR = Gtk2::Menu -> new; # templates menu while (<$dir/templates/*.template>){ my $ff = $_; next if !-f $ff; # *101 -T bug in Perl, fixed 0112.1 $ff =~ s/^.*\///; $menuR -> append($smenu[$i] = Gtk2::MenuItem -> new($ff)); $smenu[$i] -> signal_connect("activate" => sub{&open_file("$dir/templates/$ff", "no-check"); $file = "untitled"; &set_tab}); $i++; } $menuR -> append(Gtk2::SeparatorMenuItem -> new); $menuR -> append($smenu[$i] = Gtk2::MenuItem -> new("Save as template")); $smenu[$i] -> signal_connect("activate" => sub{&file_dialog("save-template")}); return $menuR; } ### FTP PROFILES # *OK 0105 sub ftp_profiles{ my $i = 2; my @smenu; my $menuR = Gtk2::Menu -> new; # auto-ftp profiles menu return $menuR if !-e $ftpprf || !-x "/usr/bin/auto-ftp"; $menuR -> append(Gtk2::TearoffMenuItem -> new); $menuR -> append($smenu[0] = Gtk2::CheckMenuItem -> new("Auto-FTP (Ctrl+S)")); $smenu[0] -> signal_connect("activate" => sub{$autoftp = !$autoftp}); $menuR -> append(Gtk2::SeparatorMenuItem -> new); $menuR -> append($ftpM = Gtk2::MenuItem -> new("FTP-out -> $profile")); # global item $ftpM -> signal_connect("activate" => sub{&auto_ftp($file, $profile)}); $menuR -> append(Gtk2::SeparatorMenuItem -> new); while (<$ftpprf/*>){ my $ff = $_; next if !-f $ff; # *101 -T bug in Perl, fixed 0112.1 $ff =~ s/^.*\///; $menuR -> append($smenu[$i] = Gtk2::MenuItem -> new($ff)); $smenu[$i] -> signal_connect("activate" => sub{&auto_ftp($file, $ff)}); $i++; } if (-x "/usr/bin/gftp"){ # gFTP is quite good too ;) $menuR -> append(Gtk2::SeparatorMenuItem -> new); $menuR -> append($smenu[$i] = Gtk2::MenuItem -> new("Open gFTP")); $smenu[$i] -> signal_connect("activate" => sub{system("gftp $file &")}); } return $menuR; } ### RECENT FILES # dev add sort-engine :) 0105 -> 0108.2 sub recent_files{ my ($xfile, $mode) = @_; my (@lines, $menuR); &save_last_files(@lines) if !-f "$dir/recent.files"; # fix 20070101 if (-f "$dir/recent.files"){ open FILE, "< $dir/recent.files"; @lines = ; close FILE; ## dev, add orderer to here *! .. trying :) *0 ## THE orderer ? BUILD this *! #delete(@lines, $xfile) if grep/^$xfile$/, @lines; unshift(@lines, "$xfile\n") if -f $xfile && (!grep/^$xfile$/, @lines); splice(@lines, $recent) if int(@lines) > $recent; # max count my $i = 1; my @smenu; $menuR = Gtk2::Menu -> new; $menuR -> append(Gtk2::TearoffMenuItem -> new); while (<@lines> ){ chomp(my $ff = $_); next if !-f $ff; $menuR -> append($smenu[$i] = Gtk2::MenuItem -> new($ff)); $smenu[$i] -> signal_connect("activate" => sub{\&open_file($ff, "check")}); $i++; } $menuR -> append(Gtk2::SeparatorMenuItem -> new()); $menuR -> append($smenu[$i] = Gtk2::MenuItem -> new("Clear list")); $smenu[$i] -> signal_connect("activate" => sub{unlink "$dir/recent.files" if &dialog("warning", "yes-no", "Clear recent files list?") eq "yes"; &recent_files}); # reload menu $menu03 -> set_submenu($menuR); $menu03 -> show_all; } &save_last_files(@lines) if $mode ne "read"; return $menuR; } ### HELP # *OK 0105 sub help{ my $help = < "application/x-c++", css => "text/css", html => "text/html", perl => "application/x-perl", php => "application/x-php", python => "text/x-python", sh => "application/x-shellscript", xml => "text/xml", none => "text/none" ); ## end of ~/.gpad/gpadrc SETTINGS # return $settings; } ### GTKRC # *OK 0105 sub gtkrc{ ## SET GTK SETTINGS, FONTS AND STYLES ~/.gpad/gpad-gtkrc FILE ## DO NOT EDIT SETTINGS HERE, edit in ~/.gpad/gpad-gtkrc ! my $gtkrc = < parse_string (< $set1file"; flock FILE, 2; print FILE &settings, "\n\n"; close FILE; } if (!-f $set2file){ open FILE, "> $set2file"; flock FILE, 2; print FILE >krc, "\n\n"; close FILE; } if (!-f "$dir/run.list"){ # fix 0326 open FILE, "> $dir/run.list"; close FILE; } print "INSTALL-DIR: $dir OK\n" if -d "$dir"; return print "Install check done\n"; } ### SAVE LAST FILES # *OK 0105 sub save_last_files{ my @lines = @_; open FILE, "> $dir/recent.files"; flock FILE, 2; print FILE @lines; close FILE; return 0; } ############################ MENU STUFF ############################## ### SESSIONS SUB sub sessions_sub{ my $sessM = Gtk2::Menu -> new; $sessM -> append(my $menu61 = Gtk2::MenuItem -> new(" Open session ")); $sessM -> append(my $menu62 = Gtk2::MenuItem -> new(" Save session ")); $menu61 -> signal_connect("activate" => sub{&open_session}); $menu62 -> signal_connect("activate" => sub{&store_session}); return $sessM; } ### TOOLS MENU # *OK 0104 sub tools_menu{ our $xmenu = shift; our ($menu101, $menu102, $menu103, $menu104, $menu105); # for tools.plugin -file if (-x "/usr/bin/gimp"){ $xmenu -> append(my $menu41 = Gtk2::MenuItem -> new(" Gimp ")); $menu41 -> signal_connect("activate" => sub{run("gimp")}); } if (-x "/usr/bin/gftp"){ $xmenu -> append(my $menu42 = Gtk2::MenuItem -> new(" gFTP ")); $menu42 -> signal_connect("activate" => sub{run("gftp")}); } if (-x "/usr/bin/gcpicker"){ $xmenu -> append(my $menu44 = Gtk2::MenuItem -> new(" gCpicker ")); $menu44 -> signal_connect("activate" => sub{run("/usr/bin/gcpicker")}); } $xmenu -> append(Gtk2::SeparatorMenuItem -> new); $xmenu -> append(my $menu43 = Gtk2::MenuItem -> new(" Terminal ")); $menu43 -> signal_connect("activate" => sub{run($terminal)}); do "$dir/tools.plugin" if -f "$dir/tools.plugin"; # 0326.3 return $xmenu; } ### RUN MENU sub run_menu{ my $xmenu = Gtk2::Menu -> new; $xmenu -> append(my $menu31 = Gtk2::MenuItem -> new("Firefox")); $xmenu -> append(my $menu32 = Gtk2::MenuItem -> new("Opera")); $xmenu -> append(Gtk2::SeparatorMenuItem -> new); $xmenu -> append(my $menu33 = Gtk2::ImageMenuItem -> new_from_stock("gtk-execute", $accel)); $menu31 -> signal_connect("activate" => sub{&run("firefox $file")}); $menu32 -> signal_connect("activate" => sub{&run("opera $file")}); $menu33 -> signal_connect("activate" => sub{&run_ex}); return $xmenu; } ### READ RUN LIST sub read_run_list{ my @list = &get_file("$dir/run.list"); my $i = 0; while(<@list>){ chomp($list[$i]); $i++; } return $combo -> set_popdown_strings(@list); } ### PACKAGE sub package{ my $vbox0 = Gtk2::VBox -> new; # mainbox my $vbox1 = Gtk2::VBox -> new; # menubox #my $stat = Gtk2::Statusbar -> new; # TEST # $stat -> set_has_resize_grip(1); $vbox1 -> pack_start($main, 0, 0, 0); # main menu ## INTERNAL COMMAND-LINE $hbox0 -> pack_start($combo, 1, 10, 0); &read_run_list; $entry -> signal_connect("key-release-event" => sub{&check_keys; # global $entry &run($entry -> get_text) if $lastkey == 13}); $hbox0 -> pack_start(my $button = Gtk2::Button -> new("Run"), 0, 1, 0); $button -> signal_connect("clicked" => sub{&run($entry -> get_text)}); $vbox0 -> pack_end($hbox0, 0, 0, 0); $entry -> set_text($session[4]); # fix 0328.2, utf8 decode removed $vbox0 -> pack_start($vbox1, 0, 0, 0); # add menu $vbox0 -> pack_start($tabs, 1, 100, 0); # add tabs # $vbox0 -> pack_start($stat, 0, 0, 0); # Statusbar TEST 0108.1 -> removed 0108.2 return $vbox0; } ### SET EDITOR # *OK 0104 sub set_editor{ my $xview = shift; $xview -> set_editable($mode); $xview -> set_justification ("left"); $xview -> set_tabs_width($tabwidth); $xview -> set_smart_home_end($smartkeys); $xview -> set_insert_spaces_instead_of_tabs($tabtospace); $xview -> set_cursor_visible($mode); $xview -> set_left_margin($lm); $xview -> set_right_margin($rm); $xview -> set_show_line_numbers($nums); $xview -> set_show_line_markers($markers); $xview -> set_show_margin($margin); $xview -> set_auto_indent ($autoindent); $xview -> set_marker_pixbuf (1, undef); # dev ? *0 "?" $xview -> set_highlight_current_line($highlight); $xview -> set_wrap_mode ($wrap); return 0; } ### FIX GTK # *OK 0104 .. fixing Gtk+ font-size bugs here a bit ;) sub fix_gtk{ if ($ENV{"GNOME_DESKTOP_SESSION_ID"}){ # fixing some Gtk+ fontsize bugs $menufont = $menufont - 1.5; # use $menufont and $codefont Your $codefont = $codefont - 1.2; # ~/.gpad/gpad-gtkrc file } # Xfce4 12 font <~> Gnome 10.5 font } ### GET LANGSTR # ?OK 0104 -> check again 0105 sub get_langstr{ my $xbuffer = shift; $xbuffer = &get_buffer if !$xbuffer; my $tmp = $xbuffer -> get_language if $xbuffer; my $str = $tmp -> get_name if $tmp; $str = "none" if !$str; return $str; } ### VIEW INFO # *OK 0104 sub view_info{ my @tmp; my @files2 = @files; splice(@files2, 35); push(@tmp, "\n$_") while(<@files2>); my @stat = stat $file; my $time = localtime $stat[9]; my $tmp2 = $profile; $tmp2 = "none" if !$tmp2; my $str = &get_langstr(); my $xbuffer = &get_buffer; my $cnt = $xbuffer -> get_line_count if $xbuffer; my $info = < set_tab_pos("top") if $tabs -> get_tab_pos eq "bottom"; return $tabs -> set_tab_pos("left") if $tabs -> get_tab_pos eq "top"; return $tabs -> set_tab_pos("right") if $tabs -> get_tab_pos eq "left"; return $tabs -> set_tab_pos("bottom") if $tabs -> get_tab_pos eq "right"; } ### LOAD SESSION # *OK 0104 sub load_session{ my $xfile = "$dir/last.session"; unlink $xfile if -s $xfile > 1024; # bugfix *18 if ((!grep/^--new$/, @ARGV) && -f $xfile){ open FILE, "< $xfile"; @session = ; close FILE; return &error("Wrong format in $xfile") if @session > 13; # just in case $wdth = $session[1] if $session[1] =~ /^\d{2,4}$/; $hght = $session[2] if $session[2] =~ /^\d{2,4}$/; chomp($session[3]); # last file, not in use .. #$file = $session[3] if -f $session[3] && !-f $file; # .. anymore due session-memory chomp($session[4]); # last command chomp($commandline = $session[5]) if $session[5] =~ /^\d{1}$/; chomp($tabpos = $session[6]) if length $session[6] > 2; # tab-bar position chomp($profile = $session[7]) if length $session[7] > 1; # last FTP-profile @files = split/\|/, $session[@files - 1]; # last session files, must be last in array } } ### CREATE BACKUP sub create_backup{ return 0 if $dobackup < 1 || !-f $file; copy "$file~", "$file~~" if -f "$file~"; # backup backup return copy $file, "$file~"; } ### SAVE SESSION # *OK 0104 sub save_session{ my $xfile = "$dir/last.session"; unlink $xfile; # bugfix *18 $session[0] = time; ($session[1], $session[2]) = $window -> get_size; # window size $session[3] = "\#";#$file if -T $file; # last file memory # not in use, remove ? $session[4] = $entry -> get_text; # last command memory, bugfix *13 $session[5] = $commandline; # commandline visible $session[6] = $tabs -> get_tab_pos; # tab-bar position $session[7] = $profile; # last used FTP-profile $session[12] = join "|", @files; # session files (must be in last on array) $session[12] =~ s/\/gpadrc$|\/gpad-gtkrc$//g; # don't remember setting files # check 0107.4 open FILE, "> $xfile"; flock FILE, 2; for (my $i = 0; $i < 13; $i++){ chomp $session[$i]; print FILE "$session[$i]\n"; } close FILE; return 0; } ### RESET SETTINGS # *OK 0104 sub reset_settings{ return 0 if &dialog("warning", "yes-no", "Restoring default settings!\n" . "Are You sure?") ne "yes"; copy $set1file, "$set1file.backup"; copy $set2file, "$set2file.backup"; unlink $set1file; unlink $set2file; error("Reset failed!") if -f $set1file || -f $set2file; return 0 if &dialog("info", "yes-no", "\u$name will be restarted, is that OK now?") ne "yes"; &close_all; system("$0 &"); $window -> destroy if $window; exit 0; } ### CLOSE ALL # *OK, but odd: 0105 sub close_all{ $tabs -> set_current_page(-1); # last tab &close_tab while($tabs -> get_current_page > 0 && $globalresp ne "cancel"); &close_tab; # should be a tab 0 for sure? &close_tab; # but still needed this one, odd :) return 0; } ### QUIT # *OK 0104 sub quit{ $globalresp = "none"; &close_all; return print "Canceled by You3\n" if $globalresp eq "cancel"; # Removing Execute temp files my $xfile1 = "$dir/filetmp.run"; my $xfile2 = "$dir/tmp.run"; unlink $xfile1 if -f $xfile1; unlink $xfile2 if -f $xfile2; # Removing CRASH-BACKUP files unlink $backup if -f $backup; # remove runtime backup-file if (-f "$backup.bu"){ if (dialog("question", "yes-no", "Removing CRASH-BACKUP file $backup.bu, is that OK?") eq "yes"){ unlink "$backup.bu" if -f "$backup.bu" } } # Removing temporary remote files (Open Location files) my @tmp = <$dir/temp/*.tmp>; if (int @tmp > 0){ if (dialog("question", "yes-no", "Removing temporary remote files, is that OK?") eq "yes"){ unlink "$_" while(<$dir/temp/*.tmp>); } } return print "Canceled by You2\n" if $globalresp eq "cancel"; # is this needed anymore? # $window -> destroy if $window; # same odd error here, look gClip exit 0; } # end __END__ ####################################################################### Dev: Ruby and PHP manuals are a lot better than Perl-one :| http://gtk.php.net/manual/en/gtk.gtktextbuffer.php http://ruby-gnome2.sourceforge.jp/hiki.cgi?Gtk http://www.gtk.org/ http://gtk2-perl.sourceforge.net/doc/pod/idx.html http://gtk2-perl.sourceforge.net/doc/pod/Gtk2/TextView.html http://gtk2-perl.sourceforge.net/doc/pod/Gtk2/TextBuffer.html http://gtk2-perl.sourceforge.net/doc/pod/Gtk2/SourceView.html http://live.gnome.org/GTK2-Perl/FrequentlyAskedQuestions http://developer.gnome.org/ http://personal.riverusers.com/~swilhelm/gtkperl-tutorial/ http://gtk2-perl.sourceforge.net/doc/pod/Gtk2/AccelGroup.html CHECK 0107 -> 0328.2 main -> append(menu) TODO: Color menu not working -> OK Templates -> OK Highlight -> OK Missing window in closing -> OK Cancel-button to close-dialog -> OK Default settings missing on install -> OK SAR *519 -> 911 !!! Replace HTML -> OK -> add umlauts -> 0328.2 ! Cursor-pos memory when Highlight change -> HOW TO DO IT, NO DOCS? FIX ARGV[0] file-open -> OK Buffer modified * to window title -> OK $dialog -> action_area -> pack_start .. ? change run entry to combo -> OK, with memory + Open location combo too. goto fix copy-tab highlight Read Mime-Types from first mime-dir autom. -> 911 !!! Fix NOW somehow :) html shtml xhtml syntax highlight, look *7 Fixed: *X 20072012.2 Fixed bug if path includes . marks, look *8 20072011.1 Umlauts bug fixed, I hope... look *6 20071811.1 Syntax highlight error if Ubuntu 7.04 updated to Ubuntu 7.10 Close all auto-opened files (all files) and start gPad again, syntax highlight should then work OK. If not working, reset settings to default values (Settings -> Reset settings) 20071001.1 Find-dialog to operate 20070328.3 Edit -> Replace special replaces now all HTML entities + Word-wrap 20070328.2 UTF8-fixes and Ctrl+T creates new tab. Ctrl+W and mouse middle-button closes tabs 20070326.4, tools.plugin file look http://uhvo.org/sec/gpad-tools.plugin.txt 20070326.2, fixed mime-types somehow, not good at all, but works? 20070326.1, simple-menu changed to full menu, Perl and PHP highlight somehow missing HELP! ;) 20070112.1, Found bug in Perl with -T file check and umlauts, fixed with -f 20070108.2, No for Statusbar, Yes for Combo-box in Open location and Run entry 20070108.1, statusbaaar ? NOT COMING, REMOVED! -> OK 20070107.3, fixed argv file open, added TAB-MENU and 0107.3 bugfixes 20070107.2, Cancel for quiting if not saved files 20070106.1, replace HTML and select all 20070105.4, lot more bugs and new icon 20070105.3, dynamic ftp menu, fixed Gtk2::FileChooser open_mode bug, + more bugs. 20070105.2, check edition, auto-ftp message etc 20070104.4, Highlighting, 2 modes: simple-menu and full-menu OK! :) 20070104.0, Templates 20070103.5, Color edition, simple-menu mode OK 20070103.4, Ctrl+Q edition :D 20070103, setings fixed, and a lot more of speed, nice clipboard 20070102, ... tabs almost ok .. OK -> Highlight works1! ;) 20070101, FAST Open Location (with wget), should change to get. 20070101, fix,fix,fix, do not use filename as 0 (zero) :) 20070101, TABS are IN! YES! :) 20061231, TABS are incoming, nice ;) 20061231, added Auto-FTP <-> gPad etc lock-file, updated Auto-FTP too 20061231, fixed UID with basedir, save_file, FTP with Ctrl+S 20061230, CRASH-BACKUP loop, nice now I think? :) *10 20061230, last-files, should be OK now ## license: http://creativecommons.org/licenses/nc-sa/1.0/ ## auto-ftp -f ~/d2/gpad.txt -p gpad-sec --newname gpad.txt --force-auto ## auto-ftp -f ~/d2/gpad.txt -p dash-sec --newname gpad.txt --force-auto