home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0040 - 0049 / ibm0040-0049 / ibm0040.tar / ibm0040 / ZINC_6.ZIP / DOSSRC.ZIP / BGIDSP.CPP next >
Encoding:
C/C++ Source or Header  |  1991-06-01  |  15.9 KB  |  530 lines

  1. //    Zinc Interface Library - BGIDSP.CPP
  2. //    COPYRIGHT (C) 1990, 1991.  All Rights Reserved.
  3. //    Zinc Software Incorporated.  Pleasant Grove, Utah  USA
  4.  
  5. #include "ui_dsp.hpp"
  6. #include <dos.h>
  7. #include <mem.h>
  8. #include <alloc.h>
  9. #include <string.h>
  10. #include <graphics.h>
  11.  
  12. static char fillLine[256];
  13.  
  14. UI_DOS_BGI_DISPLAY::UI_DOS_BGI_DISPLAY(int driver, int mode):
  15.     UI_DISPLAY(FALSE, 8, 14)
  16. {
  17.     // Find the type of display.
  18.     if (driver == DETECT)
  19.     {
  20.         detectgraph(&driver, &mode);
  21.         if (driver < 0)
  22.             return;
  23.     }
  24.  
  25.     // Try to initialize the graphics driver.
  26.     int tDriver = -3;
  27.     int tMode;
  28.     _path->SetFileName(0);
  29.     char *pathToDriver = NULL;
  30.     do
  31.     {
  32.         tDriver = driver;
  33.         tMode = mode;
  34.         initgraph(&tDriver, &tMode, pathToDriver);
  35.         pathToDriver = _path->NextPathName();
  36.     } while (tDriver == -3 && pathToDriver);
  37.     if (tDriver < 0)
  38.         return;
  39.  
  40.     lines = getmaxy()+ 1;
  41.     columns = getmaxx()+ 1;
  42.     maxColor = getmaxcolor();
  43.  
  44.     // Fill the screen according to the specified palette.
  45.     settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
  46.     settextjustify(LEFT_TEXT, TOP_TEXT);
  47.     setfillstyle(_backgroundPalette->fillPattern, MapColor(_backgroundPalette, FALSE));
  48.     setviewport(0, 0, columns - 1, lines - 1, TRUE);
  49.     bar(0, 0, columns - 1, lines - 1);
  50.  
  51.     // Define the screen display region.
  52.     Add(0, new UI_REGION_ELEMENT(ID_SCREEN, 0, 0, columns - 1, lines - 1));
  53.     installed = TRUE;
  54. }
  55.  
  56. UI_DOS_BGI_DISPLAY::~UI_DOS_BGI_DISPLAY(void)
  57. {
  58.     // Restore the display.
  59.     if (installed)
  60.         closegraph();
  61. }
  62.  
  63. // ----- Member functions ---------------------------------------------------
  64.  
  65. void UI_DOS_BGI_DISPLAY::Bitmap(SCREENID screenID, int column, int line,
  66.     int bitmapWidth, int bitmapHeight, const UCHAR *bitmapArray,
  67.     const UI_PALETTE *palette, const UI_REGION *clipRegion)
  68. {
  69.     UI_REGION tRegion;
  70.     UI_REGION region;
  71.     region.left = column;
  72.     region.top = line;
  73.     region.right = column + bitmapWidth - 1;
  74.     region.bottom = line + bitmapHeight - 1;
  75.     if (clipRegion)
  76.     {
  77.         region.left = Max(region.left, clipRegion->left);
  78.         region.top = Max(region.top, clipRegion->top);
  79.         region.right = Min(region.right, clipRegion->right);
  80.         region.bottom = Min(region.bottom, clipRegion->bottom);
  81.     }
  82.  
  83.     // Draw the bitmap on the display.
  84.     int hidden = FALSE;
  85.     for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
  86.         if (d_region->screenID == screenID && d_region->Overlap(region, tRegion))
  87.         {
  88.             if (!hidden && eventManager)
  89.             {
  90.                 hidden = TRUE;
  91.                 eventManager->DevicesHide(region);
  92.                 setviewport(0, 0, columns - 1, lines - 1, TRUE);
  93.             }
  94.             for (int row = tRegion.top; row <= tRegion.bottom; row++)
  95.             {
  96.                 UCHAR *pixel = (UCHAR *)(bitmapArray + (row - region.top) * bitmapWidth + tRegion.left - region.left);
  97.                 for (int column = tRegion.left; column <= tRegion.right; column++, pixel++)
  98.                     putpixel(column, row, *pixel);
  99.             }
  100.         }
  101.  
  102.     // Show the screen devices.
  103.     if (hidden && eventManager)
  104.         eventManager->DevicesShow(region);
  105. }
  106.  
  107. void UI_DOS_BGI_DISPLAY::Ellipse(SCREENID screenID, int x, int y, int startAngle,
  108.     int endAngle, int xRadius, int yRadius, const UI_PALETTE *palette,
  109.     int fill, int xor, const UI_REGION *clipRegion)
  110. {
  111.     // Compute the minimum rectangle that the ellipse will fit in.
  112.     UI_REGION region, tRegion;
  113.     region.left = x - xRadius;
  114.     region.right = x + xRadius;
  115.     region.top = y - yRadius;
  116.     region.bottom = y + yRadius;
  117.     if (clipRegion)
  118.     {
  119.         region.left = Max(region.left, clipRegion->left);
  120.         region.top = Max(region.top, clipRegion->top);
  121.         region.right = Min(region.right, clipRegion->right);
  122.         region.bottom = Min(region.bottom, clipRegion->bottom);
  123.     }
  124.  
  125.     // Draw the ellipse on the display.
  126.     int hidden = FALSE;
  127.     for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
  128.         if ((xor || d_region->screenID == screenID) &&
  129.             d_region->Overlap(region, tRegion))
  130.         {
  131.             if (!hidden && eventManager)
  132.             {
  133.                 hidden = TRUE;
  134.                 eventManager->DevicesHide(region);
  135.                 setcolor(MapColor(palette, TRUE));
  136.                 if (fill)
  137.                     setfillstyle(palette->fillPattern, MapColor(palette, FALSE));
  138.                 if (xor)
  139.                     setwritemode(XOR_PUT);
  140.             }
  141.  
  142.             setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
  143.             if (fill)
  144.             {
  145.                 if (startAngle == 0 && endAngle == 360)
  146.                     fillellipse(x - tRegion.left, y - tRegion.top, xRadius, yRadius);
  147.                 else
  148.                     sector(x - tRegion.left, y - tRegion.top, startAngle, endAngle, xRadius, yRadius);
  149.             }
  150.             else
  151.                 ellipse(x - tRegion.left, y - tRegion.top, startAngle, endAngle, xRadius, yRadius);
  152.         }
  153.  
  154.     // Show the screen devices.
  155.     if (hidden && eventManager)
  156.     {
  157.         eventManager->DevicesShow(region);
  158.         if (xor)
  159.             setwritemode(COPY_PUT);
  160.     }
  161. }
  162.  
  163. void UI_DOS_BGI_DISPLAY::Line(SCREENID screenID, int x1, int y1, int x2, int y2,
  164.     const UI_PALETTE *palette, int width, int xor, const UI_REGION *clipRegion)
  165. {
  166.     // Compute the minimum rectangle that the line will fit in.
  167.     UI_REGION region, tRegion;
  168.     region.left = Min(x1, x2);
  169.     region.right = Max(x1, x2);
  170.     region.top = Min(y1, y2);
  171.     region.bottom = Max(y1, y2);
  172.     if (clipRegion)
  173.     {
  174.         region.left = Max(region.left, clipRegion->left);
  175.         region.top = Max(region.top, clipRegion->top);
  176.         region.right = Min(region.right, clipRegion->right);
  177.         region.bottom = Min(region.bottom, clipRegion->bottom);
  178.     }
  179.  
  180.     // Draw the line on the display.
  181.      int hidden = FALSE;
  182.     for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
  183.         if ((xor || d_region->screenID == screenID) &&
  184.             d_region->Overlap(region, tRegion))
  185.         {
  186.             if (!hidden && eventManager)
  187.             {
  188.                 hidden = TRUE;
  189.                 eventManager->DevicesHide(region);
  190.                 setcolor(MapColor(palette, TRUE));
  191.                 if (xor)
  192.                     setwritemode(XOR_PUT);
  193.             }
  194.  
  195.             setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
  196.             line(x1 - tRegion.left, y1 - tRegion.top, x2 - tRegion.left, y2 - tRegion.top);
  197.         }
  198.  
  199.     // Show the screen devices.
  200.     if (hidden && eventManager)
  201.     {
  202.         eventManager->DevicesShow(region);
  203.         if (xor)
  204.             setwritemode(COPY_PUT);
  205.     }
  206. }
  207.  
  208. int UI_DOS_BGI_DISPLAY::MapColor(const UI_PALETTE *palette, int foreground)
  209. {
  210.     if (maxColor == 15)
  211.     {
  212.         if (foreground)
  213.             return(palette->colorForeground);
  214.         return(palette->colorBackground);
  215.     }
  216.     else if (maxColor == 1)
  217.     {
  218.         if (foreground)
  219.             return(palette->bwForeground);
  220.         return(palette->bwBackground);
  221.     }
  222.     if (foreground)
  223.         return(palette->grayScaleForeground);
  224.     return(palette->grayScaleBackground);
  225. }
  226.  
  227. void UI_DOS_BGI_DISPLAY::Polygon(SCREENID screenID, int numPoints,
  228.     const int *polygonPoints, const UI_PALETTE *palette, int fill, int xor,
  229.     const UI_REGION *clipRegion)
  230. {
  231.     // Compute the minimum rectangle that the polygon will fit in.
  232.     UI_REGION region, tRegion;
  233.     region.left = columns;
  234.     region.right = 0;
  235.     region.top = lines;
  236.     region.bottom = 0;
  237.     for (int i = 0; i < numPoints * 2; i += 2)
  238.     {
  239.         region.left = Min(region.left, polygonPoints[i]);
  240.         region.right = Max(region.right, polygonPoints[i]);
  241.         region.top = Min(region.top, polygonPoints[i+1]);
  242.         region.bottom = Max(region.bottom, polygonPoints[i+1]);
  243.     }
  244.     if (clipRegion)
  245.     {
  246.         region.left = Max(region.left, clipRegion->left);
  247.         region.top = Max(region.top, clipRegion->top);
  248.         region.right = Min(region.right, clipRegion->right);
  249.         region.bottom = Min(region.bottom, clipRegion->bottom);
  250.     }
  251.  
  252.     // Draw the polygon on the display.
  253.     int hidden = FALSE;
  254.     int *tPolygon = new int[numPoints * 2];
  255.     for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
  256.         if ((xor || d_region->screenID == screenID) &&
  257.             d_region->Overlap(region, tRegion))
  258.         {
  259.             if (!hidden && eventManager)
  260.             {
  261.                 hidden = TRUE;
  262.                 eventManager->DevicesHide(region);
  263.                 setcolor(MapColor(palette, TRUE));
  264.                 if (fill)
  265.                     setfillstyle(palette->fillPattern, MapColor(palette, FALSE));
  266.                 if (xor)
  267.                     setwritemode(XOR_PUT);
  268.             }
  269.  
  270.             setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
  271.             for (i = 0; i < numPoints * 2; i += 2)
  272.             {
  273.                 tPolygon[i] = polygonPoints[i] - tRegion.left;
  274.                 tPolygon[i+1] = polygonPoints[i+1] - tRegion.top;
  275.             }
  276.             if (fill)
  277.                 fillpoly(numPoints, tPolygon);
  278.             else
  279.                 drawpoly(numPoints, tPolygon);
  280.         }
  281.     delete tPolygon;
  282.  
  283.     // Show the screen devices.
  284.     if (hidden && eventManager)
  285.     {
  286.         eventManager->DevicesShow(region);
  287.         if (xor)
  288.             setwritemode(COPY_PUT);
  289.     }
  290. }
  291.  
  292. #pragma argsused
  293. void UI_DOS_BGI_DISPLAY::Rectangle(SCREENID screenID, int left, int top, int right,
  294.     int bottom, const UI_PALETTE *palette, int width, int fill, int xor,
  295.     const UI_REGION *clipRegion)
  296. {
  297.     // Assign the rectangle to the region structure.
  298.     UI_REGION region, tRegion;
  299.     region.left = left;
  300.     region.right = right;
  301.     region.top = top;
  302.     region.bottom = bottom;
  303.     if (clipRegion)
  304.     {
  305.         region.left = Max(region.left, clipRegion->left);
  306.         region.top = Max(region.top, clipRegion->top);
  307.         region.right = Min(region.right, clipRegion->right);
  308.         region.bottom = Min(region.bottom, clipRegion->bottom);
  309.     }
  310.  
  311.     // Draw the rectangle on the display.
  312.     int hidden = FALSE;
  313.     for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
  314.         if ((xor || d_region->screenID == screenID) &&
  315.             d_region->Overlap(region, tRegion))
  316.         {
  317.             if (!hidden && eventManager)
  318.             {
  319.                 hidden = TRUE;
  320.                 eventManager->DevicesHide(region);
  321.                 setcolor(MapColor(palette, TRUE));
  322.                 if (fill)
  323.                     setfillstyle(palette->fillPattern, MapColor(palette, FALSE));
  324.                 if (xor)
  325.                     setwritemode(XOR_PUT);
  326.             }
  327.  
  328.             setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
  329.             if (fill && xor)
  330.             {
  331.                 for (int i = tRegion.top; i <= tRegion.bottom; i++)
  332.                     line(left - tRegion.left, i - tRegion.top, right - tRegion.left, i - tRegion.top);
  333.             }
  334.             else if (fill)
  335.                 bar(left - tRegion.left, top - tRegion.top, right - tRegion.left, bottom - tRegion.top);
  336.             else
  337.                 rectangle(left - tRegion.left, top - tRegion.top, right - tRegion.left, bottom - tRegion.top);
  338.         }
  339.  
  340.     // Show the screen devices.
  341.     if (hidden && eventManager)
  342.     {
  343.         eventManager->DevicesShow(region);
  344.         if (xor)
  345.             setwritemode(COPY_PUT);
  346.     }
  347. }
  348.  
  349. void UI_DOS_BGI_DISPLAY::RectangleXORDiff(const UI_REGION &oldRegion,
  350.     const UI_REGION &newRegion)
  351. {
  352.     // See if the regions match.
  353.     if (oldRegion.left == newRegion.left && oldRegion.top == newRegion.top &&
  354.         oldRegion.right == newRegion.right && oldRegion.bottom == newRegion.bottom)
  355.         return;
  356.  
  357.     // Hide the screen devices.
  358.     UI_REGION region;
  359.     region.left = Min(oldRegion.left, newRegion.left);
  360.     region.top = Min(oldRegion.top, newRegion.top);
  361.     region.right = Max(oldRegion.right, newRegion.right);
  362.     region.bottom = Max(oldRegion.bottom, newRegion.bottom);
  363.     if (eventManager)
  364.         eventManager->DevicesHide(region);
  365.  
  366.     // Draw the XOR rectangles on the display.
  367.     setwritemode(XOR_PUT);
  368.     setcolor(MapColor(_xorPalette, TRUE));
  369.     setviewport(0, 0, columns - 1, lines - 1, TRUE);
  370.     rectangle(oldRegion.left, oldRegion.top, oldRegion.right, oldRegion.bottom);
  371.     rectangle(newRegion.left, newRegion.top, newRegion.right, newRegion.bottom);
  372.     setwritemode(COPY_PUT);
  373.  
  374.     // Show the screen devices.
  375.     if (eventManager)
  376.         eventManager->DevicesShow(region);
  377. }
  378.  
  379. void UI_DOS_BGI_DISPLAY::RegionConvert(UI_REGION ®ion, USHORT *oldFlags, USHORT newFlags)
  380. {
  381.     // Check for a convertable region.
  382.     if (FlagSet(*oldFlags, newFlags))
  383.         return;
  384.  
  385.     // These variables handle Text<-->Graphics coordinate problems.
  386.     region.left *= 8;
  387.     region.top *= 14;
  388.     region.right = region.right * 8 + 7;
  389.     region.bottom = region.bottom * 14 + 12;
  390.  
  391.     *oldFlags |= newFlags;
  392. }
  393.  
  394. #pragma argsused
  395. void UI_DOS_BGI_DISPLAY::RegionMove(const UI_REGION &oldRegion, int newColumn, int newLine,
  396.     SCREENID oldScreenID, SCREENID newScreenID)
  397. {
  398.     unsigned size = imagesize(oldRegion.left, oldRegion.top, oldRegion.right, oldRegion.bottom);
  399.     void far *buffer = farmalloc(size);
  400.     getimage(oldRegion.left, oldRegion.top, oldRegion.right, oldRegion.bottom, buffer);
  401.     putimage(newColumn, newLine, buffer, COPY_PUT);
  402.     farfree(buffer);
  403. }
  404.  
  405. void UI_DOS_BGI_DISPLAY::Text(SCREENID screenID, int left, int top,
  406.     const char *text, const UI_PALETTE *palette, int length,
  407.     int fill, int xor, const UI_REGION *clipRegion)
  408. {
  409.     UI_REGION tRegion;
  410.     UI_REGION region;
  411.     int offset;
  412.  
  413.     // Copy the text to a scrap buffer
  414.     if (xor)
  415.     {
  416.         Rectangle(screenID, left, top,
  417.             left + length * textwidth("X") - 1,
  418.             top + textheight("X") - 1, palette, 1, TRUE, TRUE);
  419.         return;
  420.     }
  421.     else if (length > 0)
  422.     {
  423.         memcpy(fillLine, text, length);
  424.         fillLine[length] = '\0';
  425.     }
  426.     else
  427.         strcpy(fillLine, text);
  428.  
  429.     // Convert the cell coordinates.
  430.     int height = textheight((char *)fillLine); // Typecast Borland bug
  431.     int cell_width = textwidth("W");
  432.     int width = (length == -1 ? textwidth((char *)fillLine): length * cell_width); // Typecast Borland bug
  433.     region.left = left;
  434.     region.top = top;
  435.     region.right = region.left + width - 1;
  436.     region.bottom = region.top + height - 1;
  437.     if (clipRegion)
  438.     {
  439.         region.left = Max(region.left, clipRegion->left);
  440.         region.top = Max(region.top, clipRegion->top);
  441.         region.right = Min(region.right, clipRegion->right);
  442.         region.bottom = Min(region.bottom, clipRegion->bottom);
  443.     }
  444.  
  445.     // Draw the text on the display.
  446.     int hidden = FALSE;
  447.     for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
  448.         if ((xor || d_region->screenID == screenID) &&
  449.             d_region->Overlap(region, tRegion))
  450.         {
  451.             int text_left;
  452.             int text_top;
  453.  
  454.             if (tRegion.left + cell_width <= tRegion.right + 1)
  455.             {        // Patch for Borland setviewport bug.
  456.                 if (!hidden && eventManager)
  457.                 {
  458.                     hidden = TRUE;
  459.                     eventManager->DevicesHide(region);
  460.                     settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
  461.                     settextjustify(LEFT_TEXT, TOP_TEXT);
  462.                     setcolor(MapColor(palette, TRUE));
  463.                     if (fill)
  464.                         setfillstyle(palette->fillPattern, MapColor(palette, FALSE));
  465.                     if (xor)
  466.                         setwritemode(XOR_PUT);
  467.                 }
  468.                 if (tRegion.top > region.top || tRegion.bottom < region.bottom)
  469.                 {
  470.                     // This is the case where the text is going to get 
  471.                     // clipped because it overlaps a region boundary.  Try to
  472.                     // find any regions of the same ID that are adjacent
  473.                     // above or below and coalesce them temporarily.
  474.                     for (UI_REGION_ELEMENT *a_reg = First(); a_reg; a_reg = a_reg->Next())
  475.                         if (a_reg->screenID == screenID &&
  476.                             a_reg != d_region &&
  477.                             a_reg->region.left < tRegion.right &&
  478.                             a_reg->region.right > tRegion.left)
  479.                         {
  480.                             if ((tRegion.top > region.top &&
  481.                                    tRegion.top == a_reg->region.bottom + 1)||
  482.                                     (tRegion.bottom < region.bottom &&
  483.                                      tRegion.bottom == a_reg->region.top - 1))
  484.                             {
  485.                                 tRegion.left = Max(tRegion.left, a_reg->region.left);
  486.                                 tRegion.top = Min(tRegion.top, a_reg->region.top);
  487.                                 tRegion.right = Min(tRegion.right, a_reg->region.right);
  488.                                 tRegion.bottom = Max(tRegion.bottom, a_reg->region.bottom);
  489.                             }
  490.                         }
  491.                 }
  492.                 setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
  493.                 if (region.left < tRegion.left)
  494.                 {
  495.                     offset = (tRegion.left - region.left - 1)/ cell_width + 1;
  496.                     text_left = offset * cell_width - tRegion.left + region.left;
  497.                 }
  498.                 else
  499.                 {
  500.                     offset = 0;
  501.                     text_left = region.left - tRegion.left;
  502.                 }
  503.                 text_top = region.top - tRegion.top;
  504.                 if (fill)
  505.                     bar(text_left, text_top, text_left + width - 1, text_top + height - 1);
  506.                 outtextxy(text_left, text_top, (char *)&fillLine[offset]); // Typecast Borland bug
  507.             }
  508.         }
  509.  
  510.     // Show the screen devices.
  511.     if (hidden && eventManager)
  512.     {
  513.         eventManager->DevicesShow(region);
  514.         if (xor)
  515.             setwritemode(COPY_PUT);
  516.     }
  517. }
  518.  
  519. #pragma argsused
  520. int UI_DOS_BGI_DISPLAY::TextHeight(const char *string, SCREENID screenID)
  521. {
  522.     return textheight((char *)string); // Typecast Borland bug
  523. }
  524.  
  525. #pragma argsused
  526. int UI_DOS_BGI_DISPLAY::TextWidth(const char *string, SCREENID screenID)
  527. {
  528.     return textwidth((char *)string); // Typecast Borland bug
  529. }
  530.