Text editor with slightly fancy text abilities 
Author Message
 Text editor with slightly fancy text abilities

A couple of weeks ago someone asked for a way to get postscript out
of the text widget.  Well one evening I threw the following together
after a couple hours work.  It doesn't, now, generate postscript or anything
which could generate postscript.  But one could have it generate troff
(or TeX) and from that generate postscript.

It uses tags to record what styles/sizes are wanted where.  It can save
all the tag information and read that back in.

I had wanted to make a version which did the same things which troff -ms
could accept.  But then I realized there was no way to represent, on
the screen, indented paragraphs.  Ohwell.. no quicky implementations of
Microsoft Word here...

#!/usr/local/bin/wish -f
# txt.tk -- A multi font & multi type size text editor.

# Date: February 9, 1993
# The user is able to manipulate the text presentation along two axes.
# One axis is font style (bold, normal, italic) and the other is size.
# S/he is able to change either axis at will without any let or hindrance.
# To support that there are n_styles * n_sizes tags for all permutations
# of both axes.  Each tag type has a font associated with it.  The tag
# name is used to mark the text as to what it is.
# A data format is used within this program for reading/writing marked
# up text.  Functions are available to convert the marked up form to
# a document layout language (troff, latex, maybe postscript).
# A special purpose editor which had buttons to create things on
# a higher level of abstraction than this.  For instance: A `section
# header' button would create a couple lines of text, the middle one
# being in bold face, containing the words "Section-name", already
# selected and ready to be deleted once the user typed the real
# section name.  It would abstract, perhaps, the -ms macro set facilities.
# It would still save in this internal data format, and would convert
# to the real one.
# A version of the above would work for C code.  A button marked "if(){}else{}"
# to create an if-block.  Here it's a bit different though since we don't want
# the user to type into the middle of the word `if'..  so the <Any-Keypress>
# binding must be aware of what can be typed into and what can't.  It would
# use different fonts for different kinds of things (bold for (){}, italic
# for keywords, etc).
# Text search functions.
# Include windows containing graphics.  Or maybe a button to start sound
# or animation.
# Turn it into an \*[interp] style object.  Maybe some of the above
# can be enabled through subclassing.
# Edit functions: At least undo.  Cut & Paste is already handled by X stuff
#       but we're talking about non-normal text here.  Which implies special
#       handling.. is the Tk selection command sufficient?  Do we instead have
#       to come up with our own clipboard?

# Buttons:
# Font style:   BOLD, NORMAL, ITALIC
# Save:         As data, As troff
# Import:       As data, As text

frame .cmd
text  .txt
pack append . \
        .cmd {top fillx} \
        .txt {top fill expand}

frame .cmd.save
frame .cmd.import
frame .cmd.style
frame .cmd.size
pack append .cmd \
        .cmd.save       { left fillx expand } \
        .cmd.import     { left fillx expand } \
        .cmd.style      { left fillx expand } \
        .cmd.size       { left fillx expand }

button .cmd.save.asData  -text "Save"       -command saveAsData
button .cmd.save.asTroff -text "Save Troff" -command saveAsTroff
button .cmd.save.quit    -text "Quit"       -command exit
pack append .cmd.save \
        .cmd.save.asData  {top fillx expand} \
        .cmd.save.asTroff {top fillx expand} \
        .cmd.save.quit    {top fillx expand}

button .cmd.import.data -text "Import"      -command importData
button .cmd.import.text -text "Import text" -command importText
pack append .cmd.import \
        .cmd.import.data {top fillx expand} \
        .cmd.import.text {top fillx expand}

button .cmd.style.bold   -text "Bold"   -command fontBold
button .cmd.style.normal -text "Normal" -command fontNormal
button .cmd.style.italic -text "Italic" -command fontItalic
pack append .cmd.style \
        .cmd.style.bold         {top fillx expand} \
        .cmd.style.normal       {top fillx expand} \
        .cmd.style.italic       {top fillx expand}

button .cmd.size.tiny   -text "Tiny"   -command sizeTiny
button .cmd.size.small  -text "Small"  -command sizeSmall
button .cmd.size.normal -text "Normal" -command sizeNormal
button .cmd.size.large  -text "Large"  -command sizeLarge
button .cmd.size.huge   -text "Huge"   -command sizeHuge
pack append .cmd.size \
        .cmd.size.tiny          {top fillx expand} \
        .cmd.size.small         {top fillx expand} \
        .cmd.size.normal        {top fillx expand} \
        .cmd.size.large         {top fillx expand} \
        .cmd.size.huge          {top fillx expand}

# button .cmd.save -text "Save" -command {
#                       set curtag ""
#                       set s ""
#                       set end [split [.txt index end] "."]
#                       set endl [lindex $end 0]
#                       for {set l 1} {$l <= $endl} {incr l} {
#                               set e [lindex [split [.txt index "$l.0 lineend"] "."] 1]
#                               for {set c 0} {$c < $e} {incr c} {
#                                       set char [.txt get $l.$c]
#                                       set tags [.txt tag names $l.$c]
#                                       set tag ""
#                                       foreach t $tags {
#                                               if {$tag == "" && $t != "sel"} {
#                                                       set tag $t
#                                               }
#                                       }
#                                       if {$tag != $curtag} {
#                                               if {$curtag != ""} {append s "\}"}
#                                               if {$tag    != ""} {append s "\\$tag\{"}
#                                               set curtag $tag
#                                       }
#                                       append s $char
#                               }
#                               if {$curtag != ""} {
#                                       append s "\}\n"
#                                       set curtag ""
#                               } else {
#                                       append s "\n"
#                               }
#                       }
#                       puts stdout "$s"
#               }

