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

  1. /*********************************************************************
  2. *
  3. * WRCFUNCS
  4. *
  5. * Kurzbeschreibung:
  6. * Das Modul stellt Fensterfunktionen zur Verfuegung, die auf Rechteck-
  7. * listen arbeiten: wind_redraw(), wind_rscroll(), wind_rubberbox()
  8. *
  9. * Versionen:
  10. * 1.0  mo  12.08.92  Basisversion uebernommen aus VDIX und WX
  11. *
  12. * Autoren:
  13. * mo   (\/) Martin Osieka, Erbacherstr. 2, D-6100 Darmstadt
  14. *
  15. *********************************************************************/
  16.  
  17. #include <stddef.h>
  18. #define FALSE 0
  19. #define TRUE  1
  20.  
  21. #include <aes.h>
  22. #if 0
  23. #include <aesr.h>
  24. #else
  25. /* Nachbildung von Funktionen aus aesr.h */
  26. extern int rc_intersect( GRECT *rclip, GRECT *rect);
  27. #define rc_set( r, x, y, w, h) \
  28.   (r)->g_x = (x); (r)->g_y = (y); (r)->g_w = (w); (r)->g_h = (h)
  29. #define wind_rget( win, mode, r) \
  30.   wind_get( win, mode, &(r)->g_x, &(r)->g_y, &(r)->g_w, &(r)->g_h)
  31. #define wind_gdesk( r) \
  32.   wind_rget( 0, WF_WORKXYWH, r)
  33. #define wind_gfirst( win, r) \
  34.   wind_rget( win, WF_FIRSTXYWH, r)
  35. #define wind_gnext( win, r) \
  36.   wind_rget( win, WF_NEXTXYWH, r)
  37.  
  38. int graf_rmkstate( GRECT *rmouse, int *kstate)
  39. {
  40.   int mstate;
  41.  
  42.   graf_mkstate( &rmouse->g_x, &rmouse->g_y, &mstate, kstate);
  43.   rmouse->g_w = rmouse->g_h = 1;
  44.   return( mstate);
  45. } /* graf_rmkstate */
  46.  
  47. GRECT *rc_catch( GRECT *rmax, GRECT *rect)
  48. /* Faengt das Rechteck <rect> in <rmax> */
  49. {
  50.   if (rect->g_w >= rmax->g_w) {
  51.     rect->g_x = rmax->g_x + (rmax->g_w - rect->g_w) / 2;
  52.   }
  53.   else {
  54.     if (rect->g_x < rmax->g_x) rect->g_x = rmax->g_x;
  55.     if (rect->g_x + rect->g_w >= rmax->g_x + rmax->g_w) {
  56.       rect->g_x = rmax->g_x + rmax->g_w - rect->g_w;
  57.     };
  58.   };
  59.  
  60.   if (rect->g_h >= rmax->g_h) {
  61.     rect->g_y = rmax->g_y + (rmax->g_h - rect->g_h) / 2;
  62.   }
  63.   else {
  64.     if (rect->g_y < rmax->g_y) rect->g_y = rmax->g_y;
  65.     if (rect->g_y + rect->g_h >= rmax->g_y + rmax->g_h) {
  66.       rect->g_y = rmax->g_y + rmax->g_h - rect->g_h;
  67.     };
  68.   };
  69.   return( rect);
  70. } /* rc_catch */
  71.  
  72. #endif
  73.  
  74. #include <wrc.h>
  75.  
  76. #include <vdi.h>
  77. extern int vhandle;
  78.  
  79. #include <wrcfuncs.h>
  80.  
  81.  
  82. /********************************************************************/
  83.  
  84. static void wind_sredraw( int win, GRECT *rect, wdrawF drawfunc)
  85. /*
  86.  | Gibt den Inhalt des Rechtecks <rect> im Fenster <win> neu aus.
  87.  | Ist <rect>==NULL wird als Rechteck die Ausgabeflaeche des Fensters
  88.  | benutzt.
  89.  | Diese Funktion sollte nur benutzt werden, falls die Rechteckliste
  90.  | des Fensters nicht komplett gespeichert werden konnte.
  91.  */
  92. {
  93.   GRECT rvis, rclip;
  94.  
  95.   wind_update( BEG_UPDATE);
  96.   graf_mouse( M_OFF, NULL);
  97.  
  98.   wind_gdesk( &rclip);
  99.   if ((rect == NULL) || rc_intersect( rect, &rclip)) {
  100.  
  101.     wind_gfirst( win, &rvis);
  102.     while ((rvis.g_w > 0) && (rvis.g_h > 0)) {
  103.       if (rc_intersect( &rclip, &rvis)) {
  104.         drawfunc( win, &rvis);
  105.       };
  106.       wind_gnext( win, &rvis);
  107.     };
  108.  
  109.   };
  110.   graf_mouse( M_ON, NULL);
  111.   wind_update( END_UPDATE);
  112. } /* wind_sredraw */
  113.  
  114.  
  115. void wind_redraw( int win, GRECT *rect, wdrawF drawfunc)
  116. /*
  117.  | Gibt den Inhalt des Rechtecks <rect> im Fenster <win> neu aus.
  118.  | Ist <rect>==NULL wird als Rechteck die Ausgabeflaeche des Fensters
  119.  | benutzt.
  120.  | ACHTUNG: <drawfunc> muss sich selbst um das Clipping kuemmern
  121.  */
  122. {
  123.   wlistT wl;
  124.   wrectS *pwr;
  125.  
  126.   wind_update( BEG_UPDATE);
  127.   graf_mouse( M_OFF, NULL);
  128.  
  129.   if (wrc_lwin( &wl, win, rect)) {
  130.     for (pwr = wl; pwr != NULL; pwr = pwr->next) {
  131.       drawfunc( win, &pwr->r);
  132.     };
  133.     wrc_lfree( &wl);
  134.   }
  135.   else {
  136.     wind_sredraw( win, rect, drawfunc);
  137.   };
  138.  
  139.   graf_mouse( M_ON, NULL);
  140.   wind_update( END_UPDATE);
  141. } /* wind_redraw */
  142.  
  143.  
  144. /*------------------------------------------------------------------*/
  145.  
  146. void vs_rclip( int vh, GRECT *rclip)
  147. /*
  148.  | vs_clip() mit Rechteck-Schnittstelle
  149.  */
  150. {
  151.   int xyclip[ 4];
  152.  
  153.   if (rclip == NULL) {
  154.     vs_clip( vh, FALSE, xyclip);
  155.   }
  156.   else {
  157.     xyclip[ 0] = rclip->g_x;
  158.     xyclip[ 1] = rclip->g_y;
  159.     xyclip[ 2] = rclip->g_x + rclip->g_w - 1;
  160.     xyclip[ 3] = rclip->g_y + rclip->g_h - 1;
  161.     vs_clip( vh, TRUE, xyclip);
  162.   };
  163. } /* vs_rclip */
  164.  
  165.  
  166. void v_rcpy( int vh, GRECT *rdest, int scrollx, int scrolly)
  167. /*
  168.  | Kopiert einen Bildschirmbereich nach <rdest>.
  169.  | Die Funktion erwartet, dass sich sowohl das Quell- als auch das
  170.  | Zielrechteck komplett im sichtbaren Bereich des Bildschirms
  171.  | befindet, da ohne Clipping kopiert wird!
  172.  */
  173. {
  174.   MFDB scrmfdb;
  175.   int xy[ 8];
  176.  
  177.   scrmfdb.fd_addr = NULL;
  178.   xy[ 0] = rdest->g_x - scrollx;
  179.   xy[ 1] = rdest->g_y - scrolly;
  180.   xy[ 2] = xy[ 0] + rdest->g_w - 1;
  181.   xy[ 3] = xy[ 1] + rdest->g_h - 1;
  182.   xy[ 4] = rdest->g_x;
  183.   xy[ 5] = rdest->g_y;
  184.   xy[ 6] = xy[ 4] + rdest->g_w - 1;
  185.   xy[ 7] = xy[ 5] + rdest->g_h - 1;
  186.  
  187.   vs_rclip( vh, NULL);
  188.   v_hide_c( vh);
  189.   vro_cpyfm( vh, S_ONLY, xy, &scrmfdb, &scrmfdb);
  190.   v_show_c( vh, 1);
  191. } /* v_rcpy */
  192.  
  193.  
  194. void wind_rscroll( int win,
  195.   GRECT *rscroll, int scrollx, int scrolly, wdrawF drawfunc)
  196. /*
  197.  | Verschiebt den Inhalt des Rechtecks <rscroll> im Fenster <win>
  198.  | um den Betrag <scrollx/y>. Ist <rscroll>==NULL wird als Rechteck
  199.  | die Ausgabeflaeche des Fensters benutzt.
  200.  | Alle Bereiche, die nicht durch Verschieben erzeugt werden
  201.  | koennen, werden ueber <drawfunc> neu ausgegeben.
  202.  | ACHTUNG: <drawfunc> muss sich selbst um das Clipping kuemmern
  203.  */
  204. {
  205.   wlistT wlvis;
  206.   wrectS *pwrvis;
  207.  
  208.   if ((scrollx == 0) && (scrolly == 0)) return;
  209.  
  210.   wind_update( BEG_UPDATE);
  211.   graf_mouse( M_OFF, NULL);
  212.  
  213.   /*** sichtbare Rechtecke des Fensters bestimmen ***/
  214.   if (wrc_lwin( &wlvis, win, rscroll)) {
  215.  
  216.     /*** Rechteckliste aufteilen ***/
  217.     wrc_lscroll( &wlvis, scrollx, scrolly);
  218.  
  219.     /*** Rechtecke ausgeben ***/
  220.     for (pwrvis = wlvis; pwrvis != NULL; pwrvis = pwrvis->next) {
  221.       if (pwrvis->scroll) {
  222.         v_rcpy( vhandle, &pwrvis->r, scrollx, scrolly);
  223.       }
  224.       else {
  225.         drawfunc( win, &pwrvis->r);
  226.       };
  227.     };
  228.  
  229.     wrc_lfree( &wlvis);
  230.   }
  231.   else {
  232.     wind_sredraw( win, NULL, drawfunc);
  233.   };
  234.  
  235.   graf_mouse( M_ON, NULL);
  236.   wind_update( END_UPDATE);
  237. } /* wind_rscroll */
  238.  
  239.  
  240. /*------------------------------------------------------------------*/
  241.  
  242. static void v_userline( int vh, GRECT *rline)
  243. /*
  244.  | Zeichnet die durch <rline> definierte Gerade.
  245.  | Das Muster beginnt mit einem Punkt
  246.  | - waagrechte Gerade: falls die Zeile ungerade ist
  247.  | - senkrechte Gerade: falls entweder die Startzeile oder
  248.  |   die Spalte ungerade sind (exklusiv)
  249.  | Eine schnellere Loesung waere es nur Koordinaten zu benutzen,
  250.  | die ein Vielfaches von zwei sind (dann muss das Muster
  251.  | nur einmal gesetzt werden)
  252.  | (Dieser Algorithmus entspricht dem Vorgehen des GEM beim
  253.  | Zeichnen von Geisterrahmen)
  254.  */
  255. {
  256.   int pat;
  257.   int xyline[ 4];
  258.  
  259.   xyline[ 0] = rline->g_x;
  260.   xyline[ 1] = rline->g_y;
  261.   xyline[ 2] = rline->g_x + rline->g_w - 1;
  262.   xyline[ 3] = rline->g_y + rline->g_h - 1;
  263.  
  264.   if (xyline[ 1] == xyline[ 3]) { /* waagrecht */
  265.     pat = (xyline[1] & 1) ? 0xAAAA : 0x5555;
  266.   }
  267.   else { /* senkrecht */
  268.     pat = ((xyline[0] ^ xyline[1]) & 1) ? 0xAAAA : 0x5555;
  269.   };
  270.   vsl_udsty( vh, pat);
  271.   v_pline( vh, 2, xyline);
  272. } /* v_userline */
  273.  
  274.  
  275. #define NONO 0  /* Beide Endpunkte ausgeben */
  276. #define NOS  1  /* Startpunkt nicht ausgeben */
  277. #define NOE  2  /* Endpunkt nicht ausgeben */
  278. #define NOSE 3  /* Keinen der Endpunkte ausgeben */
  279.  
  280. static void v_rubberline( int vh,
  281.   int x1, int y1, int x2, int y2,
  282.   int mode, wlistT wl)
  283. /*
  284.  | Zeichnet eine Gerade zwischen dem Anfangspunkt <x1/y1> und dem
  285.  | Endpunkt <x2/y2>, wobei die Liste der Cliprechtecke in <wl>
  286.  | beachtet wird. <mode> bestimmt die Ausgabe des Anfangs- und End-
  287.  | punkts der Geraden. Die Gerade wird immer von links nach rechts
  288.  | bzw. von oben nach unten gezogen.
  289.  | HINWEIS: Oft ist die Segmentierung eine Geraden unnoetig.
  290.  | Das Zusammenlegen erfordert allerdings einigen Aufwand.
  291.  */
  292. {
  293.   int x, y;
  294.   GRECT rline, rlinep;
  295.   wrectS *pwr;
  296.  
  297.   /*** Anfangspunkt entfernen ***/
  298.   if (mode & NOS) {
  299.     if ((x1 == x2) && (y1 == y2)) return;
  300.     if (x1 != x2) {
  301.       x1 += (x1 < x2) ? 1 : -1;
  302.     }
  303.     else {
  304.       y1 += (y1 < y2) ? 1 : -1;
  305.     };
  306.   };
  307.  
  308.   /*** Endpunkt entfernen ***/
  309.   if (mode & NOE) {
  310.     if ((x1 == x2) && (y1 == y2)) return;
  311.     if (x1 != x2) {
  312.       x2 -= (x1 < x2) ? 1 : -1;
  313.     }
  314.     else {
  315.       y2 -= (y1 < y2) ? 1 : -1;
  316.     };
  317.   };
  318.  
  319.   /*** Erst jetzt Punkte sortieren ***/
  320.   if (x1 > x2) { x = x1; x1 = x2; x2 = x; };
  321.   if (y1 > y2) { y = y1; y1 = y2; y2 = y; };
  322.  
  323.   /*** Linienrechteck erzeugen ***/
  324.   rline.g_x = x1;
  325.   rline.g_y = y1;
  326.   rline.g_w = x2 - x1 + 1;
  327.   rline.g_h = y2 - y1 + 1;
  328.  
  329.   /*** Linie clippen und zeichnen ***/
  330.   for (pwr = wl; pwr != NULL; pwr = pwr->next) {
  331.     rlinep = rline;
  332.     if (rc_intersect( &pwr->r, &rlinep)) {
  333.       v_userline( vh, &rlinep);
  334.     };
  335.   };
  336. } /* v_rubberline */
  337.  
  338.  
  339. int wind_rubberbox( int win, GRECT *rmouse, GRECT *rsel)
  340. /*
  341.  | Erlaubt dem Anwender ein Selektionsrechteck in einem Fenster <win>
  342.  | aufzuziehen, beginnend an der Position <rmouse> (Das Desktop hat
  343.  | die Fensterkennung 0). Das Rechteck kann maximal die Groesse der
  344.  | Arbeitsflaeche des Fensters annehmen und ist auch nur in ihm
  345.  | sichtbar. Reicht der Speicher nicht fuer eine Liste der
  346.  | Cliprechtecke des Fensters wird nicht geclippt und es ist
  347.  | somit auch in den anderen Fenstern sichtbar.
  348.  | Die Funktion liefert den Status der Sondertasten der Tastatur
  349.  | beim Loslassen des Mausknopfs.
  350.  |
  351.  |       o            S - Startpunkt
  352.  |  S+-------+        M - Maus
  353.  |   |       |        o - aeussere Geraden
  354.  |  o|       |i       i - innere Geraden
  355.  |   |       |
  356.  |   +-------+
  357.  |       i
  358.  */
  359. {
  360.   wlistT wl;            /* Liste der Cliprechtecke von <win> */
  361.   wrectS wrdummy;
  362.   GRECT rmaxsel;        /* Ausgabeflaeche von <win> */
  363.   int x1, y1;           /* Startposition */
  364.   int x2, y2;           /* Letzte Mausposition */
  365.   int newx2, newy2;     /* Neue Mausposition */
  366.   int mstate, kstate;   /* Maustasten und Status der Sondertasten */
  367.   int xbigger, ybigger; /* TRUE falls Selektionsrechteck in einer
  368.                            Richtung absolut groesser wird */
  369.  
  370.   wind_update( BEG_UPDATE);
  371.   wind_update( BEG_MCTRL);
  372.  
  373.   /*** Rechtecke und Startposition bestimmen ***/
  374.   wind_rget( win, WF_WORKXYWH, &rmaxsel); /* Maximalrechteck */
  375.  
  376.   if (!wrc_lwin( &wl, win, &rmaxsel)) {  /* Cliprechtecke */
  377.     wl = &wrdummy;
  378.     wrdummy.next = NULL;
  379.     wrdummy.r = rmaxsel;
  380.   };
  381.   x1 = x2 = rmouse->g_x; /* Startposition */
  382.   y1 = y2 = rmouse->g_y;
  383.  
  384.   /*** VDI-Voreinstellung ***/
  385.   vswr_mode( vhandle, MD_XOR);
  386.   vs_rclip( vhandle, NULL); /* mach ich selbst */
  387.   vsl_color( vhandle, BLACK);
  388.   vsl_type( vhandle, 7); /* Linientyp wird selbst definiert */
  389.  
  390.   /*** Zeichnen des Startpunkt (dieser wird nie mehr veraendert) ***/
  391.   v_hide_c( vhandle);
  392.   v_rubberline( vhandle, x1, y1, x2, y2, NONO, wl);
  393.   v_show_c( vhandle, 1);
  394.  
  395.   while (TRUE) {
  396.  
  397.     /*** Neue Position innerhalb des Maximalrechtecks bestimmen ***/
  398.     mstate = graf_rmkstate( rmouse, &kstate);
  399.     if ((mstate & 1) == 0) break;
  400.     rc_catch( &rmaxsel, rmouse);
  401.     newx2 = rmouse->g_x;
  402.     newy2 = rmouse->g_y;
  403.  
  404.     /*** Keine abrupte Richtungsumkehr ***/
  405.     if ((x2 < x1) && (newx2 > x1)) newx2 = x1;
  406.     if ((x2 > x1) && (newx2 < x1)) newx2 = x1;
  407.     if ((y2 < y1) && (newy2 > y1)) newy2 = y1;
  408.     if ((y2 > y1) && (newy2 < y1)) newy2 = y1;
  409.  
  410.     /*** Es hat sich was veraendert? ... dann neu zeichnen ***/
  411.     if ((newx2 != x2) || (newy2 != y2)) {
  412.  
  413.       v_hide_c( vhandle);
  414.  
  415.       /*** Loeschen der aeusseren Linien ***/
  416.       if ((y1 != y2) && (y2 != newy2)) {
  417.         v_rubberline( vhandle, x1, y2, x2, y2, (x2 == newx2) ? NOSE : NOS, wl);
  418.       };
  419.       if ((x1 != x2) && (x2 != newx2)) {
  420.         v_rubberline( vhandle, x2, y1, x2, y2, NOSE, wl);
  421.       };
  422.  
  423.       /*** Veraendern der inneren Linien (eventuell auch aeussere) ***/
  424.       xbigger = (x2 == x1) || ((newx2 < x2) && (x2 < x1)) || ((newx2 > x2) && (x2 > x1));
  425.       ybigger = (y2 == y1) || ((newy2 < y2) && (y2 < y1)) || ((newy2 > y2) && (y2 > y1));
  426.       v_rubberline( vhandle, x2, y1, newx2, y1, xbigger ? NOS : NOE, wl);
  427.       if ((y1 != y2) && (y2 == newy2)) {
  428.         v_rubberline( vhandle, x2, y2, newx2, y2, xbigger ? NOS : NOE, wl);
  429.       };
  430.       v_rubberline( vhandle, x1, y2, x1, newy2, ybigger ? NOS : NOE, wl);
  431.       if ((x1 != x2) && (x2 == newx2)) {
  432.         v_rubberline( vhandle, x2, y2, x2, newy2, ybigger ? NOS : NOE, wl);
  433.       };
  434.  
  435.       /*** Neuzeichnen der aeusseren Linien ***/
  436.       if ((y1 != newy2) && (y2 != newy2)) {
  437.         v_rubberline( vhandle, x1, newy2, newx2, newy2, (x2 == newx2) ? NOSE : NOS, wl);
  438.       };
  439.       if ((x1 != newx2) && (x2 != newx2)) {
  440.         v_rubberline( vhandle, newx2, y1, newx2, newy2, NOSE, wl);
  441.       };
  442.  
  443.       v_show_c( vhandle, 1);
  444.  
  445.       /*** Neue Mausposition uebernehmen ***/
  446.       x2 = newx2;
  447.       y2 = newy2;
  448.  
  449.     };
  450.   };
  451.  
  452.   /*** Loeschen der aeusseren und inneren Linien ***/
  453.   v_hide_c( vhandle);
  454.   v_rubberline( vhandle, x1, y1, x2, y1, NONO, wl);
  455.   if (y1 != y2) {
  456.     v_rubberline( vhandle, x1, y1, x1, y2, NOSE, wl);
  457.     if (x1 != x2) v_rubberline( vhandle, x2, y1, x2, y2, NOSE, wl);
  458.     v_rubberline( vhandle, x1, y2, x2, y2, NONO, wl);
  459.   };
  460.   v_show_c( vhandle, 1);
  461.   vswr_mode( vhandle, MD_REPLACE);
  462.  
  463.   if (wl != &wrdummy) {
  464.     wrc_lfree( &wl);  /* Cliprechtecke wieder freigeben */
  465.   };
  466.  
  467.   /*** Selektionsrechteck zurueckgeben ***/
  468.   if (x1 > x2) { newx2 = x2; x2 = x1; x1 = newx2; };
  469.   if (y1 > y2) { newy2 = y2; y2 = y1; y1 = newy2; };
  470.   rc_set( rsel, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
  471.  
  472.   wind_update( END_MCTRL);
  473.   wind_update( END_UPDATE);
  474.  
  475.   return( kstate);
  476. } /* wind_rubberbox */
  477.  
  478.  
  479. /********************************************************************/
  480.