A A
A A
Practical Programming in Tcl and Tk, Fourth Edition By Brent B. Welch , Ken Jones, Jeffrey Hobbs
Publisher: Prentice Hall PTR Pub Date: June 10, 2003 ISBN: 0-13-038560-3 Pages: 960
Practical Programming in Tcl/Tk is described as the "bible" for Tcl programmers. It is a guide to the Tcl/Tk programming language and GUI toolkit. This revision includes substantial updates to cover the new version 8.4-giving both an overview of the features, as well as details about every command in the language. The third edition, written on version 8.2, sold over 30,000 copies. Version 8.4 of Tcl - Tool Command Language-provides substantial updates to one of the most popular UNIX scripting languages. The latest release, includes the addition of a virtual filesystem (VFS), many additional programming widgets (spinbox, panedwindow, labelframe),and improved performance of about 20% over 8.3. The book provides a guide to the best ways to use the tooklit. It not only gives accurate details, but includes extensive examples that demonstrate the best way to use the toolkit. The authors are experts that have both developed the technology and used it to solve problems, so they have many valuable insights to relate to the readers. [ Team LiB ]
[ Team LiB ]
Practical Programming in Tcl and Tk, Fourth Edition By Brent B. Welch , Ken Jones, Jeffrey Hobbs
Publisher: Prentice Hall PTR Pub Date: June 10, 2003 ISBN: 0-13-038560-3 Pages: 960
Copyright List of Examples List of Tables Preface Why Tcl? Tcl and Tk Versions Extending Tcl and Tk Tcl on the World Wide Web Ftp Archives Newsgroups Who Should Read This Book How to Read This Book On-line Examples Typographic Conventions Hot Tips Book Organization What's New in the Fourth Edition Other Tcl Books First Edition Thanks Second Edition Thanks Third Edition Thanks Fourth Edition Thanks Contact the Author
Part I. Tcl Basics Chapter 1. Tcl Fundamentals Tcl Commands Hello, World! Variables Command Substitution Math Expressions Backslash Substitution Grouping with Braces and Double Quotes Procedures A Factorial Example More about Variables More about Math Expressions Comments Substitution and Grouping Summary Fine Points Reference Chapter 2. Getting Started The
source
Command
UNIX Tcl Scripts Windows Start Menu Macintosh OS 8/9 and ResEdit The
console
Command
Command-Line Arguments Predefined Variables Chapter 3. The Guestbook CGI Application A Quick Introduction to HTML CGI for Dynamic Pages The
guestbook.cgi Script
Defining Forms and Processing Form Data Handling Errors in CGI Scripts Next Steps Chapter 4. String Processing in Tcl
string Command The append Command The format Command The scan Command The binary Command
The Related Chapters Chapter 5. Tcl Lists Tcl Lists Constructing Lists
llength , lindex, and lrange linsert and lreplace Searching Lists: lsearch Sorting Lists: lsort
Getting List Elements: Modifying Lists:
The The
If Then Else Switch UNREGISTEREDWhile VERSION OF CHM Foreach For Break and Continue Catch UNREGISTEREDError VERSION OF CHM Return
global
Command
upvar upvar
array
Command
Building Data Structures with Arrays Chapter 9. Working with Files and Programs Running Programs with The
exec
file Command
Cross-Platform File Naming Manipulating Files and Directories File Attributes Input/Output Command Summary Opening Files for I/O Reading and Writing The Current Directory Matching File Names The
Part II. Advanced Tcl Chapter 10. Quoting Issues and Eval
list Command concat inside eval The uplevel Command The subst Command
Constructing Code with the Exploiting the
Chapter 11. Regular Expressions When to Use Regular Expressions Regular Expression Syntax Advanced Regular Expressions Syntax Summary The The
regexp regsub
Command Command
regsub
Other Commands That Use Regular Expressions Chapter 12. Script Libraries and Packages Locating Packages: The Using Packages Summary of Package Loading The
auto_path Variable
package unknown
Command
tclIndex File
Command
Interactive Conveniences Tcl Shell Library Environment Coding Style Chapter 13. Reflection and Debugging
namespace Command
after Command fileevent Command The vwait Command The fconfigure Command
The The
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Chapter 17. Socket Programming
Networking Extensions for Tcl Client Sockets Server Sockets The Echo Service
http Package
Basic Authentication Chapter 18. TclHttpd Web Server Integrating TclHttpd with Your Application Domain Handlers Application Direct URLs Document Types HTML + Tcl Templates Form Handlers Programming Reference Standard Application Direct URLs The TclHttpd Distribution Server Configuration Chapter 19. Multiple Interpreters and Safe-Tcl The
interp
Command
Creating Interpreters Safe Interpreters Command Aliases Hidden Commands Substitutions I/O from Safe Interpreters The Safe Base Security Policies Chapter 20. Safe-Tk and the Browser Plugin Tk in Child Interpreters The Browser Plugin Security Policies and Browser Plugin Configuring Security Policies Chapter 21. Multi-Threaded Tcl Scripts What are Threads? Thread Support in Tcl Getting Started with the Thread Extension Sending Messages to Threads
Preserving and Releasing Threads Error Handling Shared Resources Managing I/O Channels Shared Variables Mutexes and Condition Variables Thread Pools The
Thread
Package Commands
Chapter 22. Tclkit and Starkits Getting Started with Tclkit Virtual File Systems Using sdx to Bundle Applications Exploring the Virtual File System in a Starkit Creating
tclhttpd.kit
Part III. Tk Basics Chapter 23. Tk Fundamentals Hello, World! in Tk Naming Tk Widgets Configuring Tk Widgets Tk Widget Attributes and the Resource Database Summary of the Tk Commands Other Widget Sets Chapter 24. Tk by Example ExecLog The Example Browser A Tcl Shell Chapter 25. The Pack Geometry Manager Packing toward a Side Horizontal and Vertical Stacking The Cavity Model Packing Space and Display Space Resizing and Anchoring Packing Order Choosing the Parent for Packing Unpacking a Widget Packer Summary Window Stacking Order Chapter 26. The Grid Geometry Manager A Basic Grid Spanning Rows and Columns
-expand
grid Command
place
The
Basics
place
Command
Event Syntax Modifiers Event Sequences Virtual Events Generating Events Event Summary
Part IV. Tk Widgets Chapter 30. Buttons and Menus Button Commands and Scope Issues Buttons Associated with Tcl Variables Button Attributes Button Operations Menus and Menubuttons Menu Bindings and Events Manipulating Menus and Menu Entries Menu Attributes A Menu by Name Package Chapter 31. The Resource Database An Introduction to Resources Loading Option Database Files Adding Individual Database Entries Accessing the Database User-Defined Buttons User-Defined Menus Chapter 32. Simple Tk Widgets Frames, Labelframes, and Toplevel Windows The Label Widget The Message Widget The Scale Widget The
bell Command
Chapter 33. Scrollbars Using Scrollbars The Scrollbar Protocol The Scrollbar Widget Chapter 34. The Entry and Spinbox Widgets Using Entry Widgets Using Spinbox Widgets Entry and Spinbox Bindings Entry and Spinbox Attributes Programming Entry and Spinbox Widgets Chapter 35. The Listbox Widget Using Listboxes The Listbox Widget Listbox Bindings and Events Listbox Attributes Chapter 36. The Text Widget Text Indices Text Marks Text Tags The Selection Tag Bindings Searching Text Embedded Widgets Embedded Images Looking inside the Text Widget The Undo Mechanism Text Bindings and Events Text Operations Text Attributes Chapter 37. The Canvas Widget Canvas Coordinates Hello, World! The Min Max Scale Example Canvas Objects Canvas Operations Generating Postscript Canvas Attributes Hints
Part V. Tk Details Chapter 38. Selections and the Clipboard> The Selection Model
Chapter 39. Focus, Grabs, and Dialogs Standard Dialogs Custom Dialogs Animation with the
update
Command
Configuring Attributes
font Command
Text Attributes Gridding, Resizing, and Geometry A Font Selection Application Chapter 43. Send The
send Command
Part VI. C Programming Chapter 47. C Programming and Tcl Basic Concepts Creating a Loadable Package A C Command Procedure
autoconf
The Sample Extension Chapter 49. Writing a Tk Widget in C Initializing the Extension The Widget Data Structure The Widget Class Command The Widget Instance Command Configuring and Reconfiguring Attributes Specifying Widget Attributes Displaying the Clock The Window Event Procedure Final Cleanup Chapter 50. C Library Overview An Overview of the Tcl C Library An Overview of the Tk C Library
Part VII. Changes Chapter 51. Tcl 7.4/Tk 4.0 wish Obsolete Features The
cget Operation
pack info
Focus The
send Command
Menus Listboxes No
geometry Attribute
tk colormodel scrollincrement
bell Command
grid Geometry
Manager
The Text Widget The Entry Widget Chapter 53. Tcl 7.6/Tk 4.2 More
file Operations
tk scaling
Command
Application Embedding Native Menus and Menubars CDE Border Width Native Buttons and Scrollbars Images in Text Widgets
Chapter 55. Tcl/Tk 8.1 Unicode and Internationalization Thread Safety Advanced Regular Expressions New String Commands The DDE Extension Miscellaneous Chapter 56. Tcl/Tk 8.2 The Trf Patch Faster String Operations Empty Array Names Browser Plugin Compatibility Finer Control of Windows Serial Port Monitoring Regular Expression Expanded Syntax Option Chapter 57. Tcl/Tk 8.3 New File Manipulation Commands and Options New
Removing Duplicate List Elements with Deleting Elements from an Array Enhanced
clock
Features
Support for Delayed Package Loading in The Img Patch The Dash Patch Other New Tk Features The Patch Releases Chapter 58. Tcl/Tk 8.4 64-Bit Support
pkg_mkIndex
Additional Filesystem Features and Commands New and Enhanced List Commands Array Searching and Statistics Enhanced Support for Serial Communications New String Comparison Operators Command Tracing Additional Introspection Commands Other Tcl Changes New Tk Widgets Text Widget Undo Mechanism and Other Enhancements New
Displaying Both Text and an Image in a Widget New Button Relief Attributes Controlling the State of Entries and Listboxes More Window Manager Interaction Other Tk Changes Chapter 59. About The CD-ROM
Technical Support
Index
[ Team LiB ]
[ Team LiB ]
Copyright
Library of Congress Cataloging-in-Publication available Editorial/production supervision: Kathleen M. Caren Executive Editor: Mark Taub Editorial Assistant: Noreen Regina Marketing Manager: Kate Hargett Manufacturing Manager: Maura Zaldivar Cover Design Director: Jerry Votta 2003 Pearson Education Inc. Publishing as Prentice Hall PTR Upper Saddle River, NJ 07458 Prentice Hall books are widely used by corporations and government agencies for training, marketing, and resale. For information regarding corporate and government bulk discounts, contact: Corporate and Government Sales: (800) 382-3419 or [email protected] All products mentioned herein are trademarks or registered trademarks of their respective owners. All rights reserved. No part of this book may be reproduced, in any form or by any means, without permission in writing from the publisher. Printed in the United States of America 10 9 8 7 6 5 4 3 2 1 Pearson Education LTD. Pearson Education Australia PTY, Limited Pearson Education Singapore, Pte. Ltd. Pearson Education North Asia Ltd. Pearson Education Canada, Ltd. Pearson Educacin de Mexico, S.A. de C.V. Pearson Education-Japan Pearson Education Malaysia, Pte. Ltd.
Dedication
to
Jody, Christopher, Daniel, and Michael -Brent Dean, for his support and patience -Ken
[ Team LiB ]
List of Examples
1. Tcl Fundamentals 1.1 The "Hello, World!" example 1.2 Tcl variables 1.3 Command substitution 1.4 Simple arithmetic 1.5 Nested commands 1.6 Built-in math functions 1.7 Grouping expressions with braces 1.8 Quoting special characters with backslash 1.9 Continuing long lines with backslashes 1.10 Grouping with double quotes vs. braces 1.11 Embedded command and variable substitution 1.12 Defining a procedure 1.13 A while loop to compute factorial 1.14 A recursive definition of factorial 1.15 Using set to return a variable value 1.16 Embedded variable references 1.17 Using info to determine if a variable exists 1.18 Controlling precision with tcl_precision 2. Getting Started 2.1 A standalone Tcl script on UNIX 2.2 A standalone Tk script on UNIX 2.3 Using /bin/sh to run a Tcl script 2.4 The EchoArgs script 3. The Guestbook CGI Application 3.1 A simple CGI script
3.2 Output of Example 3-1 3.3 The guestbook.cgi script, version 1 3.4 The Cgi_Header procedure 3.5 The guestbook.cgi script, version 2
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE 3.6 Initial output of guestbook.cgi with no data
3.7 Output of guestbook.cgi with guestbook data 3.8 The newguest.html form 3.9 The newguest.cgi script UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE 3.10 The newguest.cgi script with error handling 4. String Processing in Tcl 4.1 Comparing strings with string compare 4.2 Comparing strings with string equal 4.3 Comparing strings with eq 4.4 Mapping Microsoft World special characters to ASCII 5. Tcl Lists 5.1 Constructing a list with the list command 5.2 Using lappend to add elements to a list 5.3 Using lset to set an element of a list 5.4 Using concat to splice lists together 5.5 Double quotes compared to the concat and list commands 5.6 Modifying lists with lreplace 5.7 Deleting a list element by value 5.8 Sorting a list using a comparison function 5.9 Use split to turn input data into Tcl lists 5.10 Implementing join in Tcl 6. Control Structure Commands 6.1 A conditional if then else command 6.2 Chained conditional with elseif 6.3 Using switch for an exact match 6.4 Using switch with substitutions in the patterns
6.5 A switch with "fall through" cases 6.6 Comments in switch commands 6.7 A while loop to read standard input 6.8 Looping with foreach 6.9 Parsing command-line arguments 6.10 Using list with foreach 6.11 Multiple loop variables with foreach 6.12 Multiple value lists with foreach 6.13 A for loop 6.14 A standard catch phrase 6.15 A longer catch phrase 6.16 There are several possible return values from catch 6.17 Raising an error 6.18 Preserving errorInfo when calling error 6.19 Raising an error with return 7. Procedures and Scope 7.1 Default parameter values 7.2 Variable number of arguments 7.3 Variable scope and Tcl procedures 7.4 A random number generator 7.5 Print variable by name 7.6 Improved incr procedure 8. Tcl Arrays 8.1 Using arrays 8.2 Referencing an array indirectly 8.3 Referencing an array indirectly using upvar 8.4 ArrayInvert inverts an array 8.5 Using arrays for records, version 1 8.6 Using arrays for records, version 2 8.7 Using arrays for records, version 3
8.8 Using a list to implement a stack 8.9 Using an array to implement a stack 8.10 A list of arrays 8.11 A list of arrays
UNREGISTERED VERSION OFin-memory PDF CONVERTER By THETA-SOFTWARE 8.12 A simple CHM TO database
9. Working with Files and Programs 9.1 Using exec on a process pipeline 9.2 Comparing CHM TO times UNREGISTERED VERSION OF file modify PDF CONVERTER By THETA-SOFTWARE 9.3 Determining whether pathnames reference the same file 9.4 Opening a file for writing 9.5 A more careful use of open 9.6 Opening a process pipeline 9.7 Prompting for input 9.8 A read loop using gets 9.9 A read loop using read and split 9.10 Copy a file and translate to native format 9.11 Finding a file by name 9.12 Printing environment variable values 10. Quoting Issues and Eval 10.1 Using list to construct commands 10.2 Generating procedures dynamically with a template 10.3 Using eval with $args 10.4 lassign: list assignment with foreach 10.5 The File_Process procedure iterates over lines in a file 11. Regular Expressions 11.1 Expanded regular expressions allow comments 11.2 Using regular expressions to parse a string 11.3 A pattern to match URLs 11.4 An advanced regular expression to match URLs 11.5 The Url_Decode procedure
11.6 The Cgi_List and Cgi_Query procedures 11.7 Cgi_Parse and Cgi_Value store query data in the cgi array 11.8 Html_DecodeEntity 11.9 Html_Parse 12. Script Libraries and Packages 12.1 Maintaining a tclIndex file 12.2 Loading a tclIndex file 13. Reflection and Debugging 13.1 Calculating clicks per second 13.2 Printing a procedure definition 13.3 Mapping form data onto procedure arguments 13.4 Finding built-in commands 13.5 Getting a trace of the Tcl call stack 13.6 A procedure to read and evaluate commands 13.7 Using info script to find related files 13.8 Tracing variables 13.9 Creating array elements with array traces 13.10 Interactive history usage 13.11 Implementing special history syntax 13.12 A Debug procedure 13.13 Time Stamps in log records 14. Namespaces 14.1 Random number generator using namespaces 14.2 Random number generator using qualified names 14.3 Nested namespaces 14.4 The code procedure to wrap callbacks 14.5 Listing commands defined by a namespace 15. Internationalization 15.1 MIME character sets and file encodings 15.2 Using scripts in nonstandard encodings
15.3 Three sample message catalog files 15.4 Using msgcat::mcunknown to share message catalogs 16. Event-Driven Programming 16.1 A read event file handler
UNREGISTERED VERSION vwait to activate the event loop 16.2 Using OF CHM TO PDF CONVERTER By THETA-SOFTWARE
16.3 A read event file handler for a nonblocking channel 17. Socket Programming 17.1 Opening a client socket with a timeout UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE 17.2 Opening a server socket 17.3 The echo service 17.4 A client of the echo service 17.5 Opening a connection to an HTTP server 17.6 Opening a connection through a HTTP proxy 17.7 Http_Head validates a URL 17.8 Using Http_Head 17.9 Http_Get fetches the contents of a URL" endterm="ch17list09.title"/> 17.10 HttpGetText reads text URLs 17.11 HttpCopyDone is used with fcopy 17.12 Downloading files with http::geturl 17.13 Basic Authentication using http::geturl 18. TclHttpd Web Server 18.1 The hello.tcl file implements /hello/world 18.2 A simple URL domain 18.3 Application Direct URLs 18.4 Alternate types for Application Direct URLs 18.5 A sample document type handler 18.6 A one-level site structure 18.7 A two-level site structure 18.8 A HTML + Tcl template file 18.9 SitePage template procedure, version 1
18.10 SiteMenu and SiteFooter template procedures 18.11 The SiteLink procedure 18.12 Mail form results with /mail/forminfo 18.13 Mail message sent by /mail/forminfo 18.14 Processing mail sent by /mail/forminfo 18.15 Processing mail sent by /mail/forminfo, Safe-Tcl version 18.16 A self-checking form procedure 18.17 A page with a self-checking form 18.18 Generating a table with html::foreach 18.19 The /debug/source Application Direct URL implementation 19. Multiple Interpreters and Safe-Tcl 19.1 Creating and deleting an interpreter 19.2 Creating a hierarchy of interpreters 19.3 A command alias for exit 19.4 Querying aliases 19.5 Dumping aliases as Tcl commands 19.6 Substitutions and hidden commands 19.7 Opening a file for an unsafe interpreter 19.8 The Safesock security policy 19.9 The Tempfile security policy 19.10 Restricted puts using hidden commands 19.11 A safe after command 20. Safe-Tk and the Browser Plugin 20.1 Using EMBED to insert a Tclet 21. Multi-Threaded Tcl Scripts 21.1 Creating a separate thread to perform a lengthy operation 21.2 Initializing a thread before entering its event loop 21.3 Creating several threads in an application 21.4 Using joinable threads to detect thread termination 21.5 Examples of synchronous message sending
21.6 Using a return variable with synchronous message sending 21.7 Executing commands after thread::wait returns 21.8 Creating a custom thread error handler 21.9 A basic implementation of a logging thread
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE 21.10 Deferring socket transfer until after the connection callback
21.11 Working around Tcl's socket transfer bug 21.12 A multi-threaded echo server 21.13 Using a CHM TO PDF a shared resource UNREGISTERED VERSION OFmutex to protect CONVERTER By THETA-SOFTWARE 21.14 Standard condition variable use for a signalling thread 21.15 Standard condition variable use for a waiting thread 22. Tclkit and Starkits 22.1 Accessing a Zip file through a VFS 22.2 The output of sdx lsk hello.kit 22.3 The main program of a Starkit 22.4 The pkgIndex.tcl in a Starkit 22.5 A Starkit that examines its Virtual File System 22.6 Creating a simple Starkit 22.7 The contents of the tclhttpd.vfs directory, version 1 22.8 The main program for the TclHttpd Starkit, version 1 22.9 Contents of the tclhttpd.vfs directory, version 2 22.10 The main program for the TclHttpd Starkit, version 2 22.11 The Standard Tcl Library Starkit main.tcl file 22.12 The main program for TclHttpd Starkit, version 3 22.13 Examining the views in a Metakit database 22.14 Examining data in a Metakit view 22.15 Selecting data with mk::select 22.16 Creating a new view 22.17 Adding data to a view 22.18 Storing data in a Starkit 23. Tk Fundamentals
23.1 "Hello, World!" Tk program 23.2 Looking at all widget attributes 24. Tk by Example 24.1 Logging the output of a program run with exec 24.2 A platform-specific cancel event 24.3 A browser for the code examples in the book 24.4 A Tcl shell in a text widget 24.5 Macintosh look and feel 24.6 Windows look and feel 24.7 UNIX look and feel 25. The Pack Geometry Manager 25.1 Two frames packed inside the main frame 25.2 Turning off geometry propagation 25.3 A horizontal stack inside a vertical stack 25.4 Even more nesting of horizontal and vertical stacks 25.5 Mixing bottom and right packing sides 25.6 Filling the display into extra packing space 25.7 Using horizontal fill in a menu bar 25.8 The effects of internal padding (-ipady) 25.9 Button padding vs. packer padding 25.10 The look of a default button 25.11 Resizing without the expand option 25.12 Resizing with expand turned on 25.13 More than one expanding widget 25.14 Setup for anchor experiments 25.15 The effects of noncenter anchors 25.16 Animating the packing anchors 25.17 Controlling the packing order 25.18 Packing into other relatives 26. The Grid Geometry Manager
26.1 A basic grid 26.2 A grid with sticky settings 26.3 A grid with row and column specifications 26.4 A grid with external padding
UNREGISTERED VERSION OF CHM TOpadding 26.5 A grid with internal PDF CONVERTER By THETA-SOFTWARE
26.6 All combinations of -sticky settings 26.7 Explicit row and column span 26.8 Grid syntax row TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM and column span 26.9 Row padding compared to cell padding 26.10 Gridding a text widget and scrollbar 26.11 Uniform column width 27. The Place Geometry Manager 27.1 Centering a window with place 27.2 Covering a window with place 27.3 Combining relative and absolute sizes 27.4 Positioning a window above a sibling with place 27.5 Pane_Create sets up vertical or horizontal panes 27.6 PaneDrag adjusts the percentage 27.7 PaneGeometry updates the layout 28. The Panedwindow Widget 28.1 A panedwindow with complex managed widgets 29. Binding Commands to Events 29.1 Bindings on different binding tags 29.2 Output from the UNIX xmodmap program 29.3 Emacs-like binding convention for Meta and Escape 29.4 Virtual events for cut, copy, and paste 30. Buttons and Menus 30.1 A troublesome button command 30.2 Fixing the troublesome situation 30.3 A button associated with a Tcl procedure
30.4 Radiobuttons and checkbuttons 30.5 A command on a radiobutton or checkbutton 30.6 A menu sampler 30.7 A menu bar in Tk 8.0 30.8 Using the <<MenuSelect>> virtual event 30.9 A simple menu by name package 30.10 Using the Tk 8.0 menu bar facility 30.11 MenuGet maps from name to menu 30.12 Adding menu entries 30.13 A wrapper for cascade entries 30.14 Using the menu by name package 30.15 Keeping the accelerator display up to date 31. The Resource Database 31.1 Reading an option database file 31.2 A file containing resource specifications 31.3 Using resources to specify user-defined buttons 31.4 Resource_ButtonFrame defines buttons based on resources 31.5 Using Resource_ButtonFrame 31.6 Specifying menu entries via resources 31.7 Defining menus from resource specifications 31.8 Resource_GetFamily merges user and application resources 32. Simple Tk Widgets 32.1 Labelframe example 32.2 Using the labelAnchor option to position a labelframe's anchor 32.3 Associating an existing label widget with a labelframe 32.4 Macintosh window styles 32.5 A label that displays different strings 32.6 The message widget formats long lines of text 32.7 Controlling the text layout in a message widget 32.8 A scale widget
33. Scrollbars 33.1 A text widget and two scrollbars 33.2 Scroll_Set manages optional scrollbars 33.3 Listbox with optional scrollbars
UNREGISTEREDThe Entry and Spinbox Widgets CONVERTER By THETA-SOFTWARE 34. VERSION OF CHM TO PDF
34.1 Associating entry widgets with variables and commands 34.2 Restricting entry text to integer values 34.3 Reestablishing validation CONVERTER UNREGISTERED VERSION OF CHM TO PDFusing an idle taskBy THETA-SOFTWARE 34.4 A simple spinbox with calculated values 34.5 Formatting numeric values in a spinbox 34.6 Enumerating spinbox values and wrapping 34.7 Using the spinbox readonly state 35. The Listbox Widget 35.1 Using -listvariable to link a listbox and variable 35.2 Choosing items from a listbox 35.3 Using the <<ListboxSelect>> virtual event 36. The Text Widget 36.1 Tag configurations for basic character styles 36.2 Line spacing and justification in the text widget 36.3 An active text button 36.4 Delayed creation of embedded widgets 36.5 Using embedded images for a bulleted list 36.6 Finding the current range of a text tag 36.7 Dumping the text widget 36.8 Dumping the text widget with a command callback 37. The Canvas Widget 37.1 A large scrolling canvas 37.2 The canvas "Hello, World!" example 37.3 A min max scale canvas example 37.4 Moving the markers for the min max scale
37.5 Canvas arc items 37.6 Canvas bitmap items 37.7 Canvas image items 37.8 A canvas stroke drawing example 37.9 Canvas oval items 37.10 Canvas polygon items 37.11 Dragging out a box 37.12 Simple edit bindings for canvas text items 37.13 Using a canvas to scroll a set of widgets 37.14 Generating Postscript from a canvas 38. Selections and the Clipboard 38.1 Paste the PRIMARY or CLIPBOARD selection 38.2 Separate paste actions 38.3 Bindings for canvas selection 38.4 Selecting objects 38.5 A canvas selection handler 38.6 The copy and cut operations 38.7 Pasting onto the canvas 39. Focus, Grabs, and Dialogs 39.1 Procedures to help build dialogs 39.2 A simple dialog 39.3 A feedback procedure 40. Tk Widget Attributes 40.1 Equal-sized labels 40.2 3D relief sampler 40.3 Padding provided by labels and buttons 40.4 Anchoring text in a label or button 40.5 Borders and padding 41. Color, Images, and Cursors 41.1 Resources for reverse video
41.2 Computing a darker color 41.3 Specifying an image for a widget 41.4 Specifying a bitmap for a widget 41.5 The built-in bitmaps
45.10 Tracing a Tcl variable in a preference item 46. A User Interface to Bindings 46.1 A user interface to widget bindings 46.2 Bind_Display presents the bindings for a widget or class 46.3 Related listboxes are configured to select items together 46.4 Controlling a pair of listboxes with one scrollbar 46.5 Drag-scrolling a pair of listboxes together 46.6 An interface to define bindings 46.7 Defining and saving bindings 47. C Programming and Tcl 47.1 The initialization procedure for a loadable package 47.2 The RandomCmd C command procedure 47.3 The RandomObjCmd C command procedure 47.4 The Tcl_Obj structure 47.5 The Plus1ObjCmd procedure 47.6 The Blob and BlobState data structures 47.7 The Blob_Init and BlobCleanup procedures 47.8 The BlobCmd command procedure 47.9 BlobCreate and BlobDelete 47.10 The BlobNames procedure 47.11 \The BlobN and BlobData procedures 47.12 The BlobCommand and BlobPoke procedures 47.13 A canonical Tcl main program and Tcl_AppInit 47.14 A canonical Tk main program and Tk_AppInit 47.15 Calling C command procedure directly with Tcl_Invoke 48. Compiling Tcl and Extensions Writing a Tk Widget in C 49.1 The Clock_Init procedure 49.2 The Clock widget data structure 49.3 The ClockCmd command procedure
49.4 The ClockObjCmd command procedure 49.5 The ClockInstanceCmd command procedure 49.6 The ClockInstanceObjCmd command procedure 49.7 ClockConfigure allocates resources for the widget
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE 49.8 ClockObjConfigure allocates resources for the widget
49.9 The Tk_ConfigSpec typedef 49.10 Configuration specs for the clock widget 49.11 The OF CHM TO typedef UNREGISTERED VERSIONTk_OptionSpecPDF CONVERTER By THETA-SOFTWARE 49.12 The Tk_OptionSpec structure for the clock widget 49.13 ComputeGeometry computes the widget's size 49.14 The ClockDisplay procedure 49.15 The ClockEventProc handles window events 49.16 The ClockDestroy cleanup procedure 49.17 The ClockObjDelete command 500C Library Overview [ Team LiB ]
[ Team LiB ]
List of Tables
1. Tcl Fundamentals 1-1 Backslash sequences 1-2 Arithmetic operators from highest to lowest precedence 1-3 Built-in math functions 1-4 Built-in Tcl commands 2. Getting Started 2-1 Wish command line options 2-2 Variables defined by tclsh and wish 3. The Guestbook CGI Application 3-1 HTML tags used in the examples 4. String Processing in Tcl 4-1 The string command 4-2 Matching characters used with string match 4-3 Character class names 4-4 Format conversions 4-5 Format flags 4-6 Binary conversion types 5. Tcl Lists 5-1 List-related commands 5-2 Options to the lsearch command 8. Tcl Arrays 8-1 The array command 9. Working with Files and Programs 9-1 Summary of the exec syntax for I/O redirection 9-2 The file command options 9-3 Array elements defined by file stat
9-4 Platform-specific file attributes 9-5 Tcl commands used for file access 9-6 Summary of the open access arguments 9-7 Summary of POSIX flags for the access argument
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE 9-8 glob command options
9-9 The registry command 9-10 The registry data types 11. Regular Expressions UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE 11-1 Additional advanced regular expression syntax 11-2 Backslash escapes in regular expressions 11-3 Character classes 11-4 Embedded option characters used with the (?x) syntax 11-5 Options to the regexp command 11-6 Sample regular expressions 12. Script Libraries and Packages 12-1 Options to the pkg_mkIndex command 12-2 The package command 13. Reflection and Debugging 13-1 clock format keywords 13-2 The clock command 13-3 The info command 13-4 The history command 13-5 Special history syntax 14. Namespaces 14-1 The namespace command 15. Internationalization 15-1 The encoding command 15-2 The msgcat package 16. Event-Driven Programming 16-1 The after command
16-2 The fileevent command 16-3 I/O channel properties controlled by fconfigure 16-4 Serial line properties controlled by fconfigure 16-5 End of line translation modes 17. Socket Programming 17-1 Options to the http::geturl command 17-2 The http support procedures 17-3 Elements of the http::geturl state array 18. TclHttpd Web Server 18-1 Httpd support procedures 18-2 Url support procedures 18-3 Doc procedures for configuration 18-4 Doc procedures for generating responses 18-5 Doc procedures that support template processing 18-6 Elements of the page array 18-7 Elements of the env array 18-8 Status Application Direct URLs 18-9 Debug Application Direct URLs 18-10 Application Direct URLS that email form results 18-11 Basic TclHttpd parameters 19. Multiple Interpreters and Safe-Tcl 19-1 The interp command 19-2 Commands hidden from safe interpreters 19-3 The safe base master interface 19-4 The safe base slave aliases 20. Safe-Tk and the Browser Plugin 20-1 Tk commands omitted from safe interpreters 20-2 Aliases defined by the browser package 20-3 The browser::getURL callbacks 21. Multi-Threaded Tcl Scripts
21-1 The commands of the thread namespace 21-2 Thread configuration options 21-3 The commands of the tsv namespace 21-4 The commands of the tpool namespace
UNREGISTERED VERSION OF CHM TO PDF options 21-5 Thread pool configuration CONVERTER By THETA-SOFTWARE
22. Tclkit and Starkits 22-1 Return values of the starkit::startup procedure 23. VERSION OF UNREGISTEREDTk FundamentalsCHM TO PDF CONVERTER By THETA-SOFTWARE 23-1 Tk widget-creation commands 23-2 Tk widget-manipulation commands 23-3 Tk support procedures 25. The Pack Geometry Manager 25-1 The pack command 25-2 Packing options 26. The Grid Geometry Manager 26-1 The grid command 26-2 Grid widget options 27. The Place Geometry Manager 27-1 The place command 27-2 Placement options 28. The Panedwindow Widget 28-1 Panedwindow operations 28-2 Panedwindow attributes 28-3 Panedwindow managed widget options 29. Binding Commands to Events 29-1 Event types 29-2 Event modifiers 29-3 The event command 29-4 A summary of the event keywords 30. Buttons and Menus
30-1 Resource names of attributes for all button widgets 30-2 Button operations 30-3 Menu entry index keywords 30-4 Menu operations 30-5 Menu attribute resource names 30-6 Attributes for menu entries 32. Simple Tk Widgets 32-1 Attributes for frame, labelframe, and toplevel widgets 32-2 Label Attributes 32-3 Message Attributes 32-4 Bindings for scale widgets 32-5 Attributes for scale widgets 32-6 Operations on the scale widget 33. Scrollbars 33-1 Attributes for the scrollbar widget 33-2 Bindings for the scrollbar widget 33-3 Operations on the scrollbar widget 34. The Entry and Spinbox Widgets 34-1 Entry and spinbox validation substitutions 34-2 Entry and spinbox bindings 34-3 Entry and spinbox attribute resource names 34-4 Entry and spinbox indices 34-5 Entry and spinbox operations 35. The Listbox Widget 35-1 Listbox indices 35-2 Listbox operations 35-3 Listbox item configuration options 35-4 The values for the selectMode of a listbox 35-5 Bindings for browse selection mode 35-6 Bindings for single selection mode
35-7 Bindings for extended selection mode 35-8 Bindings for multiple selection mode 35-9 Listbox scroll bindings 35-10 Listbox attribute resource names
38. Selections and the Clipboard 38-1 The selection command 38-2 The clipboard command 39. Focus, Grabs, and Dialogs 39-1 Options to tk_messageBox 39-2 Options to the standard file and directory dialogs 39-3 Options to tk_chooseColor 39-4 The focus command 39-5 The grab command 39-6 he tkwait command 40. Tk Widget Attributes 40-1 Size attribute resource names 40-2 Border and relief attribute resource names 40-3 Highlight attribute resource names 40-4 Layout attribute resource names 41. Color, Images, and Cursors 41-1 Color attribute resource names 41-2 Windows system colors 41-3 Macintosh system colors 41-4 Visual classes for displays 41-5 Summary of the image command 41-6 Bitmap image options 41-7 Photo image attributes 41-8 Photo image operations 41-9 Copy options for photo images 41-10 Read options for photo images 41-11 Write options for photo images 41-12 Cursor attribute resource names 42. Fonts and Text Attributes 42-1 Font attributes
42-2 X Font specification components 42-3 Layout attribute resource names 42-4 The font command 42-5 Selection attribute resource names
55. Tcl/Tk 8.1 55-1 The testthread command 55-2 The dde command options [ Team LiB ]
[ Team LiB ]
Preface
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE and an Tcl stands for Tool Command Language. Tcl is really two things: a scripting language,
interpreter for that language that is designed to be easy to embed into your application. Tcl and its associated graphical user-interface toolkit, Tk, were designed and crafted by Professor John Ousterhout of the University of California, Berkeley. You can find these packages on the Internet and use them freely in your application, even if it is commercial. The Tcl interpreter has been ported from UNIX to DOS, PalmOS, VMS, Windows, OS/2, NT, and Macintosh UNREGISTERED VERSION OF CHM TO PDF CONVERTERwindow system to Windows and environments. The Tk toolkit has been ported from the X By THETA-SOFTWARE Macintosh. I first heard about Tcl in 1988 while I was Ousterhout's Ph.D. student at Berkeley. We were designing a network operating system, Sprite. While the students hacked on a new kernel, John wrote a new editor and terminal emulator. He used Tcl as the command language for both tools so that users could define menus and otherwise customize those programs. This was in the days of X10, and he had plans for an X toolkit based on Tcl that would help programs cooperate with each other by communicating with Tcl commands. To me, this cooperation among tools was the essence of Tcl. This early vision imagined that applications would be large bodies of compiled code and a small amount of Tcl used for configuration and high-level commands. John's editor, mx, and the terminal emulator, tx, followed this model. While this model remains valid, it has also turned out to be possible to write entire applications in Tcl. This is because the Tcl/Tk shell, wish, provides access to other programs, the file system, network sockets, plus the ability to create a graphical user interface. For better or worse, it is now common to find applications that contain thousands of lines of Tcl script. This book was written because, while I found it enjoyable and productive to use Tcl and Tk, there were times when I was frustrated. In addition, working at Xerox PARC, with many experts in languages and systems, I was compelled to understand both the strengths and weaknesses of Tcl and Tk. Although many of my colleagues adopted Tcl and Tk for their projects, they were also just as quick to point out its flaws. In response, I have built up a set of programming techniques that exploit the power of Tcl and Tk while avoiding troublesome areas. This book is meant as a practical guide to help you get the most out of Tcl and Tk and avoid some of the frustrations I experienced. It has been about 14 years since I was introduced to Tcl, and about eight years since the first edition of this book. During several of those years I worked under John Ousterhout, first at Sun Microsystems and then at Scriptics Corporation. There I remained mostly a Tcl programmer while others in our group have delved into the C implementation of Tcl itself. I've built applications like HTML editors, email user interfaces, Web servers, and the customer database we ran our business on. This experience is reflected in this book. The bulk of the book is about Tcl scripting, and the aspects of C programming to create Tcl extensions is given a lighter treatment. I have been lucky to remain involved in the core Tcl development, and I hope I can pass along the insights I have gained by working with Tcl. [ Team LiB ]
[ Team LiB ]
Why Tcl?
As a scripting language, Tcl is similar to other UNIX shell languages such as the Bourne Shell (sh), the C Shell (csh), the Korn Shell (ksh), and Perl. Shell programs let you execute other programs. They provide enough programmability (variables, control flow, and procedures) to let you build complex scripts that assemble existing programs into a new tool tailored for your needs. Shells are wonderful for automating routine chores. It is the ability to easily add a Tcl interpreter to your application that sets it apart from other shells. Tcl fills the role of an extension language that is used to configure and customize applications. There is no need to invent a configuration file format or a command language for your new application, or struggle to provide some sort of user-programmability for your tool. Instead, by adding a Tcl interpreter, you structure your application as a set of primitive operations that can be composed by a script to best suit the needs of your users. It also allows other programs to have programmatic control over your application, leading to suites of applications that work well together. The Tcl C library has clean interfaces and is simple to use. The library implements the basic interpreter and a set of core scripting commands that implement variables, flow control, and procedures (see page 22). There is also a broad set of APIs that access operating system services to run other programs, access the file system, and use network sockets. Tk adds commands to create graphical user interfaces. The Tcl and Tk C APIs provide a "virtual machine" that is portable across UNIX, Windows, and Macintosh environments. The Tcl virtual machine is extensible because your application can define new Tcl commands. These commands are associated with a C or C++ procedure that your application provides. The result is applications that are split into a set of primitives written in a compiled language and exported as Tcl commands. A Tcl script is used to compose the primitives into the overall application. The script layer has access to shell-like capability to run other programs, has access to the file system, and can call directly into the compiled part of the application through the Tcl commands you define. In addition, from the C programming level, you can call Tcl scripts, set and query Tcl variables, and even trace the execution of the Tcl interpreter. There are many Tcl extensions freely available on the Internet. Most extensions include a C library that provides some new functionality, and a Tcl interface to the library. Examples include database access, telephone control, MIDI controller access, and expect, which adds Tcl commands to control interactive programs. The most notable extension is Tk, a toolkit for graphical user interfaces. Tk defines Tcl commands that let you create and manipulate user interface widgets. The script-based approach to user interface programming has three benefits: Development is fast because of the rapid turnaround; there is no waiting for long compilations. The Tcl commands provide a higher-level interface than most standard C library userinterface toolkits. Simple user interfaces require just a handful of commands to define them. At the same time, it is possible to refine the user interface in order to get every detail just so. The fast turnaround aids the refinement process. The user interface can be factored out from the rest of your application. The developer
can concentrate on the implementation of the application core and then fairly painlessly work up a user interface. The core set of Tk widgets is often sufficient for all your user interface needs. However, it is also possible to write custom Tk widgets in C, and again there are many contributed Tk widgets available on the network. There are other choices for extension languages that include Visual Basic, Scheme, Elisp, Perl, Python, Ruby and Javascript. Your choice between them is partly a matter of taste. Tcl has simple constructs and looks somewhat like C. It is easy to UNREGISTERED VERSION OF CHM TO PDF CONVERTER addTHETA-SOFTWAREwriting C By new Tcl primitives by procedures. Tcl is very easy to learn, and I have heard many great stories of users completing impressive projects in a short amount of time (e.g., a few weeks), even though they never used Tcl before. Java has exploded onto the computer scene since this book was first published. Java is a great systems programming language that in the long run could displace C and C++. This is fine for UNREGISTERED VERSION OF CHM TO PDF CONVERTER By in any system programming THETA-SOFTWARE Tcl, which is designed to glue together building blocks written language. Tcl was designed to work with C, but has been adapted to work with the Java Virtual Machine. Where I say "C or C++", you can now say "C, C++, or Java," but the details are a bit different with Java. This book does not describe the Tcl/Java interface, but you can find TclBlend on the CD-ROM. TclBlend loads the Java Virtual Machine into your Tcl application and lets you invoke Java methods. It also lets you implement Tcl commands in Java instead of C or C++. Jacl is a Tcl interpreter written in Java. It has some limitations compared with the native C-based Tcl interpreter, but Jacl is great if you cannot use the native interpreter. Javascript is a language from Netscape that is designed to script interactions with Web pages. Javascript is important because of its use in HTML user interfaces. However, Tcl provides a more general purpose scripting solution that can be used in a wide variety of applications. The Tcl/Tk Web browser plugin provides a way to run Tcl in your browser. It turns out to be more of a Java alternative than a JavaScript alternative. The plugin lets you run Tcl applications inside your browser, while JavaScript gives you fine grain control over the browser and HTML display. The plugin is described in Chapter 20. [ Team LiB ]
[ Team LiB ]
Tcl/Tk 8.3 adds a broad collection of enhancements to Tcl and Tk. Tk started to get some long deserved attention with adoption of the Dash and Image patches from Jan Nijtmans. The 8.3.0 release was in February, 2000, and the last patch release, 8.3.5, was made in October, 2002. Tcl/Tk 8.4 features a focus on performance, the addition of the Virtual File System Interface, and 3 new core Tk widgets: spinbox, labeledframe, and panedwindow. This release was a long time in UNREGISTERED VERSION OF CHM development. The first beta release was in June, 2000, and the TO PDF CONVERTER By THETA-SOFTWARE 8.4.2 release was made in March, 2003. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
http://www.purl.org/NET/Tcl-FAQ/
[ Team LiB ]
Ftp Archives
These are some of the FTP sites that maintain Tcl archives: ftp://ftp.tcl.tk/pub/tcl ftp://src.doc.ic.ac.uk/packages/tcl/ ftp://ftp.luth.se/pub/unix/tcl/ ftp://ftp.sunet.se/pub/lang/tcl ftp://ftp.cs.columbia.edu/archives/tcl ftp://ftp.funet.fi/pub/languages/tcl You can use a World Wide Web browser like Mozilla, Netscape, Internet Explorer, or Lynx to access these sites. [ Team LiB ]
[ Team LiB ]
Newsgroups
The comp.lang.tcl newsgroup TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM is very active. It provides a forum for questions and answers about Tcl. Announcements about Tcl extensions and applications are posted to the comp.lang.tcl.announce newsgroup. The following web service provides a convenient way to read newsgroups. Enter comp.lang.tcl in the search field on this page: http://groups.google.com
[ Team LiB ]
[ Team LiB ]
I recommend the on-line manual pages for the Tcl and Tk commands. They provide a detailed reference UNREGISTERED guide to each command. This book summarizes much of the information from the VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE manual pages, but it does not provide the complete details, which can vary from release to release. HTML versions of the on-line manual pages can be found on the CD-ROM that comes with this book. [ Team LiB ]
[ Team LiB ]
On-line Examples
The book comes with a CD-ROM that has source code for all of the examples, plus a selection of Tcl freeware found on the Internet. The CD-ROM is readable on UNIX, Windows, and Macintosh. There, you will find the versions of Tcl and Tk that were available as the book went to press. You can also retrieve the sources shown in the book from my personal Web site: http://www.beedub.com/book/ [ Team LiB ]
[ Team LiB ]
Typographic Conventions
The more VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED important examples are set apart with a title and horizontal rules, while others appear in-line. The examples use courier for Tcl and C code. When interesting results are returned by a Tcl command, those are presented below in oblique courier. The => is not part of the return value in the following example.
The courier font is also used when naming Tcl commands and C procedures within sentences. The usage of a Tcl command is presented in the following example. The command name and constant keywords appear in courier. Variable values appear in courier oblique. Optional arguments are surrounded with question marks.
[ Team LiB ]
Hot Tips
The icon in the margin marks a "hot tip" as judged by the reviewers of the book. The visual markers help you locate the more useful sections in the book. These are also listed in the index under Hot Tip. [ Team LiB ]
[ Team LiB ]
Book Organization
The chapters of the book CHM TO into CONVERTER first part describes basic Tcl UNREGISTERED VERSION OFare divided PDFseven parts. The By THETA-SOFTWARE features. The first chapter describes the fundamental mechanisms that characterize the Tcl language. This is an important chapter that provides the basic grounding you will need to use Tcl effectively. Even if you have programmed in Tcl already, you should review Chapter 1. Chapter 2 goes over the details of using Tcl and Tk on UNIX, Windows, and Macintosh. Chapter 3 presents a sample application, a CGI script, that illustrates typical Tcl programming. The rest of Part I covers the basic CHM TO PDF more detail, including string handling, data UNREGISTERED VERSION OFTcl commands in CONVERTER By THETA-SOFTWARE types, control flow, procedures, and scoping issues. Part I finishes with a description of the facilities for file I/O and running other programs. Part II describes advanced Tcl programming. It starts with eval, which lets you generate Tcl programs on the fly. Regular expressions provide powerful string processing. If your dataprocessing application runs slowly, you can probably boost its performance significantly with the regular expression facilities. Namespaces partition the global scope of procedures and variables. Unicode and message catalogs support internationalized applications. Libraries and packages provide a way to organize your code for sharing among projects. The introspection facilities of Tcl tell you about the internal state of Tcl. Event driven I/O helps server applications manage several clients simultaneously. Network sockets are used to implement the HTTP protocol used to fetch pages on the World Wide Web. The last few chapters in Part II describe platforms and frameworks for application development. Safe-Tcl is used to provide a secure environment to execute Tcl applets in a Web browser. TclHttpd is an extensible web server built in Tcl. You can build applications on top of this server, or embed it into your existing applications to give them a web interface. Starkits are an exciting new way to package and deploy Tcl/Tk applications. They use the new Virtual File System (VFS) facilities to embed a private file system right in the Starkit. Part III introduces Tk. It gives an overview of the toolkit facilities. A few complete examples are examined in detail to illustrate the features of Tk. Event bindings associate Tcl commands with events like keystrokes and button clicks. Part III ends with three chapters on the Tk geometry managers that provide powerful facilities for organizing your user interface. Part IV describes the Tk widgets. These include buttons, menus, scrollbars, labels, text entries, multiline and multifont text areas, drawing canvases, listboxes, and scales. The Tk widgets are highly configurable and very programmable, but their default behaviors make them easy to use as well. The resource database that can configure widgets provides an easy way to control the overall look of your application. Part V describes the rest of the Tk facilities. These include selections, keyboard focus, and standard dialogs. Fonts, colors, images, and other attributes that are common to the Tk widgets are described in detail. This part ends with a few larger Tk examples. Part VI is an introduction to C programming and Tcl. The goal of this part is to get you started in the right direction when you need to extend Tcl with new commands written in C or integrate Tcl into custom applications. Part VII provides a chapter for each of the Tcl/Tk releases covered by the book. These chapters provide details about what features were changed and added. They also provide a quick reference if you need to update a program or start to use a new version.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Tcl Commands
Tcl stands for Tool Command Language. A command does something for you, like output a string, compute a math expression, or display a widget on the screen. Tcl casts everything into the mold of a command, even programming constructs like variable assignment and procedure definition. Tcl adds a tiny amount of syntax needed to properly invoke commands, and then it leaves all the hard work up to the command implementation. The basic syntax for a Tcl command is:
The command is either the name of a built-in command or a Tcl procedure. White space (i.e., spaces or tabs) is used to separate the command name and its arguments, and a newline (i.e., the end of line character) or semicolon is used to terminate a command. Tcl does not interpret the arguments to the commands except to perform grouping, which allows multiple words in one argument, and substitution, which is used with programming variables and nested command calls. The behavior of the Tcl command processor can be summarized in three basic steps:
Argument grouping. Value substitution of nested commands, variables, and backslash escapes. Command invocation. It is up to the command to interpret its arguments. This model is described in detail in this Chapter. [ Team LiB ]
[ Team LiB ]
Hello, World!
Example 1-1 The "Hello, World!" example UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
puts stdout {Hello, World!} => Hello, World!
The braces are syntax for the interpreter, and they get stripped off before the value is passed to the command. Braces group all characters, including newlines and nested braces, until a matching brace is found. Tcl also uses double quotes for grouping. Grouping arguments will be described in more detail later. [ Team LiB ]
[ Team LiB ]
Variables
The set command is used to assign a value to a variable. It takes two arguments: The first is the name of the variable, and the second is the value. Variable names can be any length, and case is significant. In fact, you can use any character in a variable name.
The interpreter will create the variable when it is first assigned a value. The value of a variable is obtained later with the dollar-sign syntax, illustrated in Example 1-2:
The second set command assigns to variable b the value of variable var. The use of the dollar sign is our first example of substitution. You can imagine that the second set command gets rewritten by substituting the value of var for $var to obtain a new command.
set b 5
The actual implementation of substitution is more efficient, which is important when the value is large. [ Team LiB ]
[ Team LiB ]
Command Substitution
The second form of substitution TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM is command substitution. A nested command is delimited by square brackets, [ ]. The Tcl interpreter takes everything between the brackets and evaluates it as a command. It rewrites the outer command by replacing the square brackets and everything between them with the result of the nested command. This is similar to the use of backquotes in other shells, except that it has the additional advantage of supporting arbitrary nesting of commands.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 1-3 Command substitution
set len [string length foobar] => 6
This command returns the length of the string foobar. The string command is described in detail starting on page 49. The nested command runs first. Then, command substitution causes the outer command to be rewritten as if it were:
set len 6
If there are several cases of command substitution within a single command, the interpreter processes them from left to right. As each right bracket is encountered, the command it delimits is evaluated. This results in a sensible ordering in which nested commands are evaluated first so that their result can be used in arguments to the outer command. [ Team LiB ]
[ Team LiB ]
Math Expressions
The Tcl interpreter itself does not evaluate math expressions. Tcl just does grouping, substitutions and command invocations. The expr command is used to parse and evaluate math expressions.
The math syntax supported by expr is the same as the C expression syntax. The expr command deals with integer, floating point, and boolean values. Logical operations return either 0 (false) or 1 (true). Integer values are promoted to floating point values as needed. Octal values are indicated by a leading zero (e.g., 033 is 27 decimal). Hexadecimal values are indicated by a leading 0x. Scientific notation for floating point numbers is supported. A summary of the operator precedence is given on page 20. You can include variable references and nested commands in math expressions. The following example uses expr to add the value of x to the length of the string foobar. As a result of the innermost command substitution, the expr command sees 6 + 7, and len gets the value 13:
The expression evaluator supports a number of built-in math functions. (For a complete listing, see page 21.) Example 1-6 computes the value of pi:
The implementation of expr is careful to preserve accurate numeric values and avoid conversions between numbers and strings. However, you can make expr operate more efficiently by grouping the entire expression in curly braces. The explanation has to do with the byte code compiler that Tcl uses internally, and its effects are explained in more detail on page 15. For now, you should be aware that these expressions are all valid and run faster than the examples shown above:
expr {7.2 / 4} set len [expr {[string length foobar] + $x}] set pi [expr {2*asin(1.0)}]
[ Team LiB ]
Backslash Substitution
The final type of substitution done by the Tcl interpreter is backslash substitution. This is used to quote characters that have special meaning to the interpreter. For example, you can specify a literal dollar sign, brace, or bracket by quoting it with a backslash. As a rule, however, if you find yourself using lots of backslashes, there is probably a simpler way to achieve the effect you are striving for. In particular, the list command described on page 65 will do quoting for you automatically. In Example 1-8 backslash is used to get a literal $:
The second set command in the example illustrates an important property of Tcl. The value of dollar does not affect the substitution performed in the assignment to x. In other words, the Tcl parser does not care about the value of a variable when it does the substitution. In the example, the value of x and dollar is the string $foo. In general, you do not have to worry about the value of variables until you use eval, which is described in Chapter 10. You can also use backslash sequences to specify characters with their Unicode, hexadecimal, or octal value:
The value of variable escape is the ASCII ESC character, which has character code 27. Table 11 on page 20 summarizes backslash substitutions. A common use of backslashes is to continue long commands on multiple lines. This is necessary because a newline terminates a command. The backslash in the next example is required; otherwise the expr command gets terminated by the newline after the plus sign.
There are two fine points to escaping newlines. First, if you are grouping an argument as described in the next section, then you do not need to escape newlines; the newlines are automatically part of OF CHM TO PDF terminate the command. Second, a backslash as the UNREGISTERED VERSIONthe group and do notCONVERTER By THETA-SOFTWARE last character in a line is converted into a space, and all the white space at the beginning of the next line is replaced by this substitution. In other words, the backslash-newline sequence also consumes all the leading white space on the next line. [ Team LiB ] UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
[ Team LiB ]
length of $s is [string length $s]." Hello is 5. length of $s is [string length $s].} $s is [string length $s].
In the second command of Example 1-10, the Tcl interpreter does variable and command substitution on the second argument to puts. In the third command, substitutions are prevented, so the string is printed as is. In practice, grouping with curly braces is used when substitutions on the argument must be delayed until a later time (or never done at all). Examples include loops, conditional statements, and procedure declarations. Double quotes are useful in simple cases like the puts command previously shown. Another common use of quotes is with the format command. This is similar to the C printf function. The first argument to format is a format specifier that often includes special characters like newlines, tabs, and spaces. The easiest way to specify these characters is with backslash sequences (e.g., \n for newline and \t for tab). The backslashes must be substituted before the format command is called, so you need to use quotes to group the format specifier.
Here format is used to align a name and a value with a tab. The %s and %5.3f indicate how the remaining arguments to format are to be formatted. Note that the trailing \n usually found in a C printf call is not needed because puts provides one for us. For more information about the format command, see page 56.
If an argument is made up of only a nested command, you do not need to group it with doublequotes because the Tcl parser treats the whole nested command as part of the group.
$x+$y=[expr $x + $y]
The white space inside the nested command is ignored for the purposes of grouping the argument. By the time Tcl encounters the left bracket, it has already done some variable substitutions to obtain:
7+9=
When the left bracket is encountered, the interpreter calls itself recursively to evaluate the nested command. Again, the $x and $y are substituted before calling expr. Finally, the result of expr is substituted for everything from the left bracket to the right bracket. The puts command gets the following as its second argument:
7+9=16
The point of this example is that the grouping decision about puts's second argument is made before the command substitution is done. Even if the result of the nested command contained spaces or other special characters, they would be ignored for the purposes of grouping the arguments to the outer command. Grouping and variable substitution interact the same as grouping and command substitution. Spaces or special characters in variable values do not affect grouping decisions because these decisions are made before the variable values are substituted. If you want the output to look nicer in the example, with spaces around the + and =, then you must use double quotes to explicitly group the argument to puts:
The double quotes are used for grouping in this case to allow the variable and command substitution on the argument to puts.
In general, you can place a bracketed command or variable reference anywhere. The following computes a command name:
[ Team LiB ]
Procedures
Tcl uses the proc command to define procedures. Once defined, a Tcl procedure is used just like any of the other built-in Tcl commands. The basic syntax to define a procedure is:
The first argument is the name of the procedure being defined. The second argument is a list of parameters to the procedure. The third argument is a command body that is one or more Tcl commands. The procedure name is case sensitive, and in fact it can contain any characters. Procedure names and variable names do not conflict with each other. As a convention, this book begins procedure names with uppercase letters and it begins variable names with lowercase letters. Good programming style is important as your Tcl scripts get larger. Tcl coding style is discussed in Chapter 12.
The Diag procedure defined in the example computes the length of the diagonal side of a right triangle given the lengths of the other two sides. The sqrt function is one of many math functions supported by the expr command. The variable c is local to the procedure; it is defined only during execution of Diag. Variable scope is discussed further in Chapter 7. It is not really necessary to use the variable c in this example. The procedure can also be written as:
The return command is used to return the result of the procedure. The return command is optional in this example because the Tcl interpreter returns the value of the last command in the body as the value of the procedure. So, the procedure could be reduced to:
Note the stylized use of curly braces in the example. The curly brace at the end of the first line starts the third argument to proc, which is the command body. In this case, the Tcl interpreter sees the opening left brace, causing it to ignore newline characters and scan the text until a matching right brace is found. Double quotes have the same property. They group characters, including newlines, until another double quote is found. The result of the grouping is that the third argument to proc is a sequence of commands. When they are evaluated later, the embedded newlines will terminate each command.
The other crucial effect of the curly braces around the procedure body is to delay any substitutions in the body until the time the procedure is called. For example, the variables a, b, and c are not defined until the procedure is called, so we do not want to do variable substitution at the time Diag is defined. The proc command supports additional features such as having variable numbers of arguments
UNREGISTERED VERSION OF CHM TO PDF CONVERTERdetail in Chapter 7. By THETA-SOFTWARE and default values for arguments. These are described in
[ Team LiB ]
[ Team LiB ]
A Factorial Example
To reinforce what we have learned so far, below is a longer example that uses a while loop to compute the factorial function:
The semicolon is used on the first line to remind you that it is a command terminator just like the newline character. The while loop is used to multiply all the numbers from one up to the value of x. The first argument to while is a boolean expression, and its second argument is a command body to execute. The while command and other control structures are described in Chapter 6. The same math expression evaluator used by the expr command is used by while to evaluate the boolean expression. There is no need to explicitly use the expr command in the first argument to while, even if you have a much more complex expression. The loop body and the procedure body are grouped with curly braces in the same way. The opening curly brace must be on the same line as proc and while. If you like to put opening curly braces on the line after a while or if statement, you must escape the newline with a backslash:
Curly braces around the boolean expression are crucial because they delay variable substitution until the while command implementation tests the expression. The following example is an infinite loop:
UNREGISTERED VERSION OF CHMThe reasonCONVERTERinterpreter will substitute for $i The loop will run indefinitely.[*] TO PDF is that the Tcl By THETA-SOFTWARE
before while is called, so while gets a constant expression 1<=10 that will always be true. You can avoid these kinds of errors by adopting a consistent coding style that groups expressions with curly braces:
[*]
compiler that caused this loop TO PDF This bug is fixed By THETA-SOFTWARE UNREGISTERED VERSION OF CHMto terminate!CONVERTER in the 8.0.5 patch release.
Ironically, Tcl 8.0 introduced a byte-code compiler, and the first releases of Tcl 8.0 had a bug in the
The incr command is used to increment the value of the loop variable i. This is a handy command that saves us from the longer command:
The incr command can take an additional argument, a positive or negative integer by which to change the value of the variable. Using this form, it is possible to eliminate the loop variable i and just modify the parameter x. The loop body can be written like this:
Example 1-14 shows factorial again, this time using a recursive definition. A recursive function is one that calls itself to complete its work. Each recursive call decrements x by one, and when x is one, then the recursion stops.
[ Team LiB ]
[ Team LiB ]
This is a somewhat tricky example. In the last command, $name gets substituted with var. Then, the set command returns the value of var, which is the value of var. Nested set commands provide another way to achieve a level of indirection. The last set command above can be written as follows:
Using a variable to store the name of another variable may seem overly complex. However, there are some times when it is very useful. There is even a special command, upvar, that makes this sort of trick easier. The upvar command is described in detail in Chapter 7.
set foo filename set object $foo.o => filename.o set a AAA set b abc${a}def => abcAAAdef UNREGISTERED VERSION set .o yuk! set x ${.o}y => yuk!y
Any number of variable names can be passed to the unset command. However, unset will raise an error if a variable is not already defined, unless the -nocomplain is given. Use -- to unset a variable named -nocomplain.
Example 7-6 on page 92 implements a version of incr which handles this case.
[ Team LiB ]
[ Team LiB ]
In Tcl 8.0 and later versions, the overhead of conversions is eliminated in most cases by the built-in compiler. Even so, Tcl was not designed to support math-intensive applications. You may want to implement math-intensive code in a compiled language and register the function as a Tcl command as described in Chapter 47. There is support for string comparisons by expr, so you can test string values in if statements. You must use quotes so that expr knows to do string comparisons:
However, the string compare and string equal commands described in Chapter 4 are more reliable because expr may do conversions on strings that look like numbers. The issues with string operations and expr are discussed on page 52. Tcl 8.4 introduced eq and ne expr operators to allow strict string based comparison. Expressions can include variable and command substitutions and still be grouped with curly braces. This is because an argument to expr is subject to two rounds of substitution: one by the Tcl interpreter, and a second by expr itself. Ordinarily this is not a problem because math values do not contain the characters that are special to the Tcl interpreter. The second round of substitutions is needed to support commands like while and if that use the expression evaluator internally.
UNREGISTERED VERSION OFexpressionsPDF CONVERTERlet expr do command and variable You should always group CHM TO in curly braces and By THETA-SOFTWARE
substitutions. Otherwise, your values may suffer extra conversions from numbers to strings and back to numbers. Not only is this process slow, but the conversions can lose precision in certain circumstances. For example, suppose x is computed from a math function:
set x [expr {sqrt(2.0)}] UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE At this point the value of x is a double-precision floating point value, just as you would expect. If you do this:
then you may or may not get 2.0 as the result! This is because Tcl will substitute $x and expr will concatenate all its arguments into one string, and then parse the expression again. In contrast, if you do this:
then expr will do the substitutions, and it will be careful to preserve the floating point value of x. The expression will be more accurate and run more efficiently because no string conversions will be done. The story behind Tcl values is described in more detail in Chapter 47 on C programming and Tcl. [ Team LiB ]
[ Team LiB ]
Comments
Tcl uses the pound character, #, for comments. Unlike in many other languages, the # must occur at the beginning of a command. A # that occurs elsewhere is not treated specially. An easy trick to append a comment to the end of a command is to precede the # with a semicolon to terminate the previous command:
# Here are some parameters set rate 7.0 ;# The interest rate set months 60 ;# The loan term
One subtle effect to watch for is that a backslash effectively continues a comment line onto the next line of the script. In addition, a semicolon inside a comment is not significant. Only a newline terminates comments:
# Here is the start of a Tcl comment \ and some more of it; still in the comment
The behavior of a backslash in comments is pretty obscure, but it can be exploited as shown in Example 2-3 on page 27. A surprising property of Tcl comments is that curly braces inside comments are still counted for the purposes of finding matching brackets. The motivation for this odd feature was to keep the original Tcl parser simpler. However, it means that the following will not work as expected to comment out an alternate version of an if expression:
The previous sequence results in an extra left curly brace, and probably a complaint about a missing close brace at the end of your script! A technique I use to comment out large chunks of code is to put the code inside an if block that will never execute:
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Fine Points
A common error is to forget a space between arguments when grouping with braces or quotes. This is because white space is used as the separator, while the braces or quotes only provide grouping. If you forget the space, you will get syntax errors about unexpected characters after the closing brace or quote. The following is an error because of the missing space between } and {: if {$x > 1}{puts "x = $x"}
A double quote is only used for grouping when it comes after white space. This means you can include a double quote in the middle of a group without quoting it with a backslash. This requires that curly braces or white space delimit the group. I do not recommend using this obscure feature, but this is what it looks like: set silly a"b
When double quotes are used for grouping, the special effect of curly braces is turned off. Substitutions occur everywhere inside a group formed with double quotes. In the next command, the variables are still substituted: set x xvalue set y "foo {$x} bar" => foo {xvalue} bar
When double quotes are used for grouping and a nested command is encountered, the nested command can use double quotes for grouping, too. puts "results [format "%f %f" $x $y]"
Spaces are not required around the square brackets used for command substitution. For the purposes of grouping, the interpreter considers everything between the square brackets as part of the current group. The following sets x to the concatenation of two command results because there is no space between ] and [. set x [cmd1][cmd2]
Newlines and semicolons are ignored when grouping with braces or double quotes. They get included in the group of characters just like all the others. The following sets x to a string that contains newlines: set x "This is line one. This is line two. This is line three."
During command substitution, newlines and semicolons are significant as command terminators. If you have a long command that is nested in square brackets, put a backslash before the newline if you want to continue the command on another line. This was illustrated in Example 1-9 on page 8. A dollar sign followed by something other than a letter, digit, underscore, or left parenthesis is treated as a literal dollar sign. The following sets x to the single character $.
[ Team LiB ]
Reference
Backslash Sequences
\<newline> Replace the newline and the leading white space on the next line with a space. \\ \ooo \xhh Backslash. ('\') Octal specification of character code. 1, 2, or 3 octal digits (0-7). Hexadecimal specification of character code. 1 or 2 hex digits. Be careful when using this in a string of characters, because all hexadecimal characters following the \x will be consumed, but only the last 2 will specify the value. Hexadecimal specification of a 16-bit Unicode character value. 4 hex digits. Replaced with literal c if c is not one of the cases listed above. In particular, \$, \", \{, \}, \], and \[ are used to obtain these characters.
\uhhhh \c
Arithmetic Operators
Unary minus, bitwise NOT, logical NOT. Multiply, divide, remainder. Add, subtract. Left shift, right shift. Comparison: less, greater, less or equal, greater or equal.
| Bitwise CHM UNREGISTERED VERSION OFOR. TO PDF CONVERTER By THETA-SOFTWARE && || x?y:z Logical AND. Logical OR. If x then y else z.
atan2(y,x) Rectangular (x,y) to polar (r,th). atan2 gives th. ceil(x) cos(x) cosh(x) exp(x) floor(x) fmod(x,y) Least integral value greater than or equal to x. Cosine of x. Hyperbolic cosine of x. Exponential, ex. Greatest integral value less than or equal to x. Floating point remainder of x/y.
hypot(x,y) Returns sqrt(x*x + y*y). r part of polar coordinates. log(x) log10(x) pow(x,y) sin(x) sinh(x) sqrt(x) Natural log of x. Log base 10 of x. x to the y power, xy. Sine of x. Hyperbolic sine of x. Square root of x.
Tangent of x. Hyperbolic tangent of x. Absolute value of x. Promote x to floating point. Truncate x to an integer. Round x to an integer. Return a random floating point value between 0.0 and 1.0. Set the seed for the random number generator to the integer x. Promote x to a wide (64-bit) integer. (Tcl 8.4)
228 Schedule a Tcl command for later execution. 56 Append arguments to a variable's value. No spaces added. 97 Query array state and search through elements. 59 Convert between strings and binary data. 83 Exit loop prematurely. 83 Trap errors. 122 Change working directory. 183 Get the time and format date strings. 121 Close an open I/O stream. 65 Concatenate arguments with spaces between. Splices lists. 29 Control the console used to enter commands interactively. 83 Continue with next loop iteration. 85 Raise an error. 116 Check for end of file. 130 Concatenate arguments and evaluate them as a command. 105 Fork and execute a UNIX program. 124 Terminate the process. 6 Evaluate a math expression.
Command fblocked
Pg.
Description
fconfigure 231 Set and query I/O channel properties. fcopy file 250 Copy from one I/O channel to another. 108 Query the file system.
foreach 79 Loop construct over a CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDFlist, or lists, of values. format gets glob global history if incr info interp join lappend lindex linsert list llength load lrange lreplace lsearch lset lsort namespace open package pid 56 Format a string similar to C sprintf. 119 Read a line of input from an I/O stream. 122 Expand a pattern to matching file names. 90 Declare global variables. 196 Use command-line history. 76 Test a condition. Allows else and elseif clauses. 12 Increment a variable by an integer amount. 186 Query the state of the Tcl interpreter. 292 Create additional Tcl interpreters. 72 Concatenate list elements with a given separator string. 66 Add elements to the end of a list. 68 Fetch an element of a list. 68 Insert elements into a list. 65 Create a list out of the arguments. 68 Return the number of elements in a list. 697 Load shared libraries that define Tcl commands. 68 Return a range of list elements. 68 Replace elements of a list. 69 Search for an element of a list that matches a pattern. 62 Set an element in a list. (Tcl 8.4) 70 Sort a list. 213 Create and manipulate namespaces. 116 Open a file or process pipeline for I/O. 175 Provide or require code packages. 124 Return the process ID.
Command proc puts pwd read regexp regsub rename return scan seek set socket source split string subst switch tell time trace unknown unset uplevel upvar variable vwait while [ Team LiB ]
Description
119 Output a string to an I/O stream. 122 Return the current working directory. 120 Read blocks of characters from an I/O stream. 158 Match regular expressions. 162 Substitute based on regular expressions. 88 Change the name of a Tcl command. 86 Return a value from a procedure. 58 Parse a string according to a format specification. 121 Set the seek offset of an I/O stream. 5 Assign a value to a variable. 239 Open a TCP/IP network connection. 26 Evaluate the Tcl commands in a file. 71 Chop a string up into list elements. 49 Operate on strings. 140 Substitute embedded commands and variable references. 77 Test several conditions. 121 Return the current seek offset of an I/O stream. 202 Measure the execution time of a command. 193 Monitor variable assignments. 178 Handle unknown commands. 13 Delete variables. 138 Execute a command in a different scope. 91 Reference a variable in a different scope. 207 Declare namespace variables. 230 Wait for a variable to be modified. 79 Loop until a boolean expression is false.
[ Team LiB ]
[ Team LiB ]
source filename
The source command reads Tcl commands from a file and evaluates them just as if you had typed them interactively. Chapter 3 develops a sample application. To get started, just open an editor on a file named cgi1.tcl. Each time you update this file you can save it, reload it into Tcl with the source command, and test it again. Development goes quickly because you do not wait for things to compile! [ Team LiB ]
[ Team LiB ]
Example 2-1 A standalone Tcl CONVERTER By UNREGISTERED VERSION OF CHM TO PDFscript on UNIX THETA-SOFTWARE
#!/usr/local/bin/tclsh puts stdout {Hello, World!}
The actual pathnames for tclsh and wish may be different on your system. If you type the pathname for the interpreter wrong, you receive a confusing "command not found" error. You can find out the complete pathname of the Tcl interpreter with the info nameofexecutable command. This is what appears on my system:
On most UNIX systems, this special first line is limited to 32 characters, including the #!. If the pathname is too long, you may end up with /bin/sh trying to interpret your script, giving you syntax errors. You might try using a symbolic link from a short name to the true, long name of the interpreter. However, watch out for systems like older versions of Solaris in which the script interpreter cannot be a symbolic link. Fortunately, Solaris doesn't impose a 32-character limit on the pathname, so you can just use a long pathname.
The next example shows a trick that works around the pathname length limitation in all cases. The trick comes from a posting to comp.lang.tcl by Kevin Kenny. It takes advantage of a difference between comments in Tcl and the Bourne shell. Tcl comments are described on page 16. In the example, the exec Bourne shell command that runs the Tcl interpreter is hidden in a comment as far as Tcl is concerned, but it is visible to /bin/sh. The exec command (in /bin/sh) replaces the current program, so that is all that the Bourne shell processes; Tcl interprets the rest of the script.
You do not even have to know the complete pathname of tclsh or wish to use this trick. You can just do the following:
#!/bin/sh # Run wish from the users PATH \ exec wish -f "$0" ${1+"$@"}
The drawback of an incomplete pathname is that many sites have different versions of wish and tclsh that correspond to different versions of Tcl and Tk. In addition, some users may not have these programs in their PATH. You can hide more than one Bourne shell command in a script with this trick. For example, you might need to set environment variables:
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE "c:\Program Files\Tcl84\wish84.exe" "c:\My Files\script.tcl"
This starts c:\My Files\script.tcl as a standalone Tcl/Tk program.
[ Team LiB ]
[ Team LiB ]
Set the name of the resource to be tclshrc. You do this through the Get Resource Info dialog under the Resources menu in ResEdit. This sequence of commands is captured in an application called Drag n Drop Tclets, which comes with the Macintosh Tcl distribution. If you drag a Tcl script onto this icon, it will create a copy of Wish and create the tclshrc text resource that has a source command that will load that script. If you have a Macintosh development environment, you can build a version of Wish that has additional resources built right in. You add the resources to the applicationInit.r file. If a resource contains Tcl code, you use it like this:
If you don't want to edit resources, you can just use the Wish Source menu to select a script to run.
Macintosh OS X
Mac OS X can run the same Tcl/Tk as Macintosh system 8 or 9. However, the preferred version for Mac OS X is Tcl/Tk Aqua, which uses the native windowing system known as Aqua. There are some differences in the application structure due to the new application framework used when building this variant. Wish checks the Resources/Scripts directory in its application bundle for a file called AppMain.tcl, if found it is used as the startup script and the Scripts folder is added to the auto_path. This is similar in spirit to the tclshrc resource described above. Daniel Steffen deserves a great deal of credit for the Tcl/Tk Aqua port and his continued support of the Macintosh platform. He has put together a great distribution that includes many popular extensions, which you can find on the CD-ROM. You can find out more about Tcl/Tk on Macintosh through these URLs:
[ Team LiB ]
console hide
console show
The console is implemented by a second Tcl interpreter. You can evaluate Tcl commands in that interpreter with:
There is an alternate version of this console called TkCon. It is included on the CD-ROM, and you can find current versions on the Internet. TkCon was created by Jeff Hobbs and has lots of nice features. You can use TkCon on Unix systems, too. Some of its features were added to console in 8.4. [ Team LiB ]
[ Team LiB ]
Command-Line Arguments
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
If you run a script from the command line, for example from a UNIX shell, you can pass the script command-line arguments. You can also specify these arguments in the shortcut command in Windows. For example, under UNIX you can type this at a shell:
The Tcl shells pass the command-line arguments to the script as the value of the argv variable. The number of command-line arguments is given by the argc variable. The name of the program, or script, is not part of argv nor is it counted by argc. Instead, it is put into the argv0 variable. Table 2-2 lists all the predefined variables in the Tcl shells. argv is a list, so you can use the lindex command, which is described on page 63, to extract items from it:
The following script prints its arguments (foreach is described on page 79):
If no script is specified, then wish just enters an interactive command loop. Table 2-1 lists the options that wish supports:
[ Team LiB ]
Predefined Variables
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
argv A list CHM TO PDF CONVERTER UNREGISTERED VERSION OF of the command-line arguments.By THETA-SOFTWARE argv0 embed_args env The name of the script being executed. If being used interactively, argv0 is the name of the shell program. The list of arguments in the <EMBED> tag. Tcl applets only. See page 314. An array of the environment variables. See page 124.
tcl_interactive True (one) if the tclsh is prompting for commands. tcl_library tcl_patchLevel tcl_platform tcl_prompt1 tcl_prompt2 tcl_version auto_path auto_index auto_noload auto_noexec geometry [ Team LiB ] The script library directory. Modified version number, e.g., 8.0b1. Array containing operating system information. See page 192. If defined, this is a command that outputs the prompt. If defined, this is a command that outputs the prompt if the current command is not yet complete. Version number. The search path for script library directories. See page 172. A map from command name to a Tcl command that defines it. If set, the library facility is disabled. If set, the auto execute facility is disabled. (wish only). The value of the -geometry argument.
[ Team LiB ]
[ Team LiB ]
As shown here, the tags usually come in pairs. The open tag may have some parameters, and the close tag name begins with a slash. The case of a tag is not considered, so <title>, <Title>, and <TITLE> are all valid and mean the same thing. The corresponding close tag could be </title>, </Title>, </TITLE>, or even </TiTlE>. The <A> tag defines hypertext links that reference other pages on the Web. The hypertext links connect pages into a Web so that you can move from page to page to page and find related information. It is the flexibility of the links that makes the Web so interesting. The <A> tag takes an HREF parameter that defines the destination of the link. If you wanted to link to my home page, you would put this in your page:
When this construct appears in a Web page, your browser typically displays "Brent Welch" in blue underlined text. When you click on that text, your browser switches to the page at the address "http://www.beedub.com/". There is a lot more to HTML, of course, but this should give you a basic idea of what is going on in the examples. Table 3-1 summarizes the HTML tags that will be used in the examples:
Main tag that surrounds the whole document. Delimits head section of the HTML document. Defines the title of the page. Delimits the body section. Lets you specify page colors. HTML defines 6 heading levels: H1, H2, H3, H4, H5, H6. Start a new paragraph. One blank line. Bold text. Italic text. Used for hypertext links. Specify an image. Definition list. Term clause in a definition list. Definition clause in a definition list. An unordered list. A bulleted item within a list. Create a table. A table row. A cell within a table row. Defines a data entry form. A one-line entry field, checkbox, radio button, or submit button.
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDFeach time it is viewed. This is how pages that give upCONVERTER By THETA-SOFTWARE In contrast, a dynamic page is computed
to-the-minute stock prices work, for example. A dynamic page does not mean it includes animations; it just means that a program computes the page contents when a user visits the page. The advantage of this approach is that a user might see something different each time he or she visits the page. As we shall see, it is also easier to maintain information in a database of some sort and generate the HTML formatting for the data with a program. A CGI (Common Gateway Interface) program is used to compute Web pages. The CGI standard defines how inputs are passed to the program as well as a way to identify different types of results, such as images, plain text, or HTML markup. A CGI program simply writes the contents of the document to its standard output, and the Web server takes care of delivering the document to the user's Web browser. Example 3-1 is a very simple CGI script:
The program computes a simple HTML page that has the current time. Each time a user visits the page, she will see the current time on the server. The server that has the CGI program and the user viewing the page might be on different sides of the planet. The output of the program is divided into two sections: the protocol header and the page contents. In this simple example, the protocol header just has a Content-Type line that tells your Web browser what kind of data comes next. A blank line separates the protocol header from the page, which starts with a <TITLE> tag, in this case. The clock command is used twice: once to get the current time in seconds, and a second time to format the time into a nice-looking string. The clock command is described in detail on page 183. Fortunately, there is no conflict between the markup syntax used by HTML and the Tcl syntax for embedded commands, so we can mix the two in the argument to the puts command. Double quotes are used to group the argument to puts so that the clock command will be executed. Example 3-2 shows what the output of the program will look like:
This example is a bit sloppy in its use of HTML, but it should display properly in most Web browsers. Example 3-3 includes all the required tags for a proper HTML document. [ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 3-3 The guestbook.cgi script, version 1
#!/bin/sh # guestbook.cgi # Implement a simple guestbook page. # The set of visitors is kept in a simple database. # The newguest.cgi script will update the database. # \ exec tclsh "$0" ${1+"$@"} # The guestbook.data file has the database # The datafile is in the same directory as the script set dir [file dirname [info script]] set datafile [file join $dir guestbook.data] puts "text/html" puts "" set title "Brent's Guestbook" puts "<HTML><HEAD><TITLE>$title</TITLE></HEAD>" puts "<BODY BGCOLOR=white TEXT=black>" puts "<H1>$title</H1>" if {![file exists $datafile]} { puts "No registered guests, yet. <P> Be the first <A href='newguest.html'>registered guest!</A>" } else { puts "The following folks have registered in my GuestBook. <P> <A href='newguest.html'>Register</A> <H2>Guests</H2>" catch {source $datafile} foreach name [lsort [array names Guestbook]] { set item $Guestbook($name) set homepage [lindex $item 0] set markup [lindex $item 1] puts "<H3><A href=$homepage>$name</A></H3>" puts $markup }
} puts "</BODY></HTML>"
source cgihacks.tcl
The problem is that the current directory of the CGI process may not be the same as the directory that contains the CGI script or the cgihacks.tcl file. You can use the info script command to find out where the CGI script is, and from that load the supporting file. The file dirname and file join commands manipulate file names in a platform-independent way. They are described on page 108. I use the following trick to avoid putting absolute file names into my scripts, which would have to be changed if the program moves later:
set dir [file dirname [info script]] source [file join $dir cgihacks.tcl]
You can also create script libraries as described in Chapter 12. That chapter describes tools to create an index of procedures so an application can quickly load the procedures it needs, and how to create packages of procedures so you can keep your code organized. However you set them up, it is always a good idea to have a library of procedures you share with other applications.
The way you start your HTML page is a great candidate for capturing in a Tcl procedure. For example, I like to have the page title appear in the TITLE tag in the head, and repeated in an H1 tag at the beginning of the body. You may also have a favorite set of colors or fonts that you want to specify in the BODY tag. By putting all this into a Tcl procedure, you can make it easy to share this among all your scripts. If your tastes change tomorrow, then you can change the Tcl procedure in one spot and affect all CGI scripts that share the procedure. Example 3-4 shows Cgi_Header that generates a simple standard page header:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 3-4 The Cgi_Header procedure
proc Cgi_Header {title {body {bgcolor=white text=black}}} { puts stdout "Content-Type: text/html
The Cgi_Header procedure takes as arguments the title for the page and some optional parameters for the HTML BODY tag. The procedure definition uses the syntax for an optional parameter, so you do not have to pass bodyparams to Cgi_Header. The default specifies black text on a white background to avoid the standard gray background of most browsers. Default values for procedure parameters are described on page 87.
<A href='newguest.html'>registered guest!</A>" } else { puts "The following folks have registered in my GuestBook. <P> <A href='newguest.html'>Register</A> <h2>Guests</h2>" catch {source $datafile} foreach name [lsort [array names Guestbook]] { set item $Guestbook($name) set homepage [lindex $item 0] set markup [lindex $item 1] puts "<H3><A href=$homepage>$name</A></H3>" puts $markup } } puts "</BODY></HTML>"
Example 3-5 is a new version of the original CGI script that loads the cgihacks.tcl file and uses Cgi_Header. The Cgi_Header procedure just contains a single puts command that generates the standard boilerplate that appears at the beginning of the output. Note that several lines are grouped together with double quotes. Double quotes are used so that the variable references mixed into the HTML are substituted properly. The output of the Cgi_Header procedure matches what we wrote by hand in Example 3-3.
If the database file does not exist, a different page is displayed to encourage a registration. The page includes a hypertext link to a registration page, newguest.html, which is described on page 43. The output of the program would be as below in Example 3-6 if there were no data file:
Note the inconsistent indentation of the HTML that comes from the indentation in the puts command used for that part of the page. The browser doesn't care about white space in the HTML. You have a choice between lining up the Tcl commands in your CGI script, or UNREGISTERED output. Here we CHM two different examples. The Cgi_Header procedure lining up VERSION OF have TO PDF CONVERTER By THETA-SOFTWARE the HTML produces output that is lined up, but the procedure definition looks a bit odd. The main script, in contrast, keeps its Tcl commands neatly indented, but that shows up in the output. If you generate most of your HTML from code, you may choose to keep your code tidy.
Example 3-7 shows the output of the guestbook.cgi script when there is some data in the
set dir [file dirname [info script]] set datafile [file join $dir guestbook.data]
By using Tcl commands to represent the data, we can load the data with the source command. The catch command is used to protect the script from a bad data file, which will show up as an error from the source command. Catching errors is described in detail on page 85:
The Guestbook variable is the array defined in guestbook.data. Array variables are the topic of Chapter 8. Each element of the array is defined with a Tcl command that looks like this:
The person's name is the array index, or key. The value of the array element is a Tcl list with two elements: their URL and some additional HTML markup that they can include in the guestbook. Tcl lists are the topic of Chapter 5. The following example shows what the command looks like with real data:
The spaces in the name result in additional braces to group the whole variable name and each list element. This syntax is explained on page 96. Do not worry about it now. We will see on page 46 that all the braces in the previous statement are generated automatically. The main point is that the person's name is the key, and the value is a list with two elements. The array names command returns all the indices, or keys, in the array, and the lsort command sorts these alphabetically. The foreach command loops over the sorted list, setting the loop variable x to each key in turn:
The lsort command will sort the names based on the person's first name. You can have lsort sort things in a variety of ways. One trick we can use here is to have lsort treat each key as a list and sort on the last item in the list (i.e., the last name):
The lsort command is described in more detail on page 70. The foreach command assigns name to each key of the Guestbook array. We get the value like this:
The two list elements are extracted with lindex, which is described on page 68.
We generate the HTML for the guestbook entry as a level-three header that contains a hypertext link to the guest's home page. We follow the link with any HTML markup text that the guest has supplied to embellish his or her entry:
The homepage and markup variables are not strictly necessary, and the code could be written more compactly without them. However, the variables make the code more understandable. Here is what it looks like without the temporary variables:
[ Team LiB ]
The INPUT tag is used to define several kinds of input elements, and its type parameter indicates what kind. In this case, TYPE=text creates a one-line text entry field. The submit button is defined with an INPUT tag that has TYPE=submit , and the VALUE parameter becomes the text that appears on the submit button:
A general type-in window is defined with the TEXTAREA tag. This creates a multiline, scrolling text field that is useful for specifying lots of information, such as a free-form comment. In our case, we will let guests type in HTML that will appear with their guestbook entry. The text between the open and close TEXT-AREA tags is inserted into the type-in window when the page is first displayed.
A common parameter to the form tags is NAME= something . This name identifies the data that will come back from the form. The tags also have parameters that affect their display, such as the label on the submit button and the size of the text area. Those details are not important for our example. The complete form is shown in Example 3-8 :
<HEAD> <TITLE>Register in my Guestbook</TITLE> </HEAD> <BODY BGCOLOR=white TEXT=black> <FORM ACTION="newguest.cgi" METHOD="POST"> <H1>Register in my Guestbook</H1> UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
<UL> <LI>Name <INPUT TYPE="text" NAME="name" SIZE="40"> <LI>URL <INPUT TYPE="text" NAME="url" SIZE="40"> <P> If you don't have a home page, you can use an email URL like "mailto:[email protected]" <LI>Additional HTML to include after your link: UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE <BR> <TEXTAREA NAME="html" COLS="60" ROWS="15"> </TEXTAREA> <LI><INPUT TYPE="submit" NAME="new" VALUE="Add me to your guestbook"> <LI><INPUT TYPE="submit" NAME="update" VALUE="Update my guestbook entry"> </UL> </FORM> </BODY> </HTML>
The procedures in the ncgi package are in the ncgi namespace. Tcl namespaces are described in detail in Chapter 14 . Procedures in a namespace are qualified with the name of the namespace and :: syntax. For example, the standard setup procedure for a CGI script is ncgi::parse . The "n" in ncgi is for "new". Don Libes wrote the original package for CGI scripts known as cgi.tcl . There is also the cgilib.tcl package that contains Cgi_Header and some other procedures described in earlier editions of this book. The ncgi and html packages of tcllib provide most of the features in both cgi.tcl and cgilib.tcl , but follow the standard namespace conventions use by the packages in tcllib. You can still find cgi.tcl on the Web at http://expect.nist.gov/cgi.tcl/
something useful with it, and then returns a new page for the browser to display. In our case, the FORM tag names newguest.cgi as the program to handle the data:
The CGI specification defines how the data from the form is passed to the program. The data is encoded and organized so that the program can figure out the values the user specified for each form element. The encoding is handled rather nicely with some regular expression tricks that are done in ncgi::parse . ncgi::parse saves the form data, and ncgi::value gets a form value in the script. These procedures are described in Example 11-6 on page 165. Example 3-9 starts out by calling ncgi::parse :
<TR><TD>Name</TD> <TD>[ncgi::value name]</TD></TR> <TR><TD>URL</TD> <TD><A HREF='[ncgi::value url]'>[ncgi::value url]</A></TD></TR> <TR><TD>Extra HTML</TD> <TD>[ncgi::value html]</TD></TR> </TABLE> " UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE puts </BODY></HTML>
In this command, the variable out gets the result of the open command, which is either a file descriptor or an error message. This style of using catch is described in detail in Example 6-14 on page 83.
The script writes the data as a Tcl set command. The list command is used to format the data properly:
puts $out [list set Guestbook([ncgi::value name]) \ [list [ncgi::value url] [ncgi::value html]]]
There are two lists. First, the url and html values are formatted into one list. This list will be the
value of the array element. Then the whole Tcl command is formed as a list. In simplified form, the command is generated from this:
Using the list command ensures that the result will always be a valid Tcl command that sets the variable to the given value. This is a very important technique. If you want to generate Tcl commands, the best way to do it is to generate lists using list manipulation commands. The list command is described in more detail on page 65. [ Team LiB ]
[ Team LiB ]
When you aim the browser at your CGI script, it should at least create the file. If not, then the Web server cannot find your script, or it cannot find the Tclsh required by your script. Doublecheck your setup and the #! line in your script. On Windows, your best bet may be to use the TclHttpd Web server, which has a built-in ability to run Tcl CGI scripts. TclHttpd has other even cooler ways to generate pages, too. If your script suddenly stops working after you've modified it, then you have introduced a programming bug. I generally put all of the script into a catch statement and print out any errors that occur. That way the errors will be displayed by the browser instead of filed into the void by your Web server. Example 3-10 shows the newguest.cgi script rewritten so the catch statement surrounds all the statements. At the end, the value of the errorInfo variable is printed out if an error has occurred:
# Append a Tcl set command that defines the guest's entry puts $out "" puts $out [list set Guestbook([ncgi::value name]) \ [list [ncgi::value url] [ncgi::value html]]] close $out # Return a page to the browser Cgi_Header "Guestbook Registration Confirmed" \ {BGCOLOR=white TEXT=black} puts " <TABLE BORDER=1> <TR><TD>Name</TD> <TD>[ncgi::value name]</TD></TR> <TR><TD>URL</TD> <TD><A HREF='[ncgi::value url]'>[ncgi::value url]</A></TD></TR> <TR><TD>Extra HTML</TD> <TD>[ncgi::value html]</TD></TR> </TABLE> </BODY></HTML> " # End of main script } err]} { # Error occurred - display in the Web page puts puts puts puts } "Content-Type: text/plain" "" "CGI error occurred in [info script]" $errorInfo
[ Team LiB ]
[ Team LiB ]
Next Steps
There are VERSION details that can be CONVERTER By THETA-SOFTWARE UNREGISTERED a number ofOF CHM TO PDF added to this example. Users may want to update their entry, for example. They could do that now, but they would have to retype everything. They might also like a chance to check the results of their registration and make changes before committing them. This requires another page that displays their guest entry as it would appear on a page, and also has the fields that let them update the data.
The details of how a CGI UNREGISTERED VERSION OFscript isTO PDFup with a Web server vary from server to server. You CHM hooked CONVERTER By THETA-SOFTWARE
should ask your local Webmaster for help if you want to try this out on your local Web site. The Tcl Web Server comes with this guestbook example already set up, plus it has a number of other very interesting ways to generate pages. My own taste in Web page generation has shifted from CGI to a template-based approach supported by the Tcl Web Server. This is the topic of Chapter 18. The next few chapters describe basic Tcl commands and data structures. We return to the CGI example in Chapter 11 on regular expressions. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
This trick of feeding a Tcl command bad arguments to find out its usage is common across many commands. Table 4-1 summarizes the string command.
string last subString Returns the index in string of the last occurrence of subString , or -1 if string ?startIndex? subString is not found. startIndex may be specified to start in the middle of string . string length string string map ?-nocase? charMap string string match ?nocase? pattern str string range str i j string repeat str count string replace str first last ? newstr ? Returns the number of characters in string . Returns a new string created by mapping characters in string according to the input, output list in charMap . See page 55. Returns 1 if str matches the pattern , else 0. Glob-style matching is used. See page 53. Returns the range of characters in str from i to j . Returns str repeated count times. Returns a new string created by replacing characters first through last with newstr , or nothing.
string tolower string Returns string in lower case. first and last determine the range of string on ? first ? ? last ? which to operate. string totitle string Capitalizes string by replacing its first character with the Unicode title case, or ? first ? ? last ? upper case, and the rest with lower case. first and last determine the range of string on which to operate. string toupper string Returns string in upper case. first and last determine the range of string ? first ? ? last ? on which to operate. string trim string ? chars ? string trimleft string ? chars ? string trimright string ? chars ? Trims the characters in chars from both ends of string . chars defaults to whitespace. Trims the characters in chars from the beginning of string . chars defaults to whitespace. Trims the characters in chars from the end of string . chars defaults to whitespace.
string wordend str ix Returns the index in str of the character after the word containing the character at index ix . string wordstart str ix Returns the index in str of the first character in the word containing the character at index ix .
These are the string operations I use most: The equal operation, which is shown in Example 4-2 on page 53. String match . This pattern matching operation is described on page 53. The tolower, totitle, and toupper operations convert case. The trim , trimright , and trimleft operations are handy for cleaning up strings. These new operations were added in Tcl 8.1 (actually, they first appeared in the 8.1.1 patch release): The equal operation, which is simpler than using string compare .
The is operation that test for kinds of strings. String classes are listed in Table 4-3 on page 54. The map operation that translates characters (e.g., like the Unix tr command.) The repeat and replace operations. The totitle operation, which is handy for capitalizing words.
String Indices
Several of the string operations involve string indices that are positions within a string. Tcl counts characters in strings starting with zero. The special index end is used to specify the last character in a string:
Tcl 8.1 added syntax for specifying an index relative to the end. Specify end- N to get the N th character before the end. For example, the following command returns a new string that drops the first and last characters from the original:
There are several operations that pick apart strings: first , last , wordstart , wordend , index , and range . If you find yourself using combinations of these operations to pick apart data, it may be faster if you can do it with the regular expression pattern matcher described in Chapter 11 .
Despite the quotes, the expression operators that work on numbers and strings first convert try converting items to numbers if possible, and then converts them back if it detects a case of string comparison. The conversion back is always done as a decimal number. This can lead to unexpected conversions between strings that look like hexadecimal or octal numbers. The following boolean expression is true!
A safe way to compare strings is to use the string compare and string equal operations. The eq and ne expr operators were introduced in 8.4 to allow more compact strict string comparison. These operations also work faster because the unnecessary conversions are eliminated. Like the C library strcmp function, string compare returns 0 if the strings are equal, minus 1 if the first string is lexicographically less than the second, or 1 if the first string is greater than the second:
The string equal command added in Tcl 8.1 makes this simpler:
The eq operator added in Tcl 8.4 is semantically equal, but more compact. It also avoids any internal format conversions. There is also a ne operator to efficiently test for inequality.
String Matching
The string match command implements glob -style pattern matching that is modeled after the file name pattern matching done by various UNIX shells. The heritage of the word "glob" is rooted in UNIX, and Tcl preserves this historical oddity in the glob command that does pattern matching on file names. The glob command is described on page 122. Table 4-2 shows the three constructs used in string match patterns:
* ? [ chars ]
Match any number of any characters. Match exactly one character. Match any character in chars .
Any other characters in a pattern are taken as literals that must match the input exactly. The following example matches all strings that begin with a :
UNREGISTERED all two-letter strings: TO PDF CONVERTER By THETA-SOFTWARE To match VERSION OF CHM
string match ?? XY => 1
Be careful! Square brackets are also special to the Tcl interpreter, so you will need to wrap the pattern up in curly braces to prevent it from being interpreted as a nested command. Another approach is to put the pattern into a variable:
You can specify a range of characters with the syntax [ x-y ] . For example, [a-z] represents the set of all lower-case letters, and [0-9] represents all the digits. You can include more than one range in a set. Any letter, digit, or the underscore is matched with:
The set matches only a single character. To match more complicated patterns, like one or more characters from a set, then you need to use regular expression matching, which is described on page 158. If you need to include a literal * , ? , or bracket in your pattern, preface it with a backslash:
In this case the pattern is quoted with curly braces because the Tcl interpreter is also doing backslash substitutions. Without the braces, you would have to use two backslashes. They are replaced with a single
Character Classes
The string is command tests a string to see whether it belongs to a particular class . This is useful for input validation. For example, to make sure something is a number, you do:
if {![string is integer -strict $input]} { error "Invalid input. Please enter a number." }
Classes are defined in terms of the Unicode character set, which means they are more general than specifying character sets with ranges over the ASCII encoding. For example, alpha includes many characters outside the range of [A-Za-z] because of different characters in other alphabets. The classes are listed in Table 4-3 .
wordchar Alphabet, digit, and the underscore. xdigit Valid hexadecimal digits.
Mapping Strings
The string map command translates a string based on a character map. The map is in the form of a input, output list. Wherever a string contains an input sequence, that is replaced with the corresponding output. For example:
The inputs and outputs can be more than one character and they do not have to be the same length:
Example 4-4 is more practical. It uses string map to replace fancy quotes and hyphens produced by Microsoft Word into ASCII equivalents. It uses the open , read , and close file operations that are described in Chapter 9 , and the fconfigure command described on page 234 to ensure that the file format is UNIX friendly.
[ Team LiB ]
[ Team LiB ]
The append command provides an efficient way to add items to the end of a string. It modifies a variable directly, so it can exploit the memory allocation scheme used internally by Tcl. Using the append command like this:
The lappend command described on page 65 has similar performance benefits when working with Tcl lists. [ Team LiB ]
[ Team LiB ]
d u i o x or X c s f e or E g or G
Signed integer. Unsigned integer. Signed integer. The argument may be in hex (0x) or octal (0) format. Unsigned octal. Unsigned hexadecimal. 'x' gives lowercase results. Map from an integer to the ASCII character it represents. A string. Floating point number in the format a.b. Floating point number in scientific notation, a.bE+-c. Floating point number in either %f or %e format, whichever is shorter.
A position specifier is i$, which means take the value from argument i as opposed to the normally corresponding argument. The position counts from 1. If a position is specified for one format keyword, the position must be used for all of them. If you group the format specification with double quotes, you need to quote the $ with a backslash:
The position specifier is useful for picking a string from a set, such as this simple languagespecific example. The message catalog facility described in Chapter 15 is a much more sophisticated way to solve this problem. The position is also useful if the same value is repeated in the formatted string. The flags in a format are used to specify padding and justification. In the following examples, the # causes a leading 0x to be printed in the hexadecimal value. The zero in 08 causes the field to be padded with zeros. Table 4-5 summarizes the format flag characters.
After the flags you can specify a minimum field width value. The value is padded to this width with spaces, or with zeros if the 0 flag is used:
space Precede a number with a space, unless the number has a leading sign. Useful for packing numbers close together. 0 Pad with zeros. point. Do not remove trailing zeros (%g). format "%-20s %3d" Label 2 => Label 2
UNREGISTERED VERSION octal. Leading 0x forCONVERTER By THETA-SOFTWARE OF CHM TO PDF hex. Always include a decimal point in floating # Leading 0 for
set maxl 8 format "%-*s = %s" $maxl Key Value => Key = Value
The precision comes next, and it is specified with a period and a number. For %f and %e it indicates how many digits come after the decimal point. For %g it indicates the total number of significant digits used. For %d and %x it indicates how many digits will be printed, padding with zeros if necessary.
The storage length part comes last but it only became useful in Tcl 8.4 where wide integer support was added. Otherwise Tcl maintains all floating point values in double-precision, and all integers as long words. Wide integers are a minimum of 64-bits wide. By adding the l (long) word length specifier, we can see the difference between regular and wide integers.
[ Team LiB ]
[ Team LiB ]
The format for scan is nearly the same as in the format command. The %c scan format converts one character to its decimal value. The scan format includes a set notation. Use square brackets to delimit a set of characters. The set matches one or more characters that are copied into the variable. A dash is used to specify a range. The following scans a field of all lowercase letters.
If the first character in the set is a right square bracket, then it is considered part of the set. If the first character in the set is ^, then characters not in the set match. Again, put a right square bracket immediately after the ^ to include it in the set. Nothing special is required to include a left square bracket in the set. As in the previous example, you will want to protect the format with braces, or use backslashes, because square brackets are special to the Tcl parser. [ Team LiB ]
[ Team LiB ]
This section describes the binary command that provides conversions between strings and packed binary data representations. The binary format command takes values and packs them according to a template. For example, this can be used UNREGISTERED VERSION OF CHM TO PDF CONVERTER By to format a floating point vector in THETA-SOFTWARE memory suitable for passing to Fortran. The resulting binary value is returned:
The binary scan command extracts values from a binary string according to a similar template. For example, this is useful for extracting data stored in binary data file. It assigns values to a set of Tcl variables:
Format Templates
The format template consists of type keys and counts. The count is interpreted differently depending on the type. For types like integer (i) and double (d), the count is a repetition count (e.g., i3 means three integers). For strings, the count is a length (e.g., a3 means a threecharacter string). If no count is specified, it defaults to 1. If count is *, then binary scan uses all the remaining bytes in the value. Several type keys can be specified in a template. Each key-count combination moves an imaginary cursor through the binary data. There are special type keys to move the cursor. The x key generates null bytes in binary format, and it skips over bytes in binary scan. The @ key uses its count as an absolute byte offset to which to set the cursor. As a special case, @* skips to the end of the data. The X key backs up count bytes. The types are summarized in Table 4-6. In the table, count is the optional count following the type letter.
a A character string of length count. Padded with nulls in binary format. A A character string of length count. Padded with spaces in binary format. Trailing nulls and blanks are discarded in binary scan. b A binary string of length count. Low-to-high order. B A binary string of length count. High-to-low order. h A hexadecimal string of length count. Low-to-high order. H A hexadecimal string of length count. High-to-low order. (More commonly used than h.) c An 8-bit character code. The count is for repetition. s A 16-bit integer in little-endian byte order. The count is for repetition. S A 16-bit integer in big-endian byte order. The count is for repetition. i A 32-bit integer in little-endian byte order. The count is for repetition. I A 32-bit integer in big-endian byte order. The count is for repetition. f Single-precision floating point value in native format.The count is for repetition. d Double-precision floating point value in native format. The count is for repetition. w A 64-bit integer in little-endian byte order. The count is for repetition. (Tcl 8.4) W A 64-bit integer in big-endian byte order. The count is for repetition. (Tcl 8.4) x Pack count null bytes with binary format. Skip count bytes with binary scan. X Backup count bytes. @ Skip to absolute position specified by count. If count is *, skip to the end. Numeric types have a particular byte order that determines how their value is laid out in memory. The type keys are lowercase for little-endian byte order (e.g., Intel) and uppercase for big-endian byte order (e.g., SPARC and Motorola). Different integer sizes are 16-bit (s or S), 32-bit (i or I), and, with Tcl 8.4 or greater, 64-bit (w or W). Note that the official byte order for data transmitted over a network is big-endian. Floating point values are always machinespecific, so it only makes sense to format and scan these values on the same machine. There are three string types: character (a or A), binary (b or B), and hexadecimal (h or H). With these types the count is the length of the string. The a type pads its value to the specified length with null bytes in binary format and the A type pads its value with spaces. If the value is too long, it is truncated. In binary scan, the A type strips trailing blanks and nulls. A binary string consists of zeros and ones. The b type specifies bits from low-to-high order, and the B type specifies bits from high-to-low order. A hexadecimal string specifies 4 bits (i.e., nybbles) with each character. The h type specifies nybbles from low-to-high order, and the H type specifies nybbles from high-to-low order. The B and H formats match the way you normally write out numbers.
Examples
When you experiment with binary format and binary scan, remember that Tcl treats things as strings by default. A "6", for example, is the character 6 with character code 54 or 0x36. The c type returns these character codes:
set input 6 binary scan $input "c" 6val set 6val UNREGISTERED VERSION OF CHM TO => 54
UNREGISTERED VERSION OFlist TO PDF CONVERTER By THETA-SOFTWARE binary scan abc "c3" CHM
=> 1 set list => 97 98 99
The previous example uses a single type key, so binary scan sets one corresponding Tcl variable. If you want each character code in a separate variable, use separate type keys:
Use the a and A formats to extract fixed width fields. Here the * count is used to get all the rest of the string. Note that A trims trailing spaces:
binary scan "hello world " a3x2A* first second puts "\"$first\" \"$second\"" => "hel" " world"
Use the @ key to seek to a particular offset in a value. The following command gets the second double-precision number from a vector. Assume the vector is read from a binary data file:
With binary format, the a and A types create fixed width fields. A pads its field with spaces, if necessary. The value is truncated if the string is too long:
Remember that floating point values are always in native format, so you have to read them on the same type of machine that they were created. With integer data you specify either bigendian or little-endian formats. The tcl_platform variable described on page 193 can tell you the byte order of the current platform.
fconfigure stdout -translation binary -encoding binary puts [binary format "B8" 11001010]
[ Team LiB ]
[ Team LiB ]
Related Chapters
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
To learn more about manipulating data in Tcl, read about lists in Chapter 5 and arrays in Chapter 8. For more about pattern matching, read about regular expressions in Chapter 11.
[ Team LiB ]
[ Team LiB ]
Tcl Lists
A Tcl list is a sequence of CHM When you write out a list, it THETA-SOFTWARE UNREGISTERED VERSION OF values.TO PDF CONVERTER By has the same syntax as a Tcl command. A list has its elements separated by white space. Braces or quotes can be used to group words with white space into a single list element. Because of the relationship between lists and commands, the list-related commands described in this chapter are used often when constructing Tcl commands.
Early versions of Tcl represented all values as strings. Lists were just strings with special syntax to group their elements. The string representation was parsed on each list access, so you could have performance problems with large lists. The performance of lists was improved by the Tcl compiler added in Tcl 8.0. The Tcl runtime now stores lists using an C array of pointers to each element. (The Tcl_Obj type is described on page 694.) Tcl can access any element in the list with the same cost. Appending new elements to a list is made efficient by over allocating the array so there is room to grow. The internal format also records the number of list elements, so getting the length of a list is cheap. However, you can still get into performance trouble if you use a big Tcl list like a string, e.g., for output. Tcl will convert the list into a string representation if you print it to a file, or manipulate it with string commands. Table 5-1 describes Tcl commands for lists.
list arg1 arg2 ... lindex list ?i ...? llength list lrange list i j lappend listVar arg ... linsert list index arg arg ... lreplace list i j arg arg ... lsearch ? options? list value lset listVar ?i ...? newValue lsort ?switches? list
Creates a list out of all its arguments. Returns the ith element from list. Specifying multiple index elements allows you to descend into nested lists easily. Returns the number of elements in list. Returns the ith through jth elements from list. Appends elements to the value of listVar. Inserts elements into list before the element at position index. Returns a new list. Replaces elements i through j of list with the args. Returns a new list. Returns the index of the element in list that matches the value according to the options. Glob matching is the default. Returns -1 if not found. Set the ith element in variable listVar to newValue. (Tcl 8.4) Sorts elements of the list according to the switches: -ascii, dictionary, -integer, -real, -increasing, -decreasing, -index ix, -unique, -command command. Returns a new list. Joins multiple lists together into one list. Merges the elements of a list together by separating them with joinString. Splits a string up into list elements, using the characters in splitChars as boundaries between list elements.
concat list list ... join list joinString split string splitChars [ Team LiB ]
[ Team LiB ]
Constructing Lists
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Constructing a list can be tricky if you try to write the proper list syntax by hand. The manual approach works for simple cases. In more complex cases, however, you should use Tcl commands that build lists. Using list commands eliminates the struggle to get the grouping and quoting right, and the list is maintained in an efficient internal format. If you create lists by hand with quoting, there is additional overhead to parse the string representation the first time you use the list.
The first list, l1, has three elements. The values of the elements do not affect the list structure. The second list, l2, has two elements, the value of l1 and the value of x. Internally Tcl shares values instead of making copies, so constructing lists out of other values is quite efficient. When you first experiment with Tcl lists, the treatment of curly braces can be confusing. In the assignment to x, for example, the curly braces disappear. However, they seem to come back again when $x is put into a bigger list. Also, the double quotes around a b get changed into
curly braces. What's going on? There are three steps in the process. In the first step, the Tcl parser groups arguments to the list command. In the grouping process, the braces and quotes are syntax that define groups. These syntax characters get stripped off. The braces and quotes are not part of the values being grouped. In the second step, the list command creates an internal list structure. This is an array of references to each value. In the third step the value is printed out. This step requires conversion of the list into a string representation. The string representation of the list uses curly braces to group values back into list elements.
The lappend command is unique among the list-related commands because its first argument is the name of a list-valued variable, while all the other commands take list values as arguments. You can call lappend with the name of an undefined variable and the variable will be created.
Example 5-4 Using concat to splice lists together UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
set x {4 5 6} set y {2 3} set z 1 concat $z $y $x => 1 2 3 4 5 6
Double quotes behave much like the concat command. In simple cases, double quotes behave exactly like concat. However, the concat command trims extra white space from the end of its arguments before joining them together with a single separating space character. Example 5-5 compares the use of list, concat, and double quotes:
Example 5-5 Double quotes compared to the concat and list commands
set x {1 2} => 1 2 set y "$x 3" => 1 2 3 set y [concat $x 3] => 1 2 3 set s { 2 } => 2 set y "1 $s 3" => 1 2 3 set y [concat 1 $s 3] => 1 2 3 set z [list $x $s 3] => {1 2} { 2 } 3
The distinction between list and concat becomes important when Tcl commands are built dynamically. The basic rule is that list and lappend preserve list structure, while concat (or double quotes) eliminates one level of list structure. The distinction can be subtle because there are examples where list and concat return the same results. Unfortunately, this can lead to data-dependent bugs. Throughout the examples of this book, you will see the list command used to safely construct lists. This issue is discussed more in Chapter 10.
[ Team LiB ]
[ Team LiB ]
llength
The llength command returns TO PDF CONVERTER a list. UNREGISTERED VERSION OF CHMthe number of elements in By THETA-SOFTWARE llength {a b {c d} "e f g" h} => 5 llength {} => 0 UNREGISTERED VERSION OF CHM TO
The lindex command returns a particular element of a list. It takes an index; list indices count from zero.
You can use the keyword end to specify the last element of a list, or the syntax end-N to count back from the end of the list. The following commands are equivalent ways to get the element just before the last element in a list.
The lrange command returns a range of list elements. It takes a list and two indices as arguments. Again, end or end-N can be used as an index:
[ Team LiB ]
[ Team LiB ]
lreplace replaces a range of list elements with new elements. If you don't specify any new elements, you effectively delete elements from a list. Note: linsert and lreplace do not modify an existing list like the lappend and lset commands. Instead, they return a new list value. In the Example 5-6, the lreplace command does not change the value of x:
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF the glob pattern CONVERTER By THETA-SOFTWARE In the following example, CHM TO PDF l* matches the value list, and lsearch returns the
index of that element in the input list:
Tcl 8.4 added several features to lsearch, including typed searching, optimized searches for sorted lists, and the ability to find all matching elements of a list. The lsearch typed searches use the internal object representation for efficiency and speed. For example, if you have a list of numbers, the -integer option tells lsearch to leave the values in their native integer format. Otherwise it would convert them to strings as it did the search. If your list has been sorted, the -sorted option tells lsearch to perform an efficient binary search. Sorting lists is described on page 70. The -inline option returns the list value instead of the index. This is most useful when you are matching a pattern, and it works well with the -all option that returns all matching indices, or values:
set foo {the quick brown fox jumped over a lazy dog} lsearch -inline -all $foo *o* => brown fox over dog
-decreasing Assume list elements are in decreasing order. Only meaningful when used with -sorted. -dictionary The list elements are to be compared using dictionary-style comparison. Only meaningful when used with -exact or -sorted. -exact -glob Do exact string matching. Mutually exclusive with -glob and -regexp. Do glob-style pattern matching (default). Mutually exclusive with -exact and regexp.
-increasing Assume list elements are in increasing order. Only meaning when used with sorted. -inline -integer -not -real -regexp -sorted Return the actual matching element(s) instead of the index to the element. An empty string is returned if no elements match. The list elements are to be compared as integers. Only meaning when used with -exact or -sorted. Negate the sense of the match. Examine all elements as real (floating-point) values. Only meaning when used with -exact or -sorted. Do regular expression pattern matching. Mutually exclusive with -exact and glob. Regular expressions are described in Chapter 11. Specifies that the list is presorted, so Tcl can do a faster binary search to find the pattern. Specify the start index in the list to begin searching.
[ Team LiB ]
Sorting Lists:
lsort
You can sort a list in variety of ways with lsort. The list is THETA-SOFTWARE UNREGISTERED VERSIONaOF CHM TO PDF CONVERTER Bynot sorted in place. Instead, a new list value is returned. The basic types of sorts are specified with the -ascii, -dictionary, integer, or -real options. The -increasing or -decreasing option indicate the sorting order. The default option set is -ascii -increasing. An ASCII sort uses character codes, and a dictionary sort folds together case and treats digits like numbers. For example:
You can provide your own sorting function for special-purpose sorting. For example, suppose you have a list of names, where each element is itself a list containing the person's first name, middle name (if any), and last name. The default sorts by everyone's first name. If you want to sort by their last name, you need to supply a sorting command.
The NameCompare procedure extracts the last element from each of its arguments and compares those. If they are equal, then it just compares the whole of each argument. Tcl 8.0 added a -index option to lsort that can be used to sort lists on an index. Instead of using NameCompare, you could do this:
Tcl 8.3 added a -unique option that removes duplicates during sort:
[ Team LiB ]
[ Team LiB ]
set line {welch:*:28405:100:Brent Welch:/usr/welch:/bin/csh} split $line : UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE => welch * 28405 100 {Brent Welch} /usr/welch /bin/csh lindex [split $line :] 4 => Brent Welch
Even if your data has space-separated words, you should be careful when using list operators on arbitrary input data. Otherwise, stray double quotes or curly braces in the input can result in invalid list structure and errors in your script. Your code will work with simple test cases, but when invalid list syntax appears in the input, your script will raise an error. The next example shows what happens when input is not a valid list. The syntax error, an unmatched quote, occurs in the middle of the list. However, you cannot access any of the list because the lindex command tries to convert the value to a list before returning any part of it.
Example 5-9 Use split to turn input data into Tcl lists
set line {this is "not a tcl list} lindex $line 1 => unmatched open quote in list lindex [split $line] 2 => "not
The default separator character for split is white space, which contains spaces, tabs, and newlines. If there are multiple separator characters in a row, these result in empty list elements; the separators are not collapsed. The following command splits on commas, periods, spaces, and tabs. The backslashspace sequence is used to include a space in the set of characters. You could also group the argument to split with double quotes:
A trick that splits each character into a list element is to specify an empty string as the split character. This lets you get at individual characters with list operations:
However, if you write scripts that process data one character at a time, they may run slowly. Read Chapter 11 about regular expressions for hints on really efficient string processing and using regexp for a multi-character split routine. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Related Chapters
Arrays are the other main data structure in Tcl. They are described in Chapter 8. List operations are used when generating Tcl code dynamically. Chapter 10 describes these techniques when using the eval command. The foreach command loops over the values in a list. It is described on page 79 in Chapter 6. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
If Then Else The if command is the basic conditional command. If an expression is true, then execute one command body; otherwise, execute another command body. The second command body (the else clause) is optional. The syntax of the command is:
The then and else keywords are optional. In practice, I omit then but use else as illustrated in the next example. I always use braces around the command bodies, even in the simplest cases:
The style of this example takes advantage of the way the Tcl interpreter parses commands. Recall that newlines are command terminators, except when the interpreter is in the middle of a group defined by braces or double quotes. The stylized placement of the opening curly brace at the end of the first and third lines exploits this property to extend the if command over multiple lines. The first argument to if is a boolean expression. As a matter of style this expression is grouped with curly braces. The expression evaluator performs variable and command substitution on the expression. Using curly braces ensures that these substitutions are performed at the proper time. It is possible to be lax in this regard, with constructs such as:
if $x break continue
This is a sloppy, albeit legitimate, if command that will either break out of a loop or continue with the next iteration depending on the value of variable x. This style is fragile and error prone. Instead, always use braces around the command bodies to avoid trouble later when you modify the command. The following is much better (use then if it suits your taste):
if [command] body1
if {[command]} body1
You can create chained conditionals by using the elseif keyword. Again, note the careful placement of curly braces that create a single if command:
Any number of conditionals can be chained in this manner. However, the switch command provides a more powerful way to test multiple conditions. [ Team LiB ]
[ Team LiB ]
Switch The switch command is used to branch to one of many command bodies depending on the value of an expression. The choice can be made on the basis of pattern matching as well as simple comparisons. Pattern matching is discussed in more detail in Chapter 4 and Chapter 11. The general form of the command is:
Any number of pattern-body pairs can be specified. If multiple patterns match, only the body of the first matching pattern is evaluated. You can also group all the pattern-body pairs into one argument:
The first form allows substitutions on the patterns but will require backslashes to continue the command onto multiple lines. This is shown in Example 6-4 on page 78. The second form groups all the patterns and bodies into one argument. This makes it easy to group the whole command without worrying about newlines, but it suppresses any substitutions on the patterns. This is shown in Example 6-3. In either case, you should always group the command bodies with curly braces so that substitution occurs only on the body with the pattern that matches the value. There are four possible flags that determine how value is matched. -exact -glob Matches the value exactly to one of the patterns. This is the default. Uses glob-style pattern matching. See page 53.
-regexp Uses regular expression pattern matching. See page 144. -No flag (or end of flags). Necessary when value can begin with -.
The switch command raises an error if any other flag is specified or if the value begins with -. In practice I always use the -- flag before value so that I don't have to worry about that problem. If the pattern associated with the last body is default, then this command body is executed if no other patterns match. The default keyword works only on the last pattern-body pair. If you use the default pattern on an earlier body, it will be treated as a pattern to match the literal string default:
If you have variable references or backslash sequences in the patterns, then you cannot use braces around all the pattern-body pairs. You must use backslashes to escape the newlines in the command:
Example 6-4 Using switch with CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDFsubstitutions in the patterns
switch -regexp -- $value \ ^$key { body1 }\ \t### { body2 }\ UNREGISTERED VERSION OF CHM {[0-9]*} { body3 }
In this example, the first and second patterns have substitutions performed to replace $key with its value and \t with a tab character. The third pattern is quoted with curly braces to prevent command substitution; square brackets are part of the regular expression syntax, too. (See page Chapter 11.) If the body associated with a pattern is just a dash, -, then the switch command "falls through" to the body associated with the next pattern. You can tie together any number of patterns in this manner.
[ Team LiB ]
[ Team LiB ]
While The while command takes two arguments, a test and a command body:
The while command repeatedly tests the boolean expression and then executes the body if the expression is true (nonzero). Because the test expression is evaluated again before each iteration of the loop, it is crucial to protect the expression from any substitutions before the while command is invoked. The following is an infinite loop (see also Example 1-13 on page 12):
It is also possible to put nested commands in the boolean expression. The following example uses gets to read standard input. The gets command returns the number of characters read, returning -1 upon end of file. Each time through the loop, the variable line contains the next line in the file:
[ Team LiB ]
[ Team LiB ]
Foreach The foreach command loops over a command body assigning one or more loop variables to each of the values in OF CHM TO PDF CONVERTER By which were introduced UNREGISTERED VERSIONone or more lists. Multiple loop variables,THETA-SOFTWARE in Tcl 7.5, are a very useful feature. The syntax for the simple case of a single variable and a single list is:
It is also common to use a list-valued variable or command result instead of a static list value. The next example loops through command-line arguments. The variable argv is set by the Tcl interpreter to be a list of the command-line arguments given when the interpreter was started:
The loop uses the state variable to keep track of what is expected next, which in this example is either a flag or the integer value for -max. The -- flag to switch is required in this example because the switch command complains about a bad flag if the pattern begins with a character. The -glob option lets the user abbreviate the -force and -verbose options. If the list of values is to contain variable values or command results, then the list command should be used to form the list. Avoid double quotes because if any values or command results contain spaces or braces, the list structure will be reparsed, which can lead to errors or unexpected results.
The loop variable x will take on the value of a, the value of b, and the result of the foo command, regardless of any special characters or whitespace in those values.
If you have a command that returns a short list of values, then you can abuse the foreach command to assign the results of the commands to several variables all at once. For example, suppose the command MinMax returns two values as a list: the minimum and maximum values. Here is one way to get the values:
set result [MinMax $list] set min [lindex $result 0] set max [lindex $result 1]
The break in the body of the foreach loop guards against the case where the command
UNREGISTERED VERSION OF we expected. This trick is encapsulated into the lassign procedure in returns more values than CHM TO PDF CONVERTER By THETA-SOFTWARE
Example 10-4 on page 139.
[ Team LiB ]
[ Team LiB ]
For The for command is similar to the C for statement. It takes four arguments:
The first argument is a command to initialize the loop. The second argument is a boolean expression that determines whether the loop body will execute. The third argument is a command to execute after the loop body:
You could use for to iterate over a list, but you should really use foreach instead. Code like the following is slow and cluttered:
for {set i 0} {$i < [llength $list]} {incr i} { set value [lindex $list $i] }
[ Team LiB ]
[ Team LiB ]
Break
and Continue
You can control loop execution with PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TOthe break and continue commands. The break command causes immediate exit from a loop, while the continue command causes the loop to continue with the next iteration. There is no goto command in Tcl.
[ Team LiB ]
[ Team LiB ]
Catch Until now we have ignored the possibility of errors. In practice, however, a command will raise an error if it is called with the wrong number of arguments, or if it detects some error condition particular to its implementation. An uncaught error aborts execution of a script.[*] The catch command is used to trap such errors. It takes two arguments:
[*]
More precisely, the Tcl script unwinds and the current Tcl_Eval procedure in the C runtime library returns TCL_ERROR. There are three cases. In interactive use, the Tcl shell prints the error message. In Tk, errors that arise during event handling trigger a call to bgerror , a Tcl procedure you can implement in your application. In your own C code, you should check the result of Tcl_Eval and take appropriate action in the case of an error.
The first argument to catch is a command body. The second argument is the name of a variable that will contain the result of the command, or an error message if the command raises an error. catch returns zero if there was no error caught, or a nonzero error code if it did catch an error. You should use curly braces to group the command instead of double quotes because catch invokes the full Tcl interpreter on the command. If double quotes are used, an extra round of substitutions occurs before catch is even called. The simplest use of catch looks like the following:
catch { command }
A more careful catch phrase saves the result and prints an error message:
if {[catch { command arg1 arg2 ... } result]} { puts stderr $result } else { # command was ok, result contains the return value }
A more general catch phrase is shown in the next example. Multiple commands are grouped into a command body. The errorInfo variable is set by the Tcl interpreter after an error to reflect the stack trace from the point of the error:
command2 command3 } result]} { global errorInfo puts stderr $result puts stderr "*** Tcl TRACE ***" puts stderr $errorInfo } else { UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE # command body ok, result of last command is in result }
These examples have not grouped the call to catch with curly braces. This is acceptable because catch always returns an integer, CONVERTER By will parse correctly. However, if UNREGISTERED VERSION OF CHM TO PDF so the if command THETA-SOFTWARE we had used while instead of if, then curly braces would be necessary to ensure that the catch phrase was evaluated repeatedly.
Example 6-16 There are several possible return values from catch
switch [catch { command1 command2 ... } result] { 0 { 1 { 2 { return $result 3 { break 4 { continue default { }
# # ;# ;# ;# #
Normal completion } Error case } return from procedure} break out of the loop} continue loop} User-defined error codes }
[ Team LiB ]
[ Team LiB ]
Error The error command raises an error condition that terminates a script unless it is trapped with the catch command. The command takes up to three arguments:
The message becomes the error message stored in the result variable of the catch command. If the info argument is provided, then the Tcl interpreter uses this to initialize the errorInfo global variable. That variable is used to collect a stack trace from the point of the error. If the info argument is not provided, then the error command itself is used to initialize the errorInfo trace.
In the previous example, the error command itself appears in the trace. One common use of the info argument is to preserve the errorInfo that is available after a catch. In the next example, the information from the original error is preserved:
The code argument specifies a concise, machine-readable description of the error. It is stored into the global errorCode variable. It defaults to NONE. Many of the file system commands return an errorCode that has three elements: POSIX, the error name (e.g., ENOENT), and the
In addition, your application can define error codes of its own. Catch phrases can examine the code in the global errorCode variable and decide how to respond to the error.
[ Team LiB ]
Return The return command is used to return from a procedure. It is needed if return is to occur before the end of the procedure body, or if a constant value needs to be returned. As a matter of style, I also use return at the end of a procedure, even though a procedure returns the value of the last command executed in the body. Exceptional return conditions can be specified with some optional arguments to return. The complete syntax is:
The -code option value is one of ok, error, return, break, continue, or an integer. ok is the default if -code is not specified. The -code error option makes return behave much like the error command. The errorcode option sets the global errorCode variable, and the -errorinfo option initializes the errorInfo global variable. When you use return -code error, there is no error command in the stack trace. Compare Example 6-17 with Example 6-19:
The return, break, and continue code options take effect in the caller of the procedure doing the exceptional return. If -code return is specified, then the calling procedure returns. If code break is specified, then the calling procedure breaks out of a loop, and if -code continue is specified, then the calling procedure continues to the next iteration of the loop. These -code options to return enable the construction of new control structures entirely in Tcl. The following example implements the break command with a Tcl procedure:
You can return integer-valued codes of your own with return -code, and trap them with catch
in order to create your own control structures. There are also a number of exception packages available on the net that provide Java-like try-catch-except structures for Tcl, although the Tcl exception mechanism strikes a nice balance between simplicity and power. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER contain any characters. Procedure By THETA-SOFTWARE by the Tcl interpreter. The name is case sensitive and can
The first argument is the procedure name, which is added to the set of commands understood names do not conflict with variable names. The second argument is a list of parameter names. The last argument is the body of the procedure. Once defined, a Tcl procedure is used just like any other Tcl command. When it is called, each argument is assigned to the corresponding parameter and the body is evaluated. The result of the procedure is the result returned by the last command in the body. The return command can be used to return a specific value. Procedures can have default parameters so that the caller can leave out some of the command arguments. A default parameter is specified with its name and default value, as shown in the next example:
Here the procedure P2 can be called with one, two, or three arguments. If it is called with only one argument, then the parameters b and c take on the values specified in the proc command. If two arguments are provided, then only c gets the default value, and the arguments are assigned to a and b. At least one argument and no more than three arguments can be passed to P2. A procedure can take a variable number of arguments by specifying the args keyword as the last parameter. When the procedure is called, the args parameter is a list that contains all the remaining values:
set y {two things} set z \[special\$ ArgTest $x => a = one b = foo args = ArgTest $y $z => a = two things b = [special$ args = ArgTest $x $y $z => a = one b = two things args = {[special$} ArgTest $z $y $z $x => a = [special$ b = two things args = {[special$} one
The effect of the list structure in args is illustrated by the treatment of variable z in Example 72. The value of z has special characters in it. When $z is passed as the value of parameter b, its value comes through to the procedure unchanged. When $z is part of the optional parameters, quoting is automatically added to create a valid Tcl list as the value of args. Example 10-3 on page 136 illustrates a technique that uses eval to undo the effect of the added list structure. [ Team LiB ]
[ Team LiB ]
rename
UNREGISTERED VERSION OF CHMthe name of a command. There are two main uses for rename. TO PDF CONVERTER By THETA-SOFTWARE The rename command changes
The first is to augment an existing procedure. Before you redefine it with proc, rename the existing command:
rename exec {}
Command renaming and deletion can be traced with the trace command described in Chapter 13. [ Team LiB ]
[ Team LiB ]
Scope
By default there is a single, global scope for procedure names. This means that you can use a procedure anywhere in your script. Variables defined outside any procedure are global variables. However, as described below, global variables are not automatically visible inside procedures. There is a different namespace for variables and procedures, so you could have a procedure and a global variable with the same name without conflict. You can use the namespace facility described in Chapter 7 to manage procedures and global variables. Each procedure has a local scope for variables. That is, variables introduced in the procedure live only for the duration of the procedure call. After the procedure returns, those variables are undefined. Variables defined outside the procedure are not visible to a procedure unless the upvar or global scope commands are used. You can also use qualified names to name variables in a namespace scope. The global and upvar commands are described later in this chapter. Qualified names are described on page 208. If the same variable name exists in an outer scope, it is unaffected by the use of that variable name inside a procedure. In Example 7-3, the variable a in the global scope is different from the parameter a to P1. Similarly, the global variable b is different from the variable b inside P1:
[ Team LiB ]
[ Team LiB ]
The global command adds a global variable to the current scope. A common mistake is to have a single global command and expect that to apply to all procedures. However, a global command in the global scope has no effect. Instead, you must put a global command in all procedures that access the global variable. The variable can be undefined at the time the global command is used. When the variable is defined, it becomes visible in the global scope. Example 7-4 shows a random number generator. Before we look at the example, let me point out that the best way to get random numbers in Tcl is to use the rand() math function:
The point of the example is to show a state variable, the seed, that has to persist between calls to random, so it is kept in a global variable. The choice of randomSeed as the name of the global variable associates it with the random number generator. It is important to pick names of global variables carefully to avoid conflict with other parts of your program. For comparison, Example 14-1 on page 206 uses namespaces to hide the state variable:
proc RandomRange { range } { expr int([Random]*$range) } RandomInit [pid] => 5049 Random => 0.517686899863 Random => 0.217176783265 RandomRange 100 => 17
[*]
Adapted from Exploring Expect by Don Libes, O'Reilly & Associates, Inc., 1995, and from Numerical Recipes in C by Press et al., Cambridge University Press, 1988.
[ Team LiB ]
[ Team LiB ]
The variable in the uplevel stack frame can be either a scalar variable, an array element, or an array name. In the first two cases, the local variable is treated like a scalar variable. In the case of an array name, then the local variable is treated like an array. The use of upvar and arrays is discussed further in Chapter 8 on page 99. The following procedure uses upvar to print the value of a variable given its name.
You can use upvar to fix the incr command. One drawback of the built-in incr is that it raises an error if the variable does not exist. We can define a new version of incr that initializes the variable if it does not already exist:
[ Team LiB ]
[ Team LiB ]
Using the name directly like this is somewhat risky. If there were an object named x, then this trick might conflict with an unrelated variable named x elsewhere in your program. You can modify the name to make this trick more robust:
Your code can pass name around as a handle on an object, then use upvar to get access to the data associated with the object. Your code is just written to use the state variable, which is an alias to the state variable for the current object. This technique is illustrated in Example 17-7 on page 245.
Namespaces and
upvar
You can use upvar to create aliases for namespace variables, too. Namespaces are described in Chapter 14. For example, as an alternative to reserving all global variables beginning with state, you can use a namespace to hide these variables:
Now state is an alias to the namespace variable. This upvar trick works from inside any namespace.
The aliases created with upvar do not work with these commands, nor do they work if you use trace, which is described on page 193. Instead, you must use the actual name of the global variable. To continue the above example where state is an alias, you cannot:
The backslash turns off the array reference so Tcl does not try to access name as an array. You do not need to worry about special characters in $name, except parentheses. Once the name has been passed into the Tk widget it will be used directly as a variable name. Text variables for labels are explained on page 490, and text variables for entry widgets are illustrated in Example 34-1 on page 508. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Array Syntax
The index of an array is delimited by parentheses. The index can have any string value, and it can be the result of variable or command substitution. Array elements are defined with set:
Example 8-1 uses the loop variable value $i as an array index. It sets arr(x) to the product of 1 * 2 * ... * x:
Complex Indices
An array index can be any string, like orange, 5, 3.1415, or foo,bar. The examples in this chapter, and in this book, often use indices that are pretty complex strings to create flexible data structures. As a rule of thumb, you can use any string for an index, but avoid using a string that contains spaces.
The main Tcl parser does not know about array syntax. All the rules about grouping and substitution described in Chapter 1 are still the same in spite of the array syntax described here. Parentheses do not group like curly braces or quotes, which is why a space causes problems. If you have complex indices, use a comma to separate different parts of the index. If you use a space in an index instead, then you have a quoting problem. The space in the index
needs to be quoted with a backslash, or the whole variable reference needs to be grouped:
set {arr(I'm asking for trouble)} {I told you so.} set arr(I'm\ asking\ for\ trouble) {I told you so.}
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE value. The following works well:
set index {I'm asking for trouble} set arr($index) {I told you so.}
If the array index is stored in a variable, then there is no problem with spaces in the variable's
Array Variables
You can use an array element as you would a simple variable. For example, you can test for its existence with info exists, increment its value with incr, and append elements to it with lappend:
You can delete an entire array, or just a single array element with unset. Using unset on an array is a convenient way to clear out a big data structure. It is an error to use a variable as both an array and a normal variable. The following is an error:
set arr(0) 1 set arr 3 => can't set "arr": variable is array
The name of the array can be the result of a substitution. This is a tricky situation, as shown in Example 8-2:
A better way to deal with this situation is to use the upvar command, which is introduced on page 91. The previous example is much cleaner when upvar is used:
[ Team LiB ]
[ Team LiB ]
UNREGISTEREDindex [array names arr PDF CONVERTER By THETA-SOFTWARE VERSION OF CHM TO pattern] { foreach
# use arr($index) }
The order of the names returned by array names is arbitrary. It is essentially determined by the hash table implementation of the array. You can limit what names are returned by specifying a pattern that matches indices. The pattern is the kind supported by the string match command, which is described on page 53. It is also possible to iterate through the elements of an array one at a time using the searchrelated commands listed in Table 8-1. The ordering is also random, and I find the foreach over the results of array names much more convenient. If your array has an extremely large number of elements, or if you need to manage an iteration over a long period of time, then the array search operations might be more appropriate. Frankly, I never use them. Table 8-1 summarizes the array command:
array size arr array unset arr ? pattern? array startsearch arr
Returns the value of the next element in arr in the search identified by the token id. Returns an empty string if no more elements remain in the search. Returns 1 if more elements remain in the search. Ends the search identified by id. Returns statistics about the array hash table. (Tcl 8.4)
array set fruit { best kiwi worst peach ok banana } array get fruit => ok banana best kiwi worst peach
Another way to loop through the contents of an array is to use array get and the two-variable form of the foreach command.
foreach {key value} [array get fruit] { # key is ok, best, or worst # value is some fruit }
upvar $arrName array $inverseName inverse foreach {index value} [array get array $pattern] { set inverse($value) $index } }
[ Team LiB ]
A good use for arrays is to collect together a set of related variables for a module, much as one would use a record in other languages. By collecting these together in an array that has the same name as the module, name conflicts between different modules are avoided. Also, in each of the module's procedures, a single global statement will suffice to make all the state variables visible. You can also use upvar to manage a collection of arrays, as shown in Example 8-9 on page 101.
Simple Records
Suppose we have a database of information about people. The following examples show three different ways to store the employee name, ID, manager, and phone number. Each example implements Emp_AddRecord that stores the values, and one example accessor function that returns information about the employee (e.g., Emp_Manager.) By using simple procedures to return fields of the record, the implementation is hidden so that you can change it more easily. Example 8-5 uses on array for each field. The name of the person is the index into each array:
The employeeName array provides a secondary key. It maps from the employee ID to the name so that the other information can be obtained if you have an ID instead of a name. Example 8-6 implements the same little database using a single array with more complex indices:
Example 8-6 Using arrays for records, version 2 UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
proc Emp_AddRecord {id name manager phone} { global employee set employee(id,$name) $id set employee(manager,$name) $manager set employee(phone,$name) $phone CONVERTER UNREGISTERED VERSION OF CHM TO PDF set employee(name,$id) $name } proc Emp_Manager {name} { global employee return $employee(manager,$name) }
By THETA-SOFTWARE
Example 8-7 shows the last approach. Each array element is a list of fields, and the accessor functions hide the lindex command used to pick out the right field. Here the cross referencing by ID is implement differently. If we can assume that names and IDs are distinct, we can keep the cross reference in the same array:
The difference between these three approaches is partly a matter of taste. Using a single array can be more convenient because there are fewer variables to manage. Using the lists for the fields is probably the most space efficient because there are fewer elements in the array, but maintaining the lindex offsets is tedious. In any case, you should hide the implementation in a small set of procedures.
A Stack
A stack can be implemented with either a list or an array. If you use a list, then the push and pop operations have a runtime cost that is proportional to the size of the stack. If the stack has a few elements this is fine. If there are a lot of items in a stack, you may wish to use arrays instead.
In these examples, the name of the stack is a parameter, and upvar is used to convert that into the data used for the stack. The variable is a list in Example 8-8 and an array in Example 8-9. The user of the stack module does not have to know. The array implementation of a stack uses one array element to record the number of items in the stack. The other elements of the array have the stack values. The Push and Pop procedures both guard against a nonexistent array with the info exists command. When the first assignment to S(top) is done by Push, the array variable is created in the caller's scope. The example uses array indices in two ways. The top index records the depth of the stack. The other indices are numbers, so the construct $S($S(top)) is used to reference the top of the stack.
A List of Arrays
Suppose you have many arrays, each of which stores some data, and you want to maintain an overall ordering among the data sets. One approach is to keep a Tcl list with the name of each array in order. Example 8-10 defines RecordInsert to add an array to the list, and an iterator function, RecordIterate, that applies a script to each array in order. The iterator uses upvar to make data an alias for the current array. The script is executed with eval, which is UNREGISTERED in detail in Chapter 10.TO PDFcommands in scriptTHETA-SOFTWARE with described VERSION OF CHM The Tcl CONVERTER By can reference the arrays the name data:
Another way to implement this list-of-records structure is to keep references to the arrays that come before and after each record. Example 8-11 shows the insert function and the iterator function when using this approach. Once again, upvar is used to set up data as an alias for the current array in the iterator. In this case, the loop is terminated by testing for the existence of the next array. It is perfectly all right to make an alias with upvar to a nonexistent variable. It is also all right to change the target of the upvar alias. One detail that is missing from the example is the initialization of the very first record so that its next element is the empty string:
Suppose you have to manage a lot of records, each of which contain a large chunk of data and one or more key values you use to look up those values. The procedure to add a record is called like this:
The datablob might be a name, value list suitable for passing to array set, or simply a large chunk of text or binary data. One implementation of Db_Insert might just be:
The problem with this approach is that it duplicates the data chunks under each key. A better approach is to use two arrays. One stores all the data chunks under a simple ID that is generated automatically. The other array stores the association between the keys and the data chunks. Example 8-12, which uses the namespace syntax described in Chapter 14, illustrates this approach. The example also shows how you can easily dump data structures by writing array set commands to a file, and then load them later with a source command:
puts $out [list namespace eval db \ [list variable uid $uid]] puts $out [list array set db::data [array get db::data]] puts $out [list array set db::index [array get db::index]] close $out } proc db::load {filename} { source $filename UNREGISTERED VERSION OF CHM }
[ Team LiB ]
[ Team LiB ]
exec
[*]
The exec VERSION OF CHM TO PDF CONVERTER For example: UNREGISTEREDcommand runs programs from your Tcl script. By THETA-SOFTWARE
Unlike other UNIX shell exec commands, the Tcl exec does not replace the current process with the new one. Instead, the Tcl library forks first and executes the program as a child process.
The standard output of the program is returned as the value of the exec command. However, if the program writes to its standard error channel or exits with a nonzero status code, then exec raises an error. If you do no care about the exit status, or you use a program that insists on writing to standard error, then you can use catch to mask the errors:
The exec command supports a full set of I/O redirection and pipeline syntax. Each process normally has three I/O channels associated with it: standard input, standard output, and standard error. With I/O redirection, you can divert these I/O channels to files or to I/O channels you have opened with the Tcl open command. A pipeline is a chain of processes that have the standard output of one command hooked up to the standard inpu of the next command in the pipeline. Any number of programs can be linked together into a pipeline.
Example 9-1 uses exec to run three programs in a pipeline. The first program is sort , which takes its input from the file /etc/passwd . The output of sort is piped into uniq , which suppresses duplicate lines. The outpu of uniq is piped into wc , which counts the lines. The error output of the command is diverted to the null device to suppress any error messages. Table 9-1 provides a summary of the syntax understood by the exec command.
-keepnewline (First argument.) Do not discard trailing newline from the result. | |& < fileName <@ fileId << value > fileName 2> fileName >& fileName >> fileName Pipes standard output from one process into another. Pipes both standard output and standard error output. Takes input from the named file. Takes input from the I/O channel identified by fileId . Takes input from the given value . Overwrites fileName with standard output. Overwrites fileName with standard error output. Overwrites fileName with both standard error and standard out. Appends standard output to the named file.
2>> fileName Appends standard error to the named file. >>& fileName Appends both standard error and standard output to the named file. >@ fileId 2>@ fileId >&@ fileId & Directs standard output to the I/O channel identified by fileId . Directs standard error to the I/O channel identified by fileId . Directs both standard error and standard output to the I/O channel. As the last argument, indicates pipeline should run in background.
A trailing & causes the program to run in the background. In this case, the process identifier is returned by the exec command. Otherwise, the exec command blocks during execution of the program, and the standard output of the program is the return value of exec . The trailing newline in the output is trimmed off, unless you specify -keepnewline as the first argument to exec . If you look closely at the I/O redirection syntax, you'll see that it is built up from a few basic building blocks. The basic idea is that | stands for pipeline, > for output, and < for input. The standard error is joined to the standard output by & . Standard error is diverted separately by using 2> . You can use your own I/O channels by using @ .
ls
instead of:
exec ls
This is handy if you are using the Tcl interpreter as a general shell. It can also cause unexpected behavior whe you are just playing around. To turn this off, define the auto_noexec variable:
Windows 3.1 has an unfortunate combination of special cases that stem from console-mode programs, 16-bit programs, and 32-bit OF CHM In PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION programs. TOaddition, pipes are really just simulated by writing output from one process to a temporary file and then having the next process read from that file. If exec or a process pipeline fails, it is because of a fundamental limitation of Windows. The good news is that Windows 98 and Windows NT cleaned up most of the problems with exec . Windows NT, Window 2000, and Windows XP are pretty robust.
Tcl 8.0p2 was the last release to officially support Windows 3.1. That release includes Tcl1680.dll , which is necessary to work with the win32s subsystem. If you copy that file into the same directory as the other Tcl UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE DLLs, you may be able to use some later releases of Tcl on Windows 3.1. However, Tcl 8.3 completely removed support for win32s while adding support for Windows XP-64. AppleScript
on Macintosh
The exec command is not provided on the Macintosh. Tcl ships with an AppleScript extension that lets you control other Macintosh applications. You can find documentation in the AppleScript.html that goes with the distribution. You must use package require to load the AppleScript command:
package require Tclapplescript AppleScript junk => bad option "junk": must be compile, decompile, delete, execute, info, load, run, or store
[ Team LiB ]
[ Team LiB ]
file attributes name ? option? ?value? ... file channels ? pattern? file copy ?-force? source destination file delete ?-force? name file dirname name file executable name file exists name file extension name
file join path path... Joins pathname components into a new pathname. (Tcl 7.5) file link ?-type? name Returns the link pointed to by name, or creates a link to target if ?target? it is specified. type can be -hard or -symbolic. (Tcl 8.4) file lstat name var file mkdir name file mtime name ?time? Places attributes of the link name into var. Creates directory name. (Tcl 7.6) Returns modify time of name as a decimal string. If time is specified, the modify time of the file is set. Returns the platform-native version of name. (Tk 8.0).
Returns a unique, absolute, path for name while eliminating extra /, /., and /.. components. (Tcl 8.4) Returns 1 if current user owns the file name, else 0. relative, absolute, or volumerelative. (Tcl 7.5) Returns 1 if name has read permission, else 0. Returns the contents of the symbolic link name. Changes the name of old to new. (Tcl 7.6) Returns all but the extension of name (i.e., up to but not including Returns the default file separator character on this file system, or the separator character for name if it is specified. (Tcl 8.4) Returns the number of bytes in name. Splits name into its pathname components. (Tcl 7.5) Places attributes of name into array var. The elements defined for var are listed in Table 9-3. Returns a tuple of the filesystem for name (e.g. native or vfs) and the platform-specific type for name (e.g NTFS or FAT32). (Tcl 8.4) Returns the last pathname component of name. Returns type identifier, which is one of: file, directory, characterSpecial, blockSpecial, fifo, link, or socket. Returns the available file volumes on this computer. On Unix, this always returns /. On Windows, this would be a list like {a:/ c:/}. (Tcl 8.3) Returns 1 if name has write permission, else 0.
file owned name file pathtype name file readable name file readlink name file rename ?-force? old new file rootname name
file size name file split name file stat name var
[ Team LiB ]
The good news is that Tcl provides operations that let you deal with file pathnames in a platform-independent manner. The file operations described in this chapter allow either native format or the UNIX naming convention. The backslash used in Windows pathnames is especially awkward because the backslash is special to Tcl. Happily, you can use forward slashes instead:
c:/Program Files/Tcl/lib/Tcl7.6
There are some ambiguous cases that can be specified only with native pathnames. On my Macintosh, Tcl and Tk are installed in a directory that has a slash in it. You can name it only with the native Macintosh name:
Disk:Applications:Tcl/Tk 4.2
Another construct to watch out for is a leading // in a file name. This is the Windows syntax for network names that reference files on other computers. You can avoid accidentally constructing a network name by using the file join command described next. Of course, you can use network names to access remote files. If you must communicate with external programs, you may need to construct a file name in the native syntax for the current platform. You can construct these names with file join described later. You can also convert a UNIX-like name to a native name with file nativename. Several of the file operations operate on pathnames as opposed to returning information about the file itself. You can use the dirname, extension, join, normalize, pathtype, rootname, split, and tail operations on any string; there is no requirement that the pathnames refer to an existing file.
Building up Pathnames:
file join
You can get into trouble if you try to construct file names by simply joining components with a
slash. If part of the name is in native format, joining things with slashes will result in incorrect pathnames on Macintosh and Windows. The same problem arises when you accept user input. The user is likely to provide file names in native format. For example, this construct will not create a valid pathname on the Macintosh because $tcl_library is in native format:
The file join operation can join any number of pathname components. In addition, it has the feature that an absolute pathname overrides any previous components. For example (on UNIX), /b/c is an absolute pathname, so it overrides any paths that come before it in the arguments to file join: file join a b/c d => a/b/c/d file join a /b/c d => /b/c/d
On Macintosh, a relative pathname starts with a colon, and an absolute pathname does not. To specify an absolute path, you put a trailing colon on the first component so that it is interpreted as a volume specifier. These relative components are joined into a relative pathname:
In the next case, b:c is an absolute pathname with b: as the volume specifier. The absolute name overrides the previous relative name:
The file join operation converts UNIX-style pathnames to native format. For example, on Macintosh you get this:
Chopping Pathnames:
The file split command divides a pathname into components. It is the inverse of file join. The split operation detects automatically if the input is in native or UNIX format. The results of file split may contain some syntax to help resolve ambiguous cases when the results are passed back to file join. For example, on Macintosh a UNIX-style pathname is split on slash separators. The Macintosh syntax for a volume specifier (Disk:) is returned on the leading component:
A common reason to split up pathnames is to divide a pathname into the directory part and the file part. This task is handled directly by the dirname and tail operations. The dirname operation returns the parent directory of a pathname, while tail returns the trailing component of the pathname:
For a pathname with a single component, the dirname option returns ".", on UNIX and Windows, or ":" on Macintosh. This is the name of the current directory. The extension and root options are also complementary. The extension option returns everything from the last period in the name to the end (i.e., the file suffix including the period.) The root option returns everything up to, but not including, the last period in the pathname:
[ Team LiB ]
[ Team LiB ]
UNREGISTERED patterns areOF CHM TO PDF CONVERTER operations. Instead, you can use the File name VERSION not directly supported by the file By THETA-SOFTWARE
Copying Files
The file copy operation copies files and directories. The following example copies file1 to file2. If file2 already exists, the operation raises an error unless the -force option is specified:
Several files can be copied into a destination directory. The names of the source files are preserved. The -force option indicates that files under directory can be replaced:
Directories can be recursively copied. The -force option indicates that files under dir2 can be replaced:
Creating Directories
The file mkdir operation creates one or more directories:
It is not an error if the directory already exists. Furthermore, intermediate directories are created if needed. This means that you can always make sure a directory exists with a single mkdir operation. Suppose /tmp has no subdirectories at all. The following command creates
The -force option is not understood by file mkdir, so the following command accidentally creates a folder named -force, as well as one named oops.
Deleting Files
The file delete operation deletes files and directories. It is not an error if the files do not exist. A non-empty directory is not deleted unless the -force option is specified, in which case it is recursively deleted:
To delete a file or directory named -force, you must specify a nonexistent file before the force to prevent it from being interpreted as a flag (-force -force won't work):
Using file rename is the best way to update an existing file. First, generate the new version of the file in a temporary file. Then, use file rename to replace the old version with the new version. This ensures that any other programs that access the file will not see the new version UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE until it is complete. [ Team LiB ]
[ Team LiB ]
File Attributes
There are several file operations that return specific file attributes: atime, executable, exists, isdirectory, isfile, mtime, owned, readable, readlink, size and type. Refer to Table 9-2 on page 108 for their function. The following command uses file mtime to compare the modify times of two files. If you have ever resorted to piping the results of ls -l into awk in order to derive this information in other shell scripts, you will appreciate this example:
You can use the optional time argument to mtime and atime to set the file's time attributes, like the Unix touch command. The stat and lstat operations return a collection of file attributes. They take a third argument that is the name of an array variable, and they initialize that array with elements that contain the file attributes. If the file is a symbolic link, then the lstat operation returns information about the link itself and the stat operation returns information about the target of the link.
mtime The last modify time, in seconds. nlink The number of links, or directory references, to the file. size type uid The number of bytes in the file. file, directory, characterSpecial, blockSpecial, fifo, link, or socket. The owner's user ID, an integer.
The array elements are listed in Table 9-3. All the element values are decimal strings, except for type, which can have the values returned by the type option. The element names are based on the UNIX stat system call. Use the file attributes command described later to get other platform-specific attributes. Example 9-3 uses the device (dev) and inode (ino) attributes of a file to determine whether two pathnames reference the same file. These attributes are UNIX specific; they are not well UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE defined on Windows and Macintosh.
The file attributes operation was added in Tcl 8.0 to provide access to platform-specific attributes. The attributes operation lets you set and query attributes. The interface uses option-value pairs. With no options, all the current values are returned.
file attributes book.doc => -creator FRAM -hidden 0 -readonly 0 -type MAKR
These Macintosh attributes are explained in Table 9-4. The four-character type codes used on Macintosh are illustrated on page 600. With a single option, only that value is returned:
The attributes are modified by specifying one or more optionvalue pairs. Setting attributes can raise an error if you do not have the right permissions:
-permissions mode
File permission bits. mode is an octal number or symbolic representation (e.g. a+x) with bits defined by the chmod system call, or a simplified lsstyle string of the form rwxrwxrwx (must be 9 characters). (UNIX) The group owner of the file. (UNIX) The owner of the file. (UNIX) The archive bit, which is set by backup programs. (Windows) If set, then you cannot remove the file. (Windows) The long (expanded) version of the pathname. Read-only. (Windows) The short (8.3) version of the pathname. Read-only. (Windows) If set, then the file does not appear in listings. (Windows, Macintosh) If set, then you cannot write the file. (Windows, Macintosh) type is 4-character code of creating application. (Macintosh) type is 4-character type code. (Macintosh)
-group ID -owner ID -archive bool -system bool -longname -shortname -hidden bool -readonly bool -creator type -type type [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
The what argument is either a file name or a pipeline specification similar to that used by the exec command. The access argument can take two forms, either a short character sequence that is compatible with the fopen library routine, or a list of POSIX access flags. Table 9-6 summarizes the first form, while Table 9-7 summarizes the POSIX flags. If access is not specified, it defaults to read.
The permissions argument is a value used for the permission bits on a newly created file. UNIX uses three bits each for the owner, group, and everyone else. The bits specify read, write, and execute permission. These bits are usually specified with an octal number, which has a leading zero, so that there is one octal digit for each set of bits. The default permission bits are 0666, which grant read/write access to everybody. Example 9-4 specifies 0600 so that the file is readable and writable only by the owner. 0775 would grant read, write, and execute permissions to the owner and group, and read and execute permissions to everyone else. You can set other special properties with additional high-order bits. Consult the UNIX manual page on chmod command for more details.
r+ Opens for reading and writing. The file must exist. w Opens for writing. Truncate if it exists. Create if it does not exist.
w+ Opens for reading and writing. Truncate or create. a Opens for writing. Data is appended to the file.
NOCTTY Prevents OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSIONterminal devices from becoming the controlling terminal. NONBLOCK Does not block during the open. TRUNC Truncates the file if it exists.
The following example illustrates how to use a list of POSIX access flags to open a file for reading and writing, creating it if needed, and not truncating it. This is something you cannot do with the simpler form of the access argument:
In general, you should check for errors when opening files. The following example illustrates a catch phrase used to open files. Recall that catch returns 1 if it catches an error; otherwise, it returns zero. It treats its second argument as the name of a variable. In the error case, it puts the error message into the variable. In the normal case, it puts the result of the command into the variable:
You can open a process pipeline by specifying the pipe character, |, as the first character of the first argument. The remainder of the pipeline specification is interpreted just as with the exec command, including input and output redirection. The second argument determines which end of the pipeline open returns. The following example runs the UNIX sort program on the password file, and it uses the split command to separate the output lines into list elements:
You can open a pipeline for both read and write by specifying the r+ access mode. In this case, you need to worry about buffering. After a puts, the data may still be in a buffer in the Tcl library. Use the flush command to force the data out to the spawned processes before you try to read any output from the pipeline. You can also use the fconfigure command described on page 233 to force line buffering. Remember that read-write pipes will not work at all with Windows 3.1 because pipes are simulated with files. Event-driven I/O is also very useful with pipes. It means you can do other processing while the pipeline executes, and simply respond when the pipe generates data. This is described in Chapter 16.
Expect
If you are trying to do sophisticated things with an external application, you will find that the Expect extension provides a much more powerful interface than a process pipeline. Expect adds Tcl commands that are used to control interactive applications. It is extremely useful for automating a variety of applications such as ssh, Telnet, and programs under test. Tcl is able to handle simple FTP sessions, telnet and many command line controllable applications, but Expect has extra control at the tty level that is essential for certain applications. It comes on some systems as a specially built Tcl shell named expect, and it is also available as an extension that you can dynamically load into Tcl shells with:
Expect was created by Don Libes at the National Institute of Standards and Technology (NIST). Expect is described in Exploring Expect (Libes, O'Reilly & Associates, Inc., 1995). You can find the software on the CD and on the web at: http://expect.nist.gov/ [ Team LiB ]
[ Team LiB ]
There may be cases when the standard I/O channels are not available. The wish shells on Windows UNREGISTEREDand Macintosh have no TO PDF CONVERTER By THETA-SOFTWARE close VERSION OF CHM standard I/O channels. Some UNIX window managers the standard I/O channels when you start programs from window manager menus. You can also close the standard I/O channels with close.
The gets command reads a line of input, and it has two forms. In the previous example, with just a single argument, gets returns the line read from the specified I/O channel. It discards the trailing newline from the return value. If end of file is reached, an empty string is returned. You must use the eof command to tell the difference between a blank line and end-of-file. eof returns 1 if there is end of file. Given a second varName argument, gets stores the line into a named variable and returns the number of bytes read. It discards the trailing newline, which is not counted. A -1 is returned if the channel has reached the end of file.
The read command reads blocks of data, and this capability is often more efficient. There are two forms for read: You can specify the -nonewline argument or the numBytes argument, but not both. Without numBytes, the whole file (or what is left in the I/O channel) is read and returned. The -nonewline argument causes the trailing newline to be discarded. Given a byte count argument, read returns that amount, or less if there is not enough data in the channel. The trailing newline is not discarded in this case.
For moderate-sized files, it is about 10 percent faster to loop over the lines in a file using the read loop in the second example. In this case, read returns the whole file, and split chops the file into list elements, one for each line. For small files (less than 1K) it doesn't really matter. For large files (megabytes) you might induce paging with this approach.
To suppress conversions, use the fconfigure command, which is described in more detail on page 234. Example 9-10 demonstrates a File_Copy procedure that translates files to native format. It is complicated because it handles directories.
return } if {[file isdirectory $dest]} { set dest [file join $dest [file tail $src]] } set in [open $src] set out [open $dest w] puts VERSION $out [read PDF UNREGISTERED -nonewline OF CHM TO $in] CONVERTER By close $out ; close $in }
THETA-SOFTWARE
If the channel was a process pipeline and any of the processes wrote to their standard error channel, then Tcl believes this is an error. The error is raised when the channel to the pipeline is finally closed. Similarly, if any of the processes in the pipeline exit with a nonzero status, close raises an error.
[ Team LiB ]
[ Team LiB ]
cd
and pwd
Every process has a current directory that is used as the starting point when resolving a relative pathname. The pwd command returns the current directory, and the cd command changes the current directory. Example 9-11 uses these commands. [ Team LiB ]
[ Team LiB ]
glob
UNREGISTEREDcommand expands a pattern intoCONVERTER By THETA-SOFTWARE form of VERSION OF CHM TO PDF the set of matching file names. The general The glob
-nocomplain
-types types --
Unlike the glob matching in csh, the Tcl glob command matches only the names of existing files. In csh, the {a,b} construct can match nonexistent names. In addition, the results of glob are not sorted. Use the lsort command to sort its result if you find it important. Example 9-11 shows the FindFile procedure, which traverses the file system hierarchy using
recursion. At each iteration it saves its current directory and then attempts to change to the next subdirectory. A catch guards against bogus names. The glob command matches file names:
The -types option allows for special filtered matching similar to the UNIX find command. The first form is like the -type option of find: b (block special file), c (character special file), d (directory), f (plain file), l (symbolic link), p (named pipe), or s (socket), where multiple types may be specified in the list. Glob will return all files which match at least one of the types given. The second form specifies types where all the types given must match. These are r (readable), w (writable) and x (executable) as file permissions, and readonly and hidden as special cases. On the Macintosh, MacOS types and creators are also supported, where any item which is four characters long is assumed to be a MacOS type (e.g. TEXT). Items which are of the form {macintosh type XXXX} or {macintosh creator XXXX} will match types or creators respectively. Unrecognized types, or specifications of multiple MacOS types/creators will signal an error. The two forms may be mixed, so -types {d f r w} will find all regular files OR directories that have both read AND write permissions.
[ Team LiB ]
There is no built-in mechanism to control processes in the Tcl core. On UNIX systems you can exec the kill program to terminate a process:
[ Team LiB ]
[ Team LiB ]
Environment Variables
Environment variables are a collection of string-valued variables associated with each process. The process's environment variables are available through the global array env. The name of the environment variable is the index, (e.g., env(PATH)), and the array element contains the current value of the environment variable. If assignments are made to env, they result in changes to the corresponding environment variable. Environment variables are inherited by child processes, so programs run with the exec command inherit the environment of the Tcl script. The following example prints the values of environment variables.
Note: Environment variables can be initialized for Macintosh applications by editing a resource of type STR# whose name is Tcl Environment Variables. This resource is part of the tclsh and wish applications. Follow the directions on page 28 for using ResEdit. The format of the resource values is NAME=VALUE. [ Team LiB ]
[ Team LiB ]
The rootname is one of HKEY_LOCAL_MACHINE, HKEY_PERFORMANCE_DATA, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, or HKEY_DYN_DATA. Tables 9-9 and 9-10 summarize the registry command and data types:
registry set key registry set key valueName data ?type? registry type key valueName registry values key ?pat?
Arbitrary binary data. Arbitrary binary data. A string that contains references to environment variables with the %VARNAME% syntax. A 32-bit integer.
dword_big_endian A 32-bit integer in the other byte order. It is represented in Tcl as a decimal string. link multi_sz resource_list [ Team LiB ] A symbolic link. An array of strings, which are represented as a Tcl list. A device driver resource list.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
list
Command
UNREGISTEREDtricky to assemble a command so that it is evaluatedTHETA-SOFTWARE same VERSION OF CHM TO PDF CONVERTER By properly by eval. The It can be
difficulties apply to commands like after, uplevel, and the Tk send command, all of which have similar properties to eval, except that the command evaluation occurs later or in a different context. Constructing commands dynamically is a source of many problems. The worst part is that you can write code that works sometimes but not others, which can be very confusing.
The root of the quoting problems is the internal use of concat by eval and similar commands to concatenate their arguments into one command string. The concat can lose some important list structure so that arguments are not passed through as you expect. The general strategy to avoid these problems is to use list and lappend to explicitly form the command callback as a single, well-structured list.
set cmd {puts stdout "Hello, World!"} => puts stdout "Hello, World!" # sometime later... eval $cmd => Hello, World!
In this case, the value of cmd is passed to Tcl. All the standard grouping and substitution are done again on the value, which is a puts command. However, suppose that part of the command is stored in a variable, but that variable will not be defined at the time eval is used. We can artificially create this situation like this:
set string "Hello, World!" set cmd {puts stdout $string} => puts stdout $string unset string eval $cmd => can't read "string": no such variable
In this case, the command contains $string. When this is processed by eval, the interpreter looks for the current value of string, which is undefined. This example is contrived, but the same problem occurs if string is a local variable, and cmd will be evaluated later in the global scope. A common mistake is to use double quotes to group the command. That will let $string be substituted now. However, this works only if string has a simple value, but it fails if the value of string contains spaces or other Tcl special characters:
set cmd "puts stdout $string" => puts stdout Hello, World! eval $cmd => bad argument "World!": should be "nonewline"
The problem is that we have lost some important structure. The identity of $string as a single argument gets lost in the second round of parsing by eval. The solution to this problem is to construct the command using list, as shown in the following example:
The trick is that list has formed a list containing three elements: puts, stdout, and the value of string. The substitution of $string occurs before list is called, and list takes care of grouping that value for us. In contrast, using double quotes is equivalent to:
The problem here is that concat does not preserve list structure. The main lesson is that you should use list to construct commands if they contain variable values or command results that must be substituted now. If you use double quotes, the values are substituted but you lose proper command structure. If you use curly braces, then values are not substituted until later, which may not be in the right context.
after 100 [list doCmd $param1 $param2] send $interp [list doCmd $param1 $param2] ;# Safe!
The danger here is that concat and list can result in the same thing, so you can be led down the rosy garden path only to get errors later when values change. The two previous examples always work. The next two work only if param1 and param2 have values that are single list elements:
after 100 doCmd $param1 $param2 send $interp doCmd $param1 $param2 ;# Unsafe!
If you use other Tcl extensions that provide eval-like functionality, carefully check their documentation to see whether they contain commands that concat their arguments into a command. For example, Tcl-DP, which provides a network version of send, dp_send, also uses concat.
There is a variation on command callbacks called a command prefix. In this case, the command is given additional arguments when it is invoked. In other words, you provide only part of the command, the command prefix, and the module that invokes the callback adds additional arguments before using eval to invoke the command. For example, when you create a network server, you supply a procedure that is called when a client makes a connection. That procedure is called with three additional arguments that indicate the client's socket, IP address, and port number. This is described in more detail on page 240. The tricky thing is that you can define your callback procedure to take four (or more) arguments. In this case you specify some of the parameters when you define the callback, and then the socket subsystem specifies the remaining arguments when it makes the callback. The following command creates the server side of a socket:
The myname parameter is set when you construct the command prefix. The remaining parameters are set when the callback is invoked. The use of list in this example is not strictly necessary because "we know" that virtualhost will always be a single list element. However, using list is just a good habit when forming callbacks, so I always write the code this way. There are many other examples of callback arguments that are really command prefixes. Some of these include the scrolling callbacks between Tk scrollbars and their widgets, the command aliases used with Safe Tcl, the sorting functions in lsort, and the completion callback used with fcopy. Example 13-6 on page 191 shows how to use eval to make callbacks from Tcl procedures.
If you run TraceGen on it and look at the results, you see this:
TraceGen foo info body foo => global _trace_count _trace_msec incr _trace_count(foo) incr _trace_msec(foo) [lindex [time { set result [foo-orig $x $y] } 1] 0] return $result
The tracing provided by TraceGen is similar to what you can achieve with the features of the Tcl 8.4 trace command. With command tracing, which is described on page 194, you can track the calls and results of procedures. [ Team LiB ]
[ Team LiB ]
Exploiting the
concat
inside eval
The previous section warns about the danger of concatenation when forming commands. However, there are times when concatenation is done for good reason. This section illustrates cases where the concat done by eval is useful in assembling a command by concatenating multiple lists into one list. A concat is done internally by eval when it gets more than one argument:
The effect of concat is to join all the lists into one list; a new level of list structure is not added. This is useful if the lists are fragments of a command. It is common to use this form of eval with the args construct in procedures. Use the args parameter to pass optional arguments through to another command. Invoke the other command with eval, and the values in $args get concatenated onto the command properly. The special args parameter is illustrated in Example 7-2 on page 88.
After a button is created, it is made visible by packing it into the display. The pack command can also take many arguments to control screen placement. Here, we just specify a side and let the packer take care of the rest of the details:
Even though there are only two Tcl commands to create a user interface button, we will write a procedure that replaces the two commands with one. Our first version might be:
proc PackedButton {name txt cmd} { button $name -text $txt -command $cmd pack $name -side left }
This is not a very flexible procedure. The main problem is that it hides the full power of the Tk
button command, which can really take more than 30 widget configuration options, such as background, -cursor, -relief, and more. They are listed on page 459. For example, you can easily make a red button like this:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER Byextra configuration options to the A better version of PackedButton uses args to pass through THETA-SOFTWARE
button command. The args parameter is a list of all the extra arguments passed to the Tcl procedure. My first attempt to use $args looked like this, but it was not correct:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE button $name -text $txt -command $cmd $args
pack $name -side left } PackedButton .foo "Hello, World!" {exit} -background red => unknown option "-background red"
The problem is that $args is a list value, and button gets the whole list as a single argument. Instead, button needs to get the elements of $args as individual arguments.
In this case, you can use eval because it concatenates its arguments to form a single list before evaluation. The single list is, by definition, the same as a single Tcl command, so the button command parses correctly. Here we give eval two lists, which it joins into one command:
The use of the braces in this command is discussed in more detail below. We also generalize our procedure to take some options to the pack command. This argument, pack, must be a list of packing options. The final version of PackedButton is shown in Example 10-3:
In PackedButton, both pack and args are list-valued parameters that are used as parts of a command. The internal concat done by eval is perfect for this situation. The simplest call to PackedButton is:
The quotes and curly braces are redundant in this case but are retained to convey some type information. The quotes imply a string label, and the braces imply a command. The pack argument takes on its default value, and the args variable is an empty list. The two commands executed by PackedButton are:
button .new -text New -command New pack .new -side right
PackedButton creates a horizontal stack of buttons by default. The packing can be controlled with a packing specification:
button .new -text Save -command { Save $file } pack .new -side left
The remaining arguments, if any, are passed through to the button command. This lets the caller fine-tune some of the button attributes:
button .quit -text Quit -command { Exit } -background red pack .quit -side left -padx 5
You can see a difference between the pack and args argument in the call to PackedButton. You need to group the packing options explicitly into a single argument. The args parameter is automatically made into a list of all remaining arguments. In fact, if you group the extra button parameters, it will be a mistake:
PackedButton .quit Quit { Exit } {-side left -padx 5} \ {-background red} => unknown option "-background red"
eval
You may be tempted to use double quotes instead of curly braces in your uses of eval. Don't give in! Using double quotes is, mostly likely, wrong. Suppose the first eval command is written like this:
These versions happen to work with the following call because txt and cmd have one-word values with no special characters in them:
PackedButton .save "Save As" [list Save $file] => unknown option "As"
The problem is that the structure of the button command is now wrong. The value of txt and cmd are substituted first, before eval is even called, and then the whole command is parsed again. The worst part is that sometimes using double quotes works, and sometimes it fails. The success of using double quotes depends on the value of the parameters. When those values contain spaces or special characters, the command gets parsed incorrectly.
The following variations are also correct. The first uses list to do quoting automatically, and the others use backslashes or braces to prevent the extra round of substitutions:
eval [list button $path -text $txt -command $cmd] $args eval button \$path -text \$txt -command \$cmd $args eval button {$path} -text {$txt} -command {$cmd} $args
Finally, here is one more incorrect approach that tries to quote by hand:
The problem is that double quotes disable the quoting you normally expect with curly braces. Consider this little example that uses double quotes. The curly braces around $blob have no special effect, and the interpreter sees unbalanced braces:
If we group instead with curly braces, then the variable substitution occurs once, after the arguments to puts have been grouped, and there is no error.
Of course, these simple examples are contrived, but they illustrate the need to be careful with your list construction when using eval! [ Team LiB ]
[ Team LiB ]
As with upvar, the level parameter is optional, but recommended for good style, and defaults to 1, which means to execute the command in the scope of the calling procedure. The other common use of level is #0, which means to evaluate the command in the global scope. You can count up farther than one (e.g., 2 or 3), or count down from the global level (e.g., #1 or #2), but these cases rarely make sense. When you specify the command argument, you must be aware of any substitutions that might be performed by the Tcl interpreter before uplevel is called. If you are entering the command directly, protect it with curly braces so that substitutions occur in the other scope. The following affects the variable x in the caller's scope:
However, the following will use the value of x in the current scope to define the value of x in the calling scope, which is probably not what was intended:
If you are constructing the command dynamically, again use list. This fragment is used later in Example 10-4:
It is common to have the command in a variable. This is the case when the command has been passed into your new control flow procedure as an argument In this case, you should evaluate the command one level up. Put the level in explicitly to avoid cases where $cmd looks like a number!
uplevel 1 $cmd
Another common scenario is reading commands from users as part of an application. In this case, you should evaluate the command at the global scope. Example 16-2 on page 230 illustrates this use of uplevel:
uplevel #0 $cmd
If you are assembling a command from a few different lists, such as the args parameter, then you can use concat to form the command:
Example 10-4 shows list assignment using the foreach trick described on Page 81. List assignment is useful if a command returns several values in a list. The lassign procedure assigns the list elements to several variables. The lassign procedure hides the foreach trick, but it must use the uplevel command so that the loop variables get assigned in the correct scope. The list command is used to construct the foreach command that is executed in the caller's scope. This is necessary so that $variables and $values get substituted before the command is evaluated in the other scope.
proc lassign {valueList args} { if {[llength $args] == 0} { error "wrong # args: lassign list varname ?varname..?" } if {[llength $valueList] == 0} { # Ensure one trip through the foreach loop set valueList [list {}] } uplevel 1 [list foreach $args $valueList {break}] return [lrange $valueList [llength $args] end] }
Example 10-5 illustrates a new control structure with the File_Process procedure that applies a callback to each line in a file. The call to uplevel allows the callback to be concatenated with the line to form the command. The list command is used to quote any special characters in line, so it appears as a single argument to the command.
proc File_Process {file callback} { set in [open $file] while {[gets $in line] >= 0} { uplevel 1 $callback [list $line] } close $in }
The first form limits callback to be the name of the command, while the second form allows callback to be a command prefix. Once again, what is the bug with this version?
The arbitrary value of $line is concatenated to the callback command, and it is likely to be a malformed command when executed. [ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE subst {a=$a date=[exec date]}
=> a=foo bar date=Thu Dec 15 10:13:48 PST 1994
The subst command does not honor the quoting effect of curly braces. It does substitutions regardless of braces:
subst {a=$a date={[exec date]}} => a=foo bar date={Thu Dec 15 10:15:31 PST 1994}
You can use other backslash substitutions like \uXXXX to get Unicode characters, \n to get newlines, or \-newline to hide newlines. The subst command takes flags that limit the substitutions it will perform. The flags are nobackslashes, -nocommands, or -novariables. You can specify one or more of these flags before the string that needs to be substituted:
subst -novariables {a=$a date=[exec date]} => a=$a date=Thu Dec 15 10:15:31 PST 1994
subst
The subst command can be used with the regsub command to do efficient, two-step string processing. In the first step, regsub is used to rewrite an input string into data with embedded Tcl commands. In the second step, subst or eval replaces the Tcl commands with their result. By artfully mapping the data into Tcl commands, you can dynamically construct a Tcl script that processes the data. The processing is efficient because the Tcl parser and the regular expression processor have been highly tuned. Chapter 11 has several examples that use this technique.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
One of the stumbling blocks with regular expressions is that they use some of the same special characters as Tcl. Any pattern that contains brackets, dollar signs, or spaces must be quoted when used in a Tcl command. In many cases you can group the regular expression with curly braces, so Tcl pays no attention to it. However, when using Tcl 8.0 (or earlier) you may need Tcl to do backslash substitutions on part of the pattern, and then you need to worry about quoting the special characters in the regular expression. Advanced regular expressions eliminate this problem because backslash substitution is now done by the regular expression engine. Previously, to get \n to mean the newline character (or \t for tab) you had to let Tcl do the substitution. With Tcl 8.1, \n and \t inside a regular expression mean newline and tab. In fact, there are now about 20 backslash escapes you can use in patterns. Now more than ever, remember to group your patterns with curly braces to avoid conflicts between Tcl and the regular expression engine.
The patterns in the first sections of this chapter ignore this problem. The sample expressions in Table 11-7 on page 161 are quoted for use within Tcl scripts. Most are quoted simply by putting the whole pattern in braces, but some are shown without braces for comparison. [ Team LiB ]
[ Team LiB ]
Matching Characters
Most characters simply match themselves. The following pattern matches an a followed by a b:
ab
The general wild-card character is the period, ".". It matches any single character. The following pattern matches an a followed by any character:
a.
Remember that matches can occur anywhere within a string; a pattern does not have to match the whole string. You can change that by using anchors, which are described on page 147.
Character Sets
The matching character can be restricted to a set of characters with the [xyz] syntax. Any of the characters between the two brackets is allowed to match. For example, the following matches either Hello or hello:
[Hh]ello
The matching set can be specified as a range over the character set with the [x-y] syntax. The following matches any digit:
[0-9]
If you want a ] in your character set, put it immediately after the initial opening bracket. You do not need to do anything special to include [ in your character set. The following matches any square brackets or curly braces:
[][{}]
Most regular expression syntax characters are no longer special inside character sets. This means you do not need to backslash anything inside a bracketed character set except for backslash itself. The following pattern matches several of the syntax characters used in regular expressions:
[][+*?()|\\]
Advanced regular expressions add names and backslash escapes as shorthand for common sets of characters like white space, alpha, alphanumeric, and more. These are described on page 149 and listed in Table 11-3 on page 156.
Quantifiers
Repetition is specified with *, for zero or more, +, for one or more, and ?, for zero or one. These quantifiers apply to the previous item, which is either a matching character, a character set, or a subpattern grouped with parentheses. The following matches a string that contains b followed by zero or more a's:
ba*
You can group part of the pattern with parentheses and then apply a quantifier to that part of the pattern. The following matches a string that has one or more sequences of ab:
(ab)+
The pattern that matches anything, even the empty string, is:
.*
These quantifiers have a greedy matching behavior: They match as many characters as possible. Advanced regular expressions add nongreedy matching, which is described on page 151. For example, a pattern to match a single line might look like this:
.*\n
However, as a greedy match, this will match all the lines in the input, ending with the last newline in the input string. The following pattern matches up through the first newline.
[^\n]*\n
We will shorten this pattern even further on page 151 by using nongreedy quantifiers. There are also special newline sensitive modes you can turn on with some options described on page 153.
Alternation
Alternation lets you test more than one pattern at the same time. The matching engine is designed to be able to test multiple patterns in parallel, so alternation is efficient. Alternation is specified with |, the pipe symbol. Another way to match either Hello or hello is:
hello|Hello
(h|H)ello
or as:
[hH]ello
Anchoring a Match
UNREGISTERED VERSION OF CHMmatch. You can anchor theBy THETA-SOFTWARE the string characters before and after the TO PDF CONVERTER match to the beginning of
by starting the pattern with ^, or to the end of the string by ending the pattern with $. You can force the pattern to match the whole string by using both. All strings that begin with spaces or tabs are matched with: By default a pattern does not have to match the whole string. There can be unmatched
Backslash Quoting
Use the backslash character to turn off these special characters :
. * ? + [ ] ( ) ^ $ | \
\+
Remember that this quoting is not necessary inside a bracketed expression (i.e., a character set definition.) For example, to match either plus or question mark, either of these patterns will work:
(\+|\?) [+?]
To match a single backslash, you need two. You must do this everywhere, even inside a bracketed expression. Or you can use \B, which was added as part of advanced regular expressions. Both of these match a single backslash:
\\ \B
Versions of Tcl before 8.1 ignored unknown backslash sequences in regular expressions. For example, \= was just =, and \w was just w. Even \n was just n, which was probably frustrating to many beginners trying to get a newline into their pattern. Advanced regular expressions add backslash sequences for tab, newline, character classes, and more. This is a convenient improvement, but in rare cases it may change the semantics of a pattern. Usually these cases are where an unneeded backslash suddenly takes on meaning, or causes an error because it is unknown.
Matching Precedence
If a pattern can match several parts of a string, the matcher takes the match that occurs earliest in the input string. Then, if there is more than one match from that same point because of alternation in the pattern, the matcher takes the longest possible match. The rule of thumb is: first, then longest. This rule gets changed by nongreedy quantifiers that prefer a shorter match. Watch out for *, which means zero or more, because zero of anything is pretty easy to match. Suppose your pattern is:
[a-z]*
This pattern will match against 123abc, but not how you expect. Instead of matching on the letters in the string, the pattern will match on the zero-length substring at the very beginning of the input string! This behavior can be seen by using the -indices option of the regexp command described on page 158. This option tells you the location of the matching string instead of the value of the matching string.
Capturing Subpatterns
Use parentheses to capture a subpattern. The string that matches the pattern within parentheses is remembered in a matching variable, which is a Tcl variable that gets assigned the string that matches the pattern. Using parentheses to capture subpatterns is very useful. Suppose we want to get everything between the <td> and </td> tags in some HTML. You can use this pattern:
<td>([^<]*)</td>
The matching variable gets assigned the part of the input string that matches the pattern inside the parentheses. You can capture many subpatterns in one match, which makes it a very
efficient way to pick apart your data. Matching variables are explained in more detail on page 158 in the context of the regexp command. Sometimes you need to introduce parentheses but you do not care about the match that occurs inside them. The pattern is slightly more efficient if the matcher does not need to remember the match. Advanced regular expressions add noncapturing parentheses with this syntax:
[ Team LiB ]
The above command behaves identically when using advanced regular expressions, although you can now also write it like this:
The curly braces hide the brackets from the Tcl parser, so they do not need to be escaped with backslash. This saves us two characters and looks a bit cleaner.
Again, always group your pattern with curly braces to avoid confusion. Advanced regular expressions add a lot of new backslash sequences. They are listed in Table 11-4 on page 156. Some of the more useful ones include \s, which matches space-like characters, \w, which matches letters, digit, and the underscore, \y, which matches the beginning or end of a word, and \B, which matches a backslash.
Character Classes
Character classes are names for sets of characters. The named character class syntax is valid only inside a bracketed character set. The syntax is:
For example, alpha is the name for the set of uppercase and lowercase letters. The following two patterns are almost the same:
[A-Za-z] [[:alpha:]]
The difference is that the alpha character class also includes accented characters like . If you match data that contains nonASCII characters, the named character classes are more general than trying to name the characters explicitly. There are also backslash sequences that are shorthand for some of the named character classes. The following patterns to match digits are equivalent:
[0-9] [[:digit:]] \d
The following patterns match space-like characters including backspace, form feed, newline, carriage return, tag, and vertical tab:
[ \b\f\n\r\t\v] [[:space:]] \s
The named character classes and the associated backslash sequence are listed in Table 11-3 on page 156. You can use character classes in combination with other characters or character classes inside a character set definition. The following patterns match letters, digits, and underscore:
[[:digit:][:alpha:]_] [\d[:alpha:]_]
[[:alnum:]_] \w
Note that \d, \s and \w can be used either inside or outside character sets. When used outside a bracketed expression, they form their own character set. There are also \D, \S, and \W, which are the complement of \d, \s, and \w. These escapes (i.e., \D for not-a-digit) cannot be used inside a bracketed character set. There are two special character classes, [[:<:] and [[:>:]], that match the beginning and end of a word, respectively. A word is defined as one or more characters that match \w.
Nongreedy Quantifiers
The *, +, and ? characters are quantifiers that specify repetition. By default these match as many characters as possible, which is called greedy matching. A nongreedy match will match as few characters as possible. You can specify nongreedy matching by putting a question mark after these quantifiers. Consider the pattern to match "one or more of not-a-newline followed by a newline." The not-a-newline must be explicit with the greedy quantifier, as in:
[^\n]+\n
.+\n
then the "." could well match newlines, so the pattern would greedily consume everything until the very last newline in the input. A nongreedy match would be satisfied with the very first newline instead:
.+?\n
By using the nongreedy quantifier we've cut the pattern from eight characters to five. Another example that is shorter with a nongreedy quantifier is the HTML example from page 148. The following pattern also matches everything between <td> and </td>:
<td>(.*?)</td>
Even ? can be made nongreedy, ??, which means it prefers to match zero instead of one. This only makes sense inside the context of a larger pattern. Send me email if you have a compelling example for it!
Bound Quantifiers
The {m,n} syntax is a quantifier that means match at least m and at most n of the previous matching item. There are two variations on this syntax. A simple {m} means match exactly m of the previous matching item. A {m,} means match m or more of the previous matching item. All of these can be made nongreedy by adding a ? after them.
Back References
("[^"]*"|'[^']*')
('|").*?\1
The first set of parenthesis matches the leading quote, and then the \1 refers back to that particular quote character. The nongreedy quantifier ensures that the pattern matches up to the first occurrence of the matching quote.
Look-ahead
Look-ahead patterns are subexpressions that are matched but do not consume any of the input. They act like constraints on the rest of the pattern, and they typically occur at the end of your pattern. A positive look-ahead causes the pattern to match if it also matches. A negative look-ahead causes the pattern to match if it would not match. These constraints make more sense in the context of matching variables and in regular expression substitutions done with the regsub command. For example, the following pattern matches a filename that begins with A and ends with .txt
^A.*\.txt$
The next version of the pattern adds parentheses to group the file name suffix.
^A.*(\.txt$)
The parentheses are not strictly necessary, but they are introduced so that we can compare the pattern to one that uses look-ahead. A version of the pattern that uses look-ahead looks like
this:
^A.*(?=\.txt$)
The pattern with the look-ahead constraint matches only the part of the filename before the .txt, but only if the .txt is present. In other words, the .txt is not consumed by the match. This is visible in the value of the matching variables used with the regexp command. It would also affect the substitutions done in the regsub command. There is negative look-ahead too. The following pattern matches a filename that begins with A and does not end with .txt.
^A.*(?!\.txt$)
Character Codes
The \nn and \mmm syntax, where n and m are digits, can also mean an 8-bit character code corresponding to the octal value nn or mmm. This has priority over a back reference. However, I just wouldn't use this notation for character codes. Instead, use the Unicode escape sequence, \unnnn, which specifies a 16-bit value. The \xnn sequence also specifies an 8-bit character code. Unfortunately, the \x escape consumes all hex digits after it (not just two!) and then truncates the hexadecimal value down to 8 bits. This misfeature of \x is not considered a bug and will probably not change even in future versions of Tcl. The \Uyyyyyyyy syntax is reserved for 32-bit Unicode, but I don't expect to see that implemented anytime soon.
Collating Elements
Collating elements are characters or long names for characters that you can use inside character sets. Currently, Tcl only has some long names for various ASCII punctuation characters. Potentially, it could support names for every Unicode character, but it doesn't because the mapping tables would be huge. This section will briefly mention the syntax so that you can understand it if you see it. But its usefulness is still limited. Within a bracketed expression, the following syntax is used to specify a collating element:
[.identifier.]
The identifier can be a character or a long name. The supported long names can be found in the generic/regc_locale.c file in the Tcl source code distribution. A few examples are shown below:
Equivalence Classes
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
An equivalence class is all characters that sort to the same position. This is another feature that has limited usefulness in the current version of Tcl. In Tcl, characters sort by their Unicode character value, so there are no equivalence classes that contain more than one character! However, you could imagine a character class for 'o', '', and other accented versions of the letter o. The syntax for equivalence classes within bracketed expressions is:
where char is any one of the characters in the character class. This syntax is valid only inside a character class definition.
Embedded Options
You can start a pattern with embedded options to turn on or off case sensitivity, newline sensitivity, and expanded syntax, which is explained in the next section. You can also switch from advanced regular expressions to a literal string, or to older forms of regular expressions. The syntax is a leading:
(?chars)
where chars is any number of option characters. The option characters are listed in Table 11-5 on page 157.
Expanded Syntax
Expanded syntax lets you include comments and extra white space in your patterns. This can greatly improve the readability of complex patterns. Expanded syntax is turned on with a regexp command option or an embedded option. Comments start with a # and run until the end of line. Extra white space and comments can occur anywhere except inside bracketed expressions (i.e., character sets) or within multicharacter syntax elements like (?=. When you are in expanded mode, you can turn off the comment character or include an explicit space by preceding them with a backslash. Example 11-1 shows a pattern to match URLs. The leading (?x) turns on expanded syntax. The whole pattern is grouped in curly braces to hide it from Tcl. This example is considered again in more detail in Example 11-3 on page 159:
[ Team LiB ]
[ Team LiB ]
Syntax Summary
Table 11-1 summarizes the syntax of regular expressions By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER available in all versions of Tcl:
Advanced regular expressions, which were introduced in Tcl 8.1, add more syntax that is summarized in Table 11-2:
Matches m instances of the previous pattern item. Matches m instances of the previous pattern item. Nongreedy. Matches m or more instances of the previous pattern item. Matches m or more instances of the previous pattern item. Nongreedy. Matches m through n instances of the previous pattern item.
{m,n}? Matches m through n instances of the previous pattern item. Nongreedy. *? +? ?? Matches zero or more instances of the previous pattern item. Nongreedy. Matches one or more instances of the previous pattern item. Nongreedy. Matches zero or one instances of the previous pattern item. Nongreedy.
(?:re) Groups a subpattern, re, but does not capture the result. (?=re) Positive look-ahead. Matches the point where re begins. (?!re) Negative look-ahead. Matches the point where re does not begin. (?abc) Embedded options, where abc is any number of option letters listed in Table 11-5. \c [: :] [. .] [= =] One of many backslash escapes listed in Table 11-4. Delimits a character class within a bracketed expression. See Table 11-3. Delimits a collating element within a bracketed expression. Delimits an equivalence class within a bracketed expression.
Table 11-3 lists the named character classes defined in advanced regular expressions and their associated backslash sequences, if any. Character class names are valid inside bracketed character sets with the [:class:] syntax.
xdigit Hexadecimal digits: zero through nine, a-f, A-F. Table 11-4 lists backslash sequences supported in Tcl 8.1.
Table 11-4. Backslash escapes in regular expressions UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
\a \A \b \B Alert, or "bell", character. Matches only at the beginning of the string. Backspace character, \u0008. Synonym for backslash. Control-X. Digits. Same as [[:digit:]] Not a digit. Same as [^[:digit:]] Escape character, \u001B. Form feed, \u000C. Matches the beginning of a word. Matches the end of a word. Newline, \u000A. Carriage return, \u000D. Space. Same as [[:space:]] Not a space. Same as [^[:space:]] Horizontal tab, \u0009.
\uXXXX A 16-bit Unicode character code. \v \w \W \xhh \y \Y \Z \0 \x \xy Vertical tab, \u000B. Letters, digit, and underscore. Same as [[:alnum:]_] Not a letter, digit, or underscore. Same as [^[:alnum:]_] An 8-bit hexadecimal character code. Consumes all hex digits after \x. Matches the beginning or end of a word. Matches a point that is not the beginning or end of a word. Matches the end of the string. NULL, \u0000 Where x is a digit, this is a back-reference. Where x and y are digits, either a decimal back-reference, or an 8-bit octal character code.
Table 11-5 lists the embedded option characters used with the (?abc) syntax.
\xyz
Where x, y and z are digits, either a decimal back-reference or an 8-bit octal character code.
Table 11-5 lists the embedded option characters used with the (?abc) syntax.
Table 11-5. Embedded option characters used with the (?x) syntax
b The rest of the pattern is a basic regular expression (a la vi or grep). c Case sensitive matching. This is the default. e The rest of the pattern is an extended regular expression (a la Tcl 8.0). i Case insensitive matching. m Synonym for the n option. n Newline sensitive matching . Both lineanchor and linestop mode. p Partial newline sensitive matching. Only linestop mode. q The rest of the pattern is a literal string. s No newline sensitivity. This is the default. t Tight syntax; no embedded comments. This is the default. w Inverse partial newline-sensitive matching. Only lineanchor mode. x Expanded syntax with embedded white space and comments. [ Team LiB ]
[ Team LiB ]
regexp ?flags? pattern string UNREGISTERED VERSION OF CHM TO ?match sub1 sub2...? THETA-SOFTWARE PDF CONVERTER By The flags are described in Table 11-6:
-indices
-expanded -line
-lineanchor Change the behavior of ^ and $ so they are line-oriented as discussed on page 153. -linestop -about -Change matching so that . and character classes do not match newlines as discussed on page 153. Useful for debugging. It returns information about the pattern instead of trying to match it against the input. Signals the end of the options. You must use this if your pattern begins with -.
The pattern argument is a regular expression as described earlier. If string matches pattern, then regexp stores the results of the match in the variables provided. These match variables are optional. If present, match is set to the part of the string that matched the pattern. The remaining variables are set to the substrings of string that matched the corresponding subpatterns in pattern. The correspondence is based on the order of left parentheses in the pattern to avoid ambiguities that can arise from nested subpatterns. Example 11-2 uses regexp to pick the hostname out of the DISPLAY environment variable, which has the form:
hostname:display.screen
The pattern involves a complementary set, [^:], to match anything except a colon. It uses repetition, *, to repeat that zero or more times. It groups that part into a subexpression with parentheses. The literal colon ensures that the DISPLAY value matches the format we expect. The part of the string that matches the complete pattern is stored into the match variable. The part that matches the subpattern is stored into host. The whole pattern has been grouped with braces to quote the square brackets. Without braces it would be:
With advanced regular expressions the nongreedy quantifier *? can replace the complementary set:
This is quite a powerful statement, and it is efficient. If we had only had the string command to work with, we would have needed to resort to the following, which takes roughly twice as long to interpret:
set i [string first : $env(DISPLAY)] if {$i >= 0} { set host [string range $env(DISPLAY) 0 [expr $i-1]] }
set match => http://www.beedub.com:80/index.html set protocol => http set server => www.beedub.com set x => :80 UNREGISTERED VERSION OF CHM TO PDF CONVERTER set port => 80 set path => /index.html
By THETA-SOFTWARE
[^:]+:
.+?:
The next part of the pattern looks for the server name, which comes after two slashes. The server name is followed either by a colon and a port number, or by a slash. The pattern uses a complementary set that specifies one or more characters that are not a colon or a slash. This matches the //www.beedub.com part of the URL:
//[^:/]+
The port number is optional, so a subpattern is delimited with parentheses and followed by a question mark. An additional set of parentheses are added to capture the port number without the leading colon. This matches the :80 part of the URL:
(:([0-9]+))?
The last part of the pattern is everything else, starting with a slash. This matches the /index.html part of the URL:
/.*
To make this pattern really useful, we delimit several subpatterns with parentheses:
([^:]+)://([^:/]+)(:([0-9]+))?(/.*)
These parentheses do not change the way the pattern matches. Only the optional port number really needs the parentheses in this example. However, the regexp command gives us access to the strings that match these subpatterns. In one step regexp can test for a valid URL and divide it into the protocol part, the server, the port, and the trailing path. The parentheses around the port number include the : before the digits. We've used a dummy variable that gets the : and the port number, and another match variable that just gets the port number. By using noncapturing parentheses in advanced regular expressions, we can eliminate the unused match variable. We can also replace both complementary character sets with a nongreedy .+? match. Example 11-4 shows this variation:
The table in this section lists regular expressions as you would use them in Tcl commands. Most are quoted with curly braces to turn off the special meaning of square brackets and dollar signs. Other patterns are grouped with double quotes and use backslash quoting because the patterns include backslash sequences like \n and \t. In Tcl 8.0 and earlier, these must be substituted by Tcl before the regexp command is called. In these cases, the equivalent advanced regular expression is also shown.
{^(yes|YES|Yes)$} UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Exactly "yes", "Yes", or "YES". {^[^ \t:\]+:} {^\S+?:} "^\[ \t]*$" {(?n)^\s*$} "(\n|^)\[^\n\]*(\n|$)" {^[A-Za-z]+$} {^[[:alpha:]]+$} {[A-Za-z0-9_]+} {\w+} {[][${}\\]} "\[^\n\]*\n" {.*?\n} {\.} {[][$^?+*()|\\]} Begins with colon-delimited field that has no spaces or tabs. Same as above, using \S for "not space". A string of all spaces or tabs. A blank line using newline sensitive mode. A blank line, the hard way. Only letters. Only letters, the Unicode way. Letters, digits, and the underscore. Letters, digits, and the underscore using \w. The set of Tcl special characters: ] [ $ { } \ Everything up to a newline. Everything up to a newline using nongreedy *? A period. The set of regular expression special characters: ][$^?+*()|\ <H1>(.*?)</H1> <!--.*?--> {[0-9a-hA-H][0-9a-hAH]} {[[:xdigit:]]{2}} {\d{1,3}} [ Team LiB ] An H1 HTML tag. The subpattern matches the string between the tags. HTML comments. 2 hex digits. 2 hex digits, using advanced regular expressions. 1 to 3 digits, using advanced regular expressions.
[ Team LiB ]
The regsub command returns the number of matches and replacements, or 0 if there was no match. regsub copies string to varname, replacing occurrences of pattern with the substitution specified by subspec. If the pattern does not match, then string is copied to varname without modification. The optional switches include: -all, which means to replace all occurrences of the pattern. Otherwise, only the first occurrence is replaced. The -nocase, -expanded, -line, -linestop, and -lineanchor switches are the same as in the regexp command. They are described on page 158. The -- switch separates the pattern from the switches, which is necessary if your pattern begins with a -. The replacement pattern, subspec, can contain literal characters as well as the following special sequences: & is replaced with the string that matched the pattern. \x , where x is a number, is replaced with the string that matched the corresponding subpattern in pattern. The correspondence is based on the order of left parentheses in the pattern specification. The following replaces a user's home directory with a ~:
set file tclIO.c regsub {([^\.]*)\.c$} $file {cc -c & -o \1.o} ccCmd
The matching pattern captures everything before the trailing .c in the file name. The & is replaced with the complete match, tclIO.c, and \1 is replaced with tclIO, which matches the pattern between the parentheses. The value assigned to ccCmd is:
cc -c tclIO.c -o tclIO.o
[ Team LiB ]
[ Team LiB ]
regsub
One of the most powerful combinations of Tcl commands is regsub and subst. This section describes a few examples that use regsub to transform data into Tcl commands, and then use subst to replace those commands with a new version of the data. This technique is very efficient because it relies on two subsystems that are written in highly optimized C code: the regular expression engine and the Tcl parser. These examples are primarily written by Stephen Uhler.
URL Decoding
When a URL is transmitted over the network, it is encoded by replacing special characters with a %xx sequence, where xx is the hexadecimal code for the character. In addition, spaces are replaced with a plus (+). It would be tedious and very inefficient to scan a URL one character at a time with Tcl statements to undo this encoding. It would be more efficient to do this with a custom C program, but still very tedious. Instead, a combination of regsub and subst can efficiently decode the URL in just a few Tcl commands. Replacing the + with spaces requires quoting the + because it is the one-or-more special character in regular expressions:
The %xx are replaced with a format command that will generate the right character:
The %c directive to format tells it to generate the character from a character code number. We force a hexadecimal interpretation with a leading 0x. Advanced regular expressions let us write the "2 hex digits" pattern a bit more cleanly:
The resulting string is passed to subst to get the format commands substituted:
For example, if the input is %7ewelch, the result of the regsub is:
[format %c 0x7e]welch
~welch
name1=value1&name2=value2&name3=value3
Example 11-6 shows Cgi_List and Cgi_Query. Cgi_Query receives the form data from the standard input or the QUERY_STRING environment variable, depending on whether the form data is transmitted with a POST or GET request. These HTTP operations are described in detail in Chapter 17. Cgi_List uses split to get back a list of names and values, and then it decodes them with Url_Decode. It returns a Tcl-friendly name, value list that you can either iterate through with a foreach command, or assign to an array with array set:
global env if {![info exists env(QUERY_STRING)] || [string length $env(QUERY_STRING)] == 0} { if {[info exists env(CONTENT_LENGTH)] && [string length $env(CONTENT_LENGTH)] != 0} { set query [read stdin $env(CONTENT_LENGTH)] } else { gets stdin query } set env(QUERY_STRING) $query set env(CONTENT_LENGTH) 0 } return $env(QUERY_STRING) }
An HTML form can have several form elements with the same name, and this can result in more than one value for each name. If you blindly use array set to map the results of Cgi_List into an array, you will lose the repeated values. Example 11-7 shows Cgi_Parse and Cgi_Value that store the query data in a global cgi array. Cgi_Parse adds list structure whenever it finds a repeated form value. The global cgilist array keeps a record of how many times a form value is repeated. The Cgi_Value procedure returns elements of the global cgi array, or the empty string if the requested value is not present.
Example 11-7 Cgi_Parse and Cgi_Value store query data in the cgi array
proc Cgi_Parse {} { global cgi cgilist catch {unset cgi cgilist} set query [Cgi_Query] regsub -all {\+} $query { } query foreach {name value} [split $query &=] { set name [CgiDecode $name] if {[info exists cgilist($name)] && ($cgilist($name) == 1)} { # Add second value and create list structure set cgi($name) [list $cgi($name) \ [Url_Decode $value]] } elseif {[info exists cgi($name)]} { # Add additional list elements lappend cgi($name) [CgiDecode $value] } else { # Add first value without list structure set cgi($name) [CgiDecode $value] set cgilist($name) 0 ;# May need to listify } incr cgilist($name) } return [array names cgi] } proc Cgi_Value {key} { global cgi if {[info exists cgi($key)]} { return $cgi($key) } else {
return {} } } proc Cgi_Length {key} { global cgilist if {[info exist cgilist($key)]} { return $cgilist($key) } elseVERSION OF CHM TO PDF CONVERTER UNREGISTERED { return 0 } }
By THETA-SOFTWARE
The decimal encoding (e.g., ©) is also more awkward than the hexadecimal encoding used in URLs. We cannot force a decimal interpretation of a number in Tcl. In particular, if the entity has a leading zero (e.g., 
) then Tcl interprets the value (e.g., 010) as octal. The scan command is used to do a decimal interpretation. It scans into a temporary variable, and set is used to get that value:
regsub -all {&#([0-9][0-9]?[0-9]?);?} $new \ {[format %c [scan \1 %d tmp; set tmp]]} new
With advanced regular expressions, this could be written as follows using bound quantifiers to specify one to three digits:
The named entities are converted with an array that maps from the entity names to the special
character. The only detail is that unknown entity names (e.g., &foobar;) are not converted. This mapping is done inside HtmlMapEntity, which guards against invalid entities.
[x < y]
[x < y]
The following example is the brainchild of Stephen Uhler. It uses regsub to transform HTML into a Tcl script. When it is evaluated the script calls a procedure to handle each tag in an HTML document. This provides a general framework for processing HTML. Different callback procedures can be applied to the tags to achieve different effects. For example, the html_library-0.3 package on the CD-ROM uses Html_Parse to display HTML in a Tk text widget.
The main regsub pattern can be written more simply with advanced regular expressions:
<Title>My Home Page</Title> <Body bgcolor=white text=black> <H1>My Home</H1> This is my <b>home</b> page.
Render .text Render .text Render .text } Render .text } Render .text Render .text This is my } Render .text Render .text } Render .text
{hmstart} {} {} {} {Title} {} {} {My Home Page} {Title} {/} {} { {Body} {} {bgcolor=white text=black} { {H1} {} {} {My Home} {H1} {/} {} { {b} {} {} {home} {b} {/} {} { page. {hmstart} / {} {}
One overall point to make about this example is the difference between using eval and subst with the generated script. The decoders shown in Examples 11-5 and 11-8 use subst to selectively replace encoded characters while ignoring the rest of the text. In Html_Parse we must process all the text. The main trick is to replace the matching text (e.g., the HTML tag) with some Tcl code that ends in an open curly brace and starts with a close curly brace. This effectively groups all the unmatched text. When eval is used this way you must do something with any braces and backslashes in the unmatched text. Otherwise, the resulting script does not parse correctly. In this case, these special characters are encoded as HTML entities. We can afford to do this because the cmd that is called must deal with encoded entities already. It is not possible to quote these special characters with backslashes because all this text is inside curly braces, so no backslash substitution is performed. If you try that the backslashes will be seen by the cmd callback. Finally, I must admit that I am always surprised that this works:
I always forget that $start and $html are substituted in spite of the braces. This is because double quotes are being used to group the argument, so the quoting effect of braces is turned off.
UNREGISTERED VERSION OF CHM html regsub -all --> $html \x81 TO PDF CONVERTER By THETA-SOFTWARE
This replaces all the end comment sequences with a single character that is not allowed in HTML. Now you can delete the comments like this:
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Chapter 12. Script Libraries and UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Packages
Collections of Tcl commands are kept in libraries and organized into packages. Tcl automatically loads libraries as an application uses their commands. Tcl commands discussed are: package, pkg_mkIndex, auto_mkindex, unknown, and tcl_findLibrary.
UNREGISTEREDgroup useful OF CHM TO PDF CONVERTER Bybe used by multiple applications. VERSION sets of Tcl procedures so that they can THETA-SOFTWARE Libraries
For example, you could use any of the code examples that come with this book by creating a script library and then directing your application to check in that library for missing procedures. One way to structure a large application is to have a short main script and a library of support scripts. The advantage of this approach is that not all the Tcl code needs to be loaded to start the application. Applications start up quickly, and as new features are accessed, the code that implements them is loaded automatically. The Tcl package facility supports version numbers and has a provide/require model of use. Typically, each file in a library provides one package with a particular version number. Packages also work with shared object libraries that implement Tcl commands in compiled code, which are described in Chapter 47. A package can be provided by a combination of script files and object files. Applications specify which packages they require and the libraries are loaded automatically. The package facility is an alternative to the auto loading scheme used in earlier versions of Tcl. You can use either mechanism, and this chapter describes them both. If you create a package you may wish to use the namespace facility to avoid conflicts between procedures and global variables used in different packages. Namespaces are the topic of Chapter 14. Before Tcl 8.0 you had to use your own conventions to avoid conflicts. This chapter explains a simple coding convention for large Tcl programs. I use this convention in exmh, a mail user interface that has grown from about 2,000 to over 35,000 lines of Tcl code. A majority of the code has been contributed by the exmh user community. Such growth might not have been possible without coding conventions. [ Team LiB ]
[ Team LiB ]
Disk:System Folder:Extensions:Tool Command Language:tcl8.4 Disk:System Folder:Extensions:Tool Command Language Disk:System Folder:Extensions:Tool Command Language:tk8.4
The package facility searches these directories and their subdirectories for packages. The easiest way to manage your own packages is to create a directory at the same level as the Tcl library:
/usr/local/tcl/lib/welchbook
Packages in this location, for example, will be found automatically because the auto_path list includes /usr/local/tcl/lib. You can also add directories to the auto_path explicitly:
One trick I often use is to put the directory containing the main script into the auto_path. The following command sets this up:
If your code is split into bin and lib directories, then scripts in the bin directory can add the adjacent lib directory to their auto_path with this command:
[ Team LiB ]
Using Packages
Each script file in a library declares what package it implements with the package provide command:
The name identifies the package, and the version has a major.minor format. The convention is that the minor version number can change and the package implementation will still be compatible. If the package changes in an incompatible way, then the major version number should change. For example, Chapter 17 defines several procedures that use the HTTP network protocol. These include http::geturl, http::wait, and http::cleanup. The file that contains the procedures starts with this command:
Case is significant in package names. In particular, the package that comes with Tcl is named http - all lowercase. More than one file can contribute to the same package simply by specifying the same name and version. In addition, different versions of the same package can be kept in the same directory but in different files. An application specifies the packages it needs with the package require command:
If the version is left off, then the highest available version is loaded. Otherwise the highest version with the same major number is loaded. For example, if the client requires version 1.1, version 1.2 could be loaded if it exists, but versions 1.0 and 2.0 would not be loaded. You can restrict the package to a specific version with the -exact flag. If no matching version can be found, then the package require command raises an error.
For example:
In this example, .so, .shlib, and .dll are file suffixes for shared libraries on UNIX,
Macintosh, and Windows systems, respectively. You can have packages that have some of their commands implemented in C, and some implemented as Tcl procedures. The script files and the shared library must simply declare that they implement the same package. The pkg_mkIndex procedure will detect this and set up the auto_index, so some commands are defined by sourcing scripts, and some are defined by loading shared libraries. If your file servers support more than one machine architecture, such as Solaris and Linux systems, you probably keep the shared library files in machine-specific directories. In this case the auto_path should also list the machine-specific directory so that the shared libraries there can be loaded automatically. If your system administrator configured the Tcl installation properly, this should already be set up. If not, or you have your shared libraries in a nonstandard place, you must append the location to the auto_path variable.
[ Team LiB ]
[ Team LiB ]
Use pkg_mkIndex to maintain your index files. Decide at this time whether or not to use direct or lazy package loading. Put the appropriate package require and package provide commands in your code. Ensure that your library directories, or their parent directories, are listed in the auto_path variable. [ Team LiB ]
[ Team LiB ]
package vcompare v1 v2 Compares version v1 and v2. Returns 0 if they are equal, -1 if v1 is less than v2, or 1 if v1 is greater than v2. package versions package package vsatisfies v1 v2 [ Team LiB ] Returns which versions of the package are registered. Returns 1 if v1 is greater or equal to v2 and still has the same major version number. Otherwise returns 0.
[ Team LiB ]
You will need to update the tclIndex file if you add procedures or change any of their names. A conservative approach to this is shown in the next example. It is conservative because it recreates the index if anything in the library has changed since the tclIndex file was last generated, whether or not the change added or removed a Tcl procedure.
} }
The auto_path variable contains a list of directories to search for unknown commands. To continue our example, you can make the procedures in the book examples available by putting this command at the beginning of your scripts:
This has no effect if you have not created the tclIndex file. If you want to be extra careful, you can call Library_UpdateIndex. This will update the index if you add new things to the library.
This will not work if there is no tclIndex file at all because Tcl won't be able to find the implementation of Library_UpdateIndex. Once the tclIndex has been created for the first time, then this will ensure that any new procedures added to the library will be installed into tclIndex. In practice, if you want this sort of automatic update, it is wise to include something like the Library_UpdateIndex procedure directly into your application as opposed to loading it from the library it is supposed to be maintaining. [ Team LiB ]
[ Team LiB ]
source [file join $dir bind_ui.tcl] load [file join $dir mime.so] Mime
The $dir gets substituted with the name of the directory that contains the library file, so the result is a source or load command that defines the missing Tcl command. The substitution is done with eval, so you could initialize auto_index with any commands at all. Example 12-2 is a simplified version of the code that reads the tclIndex file.
auto_noload
If you do not want the unknown procedure to try and load procedures, you can set the auto_noload variable to disable the mechanism:
Auto loading is quite fast. I use it regularly on applications both large and small. A large application will start faster if you only need to load the code necessary to start it up. As you access more features of your application, the code will load automatically. Even a small application benefits from auto loading because it encourages you to keep commonly used code in procedure libraries. [ Team LiB ]
[ Team LiB ]
Interactive Conveniences
The unknown command provides a few other conveniences. These are used only when UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE you are typing commands directly. They are disabled once execution enters a procedure or if the Tcl shell is not being used interactively. The convenience features are automatic execution of programs, command history, and command abbreviation. These options are tried, in order, if a command implementation cannot be loaded from a script library.
Auto Execute
The unknown procedure implements a second feature: automatic execution of external programs. This makes a Tcl shell behave more like other UNIX shells that are used to execute programs. The search for external programs is done using the standard PATH environment variable that is used by other shells to find programs. If you want to disable the feature all together, set the auto_noexec variable:
History
The history facility described in Chapter 13 is implemented by the unknown procedure.
Abbreviations
If you type a unique prefix of a command, unknown recognizes it and executes the matching command for you. This is done after automatic program execution is attempted and history substitutions are performed. [ Team LiB ]
[ Team LiB ]
The first two directories correspond to the standard installation directories, while the last three correspond to the standard build environment for Tcl or Tk. The first directory in the list that contains a valid init.tcl file becomes the Tcl script library. This directory location is saved in the tcl_library global variable, and it is also returned by the info library command. The primary thing defined by init.tcl is the implementation of the unknown procedure. It also initializes auto_path to contain $tcl_library and the parent directory of $tcl_library. There may be additional directories added to auto_path depending on the compiled in value of
tcl_pkgPath.
tcl_findLibrary
A generalization of this search is implemented by tcl_findLibrary. This procedure is designed for use by extensions OF CHM [incr Tcl]. Of course, Tcl By THETA-SOFTWARE UNREGISTERED VERSION like Tk andTO PDF CONVERTER cannot use tcl_findLibrary itself because it is defined in init.tcl! The tcl_findLibrary procedure searches relative to the location of the main program (e.g., tclsh or wish) and assumes a standard installation or a standard build environment. It also supports an override by an environment variable, and it takes care of sourcing an initialization script. The usage of tcl_findLibrary is: UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE tcl_findLibrary base version patch script enVar varName
The base is the prefix of the script library directory name. The version is the main version number (e.g., "8.0"). The patch is the full patch level (e.g., "8.0.3"). The script is the initialization script to source from the directory. The enVar names an environment variable that can be used to override the default search path. The varName is the name of a variable to set to name of the directory found by tcl_findLibrary. A side effect of tcl_findLibrary is to source the script from the directory. An example call is:
This call first checks to see whether TK_LIBRARY is defined in the environment. If so, it uses its value. Otherwise, it searches the following directories for a file named tk.tcl. It sources the script and sets the tk_library variable to the directory containing that file. The search is relative to the value returned by info nameofexecutable:
Tk also adds $tk_library to the end of auto_path, so the other script files in that directory are available to the application:
[ Team LiB ]
[ Team LiB ]
Coding Style
If you supply a package, you need to follow some simple coding conventions to make your library easier to use by other programmers. You can use the namespace facility introduced in Tcl 8.0. You can also use conventions to avoid name conflicts with other library packages and the main application. This section describes the conventions I developed before namespaces were added to Tcl.
In general, I try to use a single global or namespaced array for a package (namespaces are discussed in Chapter 14). The array provides a convenient place to collect a set of related variables, much as a struct is used in C. For example, the preferences package uses the pref array to hold all its state information. It is also a good idea to keep the use of the array private. It is better coding practice to provide exported procedures than to let other modules access your data structures directly. This makes it easier to change the implementation of your
package without affecting its clients. When choosing a namespace name, try to make it significant to your application. If you do need to export a few key variables from your module, use the underscore convention to distinguish exported variables. If you need more than one global variable, just stick with the prefix convention to avoid conflicts, or provide accessor functions instead.
John Ousterhout has published two programming style guides, one for C programming known as The Engineering Manual and one for Tcl scripts known as The Style Guide. These describe UNREGISTERED VERSION OF CHM TO PDF CONVERTERfor modules, procedures, and details about file structure as well as naming conventions By THETA-SOFTWARE variables. The Tcl Style Guide conventions use Tcl namespaces to separate packages. Namespaces automatically provide a way to avoid conflict between procedure names. Namespaces also support collections of variables without having to use arrays for grouping. You can find these style guides on the CD-ROM and also in ftp://ftp.tcl.tk/pub/tcl/doc. The Engineering Manual is distributed as a compressed tar file, engManual.tar.Z, that contains sample files as well as the main document. The Style Guide is distributed as styleGuide.ps (or .pdf). [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Table 13-1. The clock command UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
clock clicks ?-milliseconds? A high resolution counter. The precision is milliseconds, if specified (Tcl 8.4), or a system-dependent value. Formats a clock value according to str. See Table 13-2. Parses date string and return seconds value. The clock value determines the date. Returns the current time in seconds.
clock format value ?-format str? clock scan string ?-base clock? ?-gmt boolean? clock seconds
clock format [clock seconds] => Fri Nov 22 4:09:14 PM PST 2002
The clock seconds command returns the current time, in seconds since a starting epoch. The clock format command formats an integer value into a date string. It takes an optional argument that controls the format. The format strings contains % keywords that are replaced with the year, month, day, date, hours, minutes, and seconds, in various formats. The default string is:
%a %b %d %H:%M:%S %Z %Y
%B Full month name. %c Locale specific date and time (e.g., Nov 24 16:00:59 1996). %C First two digits of the four-digit year (19 or 20). %d Day of month (01 31). %D Date as %m/%d/%y (e.g., 02/19/97). %e Day of month (1 31), no leading zeros. %h Abbreviated month name. %H Hour in 24-hour format (00 23). %I Hour in 12-hour format (01 12). %j Day of year (001 366). %k Hour in 24-hour format, without leading zeros (0 - 23). %l Hour in 12-hour format, without leading zeros (1 12). %m Month number (01 12). %M Minute (00 59). %n Inserts a newline. %p AM/PM indicator. %r Time as %I:%M:%S %p (e.g., 02:39:29 PM). %R Time as %H:%M (e.g., 14:39). %s Seconds since the epoch. %S Seconds (00 59). %t Inserts a tab. %T Time as %H:%M:%S (e.g., 14:34:29). %u Weekday number (Monday = 1, Sunday = 7). %U Week of year (00 52) when Sunday starts the week. %V Week of year according to ISO-8601 rules (Week 1 contains January 4). %w Weekday number (Sunday = 0). %W Week of year (00 52) when Monday starts the week. %x Locale specific date format (e.g., Feb 19 1997). %X Locale specific time format (e.g., 20:10:13). %y Year without century (00 99). %Y Year with century (e.g. 1997). %Z Time zone name. The clock clicks command returns the value of the system's highest resolution clock. The units of the clicks is milliseconds if -milliseconds is specified, otherwise it is undefined. The main use of this command is to measure the relative time of different performance tuning trials.
The -milliseconds flag was added in Tcl 8.4. Example 13-1 shows how to calibrate the clicks value by counting the clicks per second over 10 seconds, which will vary from system to system:
Tcl implements the standard interpretation of two-digit year values, which is that 7099 are 19701999, 0069 are 20002069. Versions of Tcl before 8.0 did not properly deal with twodigit years in all cases. Note, however, that Tcl is limited by your system's time epoch and the number of bits in an integer. On Windows, Macintosh, and most UNIX systems, the clock epoch is January 1, 1970. A 32-bit integer can count enough seconds to reach forward into the year 2037, and backward to the year 1903. If you try to clock scan a date outside that range, Tcl will raise an error because the seconds counter will overflow or underflow. In this case, Tcl is just reflecting limitations of the underlying system. Some 64-bit systems (such as Solaris 8 64bit) use 64-bit integers for the system clock, which Tcl 8.4 supports. This extends the recognized range into the billions of years. If you leave out a date, clock scan assumes the current date. You can also use the -base option to specify a date. The following example uses the current time as the base, which is redundant:
The date parser allows these modifiers: year, month, fortnight (two weeks), week, day, hour, minute, second. You can put a positive or negative number in front of a modifier as a multiplier. For example:
clock format [clock scan "10:30:44 PM 1 week"] => Fri Nov 29 10:30:44 PM PST 2002 clock format [clock scan "10:30:44 PM -1 week"] Fri Nov 15 10:30:44 PM PST 2002
You can also use tomorrow, yesterday, today, now, last, this, next, and ago, as modifiers.
clock format [clock scan "3 years ago"] => Mon Nov 22 4:18:34 PM PST 1999
Both clock format and clock scan take a -gmt option that uses Greenwich Mean Time. Otherwise, the local time zone is used.
clock format [clock seconds] -gmt true => Sat Nov 23 12:19:13 AM GMT 2002 clock format [clock seconds] -gmt false => Fri Nov 22 4:19:35 PM PST 2002
[ Team LiB ]
[ Team LiB ]
info locals ?pattern? info nameofexecutable info patchlevel info procs ?pattern? info script ?filename? info sharedlibextension info tclversion
Variables
There are three categories of variables: local, global, and visible. Information about these categories is returned by the locals, globals, and vars operations, respectively. The local variables include procedure arguments as well as locally defined variables. The global variables include all variables defined at the global scope. The visible variables include locals, plus any variables made visible via global or upvar commands. A pattern can be specified to limit the returned list of variables to those that match the pattern. The pattern is interpreted according to the rules of string match, which is described on page 53:
Namespaces, which are the topic of the next chapter, partition global variables into different scopes. You query the variables visible in a namespace with:
Remember that a variable may not be defined yet even though a global or upvar command has declared it visible in the current scope. Use the info exists command to test whether a variable or an array element is defined or not. An example is shown on page 96.
Procedures
You can find out everything about a Tcl procedure with the args, body, and default operations. This is illustrated in the following Proc_Show example. The puts commands use the -nonewline flag because the newlines in the procedure body, if any, are retained:
Example 13-3 is a more elaborate example of procedure introspection that comes from the direct.tcl file, which is CHM the PDF CONVERTER By in Chapter 18. This code UNREGISTERED VERSION OFpart of TO Tcl Web Server describedTHETA-SOFTWARE is used to map URL requests and the associated query data directly into Tcl procedure calls. This is discussed in more detail on page 262. The Web server collects Web form data into an array called form. Example 13-3 matches up elements of the form array with procedure arguments, and it collects extra elements into an args parameter. If a form value is missing, then the default argument value or the empty string is used:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 13-3 Mapping form data onto procedure arguments
# cmd is the name of the procedure to invoke # form is an array containing form values set cmdOrig $cmd set params [info args $cmdOrig] # Match elements of the form array to parameters foreach arg $params { if {![info exists form($arg)]} { if {[info default $cmdOrig $arg value]} { lappend cmd $value } elseif {[string equal $arg "args"]} { set needargs yes } else { lappend cmd {} } } else { lappend cmd $form($arg) } } # If args is a parameter, then append the form data # that does not match other parameters as extra parameters if {[info exists needargs]} { foreach {name value} [array get form] { if {[lsearch $params $name] < 0} { lappend cmd $name $value } } } # Eval the command set code [catch $cmd result]
The info commands operation returns a list of all commands, which includes both built-in commands defined in C and Tcl procedures. There is no operation that just returns the list of
built-in commands. Example 13-4 finds the built-in commands by removing all the procedures from the list of commands.
Command Evaluation
If you want to know how many Tcl commands are executed, use the info cmdcount command. This counts all commands, not just top-level commands. The counter is never reset, so you
need to sample it before and after a test run if you want to know how many commands are executed during a test. Command tracing provides detailed information about the execution of commands. It is described along with variable tracing on page 193. The info complete operation figures out whether a string is a complete Tcl command. This is useful for command interpreters that need to wait until the user has typed in a complete Tcl UNREGISTERED VERSION OF it to eval. Example 13-6 defines By THETA-SOFTWARE a line of command before passing CHM TO PDF CONVERTER Command_Process that gets input and builds up a command. When the command is complete, the command is executed at the global scope. Command_Process takes two callbacks as arguments. The inCmd is evaluated to get the line of input, and the outCmd is evaluated to display the results. Chapter 10 describes callbacks why the curly braces are used with eval as they are in this example:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 13-6 A procedure to read and evaluate commands
proc Command_Process {inCmd outCmd} { global command append command(line) [eval $inCmd] if {[info complete $command(line)]} { set code [catch {uplevel #0 $command(line)} result] eval $outCmd {$result $code} set command(line) {} } } proc Command_Read {{in stdin}} { if {[eof $in]} { if {$in != "stdin"} { close $in } return {} } return [gets $in] } proc Command_Display {file result code} { puts stdout $result } while {![eof stdin]} { Command_Process {Command_Read stdin} \ {Command_Display stdout} }
I often use info script to source or process files stored in the same directory as the script that is running. A few examples are shown in Example 13-7.
The pathname of the Tcl library is stored in the tcl_library variable, and it is also returned by the info library command. While you could put scripts into this directory, it might be better to have a separate directory and use the script library facility described in Chapter 12. This makes it easier to deal with new releases of Tcl and to package up your code if you want other sites to use it.
Version Numbers
Each Tcl release has a version number such as 7.4 or 8.0. This number is returned by the info tclversion command. If you want your script to run on a variety of Tcl releases, you may need to test the version number and take different actions in the case of incompatibilities between releases. The Tcl release cycle starts with one or two alpha and beta releases before the final release, and there may even be a patch release after that. The info patchlevel command returns a qualified version number, like 8.0b1 for the first beta release of 8.0. We switched from using "p" (e.g., 8.0p2) to a three-level scheme (e.g., 8.0.3) for patch releases. The patch level is zero for the final release (e.g., 8.2.0). In general, you should be prepared for feature changes during the beta cycle, but there should only be bug fixes in the patch releases. Another rule of thumb is that the Tcl script interface remains quite compatible between releases; feature additions are upward compatible.
Execution Environment
The file name of the program being executed is returned with info nameofexecutable. This is more precise than the name in the argv0 variable, which could be a relative name or a name
found in a command directory on your command search path. It is still possible for info nameofexecutable to return a relative pathname if the user runs your program as ./foo, for example. The following construct always returns the absolute pathname of the current program. If info nameofexecutable returns an absolute pathname, then the value of the current directory is ignored. The pwd command is described on page 122:
[ Team LiB ]
Cross-Platform Support
Tcl is designed so that you can write scripts that run unchanged on UNIX, Macintosh, and Windows platforms. In practice, you may need a small amount of code that is specific to a particular platform. You can find out information about the platform via the tcl_platform variable. This is an array with these elements defined: tcl_platform(platform) is one of unix, macintosh, or windows. tcl_platform(os) identifies the operating system. Examples include MacOS, Solaris, Linux, Win32s (Windows 3.1 with the Win32 subsystem), Windows 95, Windows NT, and SunOS. tcl_platform(osVersion) gives the version number of the operating system. tcl_platform(machine) identifies the hardware. Examples include ppc (Power PC), 68k (68000 family), sparc, intel, mips, and alpha. tcl_platform(byteOrder) identifies the byte order of this machine and is one of littleEndian or bigEndian. tcl_platform(wordSize) identifies the size of the native machine word in bytes. This was introduced in Tcl 8.4. tcl_platform(isWrapped) indicates that the application has been wrapped up into a single executable with TclPro Wrapper. This is not defined in normal circumstances. tcl_platform(user) gives the login name of the current user. tcl_platform(debug) indicates that Tcl was compiled with debugging symbols. tcl_platform(threaded) indicates that Tcl was compiled with thread support enabled. On some platforms a hostname is defined. If available, it is returned with the info hostname command. This command may return an empty string. One of the most significant areas affected by cross-platform portability is the file system and the way files are named. This topic is discussed on page 110. [ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE trace variable name ops command
trace vdelete name ops command trace vinfo name
The name is a Tcl variable name, which can be a simple variable, an array, or an array element. If a whole array is traced, the trace is invoked when any element is used according to ops. The ops argument is one or more of the letters r, for read traces, w, for write traces, u, for unset traces, and a for array traces. The command is executed when one of these events occurs. It is invoked as:
The name1 argument is the variable or array name. The name2 argument is the name of the array index, or null if the trace is on a simple variable. If there is an unset trace on an entire array and the array is unset, name2 is also null. The value of the variable is not passed to the procedure. The traced variable is one level up the Tcl call stack. The upvar, uplevel, or global commands need to be used to make the variable visible in the scope of command. These commands are described in more detail in Chapter 7. A read trace is invoked before the value of the variable is returned, so if it changes the variable itself, the new value is returned. A write trace is called after the variable is modified. The unset trace is called after the variable is unset. The array trace, which was added in Tcl 8.4, is called before the array command (e.g., array names) is used on the variable. A variable trace is automatically deleted when the variable is unset.
Command Tracing
The new form of trace supports both variable and command tracing:
trace add type name ops command trace remove type name ops command trace info type name
The type is one of command, execution or variable. For command, ops is a list and may contain rename, to trace the renaming of a Tcl command, or delete, to trace the deletion of a
command. Command tracing cannot be used to prevent the actual deletion of a command, it just receives the notification. No command traces are triggered when an interpreter is deleted. The command is invoked as:
For execution, the ops may be any of enter, leave, enterstep, and leavestep. enter invokes command immediately before the command name is executed, and leave will invoke command immediately following each execution. enterstep and leavestep are similar but they operate on the Tcl procedure name, invoking command for each Tcl command inside the procedure. In order to do this, they prevent the bytecode compilation of that procedure. This allows you to create a simple debugger in pure Tcl. The enter and enterstep operations invoke command as:
command command-string op
The command-string is the current command being executed, code is the result code of the execution and result is the result string. Example 6-16 on page 84 illustrates the different result codes. For variable tracing, the ops may be one or more of read, write, unset, or array. This is an alternate way to set up the variable traces described earlier.
Read-Only Variables
Example 13-8 uses traces to implement a read-only variable. A variable is modified before the trace procedure is called, so the ReadOnly variable is needed to preserve the original value. When a variable is unset, the traces are automatically removed, so the unset trace action reestablishes the trace explicitly. Note that the upvar alias (e.g., var) cannot be used to set up the trace. Instead, uplevel is used to create the trace in the original context of the variable. In general, essentially all traces are on global or namespace variables.
upvar 1 $varName var switch $op { w { set var $ReadOnly($varName) } u { set var $ReadOnly($varName) # Re-establish the trace CONVERTER name UNREGISTERED VERSION OF CHM TO PDF using the trueBy THETA-SOFTWARE uplevel 1 [list ReadOnlyVar $varName] } } }
This example merely overrides the new value with the saved value. Another alternative is to raise an error with the error command. This will cause the command that modified the variable to return the error. Another common use of trace is to update a user interface widget in response to a variable change. Several of the Tk widgets have this feature built into them. If more than one trace is set on a variable, then they are invoked in reverse order; the most recent trace is executed first. If there is a trace on an array and on an array element, then the trace on the array is invoked first.
A trace is deleted with the vdelete option, which has the same form as the variable option. The trace in the previous example can be removed with the following command:
[ Team LiB ]
[ Team LiB ]
history VERSION OF Adds the command to the history THETA-SOFTWARE UNREGISTERED add command ? CHM TO PDF CONVERTER By list. If exec is specified, then exec? history change new ? event?
history event ?event? Returns the command specified by event. history info ?count? Returns a formatted history list of the last count commands, or of all commands. Limits the history to the last count commands. Returns the number of the next event. Repeats the specified command.
The Tcl shell programs keep a log of the commands that you type by using a history facility. The log is controlled and accessed via the history command. The history facility uses the term event to mean an entry in its history log. The events are just commands, and they have an event ID that is their index in the log. You can also specify an event with a negative index that counts backwards from the end of the log. Event -1 is the previous event. Table 13-4 summarizes the Tcl history command. In the table, event defaults to -1. In practice you will want to take advantage of the ability to abbreviate the history options and even the name of the history command itself. For the command, you need to type a unique prefix, and this depends on what other commands are already defined. For the options, there are unique one-letter abbreviations for all of them. For example, you could reuse the last word of the previous command with [history w $]. This works because a $ that is not followed by alphanumerics or an open brace is treated as a literal $. Several of the history operations update the history list. They remove the actual history command and replace it with the command that resulted from the history operation. The event and redo operations all behave in this manner. This makes perfect sense because you would rather have the actual command in the history, instead of the history command used to retrieve the command.
History Syntax
Some extra syntax is supported when running interactively to make the history facility more convenient to use. Table 13-5 shows the special history syntax supported by tclsh and wish.
!prefix !pattern
^old^new Globally replaces old with new in the last command. The next example shows how some of the history operations work:
If you want to improve the history syntax, you will need to modify the unknown command, which is where it is implemented. This command is discussed in more detail in Chapter 12. Here is the code from the unknown command that implements the extra history syntax. The main limitation in comparison with the C shell history syntax is that the ! substitutions are performed only when ! is at the beginning of the command:
UNREGISTERED VERSION Implementing special history THETA-SOFTWARE Example 13-11 OF CHM TO PDF CONVERTER By syntax
# Excerpts from the standard unknown command # uplevel is used to run the command in the right context if {$name == "!!"} { UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE set newcmd [history event] } elseif {[regexp {^!(.+)$} $name dummy event]} { set newcmd [history event $event] } elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $name x old new]} { set newcmd [history event -1] catch {regsub -all -- $old $newcmd $new newcmd} } if {[info exists newcmd]} { history change $newcmd 0 return [uplevel $newcmd] }
[ Team LiB ]
[ Team LiB ]
Debugging
The rapid turnaround with Tcl coding means that it is often sufficient to add a few puts statements to your script to gain some insight about its behavior. This solution doesn't scale too well, however. A slight improvement is to add a Debug procedure that can have its output controlled better. You can log the information to a file, or turn it off completely. In a Tk application, it is simple to create a text widget to hold the contents of the log so that you can view it from the application. Here is a simple Debug procedure. To enable it you need to set the debug(enable) variable. To have its output go to your terminal, set debug(file) to stderr.
[ Team LiB ]
[ Team LiB ]
http://www.activestate.com/Tcl The current version of the Tcl Dev Kit contains these tools:
Checker
The Checker is a static code checker. This is a real win for large program development. It examines every line of your program looking for syntax errors and dubious coding practices. It has detailed knowledge of Tcl, Tk, Expect, [incr Tcl], and TclX commands and validates your use of them. It checks that you call Tcl procedures with the correct number of arguments, and can cross-check large groups of Tcl files. It knows about changes between Tcl versions, and it can warn you about old code that needs to be updated.
Compiler
The Compiler is really just a reader and writer for the byte codes that the Tcl byte-code compiler generates internally. It lets you precompile scripts and save the results, and then load the byte-code later instead of raw source. This provides a great way to hide your source code, if that is important to you. It turns out to save less time than you might think, however. By the time it reads the file from disk, decodes it, and builds the necessary Tcl data structures, it is not much faster than reading a source file and compiling it on the fly.
TclApp
TclApp assembles a collection of Tcl scripts, data files, and a Tcl/Tk interpreter into Starkits and Starpacks, which are described in Chapter 22. TclApp provides a more friendly user interface than the sdx command line tool described in that Chapter. The Tcl Dev Kit comes with pre-built Starkit runtimes that OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSIONinclude Metakit, Expect, [incr Tcl], and TclX.
Inspector
The Inspector is an improved version of the tkinspect application that lets you look at the state of other Tk applications. It displays procedures, variables, and the Tk widget hierarchy. You can issue commands to another application to change variables or test out commands. This turns out to be a very useful way to debug Tk applications. The original tkinspect was written by Sam Shen. [ Team LiB ]
[ Team LiB ]
Other Tools
The Tcl community has built many interesting and useful tools to help your Tcl development. Only two of them are mentioned below, but you can find many more at the Tcl Resource Center: http://www.tcl.tk/resource/
Critcl
Critcl is a tool that lets you mix C code right into your Tcl scripts. When the cproc command encounters its code for the first time, it automatically compiles it with gcc and loads it into your application. This provides an easy way to recode small parts of your application in C to get a performance boost. It's home page is: http://www.equi4.com/critcl
to update my applications to use bgerror instead of tkerror. If you have an application that runs under either Tk 4.0 or Tk 4.1, you can simply define both:
[ Team LiB ]
[ Team LiB ]
Performance Tuning
The time command measures the execution time of a Tcl command. It takes an optional parameter that is a repetition count:
If you need the result of the command being timed, use set to capture the result:
An extensive benchmark suite that compares various Tcl versions is available at: http://wiki.tcl.tk/Tcl%20Benchmarks
catch {close $log(file)} set log(file) [open $file w] set log(last) [clock clicks] } proc Log_Flush {} { global log catch {flush $log(file)} } UNREGISTERED VERSION OF CHM TO proc Log_Close {} { global log catch {close $log(file)} catch {unset log(file)} }
The previous expression is not fully defined until runtime, so it has to be parsed and executed each time it is used. If the expression is grouped with braces, then the compiler knows in advance what operations will be used and can generate byte codes to implement the expression more efficiently. The operation of the compiler is essentially transparent to scripts, but there are some differences in lists and expressions. These are described in Chapter 54. With lists, the good news is that large lists are more efficient. The problem is that lists are parsed more aggressively, so syntax errors at the end of a list will be detected even if you access only the
beginning of the list. There were also some bugs in the code generator in the widely used Tcl 8.0p2 release. Most of these were corner cases like unbraced expressions in if and while commands. Most of these bugs were fixed in the 8.0.3 patch release, and the rest were cleaned up in Tcl 8.1 with the addition of a new internal parsing package. The internal compiler continues to improve over time, with 8.4 extending the core instruction table to significantly improve performance over previous versions. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Using Namespaces
Namespaces add new syntax to procedure and variable names. A double colon, ::, separates the namespace name from the variable or procedure name. You use this syntax to reference procedures and variables in a different namespace. The namespace import command lets you name things in other namespaces without the extra syntax. Namespaces can be nested, so you can create a hierarchy of scopes. These concepts are explained in more detail in the rest of this chapter. One feature not provided by namespaces is any sort of protection, or a way to enforce access controls between different namespaces. This sort of thing is awkward, if not impossible, to provide in a dynamic language like Tcl. For example, you are always free to use namespace eval to reach into any other namespace. Instead of providing strict controls, namespaces are meant to provide structure that enables large scale programming. The package facility described in Chapter 12 was designed before namespaces. This chapter illustrates a style that ties the two facilities together, but they are not strictly related. It is possible to create a package named A that implements a namespace B, or to use a package without namespaces, or a namespace without a package. However, it makes sense to use the facilities together. Example 14-1 repeats the random number generator from Example 7-4 on page 91 using namespaces. The standard naming style conventions for namespaces use lowercase:
Example 14-1 defines three procedures and a variable inside the namespace random. From inside the namespace, you can use these procedures and variables directly. From outside the namespace, you use the :: syntax for namespace qualifiers. For example, the state variable is just seed within the namespace, but you use random::seed to refer to the variable from outside the namespace. Using the procedures looks like this:
Importing and exporting are described in more detail later. [ Team LiB ]
[ Team LiB ]
Namespace Variables
The variable command defines a variable inside a namespace. It is like the set command because it can define a value for the variable. You can declare several namespace variables with one variable command. The general form is:
If you have an array, do not assign a value in the variable command. Instead, use regular Tcl commands after you declare the variable. You can put any commands inside a namespace block:
namespace eval foo { variable arr array set arr {name value name2 value2} }
A namespace variable is similar to a global variable because it is outside the scope of any procedures. Procedures use the variable command or qualified names to reference namespace variables. For example, the random procedure has a variable command that brings the namespace variable into the current scope:
variable seed
If a procedure has a variable command that names a new variable, it is created in the namespace when it is first set.
You need to be careful when you use variables inside a namespace block. If you declare them with a variable command, they are clearly namespace variables. However, if you forget to declare them, then they will either become namespace variables, or latch onto an existing global variable by the same name. Consider the following code:
namespace eval foo { variable table for {set i 1} {$i <= 256} {incr i} {
If there is already a global variable i, then the for loop will use that variable. Otherwise, it will create the foo::i variable. I found this behavior surprising, but it does make it easier to access global variables like env without first declaring them with global inside the namespace block.
Qualified Names
UNREGISTERED VERSION begins with ::,PDF CONVERTER By THETA-SOFTWARE fully A fully qualified name OF CHM TO which is the name for the global namespace. A
qualified name unambiguously names a procedure or a variable. The fully qualified name works anywhere. If you use a fully qualified variable name, it is not necessary to use a global command. For example, suppose namespace foo has a namespace variable x, and there is also a global variable x. The global variable x can be named with this:
::x
The :: syntax does not affect variable substitutions. You can get the value of the global variable x with $::x. Name the namespace variable x with this:
::foo::x
A partially qualified name does not have a leading ::. In this case the name is resolved from the current namespace. For example, the following also names the namespace variable x:
foo::x
You can use qualified names with global. Once you do this, you can access the variable with its short name:
The Tcl byte-code compiler generates faster code when you declare namespace and global variables. Each procedure context has its own table of variables. The table can be accessed by
a direct slot index, or by a hash table lookup of the variable name. The hash table lookup is slower than the direct slot access. When you use the variable or global command, then the compiler can use a direct slot access. If you use qualified names, the compiler uses the more general hash table lookup. [ Team LiB ]
[ Team LiB ]
Command Lookup
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
A command is looked up first in the current name space. If it is not found there, then it is looked up in the global namespace. This means that you can use all the built-in Tcl commands inside a namespace with no special effort.
You can play games by redefining commands within a namespace. For example, a namespace could define a procedure named set. To get the built-in set you could use ::set, while set UNREGISTERED VERSION OF CHM TO PDF CONVERTER By need to be quite careful when you referred to the set defined inside namespace. Obviously you THETA-SOFTWARE do this. You can use qualified names when defining procedures. This eliminates the need to put the proc commands inside a namespace block. However, you still need to use namespace eval to create the namespace before you can create procedures inside it. Example 14-2 repeats the random number generator using qualified names. random::init does not need a variable command because it uses a qualified name for seed:
[ Team LiB ]
[ Team LiB ]
Nested Namespaces
Namespaces can be nested inside other namespaces. Example 14-3 shows three namespaces that have their own specific variable x. The fully qualified names for these variables are ::foo::x, ::bar::x, and ::bar::foo::x.
In Example 14-3 the partially qualified name foo::x can reference one of two variables depending on the current namespace. From the global scope the name foo::x refers to the namespace variable x inside ::foo. From the ::bar namespace, foo::x refers to the variable x inside ::bar::foo. If you want to unambiguously name a variable in the current namespace, you have two choices. The simplest is to bring the variable into scope with the variable command:
If you need to give out the name of the variable, then you have two choices. The most general solution is to use the namespace current command to create a fully qualified name:
The drawback of this OF CHM that it litters your code with THETA-SOFTWARE UNREGISTERED VERSIONapproach isTO PDF CONVERTER By references to ::myname::, which might be subject to change during program development. [ Team LiB ]
[ Team LiB ]
When you create the pkgIndex.tcl package index file with pkg_mkIndex, which is described Chapter 12, you should be aware that only exported names appear in the index. Because of this, I often resort to exporting everything. I never plan to import the names, but I do rely on automatic code loading based on the index files. This exports everything:
namespace export *
The namespace import command makes commands in another namespace visible in the current namespace. An import can cause conflicts with commands in the current namespace. The namespace import command raises an error if there is a conflict. You can override this with the -force option. The general form of the command is:
The pat is a string match type pattern that is matched against exported commands defined in namespace. You cannot use patterns to match namespace. The namespace can be a fully or partially qualified name of a namespace.
If you are lazy, you can import all procedures from a namespace:
The drawback of this approach is that random exports an init procedure, which might conflict with another module you import in the same way. It is safer to import just the procedures you UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE plan on using:
If the set of procedures in a namespace changes, or if its export list changes, then this has no effect on any imports that have already occurred from that namespace. [ Team LiB ]
[ Team LiB ]
set callback [namespace code {set x 1}] => namespace inscope ::current {set x 1} # sometime later ... eval $callback
When you evaluate $callback later, it executes in the ::current namespace because of the namespace inscope command. In particular, if there is a namespace variable ::current::x, then that variable is modified. An alternative to using namespace code is to name the variable with a qualified name:
The drawback of this approach is that it makes it tedious to move the code to a different namespace. If you need substitutions to occur on the command when you define it, use list to construct it. Using list is discussed in more detail on pages 131 and 455. Example 14-4 wraps up the list and the namespace inscope into the code procedure, which is handy because you almost always want to use list when constructing callbacks. The uplevel in code ensures that the correct namespace is captured; you can use code anywhere:
The example defines a callback that will set ::foo::x to y value. If you want to set x to the
value that y has at the time of the callback, then you do not want to do any substitutions. In that case, the original namespace code is what you want:
set callback [namespace code {set x $y}] => namespace inscope ::foo {set x $y}
UNREGISTERED VERSION OF CHM TO PDF CONVERTER Bynamespace inscope correctly THETA-SOFTWARE If the callback has additional arguments added by the caller,
adds them. For example, the scrollbar protocol described on page 501 adds parameters to the callback that controls a scrollbar. [ Team LiB ]
[ Team LiB ]
Introspection
The info commands operation returns all the commands that are currently visible. It is described in more detail on page 190. You can limit the information returned with a string match pattern. You can also include a namespace specifier in the pattern to see what is visible in a namespace. Remember that global commands and imported commands are visible, so info commands returns more than just what is defined by the namespace. Example 14-5 uses namespace origin, which returns the original name of imported commands, to sort out the commands that are really defined in a namespace:
[ Team LiB ]
[ Team LiB ]
namespace eval name cmd Concatenates args, if present, onto cmd and evaluates it in name ?args? ... namespace. namespace exists name namespace export ?clear? ?pat? ?pat? ... namespace forget pat ? pat? ... namespace import ?force? pat ?pat? ... namespace inscope name cmd ?args? ... namespace origin cmd Returns 1 if namespace name exists, 0 otherwise. (Tcl 8.4) Adds patterns to the export list for current namespace. Returns export list if no patterns. Undoes the import of names matching patterns. Adds the names matching the patterns to the current namespace. Appends args, if present, onto cmd as list elements and evaluates it in name namespace. Returns the original name of cmd.
namespace parent ?name? Returns the parent namespace of name, or of the current namespace. namespace qualifiers name namespace which ?flag? name namespace tail name [ Team LiB ] Returns the part of name up to the last :: in it. Returns the fully qualified version of name. The flag is one of command, -variable, or -namespace. Returns the last component of name.
[ Team LiB ]
Exporting procedures makes it more convenient for users of your package. It is not strictly necessary because they can always use qualified names to reference your procedures. An export list is a good hint about which procedures are expected to be used by other packages. Remember that the export list determines what procedures are visible in the index created by pkg_mkIndex. Callbacks execute at the global scope. If you use variable traces and variables associated with Tk widgets, these are also treated as global variables. If you want a callback to invoke a namespace procedure, or if you give out the name of a namespace variable, then you must construct fully qualified variable and procedure names. You can hardwire the current namespace: button .foo -command ::myname::callback \ -textvariable ::myname::textvar
[ Team LiB ]
[ Team LiB ]
[incr Tcl]
Object System
The Tcl namespace facility does not provide classes and inheritance. It just provides new scopes and a way to hide procedures and variables inside a scope. There are Tcl C APIs that support hooks in variable name and command lookup for object systems so that they can implement classes and inheritance. By exploiting these interfaces, various object systems can be added to Tcl as shared libraries.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE with The Tcl namespace facility was proposed by Michael McLennan based on his experiences
[incr Tcl], which is the most widely used object-oriented extension for Tcl. [incr Tcl] provides classes, inheritance, and protected variables and commands. If you are familiar with C++, [incr Tcl] should feel similar. A complete treatment of [incr Tcl] is not made in this book. [incr Tcl] From The Ground Up (Chad Smith, Osborn-McGraw Hill, 1999) is an excellent source of information. You can find a version of [incr Tcl] on the CD-ROM. The [incr Tcl] home page is: http://www.tcltk.com/itcl/ The [incr Tcl] sources are maintained on SourceForge: http://incrtcl.sourceforge.net/ [ Team LiB ]
[ Team LiB ]
xotcl
Object System
Xotcl is a more recently developed object-oriented extension that blends object-orientation and scripting in a way that preserves the benefits of both. It includes features such as dynamic object aggregation, per-object mixins, filters, dynamic component loading and more. The xotcl home page is: http://www.xotcl.org/ [ Team LiB ]
[ Team LiB ]
Notes
The final VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTEREDsection of this chapter touches on a variety of features of the namespace facility.
However, because of the default behavior of packages, there may not be anything that matches foo::* after the package require. Instead, there are entries in the auto_index array that will be used to load those procedures when you first use them. The auto loading mechanism is described in Chapter 12. To account for this, Tcl calls out to a hook procedure called auto_import. This default implementation of this procedure searches auto_index and forcibly loads any pending procedures that match the import pattern. Packages like [incr Tcl] exploit this hook to implement more elaborate schemes. The auto_import hook was first introduced in Tcl 8.0.3.
Namespaces and
uplevel
Namespaces affect the Tcl call frames just like procedures do. If you walk the call stack with info level, the namespace frames are visible. This means that you can get access to all
variables with uplevel and upvar. Level #0 is still the absolute global scope, outside any namespace or procedure. Try out Call_Trace from Example 13-5 on page 190 on your code that uses namespaces to see the effect.
Naming Quirks
When you name a namespace, you are allowed to have extra colons at the end. You can also have two or more colons as the separator between namespace name components. These rules make it easier to assemble names by adding to the value returned from namespace current. These all name the same namespace:
The name of the global namespace can be either :: or the empty string. This follows from the treatment of :: in namespace names. When you name a variable or command, a trailing :: is significant. In the following command a variable inside the ::foo::bar namespace is modified. The variable has an empty string for its name!
If you want to embed a reference to a variable just before two colons, use a backslash to turn off the variable name parsing before the colons:
Miscellaneous
You can remove names you have imported:
You can even move a procedure into another namespace with rename:
[ Team LiB ]
[ Team LiB ]
In spite of all the changes to support Unicode, there are few changes visible to the Tcl script writer. Scripts written for Tcl 8.0 and earlier continue to work fine with Tcl 8.1 and later versions. You only need to modify scripts if you want to take advantage of the features added to support internationalization. This chapter begins with a discussion of what a character set is and why different codings are used to represent them. It concludes with a discussion of message catalogs. [ Team LiB ]
[ Team LiB ]
European UNREGISTERED alphabets include accentedPDF CONVERTER and THETA-SOFTWARE VERSION OF CHM TO characters like , , By . The ISO Latin-1 encoding is a superset of ASCII that encodes 256 characters. It shares the ASCII encoding in values 0 through 127 and uses the "high half" of the encoding space to represent accented characters as well as special characters like . There are several ISO Latin encodings to handle different alphabets, and these share the trick of encoding ASCII in the lower half and other characters in the high half. You might see these encodings referred to as iso8859-1 , iso8859-2 , and so on.
Asian character sets are simply too large to fit into 8-bit encodings. There are a number of 16-bit encodings for these languages. If you work with these, you are probably familiar with the "Big 5" or ShiftJIS encodings. Unicode is an international standard character set encoding. There are both 16-bit Unicode and 32-bit Unicode standards, but Tcl and just about everyone else use the 16-bit standard. Unicode has the important property that it can encode all the important character sets without conflicts and overlap. By converting all characters to the Unicode encoding, Tcl can work with different character sets simultaneously. As of 8.4, Tcl is compliant with Unicode v3.1. For more information on Unicode, see http://www.unicode.org/
The "cp" is short for "code page," the term that Windows uses to refer to different encodings. On my Unix system, the system encoding is iso8859-1 .
But this is not a good idea. It immediately changes how Tcl passes strings to your operating system, and it is likely to leave Tcl in an unusable state. Tcl automatically determines the system encoding for you. Don't bother trying to set it yourself. The encoding names command lists all the encodings that Tcl knows about. The encodings are kept in files stored in the encoding directory under the Tcl script library. They are loaded automatically the first time you use an encoding. [View full width] lsort [encoding names] => ascii big5 cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp737 cp775 cp850 cp852 cp855 cp857 cp860 cp861 cp862 cp863 cp864 cp865 cp866 cp869 cp874 cp932 cp936 cp949 cp950 dingbats euc-cn euc-jp euc-kr gb12345 gb1988 gb2312 identity iso2022 iso2022-jp iso2022-kr iso8859-1 iso8859-2 iso8859-3 iso8859-4 iso8859-5 iso8859-6 iso8859-7 iso8859-8 iso8859-9 jis0201 jis0208 jis0212 ksc5601 macCentEuro macCroatian macCyrillic macDingbats macGreek macIceland macJapan macRoman macRomania macThai macTurkish macUkraine shiftjis symbol unicode utf-8
The encoding names reflect their origin. The "cp" refers to the "code pages" that Windows uses to manage encodings. The "mac" encodings come from the Macintosh. The "iso," "euc," "gb," and "jis" encodings come from various standards bodies.
fconfigure
The conversion to Unicode happens automatically in the Tcl C library. When Tcl reads and writes files, it translates from the current system encoding into Unicode. If you have files in different encodings, you can use the fconfigure command to set the encoding. For example, to read a file in the standard Russian encoding (iso8859-7 ):
set in [open README.russian] fconfigure $in -encoding iso8859-7 Example 15-1 shows a simple utility I use in exmh , [*] a MIME-aware mail reader. MIME has its own convention for specifying the character set encoding of a mail message that differs slightly from Tcl's naming convention. The procedure launders the name and then sets the encoding. Exmh was already aware of MIME character sets, so it could choose fonts for message display. Adding this procedure and adding two calls to it was all I had to do to adapt exmh to Unicode.
[*]
The exmh home page is http://www.beedub.com/exmh/ . It is a wonderful tool that helps me manage tons of email. It is written in Tcl/Tk, of course, and relies on the MH mail system, which limits it to UNIX.
If you want to read a data file and suppress all character set transformations, use the binary encoding:
Under the binary encoding, Tcl reads in each 8-bit byte and stores it into the lower half of a 16-bit Unicode character with the high half set to zero. During binary output, Tcl writes out the lower byte of each Unicode character. You can see that reading in binary and then writing it out doesn't change any bits. Watch out if you read something in one encoding and then write it out in binary. Any information in the high byte of the Unicode character gets lost! Tcl actually handles the binary encoding more efficiently than just described, but logically the previous description is still accurate. As described in Chapter 47 , Tcl can manage data in several forms, not just strings. When you read a file in binary format, Tcl stores the data as a ByteArray that is simply 8 bits of data in each byte. However, if you ask for this data as a string (e.g., with the puts command), Tcl automatically converts from 8-bit bytes to 16-bit Unicode characters by setting the high byte to all zeros. The binary command also manipulates data in ByteArray format. If you read a file with the binary encoding and then use the binary command to process the data, Tcl will keep the data in an efficient form. The string command also understands the ByteArray format, so you can do operations like string length , string range , and string index on binary data without suffering the conversion cost from a ByteArray to a UTF-8 string.
or
fconfigure $input -encoding binary set unicode [encoding convertfrom gb12345 [read $input]]
In general, you can lose information when you go from Unicode to any other encoding, so you ought to be aware of the limitations of the encodings you are using. In particular, the binary encoding may not preserve your data if it starts out from an arbitrary Unicode string. Similarly, an encoding like iso8859-2 may simply not have a representation of a given Unicode character.
encoding convertfrom ? encoding ? data encoding convertto ? encoding ? string encoding names
Converts binary data from the specified encoding , which defaults to the system encoding, into Unicode. Converts string from Unicode into data in the encoding format, which defaults to the system encoding. Returns the names of known encodings.
UNREGISTERED VERSION encoding ? Queries or change the By THETA-SOFTWARE encoding system ? OF CHM TO PDF CONVERTER system encoding.
[ Team LiB ]
[ Team LiB ]
Message Catalogs
A message catalog is a list of messages that your application will display. The main idea is that you can maintain several catalogs, one for each language you support. Unfortunately, you have to be explicit about using message catalogs. Everywhere you generate output or display strings in Tk widgets, you need to change your code to go through a message catalog. Fortunately, Tcl uses a nice trick to make this fairly easy and to keep your code readable. Instead of using keys like "message42" to get messages out of the catalog, Tcl just uses the strings you would use by default. For example, instead of this code:
If you have not already loaded your message catalog, or if your catalog doesn't contain a mapping for "Hello, World!", then msgcat::mc just returns its argument. Actually, you can define just what happens in the case of unknown inputs by defining your own msgcat::mcunknown procedure, but the default behavior is quite good. The message catalog is implemented in Tcl in the msgcat package. You need to use package require to make it available to your scripts:
In addition, all the procedures in the package begin with "mc," so you can use namespace import to shorten their names further. I am not a big fan of namespace import, but if you use message catalogs, you will be calling the msgcat::mc function a lot, so it may be worthwhile to import it:
Specifying a Locale
A locale identifies a language or language dialect to use in your output. A three-level scheme is used in the locale identifier:
language_country_dialect
The language codes are defined by the ISO-3166 standard. For example, "en" is English and "es" is Spanish. The country codes are defined by the ISO-639 standard. For example, US is for the United States and UK is for the United Kingdom. The dialect is up to you. The country and dialect parts are optional. Finally, the locale specifier is case insensitive. The following examples are all valid locale specifiers:
Users can set their initial locale with the LANG and LOCALE environment variables. If there is no locale information in the environment, then the "c" locale is used (i.e., the C programming language.) You can also set and query the locale with the msgcat::mclocale procedure:
The msgcat::mcpreferences procedure returns a list of the user's locale preferences from most specific (i.e., including the dialect) to most general (i.e., only the language). For example:
The locale is a locale description like es or en_US_Scottish. The src-string is the string used as the key when calling msgcat::mc. The dest-string is the result of msgcat::mc when the locale is in force. The msgcat::mcload procedure should be used to load your message catalog files. It expects the files to be named according to their locale (e.g., en_US_Scottish.msg), and it binds the message catalog to the current namespace. The msgcat::mcload procedure loads files that match the msgcat::mcpreferences and have the .msg suffix. For example, with a locale of en_UK_Scottish, msgcat::mcload would look for
these files:
The standard place for message catalog files is in the msgs directory below the directory containing a package. With this arrangement you can call msgcat::mcload as shown below. The use of info script to find related files is explained on page 192.
The message catalog file is sourced, so it can contain any Tcl commands. You might find it convenient to import the msgcat::mcset procedure. Be sure to use -force with namespace import because that command might already have been imported as a result of loading other message catalog files. Example 15-3 shows three trivial message catalog files:
## en_US.msg namespace import -force msgcat::mcset mcset en_US Hello Hello_en_US mcset en_US Goodbye Goodbye_en_US # end of en_US.msg ## en_US_Texan.msg namespace import -force msgcat::mcset mcset en_US_Texan Hello Howdy! # end of en_US_Texan.msg
Assuming the files from Example 15-3 are all in the msgs directory below your script, you can load all these files with these commands:
msgcat::mclocale en_US_Texan msgcat::mcload [file join [file dirname [info script]] msgs]
If the dialect does not specify a mapping, then the country mapping is checked:
What happens is that msgcat::mcset and msgcat::mc are sensitive to the current Tcl namespace. Namespaces are described in detail in Chapter 14. If the foo package loads its message catalog while inside the foo namespace, then any calls to msgcat::mc from inside the foo namespace will see those definitions. In fact, if you call msgcat::mc from inside any namespace, it will find only message catalog definitions defined from within that namespace. If you want to share message catalogs between namespaces, you will need to implement your own version of msgcat::mcunknown that looks in the shared location. Example 15-4 shows a version that looks in the global namespace before returning the default string.
unset insideUnknown return $result } else { # Being called because the message isn't found # in the global namespace return $src } }
msgcat::mcload directory
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
after 500
The after command treats its arguments like eval; if you give it extra arguments, it concatenates them to form a single command. If your argument structure is important, use list to build the command. The following example always works, no matter what the value of myvariable is:
The return value of after is an identifier for the registered command. You can cancel this command with the after cancel operation. You specify either the identifier returned from after, or the command string. In the latter case, the event that matches the command string exactly is canceled. Table 16-1 summarizes the after command:
after milliseconds after ms arg ? arg...? after cancel id after cancel command after idle command after info ?id?
Pauses for milliseconds. Concatenates the args into a command and executes it after ms milliseconds. Immediately returns an ID. Cancels the command registered under id. Cancels the registered command. Runs command at the next idle moment. Returns a list of IDs for outstanding after events, or the command associated with id.
[ Team LiB ]
[ Team LiB ]
You should check for end of file in your read handler because it will be called when end of file occurs. It is important to close the channel inside the handler because closing the channel automatically unregisters the handler. If you forget to close the channel, your read event handler will be called repeatedly. Example 16-1 shows a read event handler. A pipeline is opened for reading and its command executes in the background. The Reader command is invoked when data is available on the pipe. When end of file is detected a variable is set, which signals the application waiting with vwait. Otherwise, a single line of input is read and processed. The vwait command is described on the next page. Example 24-1 on page 378 also uses fileevent to read from a pipeline.
} gets $pipe line # Process the line here... } set pipe [open "|some command"] fileevent $pipe readable [list Reader $pipe] vwait done
There can be at most one read handler and one write handler for an I/O channel. If you register a handler and one is already registered, then the old registration is removed. If you call fileevent without a command argument, it returns the currently registered command, or it returns the empty string if there is none. If you register the empty string, it deletes the current file handler. Table 16-2 summarizes the fileevent command.
[ Team LiB ]
Waiting with vwait causes Tcl to enter the event loop. Tcl will process events until the variable x is modified. The vwait command completes when some Tcl code runs in response to an event and modifies the variable. In this case the event is a timer event, and the Tcl code is simply:
set x 1
In some cases vwait is used only to start the event loop. Example 16-2 sets up a file event handler for stdin that will read and execute commands. Once this is set up, vwait is used to enter the event loop and process commands until the input channel is closed. The process exits at that point, so the vwait variable Stdin(wait) is not used:
[ Team LiB ]
[ Team LiB ]
[View full width] fconfigure stdin UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE => -blocking 1 -buffering none -buffersize 4096 -encoding iso8859-1 -eofchar {} -translation lf
Table 16-3 summarizes the properties controlled by fconfigure, not including properties for serial lines.
-translation End of line translation: auto, lf, cr, crlf, binary. -peername -peerport Sockets only. IP address of remote host. Sockets only. Port number of remote host.
Serial lines have many additional properties. Before Tcl 8.4, you could only control the baud rate, parity and number of bits using the -mode property. Many new properties for serial line control were added in Tcl 8.4. Table 16-4 lists the serial line properties set by fconfigure.
Format: baud,parity,data,stop. Returns a list of two integers representing the current number of bytes in the input and output queues. Tcl 8.4. Specifies the timeout in milliseconds for blocking reads. Tcl 8.4. Sets up the handshake output lines. Tcl 8.4. Returns the current serial line status. Tcl 8.4. Specifies the software handshake characters. Tcl 8.4. Specifies one of rtscts, xonxoff or (Windows only) dtrdsr. Tcl 8.4.
-pollinterval Sets the maximum time for polling of fileevents (Windows only.) Tcl 8.4. -sysbuffer Specifies the size of system buffers for a serial channel. (Windows only.) Tcl 8.4.
Nonblocking I/O
By default, I/O channels are blocking. A gets or read will wait until data is available before returning. A puts may also wait if the I/O channel is not ready to accept data. This behavior is all right if you are using disk files, which are essentially always ready. If you use pipelines or network sockets, however, the blocking behavior can hang up your application. The fconfigure command can set a channel into nonblocking mode. A gets or read command may return immediately with no data. This occurs when there is no data available on a socket or pipeline. A puts to a nonblocking channel will accept all the data and buffer it internally. When the underlying device (i.e., a pipeline or socket) is ready, then Tcl automatically writes out the buffered data. Nonblocking channels are useful because your application can do something else while waiting for the I/O channel. You can also manage several nonblocking I/O channels at once. Nonblocking channels should be used with the fileevent command described earlier. The following command puts a channel into nonblocking mode:
It is not strictly necessary to put a channel into nonblocking mode if you use fileevent. However, if the channel is in blocking mode, then it is still possible for the gets or read done by your fileevent procedure to block. For example, an I/O channel might have some data ready, but not a complete line. In this case, a gets would block, unless the channel is nonblocking. Perhaps the best motivation for a nonblocking channel is the buffering behavior of a nonblocking puts. You can even close a channel that has buffered data, and Tcl will automatically write out the buffers as the channel becomes ready. For these reasons, it is common to use a nonblocking channel with fileevent. Example 16-3 shows a fileevent handler for a nonblocking channel. As described above, the gets may not find a complete line, in which case it doesn't read anything and returns -1.
fconfigure $pipe -blocking 0 proc Reader { pipe } { global done if {[eof $pipe]} { catch {close $pipe} set done 1 return } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE if {[gets $pipe line] < 0} { # We blocked anyway because only part of a line # was available for input } else { # Process one line } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE } vwait done
Buffering
By default, Tcl buffers data, so I/O is more efficient. The underlying device is accessed less frequently, so there is less overhead. In some cases you may want data to be visible immediately and buffering gets in the way. The following turns off all buffering:
Full buffering means that output data is accumulated until a buffer fills; then a write is performed. For reading, Tcl attempts to read a whole buffer each time more data is needed. The read-ahead for buffering will not block. The -buffersize parameter controls the buffer size:
Line buffering is used by default on stdin and stdout. Each newline in an output channel causes a write operation. Read buffering is the same as full buffering. The following command turns on line buffering:
On UNIX, text lines end with a newline character (\n). On Macintosh they end with a carriage return (\r). On Windows they end with a carriage return, newline sequence (\r\n). Network sockets also use the carriage return, newline sequence. By default, Tcl accepts any of these, and the line terminator can even change within a channel. All of these different conventions are converted to the UNIX style so that once read, text lines always end with a newline character (\n). Both the read and gets commands do this conversion. By default, text lines are generated in the platform-native format during output. The default behavior is almost always what you want, but you can control the translation with fconfigure. Table 16-5 shows settings for -translation:
In Tcl 8.4 the end-of-file character trick is used by Tcl_EvalFile and source to allow Tclkit and other tools to append non-script data to script files. This is enabled by default, and should not normally interfere with your scripts.
Serial Devices
The -mode attribute specifies the baud rate, parity mode, the number of data bits, and the number of stop bits:
Tcl 8.4 added the enhanced control of serial channels for Windows and Unix systems. The options are listed in Table 16-4. Windows has some special device names that always connect you to the serial line devices when you use open. They are com1 through com9. To access com devices above 9, use this form: {\\.\comXX}. The Windows system console is named con. The Windows null device is UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE nul. UNIX has names for serial devices in /dev. The serial devices are /dev/ttya, /dev/ttyb, and so on. The system console is /dev/console. The current terminal is /dev/tty. The null device is /dev/null. Macintosh needs a special command to open serial devices. This is provided by a third-party UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE extension that you can find at the Tcl Resource Center under: http://www.tcl.tk/resource/software/extensions/macintosh/
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
The Scotty Tcl extension provides access to other network protocols like UDP, DNS, and RPC. It also supports the SNMP network management protocol and the MIB database associated with SNMP. Scotty is a great extension package that is widely used for network management applications. It is a C-level extension, so you have to compile it yourself or find a binary distribution. Its home page is: http://wwwsnmp.cs.utwente.nl/~schoenw/scotty/
SMTP server. Accept incoming email via SMTP. URI manipulation. Package for parsing URLs. There is good on-line documentation for these packages at: http://tcllib.sourceforge.net/tcllib/doc/
HTTP
The Tcl distribution includes an HTTP client, which is described on page 251. You don't need to add tcllib to get this. In addition, there is a nice web server built in Tcl, which is the topic of Chapter 18. [ Team LiB ]
[ Team LiB ]
Client Sockets
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
A client opens a socket by specifying the host address and port number for the server of the socket. The host address gives the network location (i.e., which computer), and the port selects a particular server from all the possible servers that may be running on that host. For example, HTTP servers typically use port 80, while FTP servers use port 20. The following example shows how to open a client socket to a Web server:
There are two forms for host names. The previous example uses a domain name: www.tcl.tk. You can also specify raw IP addresses, which are specified with four dot-separated integers (e.g., 192.220.75.86). A domain name is mapped into a raw IP address by the system software, and it is almost always a better idea to use a domain name in case the IP address assignment for the host changes. This can happen when hosts are upgraded or they move to a different part of the network. Some systems also provide symbolic names for well-known port numbers. For example, instead of using 20 for the FTP service, you can use ftp. On UNIX systems, the well-known port numbers are listed in the file named /etc/services.
Ordinarily the address and port on the client side are chosen automatically. If your computer has multiple network interfaces, you can select one with the -myaddr option. The address value can be a domain name or an IP address. If your application needs a specific client port, it can choose one with the -myport option. If the port is in use, the socket command will raise an error. The -async option causes connection to happen in the background, and the socket command returns immediately. The socket becomes writable when the connection completes, or fails. You can use fileevent to get a callback when this occurs. This is shown in Example 17-1. If you use the socket before the connection completes, and the socket is in blocking mode, then Tcl automatically blocks and waits for the connection to complete. If the socket is in nonblocking mode, attempts to use the socket return immediately. The gets and read commands would return -1, and fblocked would return 1 in this situation. In some cases, it can take a long time to open the connection to the server. Usually this occurs when the server host is down, and it may take longer than you want for the connection to time
out. The following example sets up a timer with after so that you can choose your own timeout limit on the connection:
[ Team LiB ]
[ Team LiB ]
Server Sockets
UNREGISTERED VERSION OF CHM TOclients. The way this works is that the socket command PDF CONVERTER By THETA-SOFTWARE A TCP server socket allows multiple
creates a listening socket, and then new sockets are created when clients make connections to the server. Tcl takes care of all the details and makes this easy to use. You simply specify a port number and give the socket command a callback to execute when a client connects to your server socket. The callback is just a Tcl command. A simple example is shown below:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 17-2 Opening a server socket
set listenSocket [socket -server Accept 2540] proc Accept {newSock addr port} { puts "Accepted $newSock from $addr port $port" } vwait forever
The Accept command is the callback made when clients connect to the server. Tcl adds additional arguments to the callback before it calls it. The arguments are the new socket connection, and the host and port number of the remote client. In this simple example, Accept just prints out its arguments. The vwait command puts Tcl into its event loop so that it can do the background processing necessary to accept connections. The vwait command will wait until the forever variable is modified, which won't happen in this simple example. The key point is that Tcl processes other events (e.g., network connections and other file I/O) while it waits. If you have a Tk application (e.g., wish), then it already has an event loop to handle window system events, so you do not need to use vwait. The Tcl event loop is discussed on page 227.
The last argument to the socket command is the server's port number. For your own unofficial servers, you'll need to pick port numbers higher than 1024 to avoid conflicts with existing services. UNIX systems prevent user programs from opening server sockets with port numbers less than 1024. If you use 0 as the port number, then the operating system will pick the listening port number for you. You must use fconfigure to find out what port you have:
[ Team LiB ]
[ Team LiB ]
THETA-SOFTWARE
The echo server accepts connections from clients. It reads data from the clients and writes that data back. The example uses fileevent to wait for data from the client, and it uses fconfigure to adjust the buffering behavior of the network socket. You can use Example 17-3 as a template for more interesting services. The Echo_Server procedure opens the socket and saves the result in echo(main). When this socket is closed later, the server stops accepting new connections but existing connections won't be affected. If you want to experiment with this server, start it and wait for connections like this:
The EchoAccept procedure uses the fconfigure command to set up line buffering. This means
that each puts by the server results in a network transmission to the client. The importance of this will be described in more detail later. A complete description of the fconfigure command is given in Chapter 16. The EchoAccept procedure uses the fileevent command to register a procedure that handles I/O on the socket. In this example, the Echo procedure will be called whenever the socket is readable. Note that it is not necessary to put the socket into nonblocking mode when using the fileevent callback. The effects of nonblocking mode are discussed on page 232. EchoAccept saves information about each client in the echo array. This is used only to print out a message when a client closes its connection. In a more sophisticated server, however, you may need to keep more interesting state about each client. The name of the socket provides a convenient handle on the client. In this case, it is used as part of the array index. The Echo procedure first checks to see whether the socket has been closed by the client or there is an error when reading the socket. The if expression only performs the gets if the eof does not return true:
Closing the socket automatically clears the fileevent registration. If you forget to close the socket upon the end of file condition, the Tcl event loop will invoke your callback repeatedly. It is important to close it when you detect end of file.
In the normal case, the server simply reads a line with gets and then writes it back to the client with puts. If the line is "quit," then the server closes its main socket. This prevents any more connections by new clients, but it doesn't affect any clients that are already connected. Example 17-4 shows a sample client of the Echo service. The main point is to ensure that the socket is line buffered so that each puts by the client results in a network transmission. (Or, more precisely, each newline character results in a network transmission.) If you forget to set line buffering with fconfigure, the client's gets command will probably hang because the server will not get any data; it will be stuck in buffers on the client. [ Team LiB ]
[ Team LiB ]
The Http_Open procedure uses regexp to pick out the server and port from the URL. This regular expression is described in detail on page 159. The leading http:// is optional, and so is the port number. If the port is left off, then the standard port 80 is used. If the regular expression matches, then a socket command opens the network connection. The protocol begins with the client sending a line that identifies the command (GET), the path, and the protocol version. The path is the part of the URL after the server and port specification. The rest of the request is lines in the following format:
key: value
The Host identifies the server, which supports servers that implement more than one server name. The User-Agent identifies the client program, which is often a browser like Netscape Navigator, Mozilla, or Internet Explorer. The key-value lines are terminated with a blank line. This data is flushed out of the Tcl buffering system with the flush command. The server will respond by sending the URL contents back over the socket. This is described shortly, but first we consider proxies.
Proxy Servers
A proxy is used to get through firewalls that many organizations set up to isolate their network from the Internet. The proxy accepts HTTP requests from clients inside the firewall and then forwards the requests outside the firewall. It also relays the server's response back to the client. The protocol is nearly the same when using the proxy. The difference is that the complete URL is passed to the GET command so that the proxy can locate the server. Example 17-6 uses a proxy if one is defined:
The Http_Head procedure uses Http_Open to contact the server. The HttpHeader procedure is registered as a fileevent handler to read the server's reply. A global array keeps state about each operation. The URL is used in the array name, and upvar is used to create an alias to the name (upvar is described on page 92):
You cannot use the upvar alias as the variable specified to vwait. Instead, you must use the actual name. The backslash turns off the array reference in order to pass the name of the array element to vwait, otherwise Tcl tries to reference url as an array:
vwait $url\(status)
The HttpHeader procedure checks for special cases: end of file, an error on the gets, or a short read on a nonblocking socket. The very first reply line contains a status code from the server that is in a different format than the rest of the header lines:
code message
The code is a three-digit numeric code. 200 is OK. Codes in the 400's and 500's indicate an error. The codes are explained fully in RFC 1945 that specifies HTTP 1.0. The first line is saved with the key http:
The rest of the header lines are parsed into key-value pairs and appended onto state(headers). This format can be used to initialize an array:
When HttpHeader gets an empty line, the header is complete and it sets the state(status) variable, which signals Http_Head. Finally, Http_Head returns the status to its caller. The complete information about the request is still in the global array named by the URL. Example 17-8 illustrates the use of Http_Head:
if {![string match 2* $header(http)]} { catch {close $sock} if {[info exists header(location)] && [string match 3* $header(http)]} { # 3xx is a redirection to another URL set state(link) $header(location) return [Http_Get $header(location) $query] } return -code error $header(http) } # Set up to read the content data switch -glob -- $header(content-type) { text/* { # Read HTML into memory fileevent $sock readable [list HttpGetText $url] } default { # Copy content data to a file fconfigure $sock -translation binary set state(filename) [File_TempName http] if [catch {open $state(filename) w} out] { set state(status) error set state(error) $out close $sock return $header(content-type) } set state(fd) $out fcopy $sock $out -command [list HttpCopyDone $url] } } vwait $url\(status) return $header(content-type) }
Http_Get uses Http_Open to initiate the request, and then it looks for errors. It handles redirection errors that occur if a URL has changed. These have error codes that begin with 3. A common case of this error is when a user omits the trailing slash on a URL (e.g., http://www.tcl.tk). Most servers respond with:
If the content-type is text, then Http_Get sets up a fileevent handler to read this data into memory. The socket is in nonblocking mode, so the read handler can read as much data as possible each time it is called. This is more efficient than using gets to read a line at a time. The text will be stored in the state(body) variable for use by the caller of Http_Get. Example 17-10 shows the HttpGetText fileevent handler:
if {[eof $state(sock)]} { # Content complete set state(status) done close $state(sock) } elseif {[catch {read $state(sock)} block]} { set state(status) error lappend state(headers) [list error $block] close $state(sock) UNREGISTERED VERSION OF CHM TO PDF CONVERTER By } else { append state(body) $block } }
THETA-SOFTWARE
The content may be in binary format. This poses a problem for Tcl 7.6 and earlier. A null character will terminate the value, so values with embedded nulls cannot be processed safely by Tcl scripts. Tcl 8.0 supports strings and variable values with arbitrary binary data. Example 17-9 uses fcopy to copy data from the socket to a file without storing it in Tcl variables. This command was introduced in Tcl 7.5 as unsupported0, and became fcopy in Tcl 8.0. It takes a callback argument that is invoked when the copy is complete. The callback gets additional arguments that are the bytes transferred and an optional error string. In this case, these arguments are added to the url argument specified in the fcopy command. Example 17-11 shows the HttpCopyDone callback:
The user of Http_Get uses the information in the state array to determine the status of the fetch and where to find the content. There are four cases to deal with: There was an error, which is indicated by the state(error) element. There was a redirection, in which case, the new URL is in state(link). The client of Http_Get should change the URL and look at its state instead. You can use upvar to redefine the alias for the state array: upvar #0 $state(link) state
There was text content. The content is in state(body). There was another content-type that was copied to state(filename).
The -command argument makes fcopy work in the background. When the copy is complete or an error occurs, the callback is invoked with one or two additional arguments: the number of bytes copied, and, in the case of an error, it is also passed an error string:
fcopy $in $out -command [list CopyDone $in $out] proc CopyDone {in out bytes {error {}} { close $in ; close $out }
With a background copy, the fcopy command transfers data from input until end of file or size bytes have been transferred. If no -size argument is given, then the copy goes until end of file. It is not safe to do other I/O operations with input or output during a background fcopy. If either input or output gets closed while the copy is in progress, the current copy is stopped. If the input is closed, then all data already queued for output is written out. Without a -command argument, the fcopy command reads as much as possible depending on the blocking mode of input and the optional size parameter. Everything it reads is queued for output before fcopy returns. If output is blocking, then fcopy returns after the data is written out. If input is blocking, then fcopy can block attempting to read size bytes or until end of file. The fcopy command had a bug which ignored the encoding on the channels which was corrected in 8.3.4. [ Team LiB ]
[ Team LiB ]
The http::config command is used to set the proxy information, time-outs, and the UserAgent and Accept headers that are generated in the HTTP request. You can specify the proxy host and port, or you can specify a Tcl command that is run to determine the proxy. With no arguments, http::config returns the current settings:
http::config => -accept */* -proxyfilter http::ProxyRequired -proxyhost {} -proxyport {} -useragent {Tcl http client package 2.4}
You can set one or more options: http::config -proxyhost webcache.eng -proxyport 8080 The default proxy filter just returns the -proxyhost and -proxyport values if they are set. You can supply a smarter filter that picks a proxy based on the host in the URL. The proxy filter is called with the hostname and should return a list of two elements, the proxy host and port. If no proxy is required, return an empty list.
http::geturl
The http::geturl procedure does a GET, POST, or HEAD transaction depending on its arguments. By default, http::geturl blocks until the request completes and it returns a token that represents the transaction. As described below, you use the token to get the results of the transaction. If you supply a -command callback option, then http::geturl returns immediately and invokes callback when the transaction completes. The callback is passed the token that represents the transaction.
The leading http:// in the URL is optional. The return value is a token that represents the transaction. There are other http:: commands that return information when passed the token. The token is also the name of an array that contains state about the transaction. Make sure to clean up this array to free memory when you are done: http::cleanup $token If you need to access the array directly, use upvar to create an alias:
-command callback
-progress command
Aborts the request after msec milliseconds have elapsed. Use mime-type as the Content-Type value during a POST operation. If bool is true, a HEAD request is made.
currentsize The current number of bytes transferred. error http meta posterror status totalsize type url An explanation of why the transaction was aborted. The HTTP reply status. A list of the keys and values in the reply header. An explanation of why the transaction was aborted when writing post query data, if any. The current status: pending, ok, eof, or reset. The expected size of the returned data. The content type of the returned data. The URL of the request.
You can take advantage of the asynchronous interface by specifying a command that is called
when the transaction completes. The callback is passed the token returned from http::geturl so that it can access the transaction state:
http::geturl $url -command [list Url_Display $text $url] proc Url_Display {text url token} { upvar #0 $token state # Display the url in text }
You can have http::geturl copy the URL to a file or socket with the -channel option. This is useful for downloading large files or images. In this case, you can get a progress callback so that you can provide user feedback during the transaction. Example 17-12 shows a simple downloading script:
http::formatQuery
If you specify form data with the -query option, then http::geturl does a POST transaction. You need to encode the form data for safe transmission. The http::formatQuery procedure takes a list of keys and values and encodes them in x-www-url-encoded format. Pass this result as the query data:
http::register
and http::unregister
The http::register procedure registers a protocol handler for URL protocols other than HTTP. The http::unregister procedure removes the handler registration. The primary application is UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE to provide secure web access via HTTPS and the TLS extension.
package require tls http::register https 443 ::tls::socket set token [http::geturl https://my.secure.site/]
You can cancel an outstanding transaction with http::reset: http::reset $token This is done automatically when you setup a -timeout with http::config.
http::cleanup
When you are done with the data returned from http::geturl, use the http::cleanup procedure to unset the state variable used to store the data. [ Team LiB ]
[ Team LiB ]
Basic Authentication
Web pages are often password protected. The most common form of this uses a protocol called Basic Authentication, which is not very strong, but easy to implement. With this scheme, the server responds to an HTTP request with a 401 error status and a Www-Authenticate header, which specifies the authentication protocol the server wants to use. For example, the server response can contain the following information:
The realm is meant to be an authentication domain. In practice, it is used in the string that gets displayed to the user as part of the password prompt. For example, a Web browser will display this prompt:
After getting the user name and password from the user, the Web browser tries its HTTP request again. This time it includes an Authorization header that contains the user name and password encoded with base64 encoding. There is no encryption at all - anyone can decode the string, which is why this is not a strong form of protection. The Standard Tcl Library includes a base64 package that has base64::encode and base64::decode procedures. Example 17-13 illustrates the Basic Authentication protocol. It uses the -headers option to http::geturl that lets you pass additional headers in the request.
# Encode username:password and pass this in # the Authorization header set auth [base64::encode \ [lindex $answer 0]:[lindex $answer 1]] set token [http::geturl $url -headers \ [list Authorization "Basic $auth"]] http::wait $token TO PDF CONVERTER By VERSION OF CHM
UNREGISTERED
}
THETA-SOFTWARE
} return $token }
UNREGISTERED VERSION a promptProc argument that is the name of a procedure to call to get the OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 17-13 takes
username and password. This procedure could display a Tk dialog box, or prompt for user input from the terminal. In practice, you probably already know the username and password. In this case, you can skip the initial challengeresponse steps and simply supply the Authorization header on the first request:
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
TclHttpd Architecture
You may find it helpful to read the code to learn more about the features of the server. In this section, there are references to Tcl files in the source, which are in the lib directory of the distribution that is on the CD-ROM. Figure 18-1 shows the basic components of the server. At the core is the Httpd module (httpd.tcl), which implements the server side of the HTTP protocol. The "d" in Httpd stands for daemon, which is the name given to system servers on UNIX. This module manages network requests, dispatches them to the Url module, and provides routines used to return the results to requests.
Figure 18-1. The dotted box represents one application that embeds TclHttpd. Document templates and Application Direct URLs provide direct connections from an HTTP request to your application. You can also implement completely custom URL handlers.
The Url module (url.tcl) divides the Web site into domains, which are subtrees of the URL hierarchy provided by the server. The idea is that different domains may have completely different implementations. For example, the Document domain (doc.tcl) maps its URLs into files and directories on your hard disk, while the Application Direct domain (direct.tcl) maps URLs into Tcl procedure calls within your application. The CGI domain (cgi.tcl) maps URLs onto other programs that compute Web pages.
Suppose you put that file into the directory /tmp/tclhttpd_test. Then you can start the server like this:
The TclHttpd main program, bin/httpd.tcl, may conflict with the main program of your existing application. For those applications that embed Tcl interpreters in a more custom manner, you will need to modify bin/httpd.tcl for use with your application. That script is not UNREGISTEREDand it is well-commented. The key elements are the Httpd_Server call that opens the very big, VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE listening socket for the Web server, and the vwait at the very end that activates the event loop. The rest is all about argument parsing and initializing the various modules that support the server. It is those aspects that may differ for your custom server application. [ Team LiB ]
[ Team LiB ]
Domain Handlers
You can implement new kinds of domains that provide your own interpretation of a URL. This is the most flexible interface available to extend the Web server. You provide a callback that is invoked to handle every request in a domain, or subtree, of the URL hierarchy. The callback interprets the URL, computes the page content, and returns the data using routines from the Httpd module. Example 18-2 defines a simple domain that always returns the same page to every request. The domain is registered with the Url_PrefixInstall command. The arguments to Url_PrefixInstall are the URL prefix and a callback that is called to handle all URLs that match that prefix. In the example, all URLs that have the prefix /simple are dispatched to the SimpleDomain procedure. The SimpleDomain handler illustrates several properties of domain handlers. The sock and suffix arguments to SimpleDomain are appended by Url_Dispatch when it invokes the domain handler. The sock is the socket connection to the client. The suffix parameter is the part of the URL after the prefix. For example, if the server receives a request for the URL /simple/page, then the prefix is /simple and the suffix is /page. The prefix argument is defined when the callback is registered with Url_PrefixInstall. You can specify whatever information you need to pass to the domain handler. In this simple example, we probably don't need the prefix, but if you implement several different URL domains with the same handler, then you can pass in the prefix to distinguish them.
Returning Results
Finally, once the page has been computed, the Httpd_ReturnData procedure is used to return the page to the client. This takes care of the HTTP protocol as well as returning the data. There are three related procedures, Httpd_ReturnFile, Httpd_Error, and Httpd_Redirect. These are summarized in Table 18-1 on page 277. [ Team LiB ]
[ Team LiB ]
Example 18-3 defines /demo as an Application Direct URL domain that is implemented by procedures that begin with Demo. There are just three URLs defined:
/demo /demo/time
/demo/echo
The /demo page displays a hypertext link to the /demo/time page and a simple form that will be handled by the /demo/echo page. This page is static, so there is just one return command in the procedure body. Each line of the string ends with:
You could create an HTML form that had elements named a, b, and c, and specified
/demo/param for the ACTION parameter of the FORM tag. Or you could type the following into your browser to embed the query data right into the URL:
/demo/param?a=5&b=7&c=red&d=%7ewelch&e=two+words
The ? separates the query data from the URL, and each query item is separated by &. In this case, when your procedure is called, a is 5, b is 7, c is red, and the args parameter becomes a list of:
The %7e and the + are special codes for nonalphanumeric characters in the query data. The + becomes a space, and the %xx sequence is replaced by the character with character code xx (e.g., %7e becomes ~). Normally, this encoding is taken care of automatically by the Web browser when it gets data from a form and passes it to the Web server. However, if you type query data directly or format URLs with complex query data in them, then you need to encode special values as we did here. Use the Url_Encode procedure to encode URLs that you put into Web pages. The Web server automatically decodes the values as it makes the assignments to the Application Direct URL procedure parameters. If a parameter does not match the query data, it gets its default value from the procedure definition, or it gets the empty string. Consider this example:
/demo/param?b=5
set in [open $filename] fconfigure $in -translation binary set X [read $in] close $in return $X }
[ Team LiB ]
Document Types
The Document domain (doc.tcl) maps URLs onto files and directories. It provides more ways to extend the server by registering different document type handlers. You can make up new types to support your application. Example 18-5 shows the pieces needed to create a handler for a fictitious document type application/myjunk that is invoked to handle files with the .junk suffix. Use the Mtype_Add procedure to register the mapping from file suffix to document type:
The server finds the document handler in a two-step process. First, the type of a file is determined by its suffix. The mime.types file contains a map from suffixes to MIME types such as text/html or image/gif. This map is controlled by the Mtype module in mtype.tcl. Second, the server checks for a Tcl procedure with the appropriate name:
Doc_mimetype
The matching procedure, if any, is called to handle the URL request. The procedure should use routines in the Httpd module to return data for the request. If there is no matching Doc_mimetype procedure, then the default document handler uses Httpd_ReturnFile and specifies the Content Type based on the file extension. This is the heart of the default document handler:
As another example, the HTML+Tcl templates use the .tml suffix that is mapped to the application/x-tcl-template type. You can find the document handler Doc_application/xtcl-template in doc.tcl. The TclHttpd distribution also includes support for files with a .snmp extension that implements a template-based Web interface to the Scotty SNMP Tcl extension.
[ Team LiB ]
The library directory is where you should put most of your code. The library directory is specified with the -library command line argument, and the server loads all files in the library upon startup. The advantage of putting procedure definitions in the library is that they are defined one time but executed many times. This works well with the Tcl bytecode compiler. The disadvantage is that if you modify procedures in these files, you have to explicitly source them into the server for these changes to take effect. You can restart the server, or you can use the /debug/source URL described on page 282 to reload source files into OF CHM TO PDF UNREGISTERED VERSION the running server. CONVERTER By THETA-SOFTWARE The .tml files are best for variable definitions that you want to share among pages in a directory, or as a staging area for procedures during development. The advantage of putting code into the per-directory .tml files is that changes are picked up immediately with no effort on your part. The server automatically checks if these files are modified and sources them each time it processes your templates. However, using .tml files tends to UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE scatter your code around the URL tree and can make it harder to maintain. I try to put as little code as possible directly in my page.tml template files. It is awkward to put lots of code there, and you cannot share procedures and variable definitions easily with other pages. Instead, my goal is to have only procedure calls in the template files, and put the procedure definitions elsewhere. If you want control structures in your page, such as if and foreach, you may want to use the version of those commands provided by the html package, as described on page 277.
Of course, your Web site is likely to have more pages and a more elaborate structure. For example, you might have several main sections, each with a collection of pages, or even a three-level hierarchy of pages. Example 18-7 shows another simple data structure to define a two-level structure. The site(sections) variable stores the names and URLs of the main sections. For each section, there is an element of site that lists the pages in that section. Only the About section is shown in the example:
set site(sections) { About /about Products /products Support /support } set site(About) { Company company.html Contacts contacts.html Directions directions.html }
In practice, you may want to include more information in your data structure to help you generate HTML. For example, if you have graphics for the main sections, you may need to record their size. Whatever you need, collect it into your data structures and then generate the HTML from procedures. You can quickly give your whole site a face lift with new graphics by changing the template procedures that generate your pages. In contrast, if you hand-code all your pages, it can take months instead of days. Example 18-8 shows a sample template file for the one-level structure shown in Example 18-6. Each page includes two commands, SitePage and SiteFooter, that generate HTML for the navigational part of the page. Between these commands is regular HTML for the page content:
The SitePage procedure takes the page title as an argument. It generates HTML to implement a standard navigational structure. Example 18-9 has a simple implementation of SitePage:
append html $sep if {[string compare $label $title] == 0} { append html "$label" } else { append html "<a href='$url'>$label</a>" } set sep " | " } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE return $html }
The foreach loop that computes the simple menu of links turns out to be useful in many places. Example 18-10 splits out the loop and uses it in a new version of SitePage along with UNREGISTERED VERSION OF CHM version ofCONVERTERcreates a left column for the TO PDF the templates By THETA-SOFTWARE the SiteFooter procedure. This navigation and a right column for the page content. The example also puts a few more visual elements (e.g., page background color) into the site array so you can easily maintain them:
foreach {label url} $list { if {[string compare $page(url) $url] == 0} { append html $s$label } else { append html "$s<a href='$url'>$label</a>" } set s $sep } return $html }
There are many other applications for "macros" that make repetitive HTML coding chores easy. For example, take the SiteLink procedure call in Example 18-8. Instead of hand-coding the <A> tag with the link to /ordering.html, the page uses the SiteLink procedure to format the link with a consistent label for the link. Using the procedure also means that the page will automatically get updated if you change the URL associated with the ordering page by modifying site(pages). Example 18-11 shows SiteLink:
array set title { Home Home Order "Ordering Computers" Setup "New Machine Setup" AddUser "Adding a New User" Network "Network Addresses" }
[SitePage $title(Order)]
The .tml pages are a good place to define the variables because the definitions are shared by all pages in that directory, and in any subdirectories. Also, the definitions in the per-directory .tml override any definitions that come from the top-level .tml file at the root of your URL tree. Changing the definition of the variable in the .tml file immediately updates all the pages that share it. UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE The main drawback to variable references is the clash with $ in pricing. If you put $10 into a page.tml file, it will raise an error (unless the variable 10 is defined). It turns out that you want to generate prices from some database anyway, so you should avoid hard coding prices into your pages anyway. It is much better to put [price T-shirt] or $price(T-shirt) into your page than $10, although you TO do that, just quote the $ with a backslash, \$10. UNREGISTERED VERSION OFifCHMmust PDF CONVERTER By THETA-SOFTWARE [ Team LiB ]
[ Team LiB ]
Form Handlers
HTML forms and form-handling programs go together. The form is presented to the user on the client machine. The form handler runs on the server after the user fills out the form and presses the submit button. The form presents input widgets like radiobuttons, checkbuttons, selection lists, and text entry fields. Each of these widgets is assigned a name, and each widget gets a value based on the user's input. The form handler is a program that looks at the names and values from the form and computes the next page for the user to read. CGI is a standard way to hook external programs to Web servers for the purpose of processing form data. CGI has a special encoding for values so that they can be transported safely. The encoded data is either read from standard input or taken from the command line. The CGI program decodes the data, processes it, and writes a new HTML page on its standard output. Chapter 3 describes writing CGI scripts in Tcl. TclHttpd provides alternatives to CGI that are more efficient because they are built right into the server. This eliminates the overhead that comes from running an external program to compute the page. Another advantage is that the Web server can maintain state between client requests in Tcl variables. If you use CGI, you must use some sort of database or file storage to maintain information between requests.
The email message is designed to be easily processed by a Tcl program. You can use a mail processor like procmail to filter all mail with a given Subject or To field to a program for processing. It is easy to write a script that strips the headers, defines a data procedure, and uses eval to process the message body. Whenever you send data via email, if you format it with Tcl list structure, you can process it quite easily. The basic structure of such a mail reader procedure is shown in Example 18-14:
The raw eval in the mail handler is dangerous. It will be fine if the only source of email to that program is the /mail/forminfo URL handler. However, an attacker could send you an email that results in arbitrary Tcl commands being evaluated by your mail processor. The safe way to process the email is with a safe interpreter, which is described in Chapter 19. Example 18-15 adds just a few commands to create a safe interpreter for processing the incoming data. The data command is evaluated in the trusted interpreter by the alias mechanism. All other commands in the email are evaluated in the safe interpreter, and any malicious commands simply raise Tcl errors but cause no harm:
# Assume the mail message is on standard input set X [read stdin] # Strip off the mail headers, when end with a blank line if {[regsub {.*?\n\ndata} $X {data} X] != 1} { error "Malformed mail message" } proc data {fields} { foreach {name value} $fields { # Do something } } # Create the safe interpreter set i [interp create -safe] # Link the data command in the safe interpreter to the # data procedure in this interpreter interp alias $i data {} data # Process the message in the safe interpreter interp eval $i $X
Self-Posting Forms
This section illustrates a self-posting form. This is a form on a page that posts the form data to back to the same page. The page embeds a Tcl command to check its own form data. Once the data is correct, the page triggers a redirect to the next page in the flow. This is a powerful technique that I use to create complex page flows using templates. Of course, you need to save the form data at each step. You can put the data in Tcl variables, use the data to control your application, or store it into a database. TclHttpd comes with a Session module, which is one way to manage this information. For details, you should scan the session.tcl file in the distribution. Example 18-16 shows the Form_Simple procedure that generates a simple self-checking form.
Its arguments are a unique ID for the form, a description of the form fields, and the URL of the next page in the flow. The field description is a list with three elements for each field: a required flag, a form element name, and a label to display with the form element:
The Form_Simple procedure does two things at once: it computes the HTML form, and it also checks if the required fields are present. It uses some procedures from the html module to generate form elements that retain values from the previous page. If all the required fields are present, then it triggers a redirect by calling Doc_Redirect. Example 18-17 shows a page template that calls Form_Simple with the required field description:
name="name" value="value"
The value is the value of form element name based on incoming query data, or just the empty string if the query value for name is undefined. As a result, the form can post to itself and retain values from the previous version of the page. It is used like this:
The html::checkValue and html::radioValue procedures are similar to html::formValue, but are designed for checkbuttons and radio buttons. The html::select procedure formats a selection list and highlights the selected values. The html package includes a versions of foreach and if that are designed for use in templates. These commands perform a subst on their body instead of evaluating it. This lets you put HTML with variable and command references into the body to build up results. Example 18-18 shows the html::foreach procedure used to generate a table with several rows. Note that you don't have to worry about the $ in the prices because they are inside the braces of the html::foreach value list:
[ Team LiB ]
[ Team LiB ]
Programming Reference
This section summarizes many of the more useful functions defined by the server. These tables are not complete, however. You are encouraged to read through the code to learn more about the features offered by the server. A simple naming convention is used to distinguish procedures that are private to a file (e.g., HttpdEvent) and procedures that are meant to be used by other modules or by the main application (e.g., Httpd_Server). The underscore after the module prefix indicates that the procedure is public. This section does not detail the ncgi and html packages, which are quite useful to the TclHttpd programmer. There are doc files that come with tcllib, and you can find man pages for the tcllib packages in the www.tcl.tk manual section. Table 18-1 shows Httpd functions used when returning pages to the client.
Httpd_ReturnData sock type data Httpd_ReturnFile sock type file Httpd_Redirect newurl sock Httpd_SelfUrl url
Table 18-2 summarizes a few useful procedures provided by the Url module (url.tcl). The Url_DecodeQuery is used to decode query data into a Tcl-friendly list. The Url_Encode procedure is useful when encoding values directly into URLs. URL encoding is discussed in more detail on page 262
Url_DecodeQuery query
Decodes a www-url-encoded query string and returns a name, value list. Depreciated. This is equivalent to ncgi::nvlist, which takes no arguments. Returns value encoded according to the www-url-encoded standard. Registers handler as the handler for all URLs that begin with
Url_Encode value
UNREGISTERED ?-thread bool? handler VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE prefix. The handler is invoked with two additional arguments:
?-callback cmd? ?readpost bool? sock, the handle to the client, and suffix, the part of the URL after prefix. Use -thread 1 to have the handler run in a worker thread. Use -callback cmd to register a callback invoked at the very end of URL processing. Use -readpost 0 to disable pre-reading post data. CHM TO PDF CONVERTER By THETA-SOFTWARE
Url_PrefxInstall prefix
UNREGISTERED VERSION OF
The Doc module procedures for configuration are listed in Table 18-3.
Doc_CheckTemplates how
Doc_IndexFile pattern
Doc_NotFoundPage file
Doc_PublicHtml dirname
The Doc module procedures for generating results are listed in Table 18-4
Generates a 500 response on sock based on the template registered with Doc_ErrorPage. errorInfo is a copy of the Tcl error trace after the error. Generates a 404 response on sock by using the template registered with Doc_NotFoundPage. Performs a subst on the file and return the resulting page on sock. interp specifies an alternate Tcl interpreter.
Doc_NotFound sock
The Doc module also provides procedures for cookies and redirects that are useful in document templates. These are described in Table 18-5.
Doc_SetCookie -name name -value value -path path -domain domain -expires date
Table 18-6 shows the initial elements of the page array that are defined during the processing of a template.
filename The file system pathname of the requested file (e.g., /usr/local/htdocs/tclhttpd/index.html). template The file system pathname of the template file (e.g., /usr/local/htdocs/tclhttpd/index.tml). url root The part of the URL after the server name (e.g., /tclhttpd/index.tml). A relative path from the template file back to the root of the URL tree.
Table 18-7 shows the elements of the env array. These are defined during CGI requests, Application Direct URL handlers, and page template processing:
CONTENT_LENGTH The size of the query data. UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE CONTENT_TYPE DOCUMENT_ROOT GATEWAY_INTERFACE The type of the query data. File system pathname of the document root. Protocol version, which is CGI/1.1.
UNREGISTERED VERSION OF CHM TOheaders from the request. THETA-SOFTWARE HTTP_ACCEPT The Accept PDF CONVERTER By
HTTP_AUTHORIZATION The Authorization challenge from the request. HTTP_COOKIE HTTP_FROM HTTP_REFERER HTTP_USER_AGENT PATH_INFO PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_USER REQUEST_METHOD REQUEST_URI SCRIPT_NAME SERVER_NAME SERVER_PORT SERVER_PROTOCOL SERVER_SOFTWARE [ Team LiB ] The cookie from the request. The From: header of the request. The Referer indicates the previous page. An ID string for the Web browser. Extra path information after the template file. The extra path information appended to the document root. The form query data. The client's IP address. The remote user name specified by Basic authentication. GET, POST, or HEAD. The complete URL that was requested. The name of the current file relative to the document root. The server name, e.g., www.beedub.com. The server's port, e.g., 80. The protocol (e.g., http or https). A software version string for the server.
[ Team LiB ]
Status
The /status URL is implemented in the status.tcl file. The status module implements the display of hit counts, document hits, and document misses (i.e., documents not found). The Status_Url command enables the Application Direct URLs and assigns the top-level URL for the status module. The default configuration file contains this command:
Status_Url /status
/status/notfound Shows miss counts for URLs that users tried to fetch. /status/size /status/text Displays an estimated size of Tcl code and Tcl data used by the TclHttpd program. This is a version of the main status page that doesn't use the graphical histograms of hit counts.
Debugging
The /debug URL is implemented in the debug.tcl file. The debug module has several useful URLs that let you examine variable values and other internal state. It is turned on with this command in the default configuration file:
Debug_Url /debug
Table 18-9 lists the /debug URLs. These URLs often require parameters that you can specify directly in the URL. For example, the /debug/echo URL echoes its query parameters: http://yourserver:port/debug/echo?name=value&name2=val2 Note: The debug URL is active in the default configuration. If it makes you nervous, then delete the call to Debug_Url from the httpdthread.tcl file.
UNREGISTERED VERSIONthat is included PDF CONVERTER By THETA-SOFTWARE The sample URL tree OF CHM TO in the distribution includes the file htdocs/hacks.html.
This file has several small forms that use the /debug URLs to examine variables and source files. It may seem dangerous to have these facilities, but I reason that because my source directories are under my control, it cannot hurt to reload any source files. In general, the library scripts contain only procedure definitions and no global code that might reset state inappropriately. In practice, the ability to tune (i.e., fix bugs) in the running server has proven UNREGISTEREDme on many OF CHM TOlets you evolve your application without restarting it! useful to VERSION occasions. It PDF CONVERTER By THETA-SOFTWARE
/debug/echo
/debug/errorInfo Displays the errorInfo variable along with the server's version number and Webmaster email. Accepts title and errorInfo arguments. /debug/parray /debug/pvalue Displays a global array variable. The name of the variable is specified with the aname parameter. A more general value display function. The name of the variable is specified with the aname parameter. This can be a variable name, an array name, or a pattern that matches several variable names. Raises an error (to test error handling). Any parameters become the error string. Sources a file from either the server's main library directory or the Doc_TemplateLibrary directory. The file is specified with the source parameter.
/debug/raise /debug/source
Example 18-19 shows the implementation of /debug/source. You can see that it limits the files to the main script library and to the script library associated with document templates.
set file [file join $dir $source] if {[file exists $file]} break } set error [catch {uplevel #0 [list source $file]} result] set html "<title>Source $source</title>\n" if {$error} { append html "<H1>Error in $source</H1>\n" append html "<pre>$result<p>$errorInfo</pre>" } else { append html "<H1>Reloaded $source</H1>\n" append html "<pre>$result</pre>" } return $html }
Sending Email
The /mail URL is implemented in the mail.tcl file. The mail module implements various form handlers that email form data. Currently, it is UNIX-specific because it uses /usr/lib/sendmail to send the mail. It is turned on with this command in the default configuration file:
Mail_Url /mail
The Application Direct URLs shown in Table 18-10 are useful form handlers. You can specify them as the ACTION parameter in your <FORM> tags. The mail module provides two Tcl procedures that are generally useful. The MailInner procedure is the one that sends mail. It is called like this:
/mail/formdata
The sendto and from arguments are email addresses. The type is the MIME type (e.g., text/plain or text/html) and appears in a Content-Type header. The body contains the mail
message without any headers. The Mail_FormInfo procedure is designed for use in HTML+Tcl template files. It takes no arguments but instead looks in current query data for its parameters. It expects to find the same arguments as the /mail/forminfo direct URL. Using a template with Mail_FormInfo gives you more control over the result page than posting directly to /mail/forminfo, and is illustrated in Example 18-12 on page 272.
[ Team LiB ]
Quick Start
Unpack the tar file or the zip file, and you can run the server from the httpd.tcl script in the bin directory. On UNIX:
This command will start the Web server on the standard port (80). On UNIX, you need to be root to run a server on this port. By default TclHttpd uses port 8015 instead. If you run it with the -help flag, it will tell you what command line options are available. If you use wish instead of tclsh, then a simple Tk user interface is displayed that shows how many hits the server is getting. On Windows, you can double-click the httpd.tcl script to start the server. It will use wish and display the user interface. Again it will start on port 8015. You will need to create a shortcut that passes the -port argument, or edit the associated configuration file to change this. Configuring the server is described later. Once you have the server running, you can connect to it from your Web browser. Use this URL if you are running on the default (nonstandard) port: http://hostname:8015/ If you are running without a network connection, you may need to specify 127.0.0.1 for the hostname. This is the "localhost" address and will bypass the network subsystem. http://127.0.0.1:8015/
bin/mini - This has a few tiny versions of the server that provide a basic server in about 300 lines of code. Use these as a starting point by modifying the HttpdRespond procedure. bin/test - This has a number of test scripts, including the torture.tcl file that can fetch many URLs at once from a server.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE If you have your own server certificates, put the server.pem file here.
certs - This has sample certificates you can use to test a secure server for https URLs.
config - This contains autoconf support used by C extensions you can build with the server. custom - This is where you put your own custom code. Files here are automatically
UNREGISTERED VERSION OF CHM TO PDF CONVERTER samples. loaded by the server on startup. This contains a few By THETA-SOFTWARE
doc - This has a UNIX-style manual page for how to run the server. htaccess - This has sample access control files. htdocs - This is a sample URL tree that demonstrates the features of the Web server. There is also some documentation there. One directory to note is htdocs/libtml, which is the standard place to put site-specific Tcl scripts used with the Tcl+HTML template facility. lib - This has all the Tcl sources. In general, each file provides a package. You will see the package require commands partly in bin/httpd.tcl and partly in bin/httpdthread.tcl. src - There are a few C source files for a some optional packages. These have been precompiled for some platforms, and you can find the compiled libraries under src/Solaris and src/Linux.
[ Team LiB ]
[ Team LiB ]
Server Configuration
TclHttpd configures itself with two main steps: setting configuration parameters and loading packages. The configuration step uses a configuration file and command line arguments to set basic configuration parameters. The default configuration file is named tclhttpd.rc in the same directory as the start-up script (i.e., bin/tclhttpd.rc). Specify an alternate configuration file with the -config command line argument. You can override the configuration file with additional command line arguments, which are described in Table 18-11. The configuration values from the file and the command line are copied into the Config Tcl array. Package loading is split into two parts. The main bin/httpd.tcl script loads some core packages. The rest are loaded in the bin/httpdthread.tcl script. The reason for the split is to try to isolate the core of the server from application-specific functions. In addition, in the threaded version of the server, every thread loads and runs the bin/httpdthread.tcl script. You can specify an alternate package loading script with the -main command line argument. For example, to start the server for the document tree under /usr/local/htdocs and your own email address as Webmaster, you can execute this command to start the server:
Alternatively, you can put these settings into a configuration file, and start the server with that configuration file:
Parameter Port number. The default is 8015. Server name. The default is [info hostname]. IP address. The default is 0, for "any address". Directory of the root of the URL tree. The default is the htdocs directory. User ID of the TclHttpd process. The default is 50. (UNIX only.)
address UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE -docRoot directory -uid uid -gid gid -webmaster email -config filename -library directory Config(docRoot)
Config(file)
Config(library)
Specifying the IP address is necessary only if you have several network interfaces (or several IP addresses assigned to one network interface) and want the server to listen to requests on a particular network address. Otherwise, by default, the server accepts requests from any network interface.
setuid extension distributed with TclHttpd under the src directory. If either of these facilities is not available, then the attempt to change user ID gracefully fails. See the README file in the src directory for instructions on compiling and installing the extensions found there.
Webmaster Email
The Webmaster email address is used for automatic error reporting in the case of server errors. This is defined in the configuration file with the following command:
Doc_Webmaster $Config(webmaster)
If you call Doc_Webmaster with no arguments, it returns the email address you previously defined. This is useful when generating pages that contain mailto: URLs with the Webmaster address.
Document Root
The document root is the directory that contains the static files, templates, CGI scripts, and so on that make up your Web site. By default, the httpd.tcl script uses the htdocs directory next to the directory containing httpd.tcl. It is worth noting the trick used to locate this directory:
The info script command returns the full name of the http.tcl script, file dirname computes its directory, and file join finds the adjacent directory. The path ../htdocs works with file join on any platform. The default location of the configuration file is found in a similar way:
The configuration file initializes the document root with this call:
Doc_Root $Config(docRoot)
If you need to find out what the document root is, you can call Doc_Root with no arguments and it returns the directory of the document root. If you want to add additional document trees into your Web site, you can do that with a call like this in your configuration file:
The Doc_IndexFile command sets a pattern used to find the index file in a directory. The command used in the default configuration file is:
Doc_IndexFile index.{htm,html,tml,subst}
UNREGISTERED VERSION OF used by the Tcl glob command. By THETA-SOFTWARE them. This pattern will be CHM TO PDF CONVERTER
If you invent other file types with different file suffixes, you can alter this pattern to include The Doc_PublicHtml command is used to define "home directories" on your HTML site. If the URL begins with ~username, then the Web server will look under the home directory of the user for a particular directory. The command in the default configuration file is:
For example, if my home directory is /home/welch, then the URL ~welch maps to the directory /home/welch/public_html. If there is no Doc_PublicHtml command, then this mapping does not occur. You can register two special pages that are used when the server encounters an error and when a user specifies an unknown URL. The default configuration file has these commands:
These files are treated like templates in that they are passed through subst in order to include the error information or the URL of the missing page. These are pretty crude templates compared to the templates described earlier. You can count only on the Doc and Httpd arrays being defined. Look at the Doc_SubstSystemFile in doc.tcl for the truth about how these files are processed.
Document Templates
The template mechanism has two main configuration options. The first specifies an additional library directory that contains your application-specific scripts. This lets you keep your application-specific files separate from the TclHttpd implementation. The command in the default configuration file specifies the libtml directory of the document tree:
You can also specify an alternate Tcl interpreter in which to process the templates. The default is to use the main interpreter, which is named {} according to the conventions described in Chapter 19.
Doc_TemplateInterp {}
Log Files
The server keeps standard format log files. The Log_SetFile command defines the base name of the log file. The default configuration file uses this command:
Log_SetFile /tmp/log$Config(port)_
By default, the server rotates the log file each night at midnight. Each day's log file is suffixed with the current date (e.g., /tmp/logport_990218.) The error log, however, is not rotated, and all errors are accumulated in /tmp/logport_error. The log records are normally flushed every few minutes to eliminate an extra I/O operation on each HTTP transaction. You can set this period with Log_FlushMinutes. If minutes is 0, the log is flushed on every HTTP transaction. The default configuration file contains:
Log_FlushMinutes 1
CGI Directories
You can register a directory that contains CGI programs with the Cgi_Directory command. This command has the interesting effect of forcing all files in the directory to be executed as CGI scripts, so you cannot put normal HTML files there. The default configuration file contains:
Cgi_Directory /cgi-bin
This means that the cgi-bin directory under the document root is a CGI directory. If you supply another argument to Cgi_Directory, then this is a file system directory that gets mapped into the URL defined by the first argument. You can also put CGI scripts into other directories and use the .cgi suffix to indicate that they should be executed as CGI scripts. The cgi.tcl file has some additional parameters that you can tune only by setting some elements of the Cgi Tcl array. See the comments in the beginning of that file for details.
[ Team LiB ]
[ Team LiB ]
Chapter 19. Multiple Interpreters and UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Safe-Tcl
This chapter describes how to create more than one Tcl interpreter in your application. A child interpreter can be made safe so that it can execute untrusted scripts without compromising your application or your computer. Command aliases, hidden commands, and shared I/O UNREGISTEREDenable communication among interpreters. Tcl command described is: interp. channels VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Safe-Tcl was invented by Nathaniel Borenstein and Marshall Rose so that they could send Tcl scripts via email and have the recipient safely execute the script without worry of viruses or other attacks. Safe-Tcl works by removing dangerous commands like exec and open that would let an untrusted script damage the host computer. You can think of this restricted interpreter as a "padded cell" in which it is safe to execute untrusted scripts. To continue the analogy, if the untrusted code wants to do anything potentially unsafe, it must ask permission. This works by adding additional commands, or aliases, that are implemented by a different Tcl interpreter. For example, a safeopen command could be implemented by limiting file space to a temporary directory that is deleted when the untrusted code terminates. The key concept of Safe-Tcl is that there are two Tcl interpreters in the application, a trusted one and an untrusted (or "safe") one. The trusted interpreter can do anything, and it is used for the main application (e.g., the Web browser or email user interface). When the main application receives a message containing an untrusted script, it evaluates that script in the context of the untrusted interpreter. The restricted nature of the untrusted interpreter means that the application is safe from attack. This model is much like user mode and kernel mode in a multiuser operating system like UNIX or Windows/NT. In these systems, applications run in user mode and trap into the kernel to access resources like files and the network. The kernel implements access controls so that users cannot read and write each other's files, or hijack network services. In Safe-Tcl the application implements access controls for untrusted scripts. The dual interpreter model of Safe-Tcl has been generalized in Tcl 7.5 and made accessible to Tcl scripts. A Tcl script can create other interpreters, destroy them, create command aliases among them, share I/O channels among them, and evaluate scripts in them. [ Team LiB ]
[ Team LiB ]
interp alias slave cmd1 master cmd2 arg ... interp create ?-safe? slave interp delete slave interp eval slave cmd args ... interp exists slave interp expose slave cmd interp hide slave cmd interp hidden slave interp invokehidden slave cmd arg ... interp issafe slave interp marktrusted slave interp recursionlimit slave ? limit? interp share master file slave
[ Team LiB ]
Creating Interpreters
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Here is a simple example that creates an interpreter, evaluates a couple of commands in it, and then deletes the interpreter:
In Example 19-1 the interpreter is named foo. Two commands are evaluated in the foo interpreter:
Note that curly braces are used to protect the commands from any interpretation by the main interpreter. The variable a is defined in the foo interpreter and does not conflict with variables in the main interpreter. The set of variables and procedures in each interpreter is completely independent.
interp slaves foo => bar bar2 interp delete bar => interpreter named "bar" not found interp delete {foo bar}
The example creates foo, and then it creates two children of foo. The first one is created by foo with this command:
The second child is created by the main interpreter. In this case, the grandchild must be named by a two-element list to indicate that it is a child of a child. The same naming convention is used when the grandchild is deleted:
The interp slaves operation returns the names of child (i.e., slave) interpreters. The names are relative to their parent, so the slaves of foo are reported simply as bar and bar2. The name for the current interpreter is the empty list, or {}. This is useful in command aliases and file sharing described later. For security reasons, it is not possible to name the master interpreter from within the slave.
However, the operations delete, exists, share, slaves, target, and transfer cannot be
used with the per interpreter command. In particular, there is no foo delete operation; you must use interp delete foo. If you have a deep hierarchy of interpreters, the command corresponding to the slave is defined only in the parent. For example, if a master creates foo, and foo creates bar, then the master must operate on bar with the interp command. There is no "foo bar" command defined in the master.
interp eval
The interp eval command treats its arguments like eval. If there are extra arguments, they
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Chapter are all concatenated together first. This can lose important structure, as described in
10. To be safe, use list to construct your commands. For example, to safely define a variable in the slave, you should do this:
[ Team LiB ]
[ Team LiB ]
Safe Interpreters
A child can be created either safe (i.e., untrusted) or fully functional. In the examples so far, the children have been trusted and fully functional; they have all the basic Tcl commands available to them. An interpreter is made safe by eliminating certain commands. Table 19-2 lists the commands removed from safe interpreters. As described later, these commands can be used by the master on behalf of the safe interpreter. To create a safe interpreter, use the safe flag:
fconfigure Sets modes of an I/O stream. file glob load open pwd socket source Queries file attributes. Matches on file name patterns. Dynamically loads object code. Opens files and process pipelines. Determines the current directory. Opens network sockets. Loads scripts.
A safe interpreter does not have commands to manipulate the file system and other programs (e.g., cd, open, and exec). This ensures that untrusted scripts cannot harm the host computer. The socket command is removed so that untrusted scripts cannot access the network. The exit, source, and load commands are removed so that an untrusted script cannot harm the hosting application. Note that commands like puts and gets are not removed. A safe interpreter can still do I/O, but it cannot create an I/O channel. We will show how to pass an I/O channel to a child interpreter on page 299. The initial state of a safe interpreter is very safe, but it is too limited. The only thing a safe interpreter can do is compute a string and return that value to the parent. By creating command aliases, a master can give a safe interpreter controlled access to resources. A security policy implements a set of command aliases that add controlled capabilities to a safe interpreter. We will show, for example, how to provide limited network and file system access to untrusted slaves. Tcl provides a framework to manage several security policies, which is described in Chapter 20.
[ Team LiB ]
[ Team LiB ]
Command Aliases
A command alias is a command in one interpreter that is implemented by a command in another interpreter. The master interpreter installs command aliases in its slaves. The command to create an alias has the following general form:
This creates cmd1 in slave that is an alias for cmd2 in target. When cmd1 is invoked in slave, cmd2 is invoked in target. The alias mechanism is transparent to the slave. Whatever cmd2 returns, the slave sees as the return value of cmd1. If cmd2 raises an error, the error is propagated to the slave.
If target is the current interpreter, name it with {}. The empty list is the way to name yourself as the interpreter. This is the most common case, although target can be a different slave. The slave and target can even be the same interpreter. The arguments to cmd1 are passed to cmd2, after any additional arguments to cmd2 that were specified when the alias was created. These hidden arguments provide a safe way to pass extra arguments to an alias. For example, it is quite common to pass the name of the slave to the alias. In Example 19-3, exit in the interpreter foo is an alias that is implemented in the current interpreter (i.e., {}). When the slave executes exit, the master executes:
Alias Introspection
You can query what aliases are defined for a child interpreter. The interp aliases command lists the aliases; the interp alias command can also return the value of an alias, and the interp target command tells you what interpreter implements an alias. These are illustrated in the following examples:
Example 19-4 Querying aliases UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
proc Interp_ListAliases {name out} { puts $out "Aliases for $name" foreach alias [interp aliases $name] { puts $out [format "%-20s => (%s) %s" $alias \ [interp CHM $name $alias] \ UNREGISTERED VERSION OFtarget TO PDF CONVERTER By [interp alias $name $alias]] } }
THETA-SOFTWARE
Example 19-4 generates output in a human readable format. Example 19-5 generates the aliases as Tcl commands that can be used to re-create them later:
[ Team LiB ]
[ Team LiB ]
Hidden Commands
The commands listed in Table 19-2 are hidden instead of being completely removed. A hidden command can be invoked in a slave by its master. For example, a master can load Tcl scripts into a slave by using its hidden source command:
Without hidden commands, the master has to do a bit more work to achieve the same thing. It must open and read the file and eval the contents of the file in the slave. File operations are described in Chapter 9.
interp create -safe slave set in [open filename] interp eval slave [read $in] close $in
Hidden commands were added in Tcl 7.7 in order to better support the Tcl/Tk browser plug-in described in Chapter 20. In some cases, hidden commands are strictly necessary; it is not possible to simulate them any other way. The best examples are in the context of Safe-Tk, where the master creates widgets or does potentially dangerous things on behalf of the slave. These will be discussed in more detail later. A master can hide and expose commands using the interp hide and interp expose operations, respectively. You can even hide Tcl procedures. However, the commands inside the procedure run with the same privilege as that of the slave. For example, if you are really paranoid, you might not want an untrusted interpreter to read the clock or get timing information. You can hide the clock and time commands:
interp create -safe slave interp hide slave clock interp hide slave time
You can remove commands from the slave entirely like this:
interp eval slave [list rename clock {}] interp eval slave [list rename time {}]
[ Team LiB ]
[ Team LiB ]
Substitutions
You must VERSION Tcl CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED be aware of OF parsing and substitutions when commands are invoked in other interpreters. There are three cases corresponding to interp eval, interp invokehidden, and command aliases.
With interp eval the command is subject to a complete round of parsing and substitutions in the target interpreter. This occurs after the parsing and substitutions for the interp eval command itself. In addition, if you pass several arguments to interp eval, those are UNREGISTERED VERSIONevaluation. TO PDF CONVERTER the THETA-SOFTWAREas OF CHM This is similar to the way By eval command works concatenated before described in Chapter 19. The most reliable way to use interp eval is to construct a list to ensure the command is well structured:
With hidden commands, the command and arguments are taken directly from the arguments to interp invokehidden, and there are no substitutions done in the target interpreter. This means that the master has complete control over the command structure, and nothing funny can happen in the other interpreter. For this reason you should not create a list. If you do that, the whole list will be interpreted as the command name! Instead, just pass separate arguments to interp invokehidden and they are passed straight through to the target:
With aliases, all the parsing and substitutions occur in the slave before the alias is invoked in the master. The alias implementation should never eval or subst any values it gets from the slave to avoid executing arbitrary code. For example, suppose there is an alias to open files. The alias does some checking and then invokes the hidden open command. An untrusted script might pass [exit] as the name of the file to open in order to create mischief. The untrusted code is hoping that the master will accidentally eval the filename and cause the application to exit. This attack has nothing to do with opening files; it just hopes for a poor alias implementation. Example 19-6 shows an alias that is not subject to this attack:
interp alias slave open {} safeopen slave proc safeopen {slave filename {mode r}} { # do some checks, then... interp invokehidden $slave open $filename $mode } interp eval slave {open \[exit\]}
open \[exit\]
The master has to quote the brackets in its interp eval command or else the slave will try to invoke exit because of command substitution. Presumably exit isn't defined, or it is defined to terminate the slave. Once this quoting is done, the value of filename is [exit] and it is not subject to substitutions. It is safe to use $filename in the interp invokehidden command because it is only substituted once, in the master. The hidden open command also gets [exit] as its filename argument, which is never evaluated as a Tcl command. [ Team LiB ]
[ Team LiB ]
interp share interp1 chanName interp2 interp transfer interp1 chanName interp2
In these commands, chanName exists in interp1 and is being shared or transferred to interp2. As with command aliases, if interp1 is the current interpreter, name it with {}. The following example creates a temporary file for an unsafe interpreter. The file is opened for reading and writing, and the slave can use it to store data temporarily.
incr i } set out [open Temp$slave$i w+] interp transfer {} $out $slave return $out } proc TempfileExitAlias {slave} { foreach file [glob -nocomplain Temp$slave*] { file delete -force $file } interp delete $slave } interp create -safe foo interp alias foo Tempfile {} TempfileAlias foo interp alias foo exit {} TempfileExitAlias foo
The TempfileAlias procedure is invoked in the parent when the child interpreter invokes Tempfile. TempfileAlias returns the name of the open channel, which becomes the return value from Tempfile. TempfileAlias uses interp transfer to pass the I/O channel to the child so that the child has permission to access the I/O channel. In this example, it would also work to invoke the hidden open command to create the I/O channel directly in the slave. Example 19-7 is not fully safe because the unsafe interpreter can still overflow the disk or create a million files. Because the parent has transferred the I/O channel to the child, it cannot easily monitor the I/O activity by the child. Example 19-9 addresses these issues. [ Team LiB ]
[ Team LiB ]
The safe base has source and load aliases that only access directories on an access path defined by the master interpreter. The master has complete control over what files can be loaded into a slave. In general, it would be all right to source any Tcl program into an untrusted interpreter. However, untrusted scripts might learn things from the error messages they get by sourcing arbitrary files. The safe base also has versions of the package and unknown commands that support the library facility. Table 19-3 lists the Tcl procedures in the safe base:
Table 19-4 lists the aliases defined in a safe interpreter by the safe base.
source Loads scripts from directories in the access path. load file exit Loads binary extensions from the slaves access path. Only the dirname, join, extension, root, tail, pathname, and split operations are allowed. Destroys the slave interpreter.
[ Team LiB ]
[ Team LiB ]
Security Policies
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
A security policy defines what a safe interpreter can do. Designing security policies that are secure is difficult. If you design your own, make sure to have your colleagues review the code. Give out prizes to folks who can break your policy. Good policy implementations are proven with lots of review and trial attacks. The good news is that Safe-Tcl security policies can be implemented in relatively small amounts of Tcl code. This makes them easier to analyze and get correct. Here are a number of rules of thumb: Small policies are better than big, complex policies. If you do a lot of complex processing to allow or disallow access to resources, chances are there are holes in your policy. Keep it simple. Never eval arguments to aliases. If an alias accepts arguments that are passed by the slave, you must avoid being tricked into executing arbitrary Tcl code. The primary way to avoid this is never to eval arguments that are passed into an alias. Watch your expressions, too. The expr command does an extra round of substitutions, so brace all your expressions so that an attacker cannot pass [exit] where you expect a number! Security policies do not compose. Each time you add a new alias to a security policy, it changes the nature of the policy. Even if alias1 and alias2 are safe in isolation, there is no guarantee that they cannot be used together to mount an attack. Each addition to a security policy requires careful review.
bisque.eng {80 1025-} } proc Safesock_PolicyInit {slave} { interp alias $slave socket {} SafesockAlias $slave } proc SafesockAlias {slave host port} { global safesock if ![info exists safesock($host)] { error "unknown host: $host" } foreach portspec $safesock($host) { set low [set high ""] if {[regexp {^([0-9]+)-([0-9]*)$} $portspec x low high]} { if {($low <= $port && $high == "") || ($low <= $port && $high >= $port)} { set good $port break } } elseif {$port == $portspec} { set good $port } } if [info exists good] { set sock [interp invokehidden $slave socket $host $good] interp invokehidden $slave fconfigure $sock \ -blocking 0 return $sock } error "bad port: $port" }
The policy is initialized with Safesock_PolicyInit. The name of this procedure follows a naming convention used by the safe base. In this case, a single alias is installed. The alias gives the slave a socket command that is implemented by SafesockAlias in the master. The alias checks for a port that matches one of the port specifications for the host. If a match is found, then the invokehidden operation is used to invoke two commands in the slave. The socket command creates the network connection, and the fconfigure command puts the socket into nonblocking mode so that read and gets by the slave do not block the application:
set sock [interp invokehidden $slave socket $host $good] interp invokehidden $slave fconfigure $sock -blocking 0
The socket alias in the slave does not conflict with the hidden socket command. There are two distinct sets of commands, hidden and exposed. It is quite common for the alias implementation to invoke the hidden command after various permission checks are made. The Tcl Web browser plug-in ships with a slightly improved version of the Safesock policy. It adds an alias for fconfigure so that the http package can set end of line translations and buffering modes. The fconfigure alias does not let you change the blocking behavior of the socket. The policy has also been extended to classify hosts into trusted and untrusted hosts based on their address. A different table of allowed ports is used for the two classes of hosts.
The classification is done with two tables: One table lists patterns that match trusted hosts, and the other table lists hosts that should not be trusted even though they match the first table. The improved version also lets a downloaded script connect to the Web server that it came from. The Web browser plug-in is described in Chapter 20.
[lsearch -exact $files $real] < 0)} { error "permission denied" } if [catch {open $real $m $p} out] { return -code error "$name: permission denied" } lappend tempfile(channels,$slave) $out interp share {} $out $slave return $out } proc TempfileExitAlias {slave} { global tempfile interp delete $slave if [info exists tempfile(channels,$slave)] { foreach out $tempfile(channels,$slave) { catch {close $out} } unset tempfile(channels,$slave) } } # See also the puts alias in Example 244 on page 389 proc TempfilePutsAlias {slave max chan args} { # max is the file size limit, in bytes # chan is the I/O channel # args is either a single string argument, # or the -nonewline flag plus the string. if {[llength $args] > 2} { error "invalid arguments" } if {[llength $args] == 2} { if {![string match -n* [lindex $argv 0]]} { error "invalid arguments" } set string [lindex $args 1] } else { set string [lindex $args 0]\n } set size [expr [tell $chan] + [string length $string]] if {$size > $max} { error "File size exceeded" } else { puts -nonewline $chan $string } }
The TempfileAlias procedure is generalized in Example 19-9 to have parameters that specify the directory, name, and a limit to the number of files allowed. The directory and maxfile limit are part of the alias definition. Their existence is transparent to the slave. The slave specifies only the name and access mode (i.e., for reading or writing.) The Tempfile policy can be used by different slave interpreters with different parameters. The master is careful to restrict the files to the specified directory. It uses file tail to strip off any leading pathname components that the slave might specify. The tempfile(directory) definition is not shown in the example. The application must choose a directory when it creates
the safe interpreter. The Browser security policy described on page 317 chooses a directory based on the name of the URL containing the untrusted script. The TempfilePutsAlias procedure implements a limited form of puts. It checks the size of the file with tell and measures the output string to see if the total exceeds the limit. The limit comes from a parameter defined when the alias is created. The file cannot grow past the limit, at least not by any action of the child interpreter. The args parameter is used to allow an optional -nonewline flag to puts. The value of args is checked explicitly instead of using the UNREGISTERED VERSION OF CHM 10-3PDF CONVERTER eval arguments to aliases or else a TO on page 136. Never By THETA-SOFTWARE eval trick described in Example slave can attack you with arguments that contain embedded Tcl commands. The master and slave share the I/O channel. The name of the I/O channel is recorded in tempfile, and TempfileExitAlias uses this information to close the channel when the child interpreter is deleted. This is necessary because both parent and child have a reference to the UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE channel when it is shared. The child's reference is automatically removed when the interpreter is deleted, but the parent must close its own reference. The shared I/O channel lets the master use puts and tell. It is also possible to implement this policy by using hidden puts and tell commands. The reason tell must be hidden is to prevent the slave from implementing its own version of tell that lies about the seek offset value. One advantage of using hidden commands is that there is no need to clean up the tempfile state about open channels. You can also layer the puts alias on top of any existing puts implementation. For example, a script may define puts to be a procedure that inserts data into a text widget. Example 19-10 shows the difference when using hidden commands.
} proc TempfileTellAlias {slave chan} { interp invokehidden $slave tell $chan } proc TempfilePutsAlias {slave max chan args} { if {[llength $args] > 2} { error "invalid arguments" } if {[llength $args] == 2} { if {![string match -n* [lindex $args 0]]} { error "invalid arguments" } set string [lindex $args 1] } else { set string [lindex $args 0]\n } set size [interp invokehidden $slave tell $chan] incr size [string length $string] if {$size > $max} { error "File size exceeded" } else { interp invokehidden $slave \ puts -nonewline $chan $string } }
global after interp alias $slave after {} SafeAfterAlias $slave $max interp alias $slave exit {} SafeAfterExitAlias $slave # This is used to generate after IDs for the slave. set after(id,$slave) 0 } # SafeAfterAlias is an alias for after. It disallows after UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE # with only a time argument and no command. proc SafeAfterAlias {slave max args} { global after set argc [llength $args] if {$argc == 0} { UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE error "Usage: after option args" } switch -- [lindex $args 0] { cancel { # A naive implementation would just # eval after cancel $args # but something dangerous could be hiding in args. set myid [lindex $args 1] if {[info exists after(id,$slave,$myid)]} { set id $after(id,$slave,$myid) unset after(id,$slave,$myid) after cancel $id } return "" } default { if {$argc == 1} { error "Usage: after time command args..." } if {[llength [array names after id,$slave,*]]\ >= $max} { error "Too many after events" } # Maintain concat semantics set command [concat [lrange $args 1 end]] # Compute our own id to pass the callback. set myid after#[incr after(id,$slave)] set id [after [lindex $args 0] \ [list SafeAfterCallback $slave $myid $command]] set after(id,$slave,$myid) $id return $myid } } } # SafeAfterCallback is the after callback in the master. # It evaluates its command in the safe interpreter. proc SafeAfterCallback {slave myid cmd} { global after unset after(id,$slave,$myid) if [catch {
interp eval $slave $cmd } err] { catch {interp eval $slave bgerror $error} } } # SafeAfterExitAlias is an alias for exit that does cleanup. proc SafeAfterExitAlias {slave} { global after foreach id [array names after id,$slave,*] { after cancel $after($id) unset after($id) } interp delete $slave }
[ Team LiB ]
[ Team LiB ]
Chapter 20. Safe-Tk and the Browser UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Plugin
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
This chapter describes Safe-Tk that lets untrusted scripts display and manipulate graphical user interfaces. The main application of Safe-Tk is the Tcl/Tk plugin for Web browsers like Netscape Navigator and Internet Explorer. Safe-Tk supports network applets that display user interfaces. The main vehicle for Safe-Tk is a plugin for Netscape Navigator, Mozilla and Internet Explorer. The plugin supports Tcl applets, or Tclets, that are downloaded from the Web server and execute inside a window in a Web browser. For the most part, Tcl/Tk applications can run unchanged in the plugin. However, security policies place some restrictions on Tclets. The plugin supports multiple security policies, so Tclets can do a variety of interesting things in a safe manner. You can configure the plugin to use an existing wish application to host the Tcl applets if you require a newer version of Tk, or the plugin can load the Tcl/Tk shared libraries and everything runs in the browser process. You can use a custom wish that has extensions built in or dynamically loaded. This gives intranet applications of the plugin the ability to access databases and other services that are not provided by the Tcl/Tk core. With the security policy mechanism you can still provide mediated access to these resources. This chapter describes how to set up the plugin. Jeff Hobbs recently updated the plugin to use Tcl/Tk 8.4. Compiled versions of the plugin are available as part of the Tcl Dev Kit from ActiveState. The source code of the plugin is freely available. You can recompile the plugin against newer versions of Tcl/Tk, or build custom plugins that have your own Tcl extensions built in. You can find its sources at: http://tclplugin.sourceforge.net/ [ Team LiB ]
[ Team LiB ]
Tk in Child Interpreters
A child interpreter starts out with just the core Tcl commands. It does not include Tk or any other extensions that might be available to the parent interpreter. This is true whether or not the child interpreter is declared safe. You add extensions to child interpreters by using a form of the load command that specifies an interpreter:
load {} Tk child
Normally, load takes the name of the library file that contains the extension. In this case, the Tk package is a static package that is already linked into the program (e.g., wish or the plugin), so the file name is the empty string. The load command calls the Tk initialization procedure to register all the Tcl commands provided by Tk.
Embedding Tk Windows
By default, a slave interpreter that loads Tk gets a new top-level window. Wish supports a -use command line option that directs Tk to use an existing window as dot. You can use this to embed an application within another. For example, the following commands run a copy of Wish that uses the .embed toplevel as its main window:
More often, embedding is used with child interpreters. If the interpreter is not safe, you can set the argv and argc variables in the slave before loading Tk:
interp create trustedTk interp eval trustedTk \ [list set argv [list -use [winfo id .embed]]] interp eval trustedTk [list set argc 2] load {} Tk trustedTk
If the child interpreter is safe, then you cannot set argv and argc directly. The easiest way to pass -use to a safe interpreter is with the safe::loadTk command:
When Tk is loaded into a safe interpreter, it calls back into the master interpreter and evaluates the safe::TkInit procedure. The job of this procedure is to return the appropriate argv value
for the slave. The safe::loadTk procedure stores its additional arguments in the safe::tkInit variable, and this value is retrieved by the safe::TkInit procedure and returned to the slave. This protocol is used so that a safe interpreter cannot attempt to hijack the windows of its master by constructing its own argv variable!
Safe-Tk Restrictions
tk_chooseDirectory Directory chooser dialog. tk_getOpenFile tk_getSaveFile tk_messageBox toplevel wm File open dialog. File save dialog. Simple dialog boxes. Creates a detached window. Controls the window manager.
If you find these restrictions limiting, you can restore commands to safe interpreters with the interp expose command. For example, to get menus and toplevels working, you could do:
interp create -safe safeTk foreach cmd {grab menu menubutton toplevel wm} { interp expose safeTk $cmd }
Instead of exposing the command directly, you can also construct aliases that provide a subset of the features. For example, you could disable the -global option to grab. Aliases are described in detail in Chapter 19.
The Browser plugin defines a more elaborate configuration system to control what commands are available to slave interpreters. You can have lots of control, but you need to distribute the security policies that define what Tclets can do in the plugin. Configuring security policies for the plugin is described later. [ Team LiB ]
[ Team LiB ]
The width and height are interpreted by the plugin as the size of the embedded window. The src specifies the URL of the program. These parameter names (e.g., width) are case sensitive and should be lowercase. In the above example, eval.tcl is a relative URL, so it should be in the same directory as the HTML file that has the EMBED tag. The window size is fixed in the browser, which is different from normal toplevels in Tk. The plugin turns off geometry propagation on your main window so that your Tclet stays the size allocated. There are also "full window" Tclets that do not use an EMBED tag at all. Instead, you just specify the .tcl file directly in the URL. In this case, the plugin occupies the whole browser window and will resize as you resize the browser window.
Note that HTML tag parameters are case sensitive. Your Tclet may want to map all the parameter names to lowercase for convenience:
foreach {name value} [array get embed_args] { set embed_args([string tolower $name]) $value }
The plugin array has version, patchLevel, and release elements that identify the version
Example Plugins
The plugin home page is a great place to find Tclet examples. There are several plugins done by the Tcl/Tk team at Sunlabs, plus links to a wide variety of Tclets done on the Net. http://www.tcl.tk/plugin/ My first plugin was calculator for the effective wheel diameter of multigear bicycles. Brian Lewis, who built the Tcl 8.0 byte-code compiler, explained to me the concept and how important this information is to bicycle enthusiasts. The Tclet that displays the gear combinations on a Tk canvas and lets you change the number of gears and their size. You can find the result at: http://www.beedub.com/plugin/bike.html
[ Team LiB ]
policy name
The policies that are part of the standard plugin distribution are described below. The home, inside, and outside policies all provide limited network access. They differ in what set of hosts are accessible. The default trust configuration lets any Tclet request the home, inside, or outside policy. home. This provides a socket and fconfigure commands that are limited to connecting to the host from which the Tclet was downloaded. You can specify an empty string for the host argument to socket to connect back to the home host. This policy also supports open and file delete that are similar to the Tempfile policy shown in Example 19-9 on page 304. This provides limited local storage that is inside a directory that is, by default, private to the Tclet. Files in the private directory persist after the Tclet exits, so it can maintain long term state. Tclets from the same server can share the directory by putting the same prefix=partialurl argument in their EMBED tag. The partialurl must be a prefix of the Tclet's URL. Finally, the home policy automatically provides a browser package that is described later. inside. This is just like the home policy, except that the site administrator controls a table of hosts and ports to which untrusted slaves can connect with socket. A similar set of tables control what URLs can be accessed with the browser package. This is similar to the Safesock policy shown in Example 19-8 on page 302. The set of hosts is supposed to be inside the firewall. The local file storage used by this policy is distinct from that used by the home and outside policies. This is true even if Tclets try to share by using the prefix=partialurl parameter. outside. This is just like the home and inside policies, except that the set of hosts is configured to be outside the firewall. The local file storage used by this policy is distinct from that used by the home and inside policies. trusted. This policy restores all features of Tcl and Tk. This policy lets you launch all your Tcl and Tk applications from the Web browser. The default trust map settings do not allow this for any Tclet. The trust map configuration is described later. javascript. This policy provides a superset of the browser package that lets you invoke arbitrary Javascript and to write HTML directly to frames. This does not have the limited socket or temporary file access that the home, inside, and outside policies have.
However, the javascript policy places no restrictions on the URLs you can fetch, plus it lets Tclets execute Java-script, which may have its own security risks. The default trust map settings do not allow this for any Tclet.
browser::getForm url data ?raw? ? Posts data to url. The callbacks are the same as for browser::getURL. If raw is 0, then data is a name timeout? ?newcallback? ? value list that gets encoded automatically. Otherwise, writecallback? ?endcallback? it is assumed to be encoded already. browser::displayForm url frame data ?raw? Posts data to url and displays the result in frame. The raw argument is the same as in browser::getForm.
The browser::getURL function uses the browser's built-in functions, so it understands proxies and supports ftp:, http:, and file: urls. Unfortunately, the browser::getURL interface is different from the http::geturl interface. It uses a more complex callback scheme that is due to the nature of the browser's built-in functions. If you do not specify any callbacks, then the call blocks until all the data is received, and then that data is returned. The callback functions are described in Table 20-3.
newcallback name stream This is called when data starts to arrive from url. The name url mimetype identifies the requesting Tclet, and the stream identifies the datemodified size connection. The mimetype, datemodified, and size parameters are attributes of the returned data. writecallback name stream size data This is called when size bytes of data arrive for Tcllet name over stream.
endcallback name stream This is called when the request has completed, although there may be some final bytes in data. The reason is one of: EOF, reason data NETWOR_ERROR, USER_BREAK, or TIMEOUT.
[ Team LiB ]
[ Team LiB ]
Remember that the configuration files affect the client machine, which is the workstation that runs the Web browser. If you create Tclets that require custom security policies, you have the burden of distributing the configuration files to clients that will use your Tclets. You also have the burden of convincing them that your security policy is safe!
section policies allow home disallow intercom disallow inside disallow outside disallow trusted allow javascript ifallowed trustedJavaScriptURLS \ $originURL
This configuration grants all Tclets the right to use the home policy, disallows all Tclets from using the intercom, inside, outside, and trusted policies, and grants limited access to the javascript policy. If you are curious, the configuration files are almost Tcl, but not quite. I lost an argument about that one, so these are stylized configuration files that follow their own rules. For example, the originURL variable is not defined in the configuration file but is a value that is
tested later when the Tclet is loaded. I'll just give examples here and you can peer under the covers if you want to learn how they are parsed. The ifallowed clause depends on another section to describe the trust mapping for that policy. For the javascript policy, the config/plugin.cfg file contains:
section trustedJavascriptURLs
You can use a combination of allow and disallow rules in a section. The arguments to allow and disallow are URL string match patterns, and they are processed in order. For example, you could put a liberal allow rule followed by disallow rules that restrict access, or vice versa. It is probably safest to explicitly list each server that you trust.
In turn, each security policy configuration file lists what features are part of the policy. For example, the config/home.cfg file lists these features:
allow network allow persist unless {[string match {UNKNOWN *} \ [getattr originURL]]}
Each feature is implemented in a file in the safetcl directory of the distribution. For example, the url feature is implemented in safetcl/url.tcl. The code in these files follows some conventions in order to work with the configuration mechanism. Each one is implemented inside a namespace that is a child of the safefeature namespace (e.g., safefeature::url). It must implement an install procedure that is called to initialize the feature for a new Tclet. It is inside this procedure that the various allow/disallow rules are checked. The cfg::allowed command supports the rule language used in the .cfg files.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
You should always assume that a binary extension is not thread-safe unless its documentation explicitly says that it is. And even thread-safe binary extensions must be compiled with thread support enabled for you to use them in multi-threaded applications. (The default compilation options for most binary extensions don't include thread support.)
Most underlying display libraries (such as X Windows) aren't thread safe - or at least aren't typically compiled with thread-safety enabled. However, significant work has gone into making the Tk core thread-safe. The result is that you can safely use Tk in a multi-threaded Tcl application as long as only one thread uses Tk commands to manage the interface. Any other thread that needs to update the interface should send messages to the thread controlling the interface. [ Team LiB ]
[ Team LiB ]
The main thread has a unique position in a multi-threaded Tcl script. If it exits, then the entire application terminates. Also, if the main thread terminates while other threads still exist, Tcl can sometimes crash rather than exiting cleanly. Therefore, you should always design your multi-threaded applications so that your main thread waits for all other threads to terminate before it exits. Before accessing any threading features from your application, you must load the Thread extension:
The Thread extension automatically loads itself into any new threads your application creates with thread::create. All other extensions must be loaded explicitly into each thread that needs to use them. The Thread extension creates commands in three separate namespaces: The thread namespace contains all of the commands for creating and managing threads, including inter-thread messaging, mutexes, and condition variables. The tsv namespace contains all of the commands for creating and managing thread shared variables. The tpool namespace contains all of the commands for creating and managing thread pools.
Creating Threads
The thread::create command creates a new thread containing a new Tcl interpreter. Any thread can create another thread at will; you aren't limited to starting threads from only the main thread. The thread::create command returns immediately, and its return value is the ID of the thread created. The ID is a unique token that you use to interact with and manipulate the thread, in much the same way as you use a channel identifier returned by open to interact
with and manipulate that channel. There are several commands available for introspection on thread IDs: thread::id returns the ID of the current thread; thread::names returns a list of threads currently in existence; and thread::exists tests for the existence of a given thread. The thread::create command accepts a Tcl script as an argument. If you provide a script, the interpreter in the newly created thread executes it and then terminates the thread. Example 21-1 demonstrates this by creating a thread to perform a recursive search for files in a directory. For a large directory structure, this could take considerable time. By performing the search in a separate thread, the main thread is free to perform other operations in parallel. Also note how the "worker" thread loads an extension and opens a file, completely independent of any extensions loaded or files opened in other threads.
thread::create { # Load the Tcllib fileutil package to use its # findByPattern procedure. package require fileutil set files [fileutil::findByPattern [pwd] *.tcl] set fid [open files.txt w] puts $fid [join $files \n] close $fid } # The main thread can perform other tasks in parallel...
If you don't provide a script argument to thread::create, the thread's interpreter enters its event loop. You then can use the thread::send command, described on page 328, to send it scripts to evaluate. Often though, you'd like to perform some initialization of the thread before having it enter its event loop. To do so, use the thread::wait command to explicitly enter the event loop after performing any desired initialization, as shown in Example 21-2. You should always use thread::wait to cause a thread to enter its event loop, rather than vwait or tkwait, for reasons discussed in "Preserving and Releasing Threads" on page 330.
while {[llength [thread::names]] > 1} { after 500 } puts "*** That's all, folks!"
A better approach in this situation is to use joinable threads, which are supported in Tcl 8.4 or later. A joinable thread allows another thread to wait upon its termination with the thread::join command. You can use thread::join only with joinable threads, which are created by including the thread::create -joinable option. Attempting to join a thread not created with -joinable results in an error. Failing to join a joinable thread causes memory and other resource leaks in your application. Example 21-4 revises the program from Example 21-3 to use joinable threads.
UNREGISTERED that thread::join blocks.PDF CONVERTER By THETA-SOFTWARE return, it Be aware VERSION OF CHM TO While the thread is waiting for thread::join to
can't perform any other operations, including servicing its event loop. Therefore, make sure that you don't use thread::join in situations where a thread must be responsive to incoming events. [ Team LiB ] UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
[ Team LiB ]
If you also provide the name of a variable to a synchronous thread::send, then it behaves analogously to a catch command; thread::send returns the return code of the script, and the return value of the last command executed in the script - or the error message - is stored in
the variable. Tcl stores the target thread's stack trace in the sending thread's errorInfo variable.
By THETA-SOFTWARE
While the sending thread is waiting for a synchronous thread::send to return, it can't perform any other operations, including servicing its event loop. Therefore, synchronous sending is appropriate only in cases where: you want a simple way of getting a value back from another thread; you don't mind blocking your thread if the other thread takes a while to respond; or you need a response from the other thread before proceeding.
If Thread A performs a synchronous thread::send to Thread B, and while evaluating the script Thread B performs a synchronous thread::send to Thread A, then your application is deadlocked. Because Thread A is blocked in its thread::send, it is not servicing its event loop, and so can't detect Thread B's message. This situation arises most often when the script you send calls procedures in the target thread, and those procedures contain thread::send commands. Under these circumstances, it might not be obvious that the script sent will trigger a deadlock condition. For this reason, you should be cautious about using synchronous thread::send commands for complex actions. Sending in asynchronous mode, described in the next section, avoids potential deadlock situations like this.
With the -async option, thread::send sends the script to the target thread in asynchronous mode. In this case, thread::send returns immediately. By default, an asynchronous thread::send discards any return value of the script. However, if you provide the name of a variable as an additional argument to thread::send, the return value of the last command executed in the script is stored as the value of the variable. You can then either vwait on the variable or create a write trace on the variable to detect when the target thread responds. For example:
In this example, the thread::send command returns immediately; the sending thread could then continue with any other operations it needed to perform. In this case, it executes a vwait on the return variable to wait until the target thread finishes executing the script. However, while waiting for the response, it can detect and process incoming events. In contrast, the following synchronous thread::send blocks, preventing the sending thread from processing events until it receives a response from the target thread:
[ Team LiB ]
[ Team LiB ]
Each thread maintains an internal reference count. The reference count is set initially to 0, or to 1 if you create the thread with the thread::create -preserved option. Any thread can increment the reference count afterwards by executing thread::preserve, and decrement the UNREGISTERED count by executing thread::release. These commands affect the reference count of VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE reference the current thread unless you specify the ID of another thread. If a call to thread::release results in a reference count of 0 or less, the thread is marked for termination. The use of thread reference counts allows multiple threads to preserve the existence of a worker thread until all of the threads release the worker thread. But the majority of multithreaded Tcl applications don't require that degree of thread management. In most cases, you can simply create a thread and then later use thread::release to terminate it:
set worker [thread::create] thread::send -async $worker $script # Later in the program, terminate the worker thread thread::release $worker
A thread marked for termination accepts no further messages and discards any pending events. It finishes processing any message it might be executing currently, then exits its event loop. If the thread entered its event loop through a call to thread::wait, any other commands following thread::wait are executed before thread termination, as shown in Example 21-7. This can be useful for performing "clean up" tasks before terminating a thread.
Note that if a thread is executing a message script when thread::release is called (either by itself or another thread), the thread finishes executing its message script before terminating. So, if a thread is stuck in an endless loop, calling thread::release has no effect on the thread. In fact, there is no way to kill such a "runaway thread."
This system for preserving and releasing threads works only if you use the thread::wait command to enter the thread's event loop (or if you did not provide a creation script when creating the thread). If you use vwait or tkwait to enter the event loop, thread::release cannot terminate the thread. [ Team LiB ]
[ Team LiB ]
Error Handling
If an error occurs while a CHM is executing its creation script (provided by thread::create), UNREGISTERED VERSION OFthread TO PDF CONVERTER By THETA-SOFTWARE the thread dies. In contrast, if an error occurs while processing a message script (provided by thread::send), the default behavior is for the thread to stop execution of the message script, but to return to its event loop and continue running. To cause a thread to die when it encounters an uncaught error, use the thread::configure command to set the thread's unwindonerror option to true:
Error handling is determined by the thread creating the thread or sending the message. If an error occurs in a script sent by a synchronous thread::send, then the error condition is "reflected" to the sending thread, as described in "Synchronous Message Sending" on page 328. If an error occurs during thread creation or an asynchronous thread::send, the default behavior is for Tcl to send a stack trace to the standard error channel. Alternatively, you can specify the name of your own custom error handling procedure with thread::errorproc. Tcl automatically calls your procedure whenever an "asynchronous" error occurs, passing it two arguments: the ID of the thread generating the error, and the stack trace. (This is similar to defining your own bgerror procedure, as described in "The bgerror Command" on page 202.) For example, the following code logs all uncaught errors to the file errors.txt:
[ Team LiB ]
[ Team LiB ]
Shared Resources
The present working directory is a resource shared by all interpreters in all threads. If one thread changes the present working directory, then that change affects all interpreters and all threads. This can pose a significant problem, as some library routines temporarily change the present working directory during execution, and then restore it before returning. But in a multithreaded application, another thread could attempt to access the present working directory during this period and get incorrect results. Therefore, the safest approach if your application needs to access the present working directory is to store this value in a global or thread-shared variable before creating any other threads. The following example uses tsv::set to store the current directory in the pwd element of the application shared variable:
package require Thread # Save the pwd in a thread-shared variable tsv::set application pwd [pwd] set t [thread::create {#...}]
Environment variables are another shared resource. If one thread makes a change to an environment variable, then that change affects all threads in your application. This might make it tempting to use the global env array as a method for sharing information between threads. However, you should not do so, because it is far less efficient than thread-shared variables, and there are subtle differences in the way environment variables are handled on different platforms. If you need to share information between threads, you should instead use threadshared variables, as discussed in "Shared Variables" on page 337.
Although technically not a shared resource, it's important to recognize that the exit command kills the entire application, no matter which thread executes it. Therefore, you should never call exit from a thread when your intention is to terminate only that thread. [ Team LiB ]
[ Team LiB ]
Be careful with standard I/O channel UNREGISTERED VERSION OF CHM TO PDF on Windows andBy THETA-SOFTWARE CONVERTER Macintosh.
When running wish on Windows and Macintosh prior to OS X, you don't have real standard I/O channels, but simulated stdout and stderr channels direct output to the special console window. As of Thread 2.5, these simulated channels appear in the main thread's channel list, but not in any other thread's channel list. Therefore, you'll cause an error if you attempt to access these channels from any thread other than the main thread.
set fid [open myfile.txt r] # ... set t [thread::create] thread::transfer $t $fid # Duplicate the channel ID in the target thread thread::send $t [list set fid $fid]
Another option for transferring channels introduced in Thread 2.5 is thread::detach, which detaches a channel from a thread, and thread::attach, which attaches a previously detached channel to a thread. The advantage to this approach is that the thread relinquishing the channel doesn't need to know which thread will be acquiring it. This is useful when your application uses thread pools, which are described on page 342. The ability to transfer channels between threads is a key feature in implementing a multithread server, in which a separate thread is created to service each client connected. One thread services the listening socket. When it receives a client connection, it creates a new thread to service the client, then transfers the client's communication socket to that thread.
A complication arises in that you can't perform the transfer of the communication socket directly from the connection handler, like this:
socket -server ClientConnect 9001 proc ClientConnect {sock host port} { set t [thread::create { ... }] # The following command fails thread::transfer $t $sock }
The reason is that Tcl maintains an internal reference to the communication socket during the connection callback. The thread::transfer command (and the thread::detach command)
cannot transfer the channel while this additional reference is in place. Therefore, we must use the after command to defer the transfer until after the connection callback returns, as shown in Example 21-10.
Example 21-10 Deferring socket transfer until after the connection callback
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
proc _ClientConnect {sock host port} { after 0 [list ClientConnect $sock $host $port] }
UNREGISTERED VERSION OF CHM TO PDF transfer the channel # Create the client thread and CONVERTER By THETA-SOFTWARE
}
One issue in early versions of Tcl 8.4 was a bug that failed to initialize Tcl's socket support when a socket channel was transferred into a thread. The work-around for this bug is to explicitly create a socket in the thread (which can then be immediately closed) to initialize the socket support, and then transfer the desired socket. This bug has been fixed, but Example 2111 illustrates how you can perform extra initialization in a newly created thread before it enters its event loop:
Example 21-11 Working around Tcl's socket transfer bug by initializing socket support
set t [thread::create { # Initialize socket support by opening and closing # a server socket. close [socket -server {} 0] # Now sockets can be transferred safely into this thread. thread::wait }]
Example 21-12 integrates all of these techniques to create a simple multi-threaded echo server. Note that the server still uses event-driven interaction in each client thread. Technically, this isn't necessary for such a simple server, because once a client thread starts it doesn't expect to receive messages from any other thread. If a thread needs to respond to messages from other threads, it must be in its event loop to detect and service such messages. Because this requirement is common, this application demonstrates the event-driven approach.
} else { set port 9001 } socket -server _ClientConnect $port proc _ClientConnect {sock host port} { # # # # # Tcl holds a reference to the client socket during this callback, so we can't transfer the channel to our worker thread immediately. Instead, we'll schedule an after event to create the worker thread and transfer the channel once we've re-entered the event loop.
after 0 [list ClientConnect $sock $host $port] } proc ClientConnect {sock host port} { # # # # Create a separate thread to manage this client. The thread initialization script defines all of the client communication procedures and puts the thread in its event loop.
set thread [thread::create { proc ReadLine {sock} { if {[catch {gets $sock line} len] || [eof $sock]} { catch {close $sock} thread::release } elseif {$len >= 0} { EchoLine $sock $line } } proc EchoLine {sock line} { if {[string equal -nocase $line quit]} { SendMessage $sock \ "Closing connection to Echo server" catch {close $sock} thread::release } else { SendMessage $sock $line } } proc SendMessage {sock msg} { if {[catch {puts $sock $msg} error]} { puts stderr "Error writing to socket: $error" catch {close $sock} thread::release } }
}] # # # # Release the channel from the main thread. We use thread::detach/thread::attach in this case to prevent blocking thread::transfer and synchronous thread::send commands from blocking our listening socket thread.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE thread::send -async $thread [list set sock $sock]
# Attach the communication socket to the client-servicing # thread, and finish the socket setup. thread::send -async $thread { thread::attach $sock fconfigure $sock -buffering line -blocking 0 fileevent $sock readable [list ReadLine $sock] SendMessage $sock "Connected to Echo server" } } vwait forever
[ Team LiB ]
[ Team LiB ]
Shared Variables
Standard Tcl variables are a per-interpreter resource; an interpreter has no access to variables in another interpreter. For the simple exchange of information between threads, you can substitute the values of variables into a script that you send to another thread, and obtain the return value of a script evaluated by another thread. But this technique is inadequate for sharing information among multiple threads, and inefficient when transferring large amounts of information. The Thread extension supports the creation of thread-shared variables, which are accessible by all threads in an application. Thread-shared variables are stored independent of any interpreter, so if the thread that originally created a shared variable terminates, the shared variable continues to exist. Shared variables are stored in collections called arrays. The term is somewhat unfortunate, because while shared variable arrays are similar to standard Tcl arrays, they do not use the same syntax. Your application can contain as many shared variable arrays as you like. Because of the special nature of shared variables, you cannot use the standard Tcl commands to create or manipulate shared variables, or use standard variable substitution syntax to retrieve their values. (This also means that you cannot use shared variables as a widget's textvariable or -listvariable, with vwait or tkwait, or with variable traces.) All commands for interacting with shared variables are provided by the Thread extension in the tsv namespace. Most of the tsv commands are analogous to Tcl commands for creating and manipulating standard Tcl variables. Table 21-3 on page 346 describes all of the tsv commands. You create a shared variable with tsv::set, specifying the array name, the variable name (sometimes also referred to as the shared array element), and the value to assign to it. For example:
To retrieve the value of a shared variable, either use tsv::set without a value or call tsv::get. The two commands shown below are equivalent:
All shared variable commands are guaranteed to be atomic. A thread locks the variable during the entire command. No other thread can access the variable until the command is complete; if a thread attempts to do so, it blocks until the variable is unlocked. This simplifies the use of shared variables in comparison to most other languages, which require explicit locking and unlocking of variables to prevent possible corruption from concurrent access by multiple threads. This locking feature is particularly useful in the class of tsv commands that manipulate lists. Standard Tcl commands like linsert and lreplace take a list value as input, and then return a new list as output. Modifying the value of a list stored in a standard Tcl variable requires a
After reading the shared variable with tsv::get, another thread could modify the value of the
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE reason, variable before the tsv::set command executes, resulting in data corruption. For this
the tsv commands that manipulate list values actually modify the value of the shared variable. Data corruption by another thread won't occur because the shared variable is locked during the entire execution of the command:
[ Team LiB ]
[ Team LiB ]
Mutexes
A mutex, which is short for mutual exclusion, is a locking mechanism. You use a mutex to protect shared resources - such as shared variables, serial ports, databases, etc. - from concurrent access by multiple threads. Before accessing the shared resource, the thread attempts to lock the mutex. If no other thread currently holds the mutex, the thread successfully locks the mutex and can access the resource. If another thread already holds the mutex, then the attempt to lock the mutex blocks until the other thread releases the mutex. This sequence is illustrated in Example 21-13. The first step is creating a mutex with the thread::mutex create operation, which returns a unique token representing the mutex. The same token is used in all threads, and so you must make this token available (for example, through a shared variable) to all threads that access the shared resource.
Mutexes work only if all threads in an application use them properly. A "rogue" thread can ignore using a mutex and access the shared resource directly. Therefore, you should be very careful to use your mutexes consistently when designing and implementing your application.
Condition Variables
A condition variable is a synchronization mechanism that allows one or more threads to sleep until they receive notification from another thread. A condition variable is associated with a UNREGISTERED VERSION condition known as aCONVERTER By THETA-SOFTWARE mutex and a boolean OF CHM TO PDF predicate. A thread uses the condition variable to wait until the boolean predicate is true. A different thread changes the state of the predicate to true, and then notifies the condition variable. The mutex synchronizes thread access to the data used to compute the predicate value. The general usage pattern for the signalling thread is: Lock the mutex Change the state so the predicate is true Notify the condition variable Unlock the mutex The pattern for a waiting thread is: Lock the mutex Check the predicate If the predicate is false, wait on the condition variable until notified Do the work Unlock the mutex In practice, a waiting thread should always check the predicate inside a while loop, because multiple threads might be waiting on the same condition variable. A waiting thread automatically releases the mutex when it waits on the condition variable. When the signalling thread notifies the condition variable, all threads waiting on that condition variable compete for a lock on the mutex. Then when the signalling thread releases the mutex, one of the waiting threads gets the lock. It is quite possible for that thread then to change the state so that the predicate is no longer true when it releases the lock. For example, several worker threads forming a thread pool might wait until there is some type of job to process. Upon notification, the first worker thread takes the job, leaving nothing for the other worker threads to process. This sequence for using a condition variable sounds complex, but is relatively easy to code. Example 21-14 shows the sequence for the signalling thread. The first step is creating a condition variable with the thread::cond create operation, which returns a unique token representing the condition variable. As with mutexes, the same token is used in all threads, and so you must make this token available (for example, through a shared variable) to all threads that access the condition variable. When the thread is ready to update the predicate, it first
locks the associated mutex. Then it notifies the condition variable with thread::cond notify and finally unlocks the mutex.
tsv::set tasks predicate 1 # Notify the condition variable, waking all waiting threads. # Each thread will block until it can lock the mutex. thread::cond notify $cond # Unlock the mutex. thread::mutex unlock $mutex
Example 21-15 shows the sequence for a waiting thread. When a thread is ready to test the predicate, it must first lock the mutex protecting it. If the predicate is true, the thread can continue processing, unlocking the mutex when appropriate. If the predicate is false, the thread executes thread::cond wait to wait for notification. The thread::cond wait command atomically unlocks the mutex and puts the thread into a wait state. Upon notification, the thread atomically locks the mutex (blocking until it can obtain it) and returns from the thread::cond wait command. It then tests the predicate, and repeats the process until the predicate is true.
# Test the predicate, if necessary waiting until it is true. while {![tsv::get tasks predicate]} { # Wait for notification on the condition variable. # thread::cond wait internally unlocks the mutex, # blocks until it receives notification, then locks # the mutex again before returning. thread::cond wait CHM TO PDF UNREGISTERED VERSION OF$cond $mutex CONVERTER By THETA-SOFTWARE } # We now hold the mutex and know the predicate is true. Do # whatever processing is desired, and unlock the mutex when # it is no longer needed.
Tcl's threading model greatly reduces the need for condition variables. It's usually much simpler to place a thread in its event loop with thread::wait, and then send it messages with thread::send. And for applications where you want a thread pool to handle jobs on demand, the Thread extension's built-in thread pool implementation is far easier than creating your own with condition variables. [ Team LiB ]
[ Team LiB ]
Thread Pools
A thread pool is a common multi-threaded design pattern. A thread pool consists of several worker threads that wait for jobs to perform. When a job is sent to the thread pool, one of the available worker threads processes it. If all worker threads are busy, either additional worker threads are created to handle the incoming jobs, or the jobs are queued until worker threads are available. The tpool namespace of the Thread extension provides several commands for creating and managing thread pools. Using these commands is much easier than trying to build your own thread pools from scratch using mutexes, condition variables, etc. Thread pool support was added to the Thread extension in version 2.5. The tpool::create command creates a thread pool, returning the ID of the new thread pool. There are several options to tpool::create that allow you to configure the behavior of the thread pool. The -minthreads option specifies the minimum number of threads in the pool. This number of threads is created when the thread pool is created, and as worker threads in the pool terminate, new worker threads are created to bring the number up to this minimum. The maxthreads option specifies the maximum number of worker threads allowed. If a job is posted to the thread pool and there are no idle worker threads available, a new worker thread is created to handle the job only if the number of worker threads won't exceed the maximum number. If the maximum has been reached, the job is queued until a worker thread is available. The -idletime option specifies the number of seconds that a worker thread waits for a new job before terminating itself to preserve system resources. And the -initcmd and exitcmd options provide scripts to respectively initialize newly created worker threads and clean up exiting worker threads. Once you have created a thread pool, you send jobs to it with the tpool::post command. A job consists of an arbitrary Tcl script to execute. The job is executed by the first available worker thread in the pool. If there are no idle worker threads, a new worker thread is created, as long as the number of worker threads doesn't exceed the thread pool maximum. If a new worker thread can't be created, the tpool::post command blocks until a worker thread can handle the job, but while blocked the posting thread still services its event loop. The return value of tpool::post is a job ID. To receive notification that a job is complete, your thread must call tpool::wait. The tpool::wait command blocks, but continues to service the thread's event loop while blocked. Additionally, the tpool::wait command can wait for several jobs simultaneously, returning when any of the jobs are complete. The return value of tpool::wait is a list of completed job IDs. After tpool::wait reports that a job is complete, you can call tpool::get to retrieve the result of the job, which is the return value of the last command executed in the job script. If the job execution resulted in an error, the error is "reflected" to the posting thread: tpool::get raises an error and the values of errorInfo and errorCode are updated accordingly. Finally, a thread pool can be preserved and released in much the same way as an individual thread. Each thread pool maintains an internal reference count, which is initially set to 0 upon creation. Any thread can increment the reference count afterwards by executing tpool::preserve, and decrement the reference count by executing tpool::release. If a call to tpool::release results in a reference count of 0 or less, the thread pool is marked for termination. Any further reference to a thread pool once it is marked for termination results in
[ Team LiB ]
thread::detach channel
thread::errorproc ? proc?
Registers a procedure to handle errors that occur when performing asynchronous thread::send commands. When called, proc receives two argument: the ID of the thread that generated the error, and the value of that thread's errorInfo variable. Concatenates the arguments and evaluates the resulting script under the mutex protection. If no mutex is specified, an internal static one is used for the duration of the evaluation. CHM TO PDF CONVERTER By THETA-SOFTWARE Returns boolean indicating whether or not the specified thread exists. Returns the current thread's ID. 8.4 or later.)
UNREGISTERED VERSION OF
thread::exists id thread::id
thread::join id Blocks until the target thread By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTERterminates. (Available only with Tcl thread::mutex create thread::mutex destroy mutex thread::mutex lock mutex thread::mutex unlock mutex thread::names thread::preserve ?id? thread::release ?wait? ?id? Returns a token for a newly created mutex. Destroys the mutex. Locks the mutex, blocking until it can gain exclusive access. Unlocks the mutex. Returns a list of the IDs of all running threads. Increments the reference count of the indicated thread, or the current thread if no id is given. Decrements the reference count of the indicated thread, or the current thread if no id is given. If the reference count is 0 or less, mark the thread for termination. If -wait is specified, the command blocks until the target thread terminates. Sends the script, to thread id. If -async is specified, do not wait for script to complete. Stores the result of script in varname, if provided. Transfers the open channel from the current thread to the main interpreter of the target thread. This command blocks until the target thread incorporates the channel. (Available only with Tcl 8.4 or later.) Terminates a prior thread::wait to cause a thread to exit. Deprecated in favor of thread::release. Enters the event loop.
thread::transfer id channel
thread::unwind thread::wait
The thread::configure command allows an application to query and set thread configuration options, in much the same way as the fconfigure command configures channels. Table 21-2 lists the available thread configuration options.
-eventmark int
Specifies the maximum number of pending scripts sent with thread::send that the thread accepts. Once the maximum is reached, subsequent thread::send messages to this script block until the number of pending scripts drops below the maximum. A value of 0 (default) allows an unlimited number of pending scripts. If true, the thread "unwinds" (terminates its event loop) on uncaught errors. Default is false.
-unwindonerror boolean
Returns boolean indicating whether the given element exists, or if no element is given, whether the shared array exists.
tsv::get array element ? Returns the value of the shared variable. If varname is varname? provided, the value is stored in the variable, and the command returns 1 if the element existed, 0 otherwise. tsv::incr array element ?increment? tsv::lappend array element value ?value ...? tsv::lindex array element index tsv::linsert array element index value ? value ...? tsv::llength array element Increments the shared variable like incr. Appends elements to the shared variable like lappend.
Returns the indicated element from the shared variable, similar to lindex. Atomically inserts elements into the shared variable, similar to linsert, but actually modifying the variable.
tsv::lock array arg ?arg Concatenates the args and evaluates the resulting script. ...? During script execution, the command locks the specified shared array with an internal mutex. tsv::lpop array element ?index? Atomically deletes the value at the index list position from the shared variable and returns the value deleted. The default index is 0. Atomically inserts the value at the index list position in the shared variable. The default index is 0.
tsv::lrange array element first last tsv::lreplace array element value ?value ...?
Returns the indicated range of elements from the shared variable, similar to lrange. Atomically replaces elements in the shared variable, similar to lreplace, but actually modifying the variable.
tsv::lsearch array Returns the index of the first element in the shared variable UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE element ?mode? pattern
matching the pattern, similar to lsearch. Supported modes are: -exact, -glob (default), and -regexp. Atomically renames the shared variable from old to new. Returns a list of all shared variable arrays, or those whose Creates and returns the name of an accessor command for the shared variable. Other tsv commands are available as subcommands of the accessor to manipulate the shared variable. Atomically returns the value of the shared variable and deletes the element.
names match the optional By pattern. UNREGISTERED VERSION OF CHM TO PDF CONVERTERglob THETA-SOFTWARE
tsv::set array element ? Sets the value of the shared variable, creating it if necessary. value? If value is omitted, the current value is returned. tsv::unset array ? element? Deletes the shared variable, or the entire array if no element is specified.
Creates a thread pool, returning the thread pool's ID. Table 21-5 describes supported configuration options. Sends a Tcl script to the specified thread pool for execution, returning the ID of the posted job. This command blocks (entering the event loop to service events) until a worker thread can service the job Blocks (entering the event loop to service events) until one or more of the jobs whose IDs are given by the jobList argument are completed. Returns a list of completed jobs from jobList. If provided, varName is set to a list of jobs from jobList that are still pending. Returns the result of the specified jobId. tpool::wait must have reported previously that the job is complete. If no error occurred in the job, the result is the return value of the last command executed in the job script. Any error encountered in job execution is in turn thrown by tpool::get, with the errorCode and errorInfo variables set appropriately. Returns a list of existing thread pool IDs. Increments the reference count of the indicated thread pool. Decrements the reference count of the indicated thread pool. If the reference count is 0 or less, mark the thread pool for termination.
The tpool::create command supports several options for configuring thread pools. Table 21-5 lists the available thread pool configuration options.
-maxthreads number
[ Team LiB ]
[ Team LiB ]
package require Tk
Although you can use tclkit to source .tcl files, tclkit is normally used to interpret Starkits, which have a .kit suffix. On UNIX, Starkits use the #! header to associate themselves with tclkit. Make sure that tclkit is in a directory named in your PATH environment variable. On Windows, you can associate tclkit.exe with the .kit extension. Mac OS X behaves like UNIX (yay!). On Mac Classic systems you can use the File Source menu to source .kit files. Creating Starkits is described on page 352.
Inside a Starkit
Tclkit uses the Virtual Filesystem extension to make records in a Metakit database look like files and directories to your application. Through a simple packaging step described shortly, you can easily put all of the Tcl scripts and other supporting files that make up your application into a single database file. The Virtual Filesystem (VFS) extension lets you transparently access these files through the regular file system interface (e.g., open, gets, source, even cd.) A Starkit is a Metakit database that stores an application. The great thing about a Starkit is that it is a single file so it is easy to manage. There is no need to unpack files or run an installer to set things up. Instead, you can distribute your application as two files: the Tclkit interpreter and the Starkit file. Both of these embed a virtual file system that include all the bits and pieces needed for Tcl/Tk and your application. The Tclkit file is platform-specific because it contains Tcl and all the other extensions in a compiled form. There are pre-compiled Tclkits for Windows, Macintosh, and many flavors of Unix. The Starkit file is platform-independent. You can use it with the appropriate Tclkit interpreter on different platforms.
and Jean-Claude Wippler. You organize your collection of application scripts, data files, binary graphics, and online documentation into a file system directory structure. Then you use sdx to wrap that into a Starkit. Creating your own Starkits is described on page 352. You can include binary extensions in a Starkit and dynamically load them. The load command automatically copies the shared library out of the VFS to a temporary location, and loads the library from that location. The temporary file is necessary because the host OS cannot find the library inside the Starkit. UNREGISTERED VERSION OFBinary extensions make the Starkit platform-specific, but it Starkit CHM TO PDF CONVERTER By THETA-SOFTWARE is possible to put libraries for different platforms into the Starkit. For example, the kitten.kit includes extensions for Windows, Linux, and Solaris. You can combine Tclkit and a Starkit into a Starpack. The advantage of this is that it reduces deployment to a single file. The main drawback is that the Starpack file is relatively large, and it is platform-specific. Use sdx to create Starpacks as described later. The Starkit archive contains a growing collection of Starkits that include applications, games, development tools, a Wiki, tutorials and documentation bundles. There is a copy of the archive on the CD-ROM, and its home page is: http://mini.net/sdarchive/ [ Team LiB ]
[ Team LiB ]
# Examine the contents glob xyz/* => xyz/tclhttpd3.4.3 # Open and read file inside the zip archive set in [open xyz/tclhttpd3.4.3/README] => rechan16 gets $in This HTTPD is written in Tcl and Tk. UNREGISTERED VERSION OF CHM TO PDF CONVERTER [ Team LiB ]
By THETA-SOFTWARE
[ Team LiB ]
In simple cases, sdx will create the directory structure for you. For example, if you have a selfcontained Tcl script called hello.tcl, then you can turn it into a Starkit like this:
The qwrap operation (i.e., "quick wrap") creates a new Starkit, hello.kit, that includes the original hello.tcl script organized into a virtual file system hierarchy with some additional support files. You run the Starkit like this:
tclkit hello.kit
On Unix systems you can also execute the Starkit directly. The file uses the #! syntax to specify that tclkit should run the file. On Windows, you can achieve the same effect by associating tclkit.exe with files that end in .kit.
Examining a Starkit
There are two ways to look at a Starkit. You can get a listing of the files with the sdx lsk operation, or you can use sdx unwrap to extract the files from the Starkit into a kitname.vfs directory. Example 22-2 shows the lsk output for hello.kit. The dates are in YY/MM/DD format:
hello.kit: dir 67 02/11/08 12:07 hello.kit/lib: dir hello.kit/lib/app-hello: UNREGISTERED43 02/11/08 12:10 VERSION OF CHM 72 02/11/08 12:07 lib/ main.tcl app-hello/
When you run the Starkit, its Metakit database is mounted into a Virtual File System that is visible to the Tcl application. Tclkit sources the main.tcl script it finds in the VFS. The starkit::startup procedure updates the auto_path to contain the Starkit's lib directory, so any packages stored there are available to the package mechanism. By convention, the application is put into a package with the name app-kitname. Example 22-4 shows the pkgIndex.tcl, which causes the package require app-hello command to source hello.tcl.
The dir variable is set by the package mechanism to be the directory containing the pkgIndex.tcl file. That the lib directory happens to be inside the virtual file system is completely transparent to the package mechanism. The package mechanism is described in more detail in Chapter 12.
Creating a Starpack
A Starpack contains a copy of Tclkit and your Starkit. Use sdx to create Starpacks. The runtime flag specifies which Tclkit application you want to merge with your Starkit. For example, to build a Windows Starpack out of our hello.tcl application:
There are 4 variations of the Windows Tclkit. One option uses zlib to automatically compress Tclkit and the Metakit database. These have .upx in their name. The other creates a consolemode application that does not include Tk. These have -sh in their name. The smallest Tclkit, tclkit-win32-sh.upx.exe, is only 450 K. Even tclkit-win32.upx.exe is only 907 K, so you really can create complete applications that fit easily onto a floppy disk! The auto-compress variation is also available on the Linux x86 builds as the tclkit-linuxx86.upx.bin runtime file. Check the Tclkit home page for the latest set of Tclkit builds: http://www.equi4.com/tclkit [ Team LiB ]
[ Team LiB ]
The starkit::topdir variable is set by starkit::startup to be the file name of the Starkit, which is also the root of the Virtual File System inside the Starkit. The value of starkit::topdir is an absolute pathname, so it is always valid. Example 22-5 shows a Starkit that manipulates its virtual file system.
Create the Starkit by putting the code in Example 22-5 into a file named main.tcl in the write.vfs directory. Then use sdx as shown in Example 22-6:
If you run the write.kit file more than once you will notice that the write.kit/data.new file does not persist between runs. This is because, by default, the Metakit database is modified in main memory and it is not written out to the Starkit file. If you want to store files long term, use the -writable flag to sdx:
[ Team LiB ]
[ Team LiB ]
Creating tclhttpd.kit
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
The Tcl Web Server, TclHttpd, has its source tree organized so you can run the server without any installation steps. This makes it very easy to put into a Starkit. For our first version, which we will refine later, all we need is a copy of the TclHttpd source code and a copy of the Standard Tcl Library, tcllib. I used the tcllib1.3 directory that was installed in the main lib directory of my desktop Tcl environment, and the tclhttpd3.4.3 source distribution. Example 22-7 shows the contents of the tclhttpd.vfs directory:
Example 22-8 shows the short main.tcl script used to start up the Starkit. The first two lines are common to all Starkits. The starkit::autoextend command is used to add the tcllib1.3 directory to the auto_path so the Standard Tcl Library packages are available. The last line uses starkit::topdir to find the TclHttpd startup script, bin/httpd.tcl.
Example 22-8 The main program for the TclHttpd Starkit, version 1
package require starkit starkit::startup starkit::autoextend [file join $starkit::topdir tcllib1.3] source [file join $starkit::topdir tclhttpd3.4.3/bin/httpd.tcl]
The Starkit is created and used as shown below, assuming tclhttpd.vfs is in the current directory. Note that command line options are passed through, so you can also use this Starkit to host an htdocs directory outside the Starkit. If you don't specify one, the htdocs tree inside the Starkit is used:
The standard structure introduced in Example 22-2 organizes packages under a lib directory. By convention, the version numbers are dropped from the package directory names. Because everything is self contained, there really isn't any need to have explicit version numbers in the directory names. The file system for the second version of tclhttpd.kit is shown in Example 22-9.
The main.tcl file is shown in Example 22-10. There is no need to adjust the auto_path because starkit::startup ensures that the lib directory is on it.
Example 22-10 The main program for the TclHttpd Starkit, version 2
package require starkit starkit::startup source [file join $starkit::topdir bin/httpd.tcl]
One of the first things I noticed about the tclhttpd.vfs was that tcllib took up far more space than the rest of TclHttpd. TclHttpd only uses a few of the many modules in tcllib. I ended up only adding the modules I needed in order to keep the Starkit smaller. Another way to solve this problem is to use the tcllib.kit Starkit that can be shared among applications. Creating shared Starkits is the topic of the next section. [ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHMTclkitPDF CONVERTERlooks for its main.tcl file. This is true Whenever a Starkit is sourced, TO mounts its VFS and By THETA-SOFTWARE
Another side effect of starkit::startup is to set starkit::topdir. However, this variable is only set once. If you source other Starkits that call starkit::startup, then the starkit::topdir value is not disturbed. This behavior changed in Tclkit 8.4.2. In earlier versions, starkit::topdir was set by each Starkit, so you had to worry about saving its value if you loaded other Starkits. If you source tcllib.kit and cannot package require its packages, check its main.tcl. If it uses starkit::topdir in the non-Starkit case, then it is an older version. Simply unwrap it, make its main.tcl look like Example 22-11, and wrap it back up to fix the problem. The starkit::startup procedure determines the environment of the application by making a series of tests against the script environment. Its return value helps your main.tcl script distinguish between starting out as the main Starkit, or being loaded into another Starkit as a library. Table 22-1 lists the return values of the starkit::startup procedure in the order they are checked:
unwrapped The Starkit was run out of its unpacked vfs directory. tclhttpd plugin service sourced The Starkit was sourced into TclHttpd. The Starkit was sourced in the browser plugin. The Starkit was run in an NT service. The Starkit was sourced by another Starkit.
The easiest way to organize your shared Starkits is to put them into the same directory. Example 22-12 shows how the TclHttpd Starkit is modified to load the tcllib Starkit from the same directory.
[ Team LiB ]
[ Team LiB ]
Metakit
This section provides OF CHM TO PDF CONVERTER By that is used by Starkits UNREGISTERED VERSION a short overview of the Metakit databaseTHETA-SOFTWARE to store their data. You do not need to program Metakit directly to use Starkits because of the transparent VFS interface. However, Metakit is an easy-to-use database that provides more power than storing data in flat files, but not as much power (or overhead) as a full SQL database engine. Metakit has a simple, flexible programming API and an efficient implementation. By storing your application data in a Metakit table, you can have persistent data that VERSION OF CHM TO You CONVERTER By a file separate from your UNREGISTEREDlives with your application. PDFcan store the data inTHETA-SOFTWARE application, or right inside the application Starkit itself.
This Chapter gives a few introductory examples and explains some of the other features that are available. This Chapter does not provide a complete reference. The following URLs are excellent guides to the Tcl interface for Metakit. The first URL is also on the CD as sdarchive/doc/mk4dok.kit. http://www.equi4.com/metakit/tcl.html http://www.equi4.com/metakit/wiki.cgi/mk4tcl http://www.markroseman.com/tcl/mktcl.html
The mk::view command has several operations to inspect and manipulate views. The layout operation queries or sets the properties of a view. Given only a view, the layout operation returns the properties defined for the view. Each property has a type, and nested views are represented as a nested list of the property name and its list of properties. Given a set of properties, the layout operation defines new properties for a view. This may involve adding or deleting properties from any existing rows in the table. Example 22-14 shows the layout of the dirs view in a Starkit. The files property is a nested view, which provides a natural way to represent a hierarchical filesystem. The example gets the name property of tclhttpd.dirs!0.files!0, which is the first file in the first directory in the view:
Of course, real applications will want to query views for values that have certain properties. The mk::select command returns the row numbers for rows that match given criteria, or all the row numbers if no matching criteria are given. You can match on multiple properties, and there are flags that control how the match is done. For example, you can do numeric comparisons, regular expression or glob matches, and min/max comparisons. Example 22-15 shows two forms of mk::select. The KitWalk procedure enumerates the files in a given directory, which is the view $tag.dirs!$dir.files. Then it queries the row indices for the $tag.dirs view whose parent property equals $dir, and calls itself recursively to process the child directories. KitWalk provides a similar function to sdx lsk:
incr indent 2 # List the plain files in the directory, if any foreach j [mk::select $tag.dirs!$dir.files] { puts "$prefix [mk::get $tag.dirs!$dir.files!$j name]" }
The mk::set command sets property values, and the mk::row command modifies rows. Example 22-17 adds a few values to the test view. Note that you can insert into rows beyond the end of the view and it is automatically extended. If you only define some properties for a row, the other properties get default values. Other mk::row operations include insert, replace, and delete.
To test this, put this example into the main.tcl of a trivial Starkit. When you create the Starkit, remember the -writable option with sdx:
The alternative to storing data in the Starkit file is to have a separate Metakit data file. This is the approach taken by Wikit. The wikit.kit file is the Wikit application, and the wikit.tkd file is a Metakit database file that stores all the pages in the Wiki. (Creating a new Wiki is simple, just specify a different .tkd file name.) The advantage of having a separate Metakit file is that you can easily maintain your application by unwrapping and wrapping your application Starkit. Otherwise, if you put the application data directly into the Starkit you have to extract it and restore it as an additional maintenance step. In that case, you must use the mk::file save UNREGISTEREDoperations to save and TO PDF CONVERTER By THETA-SOFTWARE and load VERSION OF CHM restore your Metakit views to a file. A Wiki is a web site that users can easily edit using a simplified markup syntax. Wikit is a Wiki implementation in Tcl using Metakit to store pages. It can run as a stand-alone Tk application, a GGI script, as its own little web server, or embedded into another application as a documentation bundle. There is a copy of wikit.tkd on the CD-ROM. For example, you run a stand alone copy of the Tcler's Wiki PDF UNREGISTERED VERSION OF CHM TOas: CONVERTER By THETA-SOFTWARE
tclkit wikit.kit wikit.tkd The live Wiki is at wiki.tcl.tk[*], and you can find out more about Wikit at:
[*]
[ Team LiB ]
More Ideas
This Chapter has provided a brief introduction to Tclkit, Starkits, and Metakit. This should be enough to help you get started creating your own Starkits and using Metakit for persistent storage. You should consult the documentation on the Web for more detailed reference material.
Document Bundles
The Starkit archive includes a number of documentation bundles. For example, mk4dok.kit is a Starkit that contains all the MetaKit documentation. These document bundles are all based on Wikit. It is very easy to create Wiki-style documentation for your application and then bundle it up as a Metakit file. You can load wikit.kit and your .tkd document bundle into your application and use the "local" Wikit interface to display your documentation. For example, the critcl Starkit displays its help with this simple command:
Self-Updating Applications
The client in a client-server application is an ideal candidate for a self-updating application. The front-end client is a Starkit with some simple startup logic that connects to a server via HTTP and displays a pretty splash screen. The server, which is often based on TclHttpd, delivers code updates to the client. The client caches the code in the VFS inside the Starkit. The application is maintained on the server, and clients automatically get updated as they are used. This scenario has the same deployment advantage as browser-based applications: you deploy a "thin-client" to desktops that rarely, if ever, changes and you update the application code on the server. In addition, this application structure lets you create a nice client front-end that uses Tcl/Tk instead of HTML, yet still have the benefit of an easy to manage server-side installation of the application code. This design pattern is being used for a number of largescale commercial application deployments with considerable success. A similar system is used with the Starkit archive. If you do:
The sdx application contacts the web server running the archive and checks for any updates available for the Starkit. Only the differences are transmitted, so updates are quick, and they are automatically applied to your copy of the Starkit. This should work for all the Starkits in the snapshot of the archive on the CD-ROM.
Simple Installers
In some cases you simply must install a collection of files as part of your application. It is very easy to include those files in the VFS, and then extract them into the local file system the first time your application runs. Or, you can create a traditional "installer" that unpacks the entire application from the Starkit (or Starpack).
[ Team LiB ]
[ Team LiB ]
bindings and the widgets creates a flexible and powerful system for managing events. You can create your own bindtags and dynamically change the bindtags for a widget to support mode changes in your application. A concept related to binding is focus. At any given time, one of the widgets has the input focus, and keyboard events are directed to it. There are two general approaches to focusing: give focus to the widget under the mouse, or explicitly set the focus to a particular widget. Tk provides commands to change focus so you can implement either style of focus management. To support modal dialog boxes, you can forcibly grab the focus away from other widgets. Chapter 39 describes focus, grabs, and dialogs. The basic structure of a Tk script begins by creating widgets and arranging them with a geometry manager, and then binding actions to the widgets. After the interpreter processes the commands that initialize the user interface, the event loop is entered and your application begins running. If you use wish interactively, it creates and displays an empty main window and gives you a command-line prompt. With this interface, your keyboard commands are handled by the event loop, so you can build your Tk interface gradually. As we will see, you will be able to change virtually all aspects of your application interactively. [ Team LiB ]
[ Team LiB ]
Hello, World! in Tk
Our first Tk script is very CHM It creates a button that prints "Hello, World!" to standard UNREGISTERED VERSION OFsimple.TO PDF CONVERTER By THETA-SOFTWARE output when you press it. Above the button widget is a title bar that is provided by the window manager, which in this case is twm under X windows:
#!/usr/local/bin/wish button .hello -text Hello \ -command {puts stdout "Hello, World!"} pack .hello -padx 20 -pady 10
#!/usr/local/bin/wish
This special line is necessary if the script is in a file that will be used like other UNIX command files. Chapter 2 describes how to set up scripts on different platforms. There are two Tcl commands in the script: one to create the button, and one to make it visible on the display. The button command creates an instance of a button:
button .hello -text Hello \ -command {puts stdout "Hello, World!"} => .hello
The name of the button is .hello. The label on the button is Hello, and the command associated with the button is:
The pack command maps the button onto the screen. Some padding parameters are supplied, so there is space around the button:
If you type these two commands into wish, you will not see anything happen when the button command is given. After the pack command, though, you will see the empty main window shrink to be just big enough to contain the button and its padding. The behavior of the packer will be discussed further in Chapters 24 and 25. Tk uses an object-based system for creating and naming widgets. Associated with each class of widget (e.g., Button) is a command that creates instances of that class of widget. As the widget is created, a new Tcl command is defined that operates on that instance of the widget. Example 23-1 creates a button named .hello, and we can operate on the button using its name as a Tcl command. For example, we can cause the button to highlight a few times:
.hello flash
Tk has widget classes and instances, but it is not fully object oriented. It is not possible to subclass a widget class and use inheritance. Instead, Tk provides very flexible widgets that can be configured in many different ways to tune their appearance. The resource database can store configuration information that is shared by many widgets, and new classes can be introduced to group resources. Widget behavior is shared by using binding tags that group bindings. Instead of building class hierarchies, Tk uses composition to assemble widgets with shared behavior and attributes. [ Team LiB ]
[ Team LiB ]
Naming Tk Widgets
The period in the name of the button instance, .hello, is By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER required. Tk uses a naming system for the widgets that reflects their position in a hierarchy of widgets. The root of the hierarchy is the main window of the application, and its name is simply a dot (i.e., .). This is similar to the naming convention for directories in UNIX where the root directory is named /, and then / is used to separate components of a file name. Tk uses a dot in the same way. Each widget that is a child of the main window is named something like .foo. A child widget of .foo would be .foo.bar, and so on. OF as file systems CONVERTER that are containers for files UNREGISTERED VERSION Just CHM TO PDF have directories By THETA-SOFTWARE and other directories, the Tk window hierarchy uses frame widgets that are containers for widgets and other frames. Each component of a Tk pathname must start with a lowercase letter or a number. Obviously, a component cannot include a period, either. The lower case restriction avoids a conflict with resource class names that begin with an upper case letter. A resource name can include Tk pathname components and Tk widget classes, and case is used to distinguish them. Chapter 31 describes resources in detail.
There is one drawback to the Tk widget naming system. If your interface changes enough it can result in some widgets changing their position in the widget hierarchy. In that case they may need to change their name. You can insulate yourself from this programming nuisance by using variables to hold the names of important widgets. Use a variable reference instead of widget pathnames in case you need to change things, or if you want to reuse your code in a different interface. The widget creating commands return the name of the widget:
[ Team LiB ]
[ Team LiB ]
Configuring Tk Widgets
Example 23-1 illustrates a style of named parameter passing that is prevalent in the Tk commands. Pairs of arguments specify the attributes of a widget. The attribute names begin with -, such as -text, and the next argument is the value of that attribute. Even the simplest Tk widget can have a dozen or more attributes that can be specified this way, and complex widgets can have 30 or more attributes. However, the beauty of Tk is that you need to specify only the attributes for which the default value is not good enough. This is illustrated by the simplicity of the Hello, World example. Finally, each widget instance supports a configure operation, which can be abbreviated to config, that can query and change these attributes. The syntax for config uses the same named argument pairs used when you create the widget. For example, we can change the background color of the button to red even after it has been created and mapped onto the screen:
Widget attributes can be redefined any time, even the text and command that were set when the button was created. The following command changes .hello into a goodbye button:
You can find out more details about a widget attribute by using configure without a value:
The returned information includes the command-line switch, the resource name, the class name, the default value, and the current value, which is last. The class and resource name have to do with the resource mechanism described in Chapter 31. If you only specify configure and no attribute, then a list of the configuration information for all widget attributes is returned. Example 23-2 uses this to print out all the information about a widget:
puts $out [format "%-20s %-10s %s" Attribute Default Value] foreach item [$w configure] { puts $out [format "%-20s %-10s %s" \ [lindex $item 0] [lindex $item 3] \ [lindex $item 4]] } }
[ Team LiB ]
The tables in this book list widget attributes by their resource name.
You need to know these naming conventions if you specify widget attributes via the resource mechanism. The command-line option can be derived from the resource name by mapping it to all lowercase. The primary advantage of using resources to specify attributes is that you do not have to litter your code with attribute specifications. With just a few resource database entries you can specify attributes for all your widgets. In addition, if attributes are specified with resources, users can provide alternate resource specifications in order to override the values supplied by the application. For attributes like colors and fonts, this feature can be important to users. Resource specifications are described in detail in Chapter 31.
% man button
The tkman program provides a very nice graphical user interface to the UNIX manual pages. On the Macintosh platform, the manual pages are formatted into HTML documents that you can find in the HTML Docs folder of the Tcl/Tk distribution. On Windows, the manual pages are formatted into Help documents. You can find the manual pages on the web at: http://www.tcl.tk/man/ There are a large number of attributes that are common across most of the Tk widgets. These are described in a separate man page under the name options. Each man page begins with a STANDARD OPTIONS section that lists which of these standard attributes apply, but you have to
look at the options man page for the description. In contrast, the tables in this book always list all widget attributes. [ Team LiB ]
[ Team LiB ]
Widget Commands
Table 23-1 lists commands that create widgets. There are 18 different widgets in Tk, although 4 of them are variations on a button, and 5 are devoted to different flavors of text display.
checkbutton 458 Create a toggle button that is linked to a Tcl variable. entry frame label labelframe listbox menu menubutton message 507 Create a one-line text entry widget. 485 Create a container widget used with geometry managers. 490 Create a read-only, multiline text label. 485 Create a container widget used with geometry managers that has extra label attributes. (Tk 8.4) 519 Create a line-oriented, scrolling text widget. 462 Create a menu. 462 Create a button that posts a menu. 493 Create a read-only, multiline text message.
panedwindow 429 Create a container widget that controls other widgets in a paned fashion. (Tk 8.4) radiobutton 458 Create one of a set of radio buttons linked to one variable. scale scrollbar spinbox text 495 Create a scale widget that adjusts the value of a variable. 499 Create a scrollbar that can be linked to another widget. 511 Create a spinbox widget that is a composite entry widget with button controls for adjusting the value. (Tk 8.4) 531 Create a general-purpose, editable text widget.
Command toplevel
Pg.
Description
Table 23-2. Tk widget-manipulation commands UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Command bell bind bindtags Pg. 497 Ring the terminal bell device. 435 Bind a Tcl command to an event. 437 Create binding classes and control binding inheritance. Description
clipboard 594 Manipulate the clipboard. destroy event focus font grab grid image lower option pack place raise 605 Delete a widget. 446 Define and generate virtual events. 603 Control the input focus. 641 Set and query font attributes and measurements. 604 Steal the input focus from other widgets. 419 Arrange widgets into a grid with constraints. 626 Create and manipulate images. 409 Lower a window in the stacking order. 477 Set and query the resources database. 409 Pack a widget in the display with constraints. 427 Place a widget in the display with positions. 409 Raise a window in the stacking order.
selection 593 Manipulate the selection. send tk tkerror tkwait update winfo wm 648 Send a Tcl command to another Tk application. 669 Query or set the application name or global caret. 202 Handler for background errors. 605 Wait for an event. 608 Update the display by going through the event loop. 663 Query window state. 657 Interact with the window manager.
Support Procedures
Table 23-3 lists several support procedures that implement standard dialogs, option menus, and other facilities.
621 Install bisque family of colors. 602 Dialog to select a color. (Tk 4.2) 600 Dialog to select a directory. (Tk 8.2) 599 Create simple dialogs.
tk_focusFollowsMouse 603 Install mouse-tracking focus model. tk_focusNext tk_focusPrev tk_getOpenFile tk_getSaveFile tk_messageBox tk_optionMenu tk_popup tk_setPalette [ Team LiB ] 604 Focus on next widget in tab order. 604 Focus on previous widget in tab order. 600 Dialog to open an existing file. (Tk 4.2) 600 Dialog to open a new file. (Tk 4.2) 600 Message dialog. (Tk 4.2) 465 Create an option menu. 465 Create a pop-up menu. 621 Set the standard color palette. (Tk 4.2)
[ Team LiB ]
Tix
Tix was created by Ioi Lam, and is now supported by a team of volunteers. It includes several widgets and an infrastructure for creating new widgets in Tcl. Notable features include balloon help, tabbed windows, paned window, and a hierarchy browser. This is a C-based toolkit, although it includes a number of compound widgets created in Tcl. http://tix.sourceforge.net/
[incr Tk]
and [incr
Widgets]
[incr Tk] is a C-based framework for creating compound widgets using the [incr Tcl] object system. [incr Widgets] is the widget set created using that framework. It includes loads of widgets, from simple labeled-entry widgets up through HTML display widgets. These tools are described in Chad Smith's book, [incr Tcl] from the Ground Up (Osborne-McGraw Hill, 1999). http://incrtcl.sourceforge.net
BWidgets
BWidgets is a set of Tcl-based widgets. It includes a variety of compound widgets, including a tabbed notebook, combobox, and hierarchy browser. It is hosted at the Standard Tcl Lib (tcllib) web site: http://www.sourceforge.net/projects/tcllib
TkTable
TkTable is combination of a gridding geometry manager and several text-oriented widgets. It makes it easy to lay out tabular data like spreadsheets, and it also provides a large amount of control over the formatting of cells and their data. http://www.sourceforge.net/projects/tktable [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
ExecLog
Our first example provides a simple user interface to running another program with the exec command. The interface consists of two buttons, Run it and Quit, an entry widget in which to enter a command, and a text widget in which to log the results of running the program. The script runs the program in a pipeline and uses the fileevent command to wait for output. This structure lets the user interface remain responsive while the program executes. You could use this to run make, for example, and it would save the results in the log. The complete example is given first, and then its commands are discussed in more detail.
#!/usr/local/bin/wish # execlog - run a program with exec and log the output # Set window title wm title . ExecLog # Create a frame for buttons and entry. frame .top -borderwidth 10 pack .top -side top -fill x # Create the command buttons. button .top.quit -text Quit -command exit set but [button .top.run -text "Run it" -command Run] pack .top.quit .top.run -side right # Create a labeled entry for the command label .top.l -text Command: -padx 0 entry .top.cmd -width 20 -relief sunken \ -textvariable command pack .top.l -side left pack .top.cmd -side left -fill x -expand true
# Set up key binding equivalents to the buttons bind .top.cmd <Return> Run bind .top.cmd <Control-c> Stop focus .top.cmd # Create a text widget to log PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO the output frame .t set log [text .t.log -width 80 -height 10 \ -borderwidth 2 -relief raised -setgrid true \ -yscrollcommand {.t.scroll set}] scrollbarVERSION OF CHM TO PDF CONVERTER UNREGISTERED .t.scroll -command {.t.log yview} pack .t.scroll -side right -fill y pack .t.log -side left -fill both -expand true pack .t -side top -fill both -expand true # Run the program and arrange to read its input proc Run {} { global command input log but if [catch {open "|$command |& cat"} input] { $log insert end $input\n } else { fileevent $input readable Log $log insert end $command\n $but config -text Stop -command Stop } } # Read and log output from the program proc Log {} { global input log if [eof $input] { Stop } else { gets $input line $log insert end $line\n $log see end } } # Stop the program and fix up the button proc Stop {} { global input but catch {close $input} $but config -text "Run it" -command Run }
By THETA-SOFTWARE
Window Title
The first command sets the title that appears in the title bar implemented by the window manager. Recall that dot (i.e., .) is the name of the main window:
wm title . ExecLog
The wm command communicates with the window manager. The window manager is the program that lets you open, close, and resize windows. It implements the title bar for the window and probably some small buttons to close or resize the window. Different window managers have a distinctive look; the figure shows a title bar from twm, a window manager for X.
The frame is positioned in the main window. The default packing side is the top, so -side top is redundant here, but it is used for clarity. The -fill x packing option makes the frame fill out to the whole width of the main window:
Command Buttons
Two buttons are created: one to run the command, the other to quit the program. Their names, .top.quit and .top.run, imply that they are children of the .top frame. This affects the pack command, which positions widgets inside their parent by default:
button .top.quit -text Quit -command exit set but [button .top.run -text "Run it" \ -command Run] pack .top.quit .top.run -side right
label .top.l -text Command: -padx 0 entry .top.cmd -width 20 -relief sunken \ -textvariable command
The label and entry are positioned to the left inside the .top frame. The additional packing parameters to the entry allow it to expand its packing space and fill up that extra area with its UNREGISTERED VERSION OF CHM packing space and display By THETA-SOFTWARE display. The difference between TO PDF CONVERTER space is discussed in Chapter 25 on page 399:
pack .top.l -side left pack .top.cmd -side left -fill x -expand true
bind .top.cmd <Return> Run bind .top.cmd <Control-c> Stop focus .top.cmd
frame .t set log [text .t.log -width 80 -height 10 \ -borderwidth 2 -relief raised -setgrid true\ -yscrollcommand {.t.scroll set}] scrollbar .t.scroll -command {.t.log yview} pack .t.scroll -side right -fill y pack .t.log -side left -fill both -expand true pack .t -side top -fill both -expand true
A side effect of creating a Tk widget is the creation of a new Tcl command that operates on that widget. The name of the Tcl command is the same as the Tk pathname of the widget. In this script, the text widget command, .t.log, is needed in several places. However, it is a good idea to put the Tk pathname of an important widget into a variable because that pathname can change if you reorganize your user interface. The disadvantage of this is that you must declare the variable with global inside procedures. The variable log is used for this purpose in this example to demonstrate this style.
The pipeline diverts error output from the command through the cat program. If you do not use cat like this, then the error output from the pipeline, if any, shows up as an error message when the pipeline is closed. In this example it turns out to be awkward to distinguish between errors generated from the program and errors generated because of the way the Stop procedure is implemented. Furthermore, some programs interleave output and error output, and you might want to see the error output in order instead of all at the end. If the pipeline is opened successfully, then a callback is set up using the fileevent command. Whenever the pipeline generates output, then the script can read data from it. The Log procedure is registered to be called whenever the pipeline is readable:
The command (or the error message) is inserted into the log. This is done using the name of the text widget, which is stored in the log variable, as a Tcl command. The value of the command is appended to the log, and a newline is added so that its output will appear on the next line.
The text widget's insert function takes two parameters: a mark and a string to insert at that mark. The symbolic mark end represents the end of the contents of the text widget. The run button is changed into a stop button after the program begins. This avoids a cluttered interface and demonstrates the dynamic nature of a Tk interface. Again, because this button is used in a few different places in the script, its pathname has been stored in the variable but:
UNREGISTERED VERSION StopCHM TO PDF CONVERTER By THETA-SOFTWARE OF -command Stop $but config -text
if [eof $input] { Stop } else { gets $input line $log insert end $line\n $log see end }
catch {close $input} $but config -text "Run it" -command Run
In most cases, closing the pipeline is adequate to kill the job. On UNIX, this results in a signal, SIGPIPE, being delivered to the program the next time it does a write to its standard output. There is no built-in way to kill a process, but you can exec the UNIX kill program. The pid command returns the process IDs from the pipeline:
If you need more sophisticated control over another process, you should check out the expect Tcl extension, which is described in the book Exploring Expect (Don Libes, O'Reilly & Associates,
Inc., 1995). Expect provides powerful control over interactive programs. You can write Tcl scripts that send input to interactive programs and pattern match on their output. Expect is designed to automate the use of programs that were designed for interactive use.
Cross-Platform Issues
This script will run on UNIX and Windows, but not on Macintosh because there is no exec command. One other problem is the binding for <Control-c> to cancel the job. This is UNIXlike, while Windows users expect <Escape> to cancel a job, and Macintosh users expect <Command-period>. Platform_CancelEvent defines a virtual event, <<Cancel>>, and Stop is bound to it:
There are other virtual events already defined by Tk. The event command and virtual events are described on page 446. [ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 24-3 A browser for the code examples in the book
#!/usr/local/bin/wish # Browser for the Tcl and Tk examples in the book. # browse(dir) is the directory containing all the tcl files # Please edit to match your system configuration. switch $tcl_platform(platform) { "unix" {set browse(dir) /cdrom/tclbook2/exsource} "windows" {set browse(dir) D:/exsource} "macintosh" {set browse(dir) /tclbook2/exsource} } wm minsize . 30 5 wm title . "Tcl Example Browser" # Create a row of buttons along the top set f [frame .menubar] pack $f -fill x button $f.quit -text Quit -command exit button $f.next -text Next -command Next button $f.prev -text Previous -command Previous # The Run and Reset buttons use EvalEcho that # is defined by the Tcl shell in Example 244 on page 389 button $f.load -text Run -command Run button $f.reset -text Reset -command Reset pack $f.quit $f.reset $f.load $f.next $f.prev -side right # A label identifies the current example label $f.label -textvariable browse(current) pack $f.label -side right -fill x -expand true # Create the menubutton and menu menubutton $f.ex -text Examples -menu $f.ex.m pack $f.ex -side left set m [menu $f.ex.m]
# Create the text to display the example # Scrolled_Text is defined in Example 331 on page 500 set browse(text) [Scrolled_Text .body \ -width 80 -height 10\ -setgrid true] pack .body -fill both -expand true # Look through the example files for their ID number. foreach f [lsort -dictionary [glob [file join $browse(dir) *]]] { if [catch {open $f} in] { puts stderr "Cannot open $f: $in" continue } while {[gets $in line] >= 0} { if [regexp {^# Example ([0-9]+)-([0-9]+)} $line \ x chap ex] { lappend examples($chap) $ex lappend browse(list) $f # Read example title gets $in line set title($chap-$ex) [string trim $line "# "] set file($chap-$ex) $f close $in break } } } # Create two levels of cascaded menus. # The first level divides up the chapters into chunks. # The second level has an entry for each example. option add *Menu.tearOff 0 set limit 8 set c 0; set i 0 foreach chap [lsort -integer [array names examples]] { if {$i == 0} { $m add cascade -label "Chapter $chap..." \ -menu $m.$c set sub1 [menu $m.$c] incr c } set i [expr ($i +1) % $limit] $sub1 add cascade -label "Chapter $chap" -menu $sub1.sub$i set sub2 [menu $sub1.sub$i] foreach ex [lsort -integer $examples($chap)] { $sub2 add command -label "$chap-$ex $title($chap-$ex)" \ -command [list Browse $file($chap-$ex)] } } # Display a specified file. The label is updated to # reflect what is displayed, and the text is left
# in a read-only mode after the example is inserted. proc Browse { file } { global browse set browse(current) [file tail $file] set browse(curix) [lsearch $browse(list) $file] set t $browse(text) $t config -state normal UNREGISTERED VERSION OF CHM TO PDF CONVERTER By $t delete 1.0 end if [catch {open $file} in] { $t insert end $in } else { $t insert end [read $in] close $in UNREGISTERED VERSION OF CHM TO PDF CONVERTER By } $t config -state disabled } # Browse the next and previous files in the list set browse(curix) -1 proc Next {} { global browse if {$browse(curix) < [llength $browse(list)] - 1} { incr browse(curix) } Browse [lindex $browse(list) $browse(curix)] } proc Previous {} { global browse if {$browse(curix) > 0} { incr browse(curix) -1 } Browse [lindex $browse(list) $browse(curix)] } # Run the example in the shell proc Run {} { global browse EvalEcho [list source \ [file join $browse(dir) $browse(current)]] } # Reset the slave in the eval server proc Reset {} { EvalEcho reset }
THETA-SOFTWARE
THETA-SOFTWARE
window. The arguments specify the minimum width and height. These values can be interpreted in two ways. By default they are pixel values. However, if an internal widget has enabled geometry gridding, then the dimensions are in grid units of that widget. In this case the text widget enables gridding with its setgrid attribute, so the minimum size of the window is set so that the text window is at least 30 characters wide by five lines high:
wm minsize . 30 5
In older versions of Tk, Tk 3.6, gridding also enabled interactive resizing of the window. Interactive resizing is enabled by default in Tk 4.0 and later.
foreach f [lsort -dictionary [glob -directory $browse(dir) *]] { if {[catch {open $f} in]} { puts stderr "Cannot open $f: $in" continue } while {[gets $in line] >= 0} { if {[regexp {^# Example ([0-9]+)-([0-9]+)} $line \ x chap ex]} { lappend examples($chap) $ex lappend browse(list) $f # Read example title gets $in line set title($chap-$ex) [string trim $line "# "] set file($chap-$ex) $f close $in break }
} }
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE # The Hello, World! program
The regexp picks out the example numbers with the ([0-9]+)-([0-9]+) part of the pattern, and these are assigned to the chap and ex variables. The x variable is assigned the value of the whole match, which is more than we are interested in. Once the example number is found, the UNREGISTEREDisVERSION OF CHM TO PDF CONVERTERthe end of the foreach loop the next line read to get the description of the example. At By THETA-SOFTWARE examples array has an element defined for each chapter, and the value of each element is a list of the examples for that chapter.
# Example 1-1
Cascaded Menus
The values in the examples array are used to build up a cascaded menu structure. First a menubutton is created that will post the main menu. It is associated with the main menu with its menu attribute. The menu must be a child of the menubutton for its display to work properly:
There are too many chapters to put them all into one menu. The main menu has a cascade entry for each group of eight chapters. Each of these submenus has a cascade entry for each chapter in the group, and each chapter has a menu of all its examples. Once again, the submenus are defined as a child of their parent menu. Note the inconsistency between menu entries and buttons. Their text is defined with the -label option, not -text. Other than this they are much like buttons. Chapter 30 describes menus in more detail. The code is repeated here:
set limit 8 ; set c 0 ; set i 0 foreach key [lsort -integer [array names examples]] { if {$i == 0} { $m add cascade -label "Chapter $key..." \ -menu $m.$c set sub1 [menu $m.$c] incr c } set i [expr {($i +1) % $limit}] $sub1 add cascade -label "Chapter $key" -menu $sub1.sub$i set sub2 [menu $sub1.sub$i] foreach ex [lsort -integer $examples($key)] { $sub2 add command -label "$key-$ex $title($key-$ex)" \ -command [list Browse $file($key-$ex)] } }
global browse set browse(current) [file tail $file] $t config -state normal $t insert end [read $in] $t config -state disabled
[ Team LiB ]
[ Team LiB ]
A Tcl Shell
This section demonstrates the text widget with a simple Tcl shell application. It uses UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWAREa text widget to prompt for commands and display their results. It uses a second Tcl interpreter to evaluate the commands you type. This dual interpreter structure is used by the console built into the Windows and Macintosh versions of wish. The TkCon application written by Jeff Hobbs is an even more elaborate console that has many features to support interactive Tcl use:
http://tkcon.sourceforge.net/ UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 24-4 is written to be used with the browser from Example 24-3 in the same application. The browser's Run button runs the current example in the shell. An alternative is to have the shell run as a separate process and use the send command to communicate Tcl commands between separate applications. That alternative is shown in Example 43-2 on page 651.
# Insert the prompt and initialize the limit mark set eval(prompt) "tcl> " $t insert insert $eval(prompt) prompt $t mark set limit insert $t mark gravity limit left focus $t set eval(text) $t # Key bindings that limit input and eval things. The break in # the bindings skips the default Text binding for the event. bind $t <Return> {EvalTypein ; break} bind $t <BackSpace> { if {[%W tag nextrange sel 1.0 end] != ""} { %W delete sel.first sel.last } elseif {[%W compare insert > limit]} { %W delete insert-1c
%W see insert } break } bind $t <Key> { if [%W compare insert < limit] { %W mark set insert end } } # Evaluate everything between limit and end as a Tcl command proc EvalTypein {} { global eval $eval(text) insert insert \n set command [$eval(text) get limit end] if [info complete $command] { $eval(text) mark set limit insert Eval $command } } # Echo the command and evaluate it proc EvalEcho {command} { global eval $eval(text) mark set insert end $eval(text) insert insert $command\n Eval $command } # Evaluate a command and display its result proc Eval {command} { global eval $eval(text) mark set insert end if [catch {$eval(slave) eval $command} result] { $eval(text) insert insert $result error } else { $eval(text) insert insert $result result } if {[$eval(text) compare insert != "insert linestart"]} { $eval(text) insert insert \n } $eval(text) insert insert $eval(prompt) prompt $eval(text) see insert $eval(text) mark set limit insert return } # Create and initialize the slave interpreter proc SlaveInit {slave} { interp create $slave load {} Tk $slave interp alias $slave reset {} ResetAlias $slave interp alias $slave puts {} PutsAlias $slave
return $slave } # The reset alias deletes the slave and starts a new one proc ResetAlias {slave} { interp delete $slave SlaveInit $slave UNREGISTERED VERSION OF CHM }
# The puts alias puts stdout and stderr into the text widget proc PutsAlias {slave args} { if {[llength $args] > 3} { UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE error "invalid arguments" } set newline "\n" if {[string match "-nonewline" [lindex $args 0]]} { set newline "" set args [lreplace $args 0 0] } if {[llength $args] == 1} { set chan stdout set string [lindex $args 0]$newline } else { set chan [lindex $args 0] set string [lindex $args 1]$newline } if [regexp (stdout|stderr) $chan] { global eval $eval(text) mark gravity limit right $eval(text) insert limit $string output $eval(text) see limit $eval(text) mark gravity limit left } else { puts -nonewline $chan $string } } set eval(slave) [SlaveInit shell]
Text tags are used to give different regions of text difference appearances. A tag applies to a range of text. The tags are configured at the beginning of the script and they are applied when text is inserted. Chapter 36 describes the text widget in more detail.
Multiple Interpreters
The SlaveInit procedure creates another interpreter to evaluate the commands. This prevents conflicts with the procedures and variables used to implement the shell. Initially, the slave interpreter only has access to Tcl commands. The load command installs the Tk commands, and it creates a new top-level window that is "." for the slave interpreter. Chapter 20 describes how you can embed the window of the slave within other frames. The shell interpreter is not created with the -safe flag, so it can do anything. For example, if you type exit, it will exit the whole application. The SlaveInit procedure installs an alias, reset, that just deletes the slave interpreter and creates a new one. You can use this to clean up after working in the shell for a while. Chapter 19 describes the interp command in detail.
[ Team LiB ]
[ Team LiB ]
For each individual manager widget - such as a frame, a labelframe, or a toplevel - you have the choice of using either pack or grid to manage all of its immediate children. Attempting to use both in the same manager results in an endless loop as both geometry managers try to control the window layout. This restriction applies only to the immediate children of a manager widget; you can use a different geometry manager for "descendents" that aren't immediate children. For example, you can choose to pack all of the immediate children of the . toplevel. Then, if one of the children of . is a frame, you can choose to use either pack or grid to manage the children of that frame. The packer is a powerful constraint-based geometry manager. Instead of specifying in detail the placement of each window, the programmer defines some constraints about how windows should be positioned, and the packer works out the details. It is important to understand the algorithm the packer uses; otherwise, the constraint-based results may not be what you expect. This chapter explores the packer through a series of examples. The background of the main window is set to black, and the other frames are given different colors so you can identify frames and observe the effect of the different packing parameters. When consecutive examples differ by a small amount, the added command or option is printed in bold courier to highlight the addition. [ Team LiB ]
[ Team LiB ]
Example 25-1 Two frames packed inside the main frame UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
# Make the main window black . config -bg black # Create and pack two frames frame .one -width 40 -height 40 -bg white frame .two -width 100 -height 50 -bg grey50 pack .one .two -side top
propagate
In the previous example, the main window shrank down to be just large enough to hold its two children. In most cases this is the desired behavior. If not, you can turn it off with the pack propagate command. Apply this to the parent frame, and it will not adjust its size to fit its children:
frame .one -width 40 -height 40 -bg white frame .two -width 100 -height 50 -bg grey50 pack propagate . false pack .one .two -side top
[ Team LiB ]
[ Team LiB ]
Example 25-3 A horizontal stack inside a vertical stack UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
frame .one -bg white frame .two -width 100 -height 50 -bg grey50 # Create a row of buttons foreach b {alpha beta gamma} { button .one.$b -text $b pack .one.$b -side left } pack .one .two -side top
frame .one -bg white frame .two -width 100 -height 50 -bg grey50 foreach b {alpha beta} { button .one.$b -text $b pack .one.$b -side left } # Create a frame for two more buttons frame .one.right
foreach b {delta epsilon} { button .one.right.$b -text $b pack .one.right.$b -side bottom } pack .one.right -side right pack .one .two -side top
You can build more complex arrangements by introducing nested frames and switching between horizontal and vertical stacking as you go. Within each frame pack all the children with either a combination of -side left and -side right, or -side top and -side bottom. Example 25-4 replaces the .one.gamma button with a vertical stack of two buttons, .one.right.delta and .one.right.epsilon. These are packed toward the bottom of .one.right, so the first one packed is on the bottom. The frame .one.right was packed to the right, and in the previous example, the button .one.gamma was packed to the left. Despite the difference, they ended up in the same position relative to the other two widgets packed inside the .one frame. The next section explains why.
[ Team LiB ]
[ Team LiB ]
# pack two frames on the bottom. frame .one -width 100 -height 50 -bg grey50 frame .two -width 40 -height 40 -bg white pack .one .two -side bottom # pack another frame to the right frame .three -width 20 -height 20 -bg grey75 pack .three -side right
When we pack a third frame into the main window with -side left or -side right, the new frame is positioned inside the cavity, which is above the two frames already packed toward the bottom side. The frame does not appear to the right of the existing frames as you might have expected. This is because the .two frame occupies the whole bottom side of the packing cavity, even though its display does not fill up that side. Can you tell where the packing cavity is after this example? It is to the left of the frame .three, which is the last frame packed toward the right, and it is above the frame .two, which is the last frame packed toward the bottom. This explains why there was no difference between the previous two examples when .one.gamma was packed to the left, but .one.right was packed to the right. At that point, packing to the left or right of the cavity had the same effect. However, it will affect what happens if another widget is packed into those two configurations. Try out the following commands after running Example 25-3 and Example 25-4 and compare the difference.[*]
[*]
Answer: After Example 25-3 the new button is to the right of all buttons. After Example 25-4 the new button is between .one.beta and .one.right.
Each packing parent has its own cavity, which is why introducing nested frames can help. If you use a horizontal or vertical arrangement inside any given frame, you can more easily simulate the packer's behavior in your head! [ Team LiB ]
[ Team LiB ]
frame .one -width 100 -height 50 -bg grey50 frame .two -width 40 -height 40 -bg white # Pack with fill enabled pack .one .two -side bottom -fill x frame .three -width 20 -height 20 -bg red pack .three -side right -fill x
This is just like Example 25-5, except that -fill x has been specified for all the frames. The .two frame fills, but the .three frame does not. This is because the fill does not expand into the packing cavity. In fact, after this example, the packing cavity is the part that shows through in black. Another way to look at this is that the .two frame was allocated the whole bottom side of the packing cavity, so its fill can expand the frame to occupy that space. The .three frame has only been allocated the right side, so a fill in the X direction will not have any effect. Another use of fill is for a menu bar that has buttons at either end and some empty space between them. The frame that holds the buttons is packed toward the top. The buttons are packed into the left and right sides of the menu bar frame. Without fill, the menu bar shrinks to be just large enough to hold all the buttons, and the buttons are squeezed together. When fill is enabled in the X direction, the menu bar fills out the top edge of the display:
frame .menubar -bg white frame .body -width 150 -height 50 -bg grey50 # Create buttons at either end of the menubar foreach b {alpha beta} { button .menubar.$b -text $b } pack .menubar.alpha -side left pack .menubar.beta -side right # Let the menu bar fill along the top pack .menubar -side top -fill x pack .body
-ipadx
and -ipady
Another way to get more fill space is with the -ipadx and -ipady packing options that request more display space in the X and Y directions, respectively. Due to other constraints the request might not be offered, but in general you can use this to give a widget more display space. The next example is just like the previous one except that some internal padding has been added:
# Create and pack two frames frame .menubar -bg white frame .body -width 150 -height 50 -bg # Create buttons at either end of the foreach b {alpha beta} { button .menubar.$b -text $b } pack .menubar.alpha -side left -ipady pack .menubar.beta -side right -ipadx # Let the menu bar fill along the top
grey50 menubar
10 10
The alpha button is taller and the beta button is wider because of the internal padding. The frame has internal padding, which reduces the space available for the packing cavity, so the .menubar frame shows through above and below the buttons.
UNREGISTERED VERSION OF CHM TO PDFin more display space. For example, it would be hard CONVERTER By THETA-SOFTWARE Some widgets have attributes that result
to distinguish a frame with width 50 and no internal padding from a frame with width 40 and a -ipadx 5 packing option. The packer would give the frame 5 more pixels of display space on either side for a total width of 50.
UNREGISTERED VERSIONthe button is used to CONVERTER Byfrom the edge of the button. The padding provided by OF CHM TO PDF keep its text away THETA-SOFTWARE
following example illustrates the difference. The -anchor e button option positions the text as far to the right as possible. Example 40-5 on page 617 provides another comparison of these options:
Buttons have their own -padx and -pady options that give them more display space, too. This
# Foo has internal padding from the packer button .foo -text Foo -anchor e -padx 0 -pady 0 pack .foo -side right -ipadx 10 -ipady 10 # Bar has its own padding button .bar -text Bar -anchor e -pady 10 -padx 10 pack .bar -side right -ipadx 0 -ipady 0
In all cases, you can specify the amount of padding using any type of screen distance recognized by Tk. A simple numeric value is interpreted as pixels. You can also follow a number with one of i, m, c, or p, which is interpreted as inches, millimeters, centimeters, or typographic points, respectively.
. config -borderwidth 10 # OK is the default button frame .ok -borderwidth 2 -relief sunken button .ok.b -text OK pack .ok.b -padx 5 -pady 5 # Cancel is not button .cancel -text Cancel pack .ok .cancel -side left -padx 5 -pady 5
The .ok.b button looks the same even if it is packed with -fill both. The child widgets do not fill the external padding provided by the packer. Example 25-10 handcrafts the look of a default button. Tk 8.0 added a -default attribute for buttons that gives them the right appearance for the default button on the current platform. It looks somewhat like this on UNIX, but the appearance is different on Macintosh and Windows. Tk 8.4 added the ability to specify asymmetric padding as a list of two screen distances. For example, the following adds 5 pixels of padding to the left and right of the widgets, 3 pixels above them, and 6 pixels below them:
[ Team LiB ]
[ Team LiB ]
# Make the main window black . config -bg black # Create and pack two frames frame .menubar -bg white frame .body -width 150 -height 50 -bg grey50 # Create buttons at either end of the menubar foreach b {alpha beta} { button .menubar.$b -text $b } pack .menubar.alpha -side left pack .menubar.beta -side right # Let the menu bar fill along the top pack .menubar -side top -fill x pack .body # Resize the main window to be bigger wm geometry . 200x100 # Allow interactive resizing wm minsize . 100 50
The only widget that claims any of the new space is .menubar because of its -fill x packing option. The .body frame needs to be packed properly:
# Use all of Example 2511 then repack .body pack .body -expand true -fill both
If more than one widget inside the same parent is allowed to expand, then the packer shares the extra space between them proportionally. This is probably not the effect you want in the examples we have built so far. The .menubar, for example, is not a good candidate for expansion.
# Use all of Example 2511 then repack .menubar and .body pack .menubar -expand true -fill x pack .body -expand true -fill both
[ Team LiB ]
[ Team LiB ]
Anchoring
If a widget is left with more packing PDF than display space, you can position it within UNREGISTERED VERSION OF CHM TO space CONVERTER By THETA-SOFTWARE its packing space using the -anchor packing option. The default anchor position is center. The other options correspond to points on a compass: n, ne, e, se, s, sw, w, and nw:
# Make the main window black . config -bg black # Create two frames to hold open the cavity frame .prop -bg white -height 80 -width 20 frame .base -width 120 -height 20 -bg grey50 pack .base -side bottom # Float a label and the prop in the cavity label .foo -text Foo pack .prop .foo -side right -expand true
The .base frame is packed on the bottom. Then the .prop frame and the .foo label are packed to the right with expand set but no fill. Instead of being pressed up against the right side, the expand gives each of these widgets half of the extra space in the X direction. Their default anchor of center results in the positions shown. The next example shows some different anchor positions:
. config -bg black # Create two frames to hold open the cavity frame .prop -bg white -height 80 -width 20 frame .base -width 120 -height 20 -bg grey50
pack .base -side bottom # Float the label and prop # Change their position with anchors label .foo -text Foo pack .prop -side right -expand true -anchor sw pack .foo -side right -expand true -anchor ne
The label has room on all sides, so each of the different anchors will position it differently. The .prop frame only has room in the X direction, so it can only be moved into three different positions: left, center, and right. Any of the anchors w, nw, and sw result in the left position. The anchors center, n, and s result in the center position. The anchors e, se, and ne result in the right position. If you want to see all the variations, type in the following commands to animate the different packing anchors. The update idletasks forces any pending display operations. The after 500 causes the script to wait for 500 milliseconds:
[ Team LiB ]
[ Team LiB ]
Packing Order
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
The packer maintains an order among the children that are packed into a frame. By default, each new child is appended to the end of the packing order. The most obvious effect of the order is that the children first in the packing order are closest to the side they are packed against. You can control the packing order with the -before and -after packing options, and you can reorganize widgets after they have already been packed:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 25-17 Controlling the packing order
# Create five labels in order foreach label {one two three four five} { label .$label -text $label pack .$label -side left -padx 5 } # ShuffleUp moves a widget to the beginning of the order proc ShuffleUp { parent child } { set first [lindex [pack slaves $parent] 0] pack $child -in $parent -before $first } # ShuffleDown moves a widget to the end of the order proc ShuffleDown { parent child } { pack $child -in $parent } ShuffleUp . .five ShuffleDown . .three
Introspection
The pack slaves command returns the list of children in their packing order. The ShuffleUp procedure uses this to find out the first child so that it can insert another child before it. The ShuffleDown procedure is simpler because the default is to append the child to the end of the packing order. When a widget is repacked, then it retains all its packing parameters that have already been set. If you need to examine the current packing parameters for a widget, use the pack info command.
pack info .five => -in . -anchor center -expand 0 -fill none -ipadx 0 \ -ipady 0 -padx 0 -pady 0 -side left
[ Team LiB ]
When you do this, remember that the order in which you create widgets is important. Create the frames first, then create the widgets. The stacking order for windows will cause the later windows to obscure the windows created first. The following is a common mistake because the frame obscures the button:
If you cannot avoid this problem scenario, then you can use the raise command to fix things up. Stacking order is also discussed on page 409.
raise .a
[ Team LiB ]
[ Team LiB ]
Unpacking a Widget
The pack VERSION OF CHM TO a widget from the packing order. The widget gets UNREGISTERED forget command removesPDF CONVERTER By THETA-SOFTWARE unmapped, so it is not visible. If you unpack a parent frame, the packing structure inside it is maintained, but all the widgets inside the frame get unmapped. Unpacking a widget is useful if you want to suppress extra features of your interface. You can create all the parts of the interface, and just delay packing them in until the user requests to see them. Then you can pack and unpack them dynamically. [ Team LiB ]
[ Team LiB ]
Packer Summary
Keep these rules in mind about the packer: Pack vertically (-side top and -side bottom) or horizontally (-side left and -side right) within a frame. Only rarely will a different mixture of packing directions work out the way you want. Add frames to build more complex structures. By default, the packer puts widgets into their parent frame, and the parent frame must be created before the children that are packed into it. If you put widgets into other relatives, remember to create the frames first so the frames stay underneath the widgets packed into them. By default, the packer ignores -width and -height attributes of frames that have widgets packed inside them. It shrinks frames to be just big enough to allow for its border width and to hold the widgets inside them. Use pack propagate to turn off the shrink-wrap behavior. The packer distinguishes between packing space and display space. A widget's display might not take up all the packing space allocated to it. The -fill option causes the display to fill up the packing space in the X or Y directions, or both. The -expand true option causes the packing space to expand into any room in the packing cavity that is otherwise unclaimed. If more than one widget in the same frame wants to expand, then they share the extra space. The -ipadx and -ipady options allocate more display space inside the border, if possible. The -padx and -pady options allocate more packing space outside the border, if possible. The widget never fills this space. These values may be specified as a list of two values to get asymmetric padding (Tk 8.4.)
pack win ?win ..? ?options? pack configure win ?win ...? ?options? pack forget win ?win...? pack info win pack propagate win ?bool?
This is just like pack configure. Packs one or more widgets according to the options, which are given in Table 25-2. Unpacks the specified windows. Returns the packing parameters of win. Queries or sets the geometry propagation of win, which has other widgets packed inside it. Returns the list of widgets managed by win.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Table 25-2. Packing options
-after win -anchor anchor -before win -expand boolean -fill style -in win -ipadx amount -ipady amount -padx amount -pady amount -side side [ Team LiB ] Packs after win in the packing order. Anchors: center, n, ne, e, se, s, sw, w, or nw. Packs before win in the packing order. Controls expansion into the unclaimed packing cavity. Controls fill of packing space. Style: x, y, both, or none. Packs inside win. Horizontal internal padding, in screen units. Vertical internal padding, in screen units. Horizontal external padding, in screen units. May be a list of two screen units for asymmetric padding (Tk 8.4). Vertical external padding, in screen units. May be a list of two screen units for asymmetric padding (Tk 8.4). Sides: top, right, bottom, or left.
[ Team LiB ]
If you do this, you do not see the button. The problem is that the frame is higher in the stacking order so it obscures the button. You can change the stacking order with the raise command:
This puts .one just above .two in the stacking order. If .two was not specified, then .one would be put at the top of the stacking order. The lower command has a similar form. With one argument, it puts that window at the bottom of the stacking order. Otherwise, it puts it just below another window in the stacking order. You can use raise and lower on top-level windows to control their stacking order among all other top-level windows. For example, if a user requests a dialog that is already displayed, use raise to make it pop to the foreground of their cluttered desktop. To determine the stacking order of toplevel windows, use the wm stackorder command. (See "Toplevel Size, Placement, and Decoration" on page 658.) [ Team LiB ]
[ Team LiB ]
As discussed on page 395, you can use a combination of pack and grid to create your display. But for each individual manager widget, you must use only one of pack or grid to manage all of its immediate children. [ Team LiB ]
[ Team LiB ]
A Basic Grid
Example 26-1 uses grid to lay out a set of labels and frames in two parallel columns. It takes advantage of the relative placement feature of grid. Instead of specifying rows and columns, the order of grid commands and their arguments implies the layout. Each grid command starts a new row, and the order of the widgets in the grid command determines the column. In the example, there are two columns, and each iteration of the loop adds a new row. grid makes each column just wide enough to hold the biggest widget. Widgets that are smaller are centered in their cell. That's why the labels appear centered in their column:
foreach color {red orange yellow green blue purple} { label .l$color -text $color -bg white frame .f$color -background $color -width 100 -height 2 grid .l$color .f$color }
foreach color {red orange yellow green blue purple} { label .l$color OF CHM TO -bg CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION -text $color PDF white frame .f$color -background $color -width 100 -height 2 grid .l$color .f$color grid .l$color -sticky w grid .f$color -sticky ns }
Example 26-2 uses grid in two ways. The first grid in the loop fixes the positions of the widgets because it is the first time they are assigned to the master. The next grid commands modify the existing parameters; they just adjust the -sticky setting because their row and column positions are already known. You can specify row and column positions explicitly with the -row and -column attributes. This is generally more work than using the relative placement, but it is necessary if you need to dynamically move a widget into a different cell. Example 26-3 keeps track of rows and columns explicitly and achieves the same layout as Example 26-2:
foreach color {red orange yellow green blue purple} { label .l$color -text $color -bg white frame .f$color -background $color -width 100 -height 2 grid .l$color .f$color grid .l$color -sticky w -padx 3 grid .f$color -sticky ns -pady 1 }
Tk 8.4 added the ability to specify asymmetric padding as a list of two screen distances. For example, -padx {0.125i 0.25i} adds 1/8 inch of padding to the left and 1/4 inch padding to the right of a widget.
-ipadx
and -ipady
You can give a widget more display space than it normally needs with internal padding. The internal padding increases the size of the grid. In contrast, a -sticky setting might stretch a widget, but it will not change the size of the grid. Example 26-5 makes the labels taller with ipady:
foreach color {red orange yellow green blue purple} { label .l$color -text $color -bg white
frame .f$color -background $color -width 100 -height 2 grid .l$color .f$color grid .l$color -sticky w -padx 3 -ipady 5 grid .f$color -sticky ns -pady 1 }
set index 0 foreach x {news ns ew " " new sew wsn esn frame .f$x -borderwidth 2 -relief ridge grid .f$x -sticky news \ -row [expr {$index/4}] -column [expr label .l$x -text $x -background white grid .l$x -sticky $x -padx 2 -pady 2 \ -row [expr {$index/4}] -column [expr incr index }
{$index%4}]
[ Team LiB ]
[ Team LiB ]
. config -bg white foreach color {888 999 aaa bbb ccc fff} { frame .$color -bg #$color -width 40 -height 40 } grid .888 -row 0 -column 0 -columnspan 3 -sticky news grid .999 -row 1 -column 0 -rowspan 2 -sticky news grid .aaa -row 1 -column 1 -columnspan 2 -sticky news grid .bbb -row 2 -column 2 -rowspan 2 -sticky news grid .ccc -row 3 -column 0 -columnspan 2 -sticky news grid .fff -row 2 -column 1 -sticky news
You can also use special syntax in grid commands that imply row and column placement. Special characters represent a cell that is spanned or skipped: - represents a spanned column. ^ represents a spanned row. x represents a skipped cell. A nice feature of the implicit row and column assignments is that it is easy to make minor changes to your layout. Example 26-8 achieves the same layout:
. config -bg white foreach color {888 999 aaa bbb ccc ddd fff} { frame .$color -bg #$color -width 40 -height 40 } grid .888 -sticky news grid .999 .aaa -sticky news grid ^ .fff .bbb -sticky news grid .cccVERSION OF CHM TO PDF CONVERTER By ^ -sticky news UNREGISTERED [ Team LiB ]
THETA-SOFTWARE
[ Team LiB ]
grid columnconfigure master col ?attributes? grid rowconfigure master row ?attributes?
With no attributes, the current settings are returned. The row and col specifications can be lists instead of simple indices, so you can configure several rows or columns at once.
. config -bg black label .f1 -text left -bg #ccc label .f2 -text right -bg #aaa grid .f1 .f2 -sticky news grid .f1 -padx 10 -pady 10 grid rowconfigure . 0 -pad 20
Minimum Size
The -minsize attribute restricts a column or row to be a minimum size. The row or column can grow bigger if its widget requests it, but they will not get smaller than the minimum. One useful application of -minsize is to create empty rows or columns, which is more efficient than creating an extra frame.
enough to contain the grid. You can turn off the shrink-wrap behavior with grid propagate. If geometry propagation is off, then the grid is centered inside the master. If the master frame is too small to fit the grid, then the grid is anchored to the upper-left corner of the master and clipped on the bottom-right. By default, rows and columns do not resize when you grow the master frame. You enable resizing by specifying a -weight for a row or column that is an integer value greater than zero. Example 26-10 grids a text widget and two scrollbars. The protocol between the scrollbar and the text widget is described on page 501. The text widget is in row 0, column 0, and both of these can expand. The vertical scrollbar is in row 0, column 1, so it only grows in the Y direction. The horizontal scrollbar is in row 1, column 0, so it only grows in the X direction:
text .text -yscrollcommand ".yscroll set" \ -xscrollcommand ".xscroll set"-width 40 -height 10 scrollbar .yscroll -command ".text yview" -orient vertical scrollbar .xscroll -command ".text xview" -orient horizontal grid .text .yscroll -sticky news grid .xscroll -sticky ew grid rowconfigure . 0 -weight 1 grid columnconfigure . 0 -weight 1
You can use different weights to let different rows and columns grow at different rates. However, there are some tricky issues because the resize behavior applies to extra space, not total space. For example, suppose there are four columns that have widths 10, 20, 30, and 40 pixels, for a total of 100. If the master frame is grown to 140 pixels wide, then there are 40 extra pixels. If each column has weight 1, then each column gets an equal share of the extra
space, or 10 more pixels. Now suppose column 0 has weight 0, columns 1 and 2 have weight 1, and column 3 has weight 2. Column 0 will not grow, columns 1 and 2 will get 10 more pixels, and column 3 will get 20 more pixels. In most cases, weights of 0 or 1 make the most sense.
If a row or column has to shrink, the weights are applied in reverse. A row or column with a higher weight will shrink more. For example, put two equal sized frames in columns with different weights. When the user makes the window bigger, the frame in the column with more weight gets larger more quickly. When the window is made smaller, that frame gets smaller more quickly.
Uniform Columns
The -uniform attribute makes it easy to create columns (or rows) that are the same width (or height). Use the -uniform attribute to create a group of columns (or rows). The value of the attribute can by anything (e.g., xyz). All columns (or rows) with the same -uniform attribute are in the same group. If they all have the same -weight value, then they are all the same size. If one column (or row) in a group has a -weight that is twice what the other columns (or rows) have, then it is twice as big. This is illustrated in Example 26-11.
foreach x {alpha beta gamma x y z} { label .$x -text $x } .beta config -bg white .y config -bg white grid .alpha .beta .gamma -sticky news grid .x .y .z -sticky news grid columnconfigure . "0 1 2" -uniform group1 -weight 1 grid columnconfigure . 1 -weight 2
[ Team LiB ]
[ Team LiB ]
Table PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO26-1. The grid command
grid bbox master ?c1 r1? ?c2 r2? grid columnconfigure master col ?options? grid configure win ?win ...? ?options? grid forget win ?win...? grid info win grid location master x y Returns the bounding box, of the whole grid, the cell at c1, r1, or the cells from c1, r1 to c2, r2. Sets or queries the configuration of col. Options are minsize, -weight, -pad, and -uniform. Grids one or more widgets according to the options, which are given in Table 26-2. Unmaps the specified windows. Returns the grid options of win. Returns the cell column and row under the point x, y in master. Enables or disables shrink-wrapping of master. Sets or queries the configuration of row. Options are minsize, -weight, -pad, and -uniform. Unmaps slave, but remember its configuration. Returns the number of columns and rows. Returns the list of widgets managed by win, or just those in the specified row or column.
grid propagate master ? boolean? grid rowconfigure master row ?options? grid remove slave grid size master grid slaves win ?-row r? ?column c?
Places inside win. Column position. Columns count from zero. Spans n columns. Internal widget padding in the X direction, in screen units. Internal widget padding in the Y direction, in screen units.
-padx pixels External widget padding in the X direction, in screen units. May be a list of two screen units for asymmetric padding (Tk 8.4). -pady pixels External widget padding in the Y direction, in screen units. May be a list of two screen units for asymmetric padding (Tk 8.4). -row row -rowspan n -sticky how Row position. Rows count from zero. Spans n rows. Positions widget next to any combination of north (n), south (s), east (e), and west (w) sides of the cell. Use {} for center.
[ Team LiB ]
[ Team LiB ]
Chapter 27. The Place Geometry UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Manager
This chapter explores the place geometry manager that positions widgets on the screen.
UNREGISTERED VERSION window, orTO PDF CONVERTER By THETA-SOFTWARE a widget. position and size of a OF CHM you specify the relative position and relative size of
This is useful in a few situations, but it rapidly becomes tedious if you have to position lots of windows. The best application of place is to create special-purpose geometry managers using its relative constraints. A standard application of place is to adjust the boundary between two adjacent windows. [ Team LiB ]
The place geometry manager is much simpler than pack and grid. You specify the exact
[ Team LiB ]
place
Basics
The place command lets you specify the width and height of a window, and the X and Y locations of the window's anchor point. The size and location can be specified in absolute or relative terms. Relative specifications are more powerful. Example 27-1 uses place to center a window in its parent. You can use this command to position dialogs that you do not want to be detached top-level windows:
The -relx and -rely specify the relative X and Y positions of the anchor point of the widget $w in $parent. A relative X (or Y) value of zero corresponds to the left (or top) edge of $parent. A value of one corresponds to the right (or bottom) edge of $parent. A value of 0.5 specifies the middle. The anchor point determines what point in $w is positioned according to the specifications. In Example 27-1 the center anchor point is used so that the center of $w is centered in $parent. The relative height and width settings are used to base a widget's size on another widget. Example 27-2 completely covers one window with another window. It uses the default anchor point for windows, which is their upper-left hand corner (nw):
The absolute and relative size and position parameters are additive (e.g., -width and relwidth). You can make a window slightly larger or smaller than the parent by specifying both parameters. In Example 27-3, a negative width and height are used to make a window smaller than another one:
It is not necessary for $parent to actually be the parent widget of $w. The requirement is that $parent be the parent, or a descendant of the parent, of $w. It also has to be in the same toplevel window. This guarantees that $w is visible whenever $parent is visible. These are the same restrictions imposed by the pack geometry manager. It is not necessary to position a widget inside another widget, either. Example 27-4 positions a
window five pixels above a sibling widget. If $sibling is repositioned, then $w moves with it. This approach is useful when you decorate a resizable window by placing other widgets at its corners or edges. When the window is resized, the decorations automatically move into place:
The -bordermode outside option is specified so that any decorative border in $sibling is ignored when positioning $w. In this case the position is relative to the outside edge of $sibling. By default, the border is PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TOtaken into account to make it easy to position widgets inside their parent's border. The parent widget does not have to be a frame. Example 27-1 can be used to place a dialog in the middle of a text widget. In Example 27-4, $sibling and $w can both be label widgets. [ Team LiB ]
[ Team LiB ]
proc Pane_Create {f1 f2 args} { # Map optional arguments into array values set t(-orient) vertical set t(-percent) 0.5 set t(-in) [winfo parent $f1] array set t $args # Keep state in an array associated with the master frame set master $t(-in) upvar #0 Pane$master pane array set pane [array get t] # # # # Create the grip and set placement attributes that will not change. A thin divider line is achieved by making the two frames one pixel smaller in the adjustable dimension and making the main frame black.
set pane(1) $f1 set pane(2) $f2 set pane(grip) [frame $master.grip -background gray50 \ -width 10 -height 10 -bd 1 -relief raised \ -cursor crosshair] if {[string match vert* $pane(-orient)]} {
set pane(D) Y;# Adjust boundary in Y direction place $pane(1) -in $master -x 0 -rely 0.0 -anchor nw \ -relwidth 1.0 -height -1 place $pane(2) -in $master -x 0 -rely 1.0 -anchor sw \ -relwidth 1.0 -height -1 place $pane(grip) -in $master -anchor c -relx 0.8 } else { set pane(D) OF Adjust PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION X ;#CHM TO boundary in X direction place $pane(1) -in $master -relx 0.0 -y 0 -anchor nw \ -relheight 1.0 -width -1 place $pane(2) -in $master -relx 1.0 -y 0 -anchor ne \ -relheight 1.0 -width -1 place $pane(grip) -in $master -anchor c -rely 0.8 } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE $master configure -background black # Set up bindings for resize, <Configure>, and # for dragging the grip. bind $master <Configure> [list PaneGeometry $master] bind $pane(grip) <ButtonPress-1> \ [list PaneDrag $master %$pane(D)] bind $pane(grip) <B1-Motion> \ [list PaneDrag $master %$pane(D)] bind $pane(grip) <ButtonRelease-1> \ [list PaneStop $master] # Do the initial layout PaneGeometry $master }
All the optional arguments are available in $args. Its attribute-value structure is used to initialize a temporary array t. Default values are set before the assignment from $args. The following code is compact but doesn't check errors in the optional arguments.
set t(-orient) vertical set t(-percent) 0.5 set t(-in) [winfo parent $f1] array set t $args
Global state about the layout is kept in an array whose name is based on the master frame. The name of the master frame isn't known until after arguments are parsed, which is why t is used. After the upvar the argument values are copied from the temporary array into the global
state array:
set master $t(-in) upvar #0 Pane$master pane array set pane [array get t]
place $pane(1) -in $parent -x 0 -rely 0.0 -anchor nw \ -relwidth 1.0 -height -1 place $pane(2) -in $parent -x 0 -rely 1.0 -anchor sw \ -relwidth 1.0 -height -1 place $pane(grip) -in $parent -anchor c -relx 0.8
The position of the upper and lower frames is specified with an absolute X and a relative Y position, and the anchor setting is chosen to keep the frame visible inside the main frame. For example, the lower frame is positioned at the bottom-left corner of the container with -x 0 and -rely 1.0. The -anchor sw attaches the lower-left corner of the frame to this position. The size of the contained frames is also a combination of absolute and relative values. The width is set to the full width of the container with -relwidth 1.0. The height is set to minus one with -height -1. This value gets added to a relative height that is determined later. It will leave a little space between the two contained frames. The resize grip is just a small frame positioned at the boundary. Initially it is just placed over toward one size with -relx 0.8. It gets positioned on the boundary with a -rely setting later. It has a different cursor to indicate it is active.
Event Bindings
The example uses some event bindings that are described in more detail in Chapter 29. The <Configure> event occurs when the containing frame is resized by the user. When the user presses the mouse button over the grip and drags it, there is a <ButtonPress-1> event, one or more <B1-Motion> events, and finally a <ButtonRelease-1> event. Tcl commands are bound to these events:
bind $parent <Configure> [list PaneGeometry $parent] bind $pane(grip) <ButtonPress-1> \ [list PaneDrag $parent %$pane(D)] bind $pane(grip) <B1-Motion> \ [list PaneDrag $parent %$pane(D)] bind $pane(grip) <ButtonRelease-1> [list PaneStop $parent]
Example 27-6 PaneDrag adjusts the percentage UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
proc PaneDrag {master D} { upvar #0 Pane$master pane if [info exists pane(lastD)] { set delta [expr double($pane(lastD) - $D) \ / $pane(size)] set pane(-percent) [expr $pane(-percent) - $delta] if {$pane(-percent) < 0.0} { set pane(-percent) 0.0 } elseif {$pane(-percent) > 1.0} { set pane(-percent) 1.0 } PaneGeometry $master } set pane(lastD) $D } proc PaneStop {master} { upvar #0 Pane$master pane catch {unset pane(lastD)} }
The PaneGeometry procedure adjusts the positions of the frames. It is called when the main window is resized, so it updates pane(size). It is also called as the user drags the grip. For a vertical layout, the grip is moved by setting its relative Y position. The size of the two contained frames is set with a relative height. Remember that this is combined with the fixed height of -1 to get some space between the two frames:
set pane(size) [winfo height $master] } } proc PaneTest {{p .p} {orient vert}} { catch {destroy $p} frame $p -width 200 -height 200 label $p.1 -bg blue -text foo label $p.2 -bg green -text bar pack $p -expand true -fill both pack propagate $p off Pane_Create $p.1 $p.2 -in $p -orient $orient -percent 0.3 }
[ Team LiB ]
[ Team LiB ]
Table 27-2 summarizes the placement options for a widget, which you set with the place configure command and retrieve with the place info command.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
A panedwindow widget is not only a container for other widgets, but it is also a geometry manager. It controls the size and position of the widgets that it manages. Therefore, don't use the pack, grid, or place commands to control the widgets that you add to a panedwindow. Of course, for more complex interfaces, you can add frames as the managed widgets of a panedwindow, and then pack, grid, or place other widgets within those frames. As an example, consider a layout with two text widgets. We'd like each text widget to have horizontal and vertical scrollbars, which is a natural application of grid. But then we want the entire layout managed by a 2-pane vertical panedwindow. In this case, we'll use a labelframe widget to contain each gridded text-and-scrollbar assembly, and then add each labelframe as a managed widget of our panedwindow. The result is shown in Example 28-1.
# Create the panedwindow to manage the entire display panedwindow .p -orient vertical -showhandle 1 pack .p -expand yes -fill both # Create 2 labelframe widgets, each containing a # gridded text and scrollbar assembly. foreach {w label} {code "Code:" notes "Notes:"} { set f [labelframe .p.$w -text $label] text $f.t -height 10 -width 40 \ -wrap none -font {courier 12} \ -xscrollcommand [list $f.xbar set] \ -yscrollcommand [list $f.ybar set] scrollbar $f.xbar -orient horizontal \ -command [list $f.t xview] scrollbar $f.ybar -orient vertical \ -command [list $f.t yview] grid grid grid grid grid $f.t -row 0 -column 0 -sticky news -padx 2 -pady 2 $f.ybar -row 0 -column 1 -sticky ns -padx 2 -pady 2 $f.xbar -row 1 -column 0 -sticky ew -padx 2 -pady 2 columnconfigure $f 0 -weight 1 rowconfigure $f 0 -weight 1
# Add the frame assembly to the panedwindow .p add $f -minsize 1i -padx 4 -pady 6 }
The forget operation removes widgets from a panedwindow. The widgets aren't destroyed, but they are no longer managed by the paned window, and the pane they formerly occupied is
removed from the panedwindow. You can also get a list of the widgets currently managed by a panedwindow (in the order in which they appear) with the panes operation.
For best results, create the widgets managed by a panedwindow as children of that panedwindow. Tk then automatically handles the stacking By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER order for windows so that the child appears on top of the panedwindow. If you don't create the managed widget as a child of the panedwindow, you either need to create the managed widget after the panedwindow, or else use the raise command to raise the managed widget above the panedwindow, as discussed in "Window Stacking Order" on page 409. [ Team LiB ]
[ Team LiB ]
$w configure ?option value...? $w forget win ?win...? $w identify x y $w panecget win option
$w paneconfigure index ? option? ?value? ?...? $w panes $w proxy coord $w proxy forget $w proxy place x y $w sash coord index $w sash dragto index x y $w sash mark index x y
Table 28-2 summarizes the panedwindow options for managed widgets. These are set when adding a widget to the paned window with the add operation or afterwards with paneconfigure operation. The current settings are returned by the panecget operation.
size units. UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE -padx size -pady size -sticky how -width size
[ Team LiB ]
[ Team LiB ]
Panedwindow Attributes
Table 28-3 lists the panedwindow widget attributes. The table uses the resource name for the attribute, which has capitals at internal word boundaries. In Tcl commands these options are specified with a dash and all lowercase.
handleSize height
opaqueResize Boolean. True indicates the panes should resize as a sash is moved. False (default) indicates resizing is deferred until the sash is placed. orient relief sashCursor sashPad sashRelief sashWidth showHandle width [ Team LiB ] horizontal or vertical flat, sunken, raised, groove, solid, or ridge. Cursor to display over a sash. Defaults to a double-sided arrow. Padding on both sides of a sash. Relief style for sashes. flat, sunken, raised (default), groove, solid, or ridge. Width of each sash, in screen units. Boolean, whether or not to show the sash handles. Defaults to False on Windows, and True on other platforms. Width of the widget in screen units.
[ Team LiB ]
Chapter 29. Binding Commands to UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Events
This chapter introduces the event binding mechanism in Tk. Bindings associate a Tcl command with an event like a mouse click or a key stroke. There are also facilities to define virtual events like <<Cut>> and <<Paste>> that are associated with different keystrokes on different UNREGISTERED VERSION OF discussed are: bind, bindtags, and THETA-SOFTWARE platforms. Tcl commands CHM TO PDF CONVERTER By event. Bindings associate a Tcl command with a sequence of events from the window system. Events include key press, key release, button press, button release, mouse entering a window, mouse leaving, window changing size, window open, window close, focus in, focus out, and widget destroyed. The bindings are defined on binding tags, and each widget is associated with an ordered set of binding tags. The binding tags provide a level of indirection between bindings and widgets that creates a flexible and powerful system. Virtual events are used to support a different look and feel on different platforms. A virtual event is a higher-level name, like <<Copy>>, for a lower-level event name like <Control-c> or <Key-F6>. A virtual event hides the different keystrokes used on different platforms for the same logical operation. Tk defines a few virtual events, and applications can define their own. [ Team LiB ]
[ Team LiB ]
If all arguments are present, a binding from eventSequence to command is defined for bindingTag. The bindingTag is typically a widget class name (e.g., Button) or a widget instance name (e.g., .buttons.foo). Binding tags are described in more detail later. Called with a single argument, a binding tag, bind returns the events for which there are command bindings:
bind Menubutton => <Key-Return> <Key-space> <ButtonRelease-1> <B1-Motion> <Motion> <Button-1> <Leave> <Enter>
The events in this example are keystroke and mouse events. <Button-1> is the event generated when the user presses the first, or left-hand, mouse button. <B1-Motion> is generated when the user moves the mouse while holding down the first mouse button. The <Key-space> event occurs when the user presses the space bar. The surrounding angle brackets delimit a single event, and you can define bindings for a sequence of events. The event syntax is described on page 439, and event sequences are described on page 445. If bind is given a binding tag and an event sequence, it returns the Tcl command bound to that event sequence:
The Tcl commands in event bindings support an additional syntax for event keywords. These keywords begin with a percent sign and have one more character that identifies some attribute of the event. The keywords are substituted with event-specific data before the Tcl command is evaluated. For example, %W is replaced with the widget's pathname. The %X and %Y keywords are replaced with the coordinates of the event relative to the screen. The %x and %y keywords are replaced with the coordinates of the event relative to the widget. The event keywords are summarized on page 448. The % substitutions are performed throughout the entire command bound to an event, without regard to other quoting schemes. You must use %% to obtain a single percent sign. For this reason you should make your binding commands short, adding a new procedure if necessary (e.g., tk::MbMotion), instead of littering percent signs throughout your code. A new binding is created by specifying a binding tag, an event sequence, and a command:
If the first character of the binding command is +, the command (without the +) is added to the commands, if any, for that event and binding tag:
When a binding is triggered, the command is evaluated at the global scope. A very common mistake is to confuse the scope that is active when the bind command creates a binding, and the scope that is active when the binding is triggered. The same problem crops up with the commands associated with buttons, and it is discussed in more detail at the beginning of Chapter 30. [ Team LiB ]
[ Team LiB ]
The following command returns the binding tags for text widget .t:
You can change the binding tags and their order. The tagList argument to bindtags must be a proper Tcl list. The following command reorders the binding tags for .t and eliminates the . binding tag:
By default, all the Tk widgets, except a toplevel, have four binding tags in the following order: The widget's Tk pathname (e.g., .t). Use this binding tag to provide special behavior to a particular widget. There are no bindings on this bindtag by default. The widget's class (e.g., Text). The class for a widget is derived from the name of the command that creates it. A button widget has the class Button, a text has the class Text, and so on. The Tk widgets define their default behavior with bindings on their class. The Tk pathname of the widget's toplevel window (e.g., .). This is redundant in the case of a toplevel widget, so it is not used twice. There are no bindings on this bindtag by default. The bindings on a toplevel window can be used in dialog boxes to handle keyboard accelerators. The global binding tag all. The default bindings on all are used to change focus among widgets. They are described on page 604. When there is more than one binding tag on a widget, then one binding from each binding tag
can match an event. The bindings are processed in the order of the binding tags. By default, the most specific binding tag comes first, and the most general binding tag comes last. Example 29-1 has two frame widgets that have the following behavior. When the mouse enters them, they turn red. They turn white when the mouse leaves. When the user types <Controlc>, the frame under the mouse is destroyed. One of the frames, .two, reports the coordinates of mouse clicks.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 29-1 Bindings on different binding tags
frame .one -width 30 -height 30 frame .two -width 30 -height 30 bind Frame <Enter> {%W config PDF CONVERTER UNREGISTERED VERSION OF CHM TO -bg red} bind Frame <Leave> {%W config -bg white} bind .two <Button> {puts "Button %b at %x %y"} pack .one .two -side left bind all <Control-c> {destroy %W} bind all <Enter> {focus %W}
By THETA-SOFTWARE
The Frame class has a binding on <Enter> and <Leave> that changes a frame's background color when the mouse moves in and out of the window. This binding is shared by all the frames. There is also a binding on all for <Enter> that sets the keyboard focus. Both bindings will trigger when the mouse enters a frame.
Note that you cannot use the break or continue commands inside a procedure that is called by the binding. This is because the procedure mechanism will not propagate the break or continue signal. Instead, you could use the -code option to return, which is described on page 86:
bindtags $t [list ViInsert Text $t all] bind ViInsert <Escape> {bindtags %W {ViCmd %W all}} bind ViCmd <Key-i> {bindtags %W {ViInsert Text %W all}}
The Text class bindings are used in insert mode. The command to put the widget into command mode is put on a new binding tag, ViInsert, instead of changing the default Text bindings. The bindtag command changes the mode by changing the set of binding tags for the widget. The %W is replaced with the name of the widget, which is the same as $t in this example. Of course, you need to define many more bindings to fully implement all the vi commands. [ Team LiB ]
[ Team LiB ]
Event Syntax
The bind VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTEREDcommand uses the following syntax to describe events: <modifier-modifier-type-detail> <<Event>>
The first form is for physical events like keystrokes and mouse motion. The second form is for virtual events like Cut and Paste, which correspond to different physical events on different platforms. Physical events are described in this section. Virtual events are described in more detail on page 446. The primary part of the description is the type, (e.g., Button or Motion). The detail is used in some events to identify keys or buttons, (.e.g., Key-a or Button-1). A modifier is another key or button that is already pressed when the event occurs, (e.g., Control-Key-a or B2-Motion). There can be multiple modifiers (e.g., Control-Shift-x). The < and > delimit a single event. Table 29-1 lists all physical event types. When two event types are listed together (e.g., ButtonPress and Button) they are equivalent.
FocusIn FocusOut Gravity KeyPress, Key KeyRelease Leave Map MapRequest Motion MouseWheel Property Reparent ResizeRequest Unmap Visibility
The window has received focus. The window has lost focus. The window has moved because of a change in size of its parent window. A key is pressed (down). A key is released (up). The mouse is leaving the window. The window has been mapped (opened). An application request to map a window. (Used by window managers.) The mouse is moving in the window. The scrolling mouse wheel has moved. A property on the window has been changed or deleted. A window has been reparented. An application request to resize window. (Used by window managers.) The window has been unmapped (iconified). The window has changed visibility.
Keyboard Events
The KeyPress type is distinguished from KeyRelease so that you can have different bindings for each of these events. KeyPress can be abbreviated Key, and Key can be left off altogether if a detail is given to indicate what key. Finally, as a special case for KeyPress events, the angle brackets can also be left out. The following are all equivalent event specifications:
The detail for a key is also known as the keysym, which refers to the graphic printed on the key of the keyboard. For punctuation and non-printing characters, special keysyms are defined. Case is significant in keysyms, but unfortunately there is no consistent scheme. In particular BackSpace has a capital B and a capital S. Commonly encountered keysyms include: Return, Escape, BackSpace, Tab, Up, Down, Left, Right, comma, period, dollar, asciicircum, numbersign, exclam. Starting in Tk 8.3.2, the online documentation includes a new keysym reference page that documents all standard keysyms.
There are times when you do not know what keysym is generated by a special key on your keyboard. The keysyms are defined by the window system implementation, and on UNIX systems they are affected by a dynamic keyboard map, the X modmap. You may find the next binding useful to determine just what the keysym for a particular key is on your system:
UNREGISTERED<KeyPress> OF CHM TO PDF CONVERTER By THETA-SOFTWARE VERSION {puts stdout {%%K=%K %%A=%A}} bind $w
The %K keyword is replaced with the keysym from the event. The %A is replaced with the printing character that results from the event and any modifiers like Shift. The %% is replaced with a single percent sign. Note that these substitutions occur in spite of the curly braces used UNREGISTERED VERSION OF CHM capital Q, CONVERTER By THETA-SOFTWARE Shift for grouping. If the user types a TO PDF there are two KeyPress events, one for the key, and one for the q key. The output is:
The Shift_R keysym indicates the right-hand shift key was pressed. The %A keyword is replaced with {} when modifier keys are pressed. You can check for this in <KeyPress> bindings to avoid doing anything if only a modifier key is pressed. On Macintosh, there is no event at all when the modifier keys are pressed. The following can be used with a text widget. The double quotes are necessary to force a string comparison:
Mouse Events
Button events also distinguish between ButtonPress, (or Button), and ButtonRelease. Button can be left off if a detail specifies a button by number. The following are equivalent:
Note: The event <1> implies a ButtonPress event, while the event 1 implies a KeyPress event. To avoid confusion, always specify the Key or Button type. The mouse is tracked by binding to the Enter, Leave, and Motion events. Enter and Leave are triggered when the mouse comes into and exits out of the widget, respectively. A Motion event is generated when the mouse moves within a widget. The coordinates of the mouse event are represented by the %x and %y keywords in the binding command. The coordinates are widget-relative, with the origin at the upper-left hand corner of a widget's window. The keywords %X and %Y represent the coordinates relative to the screen:
bind $w <Enter> {puts stdout "Entered %W at %x %y"} bind $w <Leave> {puts stdout "Left %W at %x %y"} bind $w <Motion> {puts stdout "%W %x %y"}
A mouse drag event is a Motion event that occurs when the user holds down a mouse button. In this case the mouse button is a modifier, which is discussed in more detail on page 443. The binding looks like this:
Other Events
The <Map> and <Unmap> events are generated when a window is opened and closed, or when a widget is packed or unpacked by its geometry manager. The <Activate> and <Deactivate> events are generated when an application is activated by the operating system. This applies to Macintosh systems, and it occurs when the user clicks in the application window. The <Configure> event is generated when the window changes size. A canvas that computes its display based on its size can bind a redisplay procedure to the <Configure> event, for example. The <Configure> event can be caused by interactive resizing. It can also be caused by a configure widget command that changes the size of the widget. You should not reconfigure a widget's size while processing a <Configure> event to avoid an indefinite sequence of these events. The <Destroy> event is generated when a widget is destroyed. You can intercept requests to delete windows, too. See also the description of the wm command on page 657. The <MouseWheel> event is generated on Windows by the small scrolling wheel built into the Microsoft Mouse. It reports a delta value using the %D keyword. Currently the delta is an integer multiple of 120, where positive values indicate a scroll up, and negative values indicate a scroll down. Note that most Unix systems don't report <MouseWheel> events, but some do report mousewheel movement via <ButtonPress-4> and <ButtonPress-5> events. Chapter 39 presents some examples that use the <FocusIn> and <FocusOut> events. The remaining events in Table 29-1 have to do with dark corners of the X protocol, and they are seldom used. More information can be found on these events in the Event Reference section of the Xlib Reference Manual (Adrian Nye, O'Reilly & Associates, Inc., 1992).
Be careful when binding events to toplevel windows because their name is used as a binding tag on all the widgets contained in them. For example, the following binding fires when the user destroys the main window, which means the application is about to exit:
[ Team LiB ]
[ Team LiB ]
Modifiers
A modifier indicates that another key or button is being held down at the time of the event. Typical modifiers are the Shift and Control keys. The mouse buttons can also be used as modifiers. If an event does not specify any modifiers, the presence of a modifier key is ignored by the event dispatcher. However, if there are two possible matching events, the more accurate match will be used. For example, consider these three bindings:
bind $w <KeyPress> {puts "key=%A"} bind $w <Key-c> {puts "just a c"} bind $w <Control-Key-c> {exit}
The last event is more specific than the others. Its binding will be triggered when the user types c with the Control key held down. If the user types c with the Meta key held down, the second binding will be triggered. The Meta key is ignored because it does not match any binding. If the user types something other than a c, the first binding is triggered. If the user presses the Shift key, then the keysym that is generated is C, not c, so the last two events do not match. There are eight possible modifier keys. The Control, Shift, and Lock modifiers are found on nearly all keyboards. The Meta and Alt modifiers tend to vary from system to system, and they may not be defined at all. They are commonly mapped to be the same as Mod1 or Mod2, and Tk will try to determine how the mappings are set. The Macintosh has a Command modifier that corresponds to the clover-leaf or apple key. The remaining modifiers, Mod3 through Mod5, are sometimes mapped to other special keys. In OpenLook environments, for example, the Paste function key is also mapped to the Mod5 modifier. The button modifiers, B1 through B5, are most commonly used with the Motion event to distinguish different mouse dragging operations. For example, <B1-Motion> is the event generated when the user drags the mouse with the first mouse button held down.
Double-click warning.
The Double, Triple, and Quadruple events match on repetitions of an event within a short period of time. These are commonly used with mouse events. Be careful: The binding for the regular press event will match on the first press of the Double. Then the command bound to the Double event will match on the second press. Similarly, a Double event will match on the first two presses of a Triple event, and so on. Verify this by trying out the following bindings:
bind . <1> {puts stdout 1} bind . <Double-1> {puts stdout 2} bind . <Triple-1> {puts stdout 3}
If you click the first mouse button several times quickly, you will see a 1, 2, and then a few 3's output. Your bindings must take into consideration that more than one binding might match a Double, Triple, or Quadruple event. This effect is compatible with an interface that selects an object with the first click, and then operates on the selected object with a Double event. In an editor, character, word, line, and paragraph selection on a single, double, triple, and quadruple click, respectively, is a good example.[*]
If you really want to disable this, you can experiment with using after to postpone processing of one event. The time constant in the bind implementation of <Double> is 500 milliseconds. At the single-click event, schedule its action to occur after 600 milliseconds, and verify at that time that the <Double> event has not occurred.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Table 29-2 summarizes the modifiers.
The UNIX xmodmap program returns the current mappings from keys to these modifiers. The
first column of its output lists the modifier. The rest of each line identifies the keysym(s) and low-level keycodes that are mapped to each modifier. The xmodmap program can also be used to change mappings. The following example shows the mappings on my system. Your setup may be different.
[ Team LiB ]
[ Team LiB ]
Event Sequences
The bind VERSION OF CHM TO PDF events in a specification, and most commonly this is UNREGISTEREDcommand accepts a sequence of CONVERTER By THETA-SOFTWARE a sequence of key events. In the following examples, the Key events are abbreviated to just the character detail, and so abc is a sequence of three Key events:
bindtags $w [list $w Text [winfo toplevel $w] all] bind $w <Control-x> break bind $w <Control-x><Control-s> {Save ; break} bind $w <Control-x><Control-c> {Quit ; break}
The break ensures that the default Text binding that inserts characters does not trigger. This trick is embodied by BindSequence in the next example. If a sequence is detected, then a break binding is added for the prefix. The procedure also supports the emacs convention that <Meta-x> is equivalent to <Escape>x. This convention arose because Meta is not that standard across keyboards. There is no meta key at all on Windows and Macintosh keyboards. The regexp command is used to pick out the detail from the <Meta> event.
The use of break and continue in bindings is not supported in Tk 3.6 and earlier. This is because only a single binding tag can match an event. To make a prefix of a sequence harmless in Tk 3.6, bind a space to it:
bind $w $prefix { }
This installs a binding for the widget, which suppresses the class binding in Tk 3.6. The space is different than a null string, {}. Binding to a null string deletes the current binding instead of replacing it with a harmless one. [ Team LiB ]
[ Team LiB ]
Virtual Events
A virtual event corresponds to one or more event sequences. THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER By When any of the event sequences occurs, then the virtual event occurs. Example 29-4 shows the cut, copy, and paste virtual events for each platform:
You can define more than one physical event that maps to the same virtual event:
With this definition any of the physical events will trigger a <<Cancel>>. This would be convenient if the same user commonly used your application on different platforms. However, it is also possible that the physical bindings on different platforms overlap in conflicting ways. By default, virtual event definitions add to existing definitions for the same virtual event. The previous command could be replaced with these three:
event add <<Cancel>> <Control-c> event add <<Cancel>> <Escape> event add <<Cancel>> <Command-period>
Several widgets use virtual events as a notification mechanism. They generate virtual events in response to various conditions so that you can create bindings to respond to those conditions. For example, the listbox widget generates a <<ListboxSelect>> virtual event whenever the listbox selection changes. The easiest way to respond to changes to the listbox selection is to
[ Team LiB ]
[ Team LiB ]
Generating Events
Your application can use the event PDF CONVERTER programmatically generate UNREGISTERED VERSION OF CHM TO generate command toBy THETA-SOFTWARE events, in essence emulating user interaction. You can generate either standard windowing events or virtual events. However, you can generate events only for the current application; you can't send events to other applications running on your system. (In other words, you can't use the event generate command to have your application control another application.) The first argument to event generate is the target widget for the event. You may provide long as it is for a window in the current application. The second argument is an event specification, using the same syntax as for creating event bindings. (See "Event Syntax" on page 439.) However, you can't generate an event sequence (such as <KeyPress-Escape><KeyPress-a>), only single events. As an example, the following command delivers a ButtonPress-3 event to a widget:
UNREGISTERED path name of the widget, or the CONVERTER By THETA-SOFTWARE VERSION OF CHM TO PDF window identifier (such as returned by winfo id) as either the
Remember that a widget must have keyboard focus to receive KeyPress or KeyRelease events. You can use the focus command to assign keyboard focus to a widget:
The event generate command also accepts options to specify additional attributes of the event, such as the x and y mouse position. Table 29-4 lists the event generate options. Of note is the -warp option, added in Tk 8.3. If you provide a -warp value of True, then the mouse pointer moves to the x and y coordinates of the generated event; otherwise, the mouse pointer remains at its current location. For example, the following commands moves the mouse pointer to the point 10,20 relative to the top-left corner of the main window:
[ Team LiB ]
[ Team LiB ]
Event Summary
Event Command Syntax
The event command is summarized in Table 29-3.
event delete virt event info event info virt event generate win event ?opt val? ...
Event Keywords
Table 29-4 lists the percent keywords and the corresponding option to the event generate command. Remember that keyword substitutions occur throughout the command, regardless of other Tcl quoting conventions. Keep your binding commands short, introducing procedures if needed. For the details about various event fields, consult the Xlib Reference Manual (O'Reilly & Associates, Inc.). The string values for the keyword substitutions are listed after a short description of the keyword. If no string values are listed, the keyword has an integer value like a coordinate or a window ID.
%d -detail value The detail field. Values: NotifyAncestor, NotifyNonlinearVirtual, NotifyDetailNone, NotifyPointer, NotifyInferior, NotifyPointerRoot, NotifyNonlinear, or NotifyVirtual. Events: Enter, Leave, FocusIn, and FocusOut. %f -focus boolean The focus field (0 or 1). Events: Enter and Leave. The height field. Events: Configure and Expose. The window field from the event, represented as a hexadecimal integer. All events. The keycode field. Events: KeyPress and KeyRelease.
The subwindow ID. All events. The type field. All events. The Tk pathname of the widget receiving the event. All events. The x_root field. Relative to the (virtual) root window. Events: ButtonPress, ButtonRelease, KeyPress, KeyRelease, and Motion. The y_root field. Relative to the (virtual) root window. Events: ButtonPress, ButtonRelease, KeyPress, KeyRelease, and Motion.
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OFscript will look different depending on the platform it is running on. widgets, so a single CHM TO PDF CONVERTER By THETA-SOFTWARE
Associated with the widgets is a resource database that stores settings like colors and fonts. Chapter 31 describes the resource database and generalizes it to store button and menu configurations. Chapter 32 describes a few simple widgets. The frame, labelframe, and toplevel are containers for other widgets. The label displays a text string. The message formats a long text string onto multiple lines. The scale represents a numeric value. The bell command rings the terminal bell. Chapter 33 describes scrollbars, which can be attached in a general way to other widgets. Chapter 34 describes entry widgets, which provide one line of editable text and spinboxes, which allow users to select from multiple values by "spinning" through selections. Chapter 35 describes the listbox widget that displays several lines of text. The lines are manipulated as units. Chapter 36 describes the general-purpose text widget. It can display multiple fonts and have binding tags on ranges of text. Chapter 37 describes the canvas widget. The canvas manages objects like lines, boxes, images, arcs, and text labels. You can have binding tags on these objects and classes of objects. [ Team LiB ]
[ Team LiB ]
This chapter describes a few useful techniques for setting up the commands in more general cases. If you use variables inside button commands, you have to understand the scoping rules that apply. This is the first topic of the chapter. Once you get scoping figured out, then the other aspects of buttons and menus are quite straightforward. [ Team LiB ]
[ Team LiB ]
I think of this as the "now" (i.e., button definition) and "later" (i.e., button use) scope problem. For example, you may want to use the values of some variables when you define a button UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE command but use the value of other variables when the button command is used. When these two contexts are mixed, it can be confusing. The next example illustrates the problem. The button's command involves two variables: x and val. The global variable x is needed later, when the button's command executes. The local variable val is needed now, in order to define the command. Example 30-1 shows this awkward mixture of scopes:
proc Trouble {args} { set b 0 # Display the value of x, a global variable label .label -textvariable x set f [frame .buttons -borderwidth 10] # Create buttons that multiply x by their value foreach val $args { button $f.$b -text $val \ -command "set x \[expr \$x * $val\]" pack $f.$b -side left incr b } pack .label $f } set x 1 Trouble -1 4 7 36
The example uses a label widget to display the current value of x. The textvariable attribute is used so that the label displays the current value of the variable, which is always a global variable. It is not necessary to have a global command inside Trouble because the value of x is not used there. The button's command is executed later at the global scope. The definition of the button's command is ugly, though. The value of the loop variable val is needed when the button is defined, but the rest of the substitutions need to be deferred until
later. The variable substitution of $x and the command substitution of expr are suppressed by quoting with backslashes:
In contrast, the following command assigns a constant expression to x each time the button is clicked, and it depends on the current value of x, which is not defined the first time through the loop. Clearly, this is incorrect:
Another incorrect approach is to quote the whole command with braces. This defers too much, preventing the value of val from being used at the correct time.
The general technique for dealing with these sorts of scoping problems is to introduce Tcl procedures for use as the button commands. Example 30-2 introduces a little procedure to encapsulate the expression:
It may seem just like extra work to introduce the helper procedure, UpdateX. However, it
makes the code clearer in two ways. First, you do not have to struggle with backslashes to get the button command defined correctly. Second, the code is much clearer about the function of the button. Its job is to update the global variable x. You can generalize UpdateX to work on any variable by passing the name of the variable to update. Now it becomes much like the incr command:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE button $f.$b -text $val -command "Update x $val"
The definition of Update uses upvar, which is explained on page 91, to manipulate the named variable in the global scope:
Double quotes are used in the button command to allow $val to be substituted. Whenever you use quotes like this, you have to be aware of the possible values for the substitutions. If you are not careful, the command you create may not be parsed correctly. The safest way to generate the command is with list:
Using list ensures that the command is a list of two elements, UpdateX and the value of val. This is important because UpdateX takes only a single argument. If val contained white space, then the resulting command would be parsed into more words than you expected. Of course, in this case we plan to always call LessTrouble with an integer value, which does not contain white space. Example 30-3 provides a more straightforward application of procedures for button commands. In this case the advantage of the procedure MaxLineLength is that it creates a scope for the local variables used during the button action. This ensures that the local variables do not accidentally conflict with global variables used elsewhere in the program. There is also the standard advantage of a procedure, which is that you may find another use for the action in another part of your program.
set max 0 if [catch {open $file} in] { return $in } foreach line [split [read $in] \n] { set len [string length $line] if {$len > $max} { set max $len } } return "Longest line is $max characters" } # Create an entry to accept the file name, # a label to display the result # and a button to invoke the action . config -borderwidth 10 entry .e -width 30 -bg white -relief sunken button .doit -text "Max Line Length" \ -command {.label config -text [MaxLineLength [.e get]]} label .label -text "Enter file name" pack .e .doit .label -side top -pady 5
The example is centered around the MaxLineLength procedure. This opens a file and loops over the lines finding the longest one. The file open is protected with catch in case the user enters a bogus file name. In that case, the procedure returns the error message from open. Otherwise, the procedure returns a message about the longest line in the file. The local variables in, max, and len are hidden inside the scope of the procedure. The user interface has three widgets: an entry for user input, the button, and a label to display the result. These are packed into a vertical stack, and the main window is given a border. Obviously, this simple interface can be improved in several ways. There is no Quit button, for example. All the action happens in the button command:
Braces are used when defining the button command so that the command substitutions all happen when the button is clicked. The value of the entry widget is obtained with .e get. This value is passed into MaxLineLength, and the result is configured as the text for the label. This command is still a little complex for a button command. For example, suppose you wanted to invoke the same command when the user pressed <Return> in the entry. You would end up repeating this command in the entry binding. It might be better to introduce a one-line procedure to capture this action so that it is easy to bind the action to more than one user action. Here is how that might look:
proc Doit {} { .label config -text [MaxLineLength [.e get]] } button .doit -text "Max Line Length" -command Doit bind .e <Return> Doit
Chapter 29 describes the bind command in detail, Chapter 32 describes the label widget, and Chapter 35 describes the entry widget. [ Team LiB ]
[ Team LiB ]
proc ShowChoices { parent varname args } { set f [frame $parent.choices -borderwidth 5] set b 0 foreach item $args { radiobutton $f.$b -variable $varname \ -text $item -value $item pack $f.$b -side left incr b } pack $f -side top } proc ShowBooleans { parent args } { set f [frame $parent.booleans -borderwidth 5] set b 0 foreach item $args { checkbutton $f.$b -text $item -variable $item pack $f.$b -side left incr b } pack $f -side top } set choice kiwi ShowChoices {} choice apple orange peach kiwi strawberry set Bold 1 ; set Italic 1 ShowBooleans {} Bold Italic Underline
The ShowChoices procedure takes as arguments the parent frame, the name of a variable, and
a set of possible values for that variable. If the parent frame is null, {}, then the interface is packed into the main window. ShowChoices creates a radiobutton for each value, and it puts the value into the text of the button. It also has to specify the value to assign to the variable when the button is clicked because the default value associated with a radiobutton is the empty string. The ShowBooleans procedure is similar to ShowChoices. It takes a set of variable names as arguments, and it creates a checkbutton for each variable. The default values for the UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE variable associated with a checkbutton are zero and one, which is fine for this example. If you need particular values, you can specify them with the -onvalue and -offvalue options. Radiobuttons and checkbuttons can have commands associated with them, just like ordinary buttons. The command is invoked after the associated Tcl variable has been updated. Remember that the Tcl variable associated with the button is defined in the global scope. For UNREGISTERED you could log the changes to variables as shown Bythe next example. VERSION OF CHM TO PDF CONVERTER in THETA-SOFTWARE example,
[ Team LiB ]
[ Team LiB ]
Button Attributes
Table 30-1 lists the attributes for the button, checkbutton, menubutton, and radiobutton widgets. Unless otherwise indicated, the attributes apply to all of these widget types. Chapters 40, 41, and 42 discuss many of these attributes in more detail. Some attributes are ignored on the Windows and Macintosh platforms because they are not supported by the native button widgets. The table uses the resource name for the attributes, which has capitals at internal word boundaries. In Tcl commands, the attributes are specified with a dash and they are all lowercase. Compare:
The first command defines a resource database entry that covers all menubuttons and gives them a red active background. This only affects menubuttons created after the database entry is added. The second command changes an existing menubutton (.mb) to have a red active background. Note the difference in capitalization of background in the two commands. The resource database is introduced on page 372, and Chapter 31 explains how to use the resource database in more detail.
Font for the text. Foreground (text) color. (Also fg). Height, in lines for text, or screen units for images.
highlightBackground Focus highlight color when widget does not have focus.
highlightColor
UNREGISTERED VERSION OFcheckbutton, menubutton, and radiobutton. CHM TO PDF CONVERTER By THETA-SOFTWARE
justify menu offRelief offValue onValue overRelief padX padY relief repeatDelay repeatInterval selectColor selectImage state takeFocus text textVariable underline value variable Text justification: center, left, or right. Menu posted when menubutton is clicked. Alternate relief style when the widget is deselected. checkbutton and radiobutton. (Tk 8.4) Value for Tcl variable when checkbutton is not selected. Value for Tcl variable when checkbutton is selected. Alternate relief style when mouse is over the widget. button, checkbutton, and radiobutton. (Tk 8.4) Extra space to the left and right of the button text. Extra space above and below the button text. flat, sunken, raised, groove, solid or ridge. The number of milliseconds a button or key must be held down before it begins to auto-repeat. For button only. (Tk 8.4) The number of milliseconds between auto-repeats. For button only. (Tk 8.4) Color for selector. checkbutton or radiobutton. Alternate graphic image for selector: checkbutton or radiobutton. normal (enabled), disabled (deactivated), or active (when the mouse pointer is over the button). Control focus changes from keyboard traversal. Text to display in the button. Tcl variable that has the value of the text. Index of text character to underline. Value for Tcl variable when radiobutton is selected. Tcl variable associated with the button: checkbutton or radiobutton.
width
Width in characters for text, or screen units for image. As of Tk 8.4, on Windows only, a negative value is treated as a minimum width for button widgets only. Maximum character length before text is wrapped, in screen units.
[ Team LiB ]
Button Operations
Table 30-2 summarizes the operations on CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF button widgets. In the table, $w is a button, checkbutton, radiobutton, or menubutton, except when noted. For the most part, these operations are used by the script libraries that implement the bindings for buttons. The cget and configure operations are the most commonly used by applications.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Table 30-2. Button operations
$w cget option $w configure ? option? ?value? ... $w deselect Returns the value of the specified attribute. Queries or manipulates the configuration information for the widget. Deselects the radiobutton or checkbutton. Set the radiobutton variable to the null string. Set the checkbutton variable to the off value. Redisplays the button several times in alternate colors. Invokes the command associated with the button. Selects the radiobutton or checkbutton, setting the associated variable appropriately. Toggles the state of the checkbutton, setting the associated variable appropriately.
[ Team LiB ]
[ Team LiB ]
menubutton .mb -text Sampler -menu .mb.menu pack .mb -padx 10 -pady 10
set m [menu .mb.menu -tearoff 1] $m add command -label Hello! -command {puts "Hello, World!"} $m add check -label Boolean -variable foo \ -command {puts "foo = $foo"} $m add separator $m add cascade -label Fruit -menu $m.sub1 set m2 [menu $m.sub1 -tearoff 0] $m2 add VERSION OF CHM TO PDF CONVERTER apple UNREGISTEREDradio -label apple -variable fruit -valueBy THETA-SOFTWARE $m2 add radio -label orange -variable fruit -value orange $m2 add radio -label kiwi -variable fruit -value kiwi
The example creates a menubutton and two menus. The main menu .mb.menu is a child of the menubutton .mb. This relationship is necessary so that the menu displays correctly when the UNREGISTERED VERSION OF CHM TO PDF CONVERTER .mb.menu.sub1 is a child of the main By THETA-SOFTWARE menubutton is selected. Similarly, the cascaded submenu menu. The first menu entry is represented by the dashed line. This is a tear-off entry that, when selected, makes a copy of the menu in a new top-level window. This is useful if the menu operations are invoked frequently. The -tearoff 0 argument is used when creating the submenu to eliminate its tear-off entry. The command, radio, and check entries are similar to the corresponding button types. The configuration options for menu entries are similar to those for buttons. The main difference is that the text string in the menu entry is defined with the -label option, not -text. Table 30-6 gives the complete set of options for menu entries. The cascade menu entry is associated with another menu. It is distinguished by the small right arrow in the entry. When you select the entry, the submenu is posted. It is possible to have several levels of cascaded menus. There is no limit to the number of levels, except that your users will complain if you nest too many menus.
A Menu Bar
You can create a menu bar manually by packing several menubuttons into a frame. The default bindings on menubuttons are such that you can drag your mouse over the menu bar and the different menus will display as you drag over their menubutton. Tk 8.0 lets you create a menu bar as a horizontal menu that is associated with a top-level window. On Windows and UNIX the menu is displayed along the top of the window. On Macintosh this menu replaces the main menu along the top of the screen when the window is activated. The menu bar menu should have all cascade entries so that when you select an entry, another menu is displayed. This is illustrated in Example 30-7. It defines variables that store the names of the menu widgets:
This creates a variable named File, Edit, and Help that store the names of the menu widgets. This trick is generalized on page 470 in a package that hides the menu widget names.
# attach it to the main window . config -menu .menubar # Create more cascade menus foreach m {File Edit Help} { set $m [menu .menubar.m$m] .menubar add cascade -label $m -menu .menubar.m$m } $File add command -label Quit -command exit # add more menu items...
System Menus
The Tk 8.0 menu bar implementation can add entries to the Windows system menu, the Macintosh Apple menu, and the Help menu on all platforms. This works by recognizing special names. For example, if the menu bar is .menubar, then the special names are .menubar.system, .menubar.apple, and .menubar.help. The Help menu is right justified on all platforms. The Apple menu is normally used by applications for their About... entry. The entries you add to the Apple menu are added to the top of the menu. The System menu appears in the Windows title bar and has entries such as Close and Minimize.
Pop-Up Menus
A pop-up menu is not associated with a menubutton. Instead, it is posted in response to a keystroke or other event in the application. The tk_popup command posts a pop-up menu:
The last argument specifies the entry to activate when the menu is posted. It is an optional parameter that defaults to 1, which avoids the tear-off entry in position zero. The menu is posted at the specified X and Y coordinates in its parent widget.
Option Menus
An option menu represents a choice with a set of radio entries, and it displays the current choice in the text of the menubutton. The tk_optionMenu command creates a menubutton and a menu full of radio entries:
The first argument is the pathname of the menubutton to create. The second is the variable name. The third is the initial value for the variable, and the rest are the other choices for the value. The menubutton displays the current choice and a small symbol, the indicator, to indicate it is an option menu.
[ Team LiB ]
If the File menu is implemented as a menu bar cascade, you create the traversal highlight like this:
menu .mbar . configure -menu .mbar .mbar add cascade -label File -underline 0 \ -menu .mbar.file
When the user types <Alt-f> over the main window, the menu is posted. The case of the highlighted letter is not important. After a menu is posted, the arrow keys change the selected entry. The <Up> and <Down> keys move within a menu, and the <Left> and <Right> keys move between adjacent menus. The bindings assume that you create your menus from left to right. If any of the menu entries have a letter highlighted with the -underline option, typing that letter invokes that menu entry. For example, an Export entry that is invoked by typing x can be created like this:
The <space> and <Return> keys invoke the menu entry that is currently selected. The <Escape> key aborts the menu selection and removes the menu.
selection is to bind to this virtual event, as shown in Example 30-8. Notification like this is useful for features such as context-sensitive help.
UNREGISTERED"Menu $w selection: TO PDF CONVERTER By THETA-SOFTWARE puts VERSION OF CHM [$w entrycget active -label]"
} bind .mbar.file <<MenuSelect>> {MenuChanged %W}
[ Team LiB ]
[ Team LiB ]
@ycoord The entry under the given Y coordinate. Use @%y in bindings. pattern A string match pattern to match the label of a menu entry. Table 30-4 summarizes the complete set of menu operations. In the table, $w is a menu widget.
$w activate index $w add type ?option value? ... $w cget option $w clone
Highlights the specified entry. Adds a new menu entry of the specified type with the given values for various attributes. Returns the value for the configuration option. Makes a linked copy of the menu. This is used to Returns the configuration information for the menu. Deletes the menu entries from index i1 to i2.
implement tear-offs and menu bars. UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE $w configure ?option? ?value? ... $w delete i1 ?i2?
$w entrycget index option Returns the value By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTERof option for the specified entry. $w entryconfigure index ? option? ?value? ... $w index index $w insert type index ?option value? ... $w invoke index $w post x y $w postcascade index $w type index $w unpost $w yposition index [ Team LiB ] Queries or modifies the configuration information for the specified menu entry. Returns the numerical value of index. Like add, but inserts the new entry after the specified index. Invokes the command associated with the entry. Displays the menu at the specified coordinates. Displays the cascade menu from entry index. Returns the type of the entry at index. Unmaps the menu. Returns the Y coordinate of the top of the entry.
[ Team LiB ]
Menu Attributes
A menu has a few global attributes, and then each menu entry has many button-like attributes that describe its appearance and behavior. Table 30-5 specifies the attributes that apply globally to the menu, unless overridden by a per-entry attribute. The table uses the X resource names, which may have a capital at interior word boundaries. In Tcl commands, use all lowercase and a leading dash.
disabledForeground Foreground (text) color when menu entries are disabled. font foreground postCommand relief selectColor takeFocus tearOff tearOffCommand title Default font for the text. Foreground color. (Also fg). Tcl command to run just before the menu is posted. The relief style of the menu (except on systems where native menus are used such, as Windows). Color for selector in check and radio type entries. Control focus changes from keyboard traversal. True if menu should contain a tear-off entry. Command to execute when menu is torn off. Two arguments are added: the original menu and the new tear-off. Title for the window created when the menu is torn off. If this is an empty string (default), the title is the text of the menubutton or cascade item from which this menu was torn off. (Tk 8.0) (Read-only) normal, menubar, or tearoff. (Tk 8.0).
type
Table 30-6 describes the attributes for menu entries, as you would use them in a Tcl command (i.e., all lowercase with a leading dash.) The attributes for menu entries are not supported directly by the resource database. However, Example 31-6 on page 481 describes how you can use the resource database for menu entries.
UNREGISTERED VERSION OF command to invoke when entry is invoked. -command Tcl CHM TO PDF CONVERTER By THETA-SOFTWARE
-compound -font -foreground -hidemargin -image -indicatoron -label -menu -offvalue -onvalue -selectcolor -selectimage -state -underline -value -variable [ Team LiB ] Where the image or bitmap should be placed relative to the text: bottom, center, left, right, top or none (default). (Tk 8.4) Default font for the text. Foreground color. (Also fg). Suppresses the margin reserved for button indicators. (Tk 8.0). Image to display instead of text or bitmap. Boolean that controls if the indicator is displayed: check and radio entries. Text to display in the menu entry. Menu posted when cascade entry is invoked. Variable value when check entry is not selected. Value for Tcl variable when check entry is selected. Color for selector: check and radio entries. Alternate image to use when entry is selected: check and radio entries. The state: normal, active, or disabled Index of text character to underline. Value for Tcl variable when radiobutton entry is selected. Tcl variable associated with the check or radio entry.
[ Team LiB ]
These procedures are repeated in Example 30-10, except that they use the Tk 8.0 menu bar mechanism. The rest of the procedures in the package are the same with either version of menu bars.
proc Menu_Setup { menubar } { global menu menu $menubar # Associated menu with its main window set top [winfo parent $menubar] $top config -menu $menubar UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE set menu(menubar) $menubar set menu(uid) 0 } proc Menu { label } { global menu if [info exists menu(menu,$label)] { UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE error "Menu $label already defined" } # Create the cascade menu set menuName $menu(menubar).mb$menu(uid) incr menu(uid) menu $menuName -tearoff 1 $menu(menubar) add cascade -label $label -menu $menuName # Remember the name to menu mapping set menu(menu,$label) $menuName }
Once the menu is set up, the menu array is used to map from a menu name, like File, to the Tk widget name such as .menubar.mb3. Even though this can be done with a couple of lines of Tcl code, the mapping is put inside the MenuGet procedure to hide the implementation. MenuGet uses return -code error if the menu name is unknown, which changes the error reporting slightly as shown in Example 6-19 on page 86. If the user specifies a bogus menu name, the undefined variable error is caught and a more informative error is raised instead. MenuGet is private to the package, so it does not have an underscore in its name.
The procedures Menu_Command, Menu_Check, Menu_Radio, and Menu_Separator are simple wrappers around the basic menu commands. They use MenuGet to map from the menu label to the Tk widget name.
$m add command -label $label -command $command } proc Menu_Check { menuName label var { command {} } } { set m [MenuGet $menuName] $m add check -label $label -command $command \ -variable $var } proc Menu_Radio { menuName label var {val {}} {command {}} } { set m [MenuGet $menuName] if {[string length $val] == 0} { set val $label } $m add radio -label $label -command $command \ -value $val -variable $var } proc Menu_Separator { menuName } { [MenuGet $menuName] add separator }
Creating a cascaded menu also requires saving the mapping between the label in the cascade entry and the Tk pathname for the submenu. This package imposes a restriction that different menus, including submenus, cannot have the same label.
Creating the sampler menu with this package looks like this:
Menu_Cascade Sampler Fruit Menu_Radio Fruit apple fruit Menu_Radio Fruit orange fruit Menu_Radio Fruit kiwi fruit
Menu Accelerators
The Menu_Bind command uses the index operation to find out what menu entry has the given label. It sets up a binding for the key sequence that will invoke the menu operation, and it updates the display of the accelerator using the entryconfigure operation. This approach has the advantage of keeping the keystroke command consistent with the menu command, as well as updating the display. The MenuInvoke procedure is used for the binding. We could use entrycget to fetch the command, and then bind directly to that. However, that wouldn't honor the state of the menu entry, which could be temporarily disabled. In addition, the invoke operation on the menu handles any special cases such as updating radiobutton variables associated with the entry. To try Menu_Bind, add an empty frame to the sampler example, and bind a keystroke to it and one of the menu commands, like this:
frame .body -width 100 -height 50 pack .body ; focus .body Menu_Bind .body <Control-q> Ctrl-Q Sampler Hello!
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
An Introduction to Resources
When a Tk widget is created, its attributes are set by one of three sources. It is important to note that Tcl command specifications have priority over resource database specifications: The most evident source of attributes are the options in Tcl commands, such as the -text quit attribute specification for a button. If an attribute is not specified on the command line, then the resource database is queried as described later. If there is nothing in the resource database, then a hard-coded value from the widget implementation is used. The resource database consists of a set of keys and values. Unlike many other databases, however, the keys are patterns that are matched against the names of widgets and attributes. This makes it possible to specify attribute values for a large number of widgets with just a few database entries. In addition, the resource database can be shared by many applications, so users and administrators can define common attributes for their whole set of applications. The resource database is maintained in main memory by the Tk toolkit. On UNIX the database is initialized from the RESOURCE_MANAGER property on the root window, or the .Xdefaults file in your home directory. On Windows and Macintosh, there are a few resources added by the tk.tcl library file. Additional files can be explicitly loaded with the option readfile command, and individual database entries are added with the option add Tcl command. The initialization of the database is different from the Xt toolkit, which loads specifications from as many as five different files to allow per-user, per-site, per-application, per-machine, and per-user-per-application specifications. You can achieve the same effect in Tk, but you must do it yourself. Example 45-1 on page 672 gives a partial solution.
Resource Patterns
The pattern language for the keys is related to the naming convention for Tk widgets. Recall that a widget name reflects its position in the hierarchy of windows. You can think of the resource names as extending the hierarchy one more level at the bottom to account for all the attributes of each individual widget. There is also a new level of the hierarchy at the top to specify the application by name. For example, the database could contain an entry like the following in order to define a font for the quit button in a frame called .buttons:
Exmh.buttons.quit.font: fixed
The leading Exmh. matches the class name for the Tcl/Tk application. The class name of the application is set from the name of the script file, with the first character capitalized. For example, if the script is /usr/local/bin/foobar, then the class is set to Foobar. You could also specify an asterisk to match any application:
*buttons.quit.font: fixed
Resource keys can also specify classes of widgets and attributes as opposed to individual instances. The quit button, for example, is an instance of the Button class. Class names for widgets are the same as the Tcl command used to create them, except for a leading capital UNREGISTERED VERSION OF CHM TO that would set the font forTHETA-SOFTWARE letter. A class-oriented specification PDF CONVERTER By all buttons in the .buttons frame would be:
Exmh.buttons.Button.font: fixed
The application class name becomes the class name for the main toplevel window. For example, if you use a script name like button.tcl, the class for . becomes Button. This causes it to inherit all the standard Button bindings and attribute values, which can cause problems in your application. Patterns let you replace one or more components of the resource name with an asterisk (*). For example, to set the font for all the widgets packed into the .buttons frame, you can use the resource name *buttons*font, or you can specify the font for all buttons with the pattern *Button.font. In these examples, we have replaced the leading Tk. with an asterisk as well. It is the ability to collapse several layers of the hierarchical name with a single asterisk that makes it easy to specify attributes for many widgets with just a few database entries. The tables in this book list attributes by their resource name. The resource names use a capital letter at the internal word boundaries. For example, if the command line switch is -offvalue, then the corresponding resource name is offValue. There are also class names for attributes, which are distinguished with a leading capital (e.g., OffValue).
The matching between a widget name and the patterns in the database can be ambiguous, with multiple patterns matching the same widget. The order of database entries determines which pattern is used, with later entries taking precedence. (This is different from the Xt toolkit, in which longer matching patterns have precedence, and instance specifications have priority over class specifications.) Suppose the database contained just two entries, in this order:
Despite the more specific *Text*foreground entry, all widgets will have a red foreground, even text widgets. For this reason you should list your most general patterns early in your resource files and give the more specific patterns later. Tk also supports different priorities among resources, as described in the next section. The ordering precedence described here applies to all resources with the same priority. [ Team LiB ]
[ Team LiB ]
key: value
The key has the pattern format previously described. The value can be anything, and there is no need to group multiword values with any quoting characters. In fact, quotes will be picked up as part of the value. Comment lines are introduced by the exclamation mark (!).
The example resource file specifies the color scheme for the Tk widget set on UNIX that is based on a family of gray levels. Color highlighting shows up well against this backdrop. These colors are applied generically to all the widgets. The hexadecimal values for the colors specify two digits (eight bits) each for red, green, and blue. Chapter 41 describes the use of color in detail. [ Team LiB ]
[ Team LiB ]
option clear
However, on UNIX the database will be initialized from your ~/.Xdefaults file, or the RESOURCE_MANAGER property on the root window, the next time the database is accessed.
[ Team LiB ]
[ Team LiB ]
The window is a Tk widget pathname. The name is a resource name. In this case, it is not a pattern or a full name. Instead, it is the resource name as specified in the tables in this book. Similarly, the class is a simple class name. It is possible to specify a null name or class. If there is no matching database entry, option get returns the empty string. It is not possible to enumerate the database, nor can you detect the difference between a value that is the empty string and the absence of a value. You can work around this by introducing well-known resource names that list other resources. This trick is used in the next section. [ Team LiB ]
[ Team LiB ]
User-Defined Buttons
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Suppose you want users to be able to define a set of their own buttons for frequently executed commands. Or perhaps users can augment the application with their own Tcl code. The following scheme, which is based on an idea from John LoVerso, lets them define buttons to invoke their own code or their favorite commands. The application creates a special frame to hold the user-defined buttons and places it
UNREGISTERED VERSION OF CHM TOcreated like this: PDF CONVERTER By THETA-SOFTWARE appropriately. Assume the frame is
frame .user -class User
The class specification for the frame means that we can name resources for the widgets inside the frame relative to *User. Users specify the buttons that go in the frame via a personal file containing resource specifications. The first problem is that there is no means to enumerate the database, so we must create a resource that lists the names of the user-defined buttons. We use the name buttonlist and make an entry for *User.buttonlist that specifies which buttons are being defined. It is possible to use artificial resource names (e.g., buttonlist), but they must be relative to an existing Tk widget.
In Example 31-3, we have listed four buttons and specified some of the attributes for each, most importantly the text and command attributes. We are assuming, of course, that the application manual publishes a set of commands that users can invoke safely. In this simple example, the commands are all one word, but there is no problem with multiword commands. There is no interpretation done of the value, so it can include references to Tcl variables and nested command calls. Example 31-4 uses these resource specifications to define the buttons:
frame $f -class $class -borderwidth 2 pack $f -side top -fill x foreach b [option get $f buttonlist {}] { if [catch {button $f.$b}] { button $f.$b -font fixed } pack $f.$b -side right } }
The catch phrase is introduced to handle a common problem with fonts and widget creation. If the user's resources specify a bogus or missing font, then the widget creation command will fail. The catch phrase guards against this case by falling back to the fixed font, which is guaranteed to exist. This problem is fixed in Tk 8.0 because the font mechanism will search for alternate fonts. Example 31-5 assumes that the resource specifications from Example 31-2 are in the file button.resources. It creates the user-defined buttons in the .users frame.
[ Team LiB ]
[ Team LiB ]
User-Defined Menus
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
User-defined menus can be set up with a similar scheme. However, it is more complex because there are no resources for specific menu entries. We must use more artificial resources to emulate this. We use menulist to name the set of menus. Then, for each of these, we define an entrylist resource. Finally, for each entry we define a few more resources. The name of the entry has to be combined with some type information, which leads to the following convention: l_entry is the label for the entry. t_entry is the type of the entry. c_entry is the command associated with the entry. v_entry is the variable associated with the entry. m_entry is the menu associated with the entry.
*User.menulist: stuff *User.stuff.text: My stuff *User.stuff.m.entrylist: keep insert find *User.stuff.m.l_keep: Keep on send *User.stuff.m.t_keep: check *User.stuff.m.v_keep: checkvar *User.stuff.m.l_insert: Insert File... *User.stuff.m.c_insert: InsertFileDialog *User.stuff.m.l_find: Find *User.stuff.m.t_find: cascade *User.stuff.m.m_find: find *User.stuff.m.find.entrylist: next prev *User.stuff.m.find.tearoff: 0 *User.stuff.m.find.l_next: Next *User.stuff.m.find.c_next: Find_Next
In Example 31-6, .user.stuff is a Tk menubutton. It has a menu as its child, .user.stuff.m, where the menu .m is set by convention. You will see this later in the code for Resource_Menubar. The entrylist for the menu is similar in spirit to the buttonlist resource. For each entry, however, we have to be a little creative with the next level of resource names. The following does not work:
The problem is that Tk does not directly support resources for menu entries, so it assumes .stuff.m.keep is a widget pathname, but it is not. You can add the resource, but you cannot retrieve it with option get. Instead, we must combine the attribute information (i.e., label) with the name of the entry:
You must do something similar if you want to define resources for items on a canvas, too, because that is not supported directly by Tk. The code to support menu definition by resources is shown in the next example:
UNREGISTERED
UNREGISTERED
radio { $menu add radiobutton -label $l -command $c \ -variable $v -value $l } separator { $menu add separator } cascade { VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE set sub [option get $menu m_$e {}] if {[string length $sub] != 0} { set submenu [menu $menu.$sub] $menu add cascade -label $l -command $c \ -menu $submenu ResourceMenu TO PDF CONVERTER By THETA-SOFTWARE VERSION OF CHM $submenu } } default { $menu add command -label $l -command $c }
} } }
set l-res [option get $w l-$resname {}] set u-res [option get $w u-$resname {}] # Site-local deletions from application resources set list [lsubtract $res ${l-res}] # Site-local additions set list [concat $list $lres] # Per-user deletions set list [lsubtract $list ${u-res}] # Per-user additions return [concat $list $ures] } proc lsubtract { orig nuke } { # Remove elements in $nuke from $orig foreach x $nuke { set ix [lsearch $orig $x] if {$ix >= 0} { set orig [lreplace $orig $ix $ix] } } return $orig }
Expanding Variables
If the command resource contains substitution syntax like $ and [], then these are evaluated later when the command is invoked by the button or menu. This is because there is no interpretation of the command value when the widgets are created. However, it may be that you want variables substituted when the buttons and menus are defined. You can use the subst command to do this:
set cmd [$button cget -command] $button config -command [subst $cmd]
Choosing the scope for the subst can be tricky. The previous command does the subst in the current scope. If this is the Resource_ButtonFrame procedure, then there are no interesting application-specific variables defined. The next command uses uplevel to do the subst in the scope of the caller of Resource_ButtonFrame. The list is necessary so that uplevel preserves the structure of the original subst command.
If you do a subst in ResourceMenu, then you need to keep track of the recursion level to get back to the scope of the caller of Resource_Menubar. The next few lines show what changes in ResourceMenu:
proc ResourceMenu { menu {level 1} } { foreach e [option get $menu entrylist {}] { # code omitted set c [option get $menu c_$e {}]
set c [uplevel $level [list subst $c]] # And the recursive call is ResourceMenu $submenu [expr $level+1] # more code omitted } }
UNREGISTERED VERSION OFoccur inTO PDF CONVERTER By THETA-SOFTWARE CHM the global scope, use this: If you want the subst to
$button config -command [uplevel #0 [list subst $cmd]]
UNREGISTERED the global scopeCHMnot be much different when you define the button than when However, VERSION OF may TO PDF CONVERTER By THETA-SOFTWARE
the button is invoked. In practice, I have used subst to capture variables defined in the procedure that calls Resource_Menubar.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
The labelframe widget, introduced in Tk 8.4, is a frame that can also display a widget along its border. The labelframe widget can create its own internal label, if needed, or it can UNREGISTERED VERSION OF CHM TO PDFyou create separately. CONVERTER By THETA-SOFTWARE automatically position a label widget that A toplevel widget is like a frame, except that it is created as a new main window. That is, it is not positioned inside the main window of the application. This is useful for dialog boxes, for example. A toplevel has the same attributes as a frame, plus screen and menu attributes. The menu attribute is used to create menubars along the top edge of a toplevel. This feature was added in Tk 8.0, and it is described on page 464. On UNIX, the screen option lets you put the toplevel on any X display. The value of the screen option has the following format:
host:display.screenNum
For example, I have one X server on my workstation sage that controls two screens. My two screens are named sage:0.0 and sage:0.1. If the screenNum specifier is left off, it defaults to 0.
Background color (also bg). Extra space around the edge of the frame. Resource class and binding class name. The value is new or the name of a window. If true, frame embeds another application. Cursor to display when mouse is over the frame. The font to use for the label. Labelframe only. The text color for the label. Labelframe only. Height, in screen units.
highlightBackground Focus highlight color when widget does not have focus. highlightColor highlightThickness labelAnchor labelWidget menu padX padY relief screen takeFocus text use visual width Focus highlight color when widget has focus. Thickness of focus highlight rectangle. Position of the embedded label; clockwise: nw (default), n, ne, en, e, es, se, s, sw, ws, w, wn. Labelframe only. Pathname of a widget to use as a label, overriding any -text option. The label must already exist. Labelframe only. The menu to use for the menubar. Toplevel only. Extra internal space to the left and right. Extra internal space above and below. flat, sunken, raised, groove, solid or ridge. An X display specification. (Toplevel only, and this cannot be specified in the resource database). Controls focus changes from keyboard traversal. The text of the embedded label. Labelframe only. A window ID from winfo id. This embeds the frame or toplevel into the specified window. Type: staticgrey, greyscale, staticcolor, pseudocolor, directcolor, or truecolor. Width, in screen units.
You cannot change the class, colormap, visual, or screen attributes after the frame, labelframe, or toplevel has been created. These settings are so fundamental that you need to destroy the frame and start over if you must change them.
groove, in comparison with the simple frame's default borderWidth of 0 and relief of flat. The rationale for this difference is that labelframes are used typically to set off distinct areas of a user interface, whereas frames are often used solely to group together other widgets for layout. In many cases, you can simply set the text attribute of the labelframe to display a textual label in the upper-left hand corner of the frame. Example 32-1 shows a labelframe around a group of radio buttons:
labelframe .s -text Sizes radiobutton .s.small -text Small -variable size -value small radiobutton .s.med -text Medium -variable size -value medium radiobutton .s.large -text Large -variable size -value large .s.large select pack .s.small .s.med .s.large -anchor w -padx 2 -pady 1 pack .s
You can change the appearance of the label's text by setting the font and foreground attributes as desired. The labelAnchor attribute accepts a map direction which controls the position of the label along the frame's border. The default, nw, places the label on the north (top) border on the west (left) side. In contrast, setting the labelAnchor to wn places the label on the west (left) border towards the north (top) side, as shown in Example 32-2:
-labelanchor wn
-labelanchor s
-labelanchor ne
You also have the option of creating a separate label widget, configuring it in any way that you like, and then associating it with a labelframe through the labelWidget attribute. The labelWidget attribute overrides any text value already set for the labelframe. Example 32-3 shows a label with a bitmap as the frame decoration:
frame .embed -container 1 -bd 4 -bg red exec wish somescript.tcl -use [winfo id .embed] &
The possible values for style include documentProc, dBoxProc, plainDBox, altDBoxProc, movableDBoxProc, zoomDocProc, rDocProc, floatProc, floatZoomProc, floatSideProc, or floatSideZoomProc. The dBoxProc, plainDBox, and altDBoxProc styles have no title bar, so there is no close box on them. The other styles have different title bars, a close box, and possibly a full-sized zoom box. The default style is documentProc. I used the following code to see what each looked like:
toplevel .$y label .$y.l -text $y pack .$y.l -padx 40 -pady 20 if [catch {unsupported1 style .$y $y} err] { puts "$y: $err" } }
[ Team LiB ]
The text can be specified indirectly by using a Tcl variable to hold the text. In this case the label is updated whenever the value of the Tcl variable changes. The variable is used from the global scope, even if there happens to be a local variable by the same name when you create the widget inside a procedure:
You can change the appearance of a label dynamically by using the configure widget operation. If you change the text or font of a label, you are liable to change the size of the widget, and this causes the packer to shuffle window positions. You can avoid this by specifying a width for the label that is large enough to hold all the strings you plan to display in it. The width is specified in characters, not screen coordinates:
The FixedWidthLabel example is used to create a label with a width big enough to hold a set of different strings. It uses the -anchor w attribute to left-justify strings that are shorter than the maximum. You can change the text for the label later by using the configure widget operation, which can be abbreviated to config:
A label can display a bitmap or image instead of a text string, which is described in Chapter 41 and the section on Bitmaps and Images. This example could use the font TO PDF CONVERTER to THETA-SOFTWARE UNREGISTERED VERSION OF CHM metrics facilities of Tk 8.0 Byget more accurate sizes of the
text for different strings. It is possible, for example, that a three-character string like OOO is wider than a four-character string like llll in a variable-width font. The font metrics command is described on page 640.
UNREGISTERED VERSION OF CHMLength CONVERTER By THETA-SOFTWARE Label Width and Wrap TO PDF
When a label is displaying text, its width attribute is interpreted as a number of characters. The label is made wide enough to hold this number of averaged width characters in the label's font. However, if the label is holding a bitmap or an image, then the width is in pixels or another screen unit. The wrapLength attribute determines when a label's text is wrapped onto multiple lines. The wrap length is always screen units. If you need to compute a wrapLength based on the font metrics, then you can use the font metrics command. If you use Tk 4.2 or earlier, then you have to measure text using a text widget with the same font. Chapter 36 describes the text widget operations that return size information for characters. You can force line breaks by including newlines (\n) in the label's text. This lets you create labels that have multiple lines of text.
Label Attributes
Table 32-2 lists the widget attributes for the label widget. The attributes are named according to their resource name, which includes a capital letter at internal word boundaries. When you specify an attribute as an option in a Tcl command when creating or reconfiguring a widget, however, you specify the attribute with a dash and all lowercase letters. Chapter 31 explains how to use resource specifications for attributes. Chapters 40, 41, and 42 discuss many of these attributes in more detail.
activeBackground activeForeground anchor background bitmap borderWidth compound cursor disabledForeground font foreground height
Background color when the label is in the active state. (Tk 8.3.2) Text color when the label is in the active state. (Tk 8.3.2) Relative position of the label within its packing space. Background color (also bg). Name of a bitmap to display instead of a text string. Extra space around the edge of the label. Where the image or bitmap should be placed relative to the text: bottom, center, left, none (default), right and top. (Tk 8.4) Cursor to display when mouse is over the label. Foreground (text) color when the label is disabled. (Tk 8.3.1) Font for the label's text. Foreground color (also fg). In screen units for bitmaps, in lines for text.
highlightBackground Focus highlight color when widget does not have focus. highlightColor highlightThickness image justify padX padY relief state takeFocus text textVariable underline width wrapLength [ Team LiB ] Focus highlight color when widget has focus. Thickness of focus highlight rectangle. Specifies image to display instead of bitmap or text. Text justification: left, right, or center. Extra space to the left and right of the label. Extra space above and below the label. flat, sunken, raised, groove, solid or ridge. normal (enabled), disabled (deactivated), or active. (Tk 8.3.1) Controls focus changes from keyboard traversal. Text to display. Name of Tcl variable. Its value is displayed. Index of character to underline. Width. In characters for text labels. Length at which text is wrapped in screen units.
[ Team LiB ]
Example 32-6 creates a message widget with one long line of THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER By text. Backslashes are used to
continue the text string without embedding any newlines. (You can also just type a long line into your script.) Note that backslash-newline collapses white space after the newline into a single space.
message .msg -justify center -text "This is a very long text\ line that will be broken into many lines by the\ message widget" pack .msg
A newline in the string forces a line break in the message display. You can retain exact control over the formatting by putting newlines into your string and specifying a very large aspect ratio. In Example 32-7, grouping with double quotes is used to continue the string over more than one line. The newline character between the quotes is included in the string, and it causes a line break:
message .msg -aspect 1000 -justify left -text \ "This is the first long line of text,
One disadvantage of a message widget is that, by default, you cannot select the text it displays. Chapter 38 describes how to define custom selection handlers, so you could define one that returned the message string. The message widget predates the text widget, which has many more features and can emulate the message widget. If selections, multiple fonts, and other formatting are important, use a text widget instead of a message widget. Text widgets are described in Chapter 36.
Message Attributes
Table 32-3 lists the attributes for the message widget. The table lists the resource name, which has capitals at internal word boundaries. In Tcl commands these options are specified with a dash and all lowercase:
highlightBackground Focus highlight color when widget does not have focus. highlightColor highlightThickness justify padX padY relief takeFocus text textVariable width Focus highlight color when widget has focus. Thickness of focus highlight rectangle. Justification: left, center, or right. Extra space to the left and right of the text. Extra space above and below the text. flat, sunken, raised, groove, solid or ridge. Controls focus changes from keyboard traversal. Text to display. Name of Tcl variable. Its value is displayed. Width, in screen units.
Both the label and message widgets have attributes that control the position of their text in much the same way that the packer controls the position of widgets within a frame. These attributes are padX, padY, anchor, and borderWidth. The anchor takes effect when the size of the widget is larger than the space needed to display its text. This happens when you specify the -width attribute or if you pack the widget with fill enabled and there is extra room. See Chapter 40 and the section on Padding and Anchors for more details. [ Team LiB ] UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
[ Team LiB ]
scale .scale -from -10 -to 20 -length 200 -variable x \ -orient horizontal -label "The value of X" \ -tickinterval 5 -showvalue true pack .scale
Example 32-8 shows a scale for a variable that ranges in value from -10 to +20. The variable x is defined at the global scope. The tickinterval option results in the labels across the bottom, and the showvalue option causes the current value to be displayed. The length of the scale is in screen units (i.e., pixels).
Scale Bindings
Table 32-4 lists the bindings for scale widgets. You must direct focus to a scale explicitly for the key bindings like <Up> and <Down> to take effect.
Clicking on the trough moves the slider by one unit of resolution toward the mouse click. Clicking on the trough moves the slider all the way to the end of the trough toward the mouse click. Moves the slider toward the left (top) by one unit. attribute.
<Control-Left> Moves the TO toward the left (top) by THETA-SOFTWARE UNREGISTERED VERSION OF CHMsliderPDF CONVERTER By the value of the bigIncrement <Control-Up> <Right> <Down> Moves the slider toward the right (bottom) one unit.
<Control-Right> Moves the slider toward the right (bottom) by the value of the bigIncrement PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TOattribute. <Control-Down> <Home> <End> Moves the slider all the way to the left (top). Moves the slider all the way to the right (bottom).
Scale Attributes
Table 32-5 lists the scale widget attributes. The table uses the resource name, which has capitals at internal word boundaries. In Tcl commands the attributes are specified with a dash and all lowercase.
highlightBackground Focus highlight color when widget does not have focus. highlightColor highlightThickness label Focus highlight color when widget has focus. Thickness of focus highlight rectangle. A string to display with the scale.
length orient relief repeatDelay repeatInterval resolution showValue sliderLength sliderRelief state takeFocus tickInterval to troughColor variable
The length, in screen units, of the long axis of the scale. horizontal or vertical. flat, sunken, raised, groove, solid or ridge. Delay before keyboard auto-repeat starts. Auto-repeat is used when pressing <Button-1> on the trough. Time period between auto-repeat events. The value is rounded to a multiple of this value. If true, value is displayed next to the slider. The length, in screen units, of the slider. The relief of the slider. normal, active, or disabled. Controls focus changes from keyboard traversal. Spacing between tick marks. Zero means no marks. Maximum value. Right or bottom end of the scale. The color of the bar on which the slider sits. Name of Tcl variable. Changes to the scale widget are reflected in the Tcl variable value, and changes in the Tcl variable are reflected in the scale display. Width of the trough, or slider bar.
width
Programming Scales
The scale operations are primarily used by the default bindings and you do not need to program the scale directly. Table 32-6 lists the operations supported by the scale. In the table, $w is a scale widget.
[ Team LiB ]
[ Team LiB ]
UNIX has an xset program that controls the bell's duration, pitch, and volume. The volume is in percent of a maximum, for example, 50. In practice, many keyboard bells only support a variable duration; the pitch and volume are fixed. The arguments of xset that control the bell are shown below.
The b argument by itself resets the bell to the default parameters. You can turn the bell off with -b, or you can use the on or off arguments.
The bell command has the side effect on most systems of resetting the screen saver for the screen, which usually makes the screen visible again. In Tk 8.4, a -nice option was added to prevent the bell command from resetting the screen saver. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Using Scrollbars
The following commands create a text widget and two scrollbars that scroll it horizontally and vertically:
scrollbar .yscroll -command {.text yview} -orient vertical scrollbar .xscroll -command {.text xview} -orient horizontal text .text -yscrollcommand {.yscroll set} \ -xscrollcommand {.xscroll set}
The scrollbar's set operation is designed to be called from other widgets when their display changes. The scrollable widget's xview and yview operations are designed to be called by the scrollbar when the user manipulates them. Additional parameters are passed to these operations as described later. In most cases you can ignore the details of the protocol and just set up the connection between the scrollbar and the widget.
proc Scrolled_Text { f args } { frame $f eval {text $f.text -wrap none \ -xscrollcommand [list $f.xscroll set] \ -yscrollcommand [list $f.yscroll set]} $args scrollbar $f.xscroll -orient horizontal \ -command [list $f.text xview] scrollbar $f.yscroll -orient vertical \ -command [list $f.text yview] grid $f.text $f.yscroll -sticky news grid $f.xscroll -sticky news grid rowconfigure $f 0 -weight 1 grid columnconfigure $f 0 -weight 1 return $f.text } set t [Scrolled_Text .f -width 40 -height 8 \ -font {courier 12}] pack .f -side top -fill both -expand true set in [open [file join $tk_library demos colors.tcl]]
Example 33-1 defines Scrolled_Text that creates a text widget with two scrollbars. It reads and inserts one of the Tk demo files into the text widget. There is not enough room to display all the text, and the scrollbars indicate how much text is visible. Chapter 36 describes the text widget in more detail.
The list command constructs the -command and -xscrollcommand values. Even though one could use double quotes here, you should make a habit of using list when constructing values that are used later as Tcl commands. Example 33-1 uses args to pass through extra options to the text widget. The use of eval and args is explained in Example 10-3 on page 136. The scrollbars and the text widget are lined up with the grid geometry manager as explained in UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 26-10 on page 417. [ Team LiB ]
[ Team LiB ]
If the two values are 0.0 and 1.0, it means that the widget's contents are fully visible, and a scrollbar is not necessary. You can monitor the protocol by using a Tcl wrapper, Scroll_Set, instead of the set operation directly. Scroll_Set waits for the scrollbar to be necessary before mapping it with a geometry manager command. It is not safe to unmap the scrollbar because that can change the size of the widget and create the need for a scrollbar. That leads to an infinite loop.
Scroll_Set takes a geometry management command as an argument, which it uses to make the scrollbar visible. Example 33-3 uses Scroll_Set with a listbox. Note that it does not grid the scrollbars directly. Instead, it lets Scroll_Set do the geometry command the first time it is necessary.
Scrolled_Listbox takes optional parameters for the listbox. It uses eval to configure the listbox with these arguments. The style of using eval shown here is explained in Example 10-3 on page 136. Example 46-4 on page 686 associates two listboxes with one scrollbar.
When the user clicks on the arrows at either end of the scrollbar, the scrollbar adds scroll num units to its command, where num is positive to scroll down, and negative to scroll up. Scrolling up one line is indicated with this command:
When the user clicks above or below the elevator of the scrollbar, the scrollbar adds scroll num pages to its command. Scrolling down one page is indicated with this command:
You can position a widget so that the top (or left) edge is at a particular offset from the beginning of the widget's contents. The offset is expressed as a floating point value between zero and one. To view the beginning of the contents:
If the offset is 1.0, the last part of the widget content's is displayed. The Tk widgets always keep the end of the widget contents at the bottom (or right) edge of the widget, unless the widget is larger than necessary to display all the contents. You can exploit this with the one-line entry widget to view the end of long strings:
[ Team LiB ]
[ Team LiB ]
The scrollbar is made up of five components: arrow1, trough1, slider, trough2, and arrow2. The arrows are on either end, with arrow1 being the arrow to the left for horizontal scrollbars, UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE or the arrow on top for vertical scrollbars. The slider represents the relative position of the information displayed in the associated widget, and the size of the slider represents the relative amount of the information displayed. The two trough regions are the areas between the slider and the arrows. If the slider covers all of the trough area, you can see all the information in the associated widget.
Scrollbar Bindings
Table 33-1 lists the default bindings for scrollbars on UNIX. Button 1 and button 2 of the mouse have the same bindings. You must direct focus to a scrollbar explicitly for the key bindings like <Up> and <Down> to take effect.
Scrollbar Attributes
Table 33-2 lists the scrollbar attributes. The table uses the resource name for the attribute, which has capitals at internal word boundaries. In Tcl commands, the attributes are specified with a dash and all lowercase. There is no length attribute for a scrollbar. Instead, a scrollbar is designed to be packed next to another widget with a fill option that lets the scrollbar display grow to the right size. Only the relief of the active element can be set. The background color is used for the slider, the arrows, and the border. The slider and arrows are displayed in the activeBackground color when the mouse is over them. The trough is always displayed in the troughColor.
highlightBackground Focus highlight color when widget does not have focus. highlightColor highlightThickness elementBorderWidth jump orient repeatDelay repeatInterval troughColor width Focus highlight color when widget has focus. Thickness of focus highlight rectangle. Width of 3D border on arrows and slider. If true, dragging the elevator does not scroll dynamically. Instead, the display jumps to the new position. Orientation: horizontal or vertical. Milliseconds before auto-repeat starts. Auto-repeat is used when pressing <Button-1> on the trough or arrows. Milliseconds between auto-repeat events. The color of the bar on which the slider sits. Width of the narrow dimension of the scrollbar.
Programming Scrollbars
The scrollbar operations are primarily used by the default bindings. Table 33-3 lists the operations supported by the scrollbar. In the table, $w is a scrollbar widget.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE $w configure Queries or modifies the widget configuration.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
One common use of an entry widget is to UNREGISTERED VERSION OF CHM TO PDF associate a label By THETA-SOFTWARE up several CONVERTER with it, and a command to execute when <Return> is pressed in the entry. The grid geometry manager is ideal for lining entries and their labels. This is implemented in the following example:
foreach {field label} {name Name address1 Address address2 {} phone Phone} { label .l$field -text $label -anchor w entry .e$field -textvariable address($field) -relief sunken grid .l$field .e$field -sticky news bind .e$field <Return> UpdateAddress }
Example 34-1 creates four entries that are linked to variables with the textvariable attribute. The variables are elements of the address array. The -relief sunken for the entry widget sets them apart visually. Widget relief is described in more detail on page 614. The Tcl command UpdateAddress is bound to the <Return> keystroke. The UpdateAddress procedure, which is not shown, can get the current values of the entry widgets through the global array address.
For validation to take effect, you must also provide a value for the validateCommand (or vcmd) attribute. This is a Tcl script to execute whenever validation takes place. If the script returns a Boolean True, the proposed change to the widget is accepted; if the script returns a Boolean False, the proposed change is rejected and the widget's text remains the same. Optionally, you can also assign a Tcl script to the invalidCommand attribute. This script executes if the validation script returns False. The validateCommand validation script can contain "percent substitutions," just like in an event binding. These substitutions occur before executing the script, whenever validation is triggered. Table 34-1 lists the validation substitutions:
proc ValidInt {val} { return [ expr {[string is integer $val] || [string match {[-+]} $val]} ] } entry .e -validate all -vcmd {ValidInt %P} pack .e
If an uncaught error occurs during the validation callback, then the validate attribute is set to none, preventing further validation from taking place. Additionally, if the return value of the validation callback is anything other than a Boolean value, validation is also disabled. Therefore, you should take care not to raise errors or return non-Boolean values from your validation callback.
Using textvariables for read-only purposes never causes a problem. However, you can run into trouble if you try to change the value of an entry using its textvariable. If you set the textvariable to a value that wouldn't be accepted by the validation script (that is, it would return False), then Tk allows the change to occur, but disables further validation by setting validate to none. So in general, you should use textvariables only to read an entry's value if you also have validation enabled.
The other caveat to validation is that if you change the value of the widget while evaluating either the validation script or the invalidCommand script, validate is set to none, disabling further validations. The intent is to prevent the change from triggering yet another validation check, which could attempt to change the widget and trigger another validation, and so on in an endless cycle. For most validation applications, this is not a major restriction. In most cases, you simply want to prevent an invalid change from taking place, which you accomplish simply by returning Boolean False from your validation script. But some sophisticated validation schemes might require edits to the widget's text. If you need to change the value of the entry from either the validateCommand or invalidCommand script, the script should also schedule an idle task to reset the validate attribute back to its previous value. Example demonstrates this with a validation command that ensures all letters inserted into an entry are upper case, by converting all characters to upper case as they are inserted. As this example modifies the value of the widget directly, it must reestablish validation in an idle task.
if {$action == 1} { $w insert insert [string toupper $new] after idle [list $w configure -validate $validation] } return 1 } entry .e -validate all -vcmd {Upper %W %v %d %S} pack .e
The show attribute is useful for entries that accept passwords or other sensitive information. If show is not empty, it is used as the character to display instead of the real value:
The state attribute determines if the contents of an entry can be modified. Set the state to disabled to prevent modification and set it to normal to allow modification.
$entry config -state disabled ;# read-only $entry config -state normal ;# editable
Tcl 8.4 added a new state, readonly, in which the contents of the widget can't be edited, just like disabled. However, the readonly state allows the user to select and copy the widget contents. If the widget is a spinbox, the user can also use the up and down spinbuttons to change the value displayed while the widget is in readonly state (but not if it is in the disabled state). The middle mouse button (<Button-2>) is overloaded with two functions. If you click and release the middle button, the selection is inserted at the insert cursor. The location of the middle click does not matter. If you press and hold the middle button, you can scroll the contents of the entry by dragging the mouse to the left or right. [ Team LiB ]
[ Team LiB ]
In addition to the text entry field, a spin box has up and down arrow buttons, allowing the user to "spin" through a fixed set of values such as dates or times. A spinbox normally allows a user to type any arbitrary UNREGISTERED VERSIONtext into the text area, but you can also configure a spinbox so that users OF CHM TO PDF CONVERTER By THETA-SOFTWARE can only spin through the valid choices. There are two ways to set the range of values for a spinbox. The first is to set numerical minimum, maximum, and increment values with the from, to, and increment attributes, respectively. Each time the user clicks the up or down arrow, the spinbox adjusts the displayed value by the increment. For example, the spinbox in Example 34-4 has a range of -10 to 10, and uses the default increment of 1.
Particularly if you start using floating-point values and increments, you might need to specify the format for displaying the value. You do so by setting a value for the format attribute in the form %<pad>.<pad>f, as used with the format command. (Note that no other format-like conversion specifiers are supported by the spinbox.) Example 34-5 demonstrates using the format attribute.
spinbox .s2 -from -10 -to 10 -increment .25 -format %4.2f pack .s2
Another option for specifying values for a spinbox is to enumerate them. Simply provide the spinbox's values attribute a list of values. If you set a spinbox's values attribute, it ignores its from, to, and increment attributes. Additionally, if you set the wrap attribute of a spinbox to True, then the spinbox wraps around from the last value to the first (or vice versa) while spinning through the values. With the
default wrap setting of False, the spinbox stops spinning values once it reaches the beginning or end. You can use the wrap feature with either enumerated values (values) or value ranges (from and to). Example 34-6 demonstrates both using enumerated values and wrapping in a spinbox.
set states [list Arizona California Nevada "New Mexico"] spinbox .s3 -values $states -wrap 1 pack .s3
In all of the spinbox examples shown so far, the user is free to type any arbitrary text into the entry portion, rather than selecting one of the spinbox values. In some applications this is acceptable, and you could use standard validation features to ensure reasonable values. (See "Validating Entry Contents" on page 508.) However, sometimes you want to allow a user to select only one of the preset spinbox values. The easiest way to accomplish this is to set the spinbox state attribute to readonly. Unlike the disabled state, which makes the widget insensitive to user actions and prevents programmatic changes to the widget's contents, the readonly state allows a user to spin through the values. You can also programmatically change the contents of the spinbox with the set operation, and even change the values while the spinbox is in the readonly state. Example 34-7 shows an example of using the readonly state for several spinboxes, allowing the user to select a date. The spinboxes are linked by textvariables to elements in a global array, so that after the user selects the date, you can easily retrieve the values from the array.
set months {Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec} spinbox .month -values $months -textvariable date(month) \ -state readonly -width 8 spinbox .date -from 1 -to 31 -textvariable date(date) \ -state readonly -width 8 spinbox .year -from 2003 -to 2010 -textvariable date(year) \ -state readonly -width 8 label .l_month -text "Month:" label .l_date -text "Date:" label .l_year -text "Year:" grid .l_month .month
.l_date .date .l_year .year .l_month .l_date .l_year -padx 2 -sticky e .month .date .year -sticky ew
[ Team LiB ]
[ Team LiB ]
<Control-Left> <Meta-b> Moves cursor left one word and starts the selection. <Control-Shift-Left> <Right> <Control-f> <Shift-Right> <Control-Right> <Metaf> <Control-Shift-Right> <Home> <Control-a> <Shift-Home> <End> <Control-e> <Shift-End> <Select> <ControlSpace> Moves cursor left one word and extends the selection. Moves right one character and starts the selection. Moves cursor right and extends the selection. Moves right one word and starts the selection. Moves cursor right one word and extends the selection. Moves cursor to beginning of widget. Moves cursor to beginning and extends the selection. Moves cursor to end of widget. Moves cursor to end and extends the selection. Anchors the selection at the insert cursor.
Selects all the text in the entry. Clears the selection in the entry.
<Delete> Deletes the CONVERTER By next character. UNREGISTERED VERSION OF CHM TO PDF selection or deletes THETA-SOFTWARE <Backspace> <Control-h> Deletes the selection or deletes previous character. <Control-d> <Meta-d> Deletes next character. Deletes next word.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE <Control-k> Deletes to the end of the entry.
<Control-t> <<Cut>> <Control-x> <<Copy>> <Control-c> <<Paste>> <Control-v> Transposes characters. Deletes the section, if it exists. Copies the selection to the clipboard. Inserts the clipboard contents at the position of the insertion cursor.
[ Team LiB ]
[ Team LiB ]
from
highlightBackground Focus highlight color when widget does not have focus. highlightColor highlightThickness increment Focus highlight color when widget has focus. Thickness of focus highlight rectangle. Floating-point value specifying the increment. When used with -from and -to, the value in the widget will be adjusted by -increment when a spin button is pressed. Spinbox only. (Tk 8.4) Background for area covered by insert cursor. Width of cursor border. Non-zero for 3D effect. Time, in milliseconds the insert cursor blinks off. Time, in milliseconds the insert cursor blinks on.
Width of insert cursor. Default is 2. Tcl script to execute when the -validatecommand script returns 0. Text justification: left, right, center. Background color when the widget is read-only. (Tk 8.4) flat, sunken, raised, groove, solid or ridge.
takeFocus textVariable to
validate validateCommand
[ Team LiB ]
sel.first The first character in the selection. sel.last @xcoord The character just after the last character in the selection. The character under the specified X coordinate.
Table 34-5 summarizes the operations on entry and spinbox widgets. In the table, $w is an entry or spinbox widget.
Returns the numerical index corresponding to index. Inserts the string at the given index. Invokes the spinbox element, either buttondown or buttonup, triggering the action associated with it. Spinbox only. (Tk 8.4)
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE $w scan mark x Starts a scroll operation. x is a screen coordinate.
$w scan dragto x $w selection adjust index Scrolls from previous mark position. Moves the boundary of an existing selection.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE $w selection clear Clears the selection.
$w selection element ?element? $w selection from index $w selection present Sets or gets the currently selected spinbox element. Spinbox only. (Tk 8.4) Sets the anchor position for the selection. Returns 1 if there is a selection in the entry.
$w selection range Selects the characters from start to the one just before end. start end $w select to index Extends the selection. $w set ?value? $w validate $w xview Gets or sets the value of the spinbox, triggering validation if it is on. Spinbox only. (Tk 8.4) Force an evaluation of the -validatecommand script, returning 0 or 1. (Tk 8.3) Returns the offset and span of visible contents. These are both real numbers between 0 and 1.0. Shifts the display so the character at index is at the left edge of the display. Shifts the display so that fraction of the contents are off the left edge of the display. Scrolls the contents by the specified number of what, which can be units or pages.
For example, the binding for <Button-1> includes the following commands:
%W icursor @%x %W select from @%x if {[%W cget -state] == "normal"} {focus %W}
Recall that the % triggers substitutions in binding commands, and that %W is replaced with the widget pathname and %x is replaced with the X coordinate of the mouse event. Chapter 29 describes bindings and these substitutions in detail. These commands set the insert point to the point of the mouse click by using the @%x index, which will be turned into something like @17
when the binding is invoked. The binding also starts a selection. If the entry is not in the disabled state, then keyboard focus is given to the entry so that it gets KeyPress events. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Using Listboxes
Manipulating Listbox Contents
The lines in a listbox are indexed from zero. The keyword index end addresses the last line. Other indices are described on page 520. The most common programming task for a listbox is to insert text. If your data is in a list, you can loop through the list and insert each element at the end:
You can insert several items at once. The next command uses eval to concatenate the list onto a single insert command:
The delete operation deletes items from a listbox. You can delete either a single item or a range of items:
The listbox widget gained a listvariable option in Tk 8.3, which works analogously to textvariable attributes in other widgets. You give listvariable the name of a variable that contains a list value. Tk then keeps the value of the variable and the listbox contents synchronized, so that each element in the variable's value is a line in the listbox. Example 35-1 shows a simple example of modifying a listbox through its linked listvariable.
listbox .choices -height 5 -width 20 -listvariable states pack .choices lappend states Arizona
Programming Listboxes
UNREGISTERED VERSION selecting items. The CONVERTER By finds the listbox entry that is most of the details of OF CHM TO PDF nearest operation THETA-SOFTWARE
It is also common to react to mouse clicks on a listbox, although the default bindings handle closest to a mouse event. If the mouse is clicked beyond the last element, the index of the last element is returned:
proc List_Select { parent values } { # Create two lists side by side frame $parent set choices [Scrolled_Listbox $parent.choices \ -width 20 -height 5 ] set picked [Scrolled_Listbox $parent.picked \ -width 20 -height 5] pack $parent.choices $parent.picked -side left \ -expand true -fill both # Selecting in choices moves items into picked bind $choices <ButtonRelease-1> \ [list ListTransferSel %W $picked] # Selecting in picked deletes items bind $picked <ButtonRelease-1> \ {ListDeleteSel %W %y} # Insert all the choices foreach x $values { $choices insert end $x } }
proc ListTransferSel {src dst} { foreach i [$src curselection] { $dst insert end [$src get $i] } } proc ListDeleteSel {w y} { foreach i [lsort -integer -decreasing [$w curselection]] { $w delete $i } } proc List_SelectValues {parent} { set picked $parent.picked.list set result {} foreach i [$w curselection] { lappend result [$w get $i] } } List_Select .f {apples oranges bananas \ grapes mangos peaches pears} pack .f -expand true -fill both
Bindings are created to move items from $choices to $picked, and to delete items from $picked. Most of the work of selecting things in the listbox is done by the built-in bindings on the Listbox binding tag. The different selection models are described on page 525. Those bindings are on <ButtonPress-1> and <B1-Motion>. The selection is complete by the time the <ButtonRelease-1> event occurs. Consider the <ButtonRelease-1> binding for $choices:
The list command is used to construct the Tcl command because we need to expand the value of $picked at the time the binding is created. The command will be evaluated later at the global scope, and picked will not be defined after the List_Select procedure returns. Or, worse yet, an existing global variable named picked will be used, which is unlikely to be correct! Short procedures are used to implement the binding commands. This style has two advantages. First, it confines the % substitutions done by bind to a single command. Second, if there are any temporary variables, such as the loop counter i, they are hidden within the scope of the procedure. The ListTransferSel gets the list of all the selected items and loops over this list to insert them into the other list. The ListDeleteSel procedure is similar. However, it sorts the selection indices in reverse order. It deletes items from the bottom up so the indices remain valid throughout the process. [ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Table 35-1. Listbox indices
0 Index of the first line.
active The index of the activated line. anchor The index of the anchor point of the selection. end Index of the last line.
number Index a line, counting from zero. @x,y The line closest to the specified X and Y coordinates.
Table 35-2 presents the operations for programming a listbox. In the table, $w is a listbox widget. Most of the operations have to do with the selection, and these operations are already programmed by the default bindings for the Listbox widget class:
$w get first ?last? $w index index $w insert index ?string string string ...? $w itemcget index option
Queries or modifies the item's configuration options. (Tk 8.3) Returns the index of the line closest to the widget-relative Y coordinate. Starts a scroll operation. x and y are widget-relative screen coordinates. Scrolls from previous mark position. Adjusts the display so the line at index is visible. Anchors the selection at the specified line. Clears the selection. Returns 1 if the line at index is in the selection. Selects the lines from start to end. Returns the number of items in the listbox. Returns the offset and span of visible contents. These are both real numbers between 0 and 1. Shifts the display so the character at index is at the left edge of the display. Shifts the display so that fraction of the contents are off the left edge of the display. Scrolls the contents horizontally by the specified number of what, which can be units or pages. Returns the offset and span of visible contents. These are both real numbers between 0 and 1. Shifts the display so the line at index is at the top edge of the display. Shifts the display so that fraction of the contents are off the top of the display. Scrolls the contents vertically by the specified number of what, which can be units or pages.
$w scan dragto x y $w see index $w selection anchor index $w selection clear start ? end? $w selection includes index $w selection set start ? end? $w size $w xview
$w xview index
$w yview index
As of Tk 8.3, the itemcget and itemconfigure operations allow you to control the appearance of individual items in the listbox, overriding the listbox's defaults. Table 35-3 lists the configuration options supported for individual items. Note that there is no direct support for setting these values through the option resource database; you can set them only through the listbox's itemconfigure operation.
Background color for the item. Foreground color for the item. Background color for the item when it's selected. Foreground color for the item when it's selected.
[ Team LiB ]
multiple More than one element can be selected by toggling the selection state of items, but you only select or deselect one line at a time. extended More than one element can be selected by dragging out a selection with the shift or control keys.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Table 35-6. Bindings for single selection mode
<ButtonPress-1> <ButtonRelease-1> <Shift-Button-1> <Key-Up> <Key-Down> <Control-Home> <Control-End> <space> <Select> <Controlslash> <Control-backslash> Selects the item under the mouse. Activates the item under the mouse.
<Button-1> <B1-Motion> <ButtonRelease-1> <Shift-Button-1> <Shift-B1-Motion> <Control-Button-1> <Control-B1Motion> <Key-Up> <KeyDown> <Shift-Up> <ShiftDown> <Control-Home> <Control-ShiftHome> <Control-End> <Control-ShiftEnd> <space> <Select> <Escape> <Control-slash> <Controlbackslash>
Selects the item under the mouse. This becomes the anchor point for adjusting the selection. Sweeps out a selection from the anchor point. Activates the item under the mouse. Adjusts the selection from the anchor item to the item under the mouse. Continues to adjust the selection from the anchor. Toggles the selection state of the item under the mouse, and makes this the anchor point. Sets the selection state of the items from the anchor point to the item under the mouse to be the same as the selection state of the anchor point. Moves the active item up (down) one line, and starts a new selection with this item as the anchor point. Moves the active element up (down) and extends the selection to include this element. Activates and selects the first element of the listbox. Extends the selection to the first element. Activates and selects the last element of the listbox. Extends the selection to the last element. Selects the active element. Cancels the previous selection action. Selects everything in the listbox. Clears the selection.
Selects the item under the mouse. Activates the item under the mouse. Moves the active item up (down) one line, and starts a new selection with this item as the anchor point. Moves the active element up (down). Activates and selects the first element of the listbox.
<Control-Shift-Home> Activates the first element of the listbox. <Control-End> Activates and selects the last element of the listbox.
UNREGISTERED VERSION OF CHM TO the last element of theBy THETA-SOFTWARE <Control-Shift-End> Activates PDF CONVERTER listbox.
<space> <Select> <Control-slash> <Control-backslash> Selects the active element. Selects everything in the listbox. Clears the selection.
Scroll Bindings
There are several bindings that scroll the display of the listbox. In addition to the standard middle-drag scrolling, there are some additional key bindings for scrolling. Table 35-9 summarizes the scroll-related bindings:
<Control-Left> <Control-Right> Scrolls horizontally by one screen width. <Control-Prior> <Control-Next> <Prior> <Next> <Home> <End> Scrolls vertically by one screen height. Scrolls to left and right edges of the screen, respectively.
can access the new selection. The easiest way to be aware of changes to the listbox selection is to bind to this virtual event, as shown in Example 35-3:
[ Team LiB ]
[ Team LiB ]
Listbox Attributes
Table 35-10 lists the OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSIONlistbox widget attributes. The table uses the resource name for the attribute, which has capitals at internal word boundaries. In Tcl commands these options are specified with a dash and all lowercase.
Table 35-10. Listbox attribute By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER resource names
activeStyle background borderWidth cursor disabledForeground exportSelection font foreground height Display style of the active element: dotbox, underline (default), or none. (Tk 8.4) Background color (also bg). Extra space around the edge of the text. Cursor to display when mouse is over the widget. Foreground color when the widget is disabled. (Tk 8.4) If true, then the selected text is exported via the X selection mechanism. Font for the text. Foreground color (also fg). Number of lines in the listbox.
highlightBackground Focus highlight color when widget does not have focus. highlightColor highlightThickness listVariable Focus highlight color when widget has focus. Thickness of focus highlight rectangle. Name of Tcl variable containing a list whose value is synchronized with the widget, where each list element is a line of the listbox. (Tk 8.3) flat, sunken, raised, groove, solid, or ridge. Background color of selection. Foreground color of selection. Width of selection border. Nonzero for 3D effect. Mode: browse, single, extended, or multiple. Boolean. Set gridding attribute. Widget state: normal or disabled. (Tk 8.4) Controls focus changes from keyboard traversal. Width, in average character sizes.
xScrollCommand yScrollCommand
Geometry Gridding
The setGrid attribute affects interactive resizing of the window containing the listbox. By default, a window can be resized to any size. If gridding is turned on, the size is restricted so that a whole number of lines and a whole number of average-width characters is displayed. Gridding affects the user feedback during an interactive resize. Without gridding the size is reported in pixel dimensions. When gridding is turned on, then the size is reported in gridded units. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Text Indices
The characters in a text widget are addressed by their line number and the character position within the line. Lines are numbered starting at one, while characters are numbered starting at zero. The numbering for lines was chosen to be compatible with other programs that number lines starting at one, like compilers that generate line-oriented error messages. Here are some examples of text indices: 1.0 1.1 The first character. The second character on the first line.
2.end The newline character on the second line. There are also symbolic indices. The insert index is the position at which new characters are normally inserted when the user types in characters. You can define new indices called marks, too, as described later. Table 36-1 summarizes the various forms for a text index.
tag.first The first character in the range tagged with tag. tag.last window Just after the last character tagged with tag. The position of the embedded window.
The index can be any of the forms listed in the table, or it can be an index expression as described in a moment. The tags, if any, are added to the newly inserted text. Otherwise,
string picks up any tags present on both sides of index. Tags are described on page 536. Multiple strings with different tags can be inserted with one command. The most common index at which to insert text is the insert index, which is where the insert cursor is displayed. The default bindings insert text at insert when you type. You must include a newline character explicitly to force a line break:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE $t insert insert "Hello, World\n"
The delete operation deletes text. If only one index is given, the character at that position is deleted. If there are two indices, all the characters up to the second index are deleted. The character at the second index is not deleted. For example, you can delete the first line with this UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE command:
As of Tk 8.4, you can delete multiple ranges of text with a single delete operation. For example, to delete the first, fourth, and eighth lines:
Index Arithmetic
The text widget supports a simple sort of arithmetic on indices. You can specify "the end of the line with this index" and "three characters before this index," and so on. This is done by grouping a modifying expression with the index. For example, the insert index can be modified like this:
The interpretation of indices and their modifiers is designed to operate well with the delete and tag add operations of the text widget. These operations apply to a range of text defined by two indices. The second index refers to the character just after the end of the range. For example, the following command deletes the word containing the insert cursor:
If you want to delete a whole line, including the trailing newline, you need to use a "lineend +1 char" modifier. Otherwise, the newline remains and you are left with a blank line. If you supply several modifiers to an index, they are applied in left to right order:
Comparing Indices
The compare operation compares two text indices and index expressions. You must use compare for reliable comparisons because, for example, index 1.3 is less than index 1.13. If you try to compare indices as numbers, you get the wrong answer. The general form of the compare operation is:
The comparison operator can be one of <, <=, ==, >=, >, or !=. The indices can be simple indices in the forms listed in Table 36-1, and they can be index expressions. Example 36-6 on page 548 uses the compare operation. [ Team LiB ]
[ Team LiB ]
Text Marks
A mark is VERSION OF CHM position CONVERTER By THETA-SOFTWARE UNREGISTERED a symbolic name for a TO PDFbetween two characters. Marks have the property that when text is inserted or deleted they retain their logical position, not their numerical index position. Marks are persistent: If you delete the text surrounding a mark, it remains intact. Marks are created with the mark set operation and must be explicitly deleted with the mark unset operation. Once defined, a mark can be used in operations that require indices. The following commands define a mark at the beginning of the word containing the insert cursor and delete from there up CHM TO PDF line: UNREGISTERED VERSION OFto the end of theCONVERTER By THETA-SOFTWARE $t mark set foobar "insert wordstart" $t delete foobar "foobar lineend" $t mark unset foobar
When a mark is defined, it is set to be just before the character specified by the index expression. In the previous example, this is just before the first character of the word where the insert cursor is. When a mark is used in an operation that requires an index, it refers to the character just after the mark. So, in many ways the mark seems associated with the character right after it, except that the mark remains even if that character is deleted. You can use almost any string for the name of a mark. However, do not use pure numbers and do not include spaces, plus (+) or minus (-). These characters are used in index arithmetic and may cause problems if you put them into mark names. The mark names operation returns a list of all defined marks. The insert mark defines where the insert cursor is displayed. The insert mark is treated specially: you cannot remove it with the mark unset operation. Attempting to do so does not raise an error, though, so the following is a quick way to unset all marks. The eval is necessary to join the list of mark names into the mark unset command:
Mark Gravity
Each mark has a gravity that determines what happens when characters are inserted at the mark. The default gravity is right, which means that the mark sticks to the character that is to its right. Inserting text at a mark with right gravity causes the mark to be pushed along so it is always after the inserted text. With left gravity the mark stays with the character to its left, so inserted text goes after the mark and the mark does not move. In versions of Tk before 4.0, marks had only right gravity, which made some uses of marks awkward. The mark gravity operation is used to query and modify the gravity of a mark: $t mark gravity foobar => right
[ Team LiB ]
[ Team LiB ]
Text Tags
A tag is a VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED symbolic name that is associated with one or more ranges of characters. A tag has attributes that affect the display of text that is tagged with it. These attributes include fonts, colors, tab stops, line spacing and justification. A tag can have event bindings so you can create hypertext. A tag can also be used to represent application-specific information. The tag names and tag ranges operations described later tell you what tags are defined and where they are applied.
You can use almost any string for the name of a tag. However, do not use pure numbers, and UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE and may do not include spaces, plus (+ ) or minus (- ). These characters are used in index arithmetic cause problems if you use them in tag names. A tag is added to a range with the tag add operation. The following command applies the tag everywhere to all the text in the widget:
You can add one or more tags when text is inserted, too:
If you do not specify tags when text is inserted, then the text picks up any tags that are present on the characters on both sides of the insertion point. (Before Tk 4.0, tags from the left-hand character were picked up.) If you specify tags in the insert operation, only those tags are applied to the text. A tag is removed from a range of text with the tag remove operation. However, even if there is no text labeled with a tag, its attribute settings are remembered. All information about a tag can be removed with the tag delete operation:
Tag Attributes
The attributes for a tag are defined with the tag configure operation. For example, a tag for blue text is defined with the following command:
Table 36-3 specifies the set of attributes for tags. Some attributes can only be applied with tags; there is no global attribute for -bgstipple , -elide , -fgstipple , -justify , -lmargin1 , -lmargin2 , offset , -overstrike , -rmargin , and -underline . Table 36-10 on page 557 lists the attributes for the text widget as a whole.
The -relief and -borderwidth attributes go together. If you only specify a relief, there is no visible effect. The default relief is flat , too, so if you specify a border width without a relief you won't see any effect either. The stipple attributes require a bitmap argument. Bitmaps and colors are explained in more detail in Chapter 41 . For example, to "grey out" text you could use a foreground stipple of gray50 :
The -elide attribute, added in Tk 8.3, controls whether or not the text is displayed. It can be quite useful to set the -elide attribute to True to hide embedded information, such as HTML or XML tags or URLs for hotlinks.
UNREGISTERED VERSION OF CHM(and bindings) for tags once inTHETA-SOFTWARE before you have You can set up the appearance TO PDF CONVERTER By your application, even
labeled any text with the tags. The attributes are retained until you explicitly delete the tag. If you are going to use the same appearance over and over again, then it is more efficient to do the setup once so that Tk can retain the graphics context. On the other hand, if you change the configuration of a tag, any text with that tag will be redrawn with the new attributes. Similarly, if TO PDF CONVERTER tag, all tagged characters UNREGISTERED VERSION OF CHMyou change a binding on a By THETA-SOFTWAREare affected immediately. Example 36-1 defines a few tags for character styles you might see in an editor. The example uses the font naming system added in Tk 8.0, which is described on page 636.
$t tag configure deleted -background grey75 $t tag configure moved -background yellow
These tags conflict, but they are never used on the same message. However, a selection could be indicated with an underline, for example:
You can add and remove the select tag to indicate what messages have been selected, and the underline is independent of the background color determined by the moved or deleted tag. If you look at the exmh implementation, the ftocColor.tcl file defines several text tags that are composed like this.
proc TextExample { f } { frame $f pack $f -side top -fill both -expand true set t [text $f.t -setgrid true -wrap word \ -width 42 -height 14 \ -yscrollcommand "$f.sy set"] scrollbar $f.sy -orient vert -command "$f.t yview" pack $f.sy -side right -fill y pack $f.t -side left -fill both -expand true $t tag configure para -spacing1 0.25i -spacing2 0.1i \ -lmargin1 0.5i -lmargin2 0.1i -rmargin 0.5i $t tag configure hang -lmargin1 0.1i -lmargin2 0.5i
end "Here is a line with end "Now is the time for this great time of need, end "The quick brown fox
no special settings\n" all good women and men to come to the aid of their no one can avoid their responsibility.\n" jumps over the lazy dog."
$t tag add para 2.0 2.end $t tag add hang 3.0 3.end } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE The example defines two tags, para and hang , that have different spacing and margins. The -spacing1 setting for para causes the white space before the second line. The -spacing2 setting causes the white space between the wrapped portions of the second paragraph. The hang tag has no spacing attributes, so the last paragraph starts UNREGISTERED VERSION OFright below PDF CONVERTER By You can also see the difference between the CHM TO the previous paragraph. THETA-SOFTWARE -lmargin1 and -lmargin2 settings. The newline characters are inserted explicitly. Each newline character defines a new line for the purposes of indexing, but not necessarily for display, as this example shows. In the third line there is no newline. This means that if more text is inserted at the end mark, it will be on line three. The values for the spacing and margin parameters are in screen units. Because different fonts are different sizes, you may need to compute the spacings as a function of the character sizes. The bbox operation returns the bounding box (x, y, width, height) for a given character:
The Tk 8.0 font metrics command, which is described on page 640, also gives detailed measurements:
Text justification is limited to three styles : left , right, or center . There is no setting that causes the text to line up on both margins, which would have to be achieved by introducing variable spacing between words.
Tab Stops
Text widgets have adjustable tab stops. The tabs attribute is a list of tab stops, which are specified with a screen unit and optionally a keyword that indicates justification. The tab justification keywords are left , right , center , and numeric , and these can be abbreviated. The default is left . The following resource specification defines tab stops at 2-centimeter intervals with different justification:
The tabs attribute applies to the whole text widget or to a tag. The last tab stop is extrapolated as needed. The following command defines a tag that has left justified tab stops every half inch:
[ Team LiB ]
[ Team LiB ]
The Selection
UNREGISTERED VERSION OF CHM TO predefined tag named By THETA-SOFTWARE PDF CONVERTER sel. If the application tags The selection is implemented with a
characters with sel, those characters are added to the selection. This is done as part of the default bindings on the text widget. The exportSelection attribute of a text widget controls whether or not selected text is exported by the selection mechanism to other applications. By default the selection is exported. UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE the sel In this case, when another widget or application asserts ownership of the selection then tag is removed from any characters that are tagged with it. Chapter 38 describes the selection mechanism in more detail. You cannot delete the sel tag with the tag delete operation. However, it is not an error to do so. You can delete all the tags on the text widget with the following command. The eval command is used to join the list of tag names into the tag delete command:
[ Team LiB ]
[ Team LiB ]
Tag Bindings
You can associate a tag with bindings so that when the user clicks on different areas of the text display, different things happen. The syntax for the tag bind command is similar to that of the main Tk bind command. You can both query and set the bindings for a tag. Chapter 29 describes the bind command and the syntax for events in detail. The only events supported by the tag bind command are Enter, Leave, ButtonPress, ButtonRelease, Motion, KeyPress, and KeyRelease. ButtonPress and KeyPress can be shorted to Button and Key as in the regular bind command. The Enter and Leave events are triggered when the mouse moves in and out of characters with a tag, which is different from when the mouse moves in and out of the window. If a character has multiple tags, then the bindings associated with all the tags will be invoked, in the order from lowest priority tag to highest priority tag. After all the tag bindings have run, the binding associated with the main widget is run, if any. The continue and break commands work inside tag bindings in a similar fashion as they work with regular command bindings. See Chapter 29 for the details. Example 36-3 defines a text button that has a highlighted relief and an action associated with it. The example generates a new tag name so that each text button is unique. The relief and background are set for the tag to set it apart visually. The winfo visual command is used to find out if the display supports color before adding a colored background to the tag. On a black and white display, the button is displayed in reverse video (i.e., white on black.) The command is bound to <Button-1>, which is the same as <ButtonPress-1>. The cursor is changed when the mouse is over the tagged area by binding to the <Enter> and <Leave> events. Upon leaving the tagged area, the cursor is restored. Another tag is used to remember the previous setting for the cursor. You could also use a global variable, but it is often useful to decorate the text with tags for your own purposes.
$t tag bind $tag <Button-1> $command $t tag add $tag $start $end # use another tag to remember the cursor $t tag bind $tag <Enter> \ [list TextButtonChangeCursor %W $start $end tcross] $t tag bind $tag <Leave> {TextButtonRestoreCursor %W} } proc TextButtonChangeCursor {t start end cursor} { UNREGISTERED VERSION OF CHM TO PDF CONVERTER By $t tag add cursor=[$t cget -cursor] $start $end $t config -cursor $cursor } proc TextButtonRestoreCursor {t} { regexp {cursor=([^ ]*)} [$t tag names] x cursor $t config -cursor $cursor UNREGISTERED VERSION OF CHM TO PDF CONVERTER By }
THETA-SOFTWARE
THETA-SOFTWARE
To behave even more like a button, the action should trigger upon <ButtonRelease-1>, and the appearance should change upon <ButtonPress-1>. If this is important to you, you can always embed a real Tk button. Embedding widgets is described later. [ Team LiB ]
[ Team LiB ]
Searching Text
The search operation scans the text widget for a string that matches a pattern. The index of the text that matches the pattern is returned. The search starts at an index and covers all the text widget unless a stop index is supplied. You can use end as the stop index to prevent the search from wrapping back to the beginning of the document. The general form of the search operation is this:
If you use a regular expression to match a pattern, you may be interested in how much text matched so you can highlight the match. The -count option specifies a variable that gets the number of matching characters:
set start [$t search -count cnt -regexp -- $pattern 1.0 end] $t tag add sel $start "$start +$cnt chars"
[ Team LiB ]
[ Team LiB ]
Embedded Widgets
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
The text widget can display embedded widgets as well as text. You can include a picture, for example, by constructing it in a canvas and then inserting the canvas into the text widget. An embedded widget takes up one character in terms of indices. You can address the widget by its index position or by the Tk pathname of the widget. For example, suppose $t names a text widget. The following commands create a button and command when the user clicks on it:
UNREGISTERED VERSIONwidget. TheTO PDF CONVERTER By THETA-SOFTWARE the Help insert it into the text OF CHM button behaves normally, and in this case it invokes
button $t.help -bitmap questhead -command Help $t window create end -window $t.help
By default an embedded widget is centered vertically on its text line. You can adjust this with the -align option to the window create command. This setting only takes effect if the window is smaller than the text in the line. I find that windows are usually larger than the text line, and in that case the -align setting has no effect. This setting is also used with images, however, where it is more common to have small images (e.g., for special bullets). Table 36-5 describes the window and image alignment settings:
baseline Bottom lines up with text baseline. bottom Bottom lines up with bottom of text line.
You can postpone the creation of the embedded widget by specifying a Tcl command that creates the window, instead of specifying the -window option. The delayed creation is useful if you have lots of widgets embedded in your text. In this case the Tcl command is evaluated just before the text widget needs to display the widget. In other words, when the user scrolls the text so the widget will appear, the Tcl command is run to create the widget:
The MakeGoBack procedure is introduced to eliminate potential quoting problems. If you need to execute more than one Tcl command to create the widget or if the embedded button has a complex command, the quoting can quickly get out of hand. Table 36-6 gives the complete set of options for creating embedded widgets. You can change these later with the window configure operation. For example:
You can specify the window to reconfigure by its pathname or the index where the window is located. In practice, naming the widget by its pathname is much more useful. Note that end is not useful for identifying an embedded window because the text widget treats end specially. You can insert a window at end, but end is always updated to be after the last item in the widget. Thus end will never name the position of an existing window. [ Team LiB ]
[ Team LiB ]
Embedded Images
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Tk 8.0 added embedded images that are much like embedded windows. They provide a more efficient way to add images than creating a canvas or label widget to hold the image. You can also put the same image into a text widget many times. Example 36-5 uses an image for the bullets in a bulleted list:
Example 36-5 Using embedded images for a THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER By bulleted list
proc BList_Setup { t imagefile } { global blist set blist(image) [image create photo -file $imagefile] $t tag configure bulletlist -tabs ".5c center 1c left" \ -lmargin1 0 -lmargin2 1c } proc BList_Item { t text {mark insert}} { global blist # Assume we are at the beginning of the line $t insert $mark \t bulletlist $t image create $mark -image $blist(image) $t insert $mark \t$text bulletlist }
In Example 36-5, tabs are used to line up the bullet and the left edges of the text. The first tab centers the bullet over a point 0.5 centimeters from left margin. The second tab stop is the same as the -lmargin2 setting so the text on the first line lines up with the text that wraps onto more lines. If you update the image dynamically, all the instances of that image in the text widget are updated, too. This follows from the image model used in Tk, which is described in Chapter 41 on page 625. The options for embedded images are mostly the same as those for embedded windows. One difference is that images have a -name option so you can reference an image without remembering its position in the text widget. You cannot use the image name directly because the same image can be embedded many times in the text widget. If you do not choose a name, the text widget assigns a name for you. The image create operation returns this name:
$t => $t =>
image create 1.0 -image image1 image1 image create end -image image1 image1#1
Table 36-7 gives the complete set of options for creating embedded images. You can change these later with the image configure operation.
-name name A name for this instance of the image. A #num may be appended to generate a unique name. -padx pixels -pady pixels [ Team LiB ] Padding on either side of the image. Padding above and below the image.
[ Team LiB ]
Looking at Tags
The tag names command returns all the tag names, or the names of the tags at a specified index:
A text tag can be applied to many different ranges of text. The tag ranges operation returns a list of indices that alternate between the start and end of tag ranges. The foreach command with two loop variables makes it easy to iterate through all the ranges:
foreach {start end} [$t tag ranges $tag] { # start is the beginning of a range # end is the end of a range }
The tag nextrange and tag prevrange operations return two indices that delimit the next and previous range of a tag. They take a starting index and an optional ending index. The tag nextrange operation skips to the next range if the tag is present at the starting index, unless the starting index is right at the start of a range. The tag prevrange operation is complementary. It does not skip the current range, unless the starting index is at the beginning of the range. These rules are used in Example 36-6 that defines a procedure to return the current range:
proc Text_CurrentRange { t tag mark } { set range [$t tag prevrange $tag $mark] set end [lindex $range 1] if {[llength $range] == 0 || [$t compare $end < $mark]} { # This occurs when the mark is at the # very beginning of the node set range [$t tag nextrange $tag $mark] if {[llength $range] == 0 || [$t compare $mark < [lindex $range 0]]} { return {} } } return $range }
Looking at Marks
The mark names operation returns the names of all the marks. Unlike tag names, you cannot supply an index to find out if there are marks there. You must use the dump operation described later. The mark next and mark previous operations search from a given index for a mark. The mark next operation will find a mark if it is at the starting index.
The dump operation returns information for the elements from ix1 to ix2, or just for the elements at ix1 if ix2 is not specified. You can limit what information is returned with options that indicate what to return: -text, -mark, -tag, -image, -window, or -all. Three pieces of information are returned for each element of the text widget: the type, the value, and the index. The possible types are text, tagon, tagoff, mark, image, and window. The information reflects the way the text widget represents its contents. Tags are represented as tagon and tagoff elements. Text is stored in segments that do not include any marks, tag elements, windows, or images. In addition, a newline ends a text segment. Example 36-7 prints out the contents of the text widget:
Instead of having dump return all the information, you can have it call a Tcl command to process each element. The command gets passed three pieces of information for each UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE element: the type, the value, and the index. Example 36-8 shows another way to print out the text widget contents:
[ Team LiB ]
[ Team LiB ]
$t insert end "Let's insert some " {} \ "special" blue " text." {}
If this operation were undone and then redone, the text would be re-inserted, but without applying the blue tag on the word "special".
[ Team LiB ]
[ Team LiB ]
Text Bindings
There is an extensive set of default bindings for text widgets. In general, the commands that move the insertion cursor also clear the selection. Often you can hold the Shift key down to extend the selection, or hold the Control key down to move the insertion cursor without UNREGISTEREDthe selection. Table 36-8 lists theCONVERTER By THETA-SOFTWARE VERSION OF CHM TO PDF default bindings for the text widget: affecting
<Shift-Up> <Control-Up> <Control-Shift-Up> <Key-Down> <Control-n> <Next> <Prior> <Shift-Next> <Shift-Prior> <Home> <Control-a> <Shift-Home> <End> <Control-e> <Shift-End> <Control-Home> <Meta-less> <Control-End> <Meta-greater> <Select> <Control-space> <Shift-Select> <Control-Shiftspace> <Control-slash> <Control-backslash> <Delete> <BackSpace> <Control-h> <Control-d> <Meta-d> <Control-k> <Control-o> <Meta-Delete> <Meta-BackSpace> <Control-t>
Moves the cursor up one line. Extends the selection. Moves the cursor up by paragraphs, which are a group of lines separated by a blank line. Moves the cursor up by paragraph. Extends the selection. All Down bindings are analogous to Up bindings. Moves the cursor by one screen. Clears the selection. Moves the cursor by one screen. Extends the selection.
Moves the cursor to line start. Clears the selection. Moves the cursor to line start. Extends the selection. Moves the cursor to line end. Clears the selection. Moves the cursor to line end. Extends the selection. Moves the cursor to the beginning of text. Clears the selection.
Selects everything in the text widget. Clears the selection. Deletes the selection, if any. Otherwise, deletes the character to the right of the cursor. Deletes the selection, if any. Otherwise, deletes the character to the left of the cursor. Deletes character to the right of the cursor. Deletes word to the right of the cursor. Deletes from cursor to end of the line. If you are at the end of line, deletes the newline character. Inserts a newline but does not advance the cursor. Deletes the word to the left of the cursor.
<<Cut>> <Control-x> <<Copy>> <Controlc> <<Paste>> <Controlv> z> <<Redo>> <Control-Z> (Unix & Mac) <Control-y> (Windows)
Copies the selection to the clipboard. Cuts the selection and saves it on the clipboard. Pastes from the clipboard.
<<Undo>> <ControlUNREGISTERED VERSION OF Undoes the last edit action if theBy THETA-SOFTWARE 8.4) CHM TO PDF CONVERTER undo attribute is true. (Tk Reapplies the last undone edit action if the undo attribute is true. (Tk 8.4)
Also added in Tk 8.4 is the <<Selection>> virtual event, which is generated whenever the text widget's selection changes. The event is fired after the selection has changed, so the binding action can access the new selection. [ Team LiB ]
[ Team LiB ]
Text Operations
Table 36-9 describes the text widget operations, including some that are not discussed in this chapter. In the table, $t is a text widget:
$t cget option $t compare i1 op i2 $t configure ... $t debug boolean $t delete i1 ?i2? ?...?
$t dlineinfo index
$t dump ?options? i1 ? i2? $t edit modified ? boolean? $t edit redo $t edit reset $t edit separator $t edit undo $t get i1 ?i2? ?...?
$t image create option value ... $t image names $t index index $t insert index chars ?
Creates an embedded image. Options are described in Table 367 on page 547. Returns the names of all embedded images. Returns the numerical value of index. Inserts chars at the specified index. If tags are specified, they Queries or assigns a gravity direction to the mark name. direction, if specified, is left or right. Returns a list of defined marks.
UNREGISTERED VERSION OF CHM TO PDFto the new characters. tags? ?chars tags? ... are added CONVERTER By THETA-SOFTWARE
$t mark gravity name ? direction? $t mark names
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE $t mark next index Returns the mark after index.
$t mark previous index $t mark set name index $t mark unset name1 ? name2 ...? $t scan mark x y $t scan dragto x y $t search ?switches? pattern index ? stopIndex? $t see index $t tag add name i1 ?i2? ?i1 i2? ?i1 i2? ... $t tag bind name ? sequence? ?script? $t tag cget name option $t tag configure name ... Queries or defines bindings for the tag name. Returns the value of option for tag name. Sets or queries the configuration of tag name. Returns the mark before index. Defines a mark name at the given index. Deletes the named mark, or marks. Anchors a scrolling operation. Scrolls based on a new position. Searches for pattern starting at index. The index of the start of the match is returned. Switches are described in Table 36-4 on page 544. Positions the display to view index. Adds the tag to i1 through, but not including i2, or just the character at i1 if i2 is not given.
$t tag delete tag1 ?tag2 Deletes information for the named tags. ...? $t tag lower tag ? below? $t tag names ?index? Lowers the priority of tag to the lowest priority or to just below tag below. Returns the names of the tags at the specified index, or in the whole widget, sorted from lowest to highest priority. Returns a list of two indices that are the next range of text with tag that starts at or after i1 and before index i2, or the end. Returns a list of two indices that are the previous range of text with tag that ends at or before i1 and at or after index i2, or 1.0.
$t tag raise tag ? above? $t tag ranges tag $t tag remove tag i1 ? i2? ?i1 i2? ?i1 i2? ... $t window cget win option $t window config win ... $t window create ix args $t window names $t xview
Raises the priority of tag to the highest priority, or to just above the priority of tag above. Returns a list describing all the ranges of tag. Removes tag from the range i1 up to, but not including i2, or just at i1 if i2 is not specified.
Returns the value of option for win. Queries or modifies the configuration of the embedded window. win is a Tk pathname or an index. Creates an embedded window at ix. Returns a list of windows embedded in $t. Returns two fractions between zero and one that describe the amount of text off-screen to the left and the amount of text displayed. Positions the text so fraction of the text is off screen to the left. Scrolls num of what, which is units or pages. Returns two fractions between zero and one that describe the amount of text off-screen toward the beginning and the amount of text displayed. Positions the text so fraction of the text is off-screen toward the beginning. Scrolls num of what, which is units or pages. Obsolete. Use the see operation, which is similar. Obsolete. Position line num at the top of screen.
$t yview moveto fraction $t yview scroll num what $t yview ?-pickplace? ix $t yview num [ Team LiB ]
[ Team LiB ]
Text Attributes
Table 36-10 lists the OF CHM TO PDF widget. The table THETA-SOFTWARE UNREGISTERED VERSIONattributes for the textCONVERTER Byuses the resource name, which has capitals at internal word boundaries. In Tcl commands, the attributes are specified with a dash and all lowercase:
Table CHM TO PDF attribute resource names UNREGISTERED VERSION OF 36-10. Text CONVERTER By THETA-SOFTWARE
autoSeparators Boolean: True (default) automatically insert undo separators after each insert or delete operation; False requires the use of the undo separator operation to insert separators. (Tk 8.4) Background color (also bg). Extra space around the edge of the text. Cursor to display when mouse is over the widget. If true, selected text is exported to the selection. Default font for the text. Foreground color (also fg). Height, in text lines.
highlightBackground Focus highlight color when widget does not have focus. highlightColor highlightThickness insertBackground insertBorderWidth insertOffTime insertOnTime insertWidth maxUndo padX padY relief selectBackground selectForeground selectBorderWidth Color for input focus highlight border. Width of highlight border. Color for the insert cursor. Size of 3D border for insert cursor. Milliseconds insert cursor blinks off. Milliseconds insert cursor blinks on. Width of the insert cursor. The maximum number of undo actions on the undo stack. A zero or a negative value implies an unlimited undo stack. (Tk 8.4) Extra space to the left and right of the text. Extra space above and below the text. flat, sunken, raised, groove, ridge, or solid. Background color of selected text. Foreground color of selected text. Size of 3D border for selection highlight.
setGrid spacing1 spacing2 spacing3 state tabs takeFocus undo width wrap xScrollCommand yScrollCommand [ Team LiB ]
Enable/disable geometry gridding. Extra space above each unwrapped line. Space between parts of a line that have wrapped. Extra space below an unwrapped line. Editable (normal) or read-only (disabled). Tab stops. Control focus changes from keyboard traversal. Boolean: True enables and False (default) disables the undo mechanism. (Tk 8.4) Width, in characters, of the text display. Line wrap mode: none, char, or word. Tcl command prefix for horizontal scrolling. Tcl command prefix for vertical scrolling.
[ Team LiB ]
[ Team LiB ]
Canvas Coordinates
The coordinate space of the canvas has 0, 0 at the top left corner. Larger X coordinates are to the right, and larger Y coordinates are downward. The position and possibly the size of a canvas object is determined by a set of coordinates. Different objects are characterized by different numbers of coordinates. For example, text objects have two coordinates, x1 y1, that specify their anchor point. A line can have many pairs of coordinates that specify the end points of its segments. The coordinates are set when the object is created, and they can be updated later with the coords operation. By default, coordinates are in pixels. Append a coordinate with one of the following letters to change the units:
c i m p
The tk scale command, which is described on page 669, changes the mapping from pixels to other screen measures. Use it before creating the canvas. The width and height attributes of the canvas determine the size of the viewable area. The scrollRegion attribute of the canvas determines the boundaries of the canvas. Its value is four numbers that specify the upper-left and lower-right coordinates of the canvas. If you do not specify a scroll region, it defaults to the size of the viewable area. Example 37-1 creates a canvas that has a 1000 by 400 scrolling region, and a 300 by 200 viewing area. The canvas is connected to two scrollbars to provide horizontal and vertical scrolling:
The highlight thickness and border width are set to 0 in Example 37-1. Otherwise, these features occupy some of CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OFthe canvas viewable area. If you want a raised border for your canvas, either use another frame, or remember to offset your positions to avoid having objects clipped by the borders. [ Team LiB ]
[ Team LiB ]
Hello, World!
Example 37-2 creates an object that you can drag around with the mouse. It introduces the use of tags to classify objects. In this case the movable tag gets bindings that let you drag the item, so any item with the movable tag shares this behavior. The example uses Scrolled_Canvas from Example 37-1. When you use a scrolled canvas, you must map from the view coordinates reported by bindings to the canvas coordinates used to locate objects:
Example 37-2 creates a text object and gives it a tag named movable:
The first argument after create specifies the type, and the remaining arguments depend on the type of object being created. Each canvas object requires some coordinates, optionally followed by attribute value pairs. The coordinates can be provided as separate arguments or, beginning in Tk 8.3, as a single-argument list. The complete set of attributes for canvas objects are presented later in this chapter. A text object needs two coordinates for its location.
Canvas Tags
The create operation returns an ID for the object being created, which would have been 1 in this case. However, the code manipulates the canvas objects by specifying a tag instead of an object ID. A tag is a more general handle on canvas objects. Many objects can have the same tag, and an object can have more than one tag. You can define bindings on tags, and UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE you can define attributes for tags that will be picked up by objects with those tags. A tag name can be almost any string, but you should avoid spaces that can cause parsing problems and pure numbers that get confused with object IDs. There are two predefined tags: current and all. The current tag applies to whatever object is under the mouse. The all tag applies to all the objects on the canvas. Many of the canvas operations take an argument that identifies objects. The value can be a tag name, or it can be the numerical object identifier returned by the create operation. Also, beginning in Tk 8.3, you can specify (as a single argument) a logical combination of tags using the operators && (and), || (or), ^ (exclusive or), ! (not), and parenthesized subexpressions. For example, to change the fill color to red on all objects with a tag of highlight or warning, you could execute the following:
To move all the objects with the tag plot1 or plot2, but that don't also include the tag fixed:
Example 37-2 on page 559 defines behavior for objects with the movable tag. Pressing button 1 starts a drag, and dragging with the mouse button down moves the object. The pathname of the canvas (%W) is passed to CanvasMark and CanvasDrag so these procedures can be used on different canvases. The %x and %y keywords get substituted with the X and Y coordinate of the event:
$can bind movable <Button-1> {CanvasMark %x %y %W} $can bind movable <B1-Motion> {CanvasDrag %x %y %W}
The CanvasMark and CanvasDrag procedures let you drag the object around the canvas. Because CanvasMark is applied to any object with the movable tag, it must first find the object that was clicked on. First, the view coordinates are mapped into the canvas coordinates with the canvasx and canvasy operations:
Try creating a few other object types and dragging them around, too:
$can create rect 10 10 30 30 -fill red -tag movable $can create line 1 1 40 40 90 60 -width 2 -tag movable $can create poly 1 1 40 40 90 60 -fill blue -tag movable
The CanvasMark and CanvasDrag procedures can be used with any canvas. They use the global array canvas to keep their state, and they parameterize the indices with the canvas pathname to avoid conflict if there is more that one canvas in the application. If you get into this coding habit early, then you will find it easy to write reusable code.
Canvas tags do not work exactly like tags in the text widget. In the text widget, a tag is completely independent of the text. You can configure a text tag before it is applied to text, and the tag configuration is remembered even if you remove it from the text. A canvas tag, in contrast, must be applied to an object before you can configure it. If you configure a canvas tag that is not applied to any objects, those settings are forgotten. If you remove all the objects that share a tag, any settings associated with those tags are forgotten. [ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO operations: bbox, coords, scale, and move. The bbox PDF CONVERTER By THETA-SOFTWARE The example introduces four canvas
The thoughtful selection of tag names help to create "self-documenting code." And tags give you more flexibility to change an implementation later on. Example 37-3 does not use object IDs. Instead, it gives each object a symbolic identifier with a tag, plus it introduces more tags to represent classes of objects. The example uses the all tag to move all the items and to find out the bounding box of the image. The left box and the left hanging text both have the left tag. They can be moved together, and they share the same bindings. Similarly, the right tag is shared by the right box and the right hanging text. Each item has its own unique tag, so it can be manipulated individually, too. Those tags are slider, lbox, lnum, rbox, and rnum:
proc Scale2 {w min max {width {}} } { global scale2 if {$width == {}} { # Set the long dimension, in pixels set width [expr $max - $min] } # Save parameters set scale2($w,scale) [expr ($max-$min)/$width.0] set scale2($w,min) $min;# Current minimum
scale2($w,max) $max scale2($w,Min) $min;# Lower bound to the scale scale2($w,Max) $max scale2($w,L) 10 scale2($w,R) [expr $width+10]
Build from 0 to 100, then scale and move it later. Distance between left edges of boxes is 100. The box is 10 wide, therefore the slider is 110 long. The left box sticks up, and the right one hangs down.
canvas $w $w create rect $w create rect $w create rect $w create text $w create text -tag {right
0 0 110 10 -fill grey -tag slider 0 -4 10 10 -fill black -tag {left lbox} 100 0 110 14 -fill red -tag {right rbox} 5 16 -anchor n -text $min -tag {left lnum} 105 16 -anchor n -text $max \ rnum} -fill red
# Stretch/shrink the slider to the right length set scale [expr ($width+10) / 110.0] $w scale slider 0 0 $scale 1.0 # move the right box and text to match new length set nx [lindex [$w coords slider] 2] $w move right [expr $nx-110] 0 # Move everything into view $w move all 10 10 # Make the canvas fit comfortably around the image set bbox [$w bbox all] set height [expr [lindex $bbox 3]+4] $w config -height $height -width [expr $width+30] # Bind drag actions $w bind left <Button-1> {Scale2Mark %W %x lbox} $w bind right <Button-1> {Scale2Mark %W %x rbox} $w bind left <B1-Motion> {Scale2Drag %W %x lbox} $w bind right <B1-Motion> {Scale2Drag %W %x rbox} }
The slider is constructed with absolute coordinates, and then it is scaled to the desired width. The alternative is to compute the coordinates based on the desired width. I have found it clearer to use numbers when creating the initial layout as opposed to using expr or introducing more variables. The scale operation stretches the slider bar to the correct length. The scale operation takes a reference point, which in our case is (0, 0), and independent scale factors for the X and Y dimensions. The scale factor is computed from the width parameter, taking into account the extra length added (10) so that the distance between the left edge of the slider boxes is $width:
The move operation repositions the right box and right hanging text. If the marker boxes are scaled, their shape gets distorted. The coords operation returns a list of four numbers: x1 y1 x2 y2. The distance to move is just the difference between the new right coordinate and the value used when constructing the slider initially. The box and text share the same tag, right, so they are both moved with a single move operation:
set nx [lindex [$w coords slider] 2] UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE $w move right [expr $nx-110] 0
After the slider is constructed, it is shifted away from (0, 0), which is the upper-left corner of the canvas. The bbox operation returns four coordinates: x1 y1 x2 y2, that define the bounding VERSION OF with TO PDF CONVERTER By y1 is zero, so y2 gives UNREGISTERED box of the items CHMthe given tag. In the example, THETA-SOFTWARE us the height of the image. The information returned by bbox can be off by a few pixels, and the example needs a few more pixels of height to avoid clipping the text. The width is computed based on the extra length added for the marker box, the 10 pixels the whole image was shifted, and 10 more for the same amount of space on the right side:
set bbox [$w bbox all] set height [expr [lindex $bbox 3]+4] $w config -height $height -width [expr $width+30]
Bindings are defined for the box and hanging text. The general tags left and right are used for the bindings. This means that you can drag either the box or the text to move the slider. The pathname of the canvas is passed into these procedures so that you could have more than one double slider in your interface:
$w $w $w $w
<Button-1> {Scale2Mark %W %x lbox} <Button-1> {Scale2Mark %W %x rbox} <B1-Motion> {Scale2Drag %W %x lbox} <B1-Motion> {Scale2Drag %W %x rbox}
Example 37-4 Moving the markers for the min max scale
proc Scale2Mark { w x what } { global scale2 # Remember the anchor point for the drag set scale2($w,$what) $x } proc Scale2Drag { w x what } { global scale2 # Compute delta and update anchor point set x1 $scale2($w,$what) set scale2($w,$what) $x set dx [expr $x - $x1] # Find out where the boxes are currently set rx [lindex [$w coords rbox] 0] set lx [lindex [$w coords lbox] 0]
if {$what == "lbox"} { # Constrain the movement to be between the # left edge and the right marker. if {$lx + $dx > $rx} { set dx [expr $rx - $lx] set scale2($w,$what) $rx } elseif {$lx + $dx < $scale2($w,L)} { set dx [expr $scale2($w,L) - $lx] set scale2($w,$what) $scale2($w,L) } $w move left $dx 0 # Update the minimum value and the hanging text set lx [lindex [$w coords lbox] 0] set scale2($w,min) [expr int($scale2($w,Min) + \ ($lx-$scale2($w,L)) * $scale2($w,scale))] $w itemconfigure lnum -text $scale2($w,min) } else { # Constrain the movement to be between the # right edge and the left marker if {$rx + $dx < $lx} { set dx [expr $lx - $rx] set scale2($w,$what) $lx } elseif {$rx + $dx > $scale2($w,R)} { set dx [expr $scale2($w,R) - $rx] set scale2($w,$what) $scale2($w,R) } $w move right $dx 0 # Update the maximum value and the hanging text set rx [lindex [$w coords right] 0] set scale2($w,max) [expr int($scale2($w,Min) + \ ($rx-$scale2($w,L)) * $scale2($w,scale))] $w itemconfigure rnum -text $scale2($w,max) } } proc Scale2Value {w} { global scale2 # Return the current values of the double slider return [list $scale2($w,min) $scale2($w,max)] }
The Scale2Mark procedure initializes an anchor position, scale2($w,$what), and Scale2Drag uses this to detect how far the mouse has moved. The change in position, dx, is constrained so that the markers cannot move outside their bounds. The anchor is updated if a constraint was used, and this means that the marker will not move until the mouse is moved back over the marker. (Try commenting out the assignments to scale2($w,$what) inside the if statement.) After the marker and hanging text are moved, the value of the associated parameter is computed based on the parameters of the scale. The Scale2Value procedure queries the current values of the double slider. [ Team LiB ]
[ Team LiB ]
Canvas Objects
The next VERSION OF CHM TO PDF CONVERTER for the canvas: arc, bitmap, image, UNREGISTEREDseveral sections describe the built-in object typesBy THETA-SOFTWARE line, oval, polygon, rectangle, text, and window. Each object has its own set of attributes, and some attributes are found on most or all object types. Table 37-1 lists the common item attributes found on all or most objects. All -active and -disabled attributes were added in Tk 8.3, as were the -state attribute, the -offset attribute, and those attributes related to dashes.
-dashoffset offset
The starting offset distance into the pattern provided by the -dash option. (Tk 8.3) The color of the interior of the object when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -fill)
The stipple pattern for the fill when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -stipple)
-offset offset
The stipple offset in the form x,y or side. side can be n, ne, e, se, s, sw, w, nw, or center. x,y is a distance relative to the canvas origin; putting # in front of the coordinate pair indicates using the toplevel origin instead. (Tk 8.3) The color of the outline when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -outline)
The stipple pattern for the outline when in the normal, active (the mouse over the object), and disabled -outlinestipple bitmap states. (Tk 8.3, except -outlinestipple) -activeoutlinestipple bitmap -disabledoutlinestipple bitmap
Width, in canvas coordinates, of the line or outline when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -width)
normal, disabled, or hidden. This overrides the canvas widget's state attribute. (Tk 8.3) List of tags for the object.
Every object has a -tags attribute used to label the object with a list of symbolic names. Most objects, even text objects, specify their color with the -fill attribute; only the bitmap object uses -foreground and -background. If the object has a border, the color of the border is specified with -outline, and the thickness of the outline is specified with -width. Starting in Tk 8.3, lines and objects with borders have a variety of -dash attributes for drawing dashed lines and borders.
Dashed Lines
Tk 8.3 introduced the ability to draw lines and object outlines using dashed lines. The primary object attribute for controlling the dash pattern is -dash, although -activedash and disableddash attributes are available for controlling the dash pattern in different object states. Each of these attributes accepts a dash pattern as a value. One dash pattern format is a list of integers. Each element represents the number of pixels of a line segment. Only the odd segments are drawn using the -outline color. The other segments are drawn transparent. For example the following command draws a line with 6-pixel dashes separated by 2-pixel spaces:
The other dash pattern format is a string containing any combination of the characters shown in Table 37-2.
UNREGISTERED VERSIONthe length of the following space OF CHM TO PDF CONVERTER By THETA-SOFTWARE _ Dash double
space Doubles the length of the space For example, the dash pattern {_. ,} is roughly equivalent to {8 4 2 8 4 4}
UNREGISTERED difference ofOF CHM TO PDF CONVERTER By THETA-SOFTWARE the stringThe main VERSION the string-based syntax versus the list-based syntax is that it
based syntax is shape-conserving. This means that all values in the dash list are multiplied by the line width before display. This assures that "." is always displayed as a dot and "-" as a dash regardless of the line width. Finally, the -dashoffset attribute specifies the starting offset (in pixels) into the pattern provided by -dash.
On systems that support only a limited set of dash patterns, the dash pattern is displayed as the closest dash pattern that is available. For example, on Windows the dash patterns {.} and {,} and {. } and {, } are displayed identically.
Arc Items
An arc is a section of an oval. The dimensions of the oval are determined by four coordinates that are its bounding box. The arc is then determined by two angles, the start angle and the extent. The region of the oval can be filled or unfilled, and there are three different ways to define the fill region. The pieslice style connects the arc with the center point of the oval. The chord style connects the two end points of the arc. The arc style just draws the arc itself and there is no fill. Example 37-5 shows three arcs with the same bounding box but different styles and angles:
canvas arc 10 10 100 100 -start 45 -extent -90 \ pieslice -fill orange -outline black arc 10 10 100 100 -start 135 -extent 90 \ chord -fill blue -outline white -width 4 arc 10 10 100 100 -start 255 -extent 45 \ arc -outline black -width 3
An arc object support all of the object attributes listed in Table 37-1. Table 37-3 lists the additional attributes supported by arc objects.
Bitmap Items
A bitmap is a simple graphic with a foreground and background color. One bit per pixel is used to choose between the foreground and the background. If you do not specify a background color, the background bits are clear and the canvas background shows through. A canvas bitmap item is positioned with two coordinates and an anchor position. Its size is determined by the bitmap data. The bitmap itself is specified with a symbolic name or by the name of a file that contains its definition. If the name begins with an @, it indicates a file name. The bitmaps built into Tk are shown in the example below. Chapter 50 outlines the C interface for registering bitmaps under a name.
set o [$c create bitmap 10 10 -bitmap @candle.xbm -anchor nw\ -background white -foreground blue] set x [lindex [$c bbox $o] 2] ;# Right edge of bitmap foreach builtin {error gray12 gray50 hourglass \ info questhead question warning} { incr x 20 set o [$c create bitmap $x 30 -bitmap $builtin -anchor c] set x [lindex [$c bbox $o] 2] }
A bitmap object supports only the -state and -tags attributes listed in Table 37-1. Table 37-4 lists the additional attributes supported by bitmap objects.
The foreground color (for one bits) when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, -foreground color except -foreground) -activeforeground color -disabledforeground color
Image Items
The canvas image objects use the general image mechanism of Tk. You must first define an image using the image command, which is described in Chapter 41 in the section Bitmaps and Images. Once you have defined an image, all you need to specify for the canvas is its position, anchor point, and any tags. The size and color information is set when the image is defined. If an image is redefined, anything displaying that image automatically gets updated. Example 377 creates one image and puts six instances of it on a canvas:
image create bitmap hourglass2 \ -file hourglass.bitmap -maskfile hourglass.mask \ -background white -foreground blue for {set x 20} {$x < 300} {incr x 20} { $c create image $x 10 -image hourglass2 -anchor nw incr x [image width hourglass2] }
An image object supports only the -state and -tags attributes listed in Table 37-1. Table 37-5
The name of an image to use when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -image) -image name -activeimage name -disabledimage name
Line Items
A line has two or more sets of coordinates, where each set of coordinates defines an end point of a line segment. The segments can be joined in several different styles, and the whole line can be drawn with a spline fit as opposed to straight-line segments. The next example draws a line in two steps. In the first pass, single-segment lines are drawn. When the stroke completes, these are replaced with a single line segment that is drawn with a spline curve.
proc StrokeInit {} { canvas .c ; pack .c bind .c <Button-1> {StrokeBegin %W %x %y} bind .c <B1-Motion> {Stroke %W %x %y} bind .c <ButtonRelease-1> {StrokeEnd %W %x %y} } proc StrokeBegin { w x y } { global stroke catch {unset stroke} set stroke(N) 0 set stroke(0) [list $x $y] } proc Stroke { w x y } { global stroke set coords $stroke($stroke(N)) lappend coords $x $y incr stroke(N)
set stroke($stroke(N)) [list $x $y] # eval gets the coordinates into individual arguments eval {$w create line} $coords {-tag segments} } proc StrokeEnd { w x y } { global stroke set coords {} for {set i 0} {$i CHM TO PDF {incr i} { UNREGISTERED VERSION OF<= $stroke(N)} CONVERTER By THETA-SOFTWARE append coords $stroke($i) " " } $w delete segments eval {$w create line} $coords \ {-tag line -joinstyle round -smooth true -arrow last} } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 37-8 uses the stroke array to hold the points of the line as it builds up the stroke. At the end of the stroke it assembles the points into a list. The eval command concatenates this list of points onto the create line command. Recall that eval uses concat if it gets multiple arguments. The other parts of the create line command are protected by braces so they get evaluated only once. Chapter 10 describes this trick in more detail on page 134. Note that as of Tk 8.3 this would not be necessary as the create line command can now accept a list of coordinates as a single argument. The arrow attribute adds an arrow head to the end of the stroke. If you try this example you will notice that the arrow is not always aimed as you expect. This is because there are often many points generated close together as you release the mouse button. In fact, the X and Y coordinates seen by StrokeEnd are always the same as those seen by the last Stroke call. If you add this duplicate point to the end of the list of points, no arrowhead is drawn at all. In practice you might want to make Stroke filter out points that are too close together. A line object supports all of the attributes listed in Table 37-1 except for -offset, the outline family of attributes, and the -outlinestipple family of attributes. Remember that the -fill attribute controls the color in which the line is drawn (not the -outline attribute, as is common for other canvas items). Table 37-6 lists the additional attributes supported by line objects. The capstyle affects the way the ends of the line are drawn. The joinstyle affects the way line segments are joined together. The capstyle and joinstyle attributes are from the X window system and may not be implemented on the Macintosh and Windows platforms.
Arrow location: none, first, last, or both. Three parameters that describe the shape of the arrow. c is the width and b is the overall length. a is the length of the part that touches the line (e.g., 8 10 3). Line ends: butt, projecting, or round.
-joinstyle what Line joints: bevel, miter, or round. -smooth boolean If true, a spline curve is drawn. -splinesteps num Number of line segments that approximate the spline.
Oval Items
An oval is defined by two sets of coordinates that define its bounding box. If the box is square, a circle is drawn. You can set the color of the interior of the oval as well as the outline of the oval. A sampler of ovals is shown in Example 37-9.
$c create oval 10 10 80 80 -fill red -width 4 $c create oval 100 10 150 80 -fill blue -width 0 $c create oval 170 10 250 40 -fill black -stipple gray12
An oval object support all of the object attributes listed in Table 37-1. There are no additional attributes supported by oval objects.
Polygon Items
A polygon is a closed shape specified by sets of points, one for each vertex of the polygon. The vertices can be connected with smooth or straight lines. Example 37-10 creates a stop sign. The picture is centered at (0, 0) and then moved fully onto the canvas:
THETA-SOFTWARE
A polygon object support all of the object attributes listed in Table 37-1. Table 37-7 lists the additional attributes supported by polygon objects
Rectangle Items
A rectangle is specified with two coordinates that are its opposite corners. A rectangle can have a fill color and an outline color. If you do not specify a fill, then the background of the canvas (or other objects) shows through. If you stipple the fill, the background also shows through the clear bits of the stipple pattern. You must use a second rectangle if you want the stippled fill to completely hide what is behind it. Example 37-11 drags out a box as the user drags the mouse. All it requires is remembering the last rectangle drawn so that it can be deleted when the next box is drawn:
global box catch {$w delete $box($w,last)} set box($w,last) [eval {$w create rect} $box($w,anchor) \ {$x $y -tag box}] }
The example uses box($w,anchor) to record the start of the box. This is a list with the X and Y coordinates. The eval command is used so that this list can be spliced into the create rect command. Note that as of Tk 8.3 this would not be necessary as the create rect command can now accept a list of coordinates as a single argument. A rectangle object support all of the object attributes listed in Table 37-1. There are no additional attributes supported by rectangle objects.
Text Items
The canvas text item provides yet another way to display and edit text. It supports selection, editing, and it can extend onto multiple lines. The position of a text item is specified by one set of coordinates and an anchor position. The size of the text is determined by the number of lines and the length of each line. A new line is started if there is a newline in the text string. If a width is specified, in screen units, then any line that is longer than this is wrapped onto multiple lines. The wrap occurs before a space character. The editing and selection operations for text items use indices to specify positions within a given text item. These are very similar to those used in the entry widget. Table 37-8 summarizes the indices for canvas text items.
sel.first Index of the first character in the selection. sel.last @x,y Index of the last character in the selection. Index of the character under the specified X and Y coordinate.
There are several canvas operations that manipulate text items. These are similar to some of the operations of the entry widget. The dchars and select to operations treat the second index differently than the corresponding operations in the entry and text widget. The character at the second index is included in the operation (e.g., deleted), while in the entry and text widget it is not. The canvas text operations are parameterized by the tag or ID of the canvas object being manipulated. If the tag refers to more than one object, then the operations apply to the first object in the display list that supports an insert cursor. The display list is described on page 581. Table 37-9 summarizes the operations on text items. In the table $t is a text item or tag
and $c is a canvas.
UNREGISTERED VERSION OFReturns thePDF CONVERTER By THETA-SOFTWARE CHM TO numerical value of index. $c index $t index
$c insert $t index string Inserts the string just before index.
$c select adjust $t Moves the boundary of an existing selection. index $c select clear $c select from $t index $c select item $c select to $t index Clears the selection. Starts a selection. Returns the ID of the selected item, if any. Extends the selection to the specified index.
There are no default bindings for canvas text items. Example 37-12 sets up some basic bindings for canvas text items. The <Button-1> and <Button-2> bindings are on the canvas as a whole. The rest of the bindings are on items with the text tag. You must add the text tag to text items that should share the editable text behavior. Small procedures are introduced for each binding to hide the details and any local variables needed in the operations.
The CanvasFocus procedure uses the canvas find overlapping operation to see if a text object has been clicked. This must be used because find closest finds an object no matter how far away it is. It also uses the type operation to make sure only text objects are given the focus. If you want other object types to respond to key events, you should change that. The CanvasPaste procedure does one of two things. It pastes the selection into the canvas item that has the focus. If no item has the focus, then a new text item is created with the selection as its value:
proc Canvas_EditBind { c } { bind $c <Button-1> \ {CanvasFocus %W [%W canvasx %x] [%W canvasy %y]} bind $c <Button-2> \ {CanvasPaste %W [%W canvasx %x] [%W canvasy %y]} bind $c <<Cut>> {CanvasTextCopy %W; CanvasDelete %W} bind $c <<Copy>> {CanvasTextCopy %W} bind $c <<Paste>> {CanvasPaste %W} $c bind text <Button-1> \ {CanvasTextHit %W [%W canvasx %x] [%W canvasy %y]} $c bind text <B1-Motion> \ {CanvasTextDrag %W [%W canvasx %x] [%W canvasy %y]} $c bind text <Delete> {CanvasDelete %W} $c bind text <Control-d> {CanvasDelChar %W} $c bind text <Control-h> {CanvasBackSpace %W} $c bind text <BackSpace> {CanvasBackSpace %W} $c bind text <Control-Delete> {CanvasErase %W} $c bind text <Return> {CanvasNewline %W} $c bind text <Any-Key> {CanvasInsert %W %A} $c bind text <Key-Right> {CanvasMoveRight %W} $c bind text <Control-f> {CanvasMoveRight %W} $c bind text <Key-Left> {CanvasMoveLeft %W} $c bind text <Control-b> {CanvasMoveLeft %W} } proc CanvasFocus {c x y} { focus $c set id [$c find overlapping [expr $x-2] [expr $y-2] \ [expr $x+2] [expr $y+2]] if {($id == {}) || ([$c type $id] != "text")} { set t [$c create text $x $y -text "" \ -tags text -anchor nw] $c focus $t $c select clear $c icursor $t 0 } } proc CanvasTextHit {c x y {select 1}} { $c focus current $c icursor current @$x,$y $c select clear $c select from current @$x,$y } proc CanvasTextDrag {c x y} { $c select to current @$x,$y } proc CanvasDelete {c} { if {[$c select item] != {}} { $c dchars [$c select item] sel.first sel.last } elseif {[$c focus] != {}} { $c dchars [$c focus] insert } } proc CanvasTextCopy {c} { if {[$c select item] != {}} { clipboard clear
set t [$c select item] set text [$c itemcget $t -text] set start [$c index $t sel.first] set end [$c index $t sel.last] clipboard append [string range $text $start $end] } elseif {[$c focus] != {}} { clipboard clear setVERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED t [$c focus] set text [$c itemcget $t -text] clipboard append $text } } proc CanvasDelChar {c} { if {[$c focus] OF CHM UNREGISTERED VERSION != {}} { TO PDF CONVERTER By THETA-SOFTWARE $c dchars [$c focus] insert } } proc CanvasBackSpace {c} { if {[$c select item] != {}} { $c dchars [$c select item] sel.first sel.last } elseif {[$c focus] != {}} { set _t [$c focus] $c icursor $_t [expr [$c index $_t insert]-1] $c dchars $_t insert } } proc CanvasErase {c} { $c delete [$c focus] } proc CanvasNewline {c} { $c insert [$c focus] insert \n } proc CanvasInsert {c char} { $c insert [$c focus] insert $char } proc CanvasPaste {c {x {}} {y {}}} { if {[catch {selection get} _s] && [catch {selection get -selection CLIPBOARD} _s]} { return ;# No selection } set id [$c focus] if {[string length $id] == 0 } { set id [$c find withtag current] } if {[string length $id] == 0 } { # No object under the mouse if {[string length $x] == 0} { # Keyboard paste set x [expr [winfo pointerx $c] - [winfo rootx $c]] set y [expr [winfo pointery $c] - [winfo rooty $c]] } CanvasFocus $c $x $y } else { $c focus $id } $c insert [$c focus] insert $_s
} proc CanvasMoveRight {c} { $c icursor [$c focus] [expr [$c index current insert]+1] } proc CanvasMoveLeft {c} { $c icursor [$c focus] [expr [$c index current insert]-1] }
Of the attributes listed in Table 37-1, text objects support only the -fill family of attributes, the -stipple family of attributes, and the -state and -tags attributes. Table 37-10 specifies the additional attributes for text items. Note that there are no foreground and background attributes. Instead, the fill color specifies the color for the text. It is possible to stipple the text as well. Additionally, the -width attribute is treated differently than for other canvas objects.
Window Items
A window item lets you position other Tk widgets on a canvas. The position is specified by one set of coordinates and an anchor position. You can also specify the width and height, or you can let the widget determine its own size. The following example uses a canvas to provide a scrolling surface for a large set of labeled entries. A frame is created and a set of labeled entry widgets are packed into it. This main frame is put onto the canvas as a single window item. This way we let grid take care of arranging all the labeled entries. The size of the canvas is set up so that a whole number of labeled entries are displayed. The scroll region and scroll increment are set up so that clicking on the scrollbar arrows brings one new labeled entry completely into view.
set f [frame $top.buttons -bd 4] button $f.quit -text Dismiss -command "destroy $top" button $f.save -text Save button $f.reset -text Reset pack $f.quit $f.save $f.reset -side right pack $f -side top -fill x # Create a scrolling canvas UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE frame $top.c canvas $top.c.canvas -width 10 -height 10 \ -yscrollcommand [list $top.c.yscroll set] scrollbar $top.c.yscroll -orient vertical \ -command [list $top.c.canvas yview] pack $top.c.yscrollCHM TO PDF -fill y UNREGISTERED VERSION OF -side right CONVERTER By THETA-SOFTWARE pack $top.c.canvas -side left -fill both -expand true pack $top.c -side top -fill both -expand true Scrolled_EntrySet $top.c.canvas $labels } proc Scrolled_EntrySet { canvas labels } { # Create one frame to hold everything # and position it on the canvas set f [frame $canvas.f -bd 0] $canvas create window 0 0 -anchor nw -window $f # Create and grid the labeled entries set i 0 foreach label $labels { label $f.label$i -text $label entry $f.entry$i grid $f.label$i $f.entry$i grid $f.label$i -sticky w grid $f.entry$i -sticky we incr i } set child $f.entry0 # # # # # Wait for the window to become visible and then set up the scroll region based on the requested size of the frame, and set the scroll increment based on the requested height of the widgets
tkwait visibility $child set bbox [grid bbox $f 0 0] set incr [lindex $bbox 3] set width [winfo reqwidth $f] set height [winfo reqheight $f] $canvas config -scrollregion "0 0 $width $height" $canvas config -yscrollincrement $incr set max [llength $labels] if {$max > 10} { set max 10 } set height [expr $incr * $max] $canvas config -width $width -height $height
} Example3713 .ex "An example" { alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau upsilon phi chi psi omega}
The tkwait visibility command is important to the example. It causes the script to suspend execution until the top-level window, $top, is displayed on the screen. The tkwait is necessary so the right information gets returned by the grid bbox commands. By waiting for a subframe of the main frame, $child, we ensure that grid has gone through all its processing to position the interior widgets. The canvas's scroll region is set to be just large enough to hold the complete frame. The scroll increment is set to the height of one of the grid cells. Each click on the scrollbar arrows brings one new grid row completely into view. A window object supports only the -state and -tags attributes listed in Table 37-1. Table 3711 lists the additional attributes supported by window objects. Note that the -width attribute is treated differently than for other canvas objects.
-width width The width, in screen units, for the widget. If the value is an empty string (default), then the window is given whatever width it requests internally. -window name The name of the widget to display within the canvas. [ Team LiB ]
[ Team LiB ]
Canvas Operations
Table 37-12 summarizes CHM TO PDF canvas widgets. In the table, $c is a canvas. UNREGISTERED VERSION OFthe operations onCONVERTER By THETA-SOFTWARE $t represents a numerical object ID, a canvas tag or - in Tk 8.3 or later - a logical combination of tags using the operators && (and), || (or), ^ (exclusive or), ! (not), and parenthesized subexpressions, grouped as a single argument (for example, {(plot1 || plot2) && !fixed}). In some cases, an operation only applies to a single object. In these cases, if a tag or tag expression identifies several objects, the first object in the display list is operated on. The canvas display list refers to the global order among canvas objects. New objects are put at the end of the display list. Objects later in the display list obscure objects earlier in the list. The term above refers to objects later in the display list. Table 37-9 describes several of the canvas operations that only apply to text objects. They are dchars, focus, index, icursor, insert, and select. Table 37-12 does not repeat those operations.
$c addtag tag enclosed x1 y1 x2 y2 $c addtag tag overlapping x1 y1 x2 y2 $c addtag tag withtag $t $c bbox $t ?tag tag ...? $c bind $t ? sequence? ?command?
$c canvasx screenx ?grid? $c canvasy screeny ?grid? $c cget option $c configure ... $c coords $t ?x1 y1 ...?
Maps from the X screen coordinate screenx to the X coordinate in canvas space, rounded to multiples of grid if specified. Maps from screen Y to canvas Y. Returns the value of option for the canvas. Queries or updates the attributes of the canvas. Queries or modifies the coordinates of the item. As of Tk 8.3, a list of coordinates can be provided as a single argument.
$c create type x y ? Creates a canvas object of the specified type at the specified x2 y2 ...? ?opt coordinates. As of Tk 8.3, a list of coordinates can be provided as a single argument. value ...? $c delete $t ?tag ...? $c dtag $t ?deltag? $c find addtagSearch ... $c gettags $t $c itemcget $t option $c itemconfigure $t ... $c lower $t ? belowThis? $c move $t dx dy $c postscript ... $c raise $t ? aboveThis? $c scale $t x0 y0 xS yS $c scan mark x y $c scan dragto x y $c type $t $t xview Deletes the item(s) specified by the tag(s) or ID(s). Removes the specified tags from the items identified by $t. If deltag is omitted, it defaults to $t. Returns the IDs of the tags that match the addtag search specification: above, all, below, closest, enclosed, overlapping and withtag. Returns the tags associated with the first item identified by $t. Returns the value of option for item $t. Queries or reconfigures item $t. Moves the items identified by $t to the beginning of the display list, or just before belowThis. Moves $t by the specified amount. Generates Postscript. Table 37-13 lists options. Moves the items identified by $t to the end of the display list, or just after aboveThis. Scales the coordinates of the items identified by $t. The distance between x0 and a given X coordinate changes by a factor of xS. Similarly for Y. Sets a mark for a scrolling operation. Scrolls the canvas from the previous mark. Returns the type of the first item identified by $t. Returns two fractions between zero and one that describes the amount of the canvas off-screen to the left and the amount of the canvas displayed. Positions the canvas so that fraction of the scroll region is off screen to the left.
Scrolls num of what, which is units or pages. Returns two fractions between zero and one that describes the amount of the canvas off screen to the top and the amount of the canvas displayed. Positions the text so that fraction of the canvas scroll region is off Scrolls num of what, which is units or pages.
UNREGISTERED VERSION OF screen TO PDF CONVERTER By THETA-SOFTWARE CHM toward the top. fraction
$t yview scroll num what [ Team LiB ]
$t yview moveto
[ Team LiB ]
Generating Postscript
The postscript operation generates Postscript based on the contents of a canvas. One limitation in earlier versions of Tk is that images and embedded windows are not captured in the Postscript output. As of Tk 8.3, images are included in the generated Postscript. Also, as of Tk 8.3 for Unix and Tk 8.4.1 for Windows, embedded windows are included in the generated Postscript if they are currently displayed on the screen (that is, displayed within the canvas's viewport and not obscured by other windows). Table 37-13 summarizes all the options for generating Postscript.
-colormap varName -colormode mode -file name -fontmap varName -height size -pageanchor anchor -pageheight size -pagewidth size -pagex position -pagey position -rotate boolean -width size
-x position -y position
Canvas X coordinate of left edge of the image. Canvas Y coordinate of top edge of the image.
You control what region of the canvas is printed with the -width, -height, -x, and -y options. You control the size and location of this in the output with the -pageanchor, -pagex, -pagey, pagewidth, and -pageheight options. The Postscript is written to the file named by the -file option, to VERSION OF CHM TO PDF CONVERTER By identifier is provided by UNREGISTERED a channel already opened for writing whose channelTHETA-SOFTWARE the channel option, or it is returned as the value of the postscript canvas operation. You control fonts with a mapping from X screen fonts to Postscript fonts. Define an array where the index is the name of the X font and the contents are the name and pointsize of a Postscript font.
Example 37-14 positions a number of text objects with different fonts onto a canvas. For each different X font used, it records a mapping to a Postscript font. The example has a fairly simple font mapping, and in fact the canvas would probably have guessed the same font mapping itself. If you use more exotic screen fonts, you may need to help the canvas widget with an explicit font map. The example positions the output at the upper-left corner of the printed page by using the pagex, -pagey, and -pageanchor options. Recall that Postscript has its origin at the lower-left corner of the page.
set last $it } } } set fontMap(fixed) [list Courier 12] } proc Postscript { c file } { global fontMap # Tweak the output color set colorMap(blue) {0.1 0.1 0.9 setrgbcolor} set colorMap(green) {0.0 0.9 0.1 setrgbcolor} # Position the text at the upper-left corner of # an 8.5 by 11 inch sheet of paper $c postscript -fontmap fontMap -colormap colorMap \ -file $file \ -pagex 0.i -pagey 11.i -pageanchor nw }
[ Team LiB ]
[ Team LiB ]
Canvas Attributes
Table 37-14 lists the OF CHM TO PDF CONVERTER table uses the resource name, which UNREGISTERED VERSIONattributes for the canvas widget. The By THETA-SOFTWARE has capitals at internal word boundaries. In Tcl commands, the attributes are specified with a dash and are all lowercase.
Table 37-14. Canvas attribute By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTERresource names
background borderWidth closeEnough confine cursor height The normal background color. The width of the border around the canvas. Distance from mouse to an overlapping object. Boolean. True constrains the view to the scroll region. Cursor to display when mouse is over the widget. Height, in screen units, of canvas display.
highlightBackground Focus highlight color when widget does not have focus. highlightColor highlightThickness insertBackground insertBorderwidth insertOffTime insertOnTime insertWidth relief scrollRegion selectBackground selectForeground selectBorderWidth state takeFocus width xScrollCommand xScrollIncrement yScrollCommand Color for input focus highlight border. Width of highlight border. Background for area covered by insert cursor. Width of cursor border. Nonzero for 3D effect. Time, in milliseconds the insert cursor blinks off. Time, in milliseconds the insert cursor blinks on. Width of insert cursor. Default is 2. flat, sunken, raised, groove, solid, or ridge. Left, top, right, and bottom coordinates of the canvas. Background color of selection. Foreground color of selection. Width of selection border. Nonzero for 3D effect. The default state for canvas objects: normal or disabled. (Tk 8.3) Controls focus changes from keyboard traversal. Width in screen units for viewable area. Tcl command prefix for horizontal scrolling. Distance for one scrolling unit in the X direction. Tcl command prefix for vertical scrolling.
The scroll region of a canvas defines the boundaries of the canvas coordinate space. It is specified as four coordinates, x1 y1 x2 y2 where (x1, y1) is the top-left corner and (x2, y2) is the lower-right corner. If the confine attribute is true, then the canvas cannot be scrolled
yScrollIncrement
The scroll region of a canvas defines the boundaries of the canvas coordinate space. It is specified as four coordinates, x1 y1 x2 y2 where (x1, y1) is the top-left corner and (x2, y2) is the lower-right corner. If the confine attribute is true, then the canvas cannot be scrolled outside this region. It is OK to position canvas objects partially or totally off the scroll region; they just may not be visible. The scroll increment attributes determine how much the canvas is scrolled when the user clicks on the arrows in the scrollbar. The closeEnough attribute indicates how far away a position can be from an object and still be considered to overlap it. This applies to the overlapping search criteria.
[ Team LiB ]
[ Team LiB ]
Hints
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Resources
There is no resource database support built into the canvas and its items. You can, however, define resources and query them yourself. For example, you could define:
*Canvas.foreground:
blue
This would have no effect by default. However, your code could look for this resource with option get, and specify this color directly for the -fill attribute of your objects:
The main reason to take this approach is to let your users customize the appearance of canvas objects without changing your code.
[ Team LiB ]
Part V: Tk Details
UNREGISTERED V describes the rest of TO PDF CONVERTER By THETA-SOFTWARE Part VERSION OF CHM the Tk toolkit.
Chapter 38 describes the selection mechanism that is used for cut and paste between applications. It includes an example that implements cut and paste of graphical objects on a canvas. Chapter 39 describes dialogs. Tk has several built-in By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER dialogs that use the native platform look and feel. The chapter also describes how to build your own dialogs. Chapter 40 is the first of three chapters that explain widget attributes in more detail. It describes size and layout attributes. Chapter 41 describes colors, images, and cursors. It explains how to use the bitmap and color photo image types. The chapter includes a complete map of the cursor font. Chapter 42 describes fonts and other text-related attributes. The extended example is a font selection application. Chapter 43 describes the Tk send command that lets you send commands among Tk applications. It also presents a socket-based alternative that can be used among applications on different hosts and with the Safe-Tcl mechanism to limit the power of remotely invoked commands. Chapter 44 explains how to interact with the window manager using the wm command. The chapter describes all the information available through the winfo command. Chapter 45 builds upon Chapter 31 to create a user preferences package and an associated user interface. The preference package links a Tcl variable used in your application to a resource specification. Chapter 46 presents a user interface to the binding mechanism. You can browse and edit bindings for widgets and classes with the interface. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDFCLIPBOARD. The CLIPBOARD selection is used for copy are identified by names like PRIMARY and CONVERTER By THETA-SOFTWARE
and paste as in Macintosh and Windows. The PRIMARY selection is described later. You could use other selection names, like SECONDARY or FOOBAR, but that only works if the other applications know about that selection name. The selection data has both a type and a format. These are described briefly later. Data is not copied into a selection. Instead, an application asserts ownership of a selection, and other applications request the value of the selection from that owner. This model is used on all platforms. The window system keeps track of ownership, and applications are informed when some other application takes away ownership. Several of the Tk widgets implement selections and take care of asserting ownership and returning its value. The X PRIMARY selection is used in a way that eliminates the explicit copy step in copy and paste user actions. Whenever you select an object in your application, your application automatically puts that value into the PRIMARY selection. The Tk entry, listbox, and text widgets do this with their text selections, although you can turn this off with the exportSelection widget attribute. Users typically insert the value of the PRIMARY selection by clicking with the middle mouse button. There is only one instance of the PRIMARY selection across all widgets and all applications. If the user makes a new selection it automatically overwrites the previous value of the PRIMARY selection.
If you want a mechanism that works on all platforms, use the CLIPBOARD selection. The PRIMARY selection is implemented by Tk on all platforms, and you can use it within an application, but on Windows and Macintosh the non-Tk applications do not know about the PRIMARY selection. The main goal of copy and paste is to provide general interoperability among all applications, so stick with the CLIPBOARD. Tk 3.6 and earlier only supported the PRIMARY selection. When Tk 4.0 added support for the CLIPBOARD, I tried to merge the two selections to "simplify" things for my users. Example 38-1 implements a Paste function that inserts either the PRIMARY or CLIPBOARD selection into a text widget. The selection get command is used to retrieve the selection value:
proc Paste { text } { if [catch {selection get} sel] { if [catch {selection get -selection CLIPBOARD} sel] { # no selection or clipboard data return } } $text insert insert $sel }
This Paste function can be convenient, but it turns out that users still need to keep track of the difference between the two selections. If a user only understands the CLIPBOARD, then the use of PRIMARY is only surprising. I learned that it is best to have a separate paste user action for the two selections. The convention is that <ButtonRelease-2> sets the insert point and inserts the PRIMARY selection. (This convention is awkward with the one- and two-button mice on Macintosh and Windows.) The <<Paste>> event (e.g., the Paste key) simply inserts the CLIPBOARD selection at the current insert point. This convention is shown in Example 38-2, although these bindings are defined automatically for the text and entry widgets:
[ Team LiB ]
[ Team LiB ]
The selection command exposes the fully general selection model of different selections, types, and formats. You can define selection handlers that return selection values, and UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE you can assert ownership of a selection and find out when you lose ownership to another application. Example 38-5 on page 596 shows a selection handler for a canvas. A selection can have a type. The default is STRING. The type is different than the name of the selection (e.g., PRIMARY or CLIPBOARD). Each type can have a format, and the default format is STRING. Ordinarily these defaults are fine. If you are dealing with non-Tk applications, however, you may need to ask for their selections by the right type (e.g., FILE_NAME). Formats include UTF8_STRING, STRING, ATOM, and INTEGER. An ATOM is a name that is registered with the X server and identified by number. "Atoms and IDs" on page 667 describes Tk commands for manipulating atoms. It is probably not a good idea to use non-STRING types and formats because it limits what other applications can use the information. The details about X selection types and formats are specified in the Inter-Client Communication Conventions Manual (David Rosenthal, Stuart Marks, X Consortium Standard). This is distributed with the X11 sources and can be found on the web at http://tronche.com/gui/x/icccm/. All of the selection operations take a -selection option that specifies the name of the selection being manipulated. This defaults to PRIMARY. Some of the operations take a displayof option that specifies what display the selection is on. The value for this option is a Tk pathname of a window, and the selection on that window's display is manipulated. This is useful in X where applications can have their windows on remote displays. The default is to manipulate the selection on the display of the main window. Table 38-1 summarizes the selection command:
selection clear ?-displayof win? ?-selection sel? selection get ?-displayof win? ?selection sel? ?-type type? selection handle ?-selection sel? ?-type type? ?-format format? window command selection own ?-displayof window? ?-selection sel? selection own ?-command command? ?-selection sel? window
Clears the specified selection. Returns the specified selection. The type defaults to STRING. Defines command to be the handler for selection requests when window owns the selection. Returns the Tk pathname of the window that owns the selection, if it is in this application. Asserts that window owns the sel selection. The command is called when ownership of the selection is taken away from window.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Selection Handlers
The selection handle command registers a Tcl command to handle selection requests. The command is called to return the value of the selection to a requesting application. If the selection value is large, the command might be called several times to return the selection in pieces. The command gets two parameters that indicate the offset within the selection to start returning data, and the maximum number of bytes to return. If the command returns fewer than that many bytes, the selection request is assumed to be completed. Otherwise, the command is called again to get the rest of the data, and the offset parameter is adjusted accordingly. You can also get a callback when you lose ownership of the selection. At that time it is appropriate to unhighlight the selected object in your interface. The selection own command sets ownership and registers a callback for when you lose ownership.
The CanvasSelect procedure selects an object. It uses the find closest canvas operation to find out what object is under the mouse, which works because the binding is on canvas items with the object tag. If the binding were on the canvas as a whole, you would use the find overlapping operation to limit selection to objects near the mouse click. The CanvasHighlight procedure is used to highlight the selected object. It displays small boxes at the corners of the object's bounding box. Finally, the CanvasSelectLose procedure is registered to be called when another application asserts ownership of the PRIMARY selection.
Once you claim ownership, Tk calls back to the CanvasSelectHandle procedure when another application, even yours, requests the selection. This uses CanvasDescription to compute a description of the canvas object. It uses canvas operations to query the object's configuration and store that as a command that will create the object:
# be used to recreate it later. set type [$w type $id] set coords [$w coords $id] set config {} # Bundle up non-default configuration settings foreach conf [$w itemconfigure $id] { # itemconfigure returns a list like # -fill {} {} {} red set default [lindex $conf 3] set value [lindex $conf 4] if {[string compare $default $value] != 0} { lappend config [lindex $conf 0] $value } } return [concat CanvasObject $type $coords $config] }
The CanvasCopy procedure puts the description of the selected item onto the clipboard with the clipboard append command. The CanvasDelete deletes an object and the highlighting, and CanvasCut is built from CanvasCopy and CanvasDelete:
The CanvasPaste operation gets the value from the CLIPBOARD selection. The selection value has all the parameters needed for a canvas create operation. It gets the position of the new object from the <Button-2> event, or from the current mouse position if the <<Paste>> event is generated. If the mouse is out of the window, then the object is just put into the middle of the canvas. The original position and the new position are used to compute values for a canvas move:
proc CanvasPaste { w {x {}} {y {}}} { # Paste the selection from the CLIPBOARD if [catch {selection get -selection CLIPBOARD} sel] { # no clipboard data return } if {[string length $x] == 0} { UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE # <<Paste>>, get the current mouse coordinates set x [expr [winfo pointerx $w] - [winfo rootx $w]] set y [expr [winfo pointery $w] - [winfo rooty $w]] if {$x < 0 || $y < 0 || $x > [winfo width $w] || $y > OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION [winfo height $w]} { # Mouse outside the window - center object set x [expr [winfo width $w]/2] set y [expr [winfo height $w]/2] } } if [regexp {^CanvasObject} $sel] { if [catch {eval {$w create} [lrange $sel 1 end]} id] { return; } # look at the first coordinate to see where to # move the object. Element 1 is the type, the # next two are the first coordinate set x1 [lindex $sel 2] set y1 [lindex $sel 3] $w move $id [expr $x-$x1] [expr $y-$y1] } }
There is more you can do for a drawing program, of course. You'd like to be able to select multiple objects, create new ones, and more. The ImPress application by Christopher Cox is a full-featured page layout application based on the Tk canvas. You can find it on the Web at: http://www.ntlug.org/~ccox/impress/ [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Standard Dialogs
UNREGISTERED VERSION OF presents aPDF CONVERTER By THETA-SOFTWARE which CHM TO choice of buttons and returns a number indicating The tk_dialog command
one was clicked by the user. The general form of the command is:
Message Box
The tk_messageBox dialog is a limited form of tk_dialog that has native implementations on the different platforms. Like tk_dialog, it allows for a message, bitmap, and a set of buttons. However, the button sets are predefined, and the bitmaps are limited. The yesno button set, for example, displays a Yes and a No button. The abortretryignore button set displays Abort, Retry, and Ignore buttons. The tk_messageBox command returns the symbolic name of the selected button (e.g., yes or retry.) The yesnocancel message box could be used when trying to quit with unsaved changes:
set choice [tk_messageBox -type yesnocancel -default yes \ -message "Save changes before quitting?" \ -icon question]
-default name -icon name -message string -parent window -title title -type type
Default button name (e.g., yes) Name: error, info, question, or warning. Message to display. Embeds dialog in window. Dialog title (UNIX and Windows) Type: abortretrycancel, ok, okcancel, retrycancel, yesno, or yesnocancel
-initialdir dir
-multiple
-title string
The file dialogs can include a listbox that lists different file types. The file types are used to limit the directory listing to match only those types. The typelist option specifies a set of file extensions and Macintosh file types that correspond to a named file type. If you do not specify
a typelist, users just see all the files in a directory. Each item in typelist is itself a list of three values:
The name UNREGISTEREDis displayed in the list of file types. The extensions is a list of file extensions VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
corresponding to that type. The empty extension "" matches files without an extension, and the extension * matches all files. The mactypes is an optional list of four-character Macintosh file types, which are ignored on other platforms. On the Macintosh, if you give both extensions and mactypes, the files must match both. If the extensions is an empty list, only the mactypes are considered. However, you can repeat name in the typelist and give extensions in one set and mactypes CHM TO PDF you do this, then files that match either the UNREGISTERED VERSION OFin another set. If CONVERTER By THETA-SOFTWARE extensions or mactypes are listed. The following typelist matches Framemaker Interchange Files that have both a .mif extension and a MIF type:
The following typelist matches GIF image files that have either a .gif extension or the GIFF file type. Note that the mactypes are optional:
The following typelist puts all these together, along with an entry for all files. The entry that comes first is displayed first:
set typelist { {"All Files" {*}} {"GIF Image" {".gif"}} {"GIF Image" {} {"GIFF"}} {"Maker Interchange Files" {".mif"} {"MIF "}} }
Color Dialog
The tk_chooseColor dialog displays a color selection dialog. It returns a color, or the empty string if the user cancels the operation. The options to tk_chooseColor are listed in Table 393:
[ Team LiB ]
Custom Dialogs
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
When you create your own dialogs, you need to understand keyboard focus, focus grabs, and how to wait for the user to finish with a dialog. Here is the general structure of your code when creating a dialog:
This sequence of commands directs keyboard focus to the toplevel containing your dialog. The grab forces the user to interact with the dialog before using other windows in your application. The tkwait command returns when the toplevel window is destroyed, and this automatically releases the grab. This assumes that the button commands in the dialog destroy the toplevel. The following sections explain these steps in more detail, and Example 39-1 on page 606 illustrates a more robust sequence.
Input Focus
The window system directs keyboard events to the toplevel window that currently has the input focus. The application, in turn, directs the keyboard events to one of the widgets within that toplevel window. The focus command sets focus to a particular widget, and it is used by the default bindings for Tk widgets. Tk remembers what widget has focus within a toplevel window and automatically gives focus to that widget when the system gives focus to a toplevel window. On Windows and Macintosh, the focus is given to an application when you click in its window. On UNIX, the window manager application gives focus to different windows, and window managers allow different conventions to shift focus. The click-to-type model is similar to Windows and Macintosh. There is also focus-follows-mouse, which gives focus to the window under the mouse. One thing to note about click-to-type is that the application does not see the mouse click that gives the window focus. Once the application has focus, you can manage the focus changes among your widgets any way you like. By default, Tk uses a click-to-type model. Text and entry widgets set focus to themselves when you click on them with the left mouse button. You can get the focus-followsmouse model within your widgets by calling the tk_focusFollowsMouse procedure. However, in many cases you will find that an explicit focus model is actually more convenient for users. Carefully positioning the mouse over a small widget can be tedious.
multiple displays. The -displayof option can be used to query the focus on a particular display. The -lastfor option finds out what widget last had the focus within the same toplevel as another window. Tk will restore focus to that window if the widget that has the focus is destroyed. The toplevel widget gets the focus if no widget claims it.
bind all <Tab> {tk_focusNext %W} bind all <Shift-Tab> {tk_focusPrev %W}
The Tk widgets highlight themselves when they have the focus. The highlight size is controlled with the highlightThickness attribute, and the color of the highlight is set with the highlightColor attribute. The Tk widgets, even buttons and scrollbars, have bindings that support keyboard interaction. A <space> invokes the command associated with a button, if the button has the input focus. All widgets have a takeFocus attribute that the tk_focusNext and tk_focusPrev procedures use to determine if a widget will take the focus during keyboard traversal. There are four possible values to the attribute: 0 indicates the widget should not take focus. 1 indicates the widget should always take focus. An empty string means the traversal procedures tk_focusNext and tk_focusPrev should decide based on the widget's state and bindings. Otherwise the value is a Tcl command prefix. The command is called with the widget name as an argument, and it should return either 0, 1, or the empty string.
Table 39-5. The grab command UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
grab ?-global? window grab current ? window? grab release window grab set ?-global? win grab status window Sets a grab to a particular window. Queries the grabs on the display of window, or on all displays if window is omitted. Releases a grab on window. Sets a grab to a particular window. Returns none, local, or global.
A global grab prevents the user from interacting with other applications, too, even the window manager. Tk menus use a global grab, for example, which is how they unpost themselves no matter where you click the mouse. When an application prompts for a password, a global grab is also a good idea. This prevents the user from accidentally typing their password into a random window. The next section includes examples that use the grab command.
The variable specified in the tkwait variable command must be a global variable. Remember this if you use procedures to modify the variable. They must declare it global or the tkwait command will not notice the assignments. The tkwait visibility waits for the visibility state of the window to change. Most commonly this is used to wait for a newly created window to become visible. For example, if you have any sort of animation in a complex dialog, you could wait until the dialog is displayed before starting the animation.
Destroying Widgets
The destroy command deletes one or more widgets. If the widget has children, all the children are destroyed, too. Chapter 44 describes a protocol on page 661 to handle destroy events that come from the window manager. You wait for a window to be deleted with the tkwait window command.
The focus,
grab, tkwait
sequence
In practice, I use a slightly more complex command sequence than just focus, grab, and tkwait. You can remember what widget used to have the focus and then restore it after the dialog completes. When you do this, it is more reliable to restore focus before destroying the dialog. This prevents a tug of war between your application and the window manager. This sequence looks like:
set old [focus] focus $toplevel grab $toplevel tkwait variable doneVar grab release $toplevel focus $old destroy $toplevel
This sequence supports another trick I use, which is to unmap dialogs instead of destroying them. This way the dialogs appear more quickly the next time they are used. This makes creating the dialogs a little more complex because you need to see if the toplevel already exists. Chapter 44 describes the window manager commands used to map and unmap windows on page 661. Example 39-1 shows Dialog_Create, Dialog_Wait, and Dialog_Dismiss that capture all of these tricks:
proc Dialog_Create {top title args} { global dialog if [winfo exists $top] { switch -- [wm state $top] { normal { # Raise a buried window raise $top } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE withdrawn iconic { # Open and restore geometry wm deiconify $top catch {wm geometry $top $dialog(geo,$top)} } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE } return 0 } else { eval {toplevel $top} $args wm title $top $title return 1 } } proc Dialog_Wait {top varName {focus {}}} { upvar $varName var # Poke the variable if the user nukes the window bind $top <Destroy> [list set $varName cancel] # Grab focus for the dialog if {[string length $focus] == 0} { set focus $top } set old [focus -displayof $top] focus $focus catch {tkwait visibility $top} catch {grab $top} # Wait for the dialog to complete tkwait variable $varName catch {grab release $top} focus $old } proc Dialog_Dismiss {top} { global dialog # Save current size and position catch { # window may have been deleted set dialog(geo,$top) [wm geometry $top] wm withdraw $top } }
The Dialog_Wait procedure allows a different focus widget than the toplevel. The idea is that you can start the focus out in the appropriate widget within the dialog, such as the first entry widget. Otherwise, the user has to click in the dialog first.
The catch statements in Dialog_Wait come from my experiences on different platforms. The tkwait visibility is sometimes required because grab can fail if the dialog is not yet visible. However, on other systems, the tkwait visi bility itself can fail in some circumstances. Tk reflects these errors, but in this case all that can go wrong is no grab. The user can still interact with the dialog without a grab, so I just ignore these errors.
Prompter Dialog
Example 39-2 A simple dialog
proc Dialog_Prompt { string } { global prompt set f .prompt if [Dialog_Create $f "Prompt" -borderwidth 10] { message $f.msg -text $string -aspect 1000 entry $f.entry -textvariable prompt(result) set b [frame $f.buttons] pack $f.msg $f.entry $f.buttons -side top -fill x pack $f.entry -pady 5 button $b.ok -text OK -command {set prompt(ok) 1} button $b.cancel -text Cancel \ -command {set prompt(ok) 0} pack $b.ok -side left pack $b.cancel -side right bind $f.entry <Return> {set prompt(ok) 1 ; break} bind $f.entry <Control-c> {set prompt(ok) 0 ; break} } set prompt(ok) 0 Dialog_Wait $f prompt(ok) $f.entry Dialog_Dismiss $f if {$prompt(ok)} { return $prompt(result) } else {
Example 39-2 shows Dialog_Prompt, which gets a value from the user, returning the value entered, or the empty string if the user cancels the operation. Dialog_Prompt uses the Tcl UNREGISTERED VERSIONto indicate the dialog CONVERTER By THETA-SOFTWARE presses OF CHM TO PDF is complete. The variable is set if the user variable prompt(ok) the OK or Cancel buttons, or if the user presses <Return> or <Control-c> in the entry widget. The Dialog_Wait procedure waits on prompt(ok), and it grabs and restores focus. If the Dialog_Create procedure returns 1, then the dialog is built: otherwise, it already existed.
Focus is set on the entry widget in the dialog with Dialog_Wait, and it is convenient if users can use special key bindings to complete the dialog. Otherwise, they need to take their hands off the keyboard and use the mouse. The example defines bindings for <Return> and <Control-c> that invoke the OK and Cancel buttons, respectively. The bindings override all other bindings by including a break command. Otherwise, the Entry class bindings insert the short-cut keystroke into the entry widget. [ Team LiB ]
[ Team LiB ]
update
Command
Suppose you want to entertain your user while your application is busy. By default, the user interface hangs until your processing completes. Even if you change a label or entry widget in the middle of processing, the updates to that widget are deferred until an idle moment. The user does not see your feedback, and the window is not refreshed if it gets obscured and uncovered. The solution is to use the update command that forces Tk to go through its event loop and update the display. The next example shows a Feedback procedure that displays status messages. A read-only entry widget displays the messages, and the update command ensures that the user sees each new message. An entry widget is used because it won't change size based on the message length, and it can be scrolled by dragging with the middle mouse button. Entry widgets also work better with update idletasks as described later:
The Tk widgets update their display at idle moments, which basically means after everything else is taken care of. This lets them collapse updates into one interaction with the window system. On UNIX, this improves the batching effects that are part of the X protocol. A call to update idletasks causes any pending display updates to be processed. Chapter 16 describes the Tk event loop in more detail.
The safest way to use update is with its idletasks option. If you use the update command with no options, then all events are processed. In particular, user input events are processed. If you are not careful, it can have unexpected effects because another thread of execution is launched into your Tcl interpreter. The current thread is suspended and any callbacks that result from input events are executed. It is usually better to use the tkwait command if you
need to process input because it pauses the main application at a well-defined point. One drawback of update idletasks is that in some cases a widget's redisplay is triggered by window system events. In particular, when you change the text of a label, it can cause the size of the label to change. The widget is too clever for us in this case. Instead of scheduling a redisplay at idle time, it requests a different size and then waits for the <Configure> event from the window system. The <Configure> event indicates a size has been chosen by the geometry and is at the schedules its redisplay. So, changing UNREGISTERED manager,doingitupdateTO point thatdoeslabelwork as expected. VERSION OF CHMthat PDF CONVERTER By THETA-SOFTWARE the label's text and idletasks not [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Configuring Attributes
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
You specify attributes for Tk widgets when you create them. You can also change them dynamically at any time after that. In both cases the syntax uses pairs of arguments. The first item in the pair identifies the attribute, the second provides the value. For example, a button can be created like this:
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE button .doit -text Doit -command DoSomething
The name of the button is .doit, and two attributes are specified: the text and the command. You can change the .doit button later with the configure widget operation:
The current configuration of a widget can be queried with another form of the configure operation. If you just supply an attribute, the settings associated with that attribute are returned:
This command returns several pieces of information: the command line switch, the resource name, the resource class, the default value, and the current value. If you don't give any options to configure, then the configuration information for all the attributes is returned. The following loop formats the information:
foreach item [$w configure] { puts "[lindex $item 0] [lindex $item 4]" }
If you just want the current value, use the cget operation:
You can also configure widget attributes indirectly by using the resource database. An advantage of using the resource database is that users can reconfigure your application without touching the code. Otherwise, if you specify attribute values explicitly in the code, they cannot be overridden by resource settings. This is especially important for attributes like fonts and colors.
The tables in this chapter list the attributes by their resource name, which may have a capital letter at an internal word boundary (e.g., activeBackground). When you specify attributes in a Tcl command, use all lowercase instead, plus a leading dash. Compare:
The first command defines a resource that affects all buttons created after that point, and the second command changes an existing button. Command-line settings override resource database specifications. Chapter 31 describes the use of resources in detail. [ Team LiB ]
[ Team LiB ]
Size
Most widgets have a OF CHM TO PDF CONVERTER By their desired size, although UNREGISTERED VERSIONwidth and height attribute that specifiesTHETA-SOFTWARE there are some special cases. For most widgets, if an explicit size isn't specified, or the size provided is 0 or less, then the widget automatically sizes itself to be just large enough to display its contents. As of Tk 8.4, on Windows, the width attribute for simple button widgets (not checkbuttons, radiobuttons, or menubuttons) accepts a negative value to specify a minimum width, enabling better compliance with native Windows look-and-feel. In all cases, the geometry VERSION a widget TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED manager forOF CHM might modify the size to some degree. The winfo operations described on page 659 return the current size of a widget. Most of the text-related widgets interpret their sizes in units of characters for width and lines for height. All other widgets, including the message widget, interpret their dimensions in screen units, which are pixels by default. The tk scale command, which is described on page 669, controls the scale between pixels and the other measures. You can suffix the dimension with a unit specifier to get a particular measurement unit:
c i m p
Scales and scrollbars can have two orientations as specified by the orient attribute, so width and height are somewhat ambiguous. These widgets do not support a height attribute, and they interpret their width attribute to mean the size of their narrow dimension. The scale has a length attribute that determines its long dimension. Scrollbars do not even have a length. Instead, a scrollbar is assumed to be packed next to the widget it controls, and the fill packing attribute is used to extend the scrollbar to match the length of its adjacent widget. Example 33-1 on page 500 shows how to arrange scrollbars with another widget. The message widget displays a fixed string on multiple lines, and it uses one of two attributes to constrain its size: its aspect or its width. The aspect ratio is defined to be 100*width/height, and it formats its text to honor this constraint. However, if a width is specified, it just uses that and uses as many lines (i.e., as much height) as needed. Example 32-6 on page 493 shows how message widgets display text. Table 40-1 summarizes the attributes used to specify the size for widgets:
aspect The aspect ratio of a message widget, which is 100 times the ratio of width divided by height. height Height, in text lines or screen units. Widgets: button, canvas, checkbutton, frame, label, labelframe, listbox, menubutton, panedwindow, radiobutton, text, and toplevel. length The long dimension of a scale. orient Orientation for long and narrow widgets, or arrangement of panes in a panedwindow: horizontal or vertical. Widgets: panedwindow, scale, and scrollbar. width Width, in characters or screen units. Widgets: button, canvas, checkbutton, entry, frame, label, labelframe, listbox, menubutton, message, panedwindow, radiobutton, scale, scrollbar, spinbox, text, and toplevel.
It is somewhat unfortunate that text-oriented widgets only take character- and line-oriented dimensions. These sizes change with the font used, and if you want a precise size you might be frustrated. Both pack and grid let the widgets decide how big to be. One trick is to put each widget, such as a label, in its own frame. Specify the size you want for the frame, and then pack the label and turn off size propagation. For example:
proc EqualSizedLabels { parent width height strings args } { set l 0 foreach s $strings { frame $parent.$l -width $width -height $height pack propagate $parent.$l false pack $parent.$l -side left eval {label $parent.$l.l -text $s} $args pack $parent.$l.l -fill both -expand true incr l } } frame .f ; pack .f EqualSizedLabels .f 1i 1c {apple orange strawberry kiwi} \ -relief raised
The frames $parent.$l are all created with the same size. The pack propagate command prevents these frames from changing size when the labels are packed into them later. The labels are packed with fill and expand turned on so that they fill up the fixed-sized frames around them. Another way to get equal sized widgets is with the -uniform column configuration that was added to grid in Tk 8.4. This is described on page 418. [ Team LiB ]
[ Team LiB ]
frame .f -borderwidth 10 pack .f foreach relief {raised sunken flat ridge groove solid} { label .f.$relief -text $relief -relief $relief \ -bd 2 -padx 3 pack .f.$relief -side left -padx 4 }
The three-dimensional appearance of widgets is determined by two attributes: borderWidth and relief. The borderWidth adds extra space around the edge of a widget's display, and this area can be displayed in a number of ways according to the relief attribute. The solid relief was added in Tk 8.0 to support the Macintosh look for entry widget, and it works well against white backgrounds. Macintosh buttons do not support different reliefs or honor border width. The activeBorderWidth attribute defines the border width for the menu entries. The relief of a menu is not configurable. It probably is not worth adjusting the menu border width attributes because the default looks OK. The native menus on Windows and Macintosh do not honor this attribute. The activeRelief attribute applies to the elements of a scrollbar (the elevator and two arrows) when the mouse is over them. The elementBorderWidth sets the size of the relief on these elements. Changing the activeRelief does not look good. The native scrollbars on Macintosh and Windows do not honor this attribute. The offRelief and overRelief attributes describe a relief style to use when a widget is in the "off state" and its indicator is not drawn, or the mouse cursor is over the widget. They were added in Tk 8.4 to provide better support for creating toolbars. The overRelief attribute applies to buttons, checkbuttons, and radiobuttons. The offRelief attribute applies only to checkbuttons and radiobuttons. Table 40-2 lists the attributes for borders and relief.
The border width for menu entries. UNIX only. The relief for active scrollbar elements. UNIX only. The width of the border around a widget, in screen units. All widgets Short for borderwidth. Tcl commands only.
elementBorderWidth The width of the border on scrollbar and scale elements. offRelief overRelief relief Alternate relief style when the widget is deselected. Widgets: checkbutton and radiobutton. (Tk 8.4) Alternate relief style when mouse is over the widget. Widgets: button, checkbutton, and radiobutton. (Tk 8.4) The appearance of the border: flat, raised, sunken, ridge, groove, or solid. All widgets.
[ Team LiB ]
[ Team LiB ]
highlightBackground The highlight color when the widget does not have focus. highlightThickness [ Team LiB ] The width of the highlight border.
[ Team LiB ]
The anchor attribute only affects the display if there is extra room for another reason. One way to get extra room is to specify a width attribute that is longer than the text. The following label has right-justified text. You can see the default padX value for labels, which is one pixel:
Another way to get extra display space is with the -ipadx and -ipady packing parameters. The example in the next section illustrates this effect. Chapter 25 has several more examples of the packing parameters.
frame .f -bg white label .f.one -text One -relief raised -bd 2 -padx 3m -pady 2m pack .f.one -side top label .f.two -text Two \ -highlightthickness 4 -highlightcolor red \ -borderwidth 5 -relief raised \ -padx 0 -pady 0 \ -width 10 -anchor nw pack .f.two -side top -pady 10 -ipady 10 -fill both focus .f.two pack .f
The number of different attributes that contribute to the size and appearance can be confusing. Example 40-5 uses a label to demonstrate the difference among size, borders, padding, and the highlight. Padding can come from the geometry manager, and it can come from widget attributes. The first label uses a raised relief, so you can see the two-pixel border. There is no highlight on a label by default. There is internal padding so that the text is spaced away from the edge of the label. The second label adds a highlight rectangle by specifying a nonzero thickness. Widgets like buttons, entries, listboxes, and text have a highlight rectangle by default. The second label's padding attributes are reduced to zero. The anchor positions the text right next to the border in the upper-left (nw) corner. Note the effect of the padding provided by the packer. There is both external and internal padding in the Y direction. The external padding (from pack -pady) results in unfilled space. The internal packing (pack -ipady) is used by the label for its display. This is different from the label's own -pady attribute, which keeps the text away from the top edge of the widget. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Colors
Table 41-1 lists the resource names PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO for color attributes. The table indicates what widgets use the different color attributes. Remember to use all lowercase and a leading dash when specifying attributes in a Tcl command.
Table 41-1. Color attribute resource names UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
background bg foreground The normal background color. All widgets. Short for background. Command line only. The normal foreground color. Widgets: button, checkbutton, entry, label, listbox, menu, menubutton, message, radiobutton, scale, spinbox, and text. Short for foreground. Command line only. The background when a mouse button will take an action. Widgets: button, checkbutton, label, menu, menubutton, radiobutton, scale, scrollbar, and spinbox. The foreground when the mouse is over an active widget. Widgets: button, checkbutton, entry, label, menu, menubutton, and radiobutton. The background when a widget is disabled. Widgets: entry and spinbox. disabledForeground The foreground when a widget is disabled. Widgets: button, checkbutton, menu, menubutton, and radiobutton. highlightBackground The highlight color when widget does not have focus. All widgets. highlightColor insertBackground readonlyBackground selectBackground selectColor selectForeground The highlight color when the widget has focus. All widgets. The color of the insert cursor. Widgets: canvas, entry, spinbox, and text. The background when a widget is in the readonly state. Widgets: entry and spinbox. The background of selected text. Widgets: canvas, entry, listbox, spinbox, and text. The color of the selector indicator. Widgets: checkbutton, menu, and radiobutton. The foreground of selected text. Widgets: canvas, entry, listbox, spinbox, and text.
fg activeBackground
activeForeground
disabledBackground
The foreground color is used to draw an element, while the background color is used for the blank area behind the element. Text, for example, is painted with the foreground color. There
troughColor
The foreground color is used to draw an element, while the background color is used for the blank area behind the element. Text, for example, is painted with the foreground color. There are several variations on foreground and background that reflect different states for widgets or items they are displaying. Each attribute also has a resource class. This is most useful for the variations on foreground and background colors. For example, Tk does not have a reverse video mode. However, with a couple of resource specifications you can convert a monochrome display into reverse video. The definitions are given in Example 41-1. The Foreground and Background resource class names are used, and the various foreground and background colors (e.g., activeBackground) have the correct resource class so these settings work. You have to set these resources before you create any widgets:
Color Palettes
The tk_setPalette command changes colors of existing widgets and installs resource values so new widgets have matching colors. If you give it a single argument, it treats this as the background and then computes new values for the other color resources. For example, if you do not like the standard Tk grey, you can lighten your spirits with a cool blue background:
tk_setPalette #0088cc
If you liked the light brown color scheme of Tk 3.6, you can restore that palette with the tk_bisque command:
tk_bisque
The tk_setPalette command can be used to change any of the color attributes. You can specify a set of name-value pairs, where the names are color resource names and the values are new color values:
Color Values
Color values are specified in two ways: symbolically (e.g., red), or by hexadecimal numbers (e.g., #ff0000). The leading # distinguishes the hexadecimal representation from the symbolic one. The number is divided into three equal-sized fields that give the red, green, and blue values, respectively. The fields can specify 4, 8, 12, or 16 bits of a color:
#RGB 4 bits per color #RRGGBB VERSION OFper color PDF 8 bits CHM TO UNREGISTERED #RRRGGGBBB 12 bits per color #RRRRGGGGBBBB 16 bits per color
CONVERTER By THETA-SOFTWARE
If you specify more resolution than is supported by the display, the low-order bits of each field are discarded. The different display PDF CONVERTER are described in the next section. UNREGISTERED VERSION OF CHM TOtypes supported by Tk By THETA-SOFTWARE Each field ranges from 0, which means no color, to a maximum, which is all ones in binary, or all f in hex, that means full color saturation. For example, pure red can be specified four ways:
There is a large collection of symbolic color names like "red," "blue," "green," "thistle," "medium sea green," and "yellow4." These names originate from X and UNIX, and Tk supports these colors on all platforms. As of Tk 8.3.2, these color names are documented in the colors online reference page. Prior to that, you could find the list in the Tk sources in the xlib/xcolor.c file. Or, run the xcolors program that comes with the standard X distribution. The Windows and Macintosh platforms have a small set of colors that are guaranteed to exist, and Tk defines names for these. The advantage of using these colors is that they are shared by all applications, so the system can manage colors efficiently. Table 41-2 lists the system colors on Windows. Several of these colors map to the same RGB value. Table 41-3 lists the system colors on Macintosh.
Grey text color. Selection background. Selection foreground. Window border when not activated. Caption background when not activated.
systemInactiveCaptionText Caption text when not activated. systemInfoBackground systemInfoText systemMenu systemMenuText systemScrollbar systemWindow systemWindowFrame systemWindowText Help pop-up background. Help pop-up text. Menu background. Menu foreground. Scrollbar background. Text window background. Text window frame. Text window text color.
systemMenuActiveText Selected menu item foreground. systemMenu systemMenuDisabled systemMenuText Menu background. Disabled menu item background. Menu foreground.
The winfo rgb command maps from a color name (or value) to three numbers that are its red,
green, and blue values. You can use this to compute variations on a color. The ColorDarken procedure shown below uses the winfo rgb command to get the red, green, and blue components of the input color. It reduces these amounts by 5 percent, and reconstructs the color specification using the format command.
By THETA-SOFTWARE
[ Team LiB ]
[ Team LiB ]
staticcolor Color with a fixed colormap defined by the system. pseudocolor Color values determined by single writable colormap. truecolor Color values determined by three colormaps defined by the system: one each for red, green, and blue.
directcolor Color values determined by three writable colormaps: one each for red, green, and blue. best Use the best visual for a given depth.
The frame and toplevel widgets support a colormap and visual attribute. You can query these attributes on all platforms. On Windows and Macintosh there is only one visual type at a time, and users may be able to change it for their whole system. On UNIX, the X server typically supports more than one visual class on the same display, and you can create frames and toplevels that use a particular visual class. The value of the visual attribute has two parts, a visual type and the desired depth of the display. The following example requests a greyscale visual with a depth of 4 bits per pixel:
A visual is associated with a colormap. Windows and Macintosh have a single colormap that is shared by all applications. UNIX allows for private colormaps, which can be useful if you UNREGISTERED VERSION lots of colors. However, the drawback ofTHETA-SOFTWARE OF CHM TO PDF CONVERTER By a private colormap is that the absolutely must have display flashes as the mouse enters windows with their own colormap. This is because the monitor hardware really only has one colormap, so the X server must swap colormaps. Macintosh and Windows manage their colormap more gracefully, although if you use too many colors some flashing can occur. Tk can simulate private colormaps on Windows, but it is probably better to let the system manage the colormap. Tk on the Macintosh always uses a 24UNREGISTERED VERSION which is basically unlimited colors, and lets the operating system dither bit truecolor visual, OF CHM TO PDF CONVERTER By THETA-SOFTWARE colors if necessary. By default a widget inherits the colormap and visual from its parent widget. The value of the colormap attribute can be the keyword new, in which case the frame or toplevel gets a new private colormap, or it can be the name of another widget, in which case the frame or toplevel shares the colormap of that widget. When sharing colormaps, the other widget must be on the same screen and using the same visual class. [ Team LiB ]
[ Team LiB ]
There are three things that can be displayed by labels and all the buttons: text, bitmaps, and images. If more than one of these attributes are specified, then the image has priority over the bitmap, and the bitmap has priority over the text. You can remove the image or bitmap attribute by specifying a null string for its value:
Tk 8.4 introduced the compound attribute for labels, menu entries, and the various button widgets, which specifies whether the widgets should display both an image (or bitmap) and text, and if so, where the image should be placed relative to the text. For example, the following command would cause a label to display a bitmap on the left, and text to the right:
Creates an image of the specified type. If name is not specified, one is made up. The remaining arguments depend on the type of image being created. Deletes the named image. Returns the height of the image, in pixels. by name is in use by any widgets.
UNREGISTERED VERSION OF Returns a boolean value indicating whether or not the image given CHM TO PDF CONVERTER By THETA-SOFTWARE image inuse name
image names image type name Returns the list of defined images. Returns the type of the named image.
UNREGISTERED VERSION OF Returns the list of possible image types. CHM TO PDF CONVERTER By THETA-SOFTWARE image types
image width name Returns the width of the image, in pixels.
The exact set of options for image create depend on the image type. There are two built-in image types: bitmap and photo. Chapter 48 describes the C interface for defining new image types.
Bitmap Images
A bitmap image has a main image and an optional mask image. The main image is drawn in the foreground color. The mask image is drawn in the background color, unless the corresponding bit is set in the main image. The remaining bits are "clear" and the widget's normal background color shows through. Table 41-6 lists the options supported by the bitmap image type:
The bitmap definition files are stylized C structure definitions that the Tk library parses. The files usually have a .xbm file name extension. These are generated by bitmap editors such as bitmap program, which comes with the standard X distribution. The -file and -maskfile options name a file that contains such a definition. The -data and -maskdata options specify a string in the same format as the contents of one of those files.
The label and all the button widgets also support a bitmap attribute, which is a special case of an image. This attribute is a little more convenient than the image attribute because the extra step of creating an image is not required. However, there are some power and flexibility with the image command, such as the ability to reconfigure a named image (e.g., for animation) that is not possible with a bitmap.
The @ syntax for the bitmap attribute signals that a file containing the bitmap is being specified. It is also possible to name built-in bitmaps. The predefined bitmaps are shown in the next figure along with their symbolic name. Chapter 48 describes the C interface for defining built in bitmaps.
frame .f -bd 4; frame .g -bd 4 ; pack .f .g -side left set parent .f ; set next .g foreach name {error gray12 gray50 hourglass \ info questhead question warning} { frame $parent.$name label $parent.$name.l -text $name -width 9 -anchor w label $parent.$name.b -bitmap $name pack $parent.$name.l -side right pack $parent.$name.b -side top pack $parent.$name -side top -expand true -fill x set tmp $parent ; set parent $next ; set next $tmp }
Photo Images
The photo image type was contributed to Tk by Paul Mackerras. It displays full color images and can do dithering and gamma correction. Table 41-7 lists the attributes for photo images. These are specified in the image create photo command.
-data string The contents of the photo as a base64 encoded or binary string. -file name -format format The name of the file containing a photo definition. Specifies the data format for the file or data string.
-gamma value A gamma correction factor, which must be greater than zero. A value greater
UNREGISTERED VERSION one CHM TO an image. than OF brightens PDF CONVERTER By THETA-SOFTWARE
-height value -palette spec The height, in screen units. The number of shades of gray or color for the image.
$p blank $p cget option $p configure ... $p copy source ? options? $p data ?options? $p get x y $p put data ?-to x1 y1 x2 y2? $p read file options $p redither $p tranparency get x y $p tranparency set x y boolean $p write file ? options?
Clears the image. It becomes transparent. Returns the configuration attribute option. Reconfigures the photo image attributes. Copies another image. Table 41-9 lists the copy options. Returns image data in the form of a list of rows, where each row is a list of colors in #rrggbb format. Table 41-11 lists the data options. Returns the pixel value at position x y. Inserts data into the image. data is a list of rows, where each row is a list of colors in #rrggbb format. Loads an image from a file. Table 41-10 lists the read options. Reapplies the dithering algorithm to the image. Returns a boolean indicating if the specified pixel is transparent Makes the specified pixel transparent if boolean is true, or opaque otherwise. Saves the image to file according to options. Table 41-11 lists the write options.
Table 41-9 lists the options available when you copy data from one image to another. The regions involved in the copy are specified by the upper-left and lower-right corners. If the lower-right corner of the source is not specified, then it defaults to the lower-right corner of the image. If the lower-right corner of the destination is not specified, then the size is determined by the area of the source. Otherwise, the source image may be cropped or replicated to fill the destination.
-compositingrule rule
Specifies how transparent pixels in the source image are combined with the destination image. When rule is overlay (default), the old contents of the destination image remain visible. When rule is set, the old contents of the destination image are discarded and the source image is used as-is.
-from x1 y1 ?x2 Specifies the location and area in the source image. If x2 and y2 are not y2? given, they are set CONVERTER By corner. UNREGISTERED VERSION OF CHM TO PDF to the bottom-right THETA-SOFTWARE -to x1 y1 ?x2 y2? Specifies the location and area in the destination. If x2 and y2 are not given, the size is determined by the source. The source may be cropped or tiled to fill the destination. Shrinks the destination so that its bottom right corner matches the and height have been set for the image. -zoom x ?y? Magnifies the source so each source pixel becomes a block of x by y pixels. y defaults to x if it is not specified. Reduces the source by taking every xth pixel in the X direction and every yth pixel in the Y direction. y defaults to x.
-shrink
UNREGISTERED VERSION OF CHM TOcornerCONVERTER By in. This has no effect if the width bottom right PDF of the data copied THETA-SOFTWARE
-subsample x ?y?
Table 41-10 lists the read options. If not specified, the format is determined automatically. If there are multiple image types that can read the same data, you may specify a read format
Table 41-11 lists the options used for write and data. When writing to files, the -format option is important because if you don't specify it, the first format found is used. On the other hand, you shouldn't use the -format option with data operation, as data returns the image date as a list of rows, where each row is a list of colors in #rrggbb format (suitable as input to the put command).
-background color -format format -from x1 y1 ?x2 y2? -grayscale [ Team LiB ]
If specified, all transparent pixels are replaced by the specified color. Specifies the format of the data. Specifies a subregion of the data to save. If x2 and y2 are not given, they are set to the lower-right corner. If specified, the data is transformed into grayscale.
[ Team LiB ]
[ Team LiB ]
On Unix systems, a foreground and background color for the cursor can be specified. Here are some example cursor specifications:
$w config -cursor watch ;# stop-watch cursor $w config -cursor {gumby blue} ;# blue gumby $w config -cursor {X_cursor red white} ;# red X on white
The other form for the cursor attribute specifies a file that contains the definition of the cursor bitmap. If two file names are specified, then the second specifies the cursor mask that determines what bits of the background get covered up. Bitmap editing programs like idraw and iconedit can be used to generate these files. Here are some example cursor specification using files. You need to specify a foreground color, and if you specify a mask file, then you also need to specify a background color:
$w config -cursor "@timer.xbm black" $w config -cursor "@timer.xbm timer.mask black red"
The cursors shown in Example 41-6 are available on all platforms. However, on Windows and Macintosh some of the cursors are mapped to native cursors and appear differently. On Windows the following cursors are mapped to native cursors: arrow, ibeam, icon, crosshair, fleur, sb_v_double_arrow, sb_h_double_arrow, center_ptr, watch, and xterm. These additional cursors are defined on Windows: starting, size, size_ne_sw, size_ns, size_nw_se, size_we, uparrow, and wait. On Windows, use the no cursor to eliminate the cursor. On Macintosh, the following cursors are mapped to native cursors: ibeam, xterm, cross, crosshair, plus, watch, arrow. These additional cursors are defined on Macintosh: text and cross-hair. As of Tk 8.3, when running on Windows you can also use Windows system cursors by specifying the name of the appropriate .ani or .cur file. For example:
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Naming a Font
There are VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED two basic ways to name a font. You can use predefined font names (e.g., system), or you can specify a set of font attributes with a platform-independent name:
UNREGISTERED VERSION is specified TO PDF CONVERTER By THETA-SOFTWARE family, OF CHM with a three element list. The first element is the font In this form, the font
the second is the size, in points, and the third is a list of style parameters. The family determines the basic look, such as courier or helvetica. The complete set of style parameters are normal, bold, roman, italic, underline, and overstrike. For example, to specify both bold and italic:
The font size is points, which are 1/72 inch. Tk maintains a scale factor that maps from points to pixels. The default scale is derived from the screen resolution, and you can change it with the tk scaling command, which is described on page 669. You can specify pixel-based sizes with negative numbers. The advantage of points over pixels is that text appears about the same size regardless of the screen resolution. (This works better on Windows and Macintosh than on Unix.) However, sometimes you want to control font size relative to other widget geometry, in which case pixel-based sizes are better. An alternate way to name font attributes uses name-value pairs. These are summarized in Table 42-1. The format is less compact, but it is useful for changing part of a font configuration because you do not need to specify everything. The same specification can be made like this:
label .foo -text "Hello" -font \ {-family times -size 12 -weight bold -slant italic}
-family name
The name can be times, courier, helvetica, and others returned by the font families command. The font size is given in points, which are 1/72 inch. The value is bold or normal. The value is roman or italic. If bool is true, an underline is drawn. If bool is true, an overstrike line is drawn.
-size points -weight value -slant value -underline bool -overstrike bool
Tk matches a font specification with the fonts available on your system. It will use the best possible font, but it may have to substitute some font parameters. Tk guarantees that the Times, Courier, and Helvetica families exist. It also understands the synonyms of Courier New for Courier, and Arial or Geneva for Helvetica.The font actual command returns the parameters chosen to match a font specification:
font actual {times 13 bold} -family Times -size 13 -weight bold -slant roman -underline 0 -overstrike 0
The Macintosh and Windows platforms have a system-defined default size. You can get this size by specifying a size of 0 in your specification. The system font uses this:
font actual system -family Chicago -size 0 -weight normal -slant roman -underline 0 -overstrike 0
Named Fonts
You can define your own names for fonts with the font create command. Creating a named font provides a level of indirection between the font parameters and the widgets that use the fonts. If you reconfigure a named font, the widgets using it will update their display automatically. This makes it easy to support a user preference for font size. For example, we can define a font name default on all platforms:
The default font can be made larger at any time with font configure. Widgets using the fonts will update automatically:
System Fonts
The Windows and Macintosh platforms have system-defined fonts that are used by most applications. When you query the configuration of the Tk widgets, you will see the system font names. The parameters for the system fonts can be tuned by the user via the system control panel. You can find out the attributes of the system font with font actual. These are the system fonts for each platform: The Windows platform supports system, systemfixed, ansi, ansifixed, device, oemfixed. The fixed suffix refers to a font where each character is the same size. The Macintosh platform has system and application.
The UNIX platform has fixed. This is the only X font name that is guaranteed to exist. X font names are described in the next section.
Unicode Fonts
Tk does character-by-character font substitution when it displays Unicode characters. This supports mixed display of ASCII and Kanji characters, for example. The great thing about this is that you do not have to worry too much about choosing fonts in the simple case. The problem with font substitution is that it can be slow. In the worst case, Tk will query every font installed in your system to find out whether it can display a particular character. If you know you will be displaying characters in a particular character set, you can optimize your interface by specifying a font that matches what you expect to display. [ Team LiB ]
[ Team LiB ]
X Font Names
Fonts can be specified with X font names on all platforms, and you must use X font names in versions of Tk before Tk 8.0. The name fixed is an example of a short X font name. Other short names might include 6x12, 9x15, or times12. However, these aliases are site-dependent. In fact, all X font names are site dependent because different fonts may be installed on different systems. The only font guaranteed to exist on the UNIX platform is named fixed. The more general form of an X font name has several components that describe the font parameters. Each component is separated by a dash, and the asterisk (*) is used for unspecified components. Short font names are system-defined aliases for these more complete specifications. Here is an example:
-*-times-medium-r-normal-*-18-*-*-*-*-*-iso8859-1
The components of X font names are listed in Table 42-2 in the order in which they occur in the font specification. The table gives the possible values for the components. If there is an ellipsis (...), then there are more possibilities, too.
The most common attributes chosen for a font are its family, weight, slant, and size. The weight is usually bold or medium. The slant component is a bit cryptic, but i means italic, r means roman (i.e., normal), and o means oblique. A given font family might have an italic version, or an oblique version, but not both. Similarly, not all weights are offered by all font families. Size can be specified in pixels (i.e., screen pixels) or points. Points are meant to be independent of the screen resolution. On a 75dpi font, there are about 10 points per pixel. Note: These "points" are different than the printer points Tk uses in screen measurements. When you use X font OF CHM size of the font is not affected by the Tk scaling factor UNREGISTERED VERSIONnames, theTO PDF CONVERTER By THETA-SOFTWARE described on page 669. It is generally a good idea to specify just a few key components and use * for the remaining components. The X server attempts to match the font specification with its set of installed fonts, but it fails if there is a specific component that it cannot match. If the first or last character UNREGISTERED of the font nameCHM TO PDF then that can matchTHETA-SOFTWARE The VERSION OF is an asterisk, CONVERTER By multiple components. following selects a 12-pixel times font:
*times-medium-r-*-*-12*
Two useful UNIX programs that deal with X fonts are xlsfonts and xfontsel. These are part of the standard X11 distribution. xlsfonts simply lists the available fonts that match a given font name. It uses the same pattern matching that the server does. Because asterisk is special to most UNIX shells, you need to quote the font name argument if you run xlsfonts from your shell. xfontsel has a graphical user interface and displays the font that matches a given font name.
The FontWidget procedure reverts to a default font if the widget creation command fails. It is careful to eliminate the font specified in args, if it exists. The explicit font overrides any setting from the resource database or the Tk defaults. Of course, widget creation might fail for some more legitimate reason, but that is allowed to happen in the backup case. Again, the missing font problem disappears when you use platform-independent font names, so you only need to resort to using FontWidget in early versions of Tk. [ Team LiB ]
[ Team LiB ]
Font Metrics
The font VERSION OF CHM TO measurement information for fonts. It returns general UNREGISTERED metrics command returnsPDF CONVERTER By THETA-SOFTWARE information about all the characters in the font:
The font measure command returns the width of a string that will be displayed in a given font. The width does not account for heavily slanted letters that overhang their bounding box, nor does it do anything special with tabs or newlines in the string. [ Team LiB ]
[ Team LiB ]
font measure font ?-displayof win? text font metrics font ?-displayof win? ? option? font names [ Team LiB ]
[ Team LiB ]
Text Attributes
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Layout
Table 42-4 summarizes two simple text layout attributes: justify and wrapLength. The text widget has several more layout-related attributes, and Chapter 36 describes those in detail. The two attributes described in this section apply to the various button widgets, the label, UNREGISTERED VERSION OF CHM TOwidgets are described in Chapters 30, 32, and 34. The PDF CONVERTER By THETA-SOFTWARE entry, and message widgets. Those justify attribute causes text to be centered, left-justified, or right-justified. The default justification is center for all the widgets in the table, except for the entry widget, which is leftjustified by default. The wrapLength attribute specifies how long a line of text is before it is wrapped onto another line. It is used to create multiline buttons and labels. This attribute is specified in screen units, however, not string length. It is probably easier to achieve the desired line breaks by inserting newlines into the text for the button or label and specifying a wrapLength of 0, which is the default.
Selection Attributes
Table 42-5 lists the selection-related attributes. The exportSelection attribute controls if the selection is exported for cut and paste to other widgets. The colors for selected text are set with selectForeground and selectBackground. The selection is drawn in a raised relief, and the selectBorderWidth attribute affects the 3D appearance. Choose a border width of zero to get a flat relief.
Share selection. Widgets: entry, canvas, listbox, and text. Foreground of selected text. Background of selected text.
[ Team LiB ]
When a widget is gridded, its size is UNREGISTERED VERSION OF CHM TO constrained to have a whole number of grid units PDF CONVERTER By THETA-SOFTWARE
displayed. The height will be constrained to show a whole number of text lines, and the width will be constrained to show a whole number of average width characters. This affects interactive resizing by users, as well as the various window manger commands (wm) that relate to geometry. When gridding is turned on, the geometry argument (e.g., 24x80) is interpreted as grid units; otherwise, it is interpreted as pixels. The window manager geometry commands are summarized in Table 44-1 on page 659. The following example creates a listbox with gridded geometry enabled. Try resizing the window in the following example with and without the -setgrid flag, and with and without the wm minsize command, which sets the minimum size of the window. The Scrolled_Listbox procedure is defined in Example 33-3 on page 502.
[ Team LiB ]
[ Team LiB ]
proc Font_Select {{top .fontsel}} { global font # Create File, Font, Size, and Format menus toplevel $top -class Fontsel -bd 10 set menubar [menu $top.menubar] $top config -menu $menubar foreach x {File Font Size Format} { set menu [menu $menubar.[string tolower $x]] $menubar add cascade -menu $menu -label $x } $menubar.file add command -label Reset -command FontReset $menubar.file add command -label OK \ -command {set font(ok) ok} $menubar.file add command -label Cancel \ -command {set font(ok) cancel} # The Fonts menu lists the available Font families. set allfonts [font families] set numfonts [llength $allfonts] set limit 20 if {$numfonts < $limit} { # Display the fonts in a single menu
foreach family $allfonts { $menubar.font add radio -label $family \ -variable font(-family) \ -value $family \ -command FontUpdate } } else {
FontReset # This label displays the current font label $top.font -textvar font(name) -bd 5 # This message displays a sampler of the font. message $top.msg -aspect 1000 \ -borderwidth 10 -font fontsel \ -text " ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 !@#$%^&*()_+-=[]{};:\"''~,.<>/?\\| " # Lay out the dialog pack $top.font $top.msg -side top set f [frame $top.buttons] button $f.ok -text Ok -command {set font(ok) 1} button $f.cancel -text Cancel -command {set font(ok) 0} pack $f.ok $f.cancel -padx 10 -side left pack $f -side top # Dialog_Wait is defined in Example 391 on page 606 set font(ok) cancel Dialog_Wait $top font(ok) destroy $top if {$font(ok) == "ok"} { return [array get font -*] } else { return {} } } # FontReset recreates a default font proc FontReset {} { catch {font delete fontsel} font create fontsel FontSet } # FontSet initializes the font array with the settings # returned by the font actual command proc FontSet {} { global font # The name is the font configuration information # with a line break so it looks nicer set font(name) [font actual fontsel] regsub -- "-slant" $font(name) "\n-slant" font(name)
# Save the actual parameters after any font substitutions array set font [font actual fontsel] } # FontSetSize adds an entry widget to the dialog so you # can enter a specific font size.
By THETA-SOFTWARE
# FontUpdate is called when any of the font settings # are changed, either from the menu or FontSetSize proc FontUpdate { } { global font # The elements of font that have a leading - are # used directly in the font configuration command. eval {font configure fontsel} [array get font -*] FontSet }
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
UNREGISTEREDcommand behaves likeTO PDFyou give it extra arguments, it concatenates them to VERSION OF CHM eval; if CONVERTER By THETA-SOFTWARE The send
form a single command. If your argument structure is important, use list to build the command. Table 43-1 lists the options to send:
The interp argument is the name of the other application. An application defines its own name when it creates its main window. The wish shell uses as its name the last component of the file name of the script. For example, when wish interprets /usr/local/bin/exmh, it sets its application name to exmh. However, if another instance of the exmh application is already running, wish chooses the name exmh #2, and so on. If wish is not executing from a file, its name is just wish. You may have noticed wish #2 or wish #3 in your window title bars, and this reflects the fact that multiple wish applications are running on your display. A script can find out its own name, so you can pass names around or put them into files in order to set up communications. The tk appname command queries or changes the application name:
mechanism. The details vary depending on your X server, and most modern X servers do this automatically. The general picture is that you generate a pseudo-random string and store it into a file, which is usually named ~/.Xauthority and must be readable only by your account. The -auth flag specifies the name of this file to the X server. Each X application reads this file and sends the contents to the X server when opening the connection to the server. If the contents match what the server read when it started, then the connection is allowed. The system is slightly more complicated than described here. The file actually contains a sequence of records to support multiple displays and client hosts. Consult your local X guru or the documentation for the details particular to your system.
Tk also requires that the xhost list be empty. The xhost mechanism is the old, not-so-secure authentication mechanism in X. With xhost you allow all programs on a list of hosts to connect to your display. The problem with this is that multiuser workstations allow remote login, so essentially anybody could log in to a workstation on the xhost list and gain access to your display. The Xauthority mechanism is much stronger because it restricts access to your account, or to accounts that you explicitly give a secret token to. The problem is that even if Xauthority is set up, the user or a program can turn on xhosts and open up access to your display. If you run the xhost program with no argument, it reports the status and what hosts are on the list. The following output is generated when access control is restricted, but programs running on sage are allowed to connect to the display:
exec xhost => Access control enabled: all hosts being restricted sage
This is not good enough for Tk send. It will fail because sage is on the list. I work in an environment where old scripts and programs are constantly adding things to my xhost list for reasons that are no longer valid. I developed a version of send that checks for errors and then does the following to clean out the xhost list. You have to enable access control and then explicitly remove any hosts on the list. These are reported after an initial line that says whether or not hosts are restricted:
xhost - ;# enable access control in general foreach host [lrange [split [exec xhost] \n] 1 end] { exec xhost -$host ;# clear out exceptions }
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 43-1 The sender application
#!/usr/local/bin/wish # sender takes up to four arguments: # 1) the name of the application to send to. # 2) a command prefix. # 3) the name of another application to notify # after the end of the data. # 4) the command to use in the notification. # Hide the unneeded window wm withdraw . # Process command line arguments if {$argc == 0} { puts stderr "Usage: send name ?cmd? ?uiName? ?uiCmd?" exit 1 } else { set app [lindex $argv 0] } if {$argc > 1} { set cmd [lindex $argv 1] } else { set cmd Send_Insert } if {$argc > 2} { set ui [lindex $argv 2] set uiCmd Send_Done } if {$argc > 3} { set uiCmd [lindex $argv 3] } # Read input and send it to the logger while {[gets stdin input] >= 0} { # Ignore errors with the logger catch {send $app [concat $cmd [list $input\n]]} } # Notify the controller, if any if [info exists ui] { if [catch {send $ui $uiCmd} msg] { puts stderr "send.tcl could not notify $ui\n$msg" }
The sender application supports communication with two processes. It sends all its input to a primary "logging" application. When the input finishes, it can send a notification message to another "controller" application. The logger and the controller could be the same application.
The combination of concat and list is tricky. The list command quotes the value of the input line. This quoted value is then appended to the command, so it appears as a single extra argument. Without the quoting by list, the value of the input line will affect the way the remote interpreter parses the command. Consider these alternatives:
This form is safe, except that it limits $cmd to a single word. If cmd contains a value like the ones given below, the remote interpreter will not parse it correctly. It will treat the whole multiword value as the name of a command:
The send command concatenates $cmd and $input together, and the result will be parsed again by the remote interpreter. The success or failure of the remote command depends on the value of the input data. If the input included Tcl syntax like $ or [ ], errors or other unexpected behavior would result. [ Team LiB ]
[ Team LiB ]
Communicating Processes
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Chapter 24 presented two examples: a browser for the examples in this book, and a simple shell in which to try out Tcl commands. In that chapter they are put into the same application. The two examples shown below hook these two applications together using the send command. Example 43-2 changes the Run and Reset procedures of the browser to send EvalEcho commands to the shell.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 43-2 Hooking the browser to an eval server
# Replace the Run and Reset procedures of the browser in # Example 243 on page 384 with these procedures # Start up the evalsrv.tcl script. proc StartEvalServer {} { global browse # Start the shell and pass it our name. exec evalsrv.tcl [tk appname] & # Wait for evalsrv.tcl to send us its name tkwait variable browse(evalInterp) } proc Run {} { global browse set apps [winfo interps] set ix [lsearch -glob $apps evalsrv.tcl*] if {$ix < 0} { # No evalsrv.tcl application running StartEvalServer } if {![info exists browse(evalInterp)]} { # Hook up to already running eval server set browse(evalInterp) [lindex $apps $ix] } if [catch {send $browse(evalInterp) {info vars}} err] { # It probably died - restart it. StartEvalServer } # Send the command asynchronously. The two # list commands foil the concat done by send and # the uplevel in EvalEcho send -async $browse(evalInterp) \ [list EvalEcho [list source $browse(current)]] } # Reset the shell interpreter in the eval server proc Reset {} { global browse send $browse(evalInterp) {EvalEcho reset} }
The number of lists created before the send command may seem excessive, but they are all necessary. The send command concatenates its arguments, so instead of letting it do that, we pass it a single list. Similarly, EvalEcho expects a single argument that is a valid command, so list is used to construct that. The StartEvalServer procedure starts up the shell. Command-line arguments are used to pass the application name of the browser to the shell. The shell completes the connection by sending its own application name back to the browser. The browser stores the name of the shell application in browser(evalInterp). The code that the shell uses is shown in Example 43-3:
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 43-4 implements Eval_Server that lets other applications connect and evaluate Tcl
Example 43-5 shows EvalRead that reads commands and evaluates them in an interpreter. If the interp is {}, it causes the commands to execute in the current interpreter. In this case an uplevel #0 is necessary to ensure the command is executed in the global scope. If you use interp eval to execute something in yourself, it executes in the current scope:
} else { gets $sock line append eval(cmdbuf,$sock) $line\n if {[string length $eval(cmdbuf,$sock)] && \ [info complete $eval(cmdbuf,$sock)]} { set code [catch { if {[string length $interp] == 0} { uplevel #0 $eval(cmdbuf,$sock) } else { interp eval $interp $eval(cmdbuf,$sock) } } result] set reply [list $code $result $errorInfo \ $errorCode]\n # Use regsub to count newlines set lines [regsub -all \n $reply {} junk] # The reply is a line count followed # by a Tcl list that occupies that number of lines puts $sock $lines puts -nonewline $sock $reply flush $sock set eval(cmdbuf,$sock) {} } } }
Example 43-6 presents Eval_Open and Eval_Remote that implement the client side of the eval connection. Eval_Open connects to the server and returns a token, which is just the socket. The main task of Eval_Remote is to preserve the information generated when the remote command raises an error The network protocol is line-oriented. The Eval_Remote command writes the command on the socket. The EvalRead procedure uses info complete to detect the end of the command. The reply is more arbitrary, so server sends a line count and that number of lines. The regsub command counts up all the newlines because it returns the number of matches it finds. The reply is a list of error codes, results, and trace information. These details of the return command are described on page 86.
} puts $sock $cmd flush $sock # Read return line count and the result. gets $sock lines set result {} while {$lines > 0} { gets $sock x UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE append result $x\n incr lines -1 } set code [lindex $result 0] set x [lindex $result 1] # Cleanup the end of the TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM stack regsub "\[^\n]+$" [lindex $result 2] \ "*Remote Server $eval(server,$sock)*" stack set ec [lindex $result 3] return -code $code -errorinfo $stack -errorcode $ec $x } proc Eval_Close {sock} { close $sock }
If an error occurs in the remote command, then a stack trace is returned. This includes the command used inside EvalRead to invoke the command, which is either the uplevel or interp eval command. This is the very last line in the stack that is returned, and regsub is used to replace this with an indication of where control transferred to the remote server:
catch [Eval_Remote sock6 set xx] => 1 set errorInfo => can't read "xx": no such variable while executing "set xx " ("uplevel" body line 1) invoked from within *Remote Server sage:4000* invoked from within "catch [Eval_Remote sock6 set xx]"
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
The wm Command
The wm command has OF CHM TO PDF that interact with the window manager. The UNREGISTERED VERSION about 20 operations CONVERTER By THETA-SOFTWARE general form of the command is:
UNREGISTERED VERSION OF CHM TO be a toplevel. Otherwise, an error is raised. In many cases, PDF CONVERTER By THETA-SOFTWARE In all cases the win argument must
the operation either sets or queries a value. If a new value is not specified, then the current settings are returned. For example, this command returns the current window geometry:
wm geometry . 400x200+0+0
There are lots of wm operations, and this reflects the complex protocol with UNIX window managers. The summary below lists the subset of operations that I find useful. The operations can be grouped into four main categories: Size, placement and decoration of windows. Use the geometry and title operations to position windows and set the title bar. Icons. Use the iconify, deiconify, and withdraw operations to open and close windows. On UNIX, closed windows are represented by an icon. Long-term session state. Use the protocol operation to get a callback when users destroy windows. Miscellaneous. Use the transient and overrideredirect operation to get specialized windows. There are platform-specific commands to select different styles of top-level windows.
Use the wm geometry command to adjust the position or size of your main windows. A geometry specification has the general form WxH+X+Y, where W is the width, H is the height, and X and Y specify the location of the upper-left corner of the window. The location +0+0 is the upper-left corner of the display. You can specify a negative X or Y to position the bottom (right) side of the window relative to the bottom (right) side of the display. For example, +0-0 is the lower-left corner, and -100-100 is offset from the lower-right corner by 100 pixels in the X and Y direction. If you do not specify a geometry, then the current geometry is returned.
Example 44-1 sets up gridded geometry for a canvas, which means that the geometry is in terms of some unit other than pixels. With the canvas, use the wm grid command to define the size of the grid. The text and listbox widgets set a grid based on the size of the characters they display. They have a setgrid attribute that turns on gridding, which is described on page 642. The wm resizable command controls whether a user can resize a window. The following command allows a resize in the X direction, but not in the Y direction:
wm resizable . 1 0
You can constrain the minimum size, maximum size, and the aspect ratio of a toplevel. The aspect ratio is the width divided by the height. The constraint is applied when the user resizes the window interactively. The minsize, maxsize, and aspect operations apply these constraints. Some window managers insist on having the user position windows. The sizefrom and positionfrom operations let you pretend that the user specified the size and position in order to work around this restriction. Table 44-1 summarizes the wm commands that deal with size, decorations, placement:
wm aspect win ?a b c d?
Constrains win's ratio of width to height to be between (a/b and c/d). Queries or sets the geometry of win. Queries or sets the grid size. w and h are the base size, in grid units. dx and dy are the size, in pixels, of a grid unit. Constrains the maximum size of win. Constrains the minimum size of win.
The stackorder operation, introduced in Tk 8.4, returns information about the stacking order of the application's toplevel windows. Given the name of a toplevel, it returns a list of toplevel children windows in stacking order, from lowest to highest. Only those toplevels that are currently mapped to the screen are returned. The following command returns all mapped toplevels in their stacking order:
wm stackorder .
The stackorder operation can also be used to determine if one toplevel is positioned above or below a second toplevel. When two window arguments separated by either isabove or isbelow are passed, a boolean result indicates whether or not the first window is currently above or below the second window in the stacking order. For example:
Icons
UNIX window managers let you close a window and replace it with an icon. The window still exists in your application, and users can open the window later. You can open and close a window yourself with the deiconify and iconify operations, respectively. Use the withdraw operation to unmap the window without replacing it with an icon. The state operation returns the current state, which is one of normal, iconified, or withdrawn. If you withdraw a window, you can restore it to the normal state with deiconify.
Windows and Macintosh do not implement icons for program windows. Instead, icons represent files and applications in the desktop environment. When you iconify under Windows, the window gets minimized and users can open it by clicking on the taskbar at the bottom of the screen. When you iconify under Macintosh, the window simply gets withdrawn from the screen. As of Tk 8.3, Windows applications have an additional state, zoomed, which is a full-screen (or "maximized") display mode. Future versions of Tk may support this state for other operating systems You can set the attributes of UNIX icons with the iconname, iconposition, iconbitmap, and iconmask operations. The icon's mask is used to get irregularly shaped icons. Chapter 41 describes how masks and bitmaps are defined. In the case of an icon, it is most likely that you have the definition in a file, so your command will look like this:
wm iconbitmap . @myfilename
Starting with Tk 8.3.3, on Windows systems, you can provide the path of a valid Windows icon file (usually .ico or .icr files) when setting the window's icon with the wm iconbitmap command. And if you use the optional -default option, introduced in Tk 8.4, the specified bitmap is used as the default icon for all windows. However, when setting the icon bitmap under windows, remember that the argument you provide must be a filename without a leading "@". For example:
Queries or specifies an alternate window to display when in the iconified state. UNIX.
wm state win ?state? Returns normal, iconic, withdrawn or (Windows only) zoomed. If specified, the window is set to the new state. wm withdraw win Unmaps the window. No icon is displayed.
If you intercept close on the main Tk window (i.e., dot), you must eventually call exit to actually stop your application. However, you can also take the time to prompt the user about unsaved changes, or even let the user change their mind about quitting. Other window manager messages that you can intercept are WM_SAVE_YOURSELF and WM_TAKE_FOCUS. The first is called periodically by some UNIX session managers, which are described below. The latter is used in the active focus model. Tk (and this book) assumes a passive focus model where the window manager assigns focus to a top-level window.
Some UNIX window managers support the notion of a session that lasts between runs of the window system. A session is implemented by saving state about the applications that are running, and using this information to restart the applications when the window system is restarted. An easy way to participate in the session protocol is to save the command used to start your application. The wm command operation does this. The wish shell saves this information, so it is just a matter of registering it with the window manager. argv0 is the command, and argv is the command-line arguments:
If your application is typically run on a different host than the one with the display (like in an Xterminal environment), then you also need to record what host to run the application on. Use the wm client operation for this. You might need to use hostname instead of uname on your
system:
Sets or queries platform-specific window attributes. (Tk 8.4) Sets or queries the WM_COLORMAP_WINDOWS property that orders windows with different colormaps. Sets or queries the focus model: active or passive. (Tk assumes the passive model.) otherwise, returns the ID of win.
UNREGISTERED VERSION OF CHM Returns the ID of the parent of win if it has been reparented; TO PDF CONVERTER By THETA-SOFTWARE wm frame win
wm group win ?leader? Queries or sets the group leader (a toplevel) for win. The window manager may unmap all the group at once.
UNREGISTERED VERSION OF CHM reparenting by the windowBy THETA-SOFTWARE TO PDF CONVERTER manager.
wm overrideredirect win ? Sets or queries the override redirect bit that suppresses boolean? wm transient win ?leader? Queries or marks a window as a transient window working for leader, another widget.
[ Team LiB ]
[ Team LiB ]
Queries or sets the name used with send. Also returns the name used for send, for backward compatibility with Tk 3.6 and earlier. Returns the last component of pathname. Returns the list of registered Tk applications on the same
Widget Size
The winfo width and winfo height operations return the width and height of a window, respectively. Alternatively, you can ask for the requested width and height of a window. Use winfo reqwidth and winfo reqheight for this information. The requested size may not be accurate, however, because the geometry manager may allocate more or less space, and the
A window's size is not set until a geometry manager maps a window onto the display. Initially, a window starts out with a width and height of 1. You can use tkwait visibility to wait for a window to be mapped before asking its width or height, or you can use update to give Tk a chance to update the display. There are some potential problems with update that are discussed on page 608. Dialog_Wait in Example 39-1 on page 606 uses tkwait visibility. The winfo geometry operation returns the size and position of the window in the standard geometry format: WxH+X+Y. In this case the X and Y offsets are relative to the parent widget, or relative to the root window in the case of the main window. You can find out how big the display is, too. The winfo screenwidth and winfo screenheight operations return this information in pixels. The winfo screenmmwidth and winfo screenmmheight return this information in millimeters. You can convert between pixels and screen distances with the winfo pixels and winfo fpixels operations. Given a number of screen units such as 10m, 3c, or 72p, these return the corresponding number of pixels. The first form rounds to a whole number, while the second form returns a floating point number. The correspondence between pixels and sizes may not be accurate because users can adjust the pixel size on their monitors, and Tk has no way of knowing about that. Chapter 40 explains screen units on page 612. For example:
Converts num, in screen units, to pixels. Returns a floating point number. Returns the geometry of win, in pixels and relative to the parent in the form WxH+X+Y Returns the height of win, in pixels.
UNREGISTERED VERSIONnum CHM TO PDF to a whole number of pixels. winfo pixels win OF Converts num CONVERTER By THETA-SOFTWARE
winfo reqheight win winfo reqwidth win winfo screenheight Returns the requested height of win, in pixels. Returns the requested width of win, in pixels. Returns the height of the screen, in pixels.
Widget Location
The winfo x and winfo y operations return the position of the upper-left corner of a window relative to its parent widget. In the case of the main window, this is its location on the screen. The winfo rootx and winfo rooty return the screen location of the upper-left corner of a widget, even if it is not a toplevel. The winfo containing operation returns the pathname of the window that contains a point on the screen. This is useful in implementing menus and drag-and-drop applications. The winfo toplevel operation returns the pathname of the toplevel that contains a widget. If the window is itself a toplevel, then this operation returns its own pathname. The winfo screen operation returns the display identifier for the screen of the window.
The winfo vrootx and winfo vrooty are used to map from the coordinates in the virtual root window to screen-relative coordinates. These operations return 0 if there is no virtual root window. Otherwise, they return a negative number. If you add this number to the value returned by winfo x or winfo y, it gives the screen-relative coordinate of the window:
winfo vrootheight win winfo vrootwidth win winfo vrootx win winfo vrooty win
Returns the height of the virtual root window for win. Returns the width of the virtual root window for win. Returns the X position of win in the virtual root. Returns the Y position of win in the virtual root.
An atom is an X technical term for an identifier that is registered with the X server. Applications map names into atoms, and the X server assigns each atom a 32-bit identifier that can be passed between applications. One of the few places this is used in Tk is when the selection UNREGISTERED VERSION OF CHMwith different toolkits. In someTHETA-SOFTWAREreturned mechanism is used to interface TO PDF CONVERTER By cases the selection is as atoms, which appear as 32-bit integers. The winfo atomname operation converts that number into an atom (i.e., a string), and the winfo atom registers a string with the X server and returns the 32-bit identifier as a hexadecimal string Each widget has an ID assigned by the window system. The winfo id command returns this identifier. The winfo pathname operation returns the Tk pathname of the widget that has a given ID, but only if the window is part of the same application.
Embedding applications.
The id operation is useful if you need to embed another application into your window hierarchy. Wish takes a -use id command-line argument that causes it to use an existing window for its main window. Other toolkits provide similar functionality. For example, to embed another Tk app in a frame:
frame .embed -container true exec wish -use [winfo id .embed] otherscript.tcl
winfo atom ?-displayof win? name winfo atomname ?-displayof win? id winfo id win winfo pathname ?-displayof win? id
Returns the 32-bit identifier for the atom name. Returns the atom that corresponds to the 32-bit ID. Returns the window ID of win. Returns the Tk pathname of the window with id, or null.
The winfo visual operation returns the visual class of a window, and the winfo screenvisual returns the default visual class of the screen. The winfo rgb operation converts from a color name or value to the red, green, and blue components of that color. Three decimal values are returned. Example 41-2 on page 624 uses this command to compute a slightly darker version of the same color. Table 44-11 summarizes operations that return information about colormaps and visual classes, which are described in Chapter 41:
winfo colormapfull win Returns 1 if the last color allocation failed. winfo depth win winfo rgb win color Returns the number of bits per pixel for win. Returns the red, green, and blue values for color.
winfo screencells win Returns the CONVERTER By cells in the default visual. UNREGISTERED VERSION OF CHM TO PDFnumber of colormap THETA-SOFTWARE winfo screendepth win Returns the number of bits per pixel in the screen's default visual.
winfo screenvisual win Returns the default visual of the screen. winfo visual win Returns the visual class of win. pixel of the available visual classes.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE per winfo visualsavailable Returns a list of pairs that specify the visual type and bits
win [ Team LiB ]
[ Team LiB ]
The tk Command
The tk command provides a few miscellaneous entry points into the Tk library. The appname operation is used to set or query the application name used with the Tk send command. If you define a new name and it is already in use by another application, (perhaps another instance of yourself), then a number is appended to the name (e.g., #2, #3, and so on). This is the syntax of the command:
tk appname ?name?
Fonts, canvas items, and widget sizes use screen units that are pixels, points, centimeters, millimeters, or inches. There are 72 points per inch. The tk scaling command, which was added in Tk 8.0, is used to set or query the mapping between pixels and points. A scale of 1.0 results in 72 pixels per inch. A scale of 1.25 results in 90 pixels per inch. This gives accurate sizes on a 90 dpi screen or it makes everything 25% larger on a 72 dpi screen. Changing the scale only affects widgets created after the change. This is the syntax of the command:
tk scaling ?num?
The tk windowingsystem command, added in Tk 8.4, returns one of x11 (X11-based), win32 (MS Windows), classic (Mac OS Classic), or aqua (Mac OS X Aqua). Traditionally, Tk applications that included platform-dependent code could simply switch on the value of the global tcl_platform(platform) element, which is set to macintosh, unix, or windows. But the introduction of Apple's OS X and the Aqua interface complicated matters. Mac OS X reports unix in the tcl_platform(platform) element. But its windowing system is not a native X Windows system, so you must use tk windowingsystem. The caret operation, introduced in Tk 8.4, sets and queries the caret location for the display of the specified Tk window. The caret is the per-display cursor location used for indicating global focus (for example, to comply with Microsoft Accessibility guidelines), as well as for location of the over-the-spot XIM (X Input Methods) or Windows IME windows. The useinputmethods operation changes the behavior of Tk on X with X Input Methods (XIM). Before Tk 8.3, XIM was recognized and used without question. As of Tk 8.3, they are recognized and initialized, but not used unless XIM is turned on with the useinputmethods operation:
tk useinputmethods 1
Table 44-12. The tk command THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER Byoperations
tk appname ?name? Queries or sets the application name, used by the Tk send command. Queries or sets the caret location for the display of the specified Tk window. PDF y represent window-relative coordinates. height is CHM TO x and CONVERTER By THETA-SOFTWARE the height of the current cursor location, or the height of the specified window. Values are returned in option-value pair format. (Tk 8.4) Queries or sets the current scaling factor used by Tk to convert between physical units and pixels. number is a floating point value that specifies the number of pixels per point on window's display. If window is omitted, it defaults to the main window. If number is omitted, the current value of the scaling factor is returned.
tk useinputmethods ?- Queries or sets the state of whether Tk should use XIM (X Input displayof window? ? Methods) for filtering events. The resulting state is returned. If XIM support is not available, this will always return 0. If window is boolean? omitted, it defaults to the main window. If boolean is omitted, the current state is returned. (Tk 8.3) tk windowingsystem Returns the current windowing system: x11 (X11-based), win32 (MS Windows), classic (Mac OS Classic), or aqua (Mac OS X Aqua). (Tk 8.4)
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
App-Defaults Files
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
We will assume that it is sufficient to have two sources of application defaults: a per-application database and a per-user database. In addition, we will allow for some resources to be specific to color and monochrome displays. The following example initializes the preference package by reading in the per-application and per-user resource specification files. There is also an initialization of the global array pref that will be used to hold state information about the preferences package. The Pref_Init procedure is called like this:
We assume $library is the directory holding support files for the foo application, and that per-user defaults will be kept in ~/.foo-defaults. These are UNIX-oriented file names. When you write cross-platform Tk applications, you will find that some file names are inherently platform-specific. The platform-independent operations described in Chapter 9 are great, but they do not change the fact that user preferences may be stored in c:/webtk/userpref.txt on Windows, Hard Disk:System:Preferences:WebTk Prefs on Macintosh, and ~/.webtk on UNIX. I find it useful to have a small amount of platform-specific startup code that defines these pathnames. The preference package uses resource files that work on all platforms:
The PrefReadFile procedure reads a resource file and then looks for another file with the suffix -color or -mono depending on the characteristics of the display. With this scheme, a UNIX user puts generic settings in ~/.foo-defaults. They put color specifications in ~/.foo-defaultscolor. They put specifications for black and white displays in ~/.foo-defaults-mono. You could extend PrefReadFile to allow for per-host files as well. Throughout this chapter we assume that the Status procedure displays messages to the user. It could be as simple as:
[ Team LiB ]
[ Team LiB ]
Defining Preferences
UNREGISTERED VERSION OF Pref_Add procedure that an application uses to define preference CHM TO PDF CONVERTER By THETA-SOFTWARE This section describes the
items. A preference item defines a relationship between a Tcl variable and a resource name. If the Tcl variable is undefined at the time Pref_Add is called, then it is set from the value for the resource. If the resource is not defined, then the variable is set to the default value.
A default value, a label, and a more extensive help string are associated with each item, which is represented by a Tcl list of five elements. A few short routines hide the layout of the item lists and make the rest of the code read better:
proc Pref_Add { prefs } { global pref append pref(items) $prefs " " foreach item $prefs { set varName [PrefVar $item] set resName [PrefRes $item] set value [PrefValue $varName $resName] if {$value == {}} { # Set variables that are still not set set default [PrefDefault $item] switch -regexp -- $default { ^CHOICE { PrefValueSet $varName [lindex $default 1] } ^OFF { PrefValueSet $varName 0 } ^ON { PrefValueSet $varName 1 }
The procedures PrefValue and PrefValueSet are used to query and set the value of the named variable, which can be an array element or a simple variable. The upvar #0 command sets the variable in the global scope.
An important side effect of the Pref_Add call is that the variables in the preference item are defined at the global scope. It is also worth noting that PrefValue will honor any existing value for a variable, so if the variable is already set at the global scope, then neither the resource value nor the default value will be used. It is easy to change PrefValue to always set the variable if this is not the behavior you want. Here is a sample call to Pref_Add:
Any number of preference items can be specified in a call to Pref_Add. The list-of-lists structure is created by proper placement of the curly braces, and it is preserved when the argument is appended to pref(items), which is the master list of preferences. In this example, Pref_Add gets passed a single argument that is a Tcl list with three elements. The Tcl variables are array elements, presumably related to the Win module of the application. The resource UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE names are associated with the main application as opposed to any particular widget. They are specified in the database like this:
[ Team LiB ]
[ Team LiB ]
proc Pref_Dialog {} { global pref if [catch {toplevel .pref}] { raise .pref } else { wm title .pref "Preferences" set buttons [frame .pref.but -bd 5] pack .pref.but -side top -fill x button $buttons.quit -text Dismiss \ -command {PrefDismiss} button $buttons.save -text Save \ -command {PrefSave} button $buttons.reset -text Reset \ -command {PrefReset ; PrefDismiss} label $buttons.label \ -text "Click labels for info on each item" pack $buttons.label -side left -fill x pack $buttons.quit $buttons.save $buttons.reset \ -side right -padx 4 frame .pref.b -borderwidth 2 -relief raised pack .pref.b -fill both set body [frame .pref.b.b -bd 10] pack .pref.b.b -fill both set maxWidth 0 foreach item $pref(items) { set len [string length [PrefComment $item]] if {$len > $maxWidth} { set maxWidth $len
} } set pref(uid) 0 foreach item $pref(items) { PrefDialogItem $body $item $maxWidth } } } UNREGISTERED
The interface supports three different types of preference items: boolean, choice, and general value. A boolean is implemented with a checkbutton that is tied to the Tcl variable, which will get a value of either 0 or 1. A boolean is identified by a default value that is either ON or OFF. A choice item UNREGISTERED byis implemented as a TO of radiobuttons, one for each choice. A choice item is VERSION OF CHM seta PDF CONVERTER By THETA-SOFTWARE identified a default value that is list with the first element equal to CHOICE. The remaining list items are the choices, with the first one being the default choice. A regexp is used to check for CHOICE instead of using list operations. This is because Tcl 8.0 will complain if the value is not a proper list, which could happen with arbitrary values. If neither of these cases, boolean or choice, are detected, then an entry widget is created to hold the general value of the preference item:
bind $f.entry <Return> "PrefEntrySet %W $varName" } } } proc PrefFixupBoolean {check varname} { upvar #0 $varname var # Update the checkbutton text each time it changes if {$var} { $check config -text On } else { $check config -text Off } } proc PrefEntrySet { entry varName } { PrefValueSet $varName [$entry get] }
In this interface, when the user clicks a radiobutton or a checkbutton, the Tcl variable is set immediately. To obtain a similar effect with the general preference item, the <Return> key is bound to a procedure that sets the associated Tcl variable to the value from the entry widget. PrefEntrySet is a one-line procedure that saves us from using the more awkward binding shown below. Grouping with double quotes allows substitution of $varName, but then we must quote the square brackets to postpone command substitution: bind $f.entry <Return> "PrefValueSet $varName \[%W get\]"
The binding on <Return> is done as opposed to using the -textvariable option because it interacts with traces on the variable a bit better. With trace you can arrange for a Tcl command to be executed when a variable is changed, as in Example 45-10 on page 680. For a general preference item it is better to wait until the complete value is entered before responding to its new value. The other aspect of the user interface is the display of additional help information for each item. If there are lots of preference items, then there isn't enough room to display this information directly. Instead, clicking on the short description for each item brings up a toplevel with the help text for that item. The toplevel is marked transient so that the window manager does not decorate it:
bind $self.msg <1> {PrefNukeItemHelp .prefitemhelp} .pref.but.label configure -text \ "Click on pop-up or another label" } proc PrefNukeItemHelp { t } { .pref.but.label configure -text \ "Click labels for info on each item" destroy $t UNREGISTERED VERSION OF CHM TO PDF CONVERTER }
By THETA-SOFTWARE
[ Team LiB ]
[ Team LiB ]
} PrefDismiss }
There is one fine point in PrefSave. The value from the entry widget for general-purpose items is obtained explicitly in case the user has not already pressed <Return> to update the Tcl variable. The interface is rounded out with the PrefReset and PrefDismiss procedures. A reset is achieved by clearing the option database and reloading it, and then temporarily clearing the preference items and their associated variables and then redefining them with Pref_Add.
Example 45-9 Read settings from the preferences file UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
proc PrefReset {} { global pref # Re-read user defaults option clear PrefReadFile $pref(appDefaults) startup PrefReadFile $pref(userDefaults) user # Clear variables set items $pref(items) set pref(items) {} foreach item $items { uplevel #0 [list unset [PrefVar $item]] } # Restore values Pref_Add $items } proc PrefDismiss {} { destroy .pref catch {destroy .prefitemhelp} }
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
The interface lets you dismiss it without saving your preference settings. This is either a feature that lets users try out settings without committing to them, or it is a bug. Fixing this requires UNREGISTERED VERSION set of variablesPDF CONVERTER By THETA-SOFTWARESave, OF CHM TO to shadow the real variables until the user hits introducing a parallel which is tedious to implement. You can also use a grab as described in Chapter 39 to prevent the user from doing anything but setting preferences. This preference package is a slightly simplified version of one I developed for exmh, which has so many preference items that a two-level scheme is necessary. The first level is a menu of preference sections, and each section is created with a single call to Pref_Add. This requires additional arguments to Pref_Add to provide a title for the section and some overall information about the preference section. The display code changes a small amount. The code for the exmh is on the CD-ROM. [ Team LiB ]
[ Team LiB ]
# Command buttons button $t.quit -text Dismiss \ -command [list destroy $frame] button $t.save -text Save \ -command [list Bind_Save $frame] button $t.edit -text Edit \ -command [list Bind_Edit $frame] button $t.new -textCHM \ UNREGISTERED VERSION OF New TO PDF CONVERTER By -command [list Bind_New $frame] pack $t.quit $t.save $t.edit $t.new -side right # A pair of listboxes and a scrollbar scrollbar $frame.s -orient vertical \ -command [list CHM TO \ UNREGISTERED VERSION OFBindYview PDF CONVERTER [list $frame.key $frame.cmd]] listbox $frame.key \ -yscrollcommand [list $frame.s set] \ -exportselection false listbox $frame.cmd \ -yscrollcommand [list $frame.s set] pack $frame.s -side left -fill y pack $frame.key $frame.cmd -side left \ -fill both -expand true
THETA-SOFTWARE
By THETA-SOFTWARE
foreach l [list $frame.key $frame.cmd] { bind $l <B2-Motion>\ [list BindDragto %x %y $frame.key $frame.cmd] bind $l <Button-2> \ [list BindMark %x %y $frame.key $frame.cmd] bind $l <Button-1> \ [list BindSelect %y $frame.key $frame.cmd] bind $l <B1-Motion> \ [list BindSelect %y $frame.key $frame.cmd] bind $l <Shift-B1-Motion> {} bind $l <Shift-Button-1> {} } # Initialize the display Bind_Display $frame }
The Bind_Interface command takes a widget name or class as a parameter. It creates a toplevel and gives it the Bindui class so that resources can be set to control widget attributes. The option add command is used to set up the default listbox sizes. The lowest priority, startup, is given to these resources so that clients of the package can override the size with their own resource specifications. At the top of the interface is a labeled entry widget. The entry holds the name of the class or widget for which the bindings are displayed. The textvariable option of the entry widget is used so that the entry's contents are available in a variable, bind(class). Pressing <Return> in the entry invokes Bind_Display that fills in the display.
global bind $frame.key delete 0 end $frame.cmd delete 0 end foreach seq [bind $bind(class)] { $frame.key insert end $seq $frame.cmd insert end [bind $bind(class) $seq] } }
The Bind_Display procedure fills in the display with the binding information. The bind command returns the events that have bindings, and what the command associated with each event is. Bind_Display loops through this information and fills in the listboxes. [ Team LiB ]
[ Team LiB ]
Example 46-3 Related listboxes are configured to select items UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE together
foreach l [list $frame.key $frame.cmd] { bind $l <Button-1> \ [list BindSelect %y $frame.key $frame.cmd] bind $l <B1-Motion> \ [list BindSelect %y $frame.key $frame.cmd] } proc BindSelect { y args } { foreach w $args { $w select clear 0 end $w select anchor [$w nearest $y] $w select set anchor [$w nearest $y] } }
A single scrollbar scrolls both listboxes. The next example shows the scrollbar command from Bind_Interface and the BindYview procedure that scrolls the listboxes:
The BindYview command is used to change the display of the listboxes associated with the scrollbar. The first argument to BindYview is a list of widgets to scroll, and the remaining arguments are added by the scrollbar to specify how to position the display. The details are essentially private between the scrollbar and the listbox. See page 501 for the details. The args keyword is used to represent these extra arguments, and eval is used to pass them through BindYview. The reasoning for using eval like this is explained in Chapter 10 on page 136. The Listbox class bindings for <Button-2> and <B2-Motion> cause the listbox to scroll as the user drags the widget with the middle mouse button. These bindings are adjusted so that both listboxes move together. The following example shows the bind commands from the Bind_Interface procedure and the BindMark and BindDrag procedures that scroll the listboxes:
The BindMark procedure does a scan mark that defines an origin, and BindDragto does a scan dragto that scrolls the widget based on the distance from that origin. All Tk widgets that scroll support yview, scan mark, and scan dragto. Thus the BindYview, BindMark, and BindDragto procedures are general enough to be used with any set of widgets that scroll together. [ Team LiB ]
[ Team LiB ]
proc Bind_New { frame } { if [catch {frame $frame.edit} f] { # Frame already created set f $frame.edit } else { foreach x {key cmd} { set f2 [frame $f.$x] pack $f2 -fill x -padx 2 label $f2.l -width 11 -anchor e pack $f2.l -side left entry $f2.e pack $f2.e -side left -fill x -expand true bind $f2.e <Return> [list BindDefine $f] } $f.key.l config -text Event: $f.cmd.l config -text Command: } pack $frame.edit -after $frame.top -fill x } proc Bind_Edit { frame } { Bind_New $frame set line [$frame.key curselection] if {$line == {}} { return } $frame.edit.key.e delete 0 end $frame.edit.key.e insert 0 [$frame.key get $line] $frame.edit.cmd.e delete 0 end $frame.edit.cmd.e insert 0 [$frame.cmd get $line]
The -width 11 and -anchor e attributes for the label widgets are specified so that the Event: and Command: labels will line up with the Bindings for label at the top.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Basic Concepts
This chapter assumes that you know some C or C++. You do THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDF CONVERTER By not have to be an expert programmer to use the Tcl APIs. Indeed, one of Tcl's strengths is the ease with which you can extend it by writing C code. This chapter provides a few working examples that explain how to initialize your application and create Tcl commands. It describes how to organize your code into packages. It concludes with notes about compiling Tcl under UNIX, Windows, and Macintosh.
Getting Started
There are two ways to get started writing C code for Tcl applications. The easiest way is to write an extension that just adds some new commands to a standard Tcl shell like tclsh or wish. With this approach the Tcl shell creates a basic framework for you, and your C code just extends this framework with new commands. Tcl supports dynamic loading, so you can compile your extension as a shared library (i.e., DLL) and load it into a running Tcl shell. This is the easiest approach because the Tcl shell handles the details of startup and shutdown, and it provides an interactive console to enter Tcl commands. In the case of wish, it also provides the framework for a graphical user interface. Finally, a loadable extension can be shared easily with other Tcl users. The second way to use the Tcl library is to add it to an existing application. If your application is very simple, it may make sense to turn it into an extension for a standard Tcl shell, which brings you back to the first, simpler approach. However, if your application already has a complex framework (e.g., it is a long-running server process), then you can just add Tcl to it and export the functionality of your application as one or more Tcl commands. Once you do this, you will find that you can extend your application with all the features provided by Tcl.
based commands, but the APIs are a little more complex. For simple tasks, and for learning, you can use just the simpler string-based command interface.
SWIG
David Beasley created a nice tool called SWIG (Simple Wrapper Interface Generator) that generates the C code that implements command procedures that expose a C or C++ API as Tcl commands. This can be a great time saver if you need to export many calls to Tcl. The only drawback is that a C interface may not feel that comfortable to the script writer. Handcrafted Tcl interfaces can be much nicer, but automatically-generated interfaces are just fine for rapid prototyping and for software testing environments. You can learn more about SWIG at its web site: http://www.swig.org/
Tcl Initialization
Before you can use your command procedures from Tcl scripts, you need to register them with Tcl. In some cases, you may also need to create the Tcl interpreter, although this is done for you by the standard Tcl shells. If you are writing an extension, then you must provide an initialization procedure. The job of this procedure is to register Tcl commands with Tcl_CreateCommand or Tcl_CreateObjCommand. This is shown in Example 47-1 on page 698. The name of this procedure must end with _Init, as in Expect_Init, Blt_Init, or Foo_Init, if you plan to create your extension as a shared library. This procedure is called automatically when the Tcl script loads your library with the load command, which is described on page 697. If you are embedding Tcl into an existing application, then you should initialize Tcl with Tcl_FindExecutable and Tcl_CreateInterp. The first call helps the Tcl runtime initialize itself, and determines the return value for info nameofexecutable. Tcl_CreateInterp creates an interpreter that includes the standard commands listed in Table 1-4 on page 22. You still have to initialize all your custom commands (e.g., by calling Foo_Init) and arrange to run a script using Tcl_Eval or Tcl_EvalFile. However, there are a lot of details to get right, and Tcl provides a higher level interface in Tcl_Main and Tcl_AppInit. Tcl_Main creates the interpreter for you, processes command line arguments to get an initial script to run, and even provides an interactive command loop. It calls out to Tcl_AppInit, which you provide, to complete the initialization of the interpreter. The use of Tcl_Main is shown in Example 47-13 on page 720. There are even more details to get right with a Tk application because of the window system and the event loop. These details are hidden behind Tk_Main, which makes a similar call out to Tk_AppInit that you provide to complete initialization.
You can also set and query Tcl variables from C using the Tcl_SetVar and Tcl_GetVar procedures. Again, there are several variations on these procedures that account for different types, like strings or Tcl_Obj values, and scalar or array variables. The Tcl_LinkVar procedure causes a Tcl variable to mirror a C variable. Modifications to the Tcl variable are reflected in the C variable, and reading the Tcl variable always returns the C variable's value. Tcl_LinkVar is built on a more general variable tracing facility, which is exposed to Tcl as the trace command, and available as the Tcl_TraceVar C API.
A well-behaved extension should provide both a C and Tcl API, but most of the core Tcl and Tk commands do not provide an exported C API. This forces you to eval Tcl scripts to get at their functionality. Example 47-15 on page 725 shows the Tcl_Invoke procedure that can help you work around this limitation. Tcl_Invoke is used to invoke a Tcl command without the parsing and substitution overhead of Tcl_Eval.
Finally, it is worth emphasizing that the source code of the Tcl C library is a great source of information. The code is well written and well commented. If you want to see how something really works, reading the code is worthwhile. [ Team LiB ]
[ Team LiB ]
The library is the file name of the shared library file (i.e., the DLL), and package is the name of the package implemented by the library. This name corresponds to the package_Init procedure called to initialize the package (e.g., Random_Init) The optional interp argument lets you load the library into a slave interpreter. If the library is in /usr/local/lib/random.so, then a Tcl script can load the package like this:
On most UNIX systems, you can set the LD_LIBRARY_PATH environment variable to a colonseparated list of directories that contain shared libraries. If you do that, then you can use relative names for the libraries:
On Macintosh, the load command looks for libraries in the same folder as the Tcl/Tk application (i.e., Wish) and in the System:Extensions:Tool Command Language folder:
On Windows, load looks in the same directory as the Tcl/Tk application, the current directory, the C:\Windows\System directory (or C:\Windows\System32 on Windows NT), the C:\Windows directory, and then the directories listed in the PATH environment variable.
Fortunately, you usually do not have to worry about these details because the Tcl package facility can manage your libraries for you. Instead of invoking load directly, your scripts can
use package require instead. The package facility keeps track of where your libraries are and knows how to call load for your platform. It is described in Chapter 12.
/* * Declare that we implement the random package * so scripts that do "package require random" * can load the library automatically. */ Tcl_PkgProvide(interp, "random", "1.1"); return TCL_OK;
Using Tcl_PkgProvide
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Random_Init uses Tcl_PkgProvide to declare what package is provided by the C code. This call helps the pkg_mkIndex procedure learn what libraries provide which packages. pkg_mkIndex saves this information in a package database, which is a file named pkgIndex.tcl. The package require command looks for the package database files along your auto_path and automatically loads your package. The general process is:
Create your shared library and put it into a directory listed on your auto_path variable, or a subdirectory of one of the directories on your auto_path. Run the pkg_mkIndex procedure in that directory, giving it the names of all the script files and shared libraries it should index. Now your shared library is ready for use by other scripts. A script uses package require to request a package. The correct load command for your system will be used the first time a command from your package is used. The package command is the same on all platforms: package require random => 1.1
[ Team LiB ]
A C Command Procedure
Tcl 8.0 introduced a new interface for Tcl commands that is designed to work efficiently with its internal on-the-fly byte code compiler. The original interface to commands was string oriented. This resulted in a lot of conversions between strings and internal formats such as integers, double-precision floating point numbers, and lists. The new interface is based on the Tcl_Obj type that can store different types of values. Conversions between strings and other types are done in a lazy fashion, and the saved conversions help your scripts run more efficiently. This section shows how to build a random number command using both interfaces. The stringbased interface is simpler, and we start with that to illustrate the basic concepts. You can use it for your first experiments with command procedures. Once you gain some experience, you can start using the interfaces that use Tcl_Obj values instead of simple strings. If you have old command procedures from before Tcl 8.0, you need to update them only if you want extra efficiency. The string and Tcl_Obj interfaces are very similar, so you should find updating your command procedures straightforward.
When the script invokes cmd, Tcl calls CmdProc like this:
The interp is type Tcl_Interp *, and it is a general handle on the state of the interpreter. Most Tcl C APIs take this parameter. The data is type ClientData, which is an opaque pointer. You can use this to associate state with your command. You register this state along with your command procedure, and then Tcl passes it back to you when the command is invoked. This is especially useful with Tk widgets, which are explained in more detail in Chapter 49. Our simple RandomCmd command procedure does not use this feature, so it passes NULL into Tcl_CreateCommand. The DeleteProc is called when the command is destroyed, which is typically when the whole Tcl interpreter is being deleted. If your state needs to be cleaned up, you can do it then. RandomCmd does not use this feature, either. The arguments from the Tcl command are available as an array of strings defined by an argv parameter and counted by an argc parameter. This is the same interface that a main program has to its command line arguments. Example 47-2 shows the RandomCmd command procedure:
/* * RandomCmd -* This implements the random Tcl command. With no arguments * the command returns a random integer. * With an integer valued argument "range", * it returns a random integer between 0 and range. */ UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE int RandomCmd(ClientData clientData, Tcl_Interp *interp, int argc, CONST char *argv[]) { int rand, error; int range = 0; UNREGISTERED buffer[20]; CHM TO PDF CONVERTER By THETA-SOFTWARE char VERSION OF if (argc > 2) { interp->result = "Usage: random ?range?"; return TCL_ERROR; } if (argc == 2) { if (Tcl_GetInt(interp, argv[1], &range) != TCL_OK) { return TCL_ERROR; } } rand = random(); if (range != 0) { rand = rand % range; } sprintf(buf, "%d", rand); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_OK; }
The return value of a Tcl command is really two things: a result string and a status code. The result is a string that is either the return value of the command as seen by the Tcl script, or an error message that is reported upon error. For example, if extra arguments are passed to the command procedure, it raises a Tcl error by doing this:
The random implementation accepts an optional argument that is a range over which the random numbers should be returned. The argc parameter is tested to see if this argument has been given in the Tcl command. argc counts the command name as well as the arguments, so in our case argc == 2 indicates that the command has been invoked something like:
random 25
The procedure Tcl_GetInt converts the string-valued argument to an integer. It does error checking and sets the interpreter's result in the case of error, so we can just return if it fails to return TCL_OK.
Finally, the real work of calling random is done. The result is formatted into a string in a temporary buffer, and the result is set with Tcl_SetResult. A normal return looks like this:
Tcl_SetResult(interp, string, freeProc) Tcl_AppendResult(interp, str1, str2, str3, (char *)NULL) Tcl_AppendElement(interp, string)
Tcl_SetResult sets the return value to be string. The freeProc argument describes how the result should be disposed of: TCL_STATIC is used in the case where the result is a constant string allocated by the compiler, TCL_DYNAMIC is used if the result is allocated with Tcl_Alloc, which is a platform- and compiler-independent version of malloc, and TCL_VOLATILE is used if the result is in a stack variable. In the TCL_VOLATILE case, the Tcl interpreter makes a copy of the result before calling any other command procedures. Finally, if you have your own memory allocator, pass in the address of the procedure that should free the result.
Tcl_AppendResult copies its arguments into the result buffer, reallocating the buffer if necessary. The arguments are concatenated onto the end of the existing result, if any. Tcl_AppendResult can be called several times to build a result. The result buffer is overallocated, so several appends are efficient. Tcl_AppendElement adds the string to the result as a proper Tcl list element. It might add braces or backslashes to get the proper structure.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE The Tcl_Obj Command Interface
The Tcl_Obj command interface replaces strings with dual-ported values. The arguments to a command are an array of pointers to Tcl_Obj structures, and the result of a command is also of type Tcl_Obj. The replacement of strings by Tcl_Obj values extends throughout Tcl. The value of a Tcl variable is kept in a Tcl_Obj, and Tcl scripts are stored in a Tcl_Obj, too. You can continue to use the old string-based API, which converts strings to Tcl_Obj values, but this conversion adds overhead. The Tcl_Obj structure stores both a string representation and a native representation. The native representation depends on the type of the value. Tcl lists are stored as an array of pointers to strings. Integers are stored as 32-bit integers. Floating point values are stored in double-precision. Tcl scripts are stored as sequences of byte codes. Conversion between the native representation and a string are done upon demand. There are APIs for accessing Tcl_Obj values, so you do not have to worry about type conversions unless you implement a new type. Example 47-3 shows the random command procedure using the Tcl_Obj interfaces:
} rand = random(); if (range != 0) { rand = rand % range; } resultPtr = Tcl_GetObjResult(interp); Tcl_SetIntObj(resultPtr, rand); return TCL_OK; }
Compare Example 47-2 with Example 47-3. You can see that the two versions of the C command procedures are similar. The Tcl_GetInt call is replaced with Tcl_GetIntFromObj call. This receives an integer value from the command argument. This call can avoid conversion from string to integer if the Tcl_Obj value is already an integer. The result is set by getting a handle on the result object and setting its value. This is done instead of accessing the interp->result field directly:
The Tcl_WrongNumArgs procedure is a convenience procedure that formats an error message. You pass in objv, the number of arguments to use from it, and additional string. The example creates this message:
Example 47-3 does not do anything obvious about storage management. Tcl initializes the result object before calling your command procedure and takes care of cleaning it up later. It is sufficient to set a value and return TCL_OK or TCL_ERROR. In more complex cases, however, you have to worry about reference counts to Tcl_Obj values. This is described in more detail later. If your command procedure returns a string, then you will use Tcl_SetStringObj. This command makes a copy of the string you pass it. The new Tcl interfaces that take strings also take length arguments so you can pass binary data in strings. If the length is minus 1, then the string is terminated by a NULL byte. A command that always returned "boring" would do this:
This is a bit too boring. In practice you may need to build up the result piecemeal. With the string-based API, you use Tcl_AppendResult. With the Tcl_Obj API you get a pointer to the result and use Tcl_AppendToObj or Tcl_AppendStringsToObj:
The Tcl_NewTypeObj allocates storage for a Tcl_Obj and sets its reference count to zero. Tcl_IncrRefCount and Tcl_DecrRefCount increment and decrement the reference count on an object. Tcl_DecrRefCount frees the storage for Tcl_Obj when it goes to zero. The initial
reference count of zero was chosen because functions like Tcl_SetObjResult automatically increment the reference count on an object. The Tcl_GetTypeFromObj and Tcl_SetTypeObj procedures just get and set the value; the reference count does not change. Type conversions are automatic. You can set a Tcl_Obj value to an integer and get back a string or double precision number later. The type implementations automatically take care of the storage for the Tcl_Obj value as it changes. Of course, if a Tcl_Obj stays the same type, then no string conversions are necessary and accesses are more efficient.
*/ Tcl_SetIntObj(objPtr, i+1); /* * Setting the result object adds a new reference, * so we decrement because we no longer care about * the integer object we modified. */ Tcl_SetObjResult(interp, objPtr); /* refCount 2*/ UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_DecrRefCount(objPtr); /* refCount 1*/ /* * Now only the interpreter result has a reference to objPtr. */ return TCL_OK; } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Pitfalls of Shared
Tcl_Obj
Values
You have to be careful when using the values from a Tcl_Obj structure. The Tcl C library provides many procedures like Tcl_GetStringFromObj, Tcl_GetIntFromObj, Tcl_GetListFromObj, and so on. These all operate efficiently by returning a pointer to the native representation of the object. They will convert the object to the requested type, if necessary. The problem is that shared values can undergo type conversions that may invalidate your reference to a particular type of the value.
Value references are only safe until the next Tcl_Get*FromObj call.
Consider a command procedure that takes two arguments, an integer and a list. The command procedure has a sequence of code like this:
Tcl_ListObjGetElements(interp, objv[1], &objc, &listPtr); /* Manipulate list */ Tcl_GetIntFromObj(interp, objv[2], &int); /* list may be invalid here */
If, by chance, both arguments have the same value, (e.g., 1 and 1), which is possible for a Tcl list and an integer, then Tcl will automatically arrange to share these values between both arguments. The pointers in objv[1] and objv[2] will be the same, and the reference count on the Tcl_Obj they reference will be at least 2. The first Tcl_ListObjGetElements call ensures the value is of type list, and it returns a direct pointer to the native list representation. However, Tcl_GetIntFromObj then helpfully converts the Tcl_Obj value to an integer. This deallocates the memory for the list representation, and now listPtr is a dangling pointer! This particular example can be made safe by reversing the calls because Tcl_GetIntFromObj copies the integer value:
Tcl_GetIntFromObj(interp, objv[2], &int); Tcl_ListObjGetElements(interp, objv[1], &objc, &listPtr); /* int is still a good copy of the value */
By the way, you should always test your Tcl_Get* calls in case the format of the value is incompatible with the requested type. If the object is not a valid list, the following command returns an error:
[ Team LiB ]
[ Team LiB ]
The blob command creates and manipulates blobs. Each blob has a name and some associated properties. The blob command uses a hash table to keep track of blobs by their name. The UNREGISTERED VERSION OFof stateTO PDF CONVERTER By that needs to be cleaned up when CHM associated with a command THETA-SOFTWARE hash table is an example the Tcl interpreter is destroyed. The Tcl hash table implementation is nice and general, too, so you may find it helpful in a variety of situations. You can associate a Tcl script with a blob. When you poke the blob, it invokes the script. This shows how easy it is to associate behaviors with your C extensions. Example 47-6 shows the data structures used to implement blobs.
blob is a key, so TCL_STRING_KEYS is used. If you use an integer key, or the address of a data structure, use TCL_ONE_WORD_KEYS. You can also have an array of integers (i.e., a chunk of data) for the key. In this case, pass in an integer larger than 1 that represents the size of the integer array used as the key. The BlobCleanup command cleans up the hash table. It iterates through all the elements of the hash table and gets the value associated with each key. This value is cast into a pointer to a Blob data structure. This iteration is a special case because each entry is deleted as we go by the BlobDelete procedure. If you do not modify the hash table, you continue the search with Tcl_NextHashEntry instead of calling Tcl_FirstHashEntry repeatedly.
void BlobCleanup(ClientData data) { BlobState *statePtr = (BlobState *)data; Blob *blobPtr; Tcl_HashEntry *entryPtr; Tcl_HashSearch search;
Tcl_Alloc , ckalloc ,
and malloc
Tcl provides its own memory allocator, Tcl_Alloc and Tcl_Free, which can be used to replace poor malloc implementations that some systems have. Tcl 8.4 has a new allocator that supports threaded applications well. The memory allocator also supports memory debugging if you compile with -DTCL_MEM_DEBUG. A Tcl memory command is added that reports on memory use and can help you track down memory problems. To support optional memory debugging, tcl.h defines ckalloc and ckfree macros that call different allocation routines depending on compile-time options. Because of this, your code should not use malloc and free directly, nor should it call Tcl_Alloc and Tcl_Free directly. Use the ckalloc and ckfree macros everywhere. In general, it is not safe to allocate memory with Tcl_Alloc or ckalloc and free it with free, or allocate memory with malloc and free it with Tcl_Free or ckfree. Also, if you compile some code with -DTCL_MEM_DEBUG, and some code without that option, you get an immediate crash.
/* * BlobCmd -* * This implements the blob command, which has these * subcommands: * create * command name ?script? * data name ?value? * N name ?value? * names ?pattern? * poke name * delete name * * Results: * A standard Tcl command result. */ int BlobCmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { BlobState *statePtr = (BlobState *)data; Blob *blobPtr; Tcl_HashEntry *entryPtr; Tcl_Obj *valueObjPtr; /* * The subCmds array defines the allowed values for the * first argument. These are mapped to values in the * BlobIx enumeration by Tcl_GetIndexFromObj. */ char *subCmds[] = { "create", "command", "data", "delete", "N", "names", "poke", NULL }; enum BlobIx { CreateIx, CommandIx, DataIx, DeleteIx, NIx, NamesIx, PokeIx }; int result, index; if (objc == 1 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subCmds, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (((index == NamesIx || index == CreateIx) && (objc > 2)) || ((index == PokeIx || index == DeleteIx) && (objc == 4))) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR;
} if (index == CreateIx) { return BlobCreate(interp, statePtr); } if (index == NamesIx) { return BlobNames(interp, statePtr); } if (objc < 3) { UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_WrongNumArgs(interp, 1, objv, "option blob ?arg ...?"); return TCL_ERROR; } else if (objc == 3) { valueObjPtr = NULL; } elseVERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED { valueObjPtr = objv[3]; } /* * The rest of the commands take a blob name as the third * argument. Hash from the name to the Blob structure. */ entryPtr = Tcl_FindHashEntry(&statePtr->hash, Tcl_GetString(objv[2])); if (entryPtr == NULL) { Tcl_AppendResult(interp, "Unknown blob: ", Tcl_GetString(objv[2]), NULL); return TCL_ERROR; } blobPtr = (Blob *)Tcl_GetHashValue(entryPtr); switch (index) { case CommandIx: { return BlobCommand(interp, blobPtr, valueObjPtr); } case DataIx: { return BlobData(interp, blobPtr, valueObjPtr); } case NIx: { return BlobN(interp, blobPtr, valueObjPtr); } case PokeIx: { return BlobPoke(interp, blobPtr); } case DeleteIx: { return BlobDelete(blobPtr, entryPtr); } } }
Building a List
The BlobNames procedure iterates through the elements of the hash table using Tcl_FirstHashEntry and Tcl_NextHashEntry. It builds up a list of the names as it goes along. Note that the object reference counts are managed for us. The Tcl_NewStringObj
returns a Tcl_Obj with reference count of zero. When that object is added to the list, the Tcl_ListObjAppendElement procedure increments the reference count. Similarly, the Tcl_NewListObj returns a Tcl_Obj with reference count zero, and its reference count is incremented by Tcl_SetObjResult:
Keeping References to
Tcl_Obj
Values
A blob has two simple properties: an integer N and a general Tcl_Obj value. You can query and set these properties with the BlobN and BlobData procedures. The BlobData procedure keeps a pointer to its Tcl_Obj argument, so it must increment the reference count on it:
N = blobPtr->N; } Tcl_SetObjResult(interp, Tcl_NewIntObj(N)); return TCL_OK; } int BlobData(Tcl_Interp *interp, Blob *blobPtr, Tcl_Obj *objPtr) { if (objPtr != NULL) { if (blobPtr->objPtr != NULL) { Tcl_DecrRefCount(blobPtr->objPtr); } Tcl_IncrRefCount(objPtr); blobPtr->objPtr = objPtr; } if (blobPtr->objPtr != NULL) { Tcl_SetObjResult(interp, blobPtr->objPtr); } return TCL_OK; }
int BlobPoke(Tcl_Interp *interp, Blob *blobPtr) { int result = TCL_OK; if (blobPtr->cmdPtr != NULL) { Tcl_Preserve(blobPtr); result = Tcl_EvalObj(interp, blobPtr->cmdPtr); /* VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED * Safe to use blobPtr here */ Tcl_Release(blobPtr); /* * blobPtr may not be valid here */ UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE } return result; }
It turns out that BlobCmd does not actually use the blobPtr after calling Tcl_EvalObj, so it could get away without using Tcl_Preserve and Tcl_Release. These procedures do add some overhead: They put the pointer onto a list of preserved pointers and have to take it off again. If you are careful, you can omit these calls. However, it is worth noting the potential problems caused by evaluating arbitrary Tcl scripts! [ Team LiB ]
[ Team LiB ]
CONST
The const keyword in C is used to create a read-only variable. Once it is set, it cannot be modified. A common use of CONST is in parameter declarations to imply that the parameter cannot be modified by a procedure. The Tcl API definitions use a CONST macro instead of const to allow for older compilers that do not support const. Several of the Tcl APIs were changed in Tcl 8.4 to include CONST where they previously did not. The most significant change is in the signature of string-based command procedures like RandomCmd in this chapter. Changes to tcl.h are generally backward compatible, so this change met with some debate. Most liked the addition of CONST because it allows better error checking, but the changes cause compiler warning messages if you compile old code with the 8.4 tcl.h. In some organizations, even compiler warnings are not allowed in code, so you may be compelled to clean up your code. There are two reasons you may not be able to change older code. First, you may need to compile the same code against older and newer versions of Tcl. Second, you may not have the time to clean up the code. CONST definitions have a tendency to percolate throughout your code. To support these scenarios, 8.4 adds compile-time defines that change the effect of the CONST additions. Table 47-1 describes these definitions:
Table 47-1. Defines to control the meaning of CONST in the Tcl APIs
NO_CONST USE_NON_CONST This defines CONST to nothing so no const keywords are used at all. This define has existed for some time. Do not use any of the new CONST keywords added in Tcl 8.4.
USE_COMPAT_CONST Only use the CONST keywords added for the return values of the Tcl 8.4 APIs. Almost all APIs return CONST values now. [ Team LiB ]
[ Team LiB ]
Tcl_DString ds; Tcl_DStringInit(&ds); Tcl_DStringAppend(&ds, "some value", -1); Tcl_DStringAppend(&ds, "something else", -1); Tcl_DStringResult(interp, &ds);
The Tcl_DStringInit call initializes a string pointer inside the structure to point to a static buffer that is also inside the structure. The Tcl_DStringAppend call grows the string. If it would exceed the static buffer, then a new buffer is allocated dynamically and the string is copied into it. The last argument to Tcl_DStringAppend is a length, which can be minus 1 if you want to copy until the trailing NULL byte in your string. You can use the string value as the result of your Tcl command with Tcl_DStringResult. This passes ownership of the string to the interpreter and automatically cleans up the Tcl_DString structure. If you do not use the string as the interpreter result, then you must call Tcl_DStringFree to ensure that any dynamically allocated memory is released:
Tcl_DStringFree(&ds);
You can get a direct pointer to the string you have created with Tcl_DStringValue:
name = Tcl_DStringValue(&ds);
There are a handful of additional procedures in the DString API that you can read about in the reference material. There are some that create lists, but this is better done with the Tcl_Obj interface (e.g., Tcl_NewListObj and friends). To some degree, a Tcl_Obj can replace the use of a Tcl_DString. For example, the Tcl_NewStringObj and Tcl_AppendToObj allocate a Tcl_Obj and append strings to it.
However, there are a number of Tcl API procedures that take Tcl_DString types as arguments instead of the Tcl_Obj type. Also, for small strings, the DString interface is still more efficient because it can do less dynamic memory allocation.
You can then pass Tcl_DStringValue(&ds) to your system call that expects a native string. Afterwards you need to call Tcl_DStringFree(&ds) to free up any memory allocated by Tcl_UtfToExternalDString. To translate strings the other way, use Tcl_ExternalToUtfDString:
The third argument to these procedures is the length of string in bytes (not characters), and minus 1 means that Tcl should calculate it by looking for a NULL byte. Tcl stores its UTF-8 strings with a NULL byte at the end so it can do this. The first argument to these procedures is the encoding to translate to or from. NULL means the system encoding. If you have data in nonstandard encodings, or need to translate into something other than the system encoding, you need to get a handle on the encoding with Tcl_GetEncoding, and free that handle later with Tcl_FreeEncoding:
The names of the encodings are returned by the encoding names Tcl command, and you can query them with a C API, too. Windows has a quirky string data type called TCHAR, which is an 8-bit byte on Windows 95/98, and a 16-bit Unicode character on Windows NT and Windows CE. If you use a C API that takes an array of TCHAR, then you have to know what kind of system you are running on to use it
properly. Tcl provides two procedures that deal with this automatically. Tcl_WinTCharToUf works like Tcl_ExternalToUtfDString, and Tcl_WinUtfToTChar works like Tcl_UtfToExternalDString:
[ Team LiB ]
Tcl_Main
and Tcl_AppInit
This section describes how to make a custom main program that includes Tcl. However, the need for custom main programs has been reduced by the use of loadable modules. If you create your commands as a loadable package, you can just load them into tclsh or wish. Even if you do not need a custom main, this section will explain how all the pieces fit together. The Tcl library supports the basic application structure through the Tcl_Main procedure that is designed to be called from your main program. Tcl_Main does three things: It calls Tcl_CreateInterp to create an interpreter that includes all the standard Tcl commands like set and proc. It also defines a few Tcl variables like argc and argv. These have the command-line arguments that were passed to your application. It calls Tcl_AppInit, which is not part of the Tcl library. Instead, your application provides this procedure. In Tcl_AppInit you can register additional application-specific Tcl commands. It reads a script or goes into an interactive loop. You call Tcl_Main from your main program and provide an implementation of the Tcl_AppInit procedure:
int Tcl_AppInit(Tcl_Interp *interp) { /* * Tcl_Init reads init.tcl from the Tcl script library. */ if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE /* * Register application-specific commands. */ Tcl_CreateObjCommand(interp, "plus1", Plus1ObjCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); Random_Init(interp); UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Blob_Init(interp); /* * This file is read if no script is supplied. */ Tcl_SetVar(interp, "tcl_rcFileName", "~/.mytcl", TCL_GLOBAL_ONLY); /* * Test of Tcl_Invoke, which is defined on page 725. */ Tcl_Invoke(interp, "set", "foo", "$xyz [foo] {", NULL); return TCL_OK; }
The main program calls Tcl_Main with the argc and argv parameters passed into the program. These are the strings passed to the program on the command line, and Tcl_Main will store these values into Tcl variables by the same name. Tcl_Main is also given the address of the initialization procedure, which is Tcl_AppInit in our example. Tcl_AppInit is called by Tcl_Main with one argument, a handle on a newly created interpreter. There are three parts to the Tcl_AppInit procedure: The first part initializes the various packages the application uses. The example calls Tcl_Init to set up the script library facility described in Chapter 12. The core Tcl commands have already been defined by Tcl_CreateInterp, which is called by Tcl_Main before the call to Tcl_AppInit. The second part of Tcl_AppInit does application-specific initialization. The example registers the command procedures defined earlier in this Chapter. The third part defines a Tcl variable, tcl_RcFileName, which names an application startup script that executes if the program is used interactively. You can use your custom program just like tclsh, except that it includes the additional commands you define in your Tcl_AppInit procedure. The sample makefile on the CD creates a program named mytcl. You can compile and run that program and test random and the other commands.
Tk_Main
The structure of Tk applications is similar. The Tk_Main procedure creates a Tcl interpreter and
the main Tk window. It calls out to a procedure you provide to complete initialization. After your Tk_AppInit returns, Tk_Main goes into an event loop until all the windows in your application have been destroyed. Example 47-14 shows a Tk_AppInit used with Tk_Main. The main program processes its own command-line arguments using Tk_ParseArgv, which requires a Tcl interpreter for error reporting. The Tk_AppInit procedure initializes the clock widget example that is the topic of Chapter 49:
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); void ClockObjDestroy(ClientData clientData); int Tk_AppInit(Tcl_Interp *interp) { /* * Initialize packages UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE */ if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } if (Tk_Init(interp) == TCL_ERROR) { return TCL_ERROR; UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE } /* * Define application-specific commands here. */ Tcl_CreateCommand(interp, "wclock", ClockCmd, (ClientData)Tk_MainWindow(interp), (Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand(interp, "oclock", ClockObjCmd, (ClientData)NULL, ClockObjDestroy); /* * Define start-up filename. This file is read in * case the program is run interactively. */ Tcl_SetVar(interp, "tcl_rcFileName", "~/.mytcl", TCL_GLOBAL_ONLY); return TCL_OK; }
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
You should be aware that Tcl_Eval may modify the string that is passed into it as a side effect of the way substitutions are performed. If you pass a constant string to Tcl_Eval, make sure your compiler has not put the string constant into read-only memory. If you use the gcc compiler, you may need to use the -fwritable-strings option. Chapter 48 shows how to get the right compilation settings for your system.
Variations on Tcl_Eval
There are several variations on Tcl_Eval. The possibilities include strings or Tcl_Obj values, evaluation at the current or global scope, a single string (or Tcl_Obj value) or a variable number of arguments, and optional byte-code compilation. The most general string-based eval is Tcl_EvalEx, which takes a counted string and some flags:
The flags are TCL_GLOBAL_EVAL and TCL_EVAL_DIRECT, which bypasses the byte-code compiler. For code that is executed only one time, TCL_EVAL_DIRECT may be more efficient.
Tcl_GlobalEval is equivalent to passing in the TCL_GLOBAL_EVAL flag. The Tcl_VarEval procedure takes a variable number of strings arguments and concatenates them before evaluation:
Tcl_EvalObj takes an object as an argument instead of a simple string. The string is compiled into byte codes the first time it is used. If you are going to execute the script many times, then the Tcl_Obj value caches the byte codes for you. The general Tcl_Obj value interface to Tcl_Eval is Tcl_EvalObjEx, which takes the same flags as Tcl_EvalEx:
For variable numbers of arguments, use Tcl_EvalObjv, which takes an array of Tcl_Obj pointers. This routine concatenates the string values of the various Tcl_Obj values before parsing the resulting Tcl command:
Bypassing Tcl_Eval
In a performance-critical situation, you may want to avoid some of the overhead associated with Tcl_Eval. David Nichols showed me how to call the implementation of a C command procedure directly. The trick is facilitated by the Tcl_GetCommandInfo procedure that returns the address of the C command procedure for a Tcl command, plus its client data pointer. The Tcl_Invoke procedure is shown in Example 47-15. It is used much like Tcl_VarEval, except that each of its arguments becomes an argument to the Tcl command without any substitutions being performed. For example, you might want to insert a large chunk of text into a text widget without worrying about the parsing done by Tcl_Eval. You could use Tcl_Invoke like this:
Or:
No substitutions are performed on any of the arguments because Tcl_Eval is out of the picture. The variable foo gets the following literal value:
$xyz [blah] {
Example 47-15 shows Tcl_Invoke. The procedure is complicated for two reasons. First, it must
handle a Tcl command that has either the object interface or the old string interface. Second, it has to build up an argument vector and may need to grow its storage in the middle of building it. It is a bit messy to deal with both at the same time, but it lets us compare the object and string interfaces. The string interfaces are simpler, but the object interfaces run more efficiently because they reduce copying and type conversions.
Example 47-15 Calling C command procedure directly with Tcl_Invoke UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
#include <tcl.h> /* * Tcl_Invoke -UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE * Directly invoke a Tcl command or procedure * * Call Tcl_Invoke somewhat like Tcl_VarEval * Each arg becomes one argument to the command, * with no further substitutions or parsing. */ /* VARARGS2 */ /* ARGSUSED */ int Tcl_Invoke TCL_VARARGS_DEF(Tcl_Interp *, arg1) { va_list argList; Tcl_Interp *interp; char *cmd; /* Command name */ char *arg; /* Command argument */ char **argv; /* String vector for arguments */ int argc, i, max; /* Number of arguments */ Tcl_CmdInfo info; /* Info about command procedures */ int result; /* TCL_OK or TCL_ERROR */ interp = TCL_VARARGS_START(Tcl_Interp *, arg1, argList); Tcl_ResetResult(interp); /* * Map from the command name to a C procedure */ cmd = va_arg(argList, char *); if (! Tcl_GetCommandInfo(interp, cmd, &info)) { Tcl_AppendResult(interp, "unknown command \"", cmd, "\"", NULL); va_end(argList); return TCL_ERROR; } max = 20; /* Initial size of argument vector */
#if TCL_MAJOR_VERSION > 7 /* * Check whether the object interface is preferred for * this command */ if (info.isNativeObjectProc) { Tcl_Obj **objv; /* Object vector for arguments */
Tcl_Obj *resultPtr; /* The result object */ int objc; objv = (Tcl_Obj **) ckalloc(max * sizeof(Tcl_Obj *)); objv[0] = Tcl_NewStringObj(cmd, strlen(cmd)); Tcl_IncrRefCount(objv[0]); /* ref count == 1*/ objc = 1; /* * Build a vector out of the rest of the arguments */ while (1) { arg = va_arg(argList, char *); if (arg == (char *)NULL) { objv[objc] = (Tcl_Obj *)NULL; break; } objv[objc] = Tcl_NewStringObj(arg, strlen(arg)); Tcl_IncrRefCount(objv[objc]); /* ref count == 1*/ objc++; if (objc >= max) { /* allocate a bigger vector and copy old one */ Tcl_Obj **oldv = objv; max *= 2; objv = (Tcl_Obj **) ckalloc(max * sizeof(Tcl_Obj *)); for (i = 0 ; i < objc ; i++) { objv[i] = oldv[i]; } Tcl_Free((char *)oldv); } } va_end(argList); /* * Invoke the C procedure */ result = (*info.objProc)(info.objClientData, interp, objc, objv); /* * Make sure the string value of the result is valid * and release our references to the arguments */ (void) Tcl_GetStringResult(interp); for (i = 0 ; i < objc ; i++) { Tcl_DecrRefCount(objv[i]); } Tcl_Free((char *)objv); return result; } #endif argv = (char **) ckalloc(max * sizeof(char *)); argv[0] = cmd;
argc = 1; /* * Build a vector out of the rest of the arguments */ while (1) { arg = va_arg(argList, char *); argv[argc] = OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION arg; if (arg == (char *)NULL) { break; } argc++; if (argc >= max) { /* allocate bigger PDF CONVERTER one */ UNREGISTERED VERSION OFaCHM TO vector and copy oldBy THETA-SOFTWARE char **oldv = argv; max *= 2; argv = (char **) ckalloc(max * sizeof(char *)); for (i = 0 ; i < argc ; i++) { argv[i] = oldv[i]; } Tcl_Free((char *) oldv); } } va_end(argList); /* * Invoke the C procedure */ result = (*info.proc)(info.clientData, interp, argc, argv); /* * Release the arguments */ Tcl_Free((char *) argv); return result; }
This version of Tcl_Invoke was contributed by Jean Brouwers. He uses TCL_VARARGS_DEF and TCL_VARARGS_START macros to define procedures that take a variable number of arguments. These standard Tcl macros hide the differences in the way you do this on different operating systems and different compilers. It turns out that there are numerous minor differences between compilers that can cause portability problems in a variety of situations. Happily, there is a nice scheme used to discover these differences and write code in a portable way. This is the topic of the next chapter. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
tcl8.4/doc
tcl8.4/library/encoding This contains the Unicode conversion tables. tcl8.4/library/package tcl8.4/test tcl8.4/tools tcl8.4/unix There are several subdirectories (e.g., http2.3) that contain Tcl script packages. This contains the Tcl test suite. These are Tcl scripts that exercise the Tcl implementation. This is a collection of scripts used to help build the Tcl distribution. This contains the .c and .h source files that are specific to UNIX. This also contains the configure script and the Makefile.in template. This contains test files for dynamic loading.
tcl8.4/unix/dltest
tcl8.4/unix/platform tcl8.4/win
These can be used to build Tcl for several different platforms. You create the package directories yourself. This contains the .c and .h source files that are specific to Windows. This also contains the configure script and the Makefile.in template. This may contain a makefile.vc that is compatible with nmake.
lib/tcl8.2
lib/package This contains Tcl scripts for package. Example package directories include tk8.4 and itcl3.2. man This contains reference documentation in UNIX man format.
If you are an expert in configure, you may be aware of other options that give you even finer control over where the different parts of the installation go. However, because of the way Tcl automatically searches for scripts and binary libraries, you should avoid deviating from the recommended structure. [ Team LiB ]
[ Team LiB ]
The configure flags are described in Table 48-3. I use ./configure because I do not have . on my PATH. Furthermore, I want to ensure that I run the configure script from the current directory! If you build for multiple platforms, create subdirectories of unix and run configure from there. For example, here we use ../configure:
% % % %
Make. The configure script uses the Makefile.in template to generate the Makefile. Once configure is complete, you build your program with make: % make
You can do other things with make. To run the test suite, do:
% make test
% make install
The Tcl Extension Architecture defines a standard set of actions, or make targets, for building Tcl sources. Table 48-4 on page 740 shows the standard make targets.
As the configure script executes, it prints out messages about the properties of the current platform. You can tell if you are in trouble if the output contains either of these messages:
or
Either of these means that configure has failed to find a working compiler. In the first case, it assumes that you are configuring on the target system but will cross-compile from a different
system. In the second case, an attempt to compile a tiny sample program failed. In either case, the resulting Makefile is useless. While cross-compiling is common on embedded processors, it is rarely necessary on UNIX and Windows. I see these messages only when my UNIX environment isn't set up right to find the compiler. Many UNIX venders no longer bundle a working compiler. Fortunately, the freely available gcc compiler has been ported to nearly every UNIX system. You should be able to search the Internet and find a ready-to-use gcc package for your platform. On Windows, Tcl is built with either the free mingw compiler the Microsoft Visual C++ compiler. It ships with a batch file, vcvars32.bat, that sets up the environment so that you can run the Microsoft compiler from the command line. You should read that file and configure your environment so that you do not have to remember to run the batch file all the time.
Any flag with disable or enable in its name can be inverted. Table 48-3 lists the nondefault setting, however, so you can just leave the flag out to turn it off. For example, when building Tcl on Solaris with the gcc compiler, shared libraries, debugging symbols, and threading support turned on, use this command:
Your builds will go the most smoothly if you organize all your sources under a common directory. In this case, you can specify the same configure flags for Tcl and all the other extensions you will compile. In particular, you must use the same --prefix and --execprefix so that everything gets installed together. If your source tree is not adjacent to the Tcl source tree, then you must use --withtclinclude or --with-tcllib so that the header files and runtime library can be found during compilation. Typically, this can happen if you build an extension under your home directory, but you are using a copy of Tcl that has been installed by your system administrator. The --withx11include and --with-x11lib flags are similar options necessary when building Tk if your X11 installation is in a nonstandard location.
Installation
The --prefix flag specifies the main directory (e.g., /home/welch/install). The directories listed in Table 48-2 are created under this directory. If you do not specify --exec-prefix, then the platform-specific binary files are mixed into the main bin and lib directories. For example, the tclsh8.4 program and libtcl8.4.so shared library will be installed in:
/home/welch/install/bin/tclsh8.4 /home/welch/install/lib/libtclsh8.4.so
/home/welch/install/lib/tcl8.4 /home/welch/install/man
If you want to have installations for several different platforms, then specify an --exec-prefix that is different for each platform. For example, if you use --execprefix=/home/welch/install/freebsd, then the tclsh8.4 program and libtcl8.4.so shared
/home/welch/install/freebsd/bin/tclsh8.4 /home/welch/install/freebsd/lib/libtclsh8.4.so
UNREGISTERED VERSION OF CHM TO slightly different installation location for binary libraries. PDF CONVERTER By THETA-SOFTWARE platforms. Note that Windows has a
They go into the arch/bin directory along with the main executable programs. [ Team LiB ]
The script libraries and manual pages will remain where they are, so they are shared by all
[ Team LiB ]
Tcl_InitStubs is similar in spirit to Tcl_PkgRequire in that you request a minimum Tcl version number. Stubs have been supported since Tcl 8.1, and the API will evolve in a backward-compatible way. Unless your extension uses new C APIs introduced in later versions, you should specify the lowest version possible so that it is compatible with more Tcl applications. [ Team LiB ]
[ Team LiB ]
Using autoconf
UNREGISTEREDuses the m4 OF CHM TO PDF CONVERTER By THETA-SOFTWAREthe VERSION macro processor to translate the configure.in template into Autoconf
configure script. The configure script is run by /bin/sh (i.e., the Bourne Shell). Creating the configure.in template is simplified by a standard m4 macro library that is distributed with autoconf. In addition, a Tcl distribution contains a tcl.m4 file that has additional autoconf macros. Among other things, these macros support the standard configure flags described in Table 48-3.
Creating configure templates can be complex and confusing. There are several layers of macro processing: m4 macros in configure.in, shell variables in configure, autoconf substitutions in Makefile.in, and Makefile variables. The days I have spent trying to change the Tcl configuration files really made me appreciate the simplicity of Tcl! Fortunately, there is now a standard set of Tcl-specific autoconf macros and a sample Tcl extension that uses them. By editing the configure.in and Makefile.in sample templates, you can ignore the details of what is happening under the covers.
Makefile Templates
Autoconf implements yet another macro mechanism for the Makefile.in templates. The basic idea is that the configure script sets shell variables as it learns things about your system. Finally, it substitutes these variables into Makefile.in to create the working Makefile. The syntax for the substitutions in Makefile.in is:
@configure_variable_name@
For example, the --prefix command line value is put into the prefix shell variable, and then substituted into the Makefile.in template wherever @prefix@ occurs. Often, the make variable and the shell variable have the same name. For example, the following statement in Makefile.in passes the TCL_LIBRARY value determined by configure through to the Makefile:
TCL_LIBRARY = @TCL_LIBRARY@
The AC_SUBST macro specifies what shell variables should be substituted in the Makefile.in template. For example:
AC_SUBST(TCL_LIBRARY)
[ Team LiB ]
[ Team LiB ]
configure.in
The configure.in file is the template for the configure script. This file is very well commented. The places you need to change are marked with __CHANGE__. The first macro to change is:
AC_INIT(generic/sample.h)
The AC_INIT macro lists a file that is part of the distribution. The name is relative to the configure.in file. Other possibilities include ../generic/tcl.h or src/mylib.h, depending on where the configure.in file is relative to your sources. The AC_INIT macro is necessary to support building the package in different directories (e.g., either tcl8.4/unix or tcl8.4/unix/solaris). The next thing in configure.in is a set of variable assignments that define the package's name and version number:
MINOR_VERSION = 4 PATCH_LEVEL =
The package name determines the file names used for the directory and the binary library file created by the Makefile. This name is also used in several configure and Makefile variables. You will need to change all references to "sample" to match the name you choose for your package. The version and patch level support a three-level scheme, but you can leave the patch level empty for two-level versions like 0.4. If you do specify a patch-level, you need to include a leading "." or "p" in it. These values are combined to create the version number like this:
VERSION = ${MAJOR_VERSION}.${MINOR_VERSION}${PATCH_LEVEL}
The configure.in file has a bunch of magic to determine the name of the shared library file (e.g., sample04.dll, libsample.0.4.so, sample.0.2.shlib, etc.). You need to change the macro to match your package name. Define samplestub_LIB_FILE if you want to generate a stub library:
AC_SUBST(sample_LIB_FILE) AC_SUBST(samplestub_LIB_FILE)
There are several standard TEA macros in configure.in that expand to a set of rules to determine the compiler and other settings. Most of these you can leave alone. Although in some cases you need to change the sample if you are creating a Tk extension, or if you need to use internal Tcl or Tk header files. For example, you may need to add TEA_PATH_TKCONFIG and TEA_LOAD_TKCONFIG, and to choose between TEA_PUBLIC_TCL_HEADERS, TEA_PRIVATE_TCL_HEADERS and between TEA_PUBLIC_TK_HEADERS and TEA_PRIVATE_TK_HEADERS. Using private headers (i.e., tclInt.h) is strongly discouraged. There is also a platform-specific section where you may which to adjust the CLEANFILES and EXTRA_SOURCES macros to match your needs. This section also defines the BUILD_sample macro on Windows. Windows compilers create a special case for shared libraries (i.e., DLLs). When you compile the library itself, you need to declare its functions one way. When you compile code that uses the library, you need to declare its functions another way. This complicates sample.h. Happily, the complexity is hidden inside the BUILD_sample macro. We will show later how this is used in sample.h to control the definition of the Sample_Init procedure. The last macro in configure.in determines which templates are processed by the configure script. The sample generates the Makefile from the Makefile.in template with this directive:
AC_OUTPUT([Makefile])
Makefile.in
The Makefile.in template is converted by the configure script into the Makefile. The sample Makefile.in is well commented so that it is easy to see where to make changes. There are a few variables with sample in their name. In particular, sample_LIB_FILE corresponds to a variable name in the configure script. You need to change both files consistently:
sample_LIB_FILE = @sample_LIB_FILE@
The @varname@ syntax is used to substitute the configure variable with its platform-specific name (e.g., libsample.dll or libsample.so). You must define the set of source files and the corresponding object files that are part of the library. In the sample, sample.c implements the core of the Secure Hash Algorithm, PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF CHM TOand the tclsample.c file implements the Tcl command interface:
sample_SOURCES
The object file definitions use the OBJEXT variable that is .o for UNIX and .obj for Windows:
sample_OBJECTS
= $(sample_SOURCES:.c=.@OBJEXT@)
The header files that you want to have installed are assigned to the GENERIC_HDRS variable. The srcdir Make variable is defined during configure to be the name of the directory containing the file named in the AC_INIT macro:
GENERIC_HDRS
= $(srcdir)/generic/sample.h
The sample Makefile includes several standard targets. Even if you decide not to use the sample Makefile.in template, you should still define the targets listed in Table 48-4 to ensure your extension is TEA compliant. Plans for automatic build environments depend on every extension implementing the standard make targets. The targets can be empty, but you should define them so that make will not complain if they are used.
all binaries libraries doc install installbinaries installlibraries install-doc test depend clean distclean
Makes these targets in order: binaries, libraries, doc. Makes executable programs and binary libraries (e.g., DLLs). Makes platform-independent libraries. Generates documentation files. Makes these targets in order: install-binaries, install-libraries, install-doc. Installs programs and binary libraries. Installs script libraries. Installs documentation files. Runs the test suite for the package. Generates makefile dependency rules. Removes files built during the make process. Removes files built during the configure process.
The TCL_STORAGE_CLASS variable is used in the definition of the EXTERN macro. You must use EXTERN before the prototype for any function you want to export from your library:
The _ANSI_ARGS_ macro is used to guard against old C compilers that do not tolerate function prototypes.
On my Solaris machine, the binary library is named sample0.4.so, while on my Windows NT machine the library is named sample04.dll. The package name is Tclsha1, and it implements the sha1 Tcl command. Ordinarily these names would be more consistent with the file names and package names in the template files. However, the names in the sample are designed to be easy to edit in the template. Assuming that you use make install to copy the binary library into the standard location for your site, you can use the package from Tcl like this:
The sha1 command returns a 128 bit encoded hash function of the input string. There are a number of options to sha1 you can learn about by reading the manual page that is included UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE with the extension. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Example 49-1 The Clock_Init procedure
int ClockCmd(ClientData clientData, Tcl_Interp *interp, int argc, CONST char *argv[]); int ClockObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); void ClockObjDelete(ClientData clientData); /* * Clock_Init is called when the package is loaded. */ int Clock_Init(Tcl_Interp *interp) { if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { return TCL_ERROR; } Tcl_CreateCommand(interp, "wclock", ClockCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand(interp, "oclock", ClockObjCmd, (ClientData)NULL, ClockObjDelete); Tcl_PkgProvide(interp, "Tkclock", "1.0"); return TCL_OK; }
[ Team LiB ]
[ Team LiB ]
Tcl_Obj *padYPtr; /* The original padY string value */ int flags; /* Flags defined below */ } Clock; /* * Flag bit definitions. */ #define REDRAW_PENDING 0x1 #define VERSION 0x2 UNREGISTEREDGOT_FOCUS OF CHM TO PDF CONVERTER By THETA-SOFTWARE #define TICKING 0x4
[ Team LiB ]
[ Team LiB ]
clockPtr->highlightBg = NULL; clockPtr->tkfont = NULL; clockPtr->textGC = None; clockPtr->token = NULL; clockPtr->clock = NULL; clockPtr->format = NULL; clockPtr->numChars = 0; clockPtr->textWidth = 0; UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE clockPtr->textHeight = 0; clockPtr->padX = 0; clockPtr->padY = 0; clockPtr->flags = 0; /* * Register a handler for when the window is UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE * exposed or resized. */ Tk_CreateEventHandler(clockPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, ClockEventProc, (ClientData) clockPtr); /* * Create a Tcl command that operates on the widget. */ clockPtr->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(clockPtr->tkwin), ClockInstanceCmd, (ClientData) clockPtr, (void (*)()) NULL); /* * Parse the command line arguments. */ if (ClockConfigure(interp, clockPtr, argc-2, argv+2, 0) != TCL_OK) { Tk_DestroyWindow(clockPtr->tkwin); return TCL_ERROR; } Tcl_SetResult(interp, Tk_PathName(clockPtr->tkwin), TCL_VOLATILE); return TCL_OK; }
The Tcl_Obj version, ClockObjCmd, does some additional work to set up an option table that is used to efficiently parse the command line options to the clock command. The option table is created the first time the clock command is used. The clientData for ClockObjCmd is initially NULL; it is used to store the option table once it is initialized. While ClockCmd uses the clientData to store a reference to the main Tk window, ClockObjCmd uses the Tk_MainWindow procedure to get a reference to the main Tk window.
{ Tk_OptionTable optionTable; Clock *clockPtr; Tk_Window tkwin; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?"); return TCL_ERROR; } optionTable = (Tk_OptionTable) clientData; if (optionTable == NULL) { Tcl_CmdInfo info; char *name; /* * Initialize the option table for this widget the * first time a clock widget is created. The option * table is saved as our client data. */ optionTable = Tk_CreateOptionTable(interp, optionSpecs); name = Tcl_GetString(objv[0]); Tcl_GetCommandInfo(interp, name, &info); info.objClientData = (ClientData) optionTable; Tcl_SetCommandInfo(interp, name, &info); } tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), Tcl_GetString(objv[1]), (char *) NULL); if (tkwin == NULL) { return TCL_ERROR; } /* * Set resource class. */ Tk_SetClass(tkwin, "Clock"); /* * Allocate and initialize the widget record. */ clockPtr = (Clock *) ckalloc(sizeof(Clock)); clockPtr->tkwin = tkwin; clockPtr->display = Tk_Display(tkwin); clockPtr->interp = interp; clockPtr->optionTable = optionTable; clockPtr->borderWidth = 0; clockPtr->borderWidthPtr = NULL; clockPtr->highlightWidth = 0; clockPtr->highlightWidthPtr = NULL; clockPtr->relief = TK_RELIEF_FLAT; clockPtr->background = NULL; clockPtr->foreground = NULL; clockPtr->highlight = NULL; clockPtr->highlightBg = NULL; clockPtr->tkfont = NULL; clockPtr->textGC = None; clockPtr->token = NULL; clockPtr->clock = NULL;
clockPtr->format = NULL; clockPtr->numChars = 0; clockPtr->textWidth = 0; clockPtr->widthPtr = NULL; clockPtr->textHeight = 0; clockPtr->heightPtr = NULL; clockPtr->padX = 0; clockPtr->padXPtr NULL; UNREGISTERED VERSION OF=CHM TO PDF CONVERTER By THETA-SOFTWARE clockPtr->padY = 0; clockPtr->padYPtr = NULL; clockPtr->flags = 0; /* * Register a handler for when the window is * exposed or resized. UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE */ Tk_CreateEventHandler(clockPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, ClockEventProc, (ClientData) clockPtr); /* * Create a Tcl command that operates on the widget. */ clockPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(clockPtr->tkwin), ClockInstanceObjCmd, (ClientData) clockPtr, (void (*)()) NULL); /* * Parse the command line arguments. */ if ((Tk_InitOptions(interp, (char *)clockPtr, optionTable, tkwin) != TCL_OK) || (ClockObjConfigure(interp, clockPtr, objc-2, objv+2, 0) != TCL_OK)) { Tk_DestroyWindow(clockPtr->tkwin); return TCL_ERROR; } Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(clockPtr->tkwin), -1); return TCL_OK; }
[ Team LiB ]
[ Team LiB ]
* Return info about one attribute, like cget. */ result = Tk_ConfigureInfo(interp, clockPtr->tkwin, configSpecs, (char *) clockPtr, argv[2], 0); } else { /* * Change one or more attributes. */ UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE result = ClockConfigure(interp, clockPtr, argc-2, argv+2,TK_CONFIG_ARGV_ONLY); } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be cget, configure, position, or size", UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE (char *) NULL); return TCL_ERROR; } return result; }
Example 49-6 shows the ClockInstanceObjCmd procedure. It uses the Tk_GetIndexFromObj routine to map the first argument to an index, which is then used in a switch statement. It uses the Tk_GetOptionValue and Tk_GetOptionInfo procedures to parse the widget configuration options.
Tcl_WrongNumArgs(interp, 1, objv, "cget option"); return TCL_ERROR; } objPtr = Tk_GetOptionValue(interp, (char *)clockPtr, clockPtr->optionTable, (objc == 3) ? objv[2] : NULL, clockPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; } else { Tcl_SetObjResult(interp, objPtr); } break; } case CLOCK_CONFIGURE: { if (objc <= 3) { /* * Return one item if the option is given, * or return all configuration information. */ objPtr = Tk_GetOptionInfo(interp, (char *) clockPtr, clockPtr->optionTable, (objc == 3) ? objv[2] : NULL, clockPtr->tkwin); if (objPtr == NULL) { return TCL_ERROR; } else { Tcl_SetObjResult(interp, objPtr); } } else { /* * Change one or more attributes. */ result = ClockObjConfigure(interp, clockPtr, objc-2, objv+2); } } } return TCL_OK; }
[ Team LiB ]
[ Team LiB ]
Tk_SetWindowBackground(clockPtr->tkwin, Tk_3DBorderColor(clockPtr->background)->pixel); /* * Set up the graphics contexts to display the widget. * The context is used to draw off-screen pixmaps, * so turn off exposure notifications. */ gcValues.background = Tk_3DBorderColor(clockPtr->background)->pixel; gcValues.foreground = clockPtr->foreground->pixel; gcValues.font = Tk_FontId(clockPtr->tkfont); gcValues.graphics_exposures = False; newGC = Tk_GetGC(clockPtr->tkwin, GCBackground|GCForeground|GCFont|GCGraphicsExposures, &gcValues); if (clockPtr->textGC != None) { Tk_FreeGC(clockPtr->display, clockPtr->textGC); } clockPtr->textGC = newGC; /* * Determine how big the widget wants to be. */ ComputeGeometry(clockPtr); /* * Set up a call to display ourself. */ if ((clockPtr->tkwin != NULL) && Tk_IsMapped(clockPtr->tkwin) && !(clockPtr->flags & REDRAW_PENDING)) { Tk_DoWhenIdle(ClockDisplay, (ClientData) clockPtr); clockPtr->flags |= REDRAW_PENDING; } return TCL_OK; }
Example 49-8 shows the ClockObjConfigure procedure. The Tk_SetOptions interface, which is used to set fields in the Clock data structure, has one potential problem. It is possible that some configuration options are correct, while others cause errors. In this case, ClockObjConfigure backs out the changes, so the whole configuration has no effect. This requires a two-pass approach, with the second pass used to restore the original values. Tk_SetOptions has a feature that lets you classify changes to the widget. The GEOMETRY_MASK and GRAPHICS_MASK are bits defined by the clock widget to divide its attributes into two classes. It changes its graphics context or recomputes its geometry only if an attribute from the appropriate class is changed.
XGCValues gcValues; GC newGC; Tk_SavedOptions savedOptions; int mask, error; Tcl_Obj *errorResult; /* * The first time CHM TO PDF CONVERTER UNREGISTERED VERSION OFthrough this loop we set theBy THETA-SOFTWARE * configuration from the command line inputs. The second * pass is used to restore the configuration in case of * errors */ for (error = 0 ; error <= 1 ; error++) { if (!error) OF UNREGISTERED VERSION { CHM TO PDF CONVERTER By THETA-SOFTWARE /* * Tk_SetOptions parses the command arguments * and looks for defaults in the resource * database. */ if (Tk_SetOptions(interp, (char *) clockPtr, clockPtr->optionTable, objc, objv, clockPtr->tkwin, &savedOptions, &mask) != TCL_OK) { continue; } } else { /* * Restore options from saved values */ errorResult = Tcl_GetObjResult(interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); } if (mask & GRAPHICS_MASK) { /* * Give the widget a default background so it doesn't * get a random background between the time it is * initially displayed by the system and we paint it */ Tk_SetBackgroundFromBorder(clockPtr->tkwin, clockPtr->background); /* * Set up the graphics contexts to display the widget. * The context is used to draw off-screen pixmaps, * so turn off exposure notifications. */ gcValues.background = Tk_3DBorderColor(clockPtr->background)->pixel; gcValues.foreground = clockPtr->foreground->pixel; gcValues.font = Tk_FontId(clockPtr->tkfont); gcValues.graphics_exposures = False; newGC = Tk_GetGC(clockPtr->tkwin, GCBackground|GCForeground|GCFont|GCGraphicsExposures, &gcValues); if (clockPtr->textGC != None) { Tk_FreeGC(clockPtr->display, clockPtr->textGC);
} clockPtr->textGC = newGC; } /* * Determine how big the widget wants to be. */ if (mask & GEOMETRY_MASK) { ComputeGeometry(clockPtr); } /* * Set up a call to display ourself. */ if ((clockPtr->tkwin != NULL) && Tk_IsMapped(clockPtr->tkwin) && !(clockPtr->flags & REDRAW_PENDING)) { Tk_DoWhenIdle(ClockDisplay, (ClientData) clockPtr); clockPtr->flags |= REDRAW_PENDING; } /* * All OK, break out and avoid error rollback. */ break; } if (!error) { Tk_FreeSavedOptions(&savedOptions); return TCL_OK; } else { Tcl_SetObjResult(interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } }
[ Team LiB ]
[ Team LiB ]
The initial field is a type, such as TK_CONFIG_BORDER. Colors and borders will be explained shortly. The next field is the command-line flag for the attribute, (e.g., -background). Then comes the resource name and the class name. The default value is next, (e.g., light blue). The offset of a structure member is next, and the Tk_Offset macro is used to compute this offset. The specflags field is a bitmask of flags. The two used in this example are TK_CONFIG_COLOR_ONLY and TK_CONFIG_MONO_ONLY, which restrict the application of the configuration setting to color and monochrome displays, respectively. You can define additional flags and pass them into Tk_ConfigureWidget if you have a family of widgets that share most, but not all, of their attributes. The tkButton.c file in the Tk sources has an example of this. The customPtr is used if you have a TK_CONFIG_CUSTOM type, which is explained in detail in the manual page for Tk_ConfigureWidget. Example 49-10 shows the Tk_ConfigSpec specification of widget attributes for the clock widget.
{TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL, (char *) NULL, 0, 0}, {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL, (char *) NULL, 0, 0}, {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth","2", Tk_Offset(Clock, borderWidth), 0}, {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", "ridge", Tk_Offset(Clock, relief), 0}, {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground", "black", Tk_Offset(Clock, foreground),0}, {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL, (char *) NULL, 0, 0}, {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", "red", Tk_Offset(Clock, highlight), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", "black", Tk_Offset(Clock, highlight),TK_CONFIG_MONO_ONLY}, {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", "light blue", Tk_Offset(Clock, highlightBg), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", "black", Tk_Offset(Clock, highlightBg), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness","HighlightThickness", "2", Tk_Offset(Clock, highlightWidth), 0}, {TK_CONFIG_PIXELS, "-padx", "padX", "Pad", "2", Tk_Offset(Clock, padX), 0}, {TK_CONFIG_PIXELS, "-pady", "padY", "Pad", "2", Tk_Offset(Clock, padY), 0}, {TK_CONFIG_STRING, "-format", "format", "Format", "%H:%M:%S", Tk_Offset(Clock, format), 0}, {TK_CONFIG_FONT, "-font", "font", "Font", "Courier 18", Tk_Offset(Clock, tkfont), 0}, {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, 0} };
There is an alternative to the Tk_ConfigureWidget interface that understands Tcl_Obj values in the widget data structure. It uses a a similar type, Tk_OptionSpec, and Tk_ConfigureWidget is replaced by the Tk_SetOptions, Tk_GetOptionValue, and Tk_GetOptionInfo procedures. Example 49-11 shows the Tk_OptionSpec type.
char *defValue; int objOffset; int internalOffset; int flags; ClientData clientData; int typeMask; } Tk_OptionSpec;
"highlightThickness","HighlightThickness", "2", Tk_Offset(Clock, highlightWidthPtr), Tk_Offset(Clock, highlightWidth), 0, 0, GEOMETRY_MASK}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", "2", Tk_Offset(Clock, padXPtr), Tk_Offset(Clock, padX), 0, 0, GEOMETRY_MASK}, {TK_OPTION_PIXELS, "-pady", "padY", "Pad", "2", Tk_Offset(Clock, padYPtr), Tk_Offset(Clock, padY), 0, 0, GEOMETRY_MASK}, {TK_OPTION_STRING, "-format", "format", "Format", "%H:%M:%S",-1, Tk_Offset(Clock, format), 0, 0, GEOMETRY_MASK}, {TK_OPTION_FONT, "-font", "font", "Font", "Courier 18", -1, Tk_Offset(Clock, tkfont), 0, 0, (GRAPHICS_MASK|GEOMETRY_MASK)}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, -1, 0, 0, 0, 0} };
Table 49-1 lists the correspondence between the configuration type of the option and the type of the associated field in the widget data structure. The same types are supported by the Tk_ConfigSpec and Tk_OptionSpec types, with a few exceptions. The TK_CONFIG_ACTIVE_CURSOR configuration type corresponds to the TK_OPTION_CURSOR; both of these set the widgets cursor. The TK_CONFIG_MM and TK_CONFIG_CURSOR types are simply not supported by Tk_OptionSpec because they were not very useful. The TK_OPTION_STRING_TABLE replaces TK_CONFIG_CAP_STYLE and TK_CONFIG_JOIN_STYLE with a more general type that works with Tcl_GetIndexFromObj. In this case, the clientData is an array of strings that are passed to Tcl_GetIndexFromObj. The index value corresponds to the integer value returned from procedures like Tk_GetCapStyle.
Cursor
TK_OPTION_STRING_TABLE
The clientData is an array of strings used with Tcl_GetIndexFromObj (alias for other option)
Tk_Uid Tk_Window
[ Team LiB ]
[ Team LiB ]
Example 49-13 OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSIONComputeGeometry computes the widget's size
static void ComputeGeometry(Clock *clockPtr) { int width, height; Tk_FontMetrics fm; /* Font size information */ struct tm *tmPtr; /* Time info split into fields */ struct timeval tv; /* BSD-style time value */ int bd; /* Padding from borders */ char clock[1000]; /* Displayed time */ /* * Get the time and format it to see how big it will be. */ gettimeofday(&tv, NULL); tmPtr = localtime(&tv.tv_sec); strftime(clock, 1000, clockPtr->format, tmPtr); if (clockPtr->clock != NULL) { ckfree(clockPtr->clock); } clockPtr->clock = ckalloc(1+strlen(clock)); clockPtr->numChars = strlen(clock); bd = clockPtr->highlightWidth + clockPtr->borderWidth; Tk_GetFontMetrics(clockPtr->tkfont, &fm); height = fm.linespace + 2*(bd + clockPtr->padY); Tk_MeasureChars(clockPtr->tkfont, clock, clockPtr->numChars, 0, 0, &clockPtr->textWidth); width = clockPtr->textWidth + 2*(bd + clockPtr->padX); Tk_GeometryRequest(clockPtr->tkwin, width, height); Tk_SetInternalBorder(clockPtr->tkwin, bd); }
Finally, we get to the actual display of the widget! The routine is careful to check that the widget still exists and is mapped. This is important because the redisplay is scheduled asynchronously. The current time is converted to a string. This uses the POSIX library procedures gettimeofday, localtime, and strftime. There might be different routines on your system. The string is painted into a pixmap, which is a drawable region of memory that is off-screen. After the whole display has been painted, the pixmap is copied into on-screen
memory to avoid flickering as the image is cleared and repainted. The text is painted first, then the borders. This ensures that the borders overwrite the text if the widget has not been allocated enough room by the geometry manager. This example allocates and frees the off-screen pixmap for each redisplay. This is the standard idiom for Tk widgets. They temporarily allocate the off-screen pixmap each time they redisplay. In the case of a clock that updates every second, it might be reasonable to permanently allocate the pixmap and store its pointer in the Clock data structure. Make sure to reallocate the pixmap if the size changes. After the display is finished, another call to the display routine is scheduled to happen in one second. If you were to embellish this widget, you might want to make the uptime period a parameter. The TICKING flag is used to note that the timer callback is scheduled. It is checked when the widget is destroyed so that the callback can be canceled. Example 49-14 shows ClockDisplay. This procedure is identical in both versions of the widget.
Tk_WindowId(tkwin), Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); Tk_Fill3DRectangle(tkwin, pixmap, clockPtr->background, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); /* * Paint the text CHM UNREGISTERED VERSION OFfirst. TO PDF CONVERTER By */ layout = Tk_ComputeTextLayout(clockPtr->tkfont, clockPtr->clock, clockPtr->numChars, 0, TK_JUSTIFY_CENTER, 0, &width, &height); x = (Tk_Width(tkwin) - width)/2; y = (Tk_Height(tkwin) - TO PDF CONVERTER By UNREGISTERED VERSION OF CHM height)/2; Tk_DrawTextLayout(clockPtr->display, pixmap, clockPtr->textGC, layout, x, y, 0, -1);
THETA-SOFTWARE
THETA-SOFTWARE
/* * Display the borders, so they overwrite any of the * text that extends to the edge of the display. */ if (clockPtr->relief != TK_RELIEF_FLAT) { Tk_Draw3DRectangle(tkwin, pixmap, clockPtr->background, clockPtr->highlightWidth, clockPtr->highlightWidth, Tk_Width(tkwin) - 2*clockPtr->highlightWidth, Tk_Height(tkwin) - 2*clockPtr->highlightWidth, clockPtr->borderWidth, clockPtr->relief); } if (clockPtr->highlightWidth != 0) { GC gc; /* * This GC is associated with the color, and Tk caches * the GC until the color is freed. Hence no freeGC. */ if (clockPtr->flags & GOT_FOCUS) { gc = Tk_GCForColor(clockPtr->highlight, pixmap); } else { gc = Tk_GCForColor(clockPtr->highlightBg, pixmap); } Tk_DrawFocusHighlight(tkwin, gc, clockPtr->highlightWidth, pixmap); } /* * Copy the information from the off-screen pixmap onto * the screen, then delete the pixmap. */ XCopyArea(clockPtr->display, pixmap, Tk_WindowId(tkwin), clockPtr->textGC, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, 0); Tk_FreePixmap(clockPtr->display, pixmap);
/* * Queue another call to ourselves. The rate at which * this is done could be optimized. */ clockPtr->token = Tk_CreateTimerHandler(1000, ClockDisplay, (ClientData)clockPtr); clockPtr->flags |= TICKING; }
[ Team LiB ]
[ Team LiB ]
Example 49-15 OF ClockEventProc handles window events UNREGISTERED VERSION TheCHM TO PDF CONVERTER By THETA-SOFTWARE
static void ClockEventProc(ClientData clientData, XEvent *eventPtr) { Clock *clockPtr = (Clock *) clientData; if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) { goto redraw; } else if (eventPtr->type == DestroyNotify) { Tcl_DeleteCommandFromToken(clockPtr->interp, clockPtr->widgetCmd); /* * Zapping the tkwin lets the other procedures * know we are being destroyed. */ clockPtr->tkwin = NULL; if (clockPtr->flags & REDRAW_PENDING) { Tk_CancelIdleCall(ClockDisplay, (ClientData) clockPtr); clockPtr->flags &= ~REDRAW_PENDING; } if (clockPtr->flags & TICKING) { Tk_DeleteTimerHandler(clockPtr->token); clockPtr->flags &= ~TICKING; } /* * This results in a call to ClockDestroy. */ Tk_EventuallyFree((ClientData) clockPtr, ClockDestroy); } else if (eventPtr->type == FocusIn) { if (eventPtr->xfocus.detail != NotifyPointer) { clockPtr->flags |= GOT_FOCUS; if (clockPtr->highlightWidth > 0) { goto redraw; } } } else if (eventPtr->type == FocusOut) { if (eventPtr->xfocus.detail != NotifyPointer) { clockPtr->flags &= ~GOT_FOCUS;
if (clockPtr->highlightWidth > 0) { goto redraw; } } } return; redraw: if ((clockPtr->tkwin != NULL) && !(clockPtr->flags & REDRAW_PENDING)) { Tk_DoWhenIdle(ClockDisplay, (ClientData) clockPtr); clockPtr->flags |= REDRAW_PENDING; } }
[ Team LiB ]
[ Team LiB ]
Final Cleanup
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
When a widget is destroyed, you need to free up any resources it has allocated. The resources associated with attributes are cleaned up by Tk_FreeOptions. The others you must take care of yourself. The ClockDestroy procedure is called as a result of the Tk_EventuallyFree call in the ClockEventProc. The Tk_EventuallyFree procedure is part of a UNREGISTEREDprotocol thatOF CHM TO widgets that might getBy THETA-SOFTWARE VERSION is needed for PDF CONVERTER deleted when in the middle of processing. Typically the Tk_Preserve and Tk_Release procedures are called at the beginning and end of the widget instance command to mark the widget as being in use. Tk_EventuallyFree will wait until Tk_Release is called before calling the cleanup procedure. The next example shows ClockDestroy:
The version of ClockDestroy that uses the Tcl_Obj interfaces calls Tk_FreeConfigOptions instead of Tk_FreeOptions. The ClockObjDelete command is called when the oclock command is removed from the interpreter. This has to clean up the option table used to parse options, if it has been initialized. There is no corresponding delete procedure for the stringbased version of the widget. Example 49-17 shows ClockObjDelete.
[ Team LiB ]
[ Team LiB ]
man Tcl_CreateCommand
The Windows Help and HTML versions are indexed by procedure. You can find the HTML on the CD-ROM and the Web: http://www.tcl.tk/man/ The Tcl and Tk sources are also excellent reference material. The code is well written with a consistent style that encourages lots of comments. Virtually all the exported APIs are used by Tcl and Tk themselves, so you can read the source code to see how the APIs are used. The Tcl and Tk sources are on the CD-ROM in tcl8.4 and tk8.4 directories. Chapter 48 describes the source directory structure and how to build Tcl from the source code. [ Team LiB ]
[ Team LiB ]
Tcl_PkgRequire checks a dependency on another package. Tcl_PkgProvide declares that a package is provided by a library. These procedures are equivalent to the package require and package provide Tcl commands. The Tcl_PkgPresent procedure returns the version number of the package, if it is loaded. Tcl_PkgProvideEx, Tcl_PkgRequireEx, and Tcl_PkgPresentEx let you set and query the clientData associated with the package. The Tcl_StaticPackage call is used by statically linked packages so that scripts can load them into slave interpreters.
Tcl_AppendElement, Tcl_GetStringResult, and Tcl_ResetResult procedures. The object interface is provided by Tcl_SetObjResult and Tcl_GetObjResult. Error information is managed with the Tcl_AddErrorInfo, Tcl_AddObjErrorInfo, Tcl_SetErrorCode, Tcl_SetObjErrorCode, Tcl_SetErrorCodeVA, Tcl_LogCommandInfo, and Tcl_PosixError procedures. The Tcl_WrongNumArgs generates a standard error message. Tcl_SetErrno, Tcl_GetErrno, Tcl_ErrnoId, and Tcl_ErrnoMsg provide platform-independent access to the errno global variable that stores POSIX error codes.
Memory Allocation
The Tcl_Alloc, Tcl_Realloc, and Tcl_Free procedures provide platform- and compilerindependent functions to allocation and free heap storage. Use these instead of alloc, realloc, and free. Note that Tcl_Alloc and Tcl_Realloc will panic if no memory is available. The following procedures will return a NULL pointer instead of panicking: Tcl_AttemptAlloc, Tcl_AttemptRealloc. The Tcl_Preserve and Tcl_Release procedures work in concert with Tcl_EventuallyFree to guard data structures against premature deallocation. These are described on page 715. The following macros are layers over the memory APIs that provide extra debugging support if the TCL_MEM_DEBUG compile-time option is used: ckalloc, ckfree, ckrealloc, attemptckalloc, attemptckrealloc. To view the debugging information, use Tcl_DumpActiveMemory or Tcl_ValidateAllMemory. Use Tcl_InitMemory to create the memory Tcl command that provides script-level access to these APIs.
Lists
You can chop a list up into its elements with Tcl_SplitList, which returns an array of strings. You can create a list out of an array of strings with Tcl_Merge. This behaves like the list command in that it will add syntax to the strings so that the list structure has one element for each of the strings. The Tcl_ScanElement, Tcl_ScanCountedElement, Tcl_ConvertCountedElement, and Tcl_ConvertElement procedures are used by Tcl_Merge. The object interface to lists is provided by Tcl_NewListObj, Tcl_SetListObj, Tcl_ListObjIndex, Tcl_ListObjLength, Tcl_ListObjAppendList, Tcl_ListObjAppendElement, Tcl_ListObjGetElements, and Tcl_ListObjReplace.
Command Parsing
If you are reading commands, you can test for a complete command with Tcl_CommandComplete. You can do backslash substitutions with Tcl_Backslash. A more formal Tcl parser is provided by these procedures: Tcl_ParseCommand, Tcl_ParseExpr, Tcl_ParseBraces, Tcl_ParseQuotedString, Tcl_ParseVarName, Tcl_ParseVar and Tcl_FreeParse. The result of the parse is a sequence of tokens, which you can evaluate with Tcl_EvalTokens and Tcl_EvalTokensStandard.
Command Pipelines
The Tcl_OpenCommandChannel procedure does all the work of setting up a pipeline between processes. It handles file redirection and implements all the syntax supported by the exec and open commands. Use Tcl_WaitPid to wait for the process to complete. If the command pipeline is run in the background, then a list of process identifiers is returned. You can detach these processes with Tcl_DetachPids, and you can clean up after them with Tcl_ReapDetachedProcs.
the history list and then behaves like Tcl_GlobalEval. You can set the recursion limit of the interpreter with Tcl_SetRecursionLimit. If you are implementing a new control structure, you may need to use the Tcl_AllowExceptions procedure. This makes it acceptable for Tcl_Eval and friends to return something other than TCL_OK and TCL_ERROR.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE error information, use Tcl_SaveResult, Tcl_RestoreResult, and Tcl_DiscardResult.
The Tcl_SubstObj procedure implements the mechanics of the subst Tcl command.
If you want to evaluate a Tcl command without modifying the current interpreter result and
Evaluating Expressions
The Tcl expression evaluator is available through the Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean, and Tcl_ExprString procedures. These all use the same evaluator, but they differ in how they return their result. The object interface to expressions is implemented with Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj, and Tcl_ExprObj. You can register the implementation of new math functions by using Tcl_CreateMathFunc, and you can query them with Tcl_GetMathFuncInfo and Tcl_ListMathFuncs.
Converting Numbers
You can convert strings into numbers with the Tcl_GetInt, Tcl_GetDouble, and Tcl_GetBoolean procedures. The Tcl_PrintDouble procedure converts a floating point number to a string. Tcl uses it any time it must do this conversion.
Tcl Objects
Tcl 8.0 uses dual-ported objects instead of strings to improve execution efficiency. The basic interface to objects is provided by Tcl_NewObj, Tl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_InvalidateStringRep, and Tcl_IsShared. Example 47-5 on page 706 and Example 47-15 on page 725 illustrate some of these procedures. You can define new object types. The interface consists of Tcl_RegisterObjType, Tcl_GetObjType, Tcl_AppendAllObjTypes, and Tcl_ConvertToType.
is an array of strings (for Tcl_Concat) or Tcl_Obj values (for Tcl_ConcatObj). They trim leading and trailing white space from each one, and concatenate them together into one string with a single space character between each value.
Dynamic Strings
The Tcl dynamic string package is designed for strings that get built up incrementally. You will need to use dynamic strings if you use the Tcl_TranslateFileName procedure. The procedures in the package are Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringFree, Tcl_DString-Result, and Tcl_DStringGetResult. Dynamic strings are explained in more detail on page 717.
Tcl_UniCharIsAlpha, Tcl_UniCharIsControl, Tcl_UniCharIsDigit, Tcl_UniCharIsGraph, Tcl_UniCharIsLower, Tcl_UniCharIsPrint, Tcl_UniCharIsPunct, Tcl_UniCharIsSpace, Tcl_UniCharIsUpper, and Tcl_UniCharIsWordChar.
Hash Tables
Tcl has a nice hash table package that automatically grows the hash table data structures as more elements are added to the table. Because everything is a string, you may need to set up a hash table that maps from a string-valued key to an internal data structure. The procedures in the package are Tcl_InitHashTable, Tcl_InitObjHashTable, Tcl_InitCustomHashTable, Tcl_DeleteHashTable, Tcl_CreateHashEntry, Tcl_Delete-HashEntry, Tcl_FindHashEntry, Tcl_GetHashValue, Tcl_SetHashValue, Tcl_GetHashKey, Tcl_FirstHashEntry, Tcl_NextHashEntry, and Tcl_HashStats. Hash tables are used in the blob command example presented in Chapter 47.
Option Processing
Tcl_GetIndexFromObj and Tcl_GetIndexFromObjStruct provide a way to look up keywords in a table. They are designed to work with options on a Tcl command. Tcl_GetIndexFromObj is illustrated in Example 47-8 on page 711.
destroy an event source. An event source manipulates the events queue with Tcl_QueueEvent, Tcl_DeleteEvents, and Tcl_SetMaxBlockTime. Each thread runs a notifier. You can enqueue events for another thread's notifier with Tcl_ThreadQueueEvent. After you do this, you must signal the other thread with Tcl_ThreadAlert. The ID of the current thread is returned from Tcl_GetCurrentThread.
UNREGISTERED VERSION OF CHM TO PDF CONVERTER Tcl_InitNotifier, implementation for custom situations. This API consists of By THETA-SOFTWARE
Tcl_FinalizeNotifier, Tcl_WaitForEvent, Tcl_Alert-Notifier, Tcl_Sleep, Tcl_CreateFileHandler, and Tcl_DeleteFileHandler.
The notifier is implemented with a public API so that you can replace the API with a new
If you want to integrate Tcl's event loop with an external one, such as the Xt event loop used by Motif, then you can use the following procedures: Tcl_WaitForEvent, Tcl_SetTimer, UNREGISTERED VERSION OF CHM TO PDF CONVERTER By and Tcl_SetServiceMode. There Tcl_ServiceAll, Tcl_ServiceEvent, Tcl_GetServiceMode, THETA-SOFTWARE is an example application of this in the unix/xtTest.c file.
File Handlers
Use Tcl_CreateFileHandler to register handlers for I/O streams. You set up the handlers to be called when the I/O stream is ready for reading or writing, or both. File handlers are called after window event handlers. Use Tcl_DeleteFileHandler to remove the handler. Tcl_CreateFileHandler is UNIX-specific because UNIX has a unified handle for files, sockets, pipes, and devices. On Windows and the Macintosh, there are different system APIs to wait for events from these different classes of I/O objects. These differences are hidden by the channel drivers for sockets and pipes. For nonstandard devices, the best thing is to create a channel driver and event source for them.
Timer Events
Register a callback to occur at some time in the future with Tcl_CreateTimerHandler. The handler is called only once. If you need to delete the handler before it gets called, use Tcl_DeleteTimerHandler.
Idle Callbacks
If there are no outstanding events, the Tk makes idle callbacks before waiting for new events to arrive. In general, Tk widgets queue their display routines to be called at idle time. Use Tcl_DoWhenIdle to queue an idle callback, and use Tcl_CancelIdleCall to remove the callback from the queue. The Tcl_Sleep procedure delays execution for a specified number of milliseconds.
Input/Output
The Tcl I/O subsystem provides buffering and works with the event loop to provide event-
driven I/O. The interface consists of Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_GetOpenFile, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_Read, Tcl_ReadChars, Tcl_Gets, Tcl_Write, Tcl_WriteObj, Tcl_WriteChars, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_Eof, Tcl_GetsObj, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw, Tcl_GetChannelOption, and Tcl_SetChannelOption.
Thread Support
The Tcl library is thread safe. The procedures listed here provide a convenient, cross-platform API for programming with threads. The following procedures serialize access to data structures: Tcl_MutexLock, Tcl_MutexUnlock, Tcl_ConditionWait, and Tcl_ConditionNotify. Thread local storage is provided by Tcl_GetThreadData. All of these procedures are self-initializing, so there are no explicit initialization calls. There are, however, Tcl_ConditionFinalize and Tcl_MutexFinalize.
The following procedures manage thread life cycle: Tcl_CreateThread, Tcl_ExitThread, Tcl_JoinThread, and Tcl_FinalizeThread. The Tcl_CreateThreadExitHandler procedure registers a procedure that is called when a thread is terminated. In particular, it can clean up thread local storage. Use Tcl_DeleteThreadExitHandler to remove a registration.
Exit Handlers
The Tcl_Exit procedure terminates the application. The Tcl_Finalize procedure cleans up Tcl's memory usage and calls exit handlers, but it does not exit. This is necessary when unloading the Tcl DLL. The Tcl_CreateExitHandler and Tcl_DeleteExitHandler set up callbacks that occur when Tcl_Exit is called.
Macintosh
The Macintosh platform has a number of APIs used to manipulate Mac-specific resources and to register handlers for Mac-specific events: Tcl_MacSetEventProc, Tcl_MacConvertTextResource, Tcl_MacEvalResource, Tcl_MacFindResource, Tcl_GetOSTypeFromObj, Tcl_SetOSTypeObj, and Tcl_NewOSTypeObj.
Panic
Tcl_Panic is used to abort the application if some serious internal error occurs. Tcl_PanicVA takes a variable number of arguments. You can alter the default behavior of Tcl_Panic by setting a handler with Tcl_SetPanicProc. The panic macro calls Tcl_Panic.
Miscellaneous
Tcl_GetHostName returns the name of the current machine. This is the same as the info hostname value. Tcl_GetTime returns the current time in seconds and microseconds. Tcl_GetVersion returns the version and patch level of the Tcl interpreter. Tcl_PutEnv sets a value in the environment, and should be used instead of putenv. Tcl_SignalId and Tcl_SignalMsg convert between signal numbers (e.g., 9) and signal names (e.g., "SIGKILL").
[ Team LiB ]
[ Team LiB ]
Creating Windows
The Tk_Init procedure creates the main window for your application. The Tk_CreateWindow and Tk_CreateWindowFromPath are used to create windows for widgets. The actual creation of the window is delayed until an idle point. You can force the window to be created with Tk_MakeWindowExist or destroy a window with Tk_DestroyWindow. The Tk_MainWindow procedure returns the handle on the application's main window. The Tk_MapWindow and Tk_UnmapWindow are used to display and withdraw a window, respectively. The Tk_MoveToplevelWindow call is used to position a top-level window. Tk_GetNumMainWindows returns the number of main windows opened by the current process. Translate between window names and the Tk_Window type with Tk_Name, Tk_PathName, and Tk_NameToWindow. You can convert from an operating system window ID to the corresponding Tk_Window with Tk_IdToWindow procedure. Tk_SetClassProcs registers widget-specific handlers to react to system wide font and color changes, to create platform-specific windows, and to handle modal input loops.
Configuring Windows
The configuration of a window includes its width, height, cursor, and so on. Tk provides a set of routines that configure a window and also cache the results. This makes it efficient to query these settings because the system does not need to be contacted. The window configuration
routines are Tk_ConfigureWindow, Tk_ResizeWindow, Tk_MoveWindow, Tk_MoveResizeWindow, Tk_SetWindowBorderWidth, Tk_DefineCursor, Tk_ChangeWindowAttributes, Tk_SetWindowBackground, Tk_SetWindowColormap, Tk_UndefineCursor, Tk_SetWindowBackgroundPixmap, Tk_SetWindowBorderPixmap, Tk_MoveWindow, and Tk_SetWindowBorder.
Window Coordinates
The coordinates of a widget relative to the root window (the main screen) are returned by Tk_GetRootCoords. The Tk_GetVRootGeometry procedure returns the size and position of a window relative to the virtual root window. The Tk_CoordsToWindow procedure locates the window under a given coordinate.
Window Information
Tk keeps lots of information associated with each window, or widget. The following calls are fast macros that return the information without calling the X server: Tk_WindowId, Tk_Parent, Tk_StrictMotif, Tk_Display, Tk_DisplayName, Tk_ScreenNumber, Tk_Screen, Tk_X, Tk_Y, Tk_Width, Tk_Height, Tk_Changes, Tk_Attributes, Tk_IsMapped, Tk_IsTopLevel, Tk_IsContainer, Tk_IsEmbedded, Tk_ReqWidth, Tk_ReqHeight, Tk_InternalBorderWidth, Tk_MinReqWidth, Tk_MinReqHeight, Tk_InternalBorderLeft, Tk_InternalBorderRight, Tk_InternalBorderTop, Tk_InternalBorderBottom, Tk_Visual, Tk_Depth, and Tk_Colormap.
Tk_GetScrollInfoObj parse arguments to scrolling commands like the xview and yview widget operations.
Event Bindings
The routines that manage bindings are exported by the Tk library, so you can manage bindings yourself. For example, the canvas widget uses the API to implement bindings on canvas items. The procedures are Tk_CreateBindingTable, Tk_DeleteBindingTable, Tk_CreateBinding, Tk_DeleteBinding, Tk_BindEvent, Tk_GetBinding, Tk_GetAllBindings, and Tk_DeleteAllBindings.
Keyboard Grab
Tk_Grab and Tk_Ungrab change the state of any keyboard grab, which is used to restrict input to a particular window.
Managing Bitmaps
Tk maintains a registry of bitmaps by name, (e.g., gray50 and questhead). You can define new bitmaps with Tk_DefineBitmap, and you can get a handle on the bitmap from its name with Tk_GetBitmap. Related procedures include Tk_NameOfBitmap, Tk_SizeOfBitmap, Tk_GetBitmapFromData, Tk_FreeBitmap, Tk_AllocBitmapFromObj, Tk_GetBitmapFromObj, and Tk_FreeBitmapFromObj.
One of the image types is photo, which has its own C interface for defining new formats. The job of a format handler is to read and write different image formats such as GIF or JPEG so that the photo image can display them. The Tk_CreatePhotoImageFormat procedure sets up the interface. There are several support routines for photo format handlers. The Tk_FindPhoto procedure maps from a photo name to its associated Tk_PhotoHandle data structure. The image is updated with Tk_PhotoBlank, Tk_PhotoPutBlock, and Tk_PhotoPutZoomedBlock. The image values can be obtained with Tk_PhotoGetImage. The size of the image can be manipulated with Tk_PhotoExpand, Tk_PhotoGetSize, and Tk_PhotoSetSize
Geometry Management
A widget requests a certain size with the Tk_GeometryRequest procedure. If it draws a border inside that area, it calls Tk_SetInternalBorder. The geometry manager responds to these requests, although the widget may get a different size. The Tk_ManageGeometry procedure sets up the relationship between the geometry manager and a widget. The Tk_MaintainGeometry procedure arranges for one window to stay at a fixed position relative to another widget. This is used by the place geometry manager. The relationship is broken with the Tk_UnmaintainGeometry call. The Tk_SetGrid call enables gridded geometry management. The grid is turned off with Tk_UnsetGrid.
3D Borders
The three-dimensional relief used for widget borders is supported by Tk_Get3DBorder, Tk_3DBorderGC, Tk_Draw3DRectangle, Tk_Fill3DRectangle, Tk_Draw3DPolygon, Tk_Free3DBorder, Tk_Fill3DPolygon, Tk_3DVerticalBevel, Tk_3DHorizontalBevel, Tk_SetBackgroundFromBorder, Tk_NameOf3DBorder, Tk_3DBorderColor, Tk_Alloc3DBorderFromObj, Tk_Get3DBorderFromObj, and Tk_Free3DBorderFromObj. Widgets use Tk_DrawFocusHighlight to draw their focus highlight.
Mouse Cursors
Allocate a cursor with Tk_GetCursor, Tk_GetCursorFromData, Tk_GetCursorFromObj, and Tk_AllocCursorFromObj. Map back to the name of the cursor with Tk_NameOfCursor. Release the cursor resource with Tk_FreeCursor or Tk_FreeCursorFromObj. Tk_SetCaretPos sets the per-window caret position, which is used for over-the-spot X Input Methods and Windows IME windows.
Graphics Contexts
A graphics context records information about colors, fonts, line drawing styles, and so on. Instead of specifying this information on every graphics operation, a graphics context is created first. Individual graphics operations specify a particular graphic context. Allocate a graphics
Allocate a Pixmap
A pixmap is a simple color image. Allocate and free pixmaps with Tk_GetPixmap and Tk_FreePixmap.
Screen Measurements
Translate between strings like 4c or 72p and screen distances with Tk_GetPixels, Tk_GetPixelsFromObj, Tk_GetMMFromObj, and Tk_GetScreenMM. The first call returns pixels (integers); the second returns millimeters as a floating point number.
Relief Style
Window frames are drawn with a particular 3D relief such as raised, sunken, or grooved. Translate between relief styles and names with Tk_GetRelief, Tk_GetReliefFromObj, and Tk_NameOfRelief.
Dashed Lines
Tk_GetDash converts from a string to a dash pattern.
Atoms
An atom is an integer that references a string that has been registered with the system. Tk maintains a cache of the atom registry to avoid contacting the system when atoms are used. Use Tk_InternAtom to install an atom in the registry, and Tk_GetAtomName to return the name UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE given an atom.
X Resource ID Management
Each window system resource like a color or pixmap has a resource ID associated with it. The Tk_FreeXId call releases an ID so it can be reused. This is used, for example, by routines like Tk_FreeColor and Tk_FreePixmap.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
wish
The wish shell no longer requires a -file (or -f) argument, so you can drop this from your script header lines. This flag is still valid but no longer necessary. The class name of the application is set from the name of the script file instead of always being Tk. If the script is /usr/local/bin/foobar, then the class is set to Foobar, for example.
[ Team LiB ]
[ Team LiB ]
Obsolete Features
Several features that OF replaced PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION wereCHM TO in previous versions are now completely unsupported. The variable that contains the version number is tk_version. The ancient (version 1) tkVersion is no longer supported. Button widgets no longer have activate and deactivate operations. Instead, configure their state attribute. Menus no longer have enable and disable operations. Instead, configure their state attribute. [ Team LiB ]
[ Team LiB ]
Nothing breaks with this change, but you should enjoy this feature. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Bindings
The hierarchy of bindings has been fixed so that it is actually useful to define bindings at each of the global (i.e., all), class, and instance levels. The new bindtags command defines the order among these sources of binding information. You can also introduce new binding classes (e.g., InsertMode), and bind things to that class. Use the bindtags command to insert this class into the binding hierarchy. The order of binding classes in the bindtags command determines the order in which bindings are triggered. Use break in a binding command to stop the progression, or use continue to go on to the next level.
The various Request events have disappeared: CirculateRequest, ConfigureRequest, MapRequest, and ResizeRequest. The Keymap event is gone, too. Extra modifier keys are ignored when matching events. Although you can still use the Any wild card modifier, it is no longer necessary. The Alt and Meta modifiers are set up in a general way so that they are associated with the Alt_L, Alt_R, Meta_L, and Meta_R keysyms. Chapter 29 describes bindings starting at page 435. [ Team LiB ]
[ Team LiB ]
Scrollbar Interface
The interface between scrollbars and the scrollable widgets has changed. Happily, the UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE change is transparent to most scripts. If you hook your scrollbars to widgets in the straightforward way, the new interface is compatible. If you use the xview and yview widget commands directly, however, you might need to modify your code. The old interface still works, but there are new features of these operations that give you even better control. You can also query the view state, so you do not need to watch the scroll set commands to keep track of what is going on. Finally, scrollable widgets CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION OF are constrained so that the end of their data remains stuck at the bottom (right) of their display. In most cases, nothing is broken by this change. Chapter 33 describes the scrollbar protocol starting at page 501. [ Team LiB ]
[ Team LiB ]
pack info Version 3 of Tk introduced a new syntax for the pack command, but the old syntax was still supported. This continues to be true in nearly all cases except the pack info command. If you are still using the old packer format, you should probably take this opportunity to convert to the new packer syntax. The problem with pack info is that its semantics changed. The new operation used to be known as pack newinfo. In the old packer, pack info returned a list of all the slaves of a window and their packing configuration. Now pack info returns the packing configuration for a particular slave. You must first use the pack slaves command to get the list of all the slaves and then use the (new) pack info to get their configuration information. Chapter 25 describes the pack geometry manager starting at page 396. [ Team LiB ]
[ Team LiB ]
Focus
The focus VERSION has been TO PDF to support different focus windows on different UNREGISTERED mechanism OF CHMcleaned upCONVERTER By THETA-SOFTWARE screens. The focus command takes a -displayof argument. Tk remembers which widget inside each toplevel has the focus. When the focus is given to a toplevel by the window manager, Tk automatically assigns focus to the right widget. The -lastfor argument queries which widget in a toplevel will get the focus by this means. Chapter 39 describes focus starting at page 603. for focus default anymore, and focus none can be achieved by passing an empty string to the regular focus command. The tk_focusFollowsMouse procedure changes from the default explicit focus model where a widget must claim the focus to one in which moving the mouse into a widget automatically gives it the focus. The tk_focusNext and tk_focusPrev procedures implement keyboard traversal of the focus among widgets. Most widgets have bindings for <Tab> and <Shift-Tab> that cycle the focus among widgets. [ Team LiB ]
UNREGISTERED VERSION OF CHM nonePDF CONVERTER By THETA-SOFTWARE real need TO commands are no longer supported. There is no The focus default and focus
[ Team LiB ]
[ Team LiB ]
There is a difference between buttons and the other button-like widgets. An extra two pixels of padding is added, in spite of all padX and padY settings in the case of simple buttons. If you UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE want your checkbuttons, radiobuttons, menubuttons, and buttons with all the same dimensions, you'll need two extra pixels of padding for everything but simple buttons. [ Team LiB ]
[ Team LiB ]
Radiobutton Value
The default value for a radiobutton is no longer the name of the widget. Instead, it is an empty string. Make sure that you specify a -value option when setting up your radiobuttons.
[ Team LiB ]
[ Team LiB ]
Entry Widget
The scrollCommand attribute changed to CONVERTER to THETA-SOFTWARE UNREGISTERED VERSION OF CHM TO PDFxScrollCommandBy be consistent with other widgets that scroll horizontally. The view operation changed to the xview operation for the same reason. Chapter 34 describes the entry widget starting on page 507.
The delete operation has changed the meaning of the second index so that the second index refers to the character immediately following the affected text. The selection operations have changed in a similar fashion. The sel.last index refers to the character immediately following UNREGISTERED VERSION OF CHM TO from sel.first to sel.last still works. The default PDF CONVERTER By THETA-SOFTWARE the end of the selection, so deleting bindings have been updated, of course, but if you have custom bindings, you must fix them. [ Team LiB ]
[ Team LiB ]
Menus
The menu associated with a menubutton must be a child widget of the menubutton. Similarly, the menu for a cascade menu entry must be a child of the menu. The @y index for a menu always returns a valid index, even if the mouse cursor is outside any entry. In this case, it simply returns the index of the closest entry, instead of none. The selector attribute is now selectColor. The postcascade operation posts the menu of a cascade entry:
[ Team LiB ]
Listboxes
Listboxes VERSION OF bit in TO PDF CONVERTER all the details. There are UNREGISTERED changed quite a CHM Tk 4.0. See Chapter 35 forBy THETA-SOFTWAREnow four Motif-like selection styles, and two of these support disjoint selections. The tk_listboxSingleSelect procedure no longer exists. Instead, configure the selectMode attribute of the listbox. A listbox has an active element, which is drawn with an underline. It is referenced with the active index keyword.
The selection commands UNREGISTERED VERSION OFfor listboxes haveCONVERTER By THETA-SOFTWARE CHM TO PDF changed. Change: $listbox select from index1 $listbox select to index2
to:
The set operation takes two indices, and anchor is a valid index, which typically corresponds to the start of a selection. You can selectively clear the selection and query whether there is a selection in the listbox. The command to clear the selection has changed. It requires one or two indices. Change:
to:
[ Team LiB ]
[ Team LiB ]
No geometry Attribute
The frame, toplevel, and listbox widgets no longer have a geometry attribute. Use the width and height attributes instead. The geometry attribute was confused with geometry specifications for top-level windows. The use of width and height is more consistent. Note that for listboxes the width and height are in terms of lines and characters, while for frames and toplevels, they are in screen units. [ Team LiB ]
[ Team LiB ]
Text Widget
The tags VERSION the text TO PDF CONVERTER up a bit, justification and UNREGISTEREDand marks ofOF CHMwidgets have been cleanedBy THETA-SOFTWAREspacing are supported, variable tab stops can be defined, and you can embed widgets in the text display.
A mark now has a gravity - either left or right - that determines what happens when characters are inserted at the mark. With right gravity you get the old behavior: The mark gets pushed along by the inserted text by sticking to the right-hand character. With left gravity it UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE remains stuck. The default is right gravity. The mark gravity operation changes it. When text is inserted, it picks up only tags that are present on both sides of the insert point. Previously it would inherit the tags from the character to the left of the insert mark. You can also override this default behavior by supplying tags to the insert operation. The widget scan operation supports horizontal scrolling. Instead of using marks like @y, you need a mark like @x,y. For a description of the new features, see Chapter 36. [ Team LiB ]
[ Team LiB ]
Color Attributes
Table 51-1 lists the names of the color attributes that changed. These attributes are described in more detail in Chapter 41 starting at page 620.
[ Team LiB ]
colormodel
In Tk 3.6, color allocations could fail if the colormap was full. In this case, Tk would revert its colormodel to monochrome and use only black and white. The tk colormodel command was used to query or set the colormodel. In Tk 4.0, color allocations do not fail. Instead, the closest possible color is allocated. Because of this, the tk colormodel operation is no longer supported. Use the winfo visual command, which is described on page 624, to find out the characteristics of your display.
[ Team LiB ]
Canvas scrollincrement
The canvas widget changed the scrollIncrement attribute to a pair of attributes: xScrollIncrement and yScrollIncrement. The default for these is now one-tenth the width (height) of the canvas instead of one pixel. Scrolling by one page scrolls by nine-tenths of the canvas display. [ Team LiB ]
[ Team LiB ]
The Selection
The selection support OF CHM TO PDF CONVERTER By THETA-SOFTWARE UNREGISTERED VERSION has been generalized in Tk 4.0 to allow use of other selections such as the CLIPBOARD and SECONDARY selections. The changes do not break anything, but you should check out the new clipboard command. Some other toolkits, notably OpenLook, can paste data only from the clipboard. Chapter 38 describes the selection starting at page 591. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Cross-Platform Scripts
Cross-platform support lets a Tcl/Tk script run unchanged on UNIX, Windows, and Macintosh. However, you can still have platform dependencies in your program. The most obvious dependency is if your script executes other programs or uses C-level extensions. These need to be ported for your script to continue to work.
Newline Translations
Windows and Macintosh have different conventions for representing the end of line in files. These differences are handled automatically by the new I/O subsystem. However, you can use the new fconfigure command described on page 231 to control the translations.
[ Team LiB ]
[ Team LiB ]
The info command added two related operations, sharedlibextention and nameofexecutable, which are described on page 192.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Multiple
foreach
loop variables
This is one of my favorite features. The foreach command supports multiple loop variables and multiple value lists. This means that you can assign values to multiple variables during each loop iteration. The values can come from the same list or from lists that are processed in parallel. Multiple foreach loop variables are described on page 81. For example, you can iterate through the contents of an array with:
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION processing TOevent. CONVERTER By THETA-SOFTWARE already OF CHM an PDF Backwards compatibility is provided if you an error occurs while
[ Team LiB ]
[ Team LiB ]
Network Sockets
The socket command provides access to TCP/IP sockets. There are C APIs to define new channels, and there are extensions that provide UDP and other protocols. Chapter 17 describes sockets starting on page 239. Example 43-4 on page 653 uses sockets as a replacement for the Tk send command.
info hostname
The info hostname command was added to find out your host identifier.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Virtual Events
UNREGISTERED VERSION OF defines virtual events like <<Cut>> <<Copy>> and <<Paste>>. These CHM TO PDF CONVERTER By THETA-SOFTWARE The new event command
virtual events map to different physical events on different platforms. For example, <<Copy>> is <Control-c> on Windows and <Command-c> on Macintosh. You can write your scripts in terms of virtual events, and you can define new virtual events for your application. You can also use the event command to generate events for testing purposes. Virtual events and the event command are described starting at page 446. [ Team LiB ]
[ Team LiB ]
Standard Dialogs
Several standard dialogs were added to Tk. These let you display alerts, prompt the user, choose colors, and select files using dialogs that are implemented in native look for each platform. For example, to ask the user a yes/no question:
tk_messageBox -type yesno \ -message "Ok to proceed?" \ -icon question => yes
The standard dialogs are described in Chapter 39 starting at page 599. [ Team LiB ]
[ Team LiB ]
New
grid
Geometry Manager
UNREGISTEREDgeometry manager was overhauled to improve its layout algorithm, and there were VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE The grid
several user-visible changes. The weights on rows and columns that affect resize behavior were changed from floating point values to integers. A -pad row and column attribute was added to provide padding for a whole row or column. The columnconfigure and rowconfigure operations now return the current settings if given no arguments. There are two new grid operations. The update operation forces an update of the grid layout. The remove operation UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE removes a widget from the grid but remembers all its grid settings, so it is easy to put it back into the grid later. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Compile-Time Errors
The compiler catches some sorts of errors earlier than the pure interpreted version. The first time a compiler runs a procedure, it translates the whole thing to byte codes first. If there are syntax errors at the end of the procedure, it prevents any code in the procedure from running. A similar problem occurs with list data. If a string is not a perfect list, then the list commands will fail when parsing it, even if they do not use the damaged part of the list. For example, lindex used to process only enough of a list to find the requested element. In Tcl 8.0 the whole list is converted into a native representation. Errors at the end of a list will prevent you from getting elements at the beginning. This is mainly an issue when you use list operations on arbitrary input data.
[ Team LiB ]
Namespaces
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Chapter 14 describes the Tcl namespace facility that partitions the global scope for variables and procedures. Namespaces are optional. Simple scripts can avoid them, but larger applications can use them for structuring. Library packages should also use namespaces to facility code sharing without conflict. [ Team LiB ]
[ Team LiB ]
Safe-Tcl
Hidden commands were added to the Safe-Tcl security model. Instead of removing unsafe commands from an interpreter, the commands are hidden. The master can invoke hidden commands inside a slave. This is necessary so that the command sees the correct context. This adds new operations to the interp command: invokehidden, hide, expose, and hidden. Hidden commands are described on page 297. Initialization of a safe interpreter with a safe base that supports auto loading and a standard exit alias has been abstracted into a Tcl interface. The safe::interpCreate and safe::interpInit procedures create or initialize a slave with the safe base. The safe::interpDelete procedure cleans up. The safe base is described on page 300. To support the Trusted security policy, the interp marktrusted command was added. This promotes an unsafe interpreter back into a trusted one. Of course, only the master can do this. [ Team LiB ]
[ Team LiB ]
New
lsort
UNREGISTERED VERSIONwas reimplemented. The new implementation is reentrant, which means OF CHM TO PDF CONVERTER By THETA-SOFTWARE The lsort command
that you can use lsort inside a sorting function called by lsort. New options have lessened the need for custom sorting procedures, too. The -dictionary option sorts cases together, and it handles numbers better. The -index option sorts lists on a key field. These are described on page 70.
[ Team LiB ]
tcl_precision
Variable
The tcl_precision variable was removed in the 8.0p2 release and added back in the 8.0.3 release. Its default value was increased from 6 to 12, which should be enough for most applications. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Http Package
A Tcl implementation of the HTTP/1.0 protocol was added to the Tcl script library. The http::geturl command is described on page 251. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Platform-Independent Fonts
A platform-independent font-naming system was added in Tk 8.0. Names like times 10 bold are interpreted on all platforms. The font command lets you create font objects that can be associated with widgets. The font metrics command returns detailed size information. The font command is described on page 640. [ Team LiB ]
[ Team LiB ]
The tk
scaling
Command
UNREGISTERED VERSION OF CHM TO PDF CONVERTER Bypixels to points. Points are used THETA-SOFTWARE The tk scaling command queries or sets the mapping from
with fonts, and points and other screen measures are used in the canvas. The tk scaling command is described on page 669. [ Team LiB ]
[ Team LiB ]
Application Embedding
Tk supports application embedding. Frames and toplevels have a -container attribute that indicates that they embed another application. This is necessary for geometry management and focus protocols. Frames and toplevels have a -use parameter that embeds them into an existing window. Wish also takes a -use command-line argument. Embedding is described on pages 489 and 312. [ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF was replaced with a -type attribute.THETA-SOFTWARE the -transient attribute CHM TO PDF CONVERTER By
[ Team LiB ]
[ Team LiB ]
UNREGISTERED VERSION OF CHM TO state displays like a default button. The normal state normal, and disabled. The active PDF CONVERTER By THETA-SOFTWARE
displays like a regular button, but leaves room for the highlight used in the active state. The disabled state, which is the default, may be smaller. You still need to program a key binding that invokes the button. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
grid rowconfigure
The grid columnconfigure and rowconfigure commands take an argument that specifies a row or column. This value can be a list:
[ Team LiB ]
[ Team LiB ]
fconfigure -error
The fconfigure -error option was added so that you can find out whether or not an asynchronous socket connection attempt has failed. It returns an empty string if the connection completed successfully. Otherwise, it returns the error message.
tcl_platform(debug)
A new element was added to the tcl_platform variable to indicate that Tcl was compiled with debugging symbols. The motivation for this is the fact that a Windows application compiled with debugging symbols cannot safely load a DLL that has been compiled without debugging symbols. Similarly, an application compiled without debugging symbols cannot safely load a DLL that does have debugging symbols. The problem is an artifact of the Microsoft C runtime library. When you build Tcl DLLs with debugging symbols their name has a trailing "d", such as tcl80d.dll instead of tcl80.dll. By testing tcl_platform(debug), a savvy application can attempt to load a matching DLL.
tcl_findLibrary
The tcl_findLibrary procedure was added to help extensions find their script library directory. This is used by Tk and other extensions. The big picture is that Tcl has a complex search path that it uses to find its own script library. It searches relative to the location of tclsh or wish and assumes a standard installation or a standard build environment. The search supports sites that have several Tcl installations and helps extensions find their correct script library. The usage of tcl_findLibrary is:
The base is the prefix of the script library directory name. The version is the main version
number (e.g., "8.0"). The patch is the full patch level (e.g., "8.0.3"). The script is the initialization script to source from the directory. The enVar names an environment variable that can be used to override the default search path. The varName is an output parameter that is set to the name of the directory found by tcl_findLibrary. A side effect of tcl_findLibrary is to source the script from the directory. An example call is:
auto_mkindex_old
The auto_mkindex procedure was reimplemented by Michael McLennan to support [incr Tcl] classes and methods. This changed the semantics somewhat so that all procedures are always indexed. Previously, only procedures defined with the word "proc" starting at the beginning of a line were indexed. The new implementation sources code into a safe interpreter and watches for proc commands however they are executed, not how they are typed into the source file. The old version of auto_mkindex was saved as auto_mkindex_old for those applications that used the trick of indenting procedure definitions to hide them from the indexing process.
safe::loadTk
This procedure was extended to take a -display displayname argument so that you can control where the main window of the safe interpreter is created. Its -use argument was extended to take either window IDs or Tk window pathnames. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
fconfigure -encoding UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE The Tcl I/O system supports character set translations. It automatically converts files to Unicode when it reads them in, and it converts them to the native system encoding during output. The fconfigure -encoding option can be used to specify alternate encodings for files. This option is described on page 219.
[ Team LiB ]
Thread Safety
The Tcl C library is thread-safe. This means that you can use Tcl in an application that uses threads. The threading model for Tcl is a thread can have one or more Tcl interpreters, but a Tcl interpreter cannot be used by different threads. For communication between threads, Tcl provides the ability to send Tcl scripts to an interpreter in another thread. The Tcl C library provides mutex variables, condition variables, and thread local storage. These primitives are used by Tcl internally, and they are meant to be used by Tcl extensions to serialize access to their own data structures. The Tcl library allows different implementations of the threading primitives. This is done to support Unix, Windows, and Macintosh. Tcl uses native threads on Windows, and Posix pthreads on Unix. MacOS does not have true threads, so it is easy to provide the required thread API.
testthread exit testthread names testthread send id ?-async? script testthread wait
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
dde ?-async? execute Sends data to the service with the given topic. service topic data dde ?-async? eval topic cmd ?arg ...? dde ?-async? poke service topic data Sends cmd and its arguments to the TclEval service with the given topic. This is an alternative to the Tk send command. Similar to the execute operation, but some services export operations under poke instead of execute.
dde ?-async? request Fetches the named item from the service with the given topic. service topic item dde services server topic dde services server {} dde services {} topic dde services {} {} [ Team LiB ] Returns server and topic if that server currently exists; otherwise, it returns the empty string. Returns all the topics implemented by server. Returns all servers that implement topic. Returns all server, topic registrations.
[ Team LiB ]
Miscellaneous
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
tcl_platform(user)
The tcl_platform(user) array element records the currently logged in user. This masks differences in environment variables and system calls used to get this information on different platforms. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
New
glob
Options
UNREGISTERED VERSION OF-path, TO PDF CONVERTER By command make it easier to CHM and -types options for glob THETA-SOFTWARE New -directory, -join,
manipulate directories in a platform-independent manner. Matching File Names with glob on page 122 describes these new options. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Canvas Improvements
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
The dash patch provided several significant improvements to the canvas widget: Canvas coordinates may be specified as a single list argument instead of individual arguments, which makes it easier to construct commands. Many items now support the notion of a dash pattern for outlines, implemented through a variety of new item options containing the word dash. Windows 95 supports only singlepixel wide dashed lines, whereas other platforms support thick dashed lines. The canvas now includes a state attribute, which modifies the default state of the canvas. Individual canvas objects all have their own -state attributes, which may override the default canvas state. Items also have new attributes to control their appearance based upon their state. The attributes that start with -active control the appearance when the mouse pointer is over the item, while the attributes starting with -disabled control the appearance when the state is disabled. Additionally, disabled canvas items don't react to canvas bindings. Advanced tag searching is available for all canvas operations that accept a tag or item ID as an argument. This adds the ability to search for canvas items based on boolean expressions of tag values. The canvas can generate Postscript for embedded images on all platforms. Additionally, on Unix platforms, it can generate Postscript for embedded widgets currently displayed on the screen (that is, displayed within the canvas's viewport and not obscured by other windows). The internal implementation of the canvas now uses Tcl_Obj values, which improved its performance.
Hidden Text
Tags in text widgets now include an -elide attribute, to hide text with that tag. This feature is used by the popular TkMan manual page browser, which can be used now without patching the Tcl core.
Pointer Warping
Tk applications now have the ability to move the mouse under program control. Use the event generate -warp option when generating KeyPress, KeyRelease, ButtonPress, ButtonRelease, or Motion events. For example:
[ Team LiB ]
Listbox Enhancements
Listboxes have a new listVariable attribute to link the contents of the listbox to a variable that contains a list value (in much the same way that the textVariable option is used in several other widgets). Listboxes also have new itemconfigure and itemcget operations to UNREGISTERED VERSION OF individual items.CONVERTER By THETA-SOFTWARE CHM TO PDF set and query the color of
but not used unless XIM is turned on (tk useinputmethods 1). This should only affect users with special input methods, and the new default behavior should be more beneficial to the average user. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
64-Bit Support
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Changes to several commands provide better support for 64-bit values, even on 32-bit platforms. (TIP #72) The changes implemented were designed to maximize backward compatibility.
[ Team LiB ]
New
file
Subcommands and
glob
Options
The file command gained several new subcommands, primarily to support the new virtual filesystem capabilities described above (TIP #17): file normalize, file separator, and file system. TIP #17 added the glob -tail option. TIP #99 added the file link command for creating hard and symbolic links. See "The file Command" on page 108 for more information on the file subcommands, and "Matching File Names with glob" on page 122 for more information on glob.
[ Team LiB ]
[ Team LiB ]
The new lset command allows you to directly change the value of an individual list element. This is much faster than using lreplace to replace the element with a new value. See "The lset Command" on page 66. The lindex command now accepts multiple indices to allow retrieval of values in nested lists. See "Getting List Elements: llength, lindex, and lrange" on 68. Many new options were added to lsearch for faster and more flexible list searching. You can use the -sorted, -ascii, -decreasing, -dictionary, -increasing, -integer, and -real options indicate that the list is already sorted in various ways, which allows lsearch to use a more efficient searching algorithm. TIP #80 added the -all, -inline, not, and -start options, giving you the ability to do things such as retrieve multiple elements with a search. See "Searching Lists: lsearch" on page 69.
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Command Tracing
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
Tcl now has the ability to trace commands as well as variables. (TIP #62) Options include triggering actions: before or after executing any specified command; before or after entering any command within a specified procedure; when a command is renamed; or when a command is deleted. A new command syntax for creating and using variable traces was also added, to match the features of command tracing. The old syntax for variable traces will be retained for now for backwards compatibility, but its use is deprecated. For more information on using UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE traces, see "Tracing Variables and Commands" on page 193. [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
regsub
The final regsub argument (the name of the variable in which to store the substituted string) is now optional. If omitted, regsub simply returns the substituted string (or the original string, of no substitutions were made). (TIP #76)
Bug Fixed in
fcopy
The fcopy command in prior versions of Tcl improperly ignored the encodings of the channels. Now fcopy respects the channel encodings, and performs proper translations on the data if the channels have different encodings. [ Team LiB ]
[ Team LiB ]
New Tk Widgets
Tk 8.4 features three new widgets: A spinbox is an extended entry widget that allows the user to move, or "spin," through a fixed set of values, such as times or dates, in addition to editing the value as in an entry. A labelframe is very similar to the standard frame, but also has the ability to display a label. (TIP #18) A panedwindow contains any number of panes, arranged horizontally or vertically. Each pane contains one widget, and each pair of panes is separated by a moveable sash, which causes the widgets on either side of the sash to be resized. (TIP #41) [ Team LiB ]
[ Team LiB ]
UNREGISTEREDnew -undo option is setTOaPDF CONVERTER the widget records every insert and the VERSION OF CHM to Boolean true value, By THETA-SOFTWARE
[ Team LiB ]
New
pack
Asymmetric Padding
Both the pack and grid commands now support asymmetric padding. If you provide a single screen distance value to either -padx or -pady, then that value is used for both the left and right (or top and bottom) padding around the widget, just as it has been in previous versions of Tk. But now if you provide a 2-element list of screen distance values, then the first value determines the padding on the left (top), and the second value determines the padding on the right (bottom).
grid
The new -uniform option for grid columnconfigure and grid rowconfigure makes it easier to create layouts with equal-sized cells. (TIP #37) [ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
[ Team LiB ]
Other Tk Changes
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE
tk_getOpenFile
The tk_getOpenFile -multiple option allows a user to select multiple files to open, returning the files selected as a list.
New
bell
The bell command has the side effect of resetting the screen saver for the screen, which usually makes the screen visible again. The new -nice option prevents the bell command from resetting the screen saver.
[ Team LiB ]
You can compile the source code like this (there are more detailed instructions in Chapter 46):
There are also source distributions in .zip files that contain the same files as the .tar.gz packages. There are Windows installers in .exe files that install ready-to-run Tcl/Tk interpreters and script libraries. The macintosh/binhex folder contains various Macintosh distributions in BINHEX format. The macintosh folder contains some of these already converted to native installers. The plugin folder contains the Web browser plugin. There is a source distribution and binary distributions for a variety of UNIX platforms, Windows, and Macintosh. The tclpro folder contains demo copies of TclPro, which is described in more detail on page 198. TclPro provides another way to get a free version of Tcl/Tk compiled for your platform. TclPro also has a nice set of development tools. You can get a demo license for the tools at: http://www.scriptics.com/registration/welchbook.html The exsource folder contains the examples from the book. These are automatically extracted from Framemaker files. One thing to watch out for is that single quotes get extracted as \". I have left these as-is. The browser.tcl script lets you view and try out the examples. The tclhttpd directory contains an unpacked version of the TclHttpd distribution. You should be able to start the server by loading the bin/httpd.tcl script into wish or tclsh. This script starts a Web server on port 8015. The tea_sample directory contains a sample Tcl extension from the Tcl Extension Architecture. This example illustrates how to create Tcl extensions on Windows and UNIX.
The download folder contains software downloaded from the Internet. Some of these have associated .README files. Others are described by files in the index folder. These descriptions are derived from the Tcl Resource Center found at: http://www.tcl.tk/resource/ The index/index.html file provides a listing and description of the software in the download folder. The CD_UTILS folder contains software you may find helpful, such as Winzip and a version of Tar for Macintosh. I have also included the mkhybrid software used to create the CD image, as well as other scripts used in the process. The welch folder contains a picture of me and a copy of my PGP key. The key ID is 7EDF9C79 and its fingerprint is:
94 D8 90 6A FD 9C AE 94
40 E3 C6 D6 B1 90 E0 03
[ Team LiB ]
[ Team LiB ]
Technical Support
Prentice Hall does not offer technical support for this software. If there is a problem with the UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE media, however, you may obtain a replacement CD by emailing a description of the problem. Send your email to:
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ]
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] #, pad with spaces in format % in clock format % in event bindings ( ) for arrays ( ) in regular expressions (?!re) in regular expressions (?=re) in regular expressions (?\\
UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE <$nopage>mv. [See file rename ]
-default, tk_messageBox option -defaultextension, tk_getOpenFile option -delta, event option -detail, event option -dictionary, lsearch option -direct, pkg_mkIndex option 2nd -displayof, send option -docRoot directory -eofchar, fconfigure option -exact, lsearch option -expanded, regular expression option -filetypes, tk_getOpenFile option -fill, pack option -format, image -glob, lsearch option -group, file attribute -handler, http\\ \\ geturl option -headers, http\\ \\ geturl option -increasing, lsearch option -indices, regular expression option -inline, lsearch option -integer, lsearch option -ipadx and -ipady pack options -keycode, event option -keysym, event option -line, regular expression option -lineanchor, regular expression option -linestop, regular expression option -longname, file property -maskdata, for image -maskfile, for image -mode, event option -mode, fconfigure option for serial devices -nocase, regexp option -not, lsearch option -override, event option -overstrike, font attribute -owner, file attribute -padx and -pady, pack options -peername, fconfigure socket option -peerport, fconfigure option -permissions, file attribute -progress, http\\ \\ geturl option -query, http\\ \\ geturl option 2nd 3rd 4th -real, lsearch option -root, event option -rootx, event option -rooty, event option
-sendevent, event option -serial, event option -shortname, file property -shrink, image operation -slant, font attribute -sorted, lsearch option -start, lsearch option -state, event option UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE -sticky, grid option -subwindow, event option -system, file attribute -timeout, http\\ \\ geturl UNREGISTEREDoption 2nd VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE -title, of standard dialog -translation, fconfigure option -underline, font attribute -validate, http\\ \\ geturl option -verbose, pkg_mkIndex option -weight, font attribute -x, event option, event option -y, event option . . in regular expressions ., (dot) in regular expressions /bin/sh _to run a Tcl script /debug, Application Direct URL /mail, Application Direct URL /status, Application Direct URL == ? in regular expressions ?, string match character ?? in regular expressions @ in binary format \\ \\ in regular expressions \\\\, backslash \\0 in regular expressions \\a in regular expressions \\A in regular expressions \\a, bell \\b in regular expressions \\B in regular expressions \\b, backspace \\c in regular expressions \\cX in regular expressions \\d in regular expressions \\D in regular expressions \\e in regular expressions \\f in regular expressions \\f, form feed \\m in regular expressions \\M in regular expressions \\n in regular expressions
\\n, newline \\r in regular expressions \\r, carriage return \\s in regular expressions \\S in regular expressions \\t in regular expressions \\t, tab \\uXXXX in regular expressions \\v in regular expressions \\v, vertical tab \\W in regular expressions \\x in regular expressions \\xhh in regular expressions \\xy in regular expressions \\xyz in regular expressions \\y in regular expressions \\Y in regular expressions \\Z in regular expressions ^ in regular expressions { } for argument grouping {m,n} in regular expressions {m,n}? in regular expressions | in regular expressions ~ in file names 3D Border 3dDarkShadow, system color 3dLight, system color 64-Bit Arithmetic Filesystem Support Value Conversions
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] A, a, in binary format abbreviation of commands abs(x), absolute value AC_OUTPUT AC_SUBST 2nd accepting socket connections access time, file acos(x), arccosine
AppleScript on Macintosh applets application activation application and user resources application class application class warning application deactivation Application Direct URL /debug /mail /status e-mail form results. form handlers specifying content type application embedding 2nd Application Initialization application name 2nd appname, tk command operation AppWorkspace, system color Aqua window system, Mac OS X 2nd arc canvas item arccosine function Architecture, Tcl Extension arcsine function arctangent function argc, Tcl variable args, example 2nd args, parameter keyword 2nd Arguments and Tcl_GetIndexFromObj, Parsing Arguments, Main Programs and Command-Line argv, saving for window session argv, Tcl variable 2nd arithmetic on text indices arithmetic operators array ArrayInvert collecting variables complex indices convert to list 2nd created with variable trace empty variable name for a Database for simple database global 2nd list of names of indices searching and statistics set from list syntax Tcl command arrow keys arrow on canvas ascii, string class asin(x), arcsine aspect ratio, message widget 2nd aspect ratio, of window
AssocData for per Interpreter Data Structures Associating State with Data asymmetric padding 2nd Asymmetric padding in geometry managers asynchronous I/O asynchronous message sending, threads 2nd atan(x), arctangent atan2(y,x), UNREGISTEREDarctangent VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE atime, file access time atom, in C attemptckalloc attemptckrealloc attribute UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE activeBackground activeForeground activeRelief anchor aspect background bitmap borderWidth button widgets Canvas Widget colormap colors, all configuring in C cursor disabledBackground disabledForeground elementBorderWidth entry widget exportSelection file foreground Frames and Toplevels geometry, old height highlightBackground highlightColor 2nd highlightThickness image insertBackground 2nd insertBorderWidth insertOffTime insertOnTime insertWidth justify Label Widget length listbox widget menu entries Message Widget of Fonts options and resources activeBorderWidth Atom and window ID information
orient padX padY platform-specific window readonlyBackground relief Scale Widget scrollbar widget selectBackground 2nd selectBorderWidth selectColor selectForeground 2nd setgrid size spinbox widget text tags text widget troughColor types, in C visual width wrapLength AUTH_TYPE, CGI environment variable auto extracting applications auto loading and auto_import auto loading, description auto, end of line translation auto-repeat, timing control auto_import, procedure hook auto_index, Tcl variable auto_mkindex_old auto_noexec, Tcl variable 2nd auto_noload, disable library auto_path, Tcl variable 2nd 3rd autoconf, configure and autoconf, tcl.m4 file autoconf, using automatic decompression automatic program execution 2nd automatic quoting
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] B, b, in binary format b, regular expression option back references
Bind_Read Bind_Save BindDefine BindDragto binding adding to arrow keys break and continue button modifiers canvas object 2nd canvas selection canvas text objects class command to event continue destroy window different binding tags double click entry widget event syntax event types execute in the global scope global in C code keyboard events listbox browse selection extended selection multiple selection single selection Meta and Escape mouse events order of execution scale widget scrollbar widget sequence of events tab key tag, defining text tags text widget 2nd 3rd Tk 4.0 changes top-level windows user interface for window changes size window dragging X, Y coordinates BindMark BindSelect bindtags, Tk command BindYview bit blit bitmap built-in canvas item definition in C code for icon 2nd
image type in label on canvas widget attribute blank, in regular expressions blinking cursor 2nd Blob and BlobState blob Command Example UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Blob_Init and BlobCleanup procedures BlobCommand and BlobPoke BlobCreate and BlobDelete BlobData and BlobN BlobNames procedure BlobState data structures UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE BLT body, http\\ \\ geturl result bold text 2nd Bonet, Achim book Web site book, font weight boolean expressions boolean preference item boolean, string class borders 3D are drawn in the canvas vs. padding, example borderWidth, widget attribute Borenstein, Nathaniel bound quantifiers bounding box, canvas bounding box, of text box on canvas break, Tcl command bindings Brouwers, Jean browse selection mode, listbox browser for the code examples browser package aliases Browser Plugin Compatiblity browser Tcl plugin browser\\ \\ displayForm displayURL getForm getURL getURL callbacks status buffering, I/O channel Building a List Building Tcl from Source built-in bitmaps built-in commands, finding
bulleted list button as event modifier associated with a Tcl procedure associated with variables attributes command container for 2nd emulate in text widget event option fixed width fixing a troublesome situation minimum width mouse as event modifiers number, mouse operations padding padding vs. packer padding problems with command procedures for commands relief attributes row of 2nd scope of command Tk widget user-defined Button, window event ButtonFace, system color ButtonFrame, system color ButtonHighlight, system color ButtonPress, window event ButtonRelease, window event ButtonShadow, system color ButtonText, system color byte code compiler 2nd 3rd ByteArrays for Binary Data
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] C command procedure. C Library, Using the Tcl C Programming and Tcl [See command procedure]
hints hit detection 2nd image object large scroll area line object min max scale moving objects object bindings object support in C objects with many points oval object polygon object postscript proposed improvements rectangle object resources for objects rotation scaling objects 2nd scroll increment scroll region 2nd selection handler example set or query item coordinates spline state stroke drawing example summary of operations tag on object 2nd tag persistence tags are not persistent tags vs. object IDs tags, logical combination text object attributes text object bindings text operations transparent text Cap Styles, Line Caps Lock key CaptionText, system color capturing program output capturing subpatterns caret Caret Management for XIM/IME Support carriage return character, \\r carriage-return line-feed translation cascaded menus case. [See switch.] catalog files managing message sample message catalogs, message namespaces and catch catching more than errors errors from open example 2nd possible return values
Tcl command cavity model, pack cd, Tcl command cd, Tcl command, multi-threaded scripts and CDE Border Width ceil(x), next highest integer cells in colormap center, anchor position UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE centering a window centimeters cget, widget operation 2nd CGI Application, Guestbook argument UNREGISTERED parsing VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE definition of Directories environment variables 2nd example script html package ncgi.tcl package script library for Cgi_Header Cgi_Parse and Cgi_Value Chained conditional with elseif change directory changing a list variable Changing Command Names with rename changing the system encoding changing widgets 2nd channel [See input/output]2nd [See input/output] drivers, I/O flush I/O stacking threads and 2nd character class names classes in regular expressions code 2nd from strings character set 2nd conversions encoding 2nd 3rd of URL checkbutton, Tk widget child windows children, of namespace choice preference item choosing items from a listbox choosing the parent for packing Chopping File Pathnames circle, canvas object Circulate, window event CirculateRequest, window event ckalloc 2nd ckfree ckrealloc
class application application, warning event binding of application resource 2nd widget clean, make target clear clipboard clear photo image clear the selection clicks per second clicks, clock operation client machine, window session client of HTTP client of the echo service client side of remote evaluation client sockets 2nd ClientData Clipboard access CLIPBOARD selection 2nd clipboard, Tk command clock formatting keywords clock seconds clock widget Clock widget data structure clock, Tcl command Clock_Init procedure ClockCmd command procedure ClockConfigure allocates resources for the widget ClockDestroy cleanup procedure ClockDisplay procedure ClockEventProc handles window events ClockInstanceCmd command procedure ClockInstanceObjCmd command procedure ClockObjCmd command procedure ClockObjConfigure, Tcl_Obj version ClockObjDelete command clone, menu operation close a window close errors from pipes close window callback close, Tcl command Closing I/O channels cntrl, in regular expressions code checker code generation code, procedure for callbacks code, read the Tcl source 2nd Codes from Command Procedures coding style collating elements color allocating in C attributes convert to number
darker color dialog to choose exhaustion name of text palettes resource names 2nd reverse video UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE RGB specification values values, in C colormap allocation UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE cells command-line argument event for frame in C size of default widget attribute columnbreak menu attribute columns of widgets columns, uniform size com port combobox [See spinbox.] comm communication package, tcllib comm extension command abbreviations aliases for safe interpreters aliases, saving as Tcl commands body build with list built-in, finding buttons C interface, String C interface, Tcl_Obj call with Tcl_Invoke callbacks complete Tcl command creating and deleting defined by a namespace, listing evaluate from C evaluation example, blob for entry widget from C using Tcl_Eval hidden from safe interpreters history 2nd http\\ \\:geturl option implement in C 2nd list-related lookup on radiobutton or checkbutton Tk 4.0 new attributes
parsing in C passing variable names prefix callbacks reading commands substitution syntax that concatenates its arguments that uses regular expressions Command key, Macintosh command line arguments command procedure 2nd and Data Objects BlobCmd call with Tcl_Invoke RandomCmd RandomObjCmd Result Codes from Command tracing command-line argument colormap display geometry name sync to Wish use visual arguments 2nd 3rd 4th arguments, in C arguments, main programs and parsing comments in line in regular expressions in resource file in switch Communicating Processes compare, string command Comparing file modify times Comparing strings 2nd 3rd comparing text indices 2nd comparison function, sorting a list compatibility, regular expression patterns Compile-Time Errors compiler, byte code compiler, make sure you have a working compiler, Microsoft Visual C++ compiler, Tcl Dev Kit Compiling Tcl and Extensions compiling Tcl and extensions multi-threaded support complex indices for arrays compound attribute to display text and image compound, widget attribute Computing a darker color
concat and eval concat and lists concat, list, double quotes comparison concat, Tcl command concatenate strings and lists condition variables 2nd standard use 2nd
Converting Numbers convertto, encoding cookie, HTTP, setting in TclHttpd coordinate space, canvas coordinates of mouse event coordinates, general Coordinates, Window copy and paste copy image area Copy options for photo images Copy, virtual event Copying Files corner grips correct quoting with eval cos(x), cosine cosh(x), hyperbolic cosine counting with regsub covering a window with place Cox, Christopher cr, end of line translation CREAT, open mode create commands in C directories elements in a hash table file pathnames file, open hash tables in C hierarchy of interpreters image types in C interpreter in C interpreter in scripts interpreters interpreters in C loadable package Starpack threads 2nd window event windows in C 2nd Critcl, tool for mixing C and Tcl crlf, end of line translation cross-platform cancel event clipboard file naming scripts virtual events ctime, file change time curly braces group arguments to eval with positioning is important stripped off vs. double quotes current directory multi-threaded scripts and current, namespace
cursor blinking 2nd entry widget in C mouse text insert widget attribute widget option in C UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Custom Dialogs cut and paste Cut, virtual event CVS repository for Tcl software Cygwin UNIX environment for Windows
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] d, in binary format d, in string format Darley, Vince dashed lines, canvas data encapsulation data in a Metakit view Data Objects, C Command Procedures and Data Structures with Arrays Data Structures, AssocData for per Interpreter data transformation Data, Using Tcl_Preserve and Tcl_Release to Guard data-driven user interface database Metakit ODBC simple in-memory 2nd using the resource date formatting date parsing date, getting current day, %d DDE Extension Deactivate, window event 2nd debug URL for TclHttpd Debug, procedure debug, text widget debugger and TclHttpd debugger, Tcl Dev Kit debugging debugging Tk applications with tkinspect declaring variables 2nd decoding HTML entities decoration, window default button default parameter values defining new binding tags delete characters in entry commands in C files interpreter interpreters in C list element by value menu items namespace text in text widget 2nd 3rd the section demibold, font depend, make target depth, screen destroy
hash tables no errors Tk command widget window window event 2nd detached window Determining UNREGISTERED if an image is used CHM TO PDF CONVERTER By THETA-SOFTWARE VERSION OF dev, file attribute dialog buiding with procedure custom data-driven approach message UNREGISTEREDfor VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE simple example to make choice window for dictionary search rules dictionary. [See array.] digit, in regular expressions digit, string class directory create current file test for packages structure, installation structure, Tcl source Tcl script from C directory selection dialog disabled canvas objects disabled entry disabledForeground, widget attribute 2nd 3rd DisabledText, system color disabling the library facility display list graphics display space, with pack display, command-line argument Display, Fonts and Text Displaying Both Text and an Image in a Widget distclean, make target distribution, Tcl source code dither image dlineinfo, text operation DLL, loading into Tcl 2nd DLLEXPORT DNS client doc, installation directory doc, make target Doc_AddRoot Doc_CheckTemplates Doc_Coookie Doc_Dynamic Doc_Error sock Doc_ErrorPage Doc_IndexFile
Doc_IsLinkToSelf Doc_NotFound Doc_NotFoundPage Doc_PublicHtml Doc_Redirect Doc_Root Doc_SetCookie Doc_Subst Doc_TemplateInterp Doc_TemplateLibrary Doc_Webmaster document root, TclHttpd 2nd document type handler, TclHttpd DOCUMENT_ROOT, CGI environment variable dollar sign syntax DOS to UNIX double click double quotes and eval compared to concat and list vs. curly braces double(x), convert to floating point Double, event double, string class Double-click, warning about downloading files with http\ \ geturl dp_send, Tcl command drag object on canvas drag out a box drag out a selection drag windows, bindings drag-and-drop drawing application, ImPress Drivers, I/O Channel DString interface 2nd Duffin, Paul dummy comment dump, text operation dword, registry value type dword_big_endian Dykstra, Dave Dynamic HTML, CGI dynamic linking 2nd Dynamic Loading and Packages Dynamic Strings, DString
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E ] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] e or E, in string format e, anchor position e, regular expression option
Emacs-like binding for Meta and Escape embed_args and plugin, variables embed_args, Tcl variable embedded application in window applications images for a bulleted list images in text options, the (?x) syntax Tk windows widgets in text window in frame window on canvas Employee DB example Empty Array Names encoding binary changing the system character set, in C character sets conversions between fconfigure option for character sets 2nd for X font I/O channels scripts in different system Tcl command 2nd end-of-file character condition makes a channel readable end-of-line character 2nd translations engineering manual, Tcl Enter, window event entry
adjust selection attributes binding to commands bindings blinking cursor changes in Tk 4.1 get the contents hidden value for password indices insert string long strings in move cursor 2nd operations read only state read-only scrolling state tips for use Tk 4.0 changes Tk widget validating contents variable for value with label entrycget, menu operation entryconfigure, menu operation env, Tcl variable to hold environment Environment Variables environment variables CGI multi-threaded scripts and eof channel eof, Tcl command eq, string comparison equal sized widgets, grid equal, string command EqualSizedLabels equivalence classes errno error background, in Tcl catching errorCode, variable errorInfo, variable 2nd fconfigure option from return handler for Tk http\\ \\:geturl result 2nd information in C reporting script Tcl command thread error handling 2nd 3rd 4th X protocol Escape key eval and double quotes
example 2nd in aliases in namespace 2nd server server for remote evaluation of code Tcl command user input wrapper procedure example UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Evaluating Expressions from C event % keywords summary bindings bindings, UNREGISTERED in C VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE for Tk-Based Window Managers generating 2nd handler, in C handler, resize in C keywords modifier sequences syntax, bindings text is selected text widget is modified Tk command types, binding virtual event loop event sources I/O handler implementation in C, Timer in C, Window in tclsh interface moves from Tk to Tcl threads and event-driven programming Examining a Metakit database Examining the File System example browser Example Plugins Example, The blob Command exception. exceptions EXCL, open mode exclusive open exec ExecLog procedure limitations on Windows syntax for I/O redirection Tcl command for running programs executable, is file execute programs automatically executing programs execution environment [See catch.] Evaluating Tcl Commands from C
exists, array command exists, interp operation exit command alias handlers hidden command multi-threaded scripts and Tcl command exmh, e-mail application exp(x), exponential expand vs. fill, with pack expand, more than one widget expand_sz, registry value type expanded regular expressions allow comments Expanding Tilde in File Names expanding variables in resources Expect Expect, Tcl extension Exploring Expect, book exponential function export from namespace exporting and importing procedures exportSelection, widget attribute expose, interp operation Expose, window event expr, Tcl command expressions and string matching, regular evaluating from C code extend a selection extended selection mode, listbox extension architecture, Tcl compiling many bundled in kitten Starkit multi-threaded scripts, using in of file name the programming sample EXTERN
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] f, in binary format f, in string format false, string class
lstat mkdir mtime, modify time multiple threads accessing name change name manipulation name manipulation in C name patterns native name of widget attributes open dialog open for I/O operations added in Tcl 7.6 ownership partial re-write pathname type read line by line read symlink value readable test rename rootname size split pathnames stat stat, array elements symbolic and hard link symbolic and hard links symbolic link tail Tcl command tilde in names type writable test file selection dialog file system interface, VFS File System, Examining the File_Process fileevent and end of file fileevent, Tcl command 2nd fill vs. expand, with pack find file by name find related files find text in widget finding files with info script first, string command Fixed-Width Button Support on Windows Systems flat, relief floor(x), next lowest integer flush, Tcl command Flynt, Clif fmod(x,y), floating point modulo focus and dialogs changes from keyboard traversal event generation and event option
events grab grab, tkwait sequence grabbing the focus highlight 2nd highlight color introduction model of UNREGISTEREDwindow VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE tab binding Tk 4.0 changes Tk command tk_focusNext focus, input FocusIn, window event UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE FocusOut, window event font actual and text attributes attributes of command summary creating named failure to find fall back to fixed family or typeface in C code measure metrics missing names platform-independent resource scaling size selection dialog 2nd selection example selection program, Unix system Tk command Fontain, Jean-Luc FontWidget handles missing fonts for loop, example for, Tcl command foreach, multiple loop variables foreach, Tcl command foreground, widget attribute forget namespace import forget, package operation form and processing form data, HTML data, TclHttpd feed character, \\f handlers HTML with browser\\ \\:getForm newguest.html self-checking HTML with entry widgets
format date and time Format flags Format Templates format text with message widget format, Tcl command 2nd Formatting strings foundry, font frame as container 2nd attributes colormap nested for packing packing example positioned on canvas reparented size Tk widget free FTP access, via VFS FTP client FTP server full screen function definition. [See procedure]
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] g or G, in string format gamma value generating events 2nd
changes in Tk 8.0 command summary external padding internal padding minimum size multiple widgets in a cell options pack, combining with 2nd panedwindow and resize behavior row and column constraints row and column padding row and column span 2nd row and column specifications sticky settings 2nd text widget and scrollbar Tk command 2nd uniform rows and columns weights window under mouse, query gridded geometry gridded geometry for a canvas gridded geometry, in C gridded, resizable listbox griddied geometry for a listbox grips on corners groove, relief group file ownership group leader, window group your patterns with curly braces grouping rules guard data with, Tcl_Preserve and Tcl_Release Guestbook CGI Application guestbook.cgi 2nd 3rd
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] H, h, in binary format handlers exit
hostname Hot Tip abbreviate history commands append is efficient args and eval array elements on demand array for module data attribute resource names Big lists can be slow bind callback is in global scope borders, padding, and highlight braces get stripped off bugs in transferring sockets between threads button command procedures canvas borders obscure features canvas hints canvas stroke example canvas tags are not persistent careful file open color, convert to RGB combining pack and grid 2nd comments at the end of line comments in switch configure tags early create managed widgets as children of a panedwindow curly brace placement detecting windowing system do not declare Tcl variables double-click warning embedding applications end-of-file makes a channel readable entry, displaying end of string errors on close eval and double quotes exit kills all threads expr is unreliable for string comparison find file by name find overlapping vs. find closest font, fall back to fixed global inside procedures grab can fail grid weights when shrinking group command bodies with braces for safety group expressions with braces group expressions with braces for performance grouping before substitution I/O operations and fileevent labels that change size list handling in C code list with foreach list, after, and send main thread must be the last one to terminate menu accelerator, consistent menu index pattern message text layout mouse cursors, all shown
name of the current interpreter 2nd namespace import takes a snapshot only exported names appear in package indexes. open a process pipeline pack the scrollbar first packing widgets to a side parentheses do not group partially qualified names UNREGISTERED VERSION can refer to two different objects. OF CHM TO PDF CONVERTER By THETA-SOFTWARE pipelines and error output quotes lose list structure resources, general patterns first result string, managing in C Scotty extension supports many network protocols UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE scrollbar for two listboxes send requires X authority send, constructing commands single round of interpretation size not set until mapped standard I/O channels in multi-threaded scripts string conversions by expr synchronous messages can deadlock multi-threaded scripts Tcl_Eval may modify its string Tcl_Obj initial reference count is zero text mark gravity The list command does automatic quoting thread\ \:join blocks threads might not start immediately after creation tkwait on global variable traces on entry values trapping errors from pipelines update, using safely Upvar aliases do not work Use arrays to collect related variables use canvas tags instead of IDs variable for widget name virtual root window coordinates Watch out for long pathnames widget data, safety in C window session protocol window size, getting correct hour, %H how auto loading works HTML A Quick Introduction comments, removing Dynamic Pages entity decoder form data mapped to procedure arguments form, self-checking Page, Beginning simple parser tags, partial list Tcl template file 2nd scrolling widgets on a canvas procedures to hide list structure
templates, for site structure templates, form handlers html package, tcllib 2nd Html_DecodeEntity Html_Parse http HTTP download http package HTTP, network protocol http\ \ cleanup config formatQuery geturl register reset unregister http\\ \\ cleanup code 2nd data error geturl geturl options geturl state array size status wait HTTP_ACCEPT, CGI environment variable HTTP_AUTHORIZATION, CGI environment variable HTTP_COOKIE, CGI environment variable HTTP_FROM, CGI environment variable Http_Get fetches the contents of a URL Http_Head validates a URL HTTP_REFERER, CGI environment variable HTTP_USER_AGENT, CGI environment variable HttpCopyDone is used with fcopy Httpd_Error Httpd_Redirect Httpd_ReturnData Httpd_ReturnFile Httpd_SelfUrl HttpGetText reads text URLs HTTPS URL access HWND, Windows identifier hyperbolic cosine function hyperbolic sine function hyperbolic tangent function hypot(x,y), hypoteneus
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] I, i, in binary format i, in string format i, regular expression option I/O events, in C 2nd icon bitmap 2nd name position
incr Tcl From The Ground Up, book[] incr Tcl object system incr Tcl, object system incr, Tcl command 2nd increment a variable index a character, entry widget canvas text object entry widget modifiers for text widgets of loadable packages of menu item string operation text widget 2nd indices, listbox widget infinite loop info hostname info script, finding files relative to info, Tcl command InfoBackground, system color InfoText, system color init.tcl, location during startup initialization application extension of Tcl procedure, for a package ino, file attribute (inode) input data into Tcl lists input focus 2nd 3rd input focus highlight input/output binary data channel properties 2nd channels, stacking command summary 2nd configuration events, in C from C from safe interpreters redirection inscope, namespace operation insert items into menu position, setting entry string into entry widget text in text widget 2nd insertBackground, widget attribute 2nd insertBorderWidth, widget attribute insertOffTime, widget attribute insertOnTime, widget attribute insertWidth, widget attribute Inspector, Tcl Dev Kit install, make target install-binaries, make target install-doc, make target
install-libraries, make target Installation Directory Structure Installation, Tcl int(x), truncate to integer integer, string class integrating TclHttpd with your application interactive command entry interactive command history UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE interactive resize interactive, detecting Interface, DString Interface, String Command Interface, Tcl_Obj Command internal padding, -ipady UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE internationalization Internet Explorer interp, for TclHttpd interp, Tcl Command interpreter creating creating in C data structures, AssocData exists test hierarchy of internal state name as a command namespaces and registry of names thread-enabled tracing commands in C interprocess communication. Introduction to HTML introspection introspection, with pack invoke menu item from program invokehidden, interp operation Invoking Scripts from C IP address, TclHttpd IRC client is, string command iso8859, fonts issafe, interp operation 2nd italic text 2nd itcl, object-oriented Tcl iterator in Tcl, creating new 2nd [See send.] intranet applications, Tcl plug-in Internationalization 2nd
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] Jacl, Tcl interpreter in Java Java Java Tcl Interpreter, Jacl Javascript Javascript, access from Tcl plug-in Johnson, Eric join in Tcl, Implementing Join Styles, Line join, file names join, Tcl command joinable threads 2nd JPEG image format justify in text widget 2nd string text in C widget attribute
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] Keeping References to Tcl_Obj Values Kenny, Kevin keyboard
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] label and an entry arranging attributes displaying different strings lining up 2nd multiline size state Tk widget width and wrap length labelframe attributes Tk widget Landers, Steve lappend, Tcl command lassign, list assignment with foreach. last, string command Layout attributes for text ldelete, Tcl procedure Leave,window event length, string command length, widget attribute Lewis, Brian lf, end of line translation lib, directory Libes, Don 2nd 3rd 4th libraries make target library and imported commands, loading based on the tclIndex File directory, Tcl how it works index introduction of procedures regular expression C search path shared Tcl C 2nd Tk C using stubs light font limit recursion depth Limitations of exec on Windows limited socket access limited temporary files lindex, Tcl command 2nd Line Cap Styles Line Join Styles line on canvas
line segment performance line spacing in text widget link, registry value type linked listboxes linking, dynamic links, symbolic and hard linsert, Tcl command list UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE accessing nested and concat append elements assignment into automatic quoting command summary UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE comparison with double quotes and concat convert to array delete by value efficient modification eliminating duplicate values extract element find matching element generating Tcl commands implement a stack insert elements join into string length of manipulation in C code 2nd modifying nested lists and lset of arrays performance of quote arguments to send replace elements searching sorting splice together split string into sublist summary of operations syntax Tcl command with foreach with interp eval list example listbox attributes bindings browse selection disabled state extended selection geometry gridding indices linked multiple selection operations constructing commands 2nd 3rd 4th 5th 6th
pair of pair working together scroll bindings selecting items selectMode attribute single selection state Tk 4.0 changes Tk widget virtual events with optional scrollbars listen, sockets listing commands defined by a namespace llength, Tcl command load automatic package changes in Tk 4.1 hidden command into slave interpreters pkg_mkIndex option shared libraries Tcl Command Tcl command 2nd tclIndex file loadable package, creating loadable package, initialization loading option database files loading package programming API locale, specifying a locate your script files, trick to locating packages, auto_path variable locating the Tcl script library location of icon location of window Lock, caps lock log files, TclHttpd Log Procedure log(x), logarithm log10(x) logging multi-threaded example logging the output of a program look-ahead in regular expressions looking at all widget attributes looking at marks looking at tags lookup, command loop break & continue event for foreach reading input while LoVerso, John
lower case conversion lower, in regular expressions lower, string class lower, Tk command lrange, Tcl command lreplace, example lreplace, Tcl command lsearch, Tcl UNREGISTEREDcommand VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE lset, Tcl command lsort, changes in Tcl 8.0 lsort, Tcl command
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] m, regular expression option Mac OS X Aqua, window system Macintosh Apple menu auto_path Classic and Aqua windowing systems command key file types look and feel serial devices shared libraries shared library location source Tcl from resource system colors system font size unsupported1 Command window styles. zoom, full Mackerras, Paul MacWindowStyle mail, sending from TclHttpd main program Command-Line Arguments Tcl_AppInit, Tcl Tk_AppInit, Tk main thread, terminating Makefile targets, TEA standard Makefile Templates Makefile.in 2nd man, installation directory managing bitmaps geometry global state message catalog files Tcl_Obj reference counts the result string 2nd user preferences X resource id manipulating file names files and directories menus and menu entries Tcl variables manual, on-line map, string command Map, window event 2nd Mapping Strings mapping windows for display MapRequest, window event mark gravity, text
mark position in text 2nd marktrusted, interp operation match, string command matching characters file names with glob precedence regular expressions and UNREGISTERED VERSIONstring CHM TO PDF CONVERTER By THETA-SOFTWARE OF math 64-bit expressions functions, built-in functions, querying
user defined virtual events MenuActive, system color MenuActiveText, system color menubutton, Tk widget MenuDisabled, system color MenuGet maps from name to menu MenuText, system color message arranging text attributes formats long lines of text text layout Tk widget Message Box message catalogs example managing namespaces and Meta key 2nd Metakit adding data to a view an embedded database creating a view or table data model examining data selecting rows tables and views microsecond precision for time Microsoft VC++ compiler Microsoft Word special characters millimeters MIME type min max scale, example minimize, window operation minimum button width minimum size, pane in panedwindow minimum size, window minimum widget size, with grid minute, %M missing font mkdir, make directory Mod, general event modifier bit mode, file attribute Modified, virtual event modifiers, event modify time, file attribute modifying a list 2nd Modifying Tcl_Obj Values module data module prefix for procedure names module support month, %B Motion, window event Mounting VFS mouse
button repeat control coordinates cursor cursor on Windows cursors event coordinates event, generate events UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE moving warping MouseWheel event MouseWheel, window event 2nd move cursor, entry widget 2nd moving the UNREGISTEREDmouse VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE msgcat package 2nd 3rd msgcat\ \ mcunknown msgcat\\ \\ mc mcload mclocale 2nd 3rd mcpreferences mcset locale mcunknown mtime, file attribute multi-threaded Tcl scripts. multicolumn palette menus multiline labels multiple foreach loop variables interpreters interpreters and Safe-Tcl 2nd loop variables with foreach return values selection mode, listbox value lists with foreach multiway branch, switch mutexes 2nd [See threads.] multi_sz, registry value type
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] n, anchor position n, regular expression option name command-line argument giving out yours manipulating file namespace syntax of all interpreters of atom of color of current interpreter 2nd of encoding of fonts of geometry manager for window of I/O channels of images of interpreter, in C of interpreter, send 2nd 3rd of packages of procedure of text marks of variable of widgets on icon qualified namespace quirks in namespaces window server Named Fonts namespace added in Tcl 8.0 and upvar callbacks and check if one exists converting packages to use efficient variable references import takes a snapshot listing commands message catalogs name manipulation nested original Tcl command uplevel, and using variables widgets, images, and interpreters Native Buttons and Scrollbars native file name native look and feel Native Menus and Menubars ncgi package 2nd
ne, anchor position ne, string comparison nested frames nested lists nested namespaces Netscape Navigator network programming network server UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Network Sockets networking extensions, tcllib New Image Types, Creating newguest.cgi script 2nd newguest.html Form newline character UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE newline sensitive matching Newline Translations Newman, Matt Nichols, David Nijtmans, Jan 2nd nlink, file attribute NNTP client NO_CONST NOCTTY, open mode NONBLOCK, open mode nonblocking I/O 2nd none, registry value type nongreedy quantifiers normal, font Numbers, Converting numeric value, widget for nw, anchor position
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] o, in string format Object Support, Canvas Object Types, Primitive Object Types, String object-oriented, incr Tcl objects with many points Objects, C Command Procedures and Data Objects, Tcl ODBC offRelief, widget attribute on-line manual open a window a window, binding catching errors from client socket with a timeout connection to an HTTP server file dialog file for an unsafe interpreter file for writing files for I/O Process Pipeline server socket Tcl command operators, arithmetic option database. [See resource.] option menus Option Processing option, Tk command optional scrollbars Options to the standard file dialogs options vs. attributes vs. resources Oracle OraTcl Order, Window Stacking Organizing source into packages orient, widget attribute original namespace Ousterhout, John 2nd 3rd oval, canvas object overRelief, widget attribute override redirect ownership, file
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] p, regular expression option pack asymmetric padding command options display space expand vs. fill grid, combining with 2nd into other relatives order of children packing order 2nd packing space and display space padding padding vs. button padding panedwindow and resizing windows scrollbars first space for Tk 4.0 changes Tk command unexpected results package convert to namespaces creating a loadable directory dynamic loading html implemented in C code index index file initialization in C ncgi 2nd Tcl command 2nd version numbers versions, comparing packaging sources in starkits padding and anchors around widgets asymmetric 2nd 3rd button vs. packer in buttons widget padX, widget attribute padY, widget attribute page array, TclHttpd page layout application palette menus pane manager Pane_Create sets up vertical or horizontal panes
PaneDrag adjusts the percentage panedwindow adding panes attributes creating managed widgets minimum pane size operations orientation of panes pane order positioning pane contents removing panes PaneGeometry updates the layout parameters, variable number of parent directory for pack namespace window 2nd 3rd 4th Parentheses are not a grouping mechanism parity, serial interface parsing arguments arguments and Tcl_GetIndexFromObj command-line arguments Tcl commands in C URLs pass by reference Passing Arrays by Name password entry, hidden value password, prompting for paste canvas example PRIMARY or CLIPBOARD selection selection at the insert cursor virtual event PATH_INFO, CGI environment variable PATH_TRANSLATED, CGI environment variable pathname from window ID pattern match glob, file name match glob, string match menu entries resource database switch command URL regular expression performance appending strings canvas items declaring variables faster string operations improving expression tuning performance improvements performance tuning Perl Photo image attributes
Photo image operations photo, C interface pid, Tcl command pie slice, canvas pipes and errors closing fileevent UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE setting up in C Pitfalls of Shared Tcl_Obj Values pixel depth pixels pixels per inch pixmap UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE configuration type in C off screen pkg_mkIndex options pkg_mkIndex, Tcl command 2nd pkgIndex.tcl in a Starkit place basics event option geometry manager panedwindow and Tk command placement options plain file Platform-Independent Fonts Platform-Specific End of Line Characters Platform-specific file attributes plugin examples, web browser Tcl 8.2 support Tcl in a Web page plus, in bindings Plus1ObjCmd procedure pointer warping Pointer Warping points points per pixel polygon, canvas item pop-up menus POP3 client POP3 server port, TclHttpd position a window above a sibling in text widget in virtual root window relative to widget text anchor POSIX errorCode file access flags for open
post menu on screen POST, form data POST, HTTP protocol postcascade , menu operation Postscript for Widgets Embedded on a Canvas Under Windows postscript from canvas pow(x,y), power precision, of expressions Predefined Variables Pref_Add Pref_Dialog Pref_Init PrefDialogItem PrefDismiss PrefEntrySet preferences data definition help initialization items, adding read from file saving to file user interface variables PrefFixupBoolean PrefItemHelp PrefReadFile PrefReset PrefSave PrefValue PrefValueSet present working directory. preserving threads 2nd PRIMARY selection Primitive Object Types print [See puts.] a procedure definition environment variable values in regular expressions string class variable by name PrintByName, Tcl procedure printer points printf. [See format command] private procedure proc, Tcl command 2nd procedure arguments from HTML forms array parameters as parameter characters allowed in names construct dynamically definition 2nd for button commands importing and exporting [See current directory.] Preserving errorInfo when calling error
introspection library multiple return values naming conventions printing definition query definition small is good to build dialogs UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE variable scope process ID Processing HTML Form Data procmail email filtering email filtering, procmail
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] q, regular expression option qualified names qualified names, performance qualifiers, namespace operation Quantifiers in regular expressions QUERY_STRING, CGI environment variable querying aliases questhead quirks, namespaces quit application, protocol to quit button quotes compared to concat and list quoting and eval 2nd and regular expressions automatic tips, funny values tips, grouping
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] radiobutton, Tk widget Raines, Paul raise an error raised, relief Raising an error with return rand(), random number Random Access I/O random access I/O example example using namespaces 2nd function in C RandomCmd C command procedure RandomObjCmd C command procedure RDONLY, open mode RDWR, open mode read and evaluate commands from a socket file line by line I/O in background option database file options for photo images Tcl command Tcl commands from a file 2nd Tcl source code 2nd readable, file readline. [See gets.] readlink, file operation readlink, with file link command readonly entry entry widget open state text widget variables readonly, file attribute realloc records, with arrays rectangle on canvas recursion limit redefining procedures redirect URL request redisplay. redo. [See update.] [See history.]
reference count, zero initial value Reference Counts, Managing Tcl_Obj References to Tcl_Obj Values, Keeping
Referencing an array indirectly reflection and debugging regexp command options 2nd in text search lsearch option Tcl command register image format, in C registry, font registry, Tcl command regsub counting with direct return of substituted string Tcl command regular expression 2nd C library new for Tcl 8.1 syntax 2nd Reid, Steve relative and absolute window sizes relative position of windows releasing threads 2nd Relief Style relief, button relief, widget attribute Remote eval using sockets REMOTE_ADDR, CGI environment variable REMOTE_USER, CGI environment variable Removing Elements from a Hash Table rename, Tcl command Renaming Files and Directories Reparent, window event reparented frame repeating a string replacing substring Reporting Script Errors REQUEST_METHOD, CGI environment variable REQUEST_URI, CGI environment variable requested hight of widget require, package operation 2nd ResEdit, Macintosh 2nd ResizeRequest, window event resizing and -expand grids text and scrollbar windows 2nd windows, effect of expand resource associated with Tcl variable attribute names attribute vs. options vs. class color database access database description
example file example font for all button widgets for canvas objects ID Management, X introduction loading from files 2nd UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE lookup in C code Macintosh name patterns non-standard names order of patterns specifications UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE user vs. application with variable references Resource_ButtonFrame, defines buttons 2nd Resource_GetFamily merges resources resource_list, registry value type RESOURCE_MANAGER property Result Codes from Command Procedures result string, managing in C 2nd return codes, Tcl_Eval Return key return multiple values return, Tcl command 2nd reverse video RGB color values 2nd ridge, relief ring the bell Rooms. [See Virtual Root.] root window ID root, file name Rose, Marshall Roseman, Mark rotation not supported, canvas round(x), round to integer row insert, Metakit view row of buttons rows of widgets rows, uniform size RS 232, serial devices rubber banding Run procedure Running Programs with exec runs Tcl commands from C, Tcl_Eval
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] s, anchor position s, in string format s, regular expression option S, s, in binary format safe after command safe base safe interpreter, creating safe interpreters Safe-Tcl 2nd 3rd Safe-Tk and the Browser Plugin Safe-Tk Restrictions safe\ \ loadTk safe\\ \\ interpAddToAccessPath interpConfigure interpCreate interpDelete interpFindInAccess interpInit setLogCmd Safesock security policy same width widgets with grid Sample Extension sample message catalog files sample regular expressions saving preferences Saving session state saving state as Tcl commands scale of screen units scale widget attributes bindings canvas implementation operations Tk widget variable scaling canvas objects scan, Tcl command scanf. scope for callbacks global variables local variables screen coordinates vs. canvas coordinates depth for toplevel height [See scan command]
identifier measurement units 2nd converting in C scaling multiple position of window relative coordinates UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE width screen savers and bell Script Errors, Reporting script library initialization setting with TCL_LIBRARY UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE using script, current script, namespace callbacks SCRIPT_NAME, CGI environment variable Scriptics Scriptics Corporation scripts and the library Scripts from C, Invoking 2nd scripts in different encodings scroll entry widget Scroll_Set manages optional scrollbars scrollbar attributes automatic hiding bindings entry widget example 2nd for canvas for listbox for two widgets horizontal or vertical operations protocol with widgets set size system color Tk widget widgets on a canvas with text ScrollFixup sdarchive, starkit archive sdx, starkit development tool se, anchor position search operation, in text search path, library 2nd searching arrays lists 2nd text widget 2nd through files second, %S secure hash algorithm, sha1 Secure sockets
secure web access security policies and Browser Plugin configuration 2nd configured for each client creating feature sets Safesock Tempfile seek, Tcl command select loop, Tcl interface select text in entry widget select. [See fileevent.] selectBackground, widget attribute 2nd selectBorderWidth, widget attribute selectColor, widget attribute selectForeground, widget attribute 2nd Selecting data with mk\ \ select Selecting Multiple Files with tk_getOpenFile selection adjust, entry widget and clipboard in C attributes canvas example 2nd clear CLIPBOARD deleting exporting to X handler example model ownership PRIMARY text widget 2nd Tk command virtual event selectMode, for listbox self-checking form self-contained Tcl distribution self-updating applications send application name in C command information command options command to another application constructing command reliably cross-platform replacement name of interpreter 2nd timeout changed in Tk 4.0 Tk command X authority required sender application sending messages to threads 2nd serial ports 2nd 3rd 4th server socket options
server sockets server, multi-threaded example SERVER_NAME, CGI environment variable SERVER_PORT, CGI environment variable SERVER_PROTOCOL, CGI environment variable SERVER_SOFTWARE, CGI environment variable services, on Windows session, window system UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE client command saving Set Conversions, Character set, Tcl command 2nd setgrid, widget attribute UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE sha1, secure hash algorithm shared libraries 2nd 3rd shared resources, threads 2nd Shared Tcl_Obj Values, Pitfalls of shared variables, threads 2nd sharing code as Starkits Shen, Sam Shift key shrinking frames and pack propagate signal handling, in C Signals, Working with significant digits Simple Records sin(x), sine single selection mode, listbox sinh(x), hyperbolic sine SiteFooter SiteMenu SitePage size font attribute not valid until window is mapped of file of integer word of label placement and decoration relative to widget slaves, interp operation sleep, Tcl_Sleep sleep. [See after.] Smith, Chad SMTP client SMTP server socket accepting connections added in Tcl 7.5 client side client timeout connect to HTTP server limited with safe interp listen share, I/O channels with interp
peer address read Tcl commands from server example special file Tcl Command socket I/O, non-blocking solid, relief sort sorting lists source example hidden command in safe interpreters loading code into TclHttpd 2nd Tcl command 2nd source code best location compiling Tcl from distribution, Tcl is worth reading,Tcl 2nd source files relative to current script space around widgets in array indices in regular expressions in string format string class spacing, widgets special characters in character sets specifying a locale Spencer, Henry 2nd spinbox attributes splice lists together spline curve on canvas split data into Tcl lists split file names split, Tcl command sqrt(x), square root square brackets srand(x), random number seed SSL and TLS SSL channel plugin stack depth limit stack trace 2nd 3rd stack, data structure stack, example stacking I/O channels stacking order, window 2nd 3rd 4th 5th 6th 7th standalone Tcl script Standard Configure Flags Standard Dialogs 2nd Standard Directory Structure Standard Header Files Standard Makefile targets, TEA standard options
Standard Tcl Library networking extensions Starkit main.tcl file tcllib 2nd starkit archive create a simple one creating tclhttpd.kit UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE examine the virtual file system files in kitten extension bundle main program packaging Tcl applications sdx development tool UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE sharing among applications starkit\ \:autoextend and auto_path starkit\\ \\:startup return values starpacks storing application data thin clients Wiki starpack how to create Tclkit and Starkits stat, file attributes stat, symlink attributes state canvas and canvas items State of Entries, Listboxes, and Labels state of window static code checker status, http\\ \\ geturl result Status, Tcl procedure status, TclHttpd stderr, standard error output stdin, standard input stdout, standard output Steffen, Daniel sticky geometry settings stop bits, serial interface Stop procedure store widget names in variables Storing application data in a Starkit strftime strftime, string characters from class names classification 2nd command interface in C command, changes in Tcl 8.1 comparison 2nd 3rd 4th [See clock format]
comparison operators comparison, using expr concatenate display. [See label. ] dynamic (DString) in C effect of backslash-newline encoding conversions expressions extract a character find last substring identifiers (UIDS) in C indices internationalization in C length in characters mapping to new strings match simple pattern matching matching, regular expressions in C object types in C processing with subst repeating replacing substring result, managing in C 2nd storage size Tcl command 2nd stroke, canvas example structures, with arrays Stub Libraries, Using style guide, Tcl Line Cap Line Join Relief Text Justification subpatterns to parse strings subst document templates Tcl command template example substitution and hidden commands before grouping no eval rules summary of package loading summary of the Tk Commands Sun Microsystems 2nd sunken, relief sw, anchor position SWIG switch example on exact strings substitutions in patterns Tcl command with fallthrough cases
Sybase SybTcl symbolic and hard links symbolic link symbolic link, file sync, command-line argument synchronous message sending, threads 2nd syntax UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE advanced regular expressions arrays character code command curly braces dollar sign UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE I/O pipelines list 2nd regular expressions square brackets Tcl Dev Kit Checker system encoding system font system menus
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T ] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] t, regular expression option tab character, \\t Tab key tab stops tab to change focus tab, default binding Table, Hash 2nd table-like layouts, grid Tables or views in a Metakit database tag canvas vs. text canvas widget 2nd canvas, logical combination text widget 2nd attributes bindings initialization tail, file name tan(x), tangent tanh(x), hyperbolic tangent target, interp operation TChar Tcl 7.4 Tcl 7.5 2nd Tcl 7.6 2nd 3rd Tcl 8.0 Patch Releases Tcl and Extensions, Compiling Tcl and the Tk Toolkit, book Tcl and Tk sources, on the web Tcl books Building Network Management Tools with Tcl/Tk Effective Tcl/Tk Programming Exploring Expect Graphical Applications with Tcl & Tk incr Tcl From The Ground Up Tcl and the Tk Toolkit Tcl/Tk for Programmers Tcl/Tk in a Nutshell Tcl/Tk Tools Web Tcl Complete Tcl C Library 2nd Tcl command [See also Tk command] after, timer events append, strings array, data type bgerror, error handler 2nd binary, convert between string and binary break, exit loop catch, error handler cd, change directory close, I/O channel
concat, concatenate strings and lists 2nd console, Windows and Macintosh 2nd continue, loop dde, dynamic data exchange encoding, character sets eof, test end of file error, raise error eval, evaluate a string UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE exec, run programs exit, terminate expr, math expressions fblocked, I/O channel fconfigure, I/O channel properties fcopy, I/O channel copy UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE file, operate on files flush, I/O channel for, loop foreach, loop format, strings 2nd from C, Tcl_Eval 2nd generating with list gets, read line glob, match file names 2nd global, variables history, of commands if, conditional incr, improved version incr, increment variable info, introspection interp, create interpreter join, merge lists lappend, append to list lindex, element from list 2nd linsert, modify list list for code generation list, create lists list-related commands llength, list length load, compiled extensions 2nd lrange, list sublist lreplace, modify list lset lsort, sort list Tcl Command memory Tcl command memory, for debugging malloc/free namespace, variables and procedures 2nd number executed open, I/O channel package, manage libraries pid, get process ID pkg_mkIndex, generate package index proc, define procedures 2nd puts, print line fileevent, select I/O channel 2nd
pwd, get working directory read, I/O channel regexp, match regular expression registry, Windows regsub, regular expression substitution rename, commands and procedures return, from procedure 2nd scan, parsing strings seek, move I/O channel offset set, getting variable value set, variable assignment socket, network source, read Tcl script file split, data into list string, collection of operations subst, substitute Tcl in data switch, multiway branch table of tell, read I/O channel offset testthread time, measure command speed trace, variables unknown, command fallback unset, delete variable uplevel, evaluate in different scope upvar, variable references vwait, wait for event while, loop writing commands to files Tcl Core Team, TCT Tcl Dev Kit development tools Tcl distribution, self-contained Tcl Engineering Manual Tcl Extension Architecture Tcl Extention Architecture (TEA) Tcl Improvement Proposal, TIP Tcl Initialization Tcl library Tcl main program and Tcl_AppInit Tcl Objects Tcl Scripts, Calling Out to Tcl Service Manager Tcl shell library environment Tcl shell, sample program 2nd Tcl source code is worth reading 2nd Tcl source directory structure Tcl Style Guide Tcl variable argc argv 2nd 3rd 4th 5th auto_index auto_noexec 2nd auto_noload auto_path 2nd 3rd 4th embed_args env 2nd
errorCode errorInfo 2nd from C tcl_interactive tcl_library 2nd tcl_patchLevel tcl_pkgPath tcl_platform UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE tcl_precision tcl_prompt1 tcl_version Tcl version Tcl, C Programming and Tcl, compiling from source UNREGISTERED VERSION 2nd CHM TO PDF CONVERTER By THETA-SOFTWARE OF Tcl, CVS repository Tcl/Tk 8.4 Tcl/Tk 8.0 2nd Tcl/Tk 8.1 2nd Tcl/Tk 8.2 2nd Tcl/Tk 8.3 Tcl/Tk Aqua Aqua, Tcl/Tk for Mac OS X Mac OS X Tcl/Tk for Programmers, book Tcl/Tk for Real Programmers, book Tcl/Tk in a Nutshell, book Tcl/Tk Tools, book Tcl_Access Tcl_AddErrorInfo Tcl_AddObjErrorInfo Tcl_Alert-Notifier Tcl_Alloc Tcl_Alloc and Tcl_Free Tcl_AllocStatBuf Tcl_AllowExceptions Tcl_AppendAllObjTypes Tcl_AppendElement 2nd Tcl_AppendObjToObj Tcl_AppendResult 2nd 3rd 4th 5th Tcl_AppendStringsToObj 2nd Tcl_AppendToObj Tcl_AppendUnicodeToObj Tcl_AppInit 2nd 3rd 4th Tcl_AsyncCreate Tcl_AsyncDelete Tcl_AsyncInvoke 2nd Tcl_AsyncMark Tcl_AsyncReady Tcl_AttemptAlloc Tcl_AttemptRealloc Tcl_AttemptSetObjLength Tcl_BackgroundError Tcl_Backslash Tcl_BadChannelOption tcl.m4 autoconf macros
TCL_BREAK Tcl_CallWhenDeleted Tcl_CancelIdleCall Tcl_ChannelBlockModeProc 2nd Tcl_ChannelBuffered Tcl_ChannelClose2Proc Tcl_ChannelCloseProc Tcl_ChannelFlushProc Tcl_ChannelGetHandleProc Tcl_ChannelGetOptionProc Tcl_ChannelHandlerProc Tcl_ChannelInputProc Tcl_ChannelOutputProc Tcl_ChannelSeekProc Tcl_ChannelSetOptionProc Tcl_ChannelType Tcl_ChannelVersion Tcl_ChannelWatchProc Tcl_ChannelWideSeekProc Tcl_Chdir Tcl_ClearChannelHandlers Tcl_Close Tcl_CommandComplete Tcl_CommandTraceInfo Tcl_Concat 2nd Tcl_ConcatObj 2nd Tcl_ConditionFinalize Tcl_ConditionNotify Tcl_ConditionWait TCL_CONTINUE Tcl_ConvertCountedElement Tcl_ConvertElement Tcl_ConvertToType Tcl_CreateAlias Tcl_CreateAliasObj Tcl_CreateChannel 2nd Tcl_CreateChannelHandler Tcl_CreateCloseHandler Tcl_CreateCommand 2nd 3rd 4th 5th 6th 7th 8th Tcl_CreateEncoding Tcl_CreateEventSource Tcl_CreateExitHandler Tcl_CreateFileHandler 2nd 3rd Tcl_CreateHashEntry 2nd Tcl_CreateInterp 2nd 3rd Tcl_CreateMathFunc Tcl_CreateObjCommand 2nd 3rd 4th Tcl_CreateObjTrace Tcl_CreateSlave Tcl_CreateThread Tcl_CreateThreadExitHandler Tcl_CreateTimerHandler Tcl_CreateTrace Tcl_CutChannel Tcl_DecrRefCount 2nd 3rd 4th 5th Tcl_Delete-HashEntry
Tcl_DeleteAssocData Tcl_DeleteChannelHandler Tcl_DeleteCloseHandler Tcl_DeleteCommand 2nd Tcl_DeleteCommandFromToken Tcl_DeleteEvents Tcl_DeleteEventSource Tcl_DeleteExitHandler UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_DeleteFileHandler 2nd Tcl_DeleteHashTable Tcl_DeleteInterp 2nd Tcl_DeleteThreadExitHandler Tcl_DeleteTimerHandler Tcl_DeleteTrace UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_DelteHashEntry Tcl_DetachChannel Tcl_DetachPids Tcl_DiscardResult Tcl_DontCallWhenDeleted Tcl_DoOneEvent 2nd Tcl_DoWhenIdle Tcl_DString Tcl_DString-Result Tcl_DStringAppend 2nd Tcl_DStringAppendElement Tcl_DStringEndSublist Tcl_DStringFree Tcl_DStringGetResult Tcl_DStringInit 2nd Tcl_DStringLength Tcl_DStringSetLength Tcl_DStringStartSublist Tcl_DStringValue 2nd Tcl_DumpActiveMemory Tcl_DuplicateObj 2nd Tcl_Eof Tcl_ErrnoId Tcl_ErrnoMsg TCL_ERROR 2nd Tcl_Eval 2nd 3rd 4th 5th Tcl_Eval modifies its argument. Tcl_Eval, Bypassing Tcl_Eval, return codes TCL_EVAL_DIRECT Tcl_EvalEx 2nd Tcl_EvalFile 2nd Tcl_EvalObj 2nd Tcl_EvalObjEx 2nd Tcl_EvalObjv 2nd Tcl_EvalTokens Tcl_EvalTokensStandard Tcl_EventuallyFree 2nd Tcl_Exit 2nd Tcl_ExitThread Tcl_ExposeCommand Tcl_ExprBoolean
Tcl_ExprBooleanObj Tcl_ExprDouble Tcl_ExprDoubleObj Tcl_ExprLong Tcl_ExprLongObj Tcl_ExprObj Tcl_ExprString Tcl_ExternalToUtf Tcl_ExternalToUtfDString 2nd Tcl_Finalize Tcl_FinalizeNotifier Tcl_FinalizeThread Tcl_FindExectuable Tcl_FindExecuatable 2nd Tcl_FindHashEntry tcl_findLibrary 2nd Tcl_FirstHashEntry 2nd 3rd Tcl_Flush Tcl_Free 2nd Tcl_Free, Tcl_Alloc and Tcl_FreeEncoding 2nd Tcl_FreeParse Tcl_FSAccess Tcl_FSChdir Tcl_FSConvertToPathType Tcl_FSCopyDirectory Tcl_FSCopyFile Tcl_FSCreateDirectory Tcl_FSData Tcl_FSDeleteFile 2nd Tcl_FSEqualPaths Tcl_FSEvalFile Tcl_FSFileAttrsGet Tcl_FSFileAttrsSet Tcl_FSFileAttrStrings Tcl_FSFileSystemInfo Tcl_FSGetCwd Tcl_FSGetFileSystemForPath Tcl_FSGetInternalRep Tcl_FSGetNativePath Tcl_FSGetNormalizedPath Tcl_FSGetPathType Tcl_FSGetTranslatedPath Tcl_FSGetTranslatedStringPath Tcl_FSJoinPath Tcl_FSJoinToPath Tcl_FSLink Tcl_FSListVolumes Tcl_FSLoadFile Tcl_FSLstat Tcl_FSMatchInDirectory Tcl_FSMountsChanged Tcl_FSNewNativePath Tcl_FSOpenFileChannel Tcl_FSPathSeparator Tcl_FSRegister
Tcl_FSRemoveDirectory Tcl_FSRenameFile Tcl_FSSplitPath Tcl_FSStat Tcl_FSUnregister Tcl_FSUtime Tcl_Get*FromObj warning Tcl_GetAlias UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_GetAliases Tcl_GetAliasObj Tcl_GetAssocData Tcl_GetBoolean Tcl_GetBooleanFromObj Tcl_GetByteArrayFromObj UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_GetChannel 2nd Tcl_GetChannelBufferSize Tcl_GetChannelHandle Tcl_GetChannelInstanceData Tcl_GetChannelMode Tcl_GetChannelName Tcl_GetChannelNames Tcl_GetChannelNamesEx Tcl_GetChannelOption Tcl_GetChannelThread Tcl_GetChannelType Tcl_GetCharLength Tcl_GetCommandInfo 2nd 3rd Tcl_GetCommandInfoFromToken Tcl_GetCurrentThread Tcl_GetCwd Tcl_GetDefaultEncodingDir Tcl_GetDouble Tcl_GetDoubleFromObj Tcl_GetEncoding 2nd Tcl_GetEncodingName Tcl_GetEncodingNames Tcl_GetErrno Tcl_GetHashKey Tcl_GetHashValue 2nd Tcl_GetHostName Tcl_GetIndexFromObj 2nd 3rd 4th 5th Tcl_GetIndexFromObjStruct Tcl_GetInt 2nd 3rd 4th Tcl_GetInterpPath Tcl_GetIntFromObj 2nd Tcl_GetListFromObj Tcl_GetLongFromObj Tcl_GetMaster Tcl_GetMathFuncInfo Tcl_GetNameOfExecutable Tcl_GetObjResult 2nd 3rd 4th Tcl_GetObjType Tcl_GetOpenFile Tcl_GetOSTypeFromObj Tcl_GetPathType Tcl_GetRange 2nd
Tcl_GetRegExpFromObj Tcl_GetRegExpInfo Tcl_Gets Tcl_GetServiceMode Tcl_GetSlave Tcl_GetSlaves Tcl_GetsObj Tcl_GetStackedChannel Tcl_GetStdChannel Tcl_GetString Tcl_GetStringFromObj Tcl_GetStringResult 2nd Tcl_GetThreadData Tcl_GetTime Tcl_GetTopChannel Tcl_GetUniChar Tcl_GetUnicode Tcl_GetUnicodeFromObj Tcl_GetVar 2nd Tcl_GetVar2 Tcl_GetVar2Ex Tcl_GetVersion Tcl_GetWideIntFromObj TCL_GLOBAL_EVAL Tcl_GlobalEval 2nd Tcl_GlobalEvalObj Tcl_HashStats Tcl_HashTable Tcl_HideCommand Tcl_IncrRefCount 2nd 3rd 4th Tcl_Init 2nd Tcl_InitCustomHashTable Tcl_InitHashTable 2nd Tcl_InitMemory Tcl_InitNotifier Tcl_InitObjHashTable Tcl_InitStubs 2nd 3rd 4th Tcl_InitStubs Tcl_InputBlocked Tcl_InputBuffered tcl_interactive, Tcl variable Tcl_InterpDeleted Tcl_InvalidateStringRep Tcl_Invoke Tcl_Invoke bypasses Tcl_Eval Tcl_IsChannelExisting Tcl_IsChannelRegistered Tcl_IsChannelShared Tcl_IsSafe Tcl_IsShared 2nd Tcl_IsStandardChannel Tcl_JoinPath Tcl_JoinThread TCL_LIBRARY, environment variable tcl_library, Tcl variable 2nd Tcl_LinkVar 2nd
Tcl_ListMathFuncs Tcl_ListObjAppendElement 2nd Tcl_ListObjAppendList 2nd Tcl_ListObjGetElements Tcl_ListObjIndex Tcl_ListObjLength Tcl_ListObjReplace Tcl_LogCommandInfo UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_MacConvertTextResource Tcl_MacEvalResource Tcl_MacFindResource Tcl_MacSetEventProc Tcl_Main 2nd Tcl_Main and Tcl_AppInit UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_MakeFileChannel Tcl_MakeSafe Tcl_MakeTcpClientChannel TCL_MEM_DEBUG Tcl_Merge 2nd Tcl_MutexFinalize Tcl_MutexLock Tcl_MutexUnlock Tcl_NewBooleanObj Tcl_NewByteArrayObj Tcl_NewDoubleObj Tcl_NewIntObj Tcl_NewListObj 2nd Tcl_NewLongObj Tcl_NewObj Tcl_NewStringObj 2nd Tcl_NewUnicodeObj Tcl_NewWideInt Tcl_NextHashEntry Tcl_NotifyChannel Tcl_NumUtfChars Tcl_Obj Tcl_Obj Command Interface, The Tcl_Obj reference count Tcl_Obj Reference Counts, Managing Tcl_Obj structure., The Tcl_Obj Values, Keeping References to Tcl_Obj Values, Modifying Tcl_Obj Values, Pitfalls of Shared Tcl_Obj version of Tk widget Tcl_ObjGetVar2 Tcl_ObjSetVar2 TCL_OK 2nd Tcl_OpenCommandChannel 2nd Tcl_OpenFileChannel Tcl_OpenTcpClient Tcl_OpenTcpServer Tcl_OutputBuffered Tcl_Panic Tcl_PanicVA Tcl_ParseBraces Tcl_ParseCommand
Tcl_ParseExpr Tcl_ParseQuotedString Tcl_ParseVar Tcl_ParseVarName tcl_patchLevel, Tcl variable tcl_pkgPath, Tcl variable Tcl_PkgPresent Tcl_PkgPresentEx Tcl_PkgProvide 2nd 3rd Tcl_PkgProvide, Using Tcl_PkgProvideEx Tcl_PkgRequire Tcl_PkgRequireEx tcl_platform threaded element tcl_platform, debug element tcl_platform, Tcl variable tcl_platform, user element Tcl_PosixError tcl_precision tcl_precision variable tcl_precision, changes in Tcl 8.0 Tcl_Preserve 2nd Tcl_PrintDouble tcl_prompt1, Tcl variable Tcl_PutEnv Tcl_QueueEvent Tcl_Read Tcl_ReadChars Tcl_ReadRaw Tcl_Realloc Tcl_ReapDetachedProcs Tcl_RecordAndEval Tcl_RecordAndEvalObj Tcl_RegExpCompile Tcl_RegExpExec Tcl_RegExpExecObj Tcl_RegExpMatch Tcl_RegExpMatchObj Tcl_RegExpRange Tcl_RegisterChannel Tcl_RegisterObjType Tcl_Release 2nd Tcl_ResetResult 2nd 3rd Tcl_RestoreResult TCL_RETURN tcl_safeCreateInterp tcl_safeDeleteInterp tcl_safeInitInterp Tcl_SaveResult Tcl_ScanCountedElement Tcl_ScanElement Tcl_Seek Tcl_ServiceAll Tcl_ServiceEvent Tcl_SetAssocData
Tcl_SetBooleanObj Tcl_SetByteArray-Length Tcl_SetByteArrayObj Tcl_SetChannelBufferSize Tcl_SetChannelOption Tcl_SetCommandInfo 2nd Tcl_SetCommandInfoFromToken Tcl_SetDefaultEncodingDir. UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_SetDefaultTranslation 2nd Tcl_SetDoubleObj Tcl_SetErrno Tcl_SetErrorCode Tcl_SetErrorCodeVA Tcl_SetHashValue 2nd UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_SetIntObj 2nd 3rd Tcl_SetListObj Tcl_SetLongObj. Tcl_SetMainLoop Tcl_SetMaxBlockTime Tcl_SetNotifier Tcl_SetObjErrorCode Tcl_SetObjLength Tcl_SetObjResult 2nd 3rd 4th Tcl_SetOSTypeObj Tcl_SetRecursionLimit Tcl_SetResult 2nd Tcl_SetServiceMode Tcl_SetStdChannel Tcl_SetStringObj 2nd 3rd 4th Tcl_SetSystemEncoding Tcl_SetTimer Tcl_SetUnicodeObj Tcl_SetVar 2nd 3rd Tcl_SetVar2 Tcl_SetVar2Ex Tcl_SetWideInt Tcl_SignalId Tcl_SignalMsg Tcl_Sleep 2nd Tcl_SourceRCFile Tcl_SpliceChannel Tcl_SplitList Tcl_SplitPath Tcl_StackChannel Tcl_Stat TCL_STATIC Tcl_StaticPackage TCL_STORAGE_CLASS Tcl_StringCaseMatch Tcl_StringMatch Tcl_SubstObj Tcl_Tell Tcl_ThreadAlert Tcl_ThreadQueueEvent Tcl_TraceCommand Tcl_TraceVar 2nd
Tcl_TraceVar2 Tcl_TranslateFileName 2nd Tcl_Ungets Tcl_UniChar Tcl_UniCharAtIndex Tcl_UniCharCaseMatch Tcl_UniCharIsAlnum Tcl_UniCharIsAlpha Tcl_UniCharIsControl Tcl_UniCharIsDigit Tcl_UniCharIsGraph Tcl_UniCharIsLower Tcl_UniCharIsPrint Tcl_UniCharIsPunct Tcl_UniCharIsSpace Tcl_UniCharIsUpper Tcl_UniCharIsWordChar Tcl_UniCharLen 2nd Tcl_UniCharNcasecmp Tcl_UniCharNcmp Tcl_UniCharToLower Tcl_UniCharToTitle Tcl_UniCharToUpper Tcl_UniCharToUtf Tcl_UniCharToUtfDString Tcl_UnlinkVar Tcl_UnregisterChannel Tcl_UnsetVar Tcl_UnsetVar2 Tcl_UnstackChannel Tcl_UntraceCommand Tcl_UntraceVar Tcl_UntraceVar2 Tcl_UpdateLinkedVar Tcl_UpVar Tcl_UpVar2 Tcl_UtfAtIndex Tcl_UtfBackslash Tcl_UtfCharComplete Tcl_UtfFindFirst Tcl_UtfFindLast Tcl_UtfNext Tcl_UtfPrev Tcl_UtfToExternal Tcl_UtfToExternalDString 2nd Tcl_UtfToLower Tcl_UtfToTitle Tcl_UtfToUniChar Tcl_UtfToUniCharDString Tcl_UtfToUpper Tcl_ValidateAllMemory TCL_VARARGS_START Tcl_VarEval 2nd Tcl_VarEvalVA Tcl_VarTraceInfo Tcl_VarTraceInfo2
tcl_version, Tcl variable TCL_VOLATILE Tcl_WaitForEvent 2nd Tcl_WaitPid Tcl_WinTCharToUtf 2nd Tcl_WinUtfToTChar 2nd Tcl_Write Tcl_WriteChars UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tcl_WriteObj Tcl_WriteRaw Tcl_WrongNumArgs 2nd TclBlend, Java integration tclConfig.sh Tclets, network applications UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE TclHttpd adding source code architecture configuration parameters debug URL displaying values document root 2nd document type handler domain handler e-mail, sending error page group ID hit counters HTML template integrating with application IP address log files not found page page array port quick start configuration script library self-checking form source code distribution sourcing Tcl scripts starkit main program 2nd 3rd starkit, creating TclPro Debugger, using templates URL domain handler user ID vfs directory webmaster e-mail 2nd tclIndex file Tclkit and Starkits Tcl/Tk interpreter thin clients zlib compression tcllib comm package html package
Standard Tcl Library TclODBC tclPkgUnknown TclPro Debugger and TclHttpd TclPro is now Tcl Dev Kit tclsh, application TclVFS extension TclX TCP/IP TCT, Tcl Core Team TEA TEA standard Makefile targets TEA, Tcl Extention Archtecture TEA_LOAD_TKCONFIG TEA_PATH_TCLCONFIG TEA_PATH_TKCONFIG TEA_PRIVATE_TCL_HEADERS TEA_PRIVATE_TK_HEADERS TEA_PUBLIC_TCL_HEADERS TEA_PUBLIC_TK_HEADERS tell, I/O channel tell, Tcl command Tempfile security policy template binary format configure.in for procedure body HTML Makefile.in SiteMenu and SiteFooter terminal, controlling terminate thread 2nd terminate process test, make target testthread, Tcl command text anchor positions, in C and image in a widget attributes attributes for tags attributes from multiple tags bindings 2nd bold bounding box bulleted list changes in Tk 4.1 clearing marks color compare indices configure tags early debug setting deleting 2nd display and fonts, in C dumping widget contents embedded window 2nd 3rd
entry widget find range of tag finding marks get string from widget hidden images in a message widget index 2nd UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE index arithmetic insert cursor insert string inserting 2nd italic justification 2nd 3rd 4th UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE justification, in C line spacing mark 2nd gravity 2nd introspection names modification, event on canvas operations read-only scan for fast scrolling scrolling operations search widget searching selection selection event tabs tag 2nd bindings initialization introspection operations Tk 4.0 changes Tk widget two scrollbars underlined undo mechanism 2nd view line virtual events widget introspection with scrollbar text variable, entry widget textvariables and upvar then. [See if.] thin clients and starkits 2nd Thomas, Michael Thread extension [See also threads.]2nd commands loading thread namespace [See also tpool namespace, tsv namespace]2nd thread\ \:attach
\:cond 2nd \:configure \:create 2nd \:detach \:errorproc \:join \:mutex 2nd \:preserve \:release \:send 2nd \:transfer \:wait thread\\ \\:attach \\:cond \\:configure \\:create \\:detach \\:errorproc \\:eval \\:exists \\:id \\:join \\:mutex \\:names \\:preserve \\:release \\:send \\:transfer \\:unwind \\:wait thread pools 2nd configuration options Thread Support 2nd 3rd threads asynchronous messages 2nd channels 2nd compiling for support condition variables 2nd configuration options creating 2nd creation vs execution current directory deadlock with synchronous messages definition echo server example environment variables error handling 2nd 3rd 4th event loop extensions file access from multiple ID, thread joinable 2nd killing 2nd logging example main thread termination
messages 2nd mutexes 2nd preserving 2nd releasing 2nd sending messages 2nd server example shared resources 2nd shared variables 2nd UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE synchronous messages 2nd Tcl interpreters and tcl_platform(threaded) thread namespace thread pools 2nd thread safety UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE thread support, testing for threading model in Tcl tpool namespace transferring I/O channels 2nd transferring sockets tsv namespace tilde in file names tilde key, asciicircum time event option formatting getting current in microseconds parsing resolution on Windows stamps in a log Tcl command time, Tcl command timeout on client socket Timer Events timer events, in C 2nd timer, high resolution timer. [See after.] TIP, Tcl Improvement Proposal title case conversion title, of window title, supressing Tix Tk 4.0, porting issues Tk 4.1, porting issues Tk 4.2, porting issues Tk 8.0, porting issues Tk 8.1, porting issues Tk 8.2, porting issues Tk 8.3, porting issues 2nd Tk by example Tk C Library tk colormodel, removed in Tk 4.0 Tk command [See also widgets.] bell bind, events bindtags, binding groups
clipboard, cut and paste destroy, window event, generation focus, on window font, control grab, focus grid, geometry manager 2nd image, manipulation lower, window option, resource database pack, geometry manager place, geometry manager raise, window selection, cut and paste send, command to application tk, miscellaneous tkerror tkwait, for event unsupported1, window styles update, events winfo, window info wm, window control Tk command summary Tk fundamentals Tk in Child Interpreters Tk main program and Tk_AppInit Tk manual pages tk scaling Tk thread safety Tk widget attributes and the resource database Tk widget-creation commands Tk widget-manipulation commands tk, Tk command Tk_3DBorder Tk_3DBorderColor Tk_3DBorderGC Tk_3DHorizontalBevel Tk_3DVerticalBevel Tk_Alloc3DBorderFromObj Tk_AllocBitmapFromObj Tk_AllocColorFromObj Tk_AllocCursorFromObj Tk_AllocFontFromObj Tk_Anchor Tk_AppInit, Tk main program and Tk_Attributes Tk_BindEvent Tk_CancelIdleCall 2nd Tk_CanvasDrawableCoords Tk_CanvasEventuallyRedraw Tk_CanvasGetCoord Tk_CanvasGetTextInfo Tk_CanvasPsBitmap Tk_CanvasPsColor Tk_CanvasPsFont Tk_CanvasPsPath
Tk_CanvasPsStipple Tk_CanvasPsY Tk_CanvasSetStippleOrigin Tk_CanvasTagsOption Tk_CanvasTkwin Tk_CanvasWindowCoords Tk_Changes Tk_ChangeWindowAttributes UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tk_CharBbox tk_chooseColor tk_chooseDirectory Tk_Class Tk_ClearSelection Tk_ClipboardAppend UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tk_ClipboardClear Tk_Colormap Tk_ComputeTextLayout 2nd TK_CONFIG_ACTIVE_CURSOR TK_CONFIG_ANCHOR TK_CONFIG_BITMAP TK_CONFIG_BOOLEAN TK_CONFIG_BORDER TK_CONFIG_CAP_STYLE TK_CONFIG_COLOR TK_CONFIG_CURSOR TK_CONFIG_CUSTOM TK_CONFIG_DOUBLE TK_CONFIG_END TK_CONFIG_FONT TK_CONFIG_INT TK_CONFIG_JOIN_STYLE TK_CONFIG_JUSTIFY TK_CONFIG_MM TK_CONFIG_PIXELS TK_CONFIG_RELIEF TK_CONFIG_STRING TK_CONFIG_SYNONYM TK_CONFIG_UID TK_CONFIG_WINDOW Tk_ConfigSpec 2nd Tk_ConfigSpec typedef Tk_ConfigureInfo 2nd Tk_ConfigureValue 2nd 3rd Tk_ConfigureWidget 2nd Tk_ConfigureWidget flags and corresponding C types Tk_ConfigureWindow Tk_CoordsToWindow Tk_CreateBinding Tk_CreateBindingTable Tk_CreateClientMessageHandler Tk_CreateErrorHandler Tk_CreateEventHandler 2nd 3rd Tk_CreateGenericHandler 2nd Tk_CreateImageType Tk_CreateItemType Tk_CollapseMotionEvents
Tk_CreateOptionTable 2nd Tk_CreatePhotoImageFormat Tk_CreateSelHandler Tk_CreateTimerHandler Tk_CreateWindow Tk_CreateWindowFromPath 2nd 3rd Tk_DefineBitmap Tk_DefineCursor Tk_DeleteAllBindings Tk_DeleteBinding Tk_DeleteBindingTable Tk_DeleteClientMessageHandler Tk_DeleteErrorHandler Tk_DeleteEventHandler Tk_DeleteGenericHandler Tk_DeleteImage Tk_DeleteOptionTable Tk_DeleteOptionTable Tk_DeleteSelHandler Tk_DeleteTimerHandler 2nd Tk_Depth Tk_DestroyWindow 2nd tk_dialog, built-in dialog Tk_Display 2nd Tk_DisplayName Tk_DistanceToTextLayout Tk_DoWhenIdle 2nd 3rd Tk_Draw3DPolygon Tk_Draw3DRectangle 2nd Tk_DrawChars Tk_DrawFocusHighlight 2nd Tk_DrawTextLayout 2nd Tk_EventuallyFree Tk_Fill3DPolygon Tk_Fill3DRectangle 2nd Tk_FindPhoto tk_focusFollowsMouse tk_focusNext Tk_Font Tk_FontId Tk_FontMetrics Tk_Free3DBorder Tk_Free3DBorderFromObj Tk_FreeBitmap Tk_FreeBitmapFromObj Tk_FreeColor 2nd Tk_FreeColorFromObj Tk_FreeColormap Tk_FreeConfigOptions Tk_FreeCursor Tk_FreeCursorFromObj Tk_FreeFont Tk_FreeFontFromObj Tk_FreeGC 2nd Tk_FreeImage Tk_FreeOptions 2nd
Tk_FreePixmap 2nd 3rd Tk_FreeSavedOptions 2nd Tk_FreeTextLayout Tk_FreeXId Tk_GCForColor Tk_GeometryRequest 2nd Tk_Get3DBorder Tk_Get3DBorderFromObj UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tk_GetAllBindings Tk_GetAnchor Tk_GetAnchorFromObj Tk_GetAtomName Tk_GetBinding Tk_GetBitmap UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE Tk_GetBitmapFromData Tk_GetBitmapFromObj Tk_GetCapStyle Tk_GetColor Tk_GetColorByValue Tk_GetColorFromObj Tk_GetColormap Tk_GetCursor Tk_GetCursorFromData Tk_GetCursorFromObj Tk_GetDash Tk_GetFont Tk_GetFontFromObj Tk_GetFontMetrics Tk_GetGC 2nd Tk_GetHINSTANCE Tk_GetHWND Tk_GetImage Tk_GetImageMasterData Tk_GetItemTypes Tk_GetJoinStyle Tk_GetJustify Tk_GetJustifyFromObj Tk_GetMMFromObj Tk_GetNumMainWindows tk_getOpenFile tk_getOpenFile, selecting multiple files Tk_GetOption Tk_GetOptionInfo 2nd Tk_GetOptionValue Tk_GetPixels Tk_GetPixelsFromObj Tk_GetPixmap 2nd Tk_GetRelief Tk_GetReliefFromObj Tk_GetRootCoords tk_getSaveFile Tk_GetScreenMM Tk_GetScrollInfo Tk_GetScrollInfoObj Tk_GetSelection Tk_GetString
Tk_GetUid Tk_GetVisual Tk_GetVRootGeometry Tk_Grab Tk_HandleEvent Tk_Height Tk_HWNDToWindow Tk_IdToWindow Tk_Image Tk_ImageChanged Tk_Init 2nd Tk_Init procedure Tk_InitImageArgs Tk_InitOptions 2nd Tk_InitStubs Tk_InternalBorderBottom Tk_InternalBorderLeft Tk_InternalBorderRight Tk_InternalBorderTop Tk_InternalBorderWidth Tk_InternAtom Tk_IntersectTextLayout Tk_IsContainer Tk_IsEmbedded Tk_IsMapped 2nd Tk_IsTopLevel Tk_Justify tk_listboxSingleSelect Tk_Main 2nd Tk_MainLoop 2nd Tk_MaintainGeometry Tk_MainWindow Tk_MakeWindowExist Tk_ManageGeometry Tk_MapWindow Tk_MeasureChars 2nd tk_messageBox Tk_MinReqHeight Tk_MinReqWidth Tk_MoveResizeWindow Tk_MoveToplevelWindow Tk_MoveWindow 2nd Tk_Name Tk_NameOf3DBorder Tk_NameOfAnchor Tk_NameOfBitmap Tk_NameOfCapStyle Tk_NameOfColor Tk_NameOfCursor Tk_NameOfFont Tk_NameOfImage Tk_NameOfJoinStyle Tk_NameOfJustify Tk_NameOfRelief Tk_NameToWindow Tk_Offset
TK_OPTION_ANCHOR TK_OPTION_BITMAP TK_OPTION_BOOLEAN TK_OPTION_BORDER TK_OPTION_COLOR TK_OPTION_CURSOR TK_OPTION_DOUBLE TK_OPTION_END UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE TK_OPTION_FONT TK_OPTION_INT TK_OPTION_JUSTIFY TK_OPTION_PIXELS TK_OPTION_RELIEF TK_OPTION_STRING UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE TK_OPTION_STRING_TABLE TK_OPTION_SYNONYM TK_OPTION_WINDOW Tk_OptionSpec Tk_OptionSpec typedef Tk_OptionTable Tk_OwnSelection Tk_Parent Tk_ParseArgv 2nd Tk_PathName 2nd Tk_PhotoBlank Tk_PhotoExpand Tk_PhotoGetImage Tk_PhotoGetSize Tk_PhotoHandle Tk_PhotoPutBlock Tk_PhotoPutZoomedBlock Tk_PhotoSetSize Tk_PointToChar Tk_PostscriptFontName Tk_QueueWindowEvent Tk_RedrawImage Tk_ReqHeight Tk_ReqWidth Tk_ResizeWindow Tk_RestackWindow Tk_RestoreSavedOptions 2nd Tk_RestrictEvent Tk_RestrictEvents Tk_Screen Tk_ScreenNumber Tk_SetAppName Tk_SetBackgroundFromBorder 2nd Tk_SetCaretPos Tk_SetClass 2nd 3rd Tk_SetClassProcs Tk_SetGrid Tk_SetInternalBorder 2nd Tk_SetOptions 2nd Tk_SetWindowBackground 2nd Tk_SetWindowBackgroundPixmap Tk_SetWindowBorder
Tk_SetWindowBorderPixmap Tk_SetWindowBorderWidth Tk_SetWindowColormap Tk_SetWindowVisual Tk_SizeOfBitmap Tk_SizeOfImage Tk_StrictMotif Tk_TextLayoutToPostscript Tk_TextWidth Tk_Uid Tk_UndefineCursor Tk_UnderlineChars Tk_UnderlineTextLayout Tk_Ungrab Tk_UnmaintainGeometry Tk_UnmapWindow Tk_UnsetGrid Tk_Visual Tk_Width Tk_Window 2nd 3rd Tk_WindowId Tk_X Tk_Y tkerror, Tcl procedure tkinspect tkman, UNIX program tkwait with global variables tkwait, Tk command TLS secure socket extension tolower, string command toolbars toolwindow, Windows toplevel attributes icon bitmap of widget Tk widget window styles totitle, string command toupper, string command tpool namespace [See also thread namespace, tsv namespace]2nd tpool\\ \\:create \\:get \\:names \\:post \\:preserve \\:release \\:wait trace command execution example for preferences execution, in C Tcl command variables, in C transfer, I/O channel to interp
transferring I/O channel threads 2nd transforming data to program with regsub transient window Transparent Fill on Canvas Text transparent images transpose characters Tranter, Jeff UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE trapping errors from pipelines Trf Patch trig functions trim, string command trimleft, string command trimright, string command UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE triple click troublesome button command troughColor, widget attribute true, string class TRUNC, open mode truncate file, open tsv namespace [See also thread namespace, tpool namespace]2nd tsv\ \:get \:set tsv\\ \\:append \\:exists \\:get \\:incr \\:lappend \\:lindex \\:linsert \\:llength \\:lock \\:lpop \\:lpush \\:lrange \\:lreplace \\:lsearch \\:move \\:names \\:object \\:pop \\:set \\:unset turn data into list Turning off geometry propagation two screens type conversions are automatic of file 2nd of images of menu item Tcl_Obj in C type-in widget. typeface. [See entry.] [See font.]
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] u, in string format Uhler, Stephen 2nd uid, user ID
UNREGISTERED VERSION in grid OF CHM TO PDF CONVERTER By THETA-SOFTWARE Uniform Rows and Columns
uniform widget size, grid UNIX look and feel UNIX Tcl Scripts UNIX to DOS unknown backslash sequences are an error unknown, in safe interpreters unknown, Tcl command unmap window 2nd Unmap, window event 2nd unpack binary data unpost, menu operation unset, Tcl command Unsetting Nonexistent Variables unsupported1, Tk command 2nd untrusted scripts update idletasks is safer update, automatic application update, Tk command uplevel, namespaces and uplevel, Tcl command upper case conversion upper, in regular expressions upper, string class upvar aliases do not work with Tk widget text variables example 2nd namespaces Tcl command textvariables variable traces URI manipulation URL access from Tcl character set Content-Encoding copy to file CVS repository Decoding domain handler, TclHttpd fetch with HTTP get with browser\\
\\:displayURL implementing by a program redirection Tcl source location Url_Decode Url_DecodeQuery Url_Encode Url_PrefxInstall use, command-line argument USE_COMPAT_CONST USE_NON_CONST User and Group ID user customization user feedback user interface to preferences user-defined buttons user-defined menus UTF-8 and Unicode 2nd
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V] [ W] [ X ] [ Y] [ Z ] validation, entry contents value, delete list element by Values, Keeping References to Tcl_Obj Values, Pitfalls of Shared Tcl_Obj variable aliases with upvar args argv 2nd 3rd array assignment auto_noexec 2nd auto_noload auto_path 2nd 3rd call by name characters allowed in names command at global scope command line arguments currently defined declaring 2nd deleting efficient names embed_args environment errorCode errorInfo 2nd for button for entry text 2nd for label text for listbox for scale widget from preferences increment manipulate from C code names namespace namespace vs. global conflict pass by reference plugin predefined, list of print by name PrintByName read-only scope and procedures Tcl command tcl_library 2nd tcl_pkgPath tcl_platform tcl_precision test if defined
thread-shared 2nd trace access trace, array example wait for modification Variable number of arguments variable, linked to C variable variables unsetting nonexistent Vasiljevic, Zoran vbox, vertical layout vcompare, package operation version number, Tcl version numbers version, patch level versions, of packages 2nd vertical layout vertical tab character, \\v VFS view text contents viewable window Virtual Events virtual events \\> 2nd 3rd 4th virtual events for cut, copy, and paste Virtual File Systems Virtual Filesystems virtual root coordinates, correcting virtual root window Visibility, window event visual available class, widget attribute 2nd command-line argument default of window volume, of bell vwait, Tcl command
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] w, anchor position w, in binary format w, regular expression option warping, mouse (pointer) Web browser status line Web browser Tcl plugin Web server, TclHttpd Web Tcl Complete, book weekday, %a when to use regular expressions while loop to read input while, Tcl command white space wide integer widget attributes attributes, in C C data structure class command, in C class definition cleanup in C container. [See frame.] containing data structure, in C definition destroy destroy, in C display in C embed in text frame for container geometry height hide by unmapping image, from C implemented in C instance command, in C introduction names in variables naming reconfigure screen of screen position spacing between Tcl_Obj version toplevel of unmapping width X, Y coordinate widgets
button canvas checkbutton entry frame label labelframe listbox menu menubutton message namespaces and panedwindow radiobutton scale scrollbar spinbox text toplevel width equal with grid event option of widget virtual root window widget attribute Wikit, a Wiki-Wiki window Activate event aspect ratio binding on close binding on open changes size children class, resource close close or delete callback colormap configuration in C Configure event coordinates, in C create options, in text creating in C current state decoration deiconify deleting depth of screen pixels Destroy event detached embedded in canvas embedding events, in C 2nd exists family relationships focus model general information in C
geometry geometry manager gridding group grouping when closed hierarchy hierarchy information icon bitmap UNREGISTERED VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE iconify ID of layout in binding location information. manager UNREGISTERED 2nd VERSION OF CHM TO PDF CONVERTER By THETA-SOFTWARE manager, miscellaneous Map event mapped onto display maximized maxsize minimize minsize mouse location MouseWheel event name of open open, is override redirect parent pathname placement platform-specific attributes position from protocol handler protocol, miscellaneous resize, interactive rooms screen information server name session state size from stacking order 2nd 3rd 4th 5th stacking order, in C startup command state styles system, detecting title 2nd toplevel of transient unmap Unmap event virtual root visibile visual 2nd visual of wait for destroy icons for
wait for visibility withdraw window manager interaction window manager, Tk-based Window, system color WindowBody, system color WindowFrame, system color Windows and exec problems auto_path com ports DLL location look and feel mouse cursor platform-specific window attributes services, Tcl applications as shared libraries Start and Menu Keys Start Menu system colors. system font size system menu text mode files toolwindow Windows Application Handles Windows IME WindowText, system color winfo, Tk command Wippler, Jean-Claude Wish command line options wish, application withdraw window wm, Tk command WM_DELETE_WINDOW WM_PROTOCOL Word size detection, integer Word, Microsoft, special characters wordchar, string class wordend, string command wordstart, string command Working with Signals World Wide Web wrapLength, widget attribute wrapping Tcl applications 2nd writable, file write only, open Write options for photo images Writing a Tk Widget in C WRONLY, open mode
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X] [ Y] [ Z ] X authority, send X Font Names X ID for resource, in C X protocol errors X resource database. [See resource. ] X Resource ID Management X selection, export string to x, regular expression option X, x, in string format X, Y coordinate of widget X, Y coordinates, in event X, Y mouse coordinates XColor XCopyArea Xdefaults. [See resource. ] xdigit, in regular expressions xdigit, string class Xerox PARC xfontsel, UNIX program xhost list and send XIM, X Input Method xlsfonts, UNIX program xmodmap, program xrdb. [See resource.] xset program XSynchronize xview scrollbar operation
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] year year 2000 compliance Year 2000 Compliance ypostion, menu operation yview scrollbar operation
[ Team LiB ]
[ Team LiB ]
[ SYMBOL] [ A ] [ B ] [ C ] [ D] [ E] [ F] [ G ] [ H] [ I ] [ J] [ K ] [ L] [ M] [ N] [ O ] [ P ] [ Q ] [ R ] [ S ] [ T] [ U] [ V ] [ W] [ X ] [ Y] [ Z ] Zeltserman, Dave Zimmer, Adrian zip file via VFS
[ Team LiB ]