/**************************************************************************

    This file is part of desktop95, a desktop manager for fvwm95.
    Copyright (C) 1996, 1997 David Barth, Hector Peraza.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

**************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <assert.h>

#include <xclass/OXFrame.h>
#include <xclass/OXWidgets.h>
#include <xclass/OXClient.h>
#include <xclass/OString.h>
#include <xclass/OIniFile.h>
#include <xclass/utils.h>

#include "OXFolder.h"

#include <X11/extensions/shape.h>

GC OXFolderLabel::_defaultGC;
//GC OSelectedPicture::_selectedGC;
GC OXFolderContainer::_lineGC;
XFontStruct *OXFolderLabel::_defaultFontStruct;

Cursor OXFolder::_defaultCursor;

/* 
*  This inclusion of main.h goes away when 
*  I figure out how to set the title bar from with the OXFolderContainer.
*/
#include "main.h"

extern int NewBrowser;
extern char *AppName;

//---------------------------------------------------------------------------

void OXFolderLabel::Activate(int a) {
  if (_active == a) return;
  _active = a;

//  _client->NeedRedraw(this); // can't use this because the XOR'ed line
  _DoRedraw();
}

void OXFolderLabel::_DoRedraw() {
  XGCValues gcval;
  int tw, x, y;
  
  tw = XTextWidth(_fontStruct, _text->GetString(), _text->GetLength());

  // center text

  x = (GetWidth() - tw) >> 1;
  y = ((GetHeight() - (_fontStruct->max_bounds.ascent +
                       _fontStruct->max_bounds.descent)) >> 1);

  if (_active) {
    SetBackgroundColor(_defaultSelectedBackground);
    XClearWindow(GetDisplay(), _id);
    gcval.foreground = _whitePixel;
    XChangeGC(GetDisplay(), _normGC, GCForeground, &gcval);
    _text->Draw(GetDisplay(), _id, _normGC, x, y + _fontStruct->max_bounds.ascent);
  } else {
    SetBackgroundColor(_client->GetColorByName("turquoise4"));
    XClearWindow(GetDisplay(), _id);
//    gcval.foreground = _blackPixel;
    gcval.foreground = _whitePixel;
    XChangeGC(GetDisplay(), _normGC, GCForeground, &gcval);
    _text->Draw(GetDisplay(), _id, _normGC, x, y + _fontStruct->max_bounds.ascent);
  }
}

/*
void OXFolderLabel::DoEdit() {
  XSetWindowAttributes wattr;
  unsigned long mask;

  // This root-window + text widget must be a separate class
  // so it could process and we could wait for it to finish like
  // a normal transient dialog (clicking outside must shut down it)
  OXCompositeFrame editWindow(_client->GetRoot(), GetWidth(), GetWidth(),
                              HORIZONTAL_FRAME | RAISED_FRAME);

  mask = CWOverrideRedirect | CWSaveUnder;
  wattr.override_redirect = True;
  wattr.save_under = True;
  // also, set border width to 1, border color to black
  XChangeWindowAttributes(GetDisplay(), editWindow.GetId(), mask, &wattr);

  OXTextEntry textEntry(&editWindow);
  OLayoutHints textLayout(LHINTS_LEFT | LHINTS_BOTTOM);
  editWindow.AddFrame(&textEntry, &textLayout);

  editWindow.MapSubwindows();
  editWindow.Resize(editWindow.GetDefaultSize());

  // position the window over the label
   {
   int ax, ay;
   Window wdummy;

   XTranslateCoordinates(GetDisplay(),
                         _id, (editWindow.GetParent())->GetId(),
                         0, 0, &ax, &ay, &wdummy);
  
   editWindow.Move(ax, ay);
   }



  editWindow.MapWindow();
  _client->WaitFor(editWindow);
  // this should somewhere be in the editWindow event processing,
  // so it will cause WaitFor to end
  //editWindow.DestroyWindow();
}
*/

//---------------------------------------------------------------------------

