Google
 

Trailing-Edge - PDP-10 Archives - mit_emacs_170_teco_1220 - info/draw.doc
There is 1 other file named draw.doc in the archive. Click here to see a list.
               AN EMACS FIGURE DRAWING LIBRARY

When writing papers on-line, I find it convenient to keep the paper's
figures on line too.  To ease the burden of drawing these figures,
I've constructed a library of EMACS subroutines (Meta-X commands)
to help.  They have turned out to be useful in other things as well, 
like getting comments lined up.

To load the library into Emacs, you have to type the command

        <M-X> Load <SP> Library <ESC> <LAMPORT>DRAW <CR> .

(That is the following sequence of characters:
    Meta-X L o a d Space L i b r a r y Escape < L A M ...  CarriageReturn
).

The commands are described below.  Note that they will do funny things
if you try to draw anything beyond the boundaries of the buffer, so
make sure that you have a few lines (possibly empty) above and below
where you're drawing.  Also, they were hastily written, and no promises
are made about their correctness.  Caveat emptor!


Line Drawing Commands
---------------------

A "line" is something that looks like the following.

                           abc                 
                         abc
                       abc
                     abc
                   abc
                 abc
               abc
             abc   

It consists of 8 identical "horizontal strips", each composed
of the three characters "abc".  It has a beginning and an end,
which cannot be distinguished in this picture.  Let us suppose
that the beginning is at the lower left.  Then this is
an "upward moving line".  It was drawn by the following
sequence of operations:

   1.  Moving the pointer to where the beginning of the line now is 
       (the lower-left "a").

   2.  Executing the command 

                    <M-X> MARK <ESC> abc <CR>
       (That's 10 characters: Meta-X M A R K Escape a b c CarriageReturn .)

   At this point the first horizontal strip "abc" appears on the screen.
   This strip is called "the mark".  (Not to be confused with EMACS own
   marks, which will not be mentioned in this note.)

   3.  Moving the pointer to near where the beginning of the
       last (top-most) horizontal strip now is -- on that line
       but not necessarily at the exact character position.

   4.  Executing the command  <M-X> DRAW <CR> .

The reason I said "near" not "at" in step 3 is that a line has a fixed
integral slope, and begins at the mark.  This means that it won't
necessarily wind up at the precise horizontal position of the pointer.
In particular, if you're trying to draw a vertical line, you don't have
to be lined up exactly to get it to be vertical.

Horizontal lines do not make sense.  Don't try drawing them.
There easy to do with Emacs anyway. (E.g., typing <M-2> <M-9> x puts a string
of 29 x's in the buffer.)

|| WARNING: The buffer location of the mark -- i.e., the number of characters
|| ahead of it in the buffer -- is remembered after doing the MARK command.
|| Things will get fouled up if this information becomes incorrect between
|| the execution of the MARK and the execution of a command like DRAW that
|| uses the mark.  This means that you must not add any characters -- like
|| spaces at the end of lines -- before the mark as you move the pointer to 
|| where you want to do the DRAW.  The safest thing to do is to create a whole
|| screenful of lines filled with spaces.  (There are innumerable ways
|| of doing this with EMACS.)  You will then be happiest in
|| overwrite mode -- which is toggled with the command
|| 
|| 	    <M-X> Overwrite Mode <CR>  .
|| 
|| In this mode, typing characters puts them on top of the existing
|| ones rather than inserting them.  This is what you probably
|| want for drawing pictures anyway.

The DRAW command in step 4 can be replaced by other commands, which
have the following effects:

    SHRINK  -  Draws a line as in the DRAW command, and then kills
               it -- i.e., deletes the characters comprising the
               line, thereby shifting left everything that was to the
               right of the line.  (The line isn't really drawn.)

    STRETCH -  Replaces the mark with what was there before, then
               draws an imaginary line as in the DRAW command, except
               of zero width.  Everything to the right of the line
               is shifted right by the number of characters in the mark,
               and each newly created horizontal strip is filled with
               the character to its left (or blank if it's the beginning
               of the line).  This allows you to move things to the right
               while maintaining the connectivity of lines.

    ERASE -    Equivalent to doing a SHRINK then a STRETCH.  Only
               works on downward moving lines.  (Sorry about that.)


EMACS uses the "Escape Convention" for completing commands,
so you can type something like  STR<ESC> instead of STRETCH,
and  MAR<ESC> instead of MARK<ESC>.  Note that you don't
need to type another Escape for the MARK command.
(The <ESC> doesn't type the <CR> for  you.)

Each of the above commands has a corresponding "V" command: e.g.,
VDRAW, VSTRETCH.  They are called as follows, where
<Meta-n> denotes a number n (positive or negative) typed
while holding the Edit key down.

      <Meta-n> <M-X> VDRAW <ESC> abc <CR>

This is equivalent to doing the following.

        1. Typing  <M-X> MARK <ESC> abc <CR> .

        2. Moving the pointer down  n-1 lines (or up |n|-1 lines if n 
           is negative).

        3. Typing  <M-X> DRAW <CR> .

In this scenario, "abc" can of course be replaced by any string,
and "DRAW" can be replaced by any of the above commands.

There's another command  DDRAW  that is similar to VDRAW, except
it draws a diagonal line with slope determined by the width of
the line.




Figures
-------

A figure is a rectangular array of characters.  You can copy figures
from the buffer into Emacs' Q-registers and insert them from the
Q-registers into the buffer.  The Q-registers you can use have
single letter names: "A", "B", ... , "Z".  In the discussion I will
use Q-registers A and B, but any other Q-registers can be used.

To put a figure into the Q-register, use the MARK command to place
a mark in one corner of the figure.  (You should use a one-character
mark, but if you don't, it's the first character of the mark
that counts.)  You then move the pointer to the diagonally opposite
corner of the figure and execute the command:

      <M-X> FCOPY <ESC> A .

This places the selected figure in Q-register A.  (The mark
is replaced by what was there before before the figure is 
copied into the Q-register.)

Note that there are four corners in which you can put the mark.
(You must then move the pointer to the diagonally opposite corner.)
If you start in the upper left-hand corner, then the picture
is copied as is.  However, starting at another corner has
the following effects:

     Either Bottom Corner: the rows are inverted -- forming a
                           mirror image about a horizontal line.

     Either Right-Hand Corner: the columns are inverted -- forming
                               a mirror image about a vertical line.

This means that putting the mark in the lower right-hand corner
makes the copy in the Q-register a 180 degree rotation of the
original figure.   (However, the characters still appear right side up.)

To put a copy of the figure in Q-register A into the buffer, put the 
pointer where you want the upper left-hand corner to go and type:

       <M-X> FIGURE <ESC> A <CR>


The following neat command:

       <M-X> TRANSPOSE <ESC> A <ESC> B <CR>

puts the transpose (rows and columns interchanged) of the figure from
Q-register A into Q-register B.  Note that forming the mirror
image about a vertical line of the transpose of a figure is the
same as rotating the figure 90 degrees clockwise.  By using FCOPY
and TRANSPOSE you can form any rotation that's a multiple of 90 degrees
and any mirroring.  For example, you can easily take a bunch of stuff like

               this and 
                       
               turn it      
                       
               on its  

side like so:
 
               t t o
               h u n
               i r  
               s n i
                   t
               a i s
               n t  
               d       .


Happy hacking!