home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Information
/
CSMP Digest
/
volume 2
/
csmp-v2-002.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.0 KB
|
1,067 lines
|
[
TEXT/R*ch
]
C.S.M.P. Digest Fri, 08 Jan 93 Volume 2 : Issue 2
Today's Topics:
How can I draw arrowheads on lines?
How long can an AE handler take?
Calling C from Pascal vs calling Pascal from C
Perfect Window Zooming (longish)
Is this a BaseAddress problem with the Quadra .?.?.?.
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. If you don't have access to news, there is
no way that I know of for you to post articles to the group.
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: tcwan@umiami.ir.miami.edu
Subject: How can I draw arrowheads on lines?
Date: 3 Dec 92 14:02:41 GMT
Organization: Univ of Miami IR
I'm not sure where to look for this info, so if someone could either
point me to the right source (I checked the UMPG, without success) or
could supply some code snippets, I'd appreciate it :) :)
I'm trying to draw arrowed lines like those in MacDraw or Canvas. Is
there a simple way to accomplish this? The lines can have any gradient
and the arrowhead sizes are supposed to be quite small (within a 4x4 to 8x8
enclosing square).
PS: I'm programming using TC 5.0.2 & TCL 1.1.2, if that helps
Thanks for your help,
t.c.
Grad Student,
Univ of Miami, FL
#I reserve the right to be wrong :)
+++++++++++++++++++++++++++
Date: 4 Dec 92 21:58:25 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <1992Dec3.090241.14165@umiami.ir.miami.edu> tcwan@umiami.ir.miami.edu writes:
>I'm not sure where to look for this info, so if someone could either
>point me to the right source (I checked the UMPG, without success) or
>could supply some code snippets, I'd appreciate it :) :)
Use a polygon. Beware the off-by-one drawing of polygons.
Cheers,
/ h+
- --
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
The word "politics" is derived from the word "poly", meaning
"many", and the word "ticks", meaning "blood sucking parasites".
-- Larry Hardiman
+++++++++++++++++++++++++++
From: tcwan@umiami.ir.miami.edu
Date: 4 Dec 92 21:42:47 EST
Organization: Univ of Miami IR
tte) writes:
> In <1992Dec3.090241.14165@umiami.ir.miami.edu> tcwan@umiami.ir.miami.edu writes:
>
>>I'm not sure where to look for this info, so if someone could either
>>point me to the right source (I checked the UMPG, without success) or
>>could supply some code snippets, I'd appreciate it :) :)
>
> Use a polygon. Beware the off-by-one drawing of polygons.
Well, Eggert Thorlacius (ebth@rhi.hi.is) suggested using an arc to approximate
a triangle, and it works pretty well. (ie: use PtToAngle to find the angle
of the line, and drawing a filled arc centered about the point where the
arrow should be. The reason I was hesitant on using polygons is that I'd have
to calculate the gradient and normal, then find out which points to set as the
vertices.
If QD supplies some of this functions for free (I believe it's done in fixed
point, so it should be faster too), I'd rather do it that way.
Thanks for all your help though :)
t.c.
> Cheers,
> / h+
> > --
> -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
> The word "politics" is derived from the word "poly", meaning
> "many", and the word "ticks", meaning "blood sucking parasites".
> -- Larry Hardiman
+++++++++++++++++++++++++++
From: lhp@daimi.aau.dk (Lasse Hiller|e Petersen)
Date: 5 Dec 92 07:14:01 GMT
Organization: DAIMI: Computer Science Department, Aarhus University, Denmark
tcwan@umiami.ir.miami.edu writes:
[How to use arcs as arrowheads deleted]
>If QD supplies some of this functions for free (I believe it's done in fixed
>point, so it should be faster too), I'd rather do it that way.
Filled arcs. That's how Word 5 does it. Ugliest arrowheads I've ever seen!
- --
Lasse Hiller|e Petersen ! /*] Once upon a time at 2:30 in
lhp@daimi.aau.dk - lassehp@imv.aau.dk ! /*< the afternoon, there lived
Department of Information & Media Science !/* *\ a wise&benevolent&wonderful
Aarhus University, Denmark ! L L wizard who wore a big hat...
---------------------------
From: goodill_eric@tandem.com (Eric Goodill)
Subject: How long can an AE handler take?
Date: 2 Dec 92 16:29:54 GMT
Organization: Tandem Computers, Inc.
Hi,
I'm writing a drag-and-drop application: you drag a file onto it, it does
it's thing to the file, and quits. The thing it does takes about 20
seconds or so (at least on a IIci). Should I go ahead and call my code
that takes this long directly from my odoc handler, or should I just set a
flag in odoc (saving the info about the dropped file in a global) and then
return to my event loop which detects the flag and takes the time. How
long does Apple's Apple event manager that called my odoc handler expect me
to take? Are there any limits to how long my handlers can take before
returning?
Cheers, Eric
Eric Goodill, goodill_eric@tandem.com, Tandem Computers, Cupertino, Calif.
+++++++++++++++++++++++++++
Organization: Royal Institute of Technology, Stockholm, Sweden
Date: Thu, 3 Dec 1992 12:32:42 GMT
In <goodill_eric-021292082533@ericg.cpd.tandem.com> goodill_eric@tandem.com (Eric Goodill) writes:
>I'm writing a drag-and-drop application: you drag a file onto it, it does
>it's thing to the file, and quits. The thing it does takes about 20
>seconds or so (at least on a IIci). Should I go ahead and call my code
>that takes this long directly from my odoc handler, or should I just set a
>flag in odoc (saving the info about the dropped file in a global) and then
>return to my event loop which detects the flag and takes the time. How
t call WaitNextEvent reliably in an AppleEvent handler,
unless you call AEInteractWithUser first.
re calling WaitNextEvent, you should be fine, since
background tasks get their time. However, it might simply be the
easiest to retrieve all files affected as a handle of FSSpecs, and
use the main loop to take the time.
Cheers,
/ h+
- --
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
"From now on I will re-label the EQ on the deck as Fizz and Wobble
instead of HF and LF."
+++++++++++++++++++++++++++
From: jpugh@apple.com (Jon Pugh)
Date: 7 Dec 92 03:25:15 GMT
Organization: Apple Computer, Inc.
In article <goodill_eric-021292082533@ericg.cpd.tandem.com>,
goodill_eric@tandem.com (Eric Goodill) wrote:
>
> Hi,
>
> I'm writing a drag-and-drop application: you drag a file onto it, it does
> it's thing to the file, and quits. The thing it does takes about 20
> seconds or so (at least on a IIci). Should I go ahead and call my code
> that takes this long directly from my odoc handler, or should I just set a
> flag in odoc (saving the info about the dropped file in a global) and then
> return to my event loop which detects the flag and takes the time. How
> long does Apple's Apple event manager that called my odoc handler expect me
> to take? Are there any limits to how long my handlers can take before
> returning?
There are no limits built into the AE manager. All events are sent with a
timeout specified. This is how the AE manager decides how long to wait for
a reply. The Finder sends a timeout of about 300 ticks, but it doesn't
wait for a reply anyhow, so it doesn't matter. The Finder just goes about
its business.
You can take as long as you like. Don't bother messing with the reply from
the odoc event (or the oapp or the pdoc events). Other events should be
handled on an event by event basis.
Jon
---------------------------
From: felciano@summit.stanford.edu (Ramon M. Felciano)
Subject: Calling C from Pascal vs calling Pascal from C
Organization: Stanford University Medical Media and Information
Date: Sun, 22 Nov 92 01:01:38 GMT
I would like to clean up my tools and utilities libraries in order to
make them as generically useful as possible. I would like the routines
to be callable both from THINK Pascal and from THINK C. Which should I
use to write the routines and build the library with?
Thanks!
Ramon
+----------------------------------------------------------------+
| Ramon M. Felciano felciano@summit.stanford.edu |
| Associate Director, SUMMIT (415) 723-9688 |
| Stanford University Medical Media and Information Technologies |
+----------------------------------------------------------------+
+++++++++++++++++++++++++++
From: mrubin@hebb.uoregon.edu (Matthew Rubin)
Date: 28 Nov 92 00:52:46 GMT
Organization: Institute of Cognitive & Decision Sciences
Calling C from Pascal vs calling Pascal from C
As Think C exists right now I don't think Symantec provided any support
for including
compiled Think Pascal libraries into a Think C project. However, the
reverse, including compiled Think C libraries into a Think Pascal project
is supported. Make sure you
declare all C functions intended to be called from the Think Pascal
environment with
the *pascal* keyword. In order to call a compiled C function in a
library after it
has been added to the Think Pascal project, you first need to create an
interface file
which gives all the prototypes (ie. function names and formal parameter
lists) for
the library functions you wish to be visible to the Think Pascal
evironment. See
Think Pascal 4.0's user manual (p. 183 -Using Think C with Think Pascal)
for more information.
+++++++++++++++++++++++++++
From: peter@ncrpda.curtin.edu.au (Peter N Lewis)
Date: 30 Nov 92 01:26:09 GMT
Organization: NCRPDA, Curtin University
In article <1992Nov28.005246.4382@sol.ctr.columbia.edu>, Matthew Rubin
<mrubin@hebb.uoregon.edu> wrote:
> As Think C exists right now I don't think Symantec provided any support
> for including compiled Think Pascal libraries into a Think C project.
> However, the reverse, including compiled Think C libraries into a Think
> Pascal project is supported. Make sure you declare all C functions
> intended to be called from the Think Pascal environment with the
> *pascal* keyword. In order to call a compiled C function in a
> library after it has been added to the Think Pascal project, you
> first need to create an interface file which gives all the prototypes
> (ie. function names and formal parameter lists) for the library
> functions you wish to be visible to the Think Pascal evironment. See
> Think Pascal 4.0's user manual (p. 183 -Using Think C with Think Pascal)
> for more information.
The problem with all this is that if you write any reasonable library in
either C or Pascal, you need to include trap calls, like HOpen. But if you
call HOpen in the Pascal library, then in includes glue code defining
HOpen, when you try to link this with a C library which also calls HOpen,
you get a link error because the glue for each HOpen (the Pascal and C
interface) are both included.
I havent found a way around this which effectively makes it impossible to
include reasonable C or Pascal libraries in a Pascal or C program. If
anyone knows how to get around this I'd be interested in hearing about it.
Peter.
_______________________________________________________________________
Peter N Lewis <peter@ncrpda.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
From: rhorn@csws19.ic.sunysb.edu (Robert Horn)
Date: 30 Nov 92 20:39:10 GMT
Organization: State University of New York at Stony Brook
In article <peter-301192092234@rocky.curtin.edu.au> peter@ncrpda.curtin.edu.au (Peter N Lewis) writes:
>In article <1992Nov28.005246.4382@sol.ctr.columbia.edu>, Matthew Rubin
><mrubin@hebb.uoregon.edu> wrote:
>
>The problem with all this is that if you write any reasonable library in
>either C or Pascal, you need to include trap calls, like HOpen. But if you
>call HOpen in the Pascal library, then in includes glue code defining
>HOpen, when you try to link this with a C library which also calls HOpen,
>you get a link error because the glue for each HOpen (the Pascal and C
>interface) are both included.
>
>I havent found a way around this which effectively makes it impossible to
>include reasonable C or Pascal libraries in a Pascal or C program. If
>anyone knows how to get around this I'd be interested in hearing about it.
Perhaps I'm missing something (nonetheless I post my ignorance across the
entire civilized world), but can't you just not include the glue for the
traps in your library? I believe that the glue is the very same glue for
both of Symantec's compilers, and even if not exactly the same, it should
be mostly compatable, since the Think C glue uses pascal calling conventions.
- --
rhorn@ic.sunysb.edu Never choose a college because it has a duckpond.
$@` Send me hate mail, I love it.
+++++++++++++++++++++++++++
From: russells@ccu1.aukuni.ac.nz (Russell Street)
Date: 30 Nov 92 23:59:31 GMT
Organization: University of Auckland, New Zealand.
peter@ncrpda.curtin.edu.au (Peter N Lewis) writes:
>In article <1992Nov28.005246.4382@sol.ctr.columbia.edu>, Matthew Rubin
><mrubin@hebb.uoregon.edu> wrote:
>> As Think C exists right now I don't think Symantec provided any support
>> for including compiled Think Pascal libraries into a Think C project.
Well not directly at least. Think Pascal libraries are compatible
with MPW object files so you can use MPW to convert them to an MPW object
file "proper" and then use Think C's oConv utility to turn it to a
Think C project -- whew!
>The problem with all this is that if you write any reasonable library in
>either C or Pascal, you need to include trap calls, like HOpen. But if you
>call HOpen in the Pascal library, then in includes glue code defining
>HOpen, when you try to link this with a C library which also calls HOpen,
>you get a link error because the glue for each HOpen (the Pascal and C
>interface) are both included.
That is because you _are_ including the glue twice. The solution
is to remove MacTraps from the Think C project before you build
it as a library.
- -----------------------------------------------------------------
Russell Street (russells@ccu1.aukuni.ac.nz)
Listeners are requested to make the necessary adjustments
+++++++++++++++++++++++++++
From: peter@ncrpda.curtin.edu.au (Peter N Lewis)
Organization: NCRPDA, Curtin University
Date: Thu, 3 Dec 1992 05:09:15 GMT
In article <1992Nov30.203910.14412@sbcs.sunysb.edu>,
rhorn@csws19.ic.sunysb.edu (Robert Horn) wrote:
>
> In article <peter-301192092234@rocky.curtin.edu.au> peter@ncrpda.curtin.edu.au (Peter N Lewis) writes:
> >I havent found a way around this which effectively makes it impossible to
> >include reasonable C or Pascal libraries in a Pascal or C program. If
> >anyone knows how to get around this I'd be interested in hearing about it.
>
> Perhaps I'm missing something (nonetheless I post my ignorance across the
> entire civilized world), but can't you just not include the glue for the
> traps in your library? I believe that the glue is the very same glue for
> both of Symantec's compilers, and even if not exactly the same, it should
> be mostly compatable, since the Think C glue uses pascal calling conventions.
Well, someone correct me if I'm wrong, but as far as I could tell at the
time I tried this, the TC glue defines HOpen (and presuambly lots of
others) as C functions, not pascal functions. The TP glue defines them as
Pascal functions. So if you don't include the C glue, the C routines will
explode when they call the pascal glue using C calling conventions.
Anyway, that was my interpretation of the problem when I tried this
briefly, I could be wrong, it happens quite often :-)
Peter.
_______________________________________________________________________
Peter N Lewis <peter@ncrpda.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
From: mrubin@hebb.uoregon.edu (Matthew Rubin)
Date: 7 Dec 92 00:11:51 GMT
Organization: Institute of Cognitive & Decision Sciences
In article <peter-031292130750@rocky.curtin.edu.au> Peter N Lewis,
peter@ncrpda.curtin.edu.au writes:
>Well, someone correct me if I'm wrong, but as far as I could tell at the
>time I tried this, the TC glue defines HOpen (and presuambly lots of
>others) as C functions, not pascal functions. The TP glue defines them
as
>Pascal functions. So if you don't include the C glue, the C routines
will
>explode when they call the pascal glue using C calling conventions.
>Anyway, that was my interpretation of the problem when I tried this
>briefly, I could be wrong, it happens quite often :-)
When I originally posted I did not anticipate calling Toolbox routines
from
within the C library. If you are going to call Toolbox routines from the
TC library,
declare the routine as *extern pascal* and don't include MacTraps in your
TC library.
That way the toolbox is only included once in TP and any toolbox
routines in the TC
library follow pascal calling conventions because of their *extern
pascal* keyword
definitions.
---------------------------
From: nerm@apple.com (Dean Yu)
Subject: Perfect Window Zooming (longish)
Date: 7 Dec 92 02:10:34 GMT
Organization: Apple Computer, Inc.
About once a year, I go on a tirade about how few programs zoom their
windows properly. Most programs zoom to the full size of the main screen;
some others only make the window as big as they need to, but still move it
to the main screen, even if I have the window on another monitor. The 7.0
Finder comes close to making me happy, but every once in a while, it has
the annoying habit of zipping a window to the main screen for some unknown
reason.
I was writing some application code recently, so I took the opportunity
to make it zoom windows the way I wished everything else would zoom
windows. I'm posting the code that came out the other side in the hopes
that more programs will zoom windows correctly in the future.
What follows are the rules describing how zooming windows should behave.
Most of it is a re-hash of the HI Tech Note on zooming windows, but some of
it is new stuff that Apple hasn't really told people "this is how you
should do it" yet.
Rules on Size:
1) The standard state of a window should be the most useful size for
your program: word processors, for example, would probably want their
standard state to be the size of a printed page. The Finder's most useful
size is the size that will just show all the icons in that window.
2) If the most useful size would be larger than the monitor you're
zooming to, the dimension that is larger than the monitor should be pinned
to that dimension of the monitor. If the standard state of a word
processor document window is 8.5 by 11 inches, but the screen is less than
11 inches high, the window should only be as high as the height of the
monitor.
3) When zooming a window to the screen with the menu bar, leave a strip
of space on the right side of the screen to let volume icons in the Finder
show through.
Rules on Position:
The basic guideline for positioning a window during zooming is that the
window should move as little as possible in order to avoid distracting the
user.
4) A window in it's standard state should be positioned so that it is
entirely on one monitor. When a window is zoomed from the user state to
the standard state, and the window is straddling more than one screen, the
window should be zoomed to the monitor that contains the largest portion of
the window's content region.
5) If possible, the standard state of a window should be anchored at the
current top left corner of the window. When a window zooms from the user
state to the standard state, and the standard state size will fit on the
screen without moving the window, just resize the window. If the standard
state of the window will not fit on the screen, offset the window so that
the standard state will fit. (Note that this is different than the zooming
window HI Tech Note, which suggests moving the window to a default position
if zooming to the standard state will cause a portion of the window to wind
up offscreen.)
This is best described with an illustration. Say you have a screen setup
like the following, where a window is partially offscreen:
_________________________
|_______________________|
__________________|.......................|
|.................|.......................|
|.................|.......................|
|.................|.......................|
|.......__________|____...................|
|.......| | |...................|
|.......| | |...................|
|-----------------|-----------------------|
|_____________|
After zooming to it's standard state, the window should be positioned on
the monitor that has most if it's content region, like this:
_________________________
|_______________________|
__________________|.......................|
|.................|.......................|
|.................|.......................|
|.................|.......................|
|...______________|.......................|
|...| ||.......................|
|...| ||.......................|
|...| ||.......................|
|...|____________||.......................|
|-----------------|-----------------------|
A Few Notes About the Code
People keep asking me why I insist on using MPW instead of Think. The
best answer I can give is that I'm used to MPW. This code was written in
MPW C, so Think C users might have to do some tweaking.
The CalculatePerfectDocumentSize() routine is the one routine that will
vary from application to application. In this routine, you should
calculate the optimum size for you document window as if you had one
infinitely large monitor. I've included what I needed to do in this
routine for my application; yours will probably be more complicated.
The coolest bit of inspiration that hit me when I was writing this code
was to have DeviceLoop() walk through the screens for me and call a routine
to figure out window area for each screen the window intersects. This
simplifies the code a lot, but of course, it limits it to System 7 users.
What a bummer.
Any illegible characters that come out are curly quotes which I use in my
source, but don't translate well when posting a Usenet article.
Finally, this code assumes standard rectangular document windows. If
you're not using 'WDEF' 0, you might have to adjust the kMinTitleBarHeight
constant. If you don't have rectangular windows, you'll have to rework the
CalcWindowAreaOnScreen() routine to figure out the area of the window based
on it's geometric shape. (Anyone remember how to figure out the area of a
circle? I don't...)
The Code (with apologies about the formatting)
struct ZoomData {
GDHandle screenWithLargestPartOfWindow;
long largestArea;
Rect windowBounds;
};
typedef struct ZoomData ZoomData, *ZoomDataPtr;
#define kNudgeSlop 4
#define kIconSpace 64
#define kMinTitleBarHeight 21
void ZoomTheWindow(WindowPeek theWindow, short zoomState);
pascal void CalcWindowAreaOnScreen(short depth, short deviceFlags, GDHandle
targetDevice, long userData);
void CalculatePerfectDocumentSize(WindowPtr theWindow, Rect
*contentSize);
short CalculateOffsetAmount(short startPoint1, short endPoint1, short
startPoint2, short endPoint2, short
screenEdge1,
short screenEdge2);
void ZoomTheWindow(WindowPeek theWindow, short zoomState)
{
ZoomData zoomData;
FontInfo systemFontInfo;
Rect newStandardRect;
Rect scratchRect;
Rect screenRect;
GrafPtr currentPort;
GrafPtr windowManagerPort;
RgnHandle localContentRegion;
short horizontalAmountOffScreen;
short verticalAmountOffScreen;
short titleBarHeight;
GetPort(¤tPort);
// Calculate the height of the title bar
GetWMgrPort(&windowManagerPort);
SetPort(windowManagerPort);
GetFontInfo(&systemFontInfo);
titleBarHeight = (short) (systemFontInfo.ascent + systemFontInfo.descent +
4);
if ((titleBarHeight % 2) == 1)
titleBarHeight--;
if (titleBarHeight < kMinTitleBarHeight)
titleBarHeight = kMinTitleBarHeight;
SetPort((WindowPtr) theWindow);
// If the window is being zoomed into the standard state, calculate the
best
// size to display the windowUs information.
if (zoomState == inZoomOut) {
zoomData.screenWithLargestPartOfWindow = nil;
zoomData.largestArea = -1;
zoomData.windowBounds = (**(theWindow->contRgn)).rgnBBox;
// Use DeviceLoop to walk through all the active screens to find the one
with
// the largest portion of the zoomed window
localContentRegion = NewRgn();
RectRgn(localContentRegion, &(((WindowPtr) theWindow)->portRect));
DeviceLoop(localContentRegion, &CalcWindowAreaOnScreen, (long) &zoomData,
(DeviceLoopFlags) singleDevices);
DisposeRgn(localContentRegion);
screenRect = (**(zoomData.screenWithLargestPartOfWindow)).gdRect;
// Go figure out the perfect size for the window as if we had an
infinitely
// large screen
CalculatePerfectDocumentSize((WindowPtr) theWindow, &newStandardRect);
// Anchor the new rectangle at the windowUs current top left corner
OffsetRect(&newStandardRect, (**theWindow->contRgn).rgnBBox.left,
(**theWindow->contRgn).rgnBBox.top);
// If the new rectangle falls off the edge of the screen, nudge it so that
itUs
// just on the screen.
SectRect(&newStandardRect, &screenRect, &scratchRect);
if (!EqualRect(&newStandardRect, &scratchRect)) {
horizontalAmountOffScreen = CalculateOffsetAmount(newStandardRect.left,
newStandardRect.right,
scratchRect.left,
scratchRect.right,
screenRect.left,
screenRect.right);
verticalAmountOffScreen = CalculateOffsetAmount(newStandardRect.top,
newStandardRect.bottom,
scratchRect.top,
scratchRect.bottom,
screenRect.top,
screenRect.bottom);
OffsetRect(&newStandardRect, horizontalAmountOffScreen,
verticalAmountOffScreen);
}
// If weUre still falling off the edge of the screen, that means that the
// perfect size is larger than the screen, so we need to shrink down the
// standard size
SectRect(&newStandardRect, &screenRect, &scratchRect);
if (!EqualRect(&newStandardRect, &scratchRect)) {
if (newStandardRect.left < screenRect.left)
newStandardRect.left = (short) (screenRect.left + kNudgeSlop);
// Move in the right edge. If weUre zooming to the main screen, leave
some
// space for the first row of Finder icons on the right.
if (newStandardRect.right > screenRect.right)
newStandardRect.right = (short) (screenRect.right - kNudgeSlop);
if ((zoomData.screenWithLargestPartOfWindow == GetMainDevice()) &&
(newStandardRect.right > (screenRect.right - kIconSpace)))
newStandardRect.right = (short) (screenRect.right - kIconSpace);
// Move in the top. If weUre zooming to the main screen, make sure the
window
// doesnUt wind up underneath the menu bar.
if (newStandardRect.top < screenRect.top)
newStandardRect.top = (short) (screenRect.top + kNudgeSlop +
titleBarHeight);
if ((zoomData.screenWithLargestPartOfWindow == GetMainDevice()) &&
(newStandardRect.top < (screenRect.top + GetMBarHeight() +
titleBarHeight)))
newStandardRect.top = (short) (screenRect.top + GetMBarHeight() +
titleBarHeight);
if (newStandardRect.bottom > screenRect.bottom)
newStandardRect.bottom = (short) (screenRect.bottom - kNudgeSlop);
}
// WeUve got the best possible window position. Slam it into the
WStateData
// record, and let ZoomWindow take care of the rest.
(**((WStateDataHandle) (theWindow->dataHandle))).stdState =
newStandardRect;
}
ClipRect(&(((WindowPtr) theWindow)->portRect));
EraseRect(&(((WindowPtr) theWindow)->portRect));
ZoomWindow((WindowPtr) theWindow, zoomState, false);
SetPort(currentPort);
}
pascal void CalcWindowAreaOnScreen(short depth, short deviceFlags, GDHandle
targetDevice, long userData)
{
#pragma unused (depth, deviceFlags)
ZoomDataPtr zoomData = (ZoomDataPtr) userData;
long windowAreaOnScreen;
Rect windowPortionOnScreen;
SectRect(&(zoomData->windowBounds), &((**targetDevice).gdRect),
&windowPortionOnScreen);
OffsetRect(&windowPortionOnScreen, -windowPortionOnScreen.left,
-windowPortionOnScreen.top);
windowAreaOnScreen = (long) windowPortionOnScreen.right * (long)
windowPortionOnScreen.bottom;
if (windowAreaOnScreen > zoomData->largestArea) {
zoomData->largestArea = windowAreaOnScreen;
zoomData->screenWithLargestPartOfWindow = targetDevice;
}
}
void CalculatePerfectDocumentSize(WindowPtr theWindow, Rect *contentSize)
{
ArticleInfoPtr currentArticle;
short runningHeight;
short lineHeight;
lineHeight = GetLineHeight();
runningHeight = (short) (lineHeight + 4);
if (lineHeight < kMinLineHeight)
lineHeight = kMinLineHeight;
currentArticle = (**((IssueInfoHandle) GetWRefCon(theWindow))).articles;
while (currentArticle != nil) {
runningHeight += lineHeight;
currentArticle = currentArticle->nextArticle;
}
runningHeight++;
SetRect(contentSize, 0, 0, (theWindow->portRect).right -
(theWindow->portRect).left, runningHeight);
}
// Figure out how much we need to move the window to get it entirely on the
// monitor. If the window wouldnUt fit completely on the monitor anyway,
donUt
// move it at all; weUll make it fit later on.
short CalculateOffsetAmount(short startPoint1, short endPoint1, short
startPoint2, short endPoint2, short
screenEdge1,
short screenEdge2)
{
short offsetAmount;
if ((startPoint1 < screenEdge1) && (endPoint1 > screenEdge2))
offsetAmount = 0;
else {
offsetAmount = (short) ((endPoint1 - startPoint1) - (endPoint2 -
startPoint2));
if (offsetAmount > 0)
offsetAmount += kNudgeSlop;
if (endPoint1 > screenEdge2)
offsetAmount = (short) (-offsetAmount);
}
return offsetAmount;
}
- -- Dean Yu
Blue Meanie, Negative Ethnic Role Model, etc.
Apple Computer, Inc.
+++++++++++++++++++++++++++
From: keith@taligent.com (Keith Rollin)
Organization: Taligent
Date: Mon, 7 Dec 1992 20:47:47 GMT
In article <nerm-061292170139@90.10.20.86>, nerm@apple.com (Dean Yu) wrote:
>
> About once a year, I go on a tirade about how few programs zoom their
> windows properly.
Dean, thanks for posting this code. I hope that you can get it incorporated
into Technote #79 sometime. Also, it might be interesting to compare your
method with MacApp's and the Finder's (what does yours do that they
don't?).
> Finally, this code assumes standard rectangular document windows. If
> you're not using 'WDEF' 0, you might have to adjust the kMinTitleBarHeight
> constant.
> ...
> #define kMinTitleBarHeight 21
> ...
> // Calculate the height of the title bar
>
> GetWMgrPort(&windowManagerPort);
> SetPort(windowManagerPort);
> GetFontInfo(&systemFontInfo);
> titleBarHeight = (short) (systemFontInfo.ascent + systemFontInfo.descent +
> 4);
> if ((titleBarHeight % 2) == 1)
> titleBarHeight--;
> if (titleBarHeight < kMinTitleBarHeight)
> titleBarHeight = kMinTitleBarHeight;
I'm wondering why you do it this way. If you wanted the size of the
titlebar, why not subtract the top of the content region from the top of
the structure region?
In fact, this approach should probably be taken on all four sides of the
window's bounds. The approach I take is to calculate the bounds for the
window's _frame_, not its content area. Once I have that, I inset it by
delta's between the window's contRgn and strucRgn. This gives me a
rectangle that I can use in calls to ZoomWindow, MoveWindow, and
SizeWindow.
> localContentRegion = NewRgn();
> RectRgn(localContentRegion, &(((WindowPtr) theWindow)->portRect));
> DeviceLoop(localContentRegion, &CalcWindowAreaOnScreen, (long) &zoomData,
> (DeviceLoopFlags) singleDevices);
> DisposeRgn(localContentRegion);
> screenRect = (**(zoomData.screenWithLargestPartOfWindow)).gdRect;
It might be more generic here to clone the contRgn and localize it, rather
than assume that the content area is rectangular.
> ClipRect(&(((WindowPtr) theWindow)->portRect));
> EraseRect(&(((WindowPtr) theWindow)->portRect));
> ZoomWindow((WindowPtr) theWindow, zoomState, false);
One thing that some programs do, including the Finder, that's really nice
is examine the case where the window size changes, but not its location. In
that circumstance, they just call SizeWindow. One of the advantages of this
is that they don't have to call EraseRect, and don't end up redrawing the
entire window contents.
- -----
Keith Rollin
Phantom Programmer
Taligent, Inc.
+++++++++++++++++++++++++++
From: nerm@apple.com (Dean Yu)
Date: Mon, 7 Dec 1992 22:22:48 GMT
Organization: Apple Computer, Inc.
In article <keith-071292122558@kip-15.taligent.com>, keith@taligent.com
(Keith Rollin) wrote:
> Dean, thanks for posting this code. I hope that you can get it incorporated
> into Technote #79 sometime. Also, it might be interesting to compare your
> method with MacApp's and the Finder's (what does yours do that they
> don't?).
The biggest difference is that if the Finder determines that the standard
state won't fit on the screen by keeping the window anchored to it's
current position, it moves the window to a default position. My version
nudges the window so that it will fit on the screen. This is one of my
biggest peeves about how the Finder zooms it's windows. If you have a
window near the bottom of the screen and you zoom it, the Finder snaps it
to the top left of the screen. I'd much rather have the window just bumped
up a bit so that all of it shows up in it's new state instead of it moving
halfway across the screen where I have to refocus on the window.
> I'm wondering why you do it this way. If you wanted the size of the
> titlebar, why not subtract the top of the content region from the top of
> the structure region?
Because I knew how 'WDEF' 0 calculates the title bar height. :)
I didn't think of your way, and I agree it's better.
- -- Dean Yu
Blue Meanie, Negative Ethnic Role Model, etc.
Apple Computer, Inc.
---------------------------
From: BLOOMDA@ctrvax.vanderbilt.edu (_creative_output_)
Subject: Is this a BaseAddress problem with the Quadra .?.?.?.
Date: 18 Nov 92 23:26:53 GMT
Organization: Camp Vanderbilt Vision Research Center
Hi, Gals & Guys.
I do pseudo-instantaneous presentation of visual stimuli using
color table tricks. I.E., I read a byte from video RAM, write
into only the high or low 4 bits, as desired, and then write
my byte back out. Appropriately managing color tables, I can
paint an image of up to 16 colors invisibly while another image
of up to 16 colors is onscreen, then swap them in one VRT.
This technique broke when I tried it on a 24-bit card set to
8-bit mode. That's when I learned about incorporating the slot
number of the video card into the base address:
( ( baseAddr >> 24 ) | something ) << 20 | baseAddr, or somesuch
One of my bosses has left town for another University. He took his
third of my funding, and now I'm part-time here, so I'm incentivized
to keep supporting him through email.
He has a Quadra.
My code generates Bus Errors on his machine, during the loop which
accesses video RAM. This is _similar_ to the errors generated by
my earlier failure to account for the slot number.
I have 'testing access' to a Quadra 700 here, but not 'development
access'. That means I can go and bother someone in his office for
a moment to see if I got it right, and crash his machine many times.
I've gotten a hold of IM v6, the monster, and shall be perusing it
tonight. It may hold a solution. However, I'm moved to ask you
folks out there if anyone has a quick hint. Anybody run into this
difference?
(s)he who helps shall receive a brief burst of good thoughts from
Music City, U.S.A. and a personal thank-you. I'll check news and
mail at 2 a.m., so listen up hard for that burst of good karma...
- - Dave =(^;|= Dave Bloom, JSPS
bn: bloomda@vuctrvax
in: bloomda@ctrvax.vanderbilt.edu
"Mekka Lekka Hai, Lekka Heinie Ho"
+++++++++++++++++++++++++++
From: absurd@apple.apple.com (Tim Dierks, software saboteur)
Date: Fri, 20 Nov 1992 00:38:14 GMT
Organization: MacDTS Marauders
In article <1992Nov18.232653.13027@news.vanderbilt.edu>,
BLOOMDA@ctrvax.vanderbilt.edu (_creative_output_) wrote:
> 8-bit mode. That's when I learned about incorporating the slot
> number of the video card into the base address:
> ( ( baseAddr >> 24 ) | something ) << 20 | baseAddr, or somesuch
>
> - Dave =(^;|= Dave Bloom, JSPS
> bn: bloomda@vuctrvax
> in: bloomda@ctrvax.vanderbilt.edu
> "Mekka Lekka Hai, Lekka Heinie Ho"
Here's the right way to get the slot number of a monitor, given its
GDevice: (as a bonus, this also gets the name of the card in
question; to just get the slot, chop off all the lines after the
*slot = ... line.
OSErr
GetSlotAndName(GDHandle gDev,short *slot,char *name)
{ OSErr err;
short refNum;
SpBlock spb;
refNum = (**gDev).gdRefNum; // video driver refNum for this GDevice
*slot = (**(AuxDCEHandle)GetDCtlEntry(refNum)).dCtlSlot;
// slot in which this video card sits
spb.spSlot = *slot; // In the slot we're interested in
spb.spID = 0;
spb.spExtDev = 0;
spb.spCategory = 1; // Get the board sResource
spb.spCType = 0;
spb.spDrvrSW = 0;
spb.spDrvrHW = 0;
spb.spTBMask = 0;
err = SNextTypeSRsrc(&spb);
if (err)
return err;
spb.spID = 2; // Getting the description string
// spSPointer was set up by
SNextTypesResource
err = SGetCString(&spb);
if (err)
return err;
strcpy(name,(char *)spb.spResult); // Get the returned string
DisposPtr((Ptr)spb.spResult); // Undocumented; we have to dispose of
it
c2pstr(name);
return noErr;
}
You should also be very careful to use SwapMMUMode() to switch into
32-bit mode any time you write to the framebuffer, regardless of what
bitdepth it is at.
Tim Dierks
MacDTS, but what?
+++++++++++++++++++++++++++
From: paul@taniwha.UUCP (Paul Campbell)
Date: 2 Dec 92 19:45:51 GMT
Organization: Taniwha Systems Design
In article <1992Nov18.232653.13027@news.vanderbilt.edu>,
BLOOMDA@ctrvax.vanderbilt.edu (_creative_output_) wrote:
> 8-bit mode. That's when I learned about incorporating the slot
> number of the video card into the base address:
> ( ( baseAddr >> 24 ) | something ) << 20 | baseAddr, or somesuch
This ONLY works for a card that has it's frame buffer in slot space at the same
time that the CPU is running in 24-bit mode. Such a card would have it's
frame buffer at NuBus address Fs000000 ('s' is the slot number), and would be
accessed at the 24-bit address XXs00000 (X is a don't care), the MMU translates
from XXsABCDE to Fs0ABCDE. This ment one could use the magic address FssABCDE
to work in both spaces (provided the card degeneratively decoded bits 20-23
of incoming addresses, which reduces it's max address space to 1Mb).
These days cards can't afford to waste the address space (by ignoring bits
20-23) - a 24-bit card needs at least 4Mb of address space for it's frame
store (plus ROM and registers) these cards need to be accessed with addresses
like FsABCDEF in 32-bit mode since in 24-bit mode only 1Mb of address space is
available. Modern cards with large frame stores and lots of off-screen GWorld
memory need >16Mb and have NuBus 'SuperSlot' addresses and need to be accessed
in 32-bit mode with addresses like sABCDEFG.
Framestore base addresses DON'T always start with their LSBs being all 0s.
Don't count on the base addresses of the framestore remaining the same if the
user changes the bit depth. (and of course don't write directly to the screen
unless you absolutely have to anyway).
In short use the slot manager to get base addresses etc from slot numbers.
Paul
- --
Paul Campbell UUCP: ..!mtxinu!taniwha!paul AppleLink: CAMPBELL.P
Use up your Quayle jokes now while they're still good "Quayle for Pres. in '94"
Q: Why is Marilyn Quayle like Marion Barry?
A: They both suck a little dope.
---------------------------
End of C.S.M.P. Digest
**********************