-- ExecStreamIO.Mesa
-- Edited by Sandman on July 1, 1980  8:33 AM
-- Edited by Brotz on December 1, 1980  11:33 AM
-- Edited by Levin on January 20, 1981  5:05 PM
DIRECTORY
  Editor,
  inD: FROM "InteractorDefs",
  intCommon: FROM "IntCommon",
  IODefs,
  LaurelExecImpDefs,
  ovD: FROM "OverviewDefs",
  StreamDefs,
  String,
  vmD: FROM "VirtualMgrDefs";
ExecStreamIO: MONITOR LOCKS LaurelExecImpDefs.lock
  IMPORTS Editor, inD, intC: intCommon, LaurelExecImpDefs, StreamDefs, String, vmD
  EXPORTS IODefs
  SHARES IODefs, StreamDefs = PUBLIC
  
  BEGIN OPEN StreamDefs, IODefs, String;
  
  in, out: StreamHandle;
  beginLine, echo: PRIVATE BOOLEAN _ TRUE;
  
  GetInputStream: PROCEDURE RETURNS [StreamHandle] = BEGIN RETURN[in] END;
    
  GetOutputStream: PROCEDURE RETURNS [StreamHandle] = BEGIN RETURN[out] END;
    
  SetInputStream: PROCEDURE [s: StreamHandle] = BEGIN in _ s END;
    
  SetOutputStream: PROCEDURE [s: StreamHandle] =
    BEGIN out _ s; beginLine _ TRUE; END;
    
  SetEcho: PROCEDURE [new: BOOLEAN] RETURNS [old: BOOLEAN] =
    BEGIN old _ echo; echo _ new END;
    
  -- Character operations
  
  
  ReadChar: PROCEDURE RETURNS [CHARACTER] = BEGIN RETURN[in.get[in]]; END;
    
  WriteChar: PROCEDURE [c: CHARACTER] =
    BEGIN out.put[out, c]; beginLine _ c = CR; END;
    
  -- Reading Strings
  
  
  ReadString: PROCEDURE [s: STRING, t: PROCEDURE [CHARACTER] RETURNS [BOOLEAN]] =
    BEGIN WriteChar[ReadEditedString[s, t, TRUE]]; END;
    
  ReadID: PROCEDURE [s: STRING] =
    BEGIN [] _ ReadEditedString[s, IsAtom, TRUE]; END;
    
  ReadLine: PROCEDURE [s: STRING] =
    BEGIN [] _ ReadEditedString[s, IsCR, TRUE]; WriteChar[CR]; END;
    
  IsCR: PRIVATE PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] =
    BEGIN RETURN[c = CR] END;
    
  IsAtom: PRIVATE PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] =
    BEGIN RETURN[IF c = SP OR c = CR THEN TRUE ELSE FALSE] END;
    
  Rubout: SIGNAL = CODE;
  LineOverflow: SIGNAL [s: STRING] RETURNS [ns: STRING] = CODE;
  
  ReadEditedString: PROCEDURE [
    s: STRING, t: PROCEDURE [CHARACTER] RETURNS [BOOLEAN], newstring: BOOLEAN]
    RETURNS [CHARACTER] =
    BEGIN
    c: CHARACTER;
    i: CARDINAL;
    state: {ti, v, li};
    c _ in.get[in];
    IF newstring THEN
      IF c = ESC THEN BEGIN WriteString[s]; c _ in.get[in]; END ELSE s.length _ 0;
    UNTIL t[c] DO
      SELECT c FROM
	DEL => SIGNAL Rubout;
	ControlA, ControlH =>
	  BEGIN
	  IF s.length > 0 THEN
	    BEGIN
	    IF echo THEN
	      WITH out SELECT FROM
		Display => clearChar[out, s[s.length - 1]];
		ENDCASE => out.put[out, c];
	    s.length _ s.length - 1;
	    END;
	  END;
	ControlW, ControlQ =>
	  BEGIN -- text to be backed up is of the form
	  -- ...
;   the  and  are to be removed.
	  state _ ti;
	  FOR i DECREASING IN [0..s.length) DO
	    SELECT s[
	      i] FROM
	      IN ['A..'Z], IN ['a..'z], IN ['0..'9] =>
		IF state = ti THEN state _ v;
	      ENDCASE => IF state = v THEN state _ li;
	    IF state = li THEN GO TO Done;
	    IF echo THEN
	      WITH out SELECT FROM
		Display => clearChar[out, s[i]];
		ENDCASE => out.put[out, ControlA];
	    REPEAT Done => s.length _ i + 1; FINISHED => s.length _ 0;
	    ENDLOOP;
	  END;
	ControlR => IF echo THEN BEGIN WriteChar[CR]; WriteString[s]; END;
	ControlX =>
	  BEGIN
	  IF echo THEN
	    WITH out SELECT FROM
	      Display => clearCurrentLine[out];
	      ENDCASE => out.put[out, c];
	  s.length _ 0;
	  END;
	ControlV =>
	  BEGIN
	  WHILE s.length >= s.maxlength DO s _ SIGNAL LineOverflow[s]; ENDLOOP;
	  s[s.length] _ c _ in.get[in];
	  s.length _ s.length + 1;
	  IF echo THEN WriteChar[c];
	  END;
	ENDCASE =>
	  BEGIN
	  WHILE s.length >= s.maxlength DO s _ SIGNAL LineOverflow[s]; ENDLOOP;
	  s[s.length] _ c;
	  s.length _ s.length + 1;
	  IF echo THEN WriteChar[c];
	  END;
      c _ in.get[in];
      ENDLOOP;
    RETURN[c];
    END;
    
  -- Writing Strings
  
  
