/* Copyright: GNU GPL v2 */
/* Author: David Muse <dmuse@engr.latech.edu> 1997 */
#include <stdio.h>
#include <string.h>
#include <Xlib.h>
#include <Intrinsic.h>
#include <xpm.h>
#include <extensions/shape.h>
#include "surreal.xpm"
#include "purplestoneswirl.xpm"
#include "cd.xpm"
#include "zip.xpm"
#include "harddisk.xpm"
#include "unixfloppy.xpm"
#include "dosfloppy.xpm"
#include "nfs.xpm"
#include "dos.xpm"

struct XpmIcon {
	Pixmap		pixmap;
	Pixmap		mask;
	XpmAttributes	xpmattributes;
};

XtAppContext	application;
Widget	mainwidget;
Display	*display;
int	screen, screenwidth, screenheight;
Window	root, mainwindow, filewindow, mountwindow, mounterwin[24], iconwin[24];
Pixel	bgpixel, fgpixel, borderpixel, zeropixel, popupfgpixel, 
		popupbgpixel, popupborderpixel, redpixel, greenpixel, 
		yellowpixel;
GC	mainwindowgc, zerogc, flipgc, thingc, flipthingc, popupgc;
GC	translucentgc;
XGCValues	gcv;
unsigned	long	gcm;
int	interval, poppedup1=0, poppedup2=0;
char	bgcolor[100], fgcolor[100], bordercolor[100], zerocolor[100];
char	popupbgcolor[100], popupfgcolor[100], popupbordercolor[100];
char	bgpix[100], popupbgpix[100];
Pixmap	bgpixmap, canvas;
struct	XpmIcon	bgtexture, popupbgpixmap, *mounter[24];
XFontStruct	*popupfont1, *popupfont2;
int	fscounter, fstabcounter;
char	dfcommand[26],mountcmd[7],umountcmd[8];
int	fsflag=0;
int	showzero=0;
struct	XpmIcon	harddisk,dos,cd,nfs,unixfloppy,dosfloppy,zip;

struct	fsrecord {
			char	mountdir[1024];
			char	filesystem[1024];
			char	blocks[11];
			char	used[11];
			char	free[11];
			char	percent[4];
			int	x1, y1, x2, y2;
			int	mounted;
			int	user;
			char	type[12];
		};

struct	fsrecord	fs[24], fstab[24];

Pixel getcolor(char *colorname) {

	XColor	color;
	XWindowAttributes	attributes;
	
	XGetWindowAttributes(display, mainwindow, &attributes);
	color.pixel=0;

	XParseColor(display, attributes.colormap, colorname, &color);
	XAllocColor(display, attributes.colormap, &color);

	return color.pixel;
}

void	detect() {

	FILE	*tempfile;
	char	word[11];
	int	flag=0;
	
	/* figure out which "df -" command to use */
	unlink("/usr/tmp/statfs");
	system("df -Bk > /usr/tmp/statfs 2> /usr/tmp/statfs");
	tempfile=fopen("/usr/tmp/statfs", "r");
	fscanf(tempfile,"%s",word);
	if (!strcmp(word,"Filesystem")) {
		sprintf(dfcommand,"df -Bk > /usr/tmp/statfs");
	} else {
		system("df -a > /usr/tmp/statfs 2> /usr/tmp/statfs");
		tempfile=fopen("/usr/tmp/statfs", "r");
		fscanf(tempfile,"%s",word);
		if (!strcmp(word,"Filesystem")) {
			sprintf(dfcommand,"df -a > /usr/tmp/statfs");
		} else {
			fclose(tempfile);
			printf("No suitable df command found to determine filesystem usage\n");
			exit(0);
		}
	}
	fclose(tempfile);
	
	/* detect which filesystem description file to use */
	if ((tempfile=fopen("/etc/default/filesys","r"))!=NULL) {
		fsflag=1;
	} else if ((tempfile=fopen("/etc/fstab","r"))!=NULL) {
		fsflag=0;
	} else {
		fclose(tempfile);
		printf("No suitable filesystem description file (/etc/fstab) or /etc/default/filesys) found\n");
		exit(0);
	}
	fclose(tempfile);

	/* detect which user mount/unmount command to use */
	/* by giving umnt a bum parameter (-h) and seeing if it */
	/* returns anything about an illegal option or if it just says */
	/* command not found.  Different shells have different messages */
	/* for not finding a command, and which behaves differently too, */
	/* so this seems a reasonable way to do it. */
	system("umnt -h 2> /usr/tmp/testumnt");
	tempfile=fopen("/usr/tmp/testumnt", "r");
	if (tempfile!=NULL) {
		while(!feof(tempfile)) {
			fscanf(tempfile,"%s",word);
			if (!strcmp("option",word)) {
				/* the response must have been 
			 	umnt: ERROR: Illegal option -- h
			 	or something like it, the command exists */
				sprintf(mountcmd,"mnt ");
				sprintf(umountcmd,"umnt ");
				flag=1;
				break;
			}
		}
		fclose(tempfile);
	}

	if (flag==0) {
		/* otherwise, the mount/unmount commands must be used */
		sprintf(mountcmd,"mount ");
		sprintf(umountcmd,"umount ");
	}

	/* clean up */
	unlink("/usr/tmp/testumnt");
}