/*
OSelectedPicture::OSelectedPicture(const OXClient *client, const OPicture *p) :
  OPicture(NULL) {

  XGCValues gcv;
  unsigned  long gcm;
  int w, h;

  _client = client;
  Display *dpy = _client->GetDisplay();
  Window Root  = _client->GetRoot()->GetId();

  w = p->GetWidth();
  h = p->GetHeight();

  _pic  = XCreatePixmap(dpy, Root, w, h, DefaultDepth(dpy, DefaultScreen(dpy)));
  _mask = p->GetMask();

  _attributes.width  = w;
  _attributes.height = h;

  XCopyArea(dpy, p->GetPicture(), _pic, _selectedGC, 0, 0, w, h, 0, 0);

  gcm = GCClipMask | GCClipXOrigin | GCClipYOrigin;
  gcv.clip_mask = p->GetMask();
  gcv.clip_x_origin = 0;
  gcv.clip_y_origin = 0;
  XChangeGC(dpy, _selectedGC, gcm, &gcv);

  XFillRectangle(dpy, _pic, _selectedGC, 0, 0, w, h);

  gcm = GCClipMask;
  gcv.clip_mask = None;
  XChangeGC(dpy, _selectedGC, gcm, &gcv);
}

OSelectedPicture::~OSelectedPicture() {
  XFreePixmap(_client->GetDisplay(), _pic);
}
*/

//---------------------------------------------------------------------------

OXFolderIcon::~OXFolderIcon() {
  if (_selpic) delete _selpic;
}

void OXFolderIcon::_DoRedraw() {
  if (_active) {
    if (_selpic) _selpic->Draw(_client->GetDisplay(), _id, _bckgndGC, 0, 0);
  } else {
    if (_pic) _pic->Draw(_client->GetDisplay(), _id, _bckgndGC, 0, 0);
  }
}

void OXFolderIcon::Activate(int a) {
  if (_active == a) return;
  _active = a;

  if (_active) {
    _selpic = new OSelectedPicture(_client, _pic);
  } else {
    if (_selpic) delete _selpic;
    _selpic = NULL;
  }

//  _client->NeedRedraw(this); // can't use this because the XOR'ed line
  _DoRedraw();
}

//---------------------------------------------------------------------------

OXFolder::OXFolder(const OXWindow *p, const OPicture *pic, OString *text,
                   char *fname, int type, unsigned long size, int w, int h,
                   unsigned int options, unsigned long back) :
  OXCompositeFrame(p, w, h, options, back) {
//  OXMainFrame(p, w, h, options | MAIN_FRAME) {

  XSetWindowAttributes wattr;
  unsigned long mask;

  _myname = new char[strlen(fname)+1];
  strcpy(_myname, fname);

  Init();

  _icon   = new OXFolderIcon(this, pic, pic->GetWidth(), pic->GetHeight(),
                                        CHILD_FRAME, _whitePixel);
  _label  = new OXFolderLabel(this, text);
  _type   = type;
  _size   = size;
  _active = False;

  mask = CWOverrideRedirect | CWBackPixmap;
//  mask = CWBackPixmap;
  wattr.background_pixmap = ParentRelative;
  wattr.override_redirect = True;
    
  XChangeWindowAttributes(GetDisplay(), _id, mask, &wattr);

  mask = CWBackPixmap;
  wattr.background_pixmap = ParentRelative;
    
  XChangeWindowAttributes(GetDisplay(), _label->GetId(), mask, &wattr);

  MapWindow();
  LowerWindow();

  AddFrame(_icon, new OLayoutHints(LHINTS_TOP | LHINTS_CENTER_X));
  AddFrame(_label, new OLayoutHints(LHINTS_BOTTOM | LHINTS_CENTER_X, 0, 0, 4, 2));

  Resize(GetDefaultSize());

//+++
  XGrabButton(GetDisplay(), AnyButton, AnyModifier, _id, True,
              ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
              GrabModeAsync, GrabModeAsync, None, None);

  XDefineCursor(GetDisplay(), _id, _defaultCursor);

//  SetMWMHints(0, 0, MWM_INPUT_MODELESS);

}

OXFolder::~OXFolder() {
  delete _label;  
  delete _icon;
}

void OXFolder::Activate(int a) {
  _active = a;
  _icon->Activate(a);
  _label->Activate(a);
}

void OXFolder::Layout() {
  XRectangle rect;

  OXCompositeFrame::Layout();
  XShapeCombineMask(GetDisplay(), _id, ShapeBounding,
                    _icon->GetX(), _icon->GetY(),
                    _icon->GetPicture()->GetMask(), ShapeSet);
  rect.x = 0;
  rect.y = 0;
  rect.width  = _label->GetWidth();
  rect.height = _label->GetHeight();
  XShapeCombineRectangles(GetDisplay(), _id, ShapeBounding,
                          _label->GetX(), _label->GetY(),
                          &rect, 1, ShapeUnion, Unsorted);
}

