GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 11-May-2007, 09:50
promsan promsan is offline
Junior Member
 
Join Date: May 2007
Location: North of the rhubarb triangle, GB
Posts: 53
promsan is on a distinguished road
Unhappy

triangle (polygon), drawing, sizing, and rotation programme using linked lists...


Hello,

I'm almost completely useless at C, and as part of a project I've got to conjure up a programme, and I'm just hoping someone can give me push to get it started.

I want to make a programme where the user can draw a triangle (and eventually any polygon) and set the size, the centre point, and rotate the thing freely.
I have to use linked lists in the programme to let the user draw multiple shapes.

I almost understand how to do this, but not quite. I'll show you what I've got so far.
(as you may rapidly notice, I've only coded the first half, the rest is bits of example code that I don't quite understand how to use yet. I accidentally deleted what I had coded before - not that it was any good)

please be merciful!

I'm just asking for a bit of help to get started

Code:
CPP / C++ / C Code:
/*
 * Shapeshifter
 */

/*
 * Passing by reference
 */
typedef struct long_line_type //this is my structure "long_line_type" and contains the following bits of info:
{
    int start_x, start_y;
    int end_x, end_y;
    int colour;
} line_type; // this is a nickname for the structure "long_line_type"

/*
typedef struct {int x, y, z;} Point;    // exclude z for 2D
// a Triangle is given by three points: Point V0, V1, V2
*/

/*
typedef struct {
    int        a, b, c;                // Vertex indices
    char    col;                    // Colour
    float    cenZ;                    // Z centroid (used for sorting)
} Triangle;
*/

/*
 * Display a single line
 */
#include "stdio.h"
#include "graphics_lib.h"
#include "math.h"
#include "conio.h"

//First define "this_line" as a pointer.
void display_line(line_type *this_line) //"display_line" = "draw_line"
{
 /* Open a graphics window */
 initwindow(800, 600);

 /* Set the colour */
 setcolor(this_line->colour); //to set colour of line. the arrow dereferernces the *

 /* Draw the line */
 line(this_line->start_x,this_line->start_y,this_line->end_x,this_line->end_y); //to set a co-ord to draw line
}
//line is a pointer to a line type
void get_line(line_type *line_pointer)
{
 //accessing the members of the "structure" (a collection of differnet variables like it's 1.2,1.2,1.3 etc but with words
//"line" is the actual name of the varaible
 //user the (). notation when you haven't got a pointer variable; use the arrow notation when you have got a pointer variable
scanf("%d", &line_pointer->start_x);
scanf("%d", &line_pointer->start_y);
scanf("%d", &line_pointer->end_x);
scanf("%d", &line_pointer->end_y);
scanf("%d", &line_pointer->colour);
}
//can't return anything

//you have stored the address &line in the pointer called "line_pointer"; line_pointer contains all the address of the 5 scanf bits above.

//line_pointer is a "postcode" (pointer) that sends data to the "house" (structure) called "line"

//passing by reference

 

 

 /*
 * THE MAIN FUNCTION - the program starts executing here
 */


int main(void)
{
 
 /* DECLARE VARIABLES */
//	char key_press;
	int x_position;
	int y_position;
	int size;
//	int shape;
	int a;
	int b;
	int c;
	int d;
	int e;
	int f;
	
 //declare a variable of line_type
 line_type line; //I've now defined summat called "line" that is now a structure of the template called "line_type"
 //call the get_line function
 get_line(&line); //send the function called "get_line" the address of "line".

 //some printfs
 printf("The line goes from %d to %d, and from %d to %d; it's colour is code %d \n",line.start_x, line.start_y, line.end_x, line.end_y, line.colour);

 /*void function{}

 /* Get line information from the user */

 /* Display the lines */

    //calling the function: "line" is a local variable; "display_line" is the type of variable to be called
 display_line(&line);

 getch();

 /* Title Screen Function */
		/* Open a graphics window */
		/* Make it 800 pixels wide by 600 pixels high */
    initwindow(800, 600);

	printf("SHAPESHIFTER, a shape drawing programme");
	printf("Press space bar to continue");
	getch();

	/* Instruction Screen Function */
	printf("1. blah blah blah; 2. blah blah blah; 3. blah blah blah; 4. blah blah blah; 5. blah blah blah; 6. blah blah blah");
 	printf("Press space bar to continue");
	getch();

	/*initialise "size"
	size=0;


	/* Size Selection Function */
			printf("please la de dah... ");
			scanf("%d",&size);


	/* Easel Screen Function */

	/* Shape Selection Switch Function */

			//Getting centre point co-ordinates
			printf("please choose a value for the x and y co-ordinates:\n");
			scanf("%d %d", &x_position, &y_position);

	        a = x_position;
		    b = y_position+(size/2);
		    
			c = x_position-(size/2);
		    d = y_position-(size/2);
			
			e = x_position+(size/2);
		    f = y_position-(size/2);

			/*

  //Triangle: 
  line(a,b,c,d);
  line(c,d,e,f);
  line(e,f,a,b);

  */

			/* LINKED LIST EXAMPLE [url]http://www.c.happycodings.com/Data_Structures/code5.html[/url]
#include <stdlib.h>   <<---- this too
#include <string.h>   <<---- this too
	  
struct llist {
 char *str;
 struct llist *next;  //a pointer to the next element
};

int main(void) { <<----- watch it!!!
 char line[1024];
 struct llist *head = NULL;  //a pointer to the first element in the list
 struct llist *new = NULL;

 while(fgets(line, 1024, stdin) != NULL) {
  new = (struct llist *)malloc(sizeof(struct llist));
  new->next = head;
  head = new;

  new->str = strdup(line);
 }

 while(head != NULL) {
  printf("%s\n", head->str);
  head = head->next;
 }


  [url]http://www.cs.ccsu.edu/~markov/ccsu_courses/161Syllabus.html#CS161%20-%20C%20programming,%20Lecture%209[/url]

  2. Allocating storage for list elements

struct list *newelement() { //creates an instance of the list structure
   return (struct list *)malloc(sizeof(struct list));
}

3. Adding list elements

void push(int val) { /* add an element in the beginning of the list
  struct list *q;
  q=newelement();    /* create new element
  (*q).val=val;      /* assign the value member 
  (*q).next=p;       /* set the pointer to the next element
  p=q;               /* set the global list pointer 
}

void append(int val) { /* add an element at the end of the list 
  struct list *q, *t;
  q=newelement();
  (*q).val=val;   /* alternative notation: q->val=val 
  (*q).next=NULL;
  if (p==NULL)    /* the list is empty 
    p=q;
  else {          /* the list is not empty 
    t=p;
    while ((*t).next!=NULL)  /* move t at the and of the list 
      t=(*t).next;
    (*t).next=q;             /* connect the new element 
    }
}

4. Reading and printing lists

void main() {
  struct list *q;
  int x;
  p=NULL;   /* initialize the list - empty list 
  do {      /* read numbers and store them in a list 
    scanf("%d",&x);
    if (x>0) append(x); /* push(x) stores the list in reverse order 
  } while (x>0);  /* x<=0 end of input 
  q=p;
  while (q!=NULL) {  /* print the list 
    printf("%d\n",(*q).val);
    q=(*q).next;
  }
} 
			*/

/*
// p=point; np=new point ?

scanf("%d",&degree);
			sin_value = sin (degree*PI/180);
			cos_value = cos (degree*PI/180);


			np1.x=(((p1.x*cos_value)-(p1.y*sin_value)));
			np1.y=(((p1.y*cos_value)+(p1.x*sin_value)));
			np2.x=(((p2.x*cos_value)-(p2.y*sin_value)));
			np2.y=(((p2.y*cos_value)+(p2.x*sin_value)));
			np3.x=(((p3.x*cos_value)-(p3.y*sin_value)));
			np3.y=(((p3.y*cos_value)+(p3.x*sin_value)));
			told(p1,p2,p3,0);
			tnew(np1,np2,np3,3,1);
			copyvalue();

or

	new_x = cos(theta) * x - sin(theta) * y;
    new_y = sin(theta) * x + cos(theta) * y;

or

	x would equal (x * cos(Ang)) - (y * sin(Ang))
	y would equal (y * cos(Ang)) + (x * sin(Ang))

  */

 getch();

 closegraph();

 return 0;
}
  #2  
Old 12-May-2007, 09:56
Howard_L Howard_L is offline
Regular Member
 
Join Date: Apr 2007
Location: Maryland/PA, USA
Posts: 406
Howard_L has a spectacular aura aboutHoward_L has a spectacular aura about

Re: triangle (polygon), drawing, sizing, and rotation programme using linked lists...


I know nothing about graphics_lib.h , but shouldn't it and the others be more like <graphics_lib.h> ?
What OS and compiler are you using?
Are you getting this to compile??
What problems are you having? (start at the beginning, (no, not your childhood)

initwindow() looks like ncurses, conio is windows afaik
  #3  
Old 12-May-2007, 13:10
promsan promsan is offline
Junior Member
 
Join Date: May 2007
Location: North of the rhubarb triangle, GB
Posts: 53
promsan is on a distinguished road
Talking

Re: triangle (polygon), drawing, sizing, and rotation programme using linked lists...


Hi Howard, thanks for replying, I really appreciate it.

1. I'm using MS Visual C++ 6.0 on Windows XP and 2000
2. It's not compiling at the moment because of what look like path errors:
Quote:
--------------------Configuration: shapeshifter - Win32 Debug--------------------
Linking...
shapeshifter.obj : error LNK2001: unresolved external symbol _line
shapeshifter.obj : error LNK2001: unresolved external symbol _setcolor
shapeshifter.obj : error LNK2001: unresolved external symbol _initwindow
Debug/shapeshifter.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

shapeshifter.exe - 4 error(s), 0 warning(s)

As for what I'm trying to do, I have to make a vector graphics drawing programme that lets a user draw at least four kinds of shapes: a line, circle, triangle, and square, but ideally any polygons.
They have to be able to set the size, colour (and fill them in), orientation (rotate), and positioning, and the order they're drawn (the zed order).

I've got to use a linked list to store the date for the data for the elements of the shape... I think that means the x and y co-ords, or radius for the circle.

I thought this meant putting the elements in a structure and then putting the structures in linked lists, but I don't quite understand how it all works.
I think I've got to pre-compute data for the shapes and then display them by going through the linked list, but I really don't know what I'm talking about!

It has to run on a standard MS Dos window as well.

I'm only going to use the basic 16 colours - I planned (hoped!) to make all the selections like toggled switches, so for instance you'd press the left or right cursor to switch the name of the colour; pressing a key to select it.
The same sort of thing for sizes (limited to integers).

..sorry I've not got much to give at the mo'; I've only just started it the other day and had a few setbacks (plus I'm not completely with it yet)
  #4  
