summaryrefslogtreecommitdiffstats
path: root/Mac
diff options
context:
space:
mode:
Diffstat (limited to 'Mac')
-rw-r--r--Mac/Demo/applescript.html13
-rw-r--r--Mac/Demo/example2.html18
-rw-r--r--Mac/Demo/index.html51
-rw-r--r--Mac/Demo/textedit.html152
-rw-r--r--Mac/Demo/using.html24
-rw-r--r--Mac/Demo/waste.html69
6 files changed, 291 insertions, 36 deletions
diff --git a/Mac/Demo/applescript.html b/Mac/Demo/applescript.html
index 35cbf49..7db5ba6 100644
--- a/Mac/Demo/applescript.html
+++ b/Mac/Demo/applescript.html
@@ -32,7 +32,7 @@ There is a tool in the standard distribution that looks through a file
for an 'AETE' or 'AEUT' resource, the internal representation of the
AppleScript dictionary. This tool is called
<CODE>gensuitemodule.py</CODE>, and lives in
-<CODE>Tools:bgen:ae</CODE>. When we start it, it asks us for an input
+<CODE>Mac:scripts</CODE>. When we start it, it asks us for an input
file and we point it to the Eudora Light executable. It starts parsing
the AETE resource, and for each AppleEvent suite it finds it prompts
us for the filename of the resulting python module. Remember to change
@@ -46,7 +46,7 @@ gensuitemodule does not currently understand this. Creating the empty
<CODE>Required_Suite.py</CODE> would hide the correct module of that
name from our application. <p>
-<CITE>
+<BLOCKQUOTE>
Time for a sidebar. If you want to re-create
<CODE>Required_Suite.py</CODE> or one of the other standard modules
you should look in <CODE>System Folder:Extensions:Scripting
@@ -55,7 +55,7 @@ AppleEvent dictionaries live. Also, if you are looking for the
<CODE>Finder_Suite</CODE> interface: don't look in the finder (it has
an old System 7.0 scripting suite), look at the extension <CODE>Finder
Scripting Extension</CODE>. <p>
-</CITE>
+</BLOCKQUOTE>
Let's glance at the <A
HREF="scripting/Eudora_Suite.py">Eudora_Suite.py</A> just created. You
@@ -81,7 +81,7 @@ arguments the verb expects, and it makes handy use of the keyword
argument scheme introduced in Python 1.3 to present a palatable
interface to the python programmer. You will see that each method
calls some routines from <CODE>aetools</CODE>, an auxiliary module
-living in <CODE>Tools:bgen:ae</CODE> which contains some other nifty
+living in <CODE>Lib:toolbox</CODE> which contains some other nifty
AppleEvent tools as well. Have a look at it sometime, there is (of
course) no documentation yet. <p>
@@ -130,10 +130,7 @@ together in the right way. <p>
Looking at the sourcefile <A
HREF="scripting/testeudora.py">testeudora.py</A> we see that it starts
-with some imports (and some <CODE>addpack</CODE> calls to extend
-<CODE>sys.path</CODE> to include <CODE>Tools:bgen:ae</CODE>, use of
-<CODE>ni</CODE> should be preferred over <CODE>addpack</CODE> but I
-have not managed to master it yet). Then we get the class definition
+with some imports. Then we get the class definition
for our main object and a constant giving the signature of Eudora. <p>
This, again, needs a little explanation. There are various ways to
diff --git a/Mac/Demo/example2.html b/Mac/Demo/example2.html
index 3bd2791..aebe73d 100644
--- a/Mac/Demo/example2.html
+++ b/Mac/Demo/example2.html
@@ -11,7 +11,7 @@ HREF="example2/InterslipControl-2.py">Source</A> and resource file (in
binary and <A HREF="example2/InterslipControl-2.rsrc.hqx">BinHex</A>
form for downloading) are available in the folder <A
HREF="example2">example2</A>. If you want to run the program on your
-machine you will also need a new copy of <A
+machine and you have Python 1.3 or earlier you will also need a new copy of <A
HREF="update-to-1.3/FrameWork.py">FrameWork.py</A>, which has been
updated since the 1.3 release. <p>
@@ -61,15 +61,13 @@ now. It will create a menu bar with an Apple menu with the about box
and a "File" menu with some pythonesque choices (which do nothing
interesting, by the way) and a "Quit" command that works. <p>
-<CITE>
-A more complete description of <A NAME="framework">FrameWork</A> is
-sorely needed, and will (at some point) be incorporated in the
-programmers manual or in place of this paragraph. For now you'll have
-to make do with the knowledge that you use FrameWork by building your
-classes upon the classes provided by it and selectively overriding
-methods to extend its functionality (or override the default
-behaviour). And you should read the Source, of Course:-) <p>
-</CITE>
+<BLOCKQUOTE>
+If you have not used <code>FrameWork</code> before you may want to
+first take a look at the <A HREF="textedit.html">Pathetic EDitor</A>
+example, which builds a minimal text editor using FrameWork and TextEdit.
+On the other hand: we don't use many features of FrameWork, so you could
+also continue with this document.
+</BLOCKQUOTE>
After the imports we get the definitions of resource-IDs in our
resource file, slightly changed from the previous version of our
diff --git a/Mac/Demo/index.html b/Mac/Demo/index.html
index fda20b7..774db68 100644
--- a/Mac/Demo/index.html
+++ b/Mac/Demo/index.html
@@ -19,7 +19,7 @@ HREF="http://www-acs.ucsd.edu/~jstrout/python/">
http://www-acs.ucsd.edu/~jstrout/python/</A>.
<P>
-The document was actually written while I was working on a "real"
+Some of these documents were actually written while I was working on a "real"
project: creating a single-button application that will allow my
girlfriend to read her mail (which actually pass thry <EM>my</EM>
mailbox, so I get to read it too, but don't tell her:-) without her
@@ -28,15 +28,16 @@ application, when finished, will connect to the net using InterSLIP,
start a (pseudo-)POP server on unix using rsh and use AppleScript to
tell Eudora to connect to that server and retrieve messages. <p>
-<CITE>
-If you want to try the examples here you will have to download some
-fixes to the 1.3 distribution to your Macintosh. You need an updated
+<BLOCKQUOTE>
+If you want to try the examples with a version of Python earlier
+than 1.3.1 you have to download some things. You need an updated
version of <A HREF="update-to-1.3/FrameWork.py">FrameWork.py</A> (to
go in <CODE>Lib:mac</CODE> and updated <A
HREF="update-to-1.3/into-PlugIns.hqx">project templates</A> to go into
-the <CODE>PlugIns</CODE> folder for PPC users.
-Users of 1.3.1 or later distributions don't need these fixes.<P>
-</CITE>
+the <CODE>PlugIns</CODE> folder for PPC users. <P>
+The TextEdit and WASTE examples are not useable with distributions
+before 1.3.3.
+</BLOCKQUOTE>
If you are reading this document on the web and would prefer to read
it offline you can transfer the whole stuff (as a BinHexed StuffIt
@@ -59,12 +60,13 @@ mac application, using a modeless dialog, menus, etc. It also explains
how to create applets, standalone applications written in Python.
<LI>
-In the Python distribution two more examples are included without
-explanation. <I>PICTbrowse</I> is an application that locates PICT
-resources and displays them, it demonstrates some quickdraw and the
-resource and list namagers. <I>Imgbrowse</I> displays image files in
-many different formats (gif, tiff, pbm, etc). It shows how to use the
-img modules on the mac.
+<A HREF="textedit.html">Using FrameWork and TextEdit</A> shows you
+how to use <code>FrameWork</code> application framework and the
+<code>TextEdit</code> toolbox to build a text editor.
+
+<LI>
+<A HREF="waste.html">Using WASTE</A> expands on this editor by using
+WASTE, an extended TextEdit replacement.
<LI>
<A HREF="plugins.html">Creating a C extension module on the Macintosh</A>
@@ -79,6 +81,27 @@ how to create a Python module interfacing to a scriptable application,
and how to use that module in your python program.
</UL>
+The Python distribution contains a few more examples, all unexplained:
+<UL>
+<LI>
+<I>PICTbrowse</I> is an application that locates PICT
+resources and displays them, it demonstrates some quickdraw and the
+resource and list managers.
+
+<LI>
+<I>Imgbrowse</I> displays image files in
+many different formats (gif, tiff, pbm, etc). It shows how to use the
+img modules on the mac.
+
+<LI>
+<I>Quicktime</I> has the standard <code>MovieInWindow</code> and
+<code>VerySimplePlayer</code> examples, re-coded in Python.
+
+<LI>
+<I>Resources</I>, <I>Sound</I> and <I>Speech</I> have some examples
+on using the respective managers.
+</UL>
+
At some point in the (possibly distant) future, I will add chapters on
how to use bgen to create modules completely automatic and how to make
your Python program scriptable, but that will have to wait. <p>
@@ -95,4 +118,4 @@ documentation. <p>
<HR>
<A HREF="http://www.cwi.nl/~jack">Jack Jansen</A>,
-<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 7-Apr-1996.
+<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 19-Apr-1996.
diff --git a/Mac/Demo/textedit.html b/Mac/Demo/textedit.html
new file mode 100644
index 0000000..d56ea0b
--- /dev/null
+++ b/Mac/Demo/textedit.html
@@ -0,0 +1,152 @@
+<HTML><HEAD><TITLE>Using FrameWork and TextEdit</TITLE></HEAD>
+<BODY>
+<H1>Using FrameWork and TextEdit</H1>
+<HR>
+
+In this document we use the <CODE>FrameWork</CODE> and <CODE>TextEdit</CODE>
+modules to create a simple text editor. The functionality
+of the editor is very basic: you can open multiple files, type text and use
+cut/copy/paste. The main intention is to explain the use of FrameWork, really. <p>
+
+<H2>FrameWork</H2>
+
+The FrameWork module provides you with a skeleton application. It declares a
+number of classes suitable for subclassing in your application, thereby
+releaving you of the burden of doing all event handling, etc. yourself. For a
+real understanding you will have to browse the source. Here is a short overview
+of the classes and what functionality they provide.
+
+<dl>
+<dt> <CODE>Application</CODE>
+<dd>
+This is the toplevel class you will override. It maintains the menu bar and contains
+the main event handling code. Normal use is to override the <code>__init__</code> routine
+to do your own initializations and override <code>makeusermenus</code> to create your menus
+(your menu callback routines may be here too, but this is by no means necessary).
+The event handling code can be overridden at various levels, from very low-level (the
+<code>dispatch</code> method) to intermedeate level (<code>do_keyDown</code>, for instance)
+to high-level (<code>do_key</code>). The application class knows about the <code>Window</code>
+objects you create, and will forward events to the appropriate window (So, normally you
+would have a <code>do_key</code> method in your window object, not your application object).
+
+<dt> <CODE>MenuBar</CODE>, <CODE>Menu</CODE> and <CODE>MenuItem</CODE>
+<dd>
+These classes (and a few friends like <CODE>SubMenu</CODE>) handle your menus. You would not
+normally override them but use them as-is. The idiom for creating menus is a bit strange,
+see the test code at the bottom of FrameWork for sample use. The apple menu is handled for you
+by <CODE>MenuBar</CODE> and <CODE>Application</CODE>.
+
+<dt> <CODE>Window</CODE>
+<dd>
+The basic window. Again, a class that you normally subclass in your application, possibly
+multiple times if you have different types of windows. The init call instantiates the data
+structure but actually opening the window is delayed until you call <code>open</code>. Your
+open method should call <code>do_postopen</code> to let the base class handle linking in to
+the application object. Similarly with <code>close</code> and <code>do_postclose</code>. The
+rest of the code is mainly event-oriented: you override <code>do_postresize</code>,
+<code>do_contentclick</code>, <code>do_update</code>, <code>do_activate</code>
+and <code>do_key</code> to "do your thing". When these methods are called the relevant environment
+has been setup (like <code>BeginDrawing</code> has been called for updates, etc).
+
+<dt> <CODE>windowbounds</CODE>
+<dd>
+Not a class but a function: you pass it a width and height and it will return you a rectangle
+you can use to create your window. It will take care of staggering windows and it will try
+to fit the window on the screen (but the resulting rect will <em>always</em> have the size you
+specify).
+
+<dt> <CODE>ControlsWindow</CODE>
+<dd>
+A subclass of Window which automatically handles drawing and clicking for controls. You override
+the same methods as for Window (if you need to: control-related things are done automatically) and
+<code>do_controlhit</code>.
+
+<dt> <CODE>ScrolledWindow</CODE>
+<dd>
+A subclass of ControlsWindow, a window with optional scrollbars. If you override <code>do_activate</code>
+or <code>do_postresize</code> you must call the ScrolledWindow methods at the end of your override.
+You call <code>scrollbars</code> to enable/disable scrollbars and <code>updatescrollbars</code> to
+update them. You provide <code>getscrollbarvalues</code> to return the current x/y values (a helper
+method <code>scalebarvalues</code> is available) and <code>scrollbarcallback</code> to update your
+display after the user has used the scrollbars.
+
+<dt> <CODE>DialogWindow</CODE>
+<dd>
+A modeless dialog window initialized from a DLOG resource. See the
+<A HREF="example2.html">second Interslip example</A> for its useage.
+</dl>
+
+<H2>A sample text editor</H2>
+
+Let us have a look at <A HREF="textedit/ped.py">ped.py</A> (in the Demo:textedit folder), the Pathetic
+EDitor. It has multiple windows, cut/copy/paste and keyboard input, but that is about all. It looks
+as if you can resize the window but it does not work. Still, it serves as an example. We will improve
+on ped later, in a <A HREF="waste.html">waste-based example</A>. <p>
+
+Ped creates two classes, <code>TEWindow</code> and <code>Ped</code>. Let us start with the latter one,
+which is a subclass of <code>FrameWork.Application</code> and our main application. The init function
+has little to do aside from the standard init: it remembers a window sequence number (for untitled windows),
+and sets things up for menu disable to work. Remember, the <code>makeusermenus</code> is called
+automatically. <p>
+
+<code>Makeusermenus</code> creates the <code>File</code> and <code>Edit</code> menus. It also initializes
+a couple of lists that are used later to correctly enable and disable menu items (and complete menus) depending
+on whether a window is open, text is selected, etc. The callback functions for the menu items are
+all methods of this class. <p>
+
+<code>Updatemenubar</code> handles greying out (and re-enabling) of menu items depending on whether there
+is a current window and its state. <p>
+
+The rest of the methods are all callbacks and simple to understand. They check whether there is an active
+window (and complain loudly if there is none: the corresponding menu entry should have been disabled
+in that case!) and call the appropriate window method. Only the <code>_open</code> method (the common code
+for <code>Open</code> and <code>New</code>) deserves some mention. It instantiates a <code>TEWindow</code>
+object and opens it with the title, filename and contents of the file to edit. Note that FrameWork takes
+care of remembering the window object. A minor note on opening the file in binary mode: this is because
+TextEdit expects MacOS style carriage-return terminated lines, not python/unix/C style newline-terminated
+lines. <p>
+
+Oh yes: the <code>quit</code> callback does a little magic too. It closes all windows, and only if this
+succeeds it actually quits. This gives the user a chance to cancel the operation if some files are unsaved.
+Quitting itself is also a bit strange: you raise <code>self</code> to break out of the main loop. This bit
+of idiom was invented by Guido, so blame him:-). <p>
+
+Lastly, there is the <code>idle</code> method, called by the Application base class when no event
+is available. It is forwarded to the active window, so it can blink the text caret. <p>
+
+The <code>TEWindow</code> object handles a single window. Due to this structuring it is absolutely no
+problem to have multiple windows open at the same time (although a real application should exercise care when
+two windows refer to the same document). TEWindow uses the standard init code inherited from
+<code>ScrolledWindow</code>, and sets itself up at the time of the <code>open</code> call. It obtains screen
+coordinates, opens the window, creates rectangles for TextEdit to work in (the magical number <code>15</code>
+here is the size of a normal scroll bar: unfortunately there is no symbolic constant for it),
+creates the TextEdit object and initializes it with our data. Finally, the scroll bars are created (the
+initial values will be obtained automatically through <code>getscrollbarvalues</code>) and we activate
+ourselves (this is unfortunately not done automatically by the MacOS event handling code). <p>
+
+<code>Do_idle</code> simply calls the TextEdit routine that blinks the cursor. <code>Getscrollbarvalues</code>
+returns the current X and Y scrollbar values, scaled to <code>0..32767</code>. For X we return <code>None</code>,
+which means "no scrollbar, please", for Y we use the scaler provided by <code>ScrolledWindow</code>. <p>
+
+<code>Scrollbar_callback</code> is called when the user uses the scrollbar. It is passed a string <code>'x'</code>
+or <code>'y'</code>, one of <code>'set', '-', '--', '+', '++'</code> and (for <code>set</code>) an absolute
+value. Note that the sign of the value passed to <code>TEPinScroll</code> is counter-intuitive. <p>
+
+<code>do_activate</code> (de)activates the scrollbars and calls the relevant TextEdit routine. Moreover, it
+tells the application object if we are now the active window, and updates the menubar. The next few methods
+are update and menu callbacks, and pretty straightforward. Note that <code>do_close</code> can
+return without closing the window (if the document is changed and the users cancels out of the operation).
+Also note the "magic" in <code>menu_save_as</code>
+that set the correct window title. <p>
+
+Things get moderately interesting again at the cut/copy/paste handling, since the TextEdit scrap is
+separate from the desktop scrap. For that reason there are various calls to routines that move the scrap
+back and forth. <code>Have_selection</code> is called by the menubar update code to determine whether cut and
+copy should be enabled. <p>
+
+Understanding the main program is left as an exercise to the reader. <p>
+
+<hr>
+That's all for this example, you could now continue with the <A HREF="waste.html">next example</A>, where we use WASTE, a more-or-less
+TextEdit compatible library with more functionality, to rebuild our editor. Or you can
+return to the <A HREF="index.html">table of contents</A> to pick another topic. <p>
diff --git a/Mac/Demo/using.html b/Mac/Demo/using.html
index 5f20097..849c6d1 100644
--- a/Mac/Demo/using.html
+++ b/Mac/Demo/using.html
@@ -14,6 +14,14 @@ HREF="http://www.python.org/doc/tut/tut.html">Python Tutorial</A> by
Guido van Rossum. This guide more-or-less replaces chapter two of the
tutorial, and provides some additional material. <p>
+There is currently no good tutorial for the mac-specific features of
+Python, but to whet your appetite: it has interfaces to many MacOS
+toolboxes (quickdraw, sound, quicktime, open scripting, etc) and
+various portable toolboxes are available too (Tk, stdwin, complex
+numbers, image manipulation, etc). Some <A HREF="index.html">
+annotated sample programs</A> are available to give you an idea of
+Python's power. <P>
+
The document refers to Python 1.3.3 or higher, some of the features
(like setting applet options) will not work in earlier versions of
Python. <p>
@@ -24,7 +32,7 @@ The name of the interpreter may differ on different installations: it
may be called <CODE>Python</CODE>, <CODE>PythonPPC</CODE> (for powerpc
macs) or <CODE>Python68K</CODE> (indeed, for 68K macs). It will always
be recognizable by the "16 ton" icon, though. You start the
-interpreter in interactive mode by double-clicking it. <p>
+interpreter in interactive mode by double-clicking its icon: <p>
<img src="html.icons/python.gif"><p>
@@ -88,7 +96,7 @@ edit-run cycle you can use the <CODE>import</CODE> statement and
is Guido's original comment for how to do this, from the 1.1 release
notes: <P>
-<CITE>
+<BLOCKQUOTE>
Make sure the program is a module file (filename must be a Python
identifier followed by '<CODE>.py</CODE>'). You can then import it
@@ -121,7 +129,7 @@ does!). The trick is to first import the module again, then reload
it. For instance, <CODE>import foo; reload(foo)</CODE>. Because the
module object already exists internally, the import statement does not
attempt to execute the module again -- it just places it in your
-workspace. </CITE>
+workspace. </BLOCKQUOTE>
<h2>Clickable python scripts</h2>
@@ -138,6 +146,14 @@ The <CODE>Scripts</CODE> folder contains a script
set the correct creator and type for all files ending in
<CODE>.py</CODE>. <p>
+<BLOCKQUOTE>
+Older releases of Python used the creator code
+<CODE>'PYTH'</CODE> in stead of <CODE>'Pyth'</CODE>. If you still have
+older Python sources on your system and named them with
+<CODE>'.py'</CODE> extension the <CODE>fixfiletypes</CODE> script will
+correct them.
+</BLOCKQUOTE>
+
<h2>Interaction with the user</h2>
Normally, the interpreter will check for user input (mouse clicks,
@@ -355,7 +371,7 @@ set) the end-of-line convention used in a file. <p>
<HR>
<A HREF="http://www.cwi.nl/~jack">Jack Jansen</A>,
-<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 15-Apr-1996.
+<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 19-Apr-1996.
</BODY>
</HTML>
diff --git a/Mac/Demo/waste.html b/Mac/Demo/waste.html
new file mode 100644
index 0000000..856d792
--- /dev/null
+++ b/Mac/Demo/waste.html
@@ -0,0 +1,69 @@
+<HTML><HEAD><TITLE>Using WASTE</TITLE></HEAD>
+<BODY>
+<H1>Using WASTE</H1>
+<HR>
+
+WASTE is an almost-compatible TextEdit replacement which overcomes
+some of the limitations of it (like the 32K limit) and provides some extensions
+(drag and drop, images, undo support). Moreover, it has a much cleaner interface
+and is therefore easier integrated in Python. <p>
+
+WASTE is written by Marco Piovanelli, <A HREF="mailto:piovanel@kagi.com">&lt;piovanel@kagi.com&gt;</A>,
+and copyrighted by him. You can always obtain the latest version (for use in C
+or Pascal programs) and the documentation from
+<A HREF="ftp://ftp.dsi.unimi.it/DSI/piovanel/WASTE">&lt;ftp://ftp.dsi.unimi.it/DSI/piovanel/WASTE&gt;</A>.
+
+We explain the useage of waste here by showing how to modify the TextEdit based
+<A HREF="textedit/ped.py">ped.py</A> of the
+<A HREF="textedit.html">previous example</A> into the waste-based <A HREF="waste/wed.py">wed.py</A>,
+so you should have both sources handy. <p>
+
+Functionally, <code>wed.py</code> provides three new things: resizable windows, a horizontal
+scroll bar and undo. <p>
+
+Let us look at the code, first at the application class <code>Wed</code>. The only real change is that
+we now handle <code>undo</code>. Aside from enabling it in the creation routine and the addition of
+a callback routine there is a bit of new code in <code>updatemenubar</code>: Waste not only handles
+the full details of implementing undo, it will also tell us what the next undo operation will undo
+(or redo). We use this to our advantage by changing the undo menu label to tell the user. <p>
+
+The <code>WasteWindow</code> has seen a bit more change. Initialization of the waste data structure is
+a bit different, in that we can specify some options at creation time. Also, waste has no <code>SetText</code>
+method but a <code>UseText</code> which expects a handle as parameter. We have to be <EM>very</EM> careful
+that we keep this handle around, because Python will happily free the handle if we have no more references
+to it (and I doubt that Waste would like this:-). A final difference in <code>open</code>
+is that we use a large number for the destination rectangle width, because we will use a horizontal scroll
+bar. <p>
+
+The <code>idle</code> method is a bit more involved, since we also call <code>WEAdjustCursor</code> to
+provide the correct cursor based on mouse-position. Users like this. <p>
+
+<code>Getscrollbarvalues</code> is simpler than its' TextEdit counterpart because Waste correctly
+updates the destination rectangle when the document changes. Also note that waste uses accessor functions
+to get at internal values, as opposed to direct struct access for TextEdit. <p>
+
+<code>Scrollbar_callback</code> on the other hand is more elaborate (but also provides more functionality).
+It also handles horizontal scrolls (scrolling one-tenth and half a screenful with the buttons). This
+function is also "multi-font-ready" in that scrolling one line will do the expected thing in case of multiple
+fonts. We will implement a multi-font editor later. A minor annoyance of Waste is that is does not provide
+a pinned scroll, so at the end of our callback routine we have to check that we have not scrolled past the
+beginning or end of the document, and adjust when needed. <p>
+
+<code>do_update</code> is also changed, because Waste is completely region-based (as opposed to rect-based).
+Hence, we erase regions here and we can also return immedeately if there is nothing to update. <p>
+
+<code>Do_postresize</code> is new: because Waste uses accessor functions we can now modify the viewRect from
+Python, which is impossible in the Python TextEdit interface, and hence we can implement resize. The
+<code>do_key</code> and <code>do_contentclick</code> methods have also seen minor changes, because the
+corresponding waste routines need a bit more information than their TextEdit counterparts. The Cut/copy/paste
+code is simplified, because Waste uses the normal desktop scrap. <p>
+
+Implementing undo is a wonder of simplicity: Waste handles all the details for us. Also, the new
+<code>can_paste</code> method (which controls greying out of the paste menu entry) is an improvement
+over what <code>ped</code> did: in ped it was possible that paste was enabled but that the data on the
+scrap was incompatible with TextEdit. No more such problems here. <p>
+
+<hr>
+That is all for now. At some point in the future I will extend this editor to incorporate multiple fonts and
+pointsizes, pictures and possibly drag-and-drop editing but I will first have to write the code for it.
+For now you will have to go back to the <A HREF="index.html">index</A> to pick another example.