# Gedi master advanced text editor. use Tk::TextEdit; use vars qw/$TOP/; my $TOP; my $text_frame; my $counter_frame; my $textwindow; my $current_line_label; my $total_line_label; my $current_column_label; my $insert_overstrike_mode_label; my $about_pop_up_reference; my $menu; my $help_menu; sub about_pop_up { my $name = ref($about_pop_up_reference); if (defined($about_pop_up_reference)) { $about_pop_up_reference->raise; $about_pop_up_reference->focus; } else { my $pop = $TOP->Toplevel(); $pop->title("About"); $pop->Label(-text=>"Gedi (Gregs EDItor)")->pack(); $pop->Label(-text=>"Ver. 1.0")->pack(); $pop->Label(-text=>"Copyright 1999")->pack(); $pop->Label(-text=>"Greg London")->pack(); $pop->Label(-text=>"All Rights Reserved.")->pack(); $pop->Label(-text=>"This program is free software.")->pack(); $pop->Label(-text=>"You can redistribute it and/or")->pack(); $pop->Label(-text=>"modify it under the same terms")->pack(); $pop->Label(-text=>"as Perl itself.")->pack(); $pop->Label(-text=>"Special Thanks to")->pack(); $pop->Label(-text=>"Nick Ing-Simmons.")->pack(); my $button_ok = $pop->Button(-text=>'OK', -command => sub {$pop->destroy(); $about_pop_up_reference = undef; } ) ->pack(); $pop->resizable('no','no'); $about_pop_up_reference = $pop; } } sub update_indicators { my ($line,$column)= split(/\./,$textwindow->index('insert')); $current_line_label->configure (-text=> "line: $line"); $current_column_label->configure (-text=> "column: $column"); my ($last_line,$last_col) = split(/\./,$textwindow->index('end')); $total_line_label->configure (-text=> "total lines: $last_line"); my $mode = $textwindow->OverstrikeMode; my $overstrke_insert='Insert Mode'; if ($mode) {$overstrke_insert='Overstrike Mode';} $insert_overstrike_mode_label->configure (-text=> "$overstrke_insert"); my $filename = $textwindow->FileName; $filename = 'NoName' unless(defined($filename)); my $edit_flag=''; if($textwindow->numberChanges) {$edit_flag='edited';} $TOP->configure(-title => "Gedi $edit_flag $filename"); $textwindow->idletasks; } sub Gedi { my($demo) = @_; $TOP = $MW->WidgetDemo( -name => $demo, -text => 'Gedi master advanced text editor ', -geometry_manager => 'grid', -title => 'GEDI Text Editor', -iconname => 'GEDI', ); $TOP->withdraw; $text_frame = $TOP->Frame->pack (-anchor=>'nw', -expand=>'yes', -fill => 'both'); # autosizing $counter_frame = $TOP->Frame->pack(-anchor=>'nw'); $textwindow = $text_frame->Scrolled( 'TextEdit', exportselection => 'true', # 'sel' tag is associated with selections # initial height, if it isnt 1, then autosizing fails # once window shrinks below height # and the line counters go off the screen. # seems to be a problem with the Tk::pack command; # height => 40, -background => 'white', -wrap=> 'none', -setgrid => 'true', # use this for autosizing -scrollbars =>'se') -> pack(-expand => 'yes' , -fill => 'both'); # autosizing $TOP->protocol('WM_DELETE_WINDOW'=> sub{$textwindow->ConfirmExit;} ); $SIG{INT} = sub {$textwindow->ConfirmExit;}; $current_line_label = $counter_frame -> Label(-text=>'line: 1') -> grid(-row=>1,-column=>1, -sticky=>'nw' ); $total_line_label = $counter_frame -> Label(-text=>'total lines: 1') -> grid(-row=>2,-column=>1, -sticky=>'nw' ); $current_column_label = $counter_frame -> Label(-text=>'column: 0') -> grid(-row=>3,-column=>1, -sticky=>'nw' ); $insert_overstrike_mode_label = $counter_frame -> Label(-text=>' ') -> grid(-row=>5,-column=>1, -sticky=>'nw' ); $textwindow->SetGUICallbacks ( [ \&update_indicators, sub{$textwindow->HighlightAllPairsBracketingCursor} ] ); $menu = $textwindow->menu; $TOP->configure(-menu => $menu); $help_menu = $menu->cascade(-label=>'~Help', -tearoff => 0, -menuitems => [ [Command => 'A~bout', -command => \&about_pop_up] ]); #$TOP->minsize(30,1); #$TOP->geometry("80x24"); while() {$textwindow->insert('insert',$_);} $textwindow->ResetUndo; $textwindow->CallNextGUICallback; # adjust height $TOP->update; my $menuheight = ($TOP->wrapper)[1]; my $TOPheight = 30 + $TOP->reqheight + $menuheight; if ($TOP->screenheight < $TOPheight) { $textwindow->GeometryRequest($textwindow->reqwidth, $textwindow->reqheight - ($TOPheight - $TOP->screenheight)); } $TOP->deiconify; } __DATA__ Tk800.015 contains many modifications to the text based modules, as well as new text modules and an application that uses them all. Text.pm, TextUndo.pm, TextEdit.pm, and gedi have all been updated since the release prior to Tk800.015. This demo contains a rundown of all the features of the text modules, and What is available in the text modules? ================================================ Text.pm ======== Text.pm is the base text editing module. Beyond the core functionality of typing text, Text.pm has built in menu support for basic editing features such as Find/Replace text, Copy/Cut/Paste, Goto Line Number, and What Line Number queries. These functions are available simply by right clicking the mouse over the text area. Doing so will cause a pop-up menu to appear which will contain cascading menus to give access to all of these new functions. Many of these functions will create their own pop-up windows. Find/Replace will create a pop-up window which contains an entry for text to find, an entry for replace text, a number of radio buttons to control options such as case sensitivity, and several command buttons to perform functions such as Find, Find All, Replace, Replace All. All of these features have corresponding methods built into the Text widget. This allows the basic functions to be built into the widget, and also allows added features to be built on the lower level methods as needed. No one should have to reinvent the wheel when it comes to text editing features. Insert and Overstrike modes are also supported in the Text.pm module. Pressing the key will toggle modes back and forth. Column based copy/cut/paste features are also available in the Text.pm module. They are bound to the following keys: clipboardColumnCopy clipboardColumnCut clipboardColumnPaste Currently, column based operations are beta versions. They compensate for tabs, but they will not behave properly unless the text is all the same font, and is the same width per character. Hopefully some future version of Text.pm will correct for this deficiency. Column paste should work with overstrike mode. TextUndo.pm ============= TextUndo.pm is the second level module, being derived from the Text.pm module. As it's name implies, TextUndo supports "UNDO" capability. It now also supports "REDO" capability. Undo/redo works on user typed commands and also programmatically, so that any application that causes text to be inserted or deleted can be undone/redone, whether it was directly typed by the user or indirectly through another method. The undo/redo functions support tags, so that if you delete text with tags, undo will re-insert the text and re-tag it as well. This will eventually allow the text modules to support more sophisticated word processing type features. Such functionality should be available in a future release of the text modules. The TextUndo.pm module also has several added features to support file based operations. File based methods include ->Save, ->Load, and ->Include. All methods take a filename as a parameter. These methods will create a progress widget to indicate the progress of the operation. The other feature of the TextUndo.pm module is the ConfirmDiscard method. This method checks to see if the text has been modified since it was last saved. If it has been modified, and the it will create a pop-up menu asking the user if they want to save the text to a file before exiting. This method can easily be tied into the exit routines, and signal handlers, to provide a consistent "save before exit?" feel. TextEdit.pm ============= The TextEdit.pm is a new module in prototype version which adds further features to the text modules. TextEdit is based off of the TextUndo module, and so has all of the features of TextUndo and Text. Features of the TextEdit.pm module include parenthesis matching. The module looks at the current cursor position and then tries to find the parenthesis that bracket the cursor. Character pairs that are searched for are: () {} [] "" '' It also checks the position of the pairs to try to highlight bad positions. The module assumes that if the pairs are not on the same line or not on the same column, then there might be a missing parenthesis somewhere. Characters that appear to not align are highlighted in red. (quotations must start and end on the same line) PARENTHISIS MATCHING DEMO: move the cursor to the x between the quotes on the line below: { ( ) ( { } [ ' ">> x <<" ' [] ] ) } PARENTHESIS MISMATCHING DEMO: move the cursor to the x between the quotes on the line below: { ( ) ( <> x <<" ' [] ] ) < IndentSelectedLines UnindentSelectedLines CommentSelectedLines UncommentSelectedLines These bindings only operate on the currently selected text. The indent string and the comment string can be programmed to be anything, but defaults to "\t" (tab) for indent and "#" for comments. (currently the widget hash is used to store these values. $w->{'INDENT_STRING'} and $w->{'LINE_COMMENT_STRING'} At some point in the future, this will be changed to use configure options to set these values. any application that changes these values should do so in such a way that when the TextEdit module changes, the application can be easily changed to handle this) gedi application ===================== gedi is short for Greg's EDItor. The "g" is soft, pronounced like a "j". The gedi application uses all of the features of the text modules, Text, TextUndo, and TextEdit. It supplies TextEdit with a callback to update the indicator displays. This information includes the current cursor position, insert/overstrike mode, length of the file, filename, and whether the file has been edited or not. The bottom of this display contains line number column number total lines insert/overstrike mode. The title bar contains filename and if the file has been edited, the word "edited". Where gedi is installed depends on your system, but it is part of the tarkit for Tk800.015 and above. gedi was created to be put a perl editor in with the perl tar kit. NOTE: THIS IS NOT THE ACTUAL GEDI APPLICATION, BUT A DEMO SET UP TO BE SIMILAR IN NATURE TO THE GEDI APPLICATION. THE ACTUAL GEDI APPLICATION IS PART OF THE TK800.015 TARKIT. WHERE IT IS LOCATED ON YOUR SYSTEM WILL VARY DEPENDING ON YOUR SYSTEM. ONCE YOU LOCATE THE GEDI APPLICATION, PUT IT IN YOUR EXECUTABLE PATH, AND YOU WILL BE ABLE TO USE IT AS A TEXT EDITOR.