From: pottier@clipper.ens.fr (Francois Pottier)
Subject: csmp-digest-v3-042
Date: Tue, 5 Jul 1994 14:50:36 +0200 (MET DST)

C.S.M.P. Digest             Tue, 05 Jul 94       Volume 3 : Issue 42
 
Today's Topics:
 
        **Novice Question on saving files**
        CODE Resources
        Code Resources with CodeWarrior
        MacTCP DNR for PowerPC?
        Major bug with Symantec CDK *Please Read*
        Perspective in GX (was Re: can toolbox draw text at an angle?)
        Still trouble finding floating windows code.
        _vSyncWait infinite loop?
        can toolbox draw text at an angle?



The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
 
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.  If you don't have access to news, you may
still be able to post messages to the group by using a mail server like
anon.penet.fi (mail help@anon.penet.fi for more information).
 
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
nef.ens.fr).  Article threads are not added to the digest until the last
article added to the thread is at least two weeks 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 digest is officially distributed by two means, by email and ftp.

If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
    help		                Sends you a summary of commands
    subscribe csmp-digest Your Name	Adds you to the mailing list
    signoff csmp-digest			Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.

The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
digest are available there.

Also, the digests are available to WAIS users.  To search back issues
with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use
http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html.


-------------------------------------------------------

>From ftrogers@eos.ncsu.edu (FRANKLIN TAREK ROGERS)
Subject: **Novice Question on saving files**
Date: 21 Jun 1994 13:21:32 GMT
Organization: North Carolina State University, Project Eos




I'm trying to save data into a file, and am having trouble understanding
the underlying concepts.  Inside Macintosh "Files"  gives a verty detailed
discussion on the subject, but all example deal only with TextEdit.
  The FSWrite command takes a pointer to a data buffer:
    What is a data buffer?  Just any allocated block of memory?

The data I wish to save is all contained within one data structure,
(memory allocated with NewPointer).  Basically what I've got is:
    typedef struct myStruct
	{
        StringPtr aString1, aString2...
	}

Is a data struct of strings considered a data buffer my the OS or do I need
to cram my info into some particular form.  Also, how would I find the
size of the data buffer when not TextEdit?

Thanks,
F. Tarek Rogers
ftrogers@eos.ncsu.edu

+++++++++++++++++++++++++++

>From Rick_Holzgrafe@taligent.com (Rick Holzgrafe)
Date: Tue, 21 Jun 1994 18:38:58 GMT
Organization: Semicolon Software

In article <2u6pgs$k9c@taco.cc.ncsu.edu>, ftrogers@eos.ncsu.edu (FRANKLIN
TAREK ROGERS) wrote:

> I'm trying to save data into a file, and am having trouble understanding
> the underlying concepts.  Inside Macintosh "Files"  gives a verty detailed
> discussion on the subject, but all example deal only with TextEdit.
>   The FSWrite command takes a pointer to a data buffer:
>     What is a data buffer?  Just any allocated block of memory?

Right. The pointer can in fact point to any memory you please, even to a
local variable if that's what you want to write out.

> The data I wish to save is all contained within one data structure,
> (memory allocated with NewPointer).  Basically what I've got is:
>     typedef struct myStruct
> 	{
>         StringPtr aString1, aString2...
> 	}

You could write out the entire struct by passing a pointer to it to
FSWrite, getting its size from 'sizeof myStruct'. However, that's not what
you want to do, because your structure contains only the pointers to the
strings, and not the strings' contents. To write out the strings, call
FSWrite once for each string, like this:

   long dataLength = (((long)myStruct.aString1[0]) & 0xff) + 1;
   FSWrite (refNum, &dataLength, (ptr)myStruct.aString1);

The example assumes that your strings are in Pascal format, so that the
first byte of the string gives the string's length. The part about '&0xff'
ensures that you don't get a negative length for strings that have the high
bit set in their length byte; it isn't always necessary but better safe
than sorry.

The example also writes each string out with its proper length: no disk
space is wasted. This means that when you read the strings back in, you'll
have to read the length byte first to see how long the string actually is.
An alternative is to always write out 256 bytes for each string (or perhaps
some shorter length guaranteed to be long enough for your purposes). This
wastes some space but ensures a simpler and easier-to-read file format.
Normally I wouldn't recommend wantonly wasting space but if it's just a few
strings the wastage may not be significant.

> how would I find the
> size of the data buffer when not TextEdit?

That entirely depends on the nature and source of the data. The solution
for Pascal strings is shown above.

> F. Tarek Rogers
> ftrogers@eos.ncsu.edu

-- Rick Holzgrafe, a member of the Taligentsia
   Rick_Holzgrafe@taligent.com
   rmh@taligent.com

---------------------------

>From Bill McCloskey <billm@interaccess.com>
Subject: CODE Resources
Date: 19 Jun 1994 01:14:55 GMT
Organization: ???

If I was going to write a 'CODE' resource in Think C, how could I execute
it in my program? Also, are there any examples for this anywhere?

Thanks for any help,
-Bill

+++++++++++++++++++++++++++

>From Mark Hanrek <hanrek@cts.com>
Date: Sun, 19 Jun 1994 05:08:25 GMT
Organization: The Information Workshop

In article <2u066f$avl@mailhost.interaccess.com> Bill McCloskey,
billm@interaccess.com writes:

> If I was going to write a 'CODE' resource in Think C, how could I
> execute it in my program? Also, are there any examples for this
> anywhere?

You would certainly want to copy the way it is done in some example
source code.  I prepared an ansewr to a question like yours before, so
I've attached it below.  It is ready to be pasted in and compiled.

Also, in your questions, you could have meant >> 'CODE' << literally or
figuratively.  Just in case, I wanted to mention that resources of type
'CODE' should remain reserved for the traditional way applications are
constructed, so I figure you are asking how you wuld create a custom code
resource with a resource type of, say, 'CoDe', or XCMD, or 'bill' or
whatever. :)

There are examples around. Be sure to look in the source code folder
under "dev" in sumex and elsewhere.

Hope this helps.

Mark Hanrek


===================================================================
Calling a Code Resource from an Application


//
//  First, determine and define the interface you would like. 
//  For instance...
//

typedef pascal OSErr (*CodeResourceProcPtr)( long param1, short param2 );


//
//  Here's a function in your application that will load and call that
//  kind of code resource, which you've compiled separately.
//


OSErr CallCodeResource( long param1, short param2 )
{
  Handle               theCodeResource;
  CodeResourceProcPtr  theEntryPoint;
  OSErr                err;

  // Get it

  theCodeResource = GetResource( 'bill', 128 );
  if ( err = ResError())
     return( err );

  // Position it

  DetachResource( theCodeResource );
  MoveHHi( theCodeResource );
  HLock( theCodeResource );
   
  // Locate it and Strip it

  theEntryPoint = (CodeResourceProcPtr) StripAddress( *theCodeResource );

  // Jump into it

  err = (*theEntryPoint)( param1, param2 ); 

  // Dispose of it

  HUnlock( theCodeResource );
  DisposeHandle( theCodeResource );

  return( err );
}



- ----------------------------------------------------------
The Code Resource Itself


// Your code resource, compiled separately, would start
// life like this...


#include <SetUpA4.h>

pascal OSErr main( long param1, short param2 );

pascal OSErr main( long param1, short param2 )
{
	RememberA0();
	SetUpA4();


    // bla bla bla


    RestoreA4();
    return( err );
}



- ----------------------------------------------------------
Setup for Separately Compiled Code Resources


In the "Set Project Type..." dialog, type "bill" into 
the code resource type, do NOT check custom header,
make sure "purgeable" is checked, and give it any name
or id you like.

The ID can be important.  If you check "multi-segment" code
resource, you have to be sure your code resource's id
is less that 64, and it does the numbering so that the
resource manager can determine at runtime which segments
belong to this code resource.  There is no other "contect"
to worry about or set up to worry about.

There are other resource numbering rules, but it I think
the important thing is to not every use 'CODE'.


- ----------------------------------------------------------
Other Notes


Think C provides a nice way of dealing with the interface 
to code resources.  All you'll have to do to the above is
change 'bill' to whatever you want, change the data type
and number of parameters you'll be needing, and the data
type of the return value, ( or void ).  That's it!

