home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- ibrowse - Browse through a directory full of images.
-
- Tim Heidmann
- Version 1.2.2
- January 18, 1994
-
- copyright 1993, Silicon Graphics
- */
-
- #include <gl.h>
- #include <fmclient.h>
- #include <device.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/errno.h>
- #include <stdlib.h>
- #include <limits.h>
- #include <dirent.h>
- #include <math.h>
- #include <string.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <time.h>
- #include <sys/time.h>
- #include <sys/prctl.h>
- #include <signal.h> /* SIGKILL */
- #include "ibrowse.h"
-
- /* Colors */
- #define ICON_BG 0xff404040
- #define ICON_FRAME 0xff0000a0
- #define ICON_TEXT 0xffffffff
- #define ICON_DROP 0xff181818
- #define ICON_ACTIVE 0xff00ffff
- #define INFO_BG 0xff808080
- #define INFO_NAME 0xff000000
- #define INFO_TEXT 0xff404040
- #define INFO_FRAME 0xff000000
- #define SCROLL_BG 0xff202020
- #define SCROLL_FRAME 0xff000000
- #define SCROLL_THUMB 0xffa0a0a0
-
- #define FDTIME(a,b) \
- ((a).tv_sec - (b).tv_sec + 0.000001 * ((a).tv_usec - (b).tv_usec))
-
- /*
- * Image driver routines. Add to this list to recognize new image types.
- */
- int Check_SGI(struct iconDirStruct *ids, int fd);
- int Iconify_SGI(struct iconDirStruct *ids, unsigned long *ip);
- char *Info_SGI(struct iconDirStruct *ids, char *buf);
- void Open_SGI(struct iconDirStruct *ids);
-
- #ifdef IL
- int Check_IL(struct iconDirStruct *ids, int fd);
- int Iconify_IL(struct iconDirStruct *ids, unsigned long *ip);
- char *Info_IL(struct iconDirStruct *ids, char *buf);
- void Open_IL(struct iconDirStruct *ids);
- #endif
-
- struct ImageFnStruct ImageFn[] = {
- 1001, Check_SGI, Iconify_SGI, Info_SGI, Open_SGI
-
- #ifdef IL
- , 1002, Check_IL, Iconify_IL, Info_IL, Open_IL
- #endif
- };
- int nImageTypes = sizeof(ImageFn) / sizeof(struct ImageFnStruct);
-
-
- /*****************************************************************************
- *
- * Just a few global variables...
- *
- *****************************************************************************/
-
- /* Arguments and flags */
- char *cmdName; /* Name by which this program was invoked. */
- char *argDirName; /* Pointer to opt command line directory arg. */
- int neverWriteIconFiles; /* -n flag: inhibits writing icon files. */
- int updateOnlyFlag; /* -u flag: update icon files offline. No UI. */
- int useIconFiles; /* -f <name>: browse icon file. Don't scan dir*/
- char *iconRootName; /* Pointer to icon file root name argument. */
- int switchModes; /* Switch between single/dbl buffer mode? */
-
- /* Environment variables passed to shell Open commands */
- char envName[MAXNAMLEN+32] = "";
- char envCurDir[PATH_MAX+32] = "";
- char envOrigDir[PATH_MAX+32] = "";
- char envModifier[32] = "";
- char envRootName[MAXNAMLEN+32] = "";
-
- /* Directory file info */
- #define MAXDIRENTS 2048
- int nDirEnts;
- struct iconDirStruct *myDirList[MAXDIRENTS];
- /* In-memory list of all files in directory. */
-
- int iconDirFD, iconFD;
- char theDirName[MAXNAMLEN+1]; /* Full pathname of current browse directory. */
- char newDirName[MAXNAMLEN+1]; /* Relative name of directory to switch to. */
- char origDirName[MAXNAMLEN+1]; /* Pathname of working directory on startup. */
- int canWriteIconFiles; /* Are icon files writable. */
- int nIconFileEnts; /* Number fo slots in icon file. */
- int iconRef[MAXDIRENTS]; /* Is icon file slot in use. */
-
- /* Display list info */
- int displayList[MAXICONS]; /* Order icons appear on the screen. */
- int nIcons = 0; /* How many icons have been found. */
- int nDisplayIcons = 0; /* How many icons are in display list. */
- unsigned long *(icons[MAXICONS]);
- /* Pointers to icon bitmaps in memory. */
- char *fontNameList[] = {"Rock", "Screen"};
- int iconFontSizeList[] = { 12, 12};
- int infoFontSizeList[] = { 18, 18};
- int nFonts = sizeof(fontNameList) / sizeof(char *);
- fmfonthandle iconFont, infoFont;
-
- /* Window position, size, view info */
- long win_sx, win_sy, win_ox, win_oy;
- int icon_nx = -1, icon_ny, icon_sx, icon_sy;
- int icon_xmargin = 40, icon_ymargin = 30;
- int scroll_bar_width = 20, scroll_bar_height;
- int scroll_thumb_min_height = 20, scroll_thumb_top, scroll_thumb_bottom;
- int info_left_margin = 20, info_line_space = 20;
- int info_area_height = 130;
- int icon_field_height, icon_field_top;
- int iFirstVisible = 0, iLastVisible;
-
- /* Interaction state */
- #define DBL_CLICK 0.5
- #define EVENTUALLY 1.0
- #define MAXMENULINES 30
- #define MAXROLLOVERS 5
- int isScrolling = FALSE;
- int scroll_start_y, scroll_start_ift;
- float scroll_factor;
- int activeIcon = -1; /* Which icon is highlighted? */
- int newActiveIcon; /* Icon cursor is over - needs hilite. */
- struct timeval lastClick = {0,0}, lastDraw = {0,0};
- int windowActive; /* Is the cursor in the window? */
- int smoothScrolling = TRUE;
- long mainMenu, directoryMenu[MAXROLLOVERS];
- int directoryList[MAXDIRENTS]; /* Index to all directories in myDirList. */
- int nDirList = 0; /* # of sub-directories in menu. */
- int nBusyDirList = 0; /* # of sub-directories currently counted.*/
- #define MAXANCESTORS 512
- char *ancestorList[MAXANCESTORS]; /* Ptrs to each dir name in theDirName. */
- int ancestorLen[MAXANCESTORS]; /* Length of each dir name. */
- int nAncestors = 0; /* # of ancestor-directories. */
- int modKeys = 0; /* Current state of all the modifier keys */
- #define SETBIT(v, b, f) {(v)&=~((int)b); if (f) (v)|=((int)b);}
-
- /* Idle processing */
- int readerPID;
- enum {Before, ReadDir, Register, CheckTimes, Checking, ReadIcons, Iconifying,
- Compacting, SaveFiles, Done}
- idleMode = Before;
- int idleFile = 0;
- DIR *theDir; /* Used for CheckTimes */
-
-
- /* Program operation flags - set by reader and display processes,
- * checked and cleared by display process.
- */
- int needToResize, /* Window size may have changed. */
- needToDraw, /* Need to redraw on next cycle. */
- needToDrawEventually, /* Redraw before too long. */
- needToDrawActive, /* Current highlighted icon has changed. */
- /* Set by display process, checked and cleared by reader process. */
- needToSwitch = FALSE, /* New directory name in newDirName. */
- needToFinish = FALSE, /* Close down shop for exiting. */
- needToReadQuick = FALSE, /* Visible icon needs to be read. */
- needToIconifyQuick = FALSE, /* Visible icon needs to be created. */
- /* Set by reader process, checked and cleared by display process. */
- switchDone, /* State switched, okay to proceed. */
- okayToFinish, /* All finished, okay to exit. */
- needToUpdateDirectory = FALSE, /* Need to remake Change Directory menu. */
- needToCount, /* nIcons may have changed. Reformat. */
- /* Set, checked, and cleared by reader process. */
- needToWriteDirFile; /* dir list entry has been marked dirty. */
-
-
-
- /* Forward definitions - display/interaction process */
- void ParseArgs(int c, char *v[]);
- void Usage();
- void InitGfx();
- void SizeWindow();
- void SizeScrollBar();
- void LimitScrollBar();
- void MakeMenu();
- void MakeDirMenu(int depth, int iStart, int nEnts);
- void ChangeDirectory(char *name);
- void GetAncestors(char *thePath);
- void DoLeftMouse(int val);
- int WhichIcon(int x, int y);
- void SetEnvVars(struct iconDirStruct *ids);
- int DoMenu();
- int SortDisplayList(int (*fn)(int *, int *));
- int CmpDirName(int *d1, int *d2);
- int CmpDirDate(int *d1, int *d2);
- int CmpDirSize(int *d1, int *d2);
- void DoInputChange(int val);
- void DoTheWork();
- void Redraw();
- void WhereIsIcon(int iDList, int *icon_i, int *icon_j, int *xsize, int *ysize,
- int *xoff, int *yoff, int *xorg, int *yorg);
- void DrawIcon(int iDList);
- void DrawIconInfo();
- void Commafy(char *s, int n);
- void DrawGenericInfo();
- void DrawScrollBar();
- void RedrawActive();
-
- /* Forward definitions - Reader process */
- void IdleLoop();
- void IdleProcess();
- void StartDirectory(char *name);
- void FinishDirectory();
- void WriteDirFile();
- void WriteDirEnt(int iEnt);
- void FileIdleLoop();
- void FileIdleProcess();
- void OpenIconFiles();
- void StartReadDir();
- int ProcessReadDir();
- void StartRegister();
- int ProcessRegister();
- void StartCheckTimes();
- int ProcessCheckTimes();
- void StartChecking();
- int ProcessChecking();
- void StartReadIcons();
- int ProcessReadIcons();
- void StartIconifying();
- int ProcessIconifying();
- void StartCompacting();
- int ProcessCompacting();
- void StartSaveFiles();
- int ProcessSaveFiles();
- void StartDone();
- void CheckFile(char *filename);
- int CheckImage(struct iconDirStruct *ids);
- void ImageToIcon(struct iconDirStruct *ids);
- void AddIcon(int iEnt);
- void AssignIcon(struct iconDirStruct *ids);
- void AllocateIcon(struct iconDirStruct *ids);
- void ReadIcon(struct iconDirStruct *ids);
- void WriteIcon(struct iconDirStruct *ids);
- char * GetStateName(int state);
- char * GetIdleModeName(int mode);
-
-
- static double PtoPfactor = -1;
-
- float pixtopoints(float npix)
- {
-
- if(PtoPfactor < 0.0)
- PtoPfactor = (72.0*getgdesc(GD_XMMAX)/25.4)/getgdesc(GD_XPMAX);
- return npix*PtoPfactor;
- }
-
- float pointstopix(float npoints)
- {
- if(PtoPfactor < 0.0)
- PtoPfactor = (72.0*getgdesc(GD_XMMAX)/25.4)/getgdesc(GD_XPMAX);
- return npoints/PtoPfactor;
- }
-
- /*****************************************************************************
- *
- * Controlling display and interaction process routines. Spawn the reader
- * process and communicate with it via flags, loop looking for events, handle
- * user interaction, redraw the display when necessary.
- *
- *****************************************************************************/
-
- main(int argc, char *argv[]) {
- short dev, val;
- int done;
-
- ParseArgs(argc, argv);
- InitGfx();
-
- prctl(PR_SETEXITSIG, SIGKILL); /* If one process dies, kill all. */
- if (useIconFiles)
- sproc(FileIdleLoop, PR_SALL);
- else {
- sproc(IdleLoop, PR_SALL);
- ChangeDirectory(argDirName);
- }
-
- if (updateOnlyFlag) {
- /* Skip the user interface and display. Wait for update to finish. */
- while (idleMode != Done) sginap(5);
-
- } else {
- /* Run fully interactive. */
- for (done = FALSE; !done; ) {
- /* Read all the pending events. */
- while (qtest()) {
- switch (dev = qread(&val)) {
- case ESCKEY:
- case QKEY:
- case WINQUIT:
- case WINCLOSE:
- case WINSHUT:
- done = TRUE; break;
-
- case LEFTMOUSE: DoLeftMouse(val); break;
- case RIGHTMOUSE: if (val && DoMenu()) done = TRUE; break;
- case REDRAW: needToResize = TRUE; break;
- case INPUTCHANGE: DoInputChange(val); break;
-
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY: SETBIT(modKeys, SHIFTKEYBIT, val); break;
- case LEFTCTRLKEY:
- case RIGHTCTRLKEY: SETBIT(modKeys, CTRLKEYBIT, val); break;
- case LEFTALTKEY:
- case RIGHTALTKEY: SETBIT(modKeys, ALTKEYBIT, val); break;
-
- default: break;
- }
- }
-
- /* Handle the events. */
- if (done) break;
- DoTheWork();
- }
- }
-
- /* Wait for reader process to clean up files and finish. */
- needToFinish = TRUE;
- while (!okayToFinish) sginap(1);
- }
-
-
- void
- ParseArgs(int c, char *v[]) {
- cmdName = v[0];
- argDirName = NULL;
- neverWriteIconFiles = FALSE;
- updateOnlyFlag = FALSE;
- useIconFiles = FALSE;
- getwd(origDirName);
-
- for (c--, v++; c > 0; c--, v++) {
- if (v[0][0] == '-') {
- /* Parse a command line option */
- switch (v[0][1]) {
- case 'n': /* Don't update .ibrowse files in this directory */
- neverWriteIconFiles = TRUE;
- break;
- case 's': /* Switch to singlebuffer mode when not scrolling. */
- switchModes = TRUE;
- break;
- case 'u': /* Update .ibrowse files. Don't run user interface. */
- updateOnlyFlag = TRUE;
- break;
- case 'f': /* Specify root name of .dir and .icon files to scan. */
- useIconFiles = TRUE;
- iconRootName = v[1];
- strcpy(theDirName, origDirName);
- c--, v++;
- break;
- default:
- Usage();
- }
- }
- else {
- /* Parse a directory name */
- if (argDirName != NULL) Usage();
- argDirName = v[0];
- }
- }
-
- /* Default to the current directory. */
- if (argDirName == NULL) argDirName = ".";
- }
-
- void
- Usage() {
- fprintf(stderr, "usage: %s [options] [<directory>]\n", cmdName);
- fprintf(stderr, "options:\n");
- fprintf(stderr, " -n Don't write icon files.\n");
- fprintf(stderr, " -s Switch to single-buffer mode when not "
- "scrolling.\n");
- fprintf(stderr, " -u Update icon files only. No display.\n");
- fprintf(stderr, " -f <name>\n");
- fprintf(stderr, " Browse <name>.dir and <name>.icon files. ");
- fprintf(stderr, "Don't scan directories.\n");
- exit(1);
- }
-
- void
- InitGfx() {
- int iFont, i;
- char title_buf[PATH_MAX + 64];
- int iconFontSize, infoFontSize;
- char fontName[128], *fontSpec;
- fmfonthandle theFont, theIconFont, theInfoFont;
-
- /* No graphics for update only */
- if (updateOnlyFlag) return;
-
- minsize(scroll_bar_width + 4*(ICONSIZE+icon_xmargin) + icon_xmargin,
- info_area_height + 1*(ICONSIZE+icon_ymargin) + icon_ymargin);
- stepunit(ICONSIZE + icon_xmargin, ICONSIZE + icon_ymargin);
- fudge(
- scroll_bar_width + ICONSIZE + 2 * icon_xmargin,
- info_area_height + ICONSIZE + 2 * icon_ymargin);
- if (useIconFiles)
- sprintf(title_buf, "%s %s", cmdName, iconRootName);
- else
- sprintf(title_buf, "%s %s", cmdName, theDirName);
- winopen(title_buf);
-
- minsize(0, 0);
- stepunit(ICONSIZE + icon_xmargin, ICONSIZE + icon_ymargin);
- fudge(
- scroll_bar_width + ICONSIZE + 2 * icon_xmargin,
- info_area_height + ICONSIZE + 2 * icon_ymargin);
- winconstraints();
-
- if (!switchModes) doublebuffer();
- RGBmode();
- gconfig();
- cpack(ICON_BG);
- clear();
- swapbuffers();
-
- getorigin(&win_ox, &win_oy);
- getsize(&win_sx, &win_sy);
- reshapeviewport();
- ortho2(0, win_sx-1, 0, win_sy-1);
- SizeWindow();
-
- qdevice(ESCKEY);
- qdevice(QKEY);
- qdevice(LEFTMOUSE);
- qdevice(RIGHTMOUSE);
- qdevice(LEFTSHIFTKEY); qdevice(RIGHTSHIFTKEY);
- qdevice(LEFTALTKEY); qdevice(RIGHTALTKEY);
- qdevice(LEFTCTRLKEY); qdevice(RIGHTCTRLKEY);
- qdevice(WINCLOSE);
- qdevice(WINQUIT);
- qdevice(WINSHUT);
- qenter(REDRAW, 0);
-
- fminit();
- /* Look for environment variable specs for the fonts to use */
- if ((fontSpec = getenv("IBROWSE_ICON_FONT")) != NULL) {
- iconFontSize = 12;
- sscanf(fontSpec, "%s %d", fontName, &iconFontSize);
- theFont = fmfindfont(fontName);
- iconFont = fmscalefont(theFont, pixtopoints(iconFontSize));
- }
- if ((fontSpec = getenv("IBROWSE_INFO_FONT")) != NULL) {
- infoFontSize = 18;
- sscanf(fontSpec, "%s %d", fontName, &infoFontSize);
- theFont = fmfindfont(fontName);
- infoFont = fmscalefont(theFont, pixtopoints(infoFontSize));
- }
-
- /* Supply default fonts if necessary */
- if (iconFont == 0 || infoFont == 0) {
- for (iFont = 0, theFont = 0; iFont < nFonts; iFont++)
- if ((theFont = fmfindfont(fontNameList[iFont])) != 0) {
- if (iconFont == 0) {
- iconFontSize = iconFontSizeList[iFont];
- iconFont = fmscalefont(theFont, pixtopoints(iconFontSize));
- }
- if (infoFont == 0) {
- infoFontSize = infoFontSizeList[iFont];
- infoFont = fmscalefont(theFont, pixtopoints(infoFontSize));
- }
- break;
- }
-
- if (theFont == 0) {
- fprintf(stderr, "Can't find any desirable fonts!\n");
- exit(1);
- }
- }
-
- mainMenu = newpup();
- for (i=0; i<MAXROLLOVERS; i++) directoryMenu[i] = newpup();
- MakeMenu();
- }
-
- void
- SizeWindow() {
- int old_icon_field_height;
-
- /* Set variables and graphics to reflect window of size win_sx by win_sy,
- with nIcons icons. */
- needToCount = FALSE;
- nDisplayIcons = nIcons;
- icon_sx = win_sx - scroll_bar_width;
- scroll_bar_height =
- icon_sy = win_sy - info_area_height;
- icon_nx = (icon_sx - icon_xmargin) / (ICONSIZE + icon_xmargin);
- if (icon_nx < 1) icon_nx = 1;
- icon_ny = (nDisplayIcons + icon_nx - 1) / icon_nx;
- old_icon_field_height = icon_field_height;
- icon_field_height = icon_ymargin +
- icon_ny * (ICONSIZE + icon_ymargin);
- if (icon_field_height != old_icon_field_height) {
- /* Layout has changed, pick a new distance from top to display. */
- icon_field_top = icon_field_height -
- (iFirstVisible / icon_nx) * (ICONSIZE + icon_ymargin);
- LimitScrollBar();
- }
- SizeScrollBar();
- }
-
- void
- SizeScrollBar() {
- int sb_hgt, ify, iRow;
-
- /* Calculate position and range of scroll bar thumb */
- scroll_thumb_top = info_area_height +
- (scroll_bar_height - scroll_thumb_min_height) *
- ((float) icon_field_top) / icon_field_height +
- scroll_thumb_min_height;
- sb_hgt = (scroll_bar_height - scroll_thumb_min_height) *
- ((float) icon_sy) / icon_field_height;
- scroll_thumb_bottom = scroll_thumb_top - sb_hgt - scroll_thumb_min_height;
- if (scroll_thumb_bottom < info_area_height)
- scroll_thumb_bottom = info_area_height;
-
- /* Calculate range of visible icons.
- ify is pixel distance into icon field from top of window. */
- ify = icon_field_height - icon_field_top;
- iRow = (ify - icon_ymargin) / (ICONSIZE + icon_ymargin);
- iFirstVisible = iRow * icon_nx;
- if (iFirstVisible < 0) iFirstVisible = 0;
- iRow = (ify - icon_ymargin + icon_sy) / (ICONSIZE + icon_ymargin);
- iLastVisible = (iRow + 1) * icon_nx - 1;
- if (iLastVisible >= nDisplayIcons) iLastVisible = nDisplayIcons - 1;
- }
-
- void
- LimitScrollBar() {
- /* Try for no empty space in the window below the icons... */
- if (icon_field_top < icon_sy)
- icon_field_top = icon_sy;
- /* ...but definitely no empty space in the window above the icons */
- if (icon_field_top > icon_field_height)
- icon_field_top = icon_field_height;
- }
-
-
- void
- MakeMenu() {
- freepup(mainMenu);
- mainMenu = defpup("Image Browser%t");
-
- /* Make the "Change Directory" Menu */
- if (!useIconFiles && (nAncestors > 0 || nDirList > 0)) {
- MakeDirMenu(0, 0, nAncestors + nDirList);
- addtopup(mainMenu, "Change Directory%m%l", directoryMenu[0]);
- }
-
- /* Allow picking some options */
- addtopup(mainMenu, "Sort by Name%x10");
- addtopup(mainMenu, "Sort by Size%x11");
- addtopup(mainMenu, "Sort by Date%x12%l");
- addtopup(mainMenu, !smoothScrolling ? "Smooth Scrolling On %x20%l" :
- "Smooth Scrolling Off%x21%l");
- addtopup(mainMenu, "About...%x90");
- addtopup(mainMenu, "Exit%x99");
- }
-
- void
- MakeDirMenu(int depth, int iStart, int nEnts) {
- int iEnt, nLocalEnts, i, iItem, isGray;
- char buf[MAXNAMLEN], buf2[MAXNAMLEN];
-
- freepup(directoryMenu[depth]);
- directoryMenu[depth] = newpup();
- nLocalEnts = nEnts > MAXMENULINES ? MAXMENULINES - 1 : nEnts;
- iItem = 1;
-
- /* Need rollover submenus to fit all the names? */
- if (nLocalEnts != nEnts && depth < MAXROLLOVERS) {
- MakeDirMenu(depth + 1, iStart + nLocalEnts, nEnts - nLocalEnts);
- addtopup(directoryMenu[depth], "more...%l%m", directoryMenu[depth + 1]);
- iItem++;
- }
-
- /* Add the names for this rollover */
- for (i = iStart; i < iStart + nLocalEnts; i++) {
- isGray = FALSE;
- if (i < nAncestors) {
- /* Make a menu item for an ancestor of the current directory */
- strncpy(buf2, ancestorList[i], ancestorLen[i]);
- buf2[ancestorLen[i]] = '\0';
- if (i == nAncestors - 1) {
- /* Last ancestor - the current directory. Gray it out. */
- sprintf(buf, "%s%%x%d%%l", buf2, 10000+i);
- isGray = TRUE;
- } else
- sprintf(buf, "%s%%x%d", buf2, 10000+i);
- } else
- /* Make a menu item for subdirectories of the current directory */
- sprintf(buf, "%s%%x%d",
- myDirList[directoryList[i - nAncestors]]->name,
- 100 + i - nAncestors);
-
- addtopup(directoryMenu[depth], buf);
- if (isGray) setpup(directoryMenu[depth], iItem, PUP_GREY);
- iItem++;
- }
- }
-
- void
- ChangeDirectory(char *name) {
- char buf[PATH_MAX];
-
- /* Clear out the Change Directory menu before switching */
- if (!updateOnlyFlag) {
- nAncestors = 0;
- nDirList = 0;
- MakeMenu();
- }
-
- /* Direct and wait for reader to close current, switch to new */
- strcpy(newDirName, name);
- switchDone = FALSE;
- needToSwitch = TRUE;
- while (!switchDone) sginap(5);
-
- /* Put current directory path in window title. Update directory menu. */
- if (!updateOnlyFlag) {
- sprintf(buf, "%s %s", cmdName, theDirName);
- wintitle(buf);
- GetAncestors(theDirName);
- MakeMenu();
- }
- }
-
- void
- GetAncestors(char *thePath) {
- /* Save pointers to each parent directory in the given pathname, plus its
- * length. Ptrs in ancestorList, len in ancestorLen, # in nAncestors.
- * "/" counts as one. Multiple /'s are ignored.
- * String is assumed to start with '/'.
- */
- ancestorList[0] = thePath;
- ancestorLen[0] = 1;
- nAncestors = 1;
- for (;;) {
- for (; *thePath == '/'; thePath++) ;
- if (*thePath == '\0') return;
-
- /* Mark the start of a new directory name and scan it all */
- ancestorList[nAncestors] = thePath;
- for (; *thePath != '\0' && *thePath != '/'; thePath++) ;
-
- /* End of name or end of path. Calc length and return or continue */
- ancestorLen[nAncestors] = thePath - ancestorList[nAncestors];
- nAncestors++;
- if (*thePath == '\0') return;
- }
- }
-
- void
- DoLeftMouse(int val) {
- int openIcon, mx, my;
- struct timeval thisTime;
- struct iconDirStruct *ids;
- char buf[PATH_MAX + 64];
- char *openCmd;
-
- if (val) {
- /* This is a left mouse button press.*/
- mx = getvaluator(MOUSEX) - win_ox;
- my = getvaluator(MOUSEY) - win_oy;
-
- if (my < info_area_height) {
- /* In the info area - do nothing */
-
- } else if (mx < scroll_bar_width) {
- /* In the scroll bar */
- if (icon_field_height < icon_sy) {
- /* Nowhere to scroll - do nothing */
- } else if (my < scroll_thumb_bottom) {
- /* In the space below the thumb */
- icon_field_top -= smoothScrolling ? icon_sy :
- (icon_sy/(ICONSIZE+icon_ymargin))*(ICONSIZE+icon_ymargin);
- LimitScrollBar();
- SizeScrollBar();
- needToDraw = TRUE;
- } else if (my > scroll_thumb_top) {
- /* In the space above the thumb */
- icon_field_top += smoothScrolling ? icon_sy :
- (icon_sy/(ICONSIZE+icon_ymargin))*(ICONSIZE+icon_ymargin);
- LimitScrollBar();
- SizeScrollBar();
- needToDraw = TRUE;
- } else {
- /* In the thumb itself - start scrolling */
- isScrolling = TRUE;
- scroll_start_y = my;
- scroll_start_ift = icon_field_top;
- scroll_factor = icon_field_height /
- (float) scroll_bar_height;
-
- /* Scroll in double buffer mode to avoid flicker */
- if (switchModes) {
- cpack(0);
- clear();
- doublebuffer();
- gconfig();
- }
- }
-
- } else {
- /* In the icon field */
- gettimeofday(&thisTime, NULL);
- openIcon = WhichIcon(mx, my);
- if (FDTIME(thisTime, lastClick) < DBL_CLICK
- && openIcon >= 0) {
- ids = myDirList[displayList[openIcon]];
- percentdone(50.0);
- SetEnvVars(ids);
- if ((openCmd = getenv("IBROWSE_OPEN_CMD")) != NULL)
- system(openCmd);
- else
- (*ImageFn[ids->iType].Open)(ids);
- percentdone(100.0);
- }
- lastClick = thisTime;
- }
-
- } else {
- /* This is a left mouse button release.*/
- if (isScrolling) {
- isScrolling = FALSE;
-
- /* Done scrolling. Go back to sngl buffer for best display. */
- if (switchModes) {
- singlebuffer();
- gconfig();
- needToDraw = TRUE;
- }
- }
- }
- }
-
- int
- WhichIcon(int x, int y) {
- int ifx, ify, iRow, iCol, iIcon;
-
- if (x < scroll_bar_width || y < info_area_height ||
- x > win_sx || y > win_sy)
- return -1;
-
- /* Which row and column? Is the cursor exactly on the icon? */
- /* ify is pixels down from top of icon field, ifx from left */
- ify = (win_sy - y) + (icon_field_height - icon_field_top);
- if (ify % (ICONSIZE + icon_ymargin) < icon_ymargin) return -1;
- iRow = ify / (ICONSIZE + icon_ymargin);
- ifx = x - scroll_bar_width;
- if (ifx % (ICONSIZE + icon_xmargin) < icon_xmargin) return -1;
- iCol = ifx / (ICONSIZE + icon_xmargin);
-
- /* Return index to display list element */
- iIcon = iRow * icon_nx + iCol;
- return (iIcon >= nIcons) ? -1 : iIcon;
- }
-
- void
- SetEnvVars(struct iconDirStruct *ids) {
- /* Set the shell environment variables passed to Open commands.
- * The environment variable strings are static variables since they
- * have to hang around for a while.
- */
- sprintf(envName, "IBROWSE_NAME=%s", ids->name);
- putenv(envName);
- sprintf(envCurDir, "IBROWSE_CUR_DIR=%s", theDirName);
- putenv(envCurDir);
- sprintf(envOrigDir, "IBROWSE_ORIG_DIR=%s", origDirName);
- putenv(envOrigDir);
- sprintf(envModifier, "IBROWSE_MODIFIERS=%d", modKeys);
- putenv(envModifier);
- sprintf(envRootName, "IBROWSE_ROOT_NAME=%s", useIconFiles?iconRootName:"");
- putenv(envRootName);
- }
-
- int
- DoMenu() {
- /* Return TRUE iff Exit is selected */
- int iMenu, flag;
- char buf[PATH_MAX];
-
- flag = FALSE;
- switch (iMenu = dopup(mainMenu)) {
- case 10: /* Sort Alphabetically */
- SortDisplayList(CmpDirName); needToDraw = TRUE;
- break;
- case 11: /* Sort by Size */
- SortDisplayList(CmpDirSize); needToDraw = TRUE;
- break;
- case 12: /* Sort by Age */
- SortDisplayList(CmpDirDate); needToDraw = TRUE;
- break;
-
- case 20: /* Smooth Scrolling On */
- smoothScrolling = TRUE;
- MakeMenu();
- break;
- case 21: /* Smooth Scrolling Off */
- smoothScrolling = FALSE;
- icon_field_top /= (ICONSIZE + icon_ymargin);
- icon_field_top *= (ICONSIZE + icon_ymargin);
- icon_field_top += icon_ymargin;
- needToDraw = TRUE;
- MakeMenu();
- break;
-
- case 90: /* About... */
- system("/usr/bin/X11/xconfirm "
- "-h \"About...\" "
- "-t \"ibrowse - version 1.2.2\" "
- "-t \" a quick hack written by Tim Heidmann\" "
- "-t \" copyright 1993, Silicon Graphics\" "
- "> /dev/null");
- break;
-
- case 99: flag = TRUE; break;
-
- default:
- if (iMenu < 100) break;
- else if (iMenu < 100 + nDirList)
- ChangeDirectory(myDirList[directoryList[iMenu-100]]->name);
- else if (iMenu < 10000) break;
- else if (iMenu < 10000 + nAncestors) {
- strncpy(buf, theDirName, ancestorList[iMenu-10000] - theDirName +
- ancestorLen[iMenu-10000]);
- buf[ancestorList[iMenu-10000] - theDirName +
- ancestorLen[iMenu-10000]] = '\0';
- ChangeDirectory(buf);
- }
- break;
- }
-
- return flag;
- }
-
- int
- SortDisplayList(int (*fn)(int *, int *)) {
- qsort(displayList, nIcons, sizeof(int),
- (int (*)(const void *, const void *)) fn);
- }
-
- int
- CmpDirName(int *d1, int *d2) {
- return (strcmp(myDirList[*d1]->name, myDirList[*d2]->name));
- }
-
- int
- CmpDirSize(int *d1, int *d2) {
- /* Put largest files first. Files of equal size sorted alphabetically */
- return
- myDirList[*d1]->size > myDirList[*d2]->size ? -1 :
- myDirList[*d1]->size < myDirList[*d2]->size ? 1 :
- strcmp(myDirList[*d1]->name, myDirList[*d2]->name);
- }
-
- int
- CmpDirDate(int *d1, int *d2) {
- /* Put newest files first. Files of the same age sorted alphabetically */
- return
- myDirList[*d1]->mtime > myDirList[*d2]->mtime ? -1 :
- myDirList[*d1]->mtime < myDirList[*d2]->mtime ? 1 :
- strcmp(myDirList[*d1]->name, myDirList[*d2]->name);
- }
-
- void
- DoInputChange(int val) {
- windowActive = val;
- if (windowActive)
- /* Mouse into window. Check modifier keys. */
- modKeys =
- getbutton(LEFTSHIFTKEY)||getbutton(RIGHTSHIFTKEY)?SHIFTKEYBIT:0 |
- getbutton(LEFTCTRLKEY) ||getbutton(RIGHTCTRLKEY) ? CTRLKEYBIT:0 |
- getbutton(LEFTALTKEY) ||getbutton(RIGHTALTKEY) ? ALTKEYBIT:0;
- else
- /* Mouse out of window. Deselect the active icon, redraw */
- if (activeIcon >= 0) {
- activeIcon = -1;
- needToDraw = TRUE;
- }
- }
-
- void
- DoTheWork() {
- int i, mx, my, delta;
- long xnew, ynew;
- struct timeval thisTime;
-
- if (needToUpdateDirectory) {
- needToUpdateDirectory = FALSE;
- nDirList = nBusyDirList;
- MakeMenu();
- }
- if (needToResize) {
- getorigin(&win_ox, &win_oy);
- getsize(&xnew, &ynew);
- if (xnew != win_sx || ynew != win_sy) {
- win_sx = xnew;
- win_sy = ynew;
- reshapeviewport();
- ortho2(0, win_sx-1, 0, win_sy-1);
- SizeWindow();
- }
- needToDraw = TRUE;
- needToResize = FALSE;
- }
- if (needToCount) SizeWindow();
- if (isScrolling) {
- my = getvaluator(MOUSEY) - win_oy;
- delta = scroll_factor * (my - scroll_start_y);
- if (!smoothScrolling) delta = delta /
- (ICONSIZE + icon_ymargin) *
- (ICONSIZE + icon_ymargin);
- icon_field_top = scroll_start_ift + delta;
-
- LimitScrollBar();
- SizeScrollBar();
- needToDraw = TRUE;
- } else if (windowActive) {
- /* Hot mouse - show info about the icon currently touched */
- mx = getvaluator(MOUSEX) - win_ox;
- my = getvaluator(MOUSEY) - win_oy;
- if ((newActiveIcon = WhichIcon(mx, my)) != activeIcon) {
- needToDrawActive = TRUE;
- }
- }
-
- if (needToDrawEventually) {
- gettimeofday(&thisTime, NULL);
- if (FDTIME(thisTime, lastDraw) > EVENTUALLY) needToDraw = TRUE;
- }
- if (needToDraw) {
- needToDraw = FALSE;
- needToDrawEventually = FALSE;
- if (needToDrawActive) activeIcon = newActiveIcon;
- needToDrawActive = FALSE;
- Redraw();
- gettimeofday(&lastDraw, NULL);
- /* If more icons have appeared, schedule another draw */
- if (nDisplayIcons != nIcons) needToDrawEventually = TRUE;
- } else if (needToDrawActive) {
- needToDrawActive = FALSE;
- RedrawActive();
- } else
- /* Not drawing; Slow down the busy loop */
- sginap(1);
- }
-
-
- void
- Redraw() {
- int iDList;
-
- /* Draw the icon field */
- scrmask(scroll_bar_width, win_sx-1, info_area_height, win_sy-1);
- cpack(ICON_BG);
- rectf(scroll_bar_width, info_area_height, win_sx-1, win_sy-1);
- fmsetfont(iconFont);
- needToReadQuick = needToIconifyQuick = FALSE;
- for (iDList = iFirstVisible; iDList <= iLastVisible; iDList++)
- DrawIcon(iDList);
-
- /* Draw the info window */
- scrmask(0, win_sx-1, 0, info_area_height-1);
- cpack(INFO_BG);
- rectfi(0, 0, win_sx-1, info_area_height-1);
- cpack(INFO_FRAME);
- recti(0, 0, win_sx-1, info_area_height-1);
- fmsetfont(infoFont);
- if (activeIcon >= 0)
- DrawIconInfo();
- else
- DrawGenericInfo();
-
- /* Draw the scroll bar */
- scrmask(0, scroll_bar_width-1, info_area_height, win_sy-1);
- DrawScrollBar();
-
- swapbuffers();
- scrmask(0, win_sx-1, 0, win_sy-1);
- }
-
- void
- DrawIcon(int iDList) {
- int icon_i, icon_j;
- int xorg, yorg, xoff, yoff, xsize, ysize;
- int name_width;
- struct iconDirStruct *ids;
-
- /* Calculate the position of this icon */
- WhereIsIcon(iDList,
- &icon_i, &icon_j, &xsize, &ysize, &xoff, &yoff, &xorg, &yorg);
-
- ids = myDirList[displayList[iDList]];
- if (ids->state == NEED2ICONIFY) {
- /* Image has not been iconified yet */
- needToIconifyQuick = TRUE;
- cpack(ICON_FRAME);
- recti(xorg+xoff, yorg+yoff, xorg+xoff+xsize, yorg+yoff+ysize);
- } else if (ids->state == ISIMAGE) {
- if (icons[ids->iicon] == NULL ||
- ((char *)(icons[ids->iicon]))[ICONSPACE] == 0) {
- /* icon pointer is NULL or extra byte at end of buffer has not
- * been set to non-zero:
- * Icon hasn't been iconified or read from icon file yet.
- */
- needToReadQuick = TRUE;
- cpack(ICON_FRAME);
- recti(xorg+xoff, yorg+yoff, xorg+xoff+xsize, yorg+yoff+ysize);
- } else {
- /* Draw the icon's dropshadow and bitmap */
- cpack(ICON_DROP);
- rectfi(xorg+xoff+3, yorg+yoff-3,
- xorg+xoff+xsize+3, yorg+yoff+ysize-3);
- lrectwrite(xorg+xoff, yorg+yoff,
- xorg+xoff+xsize-1, yorg+yoff+ysize-1,
- icons[ids->iicon]);
- }
- }
-
- /* Label it */
- name_width = fmgetstrwidth(iconFont, ids->name);
- cpack(ICON_DROP);
- cmov2i(xorg + (ICONSIZE - name_width)/2 + 1, yorg - 15 - 1);
- fmprstr(ids->name);
- cpack(ICON_TEXT);
- cmov2i(xorg + (ICONSIZE - name_width)/2, yorg - 15);
- fmprstr(ids->name);
-
- /* Active? Frame it. */
- if (iDList == activeIcon) {
- cpack(ICON_ACTIVE);
- recti(xorg+xoff-4, yorg+yoff-4,
- xorg+xoff+xsize+4, yorg+yoff+ysize+4);
- }
- }
-
- void
- WhereIsIcon(int iDList,
- int *icon_i, int *icon_j, int *xsize, int *ysize, int *xoff, int *yoff,
- int *xorg, int *yorg) {
- struct iconDirStruct *ids;
-
- /* Where does a particular icon live on the screen right now? */
- ids = myDirList[displayList[iDList]];
- *icon_j = iDList / icon_nx;
- *icon_i = iDList - *icon_j * icon_nx;
- *xsize = ids->ixsize;
- *ysize = ids->iysize;
- *xoff = (ICONSIZE - *xsize) / 2;
- *yoff = (ICONSIZE - *ysize) / 2;
- *xorg = scroll_bar_width + icon_xmargin +
- *icon_i * (ICONSIZE + icon_xmargin);
- *yorg = win_sy - (*icon_j + 1) * (ICONSIZE + icon_ymargin);
- *yorg += icon_field_height - icon_field_top;
- }
-
- void
- DrawIconInfo() {
- struct iconDirStruct *ids;
- int info_y;
- char info_buf[PATH_MAX + 64], num_buf[64];
-
- ids = myDirList[displayList[activeIcon]];
-
- cpack(INFO_NAME);
- /* File name */
- info_y = info_area_height - info_line_space - 5;
- cmov2i(info_left_margin, info_y);
- fmprstr(ids->name);
- info_y -= 5;
-
- cpack(INFO_TEXT);
- /* File type */
- info_y -= info_line_space;
- cmov2i(info_left_margin, info_y);
- fmprstr((*ImageFn[ids->iType].Info)(ids, info_buf));
-
- /* Image dimensions */
- info_y -= info_line_space;
- cmov2i(info_left_margin, info_y);
- sprintf(info_buf, "%4d x %4d pixels, %d component%s",
- ids->xsize, ids->ysize, ids->zsize, ids->zsize>1 ? "s" : "");
- fmprstr(info_buf);
-
- /* File size */
- info_y -= info_line_space;
- cmov2i(info_left_margin, info_y);
- Commafy(num_buf, ids->size);
- sprintf(info_buf, "%s bytes", num_buf);
- fmprstr(info_buf);
-
- /* Modification time */
- info_y -= info_line_space;
- cmov2i(info_left_margin, info_y);
- cftime(info_buf, "%a %b %e %r %Y", (time_t *) &ids->mtime);
- fmprstr(info_buf);
- }
-
-
- void
- Commafy(char *s, int n) {
- char buf[32], *src, *dest;
- int l;
-
- sprintf(buf, "%d", n);
- for (l = strlen(buf), src = buf, dest = s; l > 0; l--, src++, dest++) {
- *dest = *src;
- if (l > 1 && l % 3 == 1) *(++dest) = ',';
- }
- *dest = '\0';
- }
-
- void
- DrawGenericInfo() {
- int info_y;
- char info_buf[PATH_MAX + 64];
-
- cpack(INFO_NAME);
- /* Number of images */
- info_y = info_area_height - info_line_space - 5;
- cmov2i(info_left_margin, info_y);
- sprintf(info_buf, "%d images found", nDisplayIcons);
- fmprstr(info_buf);
- info_y -= 5;
-
- cpack(INFO_TEXT);
- /* General help text */
- info_y -= info_line_space;
- cmov2i(info_left_margin, info_y);
- fmprstr(GetIdleModeName(idleMode));
-
- info_y -= info_line_space;
- cmov2i(info_left_margin, info_y);
- fmprstr("Move mouse over icon for more info.");
-
- info_y -= info_line_space;
- cmov2i(info_left_margin, info_y);
- fmprstr("Double-click left mouse on icon to open.");
-
- info_y -= info_line_space;
- cmov2i(info_left_margin, info_y);
- fmprstr("Drag scroll bar with left mouse to scan.");
- }
-
- void
- DrawScrollBar() {
- /* Draw the scroll bar */
- cpack(SCROLL_BG);
- rectfi(0,info_area_height-1,scroll_bar_width-1,win_sy-1);
- cpack(SCROLL_FRAME);
- recti(0,info_area_height-1,scroll_bar_width-1,win_sy-1);
- cpack(SCROLL_THUMB);
- rectfi(1,scroll_thumb_bottom,scroll_bar_width-2,scroll_thumb_top-1);
- cpack(SCROLL_FRAME);
- recti(1,scroll_thumb_bottom,scroll_bar_width-2,scroll_thumb_top-1);
- }
-
- void
- RedrawActive() {
- int icon_i, icon_j;
- int xorg, yorg, xoff, yoff, xsize, ysize;
-
- frontbuffer(TRUE);
-
- /* Unhighlight old active icon and highlight new in the front buffer */
- scrmask(scroll_bar_width, win_sx-1, info_area_height, win_sy-1);
- if (activeIcon >= 0) {
- WhereIsIcon(activeIcon,
- &icon_i, &icon_j, &xsize, &ysize, &xoff, &yoff, &xorg, &yorg);
- cpack(ICON_BG);
- recti(xorg+xoff-4, yorg+yoff-4,
- xorg+xoff+xsize+4, yorg+yoff+ysize+4);
- }
-
- fmsetfont(infoFont);
- activeIcon = newActiveIcon;
- if (activeIcon >= 0) {
- WhereIsIcon(activeIcon,
- &icon_i, &icon_j, &xsize, &ysize, &xoff, &yoff, &xorg, &yorg);
- cpack(ICON_ACTIVE);
- recti(xorg+xoff-4, yorg+yoff-4,
- xorg+xoff+xsize+4, yorg+yoff+ysize+4);
- }
-
- /* Clear and redraw info area */
- scrmask(0, win_sx-1, 0, info_area_height-1);
- cpack(INFO_BG);
- rectfi(0,0,win_sx-1,info_area_height-1);
- cpack(INFO_FRAME);
- recti(0,0,win_sx-1,info_area_height-1);
- if (activeIcon >= 0)
- DrawIconInfo();
- else
- DrawGenericInfo();
-
- frontbuffer(FALSE);
- scrmask(0, win_sx-1, 0, win_sy-1);
- }
-
-
-
- /*****************************************************************************
- *
- * Routines for second process - Read directory, check type, iconify, etc.
- * This process watches the flag "needToSwitch" for directory changes.
- * To get the required responsiveness, The work to be done is controlled by a
- * state machine of several sequential modes, as indicated by "idleMode".
- * Within each mode, the task is segmented so that the main processing
- * routine, "IdleProcess", does one thing and returns. These tasks are
- * controlled by global variables such as idleFile, loFree, hiFull, etc.
- *
- *****************************************************************************/
-
- void
- IdleLoop() {
- readerPID = getpid();
- for (;;) {
- IdleProcess();
- if (needToFinish) {
- FinishDirectory();
- okayToFinish = TRUE;
- blockproc(readerPID);
- }
- if (needToSwitch) {
- needToSwitch = FALSE;
- if (idleMode != Before) FinishDirectory();
- StartDirectory(newDirName);
- StartReadDir();
- switchDone = TRUE;
- }
- }
- }
-
-
- /* Do idle processing - do one thing and return */
- void
- IdleProcess() {
- int iIcon, i, iEnt, cnt, loFree, hiFull;
- struct iconDirStruct *ids;
-
- switch (idleMode) {
- case ReadDir: if (!ProcessReadDir()) StartCheckTimes(); break;
- case CheckTimes: if (!ProcessCheckTimes()) StartChecking(); break;
- case Checking: if (!ProcessChecking()) StartReadIcons(); break;
- case ReadIcons: if (!ProcessReadIcons()) StartIconifying(); break;
- case Iconifying: if (!ProcessIconifying()) StartCompacting(); break;
- case Compacting: if (!ProcessCompacting()) StartSaveFiles(); break;
- case SaveFiles: if (!ProcessSaveFiles()) StartDone(); break;
-
- default:
- /* Nothing to do. Slow down this busy loop */
- sginap(5);
- break;
- }
- }
-
-
- /*
- * Try to open directory and icon files for read/write in this directory.
- * If directory or icon file cannot be opened to write, clear canWriteIconFiles
- * flag. If directory and icon files exist, open them for read, even if they
- * never get updated.
- */
-
- void
- StartDirectory(char *name) {
- char buf[PATH_MAX];
- int i;
- struct stat iconStatBuf, iconDirStatBuf;
-
- /* Check for the presence of this directory */
- if (chdir(name) < 0)
- switch (errno) {
- case ENOENT:
- fprintf(stderr, "%s: No such directory: %s/%s\n",
- cmdName, theDirName, name);
- break;
- case EACCES:
- fprintf(stderr, "%s: Access denied: %s/%s\n",
- cmdName, theDirName, name);
- break;
- default:
- fprintf(stderr, "%s: Cannot open directory: %s/%s\n",
- cmdName, theDirName, name);
- break;
- }
- getwd(theDirName);
-
- /* Try to open icon directory file */
- nDirEnts = 0;
- canWriteIconFiles = !neverWriteIconFiles;
- sprintf(buf, "%s/.ibrowse_dir", theDirName);
- iconDirFD = -1;
- if (canWriteIconFiles) iconDirFD = open(buf, O_RDWR | O_CREAT, 0666);
- if (iconDirFD < 0) {
- canWriteIconFiles = FALSE;
- iconDirFD = open(buf, O_RDONLY);
- }
- needToWriteDirFile = FALSE;
-
- /* Try to open icon file */
- sprintf(buf, "%s/.ibrowse_icon", theDirName);
- iconFD = -1;
- if (canWriteIconFiles) iconFD = open(buf, O_RDWR | O_CREAT, 0666);
- if (iconFD < 0) {
- canWriteIconFiles = FALSE;
- iconFD = open(buf, O_RDONLY);
- }
- iconStatBuf.st_size = 0;
- if (iconFD >= 0) fstat(iconFD, &iconStatBuf);
- nIconFileEnts = iconStatBuf.st_size / ICONSPACE;
- for (i=0; i<nIconFileEnts; i++) {
- icons[i] = NULL;
- iconRef[i] = -1;
- }
-
- /* If either icon file seems to have the wrong record length, force a
- rewrite, or at least don't read it. */
- if (iconDirFD >= 0) {
- fstat(iconDirFD, &iconDirStatBuf);
- if (iconStatBuf.st_size % ICONSPACE != 0 ||
- iconDirStatBuf.st_size % sizeof(struct iconDirStruct) != 0)
- if (canWriteIconFiles) {
- /* Truncate the files to 0 length */
- ftruncate(iconDirFD, 0);
- ftruncate(iconFD, 0);
- } else {
- /* Close the directory file so it doesn't get read. */
- close(iconDirFD);
- iconDirFD = -1;
- }
- }
- }
-
- void
- FinishDirectory() {
- char buf[PATH_MAX+32];
- int iEnt, iIcon;
-
- /* Tie up loose ends and exit */
- if (needToWriteDirFile && canWriteIconFiles) WriteDirFile();
- if (iconDirFD >= 0) close(iconDirFD);
- if (iconFD >= 0) close(iconFD);
-
- /* Leave no files behind if there are no images in this directory.
- * Even though this makes us scan all the files next time
- * we visit, avoid cluttering up the file system with .ibrowse... files.
- */
- if (nIcons <= 0) {
- sprintf(buf, "/bin/rm %s/.ibrowse_dir 1>/dev/null 2>&1", theDirName);
- system(buf);
- sprintf(buf, "/bin/rm %s/.ibrowse_icon 1>/dev/null 2>&1", theDirName);
- system(buf);
- }
-
- /* Unallocate malloc'd memory */
- for (iEnt = 0; iEnt < nDirEnts; iEnt++) {
- free(myDirList[iEnt]);
- myDirList[iEnt] = NULL;
- }
- for (iIcon = 0; iIcon < nIconFileEnts; iIcon++)
- if (icons[iIcon] != NULL) {
- free(icons[iIcon]);
- icons[iIcon] = NULL;
- }
- nDirEnts = 0;
- nIconFileEnts = 0;
- nIcons = 0;
- needToCount = TRUE;
- needToDraw = TRUE;
- }
-
- void
- WriteDirFile() {
- int iEnt;
-
- /* Rewrite dirty entries of entire directory file on demand. */
- if (canWriteIconFiles && iconDirFD >= 0)
- for (iEnt = 0; iEnt < nDirEnts; iEnt++)
- if ((myDirList[iEnt]->flags & DIRTYFLAG) != 0) WriteDirEnt(iEnt);
-
- needToWriteDirFile = FALSE;
- }
-
- /* Force write of a single directory entry */
- void
- WriteDirEnt(int iEnt) {
- int len;
- char buf[PATH_MAX];
-
- myDirList[iEnt]->flags &= ~DIRTYFLAG;
- lseek(iconDirFD, iEnt * sizeof(struct iconDirStruct), SEEK_SET);
- len = write(iconDirFD, myDirList[iEnt], sizeof(struct iconDirStruct));
- if (len < (int) sizeof(struct iconDirStruct)) {
- sprintf(buf, "%s: Write %s/.ibrowse_dir\n", cmdName, theDirName);
- perror(buf);
- exit(1);
- }
- }
-
-
- /*****************************************************************************
- *
- * Background process routines to browse icon files rather than scan directory.
- *
- *****************************************************************************/
-
- void
- FileIdleLoop() {
- readerPID = getpid();
- OpenIconFiles();
- StartReadDir();
- for (;;) {
- FileIdleProcess();
- if (needToFinish) {
- FinishDirectory();
- okayToFinish = TRUE;
- blockproc(readerPID);
- }
- }
- }
-
-
- /* Do idle processing - do one thing and return */
- void
- FileIdleProcess() {
- int iIcon, i, iEnt, cnt, loFree, hiFull;
- struct iconDirStruct *ids;
-
- switch (idleMode) {
- case ReadDir: if (!ProcessReadDir()) StartRegister(); break;
- case Register: if (!ProcessRegister()) StartReadIcons(); break;
- case ReadIcons: if (!ProcessReadIcons()) StartDone(); break;
-
- default:
- /* Nothing to do. Slow down this busy loop */
- sginap(5);
- break;
- }
- }
-
- void
- OpenIconFiles() {
- char buf[PATH_MAX];
-
- sprintf(buf, "%s.dir", iconRootName);
- if ((iconDirFD = open(buf, O_RDONLY)) < 0) {
- fprintf(stderr, "Cannot open directory file: %s\n", buf);
- exit(1);
- }
- sprintf(buf, "%s.icon", iconRootName);
- if ((iconFD = open(buf, O_RDONLY)) < 0) {
- fprintf(stderr, "Cannot open icon file: %s\n", buf);
- exit(1);
- }
- canWriteIconFiles = FALSE;
- }
-
- /*****************************************************************************
- *
- * Idle processing routines
- *
- *****************************************************************************/
-
- /*
- * Read icon directory file entries into memory.
- */
- void
- StartReadDir() {
- /* Set up to start reading */
- if (!canWriteIconFiles && updateOnlyFlag)
- /* We're just here to update and we can't write - Give up. */
- StartDone();
- else {
- idleMode = ReadDir;
- needToDraw = TRUE; /* Update status message */
- }
- }
-
- int
- ProcessReadDir() {
- struct iconDirStruct dirBuf;
- /*
- * Allocate memory and read next entry.
- * Return TRUE iff read is successful.
- */
- if (iconDirFD < 0) return FALSE;
-
- if (nDirEnts > MAXDIRENTS) {
- fprintf(stderr,
- "%s: Error: Too many directory entries (> %d)\n",
- cmdName, MAXDIRENTS);
- exit(1);
- }
- if (read(iconDirFD, &dirBuf, sizeof(dirBuf)) < (int) sizeof(dirBuf))
- return FALSE;
- dirBuf.index = nDirEnts;
- dirBuf.flags = UNREFFLAG; /* Clear dirty and ref bits */
- myDirList[nDirEnts] =
- (struct iconDirStruct *) malloc(sizeof(struct iconDirStruct));
- *myDirList[nDirEnts] = dirBuf;
- nDirEnts++;
- return TRUE;
- }
-
-
- /*
- * Verify that directory entries make sense and add them to the display list.
- */
- void
- StartRegister() {
- /* Set up to start adding icons */
- idleFile = 0;
- idleMode = Register;
- needToDraw = TRUE; /* Update status message */
- }
-
- int
- ProcessRegister() {
- struct iconDirStruct *ids;
- int iType;
-
- for (; idleFile < nDirEnts; idleFile++) {
- ids = myDirList[idleFile];
- /* Add image to icon display list */
- if (ids->state == NEED2ICONIFY ||
- ids->state == ISIMAGE) {
- for (iType = 0;; iType++) {
- if (iType >= nImageTypes) {
- /* Unrecognized image type ID */
- ids->state = NEED2CHECK;
- break;
- }
- if (ImageFn[iType].type == ids->type) {
- /* Found the image type ID. Remember the index. */
- ids->iType = iType;
- AddIcon(idleFile);
- idleFile++;
- return TRUE;
- }
- }
- }
- }
- return FALSE;
- }
-
-
- /*
- * Check each directory entry's modification time against the corresponding
- * entry in the icon directory file to determine if the file type and
- * iconic version are valid.
- */
- void
- StartCheckTimes() {
- /* Set up to start checking. */
- idleMode = CheckTimes;
- nBusyDirList = 0;
- if ((theDir = opendir(theDirName)) == NULL) {
- fprintf(stderr, "%s: Cannot open directory %s\n",
- cmdName, theDirName);
- StartDone();
- } else
- needToDraw = TRUE; /* Update status window */
- }
-
- int
- ProcessCheckTimes() {
- int iEnt;
- struct dirent *dirEnt;
-
- /* Check next directory entry. Return TRUE iff more files to check. */
- if ((dirEnt = readdir(theDir)) != NULL) {
- /* Check the next directory entry (ignore '.' and '..') */
- if (strcmp(dirEnt->d_name, ".") != 0 &&
- strcmp(dirEnt->d_name, "..") != 0) CheckFile(dirEnt->d_name);
- } else {
- /* No more directory entries to check. Finish up. */
- closedir(theDir);
-
- /* Flag unreferenced directory file entries */
- for (iEnt = 0; iEnt < nDirEnts; iEnt++)
- if ((myDirList[iEnt]->flags & REFFLAG) == 0) {
- myDirList[iEnt]->flags |= DIRTYFLAG;
- myDirList[iEnt]->state = NOFILE;
- }
-
- if (needToWriteDirFile && canWriteIconFiles) WriteDirFile();
- SortDisplayList(CmpDirName);
-
- qsort(directoryList, nBusyDirList, sizeof(int),
- (int (*)(const void *, const void *)) CmpDirName);
- needToUpdateDirectory = TRUE; /* Put sorted directories on menu */
- return FALSE;
- }
- return TRUE;
- }
-
-
- /*
- * Check whether unknown files are images or not.
- */
- void
- StartChecking() {
- /* Set up to check file type. */
- idleFile = 0;
- idleMode = Checking;
- needToDraw = TRUE; /* Update status window */
- }
-
- int
- ProcessChecking() {
- /* Check next file. Return TRUE iff there are more files to check. */
- for (;; idleFile++) {
- if (idleFile >= nDirEnts) {
- /* Done checking. Finish up. */
- if (needToWriteDirFile && canWriteIconFiles) WriteDirFile();
- return FALSE;
- }
- if (myDirList[idleFile]->state == NEED2CHECK) {
- if (CheckImage(myDirList[idleFile])) {
- AddIcon(idleFile);
- needToDrawEventually = TRUE;
- }
- idleFile++;
- return TRUE;
- }
- }
- }
-
-
- /*
- * Read already iconified images from icon file.
- */
- void
- StartReadIcons() {
- /* Set up to read icons. */
- idleFile = 0;
- idleMode = ReadIcons;
- needToDraw = TRUE; /* Update status window */
- }
-
- int
- ProcessReadIcons() {
- int iIcon;
- struct iconDirStruct *ids;
-
- /* Read the next icon. Return TRUE iff more icons to read. */
- ids = NULL;
-
- /* Check visible icons first for ones to be read */
- if (needToReadQuick)
- for (iIcon = iFirstVisible;; iIcon++) {
- if (iIcon > iLastVisible) {
- /* Found no more icons to quick read. */
- ids = NULL;
- needToReadQuick = FALSE;
- break;
- }
- ids = myDirList[displayList[iIcon]];
- if (ids->state == ISIMAGE && icons[ids->iicon] == NULL) {
- /* This one's visible. Update it eventually. */
- needToDrawEventually = TRUE;
- break;
- }
- }
-
- /* If no visible icons to be read, look for next one in list */
- if (ids == NULL)
- for (;;) {
- if (idleFile >= nDirEnts)
- /* Done reading icons from disk */
- return FALSE;
-
- ids = myDirList[idleFile++];
- if (ids->state == ISIMAGE && icons[ids->iicon] == NULL) break;
- }
-
- /* If we've found one to read, do it */
- if (ids != NULL) ReadIcon(ids);
- return TRUE;
- }
-
-
- /*
- * Iconify image files and save the icon to disk.
- */
- void
- StartIconifying() {
- /* Set up to start iconifying image files */
- idleFile = 0;
- idleMode = Iconifying;
- needToDraw = TRUE; /* Update status window */
- }
-
- int
- ProcessIconifying() {
- int iIcon;
- struct iconDirStruct *ids;
-
- /* Iconify the next image. Return TRUE iff more files to iconify */
- ids = NULL;
-
- /* Iconify visible icons first */
- if (needToIconifyQuick)
- for (iIcon = iFirstVisible;; iIcon++) {
- if (iIcon > iLastVisible) {
- ids = NULL;
- needToIconifyQuick = FALSE;
- break;
- }
- ids = myDirList[displayList[iIcon]];
- if (ids->state == NEED2ICONIFY) {
- needToDrawEventually = TRUE;
- break;
- }
- }
-
- /* If no visible icons to be iconified, look for next one in list */
- if (ids == NULL)
- for (;;) {
- if (idleFile >= nDirEnts)
- /* End of stuff to iconify. Go to next state. */
- return FALSE;
-
- ids = myDirList[idleFile++];
- if (ids->state == NEED2ICONIFY) break;
- }
-
- /* If we've found one to iconify, do it */
- if (ids != NULL) {
- ImageToIcon(ids);
- if (canWriteIconFiles) WriteIcon(ids);
- }
- return TRUE;
- }
-
-
- /*
- * Rearrange icon file entries and truncate to eliminate wasted space on disk.
- */
- void
- StartCompacting() {
- /* Set up to compact icon files */
- if (canWriteIconFiles) {
- idleMode = Compacting;
- needToDraw = TRUE;
- } else
- /* Can't write anything, so give up at this point. */
- StartDone();
- }
-
- int
- ProcessCompacting() {
- int i, loFree, hiFull;
- struct iconDirStruct *ids;
-
- /*
- * Compact the next icon file -
- * All icons are in memory at this point. Icon files are writable.
- * Return TRUE iff more of the files to check.
- */
- loFree = -1;
- hiFull = nIconFileEnts;
- for (;;) {
- /* Find next free/full entries */
- while (loFree < 0 || iconRef[loFree] >= 0)
- if (++loFree >= nIconFileEnts) break;
- while (hiFull >= nIconFileEnts || iconRef[hiFull] < 0)
- if (--hiFull < 0) break;
-
- /* Check for completion - no free slots or all at end of file */
- if (loFree > hiFull) break;
-
- /* Move the high icon into the low free slot */
- lseek(iconFD, loFree * ICONSPACE, SEEK_SET);
- write(iconFD, icons[hiFull], ICONSPACE);
- icons[loFree] = icons[hiFull];
- icons[hiFull] = NULL;
- iconRef[loFree] = iconRef[hiFull];
- iconRef[hiFull] = -1;
- myDirList[iconRef[loFree]]->iicon = loFree;
- WriteDirEnt(iconRef[loFree]);
- }
-
- /* Truncate icon file */
- if (loFree < nIconFileEnts) {
- lseek(iconFD, 0, SEEK_SET);
- nIconFileEnts = loFree;
- ftruncate(iconFD, nIconFileEnts * ICONSPACE);
- }
-
- /* Compact icon directory file */
- loFree = -1;
- hiFull = nDirEnts;
- for (;;) {
- /* Find next free/full entries */
- while (loFree < 0 || (myDirList[loFree]->flags & REFFLAG))
- if (++loFree >= nDirEnts) break;
- while (hiFull >= nDirEnts ||
- ((myDirList[hiFull]->flags & REFFLAG) == 0))
- if (--hiFull < 0) break;
-
- /* Check for completion - no free slots or all at end of dir */
- if (loFree > hiFull) break;
-
- /* Move the high directory entry into the low free slot */
- /* Set up new entry */
- ids = myDirList[loFree];
- myDirList[loFree] = myDirList[hiFull];
- myDirList[loFree]->index = loFree;
- WriteDirEnt(loFree);
- iconRef[myDirList[loFree]->iicon] = loFree;
- for (i = 0; i < nIcons; i++)
- if (displayList[i] == hiFull) {
- displayList[i] = loFree;
- break;
- }
-
- /* Clear out old entry */
- myDirList[hiFull] = ids;
- myDirList[hiFull]->index = hiFull;
- WriteDirEnt(hiFull);
- }
-
- /* Free unused directory entries and truncate icon directory file */
- if (loFree < nDirEnts) {
- for (i= loFree; i< nDirEnts; i++) {
- free(myDirList[i]);
- myDirList[i] = NULL;
- }
-
- lseek(iconDirFD, 0, SEEK_SET);
- nDirEnts = loFree;
- ftruncate(iconDirFD, nDirEnts * sizeof(struct iconDirStruct));
- }
-
- return FALSE;
- }
-
-
- /*
- * Save any unsaved changes to icon files.
- */
- void
- StartSaveFiles() {
- /* Set up to save icon files to disk */
- idleMode = SaveFiles;
- needToDraw = TRUE; /* Update status window */
- }
-
- int
- ProcessSaveFiles() {
- /* Save any unsaved changed to disk. For now, do it all at once. */
- if (needToWriteDirFile && canWriteIconFiles) WriteDirFile();
- return FALSE;
- }
-
-
- /*
- * All done, just sit there.
- */
- void
- StartDone() {
- /* No more to do - for now */
- idleMode = Done;
- needToDraw = TRUE; /* Update status window */
- }
-
-
- /*****************************************************************************
- *
- * Support routines for idle processing
- *
- *****************************************************************************/
-
- void
- CheckFile(char *filename) {
- int iEnt, iType;
- struct stat statBuf;
- char name_buf[512];
- struct iconDirStruct *ids;
-
- /* Try to find this file in the existing list */
- for (iEnt = 0; iEnt < nDirEnts; iEnt++) {
- if (strcmp(filename, (ids = myDirList[iEnt])->name) == 0) break;
- }
- /* Create an entry if one does not exist */
- if (iEnt >= nDirEnts) {
- iEnt = nDirEnts;
- ids = myDirList[iEnt] =
- (struct iconDirStruct *) malloc(sizeof(struct iconDirStruct));
- nDirEnts++;
- if (nDirEnts > MAXDIRENTS) {
- fprintf(stderr,
- "%s: Error: Too many directory entries (> %d)\n",
- cmdName, MAXDIRENTS);
- exit(1);
- }
- strcpy(ids->name, filename);
- ids->index = iEnt;
- ids->state = NEED2CHECK;
- ids->iicon = -1;
- ids->mtime = -1;
- ids->size = -1;
- ids->flags |= DIRTYFLAG;
- needToWriteDirFile = TRUE;
- }
- ids->flags |= REFFLAG;
-
- /* Get file status */
- sprintf(name_buf, "%s/%s", theDirName, filename);
- if (stat(name_buf, &statBuf) < 0)
- ids->state = CANTREAD;
-
- /* Add directories to the browser list, mark as not images */
- if (S_ISDIR(statBuf.st_mode)) {
- directoryList[nBusyDirList++] = iEnt;
- ids->state = NOTIMAGE;
- return;
- }
-
- /* Mark anything else not a regular file or sym link as not an image. */
- if (!S_ISREG(statBuf.st_mode) && !S_ISLNK(statBuf.st_mode)) {
- ids->state = NOTIMAGE;
- return;
- }
-
- /* Check stored mtime against actual file */
- if (statBuf.st_mtime != ids->mtime) {
- ids->mtime = statBuf.st_mtime;
- ids->size = statBuf.st_size;
- ids->state = NEED2CHECK;
- }
-
- /* If the icon index points beyond end of icon file, check again */
- if (ids->iicon >= nIconFileEnts) {
- ids->iicon = -1;
- ids->state = NEED2CHECK;
- }
-
- /* If this file has never been checked, try now */
- if (ids->state == CANTREAD)
- ids->state = NEED2CHECK;
-
- /* Add images to icon display list */
- if (ids->state == NEED2ICONIFY ||
- ids->state == ISIMAGE) {
- for (iType = 0;; iType++) {
- if (iType >= nImageTypes) {
- /* Unrecognized image type ID */
- ids->state = NEED2CHECK;
- break;
- }
- if (ImageFn[iType].type == ids->type) {
- /* Found the image type ID. Remember the index to fn lists. */
- ids->iType = iType;
- AddIcon(iEnt);
- break;
- }
- }
- }
- }
-
- int
- CheckImage(struct iconDirStruct *ids) {
- int iType, fd;
- char buf[PATH_MAX];
-
- sprintf(buf, "%s/%s", theDirName, ids->name);
- if ((fd = open(buf, O_RDONLY)) < 0)
- ids->state = CANTREAD;
-
- else {
- for (iType = 0;; iType++) {
- if (iType >= nImageTypes) {
- /* Nothing recognizes the file; not an image */
- ids->state = NOTIMAGE;
- break;
- }
- lseek(fd, 0, SEEK_SET);
- if ((*ImageFn[iType].Check)(ids, fd)) {
- /* Found it; x|y|zsize are set, calculate an icon size */
- if (ids->xsize == 0 && ids->ysize == 0)
- ids->ixsize = ids->iysize = 1;
- else {
- ids->ixsize = ids->iysize = ICONSIZE;
- if (ids->xsize > ids->ysize) {
- ids->iysize *= ((float) ids->ysize) / ids->xsize;
- if (ids->iysize <= 0) ids->iysize = 1;
- } else {
- ids->ixsize *= ((float) ids->xsize) / ids->ysize;
- if (ids->ixsize <= 0) ids->ixsize = 1;
- }
- }
-
- ids->iType = iType;
- ids->type = ImageFn[iType].type;
- ids->state = NEED2ICONIFY;
- ids->flags |= DIRTYFLAG;
- needToWriteDirFile = TRUE;
- break;
- }
- }
-
- close(fd);
- }
-
- return ids->state == ISIMAGE || ids->state == NEED2ICONIFY;
- }
-
-
- /*
- * Read image file and subsample into memory slot
- */
- void
- ImageToIcon(struct iconDirStruct *ids) {
- int iPixel;
-
- /* Verify that space is allocated in memory for the icon */
- AllocateIcon(ids);
-
- if (!(*ImageFn[ids->iType].Iconify)(ids, icons[ids->iicon]))
- /* If image can't be read, black it out */
- for (iPixel = 0; iPixel < ids->ixsize * ids->iysize; iPixel++)
- icons[ids->iicon][iPixel] = 0x00000000;
-
- /* Mark this icon valid */
- ((char *)(icons[ids->iicon]))[ICONSPACE] = 1;
-
- ids->state = ISIMAGE;
- ids->flags |= DIRTYFLAG;
- needToWriteDirFile = TRUE;
- }
-
-
- /*
- * Icon list management routines
- */
- void
- AddIcon(int iEnt) {
- /* Add an icon to the display list. */
- if (nIcons >= MAXICONS) {
- fprintf(stderr,
- "%s: Error: Too many icons (> %d)\n",
- cmdName, MAXICONS);
- exit(1);
- }
-
- displayList[nIcons++] = iEnt;
- needToCount = TRUE;
- needToDrawEventually = TRUE;
- }
-
- void
- AssignIcon(struct iconDirStruct *ids) {
- /* Assign an icon file/list slot for this icon. */
- if (ids->iicon < 0) {
- /* New icon. Need to assign an icon slot number */
- ids->iicon = nIconFileEnts++;
- icons[ids->iicon] = NULL;
- }
- iconRef[ids->iicon] = ids->index;
- }
-
- void
- AllocateIcon(struct iconDirStruct *ids) {
- /* Allocate memory for this icon in icons[].
- * v 1.2.2: Allocate an extra byte at the end of the icon buffer
- * and set it to 1 only when the icon is valid. Keeps the icon
- * from being displayed before it is completely read or iconified.
- */
- AssignIcon(ids);
- if (icons[ids->iicon] != NULL) return;
- icons[ids->iicon] = (unsigned long *) malloc(ICONSPACE + 1);
- ((char *)(icons[ids->iicon]))[ICONSPACE] = 0;
- }
-
- void
- ReadIcon(struct iconDirStruct *ids) {
- AllocateIcon(ids);
- lseek(iconFD, ids->iicon*ICONSPACE, SEEK_SET);
- read(iconFD, icons[ids->iicon], ICONSPACE);
-
- /* Mark this icon valid */
- ((char *)(icons[ids->iicon]))[ICONSPACE] = 1;
- }
-
- void
- WriteIcon(struct iconDirStruct *ids) {
- lseek(iconFD, ids->iicon*ICONSPACE, SEEK_SET);
- write(iconFD, icons[ids->iicon], ICONSPACE);
- }
-
-
- /*
- * Miscellaneous routines
- */
- char *
- GetStateName(int state) {
- switch (state) {
- case NOFILE: return "NOFILE";
- case NEED2CHECK: return "NEED2CHECK";
- case CANTREAD: return "CANTREAD";
- case ISIMAGE: return "ISIMAGE";
- case NOTIMAGE: return "NOTIMAGE";
- case NEED2ICONIFY: return "NEED2ICONIFY";
- default: return "Unknown";
- }
- }
-
-
- char *
- GetIdleModeName(int mode) {
- switch (mode) {
- case ReadDir: return "Reading Icon files..." ;
- case Register: return "Registering Images..." ;
- case CheckTimes: return "Scanning directory..." ;
- case Checking: return "Looking for images..." ;
- case ReadIcons: return "Reading icons from disk..." ;
- case Iconifying: return "Iconifying images..." ;
- case Compacting: return "Compacting files..." ;
- case SaveFiles: return "Saving icon files..." ;
- default: return "";
- }
- }
-
-
-
-