2402 lines
60 KiB
C
2402 lines
60 KiB
C
/* svgalib.c
|
|
* (c) 2000-2002 Karel 'Clock' Kulhavy
|
|
* This file is a part of the Links program, released under GPL.
|
|
*
|
|
* This does graphics driver of svgalib, svgalib mouse.
|
|
* This doesn't do svgalib keyboard.
|
|
*/
|
|
|
|
#include "cfg.h"
|
|
|
|
#ifdef GRDRV_SVGALIB
|
|
|
|
#include "links.h"
|
|
#include "bits.h"
|
|
|
|
#include <vga.h>
|
|
#include <vgamouse.h>
|
|
#include "arrow.inc"
|
|
|
|
struct irgb {
|
|
unsigned rgb[3];
|
|
};
|
|
|
|
static struct itrm *svgalib_kbd;
|
|
|
|
extern struct graphics_driver svga_driver;
|
|
static int mouse_x, mouse_y, mouse_buttons; /* For tracking the state of the mouse */
|
|
static int background_x, background_y; /* Where was the mouse background taken from */
|
|
static unsigned char *mouse_buffer, *background_buffer, *new_background_buffer;
|
|
static struct graphics_device *mouse_graphics_device;
|
|
static int global_mouse_hidden;
|
|
static long mouse_black, mouse_white; /* Mouse arrow pointer colors */
|
|
static int (* mouse_getscansegment)(unsigned char *, int, int, int);
|
|
static int (* mouse_drawscansegment)(unsigned char *, int, int, int);
|
|
static unsigned char mouse_works = 0;
|
|
static unsigned char *svga_driver_param; /* NULL by default */
|
|
static int vga_mode; /* The mode that has been selected */
|
|
static int mouse_aggregate_flag, mouse_aggregate_action;
|
|
static int flags = 0; /* OR-ed 1: running in background
|
|
* 2: vga_block()-ed
|
|
*/
|
|
#ifndef __SPAD__
|
|
static struct timer *svgalib_timer_id;
|
|
#endif
|
|
|
|
/*---------------------------LIMITATIONS---------------------------------------*/
|
|
/* pixel_set_paged works only for <=8 bytes per pixel.
|
|
* Doesn't work on video cards which have 1 pixel spanning more that 65536 bytes! ( :-) )
|
|
* vga_linewidth%vga_bytes must be zero.
|
|
* The bitmaps have all consecutive data. No vidram mallocing is performed.
|
|
*/
|
|
|
|
/*------------------------STRUCTURES-------------------------------------------*/
|
|
struct modeline{
|
|
char *name;
|
|
int number;
|
|
};
|
|
|
|
/*-------------- GLOBAL VARIABLES --------------------------------------------*/
|
|
|
|
#define NUMBER_OF_DEVICES 10
|
|
|
|
#define TEST_INACTIVITY if (dev != current_virtual_device || flags) return;
|
|
|
|
#define TEST_INACTIVITY_0 if (dev != current_virtual_device || flags) return 0;
|
|
|
|
#define RECTANGLES_INTERSECT(xl0, xh0, xl1, xh1, yl0, yh0, yl1, yh1) (\
|
|
(xl0)<(xh1)\
|
|
&& (xl1)<(xh0)\
|
|
&& (yl0)<(yh1)\
|
|
&& (yl1)<(yh0))
|
|
|
|
#define TEST_MOUSE(xl,xh,yl,yh) if (RECTANGLES_INTERSECT(\
|
|
(xl),(xh),\
|
|
background_x,background_x+arrow_width,\
|
|
(yl),(yh),\
|
|
background_y,background_y+arrow_height)\
|
|
&& !global_mouse_hidden){\
|
|
mouse_hidden=1;\
|
|
hide_mouse();\
|
|
}else mouse_hidden=0;
|
|
|
|
#define END_MOUSE if (mouse_hidden) show_mouse();
|
|
|
|
/* Actual vga mode definition */
|
|
static int vga_linewidth; /* Prepared out from vga_getmodeinfo */
|
|
static int xsize, ysize; /* Prepared out from vga_getmodeinfo */
|
|
static int vga_bytes; /* Prepared out from vga_getmodeinfo */
|
|
static int vga_colors; /* Prepared out from vga_getmodeinfo */
|
|
static int vga_misordered; /* Prepared out from vga_getmodeinfo */
|
|
static int vga_linear; /* 1 linear mode, 0 nonlinear mode (paged) */
|
|
static int palette_depth; /* 6 for normal VGA, 8 for VGA which supports 8 bit DAC */
|
|
static int accel_avail; /* Which accel fns are available */
|
|
static int do_sync; /* Tells the "normal" memory operations (those
|
|
* that do not use accelerator) to do
|
|
* vga_accel(ACCEL_SYNC) before writing into the
|
|
* memory.
|
|
*/
|
|
static int vga_page=-1;
|
|
static int mode_x; /* 1 if mode_X organization is set up */
|
|
static int fb_pixelsize; /* Number of bytes per pixel in bitmap */
|
|
static unsigned char *my_graph_mem;
|
|
static unsigned char *scroll_buffer = NULL; /* For paged scrolling only */
|
|
static struct modeline modes[]={
|
|
#ifdef G320x200x16
|
|
{"320x200x16", G320x200x16 },
|
|
#endif
|
|
#ifdef G320x200x256
|
|
{"320x200x256", G320x200x256 },
|
|
#endif
|
|
#ifdef G320x200x32K
|
|
{"320x200x32K", G320x200x32K },
|
|
#endif
|
|
#ifdef G320x200x64K
|
|
{"320x200x64K", G320x200x64K },
|
|
#endif
|
|
#ifdef G320x200x16M
|
|
{"320x200x16M", G320x200x16M },
|
|
#endif
|
|
#ifdef G320x200x16M32
|
|
{"320x200x16M32", G320x200x16M32 },
|
|
#endif
|
|
|
|
#ifdef G320x240x256
|
|
{"320x240x256", G320x240x256 },
|
|
#endif
|
|
#ifdef G320x240x32K
|
|
{"320x240x32K", G320x240x32K },
|
|
#endif
|
|
#ifdef G320x240x64K
|
|
{"320x240x64K", G320x240x64K },
|
|
#endif
|
|
#ifdef G320x240x16M
|
|
{"320x240x16M", G320x240x16M },
|
|
#endif
|
|
#ifdef G320x240x16M32
|
|
{"320x240x16M32", G320x240x16M32 },
|
|
#endif
|
|
|
|
#ifdef G320x400x256
|
|
{"320x400x256", G320x400x256 },
|
|
#endif
|
|
#ifdef G320x400x32K
|
|
{"320x400x32K", G320x400x32K },
|
|
#endif
|
|
#ifdef G320x400x64K
|
|
{"320x400x64K", G320x400x64K },
|
|
#endif
|
|
#ifdef G320x400x16M
|
|
{"320x400x16M", G320x400x16M },
|
|
#endif
|
|
#ifdef G320x400x16M32
|
|
{"320x400x16M32", G320x400x16M32 },
|
|
#endif
|
|
|
|
#ifdef G320x480x256
|
|
{"320x480x256", G320x480x256 },
|
|
#endif
|
|
#ifdef G320x480x32K
|
|
{"320x480x32K", G320x480x32K },
|
|
#endif
|
|
#ifdef G320x480x64K
|
|
{"320x480x64K", G320x480x64K },
|
|
#endif
|
|
#ifdef G320x480x16M
|
|
{"320x480x16M", G320x480x16M },
|
|
#endif
|
|
#ifdef G320x480x16M32
|
|
{"320x480x16M32", G320x480x16M32 },
|
|
#endif
|
|
|
|
#ifdef G360x480x256
|
|
{"360x480x256", G360x480x256 },
|
|
#endif
|
|
|
|
#ifdef G400x300x256
|
|
{"400x300x256", G400x300x256 },
|
|
#endif
|
|
#ifdef G400x300x32K
|
|
{"400x300x32K", G400x300x32K },
|
|
#endif
|
|
#ifdef G400x300x64K
|
|
{"400x300x64K", G400x300x64K },
|
|
#endif
|
|
#ifdef G400x300x16M
|
|
{"400x300x16M", G400x300x16M },
|
|
#endif
|
|
#ifdef G400x300x16M32
|
|
{"400x300x16M32", G400x300x16M32 },
|
|
#endif
|
|
|
|
#ifdef G400x600x256
|
|
{"400x600x256", G400x600x256 },
|
|
#endif
|
|
#ifdef G400x600x32K
|
|
{"400x600x32K", G400x600x32K },
|
|
#endif
|
|
#ifdef G400x600x64K
|
|
{"400x600x64K", G400x600x64K },
|
|
#endif
|
|
#ifdef G400x600x16M
|
|
{"400x600x16M", G400x600x16M },
|
|
#endif
|
|
#ifdef G400x600x16M32
|
|
{"400x600x16M32", G400x600x16M32 },
|
|
#endif
|
|
|
|
#ifdef G512x384x256
|
|
{"512x384x256", G512x384x256 },
|
|
#endif
|
|
#ifdef G512x384x32K
|
|
{"512x384x32K", G512x384x32K },
|
|
#endif
|
|
#ifdef G512x384x64K
|
|
{"512x384x64K", G512x384x64K },
|
|
#endif
|
|
#ifdef G512x384x16M
|
|
{"512x384x16M", G512x384x16M },
|
|
#endif
|
|
#ifdef G512x384x16M32
|
|
{"512x384x16M32", G512x384x16M32 },
|
|
#endif
|
|
|
|
#ifdef G512x480x256
|
|
{"512x480x256", G512x480x256 },
|
|
#endif
|
|
#ifdef G512x480x32K
|
|
{"512x480x32K", G512x480x32K },
|
|
#endif
|
|
#ifdef G512x480x64K
|
|
{"512x480x64K", G512x480x64K },
|
|
#endif
|
|
#ifdef G512x480x16M
|
|
{"512x480x16M", G512x480x16M },
|
|
#endif
|
|
#ifdef G512x480x16M32
|
|
{"512x480x16M32", G512x480x16M32 },
|
|
#endif
|
|
|
|
#ifdef G640x200x16
|
|
{"640x200x16", G640x200x16 },
|
|
#endif
|
|
#ifdef G640x350x16
|
|
{"640x350x16", G640x350x16 },
|
|
#endif
|
|
|
|
#ifdef G640x400x256
|
|
{"640x400x256", G640x400x256 },
|
|
#endif
|
|
#ifdef G640x400x32K
|
|
{"640x400x32K", G640x400x32K },
|
|
#endif
|
|
#ifdef G640x400x64K
|
|
{"640x400x64K", G640x400x64K },
|
|
#endif
|
|
#ifdef G640x400x16M
|
|
{"640x400x16M", G640x400x16M },
|
|
#endif
|
|
#ifdef G640x400x16M32
|
|
{"640x400x16M32", G640x400x16M32 },
|
|
#endif
|
|
|
|
#ifdef G640x480x16
|
|
{"640x480x16", G640x480x16 },
|
|
#endif
|
|
#ifdef G640x480x256
|
|
{"640x480x256", G640x480x256 },
|
|
#endif
|
|
#ifdef G640x480x32K
|
|
{"640x480x32K", G640x480x32K },
|
|
#endif
|
|
#ifdef G640x480x64K
|
|
{"640x480x64K", G640x480x64K },
|
|
#endif
|
|
#ifdef G640x480x16M
|
|
{"640x480x16M", G640x480x16M },
|
|
#endif
|
|
#ifdef G640x480x16M32
|
|
{"640x480x16M32", G640x480x16M32 },
|
|
#endif
|
|
|
|
#ifdef G720x540x256
|
|
{"720x540x256", G720x540x256 },
|
|
#endif
|
|
#ifdef G720x540x32K
|
|
{"720x540x32K", G720x540x32K },
|
|
#endif
|
|
#ifdef G720x540x64K
|
|
{"720x540x64K", G720x540x64K },
|
|
#endif
|
|
#ifdef G720x540x16M
|
|
{"720x540x16M", G720x540x16M },
|
|
#endif
|
|
#ifdef G720x540x16M32
|
|
{"720x540x16M32", G720x540x16M32 },
|
|
#endif
|
|
|
|
#ifdef G800x600x16
|
|
{"800x600x16", G800x600x16 },
|
|
#endif
|
|
#ifdef G800x600x256
|
|
{"800x600x256", G800x600x256 },
|
|
#endif
|
|
#ifdef G800x600x32K
|
|
{"800x600x32K", G800x600x32K },
|
|
#endif
|
|
#ifdef G800x600x64K
|
|
{"800x600x64K", G800x600x64K },
|
|
#endif
|
|
#ifdef G800x600x16M
|
|
{"800x600x16M", G800x600x16M },
|
|
#endif
|
|
#ifdef G800x600x16M32
|
|
{"800x600x16M32", G800x600x16M32 },
|
|
#endif
|
|
|
|
#ifdef G848x480x256
|
|
{"848x480x256", G848x480x256 },
|
|
#endif
|
|
#ifdef G848x480x32K
|
|
{"848x480x32K", G848x480x32K },
|
|
#endif
|
|
#ifdef G848x480x64K
|
|
{"848x480x64K", G848x480x64K },
|
|
#endif
|
|
#ifdef G848x480x16M
|
|
{"848x480x16M", G848x480x16M },
|
|
#endif
|
|
#ifdef G848x480x16M32
|
|
{"848x480x16M32", G848x480x16M32 },
|
|
#endif
|
|
|
|
#ifdef G960x720x256
|
|
{"960x720x256", G960x720x256 },
|
|
#endif
|
|
#ifdef G960x720x32K
|
|
{"960x720x32K", G960x720x32K },
|
|
#endif
|
|
#ifdef G960x720x64K
|
|
{"960x720x64K", G960x720x64K },
|
|
#endif
|
|
#ifdef G960x720x16M
|
|
{"960x720x16M", G960x720x16M },
|
|
#endif
|
|
#ifdef G960x720x16M32
|
|
{"960x720x16M32", G960x720x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1024x768x16
|
|
{"1024x768x16", G1024x768x16 },
|
|
#endif
|
|
#ifdef G1024x768x256
|
|
{"1024x768x256", G1024x768x256 },
|
|
#endif
|
|
#ifdef G1024x768x32K
|
|
{"1024x768x32K", G1024x768x32K },
|
|
#endif
|
|
#ifdef G1024x768x64K
|
|
{"1024x768x64K", G1024x768x64K },
|
|
#endif
|
|
#ifdef G1024x768x16M
|
|
{"1024x768x16M", G1024x768x16M },
|
|
#endif
|
|
#ifdef G1024x768x16M32
|
|
{"1024x768x16M32", G1024x768x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1072x600x256
|
|
{"1072x600x256", G1072x600x256 },
|
|
#endif
|
|
#ifdef G1072x600x32K
|
|
{"1072x600x32K", G1072x600x32K },
|
|
#endif
|
|
#ifdef G1072x600x64K
|
|
{"1072x600x64K", G1072x600x64K },
|
|
#endif
|
|
#ifdef G1072x600x16M
|
|
{"1072x600x16M", G1072x600x16M },
|
|
#endif
|
|
#ifdef G1072x600x16M32
|
|
{"1072x600x16M32", G1072x600x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1152x864x16
|
|
{"1152x864x16", G1152x864x16 },
|
|
#endif
|
|
#ifdef G1152x864x256
|
|
{"1152x864x256", G1152x864x256 },
|
|
#endif
|
|
#ifdef G1152x864x32K
|
|
{"1152x864x32K", G1152x864x32K },
|
|
#endif
|
|
#ifdef G1152x864x64K
|
|
{"1152x864x64K", G1152x864x64K },
|
|
#endif
|
|
#ifdef G1152x864x16M
|
|
{"1152x864x16M", G1152x864x16M },
|
|
#endif
|
|
#ifdef G1152x864x16M32
|
|
{"1152x864x16M32", G1152x864x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1280x720x256
|
|
{"1280x720x256", G1280x720x256 },
|
|
#endif
|
|
#ifdef G1280x720x32K
|
|
{"1280x720x32K", G1280x720x32K },
|
|
#endif
|
|
#ifdef G1280x720x64K
|
|
{"1280x720x64K", G1280x720x64K },
|
|
#endif
|
|
#ifdef G1280x720x16M
|
|
{"1280x720x16M", G1280x720x16M },
|
|
#endif
|
|
#ifdef G1280x720x16M32
|
|
{"1280x720x16M32", G1280x720x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1280x1024x16
|
|
{"1280x1024x16", G1280x1024x16 },
|
|
#endif
|
|
#ifdef G1280x1024x256
|
|
{"1280x1024x256", G1280x1024x256 },
|
|
#endif
|
|
#ifdef G1280x1024x32K
|
|
{"1280x1024x32K", G1280x1024x32K },
|
|
#endif
|
|
#ifdef G1280x1024x64K
|
|
{"1280x1024x64K", G1280x1024x64K },
|
|
#endif
|
|
#ifdef G1280x1024x16M
|
|
{"1280x1024x16M", G1280x1024x16M },
|
|
#endif
|
|
#ifdef G1280x1024x16M32
|
|
{"1280x1024x16M32", G1280x1024x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1360x768x256
|
|
{"1360x768x256", G1360x768x256 },
|
|
#endif
|
|
#ifdef G1360x768x32K
|
|
{"1360x768x32K", G1360x768x32K },
|
|
#endif
|
|
#ifdef G1360x768x64K
|
|
{"1360x768x64K", G1360x768x64K },
|
|
#endif
|
|
#ifdef G1360x768x16M
|
|
{"1360x768x16M", G1360x768x16M },
|
|
#endif
|
|
#ifdef G1360x768x16M32
|
|
{"1360x768x16M32", G1360x768x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1600x1200x16
|
|
{"1600x1200x16", G1600x1200x16 },
|
|
#endif
|
|
#ifdef G1600x1200x256
|
|
{"1600x1200x256", G1600x1200x256 },
|
|
#endif
|
|
#ifdef G1600x1200x32K
|
|
{"1600x1200x32K", G1600x1200x32K },
|
|
#endif
|
|
#ifdef G1600x1200x64K
|
|
{"1600x1200x64K", G1600x1200x64K },
|
|
#endif
|
|
#ifdef G1600x1200x16M
|
|
{"1600x1200x16M", G1600x1200x16M },
|
|
#endif
|
|
#ifdef G1600x1200x16M32
|
|
{"1600x1200x16M32", G1600x1200x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1800x1012x256
|
|
{"1800x1012x256", G1800x1012x256 },
|
|
#endif
|
|
#ifdef G1800x1012x32K
|
|
{"1800x1012x32K", G1800x1012x32K },
|
|
#endif
|
|
#ifdef G1800x1012x64K
|
|
{"1800x1012x64K", G1800x1012x64K },
|
|
#endif
|
|
#ifdef G1800x1012x16M
|
|
{"1800x1012x16M", G1800x1012x16M },
|
|
#endif
|
|
#ifdef G1800x1012x16M32
|
|
{"1800x1012x16M32", G1800x1012x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1920x1080x256
|
|
{"1920x1080x256", G1920x1080x256 },
|
|
#endif
|
|
#ifdef G1920x1080x32K
|
|
{"1920x1080x32K", G1920x1080x32K },
|
|
#endif
|
|
#ifdef G1920x1080x64K
|
|
{"1920x1080x64K", G1920x1080x64K },
|
|
#endif
|
|
#ifdef G1920x1080x16M
|
|
{"1920x1080x16M", G1920x1080x16M },
|
|
#endif
|
|
#ifdef G1920x1080x16M32
|
|
{"1920x1080x16M32", G1920x1080x16M32 },
|
|
#endif
|
|
|
|
#ifdef G1920x1440x256
|
|
{"1920x1440x256", G1920x1440x256 },
|
|
#endif
|
|
#ifdef G1920x1440x32K
|
|
{"1920x1440x32K", G1920x1440x32K },
|
|
#endif
|
|
#ifdef G1920x1440x64K
|
|
{"1920x1440x64K", G1920x1440x64K },
|
|
#endif
|
|
#ifdef G1920x1440x16M
|
|
{"1920x1440x16M", G1920x1440x16M },
|
|
#endif
|
|
#ifdef G1920x1440x16M32
|
|
{"1920x1440x16M32", G1920x1440x16M32 },
|
|
#endif
|
|
|
|
#ifdef G2048x1152x256
|
|
{"2048x1152x256", G2048x1152x256 },
|
|
#endif
|
|
#ifdef G2048x1152x32K
|
|
{"2048x1152x32K", G2048x1152x32K },
|
|
#endif
|
|
#ifdef G2048x1152x64K
|
|
{"2048x1152x64K", G2048x1152x64K },
|
|
#endif
|
|
#ifdef G2048x1152x16M
|
|
{"2048x1152x16M", G2048x1152x16M },
|
|
#endif
|
|
#ifdef G2048x1152x16M32
|
|
{"2048x1152x16M32", G2048x1152x16M32 },
|
|
#endif
|
|
|
|
#ifdef G2048x1536x256
|
|
{"2048x1536x256", G2048x1536x256 },
|
|
#endif
|
|
#ifdef G2048x1536x32K
|
|
{"2048x1536x32K", G2048x1536x32K },
|
|
#endif
|
|
#ifdef G2048x1536x64K
|
|
{"2048x1536x64K", G2048x1536x64K },
|
|
#endif
|
|
#ifdef G2048x1536x16M
|
|
{"2048x1536x16M", G2048x1536x16M },
|
|
#endif
|
|
#ifdef G2048x1536x16M32
|
|
{"2048x1536x16M32", G2048x1536x16M32 },
|
|
#endif
|
|
|
|
};
|
|
|
|
#include "fbcommon.inc"
|
|
|
|
/*--------------------------- ROUTINES ---------------------------------------*/
|
|
|
|
/* Generates these palettes:
|
|
* 7 6 5 4 3 2 1 0
|
|
* +-----+-----+---+
|
|
* | R | G | B |
|
|
* +-----+-----+---+
|
|
*
|
|
*
|
|
* 3 2 1 0
|
|
* +-+---+-+
|
|
* |R| G |B|
|
|
* +-+---+-+
|
|
*/
|
|
|
|
static void show_mouse(void);
|
|
static void hide_mouse(void);
|
|
static void redraw_mouse(void);
|
|
|
|
/* We must perform a quirkafleg
|
|
* This is an empiric magic that ensures
|
|
* Good white purity
|
|
* Correct rounding and dithering prediction
|
|
* And this is the cabbala:
|
|
* 063 021 063
|
|
* 009 009 021
|
|
* 255 085 255
|
|
* 036 036 084
|
|
*/
|
|
static void generate_palette(struct irgb *palette)
|
|
{
|
|
int a;
|
|
unsigned active_colors = (int)vga_colors;
|
|
if ((svga_driver.depth & 0x300) == 0x300)
|
|
active_colors = 216;
|
|
|
|
for (a = 0; a < vga_colors; a++) {
|
|
q_palette(active_colors, (unsigned)a, (1U << palette_depth) - 1, palette[a].rgb);
|
|
}
|
|
}
|
|
|
|
static void set_palette(struct irgb *palette)
|
|
{
|
|
int r, g, b, c;
|
|
|
|
for (c = 0; c < vga_colors; c++) {
|
|
r = (int)palette[c].rgb[0];
|
|
g = (int)palette[c].rgb[1];
|
|
b = (int)palette[c].rgb[2];
|
|
vga_setpalette(c, r, g, b);
|
|
}
|
|
}
|
|
|
|
static void svga_shutdown_driver(void)
|
|
{
|
|
if (scroll_buffer) mem_free(scroll_buffer);
|
|
if (mouse_works){
|
|
mem_free(mouse_buffer);
|
|
mem_free(background_buffer);
|
|
mem_free(new_background_buffer);
|
|
svga_driver.shutdown_device(mouse_graphics_device);
|
|
mouse_close();
|
|
mouse_works=0; /* To keep vga_select disabled */
|
|
}
|
|
shutdown_virtual_devices();
|
|
vga_unlockvc();
|
|
#ifndef __SPAD__
|
|
kill_timer(svgalib_timer_id);
|
|
#endif
|
|
vga_setmode_retry:
|
|
if (vga_setmode(TEXT) < 0) {
|
|
if (out_of_memory(0, NULL, 0))
|
|
goto vga_setmode_retry;
|
|
fatal_exit("ERROR: vga_setmode failed");
|
|
}
|
|
svgalib_free_trm(svgalib_kbd);
|
|
if (svga_driver_param)mem_free(svga_driver_param);
|
|
install_signal_handler(SIGINT, NULL, NULL, 0);
|
|
}
|
|
|
|
static void svga_register_bitmap(struct bitmap *bmp)
|
|
{
|
|
}
|
|
|
|
static void svga_unregister_bitmap(struct bitmap *bmp)
|
|
{
|
|
mem_free(bmp->data);
|
|
}
|
|
|
|
#define SYNC if (do_sync) vga_accel(ACCEL_SYNC);
|
|
|
|
/* This assures that x, y, xs, ys, data will be sane according to clipping
|
|
* rectangle. If nothing lies within this rectangle, the current function
|
|
* returns. The data pointer is automatically advanced by this macro to reflect
|
|
* the right position to start with inside the bitmap. */
|
|
#define CLIP_PREFACE \
|
|
int xs, ys;\
|
|
unsigned char *data=bmp->data;\
|
|
int mouse_hidden;\
|
|
\
|
|
TEST_INACTIVITY\
|
|
CLIP_DRAW_BITMAP\
|
|
xs = bmp->x;\
|
|
ys = bmp->y;\
|
|
if (x+xs>dev->clip.x2) xs=dev->clip.x2-x;\
|
|
if (y+ys>dev->clip.y2) ys=dev->clip.y2-y;\
|
|
if (dev->clip.x1-x>0){\
|
|
xs-=(dev->clip.x1-x);\
|
|
data+=fb_pixelsize*(dev->clip.x1-x);\
|
|
x=dev->clip.x1;\
|
|
}\
|
|
if (dev->clip.y1-y>0){\
|
|
ys-=(dev->clip.y1-y);\
|
|
data+=bmp->skip*(dev->clip.y1-y);\
|
|
y=dev->clip.y1;\
|
|
}\
|
|
/* xs, ys: how much pixels to paint\
|
|
* data: where to start painting from\
|
|
*/\
|
|
TEST_MOUSE(x,x+xs,y,y+ys)
|
|
|
|
static inline void draw_bitmap_accel(struct graphics_device *dev,
|
|
struct bitmap *bmp, int x, int y)
|
|
{
|
|
CLIP_PREFACE
|
|
|
|
if (xs*fb_pixelsize==bmp->skip) vga_accel(ACCEL_PUTIMAGE,x,y,xs,ys,data);
|
|
else for(;ys;ys--){
|
|
vga_accel(ACCEL_PUTIMAGE,x,y,xs,1,data);
|
|
data+=bmp->skip;
|
|
y++;
|
|
}
|
|
END_MOUSE
|
|
}
|
|
|
|
static inline void my_setpage(int page)
|
|
{
|
|
if (vga_page!=page){
|
|
vga_page=page;
|
|
vga_setpage(page);
|
|
}
|
|
}
|
|
|
|
static inline void paged_memcpy(int lina, unsigned char *src, int len)
|
|
{
|
|
int page = lina >> 16;
|
|
int paga = lina & 0xffff;
|
|
int remains;
|
|
|
|
my_setpage(page);
|
|
remains = 65536 - paga;
|
|
again:
|
|
if (remains >= len) {
|
|
memcpy_to_fb_inline(my_graph_mem + paga, src, len, 0);
|
|
vga_page = page;
|
|
return;
|
|
}else{
|
|
memcpy_to_fb(my_graph_mem + paga, src, remains, 0);
|
|
paga = 0;
|
|
src += remains;
|
|
len -= remains;
|
|
remains = 65536;
|
|
vga_setpage(++page);
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
|
|
static inline void draw_bitmap_drawscansegment(struct graphics_device *dev, struct bitmap *bmp, int x, int y)
|
|
{
|
|
int ys0;
|
|
|
|
CLIP_PREFACE
|
|
SYNC
|
|
for (ys0=ys;ys0;ys0--){
|
|
vga_drawscansegment(data,x,y,xs);
|
|
y++;
|
|
data+=bmp->skip;
|
|
}
|
|
END_MOUSE
|
|
}
|
|
|
|
static inline void draw_bitmap_paged(struct graphics_device *dev, struct bitmap *bmp, int x, int y)
|
|
{
|
|
int scr_start;
|
|
size_t copy_len;
|
|
|
|
CLIP_PREFACE
|
|
SYNC
|
|
scr_start = y * vga_linewidth + x * vga_bytes;
|
|
copy_len = xs * fb_pixelsize;
|
|
for(; ys; ys--) {
|
|
paged_memcpy(scr_start, data, copy_len);
|
|
data += bmp->skip;
|
|
scr_start += vga_linewidth;
|
|
}
|
|
END_MOUSE
|
|
}
|
|
|
|
static inline void draw_bitmap_linear(struct graphics_device *dev,struct bitmap *bmp, int x, int y)
|
|
{
|
|
unsigned char *scr_start;
|
|
size_t copy_len;
|
|
|
|
CLIP_PREFACE
|
|
SYNC
|
|
scr_start = my_graph_mem + y * vga_linewidth + x * vga_bytes;
|
|
copy_len = xs * fb_pixelsize;
|
|
for (; ys; ys--) {
|
|
memcpy_to_fb_inline(scr_start, data, copy_len, 0);
|
|
data += bmp->skip;
|
|
scr_start += vga_linewidth;
|
|
}
|
|
END_MOUSE
|
|
}
|
|
|
|
/* fill_area: 5,5,10,10 fills in 25 pixels! */
|
|
|
|
/* This assures that x1, x2, y1, y2 will be sane according to the
|
|
* clipping rectangle set up by set_clip_area. If empty region
|
|
* results, return from current function occurs. */
|
|
#define FILL_CLIP_PREFACE \
|
|
int mouse_hidden;\
|
|
TEST_INACTIVITY\
|
|
CLIP_FILL_AREA\
|
|
TEST_MOUSE(x1,x2,y1,y2)
|
|
|
|
|
|
static void fill_area_accel_box(struct graphics_device *dev, int x1, int y1, int x2, int y2, long color)
|
|
{
|
|
FILL_CLIP_PREFACE
|
|
|
|
vga_accel(ACCEL_SETFGCOLOR,color);
|
|
vga_accel(ACCEL_FILLBOX,x1,y1,x2-x1,y2-y1);
|
|
END_MOUSE
|
|
}
|
|
|
|
static void fill_area_accel_lines(struct graphics_device *dev, int x1, int y1, int x2, int y2, long color)
|
|
{
|
|
int y;
|
|
|
|
FILL_CLIP_PREFACE
|
|
vga_accel(ACCEL_SETFGCOLOR,color);
|
|
for (y=y1;y<y2;y++) vga_accel(ACCEL_DRAWLINE,x1,y,x2-1,y);
|
|
END_MOUSE
|
|
}
|
|
|
|
static void fill_area_linear(struct graphics_device *dev, int x1, int y1, int x2, int y2, long color)
|
|
{
|
|
unsigned char *dest;
|
|
int y;
|
|
|
|
FILL_CLIP_PREFACE
|
|
SYNC
|
|
dest=my_graph_mem+y1*vga_linewidth+x1*vga_bytes;
|
|
for (y=y2-y1;y;y--){
|
|
pixel_set(dest,(x2-x1)*vga_bytes,&color);
|
|
dest+=vga_linewidth;
|
|
}
|
|
END_MOUSE
|
|
}
|
|
|
|
/* Params are exactly the same as in pixel_set except lina, which is offset from
|
|
* my_graph_mem in bytes. Works for every vga_bytes. len is in bytes. len must
|
|
* be a whole number of pixels.
|
|
*/
|
|
static void pixel_set_paged(int lina, int len, void * color)
|
|
{
|
|
int page=lina>>16; /* Page number */
|
|
int paga=lina&0xffff; /* 16-bit address within a page */
|
|
int remains=65536-paga; /* How many bytes remain within the page*/
|
|
int offset=0; /* Offset inside the pixel */
|
|
unsigned char color0[15];
|
|
|
|
memcpy(color0,color,vga_bytes);
|
|
memcpy(color0+vga_bytes,color,vga_bytes-1);
|
|
|
|
my_setpage(page);
|
|
again:
|
|
if (remains>=len){
|
|
int done=len-len%vga_bytes;
|
|
pixel_set(my_graph_mem+paga,done,color0+offset);
|
|
paga+=done;
|
|
if (done<len)
|
|
memcpy_to_fb(my_graph_mem+paga,color0+offset,len-done, 0);
|
|
vga_page=page;
|
|
return;
|
|
}else{
|
|
int done=remains-remains%vga_bytes;
|
|
pixel_set(my_graph_mem+paga,done,color0+offset);
|
|
paga+=done;
|
|
if (done<remains)
|
|
memcpy_to_fb(my_graph_mem+paga,color0+offset,remains-done, 0);
|
|
offset+=(remains-done);
|
|
if (offset>=vga_bytes) offset-=vga_bytes;
|
|
len-=remains;
|
|
remains=65536;
|
|
vga_setpage(++page);
|
|
paga=0;
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
static void fill_area_paged(struct graphics_device *dev, int x1, int y1, int x2, int y2, long color)
|
|
{
|
|
int dest;
|
|
int y;
|
|
int len;
|
|
FILL_CLIP_PREFACE
|
|
SYNC
|
|
len=(x2-x1)*vga_bytes;
|
|
dest=y1*vga_linewidth+x1*vga_bytes;
|
|
for (y=y2-y1;y;y--){
|
|
pixel_set_paged(dest,len,&color);
|
|
dest+=vga_linewidth;
|
|
}
|
|
END_MOUSE
|
|
}
|
|
|
|
#define HLINE_CLIP_PREFACE \
|
|
int mouse_hidden;\
|
|
TEST_INACTIVITY\
|
|
CLIP_DRAW_HLINE\
|
|
TEST_MOUSE(x1,x2,y,y+1)
|
|
|
|
#define VLINE_CLIP_PREFACE \
|
|
int mouse_hidden;\
|
|
TEST_INACTIVITY\
|
|
CLIP_DRAW_VLINE\
|
|
TEST_MOUSE(x,x+1,y1,y2)
|
|
|
|
static void draw_hline_accel_line(struct graphics_device *dev, int x1, int y, int x2, long color)
|
|
{
|
|
HLINE_CLIP_PREFACE
|
|
|
|
vga_accel(ACCEL_SETFGCOLOR,color);
|
|
vga_accel(ACCEL_DRAWLINE,x1,y,x2-1,y);
|
|
END_MOUSE
|
|
}
|
|
|
|
static void draw_hline_accel_box(struct graphics_device *dev, int x1, int y, int x2, long color)
|
|
{
|
|
HLINE_CLIP_PREFACE
|
|
|
|
vga_accel(ACCEL_SETFGCOLOR,color);
|
|
vga_accel(ACCEL_FILLBOX,x1,y,x2-x1,1);
|
|
END_MOUSE
|
|
}
|
|
|
|
static void draw_vline_accel_line(struct graphics_device *dev, int x, int y1, int y2, long color)
|
|
{
|
|
VLINE_CLIP_PREFACE
|
|
|
|
vga_accel(ACCEL_SETFGCOLOR,color);
|
|
vga_accel(ACCEL_DRAWLINE,x,y1,x,y2-1);
|
|
END_MOUSE
|
|
}
|
|
|
|
static void draw_vline_accel_box(struct graphics_device *dev, int x, int y1, int y2, long color)
|
|
{
|
|
VLINE_CLIP_PREFACE
|
|
|
|
vga_accel(ACCEL_SETFGCOLOR,color);
|
|
vga_accel(ACCEL_FILLBOX,x,y1,1,y2-y1);
|
|
END_MOUSE
|
|
}
|
|
|
|
static void draw_hline_linear(struct graphics_device *dev, int x1, int y, int x2, long color)
|
|
{
|
|
unsigned char *dest;
|
|
HLINE_CLIP_PREFACE
|
|
SYNC
|
|
dest=my_graph_mem+y*vga_linewidth+x1*vga_bytes;
|
|
pixel_set(dest,(x2-x1)*vga_bytes,&color);
|
|
END_MOUSE
|
|
}
|
|
|
|
static void draw_vline_linear(struct graphics_device *dev, int x, int y1, int y2, long color)
|
|
{
|
|
unsigned char *dest;
|
|
int y;
|
|
VLINE_CLIP_PREFACE
|
|
SYNC
|
|
dest=my_graph_mem+y1*vga_linewidth+x*vga_bytes;
|
|
for (y=(y2-y1);y;y--){
|
|
memcpy_to_fb(dest, (unsigned char *)&color, vga_bytes, 0);
|
|
dest+=vga_linewidth;
|
|
}
|
|
END_MOUSE
|
|
}
|
|
|
|
static void draw_hline_paged(struct graphics_device *dev, int x1, int y, int x2, long color)
|
|
{
|
|
int dest;
|
|
int len;
|
|
HLINE_CLIP_PREFACE
|
|
SYNC
|
|
len=(x2-x1)*vga_bytes;
|
|
|
|
dest=y*vga_linewidth+x1*vga_bytes;
|
|
pixel_set_paged(dest,len,&color);
|
|
END_MOUSE
|
|
}
|
|
|
|
/* Works only for pixel length = 1 */
|
|
static void draw_vline_paged_1(struct graphics_device *dev, int x, int y1, int y2, long color)
|
|
{
|
|
int dest,n, page,paga,remains;
|
|
int byte=*(unsigned char *)&color;
|
|
VLINE_CLIP_PREFACE;
|
|
SYNC
|
|
dest=y1*vga_linewidth+x;
|
|
n=y2-y1;
|
|
page=dest>>16;
|
|
my_setpage(page);
|
|
again:
|
|
paga=dest&0xffff;
|
|
remains=(65535-paga)/vga_linewidth+1;
|
|
if (remains>=n){
|
|
for (;n;n--){
|
|
my_graph_mem[paga]=byte;
|
|
paga+=vga_linewidth;
|
|
}
|
|
vga_page=page;
|
|
END_MOUSE
|
|
return;
|
|
}else{
|
|
dest+=remains*vga_linewidth;
|
|
n-=remains;
|
|
for (;remains;remains--){
|
|
my_graph_mem[paga]=byte;
|
|
paga+=vga_linewidth;
|
|
}
|
|
vga_setpage(++page);
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
#ifdef t2c
|
|
/* Works only for pixel length 2 */
|
|
static void draw_vline_paged_2(struct graphics_device *dev, int x, int y1, int y2, long color)
|
|
{
|
|
int dest,page,n,paga,remains;
|
|
int word=*(t2c *)memory_barrier((void *)&color);
|
|
VLINE_CLIP_PREFACE;
|
|
SYNC
|
|
dest=y1*vga_linewidth+(x<<1);
|
|
n=y2-y1;
|
|
page=dest>>16;
|
|
my_setpage(page);
|
|
again:
|
|
paga=dest&0xffff;
|
|
remains=(65534-paga)/vga_linewidth+1;
|
|
if (remains>=n){
|
|
for (;n;n--){
|
|
*(t2c *)(my_graph_mem+paga)=word;
|
|
paga+=vga_linewidth;
|
|
}
|
|
vga_page=page;
|
|
END_MOUSE
|
|
return;
|
|
}else{
|
|
dest+=remains*vga_linewidth;
|
|
n-=remains;
|
|
for (;remains;remains--){
|
|
*(t2c *)(my_graph_mem+paga)=word;
|
|
paga+=vga_linewidth;
|
|
}
|
|
vga_setpage(++page);
|
|
goto again;
|
|
}
|
|
}
|
|
#endif /* #ifdef t2c */
|
|
|
|
#ifdef t4c
|
|
/* Works only for pixel length 4 */
|
|
static void draw_vline_paged_4(struct graphics_device *dev, int x, int y1, int y2, long color)
|
|
{
|
|
unsigned long dest,page,paga,remains,n;
|
|
t4c val=*(t4c *)memory_barrier((void *)&color);
|
|
|
|
VLINE_CLIP_PREFACE;
|
|
SYNC
|
|
dest=y1*(unsigned long)vga_linewidth+(x<<2);
|
|
n=y2-y1;
|
|
page=dest>>16;
|
|
my_setpage(page);
|
|
again:
|
|
paga=dest&0xffffUL;
|
|
remains=(65532-paga)/vga_linewidth+1;
|
|
if (remains>=n){
|
|
for (;n;n--){
|
|
*(t4c *)(my_graph_mem+paga)=val;
|
|
paga+=vga_linewidth;
|
|
}
|
|
vga_page=page;
|
|
END_MOUSE
|
|
return;
|
|
}else{
|
|
dest+=remains*vga_linewidth;
|
|
n-=remains;
|
|
for (;remains;remains--){
|
|
*(t4c *)(my_graph_mem+paga)=color;
|
|
paga+=vga_linewidth;
|
|
}
|
|
vga_setpage(++page);
|
|
goto again;
|
|
}
|
|
}
|
|
#endif /*t4c*/
|
|
|
|
/* Works only for pixel lengths power of two */
|
|
static void draw_vline_paged_aligned(struct graphics_device *dev, int x, int y1, int y2, long color)
|
|
{
|
|
int dest,page,paga,remains,n;
|
|
VLINE_CLIP_PREFACE;
|
|
SYNC
|
|
dest=y1*vga_linewidth+x*vga_bytes;
|
|
n=y2-y1;
|
|
page=dest>>16;
|
|
my_setpage(page);
|
|
again:
|
|
paga=dest&0xffff;
|
|
remains=(65536-paga-vga_bytes)/vga_linewidth+1;
|
|
if (remains >= n){
|
|
for (; n; n--){
|
|
memcpy_to_fb(my_graph_mem + paga, (unsigned char *)&color, vga_bytes, 0);
|
|
paga += vga_linewidth;
|
|
}
|
|
vga_page = page;
|
|
END_MOUSE
|
|
return;
|
|
}else{
|
|
dest += remains * vga_linewidth;
|
|
n -= remains;
|
|
for (; remains; remains--) {
|
|
memcpy_to_fb(my_graph_mem + paga, (unsigned char *)&color, vga_bytes, 0);
|
|
paga += vga_linewidth;
|
|
}
|
|
vga_setpage(++page);
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
/* Works for any pixel length */
|
|
static void draw_vline_paged(struct graphics_device *dev, int x, int y1, int y2, long color)
|
|
{
|
|
int lina,page,paga,remains,n;
|
|
/* lina: linear address withing the screen
|
|
* page: page number
|
|
* paga: 16-bit address within the page
|
|
* remains: how many bytes remain in the current page
|
|
* n: how many pixels remain to be drawn
|
|
*/
|
|
VLINE_CLIP_PREFACE;
|
|
SYNC
|
|
lina=y1*vga_linewidth+x*vga_bytes;
|
|
n=y2-y1;
|
|
page=lina>>16;
|
|
my_setpage(page);
|
|
again:
|
|
/* Invariant here: n>=1
|
|
* lina points to a begin of pixel
|
|
* page is set to page
|
|
*/
|
|
paga=lina&0xffff;
|
|
remains=65536-paga;
|
|
if (remains<vga_bytes){
|
|
memcpy_to_fb(my_graph_mem + paga, (unsigned char *)&color, remains, 0);
|
|
vga_setpage(++page);
|
|
memcpy_to_fb(my_graph_mem, (unsigned char *)&color + remains, vga_bytes - remains, 0);
|
|
lina+=vga_linewidth;
|
|
n--;
|
|
if (!n) goto end;
|
|
goto again;
|
|
}
|
|
remains=(remains-vga_bytes)/vga_linewidth+1;
|
|
if (remains>=n){
|
|
for (;n;n--){
|
|
memcpy_to_fb(my_graph_mem + paga, (unsigned char *)&color, vga_bytes, 0);
|
|
paga+=vga_linewidth;
|
|
}
|
|
end:
|
|
vga_page=page;
|
|
END_MOUSE
|
|
return;
|
|
}else{
|
|
lina+=remains*vga_linewidth;
|
|
n-=remains;
|
|
for (;remains;remains--){
|
|
memcpy_to_fb(my_graph_mem + paga, (unsigned char *)&color, vga_bytes, 0);
|
|
paga+=vga_linewidth;
|
|
}
|
|
if (paga>=65536)vga_setpage(++page);
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
#define SCROLL_CLIP_PREFACE \
|
|
int mouse_hidden;\
|
|
TEST_INACTIVITY_0\
|
|
TEST_MOUSE(dev->clip.x1, dev->clip.x2, dev->clip.y1, dev->clip.y2)
|
|
|
|
|
|
/* When scx is <0, moves the data x1. Scrolls the whole clip window */
|
|
static int scroll_accel(struct graphics_device *dev, struct rect_set **ignore, int scx, int scy)
|
|
{
|
|
SCROLL_CLIP_PREFACE
|
|
|
|
vga_accel(ACCEL_SCREENCOPY,
|
|
dev->clip.x1 - (scx < 0 ? scx : 0),
|
|
dev->clip.y1 - (scy < 0 ? scy : 0),
|
|
dev->clip.x1 + (scx >= 0 ? scx : 0),
|
|
dev->clip.y1 + (scy >= 0 ? scy : 0),
|
|
dev->clip.x2 - dev->clip.x1 - abs(scx),
|
|
dev->clip.y2 - dev->clip.y1 - abs(scy));
|
|
|
|
END_MOUSE
|
|
return 1;
|
|
}
|
|
|
|
static int scroll_scansegment(struct graphics_device *dev, struct rect_set **ignore, int scx, int scy)
|
|
{
|
|
int y, len, x_src, x_dest;
|
|
SCROLL_CLIP_PREFACE
|
|
SYNC
|
|
len = dev->clip.x2 - dev->clip.x1 - abs(scx);
|
|
x_src = dev->clip.x1 - (scx < 0 ? scx : 0);
|
|
x_dest = dev->clip.x1 + (scx >= 0 ? scx : 0);
|
|
if (scy > 0) {
|
|
/* Down */
|
|
for (y = dev->clip.y2 - 1; y >= dev->clip.y1 + scy; y--) {
|
|
vga_getscansegment(scroll_buffer, x_src, y - scy, len);
|
|
vga_drawscansegment(scroll_buffer, x_dest, y, len);
|
|
}
|
|
} else {
|
|
/* Up */
|
|
for (y = dev->clip.y1 - scy; y < dev->clip.y2; y++) {
|
|
vga_getscansegment(scroll_buffer, x_src, y, len);
|
|
vga_drawscansegment(scroll_buffer, x_dest, y + scy, len);
|
|
}
|
|
}
|
|
END_MOUSE
|
|
return 1;
|
|
}
|
|
|
|
static int scroll_linear(struct graphics_device *dev, struct rect_set **ignore, int scx, int scy)
|
|
{
|
|
unsigned char *dest, *src;
|
|
int y, len, dest_off, src_off;
|
|
SCROLL_CLIP_PREFACE
|
|
SYNC
|
|
if (scx >= 0) {
|
|
len = (dev->clip.x2 - dev->clip.x1 - scx) * vga_bytes;
|
|
dest_off = scx * vga_bytes;
|
|
src_off = 0;
|
|
} else {
|
|
len = (dev->clip.x2 - dev->clip.x1 + scx) * vga_bytes;
|
|
dest_off = 0;
|
|
src_off = -scx * vga_bytes;
|
|
}
|
|
|
|
if (scy > 0) {
|
|
/* Down */
|
|
dest = my_graph_mem + (dev->clip.y2 - 1) * vga_linewidth + dev->clip.x1 * vga_bytes;
|
|
src = dest - vga_linewidth * scy;
|
|
dest += dest_off;
|
|
src += src_off;
|
|
for (y = dev->clip.y2 - dev->clip.y1 - scy; y; y--) {
|
|
memcpy_to_fb(dest, src, len, 1);
|
|
dest -= vga_linewidth;
|
|
src -= vga_linewidth;
|
|
}
|
|
} else {
|
|
/* Up */
|
|
dest = my_graph_mem + dev->clip.y1 * vga_linewidth + dev->clip.x1 * vga_bytes;
|
|
src = dest - vga_linewidth * scy;
|
|
dest += dest_off;
|
|
src += src_off;
|
|
for (y = dev->clip.y2 - dev->clip.y1 + scy; y; y--) {
|
|
if (scy)
|
|
memcpy_to_fb(dest, src, len, 1);
|
|
else
|
|
memmove_in_fb(dest, src, len);
|
|
dest += vga_linewidth;
|
|
src += vga_linewidth;
|
|
}
|
|
}
|
|
END_MOUSE
|
|
return 1;
|
|
}
|
|
|
|
static inline void get_row(unsigned char *bptr, int lina, int len)
|
|
{
|
|
int page=lina>>16;
|
|
int paga=lina&0xffff;
|
|
int remains;
|
|
|
|
my_setpage(page);
|
|
remains=65536-paga;
|
|
again:
|
|
if (remains>=len){
|
|
memcpy(bptr,my_graph_mem+paga,len);
|
|
vga_page=page;
|
|
return;
|
|
}else{
|
|
memcpy(bptr,my_graph_mem+paga,remains);
|
|
paga=0;
|
|
bptr+=remains;
|
|
len-=remains;
|
|
remains=65536;
|
|
vga_setpage(++page);
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
static int scroll_paged(struct graphics_device *dev, struct rect_set **ignore, int scx, int scy)
|
|
{
|
|
int dest, src, y, len, dest_off, src_off;
|
|
SCROLL_CLIP_PREFACE
|
|
SYNC
|
|
if (scx >= 0) {
|
|
len = (dev->clip.x2 - dev->clip.x1 - scx) * vga_bytes;
|
|
dest_off = scx * vga_bytes;
|
|
src_off = 0;
|
|
} else {
|
|
len = (dev->clip.x2 - dev->clip.x1 + scx) * vga_bytes;
|
|
dest_off = 0;
|
|
src_off = -scx * vga_bytes;
|
|
}
|
|
if (scy > 0) {
|
|
/* Down */
|
|
dest = (dev->clip.y2 - 1) * vga_linewidth + dev->clip.x1 * vga_bytes;
|
|
src = dest - vga_linewidth * scy;
|
|
dest += dest_off;
|
|
src += src_off;
|
|
for (y = dev->clip.y2 - dev->clip.y1 - scy; y; y--) {
|
|
get_row(scroll_buffer, src, len);
|
|
paged_memcpy(dest, scroll_buffer, len);
|
|
dest -= vga_linewidth;
|
|
src -= vga_linewidth;
|
|
}
|
|
} else {
|
|
/* Up */
|
|
dest = dev->clip.y1 * vga_linewidth + dev->clip.x1 * vga_bytes;
|
|
src = dest - vga_linewidth * scy;
|
|
dest += dest_off;
|
|
src += src_off;
|
|
for (y = dev->clip.y2 - dev->clip.y1 + scy; y; y--) {
|
|
get_row(scroll_buffer, src, len);
|
|
paged_memcpy(dest, scroll_buffer, len);
|
|
dest += vga_linewidth;
|
|
src += vga_linewidth;
|
|
}
|
|
}
|
|
END_MOUSE
|
|
return 1;
|
|
}
|
|
|
|
/* For modes where video memory is not directly accessible through svgalib */
|
|
static inline void fill_area_drawscansegment(struct graphics_device *dev, int x1, int y1, int x2, int y2, long color)
|
|
{
|
|
int xs;
|
|
int col=*(unsigned char *)&color;
|
|
|
|
FILL_CLIP_PREFACE
|
|
SYNC
|
|
xs=x2-x1;
|
|
memset(scroll_buffer,col,xs);
|
|
for (;y1<y2;y1++){
|
|
vga_drawscansegment(scroll_buffer,x1,y1,xs);
|
|
}
|
|
END_MOUSE
|
|
}
|
|
|
|
/* Emulates horizontal line by calling fill_area */
|
|
static void draw_hline_fill_area(struct graphics_device *dev, int x1, int y, int x2, long color)
|
|
{
|
|
svga_driver.fill_area(dev,x1,y,x2,y+1,color);
|
|
}
|
|
|
|
|
|
/* Emulates vline by fill_area */
|
|
static void draw_vline_fill_area(struct graphics_device *dev, int x, int y1, int y2, long color)
|
|
{
|
|
svga_driver.fill_area(dev,x,y1,x+1,y2, color);
|
|
}
|
|
|
|
/* This does no clipping and is used only by the mouse code
|
|
* length is in bytes, not in pixels
|
|
*/
|
|
static int drawscansegment_linear(unsigned char *colors, int x, int y, int length)
|
|
{
|
|
unsigned char *ptr = my_graph_mem + vga_linewidth * y + vga_bytes * x;
|
|
|
|
memcpy_to_fb(ptr, colors, length, 0);
|
|
return 0;
|
|
}
|
|
|
|
/* This does no clipping and is used only by the mouse code
|
|
* length is in bytes, not in pixels
|
|
*/
|
|
static int getscansegment_linear(unsigned char *colors, int x, int y, int length)
|
|
{
|
|
unsigned char *ptr = my_graph_mem + vga_linewidth * y + vga_bytes*x;
|
|
|
|
memcpy_to_fb(colors, ptr, length, 1);
|
|
return 0;
|
|
}
|
|
|
|
/* This does no clipping and is used only by the mouse code
|
|
* length is in bytes, not in pixels
|
|
*/
|
|
static int drawscansegment_paged(unsigned char *colors, int x, int y, int length)
|
|
{
|
|
int lina = vga_linewidth * y + vga_bytes * x;
|
|
|
|
paged_memcpy(lina, colors, length);
|
|
return 0;
|
|
}
|
|
|
|
/* This does no clipping and is used only by the mouse code
|
|
* length is in the bytes, not in pixels
|
|
*/
|
|
static int getscansegment_paged(unsigned char *colors, int x, int y, int length)
|
|
{
|
|
int lina=vga_linewidth*y+vga_bytes*x;
|
|
|
|
get_row(colors, lina, length);
|
|
return 0;
|
|
}
|
|
|
|
static void alloc_scroll_buffer(void)
|
|
{
|
|
if (!scroll_buffer) {
|
|
if ((unsigned)xsize > (unsigned)MAXINT / fb_pixelsize) overalloc();
|
|
scroll_buffer=mem_alloc(xsize*fb_pixelsize);
|
|
}
|
|
}
|
|
|
|
static void setup_functions(void)
|
|
{
|
|
svga_driver.flags &= ~GD_DONT_USE_SCROLL;
|
|
|
|
if (accel_avail&ACCELFLAG_SETMODE){
|
|
do_sync=1;
|
|
vga_accel(ACCEL_SETMODE, BLITS_IN_BACKGROUND);
|
|
}else do_sync=0;
|
|
|
|
svga_driver.get_color = get_color_fn(svga_driver.depth);
|
|
if (!svga_driver.get_color) internal_error("Unknown bit depth %x", svga_driver.depth);
|
|
switch (vga_colors) {
|
|
case 2:
|
|
internal_error("2-color modes are not supported by links as they are buggy in svgalib and incapable of colors");
|
|
|
|
case 16:
|
|
alloc_scroll_buffer();
|
|
svga_driver.draw_bitmap = draw_bitmap_drawscansegment;
|
|
svga_driver.scroll = scroll_scansegment;
|
|
svga_driver.flags |= GD_DONT_USE_SCROLL;
|
|
svga_driver.fill_area = fill_area_drawscansegment;
|
|
svga_driver.draw_hline = draw_hline_fill_area;
|
|
svga_driver.draw_vline = draw_vline_fill_area;
|
|
mouse_getscansegment = vga_getscansegment;
|
|
mouse_drawscansegment = vga_drawscansegment;
|
|
break;
|
|
|
|
default:
|
|
mouse_getscansegment = vga_getscansegment;
|
|
mouse_drawscansegment = vga_drawscansegment;
|
|
if (accel_avail & ACCELFLAG_PUTIMAGE) {
|
|
svga_driver.draw_bitmap = draw_bitmap_accel;
|
|
} else if (vga_linear) {
|
|
svga_driver.draw_bitmap = draw_bitmap_linear;
|
|
} else if (mode_x) {
|
|
svga_driver.draw_bitmap = draw_bitmap_drawscansegment;
|
|
} else {
|
|
svga_driver.draw_bitmap = draw_bitmap_paged;
|
|
}
|
|
|
|
if (accel_avail & ACCELFLAG_FILLBOX) svga_driver.fill_area = fill_area_accel_box;
|
|
else if (accel_avail & ACCELFLAG_DRAWLINE) svga_driver.fill_area = fill_area_accel_lines;
|
|
else if (vga_linear) svga_driver.fill_area = fill_area_linear;
|
|
else if (mode_x) svga_driver.fill_area = fill_area_drawscansegment;
|
|
else svga_driver.fill_area = fill_area_paged;
|
|
|
|
if (accel_avail & ACCELFLAG_DRAWLINE) {
|
|
svga_driver.draw_hline = draw_hline_accel_line;
|
|
svga_driver.draw_vline = draw_vline_accel_line;
|
|
} else if (accel_avail & ACCELFLAG_FILLBOX) {
|
|
svga_driver.draw_hline = draw_hline_accel_box;
|
|
svga_driver.draw_vline = draw_vline_accel_box;
|
|
} else if (vga_linear) {
|
|
svga_driver.draw_hline = draw_hline_linear;
|
|
svga_driver.draw_vline = draw_vline_linear;
|
|
} else if (mode_x) {
|
|
svga_driver.draw_hline = draw_hline_fill_area;
|
|
svga_driver.draw_vline = draw_vline_fill_area;
|
|
} else {
|
|
/* Paged memory access */
|
|
svga_driver.draw_hline = draw_hline_paged;
|
|
switch (vga_bytes)
|
|
{
|
|
case 1:
|
|
svga_driver.draw_vline = draw_vline_paged_1;
|
|
break;
|
|
#ifdef t2c
|
|
case 2:
|
|
svga_driver.draw_vline = draw_vline_paged_2;
|
|
break;
|
|
#endif /* #ifdef t2c */
|
|
|
|
#ifdef t4c
|
|
case 4:
|
|
svga_driver.draw_vline = draw_vline_paged_4;
|
|
break;
|
|
#endif /* #ifdef t4c */
|
|
|
|
default:
|
|
if (vga_bytes & (vga_bytes - 1))
|
|
svga_driver.draw_vline = draw_vline_paged;
|
|
else
|
|
svga_driver.draw_vline = draw_vline_paged_aligned;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (vga_colors >= 256) {
|
|
if (vga_linear) {
|
|
mouse_drawscansegment = drawscansegment_linear;
|
|
mouse_getscansegment = getscansegment_linear;
|
|
} else if (!mode_x) {
|
|
mouse_drawscansegment = drawscansegment_paged;
|
|
mouse_getscansegment = getscansegment_paged;
|
|
}
|
|
}
|
|
|
|
if (accel_avail & ACCELFLAG_SCREENCOPY) {
|
|
svga_driver.scroll = scroll_accel;
|
|
} else if (vga_linear) {
|
|
svga_driver.scroll = scroll_linear;
|
|
svga_driver.flags |= GD_DONT_USE_SCROLL;
|
|
} else if (mode_x) {
|
|
alloc_scroll_buffer();
|
|
svga_driver.scroll = scroll_scansegment;
|
|
svga_driver.flags |= GD_DONT_USE_SCROLL;
|
|
} else {
|
|
alloc_scroll_buffer();
|
|
svga_driver.scroll = scroll_paged;
|
|
svga_driver.flags |= GD_DONT_USE_SCROLL;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#if 0
|
|
void dump_mode_info_into_file(vga_modeinfo* i)
|
|
{
|
|
FILE *f;
|
|
|
|
f=fopen(".links_svga_modeinfo","w");
|
|
if (!f) return;
|
|
fprintf(f,"Resolution %d*%d\n",i->width,i->height);
|
|
fprintf(f,"%d bytes per screen pixel\n",i->bytesperpixel);
|
|
fprintf(f,"%d colors\n",i->colors);
|
|
fprintf(f,"Linewidth %d bytes\n",i->linewidth);
|
|
fprintf(f,"Maximum logical width %d bytes\n",i->maxlogicalwidth);
|
|
fprintf(f,"Start address rangemask 0x%x\n",i->startaddressrange);
|
|
fprintf(f,"Max. pixels per logical screen %d\n",i->maxpixels);
|
|
fprintf(f,"bitblt %s\n",i->haveblit&HAVE_BITBLIT?"yes":"no");
|
|
fprintf(f,"fillblt %s\n",i->haveblit&HAVE_FILLBLIT?"yes":"no");
|
|
fprintf(f,"imageblt %s\n",i->haveblit&HAVE_IMAGEBLIT?"yes":"no");
|
|
fprintf(f,"hlinelistblt %s\n",i->haveblit&HAVE_HLINELISTBLIT?"yes":"no");
|
|
fprintf(f,"read/write page %s\n",i->flags&HAVE_RWPAGE?"yes":"no");
|
|
fprintf(f,"Interlaced %s\n",i->flags&IS_INTERLACED?"yes":"no");
|
|
fprintf(f,"Mode X layout %s\n",i->flags&IS_MODEX?"yes":"no");
|
|
fprintf(f,"Dynamically loaded %s\n",i->flags&IS_DYNAMICMODE?"yes":"no");
|
|
fprintf(f,"Linear: %s\n",vga_linear?"yes":"no");
|
|
fprintf(f,"Misordered %s\n",i->flags&RGB_MISORDERED?"yes":"no");
|
|
if (!i->flags&EXT_INFO_AVAILABLE){
|
|
fprintf(f,"Old svgalib, extended info is not available\n");
|
|
}else{
|
|
fprintf(f,"Chiptype 0x%x\n",i->chiptype);
|
|
fprintf(f,"Memory %dKB\n",i->memory);
|
|
fprintf(f,"Linewidth Unit %d\n",i->linewidth_unit);
|
|
fprintf(f,"Aperture size %d\n",i->aperture_size);
|
|
}
|
|
fprintf(f,"Accelerated putimage: %s\n",svga_driver.draw_bitmap==draw_bitmap_accel?"yes":"no");
|
|
fclose(f);
|
|
}
|
|
#endif
|
|
|
|
static void svgalib_key_in(struct itrm *p, unsigned char *ev_, int size)
|
|
{
|
|
struct links_event *ev = (struct links_event *)(void *)ev_;
|
|
if (size != sizeof(struct links_event)) return;
|
|
if (ev->ev == EV_ABORT) terminate_loop = 1;
|
|
if (ev->ev != EV_KBD) return;
|
|
if (ev->y & KBD_PASTING) goto skip;
|
|
if ((ev->y & (KBD_CTRL | KBD_ALT)) == KBD_ALT && ev->x >= '0' && ev->x <= '9') {
|
|
switch_virtual_device((ev->x - '1' + 10) % 10);
|
|
return;
|
|
}
|
|
skip:
|
|
if (g_kbd_codepage(&svga_driver) != utf8_table && ev->x >= 128 && ev->x <= 255)
|
|
if ((ev->x = cp2u(ev->x, g_kbd_codepage(&svga_driver))) == -1) return;
|
|
if (current_virtual_device && current_virtual_device->keyboard_handler) current_virtual_device->keyboard_handler(current_virtual_device, ev->x, ev->y);
|
|
}
|
|
|
|
#ifndef MOUSE_FOURTHBUTTON
|
|
#define MOUSE_FOURTHBUTTON 0
|
|
#endif
|
|
|
|
#ifndef MOUSE_FIFTHBUTTON
|
|
#define MOUSE_FIFTHBUTTON 0
|
|
#endif
|
|
|
|
#ifndef MOUSE_SIXTHBUTTON
|
|
#define MOUSE_SIXTHBUTTON 0
|
|
#endif
|
|
|
|
#define BUTTON_MASK (MOUSE_RIGHTBUTTON | MOUSE_MIDDLEBUTTON | MOUSE_LEFTBUTTON | MOUSE_FOURTHBUTTON | MOUSE_FIFTHBUTTON /*| MOUSE_SIXTHBUTTON*/)
|
|
|
|
static inline void mouse_aggregate_flush(void)
|
|
{
|
|
if (!mouse_aggregate_flag) return;
|
|
mouse_aggregate_flag=0;
|
|
if (current_virtual_device && current_virtual_device->mouse_handler) current_virtual_device->mouse_handler(current_virtual_device, mouse_x, mouse_y, mouse_aggregate_action);
|
|
}
|
|
|
|
/* Only calls appropriate callbacks, doesn't draw anything. */
|
|
#ifdef HAVE_MOUSE_GETPOSITION_6D
|
|
static void mouse_event_handler(int button, int dx, int dy, int dz, int drx, int dry, int drz)
|
|
{
|
|
#else
|
|
static void mouse_event_handler(int button, int dx, int dy)
|
|
{
|
|
int drx = 0, dry = 0;
|
|
#endif
|
|
int moved, old_mouse_x, old_mouse_y;
|
|
void (*mh)(struct graphics_device *, int, int, int);
|
|
struct graphics_device *cd = current_virtual_device;
|
|
|
|
mh = cd ? cd->mouse_handler : (void(*)(struct graphics_device *dev, int x, int y, int buttons))NULL;
|
|
old_mouse_x = mouse_x;
|
|
old_mouse_y = mouse_y;
|
|
|
|
mouse_x += dx;
|
|
if (mouse_x >= xsize) mouse_x = xsize - 1;
|
|
else if (mouse_x < 0) mouse_x = 0;
|
|
|
|
mouse_y += dy;
|
|
if (mouse_y >= ysize) mouse_y = ysize - 1;
|
|
else if (mouse_y < 0) mouse_y = 0;
|
|
|
|
redraw_mouse();
|
|
|
|
moved = (old_mouse_x != mouse_x || old_mouse_y != mouse_y);
|
|
|
|
/* Test movement without buttons */
|
|
if (!(mouse_buttons & BUTTON_MASK) && moved) {
|
|
mouse_aggregate_flag=1;
|
|
mouse_aggregate_action=B_MOVE;
|
|
}
|
|
|
|
/* Test presses */
|
|
if ((button&MOUSE_LEFTBUTTON)&&!(mouse_buttons&MOUSE_LEFTBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_LEFT|B_DOWN);
|
|
}
|
|
if ((button&MOUSE_MIDDLEBUTTON)&&!(mouse_buttons&MOUSE_MIDDLEBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_MIDDLE|B_DOWN);
|
|
}
|
|
if ((button&MOUSE_RIGHTBUTTON)&&!(mouse_buttons&MOUSE_RIGHTBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_RIGHT|B_DOWN);
|
|
}
|
|
if ((button&MOUSE_FOURTHBUTTON)&&!(mouse_buttons&MOUSE_FOURTHBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_FOURTH|B_DOWN);
|
|
}
|
|
if ((button&MOUSE_FIFTHBUTTON)&&!(mouse_buttons&MOUSE_FIFTHBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_FIFTH|B_DOWN);
|
|
}
|
|
if ((button&MOUSE_SIXTHBUTTON)&&!(mouse_buttons&MOUSE_SIXTHBUTTON)){
|
|
mouse_aggregate_flush();
|
|
/*if (mh) mh(cd,mouse_x, mouse_y,B_SIXTH|B_DOWN);*/
|
|
switch_virtual_device(VD_NEXT);
|
|
}
|
|
|
|
/* Test releases */
|
|
if (!(button&MOUSE_LEFTBUTTON)&&(mouse_buttons&MOUSE_LEFTBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_LEFT|B_UP);
|
|
}
|
|
if (!(button&MOUSE_MIDDLEBUTTON)&&(mouse_buttons&MOUSE_MIDDLEBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_MIDDLE|B_UP);
|
|
}
|
|
if (!(button&MOUSE_RIGHTBUTTON)&&(mouse_buttons&MOUSE_RIGHTBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_RIGHT|B_UP);
|
|
}
|
|
if (!(button&MOUSE_FOURTHBUTTON)&&(mouse_buttons&MOUSE_FOURTHBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_FOURTH|B_UP);
|
|
}
|
|
if (!(button&MOUSE_FIFTHBUTTON)&&(mouse_buttons&MOUSE_FIFTHBUTTON)){
|
|
mouse_aggregate_flush();
|
|
if (mh) mh(cd,mouse_x, mouse_y,B_FIFTH|B_UP);
|
|
}
|
|
if (!(button&MOUSE_SIXTHBUTTON)&&(mouse_buttons&MOUSE_SIXTHBUTTON)){
|
|
mouse_aggregate_flush();
|
|
/*if (mh) mh(cd,mouse_x, mouse_y,B_SIXTH|B_UP);*/
|
|
}
|
|
|
|
if (drx < 0 && mh) mh(cd, mouse_x, mouse_y, B_MOVE | B_WHEELUP);
|
|
if (drx > 0 && mh) mh(cd, mouse_x, mouse_y, B_MOVE | B_WHEELDOWN);
|
|
|
|
if (dry < 0 && mh) mh(cd, mouse_x, mouse_y, B_MOVE | B_WHEELLEFT);
|
|
if (dry > 0 && mh) mh(cd, mouse_x, mouse_y, B_MOVE | B_WHEELRIGHT);
|
|
|
|
/* Test drag */
|
|
if (! ((button^mouse_buttons) & BUTTON_MASK ) && moved && (button &
|
|
BUTTON_MASK)){
|
|
mouse_aggregate_flag=1;
|
|
mouse_aggregate_action=(
|
|
button&MOUSE_LEFTBUTTON?B_LEFT:
|
|
button&MOUSE_RIGHTBUTTON?B_RIGHT:
|
|
button&MOUSE_MIDDLEBUTTON?B_MIDDLE:
|
|
button&MOUSE_FOURTHBUTTON?B_FOURTH:
|
|
button&MOUSE_FIFTHBUTTON?B_FIFTH:
|
|
/*button&MOUSE_SIXTHBUTTON?B_SIXTH:*/
|
|
0) | B_DRAG;
|
|
}
|
|
mouse_buttons=button;
|
|
}
|
|
|
|
#undef BUTTON_MASK
|
|
|
|
/* Flushes the background_buffer onscreen where it was originally taken from. */
|
|
static void place_mouse_background(void)
|
|
{
|
|
struct bitmap bmp;
|
|
struct graphics_device *current_virtual_device_backup;
|
|
|
|
bmp.x = arrow_width;
|
|
bmp.y = arrow_height;
|
|
bmp.skip = arrow_width * fb_pixelsize;
|
|
bmp.data = background_buffer;
|
|
|
|
current_virtual_device_backup = current_virtual_device;
|
|
current_virtual_device = mouse_graphics_device;
|
|
svga_driver.draw_bitmap(mouse_graphics_device, &bmp, background_x, background_y);
|
|
current_virtual_device = current_virtual_device_backup;
|
|
}
|
|
|
|
/* Only when the old and new mouse don't interfere. Using it on interfering mouses would
|
|
* cause a flicker.
|
|
*/
|
|
static void hide_mouse(void)
|
|
{
|
|
|
|
global_mouse_hidden = 1;
|
|
place_mouse_background();
|
|
}
|
|
|
|
/* Gets background from the screen (clipping provided only right and bottom) to the
|
|
* passed buffer.
|
|
*/
|
|
static void get_mouse_background(unsigned char *buffer_ptr)
|
|
{
|
|
int width,height,skip,x,y;
|
|
|
|
skip=arrow_width*fb_pixelsize;
|
|
|
|
x=mouse_x;
|
|
y=mouse_y;
|
|
|
|
width=fb_pixelsize*(arrow_width+x>xsize?xsize-x:arrow_width);
|
|
height=arrow_height+y>ysize?ysize-y:arrow_height;
|
|
|
|
SYNC
|
|
for (;height;height--){
|
|
mouse_getscansegment(buffer_ptr,x,y,width);
|
|
buffer_ptr+=skip;
|
|
y++;
|
|
}
|
|
}
|
|
|
|
/* Overlays the arrow's image over the mouse_buffer
|
|
* Doesn't draw anything into the screen
|
|
*/
|
|
static void render_mouse_arrow(void)
|
|
{
|
|
int x,y, reg0, reg1;
|
|
unsigned char *mouse_ptr=mouse_buffer;
|
|
const unsigned *arrow_ptr=arrow;
|
|
|
|
for (y=arrow_height;y;y--){
|
|
reg0=*arrow_ptr;
|
|
reg1=arrow_ptr[1];
|
|
arrow_ptr+=2;
|
|
for (x=arrow_width;x;)
|
|
{
|
|
int mask=1<<(--x);
|
|
|
|
if (reg0&mask)
|
|
memcpy (mouse_ptr, &mouse_black, fb_pixelsize);
|
|
else if (reg1&mask)
|
|
memcpy (mouse_ptr, &mouse_white, fb_pixelsize);
|
|
mouse_ptr+=fb_pixelsize;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void place_mouse(void)
|
|
{
|
|
struct bitmap bmp;
|
|
struct graphics_device *current_graphics_device_backup;
|
|
|
|
bmp.x = arrow_width;
|
|
bmp.y = arrow_height;
|
|
bmp.skip = arrow_width * fb_pixelsize;
|
|
bmp.data = mouse_buffer;
|
|
|
|
current_graphics_device_backup = current_virtual_device;
|
|
current_virtual_device = mouse_graphics_device;
|
|
/* We do need to worry about SYNC because draw_bitmap already
|
|
* does it (if necessary)
|
|
*/
|
|
svga_driver.draw_bitmap(mouse_graphics_device, &bmp, mouse_x, mouse_y);
|
|
current_virtual_device = current_graphics_device_backup;
|
|
|
|
global_mouse_hidden=0;
|
|
}
|
|
|
|
/* Only when the old and the new mouse positions do not interfere. Using this routine
|
|
* on interfering positions would cause a flicker.
|
|
*/
|
|
static void show_mouse(void)
|
|
{
|
|
|
|
get_mouse_background(background_buffer);
|
|
background_x=mouse_x;
|
|
background_y=mouse_y;
|
|
memcpy(mouse_buffer,background_buffer,fb_pixelsize*arrow_area);
|
|
render_mouse_arrow();
|
|
place_mouse();
|
|
}
|
|
|
|
/* Doesn't draw anything into the screen
|
|
*/
|
|
static void put_and_clip_background_buffer_over_mouse_buffer(void)
|
|
{
|
|
unsigned char *bbufptr=background_buffer, *mbufptr=mouse_buffer;
|
|
int left=background_x-mouse_x;
|
|
int top=background_y-mouse_y;
|
|
int right,bottom;
|
|
int bmpixelsizeL=fb_pixelsize;
|
|
int number_of_bytes;
|
|
int byte_skip;
|
|
|
|
right=left+arrow_width;
|
|
bottom=top+arrow_height;
|
|
|
|
if (left<0){
|
|
bbufptr-=left*bmpixelsizeL;
|
|
left=0;
|
|
}
|
|
if (right>arrow_width) right=arrow_width;
|
|
if (top<0){
|
|
bbufptr-=top*bmpixelsizeL*arrow_width;
|
|
top=0;
|
|
}
|
|
if (bottom>arrow_height) bottom=arrow_height;
|
|
mbufptr+=bmpixelsizeL*(left+arrow_width*top);
|
|
byte_skip=arrow_width*bmpixelsizeL;
|
|
number_of_bytes=bmpixelsizeL*(right-left);
|
|
for (;top<bottom;top++){
|
|
memcpy(mbufptr,bbufptr,number_of_bytes);
|
|
mbufptr+=byte_skip;
|
|
bbufptr+=byte_skip;
|
|
}
|
|
}
|
|
|
|
/* This draws both the contents of background_buffer and mouse_buffer in a scan
|
|
* way (left-right, top-bottom), so the flicker is reduced.
|
|
*/
|
|
static inline void place_mouse_composite(void)
|
|
{
|
|
int mouse_left=mouse_x;
|
|
int mouse_top=mouse_y;
|
|
int background_left=background_x;
|
|
int background_top=background_y;
|
|
int mouse_right=mouse_left+arrow_width;
|
|
int mouse_bottom=mouse_top+arrow_height;
|
|
int background_right=background_left+arrow_width;
|
|
int background_bottom=background_top+arrow_height;
|
|
int skip=arrow_width*fb_pixelsize;
|
|
int background_length,mouse_length;
|
|
unsigned char *mouse_ptr=mouse_buffer,*background_ptr=background_buffer;
|
|
int yend;
|
|
|
|
/* First let's sync to the beam - wait for the beginning of vertical retrace
|
|
* (it would be better to wait for the beginning of the blank, however,
|
|
* svgalib doesn't provide it as VGA and SVGA cards don't provide it
|
|
*/
|
|
|
|
/* This will probably not make any good anyway.
|
|
if (vga_colors >= 256)
|
|
vga_waitretrace();
|
|
*/
|
|
|
|
if (mouse_bottom>ysize) mouse_bottom=ysize;
|
|
if (background_bottom>ysize) background_bottom=ysize;
|
|
|
|
SYNC
|
|
/* We have to sync because mouse_drawscansegment does not wait for
|
|
* the accelerator to finish. But we never waste time here because
|
|
* mouse_drawscansegment is never accelerated.
|
|
*/
|
|
/* Let's do the top part */
|
|
if (background_top<mouse_top){
|
|
/* Draw the background */
|
|
background_length=background_right>xsize?xsize-background_left
|
|
:arrow_width;
|
|
for (;background_top<mouse_top;background_top++){
|
|
mouse_drawscansegment(background_ptr,background_left
|
|
,background_top,background_length*fb_pixelsize);
|
|
background_ptr+=skip;
|
|
}
|
|
|
|
}else if (background_top>mouse_top){
|
|
/* Draw the mouse */
|
|
mouse_length=mouse_right>xsize
|
|
?xsize-mouse_left:arrow_width;
|
|
for (;mouse_top<background_top;mouse_top++){
|
|
mouse_drawscansegment(mouse_ptr,mouse_left,mouse_top,mouse_length*fb_pixelsize);
|
|
mouse_ptr+=skip;
|
|
}
|
|
}
|
|
|
|
/* Let's do the middle part */
|
|
yend=mouse_bottom<background_bottom?mouse_bottom:background_bottom;
|
|
if (background_left<mouse_left){
|
|
/* Draw background, mouse */
|
|
mouse_length=mouse_right>xsize?xsize-mouse_left:arrow_width;
|
|
for (;mouse_top<yend;mouse_top++){
|
|
mouse_drawscansegment(background_ptr,background_left,mouse_top
|
|
,(mouse_left-background_left)*fb_pixelsize);
|
|
mouse_drawscansegment(mouse_ptr,mouse_left,mouse_top,mouse_length*fb_pixelsize);
|
|
mouse_ptr+=skip;
|
|
background_ptr+=skip;
|
|
}
|
|
|
|
}else{
|
|
int l1, l2, l3;
|
|
|
|
/* Draw mouse, background */
|
|
mouse_length=mouse_right>xsize?xsize-mouse_left:arrow_width;
|
|
background_length=background_right-mouse_right;
|
|
if (background_length+mouse_right>xsize)
|
|
background_length=xsize-mouse_right;
|
|
l1=mouse_length*fb_pixelsize;
|
|
l2=(mouse_right-background_left)*fb_pixelsize;
|
|
l3=background_length*fb_pixelsize;
|
|
for (;mouse_top<yend;mouse_top++){
|
|
mouse_drawscansegment(mouse_ptr,mouse_left,mouse_top,l1);
|
|
if (background_length>0)
|
|
mouse_drawscansegment(
|
|
background_ptr + l2,
|
|
mouse_right,mouse_top, l3);
|
|
mouse_ptr+=skip;
|
|
background_ptr+=skip;
|
|
}
|
|
}
|
|
|
|
if (background_bottom<mouse_bottom){
|
|
/* Count over bottoms! tops will be invalid! */
|
|
/* Draw mouse */
|
|
mouse_length=mouse_right>xsize?xsize-mouse_left
|
|
:arrow_width;
|
|
for (;background_bottom<mouse_bottom;background_bottom++){
|
|
mouse_drawscansegment(mouse_ptr,mouse_left,background_bottom
|
|
,mouse_length*fb_pixelsize);
|
|
mouse_ptr+=skip;
|
|
}
|
|
}else{
|
|
/* Draw background */
|
|
background_length=background_right>xsize?xsize-background_left
|
|
:arrow_width;
|
|
for (;mouse_bottom<background_bottom;mouse_bottom++){
|
|
mouse_drawscansegment(background_ptr,background_left,mouse_bottom
|
|
,background_length*fb_pixelsize);
|
|
background_ptr+=skip;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* This moves the mouse a sophisticated way when the old and new position of the
|
|
* cursor overlap.
|
|
*/
|
|
static inline void redraw_mouse_sophisticated(void)
|
|
{
|
|
int new_background_x, new_background_y;
|
|
|
|
get_mouse_background(mouse_buffer);
|
|
put_and_clip_background_buffer_over_mouse_buffer();
|
|
memcpy(new_background_buffer,mouse_buffer,fb_pixelsize*arrow_area);
|
|
new_background_x=mouse_x;
|
|
new_background_y=mouse_y;
|
|
render_mouse_arrow();
|
|
place_mouse_composite();
|
|
memcpy(background_buffer,new_background_buffer,fb_pixelsize*arrow_area);
|
|
background_x=new_background_x;
|
|
background_y=new_background_y;
|
|
}
|
|
|
|
static void redraw_mouse(void)
|
|
{
|
|
if (flags) return; /* We are not drawing */
|
|
if (mouse_x!=background_x||mouse_y!=background_y){
|
|
if (RECTANGLES_INTERSECT(
|
|
background_x, background_x+arrow_width,
|
|
mouse_x, mouse_x+arrow_width,
|
|
background_y, background_y+arrow_height,
|
|
mouse_y, mouse_y+arrow_height)){
|
|
redraw_mouse_sophisticated();
|
|
}else{
|
|
/* Do a normal hide/show */
|
|
get_mouse_background(mouse_buffer);
|
|
memcpy(new_background_buffer,
|
|
mouse_buffer,arrow_area*fb_pixelsize);
|
|
render_mouse_arrow();
|
|
hide_mouse();
|
|
place_mouse();
|
|
memcpy(background_buffer,new_background_buffer
|
|
,arrow_area*fb_pixelsize);
|
|
background_x=mouse_x;
|
|
background_y=mouse_y;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static unsigned char *svga_get_driver_param(void)
|
|
{
|
|
return svga_driver_param;
|
|
}
|
|
|
|
static void generate_palette_outer(void)
|
|
{
|
|
if (vga_colors == 16 || vga_colors == 256) {
|
|
struct irgb *palette;
|
|
palette = mem_alloc(vga_colors * sizeof(*palette));
|
|
generate_palette(palette);
|
|
set_palette(palette);
|
|
mem_free(palette);
|
|
/* Palette in SVGAlib will be always color cube */
|
|
}
|
|
}
|
|
|
|
static void vga_update_palette(void)
|
|
{
|
|
if (!svga_driver.param->palette_mode)
|
|
svga_driver.depth |= 0x300;
|
|
else
|
|
svga_driver.depth &= ~0x300;
|
|
|
|
svga_driver.get_color = get_color_fn(svga_driver.depth);
|
|
if (!svga_driver.get_color) internal_error("Unknown bit depth %x", svga_driver.depth);
|
|
|
|
mouse_black = svga_driver.get_color(0);
|
|
mouse_white = svga_driver.get_color(0xffffff);
|
|
|
|
generate_palette_outer();
|
|
}
|
|
|
|
/* This is to be called after vga_setmode and sets up accelerator,
|
|
* svgalib functions */
|
|
static void setup_mode(int mode)
|
|
{
|
|
vga_modeinfo *i;
|
|
int sig;
|
|
|
|
accel_avail=vga_ext_set(VGA_EXT_AVAILABLE,VGA_AVAIL_ACCEL);
|
|
if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_SET)&VGA_CLUT8){
|
|
vga_ext_set(VGA_EXT_SET,VGA_CLUT8);
|
|
palette_depth=8;
|
|
}else palette_depth=6;
|
|
i=vga_getmodeinfo(mode);
|
|
vga_bytes=i->bytesperpixel;
|
|
fb_pixelsize=vga_bytes?vga_bytes:1;
|
|
vga_misordered=!!(i->flags&RGB_MISORDERED);
|
|
mode_x=!!(i->flags&IS_MODEX);
|
|
vga_linear=!!(i->flags&IS_LINEAR);
|
|
/*
|
|
if (!vga_linear && i->flags&CAPABLE_LINEAR && 0<=vga_setlinearaddressing()) vga_linear=1;
|
|
*/
|
|
my_graph_mem = vga_getgraphmem();
|
|
svga_driver.x = xsize = i->width;
|
|
svga_driver.y = ysize = i->height;
|
|
vga_colors = i->colors;
|
|
if (xsize == 320 && ysize == 200 && i->colors == 256) vga_linear = 1; /* The mode
|
|
does not need to page :-) */
|
|
vga_linewidth = i->linewidth;
|
|
if (!vga_linear) {
|
|
vga_page=-1;
|
|
}
|
|
vga_misordered = !!(i->flags & RGB_MISORDERED);
|
|
|
|
svga_driver.flags &= ~GD_SELECT_PALETTE;
|
|
|
|
/*dump_mode_info_into_file(i);*/
|
|
svga_driver.depth = 0;
|
|
svga_driver.depth |= vga_misordered << 8;
|
|
switch (vga_colors) {
|
|
case 16:
|
|
sig = 4;
|
|
break;
|
|
case 256:
|
|
sig = 8;
|
|
if (!svga_driver.param->palette_mode)
|
|
svga_driver.depth |= 0x300;
|
|
svga_driver.flags |= GD_SELECT_PALETTE;
|
|
break;
|
|
case 32768:
|
|
sig = 15;
|
|
break;
|
|
case 65536:
|
|
sig = 16;
|
|
break;
|
|
case 16777216:
|
|
sig = 24;
|
|
break;
|
|
default:
|
|
sig = 0; /* Only to suppress warning */
|
|
break;
|
|
}
|
|
svga_driver.depth |= sig << 3;
|
|
svga_driver.depth |= fb_pixelsize;
|
|
|
|
/* setup_functions uses depth. */
|
|
setup_functions();
|
|
generate_palette_outer();
|
|
}
|
|
|
|
#ifndef __SPAD__
|
|
static void vtswitch_handler(void *nothing)
|
|
{
|
|
int oktowrite;
|
|
|
|
vga_unlockvc();
|
|
vga_lockvc();
|
|
oktowrite = vga_oktowrite();
|
|
if (flags == 1 && oktowrite) {
|
|
flags = 0;
|
|
setup_mode(vga_mode);
|
|
if (mouse_works) {
|
|
mouse_seteventhandler((void *)mouse_event_handler);
|
|
}
|
|
if (current_virtual_device) current_virtual_device->redraw_handler(current_virtual_device, ¤t_virtual_device->size);
|
|
}
|
|
flags = (flags & ~1) | !oktowrite;
|
|
svgalib_timer_id = install_timer(100, vtswitch_handler, NULL);
|
|
}
|
|
#endif
|
|
|
|
static void svga_ctrl_c(void *i_)
|
|
{
|
|
kbd_ctrl_c();
|
|
}
|
|
|
|
/* Param: one string which is to be compared with one from modes.
|
|
* Copies the svga_driver into gr_driver.
|
|
* Returns: 0 OK
|
|
* 1 Passed mode unknown by svga_driver
|
|
* 2 Passed mode unknown by svgalib
|
|
* mikulas: Change: Returns: NULL: OK
|
|
* non-null: poiner to string with error
|
|
* description, string must be freed
|
|
*/
|
|
static unsigned char *svga_init_driver(unsigned char *param, unsigned char *display)
|
|
{
|
|
int j;
|
|
|
|
kbd_set_raw = 0;
|
|
|
|
vga_init();
|
|
svga_driver.flags |= GD_NEED_CODEPAGE;
|
|
j = 0;
|
|
|
|
svga_driver_param = NULL;
|
|
if (!param || !*param) goto not_found;
|
|
svga_driver_param=stracpy(param);
|
|
for (j = 0; (size_t)j < array_elements(modes); j++) {
|
|
if (!casestrcmp(cast_uchar modes[j].name, param)) {
|
|
goto found;
|
|
}
|
|
}
|
|
j = 1;
|
|
not_found:
|
|
{
|
|
unsigned char *m = init_str();
|
|
int l = 0;
|
|
int f = 0;
|
|
if (j) {
|
|
add_to_str(&m, &l, cast_uchar "Video mode ");
|
|
add_to_str(&m, &l, param);
|
|
add_to_str(&m, &l,
|
|
j == 1 ? cast_uchar " not supported by svgalib" :
|
|
j == 2 ? cast_uchar " not supported by your video card" :
|
|
cast_uchar " could not be set");
|
|
add_to_str(&m, &l, cast_uchar ".\n");
|
|
} else add_to_str(&m, &l, cast_uchar "There is no default video mode.\n");
|
|
for (j=0;(size_t)j<sizeof(modes)/sizeof(*modes);j++) if (vga_hasmode(modes[j].number)) {
|
|
if (f) add_to_str(&m, &l, cast_uchar ", ");
|
|
else f = 1, add_to_str(&m, &l, cast_uchar "The following modes are supported:\n");
|
|
add_to_str(&m, &l, cast_uchar modes[j].name);
|
|
}
|
|
if (f) add_to_str(&m, &l, cast_uchar "\nUse -mode switch to set video mode.\n");
|
|
else add_to_str(&m, &l, cast_uchar "There are no supported video modes. Links can't run on svgalib.\n");
|
|
if(svga_driver_param)mem_free(svga_driver_param),svga_driver_param=NULL;
|
|
return m;
|
|
}
|
|
found:
|
|
if (!vga_hasmode(modes[j].number)) {
|
|
j = 2;
|
|
goto not_found;
|
|
}
|
|
init_virtual_devices(&svga_driver, NUMBER_OF_DEVICES);
|
|
#ifdef MOUSE_NONE
|
|
if ((vga_getmousetype() & MOUSE_TYPE_MASK) == MOUSE_NONE) {
|
|
vga_setmousesupport(0);
|
|
mouse_works = 0;
|
|
} else
|
|
#endif
|
|
{
|
|
vga_setmousesupport(1);
|
|
mouse_works = 1;
|
|
}
|
|
vga_lockvc();
|
|
#ifndef __SPAD__
|
|
svgalib_timer_id = install_timer(100, vtswitch_handler, NULL);
|
|
#ifdef HAVE_VGA_RUNINBACKGROUND_VERSION
|
|
if (vga_runinbackground_version() >= 1)
|
|
#endif
|
|
vga_runinbackground(1);
|
|
#endif
|
|
vga_setmode_retry:
|
|
if (vga_setmode(modes[j].number) < 0) {
|
|
if (out_of_memory(0, NULL, 0))
|
|
goto vga_setmode_retry;
|
|
#ifndef __SPAD__
|
|
kill_timer(svgalib_timer_id);
|
|
#endif
|
|
vga_unlockvc();
|
|
shutdown_virtual_devices();
|
|
j = 3;
|
|
goto not_found;
|
|
}
|
|
vga_mode=modes[j].number;
|
|
setup_mode(modes[j].number);
|
|
svgalib_kbd = handle_svgalib_keyboard(svgalib_key_in);
|
|
|
|
if (mouse_works){
|
|
if ((unsigned)arrow_area > (unsigned)MAXINT / fb_pixelsize) overalloc();
|
|
mouse_buffer=mem_alloc(fb_pixelsize*arrow_area);
|
|
background_buffer=mem_alloc(fb_pixelsize*arrow_area);
|
|
new_background_buffer=mem_alloc(fb_pixelsize*arrow_area);
|
|
mouse_black=svga_driver.get_color(0);
|
|
mouse_white=svga_driver.get_color(0xffffff);
|
|
mouse_graphics_device=svga_driver.init_device();
|
|
virtual_devices[0] = NULL;
|
|
global_mouse_hidden=1;
|
|
background_x=mouse_x=xsize>>1;
|
|
background_y=mouse_y=ysize>>1;
|
|
show_mouse();
|
|
mouse_seteventhandler((void *)mouse_event_handler);
|
|
}else{
|
|
global_mouse_hidden=1;
|
|
/* To ensure hide_mouse and show_mouse will do nothing */
|
|
}
|
|
ignore_signals();
|
|
errno = 0;
|
|
while (signal(SIGTSTP, SIG_IGN) == SIG_ERR && errno == EINTR) errno = 0;
|
|
install_signal_handler(SIGINT, svga_ctrl_c, svgalib_kbd, 0);
|
|
return NULL;
|
|
}
|
|
|
|
/* Return value: 0 alloced on heap
|
|
* 1 alloced in vidram
|
|
* 2 alloced in X server shm
|
|
*/
|
|
static int svga_get_empty_bitmap(struct bitmap *dest)
|
|
{
|
|
if (dest->x && (unsigned)dest->x * (unsigned)dest->y / (unsigned)dest->x != (unsigned)dest->y) overalloc();
|
|
if ((unsigned)dest->x * (unsigned)dest->y > (unsigned)MAXINT / fb_pixelsize) overalloc();
|
|
dest->data=mem_alloc(dest->x*dest->y*fb_pixelsize);
|
|
dest->skip=dest->x*fb_pixelsize;
|
|
dest->flags=0;
|
|
return 0;
|
|
}
|
|
|
|
static int vga_block(struct graphics_device *dev)
|
|
{
|
|
int overridden;
|
|
|
|
overridden = (flags >> 1) & 1;
|
|
if (!overridden) {
|
|
svgalib_block_itrm(svgalib_kbd);
|
|
if (mouse_works) {
|
|
hide_mouse();
|
|
/* mouse_close(); This is not necessary as it is
|
|
handled by vga_setmode(TEXT). */
|
|
}
|
|
vga_setmode_retry:
|
|
if (vga_setmode(TEXT) < 0) {
|
|
if (out_of_memory(0, NULL, 0))
|
|
goto vga_setmode_retry;
|
|
fatal_exit("ERROR: vga_setmode failed");
|
|
}
|
|
}
|
|
flags |= 2;
|
|
return overridden;
|
|
}
|
|
|
|
static int vga_unblock(struct graphics_device *dev)
|
|
{
|
|
#ifdef DEBUG
|
|
if (!(flags & 2)) {
|
|
internal_error("vga_unblock called without vga_block");
|
|
return 0;
|
|
}
|
|
#endif /* #ifdef DEBUG */
|
|
flags &= ~2;
|
|
vga_setmousesupport(1);
|
|
vga_setmode_retry:
|
|
if (vga_setmode(vga_mode) < 0) {
|
|
if (out_of_memory(0, NULL, 0))
|
|
goto vga_setmode_retry;
|
|
fatal_exit("ERROR: vga_setmode failed");
|
|
}
|
|
setup_mode(vga_mode);
|
|
if (mouse_works) {
|
|
show_mouse();
|
|
mouse_seteventhandler((void *)mouse_event_handler);
|
|
}
|
|
svgalib_unblock_itrm(svgalib_kbd);
|
|
if (current_virtual_device) current_virtual_device->redraw_handler(current_virtual_device, ¤t_virtual_device->size);
|
|
return 0;
|
|
}
|
|
|
|
static void *svga_prepare_strip(struct bitmap *bmp, int top, int lines)
|
|
{
|
|
return (unsigned char *)bmp->data + bmp->skip * top;
|
|
}
|
|
|
|
|
|
static void svga_commit_strip(struct bitmap *bmp, int top, int lines)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int vga_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
|
|
{
|
|
int retval,i;
|
|
|
|
if (drv != &svga_driver) return select(n, readfds, writefds, exceptfds, timeout);
|
|
|
|
/* The second flag here is to suppress mouse wait
|
|
* in blocked state */
|
|
retval = vga_waitevent((mouse_works && !(flags & 2) ? VGA_MOUSEEVENT : 0)
|
|
#ifdef VGA_REDRAWEVENT
|
|
| VGA_REDRAWEVENT
|
|
#endif
|
|
, readfds, writefds, exceptfds, timeout);
|
|
if (retval < 0) return retval;
|
|
#ifdef VGA_REDRAWEVENT
|
|
if (retval & VGA_REDRAWEVENT) {
|
|
if (current_virtual_device) current_virtual_device->redraw_handler(current_virtual_device, ¤t_virtual_device->size);
|
|
check_bottom_halves();
|
|
}
|
|
#endif
|
|
if (retval & VGA_MOUSEEVENT){
|
|
mouse_aggregate_flush();
|
|
/*redraw_mouse(); mikulas: dal jsem to do mouse_event_handler,
|
|
aby ukazatel mysi nezustaval pozadu za scrollbarem */
|
|
check_bottom_halves();
|
|
}
|
|
retval = 0;
|
|
for (i = 0; i < n; i++){
|
|
if (readfds && FD_ISSET(i, readfds)) retval++;
|
|
if (writefds && FD_ISSET(i, writefds)) retval++;
|
|
if (exceptfds && FD_ISSET(i, exceptfds)) retval++;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
struct graphics_driver svga_driver = {
|
|
cast_uchar "svgalib",
|
|
svga_init_driver,
|
|
init_virtual_device,
|
|
shutdown_virtual_device,
|
|
svga_shutdown_driver,
|
|
NULL,
|
|
NULL,
|
|
svga_get_driver_param,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
svga_get_empty_bitmap,
|
|
svga_register_bitmap,
|
|
svga_prepare_strip,
|
|
svga_commit_strip,
|
|
svga_unregister_bitmap,
|
|
NULL, /* svga_draw_bitmap */
|
|
NULL, /* get_color */
|
|
NULL, /* fill_area */
|
|
NULL, /* draw_hline */
|
|
NULL, /* draw_vline */
|
|
NULL, /* scroll */
|
|
NULL, /* set_clip_area */
|
|
NULL, /* flush */
|
|
vga_block, /* block */
|
|
vga_unblock, /* unblock */
|
|
vga_update_palette, /* set_palette */
|
|
NULL, /* get_real_colors */
|
|
NULL, /* set_title */
|
|
NULL, /* exec */
|
|
NULL, /* set_clipboard_text */
|
|
NULL, /* get_clipboard_text */
|
|
0, /* depth */
|
|
0, 0, /* size */
|
|
GD_NO_LIBEVENT
|
|
#ifndef SPAD
|
|
| GD_NOAUTO
|
|
#endif
|
|
, /* flags */
|
|
NULL, /* param */
|
|
};
|
|
|
|
#endif /* GRDRV_SVGALIB */
|