-- LedgerDefs.mesa  Edited by Sweet, March 30, 1981  10:35 PM

DIRECTORY
  IODefs,
  Press,
  PressDefs,
  StreamDefs,
  StringDefs;
LedgerDefs: DEFINITIONS =
  BEGIN OPEN PressDefs;

  Column: TYPE = [0..27];
  Row: TYPE = [0..32];
  TotalRows: CARDINAL = 6;
  SmallDate: TYPE = RECORD [ SELECT OVERLAID * FROM
    comp => [cv: CARDINAL],
    ymd => [year: [60..99], month: [0..12], day: [1..31]],
    ENDCASE];
  NullDate: SmallDate = [comp[0]]; -- January 1, 1960
  Money: TYPE = LONG INTEGER;

  SortItem: TYPE = RECORD [
    date: SmallDate,
    check: CARDINAL,
    string: StringBody];
  Destination: TYPE = {file, printer, both};
  PageGroup: TYPE = {left, right, both};

  DetailItem: TYPE = RECORD [
    date: SmallDate,
    check: CARDINAL,
    category: Column,
    amount: Money,
    taxded: BOOLEAN,
    text: StringBody];

  TotalRec: TYPE = RECORD [
    isTotal, hasTotal: BOOLEAN,
    myTotal: Column];

  RowHead: TYPE = RECORD [
    SELECT tag: * FROM
      taken => NULL,
      first => [
	checkNum: CARDINAL,
	date: SmallDate,
	payee: STRING,
	amount: Money],
      ENDCASE];

  Side: TYPE = {left, right};
  ColumnEntry: TYPE = RECORD [
    SELECT tag:* FROM
      free => NULL,
      note => [s: STRING, flush: Side, columns: Column],
      money => [deductable: BOOLEAN ← FALSE, v: Money],
      taken => NULL,
      ENDCASE];

  FlagRec: TYPE = RECORD [principal, deductable: BOOLEAN];

  FontIndex: TYPE = {Hv6, Hv8, Hv10};

  Mica: TYPE = INTEGER;
  WideLine: Mica = 50;
  MediumLine: Mica = 30;
  NarrowLine: Mica = 10;
  Dot: Mica = 32;
  RowHeight: Mica = 16*Dot;
  FullHeight: Mica = (LAST[Row]+2)*RowHeight; -- row 0 is double high
  TitleRowY: Mica = BottomMar + FullHeight + 4*Dot;
  HeadingRowY: Mica = BottomMar + FullHeight-RowHeight;
  LeftMar: Mica = 41*Dot;
  BottomMar: Mica = (3*MicasPerInch)/4;
  LineNoPos: Mica = LeftMar;
  LineNoColWidth: Mica = 10*Dot;
  DateColPos: Mica = LineNoPos + LineNoColWidth;
  DateColWidth: Mica = 16*Dot;
  CheckColPos: Mica = DateColPos + DateColWidth;
  CheckColWidth: Mica = 29*Dot;
  PayeeColPos: Mica = CheckColPos + CheckColWidth;
  PayeeColWidth: Mica = 121*Dot;
  IncomeColPos: Mica = PayeeColPos + PayeeColWidth;
  AmountColWidth: Mica = 52*Dot;
  NetAmountColWidth: Mica = 60*Dot;
  ExpenseColPos: Mica = IncomeColPos + AmountColWidth;
  NetColPos: Mica = IncomeColPos - NetAmountColWidth;
  NetLabelWidth: Mica = DateColWidth + CheckColWidth + PayeeColWidth -
	NetAmountColWidth;
  CategoryColPos: Mica = ExpenseColPos + AmountColWidth;
  CategoryColWidth: Mica = 45*Dot;
  FinalLineNoPos1: Mica = CategoryColPos + BreakColumn*CategoryColWidth;
  ExtendedCategoryPos: Mica = DateColPos;
  FinalLineNoPos2: Mica = ExtendedCategoryPos +
	(LAST[Column]-BreakColumn+1)*CategoryColWidth;
  BreakColumn: Column = 11;
  FormWidth1: Mica = 2*LineNoColWidth + DateColWidth + CheckColWidth +
	PayeeColWidth + 2*AmountColWidth + BreakColumn * CategoryColWidth;
  FormWidth2: Mica = 2*LineNoColWidth +
	(LAST[Column]-BreakColumn+1)*CategoryColWidth;
  pfd: POINTER TO PressDefs.PressFileDescriptor;

  RJString: PROCEDURE [x, y: Mica, s: STRING, width: Mica] = INLINE
    BEGIN
    SplatString[x: x + width - Dot - GetWidthOfString[s],
	y: y + 4*Dot,
	s: s];
    END;

  LJString: PROCEDURE [x, y: Mica, s: STRING] = INLINE
    BEGIN
    SplatString[x: x + 2*Dot,
	y: y + 4*Dot,
	s: s];
    END;

  CenterString: PROCEDURE [x, y: Mica, s: STRING, width: Mica] = INLINE
    BEGIN
    delta: Mica = width - GetWidthOfString[s];
    SplatString[x: x + delta/2,
	y: y + 4*Dot,
	s: s];
    END;

  RowY: PROCEDURE [r: Row] RETURNS [Mica] = INLINE
    BEGIN
    RETURN [BottomMar + (LAST[Row]-r)*RowHeight];
    END;

  CategoryX: PROCEDURE [c: Column] RETURNS [Mica] = INLINE
    BEGIN
    RETURN [
      IF c < BreakColumn THEN
        CategoryColPos + c*CategoryColWidth
      ELSE ExtendedCategoryPos + (c-BreakColumn)*CategoryColWidth];
    END;

  HowMany: PROCEDURE [in, of: CARDINAL] RETURNS [CARDINAL] = INLINE
    BEGIN
    RETURN[(in+of-1)/of];
    END;

  Exhausted: PROCEDURE [ss: StringDefs.SubString] RETURNS [BOOLEAN] = INLINE
    BEGIN
    RETURN[ss.offset >= ss.base.length OR
	ss.base[ss.offset] = IODefs.ControlZ];
    END;

  Bump: PROCEDURE [ss: StringDefs.SubString] = INLINE
    BEGIN
    ss.offset ← ss.offset+1;
    END;

  CurrentChar: PROCEDURE [ss: StringDefs.SubString] RETURNS [CHARACTER] = INLINE
    BEGIN
    RETURN [ss.base[ss.offset]];
    END;

