Add support for message center in the C desktop template

This commit is contained in:
Jeremy Rand 2019-07-11 20:28:12 -04:00
parent 9f70c68ddf
commit 71dc80ea67
11 changed files with 259 additions and 92 deletions

View File

@ -90,6 +90,19 @@ COPYDIRS=
# If you have it in a different location, specify that here.
# GSPORT=/Applications/GSport/GSport.app/Contents/MacOS/GSport
# For a desktop application, it can operate in 640x200 or 320x200
# resolution. This setting is used to define which horizontal
# resolution you want to use for a desktop application. Other
# target types ignore this value.
# DESKTOP_RES_MODE=640
# For a desktop application, it can support opening and printing
# files based on paths sent to it by the message center. This
# option controls if that is or is not supported in the
# application (note: only the C desktop template supports message
# center today)
# MESSAGE_CENTER=0
# Add any rules you want to execute before any compiles or assembly
# commands are called here, if any. You can generate .c, .s or .h
# files for example. You can generate data files. Whatever you

View File

@ -36,6 +36,9 @@ CHTYP=$(ORCA) chtyp
RM=rm -f
CP=cp
DESKTOP_RES_MODE=640
MESSAGE_CENTER=0
GSPLUS=/Applications/GSplus.app/Contents/MacOS/gsplus
GSPORT=/Applications/GSport/GSport.app/Contents/MacOS/GSport

View File

@ -15,7 +15,7 @@ BASENAME=`echo $FILENAME | sed 's/\.rez$//'`
DEPSNAME="${BASENAME}.rez.d"
OBJSNAME="${BASENAME}.r"
$ORCA --trace-gsos compile $* keep="${OBJSNAME}" "$FILENAME" 2> $ERROUTPUT
$ORCA --trace-gsos compile "$@" keep="${OBJSNAME}" "$FILENAME" 2> $ERROUTPUT
RESULT=$?
awk '

View File

@ -18,7 +18,14 @@ ifeq ($(TARGETTYPE),shell)
BUILDTARGET=$(PGM)
else ifeq ($(TARGETTYPE),desktop)
FILETYPE=s16
AUXTYPE=-a 0x0000db03
ifeq ($(MESSAGE_CENTER),1)
AUXTYPE=-a 0x0000db07
else
AUXTYPE=-a 0x0000db03
endif
CFLAGS+=-dMESSAGE_CENTER=$(MESSAGE_CENTER)
REZFLAGS+=rez='-d DESKTOP_RES_MODE=$(DESKTOP_RES_MODE)'
REZFLAGS+=rez='-d MESSAGE_CENTER=$(MESSAGE_CENTER)'
else ifeq ($(TARGETTYPE),cda)
FILETYPE=cda
DISKIMAGEDEST=System/Desk.Accs

View File

@ -142,7 +142,7 @@
<key>Name</key>
<string>Desktop Resolution</string>
<key>Description</key>
<string>Specify 640 or 320 pixel desktop enviroment.</string>
<string>Specify 640x200 or 320x200 resolution desktop enviroment.</string>
<key>Type</key>
<string>popup</string>
<key>Default</key>
@ -153,6 +153,18 @@
<string>320</string>
</array>
</dict>
<dict>
<key>Identifier</key>
<string>MESSAGECENTER</string>
<key>Name</key>
<string>Message Center</string>
<key>Description</key>
<string>Specify whether the application will support opening and printing files.</string>
<key>Type</key>
<string>checkbox</string>
<key>Default</key>
<string>0</string>
</dict>
</array>
<key>Targets</key>
<array>

View File

