home *** CD-ROM | disk | FTP | other *** search
/ Dream 48 / Amiga_Dream_48.iso / Atari / c / wrc_1_0.lzh / WRC.1_0 / WRC.C next >
C/C++ Source or Header  |  1992-10-04  |  11KB  |  455 lines

  1. /*********************************************************************
  2. *
  3. * WRC
  4. *
  5. * Kurzbeschreibung:
  6. * Modul zur Verwaltung und Bearbeitung von Rechtecklisten
  7. *
  8. * Versionen:
  9. * 1.0  mo  12.08.92  Basisversion
  10. *
  11. * Autoren:
  12. * mo   (\/) Martin Osieka, Erbacherstr. 2, D-6100 Darmstadt
  13. *
  14. *********************************************************************/
  15.  
  16. #include <stddef.h>
  17. #define MIN( a, b)  ((a) <= (b) ? (a) : (b))
  18. #define MAX( a, b)  ((a) >= (b) ? (a) : (b))
  19. #define FALSE 0
  20. #define TRUE  1
  21.  
  22.  
  23. #include <aes.h>
  24. #if 0
  25. #include <aesr.h>
  26. #else
  27. /* Nachbildung von Funktionen aus aesr.h */
  28. extern int rc_intersect( GRECT *r1, GRECT *r2);
  29. #define rc_set( r, x, y, w, h) \
  30.   (r)->g_x = (x); (r)->g_y = (y); (r)->g_w = (w); (r)->g_h = (h)
  31. #define wind_rget( win, mode, r) \
  32.   wind_get( win, mode, &(r)->g_x, &(r)->g_y, &(r)->g_w, &(r)->g_h)
  33. #define wind_gdesk( r) \
  34.   wind_rget( 0, WF_WORKXYWH, r)
  35. #define wind_gfirst( win, r) \
  36.   wind_rget( win, WF_FIRSTXYWH, r)
  37. #define wind_gnext( win, r) \
  38.   wind_rget( win, WF_NEXTXYWH, r)
  39. #endif
  40.  
  41. #include <wrc.h>
  42.  
  43. /********************************************************************/
  44.  
  45. #define MAXWRS 64
  46. static wrectS wrctable[ MAXWRS]; /* Speicherbereich fuer Rechtecke */
  47. static wrectS *wrcfree;          /* Liste freier Rechtecke */
  48. static int wrcinit;              /* TRUE: Modul ist initialisiert */
  49. /*
  50.  | Diese Rechteckverwaltung arbeitet auf einem statischen Speicher-
  51.  | bereich, da sich bei einer zu grossen Zersplitterung der
  52.  | sichtbaren Bereiche eines Fensters Scrollen nicht mehr lohnt.
  53.  */
  54.  
  55.  
  56. /*------------------------------------------------------------------*/
  57.  
  58. void wrc_init( void)
  59. {
  60.   wrectS *pwr;
  61.  
  62.   if (!wrcinit) {
  63.     wrcinit = TRUE;
  64.     wrcfree = NULL;
  65.     for (pwr = &wrctable[ MAXWRS-1]; pwr >= wrctable; pwr--) {
  66.       pwr->next = wrcfree;
  67.       wrcfree = pwr;
  68.     };
  69.   };
  70. } /* wrc_init */
  71.  
  72.  
  73. void wrc_exit( void)
  74. {
  75.   wrcinit = FALSE;
  76. } /* wrc_exit */
  77.  
  78.  
  79. wrectS *wrc_alloc( void)
  80. /*
  81.  | Die Funktion liefert einen Zeiger auf eine freie Rechteck-
  82.  | beschreibung (im Fehlerfall NULL).
  83.  */
  84. {
  85.   wrectS *pwr;
  86.  
  87.   if (!wrcinit) wrc_init();
  88.  
  89.   if ((pwr = wrcfree) != NULL) {
  90.     wrcfree = pwr->next;
  91.   };
  92.   return( pwr);
  93. } /* wrc_alloc */
  94.  
  95.  
  96. void wrc_free( wrectS *pwr)
  97. /*
  98.  | Gibt die Rechteckbeschreibung <wr> frei.
  99.  */
  100. {
  101.   pwr->next = wrcfree;
  102.   wrcfree = pwr;
  103. } /* wrc_free */
  104.  
  105.  
  106. wrectS *wrc_extract( wrectS *pwrprev)
  107. /*
  108.  | Extrahiert die Rechteckbeschreibung hinter <wrprev> aus der Liste.
  109.  */
  110. {
  111.   wrectS *pwr;
  112.  
  113.   pwr = pwrprev->next;
  114.   if (pwr != NULL) {
  115.     pwrprev->next = pwr->next;
  116.   };
  117.   return( pwr);
  118. } /* wrc_extract */
  119.  
  120.  
  121. wrectS *wrc_insert( wrectS *pwrprev, wrectS *pwr)
  122. /*
  123.  | Fuegt die Rechteckbeschreibung <wr> hinter <wrprev> in die
  124.  | Liste ein.
  125.  */
  126. {
  127.   pwr->next = pwrprev->next;
  128.   pwrprev->next = pwr;
  129.   return( pwr);
  130. } /* wrc_insert */
  131.  
  132.  
  133. wrectS *wrc_add( wrectS *pwrprev, GRECT *rect)
  134. /*
  135.  | Erzeugt eine neue Rechteckbeschreibung und fügt sie
  136.  | hinter <wrprev> in die Liste ein.
  137.  */
  138. {
  139.   wrectS *pwr;
  140.  
  141.   if ((pwr = wrc_alloc()) != NULL) {
  142.     pwr->next = pwrprev->next;
  143.     pwrprev->next = pwr;
  144.     pwr->r = *rect;
  145.     pwr->scroll = FALSE;
  146.   };
  147.   return( pwr);
  148. } /* wrc_add */
  149.  
  150.  
  151. void wrc_delete( wrectS *pwrprev)
  152. /*
  153.  | Entfernt die Rechteckbeschreibung hinter <wrprev>
  154.  | aus der Liste und gibt sie frei.
  155.  */
  156. {
  157.   wrectS *pwr;
  158.  
  159.   if ((pwr = wrc_extract( pwrprev)) != NULL) {
  160.     wrc_free( pwr);
  161.   };
  162. } /* wrc_delete */
  163.  
  164.  
  165. wrectS *wrc_split( wrectS *pwrprev, GRECT *rcut, int del)
  166. /*
  167.  | Zerlegt die Rechteckbeschreibung hinter <wrprev>, falls ein
  168.  | Schnitt mit dem Rechteck <rcut> besteht. Dabei wird das
  169.  | Schnittrechteck als kopierbar definiert und die ueberstehenden
  170.  | Teile als Ausgaberechtecke in die Liste eingefuegt.
  171.  | Ist <del>==TRUE, wird das Schnittrechteck nicht eingefuegt.
  172.  */
  173. {
  174.   wrectS *pwr;
  175.   GRECT rect;
  176.   int x1, y1;
  177.   int x2, y2;
  178.   int w, h;
  179.  
  180.   pwr = pwrprev->next;
  181.   if (pwr->scroll) return( pwr);
  182.  
  183.   /*** Schnittrechteck bestimmen ***/
  184.   x1 = MAX( pwr->r.g_x, rcut->g_x);
  185.   x2 = MIN( pwr->r.g_x + pwr->r.g_w, rcut->g_x + rcut->g_w);
  186.   y1 = MAX( pwr->r.g_y, rcut->g_y);
  187.   y2 = MIN( pwr->r.g_y + pwr->r.g_h, rcut->g_y + rcut->g_h);
  188.   w = x2 - x1;
  189.   h = y2 - y1;
  190.  
  191.   /*** Fertig, falls kein Schnitt besteht ***/
  192.   if ((w <= 0) || (h <= 0)) return( pwr);
  193.  
  194.   /*** Ueberstehende Teile als Rechtecke einfuegen ***/
  195.   if (pwr->r.g_y < y1) {  /* Oberhalb */
  196.     rc_set( &rect, pwr->r.g_x, pwr->r.g_y, pwr->r.g_w, y1 - pwr->r.g_y);
  197.     if ((pwrprev = wrc_add( pwrprev, &rect)) == NULL) return( NULL);
  198.   };
  199.   if (pwr->r.g_x < x1) {  /* Links */
  200.     rc_set( &rect, pwr->r.g_x, y1, x1 - pwr->r.g_x, h);
  201.     if ((pwrprev = wrc_add( pwrprev, &rect)) == NULL) return( NULL);
  202.   };
  203.   if (del) {
  204.     wrc_extract( pwrprev);
  205.   }
  206.   else {
  207.     pwrprev = pwr;
  208.   };
  209.   if (pwr->r.g_x + pwr->r.g_w > x2) {  /* Rechts */
  210.     rc_set( &rect, x2, y1, (pwr->r.g_x + pwr->r.g_w) - x2, h);
  211.     if ((pwrprev = wrc_add( pwrprev, &rect)) == NULL) return( NULL);
  212.   };
  213.   if (pwr->r.g_y + pwr->r.g_h > y2) {  /* Unterhalb */
  214.     rc_set( &rect, pwr->r.g_x, y2, pwr->r.g_w, (pwr->r.g_y + pwr->r.g_h) - y2);
  215.     if ((pwrprev = wrc_add( pwrprev, &rect)) == NULL) return( NULL);
  216.   };
  217.  
  218.   if (del) {
  219.     /*** Schnittrechteck freigeben ***/
  220.     wrc_free( pwr);
  221.   }
  222.   else {
  223.     /*** Schnittrechteck uebernehmen ***/
  224.     rc_set( &pwr->r, x1, y1, w, h);
  225.     pwr->scroll = TRUE;
  226.   };
  227.  
  228.   return( pwrprev);
  229. } /* wrc_split */
  230.  
  231.  
  232. /*------------------------------------------------------------------*/
  233.  
  234. wrectS *wrc_lnew( wlistT *wl)
  235. /*
  236.  | Initialisiert eine Rechteckliste.
  237.  | Liefert den 'Vorgaenger' des ersten Elements.
  238.  */
  239. {
  240.   *wl = NULL;
  241.   return( (wrectS *)wl);
  242. } /* wrc_lnew */
  243.  
  244.  
  245. void wrc_lfree( wlistT *wl)
  246. /*
  247.  | Gibt alle Elemente einer Rechteckliste frei.
  248.  */
  249. {
  250.   wrectS *pwr;
  251.  
  252.   while (*wl != NULL) {
  253.     pwr = *wl;
  254.     *wl = pwr->next;
  255.     wrc_free( pwr);
  256.   };
  257. } /* wrc_lfree */
  258.  
  259.  
  260. int wrc_ldup( wlistT *wldest, wlistT *wlsour, GRECT *rclip)
  261. /*
  262.  | Dupliziert die Rechteckliste <wlsour> unter Beruecksichtigung
  263.  | des Cliprechtecks <rclip> nach <wldest>.
  264.  */
  265. {
  266.   wrectS *pwrd, *pwrs;
  267.   GRECT rect;
  268.  
  269.   pwrd = wrc_lnew( wldest);
  270.   for (pwrs = *wlsour; pwrs != NULL; pwrs = pwrs->next) {
  271.     rect = pwrs->r;
  272.     if ((rclip == NULL) || rc_intersect( rclip, &rect)) {
  273.       if ((pwrd = wrc_add( pwrd, &rect)) == NULL) {
  274.         wrc_lfree( wldest);
  275.         return( FALSE);
  276.       };
  277.       pwrd->scroll = pwrs->scroll;
  278.     };
  279.   };
  280.   return( TRUE);
  281. } /* wrc_ldup */
  282.  
  283.  
  284. void wrc_lmove( wlistT wl, int offsx, int offsy)
  285. /*
  286.  | Verschiebt alle Elemente der Rechteckliste um den Betrag <offsx/y>.
  287.  */
  288. {
  289.   wrectS *pwr;
  290.  
  291.   for (pwr = wl; pwr != NULL; pwr = pwr->next) {
  292.     pwr->r.g_x += offsx;
  293.     pwr->r.g_y += offsy;
  294.   };
  295. } /* wrc_lmove */
  296.  
  297.  
  298. void wrc_lmerge( wlistT *wl)
  299. /*
  300.  | Versucht einzelne Rechtecke der Rechteckliste zu verschmelzen.
  301.  */
  302. {
  303.   wrectS *pwr, *pwr2, *pwr2prev;
  304.  
  305.   for (pwr = *wl; pwr != NULL; pwr = pwr->next) {
  306.     pwr2prev = pwr;
  307.     for (pwr2 = pwr2prev->next; pwr2 != NULL; pwr2 = pwr2prev->next) {
  308.       if ((pwr->r.g_x == pwr2->r.g_x) && (pwr->r.g_w == pwr2->r.g_w) &&
  309.           (pwr->r.g_y + pwr->r.g_h == pwr2->r.g_y) &&
  310.           (pwr->scroll == pwr2->scroll) ) {
  311.         pwr->r.g_h += pwr2->r.g_h;
  312.         wrc_delete( pwr2prev);
  313.       }
  314.       else {
  315.         pwr2prev = pwr2;
  316.       };
  317.     };
  318.   };
  319. } /* wrc_lmerge */
  320.  
  321.  
  322. int wrc_test( wrectS *pwr1, wrectS *pwr2, int scrollx, int scrolly)
  323. /*
  324.  | Liefert TRUE, falls <wr2> vor <wr1> ausgegeben werden soll.
  325.  */
  326. {
  327.   int left, right, above, below;
  328.  
  329.   left = pwr2->r.g_x+pwr2->r.g_w <= pwr1->r.g_x;
  330.   right = pwr2->r.g_x >= pwr1->r.g_x+pwr1->r.g_w;
  331.   above = pwr2->r.g_y+pwr2->r.g_h <= pwr1->r.g_y;
  332.   below = pwr2->r.g_y >= pwr1->r.g_y+pwr1->r.g_h;
  333.  
  334.   if (scrolly <= 0) {
  335.     if (above) {
  336.       return( TRUE);
  337.     }
  338.     else if (scrollx <= 0) {
  339.       return( left ? !below : FALSE);
  340.     }
  341.     else {
  342.       return( right ? !below : FALSE);
  343.     };
  344.   }
  345.   else {
  346.     if (below) {
  347.       return( TRUE);
  348.     }
  349.     else if (scrollx <= 0) {
  350.       return( left ? !above : FALSE);
  351.     }
  352.     else {
  353.       return( right ? !above : FALSE);
  354.     };
  355.   };
  356. } /* wrc_test */
  357.  
  358.  
  359. void wrc_lsort( wlistT *wl, int scrollx, int scrolly)
  360. /*
  361.  | Sortiert die Rechteckliste so, da₧ Bereiche, die kopiert werden,
  362.  | nicht vorher neu ausgegeben werden.
  363.  */
  364. {
  365.   wrectS *pwr1, *pwr2, *pwr3;
  366.  
  367.   if ((pwr1 = *wl) != NULL) {
  368.     while ((pwr2 = pwr1->next) != NULL) {
  369.       if (wrc_test( pwr1, pwr2, scrollx, scrolly)) {
  370.         for (pwr3 = (wrectS *)wl; pwr3->next != pwr1; pwr3 = pwr3->next) {
  371.           if (wrc_test( pwr3->next, pwr2, scrollx, scrolly)) break;
  372.         };
  373.         wrc_insert( pwr3, wrc_extract( pwr1));
  374.       }
  375.       else {
  376.         pwr1 = pwr2;
  377.       };
  378.     };
  379.   };
  380. } /* wrc_lsort */
  381.  
  382.  
  383. int wrc_lwin( wlistT *wl, int win, GRECT *rect)
  384. /*
  385.  | Erzeugt aus den sichtbaren Rechtecken eines Fensters eine
  386.  | Rechteckliste.
  387.  */
  388. {
  389.   GRECT rvis, rclip;
  390.   wrectS *pwr;
  391.  
  392.   pwr = wrc_lnew( wl);
  393.   wind_gdesk( &rclip);
  394.   if ((rect == NULL) || rc_intersect( rect, &rclip)) {
  395.  
  396.     wind_gfirst( win, &rvis);
  397.     while ((rvis.g_w > 0) && (rvis.g_h > 0)) {
  398.       if (rc_intersect( &rclip, &rvis)) {
  399.         if ((pwr = wrc_add( pwr, &rvis)) == NULL) {
  400.           wrc_lfree( wl);
  401.           return( FALSE);
  402.         };
  403.       };
  404.       wind_gnext( win, &rvis);
  405.     };
  406.     wrc_lmerge( wl);
  407.  
  408.   };
  409.   return( TRUE);
  410. } /* wrc_lwin */
  411.  
  412.  
  413. int wrc_lscroll( wlistT *wlvis, int scrollx, int scrolly)
  414. /*
  415.  | Wandelt die Rechteckliste <wlvis> in eine Liste um, die
  416.  | aus kopierbaren und aus normalen Rechtecken besteht.
  417.  | Ein Rechteck gilt als kopierbar, wenn seine Flaeche durch
  418.  | Verschieben einer beliebigen Flaeche der Rechteckliste um
  419.  | den Betrag <scrollx/y> erzeugt werden kann. Die Reihenfolge
  420.  | der entstehenden Liste muss bei der Ausgabe beachtet werden.
  421.  | Die Funktion liefert bei Erfolg TRUE, sonst FALSE.
  422.  | Im Fehlerfall enthaelt <wlvis> eine Kopie der urspruenglichen
  423.  | Liste.
  424.  */
  425. {
  426.   wlistT wl;
  427.   wrectS *pwr, *pwrvis;
  428.  
  429.   /*** Liste der verschobenen Rechtecke bestimmen ***/
  430.   if (!wrc_ldup( &wl, wlvis, NULL)) return( FALSE);
  431.   wrc_lmove( wl, scrollx, scrolly);
  432.  
  433.   /*** sichtbare Rechtecke aufteilen ***/
  434.   for (pwr = wl; pwr != NULL; pwr = pwr->next) {
  435.     pwrvis = (wrectS *)&wlvis;
  436.     while (pwrvis->next != NULL) {
  437.       if ((pwrvis = wrc_split( pwrvis, &pwr->r, FALSE)) == NULL) {
  438.         /*** Fehler: alte Liste wiederherstellen ***/
  439.         wrc_lfree( wlvis);
  440.         wrc_lmove( wl, -scrollx, -scrolly);
  441.         *wlvis = wl;
  442.         return( FALSE);
  443.       };
  444.     };
  445.   };
  446.   wrc_lfree( &wl);
  447.   wrc_lmerge( wlvis);
  448.  
  449.   /*** Ausgabereihenfolge der Rechtecke bestimmen ***/
  450.   wrc_lsort( wlvis, scrollx, scrolly);
  451.  
  452.   return( TRUE);
  453. } /* wrc_lscroll */
  454.  
  455.