Intead of using DetachResource / DisposeHandle, you could 
also just ReleaseResource it when you are done with it,
which will save on disk thrashing if you will be accessing
it a number of times.

And don't forget the keyword 'pascal' in the typedef!  You
could look at your code all day long and not catch that one!

:) :)   Have fun.  


Mark Hanrek
The Information Workshop

+++++++++++++++++++++++++++

>From oster@netcom.com (David Phillip Oster)
Date: Mon, 20 Jun 1994 15:52:59 GMT
Organization: Netcom Online Communications Services (408-241-9760 login: guest)


Mark Hanrek <hanrek@cts.com> posted a code example of calling a code resource.
It contained some errors:
1.) it called DetachResource at the beginning and DisposHandle at the end.
It is often better to omit these two steps, and just do a HGetState() at
the beginning and an HSetState() at the end.

2.) It assumes that both the calling C program and the code resource are
either both 680x0 code or both PowerPC code. If there is a chance that they
might be mixed, you need to call the code resource slightly differently.
This is fully documented in the PowerPC volume of InsideMac. You also might
want to consider creating a "fat" code resource, chich contains both 680x0
and PowerPC instructions so it it will run at top speed no matter who calls

+++++++++++++++++++++++++++

>From Kevin.R.Boyce@gsfc.nasa.gov (Kevin R. Boyce)
Date: Mon, 20 Jun 1994 12:38:47 -0400
Organization: NASA/GSFC

Mark Hanrek <hanrek@cts.com> wrote:

> In article <2u066f$avl@mailhost.interaccess.com> Bill McCloskey,
> billm@interaccess.com writes:
> 
> > If I was going to write a 'CODE' resource in Think C, how could I
> > execute it in my program? Also, are there any examples for this
> > anywhere?
> 
> You would certainly want to copy the way it is done in some example
> source code.  I prepared an ansewr to a question like yours before, so
> I've attached it below.  It is ready to be pasted in and compiled.

[Sample code that is almost identical to my own stock answer deleted.]

There is one other thing you need to be aware of, if you are using any
system callbacks in your code resource.  (System callbacks are things like
dialog filters, that get called from within an OS/Toolbox routine that you
call.)  The problem is that the system may have messed with A4 before
calling your callback routine, so you have to set it up within the
callback.  

Here is the second half of my stock answer, where I discuss this in detail:

And one final (very important) point is that the A4 routines are static
(they only apply to the file in which they appear).  So if you need to
use SetUpA4() in a file other than the one which called RememberA0(),
you need to call RememberA4() (NOT RememberA0()) from within that file,
sometime before the call to SetUpA4().  Uh, maybe an example would
help (this also demonstrates how to return the value of a global)...

- - file MainCode.c ---
#include <SetUpA4.h>
char	aGlobal;

char main(long foo)		/* Wants to return value of aGlobal */
{
	char	retVal;
	
	RememberA0();
	SetUpA4();
	...
	DoSomeDialog();
	...
	retVal = aGlobal;	/* Have to do this while A4 is still valid! */
	RestoreA4();		/* A4 no longer points to our global area */
	return retVal;		/* But local (automatic) variables are still ok */
}


- - file MyDialogs.c ---

#include <SetUpA4.h>
extern short	aGlobal;

void DoSomeDialog()
{
	DialogPtr	theDialog;
	short		itemHit;
	
	RememberA4();		/* Save A4 for functions in this file. */
	theDialog = GetNewDialog( dlgRsrcID, nil, (WindowPtr)-1 );
	ModalDialog( myFilter, &itemHit );
	...
	return;
}

pascal Boolean MyFilter(DialogPtr theDlg, EventRecord *theEvent, short
*itemHit )
{
	Boolean	status;
	
	SetUpA4();
	
	if ( theEvent->what == keyDown ) {
		aGlobal = (theEvent->message) & charCodeMask;
		*itemHit = ok;
		status = TRUE;
	} else {
		status = FALSE;
	}
	RestoreA4();
	return status;
}


-- 
Kevin      Kevin.R.Boyce@gsfc.nasa.gov
I then suspended the assembly by the edges of the CD, and began filling
the box with Inside Macintosh volumes. --Kevin Bell

+++++++++++++++++++++++++++

>From Mark Hanrek <hanrek@cts.com>
Date: Tue, 21 Jun 1994 08:45:55 GMT
Organization: The Information Workshop

In article <osterCrpDGC.7K4@netcom.com> David Phillip Oster,
oster@netcom.com writes:

>It contained some errors:
>1.) it called DetachResource at the beginning and DisposHandle at the
end.
>It is often better to omit these two steps, and just do a HGetState() at
>the beginning and an HSetState() at the end.
>
>2.) It assumes that both the calling C program and the code resource are
>either both 680x0 code or both PowerPC code. If there is a chance that
they
>might be mixed, you need to call the code resource slightly differently.
>This is fully documented in the PowerPC volume of InsideMac. You also
might
>want to consider creating a "fat" code resource, chich contains both
680x0
>and PowerPC instructions so it it will run at top speed no matter who
calls

David,

Neither are errors.  Errors are where you do something wrong.

The first is a situational kind of thing.

As for the PowerPC concerns, that is not appropriate here, because the
Bill asked how to call a code resource, and he was given just what he
needs to be successful.

The objective in answering questions is to hopefully make it so the
answer makes whatever it is seem like a piece of cake.

My DetachResource approach isolates him from Resource Manager concerns so
this does not foul up his first experiences.  Moving the handle high also
eliminates memory fragmentation concerns. By and by, he will know as much
about it as you or I and be answering questions himself. :)

Not only that, if he wanted to take advantage of what you mentioned, how
would he do that?  All you did was mention that there was a concern, and
a reference to HGetState.

Kevin on the other hand, rather than simply mentioning that there are
concerns with dialog callbacks, laid it all out in black and white, and
very clearly.  A piece of cake. :)


Mark Hanrek

P.S. There were, though, tons of editing errors in my post. Something
must have gone wrong with the editor.  ( yeah, right :)

---------------------------

>From will@cs.su.oz.au (William Uther)
Subject: Code Resources with CodeWarrior
Date: 20 Jun 1994 16:16:24 +1000
Organization: Basser Dept of Computer Sciece, Uni of Sydney, Australia

Hi,
  I've just been trying to covert a THINK C 6.0 Code Resource to CodeWarrior.
I'm using the 68k DR3.  I've set the prefs up to produce a code resource and
included all the files.
  When I test the code resource it doesn't work.  The A4 world is set up by the
program calling the code resource.  And seems to be correct.  One of the first
things the code resource does is call TextBox to display a debug string.
The call is in the assembler - but it doesn't come up.  I have no idea
wot's wrong.  There are NO compile or link errors.

Are there any bugs in DR3 with code resources, or is there some strange thing I
have to set - I've RTFM'd but there really isn't much there.

\x/ill            :-}


+++++++++++++++++++++++++++

>From rang@winternet.com (Anton Rang)
Date: 20 Jun 1994 12:27:49 GMT
Organization: Minnesota Angsters

In article <2u3c7o$6sh@staff.cs.su.oz.au> will@cs.su.oz.au (William Uther) writes:
>When I test the code resource it doesn't work.  The A4 world is set
>up by the program calling the code resource.  And seems to be
>correct.

  You say the A4 world is set up by the *caller*?  Are you following
the CodeWarrior rules on this?  (They're different from THINK.)  In
THINK C, the A4 register needs to point to the beginning of the code
resource.  I don't recall the CW rules for sure, but it's definitely
different, more along the lines of 'A4 = the end plus $8000'.  (Run
one of the examples that uses A4, or write a quick one, and pop into
the debugger to check for sure.)
--
Anton Rang (rang@winternet.com)

+++++++++++++++++++++++++++

>From will@cs.su.oz.au (William Uther)
Date: 20 Jun 1994 22:43:21 +1000
Organization: Basser Dept of Computer Sciece, Uni of Sydney, Australia

Hello again,
  Fixed the problem - I was assuming that CW used a similar A4 world to THINK
and MPW - A4 was being set wrong and yet it wasn't crashing.  It would be nice
if this were mentioned in the manuals (I eventaully found it, well documented,
in a code example).

\x/ill       :-}

