Chapter 36. The Text Widget

Tk text widget is a general-purpose editable text widget with features for line spacing, justification, tags, marks, and embedded windows.

The Tk text widget is versatile, simple to use for basic text display and manipulation, and has many advanced features to support sophisticated applications. The line spacing and justification can be controlled on a line-by-line basis. Fonts, sizes, and colors are controlled with tags that apply to ranges of text. Edit operations use positional marks that keep track of locations in text, even as text is inserted and deleted.

Tags are the most important feature of the text widget. You can define attributes like font and justification for a tag. When that tag is applied to a range of text, the text uses those attributes. Text can pick up attributes from any number of tags, so you can compose different tags for justification, font, line spacing, and more. You can also define bindings for tags so that ranges of text can respond to the mouse. Any interesting application of the text widget uses tags extensively.

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

The first character.

1.1

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.

Table 36-1. Text indices

line.char

Lines count from 1. Characters count from 0.

@x,y

The character under the specified screen position.

current

The character currently under the mouse.

end

Just after the very last character.

image

The position of the embedded image.

insert

The position right after the insert cursor.

mark

Just after the named mark.

tag.first

The first character in the range tagged with tag.

tag.last

Just after the last character tagged with tag.

window

The position of the embedded window.

Inserting and Deleting Text

You add text with the insert operation ($t is a text widget):

$t insert index string ?tagList? ?string tagList? ...

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:

$t insert insert "Hello, World
"

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 command:

$t delete 1.0 2.0

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:

$t delete 1.0 2.0 4.0 5.0 8.0 9.0

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:

"insert lineend"
"insert -3 chars"

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:

$t delete "insert wordstart" "insert wordend"

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:

$t delete "insert linestart" "insert lineend +1 char"

Table 36-2 summarizes the set of index modifiers.

Table 36-2. Index modifiers for text widgets

+ count chars

count characters past the index.

- count chars

count characters before the index.

+ count lines

count lines past the index, retaining character position.

- count lines

count lines before the index, retaining character position.

linestart

The beginning of the line.

lineend

The end of the line (i.e., the newline character).

wordstart

The first character of a word.

wordend

Just after the last character of a word.

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:

$t compare ix1 op ix2

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.

Text Marks

A mark is a symbolic name for a position between 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 to the end of the line:

$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:

eval {$t mark unset} [$t mark names]

Mark Gravity

Mark Gravitymark gravity, text
$t mark gravity foobar
=> right
$t mark gravity foobar left

Text Tags

A tag is a 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 do not include spaces, plus (+) or minus (-). These characters are used in index arithmetic and may 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:

$t tag add everywhere 1.0 end

You can add one or more tags when text is inserted, too:

$t insert insert "new text" {someTag someOtherTag}

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:

$t tag remove everywhere 3.0 6.end
$t tag delete everywhere

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:

$t tag configure blue -foreground blue

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:

$t tag configure disabled -fgstipple 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.

Table 36-3. Attributes for text tags

-background color

The background color for text.

-bgstipple bitmap

A stipple pattern for the background color.

-borderwidth pixels

The width for 3D border effects.

-elide boolean

If True, then the text is not displayed. (Tk 8.3)

-fgstipple bitmap

A stipple pattern for the foreground color.

-font font

The font for the text.

-foreground color

The foreground color for text.

-justify how

Justificationleft, right, or center.

-lmargin1 pixels

Normal left indent for a line.

-lmargin2 pixels

Indent for the part of a line that gets wrapped.

-offset pixels

Baseline offset. Positive for superscripts.

-overstrike boolean

Draw text with a horizontal line through it.

-relief what

flat, sunken, raised, groove, solid or ridge.

-rmargin pixels

Right-hand margin.

-spacing1 pixels

Additional space above a line.

-spacing2 pixels

Additional space above wrapped part of line.

-spacing3 pixels

Additional space below a line.

-tabs tabstops

Specifies tab stops.

-underline boolean

If true, the text is underlined.

-wrap mode

Line wrapnone, char, or word.