//+++
int OXFolder::HandleButton(XButtonEvent *event) {

//  XSetInputFocus(GetDisplay(), _id, RevertToParent, CurrentTime);

  event->window = _fw->GetId();
  event->subwindow = _id;

  _fw->HandleButton(event);

  if ((event->type == ButtonPress) &&(event->button == Button1)) {
    _buttonState = PRESSED;
    bx = _x;
    by = _y;
    x0 = event->x;
    y0 = event->y;
  }

  if ((event->type == ButtonRelease) &&(event->button == Button1)) {
    _buttonState = RELEASED;
    if ((bx != _x) || (by != _y)) SaveNewPos();
  }

//  XSendEvent(GetDisplay(), _fw->GetId(), False, None, (XEvent *)event);

//  if (event->type == ButtonPress) {
//    XSetInputFocus(GetDisplay(), _id, RevertToParent, CurrentTime);
//    Activate(True);
//  }
  return True;
}

int OXFolder::HandleDoubleClick(XButtonEvent *event) {

  event->window = _fw->GetId();
  event->subwindow = _id;

  _fw->HandleDoubleClick(event);

//  XSendEvent(GetDisplay(), _fw->GetId(), False, None, (XEvent *)event);

//  if (event->type == ButtonPress) {
//    XSetInputFocus(GetDisplay(), _id, RevertToParent, CurrentTime);
//    Activate(True);
//  }
  return True;
}

int OXFolder::HandleMotion(XMotionEvent *event) {
  int x, y;

  if (!_buttonState) return True;

  x = _x + event->x - x0;
  y = _y + event->y - y0;
  Move(x, y);
  return True;
}  

void OXFolder::SaveNewPos() {
  char line[20];
  char *temp = new char[strlen(_myname)+strlen(".ini")+1];

  sprintf(temp, "%s.ini", _myname);
  OIniFile ini(temp, INI_WRITE);
  ini.PutNext("defaults");
  sprintf(line, "%d", _x);
  ini.PutItem("X-Position", line);
  sprintf(line, "%d", _y);
  ini.PutItem("Y-Position", line);
  //ini.PutItem("Icon", _icon->GetPicture->GetName());
  ini.PutNewLine();

  delete temp;
}

void OXFolder::Init() {
  FILE *f;
  char line[MAX_LINE_LEN];
  char *temp = new char[strlen(_myname)+strlen(".ini")+1];

  sprintf(temp,"%s.ini", _myname);
  
  if ((f = fopen(temp,"r")) == NULL) {
    bx = by = -1;
    return;
  }
  fclose(f);

  OIniFile ini(temp, INI_READ);
  ini.GetNext(line);
  ini.GetItem("X-Position", line);
  bx = atoi(line);
  ini.GetItem("Y-Position", line);
  by = atoi(line);

  delete temp;
}

void OXFolder::InitPos() {
  if (bx != -1) Move(bx, by);
}

//---------------------------------------------------------------------------

OXFolderContainer::OXFolderContainer(const OXWindow *p, int w, int h,
                    unsigned int options, unsigned long back) :
  OXCompositeFrame(p, w, h, options, back) {
    char mimerc[PATH_MAX];

    sprintf(mimerc, "%s/.mime.types", getenv("HOME"));
    MimeTypesList = new OMimeTypes(_client, mimerc);

    _last_active = NULL;
    _dragging = False;
    _total = _selected = 0;
    _popup = objectMenu; // _MakeMenu();
    _sortType = SORT_BY_NAME;

    _firstfolder = NULL;

    SetLayoutManager(new OTileLayout(this, 8));

    XGrabButton(GetDisplay(), AnyButton, AnyModifier, _id, True,
                ButtonPressMask | ButtonReleaseMask |
                PointerMotionMask,
                GrabModeAsync, GrabModeAsync, None, None);

/*
XSelectInput(GetDisplay(), _client->GetRoot()->GetId(),
             ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
*/
}