P.S.  Aside from the odd conversion problem from THINK C, CW is very good - I
am in the process of converting everything.


---------------------------

>From Frank Price <wprice@netcom.com>
Subject: MacTCP DNR for PowerPC?
Date: Tue, 21 Jun 1994 03:16:28 GMT
Organization: Netcom

I noticed that the DNR.c file on the CodeWarrior DR3 CD and the MacOnRISC
release CD is basically bogus when it actually gets compiled.  It is far
from a complete conversion to native code...at least as far as
CodeWarrior is concerned.  After making many small changes that were
obvious, the functions still "don't match prototypes."  Anyway, I'd
rather not muck with this file if there is an official or correctly
updated version out there.  Anyone know what the story is or want to send
me an updated file?

Thanks!
Frank

+++++++++++++++++++++++++++

>From scouten@maroon.tc.umn.edu (Eric Scouten)
Date: Tue, 21 Jun 1994 14:29:56 GMT
Organization: University of Minnesota, Student Affairs

In article <netnewsCrq93H.JBq@netcom.com>, Frank Price <wprice@netcom.com>
wrote:

> I noticed that the DNR.c file on the CodeWarrior DR3 CD and the MacOnRISC
> release CD is basically bogus when it actually gets compiled.  It is far
> from a complete conversion to native code...at least as far as
> CodeWarrior is concerned.  After making many small changes that were
> obvious, the functions still "don't match prototypes."  Anyway, I'd
> rather not muck with this file if there is an official or correctly
> updated version out there.  Anyone know what the story is or want to send
> me an updated file?

Sorry. You'll have to rewrite DNR.c.

Apple did a pretty poor job of creating a universal header for this file.
You will have to change all of the typedefs and the ProcInfo definitions.
The following is an excerpt from some of my own TCP code that shows the
corrected values.

- -------

// NOTE: The dnr.c file created for universal headers contained an error.
All
// of the selectors are treated by the DNR as long values, not short. This
has
// been corrected in TurboTCP.

extern "C" {

typedef OSErr (*OpenResolverProcPtr)(long selector, char* fileName);
                   //                ^^^^ this was "short" in dnr.c
typedef OSErr (*CloseResolverProcPtr)(long selector);
typedef OSErr (*StrToAddrProcPtr)(long selector, char* hostName,
        struct hostInfo* rtnStruct, long resultProc, char* userData);
typedef OSErr (*AddrToStrProcPtr)(long selector, long address, char*
hostName);
typedef OSErr (*AddrToNameProcPtr)(long selector, unsigned long addr,
        struct hostInfo* rtnStruct, long resultProc, char* userData);
typedef OSErr (*HInfoProcPtr)(long selector, char* hostName,
        struct returnRec* returnRecPtr, long resultProc, char* userData);
typedef OSErr (*MXInfoProcPtr)(long selector, char* hostName,
        struct returnRec* returnRecPtr, long resultProc, char* userData);

};

#if USESROUTINEDESCRIPTORS

enum {
	uppOpenResolverProcInfo = kCStackBased
		 | RESULT_SIZE(SIZE_CODE(sizeof(short)))
		 | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
		 | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char*)))
};

// etc.

//
// change parameter 1 of all ProcInfos to (sizeof(long))
//

- -------

Hope this was helpful.

-Eric


-- 
Eric Scouten  *  U of MN  *  scouten@maroon.tc.umn.edu  *  +1 612 626 0746
  ** MS Computer Science student, Univ of Illinois, starting Aug '94 **

Maps tell the truth, the whole truth, and anything but the truth.

---------------------------

>From kerr@math.ohio-state.edu (Kerr Gibson)
Subject: Major bug with Symantec CDK *Please Read*
Date: 21 Jun 1994 19:13:36 -0400
Organization: Department of Mathematics, The Ohio State University


Thought I would write this to spare you some of the headaches I went
through in linking a Symantec PPC project.


My original problem was that I had ported an old project to a new Virtual
Architect PPC project.  The project linked via the ToolServer and produced
an application which inexplicably would not run.  All it would do was produce
an error and quit.

The actual bug has to do with Quicktime and the makefile for the ToolServer. 
My original project uses Quicktime and the QuickTime xcoff library is not
included in the VA PPC starter project. "Uh Oh.", I think, "I had better make
sure the Quicktime lib is included in the linker script for the ToolServer.  
So I open the PPCBuild.ts file and find the following:

...
MakePEF {XCOFFname} -o {AppName} 6
   -l "AppleScriptLib.xcoff.o=AppleScriptLib" 6
   -l "InterfaceLib.xcoff.o=InterfaceLib" 6
   -l "MathLib.xcoff.o=MathLib" 6
   -l "ObjectSupportLib.xcoff.o=ObjectSupportLib" 6
   -l "QuickTimeLib.xcoff.o=InterfaceLib" 6
   -l "StdCLib.xcoff.o=StdCLib" 6
   -ft 'APPL' -fc "{Creator}"

Lo and behold, it is already there. "Ok Cool", I say to myself, "I just won't
change the file." So I leave it alone and then I spend the next week trying to
figure out why my program links but wont run.  The astute observer of course
will see what I failed to notice:

-l "QuickTimeLib.xcoff.o=InterfaceLib" 6
                         ^^^^^^^^^^^^
      Its the wrong d*mn library name!

This explains the issue. The linker did not report an error because the library
really was loaded.  Unfortunately it was loaded right over top of the previous
InterfaceLib PEF file!  The reason this bug was never found is because if there
is no Quicktime lib in the project, it is ignored by this script.  I imagine
that this little diddy wreaked hell with the code fragment, hence, it was 
unable to run.
I had been duped by a simple copy/paste error (see 3 lines above it).  Now 
I don't have a problem with copy/paste errors, God knows I make them all the 
time.  But I'm a little miffed that certain libraries were never tested with 
the final out-the-door product.

Anyway, if you want to use QuickTime with the CDK, this is your warning.

--Kerr Gibson

P.S. I'm also pissed that the Finder did not give me an error code- all
it said was "The Application xxx could not be launched because an error
ocurred."  What gives?








---------------------------

>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Subject: Perspective in GX (was Re: can toolbox draw text at an angle?)
Date: 21 Jun 94 14:06:37 +1200
Organization: University of Waikato, Hamilton, New Zealand

In article <3624861694.8241498@tempest.tempest.net.hk>, johnb@tempest.net.hk (John W. Blackburne) writes:
> Jens Alfke (jens_alfke@powertalk.apple.com) wrote:
>
>> Why yes -- QuickDraw GX supports arbitrary transformations of text,
> including
>> skew and perspective in addition to rotation. Anything you can describe in
> a
>> 3x3 matrix. Not only that, but you can allow the user to edit the
> transformed
>> text (typing into perspective text is pretty trippy.) You can also fit text
>> to a curve, but it's not directly editable after that.
>
> Can someone please explain to me how this works. If you are using a 3 x 3
> matrix (on an anything x anything matrix) for transformations you get
> linear transformations, which include scaling, rotating, reflecting and
> skewing but NOT transforming the perspective of a shape, at least not when
> operating on the real two-dimensional space QD GX works in.

Yes, you can. Remember, these are 3 x 3 matrices, not 2 x 2. Also,
perspective is very much a linear transformation, since it maps straight lines
to straight lines, after all.

Here's how it works: for transformations other than perspective, you work
in homogeneous coordinates, which normally look like this:

    [x y 1] [a b 0] = [x' y' 1]
	    [c d 0]
	    [e f 1]

Perspective transforms work like this:

    [x y 1] [1 0 u] = [x y (xu + yv + 1)]
	    [0 1 v]
	    [0 0 1]

The matrix doesn't quite fit into the usual normalized form, but QuickDraw GX
supports it just fine. And when you normalize the result vector, you end up with

    x' = x / (xu + yv + 1)
    y' = y / (xu + yv + 1)

et voila! A perspective transformation. Of course, you can combine these
with other linear transformations in the usual way.

Now the big mystery: with all the other convenience routines that they bothered
to put into the QuickDraw GX API, why didn't they include one to build
perpective transformations?

Lawrence D'Oliveiro                       fone: +64-7-856-2889
Info & Tech Services Division              fax: +64-7-838-4066
University of Waikato            electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
"If you want competence, you must read everything. But, if you want
originality, you must not."                    -- Edward de Bono

