home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / tech / protocol.hqx / ProtocolSources.pit / UProtocolchart.inc1.p < prev    next >
Encoding:
Text File  |  1986-02-04  |  15.6 KB  |  798 lines

  1. {copyright 1986 by Herb Barad}
  2. {Protocol is a program to produce a PICT representation of a class}
  3. {hierarchy from a textual description.}
  4. {parts from Flow MacApp sample - copyright 1986 by Apple Computer}
  5.  
  6. CONST
  7.  maxKeyword = 32;
  8.  
  9.  picDwgBeg = 130;
  10.  picDwgEnd = 131;
  11.  picGrpBeg = 140;
  12.  picGrpEnd = 141;
  13.  picTxtBeg = 150;
  14.  picTxtEnd = 151;
  15.  
  16.  nMdrwSizes = 8;
  17.  
  18.  
  19. TYPE
  20.  HTxtPicRec = ^PTxtPicRec;
  21.  PTxtPicRec = ^TTxtPicRec;
  22.  TTxtPicRec = PACKED RECORD
  23.                tJus:   Byte;
  24.                tFlip:  Byte;
  25.                tRot:   Byte;
  26.                tLine:  Byte;
  27.                tXtra:  Byte;
  28.                END;
  29.  PByte = ^Byte;
  30.  
  31.  
  32.  KWSpec = RECORD
  33.            keyword:      KeyStr;
  34.            itsShape:     KShape;
  35.            itsAlignment: KAlignment;
  36.            itsStyle:     Style;
  37.            END;
  38.  
  39.  KWTable = ARRAY[0..maxKeyword] OF KWSpec;
  40.  
  41. VAR
  42.  nKeywords:     INTEGER;
  43.  keywordTable:    KWTable;
  44.  commentHandle: Handle;
  45.  
  46.  mDrwSizes:     ARRAY[1..nMdrwSizes] OF INTEGER; {font sizes in MacDraw}
  47.  
  48.  
  49.  PROCEDURE InitProtocolchart;
  50.  BEGIN
  51.   nKeyWords := 0;
  52.  
  53.   WITH keywordTable[0] DO
  54.    BEGIN
  55.     keyword := 'default';
  56.     itsShape := shNone;
  57.     itsAlignment := alMiddle;
  58.     itsStyle := [];
  59.    END;
  60.  
  61.   commentHandle := NewHandle(0);
  62.  
  63.   mDrwSizes[1] := 09;
  64.   mDrwSizes[2] := 10;
  65.   mDrwSizes[3] := 12;
  66.   mDrwSizes[4] := 14;
  67.   mDrwSizes[5] := 18;
  68.   mDrwSizes[6] := 24;
  69.   mDrwSizes[7] := 36;
  70.   mDrwSizes[8] := 48;
  71.  END;
  72.  
  73.  
  74.  PROCEDURE AddKeyword(aKeyWord: KeyStr; aShape: KShape; anAlignment: KAlignment; aStyle: Style);
  75.  BEGIN
  76.   IF nKeywords < maxKeyword THEN
  77.    BEGIN
  78.    nKeywords := nKeyWords + 1;
  79.    WITH keywordTable[nKeywords] DO
  80.     BEGIN
  81.     keyword := aKeyWord;
  82.     itsShape := aShape;
  83.     itsAlignment := anAlignment;
  84.     itsStyle := aStyle;
  85.     END;
  86.    END;
  87.  END;
  88.  
  89.  
  90.  PROCEDURE TNode.INode(aTree: TTree;
  91.          aCaption : String80;
  92.          anAlignment : KAlignment;
  93.          aStyle : Style;
  94.          aShape : KShape;
  95.          aNumber : NumStr);
  96.   VAR
  97.    gZeroRect: Rect;
  98.  BEGIN
  99.   fFirstChild := NIL;
  100.   fNextChild := NIL;
  101.   fTree := aTree;
  102.   fCaption := aCaption;
  103.   fAlignment := anAlignment;
  104.   fFace := aStyle;
  105.   fNumber := aNumber;
  106.  
  107.   IF aShape = shDRect THEN
  108.    BEGIN
  109.    aShape := shRect;
  110.    fDoubled := TRUE;
  111.    END
  112.   ELSE
  113.    fDoubled := FALSE;
  114.   fShapeKind := aShape;
  115.  
  116.   SetRect(gZeroRect, 0, 0, 0, 0);
  117.   fBounds := gZeroRect;
  118.  END;
  119.  
  120.  
  121.  PROCEDURE TNode.Free;
  122.  BEGIN
  123.   FreeObject(fFirstChild);
  124.   FreeObject(fNextChild);
  125.   INHERITED Free;
  126.  END;
  127.  
  128.  
  129. {$IFC qDebug}
  130. {$IFC qTrace}{$D+}{$ENDC}
  131.  PROCEDURE TNode.Inspect; OVERRIDE;
  132.  BEGIN
  133.   INHERITED Inspect;
  134.  
  135.   Writeln('"', fCaption, '"');
  136.  
  137.   Write('fFirstChild = ');
  138.   WritePtr(fFirstChild);
  139.   Write('  fNextChild = ');
  140.   WritePtr(fNextChild);
  141.   Write('  fBounds = ');
  142.   WriteRect(fBounds);
  143.   Writeln;
  144.  
  145.   Write('fAlignment = ',     ORD(fAlignment):1,
  146.           '  fNumber = ', fNumber,
  147.           '  fShapeKind = ', ORD(fShapeKind):1);
  148.   IF fDoubled THEN
  149.    Writeln('  doubled')
  150.   ELSE
  151.    Writeln;
  152.  END;
  153. {$IFC qTrace}{$D++}{$ENDC}
  154. {$ENDC}
  155.  
  156.  
  157.  PROCEDURE TNode.AddChild (child : TNode);
  158.   VAR
  159.    sib : TNode;
  160.  BEGIN
  161.   IF fFirstChild = NIL THEN
  162.    fFirstChild := child
  163.   ELSE
  164.    BEGIN
  165.     sib := fFirstChild;
  166.     while sib.fNextChild <> NIL do
  167.      sib := sib.fNextChild;
  168.     sib.fNextChild := child;
  169.    END;
  170.  END;
  171.  
  172.  
  173.  PROCEDURE TNode.AddLinkHeight (sib : TNode;
  174.          VAR v : INTEGER);
  175.  BEGIN
  176.   WITH fTree do
  177.    BEGIN
  178.    IF (sib <> NIL) and (fShapeKind <> shNone) THEN
  179.     v := v + 2 * fPenThickness + fSpacing
  180.    ELSE IF fShapeKind = shOval THEN
  181.     v := v + fPenThickness + fSpacing;
  182.  
  183.    IF fShapeKind <> shNone THEN
  184.     v := v + fShadow;
  185.    END;
  186.  END;
  187.  
  188.  
  189.  PROCEDURE TNode.Condense;
  190.   VAR
  191.    sib, child : TNode;
  192.  BEGIN
  193.   IF (fShapeKind = shRect) and (fFirstChild = NIL) THEN
  194.    BEGIN
  195.     sib := fNextChild;
  196.     IF sib <> NIL THEN
  197.      IF (sib.fFirstChild = NIL) and (sib.fShapeKind = shRect) THEN
  198.       BEGIN
  199.        fShapeKind := shRectNone;
  200.        fNextChild := NIL;
  201.        fFirstChild := sib;
  202.        child := sib;
  203.        while child <> NIL do
  204.         IF (child.fFirstChild = NIL) and (child.fShapeKind = shRect) THEN
  205.          BEGIN
  206.           child.fShapeKind := shNone;
  207.           sib := child;
  208.           child := child.fNextChild;
  209.          END
  210.         ELSE
  211.          BEGIN
  212.           fNextChild := child;
  213.           sib.fNextChild := NIL;
  214.           child := NIL;
  215.          END;
  216.       END;
  217.    END
  218.   ELSE
  219.    BEGIN
  220.     child := fFirstChild;
  221.     IF (child <> NIL) and (fAlignment <> alLeft) and (fShapeKind <> shNone) THEN
  222.      fShapeKind := shRoundRect;
  223.     while child <> NIL do
  224.      BEGIN
  225.       child.Condense;
  226.       child := child.fNextChild;
  227.      END;
  228.    END;
  229.  END;
  230.  
  231.  
  232.  PROCEDURE TNode.Draw(area: Rect; forPicture: BOOLEAN);
  233.   VAR
  234.    ignore: Rect;
  235.    endPt:  Point;
  236.    intersect: BOOLEAN;
  237.  
  238.  BEGIN
  239.   intersect := SectRect(area, fBounds, ignore);
  240.  
  241.   IF forPicture AND (fShapeKind <> shNone) THEN {don't group if there is no enclosure}
  242.    PicComment(picGrpBeg, 0, NIL);
  243.  
  244.   DrawEnclosure(forPicture);
  245.   DrawCaption(forPicture);
  246.   endPt := thePort^.pnLoc;
  247.  
  248.   IF forPicture AND (fShapeKind <> shNone) THEN
  249.    PicComment(picGrpEnd, 0, NIL);
  250.  
  251.   IF intersect THEN
  252.    DrawChildren(area, forPicture);
  253.  
  254.   IF fNumber <> '' THEN
  255.    DrawNumber(area, forPicture, endPt);
  256.  END;
  257.  
  258.  
  259.  PROCEDURE TNode.DrawCaption(forPicture: BOOLEAN);
  260.   VAR
  261.    w, h, v, ignore : INTEGER;
  262.    s: String80;
  263.  BEGIN
  264.   MeasureText(v, ignore, w);
  265.   v := fBounds.top + v;
  266.  
  267.   IF forPicture THEN
  268.    BEGIN
  269.    SetHandleSize(commentHandle, SIZEOF(TTxtPicRec));
  270.    WITH HTxtPicRec(commentHandle)^^ DO
  271.     BEGIN
  272.     CASE fAlignment OF
  273.      alLeft:   tJus := 1;
  274.      alMiddle: tJus := 2;
  275.      alRight:  tJus := 3;
  276.      OTHERWISE tJus := 1;
  277.      END;
  278.  
  279.     tFlip := 0;
  280.     tRot := 0;
  281.     tLine := 2;
  282.     tXtra := 0
  283.     END;
  284.  
  285.    PicComment(picTxtBeg, SIZEOF(TTxtPicRec), commentHandle);
  286.  
  287.    SetHandleSize(commentHandle, 0);
  288.    END;
  289.  
  290.   case fAlignment OF
  291.    alLeft :
  292.     h := fBounds.left + fTree.fTypeSize;
  293.    alMiddle :
  294.     h := (fBounds.left + fBounds.right - w) div 2;
  295.    alRight :
  296.     h := fBounds.right - fTree.fTypeSize - w;
  297.   END;
  298.  
  299.   MoveTo(h, v);
  300.   s := fCaption; {In case of heap compaction}
  301.   DrawString(s);
  302.  
  303.   IF forPicture THEN
  304.    PicComment(picTxtEnd, 0, NIL);
  305.  END;
  306.  
  307.  
  308.  PROCEDURE TNode.DrawChildren(area: Rect; forPicture: BOOLEAN);
  309.   VAR
  310.    child : TNode;
  311.  BEGIN
  312.   child := fFirstChild;
  313.   while child <> NIL do
  314.    BEGIN
  315.     child.Draw(area, forPicture);
  316.     child.DrawLink(child.fNextChild, forPicture);
  317.     child := child.fNextChild;
  318.    END;
  319.  END;
  320.  
  321.  
  322.  PROCEDURE TNode.DrawEnclosure(forPicture: BOOLEAN);
  323.   VAR
  324.     thickness, roundness, shadowOffset: INTEGER;
  325.     r: Rect;
  326.     shadow: Rect;
  327.  BEGIN
  328.    WITH fTree do
  329.     BEGIN
  330.     thickness := fPenThickness;
  331.     roundness := 3 * fTypeSize;
  332.     r := fBounds;
  333.     END;
  334.  
  335.    shadowOffset := fTree.fShadow;
  336.    IF shadowOffset > 0 THEN
  337.     BEGIN
  338.     shadow := r;
  339.     OffsetRect(shadow, shadowOffset, shadowOffset);
  340.     END;
  341.  
  342.    IF forPicture THEN
  343.     InsetRect(r, (thickness+1) DIV 2, (thickness+1) DIV 2);
  344.  
  345.    PenSize(thickness, thickness);
  346.  
  347.    case fShapeKind OF
  348.     shRect, shRectNone :
  349.      BEGIN
  350.      IF shadowOffset > 0 THEN
  351.       BEGIN
  352.       FillRect(shadow, black);
  353.       FillRect(r, white);
  354.       END;
  355.      FrameRect(r);
  356.  
  357.      IF fDoubled THEN
  358.       BEGIN
  359.       InsetRect(r, (3 * thickness) DIV 2 + 2, 0);
  360.       FrameRect(r);
  361.       END;
  362.      END;
  363.  
  364.     shOval :
  365.      BEGIN
  366.      IF shadowOffset > 0 THEN
  367.       BEGIN
  368.       FillOval(shadow, black);
  369.       FillOval(r, white);
  370.       END;
  371.      FrameOval(r);
  372.      END;
  373.  
  374.     shRoundRect :
  375.      BEGIN
  376.      IF shadowOffset > 0 THEN
  377.       BEGIN
  378.       FillRoundRect(shadow, roundness, roundness, black);
  379.       FillRoundRect(r, roundness, roundness, white);
  380.       END;
  381.  
  382.      FrameRoundRect(r, roundness, roundness);
  383.      END;
  384.  
  385.     shNone :
  386.    END;
  387.  END;
  388.  
  389.  
  390.  PROCEDURE TNode.DrawLink(sib : TNode; forPicture: BOOLEAN);
  391.   VAR
  392.    h, v : INTEGER;
  393.  BEGIN
  394.  { do nothing, so that we have no links between sibling classes.
  395.   IF (sib <> NIL) and (fShapeKind <> shNone) THEN
  396.    BEGIN
  397.     with fBounds do
  398.      BEGIN
  399.       h := (left + right) div 2;
  400.       v := bottom;
  401.      END;
  402.     MoveTo(h, v);
  403.     LineTo(h, sib.fBounds.top);
  404.    END;
  405.  }
  406.  END;
  407.  
  408.  
  409.  PROCEDURE TNode.DrawNumber(area: Rect; forPicture: BOOLEAN; endCaption: Point);
  410.   VAR
  411.     thickness: INTEGER;
  412.     widHalf: INTEGER;
  413.     htHalf: INTEGER;
  414.     s: NumStr;
  415.     r: Rect;
  416.     f: FontInfo;
  417.     x: INTEGER;
  418.     dh: INTEGER;
  419.     dv: INTEGER;
  420.  
  421.  BEGIN
  422.   IF forPicture THEN
  423.    PicComment(picGrpBeg, 0, NIL);
  424.  
  425.   thickness := fTree.fPenThickness * 2;
  426.   IF thickness > 4 THEN
  427.    thickness := 4;
  428.  
  429.   TextFont(fTree.fTypeFont);
  430.   TextFace([bold]);
  431.   TextSize(fTree.fTypeSize);
  432.   GetFontInfo(f);
  433.   PenSize(thickness, thickness);
  434.  
  435.   s := fNumber;
  436.   widHalf := StringWidth(s) DIV 2 + 2 * thickness;
  437.   htHalf := (f.ascent + f.descent + f.leading) DIV 2 + 2 * thickness;
  438.   IF widHalf > htHalf THEN
  439.    x := widHalf
  440.   ELSE
  441.    x := htHalf;
  442.  
  443.   endCaption.h := endCaption.h + htHalf * 3;
  444.  
  445.   SetRect(r, -x, -x, x, x);
  446.   OffsetRect(r, endCaption.h + widHalf - 2 * thickness,
  447.                 endCaption.v + htHalf - f.ascent - f.leading - 2 * thickness);
  448.  
  449.   dh := 0;
  450.   dv := 0;
  451.  
  452.   IF r.left < 0 THEN
  453.    dh := -r.left
  454.   ELSE IF r.right > fTree.fHead.fBounds.right THEN
  455.    dh := fTree.fHead.fBounds.right - r.right;
  456.  
  457.   IF r.top < 0 THEN
  458.    dv := -r.top
  459.   ELSE IF r.bottom > fTree.fHead.fBounds.bottom THEN
  460.    dv := fTree.fHead.fBounds.bottom - r.bottom;
  461.  
  462.   endCaption.h := endCaption.h + dh;
  463.   endCaption.v := endCaption.v + dv;
  464.   OffsetRect(r, dh, dv);
  465.  
  466.   FillOval(r, white);
  467.   FrameOval(r);
  468.   MoveTo(endCaption.h, endCaption.v);
  469.   DrawString(s);
  470.  
  471.   IF forPicture THEN
  472.    PicComment(picGrpEnd, 0, NIL);
  473.  END;
  474.  
  475.  
  476.  PROCEDURE TNode.Locate (middle : INTEGER;
  477.          VAR v : INTEGER);
  478.   VAR
  479.    dh, dv, ignore : INTEGER;
  480.    child : TNode;
  481.    r: Rect;
  482.  BEGIN
  483.   with fBounds do
  484.    BEGIN
  485.     dh := right;
  486.     dv := bottom;
  487.    END;
  488.  
  489.   SetRect(r, middle - (dh div 2), v, middle + (dh div 2), v + dv);
  490.   fBounds := r;
  491.  
  492.   MeasureText(ignore, dv, ignore);
  493.   v := v + dv;
  494.  
  495.   child := fFirstChild;
  496.   while child <> NIL do
  497.    BEGIN
  498.     child.Locate(middle, v);
  499.     child.AddLinkHeight(child.fNextChild, v);
  500.     child := child.fNextChild;
  501.    END;
  502.  
  503.   v := fBounds.bottom;
  504.  END;
  505.  
  506.  
  507.  PROCEDURE TNode.Measure (VAR dh, dv : INTEGER);
  508.   VAR
  509.    cdh, cdv, ignore : INTEGER;
  510.    child : TNode;
  511.    r: Rect;
  512.  BEGIN
  513.   MeasureText(ignore, dv, dh);
  514.  
  515.   with fTree do
  516.     dh := dh + 2 * (fTypeSize + fPenThickness);
  517.  
  518.   IF fDoubled THEN
  519.    dh := dh + 3 * fTree.fPenThickness + 4
  520.   ELSE IF (fShapeKind = shOval) OR (fShapeKind = shRoundRect) THEN {add some slop for these shapes}
  521.    dh := (dh * 9) div 7;
  522.  
  523.   child := fFirstChild;
  524.   while child <> NIL do
  525.    BEGIN
  526.     cdh := 0;
  527.     cdv := 0;
  528.     child.Measure(cdh, cdv);
  529.     IF cdh > dh THEN
  530.      dh := cdh;
  531.     dv := dv + cdv;
  532.     child.AddLinkHeight(child.fNextChild, dv);
  533.     child := child.fNextChild;
  534.    END;
  535.  
  536.   IF fFirstChild <> NIL THEN
  537.    IF (fFirstChild.fNextChild<>NIL) or (fShapeKind<>shRoundRect) or (fFirstChild.fShapeKind<>shRoundRect) THEN
  538.     with fTree do
  539.       dh := dh + 2 * (fTypeSize + fPenThickness);
  540.  
  541.   SetRect(r, 0, 0, dh, dv);
  542.  
  543.   fBounds := r;
  544.  
  545.   dh := dh + fTree.fShadow;
  546.   dv := dv + fTree.fShadow;
  547.  END;
  548.  
  549.  
  550.  PROCEDURE TNode.MeasureText (VAR topToBase, topToBottom, leftToRight : INTEGER);
  551.   VAR
  552.    typeInfo : FontInfo;
  553.    s : String80;
  554.    isTitle : boolean;
  555.    tSize : INTEGER;
  556.    extraToBottom : INTEGER;
  557.    i: INTEGER;
  558.  
  559.   BEGIN
  560.   isTitle := (fShapeKind = shNone) and (fTree.fPath[0] = self);
  561.  
  562.   TextFont(fTree.fTypeFont);
  563.   TextFace(fFace);
  564.   tSize := fTree.fTypeSize;
  565.   IF isTitle THEN
  566.    BEGIN
  567.    i := 1;
  568.    WHILE (i < nMdrwSizes) & (tSize >= mDrwSizes[i]) DO
  569.      i := i + 1;
  570.  
  571.    tSize := mDrwSizes[i];
  572.    END;
  573.  
  574.   TextSize(tSize);
  575.  
  576.   GetFontInfo(typeInfo);
  577.  
  578.   s := fCaption; {In case of heap compaction}
  579.   leftToRight := StringWidth(s);
  580.  
  581.   IF not gNowPrinting THEN
  582.    IF italic in fFace THEN
  583.     leftToRight := leftToRight + typeInfo.ascent - 2 * typeInfo.descent;
  584.  
  585.   extraToBottom := fTree.fPenThickness + fTree.fSpacing;
  586.   topToBase := typeInfo.ascent + extraToBottom;
  587.  
  588.   IF fShapeKind = shOval THEN {oval}
  589.    BEGIN
  590.     topToBase := topToBase + fTree.fSpacing;
  591.     extraToBottom := extraToBottom + ord(odd(topToBase))
  592.    END
  593.   ELSE IF fShapeKind = shRectNone THEN {first in a multi-line box}
  594.    extraToBottom := -fTree.fPenThickness - 3
  595.   ELSE IF fShapeKind = shNone THEN
  596.    IF isTitle THEN {title}
  597.      extraToBottom := topToBase + typeInfo.descent
  598.    ELSE IF fNextChild <> NIL THEN {middle of a multi-line box}
  599.     extraToBottom := -fTree.fPenThickness - 2;
  600.  
  601.   topToBottom := topToBase + typeInfo.descent + extraToBottom + fTree.fSpacing;
  602.  END;
  603.  
  604.  
  605.  PROCEDURE TTree.ITree (aTypeFont, aTypeSize: INTEGER; shadowed: BOOLEAN);
  606.    VAR
  607.     i: INTEGER;
  608.   BEGIN
  609.    fTypeFont := aTypeFont;
  610.    fTypeSize := aTypeSize;
  611.  
  612.    IF aTypeSize < 12 THEN
  613.     fPenThickness := 1
  614.    ELSE IF aTypeSize < 24 THEN
  615.     fPenThickness := 2
  616.    ELSE
  617.     fPenThickness := 4;
  618.  
  619.    IF shadowed THEN
  620.     fShadow := (fPenThickness + 3) DIV 2
  621.    ELSE
  622.     fShadow := 0;
  623.  
  624.    fSpacing := 1;
  625.    fHead := NIL;
  626.    fLastLevel := -2;
  627.   END;
  628.  
  629.  
  630.  PROCEDURE TTree.Free;
  631.   BEGIN
  632.    IF fLastLevel > -2 THEN
  633.     fPath[-1].Free;
  634.     INHERITED Free;
  635.   END;
  636.  
  637.  
  638.  PROCEDURE TTree.Draw(area: Rect; forPicture: BOOLEAN);
  639.   BEGIN
  640.    IF forPicture THEN
  641.     PicComment(picDwgBeg, 0, NIL);
  642.  
  643.    PenNormal;
  644.    fHead.Draw(area, forPicture);
  645.  
  646.    IF forPicture THEN
  647.     PicComment(picDwgEnd, 0, NIL);
  648.   END;
  649.  
  650.  
  651.  PROCEDURE TTree.GenLine (inputLine : String80);
  652.   VAR
  653.    level, len, position : INTEGER;
  654.    longerLine: STRING[82];
  655.    aCaption, keyword : String80;
  656.    anAlignment : KAlignment;
  657.    aStyle : Style;
  658.    aShape : KShape;
  659.    aNumber : NumStr;
  660.    dummy: STRING[1];
  661.    kwIndex: INTEGER;
  662.  
  663.  BEGIN
  664.   dummy := '$';
  665.   len := Length(inputLine);
  666.   longerLine := Concat(inputLine, ' ');
  667.   position := 1;
  668.   {Advance past tabs, spaces, etc - i.e. find level}
  669.   while (position <= len) & (ord(longerLine[position]) <= ord(' ')) do
  670.    position := position + 1;
  671.   IF position > len THEN
  672.    exit(GenLine);
  673.   level := position - 1;
  674.  
  675.   keyword := '';
  676.   while (position <= len) & (ord(longerLine[position]) > ord(' ')) & (longerLine[position] <> '*') do
  677.    BEGIN
  678.     dummy[1] := longerLine[position];
  679.     keyword := Concat(keyword, dummy);
  680.     position := position + 1;
  681.    END;
  682.  
  683.   kwIndex := nKeywords;
  684.   WHILE kwIndex > 0 DO
  685.    BEGIN
  686.    IF keyword = keywordTable[kwIndex].keyword THEN
  687.     LEAVE;
  688.    kwIndex := kwIndex - 1;
  689.    END;
  690.  
  691.   IF kwIndex = 0 THEN
  692.    position := level + 1;  {revert line ptr back to before keyword}
  693.  
  694.   WITH keywordTable[kwIndex] DO
  695.    BEGIN
  696.    anAlignment := itsAlignment;
  697.    aStyle := itsStyle;
  698.    aShape := itsShape;
  699.    END;
  700.  
  701.   IF longerLine[position] = '*' THEN
  702.    BEGIN
  703.    aStyle := aStyle + [bold];
  704.    position := position + 1;
  705.    END;
  706.  
  707.   while (position <= len) & (ord(longerLine[position]) <= ord(' ')) do
  708.    position := position + 1;
  709.  
  710.   Delete(longerLine, 1, position - 1); {delete keyword}
  711.   len := len - (position - 1); {adjust len accordingly}
  712.  
  713.   position := Pos('#', longerLine);
  714.   IF position > 0 THEN
  715.    BEGIN
  716.    IF len - position > kMaxNumStr THEN
  717.     len := kMaxNumStr + position;
  718.  
  719.    aNumber := Copy(longerLine, position+1, len-position);
  720.    len := position - 1;
  721.    END
  722.   ELSE
  723.    aNumber := '';
  724.  
  725.   aCaption := Copy(longerLine, 1, len);
  726.  
  727.   GenNode(level, aCaption, anAlignment, aStyle, aShape, aNumber);
  728.  END;
  729.  
  730.  
  731.  PROCEDURE TTree.GenNode (level : INTEGER;
  732.          aCaption : String80;
  733.          anAlignment : KAlignment;
  734.          aStyle : Style;
  735.          aShape : KShape;
  736.          aNumber : NumStr);
  737.   VAR
  738.    nd : TNode;
  739.  BEGIN
  740.   IF level >= maxDepth THEN
  741.    GenNode(maxDepth, aCaption, anAlignment, aStyle + [shadow], aShape, aNumber)
  742.   ELSE
  743.    BEGIN
  744.    New(nd);
  745.    fPath[level] := nd;
  746.    nd.INode(self, aCaption, anAlignment, aStyle, aShape, aNumber);
  747.    IF level >= 0 THEN
  748.     BEGIN
  749.     IF level > (fLastLevel + 1) THEN
  750.      GenNode(level - 1, 'MISSING LEVEL', alMiddle, [outline], shRect, '');
  751.     fPath[level - 1].AddChild(nd);
  752.     END;
  753.    fLastLevel := level;
  754.    END;
  755.  END;
  756.  
  757.  
  758.  PROCEDURE TTree.Layout (VAR viewRect : Rect);
  759.    VAR
  760.     dh, dv, dhPage, dvPage, dhView, dvView, h, v : INTEGER;
  761.   BEGIN
  762.    IF fLastLevel < 0 THEN
  763.     GenNode(0, 'NO TEXT', alMiddle, [outline], shRect, '');
  764.  
  765.    IF fPath[0].fNextChild = NIL THEN
  766.     fHead := fPath[0]
  767.    ELSE
  768.     fHead := fPath[-1];
  769.  
  770.    fHead.Condense;
  771.    dh := 0;
  772.    dv := 0;
  773.    fHead.Measure(dh, dv);
  774.  
  775.    SetRect(viewRect, 0, 0, dh+15, dv+15);
  776.    h := (dh + 1) div 2 + 10;
  777.    v := 0 + 10;
  778.    fHead.Locate(h, v);
  779.   END;
  780.  
  781.  
  782.  PROCEDURE TTree.SetFont (aTypeFont : INTEGER);
  783.   BEGIN
  784.    fTypeFont := aTypeFont;
  785.   END;
  786.  
  787.  
  788.  PROCEDURE TTree.SetSize (aTypeSize : INTEGER);
  789.   BEGIN
  790.    fTypeSize := aTypeSize;
  791.   END;
  792.  
  793.  
  794.  PROCEDURE TTree.SetThickness (aPenThickness : INTEGER);
  795.   BEGIN
  796.    fPenThickness := aPenThickness;
  797.   END;
  798.