home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * General routines to handle the graphic calls. *
- * *
- * Written by: Gershon Elber Ver 0.9, Apr. 1989 *
- * *
- * Support: Hercules, CGA, EGA/VGA graphic cards. *
- * *
- * 0.3 modif. - menus now can read alpha and compere to first chars in menus.*
- * 0.32 modif. - if erase of GGDrawMenu TRUE, simply clear area first. *
- * fix DrawPoint title drawing error... *
- * fix set up color default (not to be black). *
- * 0.4 modif. - MS mouse support added. *
- * 0.5 modif. - CGA support was added. *
- * 0.6 modif. - Prefix all functions/external vars with GG. *
- * Add window frame to view & status windows. *
- * 0.7 modif. - Improving the shape of the graphical cursor. *
- * Disabling stdout during graphic mode to unshow ^c... *
- * 0.8 modif. - Adding support for the EGA/VGA class of machines. *
- * 0.9 modif. - Full line editing replaced old simplified version. *
- * 1.0 modif. - Fix EGA/VGA type of devices aspect ratio. *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <alloc.h>
- #include <dir.h>
- #include <dos.h>
- #include <mem.h>
- #include <math.h>
- #include <ctype.h>
- #include <graphics.h>
- #include <string.h>
- #include <io.h>
- #include <fcntl.h>
- #include <conio.h>
-
- /* See also the conditional compilation flags in GraphGnG.h! */
-
- #include "Program.h"
- #include "GraphGnG.h"
- #include "GraphGnL.h"
- #include "MouseDrv.h"
-
- extern int MouseExists; /* Responsibility of program! */
- extern int GraphDriver; /* "" */
-
- int GGGraphMode; /* The Graphics mode value */
- double GGAspectRatio; /* Aspect ratio of a pixel on the screen */
- int GGScreenMaxX, GGScreenMaxY; /* The maximum resolution of the screen */
- int GGScreenMaxY2; /* ScreenMaxY / 2 */
- int GGScreenMaxColors; /* The maximum # of colors available */
- int GGScreenMaxPages; /* The maximum # of pages available */
- int GGScreenErrorCode; /* Reports any graphics errors */
- int GGCurrentCursorX, GGCurrentCursorY; /* Cursor current position */
- int GGScreenGraphicMode = FALSE; /* TRUE if the screen in graphic mode */
-
- static double WndwAspectRatio, GlblAspectRatio;
- static struct palettetype palette; /* Used to read palette info */
- static char *CursorImageBuffer; /* Cursor shape */
- static int LocalMoveToX, LocalMoveToY; /* Save last position we move */
- static char LastGetChar; /* Last char recieved in GGUpdateGetPoint */
- static double MouseXRatio, MouseYRatio;
- static int DefaultFontSize, MenuLineWidth; /* Depend on graphic driver */
- static int ScreenCursorColor; /* Graphic and text (in graphic screen) */
- static int ViewPortX, ViewPortY; /* Viewport offset from top left (0, 0) */
- static int OldStdOut; /* So we could recover it when exit from graph mode */
-
- #ifndef NOWINDOWS
-
- typedef struct WindowStruct { /* The window structure */
- double MinX, MaxX, MinY, MaxY;
- int FrameColor, LineColor;
- } WindowStruct;
-
- #define FRAME_X_WIDTH 0.03 /* Width of the window frames */
- #define FRAME_Y_WIDTH 0.03
-
- static WindowStruct MenuWindow = /* Menu window */
- { SW_MIN_X, SW_MAX_X, SW_MIN_Y, SW_MAX_Y,
- SW_FRAME_COLOR, SW_LINE_COLOR
- };
-
- static WindowStruct ViewWindow = /* View window */
- { VW_MIN_X, VW_MAX_X, VW_MIN_Y, VW_MAX_Y,
- VW_FRAME_COLOR, VW_LINE_COLOR
- };
-
- static WindowStruct *WndwViewWindow, *WndwMenuWindow;
-
- static void WndwDrawAllWndwFrames(void);
- static void WndwDrawWindowFrame(WindowStruct *Window);
- static void WndwSetUpAllWndws(void);
- static void WndwClearWindow(WindowStruct *Window);
- static void WndwSetViewPort(double XMin, double YMin, double XMax, double YMax);
-
- #endif NOWIDNOWS
-
- #ifndef NOMENUS
-
- static struct MenuItem *ActvMenu; /* Last drawn menu (active menu...) */
- static int ActvMenuN, ActvMenuActive; /* Info. on active menu */
-
- static void GGDrawMenuFrame(int n, int color);
- static void GGDrawMenuItems(int n, struct MenuItem m[], int *active);
-
- #endif NOMENUS
-
- #ifndef NOHELP
-
- static FILE *GGFindFile(char *FileName, char *Attribute);
- static void HelpUpdateY(double *Yaxis);
-
- #endif NOHELP
-
- static int GGUpdateGetPointKbd(int *x, int *y);
- static int GGGetKey(void);
-
- /****************************************************************************
- * Routine to move to a normalized point between -1..1 on both axes : *
- ****************************************************************************/
- void GGMyMove(double x, double y)
- {
- #ifndef NOGRAPHICS
- /* Note I use ScreenMaxY2 as X>ScreenMaxY2 left for text (menus). */
- LocalMoveToX = (int) ((x * WndwAspectRatio * GGScreenMaxY2 + GGScreenMaxY2)
- * GlblAspectRatio);
- LocalMoveToY = (int) (-y * GGScreenMaxY2 + GGScreenMaxY2);
- moveto(LocalMoveToX - ViewPortX, LocalMoveToY - ViewPortY);
- #endif NOGRAPHICS
- }
-
- /****************************************************************************
- * Routine to draw to a normalized point between -1..1 on both axes : *
- ****************************************************************************/
- void GGMyDraw(double x, double y)
- {
- #ifndef NOGRAPHICS
- int NewX, NewY;
-
- /* Note I use ScreenMaxY2 as X>ScreenMaxY2 left for text (menus). */
- NewX = (int) ((x * WndwAspectRatio * GGScreenMaxY2 + GGScreenMaxY2)
- * GlblAspectRatio);
- NewY = (int) (-y * GGScreenMaxY2 + GGScreenMaxY2);
- line(LocalMoveToX - ViewPortX, LocalMoveToY - ViewPortY,
- NewX - ViewPortX, NewY - ViewPortY);
- LocalMoveToX = NewX;
- LocalMoveToY = NewY;
- #endif NOGRAPHICS
- }
-
- /****************************************************************************
- * Routine to draw to a normelized point between -1..1 on both axes : *
- ****************************************************************************/
- void GGMySetColor(int Color)
- {
- #ifndef NOGRAPHICS
- if (Color >= GGScreenMaxColors)
- Color = Color % (GGScreenMaxColors-1) + 1;
- setcolor(Color);
- #endif NOGRAPHICS
- }
-
- /****************************************************************************
- * Routine to reset all the system to starting condition : *
- ****************************************************************************/
- void GGInitGraph(void)
- {
- #ifndef NOGRAPHICS
- int xasp, yasp, /* Used to read the aspect ratio */
- i, j;
-
- if (registerbgidriver(Herc_driver) < 0) MyExit(1);
- if (registerbgidriver(CGA_driver) < 0) MyExit(1);
- if (registerbgidriver(EGAVGA_driver) < 0) MyExit(1);
-
- /* For some wierd reason, some machines waits much more than expected on */
- /* the first delay. Lets do it now, so people will consider it part of */
- /* the initialization (make it a feature...)... */
- delay(1);
-
- if (GraphDriver == 0) {
- /* Use autodetect feature of the graphic library to see what we have */
- detectgraph(&GraphDriver, &GGGraphMode);
- if (GraphDriver < 0) {
- fprintf(stderr, "Auto detect: No graphics device detected\n");
- MyExit(1);
- }
- }
-
- /* Put in the following any graphic driver specific setup: */
- switch (GraphDriver) {
- case CGA:
- GGGraphMode = CGAHI;
- break;
- case EGA:
- GGGraphMode = EGAHI;
- break;
- case EGA64:
- GGGraphMode = EGA64HI;
- break;
- case EGAMONO:
- GGGraphMode = EGAMONOHI;
- break;
- case HERCMONO:
- GGGraphMode = HERCMONOHI;
- break;
- case VGA:
- GGGraphMode = VGAMED;
- break;
- default:
- fprintf(stderr, "Requested graphic device (%d - see .CFG file) is not supported\n",
- GraphDriver);
- MyExit(1);
- break;
- }
-
- initgraph(&GraphDriver, &GGGraphMode, "");
- GGScreenErrorCode = graphresult(); /* Read result of initialization */
- if (GGScreenErrorCode != grOk) { /* Error occured during init */
- fprintf(stderr, " Graphics System Error: %s\n",
- grapherrormsg(GGScreenErrorCode));
- MyExit(1);
- }
-
- getpalette(&palette); /* Read the palette from board */
- GGScreenMaxColors = getmaxcolor() + 1; /* Read maximum number of colors */
- ScreenCursorColor = (GGScreenMaxColors > 1 ? GGScreenMaxColors - 1 :
- GGScreenMaxColors);
-
- GGScreenMaxX = getmaxx(); /* Read size of screen */
- GGScreenMaxY = getmaxy();
- GGScreenMaxY2 = GGScreenMaxY / 2;
- GGCurrentCursorX = GGScreenMaxX / 2;
- GGCurrentCursorY = GGScreenMaxY2;
- getaspectratio(&xasp, &yasp); /* Read the hardware aspect */
- GGAspectRatio = (double) xasp / (double) yasp; /* Get correction factor: */
- GlblAspectRatio = 1.0 / GGAspectRatio;
- WndwAspectRatio = 1.0;
-
- /* Put in the following any graphic driver specific setup: */
- switch (GraphDriver) {
- case CGA:
- DefaultFontSize = 1; /* Fixed width font */
- MenuLineWidth = NORM_WIDTH;
- GlblAspectRatio = 1 / (GGAspectRatio * 1.14); /* Make bigger. */
- GGScreenMaxPages = 1;
- GGScreenMaxY -= 2; /* Dont ask my why! */
- GGScreenMaxY2 -= 1;
- break;
-
- case EGA:
- DefaultFontSize = 1; /* Fixed width font */
- MenuLineWidth = THICK_WIDTH;
- GGScreenMaxPages = 2;
- GlblAspectRatio = 1.2;/* I dont like it either, but its simple...*/
- break;
-
- case EGA64:
- DefaultFontSize = 1; /* Fixed width font */
- MenuLineWidth = THICK_WIDTH;
- GGScreenMaxPages = 1;
- GlblAspectRatio = 1.2;/* I dont like it either, but its simple...*/
- break;
-
- case EGAMONO:
- DefaultFontSize = 1; /* Fixed width font */
- MenuLineWidth = THICK_WIDTH;
- GGScreenMaxPages = 2;
- GGScreenMaxColors = 2; /* Dont want blinking lines... */
- GlblAspectRatio = 1.2;/* I dont like it either, but its simple...*/
- break;
-
- case HERCMONO:
- DefaultFontSize = 1; /* Fixed width font */
- MenuLineWidth = THICK_WIDTH;
- GGScreenMaxPages = 2;
- break;
-
- case VGA:
- DefaultFontSize = 1; /* Fixed width font */
- MenuLineWidth = THICK_WIDTH;
- GGScreenMaxPages = 2;
- GlblAspectRatio = 1.2;/* I dont like it either, but its simple...*/
- break;
- }
-
- # ifdef SINGLEPAGE
- GGScreenMaxPages = 1;
- # endif SINGLEPAGE
- # ifdef DEBUG
- GGCloseGraph();
- fprintf(stderr, "ScreenMaxX = %d, ScreenMaxY = %d, MaxColors = %d\n",
- GGScreenMaxX, GGScreenMaxY, GGScreenMaxColors);
- fprintf(stderr, "AspectRatio = %lf\n", GGAspectRatio);
- MyExit(1);
- # endif DEBUG
-
- /* Prepare the cursor (Arrow) image : */
- cleardevice();
- GGMySetColor(ScreenCursorColor);
- setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
- line(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y);
- j = CURSOR_IMAGE_X / 3;
- for (i=1; i<=7; i++) line(0, 0, j, j + i); /* Draw the arrow head */
- j = CURSOR_IMAGE_Y / 3;
- for (i=1; i<=7; i++) line(0, 0, j + i, j);
-
- CursorImageBuffer = malloc(imagesize(0, 0, CURSOR_IMAGE_X,
- CURSOR_IMAGE_Y));
- getimage(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y, CursorImageBuffer);
-
- for (i = GGScreenMaxPages - 1; i >= 0; i--) {
- setactivepage(i);
- # ifndef NOWINDOWS
- WndwSetUpAllWndws();
- # else
- GGClearAllScreen();
- # endif NOWINDOWS
- }
-
- settextstyle(DEFAULT_FONT, HORIZ_DIR, DefaultFontSize);
-
- if (MouseExists) {
- switch (GraphDriver) {
- case CGA:
- MSMouseXmax = 1000; /* Set Column Range */
- MSMouseYmax = 1000; /* Set Row range */
- break;
- case EGA:
- case EGA64:
- case EGAMONO:
- case VGA:
- /* Although 1000x1000 is the regular normalized mouse screen */
- /* it is too lazy on 1:1 ratio. */
- MSMouseXmax = 1000; /* Set Column Range */
- MSMouseYmax = 1000; /* Set Row range */
- break;
- case HERCMONO:
- /* Compensate on the text mode the mouse knows about as */
- /* hercules is not supported by the mouse driver! */
- MSMouseXmax = 8000; /* Set Column Range */
- MSMouseYmax = 8000; /* Set Row range */
- break;
- }
- MouseXRatio = ((double) GGScreenMaxX) / MSMouseXmax;
- MouseYRatio = ((double) GGScreenMaxY) / MSMouseYmax;
- }
-
- GGScreenGraphicMode = TRUE;
- i = open("nul", O_WRONLY); /* Redirect the stdout to nul: (no ^C...) */
- fflush(stdout);
- OldStdOut = dup(1);
- dup2(i, 1);
- close(i);
- #endif NOGRAPHICS
- }
-
- /****************************************************************************
- * Routine to close and shutdown graphic mode : *
- ****************************************************************************/
- void GGCloseGraph(void)
- {
- #ifndef NOGRAPHICS
- if (!GGScreenGraphicMode) return;
- closegraph(); /* Return the system to text mode */
- GGScreenGraphicMode = FALSE;
- dup2(OldStdOut, 1); /* Recover stdout to its regular status */
- close(OldStdOut);
- #endif NOGRAPHICS
- }
-
- /****************************************************************************
- * Routine to update x, y coordinates according to current x, y and key *
- * pressed. Returns TRUE only if <Enter> or alpha char is pressed. *
- ****************************************************************************/
- static int GGUpdateGetPointKbd(int *x, int *y)
- {
- int BrkPressed = FALSE;
-
- switch (LastGetChar = getch()) {
- case 0:
- switch (getch()) { /* extended character: */
- case 16: MyExit(0); /* Alt - Q, async. exit... */
- case 71:
- *x -= 1; /* Arrowes - move 1 at a time */
- *y -= 1;
- break;
- case 72:
- *y -= 1;
- break;
- case 73:
- *x += 1;
- *y -= 1;
- break;
- case 75:
- *x -= 1;
- break;
- case 77:
- *x += 1;
- break;
- case 79:
- *x -= 1;
- *y += 1;
- break;
- case 80:
- *y += 1;
- break;
- case 81:
- *x += 1;
- *y += 1;
- break;
- }
- break;
- case 10:
- case 13:
- BrkPressed = TRUE;
- break;
- case '1':
- *x -= 10; /* Shifted arrowes - move 10 at a time */
- *y += 10;
- break;
- case '2':
- *y += 10;
- break;
- case '3':
- *x += 10;
- *y += 10;
- break;
- case '4':
- *x -= 10;
- break;
- case '6':
- *x += 10;
- break;
- case '7':
- *x -= 10;
- *y -= 10;
- break;
- case '8':
- *y -= 10;
- break;
- case '9':
- *x += 10;
- *y -= 10;
- break;
- /* If the key pressed is an alpha - exit */
- default:
- if isalpha(LastGetChar) BrkPressed = TRUE;
- break;
- }
-
- return BrkPressed;
- }
-
- /****************************************************************************
- * Routine to get one x, y selected point in normelized form (-1..1) : *
- ****************************************************************************/
- void GGGetPoint(double *x, double *y)
- {
- #ifndef NOGRAPHICS
- int Xtemp, Ytemp, Buttons, Xscreen, Yscreen, Quit, GetInput;
- struct viewporttype view;
-
- WndwAspectRatio = 1.0;
-
- getviewsettings(&view); /* During Mouse input - must enable all screen */
- setviewport(ViewPortX = 0, ViewPortY = 0, getmaxx(), getmaxy(), FALSE);
-
- LastGetChar = 0x001; /* Make no kbd input if mouse input... */
-
- Xtemp = GGCurrentCursorX;
- Ytemp = GGCurrentCursorY;
- putimage(GGCurrentCursorX, /* Draw the cursor - starting position */
- GGCurrentCursorY, CursorImageBuffer, XOR_PUT);
-
- if (MouseExists) /* Update mouse on current position */
- MouseSetPosition((int) (GGCurrentCursorX / MouseXRatio),
- (int) (GGCurrentCursorY / MouseYRatio));
- Quit = FALSE;
- do {
- GetInput = FALSE;
- do {
- /* Wait for input from one of the devices: Mouse/Keyboard */
- if (MouseExists && MouseQueryBuffer()) {
- MouseGetBuffer(&Xscreen, &Yscreen, &Buttons);
- GetInput = TRUE;
- GGCurrentCursorX = (int) (Xscreen * MouseXRatio);
- GGCurrentCursorY = (int) (Yscreen * MouseYRatio);
- Quit = Buttons & 0x01;
- }
- if (kbhit()) {
- Quit = GGUpdateGetPointKbd(&GGCurrentCursorX,
- &GGCurrentCursorY);
- if (MouseExists) /* Update mouse on the new position */
- MouseSetPosition((int) (GGCurrentCursorX / MouseXRatio),
- (int) (GGCurrentCursorY / MouseYRatio));
- GetInput = TRUE;
- }
- }
- while (!GetInput);
- if (GGCurrentCursorX < 0) GGCurrentCursorX = 0;
- if (GGCurrentCursorY < 0) GGCurrentCursorY = 0;
- if (GGCurrentCursorX > GGScreenMaxX - CURSOR_IMAGE_X)
- GGCurrentCursorX = GGScreenMaxX - CURSOR_IMAGE_X;
- if (GGCurrentCursorY > GGScreenMaxY - CURSOR_IMAGE_Y / 2)
- GGCurrentCursorY = GGScreenMaxY - CURSOR_IMAGE_Y / 2;
-
- putimage(Xtemp, Ytemp, CursorImageBuffer, XOR_PUT);/* Erase old crsr!*/
- putimage(GGCurrentCursorX, GGCurrentCursorY, CursorImageBuffer,
- XOR_PUT); /* Draw new crsr! */
- Xtemp = GGCurrentCursorX; /* Save them so we could erase it later. */
- Ytemp = GGCurrentCursorY;
- }
- while (!Quit);
-
- putimage(Xtemp, /* Erase last old cursor before quiting */
- Ytemp, CursorImageBuffer, XOR_PUT);
-
- /* See GGMyMove for ScreenMaxY2 */
- *x = (((double) GGCurrentCursorX) / GlblAspectRatio - GGScreenMaxY2) /
- GGScreenMaxY2;
- *y = (((double) GGCurrentCursorY) - GGScreenMaxY2) / (-GGScreenMaxY2);
-
- setviewport(ViewPortX = view.left, ViewPortY = view.top,
- view.right, view.bottom, view.clip);
-
- if (MouseExists) {
- delay(250); /* Flush out any spikes mouse buttons had generated... */
- MouseFlushBuffer();
- }
-
- #endif NOGRAPHICS
- }
-
- /****************************************************************************
- * Routine to draw a point on screen as marker + with a title : *
- ****************************************************************************/
- void GGDrawPoint(double p[], char title[], int PointColor)
- {
- #ifndef NOGRAPHICS
- GGMySetColor(PointColor);
- GGMyMove(p[1] + POINT_SIZE, p[2]);
- GGMyDraw(p[1] - POINT_SIZE, p[2]);
- GGMyMove(p[1], p[2] + POINT_SIZE);
- GGMyDraw(p[1], p[2] - POINT_SIZE);
-
- GGPutMsgXY(title, p[1] + POINT_TITLE, p[2] + POINT_TITLE);
- #endif NOGRAPHICS
- }
-
- #ifndef NOMENUS
-
- static double MenuBaseY;
-
- /*****************************************************************************
- * Routine to draw a menu and return active flag. *
- * Gets n - number of items, m - list of string & colors, menu header first. *
- * erase - if TRUE force erase of menu area first *
- * returns bit pattern integer - one bit per entry. *
- *****************************************************************************/
- int GGMenuDraw(int n, struct MenuItem m[], int erase)
- {
- #ifndef NOGRAPHICS
- int active; /* Used to hold how is active (not null) - one bit per item */
- struct viewporttype view;
-
- getviewsettings(&view);
- if (n <= MENU_MAX_ITEMS) {
- MenuBaseY = MENU_TOP_Y - n*MENU_ITEM_Y - MENU_HEAD_Y;/*Calc menu bot*/
-
- /* Draw the frame & header of the Menu */
- GGViewPortMenuArea();
- if (erase) GGClearMenuArea();
-
- GGDrawMenuFrame(n, MENU_FRAME_COLOR);
- GGDrawMenuItems(n, m, &active); /* Draw string */
-
- ActvMenu = m; /* Save some information on active menu */
- ActvMenuN = n;
- ActvMenuActive = active;
- }
-
- if (!erase)
- setviewport(ViewPortX = view.left, ViewPortY = view.top,
- view.right, view.bottom, view.clip);
-
- return active;
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to draw the menu frame. *
- * Gets n - number of items, color - color of frame. *
- *****************************************************************************/
- static void GGDrawMenuFrame(int n, int color)
- {
- #ifndef NOGRAPHICS
- int i;
- struct linesettingstype saveline;
-
- getlinesettings(&saveline);
- setlinestyle(SOLID_LINE, 0, MenuLineWidth);
-
- GGMySetColor(color);
- GGMyMove((double) MENU_BASE_X,
- (double) MenuBaseY); /* Draw the outer frame */
- GGMyDraw((double) MENU_BASE_X,
- (double) MenuBaseY+MENU_ITEM_Y*n+MENU_HEAD_Y);
- GGMyDraw((double) MENU_BASE_X+MENU_ITEM_X,
- (double) MenuBaseY+MENU_ITEM_Y*n+MENU_HEAD_Y);
- GGMyDraw((double) MENU_BASE_X+MENU_ITEM_X,
- (double) MenuBaseY);
- GGMyDraw((double) MENU_BASE_X,
- (double) MenuBaseY);
- for (i=1; i<=n; i++) {
- GGMyMove((double) MENU_BASE_X,
- (double) MenuBaseY+MENU_ITEM_Y*i);
- GGMyDraw((double) MENU_BASE_X+MENU_ITEM_X,
- (double) MenuBaseY+MENU_ITEM_Y*i);
- }
- setlinestyle(saveline.linestyle, saveline.upattern, saveline.thickness);
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to draw the menu internal strings. *
- * Gets n - number of items, m string structure, active - active string. *
- * Returns in active the none null strings (bit per item) - active menu items.*
- *****************************************************************************/
- static void GGDrawMenuItems(int n, struct MenuItem m[], int *active)
- {
- #ifndef NOGRAPHICS
- int i, power2;
- struct textsettingstype oldtext;
-
- *active = 0;
- power2 = 1;
-
- gettextsettings(&oldtext);
- settextstyle(DEFAULT_FONT, HORIZ_DIR, DefaultFontSize);
- settextjustify(CENTER_TEXT, CENTER_TEXT);
-
- for (i=0; i<=n; i++) {
- GGMySetColor(m[i].color);
- if (i == 0)
- GGPutMsgXY(m[i].string,
- MENU_BASE_X+MENU_ITEM_X/2, MenuBaseY+MENU_ITEM_Y*(n + 0.7));
- else {
- GGPutMsgXY(m[i].string,
- MENU_BASE_X+MENU_ITEM_X/2,
- MenuBaseY+MENU_ITEM_Y*(n - i + 0.4));
- if (strlen(m[i].string)) *active |= power2;
- power2 <<= 1;
- }
- }
-
- settextstyle(oldtext.font, oldtext.direction, oldtext.charsize);
- settextjustify(oldtext.horiz, oldtext.vert);
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to pick an item from menu from active ones: *
- *****************************************************************************/
- int GGMenuPick(void)
- {
- double x, y;
- int i, select = 0, Duplicate;
-
- do {
- if (MouseExists) MouseFlushBuffer(); /* No need of old garbage! */
- GGGetPoint(&x, &y);
-
- /* Try to match the input with the menu first chars */
- Duplicate = FALSE;
- if (islower(LastGetChar)) LastGetChar = toupper(LastGetChar);
- for (i=1; i<=ActvMenuN; i++)
- if (LastGetChar == ActvMenu[i].string[0])
- if (select) Duplicate = TRUE; /* More than one match ! */
- else select = i;
- if (Duplicate) {
- GGTone(2000, 100); /* Do some noise */
- GGTone(500, 100);
- select = 0;
- continue;
- }
- /* If fails try to see if the arrow is on a valid menu item: */
- if ((!select) && (x >= MENU_BASE_X && x <= MENU_BASE_X+MENU_ITEM_X)) {
- /* Convert into integer item number (still in double...) */
- y = 1 - (y - MENU_TOP_Y + MENU_HEAD_Y) / MENU_ITEM_Y;
- select = (int) y;
- if (!((ActvMenuActive >> (select-1)) & 1))
- select = 0; /* inactive item */
- }
- }
- while (!select);
-
- return select;
- }
-
- /*****************************************************************************
- * Routine to draw the confrim special menu request *
- * Returns TRUE value if Yes selected, FALSE if No selected. *
- *****************************************************************************/
- int GGConfirm(char *s)
- {
- static struct MenuItem ConfMenu[] = { /* Confirm Menu selection */
- YELLOW, " ", /* Make space for everybody */
- MAGENTA, "Yes",
- MAGENTA, "No"
- };
- int select;
-
- GGClearMenuArea();
- strcpy(ConfMenu[0].string, s); /* Set up for new header */
- GGMenuDraw(2, ConfMenu, TRUE);
- select = GGMenuPick();
- GGClearMenuArea();
-
- return (select == 1);
- }
-
- #endif NOMENUS
-
- #ifndef NOHELP
-
- /*****************************************************************************
- * Routine to print help on menu in the menu area. Input is from file *
- * FileName , Which is scanned until MenuName is found and until $ sign *
- * It is the responsibility of this routine to clear the Menu area before *
- * and after the print help ... *
- *****************************************************************************/
- void GGPrintHelpMenu(char *FileName, char *MenuName)
- {
- #ifndef NOGRAPHICS
- FILE *f;
- char s[255]; /* Irregular high length but they are some lengthly lines */
- int i, j, flag;
- double Yaxis;
- struct textsettingstype oldtext;
-
- gettextsettings(&oldtext);
- settextstyle(DEFAULT_FONT, HORIZ_DIR, DefaultFontSize);
-
- GGClearMenuArea();
-
- if ((f = GGFindFile(FileName, "rt")) == NULL)
- return; /* Search all the path names */
- do {
- flag = fgets(s, 255, f) != NULL;
- s[strlen(s)-1] = 0; /* Clear the new line */
- }
- while (strcmp(MenuName, s) && (flag)); /* Skip until correct menu */
-
- if (!flag) {
- GGPutErrorMsg("No Such Menu in file");
- fclose(f);
- return;
- }
-
- Yaxis = 0.93; /* First line to start with */
- do { /* If we are here then we found the menu - Print it */
- flag = (fgets(s, 255, f) != NULL);
- s[strlen(s)-1] = NULL; /* Clear the new line */
- if (s[0] == '*') {
- GGMySetColor(HELP_COLOR_HEADER);
- HelpUpdateY(&Yaxis);
- s[0] = ' ';
- }
- else GGMySetColor(HELP_COLOR);
- if (s[0] != '$') /* Terminator ... */
- if (strlen(s) < MAX_HELP_MENU_CHAR) {
- GGPutMsgXY(s, MENU_BASE_X, Yaxis);
- HelpUpdateY(&Yaxis);
- }
- else {
- i = 0;
- while ((strlen(&s[i]) > MAX_HELP_MENU_CHAR)) {
- j = i + MAX_HELP_MENU_CHAR; /* Break the line ! */
- while (s[j--] != ' '); /* In the nearest space */
- s[++j] = 0; /* Put EOL instead of Space */
- GGPutMsgXY(&s[i], MENU_BASE_X, Yaxis);
- HelpUpdateY(&Yaxis);
- i = j + 1;
- }
- if ((strlen(&s[i]) > 0) && (Yaxis > -1.0)) {
- GGPutMsgXY(&s[i], MENU_BASE_X, Yaxis);
- HelpUpdateY(&Yaxis);
- }
- }
- }
- while ((flag) && (s[0] != '$'));
-
- fclose(f);
-
- GGPutErrorMsg(""); /* Wait for keystroke */
-
- GGClearMenuArea();
- settextstyle(oldtext.font, oldtext.direction, oldtext.charsize);
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to decrease Y for next line in the help printing. Test is made *
- * for last line, and wait and clear area is performed in that case. *
- *****************************************************************************/
- static void HelpUpdateY(double *Yaxis)
- {
- *Yaxis = (*Yaxis) - 0.08;
- if (*Yaxis < -0.75) {
- GGPutErrorMsg("");
- GGClearMenuArea();
- *Yaxis = 0.93;
- GGMySetColor(HELP_COLOR);
- }
- }
-
- /*****************************************************************************
- * Routine to search for a file and open it according to attribute at all *
- * directories defined by PATH environment variable and current dir. *
- *****************************************************************************/
- static FILE *GGFindFile(char *FileName, char *Attribute)
- {
- FILE *f;
- char *Path;
-
- Path = searchpath(FileName);
- if ((f = fopen(Path, Attribute)) != 0) return f;
-
- GGPutErrorMsg("No Help File Available");
- return (FILE *) NULL;
- }
-
- #endif NOHELP
-
- /*****************************************************************************
- * Routine to clear the Menu area, and set view port to it. *
- *****************************************************************************/
- void GGClearMenuArea(void)
- {
- #ifndef NOGRAPHICS
-
- #ifdef NOWINDOWS
- setviewport(ViewPortX = (int) (GGScreenMaxY * GlblAspectRatio),
- ViewPortY = 0,
- GGScreenMaxX, GGScreenMaxY, FALSE);
- clearviewport();
- #else
- WndwClearWindow(WndwMenuWindow);
- WndwAspectRatio = 1.0;
- #endif NOWINDOWS
-
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to clear the Axes area, and set view port to it. *
- *****************************************************************************/
- void GGClearViewArea(void)
- {
- #ifndef NOGRAPHICS
-
- #ifdef NOWINDOWS
- setviewport(ViewPortX = 0, ViewPortY = 0,
- (int) (GGScreenMaxY * GlblAspectRatio), GGScreenMaxY, FALSE);
- clearviewport();
- #else
- WndwClearWindow(WndwViewWindow);
- switch (GraphDriver) {
- case HERCMONO:
- case CGA:
- WndwAspectRatio = 1.0;
- break;
- case EGA:
- case EGA64:
- case EGAMONO:
- case VGA:
- WndwAspectRatio = 1.2;
- break;
- }
- #endif NOWINDOWS
-
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to clear all the screen. *
- *****************************************************************************/
- void GGClearAllScreen(void)
- {
- #ifndef NOGRAPHICS
- setviewport(ViewPortX = 0, ViewPortY = 0, getmaxx(), getmaxy(), FALSE);
- clearviewport();
- WndwAspectRatio = 1.0;
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to set the view port to the Menu area: *
- *****************************************************************************/
- void GGViewPortMenuArea(void)
- {
- #ifndef NOGRAPHICS
-
- #ifdef NOWINDOWS
- setviewport(ViewPortX = (int) (GGScreenMaxY * GlblAspectRatio),
- ViewPortY = 0,
- GGScreenMaxX, GGScreenMaxY, FALSE);
- #else
- WndwSetViewPort(WndwMenuWindow -> MinX,
- WndwMenuWindow -> MinY,
- WndwMenuWindow -> MaxX,
- WndwMenuWindow -> MaxY);
- WndwAspectRatio = 1.0;
- #endif NOWINDOWS
-
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to clear the Axes area, and set view port to it. *
- *****************************************************************************/
- void GGViewPortViewArea(void)
- {
- #ifndef NOGRAPHICS
-
- #ifdef NOWINDOWS
- setviewport(ViewPortX = 0, ViewPortY = 0,
- (int) (GGScreenMaxY * GlblAspectRatio), GGScreenMaxY, FALSE);
- #else
- WndwSetViewPort(WndwViewWindow -> MinX,
- WndwViewWindow -> MinY,
- WndwViewWindow -> MaxX,
- WndwViewWindow -> MaxY);
- WndwAspectRatio = GlblAspectRatio * GlblAspectRatio;
- #endif NOWINDOWS
-
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to clear all the screen. *
- *****************************************************************************/
- void GGViewPortAllScreen(void)
- {
- #ifndef NOGRAPHICS
- setviewport(ViewPortX = 0, ViewPortY = 0, getmaxx(), getmaxy(), FALSE);
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to print an error message on the message area : *
- *****************************************************************************/
- void GGPutErrorMsg(char *s)
- {
- #ifndef NOGRAPHICS
- int Quit = FALSE, X, Y, Buttons;
-
- GGMySetColor(RED);
- GGPutMsgXY(s, MSG_AREA_X, MSG_AREA_Y+0.1);
- GGPutMsgXY("Press Return:", MSG_AREA_X, MSG_AREA_Y);
-
- if (MouseExists) MouseFlushBuffer(); /* No need of old garbage! */
- do {
- if (kbhit()) {
- getch();
- Quit = TRUE;
- }
- if (MouseExists && MouseQueryBuffer()) {
- MouseGetBuffer(&X, &Y, &Buttons);
- Quit = (Buttons != 0);
- }
- }
- while (!Quit);
-
- GGMySetColor(BLACK); /* Erase that ... */
- GGPutMsgXY(s, MSG_AREA_X, MSG_AREA_Y + 0.1);
- GGPutMsgXY("Press Return:", MSG_AREA_X, MSG_AREA_Y);
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to print an message on the given location: *
- *****************************************************************************/
- void GGPutMsgXY(char *s, double x, double y)
- {
- #ifndef NOGRAPHICS
- GGMyMove(x, y);
- outtext(s);
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to read one line terminated by <Enter> and visualized on graphic *
- * screen. *
- * Full line editing is supported which includes: *
- * 1. Right and left arrow to move along the line. *
- * 2. Delete to delete current character. *
- * 3. Insert to toggle Insert/Overwrite mode. *
- * 4. Backspace to delete character before current one. *
- * 5. Home/End to move to beginning/End of string respectively. *
- * 6. Return to accept current line. *
- * 7. Esc to clear current line. *
- * If s is not empty it is used as starting string. *
- * Line is drawn starting from position x, y on screen (normalized -1..1). *
- *****************************************************************************/
- void GGGetGraphicLine(double x, double y, char s[], int color)
- {
- #ifndef NOGRAPHICS
- static int Insert = TRUE;
- int NextKey, Xstep, CursorPos = 0, FirstVisible = 0, Len = strlen(s),
- EndOfString = FALSE;
- char *Cursor;
- struct textsettingstype oldtext;
- struct viewporttype view;
-
- getviewsettings(&view);
- GGViewPortMenuArea();
-
- gettextsettings(&oldtext);
- settextstyle(DEFAULT_FONT, HORIZ_DIR, DefaultFontSize);
-
- Xstep = textwidth(" "); /* Get the width is pixels of current font */
-
- while (!EndOfString) {
- /* Set the first character in string to be displayed: */
- FirstVisible = CursorPos > 15 ? CursorPos - 10 : 0;
- GGMySetColor(color); /* Draw the string and the cursor: */
- GGPutMsgXY(&s[FirstVisible], x, y);
- Cursor = (Insert ? "_" : "-");
- GGMySetColor(ScreenCursorColor);
- GGMyMove(x, y);
- moverel((CursorPos - FirstVisible) * Xstep, 0);
- outtext(Cursor);
-
- NextKey = GGGetKey();
-
- GGMySetColor(BLACK); /* Erase the string and the cursor: */
- GGMyMove(x, y);
- moverel((CursorPos - FirstVisible) * Xstep, 0);
- outtext(Cursor);
- GGPutMsgXY(&s[FirstVisible], x, y);
-
- switch (NextKey) {
- case KEY_BSPACE:
- if (CursorPos == 0) {
- GGTone(1000, 100); /* Do some noise... */
- break;
- }
- movmem(&s[CursorPos], &s[CursorPos - 1], Len - CursorPos + 1);
- CursorPos--;
- Len--;
- break;
- case KEY_DELETE:
- if (CursorPos >= Len) {
- GGTone(1000, 100); /* Do some noise... */
- break;
- }
- movmem(&s[CursorPos + 1], &s[CursorPos], Len - CursorPos);
- Len--;
- break;
- case KEY_RIGHT:
- if (CursorPos >= Len) {
- GGTone(1000, 100); /* Do some noise... */
- break;
- }
- CursorPos++;
- break;
- case KEY_LEFT:
- if (CursorPos <= 0) {
- GGTone(1000, 100); /* Do some noise... */
- break;
- }
- CursorPos--;
- break;
- case KEY_RETURN:
- EndOfString = TRUE;
- break;
- case KEY_ESC:
- Len = 0; /* Clear everything */
- CursorPos = 0;
- s[0] = 0;
- break;
- case KEY_HOME:
- CursorPos = 0;
- break;
- case KEY_END:
- CursorPos = Len;
- break;
- case KEY_INSERT:
- Insert = !Insert;
- break;
- default: /* Regular ascii char */
- if (Insert) {
- movmem(&s[CursorPos], &s[CursorPos + 1],
- Len - CursorPos + 1);
- Len++;
- }
- else if (CursorPos == Len) Len++;/* We are on last character */
- s[CursorPos++] = NextKey;
- if (CursorPos == Len) s[CursorPos] = 0;
- break;
- }
- }
-
- settextstyle(oldtext.font, oldtext.direction, oldtext.charsize);
- setviewport(ViewPortX = view.left, ViewPortY = view.top,
- view.right, view.bottom, view.clip);
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Get a key from keyboard, and translating operational keys into special *
- * codes (>255). *
- *****************************************************************************/
- static int GGGetKey(void)
- {
- char c;
-
- while (TRUE) switch (c = getch()) {
- case 0: /* Extended code - get the next extended char */
- switch (getch()) {
- case 75: return KEY_LEFT;
- case 77: return KEY_RIGHT;
- case 71: return KEY_HOME;
- case 79: return KEY_END;
- case 83: return KEY_DELETE;
- case 82: return KEY_INSERT;
- }
- break;
- case 8:
- return KEY_BSPACE;
- case 10:
- case 13:
- return KEY_RETURN;
- case 27:
- return KEY_ESC;
- default:
- if isprint(c) return c;
- }
-
- return KEY_RETURN; /* Make warnings silent */
- }
-
- /*****************************************************************************
- * Routine to make some sound with given Frequency, Time milliseconds: *
- *****************************************************************************/
- void GGTone(int Frequency, int Time)
- {
- sound(Frequency);
- delay(Time);
- nosound();
- }
-
- #ifndef NOWINDOWS
-
- /*****************************************************************************
- * Routine to setup all the window to zero state, assuming graphic mode. *
- *****************************************************************************/
- static void WndwSetUpAllWndws(void)
- {
- #ifndef NOGRAPHICS
- GGClearAllScreen();
-
- WndwDrawAllWndwFrames(); /* Draw the windows frames */
-
- WndwViewWindow = &ViewWindow;
- WndwMenuWindow = &MenuWindow;
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to draw all the frames of all the windows defined in the system: *
- *****************************************************************************/
- static void WndwDrawAllWndwFrames(void)
- {
- #ifndef NOGRAPHICS
- WndwDrawWindowFrame(&MenuWindow);
- WndwDrawWindowFrame(&ViewWindow);
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to draw a frame for the window given: *
- *****************************************************************************/
- static void WndwDrawWindowFrame(WindowStruct *Window)
- {
- int i;
- double MinX = Window -> MinX, MaxX = Window -> MaxX,
- MinY = Window -> MinY, MaxY = Window -> MaxY,
- Dx = FRAME_X_WIDTH / 10.0, Dy = FRAME_Y_WIDTH / 10.0;
-
- #ifndef NOGRAPHICS
- GGMySetColor(Window -> FrameColor);
-
- for (i=0; i<10; i++) {
- GGMyMove(MinX, MinY);
- GGMyDraw(MinX, MaxY);
- GGMyDraw(MaxX, MaxY);
- GGMyDraw(MaxX, MinY);
- GGMyDraw(MinX, MinY);
-
- MinX -= Dx;
- MinY -= Dy;
- MaxX += Dx;
- MaxY += Dy;
- }
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to clear the given window interior: *
- *****************************************************************************/
- static void WndwClearWindow(WindowStruct *W)
- {
- #ifndef NOGRAPHICS
- WndwSetViewPort(W -> MinX, W -> MinY, W -> MaxX, W -> MaxY);
- clearviewport();
- #endif NOGRAPHICS
- }
-
- /*****************************************************************************
- * Routine to set up the view port. *
- *****************************************************************************/
- static void WndwSetViewPort(double XMin, double YMin, double XMax, double YMax)
- {
- #ifndef NOGRAPHICS
- setviewport(
- (ViewPortX = (int) ((XMin * GGScreenMaxY2 + GGScreenMaxY2) *
- GlblAspectRatio)),
- (ViewPortY = (int) (-YMax * GGScreenMaxY2 + GGScreenMaxY2)),
- (int) ((XMax * GGScreenMaxY2 + GGScreenMaxY2) * GlblAspectRatio),
- (int) (-YMin * GGScreenMaxY2 + GGScreenMaxY2),
- TRUE);
- #endif NOGRAPHICS
- }
-
- #endif NOWINDOWS