Logo Search packages:      
Sourcecode: zgv version File versions

mousecur.c

/* zgv 5.7 - GIF, JPEG and PBM/PGM/PPM viewer, for VGA PCs running Linux.
 * Copyright (C) 1993-2003 Russell Marks. See README for license details.
 *
 * mousecur.c - mouse cursor routines.
 *
 * These all check has_mouse and return if zero, so there's no need
 * to check that before calling them.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "zgv_io.h"
#include "rc_config.h"
#include "rcfile.h"
#include "zgv.h"

/* Zgv has more problems with drawing a mouse cursor than most
 * svgalib programs would. For example, since we need to support 640x480
 * 16-colour mode, we can't use any vgagl stuff, or at least not
 * exclusively. And for 320x400/360x480 modes, we have a specially
 * squished pointer. :-)
 */

static int usegl=-1,usenarrow=-1;

/* for area-under-cursor save buffer.
 * width/height may be less than sizes below if near edge of screen.
 */
static int savex,savey,savew,saveh;

static int screen_width,screen_height,screen_bytepp;

#define MOUSECUR_XSIZE  16
#define MOUSECUR_YSIZE  16
#define MOUSECUR_PIXMAP_SIZE  (MOUSECUR_XSIZE*MOUSECUR_YSIZE)

/* next two pixmaps are *4 as must be able to handle up to 32-bpp modes */
static unsigned char mouseptr_save[MOUSECUR_PIXMAP_SIZE*4];
static unsigned char mouseptr_pixmap[MOUSECUR_PIXMAP_SIZE*4];
static unsigned char mouseptr_pixmap_orig[MOUSECUR_PIXMAP_SIZE]=
  {
  /* 1 is black, 2 is white, 0 is transparent */
  0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
  2,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,
  2,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,
  0,2,1,1,1,1,1,2,2,0,0,0,0,0,0,0,
  0,2,1,1,1,1,1,1,1,2,2,0,0,0,0,0,
  0,0,2,1,1,1,1,1,1,1,1,2,2,0,0,0,
  0,0,2,1,1,1,1,1,1,1,1,1,1,2,0,0,
  0,0,0,2,1,1,1,1,1,2,2,2,2,0,0,0,
  0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,
  0,0,0,0,2,1,1,2,2,1,2,0,0,0,0,0,
  0,0,0,0,2,1,1,2,0,2,1,2,0,0,0,0,
  0,0,0,0,0,2,1,2,0,0,2,1,2,0,0,0,
  0,0,0,0,0,2,1,2,0,0,0,2,1,2,0,0,
  0,0,0,0,0,0,2,0,0,0,0,0,2,1,2,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  };

static unsigned char mouseptr_pixmap_narrow_orig[MOUSECUR_PIXMAP_SIZE/2]=
  {
  /* 1 is black, 2 is white, 0 is transparent */
  0,2,0,0,0,0,0,0,
  2,1,2,0,0,0,0,0,
  2,1,1,2,0,0,0,0,
  2,1,1,1,2,0,0,0,
  2,1,1,1,1,2,0,0,
  0,2,1,1,1,1,2,0,
  0,2,1,1,1,1,1,2,
  0,2,1,1,1,2,2,0,
  0,2,1,1,1,2,0,0,
  0,0,2,1,2,1,2,0,
  0,0,2,1,2,1,2,0,
  0,0,2,1,2,2,1,2,
  0,0,2,1,2,2,1,2,
  0,0,0,2,0,0,2,0,
  0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0
  };





