Logo Search packages:      
Sourcecode: zgv version File versions

zgv_io.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.
 *
 * zgv_io.c - functional replacements for svgalib routines when not using
 *          svgalib itself as the backend.
 */

#ifndef BACKEND_SVGALIB

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "zgv_io.h"
#include "readnbkey.h"


/* unsurprisingly, zgv effectively assumes certain modes will be available,
 * notably 640x480x8 (or 640x480x4) for the selector, and 640x480x8
 * (or 360x480x8, or 320x200x8) for viewer. One way or another, you
 * essentially *have* to support 640x480x8 at a minimum, it gets
 * very messy if you can't.
 *
 * Pixel formats used for zgl_*box* and zvga_drawscan*:
 *
 * 4-bit    like 8-bit, but only uses values 0..15
 * 8-bit    0..255 indicies into palette, one per byte
 * 15-bit   0rrrrrgggggbbbbb, little-endian, blue at low end.
 *          Don't bother with 15-bit unless you have to.
 * 16-bit   rrrrrggggggbbbbb, little-endian, blue at low end.
 * 24-bit   3 bytes per pixel, in BGR order.
 * 32-bit   4 bytes per pixel, in BGR0 order.
 *
 * zgv is reasonably smart about using 15/16 and 24/32-bit modes as
 * appropriate, so only supporting those which are most convenient for
 * you (e.g. 16, 32) is acceptable. A sensible set of depths to
 * support is probably 8, 16, and 32.
 *
 * Colours for zvga_*pal* are in the range 0..63 for each of R, G, B.
 *
 * If you're emulating palette-based modes in direct-colour modes,
 * don't do a redraw when the palette changes - the program itself
 * forces a redraw after palette changes when using non-svgalib
 * backends.
 */


/* possible modes. All start off with has_mode zero, so make that
 * non-zero for any you have in zvga_init() (unless you do zvga_hasmode()
 * some other way).
 */
static zvga_modeinfo modes[GLASTMODE+1]=
  {
  /* must be in same order as in zgv_io.h */
  { 0,0,0,0,0,0 },
  { 640,480,4,1,  16,0 },
  { 320,200,8,1,  256,0 },
  { 320,240,8,1,  256,0 },
  { 320,400,8,1,  256,0 },
  { 360,480,8,1,  256,0 },
  { 640,480,8,1,  256,0 },
  { 800,600,8,1,  256,0 },
  { 1024,768,8,1, 256,0 },
  { 1280,1024,8,1,      256,0 },
  { 1152,864,8,1, 256,0 },
  { 1600,1200,8,1,      256,0 },
  { 320,200,15,2, 32768,0 },
  { 320,240,15,2, 32768,0 },
  { 640,480,15,2, 32768,0 },
  { 800,600,15,2, 32768,0 },
  { 1024,768,15,2,      32768,0 },
  { 1280,1024,15,2,     32768,0 },
  { 1152,864,15,2,      32768,0 },
  { 1600,1200,15,2,     32768,0 },
  { 320,200,16,2, 65536,0 },
  { 320,240,16,2, 65536,0 },
  { 640,480,16,2, 65536,0 },
  { 800,600,16,2, 65536,0 },
  { 1024,768,16,2,      65536,0 },
  { 1280,1024,16,2,     65536,0 },
  { 1152,864,16,2,      65536,0 },
  { 1600,1200,16,2,     65536,0 },
  { 320,200,32,4, 16777216,0 },
  { 320,240,32,4, 16777216,0 },
  { 640,480,32,4, 16777216,0 },
  { 800,600,32,4, 16777216,0 },
  { 1024,768,32,4,      16777216,0 },
  { 1280,1024,32,4,     16777216,0 },
  { 1152,864,32,4,      16777216,0 },
  { 1600,1200,32,4,     16777216,0 },
  { 320,200,24,3, 16777216,0 },
  { 320,240,24,3, 16777216,0 },
  { 640,480,24,3, 16777216,0 },
  { 800,600,24,3, 16777216,0 },
  { 1024,768,24,3,      16777216,0 },
  { 1280,1024,24,3,     16777216,0 },
  { 1152,864,24,3,      16777216,0 },
  { 1600,1200,24,3,     16777216,0 }
  };

static int current_mode=0;


