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>