Note

Line wrap:

Configure tags early.

You can set up the appearance (and bindings) for tags once in your application, even before you have 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 you change a binding on a tag, all tagged characters are 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.

Example 36-1. Tag configurations for basic character styles

proc TextStyles { t } {
   $t tag configure bold -font {times 12 bold}
   $t tag configure italic -font {times 12 italic}
   $t tag configure fixed -font {courier 12}
   $t tag configure underline -underline true
   $t tag configure super -offset 6 -font {helvetica 8}
   $t tag configure sub -offset -6 -font {helvetica 8}
}

Mixing Attributes from Different Tags

A character can be labeled with more than one tag. For example, one tag could determine the font, another could determine the background color, and so on. If different tags try to supply the same attribute, a priority ordering is taken into account. The latest tag added to a range of text has the highest priority. The ordering of tags can be controlled explicitly with the tag raise and tag lower commands.

You can achieve interesting effects by composing attributes from different tags. In a mail reader, for example, the listing of messages in a mail folder can use one color to indicate messages that are marked for delete, and it can use another color for messages that are marked to be moved into another folder. The tags might be defined like this:

$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:

$t tag configure select -underline true

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.

Line Spacing and Justification

The spacing and justification for text have several attributes. These settings are complicated by wrapped text lines. The text widget distinguishes between the first display line and the remaining display lines for a given text line. For example, if a line in the text widget has 80 characters but the window is only wide enough for 30, then the line may be wrapped onto three display lines. See Table 36-10 on page 557 for a description of the text widget's wrap attribute that controls this behavior.

Spacing is controlled with three attributes, and there are global spacing attributes as well as per-tag spacing attributes. The -spacing1 attribute adds space above the first display line, while -spacing2 adds space above the subsequent display lines that exist because of wrapping. The -spacing3 attribute adds space below the last display line, which could be the same as the first display line if the line is not wrapped.

The margin settings also distinguish between the first and remaining display lines. The -lmargin1 attribute specifies the indent for the first display line, while the -lmargin2 attribute specifies the indent for the rest of the display lines, if any. There is only a single attribute, -rmargin, for the right indent. These margin attributes are only tag attributes. The closest thing for the text widget as a whole is the -padx attribute, but this adds an equal amount of spacing on both sides:

Example 36-2. Line spacing and justification in the text widget

Line spacing and justification in the text widget
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

   $t insert end "Here is a line with no special settings
"
   $t insert end "Now is the time for all good women and men to come to the aid of their
Line spacing and justification in the text widget country. In this great time of need, no one can avoid their responsibility.
"
   $t insert end "The quick brown fox jumps over the lazy dog."

   $t tag add para 2.0 2.end
   $t tag add hang 3.0 3.end
}

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 right below the previous paragraph. You can also see the difference between the -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:

$t insert 1.0 "ABCDE"
$t bbox 1.0
=> 4 4 8 12

The Tk 8.0 font metrics command, which is described on page 640, also gives detailed measurements:

font metrics {times 12}
-ascent 9 -descent 3 -linespace 12 -fixed 0

Text justification is limited to three stylesleft, 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:

*Text.tabs: 2c left 4c right 6c center 8c numeric

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:

$t tag configure foo -tabs ".5i left"

The Selection

The selection is implemented with a predefined tag named sel. If the application tags 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. In this case, when another widget or application asserts ownership of the selection then the sel 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:

eval {$t tag delete} [$t tag names]

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.

Example 36-3. An active text button

proc TextButton { t start end command } {
   global textbutton
   if ![info exists textbutton(uid)] {
      set textbutton(uid) 0
   } else {
      incr textbutton(uid)
   }
   set tag button$textbutton(uid)
   $t tag configure $tag -relief raised -borderwidth 2
   if {[regexp color [winfo visual $t]]} {
      $t tag configure $tag -background thistle
   } else {
      $t tag configure $tag -background [$t cget -fg]
      $t tag configure $tag -foreground [$t cget -bg]
   }
   # Bind the command to the tag
   $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} {
   $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
}

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.

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:

