-- Subr.Mesa, last edit February 9, 1983 10:57 am
-- General purpose procedures
-- the Implementor is SubrImpl.Mesa

DIRECTORY
  File: TYPE USING [Capability, delete, grow, Permissions, read, shrink, write],
  IO: TYPE USING[Handle],
  Rope: TYPE USING[ROPE],
  Space: TYPE USING [Handle],
  Stream: TYPE USING [Handle];

Subr: DEFINITIONS = {


-- GLOBAL VARIABLES (defined in SubrImpl, initialized by starting)
errorflg, debugflg: BOOL;
numberofleaders: CARDINAL;

-- SIGNALS
FileErrorType: TYPE = {notFound, wrongVersion};
FileError: ERROR[error: FileErrorType];
AbortMyself: SIGNAL;	-- raised usually by something that checks
			-- UserInput.userAbort

-- TYPES
PackedTime: TYPE = LONG CARDINAL;	-- instead of System.GreenwichMeanTime

TTYProcs: TYPE = REF TTYProcsRecord;
TTYProcsRecord: TYPE = RECORD[
	in: IO.Handle,	-- an input stream, possibly edited
	out: IO.Handle,	-- an output stream
	data: REF ANY,	-- narrows to UserExec.ExecHandle or ViewerClasses.Viewer
	Confirm: PROC[in, out: IO.Handle, data: REF ANY, msg: Rope.ROPE, dch: CHAR]
		RETURNS[CHAR]
	];

-- CONSTANTS
Read: File.Permissions = File.read;
Write: File.Permissions = File.write + File.grow + File.shrink + File.delete;
ReadWrite: File.Permissions = Read + Write;

-- PROGRAMS (defined in SubrImpl)
-- does not need to be explicitly started
SubrImpl: PROGRAM;

-- PROCS (defined in SubrImpl)

MakeTTYProcs: PROC[in, out: IO.Handle, data: REF ANY, 
		Confirm: PROC[in, out: IO.Handle, data: REF ANY, msg: Rope.ROPE, dch: CHAR]
			RETURNS[CHAR]] 
	RETURNS[h: TTYProcs];
	
--******
-- LONG STRINGS
-- allocate a long string
AllocateString: PROC[nchars: CARDINAL, zone: UNCOUNTED ZONE ← NIL] RETURNS[LONG STRING];
-- free the string
FreeString: PROC[str: LONG STRING, zone: UNCOUNTED ZONE ← NIL];
-- allocate a long pointer
AllocateWords: PROC[nwords: CARDINAL] RETURNS[LONG POINTER];
-- free the long pointer
FreeWords: PROC[LONG POINTER];
-- like Storage.CopyString, if zone is NIL then uses Subr.LongZone[]
CopyString: PROC[sold: LONG STRING, zone: UNCOUNTED ZONE ← NIL] 
	RETURNS[snew: LONG STRING];

-- string operations on long pointers
-- copy a string
strcpy: PROC[sto, sfrom: LONG STRING];

-- from CharIO.GetID
GetID: PROC [in: Stream.Handle, s: LONG STRING];


-- can also be used if sto and sfrom point to the same StringBody
SubStrCopy: PROC[sto, sfrom: LONG STRING, sfinx: CARDINAL];
-- removes leading blanks and TABS from str
StripLeadingBlanks: PROC[str: LONG STRING];


--******
-- PREDICATES:

-- TRUE if any char in str is = ch
Any: PROC[str: LONG STRING, ch: CHAR] RETURNS[BOOL];

-- TRUE if str ends in suf, case is ignored
EndsIn: PROC[str, suf: LONG STRING] RETURNS[BOOL];

-- TRUE if str begins with pref, case is ignored
Prefix: PROC[str, pref: LONG STRING] RETURNS[BOOL];

-- TRUE is str has control chars in it
ControlChars: PROC[str: LONG STRING] RETURNS[BOOL];

-- Miscellaneous:


--******
-- ZONES.

-- there are three zones here:
--	1) a standard 256 page Heap zone (LongZone)
--	2) an arbitrary-sixed sone where FREE's are no-ops (HugeZone)
--	3) a zone that allocates each item in a separate space (SpaceZone)

