home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Information
/
CSMP Digest
/
volume 1
/
csmp-v1-163.txt
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1994-12-08
|
50.4 KB
|
1,323 lines
|
[
TEXT/R*ch
]
C.S.M.P. Digest Sun, 09 Aug 92 Volume 1 : Issue 163
Today's Topics:
Time Manager
TAS instruction use
Can't use Sys7 icon suite commands!
How Do You Sleep?
Why can't I Quit?
CALLM/RTM (was Re: TAS instruction use)
Divisible Window Updates: Thought Crime?
The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. (This means you can't post questions to the
digest.)
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
cs.uoregon.edu). Article threads are not added to the digest until the last
article added to the thread is at least one month old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
[128.223.8.8] in the directory /pub/mac/csmp-digest. Be sure to read the
file /pub/mac/csmp-digest/README before downloading any files. The most
recent issues are available from sumex-aim.stanford.edu [36.44.0.6] in the
directory /info-mac/digest/csmp. If you don't have ftp capability, the sumex
archive has a mail server; send a message with the text '$MACarch help' (no
quotes) to LISTSERV@ricevm1.rice.edu for more information.
The digest is also available via email. Just send a note saying that you
want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
automatically receive each new issue as it is created. Sorry, back issues
are not available through the mailing list.
Send administrative mail to mkelly@cs.uoregon.edu.
-------------------------------------------------------
From: minow@apple.com (Martin Minow)
Subject: Time Manager
Date: 9 Jun 92 23:01:13 GMT
Organization: Apple Computer - MacDTS
In article <1992Jun2.101638.7127@eua.ericsson.se>, marcus@erix.ericsson.se
(Marcus Arendt) writes:
>
> Has anyone out there convinced the Time Manager to perform a
> periodic task in C? I've tried follow the instructions in
> IM VI chapter 23 but haven't succeded. Please help!
>
There's some sample code in the current (March 1992, I think) edition
of MacTutor (written by me) that might help. Also, if you have access
to the sample applications, look in the Fractal Application - there is
some sample Time Manager code hidden there.
Some things to watch out for:
- -- Your "clock-tick" function will be called as a completion routine. This
means that it can't move memory or depend on the value of A5. You can
use the time manager request record's refCon to remember A5 - see the
example on page 23-13.
- -- The best way to handle a repetitive task would probably be to use the
Process Manager's WakeUpProcess call (using the application's process
id that you've stored in a global somewhere) - that should cause your
process to leave WaitNextEvent. (This presumes System 7, of course).
This is all off the top of my head - hope it helps.
Martin Minow
minow@apple.com
+++++++++++++++++++++++++++
From: grobbins@Apple.COM (Grobbins)
Date: 10 Jun 92 05:54:11 GMT
Organization: Apple DTS, sort of
In article <26614@goofy.Apple.COM> minow@apple.com (New Guy In DTS) writes:
>In article <1992Jun2.101638.7127@eua.ericsson.se>, marcus@erix.ericsson.se
>(Marcus Arendt) writes:
>> Has anyone out there convinced the Time Manager to perform a
>> periodic task in C?
>-- The best way to handle a repetitive task would probably be to use the
> Process Manager's WakeUpProcess call (using the application's process
> id that you've stored in a global somewhere) - that should cause your
> process to leave WaitNextEvent.
Right on, Martin. This is one of my favorite System 7 strategies. It
ends up looking just like this:
TYPE enhTMTaskRec = RECORD
theTMTask: TMTask;
myA5: LONGINT
END;
enhTMTaskPtr = ^enhTMTaskRec;
FUNCTION GetTMInfo: enhTMTaskPtr;
INLINE $2E89; { put A1 on stack }
PROCEDURE MyTimeTask;
{ this routine is executed when the primed time manager task comes due }
VAR
recPtr: enhTMTaskPtr;
oldA5: LONGINT;
anOSErr: LONGINT;
BEGIN
recPtr := GetTMInfo; { get pointer to record for this task }
oldA5 := SetA5(recPtr^.myA5); { we want globals }
{ flag that time is up and wake the app }
timeTaskFlag := TRUE;
anOSErr := WakeUpProcess(myPSN);
{ make this task periodic }
PrimeTime(QElemPtr(recPtr), kTimerPrimer);
{ now back to our previously scheduled A5 world }
oldA5 := SetA5(oldA5);
END;
(code from ledApp, available from ftp.apple.com in the folder, er, directory
/dts/mac/sc/snippets/devices.hardware)
Then you can yield the maximum time in the WaitNextEvent call, either
MAXLONGINT or the appropriate idle time. Remember that Apple events
and any other events will wake a sleeping app, so feel free to crank
up the sleep value in the WNE call.
Grobbins grobbins@apple.com
Usual disclaimers apply.
+++++++++++++++++++++++++++
From: marcus@erix.ericsson.se (Marcus Arendt)
Date: 2 Jun 92 10:16:38 GMT
Organization: Ellemtel Telecom Systems Labs, Stockholm, Sweden
Has anyone out there convinced the Time Manager to perform a
periodic task in C? I've tried follow the instructions in
IM VI chapter 23 but haven't succeded. Please help!
/M.A.
- ------------------------------------------------------------------
- -- --
- -- Marcus H Arendt --
- -- Computer Science Laboratory --
- -- Ellemtel Telecom Systems Labs --
- -- P.O. Box 1505 --
- -- S-125 25 Stockholm --
- -- SWEDEN --
- -- --
- -- Email: marcus@super.eua.ericsson.se --
- -- Phone: +46-87273150 --
- -- --
- ------------------------------------------------------------------
+++++++++++++++++++++++++++
From: baker4@husc10.harvard.edu (David Baker)
Date: 6 Jul 92 23:33:50 GMT
Organization: Department of Psychology, Harvard University
Hi--
Does anyone else have the problem with the Time Manager (when computing
elapsed times) wherein the InsTime-PrimeTime-RmvTime sequence causes the
tmCount field to be completely wrong when using milliseconds (positive
values), but not microseconds (negative values)? I'm using 2^31, the maximum
long int value, as my PrimeTime count parameter. When it's negative, it's
fine, but when it's positiv, it isn't. For an approximately three-second
delay, I get 87,723,814 milliseconds.
Thanks in advance.
David
P.S. Please, if possible, respond to my "work" address below, and not to the
address in the "From" field above (my work machine doesn't have USENet
access).
- --
- -------------------------------------------------------------------------------
David P. Baker Misbrainer:
Work: dpb@huelings.harvard.edu The onions impressed herein are mine,
Home: baker4@husc.harvard.edu not throes of my imploder.
Office: William James Hall, 1204 He wouldn't want 'em, anyway.
(617) 495-3773
Department of Psychology
Harvard University
- -------------------------------------------------------------------------------
---------------------------
From: resnick@cogsci.uiuc.edu (Pete Resnick)
Subject: TAS instruction use
Organization: University of Illinois at Urbana
Date: Tue, 23 Jun 1992 03:22:08 GMT
Inside Mac VI p. 3-6 says that you should not use the TAS instruction
on a Mac SE or Mac II computer because the hardware does not support
it. Why is this? TAS is a 68000 instruction as far as my little M68000
User's Manual is concerned. What is the problem with using TAS on
these machines?
pr
- --
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
From: Mark.R.Valence@dartmouth.edu (Mark R. Valence)
Date: 23 Jun 92 13:32:25 GMT
Organization: Dartmouth College, Hanover, NH
Pete Resnick writes ---
Inside Mac VI p. 3-6 says that you should not use the TAS instruction
on a Mac SE or Mac II computer because the hardware does not support
it. Why is this? TAS is a 68000 instruction as far as my little M68000
User's Manual is concerned. What is the problem with using TAS on
these machines?
pr
- --- end of quote
The support that IM is refering to is the "indivisibility" (atomicity)
of the instruction (term used in the 68K User's Manual). What does
this mean? Well, for the standard Mac programmer (and the non-standard
Mac-programmer, too) TAS will work as you probably want it to. That
is, it will test the high bit of its operand, set the CC register
accordingly, and the set the high bit.
However, (and this is a big HOWEVER), if you are writing an operating
system for the 68K, and you want to make SURE that the TAS instruction
is not interrupted (by some task-spawwing interrupt which proceeds to
TAS the same memory location), then you must make sure that your
machine support TAS to its fullest extent. One good use of the TAS
instruction is to test guard flags to critical sections of an Operating
System. For an explanation of critical sections, semaphores, and
examples of what could go wrong, see any good Operating Systems book.
So, what should you do? Prepare for hypocracy: Use BSET #7,
<flag-byte> as a substitute for TAS. It performs the exact same
function, but is not "indivisible" (atomic).
Hope that helps,
Mark.
+++++++++++++++++++++++++++
From: hawley@adobe.com (Steve Hawley)
Organization: Adobe Systems Incorporated
Date: Wed, 24 Jun 1992 00:55:09 GMT
In article <1992Jun23.133225.10402@dartvax.dartmouth.edu> Mark.R.Valence@dartmouth.edu (Mark R. Valence) writes:
>However, (and this is a big HOWEVER), if you are writing an operating
>system for the 68K, and you want to make SURE that the TAS instruction
>is not interrupted (by some task-spawwing interrupt which proceeds to
>TAS the same memory location), then you must make sure that your
>machine support TAS to its fullest extent.
I think Pete wanted to know exactly _why_ TAS is an unsupported on the
listed Mac models. I'm curious too. According to my 68K reference, "the
operation is indivisible, using a read-modify-write memory operation."
Does this mean that those Mac models don't support read-modify-write?
You suggestion of using BSET #7, <ea> is very clever. It turns out that
BSET copies the value of bit before being set into the Z bit of the CC
register.
I'm still kind of lost as to how either mechanism wouldn't be indivisible?
Are interrupts processed on instruction boundaries or will they cause the
current instruction to be halted and restarted upon return?
If they are processed on instruction boundaries, I fail to see how either
instruction could be indivisible...
Steve Hawley
hawley@adobe.com
- --
"Did you know that a cow was *MURDERED* to make that jacket?"
"Yes. I didn't think there were any witnesses, so I guess I'll have to kill
you too." -Jake Johansen
+++++++++++++++++++++++++++
From: des7f@fulton.seas.Virginia.EDU (David E. Sappington)
Date: 24 Jun 92 08:02:10 GMT
Organization: University of Virginia
M68000 16/32-BIT MICROPROCESSOR PROGRAMMER'S REFERENCE MANUAL (4th edition)
p159 says:
TAS: "The operation is indivisible (using a read-modify-write memory cycle)
to allow synchronization of several processors.)"
resnick@cogsci.cso.uiuc.edu (Pete Resnick) writes:
[ I don't have IM-VI handy so I'll just quote Pete here. ]
> Inside Mac VI p. 3-6 says that you should not use the TAS instruction
> on a Mac SE or Mac II computer because the hardware does not support
> it.
I interpret this to mean that the Mac doesn't guarantee atomic operation
of the read-modify-write cycle. Thus (say) if you do a TAS on some address
in I/O space you can't be sure (based on r-m-w alone) that the I/O hardware
would not have changed the value in "memory" after the read but before the
write. I'm not sure how the Mac deals with the electrical signals generated
by a 680x0 executing a TAS.
hawley@adobe.com (Steve Hawley) writes:
>I'm still kind of lost as to how either mechanism wouldn't be indivisible?
Even if the read-modify-write cycle was supported (i.e. guaranteed atomic)
the TAS could be interrupted prior to the cycle: imagine a TAS <ea> where
<ea> pointed to a VM page that wasn't resident in physical memory. Of
course if r-m-w was atomic you'd get the desired behavior even if this
interrupt occurred.
>Are interrupts processed on instruction boundaries or will they cause the
>current instruction to be halted and restarted upon return?
Actually it's worse than either case. With VM an instruction might be
interrupted prior to completion. Furthermore you can't just "restart"
the instruction once the interrupt is completed; you have to "continue"
it. A good example would be a MOVEM.L <...>,-(a7) that page faults
midway through execution. Restarting would require that the initial
a7 be saved somewhere. Restarting might also cause problems when
reading/writing to I/O space since two operations on an address might
produce a different result than a single operation. On the 68010
(sorry, I don't have a manual for the higher MC chips handy) the RTE
restores the internal state of the CPU so that an instruction can be
continued.
Dave Sappington des7f@virginia.edu
Institute for Parallel Computation des7f@virginia.bitnet
University of Virginia
+++++++++++++++++++++++++++
From: Quinn <quinn@cs.uwa.edu.au>
Organization: The University of Western Australia
Date: Wed, 24 Jun 1992 08:58:04 GMT
In article <BqA40y.Cz9@news.cso.uiuc.edu> Pete Resnick,
resnick@cogsci.uiuc.edu writes:
>Inside Mac VI p. 3-6 says that you should not use the TAS instruction
>on a Mac SE or Mac II computer because the hardware does not support
>it. Why is this?
...and...
In article <1992Jun24.005509.23293@adobe.com> Steve Hawley,
hawley@adobe.com writes:
>I think Pete wanted to know exactly _why_ TAS is an unsupported on the
>listed Mac models. I'm curious too. According to my 68K reference, "the
>operation is indivisible, using a read-modify-write memory operation."
>Does this mean that those Mac models don't support read-modify-write?
Yes. Of course "Why?" is another question all together.
TAS is normally only used on multiprocessor systems. The
read-modify-write
bus cyclce ensures atomicity between processors. For a single process
(and correct me if I'm wrong 'cause I'm about to write a program that
relies on it (-: ) BSET will do the job.
Quinn "The Eskimo!" <quinn@cs.uwa.edu.au> "Real Coke, Diet .sig"
Department of Computer Science, The University of Western Australia
+++++++++++++++++++++++++++
From: jmunkki@vipunen.hut.fi (Juri Munkki)
Organization: Helsinki University of Technology
Date: Sun, 28 Jun 1992 16:55:19 GMT
In article <1992Jun24.005509.23293@adobe.com> hawley@adobe.com (Steve Hawley) writes:
>I think Pete wanted to know exactly _why_ TAS is an unsupported on the
>listed Mac models. I'm curious too. According to my 68K reference, "the
>operation is indivisible, using a read-modify-write memory operation."
>Does this mean that those Mac models don't support read-modify-write?
As far as I can remember, TAS is not supported because the classic Macintosh
relies on the fact that all Macintosh memory operations only operate on
every second clock cycle, so the remaining cycles can be used for video
access.
Of course, TAS is an exception and the result is that it causes the
processor to use the same cycles as the video memory. This causes all
those strange and wonderful popping and sizzling crashes on the old
Macs.
- --
Juri Munkki Windsurf: fast sailing
jmunkki@hut.fi Macintosh: fast software
+++++++++++++++++++++++++++
From: ray@netcom.com (Ray Fischer)
Date: 29 Jun 92 23:49:04 GMT
Organization: Netcom - Online Communication Services
hawley@adobe.com (Steve Hawley) writes ...
>You suggestion of using BSET #7, <ea> is very clever. It turns out that
>BSET copies the value of bit before being set into the Z bit of the CC
>register.
>
>I'm still kind of lost as to how either mechanism wouldn't be indivisible?
>Are interrupts processed on instruction boundaries or will they cause the
>current instruction to be halted and restarted upon return?
>
>If they are processed on instruction boundaries, I fail to see how either
>instruction could be indivisible...
When there is more than one processor on the same bus. The TAS is prevents
even another processor from getting at the memory location between the read
and the write. BSET doesn't provide this guarantee, even though the one
CPU won't interrupt the instruction while between the read and the write.
- --
Ray Fischer
rfischer@cs.stanford.edu
ray@netcom.com
+++++++++++++++++++++++++++
From: alexr@apple.com (Alexander M. Rosenberg)
Date: 1 Jul 92 17:43:52 GMT
Organization: Hackers Anonymous
In article <1992Jun23.133225.10402@dartvax.dartmouth.edu> Mark R. Valence,
Mark.R.Valence@dartmouth.edu writes:
>Pete Resnick writes ---
>
>Inside Mac VI p. 3-6 says that you should not use the TAS instruction
>on a Mac SE or Mac II computer because the hardware does not support
>it. Why is this? TAS is a 68000 instruction as far as my little M68000
>User's Manual is concerned. What is the problem with using TAS on
>these machines?
>
>--- end of quote
The address decoding hardware on the II and SE cannot handle the
Read-Modify-Write cycle that the TAS, CAS, or CAS2 instructions use. (Or so I
was lead to believe.)
That hardware generates a bus error when one of these cycles begin. It would
appear that some amount of software is available to emulate the instructions.
(They don't crash the machine under System 7.)
>
>The support that IM is refering to is the "indivisibility" (atomicity)
>of the instruction (term used in the 68K User's Manual). What does
>this mean? Well, for the standard Mac programmer (and the non-standard
>Mac-programmer, too) TAS will work as you probably want it to. That
>is, it will test the high bit of its operand, set the CC register
>accordingly, and the set the high bit.
>
It will not work necessarily at all. Do not use TAS, CAS, or CAS2 instructions.
>However, (and this is a big HOWEVER), if you are writing an operating
>system for the 68K, and you want to make SURE that the TAS instruction
>is not interrupted (by some task-spawwing interrupt which proceeds to
>TAS the same memory location), then you must make sure that your
>machine support TAS to its fullest extent. One good use of the TAS
>instruction is to test guard flags to critical sections of an Operating
>System. For an explanation of critical sections, semaphores, and
>examples of what could go wrong, see any good Operating Systems book.
>
>So, what should you do? Prepare for hypocracy: Use BSET #7,
><flag-byte> as a substitute for TAS. It performs the exact same
>function, but is not "indivisible" (atomic).
While the RMW cycle is designed to help with this sort of Operating System
support, it isn't used in the Mac OS. RMW instructions - just say no!
- ---------------------------------------------------------------------------
- - Alexander M. Rosenberg - INTERNET: alexr@apple.com - Yoyodyne -
- - 330 Waverley St., Apt B - UUCP:ucbvax!apple!alexr - Propulsion -
- - Palo Alto, CA 94301 - - Systems -
- - (415) 329-8463 - Nobody is my employer so - :-) -
- - - nobody cares what I say. - -
+++++++++++++++++++++++++++
From: ksand@apple.com (Kent Sandvik (Hacker))
Date: 3 Jul 92 02:38:27 GMT
Organization: Apple
In article <1992Jun24.080210.25912@murdoch.acc.Virginia.EDU>,
des7f@fulton.seas.Virginia.EDU (David E. Sappington) wrote:
> >Are interrupts processed on instruction boundaries or will they cause the
> >current instruction to be halted and restarted upon return?
>
> Actually it's worse than either case. With VM an instruction might be
> interrupted prior to completion. Furthermore you can't just "restart"
> the instruction once the interrupt is completed; you have to "continue"
> it. A good example would be a MOVEM.L <...>,-(a7) that page faults
> midway through execution. Restarting would require that the initial
> a7 be saved somewhere. Restarting might also cause problems when
> reading/writing to I/O space since two operations on an address might
> produce a different result than a single operation. On the 68010
> (sorry, I don't have a manual for the higher MC chips handy) the RTE
> restores the internal state of the CPU so that an instruction can be
> continued.
This is one of the reasons DTS ask developers not to use TAS.
Cheers,
Kent/DTS
+++++++++++++++++++++++++++
From: orpheus@reed.edu (P. Hawthorne)
Date: 3 Jul 92 09:45:01 GMT
Organization: Reed College, Portland, OR
Kent Sandvik (ksand@apple.com) implores:
. DTS asks developers not to use TAS.
What about CALLM/RTM on apps meant for 68020/+ machines?
Theus (orpheus@reed.edu)
+++++++++++++++++++++++++++
From: stu5s11@bcrka280.bnr.ca
Date: 7 Jul 92 19:03:47 GMT
Organization: Bell-Northern Research, Ottawa, Canada
> Kent Sandvik (ksand@apple.com) implores:
>. DTS asks developers not to use TAS.>
>
> What about CALLM/RTM on apps meant for 68020/+ machines?
>
> Theus (orpheus@reed.edu)
Motorola has eliminated the CALLM/RTM instructions on the
68030 and 68040 and future processors. The only processor
they were ever used on was the 68020.
The reason they were eliminated was that no one used them.
(At least no one who was buying more than $50 million
worth of processors) The secondary reason for eliminating
them was that it simplified the '030 and let them
use the transistors for more useful purposes.
Note that the same thing happened with the Breakpoint
instruction and some of the more obscure MMU instructions.
John Andrusiak
---------------------------
From: digi@dgp.toronto.edu (Chris DiGiano)
Subject: Can't use Sys7 icon suite commands!
Date: 3 Jul 92 22:19:36 GMT
Okay, I've read and reread the updated TN #306, but I still can't even
load an icon family, let alone draw one. Here's what I'm doing in C:
pascal OSErr GetIconSuite(Handle *theIconSuite,short theResID,short selector)=
{0x303C, 0x0501, 0xABC9};
enum IconSelectorValue {
svAllAvailableData = 0xffffffff
};
void geticon()
{
Handle h;
err = GetIconSuite(&h, 101, svAllAvailableData);
}
The GetIconSuite statement causes a bus error. Any ideas?
- ---
Chris DiGiano (416) 978-6619, fax: 0458 digi@dgp.utoronto.{ca,bitnet}
Dynamic Graphics Project, Dept. of Computer Sci. digi@dgp.toronto.edu
University of Toronto, Canada M5S 1A4 ...!uunet!dgp.toronto.edu!digi
+++++++++++++++++++++++++++
From: jackl@austin.apple.com (Jack Littleton)
Date: 6 Jul 92 18:14:51 GMT
Organization: Apple Computer, Inc.
In article <1992Jul3.181936.19713@jarvis.csri.toronto.edu>, digi@dgp.toronto.edu (Chris DiGiano) writes:
> pascal OSErr GetIconSuite(Handle *theIconSuite,short theResID,short selector)=
> {0x303C, 0x0501, 0xABC9};
>
> enum IconSelectorValue {
> svAllAvailableData = 0xffffffff
> };
>
> void geticon()
> {
> Handle h;
> err = GetIconSuite(&h, 101, svAllAvailableData);
> }
>
>
> The GetIconSuite statement causes a bus error. Any ideas?
>From what I see, you haven't allocated memory for the handle in geticon(). You need
to explicitly allocate memory for the handle by calling the toolbox routine
NewHandle.
- --
Jack Littleton
Developer Tools Engineering Group
Apple Computer, Inc.
Opinions expressed above are not necessarily those of Apple Computer, Inc.
+++++++++++++++++++++++++++
From: absurd@applelink.apple.com (Tim Dierks, software saboteur)
Date: 7 Jul 92 17:40:30 GMT
Organization: MacDTS Misfits
In article <1992Jul6.181451.15385@pcnntp.apple.com>, jackl@austin.apple.com (Jack Littleton) writes:
>
> In article <1992Jul3.181936.19713@jarvis.csri.toronto.edu>, digi@dgp.toronto.edu (Chris DiGiano) writes:
> > pascal OSErr GetIconSuite(Handle *theIconSuite,short theResID,short selector)=
> > {0x303C, 0x0501, 0xABC9};
> >
> > enum IconSelectorValue {
> > svAllAvailableData = 0xffffffff
> > };
> >
> > void geticon()
> > {
> > Handle h;
> > err = GetIconSuite(&h, 101, svAllAvailableData);
> > }
> >
> >
> > The GetIconSuite statement causes a bus error. Any ideas?
>
> >From what I see, you haven't allocated memory for the handle in geticon(). You need
> to explicitly allocate memory for the handle by calling the toolbox routine
> NewHandle.
Actually, your problem is that the prototypes are wrong; the GetIconSuite call
should be:
pascal OSErr GetIconSuite(Handle *theIconSuite,short theResID,long selector)=
{0x303C, 0x0501, 0xABC9};
Note that the selector is now a long; this matches its format as given in
the selector constants (you can see that they're all 32 bits long). You
should _not_ allocate memory for the handle ahead of time; this is why
you pass the handle by reference; so the system can allocate the handle
and pass it back.
Tim Dierks
MacDTS, but I speak for the trees
---------------------------
From: ccmlh@buitc.bu.edu (Mark Hayes)
Subject: How Do You Sleep?
Date: 30 Jun 92 16:54:12 GMT
Organization: Boston University, Boston, MA, USA
How do I pause a program for a short period of time? THINK C's UNIX
library provides a "sleep()" function, but it only pauses for
multiples of one second, and I'd like something finer than that.
Is there a toolbox function for this? I'd rather avoid something
as embarrassing as "for (x=0; x < 99999; x++)".
+++++++++++++++++++++++++++
From: Steve Kohlmeyer
Date: 1 Jul 92 00:52:53 GMT
Organization: University of Minnesota
In article <89943@bu.edu> ccmlh@buitc.bu.edu (Mark Hayes) writes:
>How do I pause a program for a short period of time? THINK C's UNIX
>library provides a "sleep()" function, but it only pauses for
>multiples of one second, and I'd like something finer than that.
>Is there a toolbox function for this? I'd rather avoid something
>as embarrassing as "for (x=0; x < 99999; x++)".
>
You can use the TickCount() function to wait in multiples of 1 tick.
(60 ticks = 1 second)
Wait(int ticks) {
long start;
start = TickCount();
while (TickCount() < start+ticks) ;
}
Steve Kohlmeyer
+++++++++++++++++++++++++++
From: d88-jwa@dront.nada.kth.se (Jon W{tte)
Organization: Royal Institute of Technology, Stockholm, Sweden
Date: Wed, 1 Jul 1992 10:49:09 GMT
.cis.umn.edu> Steve Kohlmeyer writes:
You can use the TickCount() function to wait in multiples of 1 tick.
(60 ticks = 1 second)
Wait(int ticks) {
long start;
start = TickCount();
while (TickCount() < start+ticks) ;
}
AUGH ! DON'T ! THIS IS WORSE THAN CALLING _Delay !
You should AT MINIMUM include a call to SystemTask in
the loop. Better yet, use WaitNextEvent in the loop, like:
void
Wait ( long ticks )
{
long target = TickCount ( ) + ticks ;
EventRecord er ;
while ( ( ticks = TickCount ( ) ) < target ) {
WaitNextEvent ( 0 , & er , target - ticks , NULL ) ;
}
}
Maybe you should check for suspend/resume/activate/update/apple
events in the loop, too, by calling your global event handler
routine...
- --
Jon W{tte, Svartmangatan 18, S-111 29 Stockholm, Sweden
"Difficult, obscure, incoherent and nonstandard does not imply more power."
- Andrew Kass in comp.sys.mac.hardware
+++++++++++++++++++++++++++
From: obi@gumby.ocs.com (Kuryan "Obi" Thomas)
Date: 1 Jul 92 16:40:47 GMT
Organization: Online Computer Systems, Inc.
In article <89943@bu.edu> ccmlh@buitc.bu.edu (Mark Hayes) writes:
>How do I pause a program for a short period of time? THINK C's UNIX
>library provides a "sleep()" function, but it only pauses for
>multiples of one second, and I'd like something finer than that.
>Is there a toolbox function for this? I'd rather avoid something
>as embarrassing as "for (x=0; x < 99999; x++)".
>
See Delay(), Inside Macintosh Vol II, p 384.
procedure Delay(numTicks: longint; var finalTicks: longint);
or
void Delay(long, long*);
The first arg says how long you want to sleep (in ticks; 1 tick = 1/60 sec).
The second arg gives the global tick count at the time of "wakeup."
Hope this helps.
+++++++++++++++++++++++++++
From: obi@gumby.ocs.com (Kuryan "Obi" Thomas)
Date: 2 Jul 92 20:00:34 GMT
Organization: Online Computer Systems, Inc.
In article <D88-JWA.92Jul1114909@dront.nada.kth.se>, Jon W{tte writes:
> .cis.umn.edu> Steve Kohlmeyer writes:
>
[ A code fragment; deleted. ]
>
> AUGH ! DON'T ! THIS IS WORSE THAN CALLING _Delay !
>
>
> You should AT MINIMUM include a call to SystemTask in
> the loop. Better yet, use WaitNextEvent in the loop, like:
>
[ A code fragment; deleted. ]
>
> Maybe you should check for suspend/resume/activate/update/apple
> events in the loop, too, by calling your global event handler
> routine...
I agree that this is closer to what the UNIX sleep() system call does: it
allows other processes a chance to run. However, this isn't necessarily what
is required. For example, consider the only use I've made of Delay(): if the
user presses Return or Enter in a window with a default button, I highlight
the button for an instant (as if it had been clicked with the mouse) and then
do what the button is supposed to do.
I implement "highlighting for an instant" by highlighting, calling Delay() for
5 or so ticks, and then unhighlighting. In this scenario, you would not want
to read the event loop -- you may get switched out, or worse, pick up a mouse
click on the button itself.
I would think that calling Delay() is fine in most situations except when you
are, as they say in UNIX, "sleeping on an event," i.e., napping until some
alarm goes off (printer is ready; disk i/o completed; whatever). In that case,
you would definitely want to allow yourself to be switched out and yield the
CPU to another process which can get some work done in the meantime.
+++++++++++++++++++++++++++
From: jmunkki@vipunen.hut.fi (Juri Munkki)
Organization: Helsinki University of Technology
Date: Fri, 3 Jul 1992 20:04:40 GMT
In article <Bqs28z.K2y@gumby.ocs.com> obi@gumby.ocs.com writes:
>In article <D88-JWA.92Jul1114909@dront.nada.kth.se>, Jon W{tte writes:
>> You should AT MINIMUM include a call to SystemTask in
>> the loop. Better yet, use WaitNextEvent in the loop, like:
>I implement "highlighting for an instant" by highlighting, calling Delay() for
>5 or so ticks, and then unhighlighting. In this scenario, you would not want
>to read the event loop -- you may get switched out, or worse, pick up a mouse
>click on the button itself.
No, but you should give time to background processes, so WaitNextEvent
might be a good idea. Just pass a 0 mask that tells the system that you
don't actually want any events. Another possibility is to use GetNextEvent
and SystemTask inside a loop.
The idea of multitasking is to enable the user to get the maximum amount
of efficiency from a processor. Sitting in a call to _Delay is not my idea
of making good use of the processor.
- --
Juri Munkki Windsurf: fast sailing
jmunkki@hut.fi Macintosh: fast software
+++++++++++++++++++++++++++
From: Eric.J.Baumgartner@dartmouth.edu (Eric J. Baumgartner)
Date: 6 Jul 92 18:35:20 GMT
Organization: Dartmouth College, Hanover, NH
In article <Bqs28z.K2y@gumby.ocs.com>
obi@gumby.ocs.com (Kuryan "Obi" Thomas) writes:
> For example, consider the only use I've made of Delay(): if the
> user presses Return or Enter in a window with a default button, I highlight
> the button for an instant (as if it had been clicked with the mouse) and
> then do what the button is supposed to do.
Another way to do this is to convert the event from a keystroke into a
mousedown on your button, and pass the event back to the system so that
it highlights the button. This is pretty simple to do for dialogs via
the filter; I would assume (ha ha) it would be fairly simple for
standard windows as well.
Eric Baumgartner * ebaum@dartmouth.edu
Interactive Media Lab * - When in danger or in doubt,
Dartmouth Medical School * run in circles, scream and
shout.
---------------------------
From: djpegg@utkvx4.utk.edu (PEGG, DAVID J)
Subject: Why can't I Quit?
Date: 6 Jul 92 18:21:00 GMT
Organization: University of Tennessee Computing Center
I'm writing my first program for the Mac that actually uses a Mac interface
instead of relying on stdio stuff. My menu bar consists of the apple, file,
and edit menus, plus three menus for manipulating data in the program (it's a
simple graphing porgram with four windows, each containg a separate graph).
My problem is that it won't quit. The file menu has Quit as option #8 with the
command-Q key equivalent. But choosing this (whether with the mouse or the
keys) gives me errors. I'm using Think C 5.0.2 with Think C Debugger 5.0.
Everything works fine, until I choose Quit. If I'm running the Debugger, I
usually get an "illegal instruction" error, although I sometimes get an "odd
address" error instead. If I'm not running the Debugger, one of three things
happens. Either it quits just fine (rare, and never twice in a row), the
screen freezes, permitting no mouse movement, or I get a system error: "bad
F-line instruction." (This is the most common one I see.) What does this mean?
I'm just using a regular event loop:
done = FALSE;
while (!done)
{
WaitNextEvent(...);
HandleEvent(event);
}
The variable done is a global that is set TRUE when Quit is chosen. I can't
figure it out; I'm at your mercy!
Thanks in advance,
Michael Lewis
+++++++++++++++++++++++++++
From: howard@netcom.com (Howard Berkey)
Date: 6 Jul 92 19:05:34 GMT
Organization: Netcom - Online Communication Services (408 241-9760 guest)
>
>The variable done is a global that is set TRUE when Quit is chosen. I can't
>figure it out; I'm at your mercy!
OK, first of all, what is after your event loop in main()? The way you have it
all it will do is exit the event loop but still execute commands after the
loop. A better way to quit is to use ExitToShell() in this case as your app
is guaranteed to be in the foreground when the user selects Quit or hits
command-Q in your application. Something like this in your file menu handler:
...
case quitCommand:
DoHouseCleaning(); /* everything after your event
loop as it is now... */
ExitToShell();
break;
...
On this note, could someone tell me if anything is wrong with using
ExitToShell() in the background? I've never done it, but I know that when
you use 'es' in Macsbug you want to check the app name at $910 (?) to make
sure you're escaping from the right app... Since ExitToShell() basically
just calls _Launch w/ finder as the app, I don't see any problem using it
in the background.
- -Howard
- --
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Howard Berkey howard@netcom.com
If while you are in school, there is a shortage of qualified personnel
in a particular field, then by the time you graduate with the necessary
qualifications, that field's employment market is glutted.
-- Marguerite Emmons
+++++++++++++++++++++++++++
From: d88-jwa@dront.nada.kth.se (Jon W{tte)
Organization: Royal Institute of Technology, Stockholm, Sweden
Date: Mon, 6 Jul 1992 22:48:19 GMT
> howard@netcom.com (Howard Berkey) writes:
On this note, could someone tell me if anything is wrong with using
ExitToShell() in the background? I've never done it, but I know that when
I don't think that's any problem. I certainly do it.
you use 'es' in Macsbug you want to check the app name at $910 (?) to make
sure you're escaping from the right app... Since ExitToShell() basically
Yes, but that means you exittoshell whatever application is currently
SWITCHED IN (!= foreground) - when your application executes code
that isn't an interrupt handler, it is by definition switched in.
- --
Jon W{tte, Svartmangatan 18, S-111 29 Stockholm, Sweden
"Difficult, obscure, incoherent and nonstandard does not imply more power."
- Andrew Kass in comp.sys.mac.hardware
---------------------------
From: ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Subject: CALLM/RTM (was Re: TAS instruction use)
Date: 4 Jul 92 04:00:41 GMT
Organization: University of Waikato, Hamilton, New Zealand
In article <1992Jul3.094501.12376@reed.edu>, orpheus@reed.edu (P. Hawthorne) writes:
> What about CALLM/RTM on apps meant for 68020/+ machines?
Those instructions are ONLY available on the 68020 -- not on the 68030/040.
I think nobody could figure out what to use them for. :-)
Lawrence D'Oliveiro fone: +64-7-856-2889
Computer Services Dept 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
+++++++++++++++++++++++++++
From: jimc@tau-ceti.isc-br.com (Jim Cathey)
Date: 7 Jul 92 20:04:31 GMT
Organization: ISC - Bunker Ramo, Spokane, WA
In article <1992Jul4.160041.9151@waikato.ac.nz> ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
>> What about CALLM/RTM on apps meant for 68020/+ machines?
>
>Those instructions are ONLY available on the 68020 -- not on the 68030/040.
>I think nobody could figure out what to use them for. :-)
If I remember correctly, to actually do anything they required that the
system designer also supply a custom MMU coprocessor. Nobody did this,
so they took it back out. Maybe the feature was Ada-inspired or something.
- --
+----------------+
! II CCCCCC ! Jim Cathey
! II SSSSCC ! ISC-Bunker Ramo
! II CC ! TAF-C8; Spokane, WA 99220
! IISSSS CC ! UUCP: uunet!isc-br!jimc (jimc@isc-br.isc-br.com)
! II CCCCCC ! (509) 927-5757
+----------------+
"PC's --- the junk bonds of the computer industry"
---------------------------
From: orpheus@reed.edu (P. Hawthorne)
Subject: Divisible Window Updates: Thought Crime?
Date: 5 Jul 92 23:41:39 GMT
Organization: Reed College, Portland OR
The toolbox routines for window updates assume that the entire update can
be performed at once, before going on to the next event. This is fine for
simple graphics, but some updates can take a long time. Users may decide
that they want to proceed without waiting for the update to finish.
In a perfect world, updates would be seamless. That is to say that users
could make menu selections or switch to another application while a window
was updating, as if updating windows was something the application did in
its spare time just for the exercise. PhotoShop and StrataVision, two
MacApps as elegant as they are glacial, accomplish this ideal.
The toolbox routines for updates have to be avoided for this to work. What
I want to know is: Assuming that the regions in question are dealt with
properly, is there any overwhelming reason for BeginUpdate and EndUpdate to
be called in response to window update events?
Theus (orpheus@reed.edu)
+++++++++++++++++++++++++++
From: joseph@joebloe.maple-shade.nj.us (Joseph Nathan Hall)
Date: 5 Jul 92 03:01:29 GMT
Organization: 5 Sigma Software
In article <1992Jul5.234139.4921@reed.edu> (comp.sys.mac.programmer), orpheus@reed.edu (P. Hawthorne) writes:
) The toolbox routines for window updates assume that the entire update can
) be performed at once, before going on to the next event....
...What
) I want to know is: Assuming that the regions in question are dealt with
) properly, is there any overwhelming reason for BeginUpdate and EndUpdate to
) be called in response to window update events?
Aside from the necessity of stopping the incessant flow of update
events ... no.
You WILL have to process update events, which means you will have
to call BeginUpdate/EndUpdate. Even if you don't do anything between.
I have an app that updates a window as an idle chore ... you can too.
It still processes ordinary updates (from uncovering, etc.), but I don't
use the InvalRect-type mechanism to show ongoing changes.
Although I hate to praise Microsoft for anything, particularly Word,
particularly for the Mac, I have to admit that I am quite fond of the way
that Word redraws during scrolling ... leaving as little blank screen
as possible. (I also like the way that it lets me open 3.5 MB documents
without so much as a burp.)
uunet!joebloe!joseph (609) 273-8200 day joseph%joebloe@uunet.uu.net
v v sssss | Certified Guru: all-grain brewing,| 2102 Ryan's Run East
v v s s | C, synthesizer comp & arranging, | Rt 38 & 41
v sss | photography. Also not a bad cook. | Maple Shade NJ 08052
- -----My employer isn't paying for this, and my opinions are my own-----
+++++++++++++++++++++++++++
From: tmaehl@vax1.umkc.edu
Date: 6 Jul 92 08:56:08 GMT
Organization: University of Missouri - Kansas City
In article <1992Jul5.234139.4921@reed.edu>,
orpheus@reed.edu (P. Hawthorne) writes:
> The toolbox routines for window updates assume that the entire update can
> be performed at once, before going on to the next event. This is fine for
> simple graphics, but some updates can take a long time. Users may decide
> that they want to proceed without waiting for the update to finish.
Updates should be thought of as "refresh" requests. If your app does
all of its drawing offscreen in a gworld, when you get an update event
you just copy the original back to the screen. This takes virtually no
time and is easily accomplished before going onto the next event.
*Drawing* should be nicely intertwined with reasonable calls to GNE.
But an update event doesn't require you to *draw*, just *refresh*.
Jonathan/tmaehl@vax1.umkc.edu
+++++++++++++++++++++++++++
From: k044477@hobbes.kzoo.edu (Jamie R. McCarthy)
Date: 6 Jul 92 11:46:15 GMT
Organization: Kalamazoo College
tmaehl@vax1.umkc.edu writes:
>orpheus@reed.edu (P. Hawthorne) writes:
>> some updates can take a long time. Users may decide
>> that they want to proceed without waiting for the update to finish.
>
>If your app does
>all of its drawing offscreen in a gworld, when you get an update event
>you just copy the original back to the screen. This takes virtually no
>time and is easily accomplished before going onto the next event.
Even that can take quite some time. For example, your offscreen
pixel map is 24 bits deep and you want to copy it onto an 8-bit screen,
dithered, with different source and destination rectangles. Or your
offscreen image is too big to (comfortably) fit in memory, and you have
it partly stored on disk. Or VM is on, which amounts to the same thing.
Etc., etc.
- --
Jamie McCarthy Internet: k044477@kzoo.edu AppleLink: j.mccarthy
Nobody reads signatures anyway.
+++++++++++++++++++++++++++
From: d88-jwa@dront.nada.kth.se (Jon W{tte)
Date: 6 Jul 92 13:06:39 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
.edu> orpheus@reed.edu (P. Hawthorne) writes:
I want to know is: Assuming that the regions in question are dealt with
properly, is there any overwhelming reason for BeginUpdate and EndUpdate to
be called in response to window update events?
Yes.
People patch EndUpdate for some hacks... not to mention Apple
probably has some strange fixes in there, too.
Instead, do BeginUpdate - remmeber clip region - EndUpdate
and then start drawing in the remembered region while calling
WaitNextEvent.
Or just store all drawing in an offscreen GWorld, and CopyBits
to screen when you get a refresh event. Takes memory for a
24 bit 21" screen, though.
- --
Jon W{tte, Svartmangatan 18, S-111 29 Stockholm, Sweden
"Difficult, obscure, incoherent and nonstandard does not imply more power."
- Andrew Kass in comp.sys.mac.hardware
+++++++++++++++++++++++++++
From: jimc@tau-ceti.isc-br.com (Jim Cathey)
Date: 7 Jul 92 20:34:24 GMT
Organization: ISC - Bunker Ramo, Spokane, WA
In article <1992Jul5.234139.4921@reed.edu> orpheus@reed.edu (P. Hawthorne) writes:
>The toolbox routines for window updates assume that the entire update can
>be performed at once, before going on to the next event. This is fine for
>simple graphics, but some updates can take a long time. Users may decide
>that they want to proceed without waiting for the update to finish.
I had a problem with this in a program I did that was an emulation of a
foreign windowing system (call it X, but it wasn't) using as much of the
native Mac toolbox as possible. The problem is that multiple updates
could be going on in parallel, since separate Un*x applications on
remote systems were driving each of the windows, through a translation
program. Scheduling variations and variable network delays conspire to
ensure that there is no way in hell my translation program could
complete (or even start) an update when it got an update event from the
Toolbox. So, my solution was to immediately grab the update region of
the dirty window (to save it, and to send its bounding rectangle away to
the remote client), then do a BeginUpdate/EndUpdate to clear out the
dirty status. When the update starts to come in I then do an InvalRgn
to re-dirtify the dirty area, then a BeginUpdate, then I grab a copy of
the SaveVisRgn low-memory global (per the note in IM-1). When the
remote update is finally done (which may take awhile) I restore the
SaveVisRgn from my copy (since who knows how many other updates to
other windows may have been done by then, and <Begin|End>Update don't
normally nest), and then do an EndUpdate, followed by a final CalcVis
since the saved SaveVisRgn may have been completely invalid by the
time all this was done. Messy (and probably non-optimal), but it works.
I think (in retrospect) that the business with SaveVisRgn was completely
unnecessary, since the CalcVis call cleans up all the mess. However,
it _was_ a late fix to the code.
>The toolbox routines for updates have to be avoided for this to work. What
>I want to know is: Assuming that the regions in question are dealt with
>properly, is there any overwhelming reason for BeginUpdate and EndUpdate to
>be called in response to window update events?
You don't have to avoid them (in fact you really can't avoid them and
stay 'clean'), but you do have to slaughter a chicken or two in their
name.
- --
+----------------+
! II CCCCCC ! Jim Cathey
! II SSSSCC ! ISC-Bunker Ramo
! II CC ! TAF-C8; Spokane, WA 99220
! IISSSS CC ! UUCP: uunet!isc-br!jimc (jimc@isc-br.isc-br.com)
! II CCCCCC ! (509) 927-5757
+----------------+
"PC's --- the junk bonds of the computer industry"
+++++++++++++++++++++++++++
From: ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 8 Jul 92 18:18:01 +1200
Organization: University of Waikato, Hamilton, New Zealand
In article <2370@tau-ceti.isc-br.com>, jimc@tau-ceti.isc-br.com (Jim Cathey) writes:
> In article <1992Jul5.234139.4921@reed.edu> orpheus@reed.edu (P. Hawthorne) writes:
>>The toolbox routines for window updates assume that the entire update can
>>be performed at once, before going on to the next event. This is fine for
>>simple graphics, but some updates can take a long time. Users may decide
>>that they want to proceed without waiting for the update to finish.
>
> I had a problem with this in a program I did that was an emulation of a
> foreign windowing system ... [with] multiple updates
> could be going on in parallel, ...
> [and] no way in hell my translation program could
> complete (or even start) an update when it got an update event from the
> Toolbox. So, my solution was to immediately grab the update region of
> the dirty window (to save it, and to send its bounding rectangle away to
> the remote client), then do a BeginUpdate/EndUpdate to clear out the
> dirty status.
Yup, this sounds like mostly the right way to me, so far.
> When the update starts to come in I then do an InvalRgn
> to re-dirtify the dirty area, then a BeginUpdate, then I grab a copy of
> the SaveVisRgn low-memory global (per the note in IM-1). When the
> remote update is finally done (which may take awhile) I restore the
> SaveVisRgn from my copy (since who knows how many other updates to
> other windows may have been done by then, and <Begin|End>Update don't
> normally nest), and then do an EndUpdate, followed by a final CalcVis
> since the saved SaveVisRgn may have been completely invalid by the
> time all this was done.
...
> However, it _was_ a late fix to the code.
As an alternative technique, why not leave the visRgn alone, and just set the
clip region to the area needing updating? I guess the answer is you're using
the grafport clip region to directly implement an application-settable clip
region. So why not maintain a separate "application clip region", so the clip
region of the grafport becomes the intersection of this and the region
currently being updated?
Just a way of avoiding fiddling with visRgns and faking out the Toolbox,
that's all.
To allow for multiple concurrent window updates while still being responsive
to mouse and key events, how about this:
For each window, in addition to the standard Toolbox structures, you maintain
two additional regions: an application-level clip region (representing the
area that the application really wants to draw into) and a region needing
updating. Every time you get a Toolbox update event for such a window, you
simply do a UnionRgn of the updateRgn with your separate update region,
and then call ValidRgn or ValidRect (quicker than BeginUpdate/EndUpdate) to
clear the update event.
Then each time around your event loop, you select a window with a non-null
region needing updating. You extract a band from this region (say a rectangle
extending the full width of the window, but limited to some maximum height),
representing an area that you can update in the maximum interval that you're
prepared to tolerate between responses to mouse/key events. You set the clip
region to the intersection of this band and the application-level clip region,
and do your updating of that area (hopefully minimizing your attempts to draw
objects that fall entirely outside the clip region). And you subtract the band
from the region needing updating.
How does this sound? There is a potential complication if your on-screen
drawing involves CopyBits dithering (the error propagation may not match up
across the band boundaries), but it's not insurmountable.
Lawrence D'Oliveiro fone: +64-7-856-2889
Computer Services Dept 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
---------------------------
End of C.S.M.P. Digest
**********************