$t search ?options? pattern index ?stopIndex?

Table 36-4 summarizes the options to the search operation:

Table 36-4. Options to the search operation

-forward

Searches forward from index. This is the default.

-backward

Searches backward from index.

-exact

Matches pattern exactly. This is the default.

-regexp

Uses regular expression pattern matching.

-nocase

Lowercase letters in pattern can match upper case letters.

-count varName

Returns in varName the number of characters that matched pattern.

--

Ends the options. Necessary if pattern begins with -.

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"

Embedded Widgets

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 insert it into the text widget. The button behaves normally, and in this case it invokes the Help command when the user clicks on it:

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:

Table 36-5. Window and image alignment options

top

Top lines up with top of text line.

center

Center lines up with center of text line.

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:

Example 36-4. Delayed creation of embedded widgets

$t window create end -create [list MakeGoBack $t]
proc MakeGoBack { t } {
   button $t.goback -text "Go to Line 1" 
      -command [list $t see 1.0]
}

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:

$t window configure $t.goback -padx 2

Table 36-6. Options to the window create operation

-align where

Alignmenttop, center, bottom, or baseline.

-create command

Tcl command to create the widget.

-padx pixels

Padding on either side of the widget.

-pady pixels

Padding above and below the widget.

-stretch boolean

If true, the widget is stretched vertically to match the spacing of the text line.

-window pathname

Tk pathname of the widget to embed.

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.

Embedded Images

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 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 	 bulletlist
   $t image create $mark -image $blist(image)
   $t insert $mark 	$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 image create 1.0 -image image1
=> image1
$t 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.

Table 36-7. Options to the image create operation

-align where

Alignmenttop, center, bottom, or baseline. Only has effect if image is shorter than the line height. See Table 36-5.

-image image

The Tk image to add to the text widget.

-name name

A name for this instance of the image. A #num may be appended to generate a unique name.

-padx pixels

Padding on either side of the image.

-pady pixels

Padding above and below the image.

Looking inside the Text Widget

The text widget has several operations that let you examine its contents. The simplest is get, which returns of text from the widget. If only one index is given, the character at that position is returned. If there are two indices, all the characters up to but not including the second index are returned. For example, you can get all the text with this command:

$t get 1.0 end

As of Tk 8.4, you can get multiple ranges of text with a single get operation; the result in this case is a list of the range contents. For example, to retrieve the first and third lines, without the trailing newlines, as a two-element list:

$t get 1.0 1.end 3.0 3.end

Looking at Tags

The tag names command returns all the tag names, or the names of the tags at a specified index:

$t tag names ?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:

Example 36-6. Finding the current range of a text tag

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.

Dumping the Contents

The dump operation provides the most general way to examine the contents of the text widget. The general form of the command is:

$t dump ?options? ix1 ?ix2?

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:

Example 36-7. Dumping the text widget

proc Text_Dump {t {start 1.0} {end end}} {
   foreach {key value index} [$t dump $start $end] {
      if {$key == "text"} {
         puts "$index "$value""
      } else {
         puts "$index $key $value"
      }
   }
}

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 element: the type, the value, and the index. Example 36-8 shows another way to print out the text widget contents:

Example 36-8. Dumping the text widget with a command callback

proc Text_Dump {t {start 1.0} {end end}} {
   $t dump -command TextDump $start $end
}
proc TextDump {key value index} {
   if {$key == "text"} {
      puts "$index "$value""
   } else {
      puts "$index $key $value"
   }
}

The Undo Mechanism

Beginning in Tk 8.4, the text widget supports an unlimited undo and redo mechanism. You enable the undo mechanism by setting the text widget's undo attribute to True. The undo attribute has a default value of False for backward compatibility.

