diff --git a/manifest b/manifest index 881a5f9859..7b5d82a97c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C :-)\s(CVS\s127) -D 2000-08-04T13:52:31 +C :-)\s(CVS\s128) +D 2000-08-04T14:56:25 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4 F Makefile.in 670aa9413cb2cdcded23b328a9e255c845c41a1e F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958 @@ -16,9 +16,10 @@ F src/main.c ba16b81890d962821bb90f0a4de9a29b0e495eb2 F src/parse.y 5d199034de5d29ebedb42c1c51f34db4df40cbe5 F src/select.c d382e96c2221d08367cc87976f2b574537c9de97 F src/shell.c 2fd370838742afa068cfcdd05b667ff89bab25b6 +F src/shell.tcl ca52bb831e03e10480516e5e708c0c452914a219 F src/sqlite.h 82ae53028e27919250f886ff9d7c4927de81978a F src/sqliteInt.h f6d1e139b3bfa4ceff2136684e19d76b53178ec0 -F src/tclsqlite.c 6ced80832c13e70dae5a176da2dff3d5f4801d92 +F src/tclsqlite.c b1ae6abd50d8b0e2470cc49b5e1d03329a68dd75 F src/tokenize.c 77ff8164a8751994bc9926ce282847f653ac0c16 F src/update.c 51b9ef7434b15e31096155da920302e9db0d27fc F src/util.c b75b33e6bd5d47898bb7ed9fdd0dea4fe7c19b00 @@ -68,7 +69,7 @@ F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60 F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f F www/sqlite.tcl 7c2ee68063fa59463f55d5bac1ffe3e50d8a817f F www/vdbe.tcl bcbfc33bcdd0ebad95eab31286adb9e1bc289520 -P e31be5824813d1690a4ee7bac9e49658a08c52c1 -R a1959e73cecbe5ec9f491607dba0c61e +P 695fd68eb6291bdcc04af0eec7c7cdd7ff10872b +R ba994bd9837a407cb6abaac249529cc4 U drh -Z a62979c6837973254ca7c80dad5fc80b +Z 509708daad6c84350903dba5837a203b diff --git a/manifest.uuid b/manifest.uuid index 2bf8419637..ab2ddab983 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -695fd68eb6291bdcc04af0eec7c7cdd7ff10872b \ No newline at end of file +d53cccda4fa5d2f8287421e71488817eb4ca13eb \ No newline at end of file diff --git a/src/shell.tcl b/src/shell.tcl new file mode 100644 index 0000000000..d28cba6343 --- /dev/null +++ b/src/shell.tcl @@ -0,0 +1,587 @@ +#!/usr/bin/wish +# +# A GUI shell for SQLite +# + +############################################################################ +# A console widget for Tcl/Tk. Invoke console:create with a window name, +# a prompt string, and a title to get a new top-level window that allows +# the user to enter tcl commands. This is mainly useful for testing and +# debugging. +# +# Copyright (C) 1998, 1999 D. Richard Hipp +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# +# Author contact information: +# drh@acm.org +# http://www.hwaci.com/drh/ + +# Create a console widget named $w. The prompt string is $prompt. +# The title at the top of the window is $title +# +proc console:create {w prompt title} { + upvar #0 $w.t v + if {[winfo exists $w]} {destroy $w} + if {[info exists v]} {unset v} + toplevel $w + wm title $w $title + wm iconname $w $title + frame $w.mb -bd 2 -relief raised + pack $w.mb -side top -fill x + menubutton $w.mb.file -text File -menu $w.mb.file.m + menubutton $w.mb.edit -text Edit -menu $w.mb.edit.m + pack $w.mb.file $w.mb.edit -side left -padx 8 -pady 1 + set m [menu $w.mb.file.m] + # $m add command -label {Source...} -command "console:SourceFile $w.t" + # $m add command -label {Save As...} -command "console:SaveFile $w.t" + # $m add separator + $m add command -label {Close} -command "destroy $w" + $m add command -label {Exit} -command exit + console:create_child $w $prompt $w.mb.edit.m +} + +# This routine creates a console as a child window within a larger +# window. It also creates an edit menu named "$editmenu" if $editmenu!="". +# The calling function is responsible for posting the edit menu. +# +proc console:create_child {w prompt editmenu} { + upvar #0 $w.t v + if {$editmenu!=""} { + set m [menu $editmenu] + $m add command -label Cut -command "console:Cut $w.t" + $m add command -label Copy -command "console:Copy $w.t" + $m add command -label Paste -command "console:Paste $w.t" + $m add command -label {Clear Screen} -command "console:Clear $w.t" + $m add separator + $m add command -label {Source...} -command "console:SourceFile $w.t" + $m add command -label {Save As...} -command "console:SaveFile $w.t" + catch {$editmenu config -postcommand "console:EnableEditMenu $w"} + } + scrollbar $w.sb -orient vertical -command "$w.t yview" + pack $w.sb -side right -fill y + text $w.t -font fixed -yscrollcommand "$w.sb set" + pack $w.t -side right -fill both -expand 1 + bindtags $w.t Console + set v(editmenu) $editmenu + set v(text) $w.t + set v(history) 0 + set v(historycnt) 0 + set v(current) -1 + set v(prompt) $prompt + set v(prior) {} + set v(plength) [string length $v(prompt)] + set v(x) 0 + set v(y) 0 + $w.t mark set insert end + $w.t tag config ok -foreground blue + $w.t tag config err -foreground red + $w.t insert end $v(prompt) + $w.t mark set out 1.0 + catch {rename puts console:oldputs$w} + proc puts args [format { + if {![winfo exists %s]} { + rename puts {} + rename console:oldputs%s puts + return [uplevel #0 puts $args] + } + switch -glob -- "[llength $args] $args" { + {1 *} { + set msg [lindex $args 0]\n + set tag ok + } + {2 stdout *} { + set msg [lindex $args 1]\n + set tag ok + } + {2 stderr *} { + set msg [lindex $args 1]\n + set tag err + } + {2 -nonewline *} { + set msg [lindex $args 1] + set tag ok + } + {3 -nonewline stdout *} { + set msg [lindex $args 2] + set tag ok + } + {3 -nonewline stderr *} { + set msg [lindex $args 2] + set tag err + } + default { + uplevel #0 console:oldputs%s $args + return + } + } + console:Puts %s $msg $tag + } $w $w $w $w.t] + after idle "focus $w.t" +} + +bind Console <1> {console:Button1 %W %x %y} +bind Console {console:B1Motion %W %x %y} +bind Console {console:B1Leave %W %x %y} +bind Console {console:cancelMotor %W} +bind Console {console:cancelMotor %W} +bind Console {console:Insert %W %A} +bind Console {console:Left %W} +bind Console {console:Left %W} +bind Console {console:Right %W} +bind Console {console:Right %W} +bind Console {console:Backspace %W} +bind Console {console:Backspace %W} +bind Console {console:Delete %W} +bind Console {console:Delete %W} +bind Console {console:Home %W} +bind Console {console:Home %W} +bind Console {console:End %W} +bind Console {console:End %W} +bind Console {console:Enter %W} +bind Console {console:Enter %W} +bind Console {console:Prior %W} +bind Console {console:Prior %W} +bind Console {console:Next %W} +bind Console {console:Next %W} +bind Console {console:EraseEOL %W} +bind Console <> {console:Cut %W} +bind Console <> {console:Copy %W} +bind Console <> {console:Paste %W} +bind Console <> {console:Clear %W} + +# Insert test at the "out" mark. The "out" mark is always +# before the input line. New text appears on the line prior +# to the current input line. +# +proc console:Puts {w t tag} { + set nc [string length $t] + set endc [string index $t [expr $nc-1]] + if {$endc=="\n"} { + if {[$w index out]<[$w index {insert linestart}]} { + $w insert out [string range $t 0 [expr $nc-2]] $tag + $w mark set out {out linestart +1 lines} + } else { + $w insert out $t $tag + } + } else { + if {[$w index out]<[$w index {insert linestart}]} { + $w insert out $t $tag + } else { + $w insert out $t\n $tag + $w mark set out {out -1 char} + } + } + $w yview insert +} + +# Insert a single character at the insertion cursor +# +proc console:Insert {w a} { + $w insert insert $a + $w yview insert +} + +# Move the cursor one character to the left +# +proc console:Left {w} { + upvar #0 $w v + scan [$w index insert] %d.%d row col + if {$col>$v(plength)} { + $w mark set insert "insert -1c" + } +} + +# Erase the character to the left of the cursor +# +proc console:Backspace {w} { + upvar #0 $w v + scan [$w index insert] %d.%d row col + if {$col>$v(plength)} { + $w delete {insert -1c} + } +} + +# Erase to the end of the line +# +proc console:EraseEOL {w} { + upvar #0 $w v + scan [$w index insert] %d.%d row col + if {$col>=$v(plength)} { + $w delete insert {insert lineend} + } +} + +# Move the cursor one character to the right +# +proc console:Right {w} { + $w mark set insert "insert +1c" +} + +# Erase the character to the right of the cursor +# +proc console:Delete w { + $w delete insert +} + +# Move the cursor to the beginning of the current line +# +proc console:Home w { + upvar #0 $w v + scan [$w index insert] %d.%d row col + $w mark set insert $row.$v(plength) +} + +# Move the cursor to the end of the current line +# +proc console:End w { + $w mark set insert {insert lineend} +} + +# Called when "Enter" is pressed. Do something with the line +# of text that was entered. +# +proc console:Enter w { + upvar #0 $w v + scan [$w index insert] %d.%d row col + set start $row.$v(plength) + set line [$w get $start "$start lineend"] + if {$v(historycnt)>0} { + set last [lindex $v(history) [expr $v(historycnt)-1]] + if {[string compare $last $line]} { + lappend v(history) $line + incr v(historycnt) + } + } else { + set v(history) [list $line] + set v(historycnt) 1 + } + set v(current) $v(historycnt) + $w insert end \n + $w mark set out end + if {$v(prior)==""} { + set cmd $line + } else { + set cmd $v(prior)\n$line + } + if {[info complete $cmd]} { + set rc [catch {uplevel #0 $cmd} res] + if {![winfo exists $w]} return + if {$rc} { + $w insert end $res\n err + } elseif {[string length $res]>0} { + $w insert end $res\n ok + } + set v(prior) {} + $w insert end $v(prompt) + } else { + set v(prior) $cmd + regsub -all {[^ ]} $v(prompt) . x + $w insert end $x + } + $w mark set insert end + $w mark set out {insert linestart} + $w yview insert +} + +# Change the line to the previous line +# +proc console:Prior w { + upvar #0 $w v + if {$v(current)<=0} return + incr v(current) -1 + set line [lindex $v(history) $v(current)] + console:SetLine $w $line +} + +# Change the line to the next line +# +proc console:Next w { + upvar #0 $w v + if {$v(current)>=$v(historycnt)} return + incr v(current) 1 + set line [lindex $v(history) $v(current)] + console:SetLine $w $line +} + +# Change the contents of the entry line +# +proc console:SetLine {w line} { + upvar #0 $w v + scan [$w index insert] %d.%d row col + set start $row.$v(plength) + $w delete $start end + $w insert end $line + $w mark set insert end + $w yview insert +} + +# Called when the mouse button is pressed at position $x,$y on +# the console widget. +# +proc console:Button1 {w x y} { + global tkPriv + upvar #0 $w v + set v(mouseMoved) 0 + set v(pressX) $x + set p [console:nearestBoundry $w $x $y] + scan [$w index insert] %d.%d ix iy + scan $p %d.%d px py + if {$px==$ix} { + $w mark set insert $p + } + $w mark set anchor $p + focus $w +} + +# Find the boundry between characters that is nearest +# to $x,$y +# +proc console:nearestBoundry {w x y} { + set p [$w index @$x,$y] + set bb [$w bbox $p] + if {![string compare $bb ""]} {return $p} + if {($x-[lindex $bb 0])<([lindex $bb 2]/2)} {return $p} + $w index "$p + 1 char" +} + +# This routine extends the selection to the point specified by $x,$y +# +proc console:SelectTo {w x y} { + upvar #0 $w v + set cur [console:nearestBoundry $w $x $y] + if {[catch {$w index anchor}]} { + $w mark set anchor $cur + } + set anchor [$w index anchor] + if {[$w compare $cur != $anchor] || (abs($v(pressX) - $x) >= 3)} { + if {$v(mouseMoved)==0} { + $w tag remove sel 0.0 end + } + set v(mouseMoved) 1 + } + if {[$w compare $cur < anchor]} { + set first $cur + set last anchor + } else { + set first anchor + set last $cur + } + if {$v(mouseMoved)} { + $w tag remove sel 0.0 $first + $w tag add sel $first $last + $w tag remove sel $last end + update idletasks + } +} + +# Called whenever the mouse moves while button-1 is held down. +# +proc console:B1Motion {w x y} { + upvar #0 $w v + set v(y) $y + set v(x) $x + console:SelectTo $w $x $y +} + +# Called whenever the mouse leaves the boundries of the widget +# while button 1 is held down. +# +proc console:B1Leave {w x y} { + upvar #0 $w v + set v(y) $y + set v(x) $x + console:motor $w +} + +# This routine is called to automatically scroll the window when +# the mouse drags offscreen. +# +proc console:motor w { + upvar #0 $w v + if {![winfo exists $w]} return + if {$v(y)>=[winfo height $w]} { + $w yview scroll 1 units + } elseif {$v(y)<0} { + $w yview scroll -1 units + } else { + return + } + console:SelectTo $w $v(x) $v(y) + set v(timer) [after 50 console:motor $w] +} + +# This routine cancels the scrolling motor if it is active +# +proc console:cancelMotor w { + upvar #0 $w v + catch {after cancel $v(timer)} + catch {unset v(timer)} +} + +# Do a Copy operation on the stuff currently selected. +# +proc console:Copy w { + if {![catch {set text [$w get sel.first sel.last]}]} { + clipboard clear -displayof $w + clipboard append -displayof $w $text + } +} + +# Return 1 if the selection exists and is contained +# entirely on the input line. Return 2 if the selection +# exists but is not entirely on the input line. Return 0 +# if the selection does not exist. +# +proc console:canCut w { + set r [catch { + scan [$w index sel.first] %d.%d s1x s1y + scan [$w index sel.last] %d.%d s2x s2y + scan [$w index insert] %d.%d ix iy + }] + if {$r==1} {return 0} + if {$s1x==$ix && $s2x==$ix} {return 1} + return 2 +} + +# Do a Cut operation if possible. Cuts are only allowed +# if the current selection is entirely contained on the +# current input line. +# +proc console:Cut w { + if {[console:canCut $w]==1} { + console:Copy $w + $w delete sel.first sel.last + } +} + +# Do a paste opeation. +# +proc console:Paste w { + if {[console:canCut $w]==1} { + $w delete sel.first sel.last + } + if {[catch {selection get -displayof $w -selection CLIPBOARD} topaste]} { + return + } + set prior 0 + foreach line [split $topaste \n] { + if {$prior} { + console:Enter $w + update + } + set prior 1 + $w insert insert $line + } +} + +# Enable or disable entries in the Edit menu +# +proc console:EnableEditMenu w { + upvar #0 $w.t v + set m $v(editmenu) + if {$m=="" || ![winfo exists $m]} return + switch [console:canCut $w.t] { + 0 { + $m entryconf Copy -state disabled + $m entryconf Cut -state disabled + } + 1 { + $m entryconf Copy -state normal + $m entryconf Cut -state normal + } + 2 { + $m entryconf Copy -state normal + $m entryconf Cut -state disabled + } + } +} + +# Prompt for the user to select an input file, the "source" that file. +# +proc console:SourceFile w { + set types { + {{TCL Scripts} {.tcl}} + {{All Files} *} + } + set f [tk_getOpenFile -filetypes $types -title "TCL Script To Source..."] + if {$f!=""} { + uplevel #0 source $f + } +} + +# Prompt the user for the name of a writable file. Then write the +# entire contents of the console screen to that file. +# +proc console:SaveFile w { + set types { + {{Text Files} {.txt}} + {{All Files} *} + } + set f [tk_getSaveFile -filetypes $types -title "Write Screen To..."] + if {$f!=""} { + if {[catch {open $f w} fd]} { + tk_messageBox -type ok -icon error -message $fd + } else { + puts $fd [string trimright [$w get 1.0 end] \n] + close $fd + } + } +} + +# Erase everything from the console above the insertion line. +# +proc console:Clear w { + $w delete 1.0 {insert linestart} +} + +# Start the console +# +# console:create {.@console} {% } {Tcl/Tk Console} +############################################################################### + + +if {[info command sqlite]==""} { + load ./tclsqlite.so sqlite +} + + + +proc set_title {title} { + if {$title==""} { + set main SQLite + } else { + set main "SQLite - $title" + } + wm title . $main + wm iconname . SQLite +} +set_title {} + +frame .mb -bd 1 -relief raised +pack .mb -side top -fill x +menubutton .mb.file -text File -underline 0 -menu .mb.file.m +pack .mb.file -side left -padx 5 +set m [menu .mb.file.m] +$m add separator +$m add command -label Exit -command exit +menubutton .mb.edit -text Edit -underline 0 -menu .mb.edit.m +pack .mb.edit -side left -padx 5 +#menu .mb.edit.m + +frame .f +pack .f -side top -fill both -expand 1 +console:create_child .f {sqlite> } .mb.edit.m diff --git a/src/tclsqlite.c b/src/tclsqlite.c index b15f10d13c..dc9894c71e 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -23,7 +23,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.6 2000/08/04 13:49:02 drh Exp $ +** $Id: tclsqlite.c,v 1.7 2000/08/04 14:56:25 drh Exp $ */ #include "sqlite.h" #include @@ -301,7 +301,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){ return TCL_ERROR; } zErrMsg = 0; - p = Tcl_Alloc( sizeof(*p) ); + p = (SqliteDb*)Tcl_Alloc( sizeof(*p) ); if( p==0 ){ Tcl_SetResult(interp, "malloc failed", TCL_STATIC); return TCL_ERROR;