home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Information
/
CSMP Digest
/
volume 1
/
csmp-v1-179.txt
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
Text File
|
1994-12-08
|
42.5 KB
|
1,262 lines
|
[
TEXT/R*ch
]
C.S.M.P. Digest Fri, 09 Oct 92 Volume 1 : Issue 179
Today's Topics:
ColorTables: misc. tidbits and code
Keeping the cursor visible
Zbasic+System 6/7 Speed
Function missing from MPW C library?
The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. (This means you can't post questions to the
digest.)
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
cs.uoregon.edu). Article threads are not added to the digest until the last
article added to the thread is at least one month old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
[128.223.8.8] in the directory /pub/mac/csmp-digest. Be sure to read the
file /pub/mac/csmp-digest/README before downloading any files. The most
recent issues are available from sumex-aim.stanford.edu [36.44.0.6] in the
directory /info-mac/digest/csmp. If you don't have ftp capability, the sumex
archive has a mail server; send a message with the text '$MACarch help' (no
quotes) to LISTSERV@ricevm1.rice.edu for more information.
The digest is also available via email. Just send a note saying that you
want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
automatically receive each new issue as it is created. Sorry, back issues
are not available through the mailing list.
Send administrative mail to mkelly@cs.uoregon.edu.
-------------------------------------------------------
From: k044477@hobbes.kzoo.edu (Jamie R. McCarthy)
Subject: ColorTables: misc. tidbits and code
Date: 3 Sep 92 16:32:09 GMT
Organization: Kalamazoo College
This article starts off with some AppleLink mail from Forrest Tanaka,
telling you more than you ever wanted to know about color tables, and
ends with a fair amount of ANSI C source code for manipulating them.
This is, in short, a hodgepodge of answers and solutions. If you're
a little confused about color graphics on the Mac (who isn't?!),
well, who knows--this may clear up something for you.
Please note that the code is copyrighted and may not be used directly
in a for-profit program. That's 'cause my company paid me to write
it and it's not fair for you to steal it. Sorry. If you want to use
it, fix a bug for me. (There must be at least one.) Otherwise,
you're free to use it directly in private or free programs, and to
write your own code based on mine.
Comments, especially on the source code, are heartily welcomed.
Jamie McCarthy Internet: k044477@kzoo.edu AppleLink: j.mccarthy
Item 5744291 10-July-92 16:02PDT
From: DEVSUPPORTJ Developer Support Center
To: J.MCCARTHYJ MCE-Lawrence Prod, J McCarthy
Sub: RE-ColorTable code-level Q's
July 10, 1992
Hi Jamie
I received your questions about color tables, and since there are
several questions, IUll put the text of your question in a narrow
paragraph and respond to each one in the normal paragraphs
afterwards.
When drawing offscreen, every CQD routine will handle both
indexed and sequential tables properly; in addition,
CopyBits will handle a "paletted" table for its source
PixMap. Right?
Yes. If the source PixMap to CopyBits is paletted and the destination
is a window with a palette, then CopyBits uses the value field of
each ColorSpec record as a palette index for each pixel, which is of
course the whole idea behind paletted color tables. If the
destination is anything else, then bit 14 of ctFlags is ignored and
the color table is treated as either indexed or sequential depending
on the value of bit 15. Bit 14 is also ignored when its color
tableUs PixMap is used as the destination to CopyBits.
IM V-136, contradictorially, says "The ctFlags field is
significant for gDevices only," and "Color tables that are
part of [non-GDevice] pixMaps have this bit clear." What
this means is, "Clear your own ctFlags, use indexed tables,
and don't mess with a GDevice's ctFlags." Right?
Inside Macintosh is simply wrong on this point, though it was the
popular belief for quite a while. The truth is that QuickDraw reads
ctFlags regardless of whether the color tableUs PixMap belongs to a
GDevice, a GWorld, or is one that you created. If you create your
own PixMap and want to use a sequential color table, set this bit.
If you want an indexed color table, clear this bit. QuickDraw will
read this bit and do the right thing. I personally always make
indexed color tables because I happen to be more comfortable with
them, but you can make a sequential one if you want, and QuickDraw
will have no problems with it.
ItUs true that all screen GDevices have color tables which are
sequential, but that doesnUt mean that all GDevices must have
sequential color tables. If you make a GDevice yourself, say for
off-screen drawing, then you can have either a sequential or indexed
color table. QuickDraw will read the most significant bit of ctFlags
and act accordingly.
I understand that video drivers expect sequential tables.
But, is there anything at all wrong with mixing and
matching sequential and indexed tables when they don't
belong to GDevices?
No, no problem at all. In fact, as I mentioned, you can mix and match
even if a color table belongs to a GDevice. The only thing you canUt
do is change the color table of a screenUs GDevice directly.
Must an indexed table be sorted?
No. You can arrange an indexed color table in random order if you
want to, as long as you set the value field of each the color
specification records to the pixel value that you want for each
color. For example, these two four-entry color tables are identical
assuming ctFlags is zero:
Entry value rgb Entry value rgb
0 0 white 0 2 mauve
1 1 green 1 1 green
2 2 mauve 2 3 black
3 3 black 3 0 white
IM V-138 says "...when the Color2Index routine is called,
it can find the best match to the full 48-bit resolution
available in a colorSpec." Really? Even if the inverse
table's only 3 bits and my color table consists of (for
example) a 256-shade gradation from black to white?
Doesn't that require appending a whole lot of information
after the inverse table?
Inside Macintosh is right, and so are you. If you have two colors
that differ only in the least significant bit of each of their
components, Color2Index will be able to tell the difference. The
inverse-table look-up is just the first step; itUs a coarse
estimation of what the final pixel value is. At the end of the
inverse table is a linked list of colors, called the hidden-color
list. After the inverse-table look-up is complete, this coarse
estimate is fine-tuned using the hidden-color list so that
Color2Index can tell the difference between two colors down to the
last bit. Color QuickDraw doesnUt always use the hidden-color list
though. If you use the arithmetic modes with CopyBits, only the
coarse, inverse-table look-up is done. If you use dithering with
CopyBits, the hidden-color list isnUt used either.
What will happen if you ask CQD to manipulate a table whose
top two ctFlags bits are 11? (Just out of curiosity.)
IUve done this, and itUs fine. If the PixMap that owns this color
table is used as a source to CopyBits and if the destination is a
window with a palette, this PixMap is treated as a paletted color
table. If the destination is a window without a palette or a PixMap
thatUs not associated with a window at all, the color table is
treated as a sequential color table. If the PixMap is used as the
destination to CopyBits, then itUs just treated as a sequential color
table. Think of it this way: bit 14 has an effect if the color table
belongs to the source PixMap to CopyBits and a window with a palette
is the destination. In any other case, bit 14 is ignored and bit 15
tells QuickDraw what to do.
Well, I hope that covers everything. If you need any clarifications
or any more help, just let me know!
- -- Forrest
/*
* ColorTableUtils.h
*
* Copyright ) 1992 by Lawrence Productions, Inc. All Rights Reserved.
*
* This code may not be used in any for-profit program without the
* written permission of Lawrence Productions, Inc.
*
*/
/********************************/
#pragma once
/********************************/
/*
* Note that the values of these three constants happen to equal the
* top two bits of the ctFlags field. The macro for getColorTableMode()
* is the only thing that depends on this fact.
*/
enum {
kIndexedColorTable = 0x00,
kPalettedColorTable = 0x01,
kSequentialColorTable = 0x02
} ;
/********************************/
/*
* Determine the mode of a color table.
*/
short getColorTableMode(CTabPtr theTablePtr);
#define getColorTableMode(theTablePtr) ( \
((unsigned short)(theTablePtr)->ctFlags) >> 14 )
#define colorTableIsIndexed(theTablePtr) \
(getColorTableMode(theTablePtr) == kIndexedColorTable)
#define colorTableIsPaletted(theTablePtr) \
(getColorTableMode(theTablePtr) == kPalettedColorTable)
#define colorTableIsSequential(theTablePtr) \
(getColorTableMode(theTablePtr) == kSequentialColorTable)
/*
* Determine whether a color table is sorted. Naturally, it's designed
* for indexed tables, but works (trivially) with sequential and
* paletted tables too.
*/
Boolean colorTableIsSorted(CTabPtr theTable);
#define assertColorTableIsSorted(theTable) ASSERT(colorTableIsSorted(theTable));
/*
* Find an entry's offset in a color table. Naturally, it's designed
* for indexed tables, but works (trivially) on sequential tables too.
* Paletted tables may have none or several entries that point to a
* particular palette entry, and this routine will not attempt to
* search them, returning kNoEntryFound instead.
*
* For all tables, the output is the index into the ctTable field.
*/
#define kNoEntryFound (-1)
short findEntryInSortedTable(CTabPtr theTable, short wEntry);
/*
* Add an entry to a color table. Returns TRUE if the entry was
* actually added (i.e. if the table's size went up), and FALSE if
* the entry wasn't added. The entry number is of course in the
* value field.
*
* For this one, the table really _does_ have to be indexed.
*/
Boolean addEntryToSortedIndexedTable(CTabHandle theIndexedTable, ColorSpec *theColorSpec);
/*
* Convert color storage modes back 'n' forth. These allocate memory
* and don't alter the original table.
*
* You can't switch to or from a paletted color table without knowing
* what the palette is, so no routines are provided for that.
*/
CTabHandle makeIndexedFromSequential(CTabHandle theSequentialTable);
CTabHandle makeSequentialFromSortedIndexed(CTabHandle theIndexedTable, RGBColor *fillColor);
/*
* Sort a table's entries. Does nothing if the table is sequential
* or paletted.
*/
void sortIndexedTable(CTabHandle theTable);
/*
* Compare two tables, even if they use different modes. Paletted
* tables can't be compared to anything, and so always return FALSE.
* If both tables are indexed, they must both be sorted.
*/
Boolean colorTablesAreEquivalent(CTabHandle table1, CTabHandle table2, RGBColor *fillColor);
/*
* Functions to manipulate the number of entries of a color table.
* The "get" function is simple, so it comes with a macro. The
* others alter the ctSize field and resize the handle; "set"
* sets the number of entries directly, while "change" adds or
* subtracts from the current number of entries. If the table's
* size changes, it (and memory) may be moved, even if it's
* locked. If the table is lengthened, the new entries contain
* garbage.
*/
short getNCTEntries(CTabPtr theTable);
#define getNCTEntries(theTable) ((theTable)->ctSize+1)
void setNCTEntries(CTabHandle theTable, short nEntries);
void changeNCTEntries(CTabHandle theTable, short nEntries);
/*
* Quickie macros to convert a table's depth to the maximum number of
* entries, and to convert a number of entries to a minimum depth.
*
* The function prototypes are only there to do a little parameter
* type-checking; since the macros do their conversion in place,
* the functions wouldn't actually do anything if you were to call
* them. (And if they took pointers instead of doing the work in
* place, you couldn't use register variables, ick.) If the functions
* ever actually _do_ get called, they pop into the debugger with
* an appropriate message.
*/
void convertDepthToMaxNEntries(short d, short n);
#define convertDepthToMaxNEntries(d,n) \
{ short ___depth=(d); \
for ((n)=1; ___depth>=1; --___depth) \
(n) <<= 1; }
void convertNEntriesToMinDepth(short n, short d);
#define convertNEntriesToMinDepth(n,d) \
{ short ___nEntries=(n); \
for ((d)=0; ___nEntries>1; ___nEntries>>=1) \
++(d); }
/*
* ColorTableUtils.c
*
* Copyright ) 1992 by Lawrence Productions, Inc. All Rights Reserved.
*
* This code may not be used in any for-profit program without the
* written permission of Lawrence Productions, Inc.
*
*/
/********************************/
#include "ColorTableUtils.h"
/********************************/
/*
* You'll need to put qsort.c in your project.
*/
#include <stdlib.h>
/********************************/
/*
* The only thing used from JamieUtilities.c is "jmemcmp()," which is
* just a clone of memcmp(). (I save 100 bytes of object code by
* taking it out of mem.c, because memcmp() is the only function in
* there that I would ever use. I guess I'm a fanatic.) Anyway, if
* you don't have JamieUtilities, just #include <string.h>, drop mem.c
* in your project, and change "jmemcmp" to "memcmp".
*/
#include <JamieUtilities.h>
/********************************/
short (getColorTableMode)(CTabPtr theTable)
{
ASSERT(theTable != NULL);
switch ( ((unsigned short) (theTable)->ctFlags) >> 14 ) {
case 0x00: return kIndexedColorTable; break;
case 0x01: return kPalettedColorTable; break;
case 0x02: return kSequentialColorTable; break;
default: ASSERT(0); return -1; break;
}
}
Boolean colorTableIsSorted(CTabPtr theTable)
{
register ColorSpec *theCTTable;
register short cPosition, nEntriesMinusOne, lastEntry;
ASSERT(theTable != NULL);
if (!colorTableIsIndexed(theTable)) {
return TRUE;
}
theCTTable = &theTable->ctTable[0];
nEntriesMinusOne = theTable->ctSize;
cPosition = 0;
lastEntry = -1;
for (cPosition = 0; cPosition <= nEntriesMinusOne; ++cPosition) {
register short thisEntry;
if ( (thisEntry=theCTTable[cPosition].value) < lastEntry) {
return FALSE;
} else {
lastEntry = thisEntry;
}
}
return TRUE;
}
/*
* Returns TRUE iff the entry was found. If the entry was not found,
* it returns the position where it should be inserted.
*/
Boolean engineFindEntryInSortedTable(CTabPtr tablePtr, register short wEntry, short *thePosition);
Boolean engineFindEntryInSortedTable(CTabPtr tablePtr, register short wEntry, short *thePosition)
{
/*
* I'm 99.9% sure this code will find an existing entry, but only
* 80% sure that it'll return the proper position for a nonexisting
* one, the proper position being the entry to the right. I suppose
* I should test it rigorously one of these days...
*/
register unsigned short cPosition;
register unsigned short leftBounds, rightBounds;
register ColorSpec *theCSpecArray;
if (!colorTableIsIndexed(tablePtr)) {
if (wEntry <= tablePtr->ctSize) {
*thePosition = wEntry;
return TRUE;
} else {
*thePosition = tablePtr->ctSize;
return FALSE;
}
}
assertColorTableIsSorted(tablePtr);
theCSpecArray = tablePtr->ctTable;
leftBounds = 0; rightBounds = tablePtr->ctSize + 1 - 1;
cPosition = rightBounds / 2;
while (leftBounds < rightBounds) {
if (theCSpecArray[cPosition].value == wEntry) {
*thePosition = cPosition;
return TRUE;
} else {
if (theCSpecArray[cPosition].value < wEntry) {
leftBounds = cPosition;
cPosition += rightBounds + 1;
cPosition >>= 1;
} else {
rightBounds = cPosition;
cPosition += leftBounds;
cPosition >>= 1;
}
}
}
/*
* If the requested entry is not there, we want the entry that's
* right _after_ where it would go.
*/
if (theCSpecArray[cPosition].value < wEntry) {
++cPosition;
}
ASSERT(cPosition == tablePtr->ctSize+1 || theCSpecArray[cPosition].value > wEntry);
ASSERT(cPosition == 0 || theCSpecArray[cPosition-1].value < wEntry);
*thePosition = cPosition;
return FALSE;
}
short findEntryInSortedTable(CTabPtr theTable, short wEntry)
{
short thePosition;
if (engineFindEntryInSortedTable(theTable, wEntry, &thePosition)) {
return thePosition;
} else {
return kNoEntryFound;
}
}
Boolean addEntryToSortedIndexedTable(CTabHandle theIndexedTable, ColorSpec *theColorSpec)
{
register CTabPtr theIndexedTabPtr;
short wEntry;
short thePosition;
ASSERT( colorTableIsIndexed(*theIndexedTable) );
wEntry = theColorSpec->value;
theIndexedTabPtr = *theIndexedTable;
if (engineFindEntryInSortedTable(theIndexedTabPtr, wEntry, &thePosition)) {
/* No need to add the entry, it's already there. */
theIndexedTabPtr->ctTable[thePosition] = *theColorSpec;
return FALSE;
} else {
long newSize;
newSize = sizeof(ColorTable)
+ sizeof(ColorSpec) * ( theIndexedTabPtr->ctSize + 1 );
SetHandleSize( (Handle) theIndexedTable, newSize );
theIndexedTabPtr = *theIndexedTable;
BlockMove( &theIndexedTabPtr->ctTable[thePosition],
&theIndexedTabPtr->ctTable[thePosition]+1,
(theIndexedTabPtr->ctSize+1 - thePosition) * sizeof(ColorSpec) );
theIndexedTabPtr->ctTable[thePosition] = *theColorSpec;
return TRUE;
}
}
CTabHandle makeIndexedFromSequential(CTabHandle theSequentialTable)
{
CTabHandle theIndexedTable;
register ColorSpec *theSequentialColorSpecPtr;
register ColorSpec *theIndexedColorSpecPtr;
register CTabPtr theSequentialTablePtr;
register CTabPtr theIndexedTablePtr;
register short cIndexedEntry;
register short nSequentialEntriesMinusOne;
ASSERT(theSequentialTable != NULL);
ASSERT(colorTableIsSequential(*theSequentialTable));
nSequentialEntriesMinusOne = (**theSequentialTable).ctSize;
theIndexedTable = (CTabHandle) NewHandle( sizeof(ColorTable)
+ sizeof(ColorSpec) * nSequentialEntriesMinusOne );
theIndexedTablePtr = *theIndexedTable;
theSequentialTablePtr = *theSequentialTable;
theIndexedTablePtr->ctSeed = theSequentialTablePtr->ctSeed;
theIndexedTablePtr->ctFlags = theSequentialTablePtr->ctFlags
& 0x3FFF
| 0x0000;
theIndexedTablePtr->ctSize = nSequentialEntriesMinusOne;
theIndexedColorSpecPtr = &theIndexedTablePtr->ctTable[0];
theSequentialColorSpecPtr = &theSequentialTablePtr->ctTable[0];
for (cIndexedEntry = 0;
cIndexedEntry <= nSequentialEntriesMinusOne;
++cIndexedEntry) {
theIndexedColorSpecPtr->value = cIndexedEntry;
(theIndexedColorSpecPtr++)->rgb = (theSequentialColorSpecPtr++)->rgb;
}
return theIndexedTable;
}
CTabHandle makeSequentialFromSortedIndexed(CTabHandle theIndexedTable, RGBColor *fillColor)
{
CTabHandle theSequentialTable;
register ColorSpec *theIndexedColorSpecPtr;
register ColorSpec *theSequentialColorSpecPtr;
register CTabPtr theIndexedTablePtr;
register CTabPtr theSequentialTablePtr;
register short cSequentialEntry, nextIndexedEntry, nextIndexedPosition;
register short nIndexedEntriesMinusOne, nSequentialEntriesMinusOne;
ASSERT(theIndexedTable != NULL);
ASSERT(colorTableIsIndexed(*theIndexedTable));
assertColorTableIsSorted(*theIndexedTable);
nIndexedEntriesMinusOne = (**theIndexedTable).ctSize;
nSequentialEntriesMinusOne =
(**theIndexedTable).ctTable[nIndexedEntriesMinusOne].value;
theSequentialTable = (CTabHandle) NewHandle( sizeof(ColorTable)
+ sizeof(ColorSpec) * nSequentialEntriesMinusOne );
theSequentialTablePtr = *theSequentialTable;
theIndexedTablePtr = *theIndexedTable;
theSequentialTablePtr->ctSeed = theIndexedTablePtr->ctSeed;
theSequentialTablePtr->ctFlags = theIndexedTablePtr->ctFlags
& 0x3FFF
| 0x8000;
theSequentialTablePtr->ctSize = nSequentialEntriesMinusOne;
theSequentialColorSpecPtr = &theSequentialTablePtr->ctTable[0];
theIndexedColorSpecPtr = &theIndexedTablePtr->ctTable[0];
nextIndexedPosition = 0;
nextIndexedEntry = theIndexedColorSpecPtr[0].value;
for (cSequentialEntry = 0;
cSequentialEntry <= nSequentialEntriesMinusOne;
++cSequentialEntry) {
ASSERT(cSequentialEntry <= nextIndexedEntry);
if (cSequentialEntry == nextIndexedEntry) {
theSequentialColorSpecPtr->value = cSequentialEntry;
(theSequentialColorSpecPtr++)->rgb = (theIndexedColorSpecPtr++)->rgb;
if (++nextIndexedPosition > nIndexedEntriesMinusOne) {
nextIndexedEntry = MAXINT;
} else {
nextIndexedEntry = theIndexedColorSpecPtr->value;
}
} else {
theSequentialColorSpecPtr->value = 0;
(theSequentialColorSpecPtr++)->rgb = *fillColor;
}
}
return theSequentialTable;
}
static int compareColorSpecValues(const ColorSpec *color1, const ColorSpec *color2);
static int compareColorSpecValues(register const ColorSpec *color1,
register const ColorSpec *color2)
{
if (color1->value != color2->value) {
if (color1->value < color2->value) {
return -1;
} else {
return 1;
}
}
return 0;
}
void sortIndexedTable(CTabHandle theTable)
{
register CTabPtr theTablePtr;
short oldState;
ASSERT(theTable != NULL);
theTablePtr = *theTable;
if (!colorTableIsIndexed(theTablePtr)) {
return ;
}
oldState = HGetState( (Handle) theTable );
HLock( (Handle) theTable);
qsort( &theTablePtr->ctTable[0],
theTablePtr->ctSize+1,
sizeof(ColorSpec),
(__cmp_func) compareColorSpecValues);
HSetState( (Handle) theTable, oldState );
assertColorTableIsSorted(theTablePtr);
}
Boolean colorTablesAreEquivalent(CTabHandle table1, CTabHandle table2, RGBColor *fillColor)
{
Boolean areEquivalent;
ASSERT(table1 != NULL);
ASSERT(table2 != NULL);
areEquivalent = TRUE;
if (colorTableIsPaletted(*table1) || colorTableIsPaletted(*table2)) {
/* Paletted tables can't be compared to anything. */
return FALSE;
}
if (colorTableIsSequential(*table1) || colorTableIsSequential(*table2)) {
/*
* Convert one of the tables to sequential, if need be, and compare.
*/
register CTabPtr t1, t2;
register short nEntriesMinusOne;
CTabHandle convertedTable;
convertedTable = NULL;
if (colorTableIsIndexed(*table1)) {
assertColorTableIsSorted(*table1);
convertedTable = makeSequentialFromSortedIndexed(table1, fillColor);
t1 = *convertedTable;
t2 = *table2;
} else if (colorTableIsIndexed(*table2)) {
assertColorTableIsSorted(*table2);
convertedTable = makeSequentialFromSortedIndexed(table2, fillColor);
t1 = *table1;
t2 = *convertedTable;
}
if ( (nEntriesMinusOne=t1->ctSize) != t2->ctSize) {
areEquivalent = FALSE;
} else {
register short cEntry;
for (cEntry = 0; cEntry <= nEntriesMinusOne; ++cEntry) {
/*
* When comparing sequential tables, ignore the value field.
*/
if ( t1->ctTable[cEntry].rgb.red != t2->ctTable[cEntry].rgb.red
|| t1->ctTable[cEntry].rgb.green != t2->ctTable[cEntry].rgb.green
|| t1->ctTable[cEntry].rgb.blue != t2->ctTable[cEntry].rgb.blue ) {
areEquivalent = FALSE;
break;
}
}
}
DisposHandle( (Handle) convertedTable );
} else {
/*
* Leave both tables indexed, and compare. Assume they're sorted.
*/
register CTabPtr t1, t2;
register short nEntriesMinusOne;
t1 = *table1;
t2 = *table2;
assertColorTableIsSorted(t1);
assertColorTableIsSorted(t2);
if ( (nEntriesMinusOne=t1->ctSize) != t2->ctSize) {
areEquivalent = FALSE;
} else {
register short cEntry;
areEquivalent = ( jmemcmp( // jmemcmp() is just a memcmp() clone
&t1->ctTable[0],
&t2->ctTable[0],
sizeof(ColorSpec)*(nEntriesMinusOne+1)
) == 0);
#if you_want_it_spelled_out_for_you
for (cEntry = 0; cEntry <= nEntriesMinusOne; ++cEntry) {
if ( t1->ctTable[cEntry].value != t2->ctTable[cEntry].value
|| t1->ctTable[cEntry].rgb.red != t2->ctTable[cEntry].rgb.red
|| t1->ctTable[cEntry].rgb.green != t2->ctTable[cEntry].rgb.green
|| t1->ctTable[cEntry].rgb.blue != t2->ctTable[cEntry].rgb.blue ) {
areEquivalent = FALSE;
break;
}
}
#endif
}
}
return areEquivalent;
}
short (getNCTEntries)(CTabPtr theTable)
{
return theTable->ctSize + 1;
}
void setNCTEntries(CTabHandle theTable, short nEntries)
{
short oldState;
ASSERT(nEntries >= 0);
ASSERT(nEntries <= 256); // arbitrary
if (getNCTEntries(*theTable) == nEntries) return;
(**theTable).ctSize = nEntries-1;
oldState = HGetState( (Handle) theTable );
HUnlock( (Handle) theTable );
SetHandleSize( (Handle) theTable,
sizeof(ColorTable) + (nEntries-1)*sizeof(ColorSpec));
HSetState( (Handle) theTable, oldState);
}
void changeNCTEntries(CTabHandle theTable, short nEntries)
{
if (nEntries == 0) return;
setNCTEntries(theTable, getNCTEntries(*theTable) + nEntries);
}
void (convertDepthToMaxNEntries)(short d, short n)
{
DebugStr("\pconvertDepthToMaxNEntries was somehow called!");
}
void (convertNEntriesToMinDepth)(short n, short d)
{
DebugStr("\pconvertNEntriesToMinDepth was somehow called!");
}
+++++++++++++++++++++++++++
From: k044477@hobbes.kzoo.edu (Jamie R. McCarthy)
Organization: Kalamazoo College
Date: Fri, 4 Sep 1992 20:49:09 GMT
k044477@hobbes.kzoo.edu (Jamie R. McCarthy) writes:
>This article starts off with some AppleLink mail from Forrest Tanaka,
>telling you more than you ever wanted to know about color tables, and
>ends with a fair amount of ANSI C source code for manipulating them.
I've already (sigh) found several bugs in my code. If you want an
updated version, email me.
- --
Jamie McCarthy Internet: k044477@kzoo.edu AppleLink: j.mccarthy
The same people who love MS-DOS so much that they went to PC Expo,
supported Ross Perot by an overwhelming margin. This should be
telling you something.
---------------------------
From: neath@brazil.psych.purdue.edu (Ian Neath)
Subject: Keeping the cursor visible
Date: 1 Sep 92 15:15:44 GMT
Organization: Purdue University
I have an application that cranks through a simulation model. Typically,
it takes around an hour to do each run. I have set up an animated cursor
to let me know the program is still cranking, but everytime the app
writes to the TextEdit record, the cursor is hidden by (I assume) a
call to ObscureCursor. Is it OK to keep calling ShowCursor to get
my animated cursor back? IM says to balance ShowCursor with Hide-
or ShieldCursor (or vice versa). My app seems to run fine, but since
it takes so long to do each run, I don't want the program to bomb.
Any advice, hints, etc appreciated. Thanks.
- -ian
- --
Ian Neath, PhD | There are four kinds of people in this world:
neath@psych.purdue.edu | cretins, fools, morons and lunatics - U. Eco
+++++++++++++++++++++++++++
From: wombat@claris.com (Scott Lindsey)
Date: 2 Sep 92 01:14:13 GMT
Organization: Claris Corporation, Vancouver WA
In article <Btwnq8.LMv@mentor.cc.purdue.edu>, neath@brazil.psych.purdue.edu (Ian Neath) writes:
>
> writes to the TextEdit record, the cursor is hidden by (I assume) a
> call to ObscureCursor. Is it OK to keep calling ShowCursor ...
ShowCursor won't actually show the cursor if it's only obscured. I don't
think there's a legal way to unobscure a cursor, however, setting the low-
memory global CrsrNew = 0xFF forces it to really redraw. (CrsrNew is 0x8CE and
is a 1-byte value).
- --
Scott Lindsey <wombat@claris.com>
+++++++++++++++++++++++++++
From: d88-jwa@dront.nada.kth.se (Jon W{tte)
Date: 2 Sep 92 12:33:30 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
@claris.com (Scott Lindsey) writes:
ShowCursor won't actually show the cursor if it's only obscured. I don't
think there's a legal way to unobscure a cursor, however, setting the low-
memory global CrsrNew = 0xFF forces it to really redraw. (CrsrNew is 0x8CE
and is a 1-byte value).
How abotu just calling InitCursor?
It sets the cursor to an arrow, and shows it (and clears
the show/hide count) and then you can call SetCursor to
set it to the shape you want.
- --
Jon W{tte, h+@nada.kth.se, Sweden, Phone +46-8-107069
White, Literate, Employed, Higher-Educated, Male, Straight and Not Poor.
I must be a bad guy.
+++++++++++++++++++++++++++
From: lari@strauss.cs.unc.edu (Humayun Lari)
Date: 2 Sep 92 21:54:21 GMT
Organization: The University of North Carolina at Chapel Hill
In article <15119@claris.com> wombat@claris.com (Scott Lindsey) writes:
>In article <Btwnq8.LMv@mentor.cc.purdue.edu>, neath@brazil.psych.purdue.edu (Ian Neath) writes:
>>
>> writes to the TextEdit record, the cursor is hidden by (I assume) a
>> call to ObscureCursor. Is it OK to keep calling ShowCursor ...
>
>ShowCursor won't actually show the cursor if it's only obscured. I don't
>think there's a legal way to unobscure a cursor, however, setting the low-
>memory global CrsrNew = 0xFF forces it to really redraw.
If you're in charge of the writes to the TextEdit record (i.e. using TEKey),
you could use TEInsert instead to prevent TextEdit from trying to be polite
and calling ObscureCursor. Of course, TEInsert may be a bit slower, but in
practice it seems to make little difference. And it's definitely *much* cleaner
than having the cursor flicker every time a character is appended to the TE
record (especially if you're porting a MS-DOS-based language interpreter that
thinks a row of dots on the screen is a beautiful depiction of its progress).
Humayun Lari
(lari@cs.unc.edu)
+++++++++++++++++++++++++++
From: wombat@claris.com (Scott Lindsey)
Date: 4 Sep 92 23:44:50 GMT
Organization: Claris Corporation, Vancouver WA
In article <D88-JWA.92Sep2133330@dront.nada.kth.se>, d88-jwa@dront.nada.kth.se (Jon W{tte) writes:
>
> @claris.com (Scott Lindsey) writes:
>
> ShowCursor won't actually show the cursor if it's only obscured. I don't
> think there's a legal way to unobscure a cursor, however, setting the low-
> memory global CrsrNew = 0xFF forces it to really redraw. (CrsrNew is 0x8CE
> and is a 1-byte value).
>
> How abotu just calling InitCursor?
>
> It sets the cursor to an arrow, and shows it (and clears
> the show/hide count) and then you can call SetCursor to
> set it to the shape you want.
I've lost the original message, but I think the issue was a progress cursor
(beachball or something). In fact, in ClarisWorks, I use CrsrNew to show the
cursor whenever the beachball comes up, just in case the cursor was obscured.
That way, you won't be sitting there with an obscured spinning beachball.
- --
Scott Lindsey <wombat@claris.com>
---------------------------
From: Ray.Arachelian@f204.n2603.z1.ieee.org (Ray Arachelian)
Subject: Zbasic+System 6/7 Speed
Organization: FidoNet node 1:2603/204 - Not Even Odd, Forest Hills NY
Date: Sat, 22 Aug 1992 20:25:01 GMT
Most of you won't be familiar with Zedcor's Zbasic. A fine BASIC
compiler, but perhaps you could throw in some hints about performance
problems with System 7 which didn't exist under System 6.
After a few months of System 7 use, I did install System 6.0.7 on a
Syquest cartridge so that I'd be able to test some software I'd written
with Zedcor's ZBasic with System 6, to make sure I didn't put in any
inadvertent incompatibilities (of which I did find one and fix it.)
I saw that the program ran about 3 times faster than under System 7! What
exactly gets a program that was compiled with ZBasic that slow down so
much in System 7 yet run so well under 6?
Currently I had to implement double buffering of the modem and keyboard in
order to get better performance. I'm running this on a IIcx which by no
means is a slow machine. No a Quadra, but still faster than a Plus no
less.
Having called Zedcor, I've been told they're "never" going to release
ZBasic 6.0. It will be called something like "Future" basic, and just as
the last month's call confirmed their oppinion, "it will be available next
month." :-)
Is there something ZBasic does wrong in terms of WaitNextEvent or
GetNextEvent? Certainly with ZBasic you have almost no control over these
commands, as it does it's own event handling to buffer you away from the
tool box. This is good for new programmers, but gets very cumbersome with
me.
How about the text writing routines (not TEdit routines, quickdraw text
printing routines.) Have they been slowed down in System 7 with TType?
I'm trying to track down the problem and perhaps lessen its effects if not
remove it. Another thing I notice is that if I have any INIT's or CDEVs
that grab the keyboard (QuickKeys, etc) the program slows down to hell.
I'm grabbing keystrokes via system events (IE: DIALOG(16) function in
ZBasic.)
I'd hate to do so, but if I must I'll go in there with ResEdit and force
Zbasic to produce the proper calls to WaitNextEvent with less of a delay
time slice give up. Without doubt, I don't want to force my (potential)
users to run this software under System 6.0.x :-)
Any ideas would be greatly appreciated.
* Freddie 1.3b2 * Do what thou whim shalt be a hole in the head!
- --
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ray Arachelian - Internet: Ray.Arachelian@f204.n2603.z1.ieee.org
+++++++++++++++++++++++++++
From: mxmora@unix.SRI.COM (Matt Mora)
Date: 25 Aug 92 16:03:14 GMT
Organization: SRI International, Menlo Park, California
In article <15639.2A996B26@zeus.ieee.org> Ray.Arachelian@f204.n2603.z1.ieee.org (Ray Arachelian) writes:
>Is there something ZBasic does wrong in terms of WaitNextEvent or
>GetNextEvent? Certainly with ZBasic you have almost no control over these
>commands, as it does it's own event handling to buffer you away from the
>tool box. This is good for new programmers, but gets very cumbersome with
>me.
Yes it calls WNE/GNE before every line of your basic code. Not very
efficient. Don't worry about it. Wait for future basic and
upgrade as soon as you can.
Matt
- --
___________________________________________________________
Matthew Mora | my Mac Matt_Mora@sri.com
SRI International | my unix mxmora@unix.sri.com
___________________________________________________________
+++++++++++++++++++++++++++
From: Ray.Arachelian@f204.n2603.z1.ieee.org (Ray Arachelian)
Date: 30 Aug 92 20:30:07 GMT
Organization: FidoNet node 1:2603/204 - Not Even Odd, Forest Hills NY
On 08-25-92, MXMORA@UNIX.SRI.COM wrote to ALL:
M> Yes it calls WNE/GNE before every line of your basic code. Not very
M> efficient. Don't worry about it. Wait for future basic and upgrade
M> as soon as you can.
I do plan to get Future Basic, however, I've no intention of waiting
around every time they tell me "Next Month" :-) I did find out what they
do wrong. They not only call _GetNextEvent on every line, but they also
make a LOT of calls to _SystemTask. I've even found a timing routine
where they check the timer, and call _SystemTask over and over again.
This really slows things down under System 7.... I've also tried to
replace this with a call to WaitNextEvent, however, all I've managed to do
was crash the machine. :-) See my other messages about patching...
* Freddie 1.3b2 * Do what thou whim shalt be a hole in the head!
- --
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ray Arachelian - Internet: Ray.Arachelian@f204.n2603.z1.ieee.org
+++++++++++++++++++++++++++
From: Glen.Stewart@f175.n2240.z1.ieee.org (Glen Stewart)
Date: 25 Aug 92 14:21:24 GMT
Organization: FidoNet node 1:2240/175 - The Associati, Grand Blanc MI
Zedcor may have led you astray. I've been calling them on and off for the
past 6 months. They have always told me that they ARE doing Zbasic 6.0!
In fact, they told me late last week, that they have sent the upgrade notices
to all the old users, and that 6.0 is now basically complete.
Look forward to increased support for HyperCard externals!
- --
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Glen Stewart - Internet: Glen.Stewart@f175.n2240.z1.ieee.org
+++++++++++++++++++++++++++
From: Ray.Arachelian@f204.n2603.z1.ieee.org (Ray Arachelian)
Date: 2 Sep 92 20:42:01 GMT
Organization: FidoNet node 1:2603/204 - Not Even Odd, Forest Hills NY
Generally, when I've called Zedcor, a female voice answered and told me "Not
Yet." The "Future Basic" rumor as it may be was by a male voice. This was
when I called on the weekend, so I assumed it was perhaps one of their long
hour programmers.
However the deadline seems to have lessened. Yesterday's call told me
"Middle
of this month" instead of "Next Month" so things are indeed getting
better :-)
- --
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ray Arachelian - Internet: Ray.Arachelian@f204.n2603.z1.ieee.org
---------------------------
From: mcnichol@terminator.psy.syr.edu (Brendan T. McNichols)
Subject: Function missing from MPW C library?
Date: Thu, 23 Jul 92 13:27:49 EDT
Hi all,
I am getting the following error message when building a project using
MPW C:
### Link: Error: Undefined entry, name: (Error 28) "str2dec"
Referenced from: _doscan in file: Alliance Drive
:Development:MPW:Libraries:CLibraries:CLib881.o
### Link: Errors prevented normal completion.
### MPW Shell - Execution of KLSyn88.makeout terminated.
### MPW Shell - Execution of BuildProgram terminated.
It seems to me that this means that the function "str2dec" is missing
from the CSANELib881.o library. (It is declared in SANE.h.) I am new
using MPW and I'm not sure if there's something here that I should have
done but didn't. Does anyone know how to fix this problem? Is str2dec
located in some other library? Can I get the code for str2dec and
include it in the CSANELib881.o library?
Thanks very much for any help,
Brendan
- --
Brendan T. McNichols, Computer Support (315) 443-9902
Psyracuse U. Sychology Dept. mcnichol@psy.syr.edu (NeXT)
430 Huntington Hall mcnichol@syr.edu
Syracuse, NY 13244
+++++++++++++++++++++++++++
From: keith@taligent.com (Keith Rollin)
Date: 24 Jul 92 19:38:37 GMT
Organization: Taligent
In article <1992Jul23.132750.12392@newstand.syr.edu>,
mcnichol@terminator.psy.syr.edu (Brendan T. McNichols) writes:
>
> I am getting the following error message when building a project using
> MPW C:
>
> ### Link: Error: Undefined entry, name: (Error 28) "str2dec"
> Referenced from: _doscan in file: Alliance Drive
> :Development:MPW:Libraries:CLibraries:CLib881.o
> ### Link: Errors prevented normal completion.
> ### MPW Shell - Execution of KLSyn88.makeout terminated.
> ### MPW Shell - Execution of BuildProgram terminated.
>
> It seems to me that this means that the function "str2dec" is missing
> from the CSANELib881.o library. (It is declared in SANE.h.) I am new
> using MPW and I'm not sure if there's something here that I should have
> done but didn't. Does anyone know how to fix this problem? Is str2dec
> located in some other library? Can I get the code for str2dec and
> include it in the CSANELib881.o library?
There seem to b versions of str2dec in {Libraries}Runtime.o and
{PLIbraries}PasLib.o. Whenever I have problems finding a library routine, I use
the following script.
Set Exit 0
Set SearchExpression "`Request "Enter regular expression" || Echo '""'`"
Exit if "{SearchExpression}" == ""
For folder in "{Libraries}" "{PLibraries}" "{CLibraries}"
Echo "Searching in {folder}"
For file In `files -f -s -t "OBJ " "{folder}"`
DumpObj -mods "{file}" | Search -nf /{SearchExpression}/ opt-3opt3 Dev:Null
If {status} == 0
Echo "DumpObj opt-d"{file}opt-d" -m {SearchExpression}"
End
End
End opt-wopt-w "{WorkSheet}"
Set Exit 1
- --
Keith Rollin
Phantom Programmer
Taligent, Inc.
---------------------------
End of C.S.M.P. Digest
**********************