-- LONG ZONE stuff

-- get a zone, call this as many times as you like
-- but you will get only ONE long zone
LongZone: PROC RETURNS[UNCOUNTED ZONE];

-- call to set up a zone initially
-- npages is the # pages in the spce to be allocated 
-- npages should be more than the total # pages yuou'll allocated thru
-- the long zone
SubrInit: PROC[npages: CARDINAL];

-- call to free the zone.  All the memory within the zone must have
-- already been freed
SubrStop: PROC;

-- HUGE ZONE stuff
-- get a zone, call this as many times as you like
-- but you will get only ONE huge zone, FREE operations are NOOPs
HugeZone: PROC RETURNS[UNCOUNTED ZONE];

-- allocates large # words from the huge zone
WordsFromHugeZone: PROC[zone: UNCOUNTED ZONE, nwords: LONG CARDINAL] RETURNS[LONG POINTER];

-- returns # pages used in HugeZone so far
PagesUsedInHugeZone: PROC[zone: UNCOUNTED ZONE] RETURNS[npages: CARDINAL];

-- use with care: be sure there are no outstanding pointers in to the huge zone
-- this always returns NIL
FreeHugeZone: PROC[zone: UNCOUNTED ZONE] RETURNS[UNCOUNTED ZONE];


-- SPACE ZONE stuff
SpaceZone: PROC RETURNS[UNCOUNTED ZONE];

-- file operations

-- For simulating useful functions, difficult to do directly

EnumerateDirectory: PROC [proc: PROC [File.Capability, STRING] RETURNS [BOOL]];

NewStream: PROC [name: LONG STRING, access: File.Permissions] 
	RETURNS [Stream.Handle];

-- npages should not include the leader page;  I'll add +1
NewFile: PROC[name: LONG STRING, access: File.Permissions, npages: CARDINAL]
	RETURNS[File.Capability];
	
-- if h is NIL then uses Exec.w
CheckForModify: PROC[file: LONG STRING, h: TTYProcs] 
	RETURNS[oktomodify: BOOL];

-- if h is NIL then gets the window that Exec.w is in
-- this always returns FALSE in viewers
CursorInWindow: PROC[h: TTYProcs] RETURNS[BOOL];

FindMappedSpace: PROC[space: Space.Handle] RETURNS [Space.Handle];

-- get create date (sets numberofleaders also)
-- just calls FileStream.GetLeaderPropertiesForCapability, but
-- increments numberofleaders
GetCreateDate: PROC[cap: File.Capability] RETURNS[create: LONG CARDINAL];
GetCreateDateWithSpace: PROC[cap: File.Capability, space: Space.Handle] 
	RETURNS[create: LONG CARDINAL];


-- because of bugs in Exec.GetNameandPassword
-- if h is NIL, then uses Exec.w
-- if nt = login, then GetNameandPassword uses Profile.userName
--  othewise uses name2, password2
NameType: TYPE = {login, connect};
GetNameandPassword: PROC[nt: NameType, name2, password2: LONG STRING ← NIL, 
	h: TTYProcs];

-- remote filename property mgmt
-- maxlength of remotename MUST = 125
GetRemoteFilenameProp: PROC[cap: File.Capability, remotename: LONG STRING];
-- WARNING THIS CHANGES THE CREATE DATE if the capabilities permissions
-- are not Directory.ignore
-- maxlength of remotename MUST = 125
SetRemoteFilenameProp: PROC[cap: File.Capability, remotename: LONG STRING];

-- print greeting
PrintGreeting: PROC[str: LONG STRING];

-- Parsing
GetLine: PROC[sh: Stream.Handle, line: LONG STRING] RETURNS[noteof: BOOL];
GetChar: PROC[sh: Stream.Handle] RETURNS[CHAR];
GetString: PROC[line, sub: LONG STRING, inx: CARDINAL] RETURNS[CARDINAL];

-- for debugging

DebugPrintZone: PROC[h: TTYProcs];

}.