void	defaults1() {
	strcpy(bgcolor, "DarkSlateGray\0");
	strcpy(fgcolor, "LightSlateGray\0");
	strcpy(zerocolor, "IndianRed\0");
	strcpy(popupbgcolor, "DarkSlateGray\0");
	strcpy(popupfgcolor, "#20B2AA\0");
	strcpy(popupbordercolor, "LightGray\0");
	strcpy(bgpix, "default\0");
	strcpy(popupbgpix, "default\0");
	interval=3;
}

void	defaults2() {

	if (strcmp(bgpix,"None")) {
		bgtexture.xpmattributes.valuemask |= (XpmReturnPixels | 
							XpmReturnExtensions);
		if (!strcmp(bgpix,"default")) {
			XpmCreatePixmapFromData(display, mainwindow, 
					surreal_xpm,
					&bgtexture.pixmap, 
					&bgtexture.mask, 
					&bgtexture.xpmattributes);
		} else {
			XpmReadFileToPixmap(display, mainwindow, bgpix, 
					&bgtexture.pixmap, 
					&bgtexture.mask, 
					&bgtexture.xpmattributes);
		}
	}

	if (strcmp(popupbgpix,"None")) {
		popupbgpixmap.xpmattributes.valuemask |= (XpmReturnPixels | 
							XpmReturnExtensions);
		if (!strcmp(popupbgpix,"default")) {
			XpmCreatePixmapFromData(display, mainwindow, 
					purplestoneswirl_xpm,
					&popupbgpixmap.pixmap, 
					&popupbgpixmap.mask, 
					&popupbgpixmap.xpmattributes);
		} else {
			if (!strcmp(popupbgpix,"Transparent") ||
				!strcmp(popupbgpix,"Translucent")) {
				popupbgpixmap.pixmap=0;
			} else {
				XpmReadFileToPixmap(display, mainwindow, 
					popupbgpix, 
					&popupbgpixmap.pixmap, 
					&popupbgpixmap.mask, 
					&popupbgpixmap.xpmattributes);
			}
		}
	}
}

void	parsecmdline(int argc, char *argv[]) {

	char	*argument;
	int	i;

	for (i=1; i<argc; i++) {
		argument=argv[i];
		if (argument[0]=='-') {
			if (!strncmp(argument,"-showzero",9)) {
				showzero=1;
			}
			if (!strncmp(argument,"-bg",3)) {
				strcpy(bgcolor, argv[++i]);
			}
			if (!strncmp(argument,"-bp",3)) {
				strcpy(bgpix, argv[++i]);
			}
			if (!strncmp(argument,"-fg",3)) {
				strcpy(fgcolor, argv[++i]);
			}
			if (!strncmp(argument,"-bd",3)) {
				strcpy(bordercolor, argv[++i]);
			}
			if (!strncmp(argument,"-pbg",4)) {
				strcpy(popupbgcolor, argv[++i]);
			}
			if (!strncmp(argument,"-pbp",4)) {
				strcpy(popupbgpix, argv[++i]);
			}
			if (!strncmp(argument,"-pfg",4)) {
				strcpy(popupfgcolor, argv[++i]);
			}
			if (!strncmp(argument,"-pbd",4)) {
				strcpy(popupbordercolor, argv[++i]);
			}
			if (!strncmp(argument,"-z",2)) {
				strcpy(zerocolor, argv[++i]);
			}
			if (!strncmp(argument,"-i",2)) {
				interval=atoi(argv[++i]);
			}
		}
	}
}