When enabled, each insert and delete action, whether performed by the user or programmatically, is recorded on an undo stack. You can programmatically undo an edit with the edit undo operation. The undone changes are then moved to the redo stack, so that an undone edit can be redone again with the with the edit redo operation. The redo stack is cleared whenever new edit actions are recorded on the undo stack. (Both the edit undo and edit redo operations generate error conditions if the undo or redo stack is empty, respectively.) The text widget also has default undo and redo bindings; by default, undo is <Control-z> and redo is <Control-y> on Windows, <Control-Z> on all other platforms. (See “Text Bindings” on page 551.)

Each edit undo operation undoes the last action, which is defined as all of the insert and delete commands that are recorded on the undo stack in between two separators. When the autoSeparators attribute is True (the default), a separator is automatically placed on the stack whenever:

  • the mode changes from insertion to deletion, or vice versa

  • the user moves the insert mark using the keyboard or the mouse

  • the user presses the <Return> key

If you set the autoSeparators attribute to False, you are responsible for programmatically placing separators on the stack with the edit separator operation. By turning the autoseparators off and inserting them at the desired points, you can define compound actions, such as search and replace. The default paste binding is an example of such an action, such that overwriting selected text by pasting from the clipboard is considered an atomic action.

As of Tk 8.4, only insert and delete operations are handled by the undo mechanism. In particular, tag operations, such as applying a tag to text, are not actions captured by the undo mechanism, even if the tag was applied as part of an insert operation. As an example, consider the following insertion:

$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”.

Text Bindings and Events

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 affecting the selection. Table 36-8 lists the default bindings for the text widget:

Table 36-8. Bindings for the text widget

<Any-Key>

Inserts normal printing characters.

<Button-1>

Sets the insert point, clears the selection, sets focus.

<Control-Button-1>

Sets the insert point without affecting the selection.

<B1-Motion>

Sweeps out a selection from the insert point.

<Double-Button-1>

Selects the word under the mouse.

<Triple-Button-1>

Selects the line under the mouse.

<Shift-Button-1>

Adjusts the end of selection closest to the mouse.

<Shift-B1-Motion>

Continues to adjust the selection.

<Button-2>

Pastes the selection, or sets the scrolling anchor.

<B2-Motion>

Scrolls the window.

<MouseWheel>

Scrolls vertically.

<Button-4>

Mousewheel support on Unix only; scrolls up. (Tk 8.3)

<Button-5>

Mousewheel support on Unix only; scrolls down. (Tk 8.3)

<Key-Left> <Control-b>

Moves the cursor left one character and clears the selection.

<Shift-Left>

Moves the cursor and extends the selection.

<Control-Left>

Moves the cursor by words. Clears the selection.

<Control-Shift-Left>

Moves the cursor by words. Extends selection.

<Key-Right> <Control-f>

Right bindings are analogous to Left bindings.

<Meta-b> <Meta-f>

Same as <Control-Left>, <Control-Right>.

<Key-Up> <Control-p>

Moves the cursor up one line. Clears the selection.

<Shift-Up>

Moves the cursor up one line. Extends the selection.

<Control-Up>

Moves the cursor up by paragraphs, which are a group of lines separated by a blank line.

<Control-Shift-Up>

Moves the cursor up by paragraph. Extends the selection.

<Key-Down> <Control-n>

All Down bindings are analogous to Up bindings.

<Next> <Prior>

Moves the cursor by one screen. Clears the selection.

<Shift-Next>

<Shift-Prior>

Moves the cursor by one screen. Extends the selection.

<Home> <Control-a>

Moves the cursor to line start. Clears the selection.

<Shift-Home>

Moves the cursor to line start. Extends the selection.

<End> <Control-e>

Moves the cursor to line end. Clears the selection.

<Shift-End>

Moves the cursor to line end. Extends the selection.

<Control-Home>

<Meta-less>

Moves the cursor to the beginning of text. Clears the selection.

<Control-End>

<Meta-greater>

Moves the cursor to the end of text. Clears the selection.

<Select>

<Control-space>

Sets the selection anchor to the position of the cursor.

<Shift-Select>

<Control-Shift-space>

Adjusts the selection to the position of the cursor.

<Control-slash>

Selects everything in the text widget.

