-- LedgerDetail.mesa Edited by Sweet, March 30, 1981 10:34 PM
DIRECTORY
GPsortDefs: FROM "gpsortdefs",
InlineDefs: FROM "inlinedefs",
IODefs: FROM "iodefs",
LedgerDefs: FROM "ledgerdefs",
OutputDefs: FROM "outputdefs",
StringDefs: FROM "stringdefs",
SystemDefs: FROM "systemdefs";
LedgerDetail: PROGRAM
IMPORTS GPsortDefs, InlineDefs, IODefs, LedgerDefs, OutputDefs, StringDefs, SystemDefs
EXPORTS LedgerDefs =
BEGIN OPEN LedgerDefs;
NRJOut: PUBLIC PROCEDURE [s: STRING, l: CARDINAL] =
BEGIN OPEN OutputDefs;
THROUGH [s.length..l) DO
PutChar[IF bravoOut THEN IODefs.ControlY ELSE IODefs.SP];
ENDLOOP;
PutString[s];
END;
OrderByDetail: PUBLIC PROCEDURE[p1, p2: POINTER] RETURNS [INTEGER] =
BEGIN
dip1: POINTER TO DetailItem = p1;
dip2: POINTER TO DetailItem = p2;
SELECT dip1.category FROM
>dip2.category => RETURN[1];
<dip2.category => RETURN[-1];
ENDCASE;
SELECT dip1.date.cv FROM
>dip2.date.cv => RETURN[1];
<dip2.date.cv => RETURN[-1];
ENDCASE;
SELECT dip1.check FROM
>dip2.check => RETURN[1];
<dip2.check => RETURN[-1];
ENDCASE => RETURN [0];
END;
dBuffer: POINTER TO SortItem;
nDetail: CARDINAL ← 0;
maxDetail: CARDINAL ← 30;
detail: POINTER TO ARRAY [0..0) OF InternalDetailItem;
currentDate: SmallDate;
currentCheck: CARDINAL;
currentPayee: STRING;
InternalDetailItem: TYPE = RECORD [
category: Column,
amount: Money,
taxded: BOOLEAN,
comment: STRING];
SetPayee: PROCEDURE [payee: STRING, total: Money] =
BEGIN
currentPayee ← payee;
END;
AddDetail: PROCEDURE [col: Column, amt: Money, note: STRING, ded: BOOLEAN] =
BEGIN
IF nDetail = maxDetail THEN
BEGIN
newDetail: POINTER TO ARRAY [0..0) OF InternalDetailItem;
maxDetail ← maxDetail + 20;
newDetail ← SystemDefs.AllocateHeapNode[maxDetail];
InlineDefs.COPY[
from: detail,
to: newDetail,
nwords: (nDetail-1)*SIZE[InternalDetailItem]];
SystemDefs.FreeHeapNode[detail];
detail ← newDetail;
END;
IF categoryNeg[col] THEN amt ← - amt;
detail[nDetail] ← [
category: col,
amount: amt,
taxded: ded,
comment: note];
nDetail ← nDetail + 1;
END;
DetailInput: PUBLIC PROCEDURE [p: POINTER] RETURNS [CARDINAL] =
BEGIN
dip: POINTER TO DetailItem = p;
DO
ENABLE BadData =>
BEGIN OPEN IODefs;
i: CARDINAL;
WriteString[" Aborting item "];
WriteDecimal[currentDate.month]; WriteChar['/];
WriteDecimal[currentDate.day]; WriteChar['/];
WriteDecimal[currentDate.year]; WriteChar[SP];
WriteDecimal[currentCheck]; WriteChar[CR];
FOR i IN [0..nDetail) DO
SystemDefs.FreeHeapString[detail[i].comment];
ENDLOOP;
nDetail ← 0;
LOOP
END;
IF nDetail = 0 THEN
BEGIN
desc: StringDefs.SubStringDescriptor;
IF currentPayee # NIL THEN SystemDefs.FreeHeapString[currentPayee];
currentPayee ← NIL;
IF InputLine[dBuffer] = 0 THEN RETURN[0];
currentDate ← dBuffer.date;
currentCheck ← dBuffer.check;
desc ← [base: @dBuffer.string, offset: 0, length: 1];
BreakApart[@desc, SetPayee, AddDetail];
END;
IF nDetail = 0 THEN RETURN[0];
nDetail ← nDetail - 1;
dip↑ ← [date: currentDate, check: currentCheck,
category: detail[nDetail].category,
amount: detail[nDetail].amount,
taxded: detail[nDetail].taxded,
text: [length: 0, maxlength: (200-SIZE[DetailItem])*2, text: ]];
StringDefs.AppendString[@dip.text, currentPayee];
StringDefs.AppendChar[@dip.text, IODefs.TAB];
IF detail[nDetail].comment # NIL THEN
BEGIN
StringDefs.AppendString[@dip.text, detail[nDetail].comment];
SystemDefs.FreeHeapNode[detail[nDetail].comment];
END;
RETURN [SIZE[DetailItem]+(dip.text.length+1)/2];
ENDLOOP;
END;
lastCat: Column ← LAST[Column];
prevDate: SmallDate ← NullDate;
monthTotal, yearTotal: Money;
monthCount, yearCount: CARDINAL;
taxDedOnly: PUBLIC BOOLEAN ← FALSE;
DetailOutput: PUBLIC PROCEDURE [p: POINTER, len: CARDINAL] =
BEGIN OPEN OutputDefs;
dip: POINTER TO DetailItem = p;
str: STRING = [30];
payee, note: STRING;
desc: StringDefs.SubStringDescriptor ← [
base: @dip.text,
offset: 0,
length: 1];
DoMonthTotal: PROCEDURE =
BEGIN
IF monthCount > 1 THEN
BEGIN
mName: STRING = MonthName[prevDate.month];
PutString[mName]; PutString[" total"];
PutChar[IODefs.TAB];
str.length ← 0;
MoneyToString[str, monthTotal];
NRJOut[str, 10];
PutChar[IODefs.ControlZ];
PutString["e4\bg"]; PutDecimal[mName.length+6];
PutString["t3 1t0"];
PutCR[];
END;
yearTotal ← yearTotal + monthTotal;
yearCount ← yearCount + 1;
monthTotal ← 0; monthCount ← 0;
END;
DoYearTotal: PROC =
BEGIN
IF yearCount > 1 THEN
BEGIN
PutString["Annual total"];
PutChar[IODefs.TAB];
str.length ← 0;
MoneyToString[str, yearTotal];
NRJOut[str, 10];
PutChar[IODefs.ControlZ];
PutString["e6\gb12t3 1t0"];
PutCR[];
END;
yearCount ← 0; yearTotal ← 0;
END;
IF p = NIL THEN {DoMonthTotal[]; DoYearTotal[]; RETURN};
IF firstOut THEN
BEGIN
IODefs.WriteString["Writing..."]; firstOut ← FALSE;
PutChar[IODefs.ControlZ];
PutString[tabString ← "(0,4608)(1,5664)(2,10272)(3,12384)"];
PutCR[];
END;
IF dip.category # lastCat THEN
BEGIN
DoMonthTotal[];
DoYearTotal[];
lastCat ← dip.category;
BravoNewPage[];
PrintCategoryName[dip.category];
PutChar[IODefs.ControlZ]; PutString["c\f5b"L]; PutCR[];
prevDate ← NullDate;
END;
IF dip.date.month # prevDate.month THEN
BEGIN DoMonthTotal[]; PutCR[]; END;
monthTotal ← monthTotal + dip.amount;
monthCount ← monthCount + 1;
prevDate ← dip.date;
ADateOut[dip.date, dip.check]; PutChar[IODefs.TAB];
payee ← GetUpTo[@desc, IODefs.TAB]; Bump[@desc];
PutString[payee]; SystemDefs.FreeHeapString[payee];
PutChar[IODefs.TAB];
str.length ← 0;
MoneyToString[str, dip.amount];
IF dip.taxded THEN StringDefs.AppendChar[str, 'T];
NRJOut[str, IF dip.taxded THEN 11 ELSE 10];
note ← GetRestOf[@desc];
IF note # NIL THEN
BEGIN
PutChar[IODefs.TAB];
PutString[note]; SystemDefs.FreeHeapNode[note];
END;
PutChar[IODefs.ControlZ]; PutString["\g"L]; PutChar[IODefs.CR];
END;
PrintCategoryName: PUBLIC PROCEDURE [cat: Column] =
BEGIN OPEN OutputDefs;
cName: STRING ← categoryName[cat];
ch: CHARACTER;
i: CARDINAL;
FOR i ← 0, i+1 WHILE i < cName.length DO
ch ← cName[i];
SELECT ch FROM
'- => IF cName[i+1] = '/ THEN i ← i+1
ELSE PutChar[ch];
'/ => PutChar[IODefs.SP];
ENDCASE => PutChar[ch];
ENDLOOP;
END;
GetRestOf: PUBLIC PROCEDURE [ss: StringDefs.SubString]
RETURNS [rest: STRING] =
BEGIN
IF Exhausted[ss] THEN RETURN[NIL];
rest ← SystemDefs.AllocateHeapString[ss.base.length - ss.offset];
UNTIL Exhausted[ss] DO
StringDefs.AppendChar[rest, CurrentChar[ss]];
Bump[ss];
ENDLOOP;
END;
ProduceDetailReport: PUBLIC PROCEDURE =
BEGIN
lastCat ← LAST[Column];
currentPayee ← NIL;
prevDate ← NullDate;
monthCount ← yearCount ← 0;
monthTotal ← yearTotal ← 0;
GPsortDefs.Sort[
get: DetailInput,
put: DetailOutput,
compare: OrderByDetail,
expectedItemSize: 25,
maxItemSize: 200,
reservedPages: 110];
DetailOutput[NIL,0];
END;
dBuffer ← SystemDefs.AllocateResidentPages[2];
detail ← SystemDefs.AllocateHeapNode[maxDetail * SIZE [InternalDetailItem]];
END.