+++++++++++++++++++++++++++

>From turk@apple.com (Ken Turkowski)
Date: Tue, 21 Jun 1994 21:56:40 GMT
Organization: Apple Computer, Inc.

In article <1994Jun21.140637.29986@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:

> Now the big mystery: with all the other convenience routines that they bothered
> to put into the QuickDraw GX API, why didn't they include one to build
> perpective transformations?

Try Quad2D2Quad2D(), given below. This works if you know the projective
transformations of 4 points.

Are there any other specifications you'd be interested in?

/* Original code due to Paul Heckbert.
 * Recoded by Ken Turkowski.
 * AS IS. No guarantees.
 */



#define MAXDIM 32

#define kFudge			1e-16
#define kBadMap			0
#define kProjectiveMap	1
#define kAffineMap		2

#include <math.h>

#define ConcatMap(map1Type, map2Type) ((map1Type < map2Type) ? map1Type :
map2Type)

typedef struct TPoint2D		{ float x, y; }			TPoint2D;
typedef struct TPoint3D		{ float x, y, z; }		TPoint3D;
typedef struct TVector4D	{ float x, y, z, w; }	TVector4D;

typedef FLOAT vec3[3];

void
MLAdjointMatrix3x3(float *M)
{
	float t[3][3];
	struct MX { float m[3][3]; };
	register vec3* m = (vec3*)M;
	
	t[0][0] =   m[1][1] * m[2][2] - m[1][2] * m[2][1];	/* t(0,0) */
	t[0][1] = - m[0][1] * m[2][2] + m[0][2] * m[2][1];	/* t(0,1) */
	t[0][2] =   m[0][1] * m[1][2] - m[0][2] * m[1][1];	/* t(0,2) */
	t[1][0] = - m[1][0] * m[2][2] + m[1][2] * m[2][0];	/* t(1,0) */
	t[1][1] =   m[0][0] * m[2][2] - m[0][2] * m[2][0];	/* t(1,1) */
	t[1][2] = - m[0][0] * m[1][2] + m[0][2] * m[1][0];	/* t(1,2) */
	t[2][0] =   m[1][0] * m[2][1] - m[1][1] * m[2][0];	/* t(2,0) */
	t[2][1] = - m[0][0] * m[2][1] + m[0][1] * m[2][0];	/* t(2,1) */
	t[2][2] =   m[0][0] * m[1][1] - m[0][1] * m[1][0];	/* t(2,2) */
	
	*((struct MX*)(&m[0][0])) = *((struct MX*)(&t[0][0]));
}


/****************************************************************
 * Linear transformations, for transforming vectors and matrices.
 * This works for row vectors and column vectors alike.
 *	L[nRows][lCol]	- input (left) matrix
 *	rg[lCol][rCol]	- transformation (right) matrix
 *	P[nRows][rCol]	- output (product) matrix
 *
 * Examples:
 * v[3] * M[3][3] -> w[3] :			LinearTransform(&v[0], &M[0][0], &w[0], 1, 3,
3);
 * M[3][3] * v[3] -> w[3] :			LinearTransform(&M[0][0], &v[0], &w[0], 3, 3,
1);
 * M[4][4] * N[4][4] -> P[4][4]:	LinearTransform(&M[0][0], &N[0][0],
&P[0][0], 4, 4, 4);
 * v[4] * M[4][3] -> w[3]:			LinearTransform(&v[0], &M[0][0], &w[0], 1, 4,
3);
 * v[3] tensor w[3] -> T[3][3]:		LinearTransform(&v[0], &w[0], T[3][3], 3,
1, 3);
 ****************************************************************/

void
LinearTransform(
	const float *L,		/* The left matrix */
	const float *R,		/* The right matrix */
	register float *P,	/* The resultant matrix */
	long nRows,			/* The number of rows of the left and resultant matrices */
	long lCol,			/* The number of columns in the left matrix */
	long rCol			/* The number of columns in the resultant matrix */
)
{
	register const float *lp;		/* Left matrix pointer for dot product */
	register const char *rp;		/* Right matrix pointer for dot product */
	register long k;					/* Loop counter */
	register long double sum;		/* Extended precision for intermediate results
*/
	register long rRowBytes = rCol * sizeof(float);
	register long j, i;				/* Loop counters */
	register long lRowBytes = lCol * sizeof(float);
	const char *lb = (const char*)L;

	for (i = nRows; i--; lb += lRowBytes) {	/* Each row in L */
		for (j = 0; j < rCol; j++) {	/* Each column in R */
			lp = (const float *)lb;		/* Left of ith row of L */
			rp = (const char *)(R + j);	/* Top of jth column of R */
			sum = 0;
			for (k = lCol; k--; rp += rRowBytes)
				sum += *lp++ * (*((const float*)rp));	/* *P += L[i'][k'] * R[k'][j] */
			*P++ = sum;
		}
	}
}


/****************************************************************
 ****************************************************************
 ****************************************************************
 ***	2D Projective Mappings
 ****************************************************************
 ****************************************************************
 ****************************************************************/


#define DET2(a,b, c,d) ((a)*(d) - (b)*(c))


/****************************************************************
 * UnitSquare2Quad2D()
 *
 * compute the TDMatrix3x3 M such that
 *	[x y w] = [u v 1] M
 * where the points
 *	(0,0), (0,1), (1,1), (1,0)
 * map into the points
 *	p[0], p[1], p[2], p[3].
 ****************************************************************/
int
UnitSquare2Quad2D(register const TPoint2D *p, float M[3][3])
{
	double px, py;
	double dx12, dx32, dy12, dy32;
	double d, g, h;

	px = p[0].x - p[1].x + p[2].x - p[3].x;
	py = p[0].y - p[1].y + p[2].y - p[3].y;
	
	if ((fabs(px) < kFudge) && (fabs(py) < kFudge)) {	/* Affine */
		M[0][0] = p[1].x-p[0].x;	M[0][1] = p[1].y-p[0].y;	M[0][2] = 0;	/* New
x-axis */
        M[1][0] = p[3].x-p[0].x;	M[1][1] = p[3].y-p[0].y;	M[1][2] = 0;	/*
New y-axis */
        M[2][0] = p[0].x;			M[2][1] = p[0].y;			M[2][2] = 1;	/* New origin
*/
		return(kAffineMap);
	}
	

	/* Projective mapping */
	dx12 = p[1].x - p[2].x;
	dx32 = p[3].x - p[2].x;
	dy12 = p[1].y - p[2].y;
	dy32 = p[3].y - p[2].y;
	d = DET2(dx12,dx32, dy12,dy32);	/* Discriminant */
	g = DET2(px,dx32, py,dy32);		/* X-keystoning */
	h = DET2(dx12,px, dy12,py);		/* Y-Keystoning */
	
	if (d != 0) {
		g /= d;	/* Normalize these to get a matrix in standard form */
		h /= d;
	
		M[0][0] = p[1].x-p[0].x+g*p[1].x;	M[0][1] =
p[1].y-p[0].y+g*p[1].y;	M[0][2] = g;
		M[1][0] = p[3].x-p[0].x+h*p[3].x;	M[1][1] =
p[3].y-p[0].y+h*p[3].y;	M[1][2] = h;
		M[2][0] = p[0].x;					M[2][1] = p[0].y;					M[2][2] = 1;
	
		return(kProjectiveMap);
	}
	else {
		return(kBadMap);
	}

}


/****************************************************************
 * Rect2Projective()
 *
 * compute the matrix M[3][3] such that
 *	[x y w] = [u v 1] M
 * where the points
 *	q[0], q[1], q[2], q[3]
 * map into the points
 *	p[0], p[1], p[2], p[3].
 * If the inverse flag is set, it map xy->uv instead of ux->xy
 ****************************************************************/
