v10i082: xv - display and manipulate images, Part04/10
John Bradley
bradley at halibut.cis.upenn.edu
Wed Nov 28 07:08:20 AEST 1990
Submitted-by: bradley at halibut.cis.upenn.edu (John Bradley)
Posting-number: Volume 10, Issue 82
Archive-name: xv/part04
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./xvpbm.c`
then
echo "writting ./xvpbm.c"
cat > ./xvpbm.c << '\BARFOO\'
/*
* xvpbm.c - load routine for 'pm' format pictures
*
* LoadPBM(fname, numcols) - loads a PBM, PGM, or PPM file
* WritePBM(fp,pic,w,h,r,g,b,numcols,style,raw,cmt)
*/
/*
* Copyright 1989, 1990 by the University of Pennsylvania
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* The software may be modified for your own purposes, but modified versions
* may not be distributed.
*
* This software is provided "as is" without any express or implied warranty.
*/
#include "xv.h"
/* comments on error handling:
a truncated file is not considered a Major Error. The file is loaded, the
rest of the pic is filled with 0's.
a file with garbage characters in it is an unloadable file. All allocated
stuff is tossed, and LoadPBM returns non-zero
not being able to malloc is a Fatal Error. The program is aborted. */
#define TRUNCSTR "File appears to be truncated."
static int garbage;
static long numgot, filesize;
static int loadpbm(), loadpgm(), loadppm();
static int getint(), getbit(), PBMerr();
/*******************************************/
int LoadPBM(fname,nc)
char *fname;
int nc;
/*******************************************/
{
FILE *fp;
int c, c1;
int w, h, maxv, rv;
garbage = maxv = 0;
/* open the stream, if necesary */
fp=fopen(fname,"r");
if (!fp) return 1;
/* figure out the file size (for Informational Purposes Only) */
fseek(fp, 0L, 2);
filesize = ftell(fp);
fseek(fp, 0L, 0);
/* read the first two bytes of the file to determine which format
this file is. "P1" = ascii bitmap, "P2" = ascii greymap,
"P3" = ascii pixmap, "P4" = raw bitmap, "P5" = raw greymap,
"P6" = raw pixmap */
c = getc(fp); c1 = getc(fp);
if (c!='P' || c1<'1' || c1>'6') return(PBMerr("unknown format"));
/* read in header information */
w = getint(fp); h = getint(fp);
/* if we're not reading a bitmap, read the 'max value' */
if ( !(c1=='1' || c1=='4')) {
maxv = getint(fp);
if (maxv < 1) garbage=1; /* to avoid 'div by zero' probs */
}
if (garbage) {
if (fp!=stdin) fclose(fp);
return (PBMerr("Garbage characters in header."));
}
rv = 0;
/* call the appropriate subroutine to handle format-specific stuff */
if (c1=='1' || c1=='4') rv = loadpbm(fp,w,h, c1=='4' ? 1 : 0);
else if (c1=='2' || c1=='5') rv = loadpgm(fp,w,h, maxv, c1=='5' ? 1 : 0);
else if (c1=='3' || c1=='6') rv = loadppm(fp,w,h, maxv, c1=='6' ? 1 : 0, nc);
if (fp!=stdin) fclose(fp);
return(rv);
}
/*******************************************/
static int loadpbm(fp, w, h, raw)
FILE *fp;
int w,h,raw;
{
byte *pix;
int i,j,bit;
SetISTR(ISTR_FORMAT,"PBM, %s format. (%ld bytes)",
(raw) ? "raw" : "ascii", filesize);
/* load up the XV global variables */
pic = (byte *) calloc(w*h,1);
if (!pic) FatalError("couldn't malloc 'pic'");
pWIDE = w; pHIGH = h;
/* B/W bitmaps have a two entry colormap */
r[0] = g[0] = b[0] = 255; /* 0 = white */
r[1] = g[1] = b[1] = 0; /* 1 = black */
if (!raw) {
numgot = 0;
for (i=0, pix=pic; i<h; i++)
for (j=0; j<w; j++, pix++)
*pix = getbit(fp);
if (numgot != w*h) PBMerr(TRUNCSTR);
if (garbage) {
free(pic);
return(PBMerr("Garbage characters in image data."));
}
}
else { /* read raw bits */
int trunc = 0, k = 0;
for (i=0, pix=pic; i<h; i++)
for (j=0,bit=0; j<w; j++, pix++, bit++) {
bit &= 7;
if (!bit) {
k = getc(fp);
if (k==EOF) { trunc=1; k=0; }
}
*pix = (k&0x80) ? 1 : 0;
k = k << 1;
}
if (trunc) PBMerr(TRUNCSTR);
}
return 0;
}
/*******************************************/
static int loadpgm(fp, w, h, maxv, raw)
FILE *fp;
int w,h,maxv,raw;
{
byte *pix;
int i,j,bitshift;
SetISTR(ISTR_FORMAT,"PGM, %s format. (%ld bytes)",
(raw) ? "raw" : "ascii", filesize);
/* load up the XV global variables */
pic = (byte *) calloc(w*h,1);
if (!pic) FatalError("couldn't malloc 'pic'");
pWIDE = w; pHIGH = h;
/* if maxv>255, keep dropping bits until it's reasonable */
bitshift = 0;
while (maxv>255) { maxv = maxv>>1; bitshift++; }
/* fill in a greyscale colormap where maxv maps to 255 */
for (i=0; i<=maxv; i++)
r[i] = g[i] = b[i] = (i*255)/maxv;
if (!raw) {
numgot = 0;
for (i=0, pix=pic; i<h; i++)
for (j=0; j<w; j++, pix++)
*pix = (getint(fp) >> bitshift);
}
else numgot = fread(pic, 1, w*h, fp); /* read raw data */
if (numgot != w*h) PBMerr(TRUNCSTR);
if (garbage) {
free(pic);
return (PBMerr("Garbage characters in image data."));
}
return 0;
}
/*******************************************/
static int loadppm(fp, w, h, maxv, raw, nc)
FILE *fp;
int w,h,maxv,raw,nc;
{
byte *pix, *pic24, scale[256];
int i,j,bitshift;
SetISTR(ISTR_FORMAT,"PPM, %s format. (%ld bytes)",
(raw) ? "raw" : "ascii", filesize);
/* allocate 24-bit image */
pic24 = (byte *) calloc(w*h*3,1);
if (!pic24) FatalError("couldn't malloc 'pic24'");
/* if maxv>255, keep dropping bits until it's reasonable */
bitshift = 0;
while (maxv>255) { maxv = maxv>>1; bitshift++; }
if (!raw) {
numgot = 0;
for (i=0, pix=pic24; i<h; i++)
for (j=0; j<w*3; j++, pix++)
*pix = (getint(fp) >> bitshift);
}
else numgot = fread(pic24, 1, w*h*3, fp); /* read raw data */
if (numgot != w*h*3) PBMerr(TRUNCSTR);
if (garbage) {
free(pic24);
return(PBMerr("Garbage characters in image data."));
}
/* have to scale all RGB values up (Conv24to8 expects RGB values to
range from 0-255 */
if (maxv<255) {
for (i=0; i<=maxv; i++) scale[i] = (i * 255) / maxv;
for (i=0, pix=pic24; i<h; i++)
for (j=0; j<w*3; j++, pix++)
*pix = scale[*pix];
}
i = Conv24to8(pic24,w,h,nc);
free(pic24);
return i;
}
/*******************************************/
static int getint(fp)
FILE *fp;
{
int c, i;
/* skip forward to start of next number */
c = getc(fp);
while (1) {
/* eat comments */
if (c=='#') { /* if we're at a comment, read to end of line */
while (c != '\n' && c != EOF) c=getc(fp);
}
if (c==EOF) return 0;
if (c>='0' && c<='9') break; /* we've found what we were looking for */
/* see if we are getting garbage (non-whitespace) */
if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=',') garbage=1;
c = getc(fp);
}
/* we're at the start of a number, continue until we hit a non-number */
i = 0;
while (1) {
i = (i*10) + (c - '0');
c = getc(fp);
if (c==EOF) return i;
if (c<'0' || c>'9') break;
}
numgot++;
return i;
}
/*******************************************/
static int getbit(fp)
FILE *fp;
{
int c;
/* skip forward to start of next number */
c = getc(fp);
while (1) {
/* eat comments */
if (c=='#') { /* if we're at a comment, read to end of line */
while (c != '\n' && c != EOF) c=getc(fp);
}
if (c==EOF) return 0;
if (c=='0' || c=='1') break; /* we've found what we were looking for */
/* see if we are getting garbage (non-whitespace) */
if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=',') garbage=1;
c = getc(fp);
}
numgot++;
return(c-'0');
}
/*******************************************/
static int PBMerr(st)
char *st;
{
SetISTR(ISTR_WARNING,st);
return 1;
}
/*******************************************/
int WritePBM(fp,pic,w,h,rmap,gmap,bmap,numcols,colorstyle,raw)
FILE *fp;
byte *pic;
int w,h;
byte *rmap, *gmap, *bmap;
int numcols, colorstyle, raw;
{
/* writes a PBM/PGM/PPM file to the already open stream
if (raw), writes as RAW bytes, otherwise writes as ASCII
'colorstyle' single-handedly determines the type of file written
if colorstyle==0, (Full Color) a PPM file is written
if colorstyle==1, (Greyscale) a PGM file is written
if colorstyle==2, (B/W stipple) a PBM file is written */
int magic;
byte *pix;
int i,j,len;
/* calc the appropriate magic number for this file type */
magic = 0;
if (colorstyle==0) magic = 3;
else if (colorstyle==1) magic = 2;
else if (colorstyle==2) magic = 1;
if (raw && magic) magic+=3;
if (!magic) return(PBMerr("WritePBM: unknown file format"));
/* write the header info */
fprintf(fp,"P%d\n",magic);
fprintf(fp,"# created by 'xv %s'\n", namelist[curname]);
fprintf(fp,"%d %d\n",w,h);
if (colorstyle!=2) fprintf(fp,"255\n");
if (ferror(fp)) return -1;
/* write the image data */
if (colorstyle==0) { /* 24bit RGB, 3 bytes per pixel */
for (i=0, pix=pic, len=0; i<h; i++)
for (j=0; j<w; j++,pix++) {
if (raw) {
putc(r[*pix],fp);
putc(g[*pix],fp);
putc(b[*pix],fp);
}
else {
fprintf(fp,"%3d %3d %3d ",r[*pix], g[*pix], b[*pix]);
len+=12;
if (len>58) { fprintf(fp,"\n"); len=0; }
}
}
}
else if (colorstyle==1) { /* 8-bit greyscale */
byte rgb[256];
for (i=0; i<numcols; i++) rgb[i] = MONO(rmap[i],gmap[i],bmap[i]);
for (i=0, pix=pic, len=0; i<w*h; i++,pix++) {
if (raw) putc(rgb[*pix],fp);
else {
fprintf(fp,"%3d ",rgb[*pix]);
len += 4;
if (len>66) { fprintf(fp,"\n"); len=0; }
}
}
}
else if (colorstyle==2) { /* 1-bit B/W stipple */
int bit,k;
for (i=0, pix=pic, len=0; i<h; i++) {
for (j=0, bit=0, k=0; j<w; j++, pix++) {
if (raw) {
k = (k << 1) | *pix;
bit++;
if (bit==8) {
fputc(~k,fp);
bit = k = 0;
}
}
else {
if (*pix) fprintf(fp,"0 ");
else fprintf(fp,"1 ");
len+=2;
if (len>68) { fprintf(fp,"\n"); len=0; }
}
} /* j */
if (raw && bit) {
k = k << (8-bit);
fputc(~k,fp);
}
}
}
if (ferror(fp)) return -1;
return 0;
}
\BARFOO\
else
echo "will not over write ./xvpbm.c"
fi
if `test ! -s ./xvpm.c`
then
echo "writting ./xvpm.c"
cat > ./xvpm.c << '\BARFOO\'
/*
* xvpm.c - load routine for 'pm' format pictures
*
* LoadPM(fname, numcols) - loads a PM pic, does 24to8 code if nec.
* WritePM(fp, pic, w, h, r,g,b, numcols, style)
* WriteRaw(fp, pic, w, h, r,g,b, numcols, style)
*/
/*
* Copyright 1989, 1990 by the University of Pennsylvania
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* The software may be modified for your own purposes, but modified versions
* may not be distributed.
*
* This software is provided "as is" without any express or implied warranty.
*/
#include "xv.h"
#include "pm.h"
pmpic thePic;
static int PMError();
static void flipl();
/*******************************************/
int LoadPM(fname,nc)
char *fname;
int nc;
/*******************************************/
{
FILE *fp;
int isize,i,flipit,w,h,rv;
rv = 0;
thePic.pm_image = NULL;
/* read in the PM picture */
fp=fopen(fname,"r");
if (!fp) return( PMError("unable to open file") );
flipit = 0;
fread(&thePic,PM_IOHDR_SIZE,1,fp);
if (thePic.pm_id != PM_MAGICNO) {
flipl( (byte *) &thePic.pm_id);
if (thePic.pm_id == PM_MAGICNO) flipit = 1;
else flipl( (byte *) &thePic.pm_id);
}
if (thePic.pm_id != PM_MAGICNO) return( PMError("not a PM file") );
if (flipit) {
flipl((byte *) &thePic.pm_np); flipl((byte *) &thePic.pm_nrow);
flipl((byte *) &thePic.pm_ncol); flipl((byte *) &thePic.pm_nband);
flipl((byte *) &thePic.pm_form); flipl((byte *) &thePic.pm_cmtsize);
}
/* make sure that the input picture can be dealt with */
if ( thePic.pm_nband!=1 ||
(thePic.pm_form!=PM_I && thePic.pm_form!=PM_C) ||
(thePic.pm_form==PM_I && thePic.pm_np>1) ||
(thePic.pm_form==PM_C && (thePic.pm_np==2 || thePic.pm_np>4)) ) {
fprintf(stderr,"PM picture not in a displayable format.\n");
fprintf(stderr,"(ie, 1-plane PM_I, or 1-, 3-, or 4-plane PM_C)\n");
return 1;
}
w = thePic.pm_ncol; h = thePic.pm_nrow;
isize = pm_isize(&thePic);
if (DEBUG)
fprintf(stderr,"%s: LoadPM() - loading a %dx%d %s pic, %d planes\n",
cmd, w, h, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C",
thePic.pm_np);
SetISTR(ISTR_FORMAT,"PM, %s. (%d plane %s) (%d bytes)",
(thePic.pm_form==PM_I || thePic.pm_np>1) ?
"24-bit color" : "8-bit greyscale",
thePic.pm_np, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C",
isize + PM_IOHDR_SIZE + thePic.pm_cmtsize);
/* allocate memory for picture and read it in */
thePic.pm_image = (char *) malloc(isize);
if (thePic.pm_image == NULL)
return( PMError("unable to malloc PM picture") );
if (fread(thePic.pm_image, (unsigned) isize, 1, fp) != 1)
return( PMError("file read error") );
if (fp!=stdin) fclose(fp);
if (DEBUG) fprintf(stderr,"loadpm 1\n");
/* convert PM picture to 'pic' (8 bit) format */
if (thePic.pm_form == PM_I) {
int *intptr;
byte *pic24, *picptr;
if ((pic24 = (byte *) malloc(w*h*3))==NULL)
return( PMError("unable to malloc 24-bit picture") );
intptr = (int *) thePic.pm_image;
picptr = pic24;
if (flipit) { /* if flipit, integer is RRGGBBAA instead of AABBGGRR */
for (i=w*h; i>0; i--, intptr++) {
*picptr++ = (*intptr>>24) & 0xff;
*picptr++ = (*intptr>>16) & 0xff;
*picptr++ = (*intptr>>8) & 0xff;
}
}
else {
for (i=w*h; i>0; i--, intptr++) {
*picptr++ = (*intptr) & 0xff;
*picptr++ = (*intptr>>8) & 0xff;
*picptr++ = (*intptr>>16) & 0xff;
}
}
if (DEBUG) fprintf(stderr,"loadpm 2\n");
free(thePic.pm_image);
rv=Conv24to8(pic24,w,h,nc);
free(pic24);
}
else if (thePic.pm_form == PM_C && thePic.pm_np>1) {
byte *pic24, *picptr, *rptr, *gptr, *bptr;
if ((pic24 = (byte *) malloc(w*h*3))==NULL)
return( PMError("unable to malloc 24-bit picture") );
rptr = (byte *) thePic.pm_image;
gptr = rptr + w*h;
bptr = rptr + w*h*2;
picptr = pic24;
for (i=w*h; i>0; i--) {
*picptr++ = *rptr++;
*picptr++ = *gptr++;
*picptr++ = *bptr++;
}
free(thePic.pm_image);
rv=Conv24to8(pic24,w,h,nc);
free(pic24);
}
else if (thePic.pm_form == PM_C && thePic.pm_np==1) {
/* don't have to convert, just point pic at thePic.pm_image */
pic = (byte *) thePic.pm_image;
pWIDE = w; pHIGH = h;
for (i=0; i<256; i++) r[i]=g[i]=b[i]=i; /* and build mono colortable */
rv = 0;
}
return rv;
}
/*******************************************/
int WritePM(fp, pic, w, h, rmap, gmap, bmap, numcols, colorstyle)
FILE *fp;
byte *pic;
int w,h;
byte *rmap, *gmap, *bmap;
int numcols, colorstyle;
{
/* writes a PM file to the already open stream
'colorstyle' single-handedly determines the type of PM pic written
if colorstyle==0, (Full Color) a 3-plane PM_C pic is written
if colorstyle==1, (Greyscal) a 1-plane PM_C pic is written
if colorstyle==0, (B/W stipple) a 1-plane PM_C pic is written */
char foo[256];
int i;
byte *p;
/* create 'comment' field */
sprintf(foo,"created by 'xv %s'\n", namelist[curname]);
/* fill in fields of a pmheader */
thePic.pm_id = PM_MAGICNO;
thePic.pm_np = (colorstyle==0) ? 3 : 1;
thePic.pm_ncol = w;
thePic.pm_nrow = h;
thePic.pm_nband = 1;
thePic.pm_form = PM_C;
thePic.pm_cmtsize = strlen(foo);
if (fwrite(&thePic, PM_IOHDR_SIZE, 1, fp) != 1) return -1;
/* write the picture data */
if (colorstyle == 0) { /* 24bit RGB, organized as 3 8bit planes */
for (i=0,p=pic; i<w*h; i++, p++)
putc(rmap[*p], fp);
for (i=0,p=pic; i<w*h; i++, p++)
putc(gmap[*p], fp);
for (i=0,p=pic; i<w*h; i++, p++)
putc(bmap[*p], fp);
}
else if (colorstyle == 1) { /* GreyScale: 8 bits per pixel */
byte rgb[256];
for (i=0; i<numcols; i++) rgb[i] = MONO(rmap[i],gmap[i],bmap[i]);
for (i=0, p=pic; i<w*h; i++, p++)
putc(rgb[*p],fp);
}
else /* (colorstyle == 2) */ { /* B/W stipple. pic is 1's and 0's */
for (i=0, p=pic; i<w*h; i++, p++)
putc(*p ? 255 : 0,fp);
}
if (fputs(foo,fp)==EOF) return -1;
return 0;
}
/*****************************/
static int PMError(st)
char *st;
{
SetISTR(ISTR_WARNING,"LoadPM() - %s",cmd,st);
Warning();
if (thePic.pm_image != NULL) free(thePic.pm_image);
return -1;
}
/*****************************/
static void flipl(p)
byte *p;
{
byte t;
t = p[0]; p[0]=p[3]; p[3] = t;
t = p[1]; p[1]=p[2]; p[2] = t;
}
\BARFOO\
else
echo "will not over write ./xvpm.c"
fi
if `test ! -s ./xvscrl.c`
then
echo "writting ./xvscrl.c"
cat > ./xvscrl.c << '\BARFOO\'
/*
* xvscrl.c - Scroll Bar handling functions
*
* callable functions:
*
* SCCreate() - creates the Scroll Bar window.
* SCSetRange() - sets min/max/current values of control
* SCSetVal() - sets value of control
* SCRedraw() - redraws scroll bar
* SCTrack() - called when clicked. Operates control 'til mouseup
*/
/*
* Copyright 1989, 1990 by the University of Pennsylvania
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* The software may be modified for your own purposes, but modified versions
* may not be distributed.
*
* This software is provided "as is" without any express or implied warranty.
*/
#include "xv.h"
#include "bitmaps.h"
static Pixmap upPix, downPix; /* up/down arrows */
static Pixmap up1Pix, down1Pix; /* up/down arrows (lit up) */
static Pixmap sgray; /* gray stipple for lit scrollbar */
static int pixmaps_built=0; /* true if pixmaps created already */
/* scroll regions */
#define UPLINE 0
#define UPPAGE 1
#define DNLINE 2
#define DNPAGE 3
#define THUMB 4
#define SCRLWAIT 150 /* milliseconds to wait between scrolls */
/* local functions */
#ifdef __STDC__
static int whereInScrl(SCRL *, int, int);
static void drawArrow(SCRL *, int);
#else
static int whereInScrl();
static void drawArrow();
#endif
/***************************************************/
void SCCreate(sp, parent, x, y, vert, len, minv, maxv, curv, page,
fg, bg, func)
SCRL *sp;
Window parent;
int x,y,vert,len,minv,maxv,curv,page;
unsigned long fg,bg;
void (*func)();
{
if (!pixmaps_built) {
upPix = XCreatePixmapFromBitmapData(theDisp, parent,
up_bits, up_width, up_height, fg, bg, dispDEEP);
downPix = XCreatePixmapFromBitmapData(theDisp, parent,
down_bits, down_width, down_height, fg, bg, dispDEEP);
up1Pix = XCreatePixmapFromBitmapData(theDisp, parent,
up1_bits, up1_width, up1_height, fg, bg, dispDEEP);
down1Pix = XCreatePixmapFromBitmapData(theDisp, parent,
down1_bits, down1_width, down1_height,fg,bg,dispDEEP);
sgray = XCreatePixmapFromBitmapData(theDisp, parent,
scrlgray_bits, scrlgray_width, scrlgray_height,fg,bg,dispDEEP);
}
sp->vert = vert;
sp->len = len;
sp->fg = fg;
sp->bg = bg;
sp->uplit = sp->dnlit = 0;
if (vert)
sp->win = XCreateSimpleWindow(theDisp, parent,x,y,up_width-2,len,1,fg,bg);
else FatalError("don't know HOW to make horizontal scrollbar");
if (!sp->win) FatalError("can't create scrollbar window");
sp->tsize = up_width-2; /* really only if vertical */
sp->tmin = up_height-1;
sp->tmax = len - (up_height-1) - sp->tsize;
sp->drawobj = func;
SCSetRange(sp, minv, maxv, curv, page);
XSelectInput(theDisp, sp->win, ExposureMask | ButtonPressMask);
}
/***************************************************/
void SCSetRange(sp, minv, maxv, curv, page)
SCRL *sp;
int minv, maxv, curv, page;
{
if (maxv<minv) maxv=minv;
sp->min = minv; sp->max = maxv; sp->page = page;
sp->active = (minv < maxv);
/* adjust scroll bar background */
if (sp->active) XSetWindowBackgroundPixmap(theDisp, sp->win, sgray);
else XSetWindowBackground(theDisp, sp->win, sp->bg);
SCSetVal(sp, curv);
}
/***************************************************/
void SCSetVal(sp, curv)
SCRL *sp;
int curv;
{
RANGE(curv, sp->min, sp->max); /* make sure curv is in-range */
sp->val = curv;
if (sp->active)
sp->tpos = sp->tmin + ((sp->tmax - sp->tmin)*(curv - sp->min))
/ (sp->max - sp->min);
SCRedraw(sp);
(sp->drawobj)(); /* redraw whatever the scrollbar controls */
XFlush(theDisp);
}
/***************************************************/
void SCRedraw(sp)
SCRL *sp;
{
XSetForeground(theDisp, theGC, sp->fg);
XSetBackground(theDisp, theGC, sp->bg);
XClearWindow(theDisp, sp->win);
if (sp->vert) { /* draw up/down arrows */
drawArrow(sp,UPLINE);
drawArrow(sp,DNLINE);
if (sp->active) { /* a thumb is necessary */
XSetForeground(theDisp, theGC, sp->bg);
XFillRectangle(theDisp, sp->win, theGC,
1, sp->tpos+1, sp->tsize-2, sp->tsize-2);
XSetForeground(theDisp, theGC, sp->fg);
XDrawRectangle(theDisp, sp->win, theGC,
0, sp->tpos, sp->tsize-1, sp->tsize-1);
}
}
}
/***************************************************/
static int whereInScrl(sp,x,y)
SCRL *sp;
int x,y;
{
int v;
/* returns region # that x,y is in. Returns '-1' if none */
v=0;
if (sp->vert) {
if (x<0 || x>up_width-2 || y<0 || y>sp->len) return -1;
v = y;
}
/* once we know it's in scroll bar, only have to check 'v' versus len */
if (v < sp->tmin) return UPLINE;
if (sp->active) {
if (v < sp->tpos) return UPPAGE;
if (v < sp->tpos + sp->tsize) return THUMB;
if (v <= sp->tmax + sp->tsize) return DNPAGE;
}
if (v > sp->tmax+sp->tsize) return DNLINE;
return -1;
}
/***************************************************/
static void drawArrow(sp,arr)
SCRL *sp;
int arr;
{
/* only if vertical */
if (arr == UPLINE) {
if (sp->uplit)
XCopyArea(theDisp, up1Pix, sp->win,theGC,0,0,up_width,up_height,-1,-1);
else
XCopyArea(theDisp, upPix, sp->win,theGC,0,0,up_width,up_height,-1,-1);
}
else if (arr == DNLINE) {
if (sp->dnlit)
XCopyArea(theDisp, down1Pix,sp->win,theGC,0,0,up_width,up_height,
-1, sp->len-(up_height-1));
else
XCopyArea(theDisp, downPix, sp->win,theGC,0,0,up_width,up_height,
-1, sp->len-(up_height-1));
}
XFlush(theDisp);
}
/***************************************************/
void SCTrack(sp,mx,my)
SCRL *sp;
int mx,my;
{
Window rW,cW;
int rx,ry, x,y, ipos, pos, lit, ty, tyoff, ty1;
unsigned int mask;
/* determine in which of the five regions of the scroll bar the mouse
was clicked (upline, downline, uppage, downpage, thumb) */
ty = tyoff = 0;
XSetForeground(theDisp, theGC, sp->fg);
XSetBackground(theDisp, theGC, sp->bg);
/* light up appropriate bit of scroll bar */
ipos = whereInScrl(sp,mx,my);
lit = 1;
switch (ipos) {
case UPLINE: sp->uplit = 1;
if (sp->val > sp->min) SCSetVal(sp,sp->val-1);
Timer(SCRLWAIT);
break;
case DNLINE: sp->dnlit = 1;
if (sp->val < sp->max) SCSetVal(sp,sp->val+1);
Timer(SCRLWAIT);
break;
case UPPAGE: SCSetVal(sp,sp->val - sp->page); break;
case DNPAGE: SCSetVal(sp,sp->val + sp->page); break;
case THUMB: tyoff = sp->tpos - my;
ty = sp->tpos;
XSetState(theDisp, theGC, sp->fg, sp->bg, GXinvert,
sp->fg ^ sp->bg);
XDrawRectangle(theDisp,sp->win,theGC,
0, sp->tpos, sp->tsize-1, sp->tsize-1);
break;
}
/* VERTICAL CODE ONLY */
while (XQueryPointer(theDisp,sp->win,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
if (!(mask & Button1Mask)) break; /* button released */
switch (ipos) {
case THUMB:
/* do thumb tracking */
if (x<-16 || x>16+sp->tsize) { /* outside tracking range */
if (lit) {
lit = 0;
XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
}
}
else { /* inside tracking range */
if (!lit) { /* not lit, just turn on */
lit = 1;
ty = y + tyoff;
RANGE(ty, sp->tmin, sp->tmax);
XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
}
else { /* already lit, more the thumb */
ty1 = y+tyoff;
RANGE(ty1, sp->tmin, sp->tmax);
if (ty != ty1) { /* but only if mouse has moved */
XDrawRectangle(theDisp, sp->win, theGC,
0,ty,sp->tsize-1,sp->tsize-1);
ty = ty1;
XDrawRectangle(theDisp, sp->win, theGC,
0,ty,sp->tsize-1,sp->tsize-1);
}
}
}
break;
case UPLINE:
case DNLINE: /* arrows */
pos = whereInScrl(sp,x,y);
if (pos == ipos) {
if (!lit) {
lit = 1;
if (ipos == UPLINE) { sp->uplit = 1; drawArrow(sp,UPLINE); }
else { sp->dnlit = 1; drawArrow(sp,DNLINE); }
}
else {
if (sp->val > sp->min && pos==UPLINE) {
SCSetVal(sp, sp->val-1);
Timer(SCRLWAIT);
}
else if (sp->val < sp->max && pos==DNLINE) {
SCSetVal(sp, sp->val+1);
Timer(SCRLWAIT);
}
}
}
else {
if (lit) {
lit = 0;
if (ipos == UPLINE) { sp->uplit = 0; drawArrow(sp,UPLINE); }
else { sp->dnlit = 0; drawArrow(sp,DNLINE); }
}
}
break;
}
}
if (ipos == THUMB) {
if (lit) /* turn off */
XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
XSetState(theDisp, theGC, sp->fg, sp->bg, GXcopy, AllPlanes);
if (lit && ty != sp->tpos) { /* if thumb was moved, ROUND to new val */
int dt, dv;
dt = sp->tmax - sp->tmin;
dv = sp->max - sp->min;
SCSetVal(sp, sp->min + (dv*(ty - sp->tmin)+dt/2) / dt);
}
}
if (lit && ipos == UPLINE) { sp->uplit = 0; drawArrow(sp, UPLINE); }
if (lit && ipos == DNLINE) { sp->dnlit = 0; drawArrow(sp, DNLINE); }
}
\BARFOO\
else
echo "will not over write ./xvscrl.c"
fi
if `test ! -s ./xvxbm.c`
then
echo "writting ./xvxbm.c"
cat > ./xvxbm.c << '\BARFOO\'
/*
* xvxbm.c - load routine for X11 Bitmap format pictures
*
* LoadXBM(fname) - loads an X11 Bitmap file\
* WriteXBM(fp, pic, w, h)
*/
/*
* Copyright 1989, 1990 by the University of Pennsylvania
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* The software may be modified for your own purposes, but modified versions
* may not be distributed.
*
* This software is provided "as is" without any express or implied warranty.
*/
#include "xv.h"
/*
* File Format:
* (format identifier: "#define" as first couple chars in file)
*
* looks for first line beginning with '#define'
* reads "#define identifier width" (identifier is ignored)
* looks for next line beginning with '#define'
* reads "#define identifier height" (identifier is ignored)
* looks for next occurence of characters '0x'
* read next two chars as two hex digits
* move forward to next occurence of '0x'
* repeat
*/
static int XBMError();
/*******************************************/
int LoadXBM(fname,nc)
char *fname;
int nc;
/*******************************************/
{
FILE *fp;
int c, c1;
int i, j, k, bit, w, h;
byte *pix;
long filesize;
char line[256];
byte hex[256];
k = 0;
fp=fopen(fname,"r");
if (!fp) return 1;
/* figure out the file size (for Informational Purposes Only) */
fseek(fp, 0L, 2);
filesize = ftell(fp);
fseek(fp, 0L, 0);
/* read width: skip lines until we hit a #define */
while (1) {
if (!fgets(line,256,fp))
return(XBMError("EOF reached in header info."));
if (strncmp(line,"#define",7)==0) {
if (sscanf(line,"#define %*s %d", &w) != 1)
return(XBMError("Unable to read 'width'"));
else break;
}
}
/* read height: skip lines until we hit another #define */
while (1) {
if (!fgets(line,256,fp))
return(XBMError("EOF reached in header info."));
if (strncmp(line,"#define",7)==0) {
if (sscanf(line,"#define %*s %d", &h) != 1)
return(XBMError("Unable to read 'height'"));
else break;
}
}
/* scan forward until we see the first '0x' */
c = getc(fp); c1 = getc(fp);
while (c1!=EOF && !(c=='0' && c1=='x') ) { c = c1; c1 = getc(fp); }
if (c1==EOF)
return(XBMError("No bitmap data found"));
/* load up the stuff XV expects us to load up */
SetISTR(ISTR_FORMAT,"X11 Bitmap (%ld bytes)", filesize);
pic = (byte *) calloc(w*h,1);
if (!pic) FatalError("couldn't malloc 'pic'");
pWIDE = w; pHIGH = h;
/* B/W bitmaps have a two entry colormap */
r[0] = g[0] = b[0] = 255; /* 0 = white */
r[1] = g[1] = b[1] = 0; /* 1 = black */
/* initialize the 'hex' array for zippy ASCII-hex -> int conversion */
for (i=0; i<256; i++) hex[i]=0;
for (i='0'; i<='9'; i++) hex[i] = i - '0';
for (i='a'; i<='f'; i++) hex[i] = i + 10 - 'a';
for (i='A'; i<='F'; i++) hex[i] = i + 10 - 'A';
/* read/convert the image data */
for (i=0, pix=pic; i<h; i++)
for (j=0,bit=0; j<w; j++, pix++, bit = ++bit&7) {
if (!bit) {
/* get next byte from file. we're already positioned at it */
c = getc(fp); c1 = getc(fp);
if (c<0 || c1<0) {
/* EOF: break out of loop */
c=c1='0'; i=h; j=w;
XBMError("The file would appear to be truncated.");
}
k = (hex[c] << 4) + hex[c1];
/* advance to next '0x' */
c = getc(fp); c1 = getc(fp);
while (c1!=EOF && !(c=='0' && c1=='x') ) { c = c1; c1 = getc(fp); }
}
*pix = (k&1) ? 1 : 0;
k = k >> 1;
}
fclose(fp);
return 0;
}
/*******************************************/
static int XBMError(st)
char *st;
{
SetISTR(ISTR_WARNING,st);
return 1;
}
/*******************************************/
int WriteXBM(fp, pic, w, h, fname)
FILE *fp;
byte *pic;
int w,h;
char *fname;
{
/* pic is expected to be an array of w*h bytes. '0' is considered 'black'
non-zero is considered white. Some sort of stippling algorithm should've
been called already to produce pic, otherwise the output won't be at all
useful */
int i,j,k,bit,len,nbytes;
byte *pix;
char name[256], *foo;
/* figure out a reasonable basename */
strcpy(name,fname);
foo = strchr(name,'.');
if (foo) *foo='\0'; /* truncated name at first '.' */
fprintf(fp,"#define %s_width %d\n",name,w);
fprintf(fp,"#define %s_height %d\n",name,h);
fprintf(fp,"static char %s_bits[] = {\n",name);
fprintf(fp," ");
nbytes = h * ((w+7)/8); /* # of bytes to write */
for (i=0, len=1, pix=pic; i<h; i++) {
for (j=bit=k=0; j<w; j++,pix++) {
k = (k>>1);
if (*pix) k |= 0x80;
bit++;
if (bit==8) {
fprintf(fp,"0x%02x",(byte) ~k);
nbytes--; len += 4;
if (nbytes) { fprintf(fp,","); len++; }
if (len>72) { fprintf(fp,"\n "); len=1; }
bit = k = 0;
}
}
if (bit) {
k = k >> (8-bit);
fprintf(fp,"0x%02x",(byte) ~k);
nbytes--; len += 4;
if (nbytes) { fprintf(fp,","); len++; }
if (len>72) { fprintf(fp,"\n "); len=1; }
}
}
fprintf(fp,"};\n");
if (ferror(fp)) return -1;
return 0;
}
\BARFOO\
else
echo "will not over write ./xvxbm.c"
fi
echo "Finished archive 4 of 10"
exit
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
--
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list