void	setuppixmaps() {

	harddisk.xpmattributes.valuemask = (XpmReturnPixels | 
							XpmReturnExtensions);
	cd.xpmattributes.valuemask = (XpmReturnPixels | 
							XpmReturnExtensions);
	zip.xpmattributes.valuemask = (XpmReturnPixels | 
							XpmReturnExtensions);
	dos.xpmattributes.valuemask = (XpmReturnPixels | 
							XpmReturnExtensions);
	unixfloppy.xpmattributes.valuemask = (XpmReturnPixels | 
							XpmReturnExtensions);
	dosfloppy.xpmattributes.valuemask = (XpmReturnPixels | 
							XpmReturnExtensions);
	nfs.xpmattributes.valuemask = (XpmReturnPixels | 
							XpmReturnExtensions);

	XpmCreatePixmapFromData(display, mainwindow, harddisk_xpm,
					&harddisk.pixmap, 
					&harddisk.mask, 
					&harddisk.xpmattributes);
	XpmCreatePixmapFromData(display, mainwindow, dos_xpm,
					&dos.pixmap, 
					&dos.mask, 
					&dos.xpmattributes);
	XpmCreatePixmapFromData(display, mainwindow, cd_xpm,
					&cd.pixmap, 
					&cd.mask, 
					&cd.xpmattributes);
	XpmCreatePixmapFromData(display, mainwindow, nfs_xpm,
					&nfs.pixmap, 
					&nfs.mask, 
					&nfs.xpmattributes);
	XpmCreatePixmapFromData(display, mainwindow, unixfloppy_xpm,
					&unixfloppy.pixmap, 
					&unixfloppy.mask, 
					&unixfloppy.xpmattributes);
	XpmCreatePixmapFromData(display, mainwindow, dosfloppy_xpm,
					&dosfloppy.pixmap, 
					&dosfloppy.mask, 
					&dosfloppy.xpmattributes);
	XpmCreatePixmapFromData(display, mainwindow, zip_xpm,
					&zip.pixmap, 
					&zip.mask, 
					&zip.xpmattributes);

	if (strcmp(bgpix,"None")) {
		bgpixmap=bgtexture.pixmap;
	} else {
		bgpixmap=XCreatePixmap(display, mainwindow, 55, 57, 
				DefaultDepth(display, screen));
		XFillRectangle(display, bgpixmap, flipgc, 0, 0, 55, 57);
	}

	XDrawLine(display, bgpixmap, thingc, 0, 0, 56, 0);
	XDrawLine(display, bgpixmap, thingc, 1, 1, 55, 1);
	XDrawLine(display, bgpixmap, thingc, 2, 2, 54, 2);
	XDrawLine(display, bgpixmap, thingc, 0, 0, 0, 57);
	XDrawLine(display, bgpixmap, thingc, 1, 1, 1, 56);
	XDrawLine(display, bgpixmap, thingc, 2, 2, 2, 55);


	XDrawLine(display, bgpixmap, flipthingc, 54, 0, 54, 57);
	XDrawLine(display, bgpixmap, flipthingc, 53, 1, 53, 56);
	XDrawLine(display, bgpixmap, flipthingc, 52, 2, 52, 55);
	XDrawLine(display, bgpixmap, flipthingc, 0, 56, 54, 56);
	XDrawLine(display, bgpixmap, flipthingc, 1, 55, 53, 55);
	XDrawLine(display, bgpixmap, flipthingc, 2, 54, 52, 54);

	canvas=XCreatePixmap(display, mainwindow, 55, 57, 
				DefaultDepth(display, screen));

}

void	setupfonts() {

	popupfont1=XLoadQueryFont(display, 
			"-*-helvetica-*-*-*-*-10-240-*-*-*-*-*-*");
	popupfont2=XLoadQueryFont(display, 
			"-*-helvetica-medium-r-*-*-10-240-*-*-*-*-*-*");
}

void	readstatfile() {
	FILE	*tempfile;
	int	counter;
	char	dummy[21];

	tempfile=fopen("/usr/tmp/statfs", "r");
        if (tempfile!=NULL) {
		/* clear header */
		fscanf(tempfile,"%s%s%s%s%s%s%s",
				dummy, dummy, dummy, dummy, 
				dummy, dummy, dummy);
		/* read list */
		counter=0;
		while (1) {
			strcpy(fs[counter].mountdir,"");
			fscanf(tempfile,"%s%s%s%s%s%s",
				fs[counter].filesystem,
				fs[counter].blocks,
				fs[counter].used,
				fs[counter].free,
				fs[counter].percent,
				fs[counter].mountdir);
			if (strlen(fs[counter].mountdir)>0 && counter<23) {	
				if (atoi(fs[counter].blocks)>0 || showzero==1) {
					counter++;
				}
			} else {
				break;
			}
		}
		fclose(tempfile);
	
		fscounter=counter;
	} else {
		printf("\nWarning, /usr/tmp/statfs doesn't exist.\n");
	}
}