Old 12-May-2007, 23:46
Howard_L Howard_L is offline
Regular Member
 
Join Date: Apr 2007
Location: Maryland/PA, USA
Posts: 406
Howard_L has a spectacular aura aboutHoward_L has a spectacular aura about

Re: triangle (polygon), drawing, sizing, and rotation programme using linked lists...


Boy, this is a new twist. Interesting...
I have no graphics_lib.h with dmc. (my windows compiler)

But googling around I found a graphics_lib.h which was made from this:
FILE: winbgim.h
WINBGIM Version 3.4 -- Dec 21, 1999
modified to run under Borland C++ 5.02 for Windows OR under the mingw32 g++ compiler for Windows.

It includes:
#include <stddef.h>
#include <conio.h>
#include <windows.h>

Does that look like yours ???
-----
I tried the file you have above and got this:
First a WHOLE bunch of nested comment errors....

shapeshifter1.obj(shapeshifter1) Error 42: Symbol Undefined _closegraph
shapeshifter1.obj(shapeshifter1) Error 42: Symbol Undefined _initwindow
shapeshifter1.obj(shapeshifter1) Error 42: Symbol Undefined _line
shapeshifter1.obj(shapeshifter1) Error 42: Symbol Undefined _setcolor

(similar to yours, eh?)

OK, so, are these from your program? . . . or from graphics_lib.h?
So I reduced the program to this and compiled:
CPP / C++ / C Code:
#include "graphics_lib.h"

int main()
{
  printf("\n Hello from shapeshifter1x1.c \n");

  return 1;
}
... and got no errors and on running it the printf() printed.
so let's build from there...
Where did you get your graphics_lib.c ???
I should make sure I have the same as yours ... apples to apples
Can you compile and run this reduced code?
++Howard;
  #5  
Old 13-May-2007, 06:32
promsan promsan is offline
Junior Member
 
Join Date: May 2007
Location: North of the rhubarb triangle, GB
Posts: 53
promsan is on a distinguished road
Talking

Re: Triangle (polygon), drawing, sizing, and rotation programme using linked lists...


Hiya,

Here's Graphics_lib.h

CPP / C++ / C Code:
// FILE: winbgim.h
// WINBGIM Version 3.4 -- Dec 21, 1999
// modified to run under Borland C++ 5.02 for Windows OR under the
// mingw32 g++ compiler for Windows. There are also some additions
// for mouse control and RGB colors. Documentation on how to use these
// functions is available in [url]www.cs.colorado.edu/~main/bgi/docs/[/url]
//
// Modification log by Michael Main:
// --Version 2.1: Oct 17, 1998
//   Some mouse additions to Konstantin's original code
// --Version 2.2: November 1, 1998
//   Modified getch so that it can get the arrows and other keypad keys.
// --Version 2.3: November 17, 1998
//   Fixed a bug in getpixel.
// --Version 2.4: November 25, 1998
//   Added functions getactivepage() and getvisualpage() to get the current
//   page number of the active and visual pages. In this implementation, the
//   MAX_PAGES is set to 16, but I have used only pages 0 and 1 myself.
// --Version 3.1: June 17, 1999
//   Mostly implemented by Mark Richardson:
//   Implements getimage and putimage.
//   Adds new support for rgb colors.
// --Version 3.2: June 21, 1999
//   Made modifications so that everything works with the mingw32
//   G++ compiler for Windows. Details for installing and using this
//   free compiler are in [url]www.cs.colorado.edu/~main/mingw32/README.html[/url]
// --Version 3.3: Oct 4, 1999
//   Added ismouseclick and getmouseclick
// --Version 3.4: Dec 21, 1999
//   Added clearmouseclick.
//   Fixed bug causing getmouseclick to fail when x and y are same variable.
//   Fixed bug in setcolor that sometimes caused the fill color to change
//   to the drawing color.

#ifndef __GRAPHICS_H__
#define __GRAPHICS_H__
#define far
#define huge

#include <stddef.h>
#include <conio.h>
#include <windows.h>

// added by PJK

#ifndef __COLORS
#define __COLORS
enum colors {
    BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY,
    LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE
};
#endif


/** Some different definitions for the Mingw32 g++ compiler and
*   the Borland 5.0 compiler. Added by Michael Main, June 21, 1999.
*   Michael Main -- 10/17/98 */

#if defined(_WINDOWS_H) || defined(_GNU_H_WINDOWS_H)
/* MINGW32 G++ Compiler:
*  Define the colors type in the same way that Borland does.
*  Define CLR_INVALID from Borlands /win32/wingdi.h.
*  Get the memset prototype from string.h. Note that sometimes <string.h> is
*  actually <g++/String.h> for the Windows compiler because. In this case
*  _STRING_H_ will not be defined but we can still pick it up from <../string.h>.
*  Also define random for the bgidemo function.
*/
enum colors {
    BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY,
    LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE
};
#if !defined(CLR_INVALID)
#define CLR_INVALID 0xFFFFFFFF
#endif
#include <string.h>
#ifndef _STRING_H_
#include <../string.h>
#endif
#else
/* BORLAND Compiler:
* Colors are already defined in the BC5 conio.h, using COLORS.
* So for Borland I'll replace this enum with a #define definition.
*/
//#define colors COLORS
#endif
#ifndef random
#define random(range) (rand() % (range))
#endif

// A definition to fix a misspelling of MAGENTA throughout this file:
#define MAGENT MAGENTA

enum write_modes {
    COPY_PUT, XOR_PUT, OR_PUT, AND_PUT, NOT_PUT
};

enum line_styles {
    SOLID_LINE, DOTTED_LINE, CENTER_LINE, DASHED_LINE, USERBIT_LINE
};

enum fill_styles {
    EMPTY_FILL, SOLID_FILL, LINE_FILL, LTSLASH_FILL, SLASH_FILL, BKSLASH_FILL,
    LTBKSLASH_FILL, HATCH_FILL, XHATCH_FILL, INTERLEAVE_FILL, WIDE_DOT_FILL,
    CLOSE_DOT_FILL, USER_FILL
};

enum text_directions {
    HORIZ_DIR, VERT_DIR
};

enum font_types {
    DEFAULT_FONT, TRIPLEX_FONT, SMALL_FONT, SANSSERIF_FONT, GOTHIC_FONT
};

#define LEFT_TEXT             0
#define CENTER_TEXT           1
#define RIGHT_TEXT            2
#define BOTTOM_TEXT           0
#define TOP_TEXT              2
#define NORM_WIDTH            1
#define THICK_WIDTH           3
#define DOTTEDLINE_LENGTH     2
#define CENTRELINE_LENGTH     4
#define USER_CHAR_SIZE        0
#define MAXCOLORS             15
#define CLIP_ON               1
#define CLIP_OFF              0
#define TOP_ON                1
#define TOP_OFF               0

// Definitions for the key pad extended keys are added here. I have also
// modified getch() so that when one of these keys are pressed, getch will
// return a zero followed by one of these values. This is the same way
// that it works in conio for dos applications.
// M. Main -- Nov 3, 1998
#define KEY_HOME       71
#define KEY_UP         72
#define KEY_PGUP       73
#define KEY_LEFT       75
#define KEY_CENTER     76
#define KEY_RIGHT      77
#define KEY_END        79
#define KEY_DOWN       80
#define KEY_PGDN       81
#define KEY_INSERT     82
#define KEY_DELETE     83
#define KEY_F1			  59
#define KEY_F2         60
#define KEY_F3         61
#define KEY_F4			  62
#define KEY_F5			  63
#define KEY_F6			  64
#define KEY_F7			  65
#define KEY_F8			  66
#define KEY_F9			  67

enum graphics_errors {
   grOk = 0,
   grNoInitGraph = -1,
   grNotDetected = -2,
   grFileNotFound = -3,
   grInvalidDriver   = -4,
   grNoLoadMem = -5,
   grNoScanMem = -6,
   grNoFloodMem = -7,
   grFontNotFound = -8,
   grNoFontMem = -9,
   grInvalidMode =   -10,
   grError = -11,
   grIOerror = -12,
   grInvalidFont = -13,
   grInvalidFontNum = -14,
   grInvalidDeviceNum = -15,
   grInvalidVersion = -18
};

/* Graphics drivers constants, includes X11 which is particular to XBGI. */
#define DETECT                0
#define CGA                1
#define MCGA                  2
#define EGA                3
#define EGA64                 4
#define EGAMONO                  5
#define IBM8514                  6
#define HERCMONO              7
#define ATT400                8
#define VGA                9
#define PC3270                10

/* Graphics modes constants. */
#define CGAC0                 0
#define CGAC1                 1
#define CGAC2                 2
#define CGAC3                 3
#define CGAHI                 4
#define MCGAC0                0
#define MCGAC1                1
#define MCGAC2                2
#define MCGAC3                3
#define MCGAMED                  4
#define MCGAHI                5
#define EGALO                 0
#define EGAHI                 1
#define EGA64LO                  0
#define EGA64HI                  1
#define EGAMONOHI             3
#define HERCMONOHI               0
#define ATT400C0              0
#define ATT400C1              1
#define ATT400C2              2
#define ATT400C3              3
#define ATT400MED             4
#define ATT400HI              5
#define VGALO                 0
#define VGAMED                1
#define VGAHI                 2
#define VGAMAX                                          3
#define PC3270HI              0
#define IBM8514LO             0
#define IBM8514HI             1

typedef struct arccoordstype {
    int x;
    int y;
    int xstart;
    int ystart;
    int xend;
    int yend;
} arccoordstype;

typedef char fillpatterntype[8];
typedef struct fillsettingstype {
    int pattern;
    int color;
} fillsettingstype;