.txt tag configure BOLD_TINY     -font lucidasans-bold-8
.txt tag configure BOLD_SMALL    -font lucidasans-bold-10
.txt tag configure BOLD_NORMAL   -font lucidasans-bold-12
.txt tag configure BOLD_LARGE    -font lucidasans-bold-14
.txt tag configure BOLD_HUGE     -font lucidasans-bold-18
.txt tag configure ITALIC_TINY   -font lucidasans-italic-8
.txt tag configure ITALIC_SMALL  -font lucidasans-italic-10
.txt tag configure ITALIC_NORMAL -font lucidasans-italic-12
.txt tag configure ITALIC_LARGE  -font lucidasans-italic-14
.txt tag configure ITALIC_HUGE   -font lucidasans-italic-18
.txt tag configure NORMAL_TINY   -font lucidasans-8
.txt tag configure NORMAL_SMALL  -font lucidasans-10
.txt tag configure NORMAL_NORMAL -font lucidasans-12
.txt tag configure NORMAL_LARGE  -font lucidasans-14
.txt tag configure NORMAL_HUGE   -font lucidasans-18

.txt insert 1.0 " "
.txt tag add NORMAL_NORMAL 1.0 end

# DATA form of the text looks like:
# set tags {{tag-name {range range .. }} {tag-name {range range ..} ..}
# set text {text
# and more text
# ...
# and the closing.}
# In other words.. two lists.  One is named `tags' and holds all
# the tag ranges.  The other is named `text' and holds all the text.
proc saveAsData {} {
        set tags ""
        foreach tag [.txt tag names] {
                if {$tag == "sel"} continue
                lappend tags [list $tag [.txt tag ranges $tag]]

        set of [open "untitled.txt" "w"]
        puts $of "set tags [list $tags]"
        puts $of "set text [list [.txt get 1.0 end]]"
        close $of


proc saveAsTroff {} {


proc importData {} {
        source untitled.txt
        catch {.txt delete 1.0 end}
        .txt insert 1.0 $text
        foreach tag $tags {
                set t [lindex $tag 0]
                if {$t == "sel"} continue
                set ranges [lindex $tag 1]
                set num_ranges [llength $ranges]
                for {set i 0} {$i < $num_ranges} {incr i 2} {
                        set start [lindex $ranges $i]
                        set end   [lindex $ranges [expr {$i+1}]]
                        .txt tag add $t $start $end


proc importText {} {


# scan_and_change - Scan over the currently selected range
#       and change it's type according to the parameters.
# default: The type to set it to if the position is
#       not already marked.
# type: The type of change.  FONT == Change font, SIZE == change size.
# value: What to change it to (BOLD, ITALIC, NORMAL, TINY, SMALL, NORMAL,
#       LARGE, HUGE).
proc scan_and_change {default type value} {
        if [catch {set end [.txt index sel.last]}] return
        for {set pos [.txt index sel.first]} \
            {$pos != $end} \
            {set pos [.txt index "$pos + 1 chars"]} {
                set tag ""
                foreach t [.txt tag names $pos] {
                        if {$tag == "" && $t != "sel"} { set tag $t }
                if {$tag == ""} {
                        set tag $default
                } else {
                        if {$type == "FONT"} {
                                set tag "${value}_[lindex [split $tag "_"] 1]"
                        } else {
                                set tag "[lindex [split $tag "_"] 0]_${value}"

                .txt tag remove BOLD_TINY     $pos
                .txt tag remove BOLD_SMALL    $pos
                .txt tag remove BOLD_NORMAL   $pos
                .txt tag remove BOLD_LARGE    $pos
                .txt tag remove BOLD_HUGE     $pos
                .txt tag remove ITALIC_TINY   $pos
                .txt tag remove ITALIC_SMALL  $pos
                .txt tag remove ITALIC_NORMAL $pos
                .txt tag remove ITALIC_LARGE  $pos
                .txt tag remove ITALIC_HUGE   $pos
                .txt tag remove NORMAL_TINY   $pos
                .txt tag remove NORMAL_SMALL  $pos
                .txt tag remove NORMAL_NORMAL $pos
                .txt tag remove NORMAL_LARGE  $pos
                .txt tag remove NORMAL_HUGE   $pos
                .txt tag add $tag $pos


proc fontBold   {} { scan_and_change BOLD_NORMAL   FONT BOLD   }
proc fontNormal {} { scan_and_change NORMAL_NORMAL FONT NORMAL }
proc fontItalic {} { scan_and_change ITALIC_NORMAL FONT ITALIC }

proc sizeTiny   {} { scan_and_change NORMAL_TINY   SIZE TINY   }
proc sizeSmall  {} { scan_and_change NORMAL_SMALL  SIZE SMALL  }
proc sizeNormal {} { scan_and_change NORMAL_NORMAL SIZE NORMAL }
proc sizeLarge  {} { scan_and_change NORMAL_LARGE  SIZE LARGE  }
proc sizeHuge   {} { scan_and_change NORMAL_HUGE   SIZE HUGE   }

<- "That's our advantage at Microsoft; we set the standards and we can change them."
<- Karen Hargrove of Microsoft quoted in the Feb 1993 Unix Review editorial.

Wed, 09 Aug 1995 06:23:33 GMT  
 [ 1 post ] 

 Relevant Pages 

1. Text widgets as basic text editors?

2. Fancy Text

3. Fancy Text

4. fancy printing software text Re: tgrind, etc (typesetting programs)

5. fancy text for scm

6. Compatible text editor for UNIX vi editor

7. Some questions on elided text in the text widget (and a few other text widget questions)

8. Text editor in Dolphin

9. Smalltalk with text editors

10. Text editor that saves emphases?

11. (newbies) Text Editor with layer

12. Edit Field/Text Editor?


Powered by phpBB® Forum Software