/* mouse stuff can be ignored */
void zmouse_close(void) {}
int zmouse_getbutton(void) { return 0; }
int zmouse_getx(void) { return 0; }
int zmouse_gety(void) { return 0; }
int zmouse_init_return_fd(char *dev,int type,int samplerate) { return -1; }
void zmouse_setposition(int x,int y) {}
void zmouse_setscale(int s) {}
void zmouse_setxrange(int x1,int x2) {}
void zmouse_setyrange(int y1,int y2) {}
int zmouse_update(void) { return 0; }
/* only used by mouse code, so... */
void zgl_putboxmask(int x,int y,int w,int h,void *dp) {}

/* these can also be ignored */
void zvga_disabledriverreport(void) {}
void zvga_lockvc(void) {}
int zvga_oktowrite(void) { return 1; }
void zvga_runinbackground(int stat) {}
void zvga_unlockvc(void) {}
int zgl_setcontextvga(int m) { return 0; }
int zvga_getmousetype(void) { return 0; }
/* only used by vgadisp.c, which avoids it for non-svgalib backends */
void zgl_putboxpart(int x,int y,int w,int h,int bw,int bh,void *b,
  int xo,int yo) {}

/* simple generic stuff */
int zvga_lastmodenumber(void) { return GLASTMODE; }
int zvga_getcolors(void) { return modes[current_mode].colors; }
int zvga_getcurrentmode(void) { return current_mode; }
int zvga_getxdim(void) { return modes[current_mode].width; }
int zvga_getydim(void) { return modes[current_mode].height; }


#ifdef BACKEND_SDL

#include <SDL/SDL.h>

static int caller_pal[256];
static SDL_Color sdl_pal[256];
static int palchanged=0;
static int scrnchange_line_min=(1<<30),scrnchange_line_max=-1;

static SDL_Surface *surface=NULL;

/*#define SCRNMODE_FLAGS      SDL_FULLSCREEN*/
#define SCRNMODE_FLAGS  0


static void pal_update(void)
{
if(palchanged)
  {
  palchanged=0;
  SDL_SetColors(surface,sdl_pal,0,256);
  }
}


void zgl_fillbox(int x,int y,int w,int h,int c)
{
SDL_Rect rect={x,y,w,h};

pal_update();

/* XXX may not work outside 8-bit mode... */
SDL_FillRect(surface,&rect,c);

if(y<scrnchange_line_min) scrnchange_line_min=y;
if(y+h-1>scrnchange_line_max) scrnchange_line_max=y+h-1;
}

void zgl_getbox(int x,int y,int w,int h,void *dp)
{
/* XXX NYI */
}

void zgl_putbox(int x,int y,int w,int h,void *dp)
{
int f;
int wm=w*modes[current_mode].bytesperpixel;
int xm=x*modes[current_mode].bytesperpixel;

if(SDL_MUSTLOCK(surface) && SDL_LockSurface(surface)==-1)
  return;

/* XXX hang on, memcpy is a library call, and thus disallowed :-( */
for(f=y;f<y+h;f++,dp+=wm)
  memcpy(surface->pixels+f*surface->pitch+xm,dp,wm);

if(y<scrnchange_line_min) scrnchange_line_min=y;
if(y+h-1>scrnchange_line_max) scrnchange_line_max=y+h-1;

if(SDL_MUSTLOCK(surface))
  SDL_UnlockSurface(surface);
}


int zvga_clear(void)
{
pal_update();

if(modes[current_mode].colors<=256)
  SDL_FillRect(surface,NULL,0);
else
  SDL_FillRect(surface,NULL,SDL_MapRGB(surface->format,0,0,0));

scrnchange_line_min=0;
scrnchange_line_max=modes[current_mode].height-1;

return 0;
}


/* zvga_drawline is a slightly hacked version of:
 *
 * digline: draw digital line from (x1,y1) to (x2,y2),
 * calling a user-supplied procedure at each pixel.
 * Does no clipping.  Uses Bresenham's algorithm.
 *
 * Paul Heckbert  3 Sep 85
 *
 * ...which is from "Graphics Gems", Academic Press, 1990.
 */

/* absolute value of a */
#define ABS(a)          (((a)<0) ? -(a) : (a))

/* take binary sign of a, either -1, or 1 if >= 0 */
#define SGN(a)          (((a)<0) ? -1 : 1)