<Control-backslash>

Clears the selection.

<Delete>

Deletes the selection, if any. Otherwise, deletes the character to the right of the cursor.

<BackSpace> <Control-h>

Deletes the selection, if any. Otherwise, deletes the character to the left of the cursor.

<Control-d>

Deletes character to the right of the cursor.

<Meta-d>

Deletes word to the right of the cursor.

<Control-k>

Deletes from cursor to end of the line. If you are at the end of line, deletes the newline character.

<Control-o>

Inserts a newline but does not advance the cursor.

<Meta-Delete>

<Meta-BackSpace>

Deletes the word to the left of the cursor.

<Control-t>

Transposes the characters on either side of the cursor.

<<Cut>> <Control-x>

Copies the selection to the clipboard.

<<Copy>> <Control-c>

Cuts the selection and saves it on the clipboard.

<<Paste>> <Control-v>

Pastes from the clipboard.

<<Undo>> <Control-z>

Undoes the last edit action if the undo attribute is true. (Tk 8.4)

<<Redo>>

<Control-Z> (Unix & Mac)

<Control-y> (Windows)

Reapplies the last undone edit action if the undo attribute is true. (Tk 8.4)

Text Virtual Events

As of Tk 8.4, a text widget generates a <<Modified>> virtual event whenever text is inserted into or deleted from the text widget. The event is fired after the text widget has changed, so the binding action can access the new text values. The easiest way to be aware of changes to the menu selection is to bind to this virtual event, for example:

bind .t <<Modified>> {ContentsChanged %W}

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.

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:

Table 36-9. Operations for the text widget

$t bbox index

Returns the bounding box of the character at index. Four numbers are returned: x y width height.

$t cget option

Returns the value of the configuration option.

$t compare i1 op i2

Performs index comparison. i1 and i2 are indexes. op is one of < <= == >= > !=

$t configure ...

Queries or sets configuration options.

$t debug boolean

Enables consistency checking for B-tree code.

$t delete i1 ?i2? ?...?

Deletes from i1 up to, but not including i2. Just deletes the character at i1 if i2 is not specified. Deletes multiple ranges if specified.

$t dlineinfo index

Returns the bounding box, in pixels, of the display for the line containing index. Five numbers are returned: x y width height baseline.

$t dump ?options? i1 ?i2?

Returns the marks, tags, windows, images, and text contained in the widget. Options are -all, -command command, -image, -mark, -tag, -text, and -window.

$t edit modified ?boolean?

Queries or sets the widget's modified flag. (Tk 8.4)

$t edit redo

Reapplies the last undone edit action if the undo attribute is true. (Tk 8.4)

$t edit reset

Clears the undo and redo stacks. (Tk 8.4)

$t edit separator

Inserts a separator on the undo stack if the undo attribute is true. (Tk 8.4)

$t edit undo

Undoes the last edit action if the undo attribute is true. (Tk 8.4)

$t get i1 ?i2? ?...?

Returns the text from i1 to i2, or just the character at i1 if i2 is not specified. Returns multiple ranges as a list, if specified.

$t image cget option

Returns the value of the image option.

$t image configure ?options?

Queries or sets the configuration of an embedded image.

$t image create option value ...

Creates an embedded image. Options are described in Table 36-7 on page 547.

$t image names

Returns the names of all embedded images.

$t index index

Returns the numerical value of index.

$t insert index chars ?tags? ?chars tags? ...

Inserts chars at the specified index. If tags are specified, they are added to the new characters.

$t mark gravity name ?direction?

Queries or assigns a gravity direction to the mark name. direction, if specified, is left or right.

$t mark names

Returns a list of defined marks.

$t mark next index

Returns the mark after index.

$t mark previous index

Returns the mark before index.

$t mark set name index

Defines a mark name at the given index.

$t mark unset name1 ?name2 ...?

Deletes the named mark, or marks.

$t scan mark x y

Anchors a scrolling operation.

$t scan dragto x y

Scrolls based on a new position.

$t search ?switches? pattern index ?stopIndex?

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.

