home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Information
/
CSMP Digest
/
volume 1
/
csmp-v1-214.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
|
43.2 KB
|
1,076 lines
|
[
TEXT/R*ch
]
C.S.M.P. Digest Mon, 16 Nov 92 Volume 1 : Issue 214
Today's Topics:
INIT writing 101 (long) [was: Re: little INIT code resource problem]
scanf equivalent calls that does not use global variables?
vSynchWait and PowerBook I/O
Option key madness
UnloadSeg and pointers to functions
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: absurd@applelink.apple.com (Tim Dierks, software saboteur)
Subject: INIT writing 101 (long) [was: Re: little INIT code resource problem]
Date: Thu, 15 Oct 1992 02:48:31 GMT
Organization: MacDTS Marauders
In article <zocca-141092150341@maria.amc.uva.nl>, zocca@amc.uva.nl (Vincent
Zocca) wrote:
>
>
> Hello!
>
> I've got a probably very little problem with vriting an INIT.
> What I want is to check for disk insert events and perform some action as a
> reaction to them.
> I wrote something that looks like this.
>
> {-----------------------}
>
> {headers and other stuff precede}
>
> procedure Main;
>
> var
> INITHndl: handle;
> OsError: OSErr;
> myEvent: EventRecord;
> GotEvent: Boolean;
>
> begin
>
> INITHndl := GetResource('INIT', 0);
> DetachResource(INITHndl);
>
> repeat
> GotEvent := WaitNextEvent(DiskMask, myEvent, 60, nil);
> if GotEvent then
> begin
> if (HiWord(myevent.message) <> noErr) then
> begin
> myEvent.where.h := 40;
> myEvent.where.v := 20;
> InitCursor;
> OsError := DIBadMount(myEvent.where, myevent.message);
>
> {At this point I want to perform some action}
>
> end;
> end;
> until False;
>
> end;
>
> {-----------------------}
>
>
> The code resource generated messes up the machine it's installed on. It
> does get disk events at startup though, I've tested that with a
> SysBeep(10).
>
> Ok,ok,... What is it? What am I forgetting. Give it to me. I can handle it.
Well, OK, if you can handle it....
You need to reconsider how INITs generally work on the Mac; this looks
a lot like an application, but nothing like an INIT. When an INIT is
called, it needs to install itself in some way so it can examine and
modify the goings on of the Mac, and then it needs to exit. This INIT
never exits; it just calls WaitNextEvent over and over again. At that
rate, the Finder will never get launched; the system will spend the
rest of time sitting in your little REPEAT ... UNTIL false; loop looking
for nothing but disk-inserted events.
Here's the big secret: you _cannot_ retain control; you've got to find
some way to get control later, when you want to do something. Then, the
only thing your INIT does at INIT time is install the mechanism to get
control later. Usually, this mechanism is a trap patch; if you patch
a trap, you will get control every time that trap is called; at that
time, you can do what you need to do. Careful selection of which trap
to patch will make it easy to write clever INITs.
For example, let's take your problem. You want to do something when
a "bad" disk is inserted, after the dialog comes up. Just for
argument, let's say you want to rename every new disk to "This is a
really new disk!" One way to do this would be to patch CloseWindow();
you could wait until the "bad mount" dialog got closed and then you
would have control at the right time; just after the bad disk dialog
got dismissed. This would be a _bad_ way to do this patch, for the
following reasons:
1) It's going to be a royal pain to be able to tell when the
bad disk dialog is closing, as opposed to any other window.
2) CloseWindow only gets passed the WindowPtr to the window to
close. It might be tough to figure out what disk is the one
you want to rename (or whatever).
3) There is no reason 3.
4) This is real dependant on the way this is all implemented by
Apple; if they change the way the bad-mount sequence works,
you'll be in trouble.
5) You want a trap that will be called at a time when you can
do what you need to do; for example, if you need to draw
on the screen, patch a trap that is allowed to move or
purge memory, because your patch will do so.
So the criteria for selecting a trap to patch are: 1) Ideally, it
should be called only at the time when you want to do what you want
to do, or it should be obvious whether you're interested in this call
from the arguments which get passed. 2) The trap should get passed
all the information you're going to need, or you should have a good
way to get everything you need. 3) The trap should be a natural
place to put this code; if you have to stretch to make it work, it's
more and more likely that it won't work properly on future system
software.
OK, so what's the best trap to select for your purposes? Let's list
the criteria again:
1) We want a trap that is only called when a bad disk is being
dealt with.
2) We want a trap which is passed a drive number or volume
reference number for the disk being mounted, so we can figure
out which disk to rename.
3) We want a trap which is essential to the process of mounting
a bad disk, so we can be sure it's less likely to change
very much.
4) Since you can rename a disk at any time, criterion 5), above,
isn't as important, but it would be best if we did it at
non-interrupt time, because otherwise we don't want to
make a synchronous file system call.
Given these criteria, I think the obvious choice is DIBadMount();
it's only called when a bad disk is mounted, it gets passed the
drive number in the low word of the event message, it's a crucial
part of the bad-disk process, and it's always called at a "safe"
time, since it can move or purge memory.
OK, so we'll now get control when DIBadMount gets called. We can't,
however, rename the disk yet, because it hasn't yet been mounted;
it's still an unformatted floppy. We do know, however, know that
it will be formatted and ready to rename when DIBadMount has
finished. Therefore, we will tail patch it; we'll call the real
DIBadMount near the start of our code and rename the disk when it
returns.
The only final stumbling block in our plan is that DIBadMount isn't
really a trap; it is only one routine that shares a single trap,
_Pack2. This means we need to patch _Pack2, but only do anything
when DIBadMount is called. The way that the _Pack2 call tells
which one of the Disk Initialization Package calls is being called
is from a selector which is pushed on the stack; specifically,
when an application calls DIBadMount, it first pushes the two
public parameters, the Point where, and the long eventMessage,
and then it pushes a 16-bit word onto the stack with the selector
for which call it is making; in the case of DIBadMount, it
pushes a 2. Thus, we only want to do anything if the call to
_Pack2 is passing a selector of 2; if it's anything else, we
just want to jump through to the original _Pack2 code and
forget about it; we're only interested in DIBadMount calls.
OK, so here's a description of the entire INIT: (n) indicates
footnote n.
INITEntry:
Detach our code. (1)
Get the original address of _Pack2 with GetTrapAddress.
Remember the original address of _Pack2. (2)
Set the address of _Pack2 to point to our routine Pack2Patch
using SetTrapAddress.
Return; we're done installing.
Pack2Patch:
Check the selector.
If the selector does not equal 2:
Get the original address of _Pack2.
Jump to it.
If the selector is equal to 2:
Remember the drive number which was passed.
Get the original address of _Pack2.
Call it.
If DIBadMount returned an error:
return the error
If DIBadMount returned noErr:
rename the volume, using the drive number you remembered.
return noErr
Footnotes:
(1) Our code needs to be locked and in the system heap; the easiest
way to do this is to mark the resPreload, resLocked, and resSysHeap
bits on the INIT resource. resPreload is important to make sure
the code gets placed in the best place in the heap.
(2) To remember values like this when you don't have a constant context,
the best thing to do is use PC-relative storage locations; you
need to use assembly for this, though (unless you're clever, and
sicker than I am). I just posted an example of PC-relative storage
in an article entitled "Re: Best way to get A5 into VBLTaskProc?".
(My second post on the subject). Or, if you're using Think, you
can use their A4 global stuff.
That's about all I have to say (and I think it's plenty). I haven't
given you remotely enough information to do this completely; most
lacking is a discussion of stack frame management and assembly versus
higher-level languages; you'll have to figure that out for yourself,
or ask for more.
Tim Dierks
MacDTS, but I speak too damn much.
---------------------------
From: cheng@ee.rochester.edu (Bruce Cheng)
Subject: scanf equivalent calls that does not use global variables?
Date: 4 Oct 92 18:23:47 GMT
Organization: Univ of Rochester, College of Engineering and Applied Science
Hi,
I ran into a problem when I tried to parse a binary/ascii mixed data file
for a piece of code that's to be put into a code resource. Since I cannot
include any global references in code resource, I cannot use sscanf() (cause`
sscanf() uses some global system state data for buffering???)
Well, is there any suggestion?
-Bruce
+-----------------------------------------+------------------------------------+
| Home: 716-475-9329(voice ) |Usnet: cheng@ee.rochester.edu |
| Work: 716-427-3475 |XNS: Bruce_Cheng.Henr801B@xerox.com |
| Address: 222 Norman Road, Rochester |Uucp: uunet!rochester!ur-val!cheng |
| NY14623 | |
+-----------------------------------------+------------------------------------+
- --
+-----------------------------------------+------------------------------------+
| Home: 716-271-0960(voice/data/fax) |Usnet: cheng@ee.rochester.edu |
| Work: 716-427-6227 |XNS: Bruce_Cheng.Henr801B@xerox.com |
| Address: 1559 Elmwood Avenue Apt 8 |Uucp: uunet!rochester!ur-val!cheng |
+++++++++++++++++++++++++++
From: rmf@chopin.cs.columbia.edu (Robert M. Fuhrer)
Organization: Computer Science Dept., Columbia Univ.
Date: Wed, 7 Oct 1992 21:45:15 GMT
Perhaps you can use the format-specific individual calls, such as atoi(),
atof(), and so on? They're also part of the ANSI C standard library.
- --
- -- Bob
+++++++++++++++++++++++++++
From: bwilliam@iat.holonet.net (Bill Williams)
Organization: HoloNet (BBS: 510-704-1058)
Date: Thu, 8 Oct 1992 09:25:54 GMT
>"Since I cannot
include any global references in code resource"....
I know what you probably mean, but I write code resources all the time
with lots of global references. I use Think C 5.0.3 with globals off of
register a4 using a custom header (so I can call other code segments of
mine back and forth at any point).
Bill Williams
+++++++++++++++++++++++++++
From: anders@verity.com (Anders Wallgren)
Date: 8 Oct 92 16:17:23 GMT
Organization: Verity, Mountain View, CA, USA
In article <RMF.92Oct7164515@chopin.cs.columbia.edu> Robert M.
Fuhrer, rmf@chopin.cs.columbia.edu writes:
>Perhaps you can use the format-specific individual calls, such as
atoi(),
>atof(), and so on? They're also part of the ANSI C standard
library.
I think these use globals as well - use the toolbox calls.
+++++++++++++++++++++++++++
From: rmf@chopin.cs.columbia.edu (Robert M. Fuhrer)
Date: 13 Oct 92 01:52:53 GMT
Organization: Computer Science Dept., Columbia Univ.
I just spent a minute touring through the Think C ANSI library source. [I was
thinking perhaps sscanf() might call atof(), which would be a "primitive".]
Well, atof() calls strtod(), which in turn calls __vsscanf(). This one calls
the root-level routine __vfscanf(). Unfortunately, that routine, the heart of
scanf(), uses globals to save a bit-vector of any scan-set specified, as well
as a default conversion flag struct. Oh well...
- --
- -- Bob
+++++++++++++++++++++++++++
From: potts@itl.itd.umich.edu (Paul Potts)
Date: 13 Oct 92 02:10:26 GMT
Organization: Instructional Technology Laboratory, University of Michigan
In article <RMF.92Oct12205253@chopin.cs.columbia.edu> rmf@chopin.cs.columbia.edu (Robert M. Fuhrer) writes:
>I just spent a minute touring through the Think C ANSI library source. [I was
>thinking perhaps sscanf() might call atof(), which would be a "primitive".]
>
>Well, atof() calls strtod(), which in turn calls __vsscanf(). This one calls
>the root-level routine __vfscanf(). Unfortunately, that routine, the heart of
>scanf(), uses globals to save a bit-vector of any scan-set specified, as well
>as a default conversion flag struct. Oh well...
>--
>
>-- Bob
What is it you are trying to do? You can use sscanf() in a code resource
such as an XCMD or whatever. Just include the ANSI-A4 library in your project.
You will have to do the usual A4 stuff. You don't need to access the global
A5 world to use sscanf(). It is a great utility to parse strings sent to
an XCMD for example.
Sorry if this is irrelevant... I seem to have missed the start of this thread.
- --
"Everything I say is a lie." <--- potts@oit.itd.umich.edu ---> that's me!
"C++ will make your programming simpler, more efficient, and more fun!"
+++++++++++++++++++++++++++
From: bpb9204@tamsun.tamu.edu (Brent)
Organization: Texas A&M Univ., Inc.
Date: Tue, 13 Oct 1992 17:18:37 GMT
cheng@ee.rochester.edu (Bruce Cheng) writes:
|I ran into a problem when I tried to parse a binary/ascii mixed data file
|for a piece of code that's to be put into a code resource. Since I cannot
|include any global references in code resource, I cannot use sscanf() (cause`
|sscanf() uses some global system state data for buffering???)
I was needing some sscanf() utility for a program I was writing and I
didn't feel like including the entire ANSI stuff into my project (I know
not all would be linked into the app, but a minimal print would have
doubled the size of the program I was working on).
So... I wrote my own implementation of sscanf(). My version works, in
every way but one, just like the original ANSI sscanf(). The bonus in
using this new implementation is that my sscanf() does not rely on anything
else (no __vssssssffssscan() calls) so the code only adds about 3K to your
program, instead of about 10-20K for Think C's ANSI stuff. Also, no
globals are used, so it'd be safe for SACs.
My sscanf() routine works several times faster than Think C's original
version, with the exception of floating point and hex numbers. Hex numbers
are only slightly faster and the floating point method I used is, ahem,
slower. On the other hand, speed improvements of 3-4 times are realized
for integer (short, normal, or long) types and string types.
The only difference in the data that my sscanf() function can translate
and the ANSI sscanf() is that my sscanf() does not implement generic
character sets. Does anybody even use these? I never have.
- -
So here is my current status: sscanf() is about as done as it's going
to get, but I was waiting to release it into the public domain until I
implemented a sprintf() counterpart. Is there demand for a sscanf()
function, without the sprintf()? If there is demand, meaning, if you want a
copy, email me and I'll send out a version to you.
The code was written to be freely distributable, usable by anyone for
commercial uses or not.
- -Brent
- --
- ------------------------------------------------------------------------------
Brent P. Burton, N5VMG Department of Computer Science
bpb9204@tamsun.tamu.edu Texas A&M University
What are typical family values? Good buys at WalMart.
---------------------------
From: jpurlia@qualcomm.com (John Purlia)
Subject: vSynchWait and PowerBook I/O
Date: 13 Oct 92 00:16:40 GMT
Organization: Qualcomm, Inc.
I've writted an app that communicates to an external device via the modem
port. My app runs fine on a Quadra 700 and a IIci, but hangs forever and
ever and ever when run on a PowerBook 170. A protocol analyzer reveals
that nothing is ever sent from the serial port when I call FSWrite. When I
trace through the code using MacsBug I find that the code is at the
following:
_vSynchWait
+0000 4080BB8C MOVE.W $0010(A0),D0
+0004 4080BB90 *BGT.S _vSynchWait
The value being tested is always 0001, which leads me to believe that I'm
waiting for the asynchronous I/O to complete. My question... Why does
this only happen on a PowerBook and what are some of the possibilities for
things I'm doing incorrectly?
Thanks!
...........................................................................
John Purlia : My brain; not my company's brain. My brain says...
jpurlia@qualcomm.com : "The Toolbox giveth, and the Tech Notes taketh away"
...........................................................................
+++++++++++++++++++++++++++
From: REEKES@applelink.apple.com (Jim Reekes)
Date: 13 Oct 92 19:50:02 GMT
Organization: Apple Computer, Inc.
In article <jpurlia-121092170808@129.46.5.45>, jpurlia@qualcomm.com (John
Purlia) wrote:
>
> I've writted an app that communicates to an external device via the modem
> port. My app runs fine on a Quadra 700 and a IIci, but hangs forever and
> ever and ever when run on a PowerBook 170. A protocol analyzer reveals
> that nothing is ever sent from the serial port when I call FSWrite. When I
> trace through the code using MacsBug I find that the code is at the
> following:
>
> _vSynchWait
> +0000 4080BB8C MOVE.W $0010(A0),D0
> +0004 4080BB90 *BGT.S _vSynchWait
>
> The value being tested is always 0001, which leads me to believe that I'm
> waiting for the asynchronous I/O to complete. My question... Why does
> this only happen on a PowerBook and what are some of the possibilities for
> things I'm doing incorrectly?
One suggestion. Don't use FSWrite or FSRead on the serial ports.
FS stands for File System. They are not designed for any driver calls.
They might work, but they're not the best approach.
- -----------------------------------------------------------------------
Jim Reekes, Polterzeitgeist | Macintosh Toolbox Engineering
| Sound Manager Expert
Apple Computer, Inc. | RAll opinions expressed are mine, and do
20525 Mariani Ave. MS: 81-KS | not necessarily represent those of my
Cupertino, CA 95014 | employer, Apple Computer Inc.S
+++++++++++++++++++++++++++
From: jpurlia@qualcomm.com (John Purlia)
Organization: Qualcomm, Inc.
Date: Tue, 13 Oct 1992 23:51:42 GMT
In article <REEKES-131092125119@90.10.20.67>, REEKES@applelink.apple.com
(Jim Reekes) wrote:
>
> In article <jpurlia-121092170808@129.46.5.45>, jpurlia@qualcomm.com (John
> Purlia) wrote:
> >
> > I've writted an app that communicates to an external device via the modem
> > port. My app runs fine on a Quadra 700 and a IIci, but hangs forever and
> > ever and ever when run on a PowerBook 170. A protocol analyzer reveals
> > that nothing is ever sent from the serial port when I call FSWrite. When I
> > trace through the code using MacsBug I find that the code is at the
> > following:
> >
> > _vSynchWait
> > +0000 4080BB8C MOVE.W $0010(A0),D0
> > +0004 4080BB90 *BGT.S _vSynchWait
> >
> > The value being tested is always 0001, which leads me to believe that I'm
> > waiting for the asynchronous I/O to complete. My question... Why does
> > this only happen on a PowerBook and what are some of the possibilities for
> > things I'm doing incorrectly?
>
> One suggestion. Don't use FSWrite or FSRead on the serial ports.
> FS stands for File System. They are not designed for any driver calls.
> They might work, but they're not the best approach.
>
Filling a parameter block and checking for ioResult not equal to 1 was the
first thing I tried. Same results, the I/O never completed...
But here's the solution!! :-)
I took a look at the supposed status of my I/O prior to writing any data
and discovered the following via a call to SerStatus:
Quadra 700: 0000 0000 0000
PowerBook 170: 0000 0000 FF00
That byte of FF for the PowerBook indicates that the CTS flow control hold
flag is set which meant that I couldn't transmit until it cleared. Guess
what? It NEVER clears! With a call to SerHShake I was able to tell the
serial port to ignore CTS handshaking and evrything works fine as fine can
be! (But then, I'm only operating at 1200 baud so your proverbial mileage
may very).
What does this mean? Steve Roberts and bis BEHEMOUTH bicycle will soon be
picking up his Internet mail via satellite!!! Check it out at Interop
everyone! :-)
...........................................................................
John Purlia : My brain; not my company's brain. My brain says...
jpurlia@qualcomm.com : "The Toolbox giveth, and the Tech Notes taketh away"
...........................................................................
+++++++++++++++++++++++++++
From: Bruce.Hoult@bbs.actrix.gen.nz
Date: 14 Oct 92 05:19:36 GMT
Organization: Actrix Information Exchange
In article <jpurlia-121092170808@129.46.5.45> jpurlia@qualcomm.com (John Purlia) writes:
> I've writted an app that communicates to an external device via the modem
> port. My app runs fine on a Quadra 700 and a IIci, but hangs forever and
> ever and ever when run on a PowerBook 170. A protocol analyzer reveals
> that nothing is ever sent from the serial port when I call FSWrite.
Every time (yes, it's happend more than once -- some people never
learn :-( ) that one of my serial port programs hangs on a Portable or
PowerBook it's because I've forgotten to call SerHShake to turn off
hardware handshaking.
It seems that on most Macs if the HskIn line is unconnected it floats
to the voltage that tells the Mac "carry on" but on the portables it
floats the other way when unconnected... Hardware handshaking is on
by default.
- -- Bruce
- --
Bruce.Hoult@bbs.actrix.gen.nz Twisted pair: +64 4 477 2116
BIX: brucehoult Last Resort: PO Box 4145 Wellington, NZ
"Cray's producing a 500 MIPS personal computer with 256MB RAM and 8 GB
hard disk that fits in your pocket!" "Great! Is it PC compatible?"
+++++++++++++++++++++++++++
From: John_Miller@mindlink.bc.ca (John Miller)
Date: 14 Oct 92 15:35:30 GMT
Organization: MIND LINK! - British Columbia, Canada
In article <REEKES-131092125119@90.10.20.67>, REEKES@applelink.apple.com
(Jim Reekes) wrote:
> One suggestion. Don't use FSWrite or FSRead on the serial ports.
> FS stands for File System. They are not designed for any driver calls.
> They might work, but they're not the best approach.
:) Well, maybe FS stands for "Fine Stuff", or "Fairly Straightforward"
or "Frank Schultz", but in addition to their reference in the
File Manager chapter, FSRead and FSWrite are also listed in the
Device Manager chapter. (Inside Mac II pages 178-179) . They
seem fine for simple use.
Of course, seeing as Inside Mac doesn't document a way to
determine if there's room in the serial port output buffer
before calling FSWrite, you might want to use the low
level calls to avoid hanging forever.
(I vaguely recall that the old 2 binder version of Inside Mac
didn't mention at all how to read and write to devices: you had
to have had at least enough of a whiff of UNIX to decide that,
if no Device Manager read/write calls were documented, let's
try the file calls.)
______________________________________________________________________
John Miller (604) 433-1795
Symplex Systems internet: john_miller@mindlink.bc.ca
Macintosh Consulting and Software Development
______________________________________________________________________
---------------------------
From: wfp@jupiter.claremont.edu (Frank Price)
Subject: Option key madness
Date: 12 Oct 92 04:07:50 GMT
Organization: Harvey Mudd College, Claremont, CA 91711
I am trying to read option keys from the Mac keyboard, and of course have
noticed that various keys will not even send an event when initially typed
such as Option-E and Option-U, and Option-'. How do I override this system so
that Option can be used normally for those special characters?
Thanks.
- -- Frank
__________________________________________________________________________
Frank Price | wprice@pomona.claremont.edu
| "Nothing crashes like a Macintosh."
NeXTMail appreciated | - Guy Kawasaki
+++++++++++++++++++++++++++
From: leonardr@netcom.com (Leonard Rosenthol)
Date: 12 Oct 92 16:17:45 GMT
Organization: Netcom - Online Communication Services (408 241-9760 guest)
In article <1992Oct12.040750.20383@muddcs.claremont.edu> wprice@pomona.claremont.edu writes:
>I am trying to read option keys from the Mac keyboard, and of course have
>noticed that various keys will not even send an event when initially typed
>such as Option-E and Option-U, and Option-'. How do I override this system so
>that Option can be used normally for those special characters?
>
There are two ways to do this - the right way and the wrong way!
The wrong way is what ZTerm & NCSA Telnet (to name two) do it. That is
to require the user to use THEIR KCHR resource, which requires the user to
do a bit of ResEditting of the System file, since KCHR's must live in the System
under System 7.
The right way to do it (which MicroPhone II & Smartcom do) is to
first patch _KeyTrans to map the option modiifier to something else (in the
cases above, the control modifieir). However, since the process manager
swaps patches on even minor context switches, you could STILL get the wrong
characters. So you have to do some on-the-fly munging of the KCHR (after
copying the orignal!!) - BUT remember to restore the original KCHR on
suspend/resumes!!
- --
- -----------------------------------------------------------------------------
Leonard Rosenthol Internet: leonardr@netcom.com
Director of Advanced Technology AppleLink: MACgician
Aladdin Systems, Inc. GEnie: MACgician
+++++++++++++++++++++++++++
Date: 12 Oct 92 16:38:53 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
> wfp@jupiter.claremont.edu (Frank Price) writes:
noticed that various keys will not even send an event when initially typed
such as Option-E and Option-U, and Option-'. How do I override this system
so that Option can be used normally for those special characters?
They area called dead keys, and option-e, option-u etc are NOT dead
keys on other keyboards (like swedish ones)
Try using your own KCHR (the key mapping resource) but make it
an option since peoplr outside the US have different keyboard
needs.
- --
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Suedoise (not french speaking) --
"From now on I will re-label the EQ on the deck as Fizz and Wobble
instead of HF and LF."
+++++++++++++++++++++++++++
From: David.T.Greenfield@dartmouth.edu (David T. Greenfield)
Date: 13 Oct 92 13:47:18 GMT
Organization: Dartmouth College, Hanover, NH
In article <1992Oct12.161745.8323@netcom.com>
leonardr@netcom.com (Leonard Rosenthol) writes:
> The wrong way is what ZTerm & NCSA Telnet (to name two) do it. That is
> to require the user to use THEIR KCHR resource, which requires the user to
> do a bit of ResEditting of the System file, since KCHR's must live in the System
> under System 7.
In System 7, KCHRs can be dragged in and out of the system file in the
same manner as fonts, sounds, etc.
David
david.t.greenfield@dartmouth.edu
+++++++++++++++++++++++++++
From: grobbins@Apple.COM (Grobbins)
Date: 13 Oct 92 21:06:28 GMT
Organization: Really Weird Future Mac Department, Apple Computer, Inc.
In article <1992Oct12.161745.8323@netcom.com> leonardr@netcom.com (Leonard Rosenthol) writes:
>In article <1992Oct12.040750.20383@muddcs.claremont.edu> wprice@pomona.claremont.edu writes:
>>I am trying to read option keys from the Mac keyboard, and of course have
>>noticed that various keys will not even send an event when initially typed
>>such as Option-E and Option-U, and Option-'. How do I override this system so
>>that Option can be used normally for those special characters?
>
>The wrong way is...
>to require the user to use THEIR KCHR resource, which requires the user to
>do a bit of ResEditting of the System file, since KCHR's must live in the
>System under System 7.
Not exactly. Under System 6, using a custom application KCHR is easier
since it can reside in the application's own resource fork. Just be sure
to set back to the standard system KCHR on suspends and when quitting.
While System 7 does require that the KCHR be installed in the System, this
can be done by having the user drag a keyboard file to the System suitcase.
(See Inside Mac VI, page 14-96.) This is the recommended route, and is
discussed in the Q&A Stack; I'll paste the appropriate entry below.
> The right way to do it (which MicroPhone II & Smartcom do) is to
>first patch _KeyTrans to map the option modiifier to something else (in the
>cases above, the control modifieir). However, since the process manager
>swaps patches on even minor context switches, you could STILL get the wrong
>characters. So you have to do some on-the-fly munging of the KCHR (after
>copying the orignal!!) - BUT remember to restore the original KCHR on
>suspend/resumes!!
Modifying the system KCHR on-the-fly sounds awfully unappealing, as
does searching for certain key combinations in a patch. A cleaner
patch, one which must be done from an INIT because of the automatic
patch-table swapping that Leonard refers to, would be to set bit 7 of
the keycode parameter to KeyTrans, since dead keys are not processed on
keyups.
Grobbins grobbins@apple.com
Usual disclaimers apply.
- ---
from the Q&A Stack:
I would like to use the Macintosh Option key as the Control key for
keyboards that lack a Control key, such as for Macintosh Plus keyboards. How
can I find the ASCII value that would have been returned if the Option key
weren't pressed, in a way that would be compatible with other keyboards?
There are a couple of clean ways to ignore the Option key. One is to
"reprocess" the keyboard event. The fourth byte of the event message is the
ASCII code, but the third byte is the virtual key code. The system calls the
trap KeyTrans to map the virtual key code to ASCII according to a 'KCHR'
resource. You can do the same, and since the high byte of the modifiers are
part of the input to KeyTrans, you can strip out the Option key, call
KeyTrans on the third byte of the event message, and get back the "true"
ASCII keypress. KeyTrans and 'KCHR' resources are documented in Chapter 10
of Inside Macintosh Volume V, Chapter 14 of Inside Macintosh Volume VI
(pages 14-23 and 14-96), and Macintosh Technical Note #160, "Key Mapping."
In Pascal, these steps would look something like:
keycode := BAND(event.message, keyCodeMask);{ get virtual code }
keycode := BSR(keycode, 8); { move to low byte }
{ now combine with modifiers }
keycode := BOR(keycode, BAND($FF00, event.modifiers));
keycode := BAND(keycode, $FFFF - optionKey); { strip option }
newkey := KeyTrans(KCHRHandle^, keyCode, state);
The resource ID of the current KCHR is available as
GetScript(GetEnvirons(smKeyScript), smScriptKeys). Alternatively, a pointer
to the KCHR data is available under System 7 as GetEnvirons(smKCHRCache), as
discussed in Tech Note #263, "International Canceling."
This method may work for you, but there is a possible problem: dead keys.
Since dead keys are processed before your application gets the event, your
application will not see (for example) the first Option-e typed. However,
the dead keys are specified in the 'KCHR' resource, so you can create a KCHR
(ResEdit 2.1.1 includes a template) to omit dead keys (and, if you choose,
option characters) and include it with your application. Call SetScript to
get the system to use your 'KCHR' (see Tech Note #160, IM V-313, and IM VI
14-40).
Another problem is that System 7 ignores a 'KCHR' in the application's
resources, so an application's 'KCHR' has to be installed in the system. You
can install the 'KCHR' with an installer program, or provide a keyboard file
users can drag to the System file. (To create a keyboard file, use ResEdit
to put the 'KCHR' in the System file, and then drag it out with the System 7
Finder.)
+++++++++++++++++++++++++++
From: richardk@kiwi.gen.nz (Richard Knuckey)
Date: 16 Oct 92 05:17:22 GMT
Organization: Unix Usenet Server, Western Springs, Auckland, New Zealand
> The wrong way is what ZTerm & NCSA Telnet (to name two) do it. That
> is to require the user to use THEIR KCHR resource, which requires
> the user to do a bit of ResEditting of the System file, since
> KCHR's must live in the System under System 7.
>
> The right way to do it (which MicroPhone II & Smartcom do) is to
> first patch _KeyTrans to map the option modiifier to something else
> (in the cases above, the control modifieir). However, since the
> process manager swaps patches on even minor context switches, you
> could STILL get the wrong characters. So you have to do some
> on-the-fly munging of the KCHR (after copying the orignal!!) - BUT
> remember to restore the original KCHR on suspend/resumes!!
No No No! Since when do you have to _patch_ the OS to remap the keyboard.
Never ever patch anything unless you absoulety *have* to.
All you do is call _KeyTrans yourself (see Inside Mac V) with your own
KCHR structure in memory. This is what I do in Moria when I detect a
macPlus Keyboard. Code follows:
/* Variables */
extern Handle KCHRresource;
extern long trans_state;
/* From InitWimp() - Code to set up KCHR and trans_state */
if (g->KeyboardType <= envMacPlusKbd)
{
trans_state = 0;
KCHRresource = GetResource('KCHR', 128);
MoveHHi(KCHRresource);
HLock(KCHRresource);
}
/* ------------------------------------------------------------------------
* RemapKeys
*
* This remaps the keyboard using the KCHR we loaded in initwimp.
* It calls KeyTrans, to translate vitual keycodes to ASCII values.
* This is only called on keyboards without an Escape
* or control keys such as on a MacPlus. The KCHR maps the control key
* to the option key and the tilde key to the escape key. This will work
* even under system 7.0 since we are forcing a keytranslation instead
* of simply setting the system wide KCHR, which under system 7.0 requires
* the KCHR resource to be in the system for reasons discussed in
* Inside Macintosh VI pp 14-96
*/
RemapKeys(theEvent)
EventRecord *theEvent;
{
short keycode;
char *p, *q; /* used for byte level acces to variables */
long ascii_code;
p = &keycode;
q = &theEvent->message;
p[1] = q[2];
q = &theEvent->modifiers;
p[0] = q[0];
ascii_code = KeyTrans(*KCHRresource,keycode,&trans_state);
p = &ascii_code;
theEvent->message = p[3];
}
/* From Window Handler for main Moria game window */
case keyDown:
case autoKey:
ObscureCursor();
if (g->KeyboardType <= envMacPlusKbd)
RemapKeys ( theEvent );
theChar = (char)(theEvent->message & charCodeMask);
The Biggest advantages of this way is that it doesn't muck around with
the rest of the system, It only remaps the keyboard for the window
that needs it, I doesn't require the instalation of any resources to the
system file and the KCHR does't show up in the Keyboard menu.
A disadvantage is that the system does not pass on "dead keys" to you. this
means that you won't get an option-e passed to you, since it's marked as a dead
key in the default US system KCHR. This may casue you concern. Luckely Moria
doesn't use any on these keys anyway :-). The only clean way around this
second problem if you absoluetly MUST have option-e mapped to something is yo
havethe user install a keyboard layout, and for you to switch to that layout on
resume events ,and to set it back on suspend events.
---------------------------
From: sll2@cunixa.cc.columbia.edu (Steven L Levitt)
Subject: UnloadSeg and pointers to functions
Organization: Columbia University
Date: Thu, 15 Oct 1992 18:19:40 GMT
If I have a structure on the heap which contains a point
function and I call UnloadSeg() on the segment which contains that
function, will the pointer still be valid afterward? I would like to call
UnloadSeg() each time through the main event loop, but I don't know if the Jump
Table scheme the mac employes will preserve the validity of my f
pointers.
- ----------------
Steven L. Levitt sll2@cunixa.cc.columbia.edu
An Undergrad
+++++++++++++++++++++++++++
From: keith@taligent.com (Keith Rollin)
Organization: Taligent
Date: Thu, 15 Oct 1992 23:24:43 GMT
In article <1992Oct15.181940.2146@news.columbia.edu>,
sll2@cunixa.cc.columbia.edu (Steven L Levitt) wrote:
>
> If I have a structure on the heap which contains a point
> function and I call UnloadSeg() on the segment which contains that
> function, will the pointer still be valid afterward? I would like to call
> UnloadSeg() each time through the main event loop, but I don't know if the Jump
> Table scheme the mac employes will preserve the validity of my f
> pointers.
The pointer should remain valid. If you take the address of a function, the
compiler will generate a jump table entry for that function. The function
pointer will then, in fact, point to the jump table entry.
- -----
Keith Rollin
Phantom Programmer
Taligent, Inc.
+++++++++++++++++++++++++++
From: absurd@applelink.apple.com (Tim Dierks, software saboteur)
Date: Thu, 15 Oct 1992 22:24:22 GMT
Organization: MacDTS Marauders
In article <1992Oct15.181940.2146@news.columbia.edu>,
sll2@cunixa.cc.columbia.edu (Steven L Levitt) wrote:
>
> If I have a structure on the heap which contains a point
> function and I call UnloadSeg() on the segment which contains that
> function, will the pointer still be valid afterward? I would like to call
> UnloadSeg() each time through the main event loop, but I don't know if the Jump
> Table scheme the mac employes will preserve the validity of my f
> pointers.
>
> ----------------
> Steven L. Levitt sll2@cunixa.cc.columbia.edu
> An Undergrad
The answer: usually. There are two different ways to construct a function
address, whether you're calling it or taking its address for later use.
You can either use the address in the jump table, which is constant and
doesn't move, or you can take the actual pointer to the code, which,
because it's in a code segment, could plausibly be unloaded and move
(unless it's in the same segment as your main entry point). So if
you're going to build a pointer to a function, you have three options:
1) Make sure the function is in the main segment.
2) If it's not in the main segment, make sure the segment it's in
never gets unloaded while the function pointer is supposed to
be valid.
3) Make sure you get a jump table pointer.
3) is best, except for functions which might be called at interrupt
time, such as VBL tasks; for these, 1) is best, because you won't be
able to load the segment when the function gets called. Usually,
this isn't a problem; by default, both Think and MPW give you jump
table function pointers. You're guaranteed of getting a jump table
pointer if you take the routine's address from another segment, because
that's all the code in that area knows; for example, if I take the
address of function foo() which is in the segment FooSeg from function
bar() in BarSeg, I'll be guaranteed a jump table address. Even if
the function and the code getting the address are in the same segment,
you will almost always get a jump table address. There are two
exceptions:
1) If using the -b or -b3 options in MPW C, or if you're not using
the -b option in MPW Pascal, you will get a PC-relative
function address if the source and destination are in the
same segment.
2) If you're using -model far, you'll always get a PC-relative
address due to a bug in the way it patches up your segment.
Thus, if you want to be sure your address will always be OK and it's
not in the main segment, either take the address from another
segment or don't use the -b or -b3 option for MPW C and do use
the -b option in MPW Pascal.
I'm sure there are similar things for Think, but I don't know what
they are.
Tim Dierks
MacDTS, but I post too much
+++++++++++++++++++++++++++
From: phils@chaos.cs.brandeis.edu (Phil Shapiro)
Date: 16 Oct 92 02:45:00 GMT
Organization: Symantec Corp.
In article <absurd-151092151115@seuss.apple.com> absurd@applelink.apple.com (Tim Dierks, software saboteur) writes:
[ Tim explains MPW C & Pascal's rules for creating jump table entries
and associated options. ]
I'm sure there are similar things for Think, but I don't know what
they are.
THINK C will always produce a jump table entry for functions whose
address is taken, even if the reference is intra-segment and/or the
function is declared static. I believe THINK Pascal follows the same
rule.
The only exception to the above rule is for single-segment code
resources, who don't have a jump table anyway.
-phil
- --
Phil Shapiro Software Engineer
Language Products Group Symantec Corporation
Internet: phils@cs.brandeis.edu
+++++++++++++++++++++++++++
From: Anders Wallgren <anders@verity.com>
Organization: Verity, Mountain View, CA, USA
Date: Fri, 16 Oct 92 02:18:21 GMT
In article <absurd-151092151115@seuss.apple.com> Tim Dierks,
absurd@applelink.apple.com writes:
>2) If you're using -model far, you'll always get a PC-relative
> address due to a bug in the way it patches up your segment.
This is fixed in the latest MPW on ETO.
---------------------------
End of C.S.M.P. Digest
**********************