int zvga_drawline(int x1,int y1,int x2,int y2)
{
/* I've left the indentation as it was, mainly 'cos I can't be bothered
 * to fix it :-)
 */
    int col=current_colour;
    SDL_Rect rect={0,0,1,1};
    int d, x, y, ax, ay, sx, sy, dx, dy;

    pal_update();
    dx = x2-x1;  ax = ABS(dx)<<1;  sx = SGN(dx);
    dy = y2-y1;  ay = ABS(dy)<<1;  sy = SGN(dy);

    if(y1<y2)
      {
      if(y1<scrnchange_line_min) scrnchange_line_min=y1;
      if(y2>scrnchange_line_max) scrnchange_line_max=y2;
      }
    else
      {
      if(y2<scrnchange_line_min) scrnchange_line_min=y2;
      if(y1>scrnchange_line_max) scrnchange_line_max=y1;
      }

    x = x1;
    y = y1;
    if (ax>ay) {        /* x dominant */
      d = ay-(ax>>1);
      for (;;) {
            rect.x=x; rect.y=y;
          SDL_FillRect(surface,&rect,col);
          if (x==x2) return 0;
          if (d>=0) {
            y += sy;
            d -= ax;
          }
          x += sx;
          d += ay;
      }
    }
    else {              /* y dominant */
      d = ax-(ay>>1);
      for (;;) {
            rect.x=x; rect.y=y;
          SDL_FillRect(surface,&rect,col);
          if (y==y2) return 0;
          if (d>=0) {
            x += sx;
            d -= ay;
          }
          y += sy;
          d += ax;
      }
    }

return 0;
}


int zvga_drawpixel(int x,int y)
{
SDL_Rect rect={x,y,1,1};

SDL_FillRect(surface,&rect,current_colour);

if(y<scrnchange_line_min) scrnchange_line_min=y;
if(y>scrnchange_line_max) scrnchange_line_max=y;

return 0;
}


int zvga_drawscanline(int line,unsigned char *cols)
{
pal_update();

zgl_putbox(0,line,modes[current_mode].width,1,cols);

if(line<scrnchange_line_min) scrnchange_line_min=line;
if(line>scrnchange_line_max) scrnchange_line_max=line;

return 0;
}


int zvga_drawscansegment(unsigned char *cols,int x,int y,int len)
{
zgl_putbox(x,y,len,1,cols);

if(y<scrnchange_line_min) scrnchange_line_min=y;
if(y>scrnchange_line_max) scrnchange_line_max=y;

return 0;
}


zvga_modeinfo *zvga_getmodeinfo(int mode)
{
if(mode<0 || mode>GLASTMODE) return NULL;

return(modes+mode);
}


int zvga_getpalvec(int start,int num,int *pal)
{
int f;

for(f=start;f<start+num;f++)
  *pal++=caller_pal[f];

return num;
}


/* this can be ignored if not supporting any of 320x400x8, 360x480x8,
 * and 640x480x4.
 */
int zvga_getscansegment(unsigned char *cols,int x,int y,int len)
{
return 0;
}


int zvga_hasmode(int mode)
{
if(mode<0 || mode>GLASTMODE) return 0;

return(modes[mode].has_mode);
}


void sdl_exit(void)
{
SDL_ShowCursor(SDL_ENABLE);
SDL_Quit();
}


int zvga_init(void)
{
int f;

SDL_Init(SDL_INIT_VIDEO);
/* XXX should bomb out if that fails? */

/* in case it was installed setuid root */
setgid(getgid());
setuid(getuid());

atexit(sdl_exit);

SDL_WM_SetCaption("zgv-sdl","zgv-sdl");

for(f=1;f<=GLASTMODE;f++)
  {
  modes[f].has_mode=SDL_VideoModeOK(modes[f].width,modes[f].height,
                                    modes[f].bitsperpixel,
                                    SCRNMODE_FLAGS|(modes[f].colors<=256?SDL_HWPALETTE:0));
  }

if(!modes[G640x480x256].has_mode)
  {
  /* XXX bomb out if we don't have 640x480x8? */
  }

SDL_EnableKeyRepeat(250,50);
SDL_EnableUNICODE(1);
SDL_ShowCursor(SDL_DISABLE);

return 0;
}


int zvga_setcolor(int col)
{
current_colour=col;
return 0;
}


int zvga_setmode(int mode)
{
if(zvga_hasmode(mode))
  {
  SDL_Surface *ret;
  
  if((ret=SDL_SetVideoMode(modes[mode].width,modes[mode].height,
                           modes[mode].bitsperpixel,
                           SCRNMODE_FLAGS|(modes[mode].colors<=256?SDL_HWPALETTE:0))))
    {
    current_mode=mode;
    if(modes[mode].colors<=256)
      zvga_setpalette(0,0,0,0);
    surface=ret;
    return 0;
    }
  }

return -1;
}


