• Hello MLAers! We've re-enabled auto-approval for accounts. If you are still waiting on account approval, please check this thread for more information.

System 6 extension/control panel to modify keyboard input?

The files in the GitHub should use Unix linefeeds instead of classic Mac OS carriage returns. Since you're using retro68, source files with linefeeds should be fine. CodeWarrior also supports linefeeds. Not sure about MPW or Think C or whatever.

CodeWarrior doesn't like UTF-8 and GitHub doesn't like MacRoman, so make sure the source files use only ASCII.
Search for regex [^ -~\n\t\r] to find illegal characters.

For the .r file, use the Rez include files from the Universal Interfaces RIncludes folder when you Rez and DeRez your resources so that your .r file is more readable. These .r files might be in a Xcode SDK as well.
Bash:
find "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" -name '*.r'
grep -R --include '*.r' -E "'(sysz|ICN#|vers|FREF|ics#|BNDL)'" "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
bbfind --name-pattern '*.r' -g "'(sysz|ICN#|vers|FREF|ics#|BNDL)'" "/Volumes/Devs/Metrowerks CodeWarrior 8.0/Metrowerks CodeWarrior/MacOS Support/Universal/Interfaces/RIncludes"

Rez "KeyboardCursorsOpt.rsrc.r" -o "KeyboardCursorsOpt.rsrc"

DeRez "KeyboardCursorsOpt.rsrc" -i "/Volumes/Devs/Metrowerks CodeWarrior 8.0/Metrowerks CodeWarrior/MacOS Support/Universal/Interfaces/RIncludes" Finder.r Icons.r MacTypes.r > "KeyboardCursorsOpt2.rsrc.r"
bbdiff "KeyboardCursorsOpt2.rsrc.r" "KeyboardCursorsOpt.rsrc.r"
# mv "KeyboardCursorsOpt2.rsrc.r" "KeyboardCursorsOpt.rsrc.r"

Rez -i "/Volumes/Devs/Metrowerks CodeWarrior 8.0/Metrowerks CodeWarrior/MacOS Support/Universal/Interfaces/RIncludes" Finder.r Icons.r MacTypes.r "KeyboardCursorsOpt.rsrc.r" -o "KeyboardCursorsOpt.rsrc"

How to use Rez and DeRez is described in MPW_3.0_Reference_Volume_1_1988.pdf

I'm not sure why there's no .r file for the sysz resource but I guess it's simple enough.
https://leopard-adc.pepas.com/qa/ops/ops02.html
https://developer.apple.com/library.../pdf/Operating_System_Utilities/Start_Mgr.pdf

What's CallPascal for? Isn't there a way to qualify the function pointer ABI as pascal so that the compiler knows how to call it correctly? Well, I see you didn't define it as a function pointer - just a long. In CodeWarrior, you can do this:
C:
#include <a4stuff.h>
#include <dialogs.h>
#include <string.h>
#include <Resources.h>
#include "TrapUtilities.h"

// Global Types
typedef pascal Handle ( *Get1ResourceProcPtr )( ResType theType, short theID );

// Globals
Get1ResourceProcPtr oldGet1Resource;

// Prototypes
extern "C" void __Startup__( void );
void main( void );
pascal Handle MyGet1Resource( ResType theType, short theID );

void main( void )
{
    EnterCodeResource( );
    Handle hdl = RecoverHandle( ( Ptr ) __Startup__ );  // yes, make INIT resident; it is already locked and in the system heap
    DetachResource( hdl );
    PatchATrap( _Get1Resource,      (ProcPtr)MyGet1Resource, (ProcPtr&)oldGet1Resource );
    ExitCodeResource( );
}

pascal Handle MyGet1Resource( ResType theType, short theID )
{
    EnterCodeResource( );
    Handle theResource = oldGet1Resource( theType, theID );
    ...
    ExitCodeResource( );
    return theResource;
} // MyGet1Resource

Notes about A5 and patching traps:
https://developer.apple.com/library/archive/technotes/ov/ov_14.html
But you're an INIT, not an APPL.

TrapUtilities.h:
C:
#if PRAGMA_ONCE
#pragma once
#endif

#ifdef __cplusplus
extern "C" {
#endif

#include <MacTypes.h>

bool TrapAvailable(UInt16 theTrap);

void PatchATrap( UInt16 theTrap, ProcPtr newTrap, ProcPtr *saveTrapPtr );

#ifdef __cplusplus
}
#endif

TrapUtilites.cpp:
see Inside Macintosh: Overiew - Chapter 9: Processes
and also
https://developer.apple.com/library...f/Operating_System_Utilities/Trap_Manager.pdf
https://preterhuman.net/macstuff/techpubs/mac/OSUtilities/OSUtilities-171.html

C:
#include "TrapUtilities.h"

#include <Traps.h>
#include <OSutils.h>

const long TrapMask = 0x0800;

short NumToolboxTraps( void );
TrapType GetTrapType(UInt16 theTrap);