typedef struct linesettingstype {
    int linestyle;
    unsigned int upattern;
    int thickness;
} linesettingstype;

typedef struct palettetype {
    unsigned char size;
    signed char colors[16];
} palettetype;

typedef struct textsettingstype {
    int font;
    int direction;
    int charsize;
    int horiz;
    int vert;
} textsettingstype;

typedef struct viewporttype {
    int left;
    int top;
    int right;
    int bottom;
    int clip;
} viewporttype;
 // This struct was moved here to allow access to the struct (Mark Richardson 11/29/98)
struct BGIimage {
	short width;		// 2 bytes
   short height;		// 2 bytes  Note:This means bits is also aligned to 32bit(DWORD) boundry
	char  bits[1];
};

#ifndef NOT_USE_PROTOTYPES
#define PROTO(ARGS) ARGS
#else
#define PROTO(ARGS) ()
#endif
#if defined(__cplusplus)
extern "C" {
#endif
//
// Setting this variable to 0 increase speed of drawing but
// correct redraw is not possible. By default this variable is initialized by 1
//

extern int bgiemu_handle_redraw;
//
// Default mode choosed by WinBGI if DETECT value is specified for
// device parameter of initgraoh(). Default value is VGAMAX which
// cause creation of maximized window (resolution depends on display mode)
//

extern int bgiemu_default_mode;
void _graphfreemem PROTO((void *ptr, unsigned int size));
void* _graphgetmem PROTO((unsigned int size));
void arc PROTO((int, int, int, int, int));
void bar PROTO((int, int, int, int));
void bar3d PROTO((int, int, int, int, int, int));
void circle PROTO((int, int, int));
void cleardevice PROTO((void));
void clearviewport PROTO((void));
void closegraph PROTO((void));
void detectgraph PROTO((int *, int *));
void drawpoly PROTO((int, int *));
void ellipse PROTO((int, int, int, int, int, int));
void fillellipse PROTO((int, int, int, int));
void fillpoly PROTO((int, int *));
void floodfill PROTO((int, int, int));
void getarccoords PROTO((arccoordstype *));
void getaspectratio PROTO((int *, int *));
int getbkcolor PROTO((void));
int getcolor PROTO((void));
palettetype* getdefaultpalette PROTO((void));
char* getdrivername PROTO((void));
void getfillpattern PROTO((char const *));
void getfillsettings PROTO((fillsettingstype *));
int getgraphmode PROTO((void));
void getimage PROTO((int, int, int, int, void *));
void getlinesettings PROTO((linesettingstype *));
int getmaxcolor PROTO((void));
int getmaxmode PROTO((void));
int getmaxx PROTO((void));
int getmaxy PROTO((void));
char* getmodename PROTO((int));
void getmoderange PROTO((int, int *, int *));
void getpalette PROTO((palettetype *));
int getpalettesize PROTO((void));
unsigned int getpixel PROTO((int, int));
void gettextsettings PROTO((textsettingstype *));
void getviewsettings PROTO((viewporttype *));
int getx PROTO((void));
int gety PROTO((void));
void graphdefaults PROTO((void));
char* grapherrormsg PROTO((int));
int graphresult PROTO((void));
unsigned int imagesize PROTO((int, int, int, int));
void initgraph PROTO((int *, int *, char const *));
int installuserdriver PROTO((char const *, int *));
int installuserfont PROTO((char const *));
void line PROTO((int, int, int, int));
void linerel PROTO((int, int));
void lineto PROTO((int, int));
void moverel PROTO((int, int));
void moveto PROTO((int, int));
void outtext PROTO((char const *));
void outtextxy PROTO((int, int, char const *));
void pieslice PROTO((int, int, int, int, int));
void putimage PROTO((int, int, void *, int));
void putpixel PROTO((int, int, int));
void rectangle PROTO((int, int, int, int));
int registerbgidriver PROTO((void *));
int registerbgifont PROTO((void *));
void restorecrtmode PROTO((void));
void sector PROTO((int, int, int, int, int, int));
void setactivepage PROTO((int));
void setallpalette PROTO((palettetype *));
void setaspectratio PROTO((int, int));
void setbkcolor PROTO((int));
void setcolor PROTO((int));
void setfillpattern PROTO((char const *, int));
void setfillstyle PROTO((int, int));
unsigned int setgraphbufsize PROTO((unsigned int));
void setgraphmode PROTO((int));
void setlinestyle PROTO((int, unsigned int, int));
void setpalette PROTO((int, int));
void setrgbpalette PROTO((int, int, int, int));
void settextjustify PROTO((int, int));
void settextstyle PROTO((int, int, int));
void setusercharsize PROTO((int, int, int, int));
void setviewport PROTO((int, int, int, int, int));
void setvisualpage PROTO((int));
void setwritemode PROTO((int));
int textheight PROTO((char const *));
int textwidth PROTO((char const *));
//int getch PROTO((void));
int kbhit PROTO((void));
void delay PROTO((unsigned msec));
void restorecrtmode PROTO((void));

/* Additional functions for backwards compatibility */
void graphics_on PROTO((void));
void graphics_off PROTO((void));

/* Prototypes for mouse handling functions. The mousex( ) and mousey( )
*  functions return the most recent x and y coordinates detected from the
*  mouse. For the other functions, the kind parameter should be one of these:
*   WM_MOUSEMOVE       -- mouse movement
*   WM_LBUTTONDBLCLK   -- left mouse button double-click
*   WM_LBUTTONDOWN     -- left mouse button pushed down
*   WM_LBUTTONUP       -- left mouse button released up
*   WM_MBUTTONDBLCLK   -- middle mouse button double-click (might not work!)
*   WM_MBUTTONDOWN     -- middle mouse button pushed down (might not work!)
*   WM_MBUTTONUP       -- middle mouse button released up (might not work!)
*   WM_RBUTTONDBLCLK   -- right mouse button double-click
*   WM_RBUTTONDOWN     -- right mouse button pushed down
*   WM_RBUTTONUP       -- right mouse button released up
* The parameter h must be a void function with two integer parameters.
* This function will be called whenever the corresponding event occurs.
* The two integer parameters will be the x- and y-coordinates where the
* event happened.
*
* NOTE: The middle button events aren't being caught on my Windows 95 system.
* I don't know why.
* Added by Michael Main -- 11/3/98 and 10/4/99 and 12/21/99.
*/
int mousex PROTO(( ));
int mousey PROTO(( ));
void registermousehandler PROTO((UINT kind, void h(int, int)));
//bool ismouseclick PROTO((UINT kind));
//void getmouseclick PROTO((UINT kind, int& x, int& y));
void clearmouseclick PROTO((UINT kind));

/* Prototypes for other new functions, not in the original BGI graphics.
*  There is also a new initwindow function that can be called instead of
*  initgraph. The arguments are an explicit width and height.
*  As of 11/3, the width is now the first parameter.
*  The getactivepage() and getvisualpage() functions get the number of the
*  current active or visual page.
*/
void initwindow PROTO((int, int));
int getactivepage PROTO(( ));
int getvisualpage PROTO(( ));

/* Colors can be original bgi colors (ints in the range 0...MAXCOLORS) or
*  RGB colors constructed from red, green and blue components between
*  0 and 255.
*    IS_BGI_COLOR(v): true if v is one of the original BGI colors
*    IS_RGB_COLOR(v): true if v is one of the new RGB colors
*    RED_VALUE(v) is the red value of an RGB color v
*    GREEN_VALUE(v) is the red value of an RGB color v
*    BLUE_VALUE(v) is the red value of an RGB color v
*    COLOR(r,g,b): is the rgb color formed from a red, green and blue
*                  value (all in the range 0...255).
*/

#define IS_BGI_COLOR(c) (((c) >= 0) && ((c) <= MAXCOLORS))
#define IS_RGB_COLOR(c) ((c) & 0x04000000)
#define RED_VALUE(v)   ((v) & 0xFF)
#define GREEN_VALUE(v) (((v) >> 8) & 0xFF)
#define BLUE_VALUE(v)  (((v) >> 16)& 0xFF)
#define COLOR(r,g,b)   (0x04000000 | RGB(r,g,b))
#if defined(__cplusplus)
};
#endif

#endif


This should get rid of the errors...

###
{@ @}
\U/
Last edited by admin : 13-May-2007 at 10:15. Reason: Please insert your C/C++ code between [cpp] & [/cpp] tags
  #6  
Old 13-May-2007, 09:10
promsan promsan is offline
Junior Member
 
Join Date: May 2007
Location: North of the rhubarb triangle, GB
Posts: 53
promsan is on a distinguished road

Re: triangle (polygon), drawing, sizing, and rotation programme using linked lists...


Now then,

I compiled the reduced code you wrote, and it compiles perfectly.
(well, one warning, but it runs fine)

Code:
--------------------Configuration: shapeshifter - Win32 Debug-------------------- Compiling... shapeshifter.c C:\Documents and Settings\...(rest of path deleted for obvious reasons)...\shapeshifter\shapeshifter\shapeshifter.c(5) : warning C4013: 'printf' undefined; assuming extern returning int shapeshifter.obj - 0 error(s), 1 warning(s)

I'm not sure what you mean by "graphics_lib.c", is the code I quoted what you mean?
  #7  
Old 13-May-2007, 10:27
Howard_L Howard_L is offline
Regular Member
 
Join Date: Apr 2007
Location: Maryland/PA, USA
Posts: 406
Howard_L has a spectacular aura aboutHoward_L has a spectacular aura about

Re: triangle (polygon), drawing, sizing, and rotation programme using linked lists...


Quote:
I'm not sure what you mean by "graphics_lib.c", is the code I quoted what you mean?
Yes, #include "graphics_lib.h" is what your program calls for.
It looks like it matches what I found. I found more on it here:
'http://www.cs.colorado.edu/~main/cs1300/doc/bgi/bgi.html'

If your getting print() prototype warning, I guess add:
#include <stdio.h>

Now, the idea would be to build your program up from here one step at a time, compile, run , address problem , repeat...

I started at your main(),
- added the variable list - ok
- added line_type line; - needed 'typedef struct long_line_type'
- added 'typedef struct long_line_type' -ok
- added initwindow(800, 600); - problem!

