home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Tex / td187src.lzh / MTPOPUPS.I < prev    next >
Text File  |  1991-06-08  |  17KB  |  549 lines

  1. (*#######################################################################
  2.                             M A G I C P O P U P S
  3.   #######################################################################
  4.   V1.01  19.11.90  Peter Hellinger   Popups können jetzt analog zu
  5.                                      den MagicDials verschoben werden
  6.   V1.00  21.10.90  Peter Hellinger
  7.   V0.01  02.09.90  Peter Hellinger
  8.   #######################################################################*)
  9.  
  10. IMPLEMENTATION MODULE mtPopups;
  11.  
  12. (*------------------------------*)
  13. (*       COMPILERSWITCHES       *)
  14. (*------------------------------*)
  15. (*  TDI-Version:   DEAKTIVIERT  *)
  16. (*------------------------------*)
  17. (* V-  Overflow-Checks          *)
  18. (* R-  Range-Checks             *)
  19. (* S-  Stack-Check              *)
  20. (* N-  NIL-Checks               *)
  21. (* T-  TDI-Compiler vor 3.01    *)
  22. (* Q+  Branch statt Jumps       *)
  23. (*                              *)
  24. (*------------------------------*)
  25. (*  MM2-Version:     AKTIVIERT  *)
  26. (*------------------------------*)
  27. (*$R-   Range-Checks            *)
  28. (*$S-   Stack-Check             *)
  29. (*                              *)
  30. (*------------------------------*)
  31.  
  32.  
  33. FROM SYSTEM     IMPORT  ADDRESS, ADR;
  34. FROM Storage    IMPORT  ALLOCATE, DEALLOCATE;
  35. FROM MagicSys   IMPORT  Nil, Null, Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7,
  36.                         Bit8, Bit9, Bit10, Bit11, Bit12, Bit13, Bit14, Bit15,
  37.                         LOC, Byte, ByteSet, sWORD, sINTEGER, sCARDINAL, sBITSET,
  38.                         lWORD, lINTEGER, lCARDINAL, lBITSET,
  39.                         CastToChar, CastToByte, CastToByteset, CastToInt,
  40.                         CastToCard, CastToBitset, CastToWord, CastToLInt,
  41.                         CastToLCard, CastToLBitset, CastToLWord, CastToAddr;
  42. FROM MagicAES   IMPORT  GBOX, GTEXT, GBOXTEXT, GIBOX, GSTRING, GTITLE,
  43.                         Exit, DISABLED, OBJECT, ObjcDraw, ObjcFind, TEDINFO,
  44.                         BEGMCTRL, ENDMCTRL, WindUpdate, WFFULLXYWH, WindGet,
  45.                         FormButton, GrafHandle, MUKEYBD, MUBUTTON, MUM1, 
  46.                         MUM2, MUMESAG, MUTIMER, EvntMulti, AESIntIn, AESIntOut,
  47.                         AESCall;
  48. FROM mtAppl     IMPORT  VDIHandle, MouseOn, MouseOff, MouseArrow, MouseHand;
  49. FROM mtArea     IMPORT  AREA, NewAREA, DisposeAREA, FreeArea, SaveArea,
  50.                         CopyArea, RestoreArea, MOVEUP, MOVEDOWN, MOVELEFT,
  51.                         MOVERIGHT, MoveArea;
  52. FROM MagicStrings  IMPORT  Assign, Append, Length;
  53. IMPORT  MagicAES, MagicVDI;
  54.  
  55.  
  56. TYPE    tRect =         RECORD
  57.                          x: sINTEGER;
  58.                          y: sINTEGER;
  59.                          w: sINTEGER;
  60.                          h: sINTEGER;
  61.                         END;
  62.  
  63. TYPE    obTree =        POINTER TO ARRAY [0..1000] OF MagicAES.OBJECT;
  64.         tString =       ARRAY [0..40] OF CHAR;
  65.         tTedPtr =       POINTER TO TEDINFO;
  66.  
  67. VAR     Main:           ARRAY [0..51] OF OBJECT;
  68.         MainTitle:      TEDINFO;
  69.         Sub:            ARRAY [0..51] OF OBJECT;
  70.         SubTitle:       TEDINFO;
  71.         mainArea:       AREA;
  72.         subArea:        AREA;
  73.         frontArea:      AREA;
  74.         SubBegin:       sINTEGER;
  75.         b:              sBITSET;
  76.         bool, rekExit:  BOOLEAN;
  77.         screen:         tRect;
  78.         chW, chH:       sINTEGER;
  79.         bW, bH:         sINTEGER;
  80.         mW, mH:         sINTEGER;
  81.  
  82.  
  83. PROCEDURE scanType (t: obTree; entry, flag: sINTEGER): sINTEGER;
  84. (* Scannt nach einem bestimmten Typflag *)
  85. VAR o, r: INTEGER;
  86. BEGIN
  87.  o:= entry;
  88.  WHILE (o >= entry)  DO
  89.   WITH t^[o] DO
  90.    IF flag = obType THEN  rekExit:= TRUE;  RETURN o;  END;
  91.    IF (obHead > -1) THEN
  92.     r:= scanType (t, obHead, flag);
  93.     IF rekExit THEN RETURN r; END;
  94.    END;
  95.    o:= obNext;
  96.   END;
  97.  END;
  98.  RETURN 0;
  99. END scanType;
  100.  
  101.  
  102. PROCEDURE SameLength (menu: obTree; num, max: sINTEGER);
  103. VAR i: sINTEGER;
  104. BEGIN
  105.  FOR i:= 0 TO num - 1 DO  menu^[i].obWidth:= max;  END;
  106. END SameLength;
  107.  
  108.  
  109. PROCEDURE PosMenu (menu: obTree; ob, maxW, maxH: sINTEGER);
  110. VAR x, y: sINTEGER;
  111.     b: sBITSET;
  112. BEGIN
  113.  WITH menu^[0] DO
  114.   IF ob > 0 THEN
  115.    x:= Main[0].obX + Main[ob].obX + (Main[ob].obWidth DIV 2);
  116.    y:= Main[0].obY + Main[ob].obY - (chW DIV 2);
  117.   ELSE
  118.    MagicAES.GrafMkstate (x, y, b, b);
  119.   END;
  120.   obX:= x;  obY:= y;  obWidth:= maxW;  obHeight:= maxH;
  121.   IF (obX + obWidth) > mW THEN  obX:= mW - obWidth - 1;  END;
  122.   IF (obY + obHeight) > mH THEN  obY:= mH - obHeight - 1;  END;
  123.   IF obX < screen.x THEN  obX:= screen.x + 1;  END;
  124.   IF obY < screen.y THEN  obY:= screen.y + 1;  END;
  125.  END;
  126. END PosMenu;
  127.  
  128.  
  129. PROCEDURE calcArea (tree: obTree; VAR frame: sINTEGER; VAR r: tRect);
  130. (* berechnet das umgebende Rechteck des Basis-Objekts *)
  131. VAR x: sINTEGER;
  132. BEGIN
  133.  frame:= ORD(tree^[0].Box.frame) + 1;
  134.  IF (frame > 127) THEN  frame:= 257 - frame;  END;
  135.  r.x:= tree^[0].obX - frame;
  136.  r.y:= tree^[0].obY - frame;
  137.  r.w:= tree^[0].obWidth + (frame * 2);
  138.  r.h:= tree^[0].obHeight + (frame * 2);
  139. END calcArea;
  140.  
  141.  
  142. PROCEDURE DoEvent (VAR x, y: sINTEGER;
  143.                    VAR button: sBITSET;
  144.                    VAR scan: sINTEGER): sBITSET;
  145. VAR event: sBITSET;
  146.     i:     sINTEGER;
  147.     split: RECORD
  148.             CASE: BOOLEAN OF
  149.              TRUE: wert: sINTEGER;|
  150.              FALSE: hi: CHAR;
  151.                     lo: CHAR;|
  152.             END;
  153.            END;
  154. BEGIN
  155.  (* Array's laden *)
  156.  event:= {MUKEYBD, MUTIMER, MUBUTTON};
  157.  AESIntIn[ 0]:= CastToInt (event);
  158.  AESIntIn[ 1]:= 257;
  159.  AESIntIn[ 2]:= 3;
  160.  AESIntIn[ 3]:= 0;
  161.  AESIntIn[14]:= 0;
  162.  AESIntIn[15]:= 0;
  163.  i:= AESCall(25, 16, 7, 1, 0);
  164.  event:= CastToBitset (i);
  165.  x:= AESIntOut[1];
  166.  y:= AESIntOut[2];
  167.  button:= CastToBitset (AESIntOut[3]);
  168.  (* kbshift:= CastToBitset (AESIntOut[4]); *)
  169.  split.wert:= AESIntOut[5];
  170.  scan:= CastToInt (split.hi);
  171.  (* ascii:= split.lo; *)
  172.  RETURN event;
  173. END DoEvent;
  174.  
  175.  
  176. PROCEDURE ScreenDim (VAR cw, ch, bw, bh, mw, mh: sINTEGER);
  177. VAR i: sINTEGER;
  178. BEGIN
  179.  MagicAES.GrafHandle (i, cw, ch, bw, bh);
  180.  MagicAES.WindGet (0, 7, screen);
  181.  mw:= screen.x + screen.w - 1;
  182.  mh:= screen.y + screen.h - 1;
  183. END ScreenDim;
  184.  
  185.  
  186. PROCEDURE Entprelle;
  187. VAR x, y:   sINTEGER;
  188.     button: sBITSET;
  189. BEGIN
  190.  REPEAT
  191.   MagicAES.GrafMkstate (x, y, button, b);
  192.  UNTIL button = {};
  193. END Entprelle;
  194.  
  195.  
  196.  
  197. PROCEDURE DoMenu (t: obTree; area: AREA): sINTEGER;
  198. CONST   Links =  Bit0;
  199.         Rechts = Bit1;
  200. VAR     x, y, ox, oy, i, f, j, o, d, xx, yy: sINTEGER;
  201.         ob, oldob, taste, scan, clicks: sINTEGER;
  202.         button, kbshift, event: sBITSET;
  203.         ascii: CHAR;
  204.         fr: tRect;
  205.  
  206.  PROCEDURE DrawBar (o: sINTEGER);
  207.  VAR r: tRect;
  208.  BEGIN
  209.   IF o > 0 THEN
  210.    r.x:= t^[0].obX + t^[o].obX;
  211.    r.y:= t^[0].obY + t^[o].obY;
  212.    r.w:= r.x + t^[o].obWidth - 1;
  213.    r.h:= r.y + t^[o].obHeight - 1;
  214.    MagicVDI.Bar (VDIHandle, r);
  215.   END;
  216.  END DrawBar;
  217.  
  218. BEGIN
  219.  i:= MagicVDI.SetWritemode (VDIHandle, MagicVDI.XOR);
  220.  i:= MagicVDI.SetFillcolor (VDIHandle, 1); 
  221.  bool:= MagicVDI.SetFillperimeter (VDIHandle, FALSE);
  222.  oldob:= -1;  ob:= -1;  ox:= -1;  oy:= -1;
  223.  WindUpdate (BEGMCTRL);
  224.  LOOP
  225.   event:= DoEvent (x, y, button, scan);
  226.   (* Objekt finden *)
  227.   IF (x # ox) OR (y # oy) THEN
  228.    ob:= MagicAES.ObjcFind (t, 0, 999, x, y);
  229.    ox:= x;
  230.    oy:= y;
  231.   END;
  232.   IF (MUKEYBD IN event) THEN
  233.    CASE scan OF
  234.     114,
  235.      28: (* Objekt selektiert *)
  236.          MouseOff;  DrawBar (oldob);  MouseOn;  EXIT;|
  237.      72: o:= ob;
  238.          IF o > 2 THEN
  239.           DEC (o);
  240.           IF (DISABLED IN t^[o].obState) THEN  DEC (o); END;
  241.           IF o >= 2 THEN  ob:= o;  END;
  242.          ELSE
  243.           ob:= t^[0].obTail;
  244.          END;
  245.          |
  246.      80: o:= ob;
  247.          IF (o < t^[0].obTail) AND (o > 1) THEN
  248.           INC (o);
  249.           IF (DISABLED IN t^[o].obState) THEN  INC (o); END;
  250.           IF o <= t^[0].obTail THEN  ob:= o;  END;
  251.          ELSE
  252.           ob:= 2;
  253.          END;
  254.          |
  255.      97: MouseOff;  DrawBar (oldob);  MouseOn;  ob:= -1;  EXIT;
  256.          |
  257.      ELSE ;
  258.    END;
  259.   END;
  260.   (* Rechte Maustaste? *)
  261.   IF (MUBUTTON IN event) AND (Rechts IN button) THEN
  262.    Entprelle;  MouseOff;  DrawBar (oldob);  MouseOn;  ob:= -1;  EXIT;
  263.   END;
  264.   (* Objekt gültig? *)
  265.   IF (ob > 1) AND NOT (DISABLED IN t^[ob].obState) THEN
  266.    (* Objekt selektiert? *)
  267.    IF ob # oldob THEN
  268.     MouseOff;
  269.     DrawBar (oldob);
  270.     DrawBar (ob);   
  271.     oldob:= ob;
  272.     MouseOn;
  273.    END;
  274.    (* Linke Maustaste? *)
  275.    IF (MUBUTTON IN event) AND (Links IN button) THEN
  276.     Entprelle;  MouseOff;  DrawBar (oldob);  MouseOn;  EXIT;
  277.    END;
  278.   ELSIF (ob = 1) THEN
  279.    IF (MUBUTTON IN event) AND (Links IN button) THEN
  280.     MouseHand;
  281.     LOOP
  282.      MagicAES.GrafMkstate (x, y, button, b);
  283.      IF NOT (Links IN button) THEN  EXIT;  END;
  284.      IF (x # ox) OR (y # oy) THEN
  285.       calcArea (t, f, fr);
  286.       bool:= SaveArea (frontArea, fr);
  287.       
  288.       (* Vertikale Bewegung *)
  289.       d:= oy - y;
  290.       IF (d > 0) THEN (* Menü nach oben bewegt *)
  291.        MoveArea (area, d, MOVEUP, xx, yy);
  292.        t^[0].obY:= yy + f;
  293.       ELSIF (d < 0) THEN  (* Menü nach unten bewegt *)
  294.        MoveArea (area, ABS(d), MOVEDOWN, xx, yy);
  295.        t^[0].obY:= yy + f;
  296.       END;
  297.       calcArea (t, f, fr);
  298.       CopyArea (frontArea, fr.x, fr.y);
  299.       (* Horizontale Bewegung *)
  300.       d:= ox - x;;
  301.       IF (d > 0) THEN (* Menü nach links bewegt *)
  302.        MoveArea (area, d, MOVELEFT, xx, yy);
  303.        t^[0].obX:= xx + f;
  304.       ELSIF (d < 0) THEN (* Dialog nach rechts bewegt *)
  305.        MoveArea (area, ABS(d), MOVERIGHT, xx, yy);
  306.        t^[0].obX:= xx + f;
  307.       END;
  308.       calcArea (t, f, fr);
  309.       CopyArea (frontArea, fr.x, fr.y);
  310.       ox:= x;  oy:= y;
  311.      END;
  312.     END; (* LOOP *)
  313.     calcArea (t, f, fr);
  314.     CopyArea (frontArea, fr.x, fr.y);
  315.     MouseArrow;
  316.     FreeArea (frontArea);
  317.    END;
  318.   END;
  319.  END; (* LOOP *)
  320.  i:= MagicVDI.SetWritemode (VDIHandle, MagicVDI.REPLACE);
  321.  WindUpdate (ENDMCTRL);
  322.  RETURN ob;
  323. END DoMenu;
  324.  
  325.  
  326. PROCEDURE MakeMenu (tree, menu: obTree; title: ADDRESS;
  327.                     subnum, type: sINTEGER): sINTEGER;
  328. VAR maxW, maxH, num, i, j, ob, len, offset: sINTEGER;
  329.     ted: tTedPtr;
  330. BEGIN
  331.  ted:= title;  len:= ted^.teTxtlen;
  332.  j:= 0;  num:= 0;  maxW:= (len + 4) * chW;  maxH:= chH + 1;  
  333.  (*-- Basisobjekt --*)
  334.  menu^[num].obNext:=    -1;
  335.  menu^[num].obHead:=    1;
  336.  menu^[num].obTail:=    0;
  337.  menu^[num].obType:=    GBOX;
  338.  menu^[num].obFlags:=   {};
  339.  menu^[num].obState:=   {};
  340.  menu^[num].Box.char:=  0C;
  341.  menu^[num].Box.frame:= 377C;
  342.  menu^[num].Box.flags:= {Bit15, Bit11};
  343.  menu^[num].obX:=       0;
  344.  menu^[num].obY:=       0;
  345.  menu^[num].obWidth:=   0;
  346.  menu^[num].obHeight:=  0;
  347.  INC (num);
  348.  (*-- Titelzeile --*)
  349.  menu^[num].obNext:=    -1;
  350.  menu^[num].obHead:=    -1;
  351.  menu^[num].obTail:=    -1;
  352.  menu^[num].obType:=    GBOXTEXT;
  353.  menu^[num].obFlags:=   {};
  354.  menu^[num].obState:=   {};
  355.  menu^[num].TedPtr:=    title;
  356.  menu^[num].obX:=       0;
  357.  menu^[num].obY:=       0;
  358.  menu^[num].obWidth:=   0;
  359.  menu^[num].obHeight:=  chH;
  360.  MagicAES.ObjcAdd (menu, 0, num);
  361.  INC (num);
  362.  (*-- Suchposition im Baum festlegen --*)
  363.  IF subnum > 0 THEN
  364.   ob:= SubBegin + 1;
  365.   FOR j:= 1 TO (subnum - 3) DO  ob:= tree^[ob].obNext;  END;
  366.   IF ob < SubBegin THEN RETURN -1; END;
  367.   offset:= ob - 1;
  368.   j:= tree^[ob].obHead;
  369.  ELSE
  370.   ob:= 2;  offset:= 1;  j:= 0;
  371.  END;
  372.  (*-- Objekte addieren --*)
  373.  LOOP
  374.   i:= scanType (tree, j, type);
  375.   IF tree^[i].obWidth > maxW THEN  maxW:= tree^[i].obWidth;  END;
  376.   menu^[num].obNext:=    -1;
  377.   menu^[num].obHead:=    -1;
  378.   menu^[num].obTail:=    -1;
  379.   menu^[num].obType:=    tree^[i].obType;
  380.   menu^[num].obFlags:=   tree^[i].obFlags;
  381.   menu^[num].obState:=   tree^[i].obState;
  382.   menu^[num].StringPtr:= tree^[i].StringPtr;
  383.   menu^[num].obX:=       0;
  384.   menu^[num].obY:=       maxH;
  385.   menu^[num].obWidth:=   tree^[i].obWidth;
  386.   menu^[num].obHeight:=  chH;
  387.   MagicAES.ObjcAdd (menu, 0, num);
  388.   INC (num);
  389.   INC (maxH, chH);  j:= i + 1;
  390.   IF i = tree^[ob].obTail THEN  EXIT;  END;
  391.  END;
  392.  SameLength (menu, num, maxW);
  393.  PosMenu (menu, subnum, maxW, maxH);
  394.  (*-- Offset für weitere Suche merken --*)
  395.  IF subnum = 0 THEN  SubBegin:= j; END;
  396.  RETURN offset;
  397. END MakeMenu;
  398.  
  399.  
  400. PROCEDURE PopupMenu (menu: ADDRESS; title: ARRAY OF CHAR): sINTEGER; 
  401. VAR i, j, m, s, ret, len, ob, oldob, off1, off2: sINTEGER;
  402.     r:      tRect;
  403.     bool:   BOOLEAN;
  404.     t:      obTree;
  405. BEGIN
  406.  IF menu = NIL THEN  RETURN -1;  END;
  407.  ScreenDim (chW, chH, bW, bH, mW, mH);
  408.  ret:= -1;  t:= menu;  len:= Length (title);  j:= 0;
  409.  MainTitle.tePtext:= ADR (title);
  410.  MainTitle.tePtmplt:= ADR (title);
  411.  MainTitle.tePvalid:= ADR (title);
  412.  MainTitle.teFont:= 3;
  413.  MainTitle.teResvd1:= 0;
  414.  MainTitle.teJust:= 2;
  415.  MainTitle.teColor:= 011A1H;
  416.  MainTitle.teResvd2:= 0;
  417.  MainTitle.teThickness:= -1;
  418.  MainTitle.teTxtlen:= len;
  419.  MainTitle.teTmplen:= len;
  420.  off1:= MakeMenu (t, ADR(Main), ADR(MainTitle), 0, GTITLE);
  421.  calcArea (ADR(Main), j, r);
  422.  bool:= SaveArea (mainArea, r);
  423.  ObjcDraw (ADR(Main), 0, 51, screen);
  424.  MouseOn;
  425.  LOOP
  426.   m:= DoMenu (ADR(Main), mainArea) + off1;
  427.   IF m < 1 THEN  ret:= -1;  EXIT; END;
  428.   IF Exit IN t^[m].obFlags THEN  ret:= m;  EXIT;  END;
  429.   IF m > 2 THEN
  430.    len:= Length (Main[m - off1].StringPtr^);
  431.    SubTitle.tePtext:= ADDRESS (Main[m - off1].StringPtr);
  432.    SubTitle.tePtmplt:= ADDRESS (Main[m - off1].StringPtr);
  433.    SubTitle.tePvalid:= ADDRESS (Main[m - off1].StringPtr);
  434.    SubTitle.teFont:= 3;
  435.    SubTitle.teResvd1:= 0;
  436.    SubTitle.teJust:= 2;
  437.    SubTitle.teColor:= 011A1H;
  438.    SubTitle.teResvd2:= 0;
  439.    SubTitle.teThickness:= -1;
  440.    SubTitle.teTxtlen:= len;
  441.    SubTitle.teTmplen:= len;
  442.    off2:= MakeMenu (t, ADR(Sub), ADR(SubTitle), m, GSTRING);
  443.    calcArea (ADR(Sub), j, r);
  444.    bool:= SaveArea (subArea, r);
  445.    ObjcDraw (ADR(Sub), 0, 51, screen);
  446.    s:= DoMenu (ADR(Sub), subArea);
  447.    RestoreArea (subArea);
  448.    IF s > 0 THEN  ret:= s + off2;  EXIT; END;
  449.   END; (* IF m > 2 *)
  450.  END; (* LOOP *)
  451.  RestoreArea (mainArea);
  452.  FreeArea (subArea);
  453.  FreeArea (mainArea);
  454.  RETURN ret;
  455. END PopupMenu;
  456.  
  457.  
  458. PROCEDURE StringPopup (VAR string: ARRAY OF CHAR; title: ARRAY OF CHAR): sINTEGER;
  459. VAR i, j, m, s, l1, l2, maxW, maxH, num: sINTEGER;
  460.     mr, sr: tRect;
  461.     bool: BOOLEAN;
  462.     StrArray: ARRAY [0..49] OF tString;
  463.     t: obTree;
  464. BEGIN
  465.  ScreenDim (chW, chH, bW, bH, mW, mH);
  466.  l1:= Length (string);  l2:= Length (title);
  467.  i:= 0;  j:= 0;  num:= 0;
  468.  (*-- Basisobjekt --*)
  469.  Main[num].obNext:=    -1;
  470.  Main[num].obHead:=    1;
  471.  Main[num].obTail:=    0;
  472.  Main[num].obType:=    GBOX;
  473.  Main[num].obFlags:=   {};
  474.  Main[num].obState:=   {};
  475.  Main[num].Box.char:=  0C;
  476.  Main[num].Box.frame:= 377C;
  477.  Main[num].Box.flags:= {Bit15, Bit11};
  478.  Main[num].obX:=       0;
  479.  Main[num].obY:=       0;
  480.  Main[num].obWidth:=   0;
  481.  Main[num].obHeight:=  0;
  482.  INC (num);
  483.  (*-- Titelzeile --*)
  484.  Main[num].obNext:=    -1;
  485.  Main[num].obHead:=    -1;
  486.  Main[num].obTail:=    -1;
  487.  Main[num].obType:=    GBOXTEXT;
  488.  Main[num].obFlags:=   {};
  489.  Main[num].obState:=   {};
  490.  Main[num].TedPtr:=    ADR(MainTitle);
  491.  Main[num].obX:=       0;
  492.  Main[num].obY:=       0;
  493.  Main[num].obWidth:=   0;
  494.  Main[num].obHeight:=  chH;
  495.  MagicAES.ObjcAdd (ADR(Main), 0, num);
  496.  INC (num);
  497.  MainTitle.tePtext:= ADR (title);
  498.  MainTitle.tePtmplt:= ADR (title);
  499.  MainTitle.tePvalid:= ADR (title);
  500.  MainTitle.teFont:= 3;
  501.  MainTitle.teResvd1:= 0;
  502.  MainTitle.teJust:= 2;
  503.  MainTitle.teColor:= 011A1H;
  504.  MainTitle.teResvd2:= 0;
  505.  MainTitle.teThickness:= -1;
  506.  MainTitle.teTxtlen:= l2;
  507.  MainTitle.teTmplen:= l2;
  508.  i:= 0;  j:= 0;  maxW:= (l2 + 2)* chW;  maxH:= chH + 1;
  509.  LOOP
  510.   s:= 0; 
  511.   WHILE (i < l1) AND (string[i] # '|') AND (s < 40) DO
  512.    StrArray[j, s]:= string[i];  INC (i);  INC (s);
  513.   END;
  514.   StrArray[j, s]:= 0C;
  515.   Main[num].obNext:=    -1;
  516.   Main[num].obHead:=    -1;
  517.   Main[num].obTail:=    -1;
  518.   Main[num].obType:=    GSTRING;
  519.   Main[num].obFlags:=   {};
  520.   Main[num].obState:=   {};
  521.   Main[num].StringPtr:= ADR(StrArray[j]);
  522.   Main[num].obX:=       0;
  523.   Main[num].obY:=       maxH;
  524.   Main[num].obWidth:=   (s + 2) * chW;
  525.   IF Main[num].obWidth > maxW THEN  maxW:= Main[num].obWidth;  END;
  526.   Main[num].obHeight:=  chH;
  527.   MagicAES.ObjcAdd (ADR(Main), 0, num);
  528.   INC (num);  INC (j);  INC (maxH, chH);
  529.   IF string[i] = 0C THEN  EXIT;  ELSE  INC (i);  END;
  530.  END;
  531.  SameLength (ADR(Main), num, maxW);
  532.  PosMenu (ADR(Main), 0, maxW, maxH);
  533.  calcArea (ADR(Main), j, mr);
  534.  bool:= SaveArea (mainArea, mr);
  535.  MouseOn;
  536.  ObjcDraw (ADR(Main), 0, 51, screen);
  537.  m:= DoMenu (ADR(Main), mainArea);
  538.  RestoreArea (mainArea);
  539.  FreeArea (mainArea);
  540.  IF m > 0 THEN  RETURN m - 1;  ELSE  RETURN -1;  END;
  541. END StringPopup;
  542.  
  543.  
  544. BEGIN
  545.  bool:= NewAREA (mainArea);
  546.  bool:= NewAREA (subArea);
  547.  bool:= NewAREA (frontArea);
  548. END mtPopups.
  549.