void mousecur_init(int blackcol,int whitecol)
{
int f,val;
int mode=vga_getcurrentmode();

if(!has_mouse) return;

screen_bytepp=vga_getmodeinfo(mode)->bytesperpixel;

screen_width =vga_getxdim();
screen_height=vga_getydim();

mouse_setxrange(0,screen_width-1);
mouse_setyrange(0,screen_height-1);

switch(mode)
  {
  case G640x480x16:
  case G320x200x256: case G320x240x256:
  case G320x400x256: case G360x480x256:
    usegl=0; break;
  default:
    usegl=1;
  }

usenarrow=(mode==G320x400x256 || mode==G360x480x256);

if(usegl)
  gl_setcontextvga(vga_getcurrentmode());

for(f=0;f<(usenarrow?MOUSECUR_PIXMAP_SIZE/2:MOUSECUR_PIXMAP_SIZE);f++)
  {
  switch(usenarrow?mouseptr_pixmap_narrow_orig[f]:mouseptr_pixmap_orig[f])
    {
    case 1: /* black */
      val=blackcol; break;
    case 2: /* white (ish :-)) */
      val=whitecol; break;
    default: /* assume zero - transparent */
      val=0; break;
    }
  
  switch(screen_bytepp)
    {
    case 4:
      mouseptr_pixmap[f*4  ]=(val&255);
      mouseptr_pixmap[f*4+1]=(val>>8);
      mouseptr_pixmap[f*4+2]=(val>>16);
      mouseptr_pixmap[f*4+3]=0;
      break;
    case 3:
      mouseptr_pixmap[f*3  ]=(val&255);
      mouseptr_pixmap[f*3+1]=(val>>8);
      mouseptr_pixmap[f*3+2]=(val>>16);
      break;
    case 2:
      mouseptr_pixmap[f*2  ]=(val&255);
      mouseptr_pixmap[f*2+1]=(val>>8);
      break;
    default:
      mouseptr_pixmap[f]=val;
    }
  }
}


void mousecur_on()
{
int small=0,y;

if(!has_mouse) return;

savex=mouse_getx();
savey=mouse_gety();
savew=MOUSECUR_XSIZE;
saveh=MOUSECUR_YSIZE;
if(usenarrow) savew/=2;
/* deal with being near edge of screen */
if(savex>screen_width-savew)
  savew=screen_width-savex,small=1;
if(savey>screen_height-saveh)
  saveh=screen_height-savey,small=1;

/* we need to save existing data, then draw the mouse. */
if(usegl)
  {
  /* gl-using 8/15/16/24/32-bpp version */
  gl_getbox(savex,savey,savew,saveh,mouseptr_save);
  /* since there's no gl_putboxpartmask, and clipping doesn't work for
   * gl_putboxmask, we have to do either masking or clipping ourselves.
   * Hmm. I'll pick clipping, I think...
   */
  if(small)
    /* do it a line at a time */
    for(y=0;y<saveh;y++)
      gl_putboxmask(savex,savey+y,savew,1,
                        mouseptr_pixmap+MOUSECUR_XSIZE*y*screen_bytepp);
  else
    /* full size, no problem */
    gl_putboxmask(savex,savey,savew,saveh,mouseptr_pixmap);
  }
else
  {
  static unsigned char scantmp[80];
  unsigned char *saveptr,*inptr,*outptr;
  int x;
  
  /* 16-col and low-res-8-bit version */
  
  /* save area */
  saveptr=mouseptr_save;
  for(y=0;y<saveh;y++,saveptr+=savew)
    vga_getscansegment(saveptr,savex,savey+y,savew);
  
  saveptr=mouseptr_save;
  for(y=0;y<saveh;y++)
    {
    inptr=mouseptr_pixmap+y*(usenarrow?MOUSECUR_XSIZE/2:MOUSECUR_XSIZE);
    outptr=scantmp;
    for(x=0;x<savew;x++,inptr++,saveptr++)
      *outptr++=((*inptr)?(*inptr):(*saveptr));
    vga_drawscansegment(scantmp,savex,savey+y,savew);
    }
  }
}


void mousecur_off()
{
if(!has_mouse) return;

/* redraw saved data */
if(usegl)
  gl_putbox(savex,savey,savew,saveh,mouseptr_save);
else
  {
  unsigned char *saveptr=mouseptr_save;
  int y;

  for(y=0;y<saveh;y++,saveptr+=savew)
    vga_drawscansegment(saveptr,savex,savey+y,savew);
  }
}

Generated by  Doxygen 1.6.0   Back to index