mirror of
https://github.com/autc04/Retro68.git
synced 2024-12-22 19:30:36 +00:00
8f68ffd203
Specify parameters for all C functions. Not specifying parameters is the same as specifying "void" in C++ and in C23 and later but that's not the case in C prior to C23. Compile C files with the same warnings as C++ files, additionally making the strict prototypes warning an error to catch such problems in the future. This commit isn't intended to address all the other warnings now being emitted.
305 lines
7.9 KiB
C
305 lines
7.9 KiB
C
/*
|
|
Copyright 2017 Wolfgang Thaller.
|
|
|
|
This file is part of Retro68.
|
|
|
|
Retro68 is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Retro68 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Retro68. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <Quickdraw.h>
|
|
#include <Windows.h>
|
|
#include <Menus.h>
|
|
#include <Fonts.h>
|
|
#include <Resources.h>
|
|
#include <TextEdit.h>
|
|
#include <TextUtils.h>
|
|
#include <Dialogs.h>
|
|
#include <Devices.h>
|
|
|
|
// in wdef.c
|
|
extern pascal long MyWindowDefProc(short varCode, WindowRef window, short message, long param);
|
|
|
|
static Rect initialWindowRect, nextWindowRect;
|
|
|
|
enum
|
|
{
|
|
kMenuApple = 128,
|
|
kMenuFile,
|
|
kMenuEdit
|
|
};
|
|
|
|
enum
|
|
{
|
|
kItemAbout = 1,
|
|
|
|
kItemNewDoc = 1,
|
|
kItemNewRounded = 2,
|
|
kItemNewCustomFromStub = 3,
|
|
kItemNewCustomFromRes = 4,
|
|
kItemClose = 5,
|
|
kItemQuit = 7
|
|
};
|
|
|
|
void MakeNewWindow(ConstStr255Param title, short procID)
|
|
{
|
|
if(nextWindowRect.bottom > qd.screenBits.bounds.bottom
|
|
|| nextWindowRect.right > qd.screenBits.bounds.right)
|
|
{
|
|
nextWindowRect = initialWindowRect;
|
|
}
|
|
|
|
WindowRef w = NewWindow(NULL, &nextWindowRect, title, true, procID, (WindowPtr) -1, true, 0);
|
|
|
|
OffsetRect(&nextWindowRect, 15, 15);
|
|
}
|
|
|
|
void InitCustomWDEF(void)
|
|
{
|
|
/* The 10-byte code resource stub trick.
|
|
*
|
|
* The bytes in this resource are 68K machine code for
|
|
* move.l L1(pc), -(sp) | 2F3A 0004
|
|
* rts | 4E75
|
|
* L1: dc.l 0x00000000 | 0000 0000
|
|
*
|
|
* The application loads this resource and replaces the final four bytes
|
|
* with the address of MyWindowDefProc.
|
|
*/
|
|
|
|
Handle h = GetResource('WDEF', 128);
|
|
HLock(h);
|
|
*(WindowDefUPP*)(*h + 6) = NewWindowDefUPP(&MyWindowDefProc);
|
|
// note: for 68K, the above is equivalent to:
|
|
// *(WindowDefProcPtr*)(*h + 6) = &MyWindowDefProc;
|
|
// for PPC, it creates a routine descriptor data structure to get out of the emulator again.
|
|
|
|
// On PPC only, we could also bypass the emulator by putting the routine descriptor into the resource,
|
|
// and putting the pointer to the code into it here. This wouldn't work for the 68K version of this code, though.
|
|
|
|
// By the way, this was the only part of this file relevant for dealing
|
|
// with custom WDEFs.
|
|
}
|
|
|
|
void ShowAboutBox(void)
|
|
{
|
|
WindowRef w = GetNewWindow(128, NULL, (WindowPtr) - 1);
|
|
MoveWindow(w,
|
|
qd.screenBits.bounds.right/2 - w->portRect.right/2,
|
|
qd.screenBits.bounds.bottom/2 - w->portRect.bottom/2,
|
|
false);
|
|
ShowWindow(w);
|
|
SetPort(w);
|
|
|
|
Handle h = GetResource('TEXT', 128);
|
|
HLock(h);
|
|
Rect r = w->portRect;
|
|
InsetRect(&r, 10,10);
|
|
TETextBox(*h, GetHandleSize(h), &r, teJustLeft);
|
|
|
|
ReleaseResource(h);
|
|
while(!Button())
|
|
;
|
|
while(Button())
|
|
;
|
|
FlushEvents(everyEvent, 0);
|
|
DisposeWindow(w);
|
|
}
|
|
|
|
void UpdateMenus(void)
|
|
{
|
|
MenuRef m = GetMenu(kMenuFile);
|
|
WindowRef w = FrontWindow();
|
|
if(w) // Close menu item: enabled if there is a window
|
|
EnableItem(m,kItemClose);
|
|
else
|
|
DisableItem(m,kItemClose);
|
|
|
|
m = GetMenu(kMenuEdit);
|
|
if(w && GetWindowKind(w) < 0)
|
|
{
|
|
// Desk accessory in front: Enable edit menu items
|
|
EnableItem(m,1);
|
|
EnableItem(m,3);
|
|
EnableItem(m,4);
|
|
EnableItem(m,5);
|
|
EnableItem(m,6);
|
|
}
|
|
else
|
|
{
|
|
// Application window or nothing in front, disable edit menu
|
|
DisableItem(m,1);
|
|
DisableItem(m,3);
|
|
DisableItem(m,4);
|
|
DisableItem(m,5);
|
|
DisableItem(m,6);
|
|
}
|
|
|
|
}
|
|
|
|
void DoMenuCommand(long menuCommand)
|
|
{
|
|
Str255 str;
|
|
WindowRef w;
|
|
short menuID = menuCommand >> 16;
|
|
short menuItem = menuCommand & 0xFFFF;
|
|
if(menuID == kMenuApple)
|
|
{
|
|
if(menuItem == kItemAbout)
|
|
ShowAboutBox();
|
|
else
|
|
{
|
|
GetMenuItemText(GetMenu(128), menuItem, str);
|
|
OpenDeskAcc(str);
|
|
}
|
|
}
|
|
else if(menuID == kMenuFile)
|
|
{
|
|
switch(menuItem)
|
|
{
|
|
case kItemNewDoc:
|
|
GetIndString(str,128,1);
|
|
MakeNewWindow(str, documentProc); // plain document window
|
|
break;
|
|
case kItemNewRounded:
|
|
GetIndString(str,128,2);
|
|
MakeNewWindow(str, 16); // rounded document window
|
|
break;
|
|
case kItemNewCustomFromStub:
|
|
GetIndString(str,128,3);
|
|
MakeNewWindow(str, 128*16); // custom window, loaded via 10-byte stub
|
|
break;
|
|
case kItemNewCustomFromRes:
|
|
GetIndString(str,128,4);
|
|
MakeNewWindow(str, 129*16); // custom window, compiled as resource
|
|
break;
|
|
|
|
case kItemClose: // close
|
|
w = FrontWindow();
|
|
if(w)
|
|
{
|
|
if(GetWindowKind(w) < 0)
|
|
CloseDeskAcc(GetWindowKind(w));
|
|
else
|
|
DisposeWindow(FrontWindow());
|
|
}
|
|
break;
|
|
|
|
case kItemQuit:
|
|
ExitToShell();
|
|
break;
|
|
}
|
|
}
|
|
else if(menuID == kMenuEdit)
|
|
{
|
|
if(!SystemEdit(menuItem - 1))
|
|
{
|
|
// edit command not handled by desk accessory
|
|
}
|
|
}
|
|
|
|
HiliteMenu(0);
|
|
}
|
|
|
|
void DoUpdate(WindowRef w)
|
|
{
|
|
SetPort(w);
|
|
BeginUpdate(w);
|
|
|
|
Rect r;
|
|
SetRect(&r, 20,20,120,120);
|
|
FrameOval(&r);
|
|
|
|
OffsetRect(&r, 32, 32);
|
|
FillRoundRect(&r, 16, 16, &qd.ltGray);
|
|
FrameRoundRect(&r, 16, 16);
|
|
|
|
OffsetRect(&r, 32, 32);
|
|
FillRect(&r, &qd.gray);
|
|
FrameRect(&r);
|
|
|
|
MoveTo(100,100);
|
|
DrawString("\pHello, world.");
|
|
|
|
EndUpdate(w);
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
InitGraf(&qd.thePort);
|
|
InitFonts();
|
|
InitWindows();
|
|
InitMenus();
|
|
TEInit();
|
|
InitDialogs(NULL);
|
|
|
|
SetMenuBar(GetNewMBar(128));
|
|
AppendResMenu(GetMenu(128), 'DRVR');
|
|
DrawMenuBar();
|
|
|
|
InitCustomWDEF();
|
|
|
|
InitCursor();
|
|
|
|
Rect r;
|
|
SetRect(&initialWindowRect,20,60,400,260);
|
|
nextWindowRect = initialWindowRect;
|
|
|
|
for(;;)
|
|
{
|
|
EventRecord e;
|
|
WindowRef win;
|
|
|
|
SystemTask();
|
|
if(GetNextEvent(everyEvent, &e))
|
|
{
|
|
switch(e.what)
|
|
{
|
|
case keyDown:
|
|
if(e.modifiers & cmdKey)
|
|
{
|
|
UpdateMenus();
|
|
DoMenuCommand(MenuKey(e.message & charCodeMask));
|
|
}
|
|
break;
|
|
case mouseDown:
|
|
switch(FindWindow(e.where, &win))
|
|
{
|
|
case inGoAway:
|
|
if(TrackGoAway(win, e.where))
|
|
DisposeWindow(win);
|
|
break;
|
|
case inDrag:
|
|
DragWindow(win, e.where, &qd.screenBits.bounds);
|
|
break;
|
|
case inMenuBar:
|
|
UpdateMenus();
|
|
DoMenuCommand( MenuSelect(e.where) );
|
|
break;
|
|
case inContent:
|
|
SelectWindow(win);
|
|
break;
|
|
case inSysWindow:
|
|
SystemClick(&e, win);
|
|
break;
|
|
}
|
|
break;
|
|
case updateEvt:
|
|
DoUpdate((WindowRef)e.message);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|