I see initwindow() defined in graphics_lib.h , but don't know why it is not working. That's where I am with it , , thinking about ?why not? .

Where did you get the idea to write this using graphics_lib.h ?
It would be interesting to get it working, but this is tough for me.
  #8  
Old 13-May-2007, 13:10
promsan promsan is offline
Junior Member
 
Join Date: May 2007
Location: North of the rhubarb triangle, GB
Posts: 53
promsan is on a distinguished road
Question

Re: triangle (polygon), drawing, sizing, and rotation programme using linked lists...


Hiya,

I've never had a problem with the initwindow() thing ... but then I didn't set it up myself before so...

I think you might need another file called graphics_lib.cpp

(this is for compilers that are not MS visual c++ 6.0)

Code:
// FILE: winbgim.cpp // Version 3.4, December 21, 1999 // This is Konstantin Knizhnik's implementation of Borland's BGI graphics // to run under Borland C++ 5.02 for Windows, with some mouse additions // and modifications by Michael Main. // // For documentation and modification history please see: // http://www.cs.colorado.edu/~main/bgi/README.html // http://www.cs.colorado.edu/~main/bgi/winbgim.h #include <windows.h> #include <stddef.h> #include <stdio.h> #include <iostream> // put in by MR for error messages 11/30/98 #include <math.h> #include "graphics_lib.h" #ifndef random #define random(range) (rand() % (range)) #endif //If using MS Visual Studio need to comment using namespace std; // Added for MS Visual Studio Compile //using namespace std; // Version 3.2: // Macro to convert one of my RGB colors to a standard RGB color. // In my RGB colors, the first byte is 0x10 so that it can be // easily distinguished from the earlier BGI colors. #define RGB_COLOR(c) (c & 0xFFFFFF) #define MAX_PAGES 4 static HDC hdc[4]; static HPEN hPen; static HRGN hRgn; static HFONT hFont; static NPLOGPALETTE pPalette; static PAINTSTRUCT ps; static HWND hWnd = NULL; // Initialise to null (PDM) static HBRUSH hBrush[USER_FILL+1]; static HBRUSH hBackgroundBrush; static HPALETTE hPalette; static HBITMAP hBitmap[MAX_PAGES]; static HBITMAP hPutimageBitmap; static BITMAPINFO hBitMapInfo={{sizeof(BITMAPINFOHEADER),1,1,1,32,BI_RGB,4}}; // first parameter is bitmapinfoheader size // second parameter is bitmap image width // third parameter is bitmap image height // fourth is planes of image // fifth is compression (BI_RGB is no compression) // sixth is image size (number of pixels * 4 bytes per pixel) static int timeout_expired; #define PEN_CACHE_SIZE 8 #define FONT_CACHE_SIZE 8 #define BG 16 #define TIMER_ID 1 // Constants added for the key numbers of the key pad extended keys. // These key numbers appear in the wParam parameter to the window event // handler with a WM_KEYDOWN event: // M. Main -- Nov 3, 1998 #define NUMBER_HOME 36 #define NUMBER_UP 38 #define NUMBER_PGUP 33 #define NUMBER_LEFT 37 #define NUMBER_CENTER 12 #define NUMBER_RIGHT 39 #define NUMBER_END 35 #define NUMBER_DOWN 40 #define NUMBER_PGDN 34 #define NUMBER_INSERT 45 #define NUMBER_DELETE 46 #define FUNCTION_F1 112 #define FUNCTION_F2 113 #define FUNCTION_F3 114 #define FUNCTION_F4 115 #define FUNCTION_F5 116 #define FUNCTION_F6 117 #define FUNCTION_F7 118 #define FUNCTION_F8 119 #define FUNCTION_F9 120 #define FUNCTION_F10 121 #define FUNCTION_F11 122 #define FUNCTION_F12 123 // Static variables added for the mouseclick functions: #define NO_CLICK -1 static int x_clicks[WM_MOUSELAST - WM_MOUSEFIRST + 1]; static int y_clicks[WM_MOUSELAST - WM_MOUSEFIRST + 1]; static bool click_ready[WM_MOUSELAST - WM_MOUSEFIRST + 1]; // Original Note: // When XOR or NOT write modes are used for drawing high BG bit is cleared, so // drawing colors should be adjusted to preserve this bit. // Notes from MGM: // I think understand what this note says. For example, suppse that we are // drawing with BGI color number 1, which is actually at BG+1 = 17. // The bit-pattern for this color is 00010001. Suppose that this is // XORed with a color that is already on the screen. That color might // be BGI color number 2, which is actually at BG+2 = 18 and has a // bit pattern of 00010010. In both cases, the leading four bits 0001 // are an artifact of the offset of the index numbers in the palette. // After the XOR we want this bit to remain on, resulting in // 00010011. But..., I don't think that the XOR mode is implemented // correctly. The implementation checks whether we have one of these // ADJUSTED MODES, and if so, it uses the original BGI color number // instead of BG+... So, I'm going to take out that programming. #define ADJUSTED_MODE(mode) ((mode) == XOR_PUT || (mode) == NOT_PUT) int bgiemu_handle_redraw = TRUE; int bgiemu_default_mode = VGAHI; //VGAMAX; static int screen_width; static int screen_height; static int window_width; static int window_height; static int line_style_cnv[] = { PS_SOLID, PS_DOT, PS_DASHDOT, PS_DASH, PS_DASHDOTDOT /* if user style lines are not supported */ }; static int write_mode_cnv[] = {R2_COPYPEN, R2_XORPEN, R2_MERGEPEN, R2_MASKPEN, R2_NOTCOPYPEN}; static int bitblt_mode_cnv[] = {SRCCOPY, SRCINVERT, SRCPAINT, SRCAND, NOTSRCCOPY}; static int font_weight[] = { FW_BOLD, // DefaultFont FW_NORMAL, // TriplexFont FW_NORMAL, // SmallFont FW_NORMAL, // SansSerifFont FW_NORMAL, // GothicFont FW_NORMAL, // ScriptFont FW_NORMAL, // SimplexFont FW_NORMAL, // TriplexScriptFont FW_NORMAL, // ComplexFont FW_NORMAL, // EuropeanFont FW_BOLD // BoldFont }; static int font_family[] = { FIXED_PITCH|FF_DONTCARE, // DefaultFont VARIABLE_PITCH|FF_ROMAN, // TriplexFont VARIABLE_PITCH|FF_MODERN, // SmallFont VARIABLE_PITCH|FF_DONTCARE, // SansSerifFont VARIABLE_PITCH|FF_SWISS, // GothicFont VARIABLE_PITCH|FF_SCRIPT, // ScriptFont VARIABLE_PITCH|FF_DONTCARE, // SimplexFont VARIABLE_PITCH|FF_SCRIPT, // TriplexScriptFont VARIABLE_PITCH|FF_DONTCARE, // ComplexFont VARIABLE_PITCH|FF_DONTCARE, // EuropeanFont VARIABLE_PITCH|FF_DONTCARE // BoldFont }; static char* font_name[] = { "Console", // DefaultFont "Times New Roman", // TriplexFont "Small Fonts", // SmallFont "MS Sans Serif", // SansSerifFont "Arial", // GothicFont "Script", // ScriptFont "Times New Roman", // SimplexFont "Script", // TriplexScriptFont "Courier New", // ComplexFont "Times New Roman", // EuropeanFont "Courier New Bold", // BoldFont }; static int text_halign_cnv[] = {TA_LEFT, TA_CENTER, TA_RIGHT}; static int text_valign_cnv[] = {TA_BOTTOM, TA_BASELINE, TA_TOP}; static palettetype current_palette; static struct { int width; int height; } font_metrics[][11] = { {{0,0},{8,8},{16,16},{24,24},{32,32},{40,40},{48,48},{56,56},{64,64},{72,72},{80,80}}, // DefaultFont {{0,0},{13,18},{14,20},{16,23},{22,31},{29,41},{36,51},{44,62},{55,77},{66,93},{88,124}}, // TriplexFont {{0,0},{3,5},{4,6},{4,6},{6,9},{8,12},{10,15},{12,18},{15,22},{18,27},{24,36}}, // SmallFont {{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // SansSerifFont {{0,0},{13,19},{14,21},{16,24},{22,32},{29,42},{36,53},{44,64},{55,80},{66,96},{88,128}}, // GothicFont // I am not sure about metrics of following fonts {{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // ScriptFont {{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // SimplexFont {{0,0},{13,18},{14,20},{16,23},{22,31},{29,41},{36,51},{44,62},{55,77},{66,93},{88,124}}, // TriplexScriptFont {{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // ComplexFont {{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // EuropeanFont {{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}} // BoldFont }; //struct BGIbitmapinfo { // BITMAPINFOHEADER hdr; // short color_table[16]; //}; //static BGIbitmapinfo bminfo = { // {sizeof(BITMAPINFOHEADER), 0, 0, 1, 4, BI_RGB} //}; // The following image_bits isn't used anywhere, but I am reluctant to // remove it because perhaps the original programmer counts on this // pointer being in memory after bminfo. Therefore, to get rid of the // compiler warning, I will later put some reference to image_bits; // M. Main -- Nov 4, 1998. static int* image_bits = 0; // Version 3.2: // The next three int variables may now be a BGI color (0...MAXCOLORS) or // an RGI color. Note that the windows_color has dual purpose: it is both // the color in which Windows will print text and it is the color // which Windows functions (such as Ellipse) use as the fill color. // This is because the windows SetTextColor uses its color for filling // and for text. However, we want our text to print in the drawing // color (stored in color), and we want things to be filled in // the fill color (stored in fill_settings.color), so when we output text // or draw a filled shape, we check to see if we need to call SetTextColor. static int windows_color; // Color that Windows plans to use for text & filling. static int color; // BGI's color for drawing lines and text. static int bkcolor; // Background color static fillsettingstype fill_settings; static linesettingstype line_settings; static int normal_font_size[] = { 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; static int aspect_ratio_x, aspect_ratio_y; static textsettingstype text_settings; static viewporttype view_settings; static int font_mul_x, font_div_x, font_mul_y, font_div_y; static enum { ALIGN_NOT_SET, UPDATE_CP, NOT_UPDATE_CP } text_align_mode; //Mouse handler static variables added by Michael Main, Oct 16, 1998. static int current_mouse_x = 0; static int current_mouse_y = 0; typedef void (*Handler)(int,int); static Handler mouse_handlers[WM_MOUSELAST - WM_MOUSEFIRST + 1] = { 0 }; #define BORDER_WIDTH 8 #define BORDER_HEIGHT 27 static int write_mode; static int visual_page; static int active_page; static arccoordstype ac; class char_queue { protected: char* buf; int put_pos; int get_pos; int buf_size; public: void put(char ch) { buf[put_pos] = ch; if (++put_pos == buf_size) put_pos = 0; if (put_pos == get_pos) // queue is full (void)get(); // loose one character } char get() { char ch = buf[get_pos]; if (++get_pos == buf_size) get_pos = 0; return ch; } bool is_empty() { return get_pos == put_pos; } char_queue(int buf_size = 256) { put_pos = get_pos = 0; this->buf_size = buf_size; buf = new char[buf_size]; } ~char_queue() { delete[] buf; } }; static char_queue kbd_queue; int convert_userbits(DWORD buf[32], unsigned pattern) { int i = 0, j; pattern &= 0xFFFF; while (true) { for (j = 0; pattern & 1; j++) pattern >>= 1; buf[i++] = j; if (pattern == 0) { buf[i++] = 16 - j; return i; } for (j = 0; !(pattern & 1); j++) pattern >>= 1; buf[i++] = j; } } class l2elem { public: l2elem* next; l2elem* prev; void link_after(l2elem* after) { (next = after->next)->prev = this; (prev = after)->next = this; } void unlink() { prev->next = next; next->prev = prev; } void prune() { next = prev = this; } }; class l2list : public l2elem { public: l2list() { prune(); } }; class pen_cache : public l2list { class pen_cache_item : public l2elem { public: HPEN pen; int color; int width; int style; unsigned pattern; }; pen_cache_item* free; pen_cache_item cache[PEN_CACHE_SIZE]; public: pen_cache(); void select(int color); }; // Moved the two pen_cache methods outside of the class definition to avoid // warnings about inline functions. M. Main -- Nov 3, 1998 pen_cache::pen_cache() { // Creates a linked list of pen_cache_items, all of which are // currently not used. for (int i = 0; i < PEN_CACHE_SIZE-1; i++) cache[i].next = &cache[i+1]; cache[PEN_CACHE_SIZE-1].next = NULL; free = cache; } void pen_cache::select(int color) { // Version 3.2: // The original version required color to be an index into the // palette, that has already been adjusted by adding BG. // I have changed this so that the color can now be an original // BGI color (in the range 0..MAXCOLORS) or one of the new RGB colors. for (l2elem* elem = next; elem != this; elem = elem->next) { pen_cache_item* ci = (pen_cache_item*)elem; if (ci->color == color && ci->style == line_settings.linestyle && ci->width == line_settings.thickness && (line_settings.linestyle != USERBIT_LINE || line_settings.upattern == ci->pattern)) { ci->unlink(); // LRU discipline ci->link_after(this); if (hPen != ci->pen) { hPen = ci->pen; SelectObject(hdc[0], hPen); SelectObject(hdc[1], hPen); } return; } } hPen = NULL; if (line_settings.linestyle == USERBIT_LINE) { LOGBRUSH lb; lb.lbColor = (IS_RGB_COLOR(color)) ? RGB_COLOR(color) : PALETTEINDEX(BG+color); lb.lbStyle = BS_SOLID; DWORD style[32]; hPen = ExtCreatePen(PS_GEOMETRIC|PS_USERSTYLE, line_settings.thickness, &lb, convert_userbits(style,line_settings.upattern), style); } if (hPen == NULL) { hPen = CreatePen(line_style_cnv[line_settings.linestyle], line_settings.thickness, IS_RGB_COLOR(color) ? RGB_COLOR(color) : PALETTEINDEX(BG+color)); } SelectObject(hdc[0], hPen); SelectObject(hdc[1], hPen); pen_cache_item* p; if (free == NULL) { p = (pen_cache_item*)prev; p->unlink(); DeleteObject(p->pen); } else { p = free; free = (pen_cache_item*)p->next; } p->pen = hPen; p->color = color; p->width = line_settings.thickness; p->style = line_settings.linestyle; p->pattern = line_settings.upattern; p->link_after(this); } static pen_cache pcache; // Moved the two font_cache methods outside of the class definition to avoid // warnings about inline functions. M. Main -- Nov 3, 1998 class font_cache : public l2list { class font_cache_item : public l2elem { public: HFONT font; int type; int direction; int width, height; }; font_cache_item* free; font_cache_item cache[FONT_CACHE_SIZE]; public: font_cache( ); void select(int type, int direction, int width, int height); }; font_cache::font_cache() { for (int i = 0; i < FONT_CACHE_SIZE-1; i++) cache[i].next = &cache[i+1]; cache[FONT_CACHE_SIZE-1].next = NULL; free = cache; } void font_cache::select(int type, int direction, int width, int height) { for (l2elem* elem = next; elem != this; elem = elem->next) { font_cache_item* ci = (font_cache_item*)elem; if (ci->type == type && ci->direction == direction && ci->width == width && ci->height == height) { ci->unlink(); ci->link_after(this); if (hFont != ci->font) { hFont = ci->font; SelectObject(hdc[0], hFont); SelectObject(hdc[1], hFont); } return; } } hFont = CreateFont(-height,width,direction*900,(direction&1)*900, font_weight[type],FALSE,FALSE,FALSE,DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, font_family[type],font_name[type]); SelectObject(hdc[0], hFont); SelectObject(hdc[1], hFont); font_cache_item* p; if (free == NULL) { p = (font_cache_item*)prev; p->unlink(); DeleteObject(p->font); } else { p = free; free = (font_cache_item*)p->next; } p->font = hFont; p->type = type; p->width = width; p->height = height; p->direction = direction; p->link_after(this); } static font_cache fcache; // Version 3.2: I've changed the FLAGS to PC_RESERVED, as specified in // http://msdn.microsoft.com/library/techart/msdn_palette.htm. // Elsewhere in the code, I've also changed // #define FLAGS PC_NOCOLLAPSE #define FLAGS PC_RESERVED #define PALETTE_SIZE 256 static PALETTEENTRY BGIcolor[16] = { { 0, 0, 0, FLAGS }, { 0, 0, 255, FLAGS }, { 0, 255, 0, FLAGS }, { 0, 255, 255, FLAGS }, { 255, 0, 0, FLAGS }, { 255, 0, 255, FLAGS }, { 165, 42, 42, FLAGS }, { 211, 211, 211, FLAGS }, { 47, 79, 79, FLAGS }, { 173, 216, 230, FLAGS }, { 32, 178, 170, FLAGS }, { 224, 255, 255, FLAGS }, { 240, 128, 128, FLAGS }, { 219, 112, 147, FLAGS }, { 255, 255, 0, FLAGS }, { 255, 255, 255, FLAGS } }; static PALETTEENTRY BGIpalette[16]; static short SolidBrushBitmap[8] = {~0xFF, ~0xFF, ~0xFF, ~0xFF, ~0xFF, ~0xFF, ~0xFF, ~0xFF}; static short LineBrushBitmap[8] = {~0x00, ~0x00, ~0x00, ~0x00, ~0x00, ~0x00, ~0x00, ~0xFF}; static short LtslashBrushBitmap[8] = {~0x01, ~0x02, ~0x04, ~0x08, ~0x10, ~0x20, ~0x40, ~0x80}; static short SlashBrushBitmap[8] = {~0x81, ~0x03, ~0x06, ~0x0C, ~0x18, ~0x30, ~0x60, ~0xC0}; static short BkslashBrushBitmap[8] = {~0xC0, ~0x60, ~0x30, ~0x18, ~0x0C, ~0x06, ~0x03, ~0x81}; static short LtbkslashBrushBitmap[8] = {~0x80, ~0x40, ~0x20, ~0x10, ~0x08, ~0x04, ~0x02, ~0x01}; static short HatchBrushBitmap[8] = {~0x01, ~0x01, ~0x01, ~0x01, ~0x01, ~0x01, ~0x01, ~0xFF}; static short XhatchBrushBitmap[8] = {~0x81, ~0x42, ~0x24, ~0x18, ~0x18, ~0x24, ~0x42, ~0x81}; static short InterleaveBrushBitmap[8] = {~0x55, ~0xAA, ~0x55, ~0xAA, ~0x55, ~0xAA, ~0x55, ~0xAA}; static short WidedotBrushBitmap[8] = {~0x00, ~0x00, ~0x00, ~0x00, ~0x00, ~0x00, ~0x00, ~0x01}; static short ClosedotBrushBitmap[8] = {~0x44, ~0x00, ~0x11, ~0x00, ~0x44, ~0x00, ~0x11, ~0x00}; char* grapherrormsg(int code) { static char buf[256]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL, code, 0, buf, sizeof buf, NULL); return buf; } static int gdi_error_code; int graphresult() { return gdi_error_code; } void setcolor(int c) { // Version 3.2: // Parameter c may now be original bgi color or new rgb color. // Version 3.4: // Fixed bug that forgot to set windows_color to c. if (IS_RGB_COLOR(c)) { color = windows_color = c; SetTextColor(hdc[0], RGB_COLOR(c)); SetTextColor(hdc[1], RGB_COLOR(c)); } else if (IS_BGI_COLOR(c)) { color = windows_color = c; SetTextColor(hdc[0], PALETTEINDEX(c+BG)); SetTextColor(hdc[1], PALETTEINDEX(c+BG)); } } int getmaxcolor() { return WHITE; } int getmaxmode() { return VGAMAX; } char* getmodename(int mode) { static char mode_str[32]; sprintf(mode_str, "%d x %d %s", window_width, window_height, mode < 2 ? "EGA" : "VGA"); return mode_str; } int getx() { POINT pos; GetCurrentPositionEx(hdc[active_page == visual_page ? 0 : 1], &pos); return pos.x; } int gety() { POINT pos; GetCurrentPositionEx(hdc[active_page == visual_page ? 0 : 1], &pos); return pos.y; } int getmaxx() { return window_width-1; } int getmaxy() { return window_height-1; } int getcolor() { // Version 3.2: This return value may now be either a BGI color // (from 0...MAXCOLORS) or a bgi color. return color; } char* getdrivername() { return "EGAVGA"; } void setlinestyle(int style, unsigned int pattern, int thickness) { line_settings.linestyle = style; line_settings.thickness = thickness; line_settings.upattern = pattern; } void getlinesettings(linesettingstype* ls) { *ls = line_settings; } void setwritemode(int mode) { if ((COPY_PUT <= mode) && (mode <= NOT_PUT)) write_mode = mode; } // The following function added to correct the rgb colors stored in an entry of // BGIpalette. This is needed because the screen might not be capable of // displaying the exact color requested. Call correctpalette(i) after each // change to BGIpalette[i]. // -- M. Main 11/17/98 static void correctpalette(int index) { COLORREF rgb; COLORREF rgb_at00; int red, blue, green; // Save the color currently at location 0,0 rgb_at00 = GetPixel(hdc[visual_page != active_page || bgiemu_handle_redraw ? 1 : 0], 0, 0); // Change the color at location 0,0 to color number i from the palette. putpixel(0,0,index); // Get the rgb components of the pixel at 0,0 and put that into the palette. rgb = GetPixel(hdc[visual_page != active_page || bgiemu_handle_redraw ? 1 : 0], 0, 0); if (rgb != CLR_INVALID) { red = GetRValue(rgb); blue = GetBValue(rgb); green = GetGValue(rgb); BGIpalette[index].peRed = (BYTE) (red & 0xFF); BGIpalette[index].peGreen = (BYTE) (green & 0xFF); BGIpalette[index].peBlue = (BYTE) (blue & 0xFF); SetPaletteEntries(hPalette, BG+index, 1, &BGIpalette[index]); RealizePalette(hdc[0]); } // Restore the original color to location 0,0: if (bgiemu_handle_redraw || visual_page != active_page) SetPixel(hdc[1], 0, 0, rgb); if (visual_page == active_page) SetPixel(hdc[0], 0, 0, rgb_at00); } void setpalette(int index, int color) { // Version 3.2: Added test of precondition. Notice that we are only allowed // to use this function to change one of the 0..MAXCOLORS locations // of the bgi palette to one of the 15 original bgi colors or to an rgb color. // Note: The behavior differs from original BGI in that colors already on // the screen are not changed by changing the palette, so it is not a // real palette. if ((index < 0) || (index > MAXCOLORS)) return; if (IS_BGI_COLOR(color)) { // color is one of the original 15 bgi colors BGIpalette[index] = BGIcolor[color]; current_palette.colors[index] = (signed char) color; } else { // color is an RGB color constructed with RGB_COLOR macro BGIpalette[index].peRed = RED_VALUE(color); BGIpalette[index].peGreen = GREEN_VALUE(color); BGIpalette[index].peBlue = BLUE_VALUE(color); current_palette.colors[index] = (signed char) -1; } SetPaletteEntries(hPalette, BG+index, 1, &BGIpalette[index]); RealizePalette(hdc[0]); correctpalette(index); // M. Main, Nov 17, 1998. if (index == bkcolor) { SetBkColor(hdc[0], PALETTEINDEX(BG+bkcolor)); SetBkColor(hdc[1], PALETTEINDEX(BG+bkcolor)); DeleteObject(hBackgroundBrush); hBackgroundBrush = CreateSolidBrush(PALETTEINDEX(BG+bkcolor)); } } void setrgbpalette(int index, int red, int green, int blue) { // Version 3.2: Added test of precondition. Notice that we are only allowed // to use this function to change one of the 0..MAXCOLORS locations // of the bgi palette to an explicit rgb color. // The rgb values use only the most significant 6 bits of the least significant // byte of the int parameters. // Note: The behavior differs from original BGI in that colors already on // the screen are not changed by changing the palette, so it is not a // real palette. if ((index < 0) || (index > MAXCOLORS)) return; // Mask RGB values to use only most significant 6 bits from least significant byte: BGIpalette[index].peRed = (red & 0xFC); BGIpalette[index].peGreen = (green & 0xFC); BGIpalette[index].peBlue = (blue & 0xFC); current_palette.colors[index] = (signed char) -1; SetPaletteEntries(hPalette, BG+index, 1, &BGIpalette[index]); RealizePalette(hdc[0]); correctpalette(index); // M. Main, Nov 17, 1998. if (index == bkcolor) { SetBkColor(hdc[0], PALETTEINDEX(BG+bkcolor)); SetBkColor(hdc[1], PALETTEINDEX(BG+bkcolor)); DeleteObject(hBackgroundBrush); hBackgroundBrush = CreateSolidBrush(PALETTEINDEX(BG+bkcolor)); } } void setallpalette(palettetype* pal) { // Version 3.2: Notice that we are only allowed // to use this function to change some or all of the 0..MAXCOLORS // locations of the bgi palette to specific values from original // bgi colors. // Note: The behavior differs from original BGI in that colors already on // the screen are not changed by changing the palette, so it is not a // real palette. signed char color; for (int i = 0; (i < pal->size) && (i <= MAXCOLORS); i++) { color = pal->colors[i]; if (IS_BGI_COLOR(color)) { current_palette.colors[i] = color; BGIpalette[i] = BGIcolor[color]; } } SetPaletteEntries(hPalette, BG, pal->size, BGIpalette); RealizePalette(hdc[0]); // Following loop added, M. Main, Nov 17, 1998 for (int j = 0; (j < pal->size) && (j <= MAXCOLORS); j++) correctpalette(j); if (IS_BGI_COLOR(bkcolor) && (bkcolor <= pal->size)) { SetBkColor(hdc[0], PALETTEINDEX(BG+bkcolor)); SetBkColor(hdc[1], PALETTEINDEX(BG+bkcolor)); DeleteObject(hBackgroundBrush); hBackgroundBrush = CreateSolidBrush(PALETTEINDEX(BG+bkcolor)); } } palettetype* getdefaultpalette() { static palettetype default_palette = { 16, { BLACK, BLUE, GREEN, CYAN, RED, MAGENT, BROWN, LIGHTGRAY, DARKGRAY,LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE}}; return &default_palette; } void getpalette(palettetype* pal) { *pal = current_palette; } int getpalettesize() { return MAXCOLORS+1; } void setbkcolor(int color) { // Version 3.2: Color may now be a bgi color (0 to MAXCOLORS) or an RGB color. if (IS_BGI_COLOR(bkcolor)) { SetBkColor(hdc[0], PALETTEINDEX(BG+bkcolor)); SetBkColor(hdc[1], PALETTEINDEX(BG+bkcolor)); DeleteObject(hBackgroundBrush); hBackgroundBrush = CreateSolidBrush(PALETTEINDEX(BG+bkcolor)); } else { SetBkColor(hdc[0], RGB_COLOR(bkcolor)); SetBkColor(hdc[1], RGB_COLOR(bkcolor)); DeleteObject(hBackgroundBrush); hBackgroundBrush = CreateSolidBrush(RGB_COLOR(bkcolor)); } } int getbkcolor() { // or an RGB color. return bkcolor; } void setfillstyle(int style, int color) { // Version 3.2: Color may now be bgi color or rgb color. if (!IS_BGI_COLOR(color) && !IS_RGB_COLOR(color)) return; fill_settings.pattern = style; fill_settings.color = color; SelectObject(hdc[0], hBrush[style]); SelectObject(hdc[1], hBrush[style]); } void getfillsettings(fillsettingstype* fs) { *fs = fill_settings; } static fillpatterntype userfillpattern ={-1, -1, -1, -1, -1, -1, -1, -1}; void setfillpattern(char const* upattern, int color) { // Version 3.2: Color may now be bgi color or rgb color. if (!IS_BGI_COLOR(color) && !IS_RGB_COLOR(color)) return; static HBITMAP hFillBitmap; static short bitmap_data[8]; for (int i = 0; i < 8; i++) { bitmap_data[i] = (unsigned char)~upattern[i]; userfillpattern[i] = upattern[i]; } HBITMAP h = CreateBitmap(8, 8, 1, 1, bitmap_data); HBRUSH hb = CreatePatternBrush(h); DeleteObject(hBrush[USER_FILL]); if (hFillBitmap) DeleteObject(hFillBitmap); hFillBitmap = h; hBrush[USER_FILL] = hb; SelectObject(hdc[0], hb); SelectObject(hdc[1], hb); fill_settings.color = color; fill_settings.pattern = USER_FILL; } void getfillpattern(fillpatterntype fp) { memcpy(fp, userfillpattern, sizeof userfillpattern); } static void select_fill_color() { if (windows_color != fill_settings.color) { windows_color = fill_settings.color; if (IS_RGB_COLOR(windows_color)) { SetTextColor(hdc[0], RGB_COLOR(windows_color)); SetTextColor(hdc[1], RGB_COLOR(windows_color)); } else { SetTextColor(hdc[0], PALETTEINDEX(windows_color+BG)); SetTextColor(hdc[1], PALETTEINDEX(windows_color+BG)); } } } void setusercharsize(int multx, int divx, int multy, int divy) { font_mul_x = multx; font_div_x = divx; font_mul_y = multy; font_div_y = divy; text_settings.charsize = 0; } void moveto(int x, int y) { if (bgiemu_handle_redraw || visual_page != active_page) MoveToEx(hdc[1], x, y, NULL); if (visual_page == active_page) MoveToEx(hdc[0], x, y, NULL); } void moverel(int dx, int dy) { POINT pos; GetCurrentPositionEx(hdc[1], &pos); moveto(pos.x + dx, pos.y + dy); } static void select_font() { if (text_settings.charsize == 0) { fcache.select(text_settings.font, text_settings.direction, font_metrics[text_settings.font] [normal_font_size[text_settings.font]].width *font_mul_x/font_div_x,font_metrics[text_settings.font] [normal_font_size[text_settings.font]].height *font_mul_y/font_div_y); } else { fcache.select(text_settings.font, text_settings.direction, font_metrics[text_settings.font][text_settings.charsize].width, font_metrics[text_settings.font][text_settings.charsize].height); } } static void text_output(int x, int y, const char* str) { select_font(); if (windows_color != color) { windows_color = color; if (IS_RGB_COLOR(windows_color)) { SetTextColor(hdc[0], RGB_COLOR(windows_color)); SetTextColor(hdc[1], RGB_COLOR(windows_color)); } else { SetTextColor(hdc[0], PALETTEINDEX(windows_color+BG)); SetTextColor(hdc[1], PALETTEINDEX(windows_color+BG)); } } if (bgiemu_handle_redraw || visual_page != active_page) TextOut(hdc[1], x, y, str, (int)strlen(str)); if (visual_page == active_page) TextOut(hdc[0], x, y, str, (int)strlen(str)); } void settextstyle(int font, int direction, int char_size) { if (char_size > 10) char_size = 10; text_settings.direction = direction; text_settings.font = font; text_settings.charsize = char_size; text_align_mode = ALIGN_NOT_SET; } void settextjustify(int horiz, int vert) { text_settings.horiz = horiz; text_settings.vert = vert; text_align_mode = ALIGN_NOT_SET; } void gettextsettings(textsettingstype* ts) { *ts = text_settings; } int textheight(const char* str) { SIZE ss; select_font(); GetTextExtentPoint32(hdc[0], str, (int)strlen(str), &ss); return ss.cy; } int textwidth(const char* str) { SIZE ss; select_font(); GetTextExtentPoint32(hdc[0], str, (int)strlen(str), &ss); return ss.cx; } void outtext(const char* str) { if (text_align_mode != UPDATE_CP) { text_align_mode = UPDATE_CP; int align = (text_settings.direction == HORIZ_DIR) ? (TA_UPDATECP | text_halign_cnv[text_settings.horiz] | text_valign_cnv[text_settings.vert]): (TA_UPDATECP | text_valign_cnv[text_settings.horiz] | text_halign_cnv[text_settings.vert]); SetTextAlign(hdc[0], align); SetTextAlign(hdc[1], align); } text_output(0, 0, str); } void outtextxy(int x, int y, const char* str) { if (text_align_mode != NOT_UPDATE_CP) { text_align_mode = NOT_UPDATE_CP; int align = (text_settings.direction == HORIZ_DIR) ? (TA_NOUPDATECP | text_halign_cnv[text_settings.horiz] | text_valign_cnv[text_settings.vert]): (TA_NOUPDATECP | text_valign_cnv[text_settings.horiz] | text_halign_cnv[text_settings.vert]); SetTextAlign(hdc[0], align); SetTextAlign(hdc[1], align); } text_output(x, y, str); } void setviewport(int x1, int y1, int x2, int y2, int clip) { view_settings.left = x1; view_settings.top = y1; view_settings.right = x2; view_settings.bottom = y2; view_settings.clip = clip; if (hRgn) DeleteObject(hRgn); hRgn = clip ? CreateRectRgn(x1, y1, x2, y2) : NULL; SelectClipRgn(hdc[1], hRgn); SetViewportOrgEx(hdc[1], x1, y1, NULL); SelectClipRgn(hdc[0], hRgn); SetViewportOrgEx(hdc[0], x1, y1, NULL); moveto(0,0); } void getviewsettings(viewporttype *viewport) { *viewport = view_settings; } const double pi = 3.14159265358979323846; static void arc_coords(double angle, double rx, double ry, int& x, int& y) { if (rx == 0 || ry == 0) { x = y = 0; return; } double s = sin(angle*pi/180.0); double c = cos(angle*pi/180.0); if (fabs(s) < fabs(c)) { double tg = s/c; double xr = sqrt((double)rx*rx*ry*ry/(ry*ry+rx*rx*tg*tg)); x = int((c >= 0) ? xr : -xr); y = int((s >= 0) ? -xr*tg : xr*tg); } else { double ctg = c/s; double yr = sqrt((double)rx*rx*ry*ry/(rx*rx+ry*ry*ctg*ctg)); x = int((c >= 0) ? yr*ctg : -yr*ctg); y = int((s >= 0) ? -yr : yr); } } void ellipse(int x, int y, int start_angle, int end_angle,int rx, int ry) { ac.x = x; ac.y = y; arc_coords(start_angle, rx, ry, ac.xstart, ac.ystart); arc_coords(end_angle, rx, ry, ac.xend, ac.yend); ac.xstart += x; ac.ystart += y; ac.xend += x; ac.yend += y; pcache.select(color); // VERSION 3.2: select now passed color. if (bgiemu_handle_redraw || visual_page != active_page) { Arc(hdc[1], x-rx, y-ry, x+rx, y+ry, ac.xstart, ac.ystart, ac.xend, ac.yend); } if (visual_page == active_page) { Arc(hdc[0], x-rx, y-ry, x+rx, y+ry, ac.xstart, ac.ystart, ac.xend, ac.yend); } } void fillellipse(int x, int y, int rx, int ry) { pcache.select(color); // VERSION 3.2: select now passed color. select_fill_color(); if (bgiemu_handle_redraw || visual_page != active_page) { Ellipse(hdc[1], x-rx, y-ry, x+rx, y+ry); } if (visual_page == active_page) { Ellipse(hdc[0], x-rx, y-ry, x+rx, y+ry); } } static void allocate_new_graphic_page(int page) { RECT scr; scr.left = -view_settings.left; scr.top = -view_settings.top; scr.right = screen_width-view_settings.left-1; scr.bottom = screen_height-view_settings.top-1; hBitmap[page] = CreateCompatibleBitmap(hdc[0],screen_width,screen_height); SelectObject(hdc[1], hBitmap[page]); SelectClipRgn(hdc[1], NULL); FillRect(hdc[1], &scr, hBackgroundBrush); SelectClipRgn(hdc[1], hRgn); } void setactivepage(int page) { if ((page < 0) || (page >= MAX_PAGES)) return; if (hBitmap[page] == NULL) { allocate_new_graphic_page(page); } else { SelectObject(hdc[1], hBitmap[page]); } if (!bgiemu_handle_redraw && active_page == visual_page) { POINT pos; GetCurrentPositionEx(hdc[0], &pos); MoveToEx(hdc[1], pos.x, pos.y, NULL); } active_page = page; } void setvisualpage(int page) { POINT pos; if ((page < 0) || (page >= MAX_PAGES)) return; if (hdc[page] == NULL) { allocate_new_graphic_page(page); } if (!bgiemu_handle_redraw && active_page == visual_page) { SelectObject(hdc[1], hBitmap[visual_page]); SelectClipRgn(hdc[1], NULL); BitBlt(hdc[1], -view_settings.left, -view_settings.top, window_width, window_height, hdc[0], -view_settings.left, -view_settings.top, SRCCOPY); SelectClipRgn(hdc[1], hRgn); GetCurrentPositionEx(hdc[0], &pos); MoveToEx(hdc[1], pos.x, pos.y, NULL); } SelectClipRgn(hdc[0], NULL); SelectClipRgn(hdc[1], NULL); SelectObject(hdc[1], hBitmap[page]); BitBlt(hdc[0], -view_settings.left, -view_settings.top, window_width, window_height, hdc[1], -view_settings.left, -view_settings.top, SRCCOPY); SelectClipRgn(hdc[0], hRgn); SelectClipRgn(hdc[1], hRgn); if (page != active_page) { SelectObject(hdc[1], hBitmap[active_page]); } if (active_page != visual_page) { GetCurrentPositionEx(hdc[1], &pos); MoveToEx(hdc[0], pos.x, pos.y, NULL); } visual_page = page; } void setaspectratio(int ax, int ay) { aspect_ratio_x = ax; aspect_ratio_y = ay; } void getaspectratio(int* ax, int* ay) { *ax = aspect_ratio_x; *ay = aspect_ratio_y; } void circle(int x, int y, int radius) { int ry = (unsigned)radius*aspect_ratio_x/aspect_ratio_y; int rx = radius; pcache.select(color); // VERSION 3.2: select now passed color. if (bgiemu_handle_redraw || visual_page != active_page) { Arc(hdc[1], x-rx, y-ry, x+rx, y+ry, x+rx, y, x+rx, y); } if (visual_page == active_page) { Arc(hdc[0], x-rx, y-ry, x+rx, y+ry, x+rx, y, x+rx, y); } } void arc(int x, int y, int start_angle, int end_angle, int radius) { pcache.select(color); // VERSION 3.2: select now passed color. ac.x = x; ac.y = y; ac.xstart = x + int(radius*cos(start_angle*pi/180.0)); ac.ystart = y - int(radius*sin(start_angle*pi/180.0)); ac.xend = x + int(radius*cos(end_angle*pi/180.0)); ac.yend = y - int(radius*sin(end_angle*pi/180.0)); if (bgiemu_handle_redraw || visual_page != active_page) { Arc(hdc[1], x-radius, y-radius, x+radius, y+radius, ac.xstart, ac.ystart, ac.xend, ac.yend); } if (visual_page == active_page) { Arc(hdc[0], x-radius, y-radius, x+radius, y+radius, ac.xstart, ac.ystart, ac.xend, ac.yend); } } void getarccoords(arccoordstype *arccoords) { *arccoords = ac; } void pieslice(int x, int y, int start_angle, int end_angle, int radius) { pcache.select(color); // VERSION 3.2: select now passed color. select_fill_color(); ac.x = x; ac.y = y; ac.xstart = x + int(radius*cos(start_angle*pi/180.0)); ac.ystart = y - int(radius*sin(start_angle*pi/180.0)); ac.xend = x + int(radius*cos(end_angle*pi/180.0)); ac.yend = y - int(radius*sin(end_angle*pi/180.0)); if (bgiemu_handle_redraw || visual_page != active_page) { Pie(hdc[1], x-radius, y-radius, x+radius, y+radius, ac.xstart, ac.ystart, ac.xend, ac.yend); } if (visual_page == active_page) { Pie(hdc[0], x-radius, y-radius, x+radius, y+radius, ac.xstart, ac.ystart, ac.xend, ac.yend); } } void sector(int x, int y, int start_angle, int end_angle, int rx, int ry) { ac.x = x; ac.y = y; arc_coords(start_angle, rx, ry, ac.xstart, ac.ystart); arc_coords(end_angle, rx, ry, ac.xend, ac.yend); ac.xstart += x; ac.ystart += y; ac.xend += x; ac.yend += y; pcache.select(color); // VERSION 3.2: select now passed color. if (bgiemu_handle_redraw || visual_page != active_page) { Pie(hdc[1], x-rx, y-ry, x+rx, y+ry, ac.xstart, ac.ystart, ac.xend, ac.yend); } if (visual_page == active_page) { Pie(hdc[0], x-rx, y-ry, x+rx, y+ry, ac.xstart, ac.ystart, ac.xend, ac.yend); } } void bar(int left, int top, int right, int bottom) { RECT r; if (left > right) { /* Turbo C corrects for badly ordered corners */ r.left = right; r.right = left; } else { r.left = left; r.right = right; } if (bottom < top) { /* Turbo C corrects for badly ordered corners */ r.top = bottom; r.bottom = top; } else { r.top = top; r.bottom = bottom; } pcache.select(color); // VERSION 3.2: select now passed color. select_fill_color(); if (bgiemu_handle_redraw || visual_page != active_page) { FillRect(hdc[1], &r, hBrush[fill_settings.pattern]); } if (visual_page == active_page) { FillRect(hdc[0], &r, hBrush[fill_settings.pattern]); } } void bar3d(int left, int top, int right, int bottom, int depth, int topflag) { int temp; const double tan30 = 1.0/1.73205080756887729352; if (left > right) { /* Turbo C corrects for badly ordered corners */ temp = left; left = right; right = temp; } if (bottom < top) { temp = bottom; bottom = top; top = temp; } bar(left+line_settings.thickness, top+line_settings.thickness, right-line_settings.thickness+1, bottom-line_settings.thickness+1); if (write_mode != COPY_PUT) { SetROP2(hdc[0], write_mode_cnv[write_mode]); SetROP2(hdc[1], write_mode_cnv[write_mode]); } pcache.select(color); // VERSION 3.2: select now passed color. int dy = int(depth*tan30); POINT p[11]; p[0].x = right, p[0].y = bottom; p[1].x = right, p[1].y = top; p[2].x = left, p[2].y = top; p[3].x = left, p[3].y = bottom; p[4].x = right, p[4].y = bottom; p[5].x = right+depth, p[5].y = bottom-dy; p[6].x = right+depth, p[6].y = top-dy; p[7].x = right, p[7].y = top; if (topflag) { p[8].x = right+depth, p[8].y = top-dy; p[9].x = left+depth, p[9].y = top-dy; p[10].x = left, p[10].y = top; } if (bgiemu_handle_redraw || visual_page != active_page) { Polyline(hdc[1], p, topflag ? 11 : 8); } if (visual_page == active_page) { Polyline(hdc[0], p, topflag ? 11 : 8); } if (write_mode != COPY_PUT) { SetROP2(hdc[0], R2_COPYPEN); SetROP2(hdc[1], R2_COPYPEN); } } void lineto(int x, int y) { if (write_mode != COPY_PUT) { SetROP2(hdc[0], write_mode_cnv[write_mode]); SetROP2(hdc[1], write_mode_cnv[write_mode]); } pcache.select(color); // VERSION 3.2: select now passed color. if (bgiemu_handle_redraw || visual_page != active_page) { LineTo(hdc[1], x, y); } if (visual_page == active_page) { LineTo(hdc[0], x, y); } if (write_mode != COPY_PUT) { SetROP2(hdc[0], R2_COPYPEN); SetROP2(hdc[1], R2_COPYPEN); } } void linerel(int dx, int dy) { POINT pos; GetCurrentPositionEx(hdc[1], &pos); lineto(pos.x + dx, pos.y + dy); } void drawpoly(int n_points, int* points) { if (write_mode != COPY_PUT) { SetROP2(hdc[0], write_mode_cnv[write_mode]); SetROP2(hdc[1], write_mode_cnv[write_mode]); } pcache.select(color); // VERSION 3.2: select now passed color. if (bgiemu_handle_redraw || visual_page != active_page) { Polyline(hdc[1], (POINT*)points, n_points); } if (visual_page == active_page) { Polyline(hdc[0], (POINT*)points, n_points); } if (write_mode != COPY_PUT) { SetROP2(hdc[0], R2_COPYPEN); SetROP2(hdc[1], R2_COPYPEN); } } void line(int x0, int y0, int x1, int y1) { POINT line[2]; line[0].x = x0; line[0].y = y0; line[1].x = x1; line[1].y = y1; drawpoly(2, (int*)&line); } void rectangle(int left, int top, int right, int bottom) { POINT rect[5]; rect[0].x = left, rect[0].y = top; rect[1].x = right, rect[1].y = top; rect[2].x = right, rect[2].y = bottom; rect[3].x = left, rect[3].y = bottom; rect[4].x = left, rect[4].y = top; drawpoly(5, (int*)&rect); } void fillpoly(int n_points, int* points) { pcache.select(color); // VERSION 3.2: select now passed color. select_fill_color(); if (bgiemu_handle_redraw || visual_page != active_page) { Polygon(hdc[1], (POINT*)points, n_points); } if (visual_page == active_page) { Polygon(hdc[0], (POINT*)points, n_points); } } void floodfill(int x, int y, int border) { pcache.select(color); // VERSION 3.2: select now passed color. select_fill_color(); if (IS_BGI_COLOR(border)) { if (bgiemu_handle_redraw || visual_page != active_page) { FloodFill(hdc[1], x, y, PALETTEINDEX(border+BG)); } if (visual_page == active_page) { FloodFill(hdc[0], x, y, PALETTEINDEX(border+BG)); } } else { if (bgiemu_handle_redraw || visual_page != active_page) { FloodFill(hdc[1], x, y, RGB_COLOR(border)); } if (visual_page == active_page) { FloodFill(hdc[0], x, y, RGB_COLOR(border)); } } } static int handle_input(int wait = 0) { MSG lpMsg; if (wait ? GetMessage(&lpMsg, NULL, 0, 0) : PeekMessage(&lpMsg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&lpMsg); DispatchMessage(&lpMsg); return 1; } return 0; } void delay(unsigned msec) { timeout_expired = false; SetTimer(hWnd, TIMER_ID, msec, NULL); while (!timeout_expired) handle_input(true); } int kbhit() { // If window was closed call c std lib kbhit (PDM) if (hWnd == NULL) return kbhit(); else { while (handle_input(0)); return !kbd_queue.is_empty(); } } int getch() { // Loop while queue is empty and window is still open (PDM) while (kbd_queue.is_empty() && hWnd != NULL) handle_input(0); // If window was closed call c std lib getch (PDM) if (hWnd == NULL) return _getch(); else return (unsigned char)kbd_queue.get(); } void cleardevice() { RECT scr; scr.left = -view_settings.left; scr.top = -view_settings.top; scr.right = screen_width-view_settings.left-1; scr.bottom = screen_height-view_settings.top-1; if (bgiemu_handle_redraw || visual_page != active_page) { if (hRgn != NULL) { SelectClipRgn(hdc[1], NULL); } FillRect(hdc[1], &scr, hBackgroundBrush); if (hRgn != NULL) { SelectClipRgn(hdc[1], hRgn); } } if (visual_page == active_page) { if (hRgn != NULL) { SelectClipRgn(hdc[0], NULL); } FillRect(hdc[0], &scr, hBackgroundBrush); if (hRgn != NULL) { SelectClipRgn(hdc[0], hRgn); } } moveto(0,0); } void clearviewport() { RECT scr; scr.left = 0; scr.top = 0; scr.right = view_settings.right-view_settings.left; scr.bottom = view_settings.bottom-view_settings.top; if (bgiemu_handle_redraw || visual_page != active_page) { FillRect(hdc[1], &scr, hBackgroundBrush); } if (visual_page == active_page) { FillRect(hdc[0], &scr, hBackgroundBrush); } moveto(0,0); } void detectgraph(int *graphdriver, int *graphmode) { *graphdriver = VGA; *graphmode = bgiemu_default_mode; } int getgraphmode() { return bgiemu_default_mode; } void setgraphmode(int) {} void putimage(int x, int y, void* image, int bitblt) { BGIimage* bi = (BGIimage*)image; HDC tempHDC; HBITMAP tempBMP; char *bitmapBits; char *actualBits; unsigned int localImageSize; hBitMapInfo.bmiHeader.biWidth=bi->width; hBitMapInfo.bmiHeader.biHeight=bi->height; localImageSize=(bi->width)*(bi->height)*32/8; //32 bits per pixel, 8 bits per byte hBitMapInfo.bmiHeader.biSizeImage=localImageSize; actualBits=bi->bits; bitmapBits=new char[localImageSize]; tempHDC=CreateCompatibleDC(hdc[visual_page != active_page|| bgiemu_handle_redraw ? 1 : 0]); if (0==SetDIBitsToDevice(tempHDC,0,0,bi->width,bi->height,0,0,0,bi->height-1,&(bi->bits),&hBitMapInfo,DIB_RGB_COLORS)) cerr << "Unable to copy image to offscreen buffer" << endl; tempBMP=CreateDIBSection(tempHDC,&hBitMapInfo,DIB_RGB_COLORS,(void**)&bitmapBits,0,0); if (!SelectObject(tempHDC,tempBMP)) cerr << "cannot select bitmap image in offscreen window" << endl; memcpy(bitmapBits,actualBits,localImageSize); // Select the bitmaps into the compatible DC. if (SelectObject(hdc[0], tempBMP)) // was tempBMP)) cerr << "Unable to synch graphics window with bitmap." << endl; if (!BitBlt(hdc[0],x,y,bi->width,bi->height,tempHDC,0,0,bitblt_mode_cnv[bitblt])) //bi->hdc was tempHDC cerr << "Unable to copy bitmap to graphics window." << endl; if (SelectObject(hdc[1], tempBMP)) // was tempBMP)) cerr << "Unable to synch graphics window with bitmap." << endl; if (!BitBlt(hdc[1],x,y,bi->width,bi->height,tempHDC,0,0,bitblt_mode_cnv[bitblt])) //bi->hdc was tempHDC cerr << "Unable to copy bitmap to graphics window." << endl; DeleteObject(tempBMP); //delete bitmapBits; // To prevent heap lea