int	calclineheight(int num) {

	if (num>0) {
		return (50-num)/num;
	} else {
		printf("\nWarning, Line height defaulted to 1.\n");
		return 1;
	}
}

int	calclinewidth(struct fsrecord *fs, int y, int lineheight) {

	float	blocks, used, linewidth;

	blocks=(float)atoi(fs->blocks);
	if (blocks==0.0) {
		linewidth=48;
	} else {
		used=(float)atoi(fs->used);
		linewidth=(int)((used/blocks)*48.0);
	}

	/* set up fsrecord x,y's */
	fs->x1=0;
	fs->y1=y-(lineheight/2);
	fs->x2=linewidth;
	fs->y2=y+(lineheight/2);

	return linewidth;
}

void	checkusagecb(XtPointer XtP, XtIntervalId *XtI);

void	checkusage() {

	int	i, lineheight, y, linewidth;

		/* get a list of filesystems */
		system(dfcommand);

		readstatfile();

		/* restore canvas pixmap */
		XCopyArea(display, bgpixmap, canvas, mainwindowgc, 
				0, 0, 55, 57, 0, 0);

		/* calculate line height */
		lineheight=calclineheight(fscounter);

		XSetLineAttributes(display, mainwindowgc, lineheight, 
					LineSolid, CapButt, JoinRound);
		XSetLineAttributes(display, zerogc, lineheight, 
					LineSolid, CapButt, JoinRound);

		/* draw lines */
		y=1+(lineheight/2);
		for (i=0; i<fscounter; i++) {

			/* calculate line width */
			linewidth=calclinewidth(&fs[i], y, lineheight);

			/* draw new lines */
			if (atoi(fs[i].blocks)>0) {
				XDrawLine(display, canvas, mainwindowgc, 
					3, y+3, linewidth+3, y+3);
			} else {
				XDrawLine(display, canvas, zerogc, 
					3, y+3, linewidth+3, y+3);
			}

			if (lineheight>2 && linewidth>2) {
				if (atoi(fs[i].blocks)>0) {
					/* raised */
					XDrawLine(display, canvas, thingc,
						3, y+lineheight/2+3, 
						linewidth+3, y+lineheight/2+3);
					XDrawLine(display, canvas, flipthingc,
						3, y-lineheight/2+3, 
						linewidth+3, y-lineheight/2+3);
					XDrawLine(display, canvas, flipthingc,
						3, y+lineheight/2+3, 
						3, y-lineheight/2+3);
					XDrawLine(display, canvas, thingc,
						linewidth+3, y+lineheight/2+3, 
						linewidth+3, y-lineheight/2+3);
				} else {
					/* lowered */
					XDrawLine(display, canvas, flipthingc,
						3, y+lineheight/2+3, 
						linewidth+3, y+lineheight/2+3);
					XDrawLine(display, canvas, thingc,
						3, y-lineheight/2+3, 
						linewidth+3, y-lineheight/2+3);
					XDrawLine(display, canvas, thingc,
						3, y+lineheight/2+3, 
						3, y-lineheight/2+3);
					XDrawLine(display, canvas, flipthingc,
						linewidth+3, y+lineheight/2+3, 
						linewidth+3, y-lineheight/2+3);
				}
			}

			y=y+lineheight+1;
		}

		XCopyArea(display, canvas, mainwindow, mainwindowgc, 
				0, 0, 55, 57, 0, 0);

		/* get my stuff drawn, harmlessly */
		XPending(display);

		XtAppAddTimeOut(application, interval*1000, checkusagecb, NULL);
}

void	checkusagecb(XtPointer XtP, XtIntervalId *XtI) {

	checkusage();
}

void	translucent(Window win, int width, int height) {

	int	i;
	static	unsigned char		dotted[2]={ 1, 1 };

	gcm=GCForeground | GCLineStyle | GCCapStyle | 
				GCLineWidth;
	gcv.foreground=bgpixel;
	gcv.line_style=LineOnOffDash;
	gcv.cap_style=CapButt;
	gcv.line_width=1;
	translucentgc=XCreateGC(display, mainwindow, gcm, &gcv);
	XSetDashes(display, translucentgc, 0, dotted, 2);
	for (i=0; i<height; i++) {
		if (i%2==0) {
			XDrawLine(display, win, 
					translucentgc,
					0, i, width, i);
		} else {
			XDrawLine(display, win, 
					translucentgc,
					1, i, width, i);
		}
	}
	XFreeGC(display, translucentgc);
}