int
Rect2Quad2D(double u0, double v0, double u1, double v1, const TPoint2D* p,
float M[3][3], int inverse)
{
	double du = u1 - u0;
	double dv = v1 - v0;
	int mapType;

	if (du == 0 || dv == 0)
		return(0);	/* Degenerate rectangle */
	
	if ((mapType = UnitSquare2Quad2D(p, M)) == kBadMap)
		return(kBadMap);	/* Bad perspectivity */
	
	/* Apply rectangular stretching and translation */
    M[0][0] /= du;						M[0][1] /= du;						M[0][2] /= du;
    M[1][0] /= dv;						M[1][1] /= dv;						M[1][2] /= dv;
    M[2][0] -= M[0][0]*u0+M[1][0]*v0;	M[2][1] -=
M[0][1]*u0+M[1][1]*v0;	M[2][2] -= M[0][2]*u0+M[1][2]*v0;

	if (inverse)	/* Do we want uv->xy or xy->uv? */
		AdjointMatrix3x3(M[0]);	/* xy->uv! */
	
	return(mapType);
}


/****************************************************************
 * Quad2D2Quad2D()
 *
 * compute the matrix M[3][3] such that
 *	[x y w] = [u v 1] M
 * where the points
 *	q[0], q[1], q[2], q[3]
 * map into the points
 *	p[0], p[1], p[2], p[3].
 ****************************************************************/
int
Quad2D2Quad2D(register const TPoint2D* q, const TPoint2D* p, float M[3][3])
{
	if (q[0].x==q[3].x && q[1].x==q[2].x &&	/* vertical   edges 3-0 and 1-2 */
		q[0].y==q[1].y && q[2].y==q[3].y	/* horizontal edges 0-1 and 2-3 */
	) {
		return(Rect2Quad2D(q[0].x, q[0].y, q[2].x, q[2].y, p, M, 0));
	}
	
	else if (q[0].x==q[1].x && q[2].x==q[3].x &&
			 q[1].y==q[2].y && q[3].y==q[0].y
	) {
		TPoint2D prot[4];
		prot[0]=p[1]; prot[1]=p[2]; prot[2]=p[3]; prot[3]=p[0];	/* cycle points
*/
		return(Rect2Quad2D(q[1].x, q[1].y, q[3].x, q[3].y, prot, M, 0));
	}

	else {
		float L[3][3], R[3][3];
		int map1Type, map2Type;
		
		/* Calculate mapping from quad q to unit square */
		if ((map1Type = UnitSquare2Quad2D(q, L)) == kBadMap)	/* unit square to
quad q */
			return(kBadMap);
		AdjointMatrix3x3(L[0]);
		
		/* Calculate mapping from unit square to quad p */
		if ((map2Type = UnitSquare2Quad2D(p, R)) == kBadMap)	/* unit square to
quad p */
			return(kBadMap);
		
		/* Concatenate the two transformations */
		LinearTransform(L[0], R[0], M[0], 3, 3, 3);

		return(ConcatMap(map1Type, map2Type));
	}
}


//Ken Turkowski; Apple Computer, Inc.; 1 Infinite Loop; Cupertino, CA 95014
//turk@apple.com

---------------------------

>From gilem@litecdev.eng.rpi.edu (Michael R. Gile)
Subject: Still trouble finding floating windows code.
Date: 14 Jun 1994 18:36:13 GMT
Organization: Rensselaer Polytechnic Institute, Troy NY

I am still looking for some code which implements floating windows on the mac,
which will compile using either think C or metrowerks C.  I have tried 
compiling yu's code from d e v e l o p issue 15 using both of these
compilers, with absolutely no success. The code compiles, but then crashes 
hard as soon as any events are sent to the handlers.  Does anyone
have any suggestions?  I don't have MPW, so that doesn't help.

thanks
Mike
-- 
Michael Gile                        |               Graduate Assistant
gilem@rpi.edu                       |   Computer & Systems Engineering
"Don't Blame Me, I voted for Perot!"| Rensselaer Polytechnic Institute

+++++++++++++++++++++++++++

>From egurney@vcd.hp.com (Eddy J. Gurney)
Date: Wed, 15 Jun 1994 01:01:35 GMT
Organization: Hewlett-Packard VCD

Michael R. Gile (gilem@litecdev.eng.rpi.edu) wrote:
>I am still looking for some code which implements floating windows on
>the mac, which will compile using either think C or metrowerks C. I
>have tried compiling yu's code from d e v e l o p issue 15 using both
>of these compilers, with absolutely no success. The code compiles, but
>then crashes hard as soon as any events are sent to the handlers. Does
>anyone have any suggestions? I don't have MPW, so that doesn't help.

Well, there are some bugs in the code, even with the latest version on
the Bookmark 18 CD. But it may work for your application. (I sent mail
to Dean Yu on them and did not get a response.)

Your problem most likely has to do with the fact that the code is
written for MPW and *not* THINK C, which use different methods to access
low-memory globals (unless you have compiled MacHeaders to use SysEqu.h
instead of LoMem.h, not likely for the average joe.)

Anyway, the solution is to look at the two functions GetWindowList() and
SetWindowList() and change them to

return (WindowRef)WindowList;

and 

WindowList = (WindowPeek)windowReference;

respectively.

A more robust solution would be to #ifdef THINKC (or whatever the
compiler-set define is) around these changes, but I digress...

--
Eddy J. Gurney N8FPW   Hewlett-Packard Company, Vancouver (USA!) Division
egurney@vcd.hp.com                       #include <standard-disclaimer.h>
"Failures are divided into two classes-- those who thought and never did,
      and those who did and never thought."     John Charles Salak

+++++++++++++++++++++++++++

>From kenlong@netcom.com (Ken Long)
Date: Wed, 15 Jun 1994 05:43:20 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)

There are floating window sources available on the net.  Some even have 
the word "float" or "floating" in the filename.  What I'd recommend is 
connecting to the major Mac source sites and getting all sources with 
window, WDEF and floating in the filename.  Better yet, connect and get 
any description indexes for the site, and target your files you want to 
get before you connect for the files.

"Nifty" has floaters, Infinity Windoid (an excellent one), an old file 
called "floating" does, too.  As I recall, buried down in the TCL folder, 
in a subfolder, that came with Think C there is a windoid source.

These sources may or may not have routines which result in the window 
staying in front no matter what (maybe bar dialogs), but there was a 
lengthy thread on this not to long ago.  Maybe someone saved the thread 
and would send it to you, as well.

-Ken-



+++++++++++++++++++++++++++

>From Mark Hanrek <hanrek@cts.com>
Date: Wed, 15 Jun 1994 08:10:29 GMT
Organization: The Information Workshop

In article <2tktau$asu@usenet.rpi.edu> Michael R. Gile,
gilem@litecdev.eng.rpi.edu writes:

> I am still looking for some code which implements floating windows on
the mac,
> which will compile using either think C or metrowerks C. 

Besides what was just mentioned, I know there is an example called
"Floating Windows 1.3" floating around. ( Sorry :)

But, the best floating windows C example source code, integrated with the
best windowing I have ever seen, is available as part of DTS.Lib, written
by Eric Soldan. This is THE reference for any kind of windowing on the
Mac, and it is excellent.

You can find it at ftp.apple.com.

Hope this helps.

Mark Hanrek

+++++++++++++++++++++++++++

>From jc@vivitech.com (John Cooper)
Date: Fri, 17 Jun 1994 20:13:42 GMT
Organization: Vivid Technologies Inc.

   I see a lot of people ask for code that implements floating windows. One
common suggestion is to use Yu's code from _develop_, but everyone knows
that that code is buggy. The follow-up suggestion is usually of the form:

   "The code in _develop_ still has bugs. Just go to an archive site and
    grab Infinity Windoid or ... "

   But is this all they really have to do? Just go get someone's WDEF, make
a NewWindow with it and, voila!, instant floating windows?

   Now please forgive my ignorance; I've never written a WDEF before. Could
someone explain to me how a WDEF alone achieves "floating" behavior in the
Macintosh environment? How can a WDEF itself control the BringToFront behavior
of all the other windows in an application (including doing the right thing
with dialog boxes)? Doesn't an application have to manage all the layering
itself even if a "windoid" WDEF is available? Doesn't the Infinity Windoid--
to use one example--only determine the windoid's appearance, and not it's
"floating" properties?

   Telling someone who is trying to get floating palettes working to go
get the Infinity Windoid is not enough, is it? Sure, that person will have
pretty windoids, but they won't float all by themselves, will they?

-John

