home *** CD-ROM | disk | FTP | other *** search
- // Zinc Interface Library - BGIDSP.CPP
- // COPYRIGHT (C) 1990, 1991. All Rights Reserved.
- // Zinc Software Incorporated. Pleasant Grove, Utah USA
-
- #include "ui_dsp.hpp"
- #include <dos.h>
- #include <mem.h>
- #include <alloc.h>
- #include <string.h>
- #include <graphics.h>
-
- static char fillLine[256];
-
- UI_DOS_BGI_DISPLAY::UI_DOS_BGI_DISPLAY(int driver, int mode):
- UI_DISPLAY(FALSE, 8, 14)
- {
- // Find the type of display.
- if (driver == DETECT)
- {
- detectgraph(&driver, &mode);
- if (driver < 0)
- return;
- }
-
- // Try to initialize the graphics driver.
- int tDriver = -3;
- int tMode;
- _path->SetFileName(0);
- char *pathToDriver = NULL;
- do
- {
- tDriver = driver;
- tMode = mode;
- initgraph(&tDriver, &tMode, pathToDriver);
- pathToDriver = _path->NextPathName();
- } while (tDriver == -3 && pathToDriver);
- if (tDriver < 0)
- return;
-
- lines = getmaxy()+ 1;
- columns = getmaxx()+ 1;
- maxColor = getmaxcolor();
-
- // Fill the screen according to the specified palette.
- settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
- settextjustify(LEFT_TEXT, TOP_TEXT);
- setfillstyle(_backgroundPalette->fillPattern, MapColor(_backgroundPalette, FALSE));
- setviewport(0, 0, columns - 1, lines - 1, TRUE);
- bar(0, 0, columns - 1, lines - 1);
-
- // Define the screen display region.
- Add(0, new UI_REGION_ELEMENT(ID_SCREEN, 0, 0, columns - 1, lines - 1));
- installed = TRUE;
- }
-
- UI_DOS_BGI_DISPLAY::~UI_DOS_BGI_DISPLAY(void)
- {
- // Restore the display.
- if (installed)
- closegraph();
- }
-
- // ----- Member functions ---------------------------------------------------
-
- void UI_DOS_BGI_DISPLAY::Bitmap(SCREENID screenID, int column, int line,
- int bitmapWidth, int bitmapHeight, const UCHAR *bitmapArray,
- const UI_PALETTE *palette, const UI_REGION *clipRegion)
- {
- UI_REGION tRegion;
- UI_REGION region;
- region.left = column;
- region.top = line;
- region.right = column + bitmapWidth - 1;
- region.bottom = line + bitmapHeight - 1;
- if (clipRegion)
- {
- region.left = Max(region.left, clipRegion->left);
- region.top = Max(region.top, clipRegion->top);
- region.right = Min(region.right, clipRegion->right);
- region.bottom = Min(region.bottom, clipRegion->bottom);
- }
-
- // Draw the bitmap on the display.
- int hidden = FALSE;
- for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
- if (d_region->screenID == screenID && d_region->Overlap(region, tRegion))
- {
- if (!hidden && eventManager)
- {
- hidden = TRUE;
- eventManager->DevicesHide(region);
- setviewport(0, 0, columns - 1, lines - 1, TRUE);
- }
- for (int row = tRegion.top; row <= tRegion.bottom; row++)
- {
- UCHAR *pixel = (UCHAR *)(bitmapArray + (row - region.top) * bitmapWidth + tRegion.left - region.left);
- for (int column = tRegion.left; column <= tRegion.right; column++, pixel++)
- putpixel(column, row, *pixel);
- }
- }
-
- // Show the screen devices.
- if (hidden && eventManager)
- eventManager->DevicesShow(region);
- }
-
- void UI_DOS_BGI_DISPLAY::Ellipse(SCREENID screenID, int x, int y, int startAngle,
- int endAngle, int xRadius, int yRadius, const UI_PALETTE *palette,
- int fill, int xor, const UI_REGION *clipRegion)
- {
- // Compute the minimum rectangle that the ellipse will fit in.
- UI_REGION region, tRegion;
- region.left = x - xRadius;
- region.right = x + xRadius;
- region.top = y - yRadius;
- region.bottom = y + yRadius;
- if (clipRegion)
- {
- region.left = Max(region.left, clipRegion->left);
- region.top = Max(region.top, clipRegion->top);
- region.right = Min(region.right, clipRegion->right);
- region.bottom = Min(region.bottom, clipRegion->bottom);
- }
-
- // Draw the ellipse on the display.
- int hidden = FALSE;
- for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
- if ((xor || d_region->screenID == screenID) &&
- d_region->Overlap(region, tRegion))
- {
- if (!hidden && eventManager)
- {
- hidden = TRUE;
- eventManager->DevicesHide(region);
- setcolor(MapColor(palette, TRUE));
- if (fill)
- setfillstyle(palette->fillPattern, MapColor(palette, FALSE));
- if (xor)
- setwritemode(XOR_PUT);
- }
-
- setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
- if (fill)
- {
- if (startAngle == 0 && endAngle == 360)
- fillellipse(x - tRegion.left, y - tRegion.top, xRadius, yRadius);
- else
- sector(x - tRegion.left, y - tRegion.top, startAngle, endAngle, xRadius, yRadius);
- }
- else
- ellipse(x - tRegion.left, y - tRegion.top, startAngle, endAngle, xRadius, yRadius);
- }
-
- // Show the screen devices.
- if (hidden && eventManager)
- {
- eventManager->DevicesShow(region);
- if (xor)
- setwritemode(COPY_PUT);
- }
- }
-
- void UI_DOS_BGI_DISPLAY::Line(SCREENID screenID, int x1, int y1, int x2, int y2,
- const UI_PALETTE *palette, int width, int xor, const UI_REGION *clipRegion)
- {
- // Compute the minimum rectangle that the line will fit in.
- UI_REGION region, tRegion;
- region.left = Min(x1, x2);
- region.right = Max(x1, x2);
- region.top = Min(y1, y2);
- region.bottom = Max(y1, y2);
- if (clipRegion)
- {
- region.left = Max(region.left, clipRegion->left);
- region.top = Max(region.top, clipRegion->top);
- region.right = Min(region.right, clipRegion->right);
- region.bottom = Min(region.bottom, clipRegion->bottom);
- }
-
- // Draw the line on the display.
- int hidden = FALSE;
- for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
- if ((xor || d_region->screenID == screenID) &&
- d_region->Overlap(region, tRegion))
- {
- if (!hidden && eventManager)
- {
- hidden = TRUE;
- eventManager->DevicesHide(region);
- setcolor(MapColor(palette, TRUE));
- if (xor)
- setwritemode(XOR_PUT);
- }
-
- setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
- line(x1 - tRegion.left, y1 - tRegion.top, x2 - tRegion.left, y2 - tRegion.top);
- }
-
- // Show the screen devices.
- if (hidden && eventManager)
- {
- eventManager->DevicesShow(region);
- if (xor)
- setwritemode(COPY_PUT);
- }
- }
-
- int UI_DOS_BGI_DISPLAY::MapColor(const UI_PALETTE *palette, int foreground)
- {
- if (maxColor == 15)
- {
- if (foreground)
- return(palette->colorForeground);
- return(palette->colorBackground);
- }
- else if (maxColor == 1)
- {
- if (foreground)
- return(palette->bwForeground);
- return(palette->bwBackground);
- }
- if (foreground)
- return(palette->grayScaleForeground);
- return(palette->grayScaleBackground);
- }
-
- void UI_DOS_BGI_DISPLAY::Polygon(SCREENID screenID, int numPoints,
- const int *polygonPoints, const UI_PALETTE *palette, int fill, int xor,
- const UI_REGION *clipRegion)
- {
- // Compute the minimum rectangle that the polygon will fit in.
- UI_REGION region, tRegion;
- region.left = columns;
- region.right = 0;
- region.top = lines;
- region.bottom = 0;
- for (int i = 0; i < numPoints * 2; i += 2)
- {
- region.left = Min(region.left, polygonPoints[i]);
- region.right = Max(region.right, polygonPoints[i]);
- region.top = Min(region.top, polygonPoints[i+1]);
- region.bottom = Max(region.bottom, polygonPoints[i+1]);
- }
- if (clipRegion)
- {
- region.left = Max(region.left, clipRegion->left);
- region.top = Max(region.top, clipRegion->top);
- region.right = Min(region.right, clipRegion->right);
- region.bottom = Min(region.bottom, clipRegion->bottom);
- }
-
- // Draw the polygon on the display.
- int hidden = FALSE;
- int *tPolygon = new int[numPoints * 2];
- for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
- if ((xor || d_region->screenID == screenID) &&
- d_region->Overlap(region, tRegion))
- {
- if (!hidden && eventManager)
- {
- hidden = TRUE;
- eventManager->DevicesHide(region);
- setcolor(MapColor(palette, TRUE));
- if (fill)
- setfillstyle(palette->fillPattern, MapColor(palette, FALSE));
- if (xor)
- setwritemode(XOR_PUT);
- }
-
- setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
- for (i = 0; i < numPoints * 2; i += 2)
- {
- tPolygon[i] = polygonPoints[i] - tRegion.left;
- tPolygon[i+1] = polygonPoints[i+1] - tRegion.top;
- }
- if (fill)
- fillpoly(numPoints, tPolygon);
- else
- drawpoly(numPoints, tPolygon);
- }
- delete tPolygon;
-
- // Show the screen devices.
- if (hidden && eventManager)
- {
- eventManager->DevicesShow(region);
- if (xor)
- setwritemode(COPY_PUT);
- }
- }
-
- #pragma argsused
- void UI_DOS_BGI_DISPLAY::Rectangle(SCREENID screenID, int left, int top, int right,
- int bottom, const UI_PALETTE *palette, int width, int fill, int xor,
- const UI_REGION *clipRegion)
- {
- // Assign the rectangle to the region structure.
- UI_REGION region, tRegion;
- region.left = left;
- region.right = right;
- region.top = top;
- region.bottom = bottom;
- if (clipRegion)
- {
- region.left = Max(region.left, clipRegion->left);
- region.top = Max(region.top, clipRegion->top);
- region.right = Min(region.right, clipRegion->right);
- region.bottom = Min(region.bottom, clipRegion->bottom);
- }
-
- // Draw the rectangle on the display.
- int hidden = FALSE;
- for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
- if ((xor || d_region->screenID == screenID) &&
- d_region->Overlap(region, tRegion))
- {
- if (!hidden && eventManager)
- {
- hidden = TRUE;
- eventManager->DevicesHide(region);
- setcolor(MapColor(palette, TRUE));
- if (fill)
- setfillstyle(palette->fillPattern, MapColor(palette, FALSE));
- if (xor)
- setwritemode(XOR_PUT);
- }
-
- setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
- if (fill && xor)
- {
- for (int i = tRegion.top; i <= tRegion.bottom; i++)
- line(left - tRegion.left, i - tRegion.top, right - tRegion.left, i - tRegion.top);
- }
- else if (fill)
- bar(left - tRegion.left, top - tRegion.top, right - tRegion.left, bottom - tRegion.top);
- else
- rectangle(left - tRegion.left, top - tRegion.top, right - tRegion.left, bottom - tRegion.top);
- }
-
- // Show the screen devices.
- if (hidden && eventManager)
- {
- eventManager->DevicesShow(region);
- if (xor)
- setwritemode(COPY_PUT);
- }
- }
-
- void UI_DOS_BGI_DISPLAY::RectangleXORDiff(const UI_REGION &oldRegion,
- const UI_REGION &newRegion)
- {
- // See if the regions match.
- if (oldRegion.left == newRegion.left && oldRegion.top == newRegion.top &&
- oldRegion.right == newRegion.right && oldRegion.bottom == newRegion.bottom)
- return;
-
- // Hide the screen devices.
- UI_REGION region;
- region.left = Min(oldRegion.left, newRegion.left);
- region.top = Min(oldRegion.top, newRegion.top);
- region.right = Max(oldRegion.right, newRegion.right);
- region.bottom = Max(oldRegion.bottom, newRegion.bottom);
- if (eventManager)
- eventManager->DevicesHide(region);
-
- // Draw the XOR rectangles on the display.
- setwritemode(XOR_PUT);
- setcolor(MapColor(_xorPalette, TRUE));
- setviewport(0, 0, columns - 1, lines - 1, TRUE);
- rectangle(oldRegion.left, oldRegion.top, oldRegion.right, oldRegion.bottom);
- rectangle(newRegion.left, newRegion.top, newRegion.right, newRegion.bottom);
- setwritemode(COPY_PUT);
-
- // Show the screen devices.
- if (eventManager)
- eventManager->DevicesShow(region);
- }
-
- void UI_DOS_BGI_DISPLAY::RegionConvert(UI_REGION ®ion, USHORT *oldFlags, USHORT newFlags)
- {
- // Check for a convertable region.
- if (FlagSet(*oldFlags, newFlags))
- return;
-
- // These variables handle Text<-->Graphics coordinate problems.
- region.left *= 8;
- region.top *= 14;
- region.right = region.right * 8 + 7;
- region.bottom = region.bottom * 14 + 12;
-
- *oldFlags |= newFlags;
- }
-
- #pragma argsused
- void UI_DOS_BGI_DISPLAY::RegionMove(const UI_REGION &oldRegion, int newColumn, int newLine,
- SCREENID oldScreenID, SCREENID newScreenID)
- {
- unsigned size = imagesize(oldRegion.left, oldRegion.top, oldRegion.right, oldRegion.bottom);
- void far *buffer = farmalloc(size);
- getimage(oldRegion.left, oldRegion.top, oldRegion.right, oldRegion.bottom, buffer);
- putimage(newColumn, newLine, buffer, COPY_PUT);
- farfree(buffer);
- }
-
- void UI_DOS_BGI_DISPLAY::Text(SCREENID screenID, int left, int top,
- const char *text, const UI_PALETTE *palette, int length,
- int fill, int xor, const UI_REGION *clipRegion)
- {
- UI_REGION tRegion;
- UI_REGION region;
- int offset;
-
- // Copy the text to a scrap buffer
- if (xor)
- {
- Rectangle(screenID, left, top,
- left + length * textwidth("X") - 1,
- top + textheight("X") - 1, palette, 1, TRUE, TRUE);
- return;
- }
- else if (length > 0)
- {
- memcpy(fillLine, text, length);
- fillLine[length] = '\0';
- }
- else
- strcpy(fillLine, text);
-
- // Convert the cell coordinates.
- int height = textheight((char *)fillLine); // Typecast Borland bug
- int cell_width = textwidth("W");
- int width = (length == -1 ? textwidth((char *)fillLine): length * cell_width); // Typecast Borland bug
- region.left = left;
- region.top = top;
- region.right = region.left + width - 1;
- region.bottom = region.top + height - 1;
- if (clipRegion)
- {
- region.left = Max(region.left, clipRegion->left);
- region.top = Max(region.top, clipRegion->top);
- region.right = Min(region.right, clipRegion->right);
- region.bottom = Min(region.bottom, clipRegion->bottom);
- }
-
- // Draw the text on the display.
- int hidden = FALSE;
- for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
- if ((xor || d_region->screenID == screenID) &&
- d_region->Overlap(region, tRegion))
- {
- int text_left;
- int text_top;
-
- if (tRegion.left + cell_width <= tRegion.right + 1)
- { // Patch for Borland setviewport bug.
- if (!hidden && eventManager)
- {
- hidden = TRUE;
- eventManager->DevicesHide(region);
- settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
- settextjustify(LEFT_TEXT, TOP_TEXT);
- setcolor(MapColor(palette, TRUE));
- if (fill)
- setfillstyle(palette->fillPattern, MapColor(palette, FALSE));
- if (xor)
- setwritemode(XOR_PUT);
- }
- if (tRegion.top > region.top || tRegion.bottom < region.bottom)
- {
- // This is the case where the text is going to get
- // clipped because it overlaps a region boundary. Try to
- // find any regions of the same ID that are adjacent
- // above or below and coalesce them temporarily.
- for (UI_REGION_ELEMENT *a_reg = First(); a_reg; a_reg = a_reg->Next())
- if (a_reg->screenID == screenID &&
- a_reg != d_region &&
- a_reg->region.left < tRegion.right &&
- a_reg->region.right > tRegion.left)
- {
- if ((tRegion.top > region.top &&
- tRegion.top == a_reg->region.bottom + 1)||
- (tRegion.bottom < region.bottom &&
- tRegion.bottom == a_reg->region.top - 1))
- {
- tRegion.left = Max(tRegion.left, a_reg->region.left);
- tRegion.top = Min(tRegion.top, a_reg->region.top);
- tRegion.right = Min(tRegion.right, a_reg->region.right);
- tRegion.bottom = Max(tRegion.bottom, a_reg->region.bottom);
- }
- }
- }
- setviewport(tRegion.left, tRegion.top, tRegion.right, tRegion.bottom, TRUE);
- if (region.left < tRegion.left)
- {
- offset = (tRegion.left - region.left - 1)/ cell_width + 1;
- text_left = offset * cell_width - tRegion.left + region.left;
- }
- else
- {
- offset = 0;
- text_left = region.left - tRegion.left;
- }
- text_top = region.top - tRegion.top;
- if (fill)
- bar(text_left, text_top, text_left + width - 1, text_top + height - 1);
- outtextxy(text_left, text_top, (char *)&fillLine[offset]); // Typecast Borland bug
- }
- }
-
- // Show the screen devices.
- if (hidden && eventManager)
- {
- eventManager->DevicesShow(region);
- if (xor)
- setwritemode(COPY_PUT);
- }
- }
-
- #pragma argsused
- int UI_DOS_BGI_DISPLAY::TextHeight(const char *string, SCREENID screenID)
- {
- return textheight((char *)string); // Typecast Borland bug
- }
-
- #pragma argsused
- int UI_DOS_BGI_DISPLAY::TextWidth(const char *string, SCREENID screenID)
- {
- return textwidth((char *)string); // Typecast Borland bug
- }
-