void	popdownmountwindow() {

	int i;

	if (poppedup2==1) {
		XDestroyWindow(display, mountwindow);
		poppedup2=0;
	}
}

void	popupfilewindow(struct fsrecord fs, int x, int y) {

	XSetWindowAttributes	setwinattr;
	int			winx, winy;
	unsigned long		pixel;

	if (poppedup1==0) {

		popdownmountwindow();
		
		poppedup1=2;

		if (x>=screenwidth/2) { 
			winx=x-12-177;
		} else {
			winx=x+12;
		}
	
		if (y>=screenheight/2) {
			winy=y-76;
		} else {
			winy=y;
		}
	 
		filewindow=XCreateSimpleWindow(display, root, winx, winy, 
						177, 76, 2, 
						popupborderpixel, popupbgpixel);
	
		setwinattr.override_redirect=True;
		if (strcmp(popupbgpix,"None")) {
			setwinattr.background_pixmap=popupbgpixmap.pixmap;
			XChangeWindowAttributes(display, filewindow, 
					CWOverrideRedirect | CWBackPixmap, 
					&setwinattr);
		} else {
			XChangeWindowAttributes(display, filewindow, 
					CWOverrideRedirect,
					&setwinattr);
		}
	
		XSetFont(display, popupgc, popupfont1->fid);
	
		XMapWindow(display, filewindow);
	
		if (!strcmp(popupbgpix,"Translucent")) {
			translucent(filewindow, 177, 76);
		}
	
		XDrawString(display, filewindow, popupgc, 2, 12, 
				"Mount Dir", 9);
		XDrawString(display, filewindow, popupgc, 2, 27, 
				"File System", 11);
		XDrawString(display, filewindow, popupgc, 2, 42, "Blocks", 6);
		XDrawString(display, filewindow, popupgc, 2, 57, "Free", 4);
		XDrawString(display, filewindow, popupgc, 2, 72, 
				"Percent Used", 12);
	
		XSetFont(display, popupgc, popupfont2->fid);
	
		XDrawString(display, filewindow, popupgc, 77, 12, fs.mountdir, 
				strlen(fs.mountdir));
		XDrawString(display, filewindow, popupgc, 77, 27, 
				fs.filesystem, 
				strlen(fs.filesystem));
		XDrawString(display, filewindow, popupgc, 77, 42, fs.blocks,
				strlen(fs.blocks));
		XDrawString(display, filewindow, popupgc, 77, 57, fs.free,
				strlen(fs.free));
		XDrawString(display, filewindow, popupgc, 77, 72, fs.percent,
				strlen(fs.percent));
	
		/* get my stuff drawn, harmlessly */
		XPending(display);
	
		poppedup1=1;
	}

}

void	readfstabfile() {

	int	i;
	FILE	*fstabfile;
	char	buffer[1024];
	char	filename[21];
	char	mntopts[1024];

	if (fsflag==1) {
		sprintf(filename,"/etc/default/filesys");
		fstabfile=fopen("/etc/default/filesys","r");
	} else if (fsflag==0) {
		sprintf(filename,"/etc/fstab");
		fstabfile=fopen("/etc/fstab","r");
	}

	fstabcounter=0;

	/* initiate buffer to strlen >0 */
	strcpy(buffer,"");
	
	if (fstabfile==NULL) {
		printf("The filesystem description file: %s couldn't be opened.\n",
			filename);
	}

	while (feof(fstabfile)==0 && fstabcounter<24) {

		buffer[0]=0;
	
		if (fsflag==1) {
			fscanf(fstabfile,"%s",buffer);
	
			if (!strncmp(buffer,"bdev=",5)) {
				strcpy(fstab[fstabcounter].filesystem, 
					buffer+5);
			}
	
			if (!strncmp(buffer,"mountdir=",9)) {
				strcpy(fstab[fstabcounter].mountdir, buffer+9);
			}
			
			if (!strncmp(buffer,"mount=yes",9)) {
				fstab[fstabcounter].user=1;
			}
			
			if (!strncmp(buffer,"mount=no",8)) {
				fstab[fstabcounter].user=0;
			}
			
			if (!strncmp(buffer,"fstyp=",6)) {
				strcpy(fstab[fstabcounter].type, buffer+6);
				fstabcounter++;
			}

		} else {
	
			/* get a line */
			i=0;
			sprintf(buffer,"%c",fgetc(fstabfile));
			while(buffer[i]!=10 && !feof(fstabfile)) {
				i++;
				if (!feof(fstabfile)) {
					sprintf(buffer,"%s%c",
						buffer,fgetc(fstabfile));
				}
			};

			if (!feof(fstabfile)) {
				if (buffer[0]!='#') {
					strcpy(fstab[fstabcounter].filesystem,
						"");
					strcpy(fstab[fstabcounter].mountdir,"");
					strcpy(fstab[fstabcounter].type,"");
					sscanf(buffer,"%s %s %s %s",
						fstab[fstabcounter].filesystem,
						fstab[fstabcounter].mountdir, 
						fstab[fstabcounter].type,
						mntopts);
					if (strlen(fstab[fstabcounter].
							filesystem)>0 &&
						strcmp(fstab[fstabcounter].
							type,"proc") &&
						strcmp(fstab[fstabcounter].
							type,"swap") &&
						strcmp(fstab[fstabcounter].
							type,"ignore")) {
						fstab[fstabcounter].user=0;
						if (strstr(mntopts,"user")!=
								NULL) {
							fstab[fstabcounter].
								user=1;
						}
						if (!strcmp(fstab[fstabcounter].
								mountdir,
								"none") ||
							!strcmp(fstab[
								fstabcounter].
								mountdir,
								"/") ||
							strstr(mntopts,
								"nouser")!=
								NULL) {
							fstab[fstabcounter].
								user=0;
						}
						fstabcounter++;
					}
				}
			}
		}

	}

	fclose(fstabfile);

}