void OXFolderContainer::AddFolder(const OPicture *icon, OString *name,
                                  char *fname, int type,
                                  unsigned long size) {
  // FIXME: temp
  OXFolder *f;

  folderList *travel = _firstfolder;

  OXCompositeFrame::AddFrame(f = new OXFolder(_client->GetRoot(), icon,
                                          name, fname, type, size,
                                          32, 32, VERTICAL_FRAME),
                             new OLayoutHints(LHINTS_EXPAND_Y | LHINTS_CENTER_X));

  f->SetFileWindow(this);

  if (!travel) {
    _firstfolder = new folderList;
    _firstfolder->folder = f;
    _firstfolder->next = NULL;
  } else {
    while (travel->next) travel = travel->next;
    travel->next = new folderList;
    travel = travel->next;
    travel->next = NULL;
    travel->folder = f;
  }

//  XSelectInput(GetDisplay(), f->GetId(),
//               ButtonPressMask | ButtonReleaseMask | PointerMotionMask);

}

int OXFolderContainer::HandleButton(XButtonEvent *event) {
  SListFrameElt *ptr;
  OXFolder *f;
  int total, selected, inv;

  if (event->type == ButtonPress) {

/**/  extern OXDesktopMainFrame *mainWindow;
/**/  XSetInputFocus(GetDisplay(), mainWindow->GetId(), RevertToParent, CurrentTime);


    inv = event->state & ControlMask;
    _xp = event->x;
    _yp = event->y;

    if (_last_active) {
      _last_active->Activate(False);
      _last_active = NULL;
    }
    total = selected = 0;
    for (ptr=_flist; ptr != NULL; ptr=ptr->next) {   
      f = (OXFolder *) ptr->frame;
      ++total;
      if (f->GetId() == event->subwindow) {
        f->Activate(True);
        ++selected;
        _last_active = f;
      } else {
        f->Activate(False);
      }
    }

    if (selected == 0) {
      _dragging = True;
      _x0 = _xf = _xp;
      _y0 = _yf = _yp;
      XDrawRectangle(GetDisplay(), _id, _lineGC, _x0, _y0, _xf-_x0, _yf-_y0);
    }
  }  

  if (event->type == ButtonRelease) {
    if (_dragging) {
      _dragging = False;
      XDrawRectangle(GetDisplay(), _id, _lineGC, _x0, _y0, _xf-_x0, _yf-_y0);
    } else if (event->button == Button3) {
      _popup->PlaceMenu(event->x_root, event->y_root, False, True);
    }
  }

  return True;
}  

int OXFolderContainer::HandleMotion(XMotionEvent *event) {
  SListFrameElt *ptr;
  OXFolder *f;
  int xf0, yf0, xff, yff, total, selected, inv;

  if (_dragging) {
    inv = event->state & ControlMask;
    XDrawRectangle(GetDisplay(), _id, _lineGC, _x0, _y0, _xf-_x0, _yf-_y0);
    _x0 = min(_xp, event->x);
    _xf = max(_xp, event->x);
    _y0 = min(_yp, event->y);
    _yf = max(_yp, event->y);

    total = selected = 0;
    for (ptr=_flist; ptr != NULL; ptr=ptr->next) {

      f = (OXFolder *) ptr->frame;
      ++total;
      xf0 = f->GetX() + (f->GetWidth() >> 3);
      yf0 = f->GetY() + (f->GetHeight() >> 3);
      xff = xf0 + f->GetWidth() - (f->GetWidth() >> 2);
      yff = yf0 + f->GetHeight() - (f->GetHeight() >> 2);

      if (((xf0 > _x0 && xf0 < _xf) ||
           (xff > _x0 && xff < _xf)) &&
          ((yf0 > _y0 && yf0 < _yf) ||
           (yff > _y0 && yff < _yf))) {
        f->Activate(True);
        ++selected;
      } else {
        f->Activate(False);
      }
    }

    XDrawRectangle(GetDisplay(), _id, _lineGC, _x0, _y0, _xf-_x0, _yf-_y0);
  }

  return True;
}  

