-- PrintFormat.mesa; edited by Johnsson on 17-Apr-81  9:16:44
-- edited by Paul Rovner on 6-Jan-82 19:30:07
-- edited by Michael Plass on August 27, 1982 5:31 pm

DIRECTORY
  Ascii USING [ControlZ, CR, FF, NUL, SP, TAB],
  PrintOps USING [ParametersHandle, PressProcsHandle],
  Press USING [FontSlope, FontWeight, Mica, pageHeight, pageWidth];

PrintFormat: PROGRAM
  EXPORTS PrintOps =
  BEGIN
  
  DataEnd: PUBLIC SIGNAL = CODE;
  
  Mica: TYPE = Press.Mica;
  
  ComputeLineWidth: PROCEDURE [p: PrintOps.ParametersHandle] RETURNS [width: Mica] =
    BEGIN
    SELECT p.mode FROM
      portrait => width ← Press.pageWidth - p.margins[right] - p.margins[left];
      landscape => width ← Press.pageHeight - p.margins[top] - p.margins[bottom];
      ENDCASE => ERROR;
    width ← width - (p.columns - 1)*(p.betweenColumns);
    width ← LOOPHOLE[width, CARDINAL]/p.columns;
    RETURN
    END;
    
  Data: TYPE = RECORD [
    b: STRING,
    procs: PrintOps.PressProcsHandle,
    getChar: PROCEDURE RETURNS [CHARACTER],
    spaceWidth: Mica,
    bol: BOOLEAN ← TRUE,
    i, whiteLength: CARDINAL ← 0,
    curX, bWidth: Mica ← 0,
    indentWidth, charWidth, whiteWidth: Mica ← NULL];
  
  data: POINTER TO Data ← NIL;

  Format: PUBLIC PROCEDURE [
    getChar: PROCEDURE RETURNS [CHARACTER],
    procs: PrintOps.PressProcsHandle,
    p: PrintOps.ParametersHandle] RETURNS [lastPage: CARDINAL] =
    BEGIN
    char: CHARACTER;
    ignoring: BOOLEAN ← FALSE;
    localb: STRING ← [250];
    lineWidth: Mica = ComputeLineWidth[p];
    localData: Data ← [
      b: localb, procs: procs, getChar: getChar, spaceWidth: procs.GetWidthOfCharacter[Ascii.SP]];
    tabWidth: Mica = localData.spaceWidth*p.tab;
    data ← @localData;
    DO OPEN localData;
      char ← getChar[ ! DataEnd => EXIT];
      IF ignoring AND char # Ascii.CR AND char # Ascii.FF THEN LOOP;
      SELECT char FROM
	Ascii.SP =>
	  BEGIN
	  IF bol THEN BEGIN curX ← curX + spaceWidth; LOOP END;
	  whiteLength ← i;
	  whiteWidth ← bWidth;
	  IF curX + spaceWidth > lineWidth THEN BEGIN Overflow[]; LOOP END;
	  END;
	Ascii.CR, Ascii.FF =>
	  BEGIN
	  PutPiece[];
	  procs.Character[char];
	  bol ← TRUE;
	  indentWidth ← curX ← 0;
	  ignoring ← FALSE;
	  LOOP
	  END;
	Ascii.TAB =>
	  BEGIN
	  IF bol THEN
	    BEGIN curX ← (((curX + spaceWidth)/tabWidth) + 1)*tabWidth; LOOP END;
	  PutPiece[];
	  procs.Character[char];
	  curX ← procs.GetCurrentPosition[].x;
	  LOOP
	  END;
	Ascii.ControlZ =>
	  BEGIN
	  PutPiece[];
	  UNTIL char = Ascii.CR DO
	    char ← getChar[ ! DataEnd => EXIT]; ENDLOOP;
	  procs.Character[char];
	  bol ← TRUE;
	  indentWidth ← curX ← 0;
	  LOOP
	  END;
	Ascii.NUL =>
	  BEGIN
	  PutPiece[];
	  char ← getChar[ ! DataEnd => EXIT];
	  IF char = Ascii.NUL THEN EXIT;
	  LOOP
	  END;
	'\\ => IF p.nonprog THEN {ProcessLooks[!DataEnd => CONTINUE]; LOOP}
	  ELSE CheckBol[];
	'a,'b,'c,'d,'e,'f,'g,'h,'i,'j,'k,'l,'m,'n,'o,'p,'q,'r,'s,'t,'u,'v,'w,'x,'y,'z,
	'A,'B,'C,'D,'E,'F,'G,'H,'I,'J,'K,'L,'M,'N,'O,'P,'Q,'R,'S,'T,'U,'V,'W,'X,'Y,'Z,
	'1,'2,'3,'4,'5,'6,'7,'8,'9,'0,'!,'@,'#,'$,'%,'~,'&,'*,'(,'),'-,'=,'+,'|,'←,'↑,
	'[,'],'←,'{,'},'↑,';,':,'','",',,'.,'/,'<,'>,'? => CheckBol[];
	ENDCASE => CheckBol[];
      charWidth ← procs.GetWidthOfCharacter[char];
      IF curX + charWidth > lineWidth THEN
        IF p.wrap THEN Overflow[] ELSE {ignoring ← TRUE; LOOP};
      IF i = b.maxlength THEN PutPiece[];
      b[i] ← char;
      b.length ← i ← i + 1;
      bWidth ← bWidth + charWidth;
      curX ← curX + charWidth;
      ENDLOOP;
    PutPiece[];
    lastPage ← procs.GetCurrentPageNumber[];
    data ← NIL;
    RETURN
    END;
    
  CheckBol: PROCEDURE = INLINE {
    OPEN data;
    IF bol THEN {
      IF (indentWidth ← curX) # 0 THEN procs.SkipSomeSpace[indentWidth]; bol ← FALSE}};

  ProcessLooks: PROCEDURE =
    BEGIN OPEN data;
    c: CHARACTER ← getChar[];
    SELECT c FROM
      'f => {
	font: CARDINAL;
	weight: Press.FontWeight ← medium;
	slope: Press.FontSlope ← regular;
	PutPiece[]; 
	font ← getChar[] - '0;
	UNTIL (c ← getChar[]) = '\\ DO
	  SELECT c FROM 'b => weight ← bold; 'i => slope ← italic; ENDCASE ENDLOOP;
	procs.SetCurrentFont[font, weight, slope]};
      ENDCASE => {CheckBol[]; RETURN};
    END;
    
  PutPiece: PROCEDURE =
    BEGIN OPEN data;
    IF i # 0 THEN
      BEGIN
      procs.PieceOfLine[b, bWidth];
      bWidth ← 0;
      b.length ← i ← whiteLength ← 0;
      END;
    END;
    
  Overflow: PROCEDURE =
    BEGIN OPEN data;
    IF whiteLength = 0 OR whiteLength = b.length THEN
      BEGIN PutPiece[]; procs.Character[Ascii.CR] END
    ELSE
      BEGIN
      b.length ← whiteLength;
      procs.PieceOfLine[b, whiteWidth];
      procs.Character[Ascii.CR];
      bWidth ← bWidth - whiteWidth - spaceWidth;
      b.length ← i - whiteLength - 1;
      FOR j: CARDINAL IN [0..b.length) DO
	b[j] ← b[whiteLength + j + 1]; ENDLOOP;
      i ← b.length;
      whiteLength ← 0;
      END;
    IF indentWidth # 0 THEN procs.SkipSomeSpace[indentWidth];
    curX ← indentWidth + bWidth;
    END;
    
  END...

Michael Plass on August 27, 1982 5:31 pm: Put in check for double nulls to ignore Tioga formatting.