Annotation of embedaddon/sqlite3/contrib/sqlitecon.tcl, revision 1.1
1.1 ! misho 1: # A Tk console widget for SQLite. Invoke sqlitecon::create with a window name,
! 2: # a prompt string, a title to set a new top-level window, and the SQLite
! 3: # database handle. For example:
! 4: #
! 5: # sqlitecon::create .sqlcon {sql:- } {SQL Console} db
! 6: #
! 7: # A toplevel window is created that allows you to type in SQL commands to
! 8: # be processed on the spot.
! 9: #
! 10: # A limited set of dot-commands are supported:
! 11: #
! 12: # .table
! 13: # .schema ?TABLE?
! 14: # .mode list|column|multicolumn|line
! 15: # .exit
! 16: #
! 17: # In addition, a new SQL function named "edit()" is created. This function
! 18: # takes a single text argument and returns a text result. Whenever the
! 19: # the function is called, it pops up a new toplevel window containing a
! 20: # text editor screen initialized to the argument. When the "OK" button
! 21: # is pressed, whatever revised text is in the text editor is returned as
! 22: # the result of the edit() function. This allows text fields of SQL tables
! 23: # to be edited quickly and easily as follows:
! 24: #
! 25: # UPDATE table1 SET dscr = edit(dscr) WHERE rowid=15;
! 26: #
! 27:
! 28:
! 29: # Create a namespace to work in
! 30: #
! 31: namespace eval ::sqlitecon {
! 32: # do nothing
! 33: }
! 34:
! 35: # Create a console widget named $w. The prompt string is $prompt.
! 36: # The title at the top of the window is $title. The database connection
! 37: # object is $db
! 38: #
! 39: proc sqlitecon::create {w prompt title db} {
! 40: upvar #0 $w.t v
! 41: if {[winfo exists $w]} {destroy $w}
! 42: if {[info exists v]} {unset v}
! 43: toplevel $w
! 44: wm title $w $title
! 45: wm iconname $w $title
! 46: frame $w.mb -bd 2 -relief raised
! 47: pack $w.mb -side top -fill x
! 48: menubutton $w.mb.file -text File -menu $w.mb.file.m
! 49: menubutton $w.mb.edit -text Edit -menu $w.mb.edit.m
! 50: pack $w.mb.file $w.mb.edit -side left -padx 8 -pady 1
! 51: set m [menu $w.mb.file.m -tearoff 0]
! 52: $m add command -label {Close} -command "destroy $w"
! 53: sqlitecon::create_child $w $prompt $w.mb.edit.m
! 54: set v(db) $db
! 55: $db function edit ::sqlitecon::_edit
! 56: }
! 57:
! 58: # This routine creates a console as a child window within a larger
! 59: # window. It also creates an edit menu named "$editmenu" if $editmenu!="".
! 60: # The calling function is responsible for posting the edit menu.
! 61: #
! 62: proc sqlitecon::create_child {w prompt editmenu} {
! 63: upvar #0 $w.t v
! 64: if {$editmenu!=""} {
! 65: set m [menu $editmenu -tearoff 0]
! 66: $m add command -label Cut -command "sqlitecon::Cut $w.t"
! 67: $m add command -label Copy -command "sqlitecon::Copy $w.t"
! 68: $m add command -label Paste -command "sqlitecon::Paste $w.t"
! 69: $m add command -label {Clear Screen} -command "sqlitecon::Clear $w.t"
! 70: $m add separator
! 71: $m add command -label {Save As...} -command "sqlitecon::SaveFile $w.t"
! 72: catch {$editmenu config -postcommand "sqlitecon::EnableEditMenu $w"}
! 73: }
! 74: scrollbar $w.sb -orient vertical -command "$w.t yview"
! 75: pack $w.sb -side right -fill y
! 76: text $w.t -font fixed -yscrollcommand "$w.sb set"
! 77: pack $w.t -side right -fill both -expand 1
! 78: bindtags $w.t Sqlitecon
! 79: set v(editmenu) $editmenu
! 80: set v(history) 0
! 81: set v(historycnt) 0
! 82: set v(current) -1
! 83: set v(prompt) $prompt
! 84: set v(prior) {}
! 85: set v(plength) [string length $v(prompt)]
! 86: set v(x) 0
! 87: set v(y) 0
! 88: set v(mode) column
! 89: set v(header) on
! 90: $w.t mark set insert end
! 91: $w.t tag config ok -foreground blue
! 92: $w.t tag config err -foreground red
! 93: $w.t insert end $v(prompt)
! 94: $w.t mark set out 1.0
! 95: after idle "focus $w.t"
! 96: }
! 97:
! 98: bind Sqlitecon <1> {sqlitecon::Button1 %W %x %y}
! 99: bind Sqlitecon <B1-Motion> {sqlitecon::B1Motion %W %x %y}
! 100: bind Sqlitecon <B1-Leave> {sqlitecon::B1Leave %W %x %y}
! 101: bind Sqlitecon <B1-Enter> {sqlitecon::cancelMotor %W}
! 102: bind Sqlitecon <ButtonRelease-1> {sqlitecon::cancelMotor %W}
! 103: bind Sqlitecon <KeyPress> {sqlitecon::Insert %W %A}
! 104: bind Sqlitecon <Left> {sqlitecon::Left %W}
! 105: bind Sqlitecon <Control-b> {sqlitecon::Left %W}
! 106: bind Sqlitecon <Right> {sqlitecon::Right %W}
! 107: bind Sqlitecon <Control-f> {sqlitecon::Right %W}
! 108: bind Sqlitecon <BackSpace> {sqlitecon::Backspace %W}
! 109: bind Sqlitecon <Control-h> {sqlitecon::Backspace %W}
! 110: bind Sqlitecon <Delete> {sqlitecon::Delete %W}
! 111: bind Sqlitecon <Control-d> {sqlitecon::Delete %W}
! 112: bind Sqlitecon <Home> {sqlitecon::Home %W}
! 113: bind Sqlitecon <Control-a> {sqlitecon::Home %W}
! 114: bind Sqlitecon <End> {sqlitecon::End %W}
! 115: bind Sqlitecon <Control-e> {sqlitecon::End %W}
! 116: bind Sqlitecon <Return> {sqlitecon::Enter %W}
! 117: bind Sqlitecon <KP_Enter> {sqlitecon::Enter %W}
! 118: bind Sqlitecon <Up> {sqlitecon::Prior %W}
! 119: bind Sqlitecon <Control-p> {sqlitecon::Prior %W}
! 120: bind Sqlitecon <Down> {sqlitecon::Next %W}
! 121: bind Sqlitecon <Control-n> {sqlitecon::Next %W}
! 122: bind Sqlitecon <Control-k> {sqlitecon::EraseEOL %W}
! 123: bind Sqlitecon <<Cut>> {sqlitecon::Cut %W}
! 124: bind Sqlitecon <<Copy>> {sqlitecon::Copy %W}
! 125: bind Sqlitecon <<Paste>> {sqlitecon::Paste %W}
! 126: bind Sqlitecon <<Clear>> {sqlitecon::Clear %W}
! 127:
! 128: # Insert a single character at the insertion cursor
! 129: #
! 130: proc sqlitecon::Insert {w a} {
! 131: $w insert insert $a
! 132: $w yview insert
! 133: }
! 134:
! 135: # Move the cursor one character to the left
! 136: #
! 137: proc sqlitecon::Left {w} {
! 138: upvar #0 $w v
! 139: scan [$w index insert] %d.%d row col
! 140: if {$col>$v(plength)} {
! 141: $w mark set insert "insert -1c"
! 142: }
! 143: }
! 144:
! 145: # Erase the character to the left of the cursor
! 146: #
! 147: proc sqlitecon::Backspace {w} {
! 148: upvar #0 $w v
! 149: scan [$w index insert] %d.%d row col
! 150: if {$col>$v(plength)} {
! 151: $w delete {insert -1c}
! 152: }
! 153: }
! 154:
! 155: # Erase to the end of the line
! 156: #
! 157: proc sqlitecon::EraseEOL {w} {
! 158: upvar #0 $w v
! 159: scan [$w index insert] %d.%d row col
! 160: if {$col>=$v(plength)} {
! 161: $w delete insert {insert lineend}
! 162: }
! 163: }
! 164:
! 165: # Move the cursor one character to the right
! 166: #
! 167: proc sqlitecon::Right {w} {
! 168: $w mark set insert "insert +1c"
! 169: }
! 170:
! 171: # Erase the character to the right of the cursor
! 172: #
! 173: proc sqlitecon::Delete w {
! 174: $w delete insert
! 175: }
! 176:
! 177: # Move the cursor to the beginning of the current line
! 178: #
! 179: proc sqlitecon::Home w {
! 180: upvar #0 $w v
! 181: scan [$w index insert] %d.%d row col
! 182: $w mark set insert $row.$v(plength)
! 183: }
! 184:
! 185: # Move the cursor to the end of the current line
! 186: #
! 187: proc sqlitecon::End w {
! 188: $w mark set insert {insert lineend}
! 189: }
! 190:
! 191: # Add a line to the history
! 192: #
! 193: proc sqlitecon::addHistory {w line} {
! 194: upvar #0 $w v
! 195: if {$v(historycnt)>0} {
! 196: set last [lindex $v(history) [expr $v(historycnt)-1]]
! 197: if {[string compare $last $line]} {
! 198: lappend v(history) $line
! 199: incr v(historycnt)
! 200: }
! 201: } else {
! 202: set v(history) [list $line]
! 203: set v(historycnt) 1
! 204: }
! 205: set v(current) $v(historycnt)
! 206: }
! 207:
! 208: # Called when "Enter" is pressed. Do something with the line
! 209: # of text that was entered.
! 210: #
! 211: proc sqlitecon::Enter w {
! 212: upvar #0 $w v
! 213: scan [$w index insert] %d.%d row col
! 214: set start $row.$v(plength)
! 215: set line [$w get $start "$start lineend"]
! 216: $w insert end \n
! 217: $w mark set out end
! 218: if {$v(prior)==""} {
! 219: set cmd $line
! 220: } else {
! 221: set cmd $v(prior)\n$line
! 222: }
! 223: if {[string index $cmd 0]=="." || [$v(db) complete $cmd]} {
! 224: regsub -all {\n} [string trim $cmd] { } cmd2
! 225: addHistory $w $cmd2
! 226: set rc [catch {DoCommand $w $cmd} res]
! 227: if {![winfo exists $w]} return
! 228: if {$rc} {
! 229: $w insert end $res\n err
! 230: } elseif {[string length $res]>0} {
! 231: $w insert end $res\n ok
! 232: }
! 233: set v(prior) {}
! 234: $w insert end $v(prompt)
! 235: } else {
! 236: set v(prior) $cmd
! 237: regsub -all {[^ ]} $v(prompt) . x
! 238: $w insert end $x
! 239: }
! 240: $w mark set insert end
! 241: $w mark set out {insert linestart}
! 242: $w yview insert
! 243: }
! 244:
! 245: # Execute a single SQL command. Pay special attention to control
! 246: # directives that begin with "."
! 247: #
! 248: # The return value is the text output from the command, properly
! 249: # formatted.
! 250: #
! 251: proc sqlitecon::DoCommand {w cmd} {
! 252: upvar #0 $w v
! 253: set mode $v(mode)
! 254: set header $v(header)
! 255: if {[regexp {^(\.[a-z]+)} $cmd all word]} {
! 256: if {$word==".mode"} {
! 257: regexp {^.[a-z]+ +([a-z]+)} $cmd all v(mode)
! 258: return {}
! 259: } elseif {$word==".exit"} {
! 260: destroy [winfo toplevel $w]
! 261: return {}
! 262: } elseif {$word==".header"} {
! 263: regexp {^.[a-z]+ +([a-z]+)} $cmd all v(header)
! 264: return {}
! 265: } elseif {$word==".tables"} {
! 266: set mode multicolumn
! 267: set cmd {SELECT name FROM sqlite_master WHERE type='table'
! 268: UNION ALL
! 269: SELECT name FROM sqlite_temp_master WHERE type='table'}
! 270: $v(db) eval {PRAGMA database_list} {
! 271: if {$name!="temp" && $name!="main"} {
! 272: append cmd "UNION ALL SELECT name FROM $name.sqlite_master\
! 273: WHERE type='table'"
! 274: }
! 275: }
! 276: append cmd { ORDER BY 1}
! 277: } elseif {$word==".fullschema"} {
! 278: set pattern %
! 279: regexp {^.[a-z]+ +([^ ]+)} $cmd all pattern
! 280: set mode list
! 281: set header 0
! 282: set cmd "SELECT sql FROM sqlite_master WHERE tbl_name LIKE '$pattern'
! 283: AND sql NOT NULL UNION ALL SELECT sql FROM sqlite_temp_master
! 284: WHERE tbl_name LIKE '$pattern' AND sql NOT NULL"
! 285: $v(db) eval {PRAGMA database_list} {
! 286: if {$name!="temp" && $name!="main"} {
! 287: append cmd " UNION ALL SELECT sql FROM $name.sqlite_master\
! 288: WHERE tbl_name LIKE '$pattern' AND sql NOT NULL"
! 289: }
! 290: }
! 291: } elseif {$word==".schema"} {
! 292: set pattern %
! 293: regexp {^.[a-z]+ +([^ ]+)} $cmd all pattern
! 294: set mode list
! 295: set header 0
! 296: set cmd "SELECT sql FROM sqlite_master WHERE name LIKE '$pattern'
! 297: AND sql NOT NULL UNION ALL SELECT sql FROM sqlite_temp_master
! 298: WHERE name LIKE '$pattern' AND sql NOT NULL"
! 299: $v(db) eval {PRAGMA database_list} {
! 300: if {$name!="temp" && $name!="main"} {
! 301: append cmd " UNION ALL SELECT sql FROM $name.sqlite_master\
! 302: WHERE name LIKE '$pattern' AND sql NOT NULL"
! 303: }
! 304: }
! 305: } else {
! 306: return \
! 307: ".exit\n.mode line|list|column\n.schema ?TABLENAME?\n.tables"
! 308: }
! 309: }
! 310: set res {}
! 311: if {$mode=="list"} {
! 312: $v(db) eval $cmd x {
! 313: set sep {}
! 314: foreach col $x(*) {
! 315: append res $sep$x($col)
! 316: set sep |
! 317: }
! 318: append res \n
! 319: }
! 320: if {[info exists x(*)] && $header} {
! 321: set sep {}
! 322: set hdr {}
! 323: foreach col $x(*) {
! 324: append hdr $sep$col
! 325: set sep |
! 326: }
! 327: set res $hdr\n$res
! 328: }
! 329: } elseif {[string range $mode 0 2]=="col"} {
! 330: set y {}
! 331: $v(db) eval $cmd x {
! 332: foreach col $x(*) {
! 333: if {![info exists cw($col)] || $cw($col)<[string length $x($col)]} {
! 334: set cw($col) [string length $x($col)]
! 335: }
! 336: lappend y $x($col)
! 337: }
! 338: }
! 339: if {[info exists x(*)] && $header} {
! 340: set hdr {}
! 341: set ln {}
! 342: set dash ---------------------------------------------------------------
! 343: append dash ------------------------------------------------------------
! 344: foreach col $x(*) {
! 345: if {![info exists cw($col)] || $cw($col)<[string length $col]} {
! 346: set cw($col) [string length $col]
! 347: }
! 348: lappend hdr $col
! 349: lappend ln [string range $dash 1 $cw($col)]
! 350: }
! 351: set y [concat $hdr $ln $y]
! 352: }
! 353: if {[info exists x(*)]} {
! 354: set format {}
! 355: set arglist {}
! 356: set arglist2 {}
! 357: set i 0
! 358: foreach col $x(*) {
! 359: lappend arglist x$i
! 360: append arglist2 " \$x$i"
! 361: incr i
! 362: append format " %-$cw($col)s"
! 363: }
! 364: set format [string trimleft $format]\n
! 365: if {[llength $arglist]>0} {
! 366: foreach $arglist $y "append res \[format [list $format] $arglist2\]"
! 367: }
! 368: }
! 369: } elseif {$mode=="multicolumn"} {
! 370: set y [$v(db) eval $cmd]
! 371: set max 0
! 372: foreach e $y {
! 373: if {$max<[string length $e]} {set max [string length $e]}
! 374: }
! 375: set ncol [expr {int(80/($max+2))}]
! 376: if {$ncol<1} {set ncol 1}
! 377: set nelem [llength $y]
! 378: set nrow [expr {($nelem+$ncol-1)/$ncol}]
! 379: set format "%-${max}s"
! 380: for {set i 0} {$i<$nrow} {incr i} {
! 381: set j $i
! 382: while 1 {
! 383: append res [format $format [lindex $y $j]]
! 384: incr j $nrow
! 385: if {$j>=$nelem} break
! 386: append res { }
! 387: }
! 388: append res \n
! 389: }
! 390: } else {
! 391: $v(db) eval $cmd x {
! 392: foreach col $x(*) {append res "$col = $x($col)\n"}
! 393: append res \n
! 394: }
! 395: }
! 396: return [string trimright $res]
! 397: }
! 398:
! 399: # Change the line to the previous line
! 400: #
! 401: proc sqlitecon::Prior w {
! 402: upvar #0 $w v
! 403: if {$v(current)<=0} return
! 404: incr v(current) -1
! 405: set line [lindex $v(history) $v(current)]
! 406: sqlitecon::SetLine $w $line
! 407: }
! 408:
! 409: # Change the line to the next line
! 410: #
! 411: proc sqlitecon::Next w {
! 412: upvar #0 $w v
! 413: if {$v(current)>=$v(historycnt)} return
! 414: incr v(current) 1
! 415: set line [lindex $v(history) $v(current)]
! 416: sqlitecon::SetLine $w $line
! 417: }
! 418:
! 419: # Change the contents of the entry line
! 420: #
! 421: proc sqlitecon::SetLine {w line} {
! 422: upvar #0 $w v
! 423: scan [$w index insert] %d.%d row col
! 424: set start $row.$v(plength)
! 425: $w delete $start end
! 426: $w insert end $line
! 427: $w mark set insert end
! 428: $w yview insert
! 429: }
! 430:
! 431: # Called when the mouse button is pressed at position $x,$y on
! 432: # the console widget.
! 433: #
! 434: proc sqlitecon::Button1 {w x y} {
! 435: global tkPriv
! 436: upvar #0 $w v
! 437: set v(mouseMoved) 0
! 438: set v(pressX) $x
! 439: set p [sqlitecon::nearestBoundry $w $x $y]
! 440: scan [$w index insert] %d.%d ix iy
! 441: scan $p %d.%d px py
! 442: if {$px==$ix} {
! 443: $w mark set insert $p
! 444: }
! 445: $w mark set anchor $p
! 446: focus $w
! 447: }
! 448:
! 449: # Find the boundry between characters that is nearest
! 450: # to $x,$y
! 451: #
! 452: proc sqlitecon::nearestBoundry {w x y} {
! 453: set p [$w index @$x,$y]
! 454: set bb [$w bbox $p]
! 455: if {![string compare $bb ""]} {return $p}
! 456: if {($x-[lindex $bb 0])<([lindex $bb 2]/2)} {return $p}
! 457: $w index "$p + 1 char"
! 458: }
! 459:
! 460: # This routine extends the selection to the point specified by $x,$y
! 461: #
! 462: proc sqlitecon::SelectTo {w x y} {
! 463: upvar #0 $w v
! 464: set cur [sqlitecon::nearestBoundry $w $x $y]
! 465: if {[catch {$w index anchor}]} {
! 466: $w mark set anchor $cur
! 467: }
! 468: set anchor [$w index anchor]
! 469: if {[$w compare $cur != $anchor] || (abs($v(pressX) - $x) >= 3)} {
! 470: if {$v(mouseMoved)==0} {
! 471: $w tag remove sel 0.0 end
! 472: }
! 473: set v(mouseMoved) 1
! 474: }
! 475: if {[$w compare $cur < anchor]} {
! 476: set first $cur
! 477: set last anchor
! 478: } else {
! 479: set first anchor
! 480: set last $cur
! 481: }
! 482: if {$v(mouseMoved)} {
! 483: $w tag remove sel 0.0 $first
! 484: $w tag add sel $first $last
! 485: $w tag remove sel $last end
! 486: update idletasks
! 487: }
! 488: }
! 489:
! 490: # Called whenever the mouse moves while button-1 is held down.
! 491: #
! 492: proc sqlitecon::B1Motion {w x y} {
! 493: upvar #0 $w v
! 494: set v(y) $y
! 495: set v(x) $x
! 496: sqlitecon::SelectTo $w $x $y
! 497: }
! 498:
! 499: # Called whenever the mouse leaves the boundries of the widget
! 500: # while button 1 is held down.
! 501: #
! 502: proc sqlitecon::B1Leave {w x y} {
! 503: upvar #0 $w v
! 504: set v(y) $y
! 505: set v(x) $x
! 506: sqlitecon::motor $w
! 507: }
! 508:
! 509: # This routine is called to automatically scroll the window when
! 510: # the mouse drags offscreen.
! 511: #
! 512: proc sqlitecon::motor w {
! 513: upvar #0 $w v
! 514: if {![winfo exists $w]} return
! 515: if {$v(y)>=[winfo height $w]} {
! 516: $w yview scroll 1 units
! 517: } elseif {$v(y)<0} {
! 518: $w yview scroll -1 units
! 519: } else {
! 520: return
! 521: }
! 522: sqlitecon::SelectTo $w $v(x) $v(y)
! 523: set v(timer) [after 50 sqlitecon::motor $w]
! 524: }
! 525:
! 526: # This routine cancels the scrolling motor if it is active
! 527: #
! 528: proc sqlitecon::cancelMotor w {
! 529: upvar #0 $w v
! 530: catch {after cancel $v(timer)}
! 531: catch {unset v(timer)}
! 532: }
! 533:
! 534: # Do a Copy operation on the stuff currently selected.
! 535: #
! 536: proc sqlitecon::Copy w {
! 537: if {![catch {set text [$w get sel.first sel.last]}]} {
! 538: clipboard clear -displayof $w
! 539: clipboard append -displayof $w $text
! 540: }
! 541: }
! 542:
! 543: # Return 1 if the selection exists and is contained
! 544: # entirely on the input line. Return 2 if the selection
! 545: # exists but is not entirely on the input line. Return 0
! 546: # if the selection does not exist.
! 547: #
! 548: proc sqlitecon::canCut w {
! 549: set r [catch {
! 550: scan [$w index sel.first] %d.%d s1x s1y
! 551: scan [$w index sel.last] %d.%d s2x s2y
! 552: scan [$w index insert] %d.%d ix iy
! 553: }]
! 554: if {$r==1} {return 0}
! 555: if {$s1x==$ix && $s2x==$ix} {return 1}
! 556: return 2
! 557: }
! 558:
! 559: # Do a Cut operation if possible. Cuts are only allowed
! 560: # if the current selection is entirely contained on the
! 561: # current input line.
! 562: #
! 563: proc sqlitecon::Cut w {
! 564: if {[sqlitecon::canCut $w]==1} {
! 565: sqlitecon::Copy $w
! 566: $w delete sel.first sel.last
! 567: }
! 568: }
! 569:
! 570: # Do a paste opeation.
! 571: #
! 572: proc sqlitecon::Paste w {
! 573: if {[sqlitecon::canCut $w]==1} {
! 574: $w delete sel.first sel.last
! 575: }
! 576: if {[catch {selection get -displayof $w -selection CLIPBOARD} topaste]
! 577: && [catch {selection get -displayof $w -selection PRIMARY} topaste]} {
! 578: return
! 579: }
! 580: if {[info exists ::$w]} {
! 581: set prior 0
! 582: foreach line [split $topaste \n] {
! 583: if {$prior} {
! 584: sqlitecon::Enter $w
! 585: update
! 586: }
! 587: set prior 1
! 588: $w insert insert $line
! 589: }
! 590: } else {
! 591: $w insert insert $topaste
! 592: }
! 593: }
! 594:
! 595: # Enable or disable entries in the Edit menu
! 596: #
! 597: proc sqlitecon::EnableEditMenu w {
! 598: upvar #0 $w.t v
! 599: set m $v(editmenu)
! 600: if {$m=="" || ![winfo exists $m]} return
! 601: switch [sqlitecon::canCut $w.t] {
! 602: 0 {
! 603: $m entryconf Copy -state disabled
! 604: $m entryconf Cut -state disabled
! 605: }
! 606: 1 {
! 607: $m entryconf Copy -state normal
! 608: $m entryconf Cut -state normal
! 609: }
! 610: 2 {
! 611: $m entryconf Copy -state normal
! 612: $m entryconf Cut -state disabled
! 613: }
! 614: }
! 615: }
! 616:
! 617: # Prompt the user for the name of a writable file. Then write the
! 618: # entire contents of the console screen to that file.
! 619: #
! 620: proc sqlitecon::SaveFile w {
! 621: set types {
! 622: {{Text Files} {.txt}}
! 623: {{All Files} *}
! 624: }
! 625: set f [tk_getSaveFile -filetypes $types -title "Write Screen To..."]
! 626: if {$f!=""} {
! 627: if {[catch {open $f w} fd]} {
! 628: tk_messageBox -type ok -icon error -message $fd
! 629: } else {
! 630: puts $fd [string trimright [$w get 1.0 end] \n]
! 631: close $fd
! 632: }
! 633: }
! 634: }
! 635:
! 636: # Erase everything from the console above the insertion line.
! 637: #
! 638: proc sqlitecon::Clear w {
! 639: $w delete 1.0 {insert linestart}
! 640: }
! 641:
! 642: # An in-line editor for SQL
! 643: #
! 644: proc sqlitecon::_edit {origtxt {title {}}} {
! 645: for {set i 0} {[winfo exists .ed$i]} {incr i} continue
! 646: set w .ed$i
! 647: toplevel $w
! 648: wm protocol $w WM_DELETE_WINDOW "$w.b.can invoke"
! 649: wm title $w {Inline SQL Editor}
! 650: frame $w.b
! 651: pack $w.b -side bottom -fill x
! 652: button $w.b.can -text Cancel -width 6 -command [list set ::$w 0]
! 653: button $w.b.ok -text OK -width 6 -command [list set ::$w 1]
! 654: button $w.b.cut -text Cut -width 6 -command [list ::sqlitecon::Cut $w.t]
! 655: button $w.b.copy -text Copy -width 6 -command [list ::sqlitecon::Copy $w.t]
! 656: button $w.b.paste -text Paste -width 6 -command [list ::sqlitecon::Paste $w.t]
! 657: set ::$w {}
! 658: pack $w.b.cut $w.b.copy $w.b.paste $w.b.can $w.b.ok\
! 659: -side left -padx 5 -pady 5 -expand 1
! 660: if {$title!=""} {
! 661: label $w.title -text $title
! 662: pack $w.title -side top -padx 5 -pady 5
! 663: }
! 664: text $w.t -bg white -fg black -yscrollcommand [list $w.sb set]
! 665: pack $w.t -side left -fill both -expand 1
! 666: scrollbar $w.sb -orient vertical -command [list $w.t yview]
! 667: pack $w.sb -side left -fill y
! 668: $w.t insert end $origtxt
! 669:
! 670: vwait ::$w
! 671:
! 672: if {[set ::$w]} {
! 673: set txt [string trimright [$w.t get 1.0 end]]
! 674: } else {
! 675: set txt $origtxt
! 676: }
! 677: destroy $w
! 678: return $txt
! 679: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>