PreviousUpNext

15.4.1254  src/lib/tk/src/live_text.pkg

/* ***************************************************************************
 
# Compiled by:
#     src/lib/tk/src/tk.sublib

   Annotated texts for the tk markup language.

   $Date: 2001/03/30 13:38:57 $
   $Revision: 3.0 $
   Author: cxl (Last modification by $Author: 2cxl $)

   (C) 1996, 1998, Bremen Institute for Safe Systems, Universitaet Bremen
 
  ************************************************************************** */

package   live_text
: (weak)  Live_Text             # Live_Text     is from   src/lib/tk/src/live_text.api
{
    infix my 70  +++ ;          # See below -- fixity decl's not allowed inside APIs 

    include basic_tk_types;
    include basic_utilities;


    # The two int's are the index to the last character/last row of the 
    # text. This index is calculated `lazily': If it is not given 
    # explicitly, it is only calculated if another annotated text with
    # a non-empty list of annotations is appended to the text.
    #
    fun get_livetext_text (LIVE_TEXT { str, ... } )
        =
        str;

    fun get_livetext_text_items (LIVE_TEXT { text_items, ... } )
        =
        text_items;

    fun update_livetext_text_items (LIVE_TEXT { len=>x, str=>t, ... } ) a
        = 
        LIVE_TEXT { len=>x, str=>t, text_items=>a };


    # Adding rows -- a wee bit funny, since counting starts at one
    # but we want to be graceful about line zero as well.
    #
    fun add_rows (r1, r2)
        =
        r1+ r2- (int::min (r1, 1));

    fun add2mark (r, c) (MARK (rm, cm))
            =>
            if   (rm <= 1   )   MARK (r, c+cm);
                           else   MARK (add_rows (r, rm), cm);   fi;

        add2mark (r, c) (MARK_TO_END rm)
            =>
            MARK_TO_END (add_rows (r, rm));

        add2mark (r, c) MARK_END
            => MARK_END;
    end;
                      # A wee bit debatable-- we might want to adjust the 
                      # "End" etc. marks in the text_items of the first
                      # text. Then again, end means end

    fun pair f (x, y) = (f x, f y);  #  has gone into basic_utilities 

    fun map_mark f (TEXT_ITEM_TAG { text_item_id, marks, traits, event_callbacks } )
        =>
                   TEXT_ITEM_TAG { text_item_id, marks=>map (pair f) marks, 
                         traits, event_callbacks };
       map_mark f (TEXT_ITEM_WIDGET { text_item_id, mark, subwidgets, traits,
                            event_callbacks } )
        =>
                    TEXT_ITEM_WIDGET { text_item_id, mark=>f mark, subwidgets,
                             traits, event_callbacks }; end;

    /* Concatenate two annotated texts with explicit length:
     */
    fun cat ((rows, cols), s, a) ((rows0, cols0), t, b)
        =
        { ann = a@(map (map_mark (add2mark (rows, cols))) b);
          if (rows0 <= 1) #  second text only has one line, we only add cols 
               LIVE_TEXT { len=>THE (rows, cols+cols0), str=>s$t, text_items=>ann };
          else LIVE_TEXT { len=>THE (add_rows (rows, rows0), cols0), 
                          str=>s$t, text_items=>ann };
          fi;
        };                    

    #  Count length of annotated text 
    fun livetext_length t
        =
        {   fun count (thischar, (line, char))
                =
                if (string_util::is_linefeed thischar) 
                     (line+1, 0);
                else (line, char+1); fi;

            my (rows, cols)
                =
                substring::fold_forward count (1, 0) (substring::from_string t);
        
            (int::max (rows, 1), cols);
        };

    fun get_livetext_rows_cols (LIVE_TEXT { len=>THE (r, c), ... } )
            =>
            { rows=> r, cols=> c };

        get_livetext_rows_cols (LIVE_TEXT { len=>NULL, str=>t, ... } )
            =>
            {   my (r, c)= livetext_length t; 
                { rows=> r, cols=> c }; 
            };
    end;
         
    fun ( (LIVE_TEXT { len=>NULL, str=>s, text_items => a  } )
          +++ 
          (LIVE_TEXT { len=>NULL, str=>t, text_items => [] } )
        )
            =>
            (LIVE_TEXT { len=>NULL, str=>s$t, text_items=>a } ); 

        ( (LIVE_TEXT { len=>len1, str=>s, text_items=>a } )
          +++ 
          (LIVE_TEXT { len=>len2, str=>t, text_items=>b } )
        )
            =>
            {   fun get_len (THE (r, c), s, a) =>  ((r, c), s, a);
                    get_len (NULL, s, a)       =>  (livetext_length s, s, a);
                end;

                cat (get_len (len1, s, a)) (get_len (len2, t, b));
            };
    end;


    fun nl (LIVE_TEXT { len=>NULL, str=>s, text_items=>a } )
            => 
            LIVE_TEXT { len=>NULL, str=>s$"\n", text_items=>a };

        nl (LIVE_TEXT { len=>THE (r, c), str=>s, text_items=>a } )
            => 
            LIVE_TEXT { len=>THE (r+1, 0), str=>s$"\n", text_items=>a };
    end;

    empty_livetext
        =
        LIVE_TEXT { len=>NULL, str=>"", text_items => [] };

    fun adjust_marks { rows, cols } annos
        = 
        map  (map_mark (add2mark (rows, cols)))  annos;


    #  Convert a string to an annotated text with no text_items 

    fun make str
        =
        LIVE_TEXT { len=>NULL, str, text_items => [] };


    fun livetext_join str ls
        = 
        join' ls
        where
            at = make str;

            fun join' []       =>  empty_livetext;
                join' [t]      =>  t;
                join' (t . ts) =>  at +++ at +++ (join' ts);
            end;
        end;

};


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext