-- RopeFrom.mesa
-- written by Bill Paxton,  February 1981
-- last edit by Bill Paxton, 17-Jan-82 15:51:32

-- routines for creating ropes from files, strings, and characters
-- also for creating flat ropes from other ones

-- characters go into CharsArrays so get fast access via RopeReader's (q.v.)

-- a shared CharsArray is used to hold text for chars, strings, and ropes
-- it is also used for short files

-- long files are mapped into their own CharsArray's 
	-- using Pilot spaces so don't actually read the chars at all

DIRECTORY
	IOStream,
	File,
	Rope;

RopeFrom: DEFINITIONS
	IMPORTS Rope =
BEGIN OPEN fI:File;

Offset: TYPE = INT;
MaxLen: Offset = LAST[Offset];
MaxNat: NAT = LAST[NAT];
ROPE: TYPE = Rope.ROPE;

File: PROC [
	file: fI.Capability,
	start: Offset ← 0, -- byte address in file where rope will start
			-- 0 means first page after leader page
	length: Offset ← MaxLen, -- defaults to rest of file beyond start
	activate: BOOLEAN ← FALSE,
	fileLen: Offset ← MaxLen,
	okToMapFile: BOOLEAN ← FALSE]
	RETURNS [ROPE];
	-- if activate is true, the system will start swapping the 
		-- characters into real memory
	-- fileLen is size of entire file in bytes, excluding leader page
		-- let this be defaulted if you're not sure of it
	-- set okToMapFile to FALSE if you will want to overwrite the contents later

Stream: PROC [stream: IOStream.Handle, length: Offset ← MaxLen]
	RETURNS [rope: ROPE];
	-- reads length chars from stream and puts them in a rope

String: PROC [
	string: REF READONLY TEXT,
	start: NAT ← 0, len: NAT ← LAST[NAT]]
	RETURNS [ROPE];
	-- copies len characters from string starting at start

Character: PROC [char: CHAR] RETURNS [ROPE];

Byte: PROC [x: UNSPECIFIED] RETURNS [ROPE] = INLINE {
	RETURN [Character[LOOPHOLE[x,CHAR]]] };

FlatSubstr: PROC [rope: ROPE, start: Offset ← 0, len: Offset ← MaxLen]
	RETURNS [ROPE];

FlatConcat: PROC
	[base, rest: ROPE, baseSize, restSize: Offset ← MaxLen, tryAppend: BOOLEAN ← TRUE]
	RETURNS [ROPE];

TryAppendConcat: PROC [base, rest: ROPE, baseSize, restSize: Offset ← MaxLen]
	RETURNS [ROPE];
	-- tries to append rest by copying to buffer directly after base
	-- returns NIL if cannot

FlatReplace: PROC [
	base: ROPE, start: Offset ← 0, len: Offset ← MaxLen, replace: ROPE ← NIL,
	size, baseSize, repSize: Offset ← MaxLen]
		RETURNS [ROPE];
	-- returns a new rope with the given range replaced

FlatDelete: PROC [base: ROPE, start: Offset ← 0, len, baseSize: Offset ← MaxLen]
	RETURNS [ROPE] = INLINE { RETURN [
	FlatReplace[base, start, len, NIL, MaxLen, baseSize, 0]] };

FlatInsert: PROC [
	dest: ROPE, destLoc: Offset ← 0, source: ROPE,
	destSize, sourceSize: Offset ← MaxLen]
	RETURNS [ROPE] = INLINE { RETURN [
	FlatReplace[dest, destLoc, 0, source, MaxLen, destSize, sourceSize]] };

FlatCopy: PROC [
	dest: ROPE, destLoc: Offset ← 0,
	source: ROPE, start: Offset ← 0, len: Offset ← MaxLen,
	destSize: Offset ← MaxLen]
	RETURNS [ROPE];

FlatMove: PROC [
	base: ROPE, destLoc, start: Offset ← 0, len, baseSize: Offset ← MaxLen]
	RETURNS [ROPE];
	
FlatTranspose: PROC [
	base: ROPE, astart, alen, bstart, blen: Offset,
	baseSize: Offset ← MaxLen]
	RETURNS [ROPE];
	-- [astart..astart+alen) must not intersect [bstart..bstart+blen)

FlatReplaceByChar: PROC [
	base: ROPE, char: CHAR,
	start: Offset ← 0, len, baseSize: Offset ← MaxLen,
	tryAppend: BOOLEAN ← TRUE]
	RETURNS [new: ROPE];

TryAppendReplaceByChar: PROC [
	base: ROPE, char: CHAR,
	start: Offset ← 0, len, baseSize: Offset ← MaxLen]
	RETURNS [new: ROPE];