WriteString: PROCEDURE [s: STRING] =
BEGIN
ssd: String.SubStringDescriptor _ [base: s, offset: 0, length: s.length];
WriteSubString[@ssd];
END;  -- of WriteString --
WriteSubString: ENTRY PROCEDURE [s: String.SubString] =
BEGIN
OPEN LaurelExecImpDefs;
start: ovD.CharIndex;
resumeScan: CARDINAL _ s.offset;
ssEnd: CARDINAL = s.offset + s.length;
runLength: CARDINAL;
cm: vmD.ComposeMessagePtr;
IF ioState = originalScreen THEN {ioState _ typescriptActive; SpliceExecutiveIntoEditor[]};
start _ intC.target.point;
cm _ LOOPHOLE[cmMnp.message];
inD.StopBlinkingCaret[];
[] _ Editor.MakeCharIndexVisible[start, cmMnp];
IF start > 60000 THEN {LaurelExecImpDefs.ShortenTypeScript[]; start _ intC.target.point};
vmD.StartMessageInsertion[cm, start];
UNTIL resumeScan >= ssEnd DO
  startInSS: CARDINAL _ resumeScan;
  FOR i: CARDINAL IN [startInSS .. ssEnd) DO
    SELECT s.base[i] FROM
      LF => {runLength _ i - startInSS; resumeScan _ i + 1; EXIT};
      CR => {runLength _ i - startInSS + 1; resumeScan _ i + 1; EXIT};
      ENDCASE;
    REPEAT
    FINISHED => {runLength _ ssEnd - startInSS; resumeScan _ ssEnd};
    ENDLOOP;
  IF runLength = 0 THEN LOOP;
  [] _ vmD.InsertSubstringInMessage[cm, s.base, startInSS, runLength];
  vmD.StopMessageInsertion[cm];
  Editor.RefreshFromFirstChange[start, 0, runLength, cmMnp];
  start _ start + runLength;
  [] _ Editor.MakeCharIndexVisible[start, cmMnp];
  vmD.StartMessageInsertion[cm, start];
  ENDLOOP;
vmD.StopMessageInsertion[cm];
intC.target.point _ start;
LaurelExecImpDefs.RefreshCaret[FALSE];
IF s.length ~= 0 THEN beginLine _ s.base[s.offset + s.length - 1] = CR;
END;  -- of WriteSubString --
    
  WriteLine: PROCEDURE [s: STRING] = BEGIN WriteString[s]; WriteChar[CR]; END;
    
  NewLine: PROCEDURE RETURNS [BOOLEAN] = BEGIN RETURN[beginLine] END;
    
  --  Numerical i/o
  
  
  ReadNumber: PROCEDURE [default: UNSPECIFIED, radix: CARDINAL]
    RETURNS [UNSPECIFIED] =
    BEGIN
    s: STRING _ [10];
    IF radix = 10 AND LOOPHOLE[default, INTEGER] < 0 THEN
      BEGIN default _ -default; s[0] _ '-; s.length _ 1 END;
    AppendNumber[s, default, radix];
    IF radix = 8 THEN AppendChar[s, 'B];
    [] _ ReadEditedString[s, IsAtom, TRUE];
    RETURN[StringToNumber[s, radix]];
    END;
    
  ReadDecimal: PROCEDURE RETURNS [INTEGER] =
    BEGIN
    s: STRING _ [10];
    [] _ ReadEditedString[s, IsAtom, TRUE];
    RETURN[StringToNumber[s, 10]]
    END;
    
  ReadOctal: PROCEDURE RETURNS [UNSPECIFIED] =
    BEGIN
    s: STRING _ [10];
    [] _ ReadEditedString[s, IsAtom, TRUE];
    RETURN[StringToNumber[s, 8]]
    END;
    
  OutNumber: PROCEDURE [
    stream: StreamHandle, val: INTEGER, format: NumberFormat] =
    BEGIN
    i: CARDINAL;
    neg: BOOLEAN _ FALSE;
    fill: CHARACTER _ (IF format.zerofill THEN '0 ELSE ' );
    s: STRING _ [17];
    IF val < 0 AND ~format.unsigned THEN BEGIN val _ -val; neg _ TRUE END;
    AppendNumber[s, val, format.base];
    i _ s.length;
    IF neg THEN
      BEGIN
      i _ i + 1;
      IF format.zerofill THEN BEGIN stream.put[stream, '-]; neg _ FALSE END;
      END;
    THROUGH (i..format.columns] DO stream.put[stream, fill] ENDLOOP;
    IF neg THEN stream.put[stream, '-];
    FOR i IN [0..s.length) DO stream.put[stream, s[i]] ENDLOOP;
    RETURN
    END;
    
  WriteNumber: PROCEDURE [v: UNSPECIFIED, f: NumberFormat] =
    BEGIN OutNumber[out, v, f]; beginLine _ FALSE; RETURN END;
    
  WriteDecimal: PROCEDURE [n: INTEGER] =
    BEGIN WriteNumber[n, NumberFormat[10, FALSE, FALSE, 0]]; RETURN END;
    
  WriteOctal: PROCEDURE [n: UNSPECIFIED] =
    BEGIN
    WriteNumber[n, NumberFormat[8, FALSE, TRUE, 0]];
    IF n ~ IN [0..7] THEN WriteChar['B];
    RETURN
    END;
    
  in _ StreamDefs.GetDefaultKey[ ! ANY => CONTINUE];
  out _ StreamDefs.GetDefaultDisplayStream[ ! ANY => CONTINUE];
  
  END.
z19932(635)\f1