$t see index

Positions the display to view index.

$t tag add name i1 ?i2?

?i1 i2? ?i1 i2? ...

Adds the tag to i1 through, but not including i2, or just the character at i1 if i2 is not given.

$t tag bind name ?sequence? ?script?

Queries or defines bindings for the tag name.

$t tag cget name option

Returns the value of option for tag name.

$t tag configure name ...

Sets or queries the configuration of tag name.

$t tag delete tag1 ?tag2

...?

Deletes information for the named tags.

$t tag lower tag ?below?

Lowers the priority of tag to the lowest priority or to just below tag below.

$t tag names ?index?

Returns the names of the tags at the specified index, or in the whole widget, sorted from lowest to highest priority.

$t tag nextrange tag i1 ?i2?

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.

$t tag prevrange tag i1

?i2?

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?

Raises the priority of tag to the highest priority, or to just above the priority of tag above.

$t tag ranges tag

Returns a list describing all the ranges of tag.

$t tag remove tag i1 ?i2?

?i1 i2? ?i1 i2? ...

Removes tag from the range i1 up to, but not including i2, or just at i1 if i2 is not specified.

$t window cget win option

Returns the value of option for win.

$t window config win ...

Queries or modifies the configuration of the embedded window. win is a Tk pathname or an index.

$t window create ix args

Creates an embedded window at ix.

$t window names

Returns a list of windows embedded in $t.

$t xview

Returns two fractions between zero and one that describe the amount of text off-screen to the left and the amount of text displayed.

$t xview moveto fraction

Positions the text so fraction of the text is off screen to the left.

$t xview scroll num what

Scrolls num of what, which is units or pages.

$t yview

Returns two fractions between zero and one that describe the amount of text off-screen toward the beginning and the amount of text displayed.

$t yview moveto fraction

Positions the text so fraction of the text is off-screen toward the beginning.

$t yview scroll num what

Scrolls num of what, which is units or pages.

$t yview ?-pickplace? ix

Obsolete. Use the see operation, which is similar.

$t yview num

Obsolete. Position line num at the top of screen.

Text Attributes

Table 36-10 lists the attributes for the text widget. 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:

Table 36-10. Text attribute resource names

autoSeparators

BooleanTrue (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

Background color (also bg).

borderWidth

Extra space around the edge of the text.

cursor

Cursor to display when mouse is over the widget.

exportSelection

If true, selected text is exported to the selection.

font

Default font for the text.

foreground

Foreground color (also fg).

height

Height, in text lines.

highlightBackground

Focus highlight color when widget does not have focus.

highlightColor

Color for input focus highlight border.

highlightThickness

Width of highlight border.

insertBackground

Color for the insert cursor.

insertBorderWidth

Size of 3D border for insert cursor.

insertOffTime

Milliseconds insert cursor blinks off.

insertOnTime

Milliseconds insert cursor blinks on.

insertWidth

Width of the insert cursor.

maxUndo

The maximum number of undo actions on the undo stack. A zero or a negative value implies an unlimited undo stack. (Tk 8.4)

padX

Extra space to the left and right of the text.

padY

Extra space above and below the text.

relief

flat, sunken, raised, groove, ridge, or solid.

selectBackground

Background color of selected text.

selectForeground

Foreground color of selected text.

selectBorderWidth

Size of 3D border for selection highlight.

setGrid

Enable/disable geometry gridding.

spacing1

Extra space above each unwrapped line.

spacing2

Space between parts of a line that have wrapped.

spacing3

Extra space below an unwrapped line.

state

Editable (normal) or read-only (disabled).

tabs

Tab stops.

takeFocus

Control focus changes from keyboard traversal.

undo

BooleanTrue enables and False (default) disables the undo mechanism. (Tk 8.4)

width

Width, in characters, of the text display.

wrap

Line wrap modenone, char, or word.

xScrollCommand

Tcl command prefix for horizontal scrolling.

yScrollCommand

Tcl command prefix for vertical scrolling.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.225.55.151