-- from FormCreate

  FormCreate: PROGRAM;
  SplatString: PRIVATE PROCEDURE [x, y: Mica, s: STRING];
  CreateForm: PROCEDURE [half: [1..2], date: SmallDate, totals: BOOLEAN];
  LastCheckRow: Row;
  bindingMargin: Mica;
  MonthName: ARRAY [1..12] OF STRING;

--  from LedgerOptions

  LedgerOptions: PROGRAM;
  ReadUserCm: PROCEDURE;
  extendedCats: READONLY BOOLEAN;
  categoryKey: READONLY ARRAY Column OF STRING;
  categoryNeg: READONLY ARRAY Column OF BOOLEAN;
  categoryName: READONLY ARRAY Column OF STRING;
  budgetGiven: READONLY BOOLEAN;
  budget: READONLY ARRAY Column OF ARRAY [1..12] OF Money;
  totalInfo: READONLY ARRAY Column OF TotalRec;
  leftX, leftY, rightX, rightY: READONLY INTEGER;

-- from LedgerControl

  LedgerControl: PROGRAM;
  BadData: SIGNAL;
  WarnS: PROCEDURE [s1, s2: STRING];
  WarnSS: PUBLIC PROCEDURE [s1: STRING, ss2: StringDefs.SubString];
  BravoNewPage: PROCEDURE;
  firstOut: BOOLEAN;
  bravoOut: BOOLEAN;
  tabString: STRING;
  maxBSize: CARDINAL;

-- from DataInput

  DataInput: PROGRAM;
  SkipBlanks: PROCEDURE [ss: StringDefs.SubString, notTab: BOOLEAN ← FALSE];
  GetMoney: PROCEDURE [ss: StringDefs.SubString] RETURNS [val: Money, deductable: BOOLEAN];
  GetNumber: PROCEDURE [ss: StringDefs.SubString, defaultOK: BOOLEAN ← FALSE, default: INTEGER ← 0] RETURNS [val: INTEGER];
  GetUpTo: PROCEDURE [ss: StringDefs.SubString, stop: CHARACTER] RETURNS [ans: STRING];
  GetCategory: PROCEDURE [ss: StringDefs.SubString] RETURNS [col: Column, note: STRING];
  InputLine: PROCEDURE [p: POINTER] RETURNS [CARDINAL];

  dateFirst: BOOLEAN;
  EndOfFile: BOOLEAN;
  instream: StreamDefs.StreamHandle;
  lastDate: SmallDate;
  lastCheck: CARDINAL;
  NullCheck: CARDINAL = LAST[CARDINAL];


-- from LedgerOutput

  LedgerOutput: PROGRAM;
  ARJOut: PROCEDURE [s: STRING, l: CARDINAL];
  ALJOut: PROCEDURE [s: STRING, l: CARDINAL];
  ADateOut: PROCEDURE [date: SmallDate, checkNum: CARDINAL];
  BreakApart: PROCEDURE [
    ss: StringDefs.SubString, 
    total: PROCEDURE [STRING, Money],
    detail: PROCEDURE [Column, Money, STRING, BOOLEAN]];
  Place: PROCEDURE [col: Column, amt: Money, note: STRING, 
	ded: BOOLEAN];
  MoneyToString: PUBLIC PROCEDURE [s: STRING, v: Money];
  NewItem: PROCEDURE [date: SmallDate, check: CARDINAL, payee: STRING, amt: Money];
  FinishPage: PROCEDURE [totals: BOOLEAN];
  LedgerOut: PROCEDURE [p: POINTER, len: CARDINAL];
  ytdTotal: ARRAY Column OF Money;
  bravoLedger: BOOLEAN;
  pageGroup: PageGroup;

-- from LedgerDetail

  LedgerDetail: PROGRAM;
  GetRestOf: PROCEDURE [ss: StringDefs.SubString] RETURNS [rest: STRING];
  ProduceDetailReport: PROCEDURE;
  PrintCategoryName: PROCEDURE [cat: Column];
  taxDedOnly: BOOLEAN;

-- from LedgerFonts

  GetWidthOfString: PROC [s: STRING] RETURNS [Mica];
  GetWidthOfCharacter: PROC [c: CHARACTER] RETURNS [Mica];

  FontWeight: TYPE = Press.FontWeight;
  FontSlope: TYPE = Press.FontSlope;
  SetCurrentFont: PROC [fi: FontIndex, weight: FontWeight, slope: FontSlope];
  SetFontRotation: PROC [rot: CARDINAL];

  END.