int OXFolderContainer::HandleDoubleClick(XButtonEvent *event) {
  SListFrameElt *ptr;
  OXFolder *f;
  int pid, ftype;
  char  action[PATH_MAX];
  char  fullaction[PATH_MAX];
  char  command[PATH_MAX];
  char  filename[PATH_MAX];   
  char  path[PATH_MAX];
  char *argv[PATH_MAX];
  int   argc = 0;
  char *argptr;

  for (ptr=_flist; ptr != NULL; ptr=ptr->next) {   

    f = (OXFolder *) ptr->frame;
    if (f->GetId() == event->subwindow) {

      // get file type
      ftype = f->GetType();

      // is a directory?
      if (S_ISDIR(ftype)) {
        if (NewBrowser) {
          pid = fork();
          if (pid == 0) {
            execlp("explorer",
                   "explorer",
                   f->GetName()->GetString(), 
                   NULL);
            // if we are here then execlp failed!
            fprintf(stderr, "Cannot spawn \"%s\": execlp failed!\n", AppName);
            exit(1);
          }
        } else {
          ChangeDirectory(new OString(f->GetName()->GetString()));
        }
      // is an exec file?
      // *** should take care of the zombies!
      } else if (S_ISREG(ftype) && (ftype & S_IXUSR)) {
        pid = fork();
        if (pid == 0) {
          execlp(f->GetName()->GetString(),
                 f->GetName()->GetString(),
                 NULL,
                 NULL);
          // if we are here then execlp failed!
          fprintf(stderr, "\"%s\" failed to run!\n", f->GetName()->GetString());
          exit(1);
        }
      // MIME
      } else if (MimeTypesList->GetAction(f->GetName()->GetString(), action)) {
        getcwd(path, PATH_MAX);
        sprintf(filename, "%s/%s", path, f->GetName()->GetString());
        argptr = strtok(action, " ");
        while (argptr) {
          if (strcmp(argptr, "%s") == 0) {
            argv[argc] = new char[strlen(filename)+1];
            strcpy(argv[argc], filename);
            argc++;
          } else {
            argv[argc] = new char[strlen(argptr)+1];
            strcpy(argv[argc], argptr);
            argc++;
          }
          argptr = strtok(NULL, " ");
        }
        argv[argc] = NULL;
        pid = fork();
        if (pid == 0) {
          execvp(argv[0], argv);
          // if we are here then execlp failed!
          fprintf(stderr, "Cannot spawn \"%s\": execvp failed!\n", argv[0]);
          exit(1);
        }
      } // MIME ends


      break;
    }
  }

  return True;  // required if the window processes double-click!
}

void OXFolderContainer::Sort(int sortType) {
  OXCanvas *canvas;
  SListFrameElt *ptr;
  int n;

  _sortType = sortType;

  for (n=0, ptr=_flist; ptr!=NULL; n++, ptr=ptr->next);

  _doSort(&_flist, n);
  //canvas = (OXCanvas *) this->GetParent()->GetParent();
  //canvas->Layout();
}

//---- Original list sort code by David Kastrup (c) 1992, Germany.

SListFrameElt **OXFolderContainer::_doSort(SListFrameElt **head, int n) {
  SListFrameElt *p1, *p2, **h2, **t2;
  int m;

  switch (n) {
  case 0:
    return head;

  case 1:
    return &((*head)->next);

  case 2:
    p2 = (p1 = *head)->next;
    if (_compare(p1, p2)) return &(p2->next);
    p1->next = (*head = p2)->next;
    return &((p2->next = p1)->next);
  }

  n -= m = n / 2;
  t2 = _doSort(h2 = _doSort(head, n), m);

  if (_compare(p1 = *head, p2 = *h2)) {
    do {
      if (!--n) return *h2 = p2, t2;
    } while (_compare(p1 = *(head = &(p1->next)), p2));
  }

  while(1) {
    *head = p2;
    do {
      if (!--m) return *h2 = *t2, *t2 = p1, h2;
    } while (!_compare(p1, p2 = *(head = &(p2->next))));
      *head = p1;
      do {
      if (!--n) return *h2 = p2, t2;
    } while (_compare(p1 = *(head = &(p1->next)), p2));
  }
}

int OXFolderContainer::_compare(SListFrameElt *p1, SListFrameElt *p2) {
  int type1, type2;

  OXFolder *f1 = (OXFolder *) p1->frame;
  OXFolder *f2 = (OXFolder *) p2->frame;

  switch (_sortType) {
  default:
  case SORT_BY_NAME:
    break;

  case SORT_BY_TYPE:
    type1 = f1->GetType();
    type2 = f2->GetType();

    //--- use posix macros

    if (S_ISDIR(type1)) type1 = 1;
    #if defined(S_IFLNK)
    else if ((type1 & S_IFMT) == S_IFLNK) type1 = 2;
    #endif
    #if defined(S_IFSOCK)
    else if ((type1 & S_IFMT) == S_IFSOCK) type1 = 3;
    #endif
    else if (S_ISFIFO(type1)) type1 = 4;
    else if (S_ISREG(type1) &&
            (type1 & S_IXUSR)) type1 = 5;
    else type1 = 6;
   
    if (S_ISDIR(type2)) type2 = 1;
    #if defined(S_IFLNK)
    else if ((type2 & S_IFMT) == S_IFLNK) type2 = 2;
    #endif
    #if defined(S_IFSOCK)
    else if ((type2 & S_IFMT) == S_IFSOCK) type2 = 3;
    #endif
    else if (S_ISFIFO(type2)) type2 = 4;
    else if (S_ISREG(type2) &&
            (type2 & S_IXUSR)) type2 = 5;
    else type2 = 6;

    if (type1 != type2) return (type1 <= type2);
    break;

  case SORT_BY_SIZE:
    if (f1->GetSize() != f2->GetSize()) return (f1->GetSize() <= f2->GetSize());
    break;

  }
  return (strcmp(f1->GetName()->GetString(), f2->GetName()->GetString()) <= 0);
}