+--------------------------+------------------------------------------+
| John R. Cooper           | Internet: jc@vivitech.com,               |
| Vivid Technologies, Inc. |           jcooper@world.std.com          |
| Waltham, MA 02154        | AOL:      JRCooper (jrcooper@aol.com)    |
+--------------------------+------------------------------------------+
| "God split himself into a myriad parts that he might have friends." |
| This may not be true, but it sounds good and is no sillier than any |
| other theology.                                                     |
|                        -- Long's Notes --                           |
+---------------------------------------------------------------------+

+++++++++++++++++++++++++++

>From tbrown@dorsai.org (Tommy Brown)
Date: Tue, 21 Jun 1994 20:46:07 GMT
Organization: The Dorsai Embassy, New York, NY

John Cooper (jc@vivitech.com) wrote:
:    I see a lot of people ask for code that implements floating windows. One
: common suggestion is to use Yu's code from _develop_, but everyone knows
: that that code is buggy. The follow-up suggestion is usually of the form:

:    "The code in _develop_ still has bugs. Just go to an archive site and
:     grab Infinity Windoid or ... "

:    But is this all they really have to do? Just go get someone's WDEF, make
: a NewWindow with it and, voila!, instant floating windows?

No. Although the code in develop has some bugs, as far as I know it is 
pretty much adequate. You will need to use the Infinity Windoid AND the 
code in develop to properly implement floating windows. The Infinity 
Windoid merely creates a window that looks like it should be floating. To 
make it actually float, you need to use modified code; the most recent 
code that I know of that will do the trick is what was found in develop.
-- 
Tommy Brown                 | Je suis tombe par terre, c'est la faute a
tbrown@dorsai.dorsai.org    | Voltaire. Le nez dans le ruisseau, c'est la
tommy6@aol.com              | faute a Rousseau. 
zipit@softlock.com          | - Gavroche

---------------------------

>From damon@CS.ColoState.EDU (Yimmit)
Subject: _vSyncWait infinite loop?
Date: Thu, 16 Jun 1994 03:24:29 GMT
Organization: Imladris Occupants Inc.

OK.  So, I'm doing some communications with the serial ports, but every so often
I get stuck in _vSyncWait forever.  My question is: Why?  What are the reasons
for an infinite loop to occur in _vSyncWait?  This happens just after I do an
FSWrite to the serial port.  Has anyone had this problem?  ANY help would be
appreciated since I can find no documentation on this - anywhere.

Tim Damon


+++++++++++++++++++++++++++

>From resnick@uiuc.edu (Pete Resnick)
Date: Wed, 15 Jun 1994 23:05:25 -0500
Organization: University of Illinois at Urbana-Champaign

In article <CrH04t.zH0@yuma.ACNS.ColoState.EDU>, damon@CS.ColoState.EDU
(Yimmit) wrote:

>OK.  So, I'm doing some communications with the serial ports, but every
>so often I get stuck in _vSyncWait forever.  My question is: Why?  What
>are the reasons for an infinite loop to occur in _vSyncWait?  This happens
>just after I do an FSWrite to the serial port.

The _vSyncWait loop is where synchronous calls wait for the interrupt
telling them that the I/O routine has completed. Since FSWrite is simply a
synchronous PBWrite, that's what's going on. Two causes are either (a) you
called a synchronous routine like FSWrite at interrupt time and the
interrupt for completion is never coming through or (b) the routine is
never completing, which means that the data is never getting to the serial
port (which would be very wierd). I vote for (a). :-)

pr
-- 
Pete Resnick    	(...so what is a mojo, and why would one be rising?)
Doctoral Student - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@uiuc.edu

+++++++++++++++++++++++++++

>From absurd@apple.com (Tim Dierks)
Date: Thu, 16 Jun 1994 07:24:30 GMT
Organization: Apple Computer, Inc.

In article <CrH04t.zH0@yuma.ACNS.ColoState.EDU>, damon@CS.ColoState.EDU
(Yimmit) wrote:

> OK.  So, I'm doing some communications with the serial ports, but every so often
> I get stuck in _vSyncWait forever.  My question is: Why?  What are the reasons
> for an infinite loop to occur in _vSyncWait?  This happens just after I do an
> FSWrite to the serial port.  Has anyone had this problem?  ANY help would be
> appreciated since I can find no documentation on this - anywhere.
> 
> Tim Damon

It basically means your write isn't completing; you made a synchronous
write, so it won't return until all the bytes have been shoved through the
serial port.  When it can't shove all the characters through the serial
port, it waits until it can finish. Possibilities include:
 - Handshaking is on (hardware or software) and it's been told not to send.
 This is in particular a problem when writing code that runs on PowerBooks;
apparently, a desktop machine without its hardware handshaking line hooked
up will usually think it's OK to send, while a portable will usually think
that it's not OK to send; since hardware handshaking is on by default, this
can be a surprise the first time you run your program on a PowerBook with a
cable which doesn't have that pin hooked up.
 - You made a synchronous serial call from an interrupt level which doesn't
allow the serial port's interrupts to get through; in general, only make
asynchronous calls at interrupt time.
 - Something else is screwed up; however, the first two are most likely.

Best,
 - Tim

-- 
Tim Dierks
absurd@apple.com

+++++++++++++++++++++++++++

>From jvp@tools1.ee.iastate.edu (Jim Van Peursem)
Date: 16 Jun 94 16:26:56 GMT
Organization: Iowa State University, Ames, Iowa

In <resnick-1506942305250001@resnick1.isdn.uiuc.edu> resnick@uiuc.edu (Pete Resnick) writes:

>In article <CrH04t.zH0@yuma.ACNS.ColoState.EDU>, damon@CS.ColoState.EDU
>(Yimmit) wrote:

>>OK.  So, I'm doing some communications with the serial ports, but every
>>so often I get stuck in _vSyncWait forever.  My question is: Why?  What
>>are the reasons for an infinite loop to occur in _vSyncWait?  This happens
>>just after I do an FSWrite to the serial port.

>The _vSyncWait loop is where synchronous calls wait for the interrupt
>telling them that the I/O routine has completed. Since FSWrite is simply a
>synchronous PBWrite, that's what's going on. Two causes are either (a) you
>called a synchronous routine like FSWrite at interrupt time and the
>interrupt for completion is never coming through or (b) the routine is
>never completing, which means that the data is never getting to the serial
>port (which would be very wierd). I vote for (a). :-)

  Not wierd at all actually. The problem is most likely due to improper
initialization of serial handshaking options. Some machines default to
hardware handshaking, and their port defaults to the "wait" state when
no hardware handshaking lines are present. The fix is to call SerHShake()
or the preferred, Control(14?) to initialize the handshaking options.

+---------------------------------------------------------------+
| Jim Van Peursem - Ph.D. Candidate      (Ham Radio -> KE0PH)   |
| Department of Electrical Engineering and Computer Engineering |
| Iowa State University - Ames, IA 50011 : (515) 294-8339       |
| internet - jvp@iastate.edu  -or-  jvp@cpre1.ee.iastate.edu    |
+---------------------------------------------------------------+

+++++++++++++++++++++++++++

>From d88-jwa@mumrik.nada.kth.se (Jon Wätte)
Date: 17 Jun 1994 20:55:20 GMT
Organization: The Royal Institute of Technology

In <CrH04t.zH0@yuma.ACNS.ColoState.EDU> damon@CS.ColoState.EDU (Yimmit) writes:

>OK.  So, I'm doing some communications with the serial ports, but every so often
>I get stuck in _vSyncWait forever.  My question is: Why?  What are the reasons

_vSyncWait is where your Mac spends most of its time.
It takes a parameter block as parameter, and waits until
ioResult isn't 1 anymore. I/O is usually done through
spawning off an interrupt task which sets ioResult to
the result code.

There's probably something keeping your Mac from sending
the data, like an XOFF or no CTS or something. You can
avoid such hangs by always writing in async mode (but that
brings about other problems) with PBWriteAsync.

Cheers,

					/ h+
