word.tcl 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. # word.tcl --
  2. #
  3. # This file defines various procedures for computing word boundaries in
  4. # strings. This file is primarily needed so Tk text and entry widgets behave
  5. # properly for different platforms.
  6. #
  7. # Copyright © 1996 Sun Microsystems, Inc.
  8. # Copyright © 1998 Scriptics Corporation.
  9. #
  10. # See the file "license.terms" for information on usage and redistribution
  11. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12. # The following variables are used to determine which characters are
  13. # interpreted as word characters. See bug [f1253530cdd8]. Will
  14. # probably be removed in Tcl 9.
  15. if {![info exists ::tcl_wordchars]} {
  16. set ::tcl_wordchars {\w}
  17. }
  18. if {![info exists ::tcl_nonwordchars]} {
  19. set ::tcl_nonwordchars {\W}
  20. }
  21. # Arrange for caches of the real matcher REs to be kept, which enables the REs
  22. # themselves to be cached for greater performance (and somewhat greater
  23. # clarity too).
  24. namespace eval ::tcl {
  25. variable WordBreakRE
  26. array set WordBreakRE {}
  27. proc UpdateWordBreakREs args {
  28. # Ignores the arguments
  29. global tcl_wordchars tcl_nonwordchars
  30. variable WordBreakRE
  31. # To keep the RE strings short...
  32. set letter $tcl_wordchars
  33. set space $tcl_nonwordchars
  34. set WordBreakRE(after) "$letter$space|$space$letter"
  35. set WordBreakRE(before) "^.*($letter$space|$space$letter)"
  36. set WordBreakRE(end) "$space*$letter+$space"
  37. set WordBreakRE(next) "$letter*$space+$letter"
  38. set WordBreakRE(previous) "$space*($letter+)$space*\$"
  39. }
  40. # Initialize the cache
  41. UpdateWordBreakREs
  42. trace add variable ::tcl_wordchars write ::tcl::UpdateWordBreakREs
  43. trace add variable ::tcl_nonwordchars write ::tcl::UpdateWordBreakREs
  44. }
  45. # tcl_wordBreakAfter --
  46. #
  47. # This procedure returns the index of the first word boundary after the
  48. # starting point in the given string, or -1 if there are no more boundaries in
  49. # the given string. The index returned refers to the first character of the
  50. # pair that comprises a boundary.
  51. #
  52. # Arguments:
  53. # str - String to search.
  54. # start - Index into string specifying starting point.
  55. proc tcl_wordBreakAfter {str start} {
  56. variable ::tcl::WordBreakRE
  57. set result {-1 -1}
  58. if {$start < 0} {
  59. set start 0;
  60. }
  61. regexp -indices -start $start -- $WordBreakRE(after) $str result
  62. return [lindex $result 1]
  63. }
  64. # tcl_wordBreakBefore --
  65. #
  66. # This procedure returns the index of the first word boundary before the
  67. # starting point in the given string, or -1 if there are no more boundaries in
  68. # the given string. The index returned refers to the second character of the
  69. # pair that comprises a boundary.
  70. #
  71. # Arguments:
  72. # str - String to search.
  73. # start - Index into string specifying starting point.
  74. proc tcl_wordBreakBefore {str start} {
  75. variable ::tcl::WordBreakRE
  76. set result {-1 -1}
  77. if {$start >= 0} {
  78. regexp -indices -- $WordBreakRE(before) [string range $str 0 $start] result
  79. }
  80. return [lindex $result 1]
  81. }
  82. # tcl_endOfWord --
  83. #
  84. # This procedure returns the index of the first end-of-word location after a
  85. # starting index in the given string. An end-of-word location is defined to be
  86. # the first whitespace character following the first non-whitespace character
  87. # after the starting point. Returns -1 if there are no more words after the
  88. # starting point.
  89. #
  90. # Arguments:
  91. # str - String to search.
  92. # start - Index into string specifying starting point.
  93. proc tcl_endOfWord {str start} {
  94. variable ::tcl::WordBreakRE
  95. set result {-1 -1}
  96. if {$start < 0} {
  97. set start 0
  98. }
  99. regexp -indices -start $start -- $WordBreakRE(end) $str result
  100. return [lindex $result 1]
  101. }
  102. # tcl_startOfNextWord --
  103. #
  104. # This procedure returns the index of the first start-of-word location after a
  105. # starting index in the given string. A start-of-word location is defined to
  106. # be a non-whitespace character following a whitespace character. Returns -1
  107. # if there are no more start-of-word locations after the starting point.
  108. #
  109. # Arguments:
  110. # str - String to search.
  111. # start - Index into string specifying starting point.
  112. proc tcl_startOfNextWord {str start} {
  113. variable ::tcl::WordBreakRE
  114. set result {-1 -1}
  115. if {$start < 0} {
  116. set start 0
  117. }
  118. regexp -indices -start $start -- $WordBreakRE(next) $str result
  119. return [lindex $result 1]
  120. }
  121. # tcl_startOfPreviousWord --
  122. #
  123. # This procedure returns the index of the first start-of-word location before
  124. # a starting index in the given string.
  125. #
  126. # Arguments:
  127. # str - String to search.
  128. # start - Index into string specifying starting point.
  129. proc tcl_startOfPreviousWord {str start} {
  130. variable ::tcl::WordBreakRE
  131. set word {-1 -1}
  132. if {$start > 0} {
  133. regexp -indices -- $WordBreakRE(previous) [string range [string range $str 0 $start] 0 end-1] \
  134. result word
  135. }
  136. return [lindex $word 0]
  137. }