const OPicture *OXFolderContainer::FolderPic(char *f_name, 
                                             int *type, unsigned long *size) {
  struct stat sbuf;
  const OPicture *folder_type;

  //==== FIX ME: external references

  extern OPicture *Folder_s;
  extern OPicture *ExeDoc_s;
  extern OPicture *TextDoc_s;

  *type = 0;
  *size = 0;

  //==============================================================

  char *temp = new char[strlen(f_name)+strlen(".s.xpm")+1];

  if (stat(f_name, &sbuf) == -1) {
    perror ("stat");
    return folder_type;
  }
   
  *type = sbuf.st_mode;
  *size = sbuf.st_size;

  folder_type = MimeTypesList->GetIcon(f_name, False);
  if (!folder_type) {
    folder_type = TextDoc_s;
    if (S_ISREG(*type) &&
               (*type) & S_IXUSR) {
      sprintf(temp,"%s.s.xpm", f_name);
      folder_type = (OPicture*)_client->GetPicture(temp);
      if (!folder_type) folder_type = ExeDoc_s;
    }
    if (S_ISDIR(*type))
      folder_type = Folder_s;
  } 
/*
  if (S_ISLINK(*type))
    folder_type = _slink_s;
  else
    *lpic = NULL;
*/

  return folder_type;
}  

/*
 * ChangeDirectory
 *
 * Changes current directory
 */

void OXFolderContainer::ChangeDirectory(OString *path) {

  //---- if successful then change title bar

  if (chdir(path->GetString()) == 0) {

    //---- Next, read and display directory contents
    DisplayDirectory();
  }
}

/*
 * DisplayDirectory
 *
 * Display the contents of the current directory in the container.
 * This can be used to refresh the contents of the window.
 *
 */

void OXFolderContainer::DisplayDirectory() {
  RemoveAllFolders();
  CreateFolders();

  //---- this automatically calls layout
  Sort(_sortType);

  MapSubwindows();
}

/*
 *  CreateFolders
 *
 *  This function creates folders from current dir.
 */

void OXFolderContainer::CreateFolders() {
  DIR *dirp;
  struct dirent *dp;
  int type;
  unsigned long size;
  char *t, *name;

  if ((dirp = opendir(".")) == NULL) return;
  
  while ((dp = readdir(dirp)) != NULL) {
    name = dp->d_name;
    if (strcmp(name+strlen(name)-4,".ini") &&
        strcmp (name, ".") && strcmp (name, "..")) {
      const OPicture *folder_type = FolderPic(name, &type, &size);
      OString *label = new OString(name);
      AddFolder(folder_type, label, name, type, size);
      _total++;
    }
  } 

  closedir (dirp);

  SetLayoutManager(new OTileLayout(this, 8));
  Layout();
}

void OXFolderContainer::RemoveAllFolders() {
  SListFrameElt *ptr, *next;

  ptr = _flist;
  while(ptr) {
    next = ptr->next;
    ptr->frame->DestroyWindow();
    delete ptr->frame;
    delete ptr->layout;
    delete ptr;
    ptr = next;
  }
  _flist = NULL;
  _selected = _total = 0;
  _last_active = NULL;
}

void OXFolderContainer::UnselectAll() {
  SListFrameElt *ptr;
  OXFolder *f;

  for (ptr=_flist; ptr != NULL; ptr=ptr->next) {
    f = (OXFolder *) ptr->frame;
    f->Activate(False);  
  }
  _last_active = NULL;
}

void OXFolderContainer::ArrangeFolders() {
  folderList *travel = _firstfolder;
  while (travel) {
    travel->folder->InitPos();
    travel = travel->next;
  }
}