int	mountstatus(int number) {

	int j, retval;
	
	for (j=0; j<fscounter; j++) {

		/* if the filesystem is mounted in the right direcrory... */
		if (!strcmp(fstab[number].filesystem,fs[j].filesystem) &&
			!strcmp(fstab[number].mountdir,fs[j].mountdir)) {

			retval=1;
			break;
		} else {
			retval=0;
		}
	}

	return retval;
}

void	mounterborder(int number) {
	if (fstab[number].user==1) {
		if (fstab[number].mounted==0) {
			XSetWindowBorder(display, mounterwin[number], redpixel);
		} else {
			XSetWindowBorder(display, mounterwin[number],
						greenpixel);
		}
	} else {
		XSetWindowBorder(display, mounterwin[number],
						yellowpixel);
	}
}

void	selectxpm(int i) {

	mounter[i]=&harddisk;
	if (!strcmp(fstab[i].type,"RCKRDG") || !strcmp(fstab[i].type,"iso9660") 
			|| !strcmp(fstab[i].type,"ISO9660")
			|| !strcmp(fstab[i].type,"hsfs")) {
		mounter[i]=&cd;
	} 
	if (strstr(fstab[i].filesystem,"zip")!=NULL) {
		mounter[i]=&zip;
	} 
	if (!strcmp(fstab[i].type,"NFS") || !strcmp(fstab[i].type,"nfs")) {
		mounter[i]=&nfs;
	}
	if (!strcmp(fstab[i].type,"DOS") || !strcmp(fstab[i].type,"msdos")) {
		mounter[i]=&dos;
	}
	if (strstr(fstab[i].filesystem,"fd")!=NULL) {
		mounter[i]=&unixfloppy;
	}
	if (strstr(fstab[i].filesystem,"fd")!=NULL && 
		(!strcmp(fstab[i].type,"DOS") || 
		!strcmp(fstab[i].type,"msdos"))) {
		mounter[i]=&dosfloppy;
	}
}

