/****************************************************************
 ***                                                          ***
 ***     browser.c                                            ***
 ***          A file browser                                  ***
 ***                                                          ***
 ***************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

#include "EZ.h"

static EZ_Widget *fsframe;         /* the master frame */
static EZ_Widget *fslistbox;       /* the file lister  */
static EZ_Widget *xpmbrowser;      /* the browser      */

/*************************************************************************/
static char cur_dir[512];          /* holds current directory        */

static void fslistbox_callback(EZ_Widget *, void *);  /* file lister call back          */
static void set_fslistboxitems(char *, void *);  /* update the list in file lister */
static int  selectall();           /* needed in scandir              */

/* extern int  alphasort();*/
extern void exit();
/*************************************************************************/
static char *colors[] = {
  "red",
  "green",
  "blue",
  "yellow",
  "cyan",
  "magenta",
  "white",
  "grey62",
  "bisque",
  "yellowgreen",
};
#define REDC         0
#define GREENC       1
#define BLUEC        2
#define YELLOWC      3
#define CYANC        4
#define MAGENTAC     5
#define WHITEC       6
#define GRAYC        7
#define BISQUEC      8
#define YELLOWGREENC 9
/*************************************************************************/

static char *fonts[] = {
  "fixed",
  "9x15",
 "-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*",
 "-*-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*",
 "-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*",
 "-Adobe-Times-Bold-I-Normal--*-120-*-*-*-*-*-*",
 "-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*",
 "-*-Courier-Medium-R-Normal--*-180-*-*-*-*-*-*",
 "-Adobe-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*",
 "-Adobe-Times-Bold-I-Normal--*-180-*-*-*-*-*-*",
 "-Adobe-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*",
 "-*-Courier-Medium-R-Normal--*-240-*-*-*-*-*-*",
 "-Adobe-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*",
 "-Adobe-Times-Bold-I-Normal--*-240-*-*-*-*-*-*",
};
#define NFONTS 14

/**************************************************************************/
static void colorMCallback(menu, vd)         /* set the foreground of browser */
     EZ_Widget *menu; void *vd;
{
  int i = EZ_GetWidgetReturnData(menu);
  if( i >= REDC && i <= YELLOWGREENC)
    EZ_ConfigureWidget(fslistbox, EZ_FOREGROUND, colors[i], 0);
}

static void fontMCallback(menu, vd)          /* set the font of label        */
     EZ_Widget *menu; void *vd;
{
  int i = EZ_GetWidgetReturnData(menu);
  if( i >= 0 && i < NFONTS)
    {
      EZ_ConfigureWidget(fslistbox, EZ_FONT_NAME, fonts[i], 0);      
    }
}
/**************************************************************************/

main(ac, av) int ac; char **av;
{
  EZ_Widget *tmp, *tmpa, *mbar;
  EZ_Widget *colorM, *fontM, *miscM;
  int       i;
  char      str[32];

  /* create menus */
  EZ_Initialize(ac,av,1);
  colorM = EZ_CreatePopupMenu("Colors");
  EZ_SetWidgetCallBack(colorM, colorMCallback, NULL);
  for(i = REDC; i <= YELLOWGREENC; i++)
    {
      tmp = EZ_CreateMenuNormalButton(colorM, colors[i], -1 , i);
      sprintf(str, "Ctrl-%c", *colors[i]);
      EZ_ConfigureWidget(tmp, EZ_SHORTCUT_KEY, str,0);
      if(i == WHITEC) (void) EZ_CreateMenuSeparator(colorM);
    }
  fontM = EZ_CreatePopupMenu("Font");
  EZ_SetWidgetCallBack(fontM, fontMCallback, NULL);
  for(i = 0; i < NFONTS; i++)
    {
      tmp = EZ_CreateMenuRadioButton(fontM, fonts[i], -1, 2, i, i);
      EZ_ConfigureWidget(tmp, EZ_TEXT_LINE_LENGTH, 80, 0);
    }
  miscM = EZ_CreatePopupMenu("Misc");
  tmp = EZ_CreateMenuNormalButton(miscM, "Exit", 0, -1);
  EZ_SetWidgetCallBack(tmp, (EZ_CallBack)exit, NULL);


  fsframe = EZ_CreateFrame(NULL,                          /* toplevel widget */
			   NULL
			   );
  EZ_ConfigureWidget(fsframe, EZ_STACKING, EZ_VERTICAL,EZ_PADY, 0,
		     EZ_WIDTH,200, EZ_HEIGHT,300,
		     EZ_FILL_MODE, EZ_FILL_BOTH, 0);
  
  mbar = EZ_CreateFrame(fsframe, NULL);
  EZ_ConfigureWidget(mbar, EZ_PADY, 0, EZ_EXPAND, True, EZ_HEIGHT, 0,
		     EZ_STACKING, EZ_HORIZONTAL_LEFT, EZ_PADX, 0, EZ_PADY, 0,
		     EZ_BORDER_TYPE, EZ_BORDER_UP, EZ_BORDER_WIDTH, 2,0);  
  tmp = EZ_CreateMenuButton(mbar, "Colors", 0);
  EZ_SetMenuButtonMenu(tmp, colorM);
  tmp = EZ_CreateMenuButton(mbar, "Fonts", 0);
  EZ_SetMenuButtonMenu(tmp, fontM);
  tmp = EZ_CreateMenuButton(mbar, "Misc", 0);
  EZ_SetMenuButtonMenu(tmp, miscM);

  tmpa = EZ_CreateFrame(fsframe, NULL);
  EZ_ConfigureWidget(tmpa, 
		     EZ_FILL_MODE, EZ_FILL_BOTH,          /* expand children to fit in exactly  */
		     EZ_IPADX, 10,                        /* h spacing between children widgets */
		     0);

  fslistbox = EZ_CreateListBox(tmpa,1,1);                 /* the file lister */
  EZ_ConfigureWidget(fslistbox,
		     EZ_CALL_BACK, fslistbox_callback, NULL,
		     0);

  (void)getcwd(cur_dir,512);                              /* start with the current dir  */
  set_fslistboxitems(cur_dir, NULL);                            /* fill in the file lister     */

  xpmbrowser = EZ_CreateLabel(tmpa,NULL);    
  EZ_ConfigureWidget(xpmbrowser,EZ_PADX, 0, EZ_PADY, 0,
		     /* EZ_WIDTH,100,EZ_HEIGHT,100,*/
		     EZ_BORDER_TYPE, EZ_BORDER_FRAMED_UP,
		     EZ_BORDER_WIDTH, 2, 0);
  EZ_DisplayWidget(fsframe);                              /* display the toplevel widget */ 
  EZ_EventMainLoop();                                     /* and enter the event loop    */
}