short NumToolboxTraps( void )
{
	if (GetToolboxTrapAddress(_InitGraf) == GetToolboxTrapAddress(0xAA6E))
		return(0x0200);
	else
		return(0x0400);
}

TrapType GetTrapType(UInt16 theTrap)
{
	if ((theTrap & TrapMask) > 0)
		return(ToolTrap);
	else
		return(OSTrap);
}

bool TrapAvailable(UInt16 theTrap)
{
	TrapType	tType;

	tType = GetTrapType(theTrap);
	if (tType == ToolTrap)
		if (theTrap & 0x3FF >= NumToolboxTraps())
			return false;

	return (NGetTrapAddress(theTrap, tType) !=
			GetToolboxTrapAddress(_Unimplemented));
}

void PatchATrap( UInt16 theTrap, ProcPtr newTrap, ProcPtr *saveTrapPtr )
{
	ProcPtr saveTrap;
	TrapType tType = GetTrapType( theTrap );
	saveTrap = NGetTrapAddress( theTrap, tType );
	if ( saveTrapPtr != nil )
		*saveTrapPtr = saveTrap;
	NSetTrapAddress( newTrap, theTrap, tType );
}


Regarding INITs and Think C, there's this article from MacTech magazine:
http://preserve.mactech.com/articles/mactech/Vol.05/05.10/INITinC/index.html
It describes the CallPascal function.

This tech note has some Think C sample code that has a definition for QDGlobals:
https://preterhuman.net/macstuff/technotes/ov/ov_13.html
 
From that tech note, this might be what I need:
---
/*
*this is needed because the QuickDraw global thePort is not defined at INIT time
*/
typedef struct myQDGlobalsDef {
char qdPrivates[76];
long randSeed;
BitMap screenBits;
Cursor arrow;
Pattern dkGray;
Pattern ltGray;
Pattern gray;
Pattern black;
Pattern white;
GrafPtr thePort;
} myQDGlobalsDef;
----
I'll see if I can adapt the ShowInitIcon code to use that type of thing.

The second to last link is great.
"If you only want to draw an INIT at start up to notify the user that your INIT has been installed, get a copy of Paul Mercer’s ShowINIT code (which is available as a THINK C project) and use it. Almost everyone who puts up an icon at start up uses Mercer’s code or a variant of it. "

Now THAT would be super useful. I'm going to go spelunking for that.

The files in the GitHub should use Unix linefeeds instead of classic Mac OS carriage returns. Since you're using retro68, source files with linefeeds should be fine. CodeWarrior also supports linefeeds. Not sure about MPW or Think C or whatever.

The linefeeds and utf8 vs macroman is a pain. This particular project is all done in THINK C, I'm not using Retro68. I put stuff in GitHub for sharing purposes, and to have a record to back to, but the diffs are useless because of the line endings and encoding. But if I do unix line endings, THINK C has a hard time with it, and UTF8 will result in immediate errors. I need a tool that A) syncs between retro Mac and modern Mac, and B does linefeed and encoding translation as part of that.
Anyway, thanks for all the help
 
Huzzah! (3rd icon)
(It's a good thing I'm not getting paid to do this. I spent about 1 hr figuring out how to do the keyboard thing again after 5 years, and 20 hours dinking with getting it to show on an icon. It was fun (err, mostly).

In the end, all it needed was this extra def, which I found on UMICH:
---
/mac/development/source/controlpanel0.94.sit.hqx
133 7/30/94 BinHex4.0,StuffIt3.50

THINK C source for a sample control panel, sample INIT and sample
patch. Includes compiled examples of each
---

C:
typedef struct QDGlobals {
    char privates[76];
    long randSeed;
    BitMap screenBits;
    Cursor arrow;
    Pattern dkGray;
    Pattern ltGray;
    Pattern gray;
    Pattern black;
    Pattern white;
    GrafPtr thePort;
    long    end;
} QDGlobals;

(and for some the more modern toolbox calls to get commented out: MacPlus ROM doesn't have them, and THINK C doesn't know them).

Screenshot 2025-05-04 at 9.26.16 PM.png
 
Anyone care to test it out? It should be better than the old caps lock version, at least in this respect: you can do SHIFT-Down, SHIFT-right, etc, to affect selection. If anyone still wants the caps lock version, I can upgrade it. Also, if anyone prefers an IJKL version, I can do one of those too.
 

Attachments

(It's a good thing I'm not getting paid to do this. I spent about 1 hr figuring out how to do the keyboard thing again after 5 years, and 20 hours dinking with getting it to show on an icon. It was fun (err, mostly).

It's always the UI that gets you, even if the UI is trivial! I think that's a general software engineering truth. Good stuff!

If you'd like to get people to try this out if you think it's getting to "finished" may I suggest you make a separate announcement thread? Anyone who isn't already interested in writing abstruse C has probably stopped following this thread, whereas a "here's a new extension to do X" thread might get some end-user eyes :-)
 
New version, which takes in some ideas from the Software forum: you can now hack your own key combos.
 
Back
Top