FlatInsertChar: PROC [
	base: ROPE, char: CHAR,
	loc: Offset ← 0, baseSize: Offset ← MaxLen,
	tryAppend: BOOLEAN ← TRUE]
	RETURNS [ROPE] =
	INLINE { RETURN [FlatReplaceByChar[base,char,loc,0,baseSize,tryAppend]] };

TryFlatInsertChar: PROC [
	base: ROPE, char: CHAR,
	loc: Offset ← 0, baseSize: Offset ← MaxLen]
	RETURNS [ROPE] =
	INLINE { RETURN [TryAppendReplaceByChar[base,char,loc,0,baseSize]] };

FlatAppendChar: PROC
	[base: ROPE, char: CHAR, baseSize: Offset ← MaxLen, tryAppend: BOOLEAN ← TRUE]
	RETURNS [ROPE] =
	INLINE { RETURN [FlatReplaceByChar[base,char,MaxLen,0,baseSize,tryAppend]] };

TryFlatAppendChar: PROC [base: ROPE, char: CHAR, baseSize: Offset ← MaxLen]
	RETURNS [ROPE] =
	INLINE { RETURN [TryAppendReplaceByChar[base,char,MaxLen,0,baseSize]] };

FlatAppendByte: PROC
	[base: ROPE, x: UNSPECIFIED, baseSize: Offset ← MaxLen, tryAppend: BOOLEAN ← TRUE]
	RETURNS [ROPE] = INLINE {
	RETURN [FlatAppendChar[base,LOOPHOLE[x,CHAR],baseSize,tryAppend]] };

TryFlatAppendByte: PROC
	[base: ROPE, x: UNSPECIFIED, baseSize: Offset ← MaxLen]
	RETURNS [ROPE] = INLINE {
	RETURN [TryFlatAppendChar[base,LOOPHOLE[x,CHAR],baseSize]] };

FlatReplaceByString: PROC [
	base: ROPE, string: REF READONLY TEXT,
	stringStart: NAT ← 0, stringNum: NAT ← MaxNat,
	start: Offset ← 0, len, baseSize: Offset ← MaxLen,
	tryAppend: BOOLEAN ← TRUE]
	RETURNS [new: ROPE];

TryAppendReplaceByString: PROC [
	base: ROPE, string: REF READONLY TEXT,
	stringStart: NAT ← 0, stringNum: NAT ← MaxNat,
	start: Offset ← 0, len, baseSize: Offset ← MaxLen]
	RETURNS [new: ROPE];

FlatInsertString: PROC [
	base: ROPE, string: REF READONLY TEXT,
	stringStart: NAT ← 0, stringNum: NAT ← MaxNat,
	loc: Offset ← 0, baseSize: Offset ← MaxLen,
	tryAppend: BOOLEAN ← TRUE]
	RETURNS [ROPE] = INLINE { RETURN [
	-- string is inserted at loc
	-- inserts stringNum chars from string starting with stringStart
	FlatReplaceByString[base,string,stringStart,stringNum,loc,0,baseSize,tryAppend]] };

TryFlatInsertString: PROC [
	base: ROPE, string: REF READONLY TEXT,
	stringStart: NAT ← 0, stringNum: NAT ← MaxNat,
	loc: Offset ← 0, baseSize: Offset ← MaxLen]
	RETURNS [ROPE] = INLINE { RETURN [
	-- string is inserted at loc
	-- inserts stringNum chars from string starting with stringStart
	TryAppendReplaceByString[base,string,stringStart,stringNum,loc,0,baseSize]] };

FlatAppendString: PROC [
	base: ROPE,
	string: REF READONLY TEXT,
	stringStart: NAT ← 0,
	stringNum: NAT ← MaxNat,
	baseSize: Offset ← MaxLen,
	tryAppend: BOOLEAN ← TRUE] RETURNS [ROPE] = INLINE { RETURN [
	FlatReplaceByString[base,string,stringStart,stringNum,MaxLen,0,baseSize,tryAppend]] };

TryFlatAppendString: PROC [
	base: ROPE,
	string: REF READONLY TEXT,
	stringStart: NAT ← 0,
	stringNum: NAT ← MaxNat,
	baseSize: Offset ← MaxLen] RETURNS [ROPE] = INLINE { RETURN [
	TryAppendReplaceByString[base,string,stringStart,stringNum,MaxLen,0,baseSize]] };

-- ***** miscellaneous internal stuff

StartRopeFrom, StartRopeFromEdit, StartRopeFromFile: PROC; -- for initialization only

qZone: ZONE; -- quantized zone for use within RopeEditing config 
pZone: ZONE; -- prefixed zone for use within RopeEditing config 

END.