2
This file is part of the Free Pascal run time library.
3
Copyright (c) 2002-2004 by Olle Raab
5
FreePascal system unit for MacOS.
7
See the file COPYING.FPC, included in this distribution,
8
for details about the copyright.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
**********************************************************************}
19
{ include system-independent routine headers }
25
DirectorySeparator = ':';
27
PathSeparator = ','; {Is used in MPW and OzTeX}
28
FileNameCaseSensitive = false;
29
CtrlZMarksEOF: boolean = false; (* #26 not considered as end of file *)
35
{ Default filehandles }
36
UnusedHandle : Longint = -1;
37
StdInputHandle : Longint = 0;
38
StdOutputHandle : Longint = 1;
39
StdErrorHandle : Longint = 2;
41
sLineBreak = LineEnding;
42
DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCR;
51
{*********************************}
52
{** MacOS specific functions **}
53
{*********************************}
55
{To be called at regular intervals, for lenghty tasks.
56
Yield might give time for other tasks to run under the cooperative
57
multitasked macos. For an MPW Tool, it also spinns the cursor.}
61
{To set mac file type and creator codes, to be used for files created
62
by the FPC runtime library. They must be exactly 4 chars long.}
64
procedure SetDefaultMacOSFiletype(ftype: ShortString);
65
procedure SetDefaultMacOSCreator(creator: ShortString);
68
{Whether unix and dos style paths should be translated. Default false}
69
pathTranslation: Boolean;
72
{*********************************}
73
{** Available features on macos **}
74
{*********************************}
78
macosHasGestalt: Boolean;
79
macosHasWaitNextEvent: Boolean;
80
macosHasColorQD: Boolean;
82
macosSystemVersion: Integer;
83
macosHasSysDebugger: Boolean = false;
86
macosHasAppleEvents: Boolean;
87
macosHasAliasMgr: Boolean;
90
macosHasFSSpec: Boolean;
91
macosHasFindFolder: Boolean;
94
macosHasScriptMgr: Boolean;
95
macosNrOfScriptsInstalled: Integer;
97
macosHasAppearance: Boolean;
98
macosHasAppearance101: Boolean;
99
macosHasAppearance11: Boolean;
101
macosBootVolumeVRefNum: Integer;
102
macosBootVolumeName: String[31];
107
MacOS directory separator is a colon ":" which is the only character not
108
allowed in filenames.
109
A path containing no colon or which begins with a colon is a partial path.
110
E g ":kalle:petter" ":kalle" "kalle"
111
All other paths are full (absolute) paths. E g "HD:kalle:" "HD:"
112
When generating paths, one is safe is one ensures that all partial paths
113
begins with a colon, and all full paths ends with a colon.
114
In full paths the first name (e g HD above) is the name of a mounted volume.
115
These names are not unique, because, for instance, two diskettes with the
116
same names could be inserted. This means that paths on MacOS is not
117
waterproof. In case of equal names the first volume found will do.
118
Two colons "::" are the relative path to the parent. Three is to the
125
About the implementation
126
========================
127
A MacOS application is assembled and linked by MPW (Macintosh
128
Programmers Workshop), which nowadays is free to use. For info
129
and download of MPW and MacOS api, see www.apple.com
131
It can be linked to either a graphical user interface application,
132
a standalone text only application (using SIOW) or
133
to an MPW tool, this is entirely controlled by the linking step.
135
It requires system 7 and CFM, which is always the case for PowerPC.
137
If a m68k version would be implemented, it would save a lot
138
of efforts if it also uses CFM. This System.pp should, with
139
minor modifications, probably work with m68k.
141
Initial working directory is the directory of the application,
142
or for an MPWTool, the working directory as set by the
143
Directory command in MPW.
145
Note about working directory. There is a facility in MacOS which
146
manages a working directory for an application, initially set to
147
the applications directory, or for an MPWTool, the tool's directory.
148
However, this requires the application to have a unique application
149
signature (creator code), to distinguish its working directory
150
from working directories of other applications. Due to the fact
151
that casual applications are anonymous in this sense (without an
152
application signature), this facility will not work. Also, this
153
working directory facility is not present in Carbon. Hence we
154
will manage a working directory by our self.
160
In current implementation, working directory is stored as
161
directory id. This means there is a possibility the user moves the
162
working directory or a parent to it, while the application uses it.
163
Then the path to the wd suddenly changes. This is AFAIK not in
164
accordance with other OS's. Although this is a minor caveat,
165
it is mentioned here. To overcome this the wd could be stored
166
as a path instead, but this imposes translations from fullpath
167
to directory ID each time the filesystem is accessed.
169
The initial working directory for an MPWTool, as considered by
170
FPC, is different from the MacOS working directory facility,
174
Possible improvements:
175
=====================
177
Perhaps handle readonly filesystems, as in sysunix.inc
181
{******** include system independent routines **********}
185
{*****************************************************************************
187
*****************************************************************************}
190
function paramcount : longint;
192
paramcount := argc - 1;
196
{ argument number l }
197
function paramstr(l : longint) : string;
199
if (l>=0) and (l+1<=argc) then
200
paramstr:=strpas(argv[l])
205
{ set randseed to a new pseudo random value }
208
randseed:= Cardinal(TickCount);
212
{*****************************************************************************
213
SystemUnit Initialization
214
*****************************************************************************}
216
{$ifndef FPC_DARWIN_PASCALMAIN}
217
procedure pascalmain; external name 'PASCALMAIN';
219
{Main entry point in C style, needed to capture program parameters.
220
For this to work, the system unit must be before the main program
221
in the linking order.}
222
procedure main(argcparam: Longint; argvparam: ppchar; envpparam: ppchar); cdecl; [public];
223
{$else FPC_DARWIN_PASCALMAIN}
224
procedure FPC_SYSTEMMAIN(argcparam: Longint; argvparam: ppchar; envpparam: ppchar); cdecl; [public];
225
{$endif FPC_DARWIN_PASCALMAIN}
231
{$ifndef FPC_DARWIN_PASCALMAIN}
232
pascalmain; {run the pascal main program}
233
{$endif FPC_DARWIN_PASCALMAIN}
236
procedure setup_arguments;
238
{Nothing needs to be done here.}
241
procedure setup_environment;
246
{ FindSysFolder returns the (real) vRefNum, and the DirID of the current
247
system folder. It uses the Folder Manager if present, otherwise it falls
248
back to SysEnvirons. It returns zero on success, otherwise a standard
251
function FindSysFolder(var foundVRefNum: Integer; var foundDirID: Longint): OSErr;
254
gesResponse: Longint;
264
and (Gestalt (FourCharCodeToLongword(gestaltFindFolderAttr), gesResponse) = noErr)
265
and BitIsSet (gesResponse, gestaltFindFolderPresent) then
266
begin { Does Folder Manager exist? }
267
err := FindFolder (kOnSystemDisk, FourCharCodeToLongword(kSystemFolderType),
268
kDontCreateFolder, foundVRefNum, foundDirID);
272
{ Gestalt can't give us the answer, so we resort to SysEnvirons }
273
err := SysEnvirons (curSysEnvVers, envRec);
274
if (err = noErr) then
276
myWDPB.ioVRefNum := envRec.sysVRefNum;
278
myWDPB.ioNamePtr := @volName;
279
myWDPB.ioWDIndex := 0;
280
myWDPB.ioWDProcID := 0;
281
err := PBGetWDInfoSync (@myWDPB);
282
if (err = noErr) then
284
foundVRefNum := myWDPB.ioWDVRefNum;
285
foundDirID := myWDPB.ioWDDirID;
292
procedure InvestigateSystem;
296
_GestaltDispatch = $A0AD;
297
_WaitNextEvent = $A860;
300
qdOffscreenTrap = $AB1D;
310
{Vi r�knar med att man k�r p� minst system 6.0.5. D� finns b�de Gestalt och GDevice med.}
311
{Enligt Change Histrory �r MacOS 6.0.5 mera konsistent mellan maskinmodellerna �n f�reg�ende system}
315
macosHasGestalt := TrapAvailable(_GestaltDispatch);
317
macosHasGestalt := true; {There is always Gestalt on PowerPC}
320
if not macosHasGestalt then (* If we don't have Gestalt, then we can't have any System 7 features *)
323
{ Detta kan endast g�lla p� en 68K maskin.}
324
macosHasScriptMgr := TrapAvailable(_ScriptUtil);
326
macosNrOfScriptsInstalled := 1; (* assume only Roman script, to start with *)
328
err := SysEnvirons(1, environs);
331
if environs.machineType < 0 then { gammalt ROM}
332
macosHasWaitNextEvent := FALSE
334
macosHasWaitNextEvent := TrapAvailable(_WaitNextEvent);
335
macosHasColorQD := environs.hasColorQD;
336
macosHasFPU := environs.hasFPU;
337
macosSystemVersion := environs.systemVersion;
341
macosHasWaitNextEvent := FALSE;
342
macosHasColorQD := FALSE;
343
macosHasFPU := FALSE;
344
macosSystemVersion := 0;
347
macosHasSysDebugger := (LongintPtr(MacJmp)^ <> 0);
349
macosHasCFM := false;
350
macosHasAppleEvents := false;
351
macosHasAliasMgr := false;
353
macosHasFSSpec := false;
354
macosHasFindFolder := false;
356
macosHasAppearance := false;
357
macosHasAppearance101 := false;
358
macosHasAppearance11 := false;
359
{$IFDEF THINK_PASCAL}
360
if (macosHasScriptMgr) then
361
macosNrOfScriptsInstalled := GetEnvirons(smEnabled);
363
if (macosHasScriptMgr) then
364
macosNrOfScriptsInstalled := GetScriptManagerVariable(smEnabled); {Gamla rutinnamnet var GetEnvirons.}
370
macosHasScriptMgr := Gestalt(FourCharCodeToLongword(gestaltScriptMgrVersion), response) = noErr; {F�r att ta reda p� om script mgr finns.}
371
macosNrOfScriptsInstalled := 1; (* assume only Roman script, to start with *)
372
macosHasWaitNextEvent := true;
374
if Gestalt(FourCharCodeToLongword(gestaltSystemVersion), response) = noErr then
375
macosSystemVersion := response
377
macosSystemVersion := 0; {Borde inte kunna h�nda.}
379
if Gestalt(FourCharCodeToLongword(gestaltOSAttr), response) = noErr then
380
macosHasSysDebugger := BitIsSet(response, gestaltSysDebuggerSupport)
382
macosHasSysDebugger := false;
384
if Gestalt(FourCharCodeToLongword(gestaltQuickdrawVersion), response) = noErr then
385
macosHasColorQD := (response >= $0100)
387
macosHasColorQD := false;
389
if Gestalt(FourCharCodeToLongword(gestaltFPUType), response) = noErr then
390
macosHasFPU := (response <> gestaltNoFPU)
392
macosHasFPU := false;
394
if Gestalt(FourCharCodeToLongword(gestaltCFMAttr), response) = noErr then
395
macosHasCFM := BitIsSet(response, gestaltCFMPresent)
397
macosHasCFM := false;
399
macosHasAppleEvents := Gestalt(FourCharCodeToLongword(gestaltAppleEventsAttr), response) = noErr;
400
macosHasAliasMgr := Gestalt(FourCharCodeToLongword(gestaltAliasMgrAttr), response) = noErr;
402
if Gestalt(FourCharCodeToLongword(gestaltFSAttr), response) = noErr then
403
macosHasFSSpec := BitIsSet(response, gestaltHasFSSpecCalls)
405
macosHasFSSpec := false;
406
macosHasFindFolder := Gestalt(FourCharCodeToLongword(gestaltFindFolderAttr), response) = noErr;
408
if macosHasScriptMgr then
410
err := Gestalt(FourCharCodeToLongword(gestaltScriptCount), response);
411
if (err = noErr) then
412
macosNrOfScriptsInstalled := Integer(response);
415
if (Gestalt(FourCharCodeToLongword(gestaltAppearanceAttr), response) = noErr) then
417
macosHasAppearance := BitIsSet(response, gestaltAppearanceExists);
418
if Gestalt(FourCharCodeToLongword(gestaltAppearanceVersion), response) = noErr then
420
macosHasAppearance101 := (response >= $101);
421
macosHasAppearance11 := (response >= $110);
426
macosHasAppearance := false;
427
macosHasAppearance101 := false;
428
macosHasAppearance11 := false;
433
{*****************************************************************************
434
System Dependent Exit code
435
*****************************************************************************}
437
Procedure system_exit;
441
if StandAlone <> 0 then
442
if exitcode <> 0 then
446
Writeln( '### Program exited with exit code ' + s)
447
else if macosHasSysDebugger then
448
DebugStr('A possible error occured, exit code: ' + s + '. Type "g" and return to continue.')
453
{$ifndef MACOS_USE_STDCLIB}
454
if StandAlone <> 0 then
457
c_exit(exitcode); {exitcode is only utilized by an MPW tool}
461
procedure SysInitStdIO;
463
{ Setup stdin, stdout and stderr }
464
{$ifdef MACOS_USE_STDCLIB}
465
OpenStdIO(Input,fmInput,StdInputHandle);
466
OpenStdIO(Output,fmOutput,StdOutputHandle);
467
OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
468
OpenStdIO(StdOut,fmOutput,StdOutputHandle);
469
OpenStdIO(StdErr,fmOutput,StdErrorHandle);
473
function GetProcessID: SizeUInt;
476
{$WARNING To be implemented - using GetProcessInformation???}
479
function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
486
isFolder, hadAlias, leafIsAlias: Boolean;
489
dummySysFolderDirID: Longint;
492
InvestigateSystem; {Must be first}
494
{Check requred features for system.pp to work.}
495
if not macosHasFSSpec then
496
Halt(3); //exit code 3 according to MPW
498
if FindSysFolder(macosBootVolumeVRefNum, dummySysFolderDirID) <> noErr then
499
Halt(3); //exit code 3 according to MPW
501
if GetVolumeName(macosBootVolumeVRefNum, macosBootVolumeName) <> noErr then
502
Halt(3); //exit code 3 according to MPW
504
{ To be set if this is a GUI or console application }
505
if StandAlone = 0 then
506
IsConsole := true {Its an MPW tool}
509
resHdl:= Get1Resource(FourCharCodeToLongword('siow'),0);
510
IsConsole := (resHdl <> nil); {A SIOW app is also a console}
511
ReleaseResource(resHdl);
514
{ To be set if this is a library and not a program }
517
StackLength := CheckInitialStkLen(InitialStkLen);
518
StackBottom := SPtr - StackLength;
519
pathTranslation:= false;
521
{ Setup working directory }
522
if StandAlone <> 0 then
524
if not GetAppFileLocation(workingDirectorySpec) then
525
Halt(3); //exit code 3 according to MPW
529
{ The fictive file x is used to make
530
FSMakeFSSpec return a FSSpec to a file in the directory.
531
Then by clearing the name, the FSSpec then
532
points to the directory. It doesn't matter whether x exists or not.}
534
err:= ResolveFolderAliases(0, 0, @dirStr, true,
535
workingDirectorySpec, isFolder, hadAlias, leafIsAlias);
536
workingDirectorySpec.name:='';
537
if (err <> noErr) and (err <> fnfErr) then
538
Halt(3); //exit code 3 according to MPW
542
if StandAlone <> 0 then
549
{ Setup environment and arguments }
557
initwidestringmanager;
559
if StandAlone = 0 then
561
InitGraf(@qd.thePort);
562
SetFScaleDisable(true);