@ -8,6 +8,7 @@
*/
#include <Memory.h>
#include <Locator.h>
#include <Event.h>
@ -49,7 +50,6 @@ typedef struct tDocument
GrafPortPtr wPtr;
char documentName[MAX_DOCUMENT_NAME + 1];
BOOLEAN isOnDisk;
ResultBuf255Hndl fileName;
ResultBuf255Hndl pathName;
PrRecHndl printRecordHandle;
} tDocument;
@ -80,7 +80,7 @@ const char * resourceString(int resourceId, const char * defaultValue)
HLock(handle);
result = (const char *) (*handle);
}
return(result);
return result;
}
@ -136,21 +136,69 @@ void drawContents(void)
const char * getUntitledName(void)
{
static int untitledNum = 1;
static char buffer[MAX_DOCUMENT_NAME];
static char buffer[MAX_DOCUMENT_NAME + 1];
const char *untitledFormat = resourceString(UNTITLED_STRING, " Untitled %d ");
sprintf(buffer, untitledFormat, untitledNum);
sprintf(buffer + 1, untitledFormat, untitledNum);
buffer[0] = strlen(buffer + 1);
freeResourceString(UNTITLED_STRING);
untitledNum++;
return(buffer);
// Returns a Pascal string with a length byte prefix
return buffer;
}
const char * documentNameFromGSOSString(ResultBuf255Ptr gsosString)
{
static char buffer[MAX_DOCUMENT_NAME + 1];
int nameLen = gsosString->bufString.length;
strcpy(buffer + 1, " ");
nameLen = gsosString->bufString.length;
if (nameLen > MAX_DOCUMENT_NAME - 5)
nameLen = MAX_DOCUMENT_NAME - 5;
strncat(buffer + 1, gsosString->bufString.text, nameLen);
strcat(buffer + 1, " ");
buffer[0] = strlen(buffer + 1);
return buffer;
}
const char * documentNameFromPath(wStringPtr pathString)
{
static char buffer[MAX_DOCUMENT_NAME + 1];
int nameLen = pathString->length;
char * path = pathString->text;
int lastSeparator = 0;
int offset;
for (offset = 0; offset < nameLen; offset++) {
if ((path[offset] == ':') ||
(path[offset] == '/'))
lastSeparator = offset + 1;
}
path = &(path[lastSeparator]);
nameLen -= lastSeparator;
strcpy(buffer + 1, " ");
if (nameLen > MAX_DOCUMENT_NAME - 5)
nameLen = MAX_DOCUMENT_NAME - 5;
strncat(buffer + 1, path, nameLen);
strcat(buffer + 1, " ");
buffer[0] = strlen(buffer + 1);
return buffer;
}
tDocument * newDocument(const char * windowName)
{
// windowName is a Pascal string with a length byte prefix
tDocument * documentPtr;
int titleLength;
documentPtr = malloc(sizeof(tDocument));
if (documentPtr == NULL) {
@ -161,20 +209,15 @@ tDocument * newDocument(const char * windowName)
if (toolerror() != 0) {
showErrorAlert(MALLOC_ERROR_STRING, toolerror());
free(documentPtr);
return(NULL);
return NULL;
}
PrDefault(documentPtr->printRecordHandle);
documentPtr->isOnDisk = FALSE;
documentPtr->fileName = NULL;
documentPtr->pathName = NULL;
titleLength = strlen(windowName);
if (titleLength > MAX_DOCUMENT_NAME) {
titleLength = MAX_DOCUMENT_NAME;
}
documentPtr->documentName[0] = titleLength;
strncpy(&(documentPtr->documentName[1]), windowName, titleLength);
documentPtr->documentName[0] = windowName[0];
strncpy(documentPtr->documentName + 1, windowName + 1, windowName[0]);
documentPtr->wPtr = NewWindow2(documentPtr->documentName, 0, drawContents, NULL, refIsResource,
WINDOW_RESID, rWindParam1);
@ -182,7 +225,7 @@ tDocument * newDocument(const char * windowName)
showErrorAlert(NEW_WINDOW_ERROR_STRING, toolerror());
DisposeHandle((Handle)documentPtr->printRecordHandle);
free(documentPtr);
return(NULL);
return NULL;
}
documentPtr->nextDocument = documentList;
@ -192,7 +235,7 @@ tDocument * newDocument(const char * windowName)
documentList = documentPtr;
return(documentPtr);
return documentPtr;
}
@ -418,11 +461,7 @@ void closeDocument(GrafPortPtr wPtr)
if (documentPtr == NULL)
return;
if (documentPtr->fileName != NULL) {
DisposeHandle((Handle) documentPtr->fileName);
documentPtr->fileName = NULL;
}
if (documentPtr->pathName != NULL) {
DisposeHandle((Handle) documentPtr->pathName);
documentPtr->pathName = NULL;
@ -501,11 +540,8 @@ void doFileOpen(void)
{
tDocument * documentPtr;
SFTypeList2 fileTypes;
Handle nameHandle;
ResultBuf255Ptr namePtr;
int nameLen;
char documentName[MAX_DOCUMENT_NAME];
SFReplyRec2 reply;
ResultBuf255Hndl nameHandle;
/* By default, we want to open text files only which is what
the following fileTypes request. Customize as necessary. */
@ -523,22 +559,14 @@ void doFileOpen(void)
}
if (reply.good) {
nameHandle = (Handle) reply.nameRef;
HLock(nameHandle);
namePtr = (ResultBuf255Ptr) (*nameHandle);
strcpy(documentName, " ");
nameLen = namePtr->bufString.length;
if (nameLen > MAX_DOCUMENT_NAME - 5)
nameLen = MAX_DOCUMENT_NAME - 5;
strncat(documentName, namePtr->bufString.text, nameLen);
strcat(documentName, " ");
HUnlock(nameHandle);
documentPtr = newDocument(documentName);
nameHandle = (ResultBuf255Hndl) reply.nameRef;
HLock((Handle) nameHandle);
documentPtr = newDocument(documentNameFromGSOSString(*nameHandle));
DisposeHandle((Handle) nameHandle);
if (documentPtr == NULL) {
DisposeHandle((Handle) reply.nameRef);
DisposeHandle((Handle) reply.pathRef);
} else {
documentPtr->fileName = (ResultBuf255Hndl) reply.nameRef;
documentPtr->pathName = (ResultBuf255Hndl) reply.pathRef;
documentPtr->isOnDisk = loadDocument(documentPtr);
@ -551,10 +579,9 @@ void doFileOpen(void)
void doFileSaveAs(void)
{
Handle nameHandle;
ResultBuf255Ptr namePtr;
int nameLen;
ResultBuf255Hndl nameHandle;
SFReplyRec2 reply;
const char * documentName;
tDocument * documentPtr = findDocumentFromWindow(FrontWindow());
if (documentPtr == NULL)
@ -563,9 +590,9 @@ void doFileSaveAs(void)
reply.nameRefDesc = refIsNewHandle;
reply.pathRefDesc = refIsNewHandle;
if (documentPtr->fileName == NULL)
if (documentPtr->pathName == NULL)
SFPutFile2(30, 30, refIsResource, SAVE_FILE_STRING, refIsPointer,
(Ref) &(documentPtr->fileName), &reply);
(Ref) &(documentPtr->pathName), &reply);
else
SFPutFile2(30, 30, refIsResource, SAVE_FILE_STRING, refIsPointer,
(Ref) &((*(documentPtr->pathName))->bufString), &reply);
@ -576,20 +603,15 @@ void doFileSaveAs(void)
}
if (reply.good) {
nameHandle = (Handle) reply.nameRef;
HLock(nameHandle);
namePtr = (ResultBuf255Ptr) (*nameHandle);
strcpy(documentPtr->documentName, " ");
nameLen = namePtr->bufString.length;
if (nameLen > MAX_DOCUMENT_NAME - 6)
nameLen = MAX_DOCUMENT_NAME - 6;
strncat(documentPtr->documentName, namePtr->bufString.text, nameLen);
strcat(documentPtr->documentName, " ");
documentPtr->documentName[0] = strlen(documentPtr->documentName) - 1;
HUnlock(nameHandle);
nameHandle = (ResultBuf255Hndl) reply.nameRef;
HLock((Handle) nameHandle);
documentName = documentNameFromGSOSString(*nameHandle);
documentPtr->documentName[0] = documentName[0];
strncpy(documentPtr->documentName + 1, documentName + 1, documentName[0]);
DisposeHandle((Handle) nameHandle);
SetWTitle(documentPtr->documentName, documentPtr->wPtr);
documentPtr->fileName = (ResultBuf255Hndl) reply.nameRef;
documentPtr->pathName = (ResultBuf255Hndl) reply.pathRef;
documentPtr->isOnDisk = TRUE;
saveDocument(documentPtr);
@ -788,6 +810,76 @@ void dimMenus(void)
}
void handleMessages(void)
{
#if MESSAGE_CENTER == 1
Handle msgHandle;
MessageRecGSPtr msgPtr;
wStringPtr pathPtr;
tDocument * documentPtr;
ResultBuf255Ptr resultBufPtr;
msgHandle = NewHandle(1, userid, 0, NULL);
if (toolerror() != 0) {
showErrorAlert(MALLOC_ERROR_STRING, toolerror());
return;
}
MessageCenter(getMessage, fileInfoTypeGS, msgHandle);
if (toolerror() != 0) {
DisposeHandle(msgHandle);
return;
}
MessageCenter(deleteMessage, fileInfoTypeGS, msgHandle);
HLock(msgHandle);
msgPtr = (MessageRecGSPtr)(*msgHandle);
for (pathPtr = msgPtr->fileNames;
pathPtr->length != 0;
pathPtr = (wStringPtr)(pathPtr->text + pathPtr->length))
{
documentPtr = newDocument(documentNameFromPath(pathPtr));
if (documentPtr == NULL)
continue;
documentPtr->pathName = (ResultBuf255Hndl)NewHandle(pathPtr->length + 4, userid, 0, NULL);
if (toolerror() != 0)
{
showErrorAlert(MALLOC_ERROR_STRING, toolerror());
closeDocument(documentPtr->wPtr);
continue;
}
HLock((Handle) documentPtr->pathName);
resultBufPtr = *(documentPtr->pathName);
resultBufPtr->bufSize = pathPtr->length + 4;
resultBufPtr->bufString.length = pathPtr->length;
memcpy(resultBufPtr->bufString.text, pathPtr->text, pathPtr->length);
HUnlock((Handle) documentPtr->pathName);
documentPtr->isOnDisk = loadDocument(documentPtr);
if (!documentPtr->isOnDisk)
{
closeDocument(documentPtr->wPtr);
continue;
}
if (msgPtr->printFlag)
{
doFilePrint();
closeDocument(documentPtr->wPtr);
}
}
if (msgPtr->printFlag)
doFileQuit();
DisposeHandle(msgHandle);
#endif
}
void initMenus(void)
{
int height;
@ -839,7 +931,10 @@ int main(void)
initMenus();
InitCursor();
handleMessages();
while (!shouldQuit) {
HandleDiskInsert(hdiScan | hdiHandle, 0);
dimMenus();
event = TaskMaster(everyEvent, &myEvent);
TOOLFAIL("Unable to handle next event");

View File

@ -74,9 +74,4 @@
#define TOOL_STARTUP 1
/* By default, thie template builds for 640x200 mode. To build for
* 320x200 change the following value to 320 */
#define RES_MODE ___VARIABLE_RESOLUTIONMODE___
#endif /* defined(_GUARD_PROJECT___PROJECTNAMEASIDENTIFIER____FILE___FILEBASENAMEASIDENTIFIER____) */

View File

@ -25,6 +25,38 @@ resource rVersion (1) {
"Copyright \$A9 ___YEAR___ ___FULLUSERNAME___"
};
#if MESSAGE_CENTER == 1
/* Bunde resource */
resource rBundle (1, preload, nospecialmemory) {
nil, /* rIcon ID for application if you wish a custom icon */
1,
{
{
native + LaunchThis,
{0}, /* rFinderPath ID for this document */
{nil}, /* rIcon ID for large icon for document */
{nil}, /* rIcon ID for small icon for document */
"", /* String to describe this type of document */
},
Filetype + AuxType, /* Match field bits */
MatchFileType {{$04}}, /* File type to match */
MatchAuxType { /* Auxiliary file type to match */
{$00000000,$00000000}
},
empty {},
empty {},
empty {},
empty {},
empty {},
empty {},
empty {},
empty {},
empty {},
empty {}
}
};
#endif
/* Menu bars */
resource rMenuBar (MENU_BAR) {
@ -237,7 +269,7 @@ resource rPString (HELLO_WORLD_STRING, noCrossBank) {"Hello, world!"};
/* Alert strings */
resource rAlertString (ABOUT_ALERT_STRING) {
"0" /* Custom size */
#if RES_MODE == 320
#if DESKTOP_RES_MODE == 320
"\$38\$00" /* Upper Y coordinate at 56 */
"\$10\$00" /* Left X coordinate at 16 */
"\$90\$00" /* Lower Y coorinate at 144 */
@ -288,7 +320,7 @@ resource rWindParam1 (WINDOW_RESID) {
{0, 0}, /* page ver horiz */
0, /* winfoRefCon */
10, /* wInfoHeight */
#if RES_MODE == 320
#if DESKTOP_RES_MODE == 320
{30, 10, 183, 300}, /* wposition */
#else
{30, 10, 183, 602}, /* wposition */
@ -302,7 +334,7 @@ resource rWindParam1 (WINDOW_RESID) {
/* Controls */
resource rControlTemplate (CONTROL_TEXT_EDIT) {
CONTROL_TEXT_EDIT, /* Application defined ID */
#if RES_MODE == 320
#if DESKTOP_RES_MODE == 320
{0,0,165,300}, /* Bounding rectangle */
#else
{0,0,165,620}, /* Bounding rectangle */
@ -339,7 +371,7 @@ resource rControlTemplate (CONTROL_TEXT_EDIT) {
/* Tools */
resource rToolStartup (TOOL_STARTUP) {
#if RES_MODE == 320
#if DESKTOP_RES_MODE == 320
mode320,
#else
mode640,

View File

@ -136,7 +136,7 @@
<key>Name</key>
<string>Desktop Resolution</string>
<key>Description</key>
<string>Specify 640 or 320 pixel desktop enviroment.</string>
<string>Specify 640x200 or 320x200 resolution desktop enviroment.</string>
<key>Type</key>
<string>popup</string>
<key>Default</key>

View File

@ -35,10 +35,6 @@
#define toolStartup 1
/* By default, thie template builds for 640x200 mode. To build for
* 320x200 change the following value to 320 */
#define RES_MODE ___VARIABLE_RESOLUTIONMODE___
resource rVersion (1) {
{
@ -220,7 +216,7 @@ resource rPString (appleAbout, noCrossBank) {"About ___PROJECTNAME___..."};
resource rAlertString (aboutAlertString) {
"0" /* Custom size */
#if RES_MODE == 320
#if DESKTOP_RES_MODE == 320
"\$38\$00" /* Upper Y coordinate at 56 */
"\$10\$00" /* Left X coordinate at 16 */
"\$90\$00" /* Lower Y coorinate at 144 */
@ -256,7 +252,7 @@ resource rWindParam1 (windowRes) {
{0, 0}, /* page ver horiz */
0, /* winfoRefCon */
10, /* wInfoHeight */
#if RES_MODE == 320
#if DESKTOP_RES_MODE == 320
{30, 10, 183, 300}, /* wposition */
#else
{30, 10, 183, 602}, /* wposition */
@ -268,7 +264,7 @@ resource rWindParam1 (windowRes) {
resource rToolStartup (toolStartup) {
#if RES_MODE == 320
#if DESKTOP_RES_MODE == 320
mode320,
#else
mode640,

View File

@ -9,28 +9,42 @@ cp -R pkg/Plug-ins $TMPDIR
PROJECTS=/tmp/projects.$$
cat > $PROJECTS << EOF
cda:orca:ORCAC Classic Desk Accessory
cda:orca:ORCAM Classic Desk Accessory
cdev:orca:ORCAC Control Panel
cdev:orca:ORCAM Control Panel
desktop:orca:ORCAC Desktop Application
desktop:orca:ORCAM Desktop Application
shell:gno:ORCAC GNO Shell Command
nda:orca:ORCAC New Desk Accessory
nda:orca:ORCAM New Desk Accessory
shell:orca:ORCAC Shell Command
shell:orca:ORCAM Shell Command
cda:orca:ORCAC Classic Desk Accessory:0:0
cda:orca:ORCAM Classic Desk Accessory:0:0
cdev:orca:ORCAC Control Panel:0:0
cdev:orca:ORCAM Control Panel:0:0
desktop:orca:ORCAC Desktop Application:1:1
desktop:orca:ORCAM Desktop Application:1:0
shell:gno:ORCAC GNO Shell Command:0:0
nda:orca:ORCAC New Desk Accessory:0:0
nda:orca:ORCAM New Desk Accessory:0:0
shell:orca:ORCAC Shell Command:0:0
shell:orca:ORCAM Shell Command:0:0
EOF
while read PROJECT
do
PROJECTTYPE=`echo $PROJECT | awk -F: '{print $1}'`
SHELLTYPE=`echo $PROJECT | awk -F: '{print $2}'`
PROJECTNAME=`echo $PROJECT | awk -F: '{print $3}'`
PROJECT_TYPE=`echo $PROJECT | awk -F: '{print $1}'`
SHELL_TYPE=`echo $PROJECT | awk -F: '{print $2}'`
PROJECT_NAME=`echo $PROJECT | awk -F: '{print $3}'`
SUPPORTS_RES_MODE=`echo $PROJECT | awk -F: '{print $4}'`
SUPPORTS_MESSAGE_CENTER=`echo $PROJECT | awk -F: '{print $5}'`
sed "
/^# TARGETTYPE=${PROJECTTYPE}/s/^# //
/^# export ORCA=.*\/${SHELLTYPE}$/s/^# //" Makefile > "${TMPDIR}/Templates/Apple IIgs/${PROJECTNAME}.xctemplate/Makefile"
cp -R make "${TMPDIR}/Templates/Apple IIgs/${PROJECTNAME}.xctemplate/"
/^# TARGETTYPE=${PROJECT_TYPE}/s/^# //
/^# export ORCA=.*\/${SHELL_TYPE}$/s/^# //" Makefile > "${TMPDIR}/Templates/Apple IIgs/${PROJECT_NAME}.xctemplate/Makefile"
if [ "$SUPPORTS_RES_MODE" -eq 1 ]
then
sed -i "" 's/^# DESKTOP_RES_MODE=.*$/DESKTOP_RES_MODE=___VARIABLE_RESOLUTIONMODE___/' "${TMPDIR}/Templates/Apple IIgs/${PROJECT_NAME}.xctemplate/Makefile"
fi
if [ "$SUPPORTS_MESSAGE_CENTER" -eq 1 ]
then
sed -i "" 's/^# MESSAGE_CENTER=.*$/MESSAGE_CENTER=___VARIABLE_MESSAGECENTER___/' "${TMPDIR}/Templates/Apple IIgs/${PROJECT_NAME}.xctemplate/Makefile"
fi
cp -R make "${TMPDIR}/Templates/Apple IIgs/${PROJECT_NAME}.xctemplate/"
done < $PROJECTS
rm -f $PROJECTS