home *** CD-ROM | disk | FTP | other *** search
- /*
- * FILE: screen.c
- * AUTHOR: R. Gonzalez
- * CREATED: Aug. 5, 1990
- *
- * REVISED: Norman Gaskill
- * REV. DATE: December 16, 1990
- * CHANGES: Add PC_Screen code
- *
- * generic, mac-specific, and PC methods for multi-window screens. Use
- * the Mac_Screen and PC_Screen code as a guide when writing a Screen
- * descendant for a new platform.
- */
-
- # include "screen.h"
- # include "error.h"
- # include <stdlib.h>
-
- extern Error *gerror;
-
- /******************************************************************
- * Initialize screen. Derived classes call inherited method and
- * initialize device_frame.
- ******************************************************************/
- boolean Screen::init(void)
- {
- device_frame = new(Frame);
- device_frame->init();
- normalized_frame = new(Frame);
- normalized_frame->init();
- set_normalized_frame(0.,0.,2.,2.);
- num_windows = 0;
- return TRUE;
- }
-
- /******************************************************************
- * Add new window to screen - up to derived class.
- ******************************************************************/
- int Screen::new_window(Frame *frame)
- {
- return 0; /* must return something in Turbo C++? */
- }
-
- /******************************************************************
- * Bring window to front. This is up to the derived class.
- ******************************************************************/
- void Screen::make_closest(int window_num)
- {
- }
-
- /******************************************************************
- * Get coordinate frame of window in device coordinates.
- * Up to derived class.
- ******************************************************************/
- void Screen::get_window_device_frame(int window_num,
- Frame *frame)
- {
- }
-
- /******************************************************************
- * Return screen aspect ratio: width/height in device coords.
- ******************************************************************/
- double Screen::get_device_aspect_ratio(void)
- {
- double ratio;
-
- ratio = device_frame->width/device_frame->height;
- if (ratio > 0.)
- return ratio;
- else
- return -ratio;
- }
-
- /******************************************************************
- * Change coordinate system for windows and drawing routines.
- * This is in terms of the width, height, and origin of
- * the desired coordinate system for the whole screen. Use
- * get_device_aspect_ratio to maintain aspect ratio.
- ******************************************************************/
- void Screen::set_normalized_frame(double x,double y,
- double width,double height)
- {
- normalized_frame->set(x,y,width,height);
- }
-
- /******************************************************************
- * Sets the current drawing window. Up to derived class.
- ******************************************************************/
- void Screen::set_current_window(int window_num)
- {
- }
-
- /******************************************************************
- * Sets the current drawing pen color. Up to derived class.
- ******************************************************************/
- void Screen::set_pen_color(color x)
- {
- }
-
- /******************************************************************
- * Sets window background to current color. Up to derived class.
- ******************************************************************/
- void Screen::fill_window(void)
- {
- }
-
- /******************************************************************
- * draw_line() is used to draw lines using device coordinates.
- ******************************************************************/
- void Screen::draw_line(Coord2* c1,Coord2* c2)
- {
- move_to(c1);
- draw_to(c2);
- }
-
- /******************************************************************
- * Move present pen position to new position using device
- * coordinates. Nothing is drawn. Up to derived class.
- ******************************************************************/
- void Screen::move_to(Coord2* c)
- {
- }
-
- /******************************************************************
- * Draw from present pen position to new position using device
- * coordinates. Up to derived class.
- ******************************************************************/
- void Screen::draw_to(Coord2* c)
- {
- }
-
- /******************************************************************
- * mouse_button_is_down() checks whether the mouse button is down,
- * returns TRUE if so, FALSE if not. Up to derived class. Make
- * sure to override this if you use Screen::wait(), or override
- * Screen::wait(). (Else you'll get an infinite "wait"!)
- ******************************************************************/
- boolean Screen::mouse_button_is_down(void)
- {
- return FALSE;
- }
-
- /******************************************************************
- * Wait until button is pressed.
- ******************************************************************/
- void Screen::wait(void)
- {
- while (!mouse_button_is_down())
- ;
- while (mouse_button_is_down())
- ;
- }
-
- /******************************************************************
- * Destroy screen. Derived classes call inherited method.
- ******************************************************************/
- boolean Screen::destroy(void)
- {
- device_frame->destroy();
- delete(device_frame);
- normalized_frame->destroy();
- delete(normalized_frame);
-
- return TRUE;
- }
-
- # ifdef THINK_C
-
- #include "DialogMgr.h"
- #include "EventMgr.h"
- #include "TextEdit.h"
- #include "MemoryMgr.h"
- #include "MenuMgr.h"
- #include "Quickdraw.h"
- #include "WindowMgr.h"
-
- /*------------------- Mac_Screen methods -----------------------*/
- /* Functions beginning with a capital letter and variables */
- /* containing capitals are declared in Mac headers, and */
- /* defined in the Macintosh Toolbox. */
-
- # define NIL_POINTER 0L
- # define MOVE_TO_FRONT -1L
- # define REMOVE_ALL_EVENTS 0
- # define TITLE "\p"
- # define VISIBLE 1
- # define NO_GO_AWAY 0
- # define NIL_REF_CON NIL_POINTER
- /* remove following line to retain menu bar. This is recommended
- to make it easier to recover from errors when debugging! */
- # define NO_MBAR
-
- /******************************************************************
- * You must call init() at the beginning of main(). Likely don't
- * need all these initializations; most are taken from Mark &
- * Reed's "Macintosh Programming Primer", Addison-Wesley, 1989
- ******************************************************************/
- boolean Mac_Screen::init(void)
- {
- double x,
- y,
- width,
- height;
-
- InitGraf(&thePort);
- InitFonts();
- FlushEvents(everyEvent,REMOVE_ALL_EVENTS);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(NIL_POINTER);
- InitCursor();
- HideCursor();
-
- # ifdef NO_MBAR
- old_mbar_height = MBarHeight;
- MBarHeight = 0;
- # endif
-
- Screen::init();
-
- width = screenBits.bounds.right - screenBits.bounds.left;
- height = screenBits.bounds.top - screenBits.bounds.bottom;
- x = screenBits.bounds.left + width/2.;
- y = screenBits.bounds.bottom + height/2.;
- device_frame->set(x,y,width,height);
-
- normalized_frame->height = normalized_frame->width /
- get_device_aspect_ratio();
-
- current_window = NULL;
-
- return TRUE;
- }
-
- /******************************************************************
- * Add new window to screen
- ******************************************************************/
- int Mac_Screen::new_window(Frame *frame)
- {
- Rect rectangle;
- int left,
- right,
- top,
- bottom;
- Coord2 *old_pt,
- *new_pt;
- Rect mbar_rect; /* to allow window to overlap menu */
- RgnHandle mbar_rgn;
- WindowPtr temp_window; /* This is required due to a
- bug in Think C! */
-
- old_pt = new(Coord2);
- old_pt->init();
- new_pt = new(Coord2);
- new_pt->init();
-
- old_pt->set(frame->x-frame->width/2.,frame->y-frame->height/2.);
- new_pt->convert(old_pt,normalized_frame,device_frame);
- left = new_pt->x;
- bottom = new_pt->y;
-
- old_pt->set(frame->x+frame->width/2.,frame->y+frame->height/2.);
- new_pt->convert(old_pt,normalized_frame,device_frame);
- right = new_pt->x;
- top = new_pt->y;
-
- old_pt->destroy();
- delete(old_pt);
- new_pt->destroy();
- delete(new_pt);
-
- SetRect(&rectangle,left,top,right,bottom);
-
- temp_window = NewWindow(NIL_POINTER,&rectangle,TITLE,
- VISIBLE,plainDBox,MOVE_TO_FRONT,NO_GO_AWAY,NIL_REF_CON);
-
- # ifdef NO_MBAR
- if (top < screenBits.bounds.top+old_mbar_height)
- {
- if (bottom < screenBits.bounds.top+old_mbar_height)
- SetRect(&mbar_rect,0,0,right-left,bottom-top);
- else
- SetRect(&mbar_rect,0,0,right-left,
- screenBits.bounds.top+old_mbar_height-top);
- mbar_rgn = NewRgn();
- RectRgn(mbar_rgn,&mbar_rect);
- UnionRgn(temp_window->visRgn,mbar_rgn,temp_window->visRgn);
- DisposeRgn(mbar_rgn);
- }
- # endif
-
- if (num_windows < MAX_WINDOWS)
- {
- window[num_windows++] = temp_window;
- set_current_window(num_windows-1);
- return num_windows-1;
- }
- else
- {
- gerror->report("Ran out of windows");
- DisposeWindow(temp_window);
- return num_windows-1;
- }
- }
-
- /******************************************************************
- * Bring window to front.
- ******************************************************************/
- void Mac_Screen::make_closest(int window_num)
- {
- if (window_num > -1 && window_num < num_windows)
- SelectWindow(window[window_num]);
- else
- gerror->report("Illegal window number");
- }
-
- /******************************************************************
- * Get coordinate frame of window in device coordinates.
- ******************************************************************/
- void Mac_Screen::get_window_device_frame(int window_num,
- Frame *frame)
- {
- double x,
- y,
- width,
- height;
-
- if (window_num > -1 && window_num < num_windows)
- {
- width = window[window_num]->portRect.right -
- window[window_num]->portRect.left;
- height = window[window_num]->portRect.top -
- window[window_num]->portRect.bottom;
- x = window[window_num]->portRect.left + width/2.;
- y = window[window_num]->portRect.bottom + height/2.;
- frame->set(x,y,width,height);
- }
- else
- gerror->report("Illegal window number");
- }
-
- /******************************************************************
- * Sets the current drawing window.
- ******************************************************************/
- void Mac_Screen::set_current_window(int window_num)
- {
- if (window_num > -1 && window_num < num_windows)
- {
- current_window = window[window_num];
- SetPort(current_window);
- }
- else
- gerror->report("Illegal window number");
- }
-
- /******************************************************************
- * sets the current drawing color. The colors are defined
- * in "Quickdraw.h". Call set_current_window() first!
- ******************************************************************/
- void Mac_Screen::set_pen_color(color x)
- {
- if (current_window != NULL)
- switch ((int) x)
- {
- case 0: ForeColor(blackColor);
- break;
- case 1: ForeColor(whiteColor);
- break;
- case 2: ForeColor(redColor);
- break;
- case 3: ForeColor(yellowColor);
- break;
- case 4: ForeColor(greenColor);
- break;
- case 5: ForeColor(blueColor);
- break;
- case 6: ForeColor(cyanColor);
- break;
- case 7: ForeColor(magentaColor);
- break;
- default: break;
- }
- else
- gerror->report("Can't set color with no windows");
- }
-
- /******************************************************************
- * calls the appropriate Mac Toolbox function to make the window
- * the current color. Call set_current_window() first!
- ******************************************************************/
- void Mac_Screen::fill_window(void)
- {
- if (current_window != NULL)
- FillRect(&(current_window->portRect),black);
- else
- gerror->report("Can't fill window with no windows");
- }
-
- /******************************************************************
- * Move present pen position to new position using device
- * coordinates. Call set_current_window() first!
- ******************************************************************/
- void Mac_Screen::move_to(Coord2* c)
- {
- if (current_window != NULL)
- MoveTo((int) c->x,(int) c->y);
- else
- gerror->report("Can't move_to() with no windows");
- }
-
- /******************************************************************
- * Draw from present pen position to new position using device
- * coordinates. Call set_current_window() first!
- ******************************************************************/
- void Mac_Screen::draw_to(Coord2* c)
- {
- if (current_window != NULL)
- LineTo((int) c->x,(int) c->y);
- else
- gerror->report("Can't draw_to() with no windows");
- }
-
- /******************************************************************
- * mouse_button_is_down() checks whether the mouse button is down,
- * returns TRUE if so, FALSE if not.
- ******************************************************************/
- boolean Mac_Screen::mouse_button_is_down(void)
- {
- return Button();
- }
-
- /******************************************************************
- * Destroy screen.
- ******************************************************************/
- boolean Mac_Screen::destroy(void)
- {
- int window_num;
-
- Screen::destroy();
-
- for (window_num=0 ; window_num<num_windows ; window_num++)
- DisposeWindow(window[window_num]);
-
- # ifdef NO_MBAR
- MBarHeight = old_mbar_height;
- # endif
-
- return TRUE;
- }
-
- # else
-
- /*-------------------------------- PC_Screen methods ---------------------------------*/
-
- /*-----------------NOTE: file EGAVGA.BGI must be in current directory-----------------*/
-
- # include <stdio.h>
- # define __COLORS //for THINK_C
- # include <conio.h>
- # include <graphics.h> //BORLAND Turbo C++ library of graphics functions
- # undef __COLORS //for THINK_C
- # define LIGHTGRAY 7 //for use by floodfill
-
- int current_window = -1; //keeps track of current window number
- boolean window_defined = FALSE; //valid window variable
- int win_data [MAX_WINDOWS] [6]; //window data array
-
- /******************************************************************
- * You must call init() at the beginning of main().
- ******************************************************************/
- boolean PC_Screen::init(void)
- {
- int x,y,width,height;
- int graphdriver = DETECT, graphmode, error_code;
-
- Screen::init();
- initgraph(&graphdriver, &graphmode, "..\\bgi"); //Initialize graphics,
- error_code = graphresult(); //system must be EGA or VGA
- if (error_code != grOk) //If no graphics
- return(FALSE); //hardware found is found
- if ((graphdriver != EGA) && (graphdriver != VGA))
- {
- closegraph();
- return FALSE;
- }
- width = getmaxx();
- height = getmaxy();
- x = width/2;
- y = height/2;
- device_frame->set(x,y,width,-height);
- normalized_frame->height = normalized_frame->width /
- get_device_aspect_ratio();
- return(TRUE); //Graphics OK return "true"
- }
-
- /******************************************************************
- * Add new window to screen
- ******************************************************************/
- int PC_Screen::new_window(Frame *frame)
- {
- int left,
- right,
- top,
- bottom;
- Coord2 *old_pt,
- *new_pt;
-
- old_pt = new(Coord2);
- old_pt->init();
- new_pt = new(Coord2);
- new_pt->init();
-
- old_pt->set(frame->x-frame->width/2.,frame->y-frame->height/2.);
- new_pt->convert(old_pt,normalized_frame,device_frame);
- left = new_pt->x;
- bottom = new_pt->y;
-
- old_pt->set(frame->x+frame->width/2.,frame->y+frame->height/2.);
- new_pt->convert(old_pt,normalized_frame,device_frame);
- right = new_pt->x;
- top = new_pt->y;
-
- old_pt->destroy();
- delete(old_pt);
- new_pt->destroy();
- delete(new_pt);
-
- if (num_windows < MAX_WINDOWS)
- {
- setviewport(left,top,right,bottom,1); //1=truncate output
- win_data[num_windows][0] = left;
- win_data[num_windows][1] = top;
- win_data[num_windows][2] = right;
- win_data[num_windows][3] = bottom;
- current_window = num_windows;
- num_windows++;
- return num_windows-1;
- }
- else
- {
- gerror->report("Ran out of windows");
- return num_windows;
- }
- }
-
- /******************************************************************
- * Bring window to front.
- ******************************************************************/
- void PC_Screen::make_closest(int window_num)
- {
- if (window_num > -1 && window_num < num_windows)
- {
- current_window = window_num;
- setviewport(win_data[current_window][0], //resets viewport
- win_data[current_window][1],
- win_data[current_window][2],
- win_data[current_window][3],1); //1=truncate output
- setfillstyle(SOLID_FILL, win_data[current_window][4]); //set and
- floodfill(2,2,LIGHTGRAY); //flood fill current window
- setcolor(win_data[current_window][5]); //reset draw color
- }
- else
- gerror->report("Illegal window number");
- }
-
- /******************************************************************
- * Get coordinate frame of window in device coordinates.
- ******************************************************************/
- void PC_Screen::get_window_device_frame(int window_num,Frame *frame)
- {
- int x,
- y,
- width,
- height;
- struct viewporttype viewinfo;
-
- if (window_num > -1 && window_num < num_windows)
- {
- getviewsettings(&viewinfo);
- width = viewinfo.right - viewinfo.left;
- height = viewinfo.bottom - viewinfo.top;
- x = width/2;
- y = height/2;
-
- frame->set(x,y,width,-height);
- }
- else
- gerror->report("Illegal window number");
- }
-
- /******************************************************************
- * Sets the current drawing window.
- ******************************************************************/
- void PC_Screen::set_current_window(int window_num)
- {
- if (window_num > -1 && window_num < num_windows)
- {
- window_defined = TRUE;
- current_window = window_num;
- setviewport(win_data[current_window][0], //resets viewport
- win_data[current_window][1],
- win_data[current_window][2],
- win_data[current_window][3],1); //1=truncate output
- }
- else
- gerror->report("Illegal window number");
- }
-
- /******************************************************************
- * sets the current drawing color. Call set_current_window() first!
- *----------------------------------------------------------------
- * Note from R. Gonzalez: N. Gaskill had difficulty here because
- * the Turbo C++ file "graphics.h" conflicted with
- * my use of the identifier "color" and/or with my list of color
- * constants, as defined in my "color.h". To get around this
- * he had to use "# define __COLORS" and was unable to take advan-
- * tage of the names given in "graphics.h". I think he could have
- * gotten around this by momentarily #undef-ing my constants and
- * #define-ing constants with new names for the ones given in
- * graphics.h. As it is, however, he is forced to use numerical
- * constants below.
- ******************************************************************/
- void PC_Screen::set_pen_color(int color)
- {
- if (window_defined)
- {
- switch (color) //correct colors for PC
- {
- case 0: color = 0;
- break;
- case 1: color = 15;
- break;
- case 2: color = 4;
- break;
- case 3: color = 14;
- break;
- case 4: color = 2;
- break;
- case 5: color = 1;
- break;
- case 6: color = 3;
- break;
- case 7: color = 5;
- break;
- default: break;
- }
- setcolor(color); //set draw color
- setfillstyle(SOLID_FILL, color); //set flood fill color
- win_data[current_window][5] = color; //save draw color
- }
- else
- gerror->report("Can't set color with no windows");
- }
-
- /******************************************************************
- * Make the window the current color. Call set_current_window() first!
- ******************************************************************/
- void PC_Screen::fill_window(void)
- {
- if (window_defined)
- {
- clearviewport(); //clear for next
- floodfill(2,2,LIGHTGRAY); //fill window
- win_data[current_window][4] = getcolor(); //save fill color
- }
- else
- gerror->report("Can't fill window with no windows");
- }
-
- /******************************************************************
- * Move present pen position to new position using device
- * coordinates. Call set_current_window() first!
- ******************************************************************/
- void PC_Screen::move_to(Coord2* c)
- {
- if (window_defined)
- moveto((int) c->x,(int) c->y);
- else
- gerror->report("Can't move_to() with no windows");
- }
-
- /******************************************************************
- * Draw from present pen position to new position using device
- * coordinates. Call set_current_window() first!
- ******************************************************************/
- void PC_Screen::draw_to(Coord2* c)
- {
- if (window_defined)
- lineto((int) c->x,(int) c->y);
- else
- gerror->report("Can't draw_to() with no windows");
- }
-
- /******************************************************************
- * look for keyhit.
- ******************************************************************/
- void PC_Screen::wait(void)
- {
- printf("Press any key to exit");
- getch();
- }
-
- /******************************************************************
- * Destroy screen.
- ******************************************************************/
- boolean PC_Screen::destroy(void)
- {
- int window_num;
-
- Screen::destroy();
- closegraph();
- return TRUE;
- }
-
- # endif
-