TweetFollow Us on Twitter

Color Capable
Volume Number:3
Issue Number:7
Column Tag:Macintosh II

Lazy Man's Color

By Steven Sheets, Hoffman Estates, IL

Newsbreak....Cupertino, Calif.....Color is here!

The new Macintosh // computer has color capabilities. Most color video cards will allow up to 256 specific colors out of a possible color palatte of 16,777,216 selections. A new Color Quickdraw has been designed with Color Tables, Pixel Maps, Pixel Patterns, Color Icons, Color Grafports and Color Picture Handles to work with the new machine. Three new Managers have been added to facilitate color; the Color Manager, the Color Picker Package and the Palette Manager.

Are you ready to program with this new Color Quickdraw?

Before you answer that, did you know there was an alternative way to display color on the Mac? Use the old Quickdraw color routine! You didn’t know the older Quickdraw had color? Well...

Old Color

The original Macintosh displays were in black & white. 21,888 bytes of memory were used to display the normal 512 by 342 pixel screen (1 bit per pixel). However, the original Quickdraw had the capability to draw in color. In the original Grafport record, there were 2 fields (fgColor and bkColor) that determined the settings of the Foreground and Background color.

Quickdraw predefined 8 colors (Black, White, Red, Green, Blue, Cyan, Magenta and Yellow). Each color had a long integer constant associated with it. By passing these constants to the procedures ForeColor and BackColor, the respective fields of the current Grafport were changed. When any Grafport was created, the default settings for the Foreground and Background were Black and White respectively.

Color fields were treated similar to the more often used Pen Pattern (pnPat) and Background Pattern (bkPat). Any drawing by the Pen was done in the Foreground color, any Erasing was done in the Background color. Also Foreground and Background color affect the Copybits call. When copying a bitmap onto a Grafport, any bit that was set in the source Bitmap would make the corresponding pixel appear in the Foreground color on the Grafport. Any unset bit would make the pixel appear in the Background color.

However on the black and white Macintosh, any color other than white appears as black. Thus drawing Red on White, Blue on White, or even Yellow on White has the same effect on the Pre-Mac // computers; Black on White. Interestingly the Imagewriter // printer driver does use the color commands, thus making the Imagewriter // with a color ribbon the first color Macintosh output device of any type. While the new Mac // also has the new Color Quickdraw commands, it also supports the old commands, including the use of Foreground and Background color.

Fig. 1 Our program uses classic color options

Why Use Old?

There are several reasons for not wanting to use Color Quickdraw for your first color program. It might prove simpler, until you get a handle on Color Quickdraw (and the three associated managers), to use the older Quickdraw routines. Color Quickdraw involves new conceptional models, new data structures, and new routines. While it is well worth the effort to learn (the graphic effects are stunning), there is a stiff learning curve.

The Color Quickdraw manual is even larger than the original Quickdraw manual. That is assuming that you have the new documentation. Inside Macintosh Vol. V is due out soon, but unless you currently have a beta version, you will have to wait for APDA’s final release.

Even if you have the new documentation and routines, your development system may not implement the new ROM calls. Lightspeed C, Lightspeed Pascal, MDS do not support the new Quickdraw, while MPW has to be updated to version 2.0. Many programmers will have to wait until the developers of their programming language come out with a new update until they can use the new routines. Some lucky users can input all the new calls themselves and do not need the updates. That means typing in dozens of new calls and data structures (again assuming they have the documentation). Lucky them! [Apple is still working on the equates file and rumor has it the Pallette Manager is still changing. -Ed]

Finally there is the actual code size and time in involved programming the new Quickdraw. Color Quickdraw does take more code to implement and it’s data structures are larger. The simple ForeColor and BackColor routines take very little code space.

Certainly Color Quickdraw should be used if someone is writing a color Drawing program for the Mac //. But if you only wish to add color to your existing programs, using Color Quickdraw requires you to rewrite your code, redo your graphics and in some cases, even redo your complicated bitmaps. Placing ForeColor and BackColor calls before your existing code segments is much simpler. If your Program is intended to run on any Macintosh, the older Quickdraw may be all you need or want to produce color.