void	popupmountwindow(int x, int y) {

	XSetWindowAttributes	setwinattr;
	int			winx, winy, i, longest1, longest2, longest, 
				winwidth, winheight;
	int			posx, posy;
	unsigned long		pixel;
	static	unsigned char		dotted[2]={ 1, 1 };

	if (poppedup2==0) {

		poppedup2=2;

		readfstabfile();

		for (i=0; i<fstabcounter; i++) {
			fstab[i].mounted=mountstatus(i);
		}

		longest=0;
		longest1=0;
		longest2=0;

		/* find longest name */
		for (i=0; i<fstabcounter; i++) {
			if (strlen(fstab[i].filesystem)>
				strlen(fstab[longest1].filesystem)) {
				longest1=i;
			}
			if (strlen(fstab[i].mountdir)>
				strlen(fstab[longest2].filesystem)) {
				longest2=i;
			}
		}

		longest1=XTextWidth(popupfont1, fstab[longest1].filesystem, 
					strlen(fstab[longest1].filesystem));
		longest2=XTextWidth(popupfont2, fstab[longest2].mountdir,
					strlen(fstab[longest2].mountdir));
                longest=longest1;
		if (longest2>longest) { 
			longest=longest2;
		}

		if (longest<48) {
			longest=48;
		}

		winwidth=(((fstabcounter-1)/3)+1)*(longest+10);
		winheight=240;

		if (x>=screenwidth/2) { 
			winx=x-12-winwidth;
		} else {
			winx=x+12;
		}
	
		if (y>=screenheight/2) {
			winy=y-winheight;
		} else {
			winy=y;
		}
	 
		mountwindow=XCreateSimpleWindow(display, root, 
						winx, winy, 
						winwidth, winheight, 2,
						popupborderpixel, popupbgpixel);

		XSelectInput(display, mountwindow, ButtonPressMask);

		setwinattr.override_redirect=True;
		if (strcmp(popupbgpix,"None")) {
			setwinattr.background_pixmap=popupbgpixmap.pixmap;
			XChangeWindowAttributes(display, mountwindow, 
					CWOverrideRedirect | CWBackPixmap, 
					&setwinattr);
		} else {
			XChangeWindowAttributes(display, mountwindow, 
					CWOverrideRedirect,
					&setwinattr);
		}

		XMapWindow(display, mountwindow);
	
		if (!strcmp(popupbgpix,"Translucent")) {
			translucent(mountwindow, winwidth, winheight);
		}

		for (i=0; i<fstabcounter; i++) {
	
			XSetFont(display, popupgc, popupfont1->fid);

			posy=((i%3)*80);
			posx=((i/3)*(longest+10))+3;
	
			XDrawString(display, mountwindow, popupgc, 
				posx, posy+10, 
				fstab[i].filesystem, 
				strlen(fstab[i].filesystem));
	
			XSetFont(display, popupgc, popupfont2->fid);
	
			XDrawString(display, mountwindow, popupgc, 
				posx, posy+20, 
				fstab[i].mountdir, strlen(fstab[i].mountdir));
	 
			mounterwin[i]=XCreateSimpleWindow(display, mountwindow, 
						posx, posy+22, 
						48, 48, 2, 
						popupborderpixel, popupbgpixel);

			mounterborder(i);
			
			XSetWindowBackgroundPixmap(display, mounterwin[i], 0);

			XSelectInput(display, mounterwin[i], ButtonPressMask);
	 
			iconwin[i]=XCreateSimpleWindow(display, 
						mounterwin[i], 
						0, 0, 48, 48, 0,
						popupborderpixel, popupbgpixel);

			selectxpm(i);
			
			XSetWindowBackgroundPixmap(display, iconwin[i], 
					mounter[i]->pixmap);

			XShapeCombineMask(display, iconwin[i], ShapeBounding,
					0, 0, mounter[i]->mask, ShapeSet);

			XMapWindow(display, mounterwin[i]);
			XMapWindow(display, iconwin[i]);
		}
	
		/* get my stuff drawn, harmlessly */
		XPending(display);
	
		poppedup2=1;
	}

}

void	mountunmount(int number) {

	char buf[80];

	if (fstab[number].mounted==1) {
		sprintf(buf, "%s%s",umountcmd,fstab[number].mountdir);
		system(buf);
	} else {
		sprintf(buf, "%s%s",mountcmd,fstab[number].mountdir);
		system(buf);
	}
	checkusage();
	fstab[number].mounted=mountstatus(number);
	mounterborder(number);
}

void	popdownfilewindow() {

	if (poppedup1==1) {
		XDestroyWindow(display, filewindow);
		poppedup1=0;
	}
}

void	popdownfilewindowcb(Widget w, XtPointer unused, 
			register XButtonPressedEvent *event, 
			Boolean *continue_to_dispatch) {

	popdownfilewindow();
}

void	handleclick() {

	Window	dummy;
	int	rootx, rooty, winx, winy, i;
	unsigned	int	dummyui;
	int	lineheight, y, inaline=0;
	unsigned	int	mask;

	XQueryPointer(display, mainwindow, &dummy, &dummy,
			&rootx, &rooty, &winx, &winy, &mask);

	lineheight=calclineheight(fscounter);
	y=1+(lineheight/2);

	for (i=0; i<fscounter; i++) {

		calclinewidth(&fs[i], y, lineheight);

		if (winx>=fs[i].x1+3 && winx<=fs[i].x2+3 && 	
			winy>=fs[i].y1+3 && winy<=fs[i].y2+3) {

			popupfilewindow(fs[i], rootx, rooty);

			inaline=1;
		}

		y=y+lineheight+1;
	}

	if (inaline==0) {
		if (poppedup2==0) {
			popupmountwindow(rootx, rooty);
		} else {
			popdownmountwindow();
		}
	}
			
}