-- 
 -- Jon W{tte, h+@nada.kth.se, Mac Software Engineer Deluxe --

 "My boss made me say it. He dares you to sue!"

+++++++++++++++++++++++++++

>From damon@CS.ColoState.EDU (Yimmit)
Date: Sat, 18 Jun 1994 01:28:09 GMT
Organization: Imladris Occupants Inc.

Thanks to all who replied to this problem.  Silly me, I forgot to prototype my
send function for a separate source file.  Therefore, my command parameter was
being trashed in the send function and I was accidentally sending some huge
amount of data!!  Oh well.  Thanks again!
-->Tim Damon


+++++++++++++++++++++++++++

>From Bruce@hoult.actrix.gen.nz (Bruce Hoult)
Date: Sun, 19 Jun 1994 12:41:39 +1200 (NZST)
Organization: (none)

damon@CS.ColoState.EDU (Yimmit) writes:
> OK.  So, I'm doing some communications with the serial ports, but every so often
> I get stuck in _vSyncWait forever.  My question is: Why?  What are the reasons
> for an infinite loop to occur in _vSyncWait?  This happens just after I do an
> FSWrite to the serial port.  Has anyone had this problem?  ANY help would be
> appreciated since I can find no documentation on this - anywhere.

Bet you're not calling SerHShake.

-- Bruce

---------------------------

>From kelley@cs.dal.ca (Dan Kelley)
Subject: can toolbox draw text at an angle?
Date: Thu, 16 Jun 1994 13:04:12 GMT
Organization: Oceanography, Dalhousie University, Halifax, NS, Canada

Some years ago I did some Mac programming, and was disappointed to realize that
it could not easily draw text at an angle.

Is this still the case, or has system7/truefont/... made it possible to draw text
at an angle to the horizontal?

If you have information, I'd appreciate an email (since I presume, scanning the
group for the last few days, that others might not be interested).  Thanks.  Dan.


-- 
Dan Kelley                   | dan.kelley@dal.ca            (902)494-1694
Oceanography Department      |   ``We rise again,
Dalhousie University         |     in the faces of our children''
Halifax, NS, CANADA, B3H 4J1 |   The Rankin Family <North Country>

+++++++++++++++++++++++++++

>From andrewt@fluffy.cs.wisc.edu (Andrew Thomas-Cramer)
Date: 16 Jun 1994 16:39:46 GMT
Organization: University of WI, Madison -- Computer Sciences Dept.

kelley@cs.dal.ca (Dan Kelley) writes:

>Some years ago I did some Mac programming, and was disappointed to realize that
>it could not easily draw text at an angle.

>Is this still the case, or has system7/truefont/... made it possible to draw text
>at an angle to the horizontal?

>If you have information, I'd appreciate an email (since I presume, scanning the
>group for the last few days, that others might not be interested).  Thanks.  Dan.

	I'd be interested. Please post any responses.
	Clearly, it's possible -- composition and illustration software do it 
routinely. But how is it fastest done? A transformation of the bits generated
from Toolbox routines to a new rotation, or direct use of the font description?
Or has a Toolbox routine been added lately?

	andy thomas-cramer


+++++++++++++++++++++++++++

>From jwbaxter@olympus.net (John W. Baxter)
Date: Thu, 16 Jun 1994 15:00:05 -0700
Organization: Internet for the Olympic Peninsula

In article <CrHqz1.DIJ@cs.dal.ca>, kelley@cs.dal.ca (Dan Kelley) wrote:

> Some years ago I did some Mac programming, and was disappointed to realize that
> it could not easily draw text at an angle.
> 
> Is this still the case, or has system7/truefont/... made it possible to draw text
> at an angle to the horizontal?

QuickDraw GX makes rotated text (or rotated anything, almost) trivial. 
Summer.

-- 
John Baxter    Port Ludlow, WA, USA  [West shore, Puget Sound]
   No hablo Intel.
   jwbaxter@pt.olympus.net

+++++++++++++++++++++++++++

>From gabe@shiva.com (Gabriel Lawrence)
Date: Thu, 16 Jun 94 21:59:02 GMT
Organization: Shiva Corporation

In Article <2tpv8i$4rn@spool.cs.wisc.edu>, andrewt@fluffy.cs.wisc.edu
(Andrew Thomas-Cramer) wrote:
>kelley@cs.dal.ca (Dan Kelley) writes:
>
>>Some years ago I did some Mac programming, and was disappointed to realize
>>that it could not easily draw text at an angle.
>>
>>Is this still the case, or has system7/truefont/... made it possible to draw
>>text at an angle to the horizontal?

Regular old QuickDraw never supported it but Adobe Type Manager did.  I
asked Apple a few years ago how to do it without ATM and was told that if I
used the same approach that ATM offered, they would produce a compatible
method.  They've finally offered a solution (though not really compatible)
in the form of QuickDraw GX.  The following is excerpted from "IM-QuickDraw
GX Typography"

"GXRotateShape:
Rotates the typographic shape. This function can affect the mapping of the
typographic shape's transform if the gxMapTransformShape attribute is set.
Otherwise, it converts a text shape to a glyph shape, and it changes the
values in the glyph shape's tangents array. You use the GXRotateShape
function to create vertical text. See the chapter "Typographic Styles" for
more information on vertical text."

You can also directly alter the glyph tangent array if you want to do
something like draw text along an arbitrary line.  In short, now you can
easily do amazing things to text including rotation, skews, and generic
transforms.

=Gabe=






>        I'd be interested. Please post any responses.
>        Clearly, it's possible -- composition and illustration software do it 
>routinely. But how is it fastest done? A transformation of the bits generated
>from Toolbox routines to a new rotation, or direct use of the font description?
>Or has a Toolbox routine been added lately?
>
>        andy thomas-cramer
>

- ----------------------
Gabriel Lawrence                                               Shiva Corporation
Software Tool               "All Disclaimers Apply"             gabe@shiva.com  

+++++++++++++++++++++++++++

>From Jens Alfke <jens_alfke@powertalk.apple.com>
Date: Thu, 16 Jun 1994 23:05:05 GMT
Organization: Apple Computer

In article <2tpv8i$4rn@spool.cs.wisc.edu> Andrew Thomas-Cramer,
andrewt@fluffy.cs.wisc.edu writes:
> 	Clearly, it's possible -- composition and illustration software do it 
> routinely. But how is it fastest done? A transformation of the bits
generated
> from Toolbox routines to a new rotation, or direct use of the font
description?

I'd guess that most programs currently draw offscreen and transform the
bitmap. For details on bitmap transmogrification, see "Graphics Gems 3" from
Academic Press.

> Or has a Toolbox routine been added lately?

Why yes -- QuickDraw GX supports arbitrary transformations of text, including
skew and perspective in addition to rotation. Anything you can describe in a
3x3 matrix. Not only that, but you can allow the user to edit the transformed
text (typing into perspective text is pretty trippy.) You can also fit text
to a curve, but it's not directly editable after that.

--Jens Alfke
  jens_alfke@powertalk              Rebel girl, rebel girl,
            .apple.com              Rebel girl you are the queen of my world

+++++++++++++++++++++++++++

>From Mark Hanrek <hanrek@cts.com>
Date: Fri, 17 Jun 1994 05:02:28 GMT
Organization: The Information Workshop

In article <jwbaxter-160694150005@ptpm010.olympus.net> John W. Baxter,
jwbaxter@olympus.net writes:

> QuickDraw GX makes rotated text (or rotated anything, almost) trivial. 


I heard a rumor that QuickTime 2.0 was going to have the stuff that
allows still pictures to be quickly rotated.

Then again, it does make sense for this kinda stuff to be in QuickDraw/GX.

Anyone know the skinny on this?

In particular, I am interested in rotating pixmaps an arbitrary number of
degrees, kinda thing.

Thanks.

Mark Hanrek

+++++++++++++++++++++++++++

>From jwbaxter@olympus.net (John W. Baxter)
Date: Fri, 17 Jun 1994 09:10:47 -0700
Organization: Internet for the Olympic Peninsula

In article <CrIzC4.9K0@crash.cts.com>, Mark Hanrek <hanrek@cts.com> wrote:

> In article <jwbaxter-160694150005@ptpm010.olympus.net> John W. Baxter,
> jwbaxter@olympus.net writes:
> 
> > QuickDraw GX makes rotated text (or rotated anything, almost) trivial. 
> 
...
> In particular, I am interested in rotating pixmaps an arbitrary number of
> degrees, kinda thing.