The Code

The source example is an extremely simple, standard Macintosh program. It loads and displays any MacPaint document in any of the eight Foreground and eight Background colors. A few notes:

1) The CWindow (which will display the MacPaint document) is centered on large screens (like a SuperMac monitor) or placed in the offset position.

2) The actual picture is stored in two sets of Bitmaps and Data handles. Data is stored this way since the size of a MacPaint bitmap is too large to store in 1 set (32K limit). If there is not enough memory to create the bitmaps, the program will state this and not allow a MacPaint document to be loaded

3) ForeC and BackC store the selected menu number (1-8), not the predefined Color constant. GetColor is used to convert the menu number into the color constant.

4) DoColor is the pivotal procedure; it sets the new Foreground/Background colors. Then it causes an window update so the window is redrawn in the new colors.

{Lazy Man’s Color by Steve Sheets 4/20/87 }
{Simple Demonstration of Mac // Color using the 
{ForeColor & BackColor of classical Quickdraw. }
{This program Loads and displays a MacPaint document }
(in any 2 colors.}

PROGRAM LMC;

{Various Constants:Menu ID Numbers, Window Size, }
{Window Placement, BitMap Size and Number of Colors. }
CONST
 AppleMenuID = 300;
 FileMenuID = 301;
 EditMenuID = 302;
 ForeMenuID = 303;
 BackMenuID = 304;

 OffV = 40;
 OffH = 40;
 AboutH = 300;
 AboutV = 140;
 SizeH = 576;
 SizeV1 = 360;
 SizeV2 = 720;
 BitW = 72;
 NumSec = 2;

 XColor = 8;

{Various Variables:Menus, Bitmaps, Window, Colors, }
{Done Flag & Title Name }
VAR
 Done : boolean;
 AppleMenu, FileMenu: EditMenu, 
 ForeMenu, BackMenu : MenuHandle;

 CWindow : windowptr;
 CMap : ARRAY[1..NumSec] OF bitmap;
 CData : ARRAY[1..NumSec] OF handle;

 ForeC, BackC : integer;
 Title : str255;

{Given Color Number ( 1 to XColor, as selected by Menu), }
{returns actual longint Color Number (for ForeColor or }
{BackColor). }
FUNCTION GetColor (N : integer) : longint;
BEGIN
 CASE N OF
 1 : 
 GetColor := BlackColor;
 2 : 
 GetColor := WhiteColor;
 3 : 
 GetColor := RedColor;
 4 : 
 GetColor := GreenColor;
 5 : 
 GetColor := BlueColor;
 6 : 
 GetColor := CyanColor;
 7 : 
 GetColor := MagentaColor;
 8 : 
 GetColor := YellowColor;
 OTHERWISE
 GetColor := WhiteColor;
 END;
END;

{Sets new ForeColor & BackColor and forces an Update} 
{so Window is redrawn in the new colors. }
PROCEDURE DoColor (F, B : integer);
 VAR
 count : integer;
 tempPort : Grafptr;
BEGIN
 GetPort(tempPort);
 SetPort(CWindow);
 IF F <> ForeC THEN
 BEGIN
 FOR count := 1 TO XColor DO
 CheckItem(ForeMenu, count, count = F);
 ForeC := F;
 ForeColor(GetColor(ForeC));
 END;
 IF B <> BackC THEN
 BEGIN
 FOR count := 1 TO XColor DO
 CheckItem(BackMenu, count, count = B);
 BackC := B;
 BackColor(GetColor(BackC));
 END;
 InvalRect(CWindow^.portRect);
 SetPort(tempPort);
END;

{ Loads MacPaint Picture in Bitmaps and displays it.}
PROCEDURE DoLoad;
 TYPE
 diskBlock = PACKED ARRAY[1..512] OF QDbyte;
 VAR
 MyReply : SFReply;
 MyType : SFtypelist;
 tempPoint : point;
 count : longint;
 refNum, scanline, N : integer;
 error : OSErr;
 srcBuf : ARRAY[1..2] OF diskBlock;
 srcPtr, dstPtr : Ptr;
BEGIN
 tempPoint.v := 60;
 tempPoint.h := 60;
 MyType[0] := ‘PNTG’;
 SFGetFile(tempPoint, ‘’, NIL, 1, MyType, NIL, MyReply);
 IF MyReply.good THEN
 BEGIN
 Hlock(CData[1]);
 Hlock(CData[2]);
 IF FSOpen(MyReply.fname, MyReply.vrefnum, refNum) = noErr THEN
 BEGIN
 count := 512;
 error := FSRead(refNum, count, @srcBuf);
 count := 1024;
 error := FSRead(refNum, count, @srcBuf);
 srcPtr := @srcBuf;
 FOR N := 1 TO NumSec DO
 BEGIN
 dstPtr := CData[N]^;
 FOR scanline := 1 TO SizeV1 DO
 BEGIN
 UnpackBits(srcPtr, dstPtr, BitW);
 IF ord(srcPtr) > (ord(@srcBuf) + 512) THEN
 BEGIN
 srcBuf[1] := srcBuf[2];
 count := 512;
 error := FSRead(refNum, count, @srcBuf[2]);
 srcPtr := pointer(ord(srcPtr) - 512);
 END;
 END;
 END;
 error := FSClose(refNum);
 END;
 HUnlock(CData[1]);
 HUnlock(CData[2]);
 END;
 DoColor(ForeC, BackC);
END;

{Creates a Rectangle centered on Screen (if window }
{size is smaller then the screen) or starting at a }
{standard offset (if window size is larger then }
{screen). }
PROCEDURE CenterRect (VAR R : rect;
 H, V : integer);
 VAR
 tempH : integer;
BEGIN
 IF H > Screenbits.bounds.right THEN
 tempH := OffH
 ELSE
 tempH := ((Screenbits.bounds.right - H) DIV 2);
 SetRect(R, tempH, OffV, H + tempH, V + OffV);
END;

{Draws text, centered in a rectangle in the About}
{  Box window in a certain color with a certain }
{justification }
PROCEDURE DoLine (S : str255;
 H, Top, Bottom, J : integer;
 C : longint);
 VAR
 tempInteger : integer;
 tempRect : rect;
BEGIN
 ForeColor(C);
 tempInteger := ((AboutH - H) DIV 2);
 SetRect(tempRect, tempInteger, Top, tempInteger + H, Bottom);
 TextBox(POINTER(ord(@S) + 1), LENGTH(S), tempRect, J);
END;

{Displays About Box (in color) until someone presses } 
{the button down.}
PROCEDURE DoAbout;
 VAR
 tempWindow : windowptr;
 tempRect : rect;
 tempStr : str255;
BEGIN
 CenterRect(tempRect, AboutH, AboutV);
 tempWindow := NewWindow(NIL, tempRect, ‘’, true, dBoxProc, POINTER(-1), 
false, 0);
 SetPort(tempWindow);
 TextFont(0);

 DoLine(CONCAT(Title, ‘ by Steve Sheets’), AboutH, 20, 39, teJustCenter, 
BlueColor);
 DoLine(‘Sample Mac // Color Program’, AboutH, 40, 59, teJustCenter, 
GreenColor);
 DoLine(‘This program uses the ForeColor and BackColor Quickdraw commands 
to display a MacPaint document in two colors.’, AboutH - 50, 60, AboutV, 
teJustLeft, RedColor);

 WHILE NOT button DO
 ;
 DisposeWindow(tempWindow);
END;

{Standard main menu procedure that handles }
{menu selections.  Can show About Box, open Desk }
{Accessories, Load in MacPaint file, change }
{the Done Flag (so the program quits), handle} 
{edit commands (Cut,Copy,Paste,Clear), and change }
{Foreground or Background color of the picture.}
PROCEDURE MainMenu (tempResult : LONGINT);
 VAR
 tempInteger : integer;
 tempBoolean : boolean;
 tempStr : STR255;
BEGIN
 tempInteger := LoWord(tempResult);
 CASE HiWord(tempResult) OF
 AppleMenuID : 
 IF tempInteger = 1 THEN
 DoAbout
 ELSE
 BEGIN
 GetItem(appleMenu, tempInteger, tempStr);
 tempInteger := OpenDeskAcc(tempStr);
 END;
 FileMenuID : 
 CASE tempInteger OF
 1 : 
 DoLoad;
 3 : 
 Done := true;
 OTHERWISE
 END;
 EditMenuID : 
 tempBoolean := SystemEdit(tempInteger - 1);
 ForeMenuID : 
 IF (tempInteger > 0) AND (tempInteger <= XColor) THEN
 DoColor(tempInteger, BackC);
 BackMenuID : 
 IF (tempInteger > 0) AND (tempInteger <= XColor) THEN
 DoColor(ForeC, tempInteger);
 OTHERWISE
 END;
 HiliteMenu(0);
END;

{Setup for Menus, Window, Bitmaps,  Colors }
{settings, Title and Done flag.  }
PROCEDURE DoSetup;
 TYPE
 DD = PACKED ARRAY[1..32000] OF 0..255;
 PP = ^DD;
 HH = ^PP;
 VAR
 tempStr : STR255;
 tempRect : rect;
 count : integer;
 tempLong : longint;
 tempH : HH;
BEGIN
 Title := ‘Lazy Man@s Color’;
 Title[9] := CHR(39);

 tempStr := ‘ ‘;
 tempStr[1] := CHR(appleMark);
 AppleMenu := NewMenu(AppleMenuID, tempStr);
 AppendMenu(AppleMenu, CONCAT(‘About ‘, Title, ‘...;(-’));
 AddResMenu(AppleMenu, ‘DRVR’);

 FileMenu := NewMenu(FileMenuID, ‘File’);
 AppendMenu(FileMenu, ‘Load MacPaint Documents/L;(-;Quit/Q’);

 EditMenu := NewMenu(EditMenuID, ‘Edit’);
 AppendMenu(EditMenu, ‘Undo/Z;(-;Cut/X;Copy/C; Paste/V;Clear’);

 ForeMenu := NewMenu(ForeMenuID, ‘Set Foreground’);
 AppendMenu(ForeMenu, ‘Black;White;Red;Green;Blue; Cyan;Magenta;Yellow’);

 BackMenu := NewMenu(BackMenuID, ‘Set Background’);
 AppendMenu(BackMenu, ‘Black;White;Red;Green;Blue;Cyan; Magenta;Yellow’);

 InsertMenu(AppleMenu, 0);
 InsertMenu(FileMenu, 0);
 InsertMenu(EditMenu, 0);
 InsertMenu(ForeMenu, 0);
 InsertMenu(BackMenu, 0);

 DrawMenuBar;

 CenterRect(tempRect, SizeH, SizeV2);
 CWindow := NewWindow(NIL, tempRect, Title, true, 4, POINTER(-1), false, 
0);

 CMap[1].rowBytes := BitW;
 SetRect(CMap[1].bounds, 0, 0, SizeH, SizeV1);
 CData[1] := NewHandle(BitW * SizeV1);
 IF CData[1] <> NIL THEN
 BEGIN
 tempH := HH(CData[1]);
 FOR count := 1 TO BitW * SizeV1 DO
 tempH^^[count] := 0;
 END;
 CMap[2].rowBytes := BitW;
 SetRect(CMap[2].bounds, 0, SizeV1, SizeH, SizeV2);
 CData[2] := NewHandle(BitW * SizeV1);
 IF CData[2] <> NIL THEN
 BEGIN
 tempH := HH(CData[2]);
 FOR count := 1 TO BitW * SizeV1 DO
 tempH^^[count] := 0;
 END;
 IF (CData[1] = NIL) OR (CData[2] = NIL) THEN
 BEGIN
 SetWTitle(CWindow, ‘Not Enough Memmory’);
 DisableItem(FileMenu, 1);
 END;
 ForeC := 0;
 BackC := 0;
 DoColor(1, 2);
 InitCursor;
 Done := false;
END;

{Standard main program loop that handles all }
{events (ie. mouse down, key downs & updates) until }
{the Done flag is set.  }
PROCEDURE MainLoop;
 VAR
 tempEvent : EventRecord;
 tempWindow : windowptr;
 tempCode : integer;
 tempPort : Grafptr;
 tempRect : rect;
BEGIN
REPEAT
 SystemTask;
 IF GetNextEvent(everyEvent, tempEvent) THEN
 BEGIN
 CASE tempEvent.what OF
 mouseDown : 
 BEGIN
 tempCode := FindWindow(tempEvent.where, tempWindow);
 CASE tempCode OF
 inDrag, inContent : 
 BEGIN
 IF tempWindow <> FrontWindow THEN
 SelectWindow(tempWindow)
 ELSE
 BEGIN
 IF Cwindow = tempWindow THEN
 BEGIN
 IF CWindow <> FrontWindow THEN
 SelectWindow(CWIndow)
 ELSE
 BEGIN
 SetRect(tempRect, -25000, -25000, 25000, 25000);
 DragWindow(CWindow, tempEvent.where, tempRect);
 END;
 END;
 END;
 END;
 inMenuBar : 
 MainMenu(MenuSelect(tempEvent.where));
 inSysWindow : 
 SystemClick(tempEvent, tempWindow);
 OTHERWISE
 END; { of tempCode case }
 END; { of mouseDown }
 keydown, autoKey : 
 IF BitAnd(tempEvent.modifiers, cmdKey) <> 0 THEN
 MainMenu(MenuKey(CHR(tempEvent.message MOD 256)));
 updateEvt : 
 IF CWindow = WindowPtr(tempEvent.message) THEN
 BEGIN
 GetPort(tempPort);
 SetPort(CWindow);
 BeginUpdate(CWindow);
 IF CData[1] <> NIL THEN
 BEGIN
 Hlock(CData[1]);
 CMap[1].baseAddr := CData[1]^;
 CopyBits(CMap[1], CWindow^.portBits, CMap[1].bounds, CMap[1].bounds, 
srcCopy, NIL);
 HUnlock(CData[1]);
 END;
 IF CData[2] <> NIL THEN
 BEGIN
 Hlock(CData[2]);
 CMap[2].baseAddr := CData[2]^;
 CopyBits(CMap[2], CWindow^.portBits, CMap[2].bounds, CMap[2].bounds, 
srcCopy, NIL);
 HUnlock(CData[2]);
 END;
 EndUpdate(CWindow);
 SetPort(tempPort);
 END;
 OTHERWISE
 END;
 END;
 UNTIL Done;
END;

{***PROGRAM*** }
BEGIN
 DoSetup;
 MainLoop;
END.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

The secrets of Penacony might soon come...
Version 2.2 of Honkai: Star Rail is on the horizon and brings the culmination of the Penacony adventure after quite the escalation in the latest story quests. To help you through this new expansion is the introduction of two powerful new... | Read more »
The Legend of Heroes: Trails of Cold Ste...
I adore game series that have connecting lore and stories, which of course means the Legend of Heroes is very dear to me, Trails lore has been building for two decades. Excitedly, the next stage is upon us as Userjoy has announced the upcoming... | Read more »
Go from lowly lizard to wicked Wyvern in...
Do you like questing, and do you like dragons? If not then boy is this not the announcement for you, as Loongcheer Game has unveiled Quest Dragon: Idle Mobile Game. Yes, it is amazing Square Enix hasn’t sued them for copyright infringement, but... | Read more »
Aether Gazer unveils Chapter 16 of its m...
After a bit of maintenance, Aether Gazer has released Chapter 16 of its main storyline, titled Night Parade of the Beasts. This big update brings a new character, a special outfit, some special limited-time events, and, of course, an engaging... | Read more »
Challenge those pesky wyverns to a dance...
After recently having you do battle against your foes by wildly flailing Hello Kitty and friends at them, GungHo Online has whipped out another surprising collaboration for Puzzle & Dragons. It is now time to beat your opponents by cha-cha... | Read more »
Pack a magnifying glass and practice you...
Somehow it has already been a year since Torchlight: Infinite launched, and XD Games is celebrating by blending in what sounds like a truly fantastic new update. Fans of Cthulhu rejoice, as Whispering Mist brings some horror elements, and tests... | Read more »
Summon your guild and prepare for war in...
Netmarble is making some pretty big moves with their latest update for Seven Knights Idle Adventure, with a bunch of interesting additions. Two new heroes enter the battle, there are events and bosses abound, and perhaps most interesting, a huge... | Read more »
Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, don’t remind me I could currently buy him this month I’m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly “borrowed” many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »

Price Scanner via MacPrices.net

Apple Magic Keyboards for iPads are on sale f...
Amazon has Apple Magic Keyboards for iPads on sale today for up to $70 off MSRP, shipping included: – Magic Keyboard for 10th-generation Apple iPad: $199, save $50 – Magic Keyboard for 11″ iPad Pro/... Read more
Apple’s 13-inch M2 MacBook Airs return to rec...
Apple retailers have 13″ MacBook Airs with M2 CPUs in stock and on sale this weekend starting at only $849 in Space Gray, Silver, Starlight, and Midnight colors. These are the lowest prices currently... Read more
Best Buy is clearing out iPad Airs for up to...
In advance of next week’s probably release of new and updated iPad Airs, Best Buy has 10.9″ M1 WiFi iPad Airs on record-low sale prices for up to $200 off Apple’s MSRP, starting at $399. Sale prices... Read more
Every version of Apple Pencil is on sale toda...
Best Buy has all Apple Pencils on sale today for $79, ranging up to 39% off MSRP for some models. Sale prices for online orders only, in-store prices may vary. Order online and choose free shipping... Read more
Sunday Sale: Apple Studio Display with Standa...
Amazon has the standard-glass Apple Studio Display on sale for $300 off MSRP for a limited time. Shipping is free: – Studio Display (Standard glass): $1299.97 $300 off MSRP For the latest prices and... Read more
Apple is offering significant discounts on 16...
Apple has a full line of 16″ M3 Pro and M3 Max MacBook Pros available, Certified Refurbished, starting at $2119 and ranging up to $600 off MSRP. Each model features a new outer case, shipping is free... Read more
Apple HomePods on sale for $30-$50 off MSRP t...
Best Buy is offering a $30-$50 discount on Apple HomePods this weekend on their online store. The HomePod mini is on sale for $69.99, $30 off MSRP, while Best Buy has the full-size HomePod on sale... Read more
Limited-time sale: 13-inch M3 MacBook Airs fo...
Amazon has the base 13″ M3 MacBook Air (8GB/256GB) in stock and on sale for a limited time for $989 shipped. That’s $110 off MSRP, and it’s the lowest price we’ve seen so far for an M3-powered... Read more
13-inch M2 MacBook Airs in stock today at App...
Apple has 13″ M2 MacBook Airs available for only $849 today in their Certified Refurbished store. These are the cheapest M2-powered MacBooks for sale at Apple. Apple’s one-year warranty is included,... Read more
New today at Apple: Series 9 Watches availabl...
Apple is now offering Certified Refurbished Apple Watch Series 9 models on their online store for up to $80 off MSRP, starting at $339. Each Watch includes Apple’s standard one-year warranty, a new... Read more

Jobs Board

Licensed Practical Nurse - Womens Imaging *A...
Licensed Practical Nurse - Womens Imaging Apple Hill - PRN Location: York Hospital, York, PA Schedule: PRN/Per Diem Sign-On Bonus Eligible Remote/Hybrid Regular Read more
DMR Technician - *Apple* /iOS Systems - Haml...
…relevant point-of-need technology self-help aids are available as appropriate. ** Apple Systems Administration** **:** Develops solutions for supporting, deploying, Read more
Operating Room Assistant - *Apple* Hill Sur...
Operating Room Assistant - Apple Hill Surgical Center - Day Location: WellSpan Health, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Read more
Solutions Engineer - *Apple* - SHI (United...
**Job Summary** An Apple Solution Engineer's primary role is tosupport SHI customers in their efforts to select, deploy, and manage Apple operating systems and Read more
DMR Technician - *Apple* /iOS Systems - Haml...
…relevant point-of-need technology self-help aids are available as appropriate. ** Apple Systems Administration** **:** Develops solutions for supporting, deploying, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.