3 # This code constructs the console window for an application. It
4 # can be used by non-unix systems that do not have built-in support
7 # SCCS: @(#) console.tcl 1.45 97/09/17 16:52:40
9 # Copyright (c) 1995-1997 Sun Microsystems, Inc.
11 # See the file "license.terms" for information on usage and redistribution
12 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 # TODO: history - remember partially written command
18 # This procedure constructs and configures the console windows.
23 proc tkConsoleInit {} {
26 if {! [consoleinterp eval {set tcl_interactive}]} {
30 if {"$tcl_platform(platform)" == "macintosh"} {
37 .menubar add cascade -label File -menu .menubar.file -underline 0
38 .menubar add cascade -label Edit -menu .menubar.edit -underline 0
40 menu .menubar.file -tearoff 0
41 .menubar.file add command -label "Source..." -underline 0 \
42 -command tkConsoleSource
43 .menubar.file add command -label "Hide Console" -underline 0 \
44 -command {wm withdraw .}
45 if {"$tcl_platform(platform)" == "macintosh"} {
46 .menubar.file add command -label "Quit" -command exit -accel Cmd-Q
48 .menubar.file add command -label "Exit" -underline 1 -command exit
51 menu .menubar.edit -tearoff 0
52 .menubar.edit add command -label "Cut" -underline 2 \
53 -command { event generate .console <<Cut>> } -accel "$mod+X"
54 .menubar.edit add command -label "Copy" -underline 0 \
55 -command { event generate .console <<Copy>> } -accel "$mod+C"
56 .menubar.edit add command -label "Paste" -underline 1 \
57 -command { event generate .console <<Paste>> } -accel "$mod+V"
59 if {"$tcl_platform(platform)" == "windows"} {
60 .menubar.edit add command -label "Delete" -underline 0 \
61 -command { event generate .console <<Clear>> } -accel "Del"
63 .menubar add cascade -label Help -menu .menubar.help -underline 0
64 menu .menubar.help -tearoff 0
65 .menubar.help add command -label "About..." -underline 0 \
66 -command tkConsoleAbout
68 .menubar.edit add command -label "Clear" -underline 2 \
69 -command { event generate .console <<Clear>> }
74 text .console -yscrollcommand ".sb set" -setgrid true
75 scrollbar .sb -command ".console yview"
76 pack .sb -side right -fill both
77 pack .console -fill both -expand 1 -side left
78 if {$tcl_platform(platform) == "macintosh"} {
79 .console configure -font {Monaco 9 normal} -highlightthickness 0
82 tkConsoleBind .console
84 .console tag configure stderr -foreground red
85 .console tag configure stdin -foreground blue
89 wm protocol . WM_DELETE_WINDOW { wm withdraw . }
92 .console mark set output [.console index "end - 1 char"]
93 tkTextSetCursor .console end
94 .console mark set promptEnd insert
95 .console mark gravity promptEnd left
100 # Prompts the user for a file to source in the main interpreter.
105 proc tkConsoleSource {} {
106 set filename [tk_getOpenFile -defaultextension .tcl -parent . \
107 -title "Select a file to source" \
108 -filetypes {{"Tcl Scripts" .tcl} {"All Files" *}}]
109 if {"$filename" != ""} {
110 set cmd [list source $filename]
111 if [catch {consoleinterp eval $cmd} result] {
112 tkConsoleOutput stderr "$result\n"
118 # Processes the command line input. If the command is complete it
119 # is evaled in the main interpreter. Otherwise, the continuation
120 # prompt is added and more input may be added.
125 proc tkConsoleInvoke {args} {
126 set ranges [.console tag ranges input]
130 while {[lindex $ranges $pos] != ""} {
131 set start [lindex $ranges $pos]
132 set end [lindex $ranges [incr pos]]
133 append cmd [.console get $start $end]
139 } elseif [info complete $cmd] {
140 .console mark set output end
141 .console tag delete input
142 set result [consoleinterp record $cmd]
144 .console insert insert "$result\n"
146 tkConsoleHistory reset
149 tkConsolePrompt partial
151 .console yview -pickplace insert
154 # tkConsoleHistory --
155 # This procedure implements command line history for the
156 # console. In general is evals the history command in the
157 # main interpreter to obtain the history. The global variable
158 # histNum is used to store the current location in the history.
161 # cmd - Which action to take: prev, next, reset.
164 proc tkConsoleHistory {cmd} {
171 set cmd {history event [expr [history nextid] -1]}
173 set cmd "history event $histNum"
175 if {[catch {consoleinterp eval $cmd} cmd]} {
179 .console delete promptEnd end
180 .console insert promptEnd $cmd {input stdin}
185 set cmd {history event [expr [history nextid] -1]}
186 } elseif {$histNum > 0} {
190 set cmd "history event $histNum"
193 catch {consoleinterp eval $cmd} cmd
195 .console delete promptEnd end
196 .console insert promptEnd $cmd {input stdin}
205 # This procedure draws the prompt. If tcl_prompt1 or tcl_prompt2
206 # exists in the main interpreter it will be called to generate the
207 # prompt. Otherwise, a hard coded default prompt is printed.
210 # partial - Flag to specify which prompt to print.
212 proc tkConsolePrompt {{partial normal}} {
213 if {$partial == "normal"} {
214 set temp [.console index "end - 1 char"]
215 .console mark set output end
216 if [consoleinterp eval "info exists tcl_prompt1"] {
217 consoleinterp eval "eval \[set tcl_prompt1\]"
222 set temp [.console index output]
223 .console mark set output end
224 if [consoleinterp eval "info exists tcl_prompt2"] {
225 consoleinterp eval "eval \[set tcl_prompt2\]"
231 .console mark set output $temp
232 tkTextSetCursor .console end
233 .console mark set promptEnd insert
234 .console mark gravity promptEnd left
238 # This procedure first ensures that the default bindings for the Text
239 # class have been defined. Then certain bindings are overridden for
245 proc tkConsoleBind {win} {
246 bindtags $win "$win Text . all"
248 # Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
249 # Otherwise, if a widget binding for one of these is defined, the
250 # <KeyPress> class binding will also fire and insert the character,
251 # which is wrong. Ditto for <Escape>.
253 bind $win <Alt-KeyPress> {# nothing }
254 bind $win <Meta-KeyPress> {# nothing}
255 bind $win <Control-KeyPress> {# nothing}
256 bind $win <Escape> {# nothing}
257 bind $win <KP_Enter> {# nothing}
260 tkConsoleInsert %W \t
265 %W mark set insert {end - 1c}
266 tkConsoleInsert %W "\n"
271 if {[%W tag nextrange sel 1.0 end] != ""} {
272 %W tag remove sel sel.first promptEnd
274 if [%W compare insert < promptEnd] {
279 bind $win <BackSpace> {
280 if {[%W tag nextrange sel 1.0 end] != ""} {
281 %W tag remove sel sel.first promptEnd
283 if [%W compare insert <= promptEnd] {
288 foreach left {Control-a Home} {
290 if [%W compare insert < promptEnd] {
291 tkTextSetCursor %W {insert linestart}
293 tkTextSetCursor %W promptEnd
298 foreach right {Control-e End} {
300 tkTextSetCursor %W {insert lineend}
304 bind $win <Control-d> {
305 if [%W compare insert < promptEnd] {
309 bind $win <Control-k> {
310 if [%W compare insert < promptEnd] {
311 %W mark set insert promptEnd
314 bind $win <Control-t> {
315 if [%W compare insert < promptEnd] {
320 if [%W compare insert < promptEnd] {
324 bind $win <Meta-BackSpace> {
325 if [%W compare insert <= promptEnd] {
329 bind $win <Control-h> {
330 if [%W compare insert <= promptEnd] {
334 foreach prev {Control-p Up} {
336 tkConsoleHistory prev
340 foreach prev {Control-n Down} {
342 tkConsoleHistory next
347 catch {tkConsoleInsert %W [selection get -displayof %W]}
350 bind $win <KeyPress> {
351 tkConsoleInsert %W %A
354 foreach left {Control-b Left} {
356 if [%W compare insert == promptEnd] {
359 tkTextSetCursor %W insert-1c
363 foreach right {Control-f Right} {
365 tkTextSetCursor %W insert+1c
370 eval destroy [winfo child .]
371 if {$tcl_platform(platform) == "macintosh"} {
374 source [file join $tk_library console.tcl]
378 # Same as the copy event
379 if {![catch {set data [%W get sel.first sel.last]}]} {
380 clipboard clear -displayof %W
381 clipboard append -displayof %W $data
386 if {![catch {set data [%W get sel.first sel.last]}]} {
387 clipboard clear -displayof %W
388 clipboard append -displayof %W $data
392 bind $win <<Paste>> {
394 set clip [selection get -displayof %W -selection CLIPBOARD]
395 set list [split $clip \n\r]
396 tkConsoleInsert %W [lindex $list 0]
397 foreach x [lrange $list 1 end] {
398 %W mark set insert {end - 1c}
399 tkConsoleInsert %W "\n"
401 tkConsoleInsert %W $x
409 # Insert a string into a text at the point of the insertion cursor.
410 # If there is a selection in the text, and it covers the point of the
411 # insertion cursor, then delete the selection before inserting. Insertion
412 # is restricted to the prompt area.
415 # w - The text window in which to insert the string
416 # s - The string to insert (usually just a single character)
418 proc tkConsoleInsert {w s} {
423 if {[$w compare sel.first <= insert]
424 && [$w compare sel.last >= insert]} {
425 $w tag remove sel sel.first promptEnd
426 $w delete sel.first sel.last
429 if {[$w compare insert < promptEnd]} {
430 $w mark set insert end
432 $w insert insert $s {input stdin}
438 # This routine is called directly by ConsolePutsCmd to cause a string
439 # to be displayed in the console.
442 # dest - The output tag to be used: either "stderr" or "stdout".
443 # string - The string to be displayed.
445 proc tkConsoleOutput {dest string} {
446 .console insert output $string $dest
452 # This routine is called by ConsoleEventProc when the main window of
453 # the application is destroyed. Don't call exit - that probably already
454 # happened. Just delete our window.
459 proc tkConsoleExit {} {
465 # This routine displays an About box to show Tcl/Tk version info.
470 proc tkConsoleAbout {} {
472 tk_messageBox -type ok -message "Tcl for Windows
473 Copyright \251 1996 Sun Microsystems, Inc.
475 Tcl [info patchlevel]
479 # now initialize the console