pfuentes69
/FractalViewer
/amendments
/1
First commit
pfp made amendment 1 over 2 years ago
--- FractalViewer.cp Sun Oct 31 18:00:22 2021
+++ FractalViewer.cp Sun Oct 31 18:00:22 2021
@@ -0,0 +1,158 @@
+/*****
+ * FractalViewer.c
+ *
+ * Simple object-oriented application to draw 2D CGI,
+ * mostly fractals, using QuickDraw
+ *
+ *****/
+
+/* MacHeaders Included */
+
+#include <oops.h>
+#include "FractalViewerMenus.h"
+#include "TFractalViewerWindow.h"
+
+
+/****
+ * InitMacintosh()
+ *
+ * Initialize all the managers & memory
+ *
+ ****/
+
+static void InitMacintosh(void)
+
+{
+ MaxApplZone();
+
+ InitGraf(&thePort);
+ InitFonts();
+ FlushEvents(everyEvent, 0);
+ InitWindows();
+ InitMenus();
+ TEInit();
+ InitDialogs(0L);
+ InitCursor();
+}
+/* end InitMacintosh */
+
+
+/****
+ * HandleMouseDown (theEvent)
+ *
+ * Take care of mouseDown events.
+ *
+ ****/
+
+static void HandleMouseDown(EventRecord *theEvent)
+{
+ WindowPeek wp;
+ short windowPart = FindWindow (theEvent->where, (WindowPtr*) &wp);
+
+ switch (windowPart)
+ {
+ case inSysWindow:
+ SystemClick (theEvent, (WindowPtr) wp);
+ break;
+
+ case inMenuBar:
+ HandleMenu(MenuSelect(theEvent->where));
+ break;
+
+ case inDrag:
+ if (wp->windowKind == TWINDOWKIND)
+ OBJ(wp)->Drag(theEvent->where);
+ break;
+
+ case inContent:
+ if (wp->windowKind == TWINDOWKIND) {
+ if (wp != (WindowPeek) FrontWindow())
+ OBJ(wp)->Select();
+ else
+ OBJ(wp)->Hit(theEvent->where);
+ }
+ break;
+
+ case inGoAway:
+ if (wp->windowKind == TWINDOWKIND)
+ OBJ(wp)->TrackClose(theEvent->where);
+ break;
+
+ case inGrow:
+ if (wp->windowKind == TWINDOWKIND)
+ OBJ(wp)->Grow(theEvent->where);
+ break;
+
+ case inZoomIn:
+ case inZoomOut:
+ if (wp->windowKind == TWINDOWKIND)
+ OBJ(wp)->TrackZoom(theEvent->where, windowPart);
+ }
+}
+/* end HandleMouseDown */
+
+
+/****
+ * HandleEvent()
+ *
+ * The main event dispatcher. This routine should be called
+ * repeatedly (it handles only one event).
+ *
+ *****/
+
+static void HandleEvent(void)
+{
+ short ok;
+ EventRecord theEvent;
+
+ HiliteMenu(0);
+ SystemTask (); /* Handle desk accessories */
+ AdjustMenus();
+
+ ok = GetNextEvent (everyEvent, &theEvent);
+ if (ok)
+ {
+ switch (theEvent.what)
+ {
+ case mouseDown:
+ HandleMouseDown(&theEvent);
+ break;
+
+ case keyDown:
+ case autoKey:
+ if ((theEvent.modifiers & cmdKey) != 0)
+ HandleMenu(MenuKey((char) (theEvent.message & charCodeMask)));
+ break;
+
+ case updateEvt:
+ if (((WindowPeek) theEvent.message)->windowKind == TWINDOWKIND)
+ OBJ(theEvent.message)->Update();
+ break;
+
+ case activateEvt:
+ if (((WindowPeek) theEvent.message)->windowKind == TWINDOWKIND)
+ OBJ(theEvent.message)->Activate(theEvent.modifiers & 0x01);
+ break;
+ }
+ }
+}
+/* end HandleEvent */
+
+
+/*****
+ * main()
+ *
+ * This is where everything happens
+ *
+ *****/
+
+
+void main(void)
+{
+ InitMacintosh();
+ SetUpMenus();
+
+ for (;;)
+ HandleEvent();
+}
+/* end main */
--- FractalViewerMenus.cp Sun Oct 31 18:04:19 2021
+++ FractalViewerMenus.cp Sun Oct 31 18:04:19 2021
@@ -0,0 +1,296 @@
+/*****
+ * FractalViewerMenus.cp
+ *
+ * Menu handling routines for the program
+ *
+ *****/
+
+#include <oops.h>
+#include "FractalViewerMenus.h"
+#include "FractalViewerPrefs.h"
+#include "TFractalViewerWindow.h"
+#include "TMandelbrot.h"
+#include "TJulia.h"
+#include "TPlasma.h"
+
+
+ // prototypes for utility routines
+static void enable (MenuHandle menu, short item, Boolean enableMenu);
+static findColorItem (long color);
+
+MenuHandle appleMenu,
+ fileMenu,
+ editMenu,
+ styleMenu,
+ viewMenu;
+
+enum { // Menu ids
+ appleID = 1,
+ fileID,
+ editID,
+ styleID,
+ viewID
+};
+
+enum { // items in the File menu
+ mandelItem = 1,
+ juliaItem,
+ plasmaItem,
+ closeItem,
+ prefsItem = closeItem+2, // leave space for the dashed line before Preferences
+ quitItem = prefsItem+2 // leave space for the dashed line before Quit
+};
+
+
+enum { // items in the File menu
+ restoreItem = 1,
+ zoomInItem,
+ zoomOutItem,
+ separatorItem,
+ FastModeItem,
+ NormalModeItem,
+ FineModeItem
+};
+
+
+
+/****
+ * SetUpMenus()
+ *
+ * Set up the menus.
+ *
+ ****/
+
+void SetUpMenus(void)
+
+{
+ InsertMenu(appleMenu = GetMenu(appleID), 0);
+ AddResMenu(appleMenu, 'DRVR');
+
+ InsertMenu(fileMenu = GetMenu(fileID), 0);
+ InsertMenu(editMenu = GetMenu(editID), 0);
+ InsertMenu(styleMenu = GetMenu(styleID), 0);
+ InsertMenu(viewMenu = GetMenu(viewID), 0);
+
+ DrawMenuBar();
+}
+/* end SetUpMenus */
+
+
+/****
+ * AdjustMenus()
+ *
+ * Enable or disable the items in the Edit menu if a DA window
+ * comes up or goes away. Our application doesn't do anything with
+ * the Edit menu. If one of our windows is frontmost, adjust the
+ * Width and color menus to reflect the proper values for the
+ * windows.
+ *
+ ****/
+
+#define isEnabled(mH) ((**mH).enableFlags & 0x01)
+
+void AdjustMenus(void)
+{
+ register WindowPeek wp = (WindowPeek) FrontWindow();
+ short kind = wp ? wp->windowKind : 0;
+ short i;
+ short max;
+ static short redrawForEdit = true; // did the Edit menu change?
+ static short redrawForWidth = true; // did the Width menu change?
+
+ if (kind < 0) { // enable Edit for desk accessories
+ redrawForEdit = !isEnabled(editMenu);
+ enable(editMenu, 0, true);
+ }
+ else { // disable it for all others
+ redrawForEdit = isEnabled(editMenu);
+ enable(editMenu, 0, false);
+ }
+
+ // enable the Close command for DAs and our windows
+ enable(fileMenu, closeItem, kind < 0 || kind == TWINDOWKIND);
+
+ // disable the Width and color menus if our window isn't frontmost
+ if (kind != TWINDOWKIND) {
+ redrawForWidth = isEnabled(styleMenu);
+ enable(styleMenu, 0, false);
+ enable(viewMenu, 0, false);
+ }
+ else {
+ redrawForWidth = !isEnabled(styleMenu);
+ enable(styleMenu, 0, true);
+ enable(viewMenu, 0, true);
+
+ max = CountMItems(styleMenu); // uncheck all the widths
+ for (i = 1; i <= max; i++)
+ CheckItem(styleMenu, i, false);
+
+ max = CountMItems(viewMenu); // uncheck all the colors
+ for (i = 1; i <= max; i++) {
+ CheckItem(viewMenu, i, false);
+ }
+
+ // check the style for the frontmost window
+ CheckItem(styleMenu, OBJ(wp)->GetStyle(), true);
+ // check the drawMode for the frontmost window
+ CheckItem(viewMenu, separatorItem + OBJ(wp)->GetDrawMode(), true);
+ }
+
+ if (redrawForEdit || redrawForWidth) {
+ DrawMenuBar();
+ redrawForEdit = redrawForWidth = false;
+ }
+}
+
+/**
+ * enable or disable a menu
+ *
+ **/
+
+static void enable (MenuHandle menu, short item, Boolean enableMenu)
+{
+ if (enableMenu)
+ EnableItem(menu, item);
+ else
+ DisableItem(menu, item);
+}
+
+/**
+ * given an old QuickDraw color, find its menu item number
+ *
+ **/
+
+/*
+static findColorItem (long color)
+{
+ short i;
+ short max = sizeof(colorTable) / sizeof(long);
+
+ for (i= 1; i <= max; i++)
+ if (colorTable[i] == color)
+ return i;
+ else return 0;
+ DebugStr("\pBAD COLOR!");
+}
+*/
+
+
+
+/*****
+ * HandleMenu(mSelect)
+ *
+ * Handle the menu selection. mSelect is what MenuSelect() and
+ * MenuKey() return: the high word is the menu ID, the low word
+ * is the menu item
+ *
+ *****/
+
+void HandleMenu (long mSelect)
+{
+ short menuID = HiWord(mSelect);
+ short menuItem = LoWord(mSelect);
+ Str255 name;
+ GrafPtr savePort;
+ TFractalViewerWindow *fractalWindow;
+ WindowPeek wp;
+
+ switch (menuID)
+ {
+ case appleID:
+ if (menuItem == 1)
+ {
+ Alert(128, 0L);
+ break;
+ }
+
+ GetPort(&savePort);
+ GetItem(appleMenu, menuItem, name);
+ OpenDeskAcc(name);
+ SetPort(savePort);
+ break;
+
+ case fileID:
+ switch (menuItem)
+ {
+ case mandelItem:
+ fractalWindow = new(TMandelbrot);
+ break;
+
+ case juliaItem:
+ fractalWindow = new(TJulia);
+ break;
+
+ case plasmaItem:
+ fractalWindow = new(TPlasma);
+ break;
+
+ case closeItem:
+ if ((wp = (WindowPeek) FrontWindow()) == NULL)
+ break;
+
+ if (wp->windowKind < 0)
+ CloseDeskAcc(wp->windowKind);
+ else if (wp->windowKind == TWINDOWKIND)
+ OBJ(wp)->Close();
+ break;
+
+ case prefsItem:
+ HandlePrefs();
+ break;
+
+ case quitItem:
+ ExitToShell();
+ break;
+ }
+ break;
+
+ case editID:
+ if (!SystemEdit(menuItem-1))
+ SysBeep(5);
+ break;
+
+ case styleID:
+ if ((wp = (WindowPeek) FrontWindow()) == 0L ||
+ wp->windowKind != TWINDOWKIND)
+ break;
+
+ OBJ(wp)->SetStyle(menuItem);
+ break;
+
+ case viewID:
+ if ((wp = (WindowPeek) FrontWindow()) == 0L ||
+ wp->windowKind != TWINDOWKIND)
+ break;
+
+ switch (menuItem) {
+ case restoreItem:
+ OBJ(wp)->ZoomContent(0);
+ break;
+
+ case zoomInItem:
+ OBJ(wp)->ZoomContent(+1);
+ break;
+
+ case zoomOutItem:
+ OBJ(wp)->ZoomContent(-1);
+ break;
+
+ case FastModeItem:
+ OBJ(wp)->SetDrawMode(1);
+ break;
+
+ case NormalModeItem:
+ OBJ(wp)->SetDrawMode(2);
+ break;
+
+ case FineModeItem:
+ OBJ(wp)->SetDrawMode(3);
+ break;
+
+ }
+ break;
+ }
+}
+/* end HandleMenu */
+
--- FractalViewerMenus.h Sun Oct 31 18:02:11 2021
+++ FractalViewerMenus.h Sun Oct 31 18:02:11 2021
@@ -0,0 +1,14 @@
+/*****
+ * objBullMenus.h
+ *
+ * Public interfaces for FractalViewerMenus.cp
+ *
+ *****/
+
+#pragma once // include this header
+ // only once per source file
+
+
+void HandleMenu (long mSelect);
+void AdjustMenus(void);
+void SetUpMenus(void);
--- FractalViewerPrefs.cp Wed Oct 20 22:22:50 2021
+++ FractalViewerPrefs.cp Wed Oct 20 22:22:50 2021
@@ -0,0 +1,52 @@
+#include "FractalViewerPrefs.h"
+
+enum { // Preferences Dialog Items
+ iPrefsOK = 1,
+ iPrefsCancel,
+ iPrefsBW,
+ iPrefsJuliaX = iPrefsBW + 3,
+ iPrefsJuliaY = iPrefsJuliaX + 2
+};
+
+FractalViewerPrefs GlobalPrefs;
+
+/*****
+ * HandlePrefs(void)
+ *
+ * Handle the preferences dialog
+ *
+ *****/
+
+void HandlePrefs(void)
+{
+ Boolean dlgDone = false;
+ short itemHit, itemType;
+ Handle itemHandle;
+ Rect itemRect;
+
+ DialogPtr dlgPrefs = GetNewDialog(128, nil, (WindowPtr)-1L);
+ SetDialogDefaultItem(dlgPrefs, iPrefsOK);
+ SetDialogCancelItem(dlgPrefs, iPrefsCancel);
+ ShowWindow(dlgPrefs);
+
+ while (!dlgDone) {
+ ModalDialog(nil, &itemHit);
+
+ switch (itemHit) {
+ case iPrefsOK:
+ case iPrefsCancel:
+ dlgDone = true;
+ break;
+ case iPrefsBW:
+ GetDItem(dlgPrefs, itemHit, &itemType, &itemHandle, &itemRect);
+ SetCtlValue((ControlHandle)itemHandle, !GetCtlValue((ControlHandle)itemHandle));
+ break;
+ default:
+ SysBeep(5);
+ break;
+ }
+
+ }
+
+ DisposeDialog(dlgPrefs);
+}
--- FractalViewerPrefs.h Wed Oct 20 21:40:14 2021
+++ FractalViewerPrefs.h Wed Oct 20 21:40:14 2021
@@ -0,0 +1,18 @@
+/*****
+ * FractalViewerPrefs.h
+ *
+ * Public interfaces for FractalViewerPrefs.c
+ *
+ *****/
+
+#pragma once // include this header
+ // only once per source file
+
+
+struct FractalViewerPrefs {
+ Boolean BW;
+ double JuliaX;
+ double JuliaY;
+};
+
+void HandlePrefs(void);
--- TFractalViewerWindow.cp Sun Oct 31 18:06:04 2021
+++ TFractalViewerWindow.cp Sun Oct 31 18:06:04 2021
@@ -0,0 +1,169 @@
+/*****
+ * TFractalViewerWindow.c
+ *
+ * The window methods for the application.
+ *
+ * TFractalViewerWindow inherits its Draw method from TWindow.
+ * TMandelbrot, TJulia, and others override DrawShape to draw their own kind of CGI.
+ *
+ *****/
+
+#include <Packages.h> // for NumToString prototype
+#include "TFractalViewerWindow.h"
+#include <stdlib.h>
+#include "Utils.h"
+
+
+/****
+ * TFractalViewerWindow constructor
+ *
+ * Create a bullseye window. This constructor relies
+ * on the TWindow constructor to place the window in
+ * in attractive place. Then it appends a number to the
+ * window title.
+ *
+ ****/
+
+TFractalViewerWindow::TFractalViewerWindow(void)
+{
+ Str15 numStr;
+ Str255 title;
+ long windowNumber;
+
+
+ // Set the title of the window to be
+ // the title in the resource
+ // plus the window counter.
+ // The window counter is a class variable
+ // declared in the TWindow class.
+
+
+ GetWindowTitle(title);
+ windowNumber = GetWindowNumber();
+ NumToString(GetWindowNumber(), numStr);
+ concat(title, numStr);
+ SetWindowTitle(title);
+
+}
+
+
+/****
+ * Hit
+ *
+ * Handle a mouse down in the window.
+ * Bullseye window just force a refresh.
+ *
+ ****/
+
+void TFractalViewerWindow::Hit(Point where)
+{
+ RefreshWindow(false); // preserve the scroll bars
+}
+
+
+/****
+ * GetStyle
+ * SetStyle
+ *
+ * Get and set the color style
+ *
+ ****/
+
+short TFractalViewerWindow::GetStyle()
+{
+ return style;
+}
+
+
+void TFractalViewerWindow::SetStyle(short w)
+{
+ style = w;
+ RefreshWindow(true);
+}
+
+
+
+short TFractalViewerWindow::GetDrawMode()
+{
+ return drawMode;
+}
+
+
+void TFractalViewerWindow::SetDrawMode(short m)
+{
+ if (drawMode != m) {
+ drawMode = m;
+ RefreshWindow(true);
+ }
+}
+
+
+
+/****
+ * Draw
+ *
+ * Draw the bullseye figures.
+ * Repeatedly call DrawShape with a smaller drawing area.
+ * The drawing area gets smaller by 2 * the width.
+ *
+ ****/
+
+void TFractalViewerWindow::Draw(void)
+
+{
+ RgnHandle saveClip = NewRgn();
+ PenState pen;
+ Rect drawingRect;
+
+
+ GetPenState(&pen);
+ GetClip(saveClip);
+
+ inherited::Draw();
+
+ GetWindowRect(&drawingRect, false); // Don't draw in the scroll
+ // bar areas. Note that it's
+ // ok to pass the address of
+ // drawingRect because
+ // GetWindowRect won't move
+ // memory.
+
+ sTop = drawingRect.top;
+ sLeft = drawingRect.left;
+
+ DrawShape(&drawingRect);
+
+ SetClip(saveClip);
+ DisposeRgn(saveClip);
+ SetPenState(&pen);
+
+}
+
+
+/****
+ * DrawShape methods
+ *
+ * These are the DrawShape methods for
+ * TBullWindow: does nothing
+ * TCircleBull: Circles
+ * TSquareBull: Squares
+ * TPlasma: "Triangles"
+ *
+ * All the DrawShape methods take a drawingRect
+ * as a parameter. The pen width
+ * is already set to the appropriate width.
+ *
+ ****/
+
+void TFractalViewerWindow::DrawShape(Rect *drawingRect)
+{
+}
+
+//
+// ZOOM CONTENT
+//
+
+void TFractalViewerWindow::ZoomContent(short z)
+{
+ RefreshWindow(false); // preserve the scroll bars
+}
--- TFractalViewerWindow.h Tue Oct 12 16:16:42 2021
+++ TFractalViewerWindow.h Tue Oct 12 16:16:42 2021
@@ -0,0 +1,39 @@
+/*****
+ * TFractalViewerWindow.h
+ *
+ * Object definitions for window to draw a fractal in.
+ *
+ *****/
+
+#pragma once // include this header
+ // only once per source file
+
+#include "TWindow.h"
+
+class TFractalViewerWindow : public TWindow {
+protected:
+ short style;
+ short drawMode;
+ short sWidth, sHeigth, sLeft, sTop;
+public:
+ TFractalViewerWindow(void); // constructor
+
+ virtual void Hit(Point where);
+ virtual void Draw(void);
+ virtual void DrawShape(Rect *drawingRect);
+ virtual void SetStyle(short s);
+ virtual short GetStyle();
+ virtual void SetDrawMode(short m);
+ virtual short GetDrawMode();
+ virtual void ZoomContent(short z);
+
+};
+
+
+
+ // This macro gets the object that stored in
+ // the refCon of the window and casts is so we
+ // can send messages to it
+
+#define OBJ(win) ((TFractalViewerWindow *)(((WindowPeek) win)->refCon))
+
--- TJulia.cp Sun Oct 31 18:06:43 2021
+++ TJulia.cp Sun Oct 31 18:06:43 2021
@@ -0,0 +1,227 @@
+/*****
+ * TJulia.cp
+ *
+ * TJulia draws a Julia set
+ *
+ *****/
+
+#include <Packages.h> // for NumToString prototype
+#include "TFractalViewerWindow.h"
+#include "TJulia.h"
+#include <stdlib.h>
+
+
+/****
+ * TFractalViewerWindow constructor
+ *
+ * Create a bullseye window. This constructor relies
+ * on the TWindow constructor to place the window in
+ * in attractive place. Then it appends a number to the
+ * window title.
+ *
+ ****/
+
+
+TJulia::TJulia(void)
+{
+ // Set the width, and show the window.
+ PrepareStyles();
+ SetStyle(1);
+ SetDrawMode(2);
+ // Set the default plane
+ DefaultPlane();
+
+ Show();
+}
+
+
+/****
+ * Hit
+ *
+ * Handle a mouse down in the window.
+ * Bullseye window just force a refresh.
+ *
+ ****/
+
+void TJulia::DefaultPlane()
+{
+ pWidth = 5;
+ pHeigth = 5;
+ pCX = 0.0;
+ pCY = 0.0;
+}
+
+
+void TJulia::Hit(Point where)
+{
+ Point mouse;
+ double sCX, sCY, tX, tY, hX, hY;
+ Rect drawingRect;
+
+ // Recalculate center
+ GlobalToLocal(&where);
+ hX = where.h; // - sLeft;
+ hY = where.v; // - sTop;
+
+ sCX = sWidth / 2.0;
+ sCY = sHeigth / 2.0;
+ tX = sCX - hX;
+ tY = hY - sCY;
+ pCX = pCX - pWidth * tX / (double)sWidth;
+ pCY = pCY - pHeigth * tY / (double)sHeigth;
+ RefreshWindow(false); // preserve the scroll bars
+}
+
+
+/****
+ * DrawShape methods
+ *
+ * These are the DrawShape methods for
+ * TBullWindow: does nothing
+ * TCircleBull: Circles
+ * TSquareBull: Squares
+ * TPlasma: "Triangles"
+ *
+ * All the DrawShape methods take a drawingRect
+ * as a parameter. The pen width
+ * is already set to the appropriate width.
+ *
+ ****/
+
+int TJulia::Julia(double real, double imag, short maxiterations) {
+ double zReal = real;
+ double zImag = imag;
+
+ for (int i = 0; i < maxiterations; ++i) {
+ double r2 = zReal * zReal;
+ double i2 = zImag * zImag;
+ if (r2 + i2 > 4.0)
+ return i;
+ zImag = 2.0 * zReal * zImag + 0.70882;
+ zReal = r2 - i2 - 0.28625;
+ }
+ return maxiterations;
+}
+
+
+void TJulia::DrawShape(Rect *drawingRect)
+{
+ RGBColor colPix;
+ short maxiterations;
+
+ switch (drawMode) {
+ case 1:
+ maxiterations = 20;
+ break;
+ case 2:
+ maxiterations = 100;
+ break;
+ case 3:
+ maxiterations = 200;
+ break;
+ }
+
+ short st = GetStyle() - 1;
+
+ sWidth = drawingRect->right - drawingRect->left + 1;
+ sHeigth = drawingRect->bottom - drawingRect->top + 1;
+
+ pHeigth = (double)sHeigth * pWidth / (double)sWidth;
+
+ double x_start = pCX - pWidth / 2.0;
+ double x_fin = x_start + pWidth;
+ double y_start = pCY - pHeigth / 2.0;
+ double y_fin = y_start + pHeigth;
+
+ double dx = (x_fin - x_start)/(sWidth - 1);
+ double dy = (y_fin - y_start)/(sHeigth - 1);
+
+ for (int i = 0; i < sHeigth; i++) {
+ for (int j = 0; j < sWidth; j++) {
+ double x = x_start + j*dx; // current real value
+ double y = y_fin - i*dy; // current imaginary value
+
+ int value = Julia(x, y, maxiterations);
+ if (value == maxiterations) {
+ colPix.red = 0;
+ colPix.green = 0;
+ colPix.blue = 0;
+ }
+ else {
+ value = 255 * value / maxiterations;
+ colPix = spec[st][value % 255];
+ }
+ SetCPixel(j, i, &colPix);
+ }
+ }
+
+}
+
+
+
+//
+// PREPARE STYLES METHODS
+//
+
+void TJulia::PrepareStyles()
+{
+ short ci;
+ // Style 1
+ for(ci=0; ci < 256; ci++) {
+ spec[0][ci].red = 65536 - ci * 256;
+ spec[0][ci].green = 65536 - ci * 256;
+ spec[0][ci].blue = 65536 - ci * 256;
+ }
+ // Style 2
+ for(ci=0; ci < 256; ci++) {
+ spec[1][ci].red = ci * 256;
+ spec[1][ci].green = ci * 256;
+ spec[1][ci].blue = ci * 256;
+ }
+ // Style 2
+ for(ci=0; ci < 256; ci++) {
+ spec[2][ci].red = 65535 - ci * 256;
+ spec[2][ci].green = 32768 + ci * 128;
+ spec[2][ci].blue = ci * 256;
+ }
+ // Style 2
+ for(ci=0; ci < 256; ci++) {
+ spec[3][ci].red = ci * 256;
+ spec[3][ci].green = 32768 + ci * 128;
+ spec[3][ci].blue = 65535 - ci * 256;
+ }
+ // Style 2
+ for(ci=0; ci < 256; ci++) {
+ spec[4][ci].red = 32768 - ci * 128;
+ spec[4][ci].green = ci * 256;
+ spec[4][ci].blue = 65535 - ci * 256;
+ }
+}
+
+
+//
+// ZOOM CONTENT
+//
+
+
+void TJulia::ZoomContent(short z)
+{
+ switch (z) {
+ case -1:
+ pWidth = pWidth * 1.333;
+ pHeigth = pHeigth * 1.333;
+ break;
+ case 1:
+ pWidth = pWidth * 0.666;
+ pHeigth = pHeigth * 0.666;
+ break;
+ break;
+ default:
+ DefaultPlane();
+ break;
+ }
+
+ RefreshWindow(false); // preserve the scroll bars
+}
+
+
--- TJulia.h Sun Oct 31 18:02:44 2021
+++ TJulia.h Sun Oct 31 18:02:44 2021
@@ -0,0 +1,28 @@
+/*****
+ * TJulia.h
+ *
+ * Object definitions for window to draw a Julia set in.
+ *
+ *****/
+
+#pragma once // include this header
+ // only once per source file
+
+#include "TFractalViewerWindow.h"
+
+
+class TJulia : public TFractalViewerWindow {
+protected:
+ virtual void DefaultPlane();
+ RGBColor spec[5][256];
+ int Julia(double real, double imag, short maxiterations);
+ virtual void PrepareStyles();
+ double pWidth, pHeigth;
+ double pXMin, pXMax, pYMin, pYMax;
+ double pCX, pCY;
+public:
+ TJulia(void);
+ virtual void Hit(Point where);
+ virtual void DrawShape(Rect *drawingRect);
+ virtual void ZoomContent(short z);
+};
--- TMandelbrot.cp Fri Aug 26 13:26:48 2022
+++ TMandelbrot.cp Fri Aug 26 13:26:48 2022
@@ -0,0 +1,227 @@
+/*****
+ * TMandelbrot.cp
+ *
+ * The window methods to draw a Mandelbrot set
+ *
+ *****/
+
+#include <Packages.h> // for NumToString prototype
+#include "TFractalViewerWindow.h"
+#include "TMandelbrot.h"
+#include <stdlib.h>
+
+
+/****
+ * TFractalViewerWindow constructor
+ *
+ * Create a bullseye window. This constructor relies
+ * on the TWindow constructor to place the window in
+ * in attractive place. Then it appends a number to the
+ * window title.
+ *
+ ****/
+
+
+TMandelbrot::TMandelbrot(void)
+{
+ // Set the width, and show the window.
+ PrepareStyles();
+ SetStyle(1);
+ SetDrawMode(2);
+ // Set the default plane
+ DefaultPlane();
+
+ Show();
+}
+
+
+/****
+ * Hit
+ *
+ * Handle a mouse down in the window.
+ * Bullseye window just force a refresh.
+ *
+ ****/
+
+void TMandelbrot::DefaultPlane()
+{
+ pWidth = 3.0;
+ pHeigth = 3.0;
+ pCX = -0.6;
+ pCY = 0.0;
+}
+
+
+void TMandelbrot::Hit(Point where)
+{
+ Point mouse;
+ double sCX, sCY, tX, tY, hX, hY;
+ Rect drawingRect;
+
+ // Recalculate center
+ GlobalToLocal(&where);
+ hX = where.h; // - sLeft;
+ hY = where.v; // - sTop;
+
+ sCX = sWidth / 2.0;
+ sCY = sHeigth / 2.0;
+ tX = sCX - hX;
+ tY = hY - sCY;
+ pCX = pCX - pWidth * tX / (double)sWidth;
+ pCY = pCY - pHeigth * tY / (double)sHeigth;
+ RefreshWindow(false); // preserve the scroll bars
+}
+
+
+/****
+ * DrawShape methods
+ *
+ * These are the DrawShape methods for
+ * TBullWindow: does nothing
+ * TCircleBull: Circles
+ * TSquareBull: Squares
+ * TPlasma: "Triangles"
+ *
+ * All the DrawShape methods take a drawingRect
+ * as a parameter. The pen width
+ * is already set to the appropriate width.
+ *
+ ****/
+
+int TMandelbrot::Mandelbrot(double real, double imag, short maxiterations) {
+ double zReal = real;
+ double zImag = imag;
+
+ for (int i = 0; i < maxiterations; ++i) {
+ double r2 = zReal * zReal;
+ double i2 = zImag * zImag;
+ if (r2 + i2 > 8.0)
+ return i;
+ zImag = 2.0 * zReal * zImag + imag;
+ zReal = r2 - i2 + real;
+ }
+ return maxiterations;
+}
+
+
+void TMandelbrot::DrawShape(Rect *drawingRect)
+{
+ RGBColor colPix;
+ short maxiterations;
+
+ switch (drawMode) {
+ case 1:
+ maxiterations = 20;
+ break;
+ case 2:
+ maxiterations = 100;
+ break;
+ case 3:
+ maxiterations = 200;
+ break;
+ }
+
+ short st = GetStyle() - 1;
+
+ sWidth = drawingRect->right - drawingRect->left + 1;
+ sHeigth = drawingRect->bottom - drawingRect->top + 1;
+
+ pHeigth = (double)sHeigth * pWidth / (double)sWidth;
+
+ double x_start = pCX - pWidth / 2.0;
+ double x_fin = x_start + pWidth;
+ double y_start = pCY - pHeigth / 2.0;
+ double y_fin = y_start + pHeigth;
+
+ double dx = (x_fin - x_start)/(sWidth - 1);
+ double dy = (y_fin - y_start)/(sHeigth - 1);
+
+ for (int i = 0; i < sHeigth; i++) {
+ for (int j = 0; j < sWidth; j++) {
+ double x = x_start + j*dx; // current real value
+ double y = y_fin - i*dy; // current imaginary value
+
+ int value = Mandelbrot(x, y, maxiterations);
+ if (value == maxiterations) {
+ colPix.red = 0;
+ colPix.green = 0;
+ colPix.blue = 0;
+ }
+ else {
+ value = 255 * value / maxiterations;
+ colPix = spec[st][value % 255];
+ }
+ SetCPixel(j, i, &colPix);
+ }
+ }
+
+}
+
+
+
+//
+// PREPARE STYLES METHODS
+//
+
+void TMandelbrot::PrepareStyles()
+{
+ short ci;
+ // Style 1
+ for(ci=0; ci < 256; ci++) {
+ spec[0][ci].red = 65536 - ci * 256;
+ spec[0][ci].green = 65536 - ci * 256;
+ spec[0][ci].blue = 65536 - ci * 256;
+ }
+ // Style 2
+ for(ci=0; ci < 256; ci++) {
+ spec[1][ci].red = ci * 256;
+ spec[1][ci].green = ci * 256;
+ spec[1][ci].blue = ci * 256;
+ }
+ // Style 2
+ for(ci=0; ci < 256; ci++) {
+ spec[2][ci].red = 65535 - ci * 256;
+ spec[2][ci].green = 32768 + ci * 128;
+ spec[2][ci].blue = ci * 256;
+ }
+ // Style 2
+ for(ci=0; ci < 256; ci++) {
+ spec[3][ci].red = ci * 256;
+ spec[3][ci].green = 32768 + ci * 128;
+ spec[3][ci].blue = 65535 - ci * 256;
+ }
+ // Style 2
+ for(ci=0; ci < 256; ci++) {
+ spec[4][ci].red = 32768 - ci * 128;
+ spec[4][ci].green = ci * 256;
+ spec[4][ci].blue = 65535 - ci * 256;
+ }
+}
+
+
+//
+// ZOOM CONTENT
+//
+
+
+void TMandelbrot::ZoomContent(short z)
+{
+ switch (z) {
+ case -1:
+ pWidth = pWidth * 1.333;
+ pHeigth = pHeigth * 1.333;
+ break;
+ case 1:
+ pWidth = pWidth * 0.666;
+ pHeigth = pHeigth * 0.666;
+ break;
+ break;
+ default:
+ DefaultPlane();
+ break;
+ }
+
+ RefreshWindow(false); // preserve the scroll bars
+}
+
+
--- TMandelbrot.h Tue Oct 12 17:03:39 2021
+++ TMandelbrot.h Tue Oct 12 17:03:39 2021
@@ -0,0 +1,28 @@
+/*****
+ * TMandelbrot.h
+ *
+ * Object definitions for window to draw a Mandelbrot set in.
+ *
+ *****/
+
+#pragma once // include this header
+ // only once per source file
+
+#include "TFractalViewerWindow.h"
+
+
+class TMandelbrot : public TFractalViewerWindow {
+protected:
+ virtual void DefaultPlane();
+ RGBColor spec[5][256];
+ int Mandelbrot(double real, double imag, short maxiterations);
+ virtual void PrepareStyles();
+ double pWidth, pHeigth;
+ double pXMin, pXMax, pYMin, pYMax;
+ double pCX, pCY;
+public:
+ TMandelbrot(void);
+ virtual void Hit(Point where);
+ virtual void DrawShape(Rect *drawingRect);
+ virtual void ZoomContent(short z);
+};
--- TPlasma.cp Mon Nov 15 21:01:19 2021
+++ TPlasma.cp Mon Nov 15 21:01:19 2021
@@ -0,0 +1,301 @@
+/*****
+ * TPlasma.cp
+ *
+ * Drawing clouds (Perlin noise?)
+ *
+ *****/
+
+#include <Packages.h> // for NumToString prototype
+#include "TFractalViewerWindow.h"
+#include "TPlasma.h"
+#include <stdlib.h>
+#include <math.h>
+
+
+/****
+ * TFractalViewerWindow constructor
+ *
+ * Create a bullseye window. This constructor relies
+ * on the TWindow constructor to place the window in
+ * in attractive place. Then it appends a number to the
+ * window title.
+ *
+ ****/
+
+
+TPlasma::TPlasma(void)
+{
+ PrepareStyles();
+ // Set the width, and show the window.
+ SetStyle(2);
+ Show();
+}
+
+
+/****
+ * Hit
+ *
+ * Handle a mouse down in the window.
+ * Bullseye window just force a refresh.
+ *
+ ****/
+
+
+
+
+/****
+ * Noise calculations
+ *
+ *
+ ****/
+
+
+// This code is adapted from a Javascript example found at perlin.mydevelops.com (unknown author)
+
+int p[] = {
+ 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36,
+ 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0,
+ 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56,
+ 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
+ 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55,
+ 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132,
+ 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109,
+ 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126,
+ 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183,
+ 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43,
+ 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112,
+ 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162,
+ 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106,
+ 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205,
+ 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180
+ };
+
+
+int round(float f)
+{
+ int fl = floor(f);
+ float d = f - (float)fl;
+ if (d > 0.5)
+ return fl + 1;
+ else
+ return fl;
+}
+
+int Perm(int x)
+{
+ return p[(x & 255)];
+}
+
+
+int Index(int x, int y)
+{
+ return Perm(x + Perm(y));
+}
+
+
+float Gradient(int vector,float x,float y)
+{
+ //we will find the right gradient
+ float val = 0;
+ switch (vector % 4)
+ {
+ case 0:
+ val = x + y;
+ break;
+ case 1:
+ val = -x + y;
+ break;
+ case 2:
+ val = x - y;
+ break;
+ case 3:
+ val = -x - y;
+ break;
+ }
+
+ return val;
+}
+
+
+float Smooth(float t)
+{
+ return t * t * t * (6 * t * t - 15.0 * t + 10.0);
+}
+
+
+float Interpolate(float t,float a,float b)
+{
+ return a + t * ( b - a);
+}
+
+float Perlin2D(float x,float y)
+{
+ float hX = floor(x);
+ float hY = floor(y);
+
+ float dX = x - hX;
+ float dY = y - hY;
+
+ //field for gradients
+ float gradients[4];
+
+ //now let's go through the vertices of the creator and their vectors
+ for (int i = 0; i < 4; i++) {
+ // 00, 01, 10, 11
+ int tmpX = (i & 2) ? 1: 0;
+ int tmpY = (i & 1);
+ int vector = Index(hX + tmpX, hY + tmpY);
+
+ gradients[i] = Gradient(vector, dX - tmpX, dY - tmpY);
+
+ }
+
+ //let's use the smoothing function
+ float smoothX = Smooth(dX);
+ float smoothY = Smooth(dY);
+
+ //we make a bilinear interpolation of the gradient of vectors first two and two
+ // and finally the results from the first and the second and we get the result
+ float x_prva = Interpolate(smoothX, gradients[0], gradients[2]);
+ double x_druha = Interpolate(smoothX, gradients[1], gradients[3]);
+
+ return Interpolate(smoothY, x_prva, x_druha);
+}
+
+int PerlinMapped(double value)
+{
+ //we will scale it from -1 1 to 0 1 and then from it to 0 255
+ return round( ((value + 1.0) / 2.0) * 255.0);
+}
+
+int PerlinOctFrec(int x, int y, int oct, double frec)
+{
+ double together = 0;
+// int amp = 0;
+ double frek = 0;
+
+ for(int i = 1; i <= oct; i++) {
+ frek = frec * (double)i;
+ together += Perlin2D((double)x * frek, (double)y * frek);
+ }
+
+ return PerlinMapped((double)(together / oct));
+}
+
+
+
+/****
+ * DrawShape methods
+ *
+ *
+ ****/
+
+
+
+void TPlasma::DrawShape(Rect *drawingRect)
+{
+ RGBColor colPix;
+ double frekvencia = 0.004;
+ int oktava = 3;
+
+ short st = GetStyle() - 1;
+
+ sWidth = drawingRect->right - drawingRect->left + 1;
+ sHeigth = drawingRect->bottom - drawingRect->top + 1;
+
+ for(int x=0; x<sWidth; x++) {
+ for (int y=0; y<sHeigth; y++) {
+ int shade = PerlinOctFrec(x, y, oktava, frekvencia);
+ colPix = spec[st][shade];
+ SetCPixel(x, y, &colPix);
+ }
+ }
+
+
+
+/* Test code to draw stuff using DrawPicture. It crashes for complex images (memory issues?)
+ OpenCPicParams myOpenCPicParams;
+ PicHandle myPic;
+ Rect rect;
+
+ rect.left = drawingRect->left;
+ rect.right = drawingRect->right;
+ rect.top = drawingRect->top;
+ rect.bottom = drawingRect->bottom;
+
+ myOpenCPicParams.srcRect = rect;
+ myOpenCPicParams.hRes = 0x00480000;
+ myOpenCPicParams.vRes = 0x00480000;
+ myOpenCPicParams.version = -2;
+ myOpenCPicParams.reserved1 = 0;
+ myOpenCPicParams.reserved2 = 0;
+
+ myPic = OpenCPicture(&myOpenCPicParams);
+
+ PenSize(style, style);
+ ClipRect(drawingRect);
+
+ while (drawingRect->left < drawingRect->right &&
+ drawingRect->top < drawingRect->bottom) {
+ MoveTo(drawingRect->left, drawingRect->bottom);
+ LineTo(drawingRect->right, drawingRect->bottom);
+ LineTo(drawingRect->left, drawingRect->top);
+ LineTo(drawingRect->left, drawingRect->bottom);
+ InsetRect(drawingRect, style*2, style*2);
+ }
+
+ ClosePicture();
+
+ DrawPicture(myPic, &rect);
+*/
+
+}
+
+
+//
+// PREPARE STYLES METHODS
+//
+
+
+void TPlasma::PrepareStyles()
+{
+ short ci;
+ // Style 1
+ for(ci=0; ci < 256; ci++) {
+ spec[0][ci].red = ci * 256;
+ spec[0][ci].green = ci * 256;
+ spec[0][ci].blue = 65535;
+ }
+ // Style 2
+ for(ci=0; ci < 256; ci++) {
+ spec[1][ci].red = 65535 - ci * 256;
+ spec[1][ci].green = 65535 - ci * 256;
+ spec[1][ci].blue = 65535;
+ }
+ // Style 3
+ for(ci=0; ci < 256; ci++) {
+ spec[2][ci].red = 65535 - ci * 256;
+ spec[2][ci].green = 65535 - ci * 256;
+ spec[2][ci].blue = 65535 - ci * 256;
+ }
+ // Style 4
+ for(ci=0; ci < 256; ci++) {
+ spec[3][ci].red = ci * 256;
+ spec[3][ci].green = ci * 256;
+ spec[3][ci].blue = ci * 256;
+ }
+ // Style 4
+ for(ci=0; ci < 256; ci++) {
+ spec[4][ci].red = 32768 - ci * 128;
+ spec[4][ci].green = ci * 256;
+ spec[4][ci].blue = 65535 - ci * 256;
+ }
+}
+
+
+
+//
+// ZOOM CONTENT
+//
+
+
--- TPlasma.h Mon Nov 15 20:43:08 2021
+++ TPlasma.h Mon Nov 15 20:43:08 2021
@@ -0,0 +1,23 @@
+/*****
+ * TPlasma.h
+ *
+ * Object definitions for window to draw a Plasma Fractal in.
+ *
+ *****/
+
+#pragma once // include this header
+ // only once per source file
+
+#define PI 3.1415927;
+
+#include "TFractalViewerWindow.h"
+
+
+class TPlasma : public TFractalViewerWindow {
+protected:
+ RGBColor spec[5][256];
+ virtual void PrepareStyles();
+public:
+ TPlasma(void);
+ virtual void DrawShape(Rect *drawingRect);
+};
--- TWindow.cp Tue Aug 16 13:53:05 2022
+++ TWindow.cp Tue Aug 16 13:53:05 2022
@@ -0,0 +1,405 @@
+/*****
+ * TWindow.cp
+ *
+ * Copyright © 1991 Symantec Corporation. All rights reserved.
+ *
+ * Generic window class to handle most window actions.
+ * This class is intended to demonstrate the new
+ * object-oriented features of THINK C 5.0. It is not
+ * intended to be a general purpose window class for use
+ * in commerical-quality applications.
+ *
+ * We store the object in the window's refCon and set
+ * the windowKind to TWINDOWKIND so we can tell whether
+ * there's an object in it.
+ *
+ *****/
+
+#include <oops.h>
+#include "TWindow.h"
+
+ // Prototypes for utility functions.
+
+static void EraseScrollBars (WindowPtr theWindow);
+static void InvalScrollBars (WindowPtr theWindow);
+static void ValidScrollBars (WindowPtr theWindow);
+
+short TWindow::windowCounter = 0; // the window counter that this class uses to
+ // stack its windows
+
+
+/****
+ * TWindow constructor
+ *
+ * Create a new window and place it in an
+ * attractive place on the screen.
+ *
+ ****/
+
+TWindow::TWindow(void)
+{
+ Rect myRect;
+ short offset;
+ Point originPt;
+
+ theWindow = GetNewCWindow(TWinRSRC, NULL, (void *) -1L);
+ drag = screenBits.bounds;
+ SetRect(&smallest, 60, 60, 9999, 9999);
+
+ ((WindowPeek) theWindow)->windowKind = TWINDOWKIND;
+ SetWRefCon(theWindow, (long) this);
+ SetPort(theWindow);
+
+ // Place this window in some attractive place
+ // on the screen. TWindow uses the class variable
+ // windowCounter to keep track of how many windows it
+ // has stacked, but subclasses can access this variable
+ // through the GetWindowNumber() method to create
+ // numbered windows.
+
+ originPt = topLeft(theWindow->portRect);
+ LocalToGlobal(&originPt);
+ offset = ((windowCounter) % 7) * 20;
+ MoveWindow(theWindow, originPt.h+offset, originPt.v+offset, true);
+ windowCounter++;
+}
+
+
+/****
+ * TWindow destructor
+ *
+ * Dispose of the window.
+ *
+ ****/
+
+TWindow::~TWindow(void)
+{
+ DisposeWindow(theWindow);
+}
+
+
+/****
+ * Close
+ *
+ * Close a window.
+ * This method merely deletes the object.
+ *
+ ****/
+
+void TWindow::Close()
+{
+ delete this;
+}
+
+
+
+/****
+ * GetWindowCounter
+ *
+ * Return the current value of the windowCounter
+ * instance variable.
+ *
+ ****/
+
+short TWindow::GetWindowNumber (void)
+
+{
+ return windowCounter;
+}
+
+/****
+ * Draw
+ *
+ * Draw the contents of the window.
+ * This method sets the foreground and background
+ * color, erases the window, draws the scroll area
+ * in white, and finally draws the grow icon.
+ *
+ ****/
+
+void TWindow::Draw()
+{
+ EraseRect(&theWindow->portRect);
+ BackColor(whiteColor);
+ EraseScrollBars(theWindow);
+ DrawGrowIcon(theWindow);
+
+}
+
+
+void TWindow::Hit(Point where)
+{
+ // Subclasses must do something here
+}
+
+/****
+ * Grow
+ *
+ * Grow the window.
+ * If the window actually changed size, erase the
+ * scroll bar areas. Return the new size of the window.
+ *
+ ****/
+
+long TWindow::Grow (Point where)
+{
+ long size;
+ Rect smallest;
+
+ smallest = this->smallest; // can't pass the address of
+ // and instance variable to
+ // a Toolbox routine that may
+ // move memory.
+
+ SetPort(theWindow);
+ size = GrowWindow(theWindow, where, &smallest);
+
+ if (size) {
+ EraseScrollBars(theWindow);
+ RefreshWindow(true); // force whoe window to be redrawn
+ // the "true" param to SizeWindow
+ // accumulates the new area into
+ // the update region
+
+ SizeWindow(theWindow, LoWord(size), HiWord(size), true);
+ }
+
+ return (size);
+}
+
+/****
+ * Zoom
+ *
+ * Zoom a window in reponse to a click in the zoom box.
+ *
+ ****/
+
+void TWindow::Zoom (short part)
+{
+ Rect myRect;
+
+ SetPort(theWindow);
+ EraseRect(&theWindow->portRect);
+ ZoomWindow(theWindow, part, true);
+}
+
+
+/****
+ * Update
+ *
+ * Update a window.
+ * The usual thing to do here is to call the Draw()
+ * method.
+ *
+ ****/
+
+void TWindow::Update(void)
+{
+ WindowPtr savePort;
+
+ GetPort(&savePort);
+ SetPort(theWindow);
+ BeginUpdate(theWindow);
+ Draw();
+ EndUpdate(theWindow);
+ SetPort(savePort);
+}
+
+
+/****
+ * Activate
+ *
+ * Respond to activate events.
+ * All we really have to do is make sure that the
+ * grow icon is drawn correctly. Subclasses that
+ * want to do something special when deactivate should
+ * override this method.
+ *
+ ****/
+
+void TWindow::Activate (short active)
+{
+ DrawGrowIcon(theWindow); // DrawGrowIcon knows how to draw the icon
+ // for inactive & active windows
+
+ if (active)
+ SetPort(theWindow);
+}
+
+
+
+/****
+ * Draw
+ * Select
+ * Show
+ * Hide
+ * TrackClose
+ * TrackZoom
+ * IsVisible
+ * GetWindowTitle
+ * SetWindowTitle
+ *
+ * Various OOP interfaces to the Toolbox routines.
+ *
+ ****/
+
+
+void TWindow::Drag(Point where)
+{
+ DragWindow(theWindow, where, &drag);
+}
+
+
+void TWindow::Select(void)
+{
+ SelectWindow(theWindow);
+}
+
+
+void TWindow::Show(void)
+{
+ ShowWindow(theWindow);
+}
+
+
+void TWindow::Hide(void)
+{
+ HideWindow(theWindow);
+}
+
+
+void TWindow::TrackClose (Point where)
+{
+ if (TrackGoAway(theWindow, where))
+ Close();
+}
+
+
+void TWindow::TrackZoom(Point where, short part)
+{
+ if (TrackBox(theWindow, where, part))
+ Zoom(part);
+}
+
+
+short TWindow::IsVisible()
+{
+ return ((WindowPeek) theWindow)->visible;
+}
+
+
+
+void TWindow::GetWindowTitle (Str255 theTitle)
+{
+ GetWTitle(theWindow, theTitle);
+}
+
+
+void TWindow::SetWindowTitle (Str255 theTitle)
+{
+ SetWTitle(theWindow, theTitle);
+}
+
+
+/****
+ * GetWindowRect
+ *
+ * Return the windows rectangle.
+ * This method is provided so subclasses don't have
+ * to go poking into the instance variables.
+ *
+ ****/
+
+void TWindow::GetWindowRect (Rect *theRect, Boolean entireWindow)
+{
+ *theRect = theWindow->portRect;
+ if (!entireWindow) {
+ theRect->top += 1;
+ theRect->left += 1;
+ theRect->right -= 16;
+ theRect->bottom -= 16;
+ }
+}
+
+
+/****
+ * RefreshWindow
+ *
+ * Force a window to be redrawn on the next udpate event.
+ * The Boolean parameter determines whether the scroll bars
+ * should be redrawn or not.
+ *
+ ****/
+
+void TWindow::RefreshWindow (Boolean wholeWindow)
+{
+ InvalRect(&theWindow->portRect);
+ if (!wholeWindow)
+ ValidScrollBars(theWindow);
+}
+
+
+
+/****
+ * Zoom
+ *
+ ****/
+
+void TWindow::ZoomContent(short z)
+{
+ // Child will do
+}
+
+
+/***
+ * Utility routines to validate & inval the scroll bar rectangles.
+ *
+ ***/
+
+
+typedef enum { kInval, kValid, kErase } sbarAction;
+
+static void xScrollBars (WindowPtr theWindow, sbarAction action)
+{
+ Rect botRect;
+ Rect rightRect;
+
+ rightRect = botRect = theWindow->portRect;
+
+ botRect.top = botRect.bottom-15; // The bottom scroll area
+
+ rightRect.left = rightRect.right-15; // The right scroll area
+
+ switch (action) {
+ case kInval: InvalRect(&botRect);
+ InvalRect(&rightRect);
+ break;
+
+ case kValid: ValidRect(&botRect);
+ ValidRect(&rightRect);
+ break;
+
+ case kErase: EraseRect(&botRect);
+ EraseRect(&rightRect);
+ break;
+ }
+}
+
+static void InvalScrollBars (WindowPtr theWindow)
+{
+ xScrollBars(theWindow, kInval);
+}
+
+static void ValidScrollBars (WindowPtr theWindow)
+{
+ xScrollBars(theWindow, kValid);
+}
+
+
+static void EraseScrollBars (WindowPtr theWindow)
+{
+ xScrollBars(theWindow, kErase);
+}
+
+
+
--- TWindow.h Mon Oct 11 15:04:27 2021
+++ TWindow.h Mon Oct 11 15:04:27 2021
@@ -0,0 +1,66 @@
+/*****
+ * TWindow.h
+ *
+ * Copyright © 1991 Symantec Corporation
+ *
+ * Class definition of window class.
+ * This class is intended to demonstrate the new
+ * object-oriented features of THINK C 5.0. It is not
+ * intended to be a general purpose window class for use
+ * in commerical-quaility applications.
+ *
+ *****/
+
+#pragma once // include this header
+ // only once per source file
+
+#define TWINDOWKIND 'TW' // Windows whose windowKind is
+ // TWINDOWKIND have a TWindow
+ // object stored in their refCon.
+ // If it's any other windowKind,
+ // it's not one of ours.
+
+#define TWinRSRC 128 // Resource ID of WIND resource
+ // for TWindow windows
+
+#if __cplusplus
+class TWindow { // Using Symantec C++
+#else
+class TWindow : indirect { // ...or THINK C's oop extensions
+#endif
+
+private:
+ Rect drag;
+ Rect smallest;
+ WindowPtr theWindow; // the window record
+
+ static short windowCounter; // counter for the stacker
+
+
+public:
+ TWindow(void); // constructor
+ ~TWindow(void); // destructor
+
+ virtual void Close(void);
+ short GetWindowNumber(void);
+ virtual void Draw(void);
+ virtual void Hit(Point where);
+ virtual long Grow(Point where);
+ virtual void Zoom(short part);
+ virtual void Update(void);
+ virtual void Activate(short active);
+ virtual void Drag(Point where);
+ virtual void Select(void);
+ virtual void Show(void);
+ virtual void Hide(void);
+ virtual void TrackClose(Point where);
+ virtual void TrackZoom(Point where, short part);
+ virtual short IsVisible(void);
+ virtual void GetWindowTitle (Str255 theTitle);
+ virtual void SetWindowTitle (Str255 theTitle);
+ virtual void GetWindowRect(Rect *theRect, Boolean entireWindow);
+ virtual void RefreshWindow(Boolean entireWindow);
+ virtual void ZoomContent(short z);
+
+};
+
--- Utils.cp Fri Oct 15 11:22:31 2021
+++ Utils.cp Fri Oct 15 11:22:31 2021
@@ -0,0 +1,15 @@
+#include <Packages.h> // for NumToString prototype
+#include <stdlib.h>
+#include "Utils.h"
+
+/***
+ * concatenate two Pascal strings
+ *
+ ***/
+
+void concat (StringPtr s, StringPtr p)
+{
+ BlockMove(p+1, s+1+s[0], (long) p[0]);
+ s[0] += p[0];
+}
+
--- Utils.h Fri Oct 15 11:22:51 2021
+++ Utils.h Fri Oct 15 11:22:51 2021
@@ -0,0 +1,12 @@
+/*****
+ * Utils.h
+ *
+ * several utilities
+ *
+ *****/
+
+#pragma once // include this header
+ // only once per source file
+
+void concat (StringPtr s, StringPtr p);
+