home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
irit
/
drawfuns.arc
/
GRAPHGEN.C
< prev
next >
Wrap
Text File
|
1989-09-10
|
40KB
|
1,239 lines
/*****************************************************************************
* 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