home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / turbopas / wndw_msj.arc / WNDWMSJ2.PAS < prev   
Pascal/Delphi Source File  |  1988-11-19  |  10KB  |  318 lines

  1. {From Micro/Systems Journal, Dec 88}
  2. {Advanced windowing package -
  3.    by Stephen Randy Davis, 1988
  4.  This windowing package does not suffer from the single-tasking
  5.  limitations of many windowing packages.  Specifically, these
  6.  windows may be scrolled independently, even windows that are
  7.  not currently on top.
  8.  }
  9. {Toad Hall Tweaks:
  10.  Using PRED(int) instead of int - 1, SUCC(int) instead of int + 1
  11.  Using ShL 1 instead of *2
  12.  Writing back to Turbo 3.0 (replacing 'word' with INTEGER)
  13.  Changing test attributes to 'normal', 'underlined', and 'reverse'
  14.  for mono screens.
  15.  
  16. }
  17.  
  18. TYPE
  19.   datablock = ARRAY[0..1] OF INTEGER;
  20.   Str80 = STRING[80];
  21.   windowNodePtr = ^windowNode;
  22.   masktype = INTEGER;  {TH}
  23.   windowNode = RECORD
  24.                  signature         : INTEGER;
  25.                  deltaX,deltaY     : INTEGER;
  26.                  winX,winY         : INTEGER;
  27.                  color             : INTEGER;
  28.                  currentX,currentY : INTEGER;
  29.                  priority,mask     : masktype;
  30.                  next              : windowNodePtr;
  31.                  dsize             : INTEGER;
  32.                  data              : ^datablock;
  33.                END;
  34.  
  35. CONST
  36.   CGA = $B800;      {offset of CGA/EGA}
  37.   MONO = $B000;     {mono screen}
  38.   WINSIG = $1234;
  39.  
  40. VAR
  41.   head : windowNodePtr;  {pointer to the window list}
  42.   screen : ARRAY[0..24] OF ARRAY[0..79] OF INTEGER
  43.            absolute mono:0;  {currently set for mono}
  44.   accessrights : ARRAY[0..24] OF ARRAY[0..79] OF masktype;
  45.  
  46.  
  47. {These procedures are required internally}
  48.  
  49. PROCEDURE Sig_Check(w : windowNodePtr; Msg : Str80);
  50.   {Check the node signature to make sure it's valid}
  51.   BEGIN
  52.     IF w^.signature <> WINSIG THEN BEGIN
  53.       Writeln('Signature Error: ', Msg);
  54.       Halt;
  55.     END;
  56.   END;  {of Sig_Check}
  57.  
  58.  
  59. PROCEDURE Window_Add(before, w : windowNodePtr);
  60.   {Add a window to the window list}
  61.   BEGIN
  62.     Sig_Check(w,      'Window Add W argument');
  63.     Sig_Check(before, 'Window Add Before argument');
  64.     w^.next := before^.next;
  65.     before^.next := w;
  66.   END;  {of Window_Add}
  67.  
  68.  
  69. PROCEDURE Window_Remove(w : windowNodePtr);
  70.   {Remove a window from the window list}
  71.   VAR  pntr : windowNodePtr;
  72.   BEGIN
  73.     Sig_Check(w, 'WindowRemove W argument');
  74.     pntr := head;
  75.     WHILE pntr <> NIL DO BEGIN
  76.       IF pntr^.next = w
  77.       THEN pntr^.next := w^.next;
  78.       pntr := pntr^.next;
  79.     END;
  80.   END;  {of Window_Remove}
  81.  
  82.  
  83. FUNCTION _precedence (w : windowNodePtr) : masktype;
  84.   {Calculate the precedence of a window in the list}
  85.   VAR
  86.     pntr : windowNodePtr;
  87.     p    : masktype;
  88.   BEGIN
  89.     IF w <> NIL THEN Sig_Check(w, 'Precedence W argument');
  90.     p := 0;
  91.     pntr := head^.next;
  92.     WHILE pntr <> w DO BEGIN
  93.       Sig_Check(pntr, 'Precedence chain traversal');
  94.       p := p OR pntr^.priority;
  95.       pntr := pntr^.next;
  96.     END;
  97.     _precedence := p;
  98.   END;  {of _precedence}
  99.  
  100.  
  101. PROCEDURE New_Mask(VAR w : windowNodePtr);  {TH the VAR is mine}
  102.   {Calculate a mask for the current window node}
  103.   VAR
  104.     mask,bit : masktype;
  105. {    pntr : windowNodePtr; unused}
  106.   BEGIN
  107.     mask := _precedence(NIL);
  108.     bit := 1;
  109.     WHILE (bit AND mask) <> 0 DO
  110.       bit := bit + bit;
  111.     IF bit <> 0 THEN BEGIN
  112.       w^.priority := bit;
  113.       w^.mask := NOT (mask OR bit);
  114.     END;
  115.   END;  {of New_Mask}
  116.  
  117.  
  118. PROCEDURE Set_Access(w : windowNodePtr);
  119.   {Add the current window to the access list}
  120.   VAR  x,y : INTEGER;  {TH}
  121.   BEGIN
  122.     Sig_Check(w, 'SetAccess window argument');
  123.     WITH w^ DO
  124.     FOR y := deltaY TO deltaY + PRED(winY) DO
  125.     FOR x := deltaX TO deltaX + PRED(winX) DO
  126.       accessrights [y][x] := accessrights [y][x] XOR priority;
  127.   END;  {of Set_Access}
  128.  
  129.  
  130. PROCEDURE Window_Paint (w : windowNodePtr);
  131.   {Paint the current window to the screen}
  132.   VAR x,y,offset : INTEGER;  {TH}
  133.   wd,ht : INTEGER;  {TH}
  134.   BEGIN
  135.     Sig_Check(w, 'WindowPaint window argument');
  136.     WITH w^ DO
  137.     FOR ht := 0 TO PRED(winY) DO BEGIN  {TH}
  138.       y := deltaY + ht;
  139.       offset := ht * winX;
  140.       FOR wd := 0 TO PRED(winX) DO BEGIN  {TH}
  141.         x := deltaX + wd;
  142.         IF (accessrights [y][x] AND mask) = 0
  143.         THEN screen [y][x] := w^.data^ [offset + wd];
  144.       END;  {for}
  145.     END;  {for}
  146.   END;  {of Window_Paint}
  147.  
  148.  
  149. PROCEDURE Restack;
  150.   {Restack the precedence of the windows in the list}
  151.   VAR  pntr : windowNodePtr;
  152.   BEGIN
  153.     pntr := head^.next;
  154.     WHILE pntr <> NIL DO BEGIN
  155.       pntr^.mask := _precedence(pntr);
  156.       Window_Paint(pntr);
  157.       pntr := pntr^.next;
  158.     END;  {while}
  159.   END;  {of Restack}
  160.  
  161.  
  162. PROCEDURE Window_Scroll(w : windowNodePtr; count : INTEGER);
  163.   {Scroll the current window by 'count' lines}
  164.   VAR  index,offset,total : INTEGER;  {TH}
  165.   BEGIN
  166.     WITH w^ DO
  167.     IF count > 0 THEN BEGIN
  168.       currentX := 0;                 {carriage return}
  169.       currentY := currentY + count;  {line feed(s)}
  170.       IF currentY >= winY            {if beyond window's end...}
  171.       THEN BEGIN                     {... scroll window's contents}
  172.         count := SUCC(currentY - winY);  {TH}
  173.         currentY := PRED(winY);          {TH}
  174.         offset := winX * count;
  175.         total := winX * (winY - count);
  176.         FOR index := 0 TO total DO
  177.           data^[index] := data^[index + offset];
  178.  
  179.         FOR index := total TO PRED(total + offset) DO  {TH}
  180.           data^[index] := color + INTEGER(' ');  {TH}
  181.       END;  {if scrolling}
  182.     END;  {with}
  183.     Window_Paint(w);
  184.   END;  {of Window_Scroll}
  185.  
  186. {User accessible functions are Window_Open, Window_Close, Window_Write,
  187.  and Window_Pop}
  188.  
  189.  
  190. FUNCTION window_Open (x,y,width,height,attr : INTEGER) : windowNodePtr;
  191.   {Open a window of the given size and color}
  192.   VAR
  193.     w : windowNodePtr;
  194.     i, j : INTEGER;  {TH}
  195.   BEGIN
  196.     NEW(w);
  197.     WITH w^ DO BEGIN
  198.       {Save data into window}
  199.       signature := WINSIG;  {store signature field in first thing}
  200.       deltaX := x;
  201.       deltaY := y;
  202.       winX := width;
  203.       winY := height;
  204.       color := attr;
  205.       currentX := 0;  {set cursor to beginning of window}
  206.       currentY := 0;
  207.  
  208.       {store off the section of screen into the windownode}
  209.       dsize := (winY * winX) ShL 1;  {TH}
  210.       GetMem(data,dsize);
  211.  
  212.       {Calculate priority of current window}
  213.       New_Mask(w);
  214.  
  215.       {Set the access list for this window}
  216.       Set_Access(w);
  217.  
  218.       {Now add window to the linked list}
  219.       Window_Add(head,w);
  220.  
  221.       {Finally, clear window and write it to the screen}
  222.       FOR i := 0 TO winY DO
  223.       FOR j := 0 to winX DO
  224.         data^[i * winX + j] := color;
  225.       WIndow_Paint(w);
  226.     END;
  227.     Window_Open := w;  {return function result}
  228.   END;  {of Window_Open}
  229.  
  230.  
  231. PROCEDURE Window_Close(VAR w : windowNodePtr);
  232.   {Close and remove the window from the window list}
  233.   BEGIN
  234.     Window_Remove(w);            {remove window from list}
  235.     Set_Access(w);               {now remove its mask}
  236.     FreeMem(w^.data, w^.dsize);  {free up its data memory}
  237.     Dispose(w);                  {and its node}
  238.     Restack;                     {repaint windows left}
  239.     w := NIL;                    {and return a NULL}
  240.   END;  {of Window_Close}
  241.  
  242.  
  243. PROCEDURE Window_Pop(before, w : windowNodePtr);
  244.   {Move the window 'w' after the window 'before' in the
  245.    window list.
  246.   }
  247.   BEGIN
  248.     Window_Remove(w);         {remove the window}
  249.     Window_Add(before,w);     {now reposition it}
  250.     Restack;                  {and redraw all windows}
  251.   END;  {of Window_Pop}
  252.  
  253.  
  254. PROCEDURE Window_Writeln(w : windowNodePtr; OutStr : Str80;
  255.                          nlines : INTEGER);  {TH}
  256.   {Write an ASCII string to the specified window}
  257.   VAR
  258.     i,vertoffset : INTEGER;  {TH}
  259.     count : BYTE absolute OutStr;
  260.   BEGIN
  261.     WITH w^ DO BEGIN
  262.       vertoffset := currentY * winX;
  263.       FOR i := 1 TO count DO
  264.       IF currentX < winX THEN BEGIN
  265.         data^ [vertoffset + currentX] := color + INTEGER(Outstr[i]);
  266.         currentX := SUCC(currentX);  {TH}
  267.       END;
  268.     END;  {with}
  269.     Window_Scroll(w,nlines);
  270.   END;  {of Window_Writeln}
  271.  
  272.  
  273.  
  274. PROCEDURE Exercise_W (w : windowNodePtr);
  275.   {Test code to write to and scroll the specified window}
  276.   VAR  i : INTEGER;
  277.   BEGIN
  278.     FOR i := 1 TO 100 DO
  279.       Window_Writeln(w,'This''s just a string', SUCC(i MOD 3) );  {TH}
  280.   END;  {of Exercise_W}
  281.  
  282.  
  283. VAR
  284.   background,w1,w2,w3 : windowNodePtr;
  285.   x,y : INTEGER;  {TH}
  286.  
  287. BEGIN  {main}
  288.   {Initialization section}
  289.   New(head);                    {define a head structure}
  290.   head^.signature := WINSIG;    {to point to the window list}
  291.   head^.next := NIL;
  292.   FOR y := 0 TO 24 DO           {clear the accessrights}
  293.   FOR x := 0 TO 79 DO
  294.     accessrights[y][x] := 0;
  295.   background := Window_Open(0,0,80,25,$0700);
  296.  
  297.   {Open a few overlapping windows and exercise them --
  298.    remove this to make this into an Advanced Window Unit}
  299.  
  300.   w1 := window_Open(10,10,50,10,$7000);   {1300H for CGA}
  301.   Exercise_W(w1);
  302.   w2 := window_Open(20,5,30,17,$0100);   {4200H for CGA}
  303.   Exercise_W(w2);
  304.   w3 := window_Open(30,7,20,8,$0700);    {2500H for CGA}
  305.   Exercise_W(w3);
  306.  
  307.   Exercise_W(w1);              {scroll background window}
  308.  
  309.   {change the order of the windows}
  310.   Window_Pop(w1,w2);           {pop window1 above window2}
  311.   Exercise_W(w1);              {and scroll it again}
  312.  
  313.   {remember to close the windows to remove this from the display}
  314.   Window_Close(w2);
  315.   Window_Close(w3);
  316.   Window_Close(w1);
  317. END.
  318.