Waste 1.3 extra's modified for waste 2.0 (and missing from MW's distribution of 2.0).
diff --git a/Mac/Wastemods/WEObjectHandlers.c b/Mac/Wastemods/WEObjectHandlers.c
new file mode 100644
index 0000000..f1dd5af
--- /dev/null
+++ b/Mac/Wastemods/WEObjectHandlers.c
@@ -0,0 +1,111 @@
+/*
+	WASTE Demo Project:
+	Sample WASTE Object Handlers
+
+	Copyright © 1993-1998 Marco Piovanelli
+	All Rights Reserved
+*/
+
+#include "WEObjectHandlers.h"
+
+#ifndef __ICONS__
+#include <Icons.h>
+#endif
+
+#ifndef __SOUND__
+#include <Sound.h>
+#endif
+
+/* PICTURES */
+
+pascal OSErr HandleNewPicture(Point *defaultObjectSize, WEObjectReference objectRef)
+{
+	PicHandle thePicture;
+	Rect frame;
+
+	/* get handle to object data (in this case, a picture handle) */
+	thePicture = (PicHandle) WEGetObjectDataHandle(objectRef);
+
+	/* figure out the default object size by looking at the picFrame record */
+	frame = (*thePicture)->picFrame;
+	OffsetRect(&frame, -frame.left, -frame.top);
+	defaultObjectSize->v = frame.bottom;
+	defaultObjectSize->h = frame.right;
+
+	return noErr;
+}
+
+pascal OSErr HandleDisposePicture(WEObjectReference objectRef)
+{
+	PicHandle thePicture;
+
+	/* get handle to object data (in this case, a picture handle) */
+	thePicture = (PicHandle) WEGetObjectDataHandle(objectRef);
+
+	/* kill the picture */
+	KillPicture(thePicture);
+
+	return MemError();
+}
+
+pascal OSErr HandleDrawPicture(const Rect *destRect, WEObjectReference objectRef)
+{
+	PicHandle thePicture;
+
+	/* get handle to object data (in this case, a picture handle) */
+	thePicture = (PicHandle) WEGetObjectDataHandle(objectRef);
+
+	/* draw the picture */
+	DrawPicture(thePicture, destRect);
+
+	return noErr;
+}
+
+
+/* SOUND */
+
+pascal OSErr HandleNewSound(Point *defaultObjectSize, WEObjectReference objectRef)
+{
+#pragma unused(objectRef)
+
+	/* sounds are drawn as standard 32x32 icons */
+	defaultObjectSize->v = 32;
+	defaultObjectSize->h = 32;
+
+	return noErr;
+}
+
+pascal OSErr HandleDrawSound(const Rect *destRect, WEObjectReference objectRef)
+{
+#pragma unused(objectRef)
+
+	/* draw the sound icon */
+	return PlotIconID(destRect, kAlignNone, kTransformNone, kSoundIconID);
+}
+
+pascal Boolean HandleClickSound(Point hitPt, EventModifiers modifiers,
+					UInt32 clickTime, WEObjectReference objectRef)
+{
+#pragma unused(hitPt, clickTime)
+
+	SndListHandle theSound;
+
+	/* WASTE sets the low bit of modifiers on double (multiple) clicks */
+	if (modifiers & 0x0001)
+	{
+
+		/* get a handle to the object data (in this case, a sound handle) */
+		theSound = (SndListHandle) WEGetObjectDataHandle(objectRef);
+
+		/* play the sound */
+		SndPlay(nil, theSound, false);
+
+		/* return TRUE so WASTE knows we handled the click */
+		return true;
+	}
+	else
+	{
+		/* not a double click: let WASTE handle the mouse-down */
+		return false;
+	}
+}
diff --git a/Mac/Wastemods/WEObjectHandlers.h b/Mac/Wastemods/WEObjectHandlers.h
new file mode 100644
index 0000000..d73a490
--- /dev/null
+++ b/Mac/Wastemods/WEObjectHandlers.h
@@ -0,0 +1,29 @@
+/*
+	WASTE Demo Project:
+	Sample WASTE Object Handlers
+
+	Copyright © 1993-1998 Marco Piovanelli
+	All Rights Reserved
+*/
+
+#ifndef _WASTE_
+#include "WASTE.h"
+#endif
+
+
+// PICTURES
+
+pascal OSErr HandleNewPicture(Point *defaultObjectSize, WEObjectReference objectRef);
+pascal OSErr HandleDisposePicture(WEObjectReference objectRef);
+pascal OSErr HandleDrawPicture(const Rect *destRect, WEObjectReference objectRef);
+
+// SOUNDS
+
+enum {
+	kSoundIconID	=	550
+};
+
+pascal OSErr HandleNewSound(Point *defaultObjectSize, WEObjectReference objectRef);
+pascal OSErr HandleDrawSound(const Rect *destRect, WEObjectReference objectRef);
+pascal Boolean HandleClickSound(Point hitPt, EventModifiers modifiers,
+					UInt32 clickTime, WEObjectReference objectRef);
diff --git a/Mac/Wastemods/WETabHooks.c b/Mac/Wastemods/WETabHooks.c
new file mode 100644
index 0000000..9595daf
--- /dev/null
+++ b/Mac/Wastemods/WETabHooks.c
@@ -0,0 +1,281 @@
+/*
+ *	WETabHooks.c
+ *
+ *	WASTE TABS PACKAGE
+ *	Hooks for adding tab support to WASTE
+ *
+ *	Written by:
+ *		Mark Alldritt (original code)
+ *		Dan Crevier (line breaks)
+ *		John Daub (maintenance)
+ *		Jonathan Kew (variable-width tabs)
+ *		Marco Piovanelli (?)
+ *		Bert Seltzer (horizontal scrolling)
+ *
+ */
+
+#include "WETabs.h"
+#include "WETabHooks.h"
+
+#define FIXROUND(f)			((SInt16) (((f) + 0x00008000) >> 16))
+#define BSL(A, B)			(((SInt32) (A)) << (B))
+
+static const Point kOneToOneScaling = { 1, 1 } ;
+
+pascal void _WETabDrawText
+	(
+		const char * pText,
+		SInt32 textLength,
+		Fixed slop,
+		JustStyleCode styleRunPosition,
+		WEReference we
+	)
+{
+#pragma unused ( slop, styleRunPosition )
+
+	LongRect destRect;
+	SInt32 beginChar = 0;
+	SInt32 ii;
+	SInt16 tabWidth;
+	SInt16 destLeft;
+	Point penPos;
+	SInt16 tabSize = WEGetTabSize(we);
+
+	WEGetDestRect(&destRect, we);
+	destLeft = (SInt16) destRect.left;
+
+	for ( ii = 0; ii < textLength; ii++ )
+	{
+		if (pText[ii] == '\t')
+		{
+			DrawText(pText, beginChar, ii - beginChar);
+
+			/* advance the pen to the next tab stop */
+			GetPen(&penPos);
+			tabWidth = tabSize - (penPos.h - destLeft) % tabSize;
+			MoveTo(penPos.h + tabWidth, penPos.v);
+			beginChar = ii + 1;
+		}
+	}	/* for */
+
+	DrawText(pText, beginChar, textLength - beginChar);
+}
+
+pascal SInt32 _WETabPixelToChar
+	(
+		const char * pText,
+		SInt32 textLength,
+		Fixed slop,
+		Fixed *width,
+		WEEdge *edge,
+		JustStyleCode styleRunPosition,
+		Fixed hPos,
+		WEReference we
+	)
+{
+	SInt32 beginChar = 0;
+	SInt32 offset = 0;
+	SInt32 ii;
+	Fixed lastWidth;
+	Fixed tabWidth;
+	SInt16 tabSize = WEGetTabSize(we);
+
+	/* loop through every character in the segment looking for tabs */
+	for ( ii = 0; ii < textLength; ii++ )
+	{
+		/* exit now if width has gone negative */
+		/* (i.e., if we have found which glyph was hit) */
+		if (*width <= 0)
+		{
+			break;
+		}
+
+		/* tab found? */
+		if (pText[ii] == '\t')
+		{
+			/* calculate the width of the sub-segment preceding the tab */
+			lastWidth = *width;
+			offset += PixelToChar((char *)pText + beginChar, ii - beginChar, slop,
+					lastWidth, (Boolean *) edge, width, styleRunPosition,
+					kOneToOneScaling, kOneToOneScaling);
+			beginChar = ii + 1;
+
+			/* hit point past sub-segment? */
+			if (*width >= 0)
+			{
+				/* increment hPos by width of sub-segment preceding the tab */
+				hPos += (lastWidth - *width);
+
+				/* calculate the width of the tab "glyph" (as a Fixed value) */
+				tabWidth = BSL(tabSize - FIXROUND(hPos) % tabSize, 16);
+
+				/* increment hPos by width of tab character */
+				hPos += tabWidth;
+
+				/* hit point within tab glyph? */
+				if (*width < tabWidth)
+				{
+					/* yes: determine which half of tab glyph was hit */
+					if (*width > (tabWidth >> 1))
+					{
+						*edge = kTrailingEdge;	/* second (trailing) edge of tab */
+						offset++;
+					}
+					else
+					{
+						*edge = kLeadingEdge;	/* first (leading) edge of tab */
+					}
+
+					/* returning -1 (as Fixed) in width means we're finished */
+					*width = 0xFFFF0000;
+				}
+				else
+				{
+					/* hit point is past tab: keep looping */
+					offset++;
+					*width -= tabWidth;
+				}
+			} /* if (*width >= 0) */
+		} /* if tab found */
+	} /* for */
+
+	/* no more tabs in this segment: process the last sub-segment */
+	if (*width >= 0)
+	{
+		lastWidth = *width;
+		offset += PixelToChar((char *)pText + beginChar, textLength - beginChar, slop,
+					lastWidth, (Boolean *) edge, width, styleRunPosition,
+					kOneToOneScaling, kOneToOneScaling);
+	}
+
+	/* round width to nearest integer value */
+	/* this is supposed to fix an incompatibility with the WorldScript Power Adapter */
+	*width = (*width + 0x00008000) & 0xFFFF0000;
+
+	return offset;
+}
+
+pascal SInt16 _WETabCharToPixel
+	(
+		const char * pText,
+		SInt32 textLength,
+		Fixed slop,
+		SInt32 offset,
+		SInt16 direction,
+		JustStyleCode styleRunPosition,
+		SInt16 hPos,
+		WEReference we
+	)
+{
+	LongRect destRect;
+	SInt32 beginChar = 0;
+	SInt32 ii;
+	SInt16 width;
+	SInt16 destLeft;
+	SInt16 totalWidth = 0;
+	SInt16 tabSize = WEGetTabSize(we);
+
+	WEGetDestRect(&destRect, we);
+	destLeft = (SInt16) destRect.left;
+
+	/* measure text up to offset, if offset is within this segment,
+		otherwise to textLength */
+	if (offset > textLength)
+	{
+		offset = textLength;
+	}
+
+	for ( ii = 0; ii < offset; ii++ )
+	{
+		if (pText[ii] == '\t')
+		{
+			/* calculate the pixel width of the subsegment preceding the tab */
+			width = TextWidth(pText, beginChar, ii - beginChar);
+			totalWidth += width;
+			hPos += width;
+
+			/* calculate tab width */
+			width = tabSize - (hPos - destLeft) % tabSize;
+			totalWidth += width;
+			hPos += width;
+
+			/* go to next subsegment */
+			beginChar = ii + 1;
+		}
+	} /* for */
+
+	/* calculate width of remaining characters */
+	width = CharToPixel((char *)pText + beginChar, textLength - beginChar, slop,
+						offset - beginChar, direction, styleRunPosition,
+						kOneToOneScaling, kOneToOneScaling);
+	totalWidth += width;
+
+	return totalWidth;
+}
+
+pascal StyledLineBreakCode _WETabLineBreak
+	(
+		const char * pText,
+		SInt32 textLength,
+		SInt32 textStart,
+		SInt32 textEnd,
+		Fixed *textWidth,
+		SInt32 *textOffset,
+		WEReference we
+	)
+{
+	LongRect destRect;
+	SInt32 beginChar = textStart;
+	SInt32 ii;
+	Fixed tabWidth;
+	SInt16 destWidth;
+	StyledLineBreakCode breakCode = smBreakOverflow;
+	SInt16 tabSize = WEGetTabSize(we);
+
+	WEGetDestRect(&destRect, we);
+	destWidth = (SInt16) (destRect.right - destRect.left);
+
+	for ( ii = textStart; ii < textEnd; ii++ )
+	{
+		if (pText[ii] == 0x0D)
+		{
+			/* found a <return>, so stop looking ahead for tabs */
+			ii++;
+			break;
+		}
+		if (pText[ii] == '\t')
+		{
+			/* do previous "segment" */
+			breakCode = StyledLineBreak((char *)pText, textLength, beginChar, ii, 0, textWidth, textOffset);
+			if ((breakCode != smBreakOverflow) || (ii >= textLength))
+			{
+				break;
+			}
+			beginChar = ii + 1;
+
+			/* calculate tab width (as a Fixed value) */
+			tabWidth = BSL(tabSize - (destWidth - FIXROUND(*textWidth)) % tabSize, 16);
+
+			/* if tabWidth > pixelWidth we break in tab */
+			/* don't move tab to next line */
+			if (tabWidth > *textWidth)
+			{
+				breakCode = smBreakWord;
+				*textOffset = ii + 1;
+				break;
+			}
+			else
+			{
+				*textWidth -= tabWidth;
+			}
+		}
+	} /* for */
+
+	/* do last sub-segment */
+	if ((ii - beginChar >= 0) && (breakCode == smBreakOverflow))
+	{
+		breakCode = StyledLineBreak((char *)pText, textLength, beginChar, ii, 0, textWidth, textOffset);
+	}
+
+	return breakCode;
+}
diff --git a/Mac/Wastemods/WETabHooks.h b/Mac/Wastemods/WETabHooks.h
new file mode 100644
index 0000000..6405426
--- /dev/null
+++ b/Mac/Wastemods/WETabHooks.h
@@ -0,0 +1,32 @@
+/*
+ *	WETabHooks.h
+ *
+ *	WASTE TABS PACKAGE
+ *	Private (internal) interface
+ *
+ *	Copyright (c) 1993-1998 Marco Piovanelli
+ *	All Rights Reserved
+ *
+ */
+
+
+#ifndef _WASTE_
+#include "WASTE.h"
+#endif
+
+enum {
+	kTabSizeTag			=	'tbsz'
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+pascal void _WETabDrawText(const char *, SInt32, Fixed, JustStyleCode, WEReference);
+pascal SInt32 _WETabPixelToChar(const char *, SInt32, Fixed, Fixed *, WEEdge *, JustStyleCode, Fixed, WEReference);
+pascal SInt16 _WETabCharToPixel(const char *, SInt32, Fixed, SInt32, SInt16, JustStyleCode, SInt16, WEReference);
+pascal StyledLineBreakCode _WETabLineBreak(const char *, SInt32, SInt32, SInt32, Fixed *, SInt32 *, WEReference);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Mac/Wastemods/WETabs.c b/Mac/Wastemods/WETabs.c
new file mode 100644
index 0000000..6f59e37
--- /dev/null
+++ b/Mac/Wastemods/WETabs.c
@@ -0,0 +1,116 @@
+/*
+ *	WETabs.c
+ *
+ *	WASTE TABS PACKAGE
+ *	Routines for installing/removing tab hooks; accessors
+ *
+ */
+
+
+#include "WETabs.h"
+#include "WETabHooks.h"
+
+#ifndef __ERRORS__
+#include <Errors.h>
+#endif
+
+/* static UPP's */
+static WEDrawTextUPP		_weTabDrawTextProc = nil;
+static WEPixelToCharUPP		_weTabPixelToCharProc = nil;
+static WECharToPixelUPP		_weTabCharToPixelProc = nil;
+static WELineBreakUPP		_weTabLineBreakProc = nil;
+
+pascal OSErr WEInstallTabHooks(WEReference we)
+{
+	OSErr err;
+
+	/* if first time, create routine descriptors */
+	if (_weTabDrawTextProc == nil)
+	{
+		_weTabDrawTextProc = NewWEDrawTextProc(_WETabDrawText);
+		_weTabPixelToCharProc = NewWEPixelToCharProc(_WETabPixelToChar);
+		_weTabCharToPixelProc = NewWECharToPixelProc(_WETabCharToPixel);
+		_weTabLineBreakProc = NewWELineBreakProc(_WETabLineBreak);
+	}
+
+	if ((err = WESetInfo( weDrawTextHook, &_weTabDrawTextProc, we )) != noErr)
+	{
+		goto cleanup;
+	}
+	if ((err = WESetInfo( wePixelToCharHook, &_weTabPixelToCharProc, we )) != noErr)
+	{
+		goto cleanup;
+	}
+	if ((err = WESetInfo( weCharToPixelHook, &_weTabCharToPixelProc, we )) != noErr)
+	{
+		goto cleanup;
+	}
+	if ((err = WESetInfo( weLineBreakHook, &_weTabLineBreakProc, we )) != noErr)
+	{
+		goto cleanup;
+	}
+
+cleanup:
+	return err;
+}
+
+pascal OSErr WERemoveTabHooks(WEReference we)
+{
+	UniversalProcPtr nullHook = nil;
+	OSErr err;
+
+	if ((err = WESetInfo( weDrawTextHook, &nullHook, we )) != noErr)
+	{
+		goto cleanup;
+	}
+	if ((err = WESetInfo( wePixelToCharHook, &nullHook, we )) != noErr)
+	{
+		goto cleanup;
+	}
+	if ((err = WESetInfo( weCharToPixelHook, &nullHook, we )) != noErr)
+	{
+		goto cleanup;
+	}
+	if ((err = WESetInfo( weLineBreakHook, &nullHook, we )) != noErr)
+	{
+		goto cleanup;
+	}
+
+cleanup:
+	return err;
+}
+
+pascal Boolean WEIsTabHooks(WEReference we)
+{
+	WEPixelToCharUPP hook = nil;
+
+	/* return true if our tab hooks are installed */
+
+	return 	( _weTabPixelToCharProc != nil ) &&
+			( WEGetInfo( wePixelToCharHook, &hook, we ) == noErr) &&
+			( _weTabPixelToCharProc == hook );
+}
+
+pascal SInt16 WEGetTabSize(WEReference we)
+{
+	SInt32 result;
+
+	if (WEGetUserInfo( kTabSizeTag, &result, we ) != noErr)
+	{
+		result = kDefaultTabSize;
+	}
+	return result;
+}
+
+pascal OSErr WESetTabSize(SInt16 tabSize, WEReference we)
+{
+	//	make sure tabSize is a reasonable size
+	if ((tabSize < kMinTabSize) || (tabSize > kMaxTabSize))
+	{
+		return paramErr;
+	}
+	else
+	{
+		return WESetUserInfo( kTabSizeTag, tabSize, we );
+	}
+}
diff --git a/Mac/Wastemods/WETabs.h b/Mac/Wastemods/WETabs.h
new file mode 100644
index 0000000..4a91d7c
--- /dev/null
+++ b/Mac/Wastemods/WETabs.h
@@ -0,0 +1,37 @@
+/*
+ *	WETabs.h
+ *
+ *	WASTE TABS PACKAGE
+ *	Public C/C++ interface
+ *
+ *	version 1.3.2 (August 1996)
+ *
+ *	Copyright (c) 1993-1998 Marco Piovanelli
+ *	All Rights Reserved
+ *
+ */
+
+
+#ifndef _WASTE_
+#include "WASTE.h"
+#endif
+
+enum {
+	kMinTabSize				=	1,		//	must be greater than zero
+	kDefaultTabSize			=	32,
+	kMaxTabSize				=	1024	//	arbitrary value
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+pascal OSErr WEInstallTabHooks(WEReference we);
+pascal OSErr WERemoveTabHooks(WEReference we);
+pascal Boolean WEIsTabHooks(WEReference we);
+pascal SInt16 WEGetTabSize(WEReference we);
+pascal OSErr WESetTabSize(SInt16 tabWidth, WEReference we);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Mac/Wastemods/readme.txt b/Mac/Wastemods/readme.txt
new file mode 100644
index 0000000..7f7c16e
--- /dev/null
+++ b/Mac/Wastemods/readme.txt
@@ -0,0 +1,11 @@
+These files were in the Waste 1.3 distribution, but they are missing from the
+Waste 2.0 distribution. At least: from the 2.0 distribution as included with
+MetroWerks CodeWarrior. As the Python Waste module needs them I have included them
+here. There were a few minor changes (in function signatures) to accomodate
+slight changes in the Waste 2.0 headers.
+
+All the copyright notices in the files and in Waste 1.3 seem to indicate that it
+is fine to redistribute these files. If I am mistaken in this please let me know
+and I will rectify the situation immedeately.
+
+Jack Jansen, jack@cwi.nl, 31-Jan-01.