void	handleclickcb(Widget w, XtPointer unused, 
			register XButtonPressedEvent *event, 
			Boolean *continue_to_dispatch) {

	handleclick();
}

void	exitprogcb(Widget w, XtPointer unused, 
			register XButtonPressedEvent *event, 
			Boolean *continue_to_dispatch) {

	if (event->type==DestroyNotify) {

		XFreePixmap(display, harddisk.pixmap);
		XFreePixmap(display, dos.pixmap);
		XFreePixmap(display, cd.pixmap);
		XFreePixmap(display, nfs.pixmap);
		XFreePixmap(display, unixfloppy.pixmap);
		XFreePixmap(display, dosfloppy.pixmap);
		XFreePixmap(display, zip.pixmap);

		XFreePixmap(display, canvas);
		XFreePixmap(display, bgpixmap);
		XFreeGC(display, mainwindowgc);
		XFreeGC(display, flipgc);
		XFreeGC(display, thingc);
		XFreeGC(display, flipthingc);
		XFreeGC(display, popupgc);
		XDestroyWindow(display, mainwindow);
 		XCloseDisplay(display);
		unlink("/usr/tmp/statfs");
		exit(0);
	}
}

main (int argc, char *argv[]) {

	char	*displayname=NULL;
	XEvent	report;
	int	i, exposenum=0, j;
	XTextProperty	name;
	char	*winname="asfsm";

	detect();
	defaults1();
	parsecmdline(argc, argv);

	mainwidget=XtAppInitialize(&application, "asfsm", NULL, 0, &argc, argv, 
				NULL, NULL, 0);
	XtResizeWidget(mainwidget, 55, 57, 0);
	XtRealizeWidget(mainwidget);

	display=XtDisplay(mainwidget);

	screen=DefaultScreen(display);
	screenwidth=DisplayWidth(display, screen);
	screenheight=DisplayHeight(display, screen);

	root=RootWindow(display, screen);
	mainwindow=XtWindow(mainwidget);
	XtMapWidget(mainwidget);

	defaults2();

	bgpixel=getcolor(bgcolor);
	fgpixel=getcolor(fgcolor);
	zeropixel=getcolor(zerocolor);
	popupbgpixel=getcolor(popupbgcolor);
	popupfgpixel=getcolor(popupfgcolor);
	popupborderpixel=getcolor(popupbordercolor);
	redpixel=getcolor("IndianRed");
	greenpixel=getcolor("Aquamarine3");
	yellowpixel=getcolor("PeachPuff");

	gcm=GCForeground | GCBackground | GCGraphicsExposures;
	gcv.foreground=fgpixel;
	gcv.background=bgpixel;
	gcv.graphics_exposures=True;
	mainwindowgc=XCreateGC(display, mainwindow, gcm, &gcv);
	gcm=GCForeground;
	gcv.foreground=zeropixel;
	zerogc=XCreateGC(display, mainwindow, gcm, &gcv);
	gcm=GCForeground | GCBackground;
	gcv.background=fgpixel;
	gcv.foreground=bgpixel;
	flipgc=XCreateGC(display, mainwindow, gcm, &gcv);
	gcv.foreground=popupfgpixel;
	gcv.background=popupbgpixel;
	popupgc=XCreateGC(display, mainwindow, gcm, &gcv);
	gcm=GCForeground;
	gcv.foreground=getcolor("#535353");
	thingc=XCreateGC(display, mainwindow, gcm, &gcv);
	XSetLineAttributes(display, thingc, 1, 
				LineSolid, CapButt, JoinRound);
	gcv.foreground=getcolor("#dbdbdb");
	flipthingc=XCreateGC(display, mainwindow, gcm, &gcv);
	XSetLineAttributes(display, flipthingc, 1, 
				LineSolid, CapButt, JoinRound);

	setuppixmaps();
	setupfonts();
	checkusage();

	XtAddEventHandler(mainwidget, ButtonPressMask, False, 
				handleclickcb, NULL);

	XtAddEventHandler(mainwidget, ButtonReleaseMask, False, 
				popdownfilewindowcb, NULL);

	XtAddEventHandler(mainwidget, StructureNotifyMask, False, 
				exitprogcb, NULL);

	XPending(display);
	while (1) {
		
		XtAppNextEvent(application, &report);
		XtDispatchEvent(&report);
		if (poppedup2==1) {
			for (j=0; j<fstabcounter; j++) {
				if (report.type==ButtonPress && 
					report.xany.display==display &&
					report.xany.window==mounterwin[j]) {
					mountunmount(j);
				}
			}
		}
	}
}