int zvga_setpalette(int idx,int r,int g,int b)
{
caller_pal[idx]=((r<<16)|(g<<8)|b);
sdl_pal[idx].r=(r*255)/63;
sdl_pal[idx].g=(g*255)/63;
sdl_pal[idx].b=(b*255)/63;
palchanged=1;

return 0;
}


int zvga_setpalvec(int start,int num,int *pal)
{
int f;

for(f=start;f<start+num;f++)
  zvga_setpalette(f,pal[f*3],pal[f*3+1],pal[f*3+2]);

pal_update();

return num;
}


int zvga_setrgbcolor(int r,int g,int b)
{
current_colour=SDL_MapRGB(surface->format,(r*255)/63,(g*255)/63,(b*255)/63);
return 0;
}


int zgv_io_readnbkey(void)
{
SDL_Event event;
int key;

if(scrnchange_line_min<=scrnchange_line_max)
  {
  SDL_UpdateRect(surface,0,scrnchange_line_min,modes[current_mode].width,
                 scrnchange_line_max-scrnchange_line_min+1);
  }

scrnchange_line_min=(1<<30);
scrnchange_line_max=-1;

while(SDL_PollEvent(&event))
  {
  switch(event.type)
    {
    case SDL_KEYDOWN:
      /* check for various special/awkward keys */
      switch(event.key.keysym.sym)
        {
        case SDLK_F1:
          return((event.key.keysym.mod&KMOD_SHIFT)?RK_SHIFT_F1:RK_F1);
        case SDLK_F2:
          return((event.key.keysym.mod&KMOD_SHIFT)?RK_SHIFT_F2:RK_F2);
        case SDLK_F3:
          return((event.key.keysym.mod&KMOD_SHIFT)?RK_SHIFT_F3:RK_F3);
        case SDLK_F4:
          return((event.key.keysym.mod&KMOD_SHIFT)?RK_SHIFT_F4:RK_F4);
        case SDLK_F5:
          return((event.key.keysym.mod&KMOD_SHIFT)?RK_SHIFT_F5:RK_F5);
        case SDLK_F6:
          return((event.key.keysym.mod&KMOD_SHIFT)?RK_SHIFT_F6:RK_F6);
        case SDLK_F7:
          return((event.key.keysym.mod&KMOD_SHIFT)?RK_SHIFT_F7:RK_F7);
        case SDLK_F8:
          return((event.key.keysym.mod&KMOD_SHIFT)?RK_SHIFT_F8:RK_F8);
        case SDLK_F9:
          return((event.key.keysym.mod&KMOD_SHIFT)?RK_SHIFT_F9:RK_F9);
        case SDLK_F10:        return(RK_F10);
        case SDLK_F11:        return(RK_F11);
        case SDLK_F12:        return(RK_F12);
        case SDLK_LEFT:       return(RK_CURSOR_LEFT);
        case SDLK_DOWN:       return(RK_CURSOR_DOWN);
        case SDLK_UP:         return(RK_CURSOR_UP);
        case SDLK_RIGHT:      return(RK_CURSOR_RIGHT);
        case SDLK_HOME:       return(RK_HOME);
        case SDLK_END:        return(RK_END);
        case SDLK_PAGEUP:     return(RK_PAGE_UP);
        case SDLK_PAGEDOWN:   return(RK_PAGE_DOWN);
        case SDLK_INSERT:     return(RK_INSERT);
        case SDLK_DELETE:     return(RK_DELETE);
        case SDLK_RETURN:     return(RK_ENTER);
        default:
          /* stop complaints */
        }

      if(event.key.keysym.sym==SDLK_SPACE && (event.key.keysym.mod&KMOD_CTRL))
        return(RK_CTRLSPACE);
         
      /* the rest can be dealt with the Unicode mapping + alt stuff */
      key=(event.key.keysym.unicode&0x7f);
      if(event.key.keysym.mod&(KMOD_ALT|KMOD_META))
        key+=128;
      
      return(key);
    
    case SDL_QUIT:
      /* XXX how to handle this? */
      break;
      
    default:
      break;
    }
  }

return(RK_NO_KEY);
}


int zgv_io_waitkey(void)
{
int ret;

while((ret=zgv_io_readnbkey())==RK_NO_KEY)
  SDL_WaitEvent(NULL);

return(ret);
}

#endif      /* BACKEND_SDL */


#endif      /* !BACKEND_SVGALIB */

Generated by  Doxygen 1.6.0   Back to index