QD GX does that, in two fundamentally different ways: (a) by shuffling the
pixels around in the actual bitmap geometry, or (b) by applying a rotation
transform during drawing.  (a) is often very bad, particularly if you are
going to rotate several times.  There's an example of the result of that in
the color plates at the front of Inside Mac:  QD GX Graphics.  [It starts
as a nice color ramp...it finishes as a Rorschach inkblot.]

-- 
John Baxter    Port Ludlow, WA, USA  [West shore, Puget Sound]
   No hablo Intel.
   jwbaxter@pt.olympus.net

+++++++++++++++++++++++++++

>From johnb@tempest.net.hk (John W. Blackburne)
Date: 18 Jun 1994 03:50:03 GMT
Organization: Tempest, Hong Kong

Jens Alfke (jens_alfke@powertalk.apple.com) wrote:

> Why yes -- QuickDraw GX supports arbitrary transformations of text,
including
> skew and perspective in addition to rotation. Anything you can describe in
a
> 3x3 matrix. Not only that, but you can allow the user to edit the
transformed
> text (typing into perspective text is pretty trippy.) You can also fit text
> to a curve, but it's not directly editable after that.

Can someone please explain to me how this works. If you are using a 3 x 3
matrix (on an anything x anything matrix) for transformations you get
linear transformations, which include scaling, rotating, reflecting and
skewing but NOT transforming the perspective of a shape, at least not when
operating on the real two-dimensional space QD GX works in.

John

                  Tempest, a FirstClass BBS, Hong Kong 802-7395
                              John W. Blackburne, administrator
- - When You're cruisin' in overdrive,
       Don' have to listen to no, run o' the mill talk jive ---

+++++++++++++++++++++++++++

>From Cary Clark <crclark@apple.com>
Date: Sun, 19 Jun 1994 22:04:31 GMT
Organization: Apple Computer, Inc.

In article <3624861694.8241498@tempest.tempest.net.hk> John W.
Blackburne, >>Jens Alfke (jens_alfke@powertalk.apple.com) wrote:
>> Why yes -- QuickDraw GX supports arbitrary transformations of text, 
>> including skew and perspective in addition to rotation. Anything you
>> can describe in a 3x3 matrix. Not only that, but you can allow the user
>> to edit the transformed text (typing into perspective text is pretty
>>  trippy.)

johnb@tempest.net.hk writes:
>Can someone please explain to me how this works. If you are using a 3 x 3
>matrix (on an anything x anything matrix) for transformations you get
>linear transformations, which include scaling, rotating, reflecting and
>skewing but NOT transforming the perspective of a shape, at least not
>when operating on the real two-dimensional space QD GX works in.

QuickDraw GX expresses all of its coordinates by the vector (x, y, 1).
Multiplying this by the 3x3 results in (x', y', z'). Viewing this back in
the destination space requires that z = 1, so this vector is normalized
as (x'/z', y'/z', 1). The extra divisions required by perspective
calculations are performed only when necessary, so that non-perspective
drawing isn't penalized.

Cary Clark
Apple Computer, Inc.

+++++++++++++++++++++++++++

>From kelley@cs.dal.ca (Dan Kelley)
Date: Mon, 20 Jun 1994 12:40:28 GMT
Organization: Oceanography, Dalhousie University, Halifax, NS, Canada

The answers to my question about rotated text have all mentioned GX.  I'm new
to the mac, and have 2 questions:

1) is quickdraw gx available on all shipping platforms, or is it something new?

2) is there a downloadable document on gx, or a book title I can look up?

Thanks very much to everyone who has been so helpful.
-- 
Dan Kelley                   | dan.kelley@dal.ca            (902)494-1694
Oceanography Department      |   ``We rise again,
Dalhousie University         |     in the faces of our children''
Halifax, NS, CANADA, B3H 4J1 |   The Rankin Family <North Country>

+++++++++++++++++++++++++++

>From jwbaxter@olympus.net (John W. Baxter)
Date: Mon, 20 Jun 1994 07:50:02 -0700
Organization: Internet for the Olympic Peninsula

In article <Crp4JI.JJK@cs.dal.ca>, kelley@cs.dal.ca (Dan Kelley) wrote:

> The answers to my question about rotated text have all mentioned GX.  I'm new
> to the mac, and have 2 questions:
> 
> 1) is quickdraw gx available on all shipping platforms, or is it something new?

QuickDraw GX is just emerging into the post-beta world.  It is available
for license to distribute with applications which use it, and will be
shipped with System 7.5 (real soon now).

> 2) is there a downloadable document on gx, or a book title I can look up?
There is more than "a book".  There are 7 new volumes of Inside Macintosh,
3 of which (at least) have hit the stores in paper form.  They are
available (except for the Overview document so far) on various Apple CD
ROMs.  Issue 18 of "develop" ($10 as a back issue...double check that the
back issue includes the same-numbered CD) is one source.  "develop" is
worth subscribing too regardless of the CD, IMHO.

It's been more years than it should have been since I have been in Halifax
(via cruise ship).
-- 
John Baxter    Port Ludlow, WA, USA  [West shore, Puget Sound]
   No hablo Intel.
   jwbaxter@pt.olympus.net

+++++++++++++++++++++++++++

>From bhorling@mail.trincoll.edu (Bryan Horling)
Date: Sun, 19 Jun 1994 20:55:49 -0500
Organization: Trinity College

In article <1994Jun19.220431.20334@gallant.apple.com>, Cary Clark
<crclark@apple.com> wrote:

> In article <3624861694.8241498@tempest.tempest.net.hk> John W.
> Blackburne, >>Jens Alfke (jens_alfke@powertalk.apple.com) wrote:
> >> Why yes -- QuickDraw GX supports arbitrary transformations of text, 
> >> including skew and perspective in addition to rotation. Anything you
> >> can describe in a 3x3 matrix. Not only that, but you can allow the user
> >> to edit the transformed text (typing into perspective text is pretty
> >>  trippy.)
> 
> johnb@tempest.net.hk writes:
> >Can someone please explain to me how this works. If you are using a 3 x 3
> >matrix (on an anything x anything matrix) for transformations you get
> >linear transformations, which include scaling, rotating, reflecting and
> >skewing but NOT transforming the perspective of a shape, at least not
> >when operating on the real two-dimensional space QD GX works in.
> 
> QuickDraw GX expresses all of its coordinates by the vector (x, y, 1).
> Multiplying this by the 3x3 results in (x', y', z'). Viewing this back in
> the destination space requires that z = 1, so this vector is normalized
> as (x'/z', y'/z', 1). The extra divisions required by perspective
> calculations are performed only when necessary, so that non-perspective
> drawing isn't penalized.
> 
> Cary Clark
> Apple Computer, Inc.

Is there any easy way to do rotations without QuickDraw GX?  Say you wanted
to write in the y axis label on a graph or somthing like that (so that the
the bottom of the text was parallel with the axis), how could you go about
doing it?

-- 
 Bryan C.Horling       ||||     
 Trinity College        @@      bhorling@mail.cc.trincoll.edu  
  Hartford, CT          == 

+++++++++++++++++++++++++++

>From Jens Alfke <jens_alfke@powertalk.apple.com>
Date: Mon, 20 Jun 1994 20:58:11 GMT
Organization: Apple Computer

John W. Blackburne, johnb@tempest.net.hk writes:
> Can someone please explain to me how this works. If you are using a 3 x 3
> matrix (on an anything x anything matrix) for transformations you get
> linear transformations, which include scaling, rotating, reflecting and
> skewing but NOT transforming the perspective of a shape, at least not when
> operating on the real two-dimensional space QD GX works in.

3x3 matrices, if you set the top-right and middle-right elements to be
nonzero, WILL produce perspective transforms that make it appear as though
the two-dimensional drawing plane has been rotated in 3space and projected
back onto the screen. You obviously can't draw stuff in real 3d this way,
since your input is only 2d points, but for mapping your drawing onto an
arbitrarily oriented surface in 3space it's ideal. Check out some of the
demos at the end of the SlideMaster GX demo -- there's one that does a flyby
of some 3d text, and another with a 3d rotating die. (I think for the die
they had to use a different transformation for each face.)

--Jens Alfke
  jens_alfke@powertalk              Rebel girl, rebel girl,
            .apple.com              Rebel girl you are the queen of my world

---------------------------

End of C.S.M.P. Digest
**********************