/************************************************************************
 *
 *  fslistbox callback
 */
static void fslistbox_callback(widget, vd)
     EZ_Widget *widget; void *vd;
{
  struct stat   fstat;
  int           i,length;
  char          tmpname[512];
  char          tmpnamea[512];

  /*-------------------------------------
   * first, get the corrected path name.
   *------------------------------------*/
  (void) strcpy(tmpname,cur_dir);
  (void) strcpy(tmpnamea,EZ_GetListBoxSelectedItem(fslistbox));
  length = strlen(tmpnamea);

  /*----------------------------------------
   * deal with two special case, ./ and ../
   *--------------------------------------*/
  if(length == 2)
    {
      if(! (tmpnamea[0] == '.'  && tmpnamea[1] == '/'))
	(void)strcat(tmpname, tmpnamea);
    }
  else if(length == 3)
    {
      if(tmpnamea[0] == '.' &&
	 tmpnamea[1] == '.'  &&
	 tmpnamea[2] == '/' )
	{
	  int len = strlen(tmpname);

	  if(len > 1 )
	    {
	      i = len - 2;
	      while( i > 0)
		{
		  if(tmpname[i] == '/') break;
		  i--;
		}
	      if(i > 0) tmpname[i] = '\0';
	      else {tmpname[0] = '/'; tmpname[1] = '\0';}
	    }
	  (void)strcpy(cur_dir, tmpname);
	}
      else
	(void)strcat(tmpname, tmpnamea);
    }
  else
    (void)strcat(tmpname, tmpnamea);
  
  /*------------------------------------
   * check the file type, if its a dir
   * update fslistbox; if its a regular
   * file, send it to the browser.
   *-----------------------------------*/
  stat(tmpname, &fstat);
  if(fstat.st_mode & S_IFDIR)
    set_fslistboxitems(tmpname, NULL);
  else if(fstat.st_mode & S_IFREG)
    {
      if(access(tmpname, R_OK) == 0)
	{
	  Pixmap pixmap;
	  unsigned int w, h;
	  if(EZ_CreateXPixmapFromBitmapFile(tmpname, &w, &h, &pixmap, NULL) ||
	     EZ_CreateXPixmapFromXpmFile(tmpname, &w, &h, &pixmap, NULL))
	    {
	      /* Display *dpy = EZ_GetDisplay();
		 Window  rootwin = RootWindow(dpy, EZ_GetScreen());
		 XSetWindowBackgroundPixmap(dpy, rootwin, pixmap);
		 XClearWindow(dpy,rootwin); */
	      EZ_ConfigureWidget(xpmbrowser, EZ_BITMAP_FILE, tmpname, 0);
	    }
	  else if( EZ_CreateXPixmapFromImageFile(tmpname, &w, &h, &pixmap))
	    {
	      EZ_ConfigureWidget(xpmbrowser, EZ_IMAGE_FILE, tmpname, 0);	      
	    }
	}
    }
}
/***************************************************************
 *
 *  Update the items in fslistbox.
 *     for directories, append a / to distinguish them from
 *     regular files.
 */
static void set_fslistboxitems(dir, vd)
     char *dir; void *vd;
{
  struct dirent **namelist;
  struct stat   fstat;
  int           i, length;
  char          tmpname[512];

  stat(dir, &fstat);
  if(fstat.st_mode & S_IFDIR)
    {
      length = scandir(dir, &namelist, selectall, alphasort);
      if(length < 0)
	{
	  (void)fprintf(stderr, "Cannot open directory %s ",tmpname);
	  return;
	}
      (void)strcpy(cur_dir,dir);
      i = strlen(cur_dir);
      if(i == 0 || cur_dir[i-1] != '/') strcat(cur_dir, "/");
      EZ_FreezeWidget(fslistbox); /* block display */
      EZ_ClearListBox(fslistbox);
      for(i=0; i < length; i++)
	{
	  (void)strcpy(tmpname,cur_dir);
	  (void)strcat(tmpname, namelist[i]->d_name);
	  stat(tmpname,&fstat);
	  if(fstat.st_mode & S_IFDIR) 
	    {
	      (void)strcpy(tmpname, namelist[i]->d_name);
	      (void)strcat(tmpname,"/");
	      EZ_AppendListBoxItem(fslistbox,tmpname);
	    }
	  else
	    EZ_AppendListBoxItem(fslistbox,namelist[i]->d_name);
	  free(namelist[i]);
	}
      (void) free(namelist);
      EZ_UnFreezeWidget(fslistbox); /* unblock display */
    }
}
/**************************************************************************/
static int selectall() { return(1);}
/**************************************************************************/

