Beginning of work on efiler fltk1.x

This commit is contained in:
Vedran Ljubovic 2007-07-16 07:35:32 +00:00
parent a569d78563
commit 6cf2769599
12 changed files with 2220 additions and 1911 deletions

527
efiler/EDE_Browser.cpp Normal file
View File

@ -0,0 +1,527 @@
/*
* $Id$
*
* EDE Browser class
* Part of edelib.
* Copyright (c) 2005-2007 EDE Authors.
*
* This program is licenced under terms of the
* GNU General Public Licence version 2 or newer.
* See COPYING for details.
*/
#include "EDE_Browser.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <Fl/Fl.H>
#include <Fl/Fl_Window.H>
// ---------------- SORT ----------------
// convert size string to float - used for sorting files by size
double sizetof(char *s) {
double d=atof(s);
if (strchr(s,'g') || strchr(s,'G'))
d*=1024*1024*1024;
else if (strchr(s,'m') || strchr(s,'M'))
d*=1024*1024;
else if (strchr(s,'k') || strchr(s,'K'))
d*=1024;
return d;
}
// Sort function - return true if first is larger then second, otherwise false
bool EDE_Browser::sortfn(char*s1,char*s2,SortType type) {
switch(type) {
case ALPHA_SORT:
return (strcmp(s1,s2)>0);
case ALPHA_CASE_SORT:
return (strcasecmp(s1,s2)>0);
case NUMERIC_SORT:
return (atof(s1)>atof(s2));
case DATE_SORT:
// unimplemented
// TODO: use edelib::Date
return false;
case FILE_SIZE_SORT:
return (sizetof(s1)>sizetof(s2));
}
}
// Optimized quick sort algorithm
void EDE_Browser::mqsort(char* arr[], int beg, int end, SortType type) {
bool k = sort_direction ? false : true;
if (end > beg + 1)
{
char* piv = arr[beg]; int l = beg + 1, r = end;
while (l < r)
{
if (k^sortfn(arr[l],piv,type)) // ^ is XOR
l++;
else if (l==r-1) // avoid costly swap if they're the same
r--;
else {
swap(--r,l); // Fl_Browser::swap()
char *tmp=arr[l]; // update array
arr[l]=arr[r];
arr[r]=tmp;
}
}
// avoid costly swap if they're the same
if (beg==l-1)
l--;
else {
swap(--l,beg);
char*tmp=arr[beg]; // update array
arr[beg]=arr[l];
arr[l]=tmp;
}
// recursion
mqsort(arr, beg, l, type);
mqsort(arr, r, end, type);
}
}
// callback for header buttons
void header_callback(Fl_Widget*w, void*) {
Fl_Group* heading = (Fl_Group*)w->parent();
EDE_Browser* browser = (EDE_Browser*)w->parent()->parent();
for (int i=heading->children(); i--; )
if (w == heading->child(i)) { browser->sort(i); break; }
}
// Toggle-type method
void EDE_Browser::sort(int column) {
SortType t = column_sort_types_[column];
if (t==NO_SORT) t=ALPHA_SORT;
if (column!=sort_column || sort_type==NO_SORT)
sort(column, t, false);
else
sort(column, sort_type, !sort_direction);
}
// Real sorting method with three parameters
#define SYMLEN 6
void EDE_Browser::sort(int column, SortType type, bool reverse) {
char *h=column_header_;
int hlen=strlen(h);
char colchar = Fl_Icon_Browser::column_char();
// Remove old sort direction symbol (if any) from header
char *delim = 0;
int col=0;
if (sort_type != NO_SORT) {
bool found=false;
while (delim=strchr(h, colchar)) {
if (col==sort_column) {
strncpy(delim-SYMLEN+1,delim,strlen(delim)+1);
found=true;
break;
}
h=delim+1;
col++;
}
if (!found && col==sort_column)
column_header_[hlen-SYMLEN+1]='\0';
h=column_header_;
delim = 0;
col=0;
}
// Add new symbol
char *newheader = new char[hlen+6];
if (type != NO_SORT) {
// Construct symbol
char sym[SYMLEN];
if (reverse) snprintf(sym,SYMLEN,"@-22<");
else snprintf(sym,SYMLEN,"@-22>");
// Find column
bool found=false;
while (delim=strchr(h, colchar)) {
if (col==column) {
*delim='\0';
snprintf(newheader,hlen+SYMLEN,"%s%s\t%s",column_header_,sym,delim+1);
found=true;
break;
}
h=delim+1;
col++;
}
if (!found && col==column) // Just append symbol to string
snprintf(newheader, hlen+SYMLEN,"%s%s",column_header_,sym);
} else {
strncpy (newheader, column_header_, hlen);
newheader[hlen]='\0';
}
column_header(newheader);
delete[] newheader;
sort_column=column; sort_type=type; sort_direction=reverse;
// Start actually sorting
if (type != NO_SORT) {
// First create an array of strings in a given column
char* sorttext[size()+1]; // index starts from 1 for simplicity in mqsort
for (int i=1;i<=size();i++) {
char *tmp = strdup(text(i));
char *l = tmp;
int col=0;
while (delim=strchr(l, Fl_Icon_Browser::column_char())) {
*delim = '\0';
if (col==column) break;
l=delim+1;
col++;
}
sorttext[i] = strdup(l);
free(tmp);
}
mqsort(sorttext, 1, size()+1, type);
redraw();
// Free the allocated memory
for (int i=1; i<=size(); i++) free (sorttext[i]);
}
}
// --------------------------------------
static void scroll_cb(Fl_Widget* w, void*) {
Fl_Scrollbar *s = (Fl_Scrollbar*)w;
EDE_Browser *b = (EDE_Browser*)w->parent();
b->hposition(s->value());
}
// ctor
EDE_Browser::EDE_Browser(int X,int Y,int W,int H,const char *L) : Fl_Icon_Browser(X,Y,W,H),
totalwidth_(0), column_header_(0), sort_column(0), sort_type(NO_SORT), sort_direction(false) {
heading = new Heading(X,Y,W,buttonheight);
heading->end();
heading->hide();
heading->parent(this); // for callback
hscrollbar = new Fl_Scrollbar(X, Y+H-Fl::scrollbar_size(), W-Fl::scrollbar_size(), Fl::scrollbar_size());
hscrollbar->type(FL_HORIZONTAL);
hscrollbar->hide();
hscrollbar->parent(this); // for callback
hscrollbar->callback(scroll_cb);
has_scrollbar(VERTICAL);
resizable(0);
// EDE_Browser is always a multiple-selection browser
type(FL_MULTI_BROWSER);
column_sort_types_ = new SortType[256]; // 256 columns should be enough for anyone (tm)
for (int i=0; i<256; i++) column_sort_types_[i]=NO_SORT;
}
//make buttons invisible
void EDE_Browser::hide_header() {
if (heading->visible()) resize(x(),y()-buttonheight,w(),h()+buttonheight);
heading->clear();
heading->hide();
}
// Regenerate and display header
void EDE_Browser::show_header() {
int button_x=0;
char *h = column_header_;
const int* l = Fl_Icon_Browser::column_widths();
heading->clear();
for (int i=0; i==0||l[i-1]; i++) {
// If the button is last, calculate size
int button_w = l[i];
if (button_w == 0) button_w = totalwidth_-button_x;
// Get part of header until delimiter char
char *delim = 0;
Fl_Button *b;
if (h) {
delim = strchr(h, Fl_Icon_Browser::column_char());
if (delim) *delim='\0'; // temporarily
b=new Fl_Button(button_x,heading->y(),button_w,buttonheight,strdup(h));
} else {
b=new Fl_Button(button_x,heading->y(),button_w,buttonheight,"");
}
b->align(FL_ALIGN_INSIDE|FL_ALIGN_LEFT|FL_ALIGN_CLIP);
b->callback(header_callback);
b->labelsize(12); // FIXME: hack for label size
//b->labelcolor(FL_DARK3);
heading->add(b);
button_x += l[i];
if (delim) {
*delim=Fl_Icon_Browser::column_char(); // put back delimiter
h=delim+1; // next field
}
}
if (!heading->visible()) resize(x(),y()+buttonheight,w(),this->h()-buttonheight);
heading->resizable(0); // We will resize the heading and individual buttons manually
heading->show();
heading->redraw(); //in case it was already visible
}
// Subclassed to resize heading and browser if neccessary
void EDE_Browser::column_widths(const int* l) {
totalwidth_=0;
int i;
for (i=0; l[i]; i++) totalwidth_+=l[i];
// if (total>=scroll->w()) {
// Fl_Icon_Browser::size(total,h());
// }
fprintf(stderr, "Total width is: %d\n", totalwidth_);
// If there was heading before, regenerate
if (heading->visible())
heading->size(totalwidth_,buttonheight);
// show_header();
// Second array for the Fl_Browser
int *tmp = new int[i]; // FIXME: Someone should cleanup this memory sometimes...
for (int j=0; j<i-1; j++) tmp[j]=l[j];
tmp[i-1]=0;
Fl_Icon_Browser::column_widths(tmp);
// Redraw parent so we don't get ugly artifacts after shrinking last button
// Doesn't work anymore!
// parent()->redraw();
}
const int* EDE_Browser::column_widths() const {
int i,total=0;
const int *l=Fl_Icon_Browser::column_widths();
for (i=0; l[i]; i++) total+=l[i];
int *tmp = new int[i+2]; // FIXME: Someone should cleanup this memory sometimes...
for (int j=0; l[j]; j++) tmp[j]=l[j];
tmp[i]=(totalwidth_-total);
tmp[i+1]=0;
return tmp;
}
// Subclassed handle() for keyboard searching
int EDE_Browser::handle(int e) {
if (e==FL_KEYBOARD) {
// when user presses a key, jump to row starting with that character
int k=Fl::event_key();
if ((k>='a'&&k<='z') || (k>='A'&&k<='Z') || (k>='0'&&k<='9')) {
if (k>='A'&&k<='Z') k+=('a'-'A');
int ku = k - ('a'-'A'); //upper case
int p=lineno(selection());
for (int i=1; i<=size(); i++)
if (i!=p && (text(i)[0]==k || text(i)[0]==ku)) {
// select(line,0) just moves focus to line without selecting
// if line was already selected, it won't be anymore
select(i,selected(i));
middleline(i);
break;
}
}
// Attempt to fix erratic behavior on enter key
// Fl_Browser seems to do the following on enter key:
// - when item is both selected and focused, callback isn't called at all (even when FL_WHEN_ENTER...)
// - when no item is selected, callback is called 2 times on focused item
// - when one item is selected and other is focused, callback is first called on selected then on
// focused item
// This partial fix at least ensures that callback is always called. Callback should behave properly
// when called many times.
if ((when() & FL_WHEN_ENTER_KEY_ALWAYS) && k == FL_Enter) {
// if (changed()!=0) {
//fprintf(stderr,"do_callback()\n");
do_callback();
// }
}
}
return Fl_Icon_Browser::handle(e);
}
// Overload resize for show/hide horizontal scrollbar
void EDE_Browser::resize(int X, int Y, int W, int H) {
if (W >= totalwidth_) {
// hide scrollbar
if (hscrollbar->visible())
hscrollbar->hide();
Fl_Icon_Browser::resize(X,Y,W,H);
} else {
// show scrollbar
int fsbs = Fl::scrollbar_size();
if (!hscrollbar->visible())
hscrollbar->show();
Fl_Icon_Browser::resize(X,Y,W, H-fsbs);
hscrollbar->resize(X, Y+H-fsbs, W-fsbs, fsbs);
hscrollbar->value(hscrollbar->value(), W, 0, totalwidth_);
}
}
// *****************
// class Heading - implementation
// *****************
// The following code is modified from Fl_Tile.cxx and extensively commented, as I was trying
// to figure it out ;)
static void set_cursor(Fl_Group*t, Fl_Cursor c) {
static Fl_Cursor cursor;
if (cursor == c || !t->window()) return;
cursor = c;
#ifdef __sgi
t->window()->cursor(c,FL_RED,FL_WHITE);
#else
t->window()->cursor(c);
#endif
}
static Fl_Cursor cursors[4] = {
FL_CURSOR_DEFAULT,
FL_CURSOR_WE,
FL_CURSOR_NS,
FL_CURSOR_MOVE
};
int EDE_Browser::Heading::handle(int event) {
static int sdrag; // Type of drag
static int sdx; // Event distance from the widget boundary
static int sx; // Original event x
#define DRAGH 1
#define DRAGV 2
// width of grabbing area in pixels:
#define GRABAREA 4
// Event coordinates
int evx = Fl::event_x();
int evy = Fl::event_y();
switch (event) {
case FL_MOVE:
case FL_ENTER:
case FL_PUSH: {
int mindx = 100;
int mindy = 100;
int oldx = 0;
int oldy = 0;
Fl_Widget*const* a = array();
// Is there a button boundary within GRABAREA ?
for (int i=0; i<children(); i++) {
Fl_Widget* o = *a++;
if (o == resizable()) continue; // resizable has a special meaning in Fl_Tile, but we don't use it in Heading
if (o->y()<=evy+GRABAREA && o->y()+o->h()>=evy-GRABAREA) {
int t = evx - (o->x()+o->w());
if (abs(t) < mindx) {
sdx = t;
mindx = abs(t);
}
}
}
sdrag = 0; sx = 0;
if (mindx <= GRABAREA) {sdrag = DRAGH; sx = evx;}
set_cursor(this, cursors[sdrag]);
if (sdrag) return 1;
return Fl_Group::handle(event);
}
case FL_LEAVE:
set_cursor(this, FL_CURSOR_DEFAULT);
break;
case FL_DRAG:
// This is necessary if CONSOLIDATE_MOTION in Fl_x.cxx is turned off:
// if (damage()) return 1; // don't fall behind
case FL_RELEASE: {
if (!sdrag) return 0; // should not happen
Fl_Widget* r = resizable(); if (!r) r = this;
// Calculate where the new boundary (newx) should be
int newx;
if (sdrag&DRAGH) {
newx = Fl::event_x()-sdx;
if (newx < r->x()) newx = r->x();
else if (newx > r->x()+r->w()) newx = r->x()+r->w();
}
// Mouse movement distance (dx)
int dx = Fl::event_x()-sx;
Fl_Widget*const* a = array();
// Here we check if any widget will get size 0
// because column size 0 is illegal in Browser
for (int i=children(); i--; ) {
Fl_Widget* o = a[i];
int end = o->x()+o->w(); // End coord. of widget
if ((end == newx-dx || newx<1) && o->w()+dx < 1) {
set_changed();
do_callback();
set_cursor(this, FL_CURSOR_DEFAULT);
return 1;
}
}
if (newx>=w()) newx+=dx; // last button is resized by dragging the edge
// Go again through list of widgets and resize everything
int *columns = new int[children()+1];
int j=0;
for (int i=children(); i--; ) {
Fl_Widget* o = *a++;
int end = o->x()+o->w(); // End coord. of widget
if (end == newx-dx) {
// Resize left widget
o->damage_resize( o->x(), o->y(), o->w()+dx, o->h());
} else if (end > newx-dx) {
// Resize all remaining widgets to the right
o->damage_resize(o->x()+dx, o->y(), o->w(), o->h());
}
// Push new width into the columns array
columns[j++]=o->w();
}
columns[j]=0;
// This is the EDE_Browser method. It will also resize the heading and
// the browser if neccessary
EDE_Browser*b = (EDE_Browser*)parent();
b->column_widths(columns);
b->redraw(); // OPTIMIZE (some smart damage in column_widths() ?)
free(columns);
// There will be many RELEASE events, so we update sx (used when calculating dx)
sx=Fl::event_x();
if (event == FL_DRAG) set_changed();
do_callback();
return 1;
}
}
return Fl_Group::handle(event);
}

186
efiler/EDE_Browser.h Normal file
View File

@ -0,0 +1,186 @@
/*
* $Id$
*
* EDE Browser class
* Part of edelib.
* Copyright (c) 2005-2007 EDE Authors.
*
* This program is licenced under terms of the
* GNU General Public Licence version 2 or newer.
* See COPYING for details.
*/
#ifndef EDE_Browser_H
#define EDE_Browser_H
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Tile.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Scrollbar.H>
#include <FL/Fl_Image.H>
#include "Fl_Icon_Browser.h"
enum SortType {
NO_SORT = 0, ///< don't sort, items will be shown in order of adding
ALPHA_SORT = 1, ///< standard bibliographic sort
ALPHA_CASE_SORT = 2, ///< standard bibliographic sort ignoring the case
NUMERIC_SORT = 3, ///< items are converted to numbers and sorted by size
DATE_SORT = 4, ///< sort by date (depends on user locale)
FILE_SIZE_SORT = 5 ///< same as numeric, but also considering units such as kB, MB, GB
};
/**
* \class EDE_Browser
* \brief An improved version of Fl_Browser
*
* This is a (mostly compatible) version of Fl_Browser that adds
* following features:
* * sorting by column, using one of the several offered sort types,
* * optional header which enables resizing columns and sorting
* (by clicking the title of column that you wish to sort),
* * quick search (by pressing the first character of the item you
* are searching).
*
* The type of browser is set by default to FL_MULTI_BROWSER (call
* method type() to change).
*
* The class is based on Fl_Icon_Browser (which is just a Fl_Browser
* that can display icons) that I sincerelly hope will one day go
* upstream.
*
*/
class EDE_Browser : public Fl_Icon_Browser {
private:
// Button row height
static const int buttonheight=20;
// Subclass Fl_Group for handle()-ing button resizing and clicks
class Heading : public Fl_Group {
public:
Heading(int x, int y, int w, int h, const char *label = 0) : Fl_Group(x,y,w,h,label) {}
int handle(int e);
} *heading;
Fl_Scrollbar *hscrollbar;
int totalwidth_; // total width of all columns
char *column_header_;
SortType *column_sort_types_;
// current sort:
int sort_column;
SortType sort_type;
bool sort_direction;
void hide_header();
void show_header();
void mqsort(char *labels[], int beg, int end, SortType type); // my implementation of qsort
bool sortfn(char *,char*,SortType); // sort function, per type
public:
EDE_Browser(int X,int Y,int W,int H,const char *L=0);
~EDE_Browser() {
delete[] column_sort_types_;
delete heading;
// delete scroll;
delete hscrollbar;
if (column_header_) free(column_header_); // this is a C-string
}
/**
* Get or set the column titles and display the header.
*
* \param c is formatted just like other items, e.g. it uses the same column_char()
* To hide the header, just call with a null pointer (this is the default value).
*/
void column_header(const char *c) {
free(column_header_);
if (c) {
column_header_=strdup(c);
show_header();
} else {
column_header_=0;
hide_header();
}
}
const char *column_header() { return column_header_; }
/**
* Sets the way various columns are sorted. By default all columns will use
* ALPHA_SORT e.g. classic bibliographic sort. Usually the programmer knows in
* advance what kind of data will be put into which column, so (s)he can set
* how each column will be sorted when the header buttons are clicked.
*
* \param l constant pointer to a sufficiently large array of SortType, corresponding
* to columns. Last value in this array must be 0 (NO_SORT) (there's no point for
* setting sort type of a column to NO_SORT; if you want to unsort the browser, just
* call sort(0, NO_SORT) ).
*/
void column_sort_types (const SortType *l) { for (int i=0; l[i]; i++) column_sort_types_[i]=l[i]; }
/**
* Sort items by column.
*
* \param column number of column to use for sorting
* \param type type of sorting to be used
* \param reverse if true, items will be sorted in reverse order
*/
void sort(int column, SortType type, bool reverse=false);
/**
* Sort items by column (toggle-type method). It will use the default sort type for
* given column, as set by column_sort_types(). If column is already sorted in normal
* order, this will resort in reverse - this method gives the same effect as clicking
* on column button.
*
* \param column number of column to use for sorting
*/
void sort(int column);
/**
* Set and get column widths.
* NOTE: *Unlike* Fl_Browser, you need to specify the width of the
* last column as well! If the sum of witdhs is larger than the
* Browser, a horizontal scrollbar will be shown. If it is smaller,
* there will be some unused space to the right.
*
* \param l array of column widths in pixels, ending with zero (please
* don't forget to set the last value of the array to 0). If you wish
* to make a column (practically) invisible, set width to 1 pixel.
*/
void column_widths(const int* l);
const int* column_widths() const;
// Overload handle for keyboard quick search
int handle(int e);
// Overload resize for show/hide horizontal scrollbar
void resize(int X, int Y, int W, int H);
// Overload hposition(), so that heading scrolls together with browser
void hposition(int x) {
if (heading->visible()) {
heading->resize(0-x,heading->y(),totalwidth_,buttonheight);
heading->redraw();
}
Fl_Icon_Browser::hposition(x);
}
};
#endif
//
// End of "$Id$".
//

View File

@ -1,395 +0,0 @@
//
// "$Id: FileBrowser.cxx 5071 2006-05-02 21:57:08Z fabien $"
//
// FileBrowser routines.
//
// Copyright 1999-2006 by Michael Sweet.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
// Contents:
//
// FileBrowser::full_height() - Return the height of the list.
// FileBrowser::item_height() - Return the height of a list item.
// FileBrowser::item_width() - Return the width of a list item.
// FileBrowser::item_draw() - Draw a list item.
// FileBrowser::FileBrowser() - Create a FileBrowser widget.
// FileBrowser::load() - Load a directory into the browser.
// FileBrowser::filter() - Set the filename filter.
//
//
// Include necessary header files...
//
#include "EDE_DirTree.h"
#include <fltk/Browser.h>
#include <fltk/Item.h>
#include <fltk/draw.h>
#include <fltk/Color.h>
#include <fltk/Flags.h>
#include <fltk/Font.h>
#include <fltk/string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// This library is hopelessly single-platform
#include "../edelib2/Icon.h"
#include "../edelib2/Util.h"
#include "../edelib2/NLS.h"
#include <fltk/run.h>
#define MAX_TREE_DEPTH 100
using namespace fltk;
//
// 'FileBrowser::FileBrowser()' - Create a FileBrowser widget.
//
// Fn that makes sure path ends with slash
// (ensure that path allocation is large enough to take one extra char)
void make_end_with_slash(char* path) {
int i=strlen(path);
if (path[i-1] != '/') {
path[i]='/';
path[i+1]='\0';
}
}
DirTree::DirTree(int X, // I - Upper-lefthand X coordinate
int Y, // I - Upper-lefthand Y coordinate
int W, // I - Width in pixels
int H, // I - Height in pixels
const char *l) // I - Label text
: Browser(X, Y, W, H, l) {
// Initialize the filter pattern, current directory, and icon size...
//pattern_ = "*";
//directory_ = "";
//icon_size_ = 12.0f;
//filetype_ = FILES;
show_hidden_ = false;
//Symbol* fileSmall = edelib::Icon::get(DEFAULT_ICON,edelib::Icon::SMALL);
//set_symbol(Browser::LEAF, fileSmall, fileSmall);
}
// Filesystem data
// TODO: find better icons for Amiga, Macintosh etc.
static struct {
char id[15];
char uiname[50];
char icon[20];
} filesystems[] = {
// Filesystems that should be ignored
{"auto", "", ""}, // removables will be added another way
{"autofs", "", ""}, // removables will be added another way
{"binfmt_misc", "", ""},
{"debugfs", "", ""},
{"devfs", "", ""},
{"devpts", "", ""},
{"fd", "", ""},
{"fdesc", "", ""},
{"kernfs", "", ""},
{"proc", "", ""},
{"procfs", "", ""},
{"swap", "", ""},
{"sysfs", "", ""},
{"tmpfs", "", ""},
{"usbfs", "", ""},
// Common filesystems
{"ext2", "Linux disk (%s)", "hdd_unmount"},
{"ext2fs", "Linux disk (%s)", "hdd_unmount"},
{"ext3", "Linux disk (%s)", "hdd_unmount"},
{"reiserfs", "Linux disk (%s)", "hdd_unmount"},
{"ffs", "BSD disk (%s)", "hdd_unmount"},
{"ufs", "Unix disk (%s)", "hdd_unmount"},
{"dos", "Windows disk (%s)", "win_mount"},
{"fat", "Windows disk (%s)", "win_mount"},
{"msdos", "Windows disk (%s)", "win_mount"},
{"ntfs", "Windows disk (%s)", "win_mount"},
{"pcfs", "Windows disk (%s)", "win_mount"},
{"umsdos", "Windows disk (%s)", "win_mount"},
{"vfat", "Windows disk (%s)", "win_mount"},
{"cd9660", "CD-ROM (%s)", "cdrom_unmount"},
{"cdfs", "CD-ROM (%s)", "cdrom_unmount"},
{"cdrfs", "CD-ROM (%s)", "cdrom_unmount"},
{"hsfs", "CD-ROM (%s)", "cdrom_unmount"},
{"iso9660", "CD-ROM (%s)", "cdrom_unmount"},
{"isofs", "CD-ROM (%s)", "cdrom_unmount"},
{"udf", "DVD-ROM (%s)", "dvd_unmount"},
{"cifs", "Shared directory (%s)", "server"},
{"nfs", "Shared directory (%s)", "server"},
{"nfs4", "Shared directory (%s)", "server"},
{"smbfs", "Shared directory (%s)", "server"},
{"cramfs", "Virtual (RAM) disk (%s)", "memory"},
{"mfs", "Virtual (RAM) disk (%s)", "memory"},
{"ramfs", "Virtual (RAM) disk (%s)", "memory"},
{"romfs", "Virtual (RAM) disk (%s)", "memory"},
{"union", "Virtual (RAM) disk (%s)", "memory"}, // not accurate, but good enough
{"unionfs", "Virtual (RAM) disk (%s)", "memory"}, // not accurate, but good enough
{"jfs", "IBM AIX disk (%s)", "hdd_unmount"},
{"xfs", "SGI IRIX disk (%s)", "hdd_unmount"},
// Other filesystems
{"coherent", "Unix disk (%s)", "hdd_unmount"},
{"sysv", "Unix disk (%s)", "hdd_unmount"},
{"xenix", "Unix disk (%s)", "hdd_unmount"},
{"adfs", "RiscOS disk (%s)", "hdd_unmount"},
{"filecore", "RiscOS disk (%s)", "hdd_unmount"},
{"ados", "Amiga disk (%s)", "hdd_unmount"},
{"affs", "Amiga disk (%s)", "hdd_unmount"},
{"afs", "AFS shared directory (%s)", "server"},
{"befs", "BeOS disk (%s)", "hdd_unmount"},
{"bfs", "UnixWare disk (%s)", "hdd_unmount"},
{"efs", "SGI IRIX disk (%s)", "hdd_unmount"},
{"ext", "Old Linux disk (%s)", "hdd_unmount"},
{"hfs", "Macintosh disk (%s)", "hdd_unmount"}, // Also used for HP-UX filesystem!!
{"hpfs", "OS/2 disk (%s)", "hdd_unmount"},
// {"lfs", "BSD LFS disk (%s)", "hdd_unmount"}, // This is said to not work
{"minix", "Minix disk (%s)", "hdd_unmount"},
{"ncpfs", "NetWare shared directory (%s)", "server"},
{"nwfs", "NetWare shared directory (%s)", "server"},
{"qns", "QNX disk (%s)", "hdd_unmount"},
{"supermount", "Removable disk (%s)", "cdrom_umnount"}, // ???
{"xiafs", "Old Linux disk (%s)", "hdd_unmount"},
// Virtual filesystems (various views of existing files)
// How often are these used?
// {"cachefs", "Unix virtual disk ?? (%s)", "memory"},
// {"lofs", "Solaris virtual disk ?? (%s)", "memory"},
// {"null", "BSD virtual disk ?? (%s)", "memory"},
// {"nullfs", "BSD virtual disk ?? (%s)", "memory"},
// {"overlay", "BSD virtual disk ?? (%s)", "memory"},
// {"portal", "BSD virtual disk ?? (%s)", "memory"},
// {"portalfs", "BSD virtual disk ?? (%s)", "memory"},
// {"umap", "BSD virtual disk ?? (%s)", "memory"},
// {"umapfs", "BSD virtual disk ?? (%s)", "memory"},
{"", "", ""}
};
//
// 'FileBrowser::load()' - Load basic directory list into browser
//
int // O - Number of files loaded
DirTree::load()
{
int num_files=0;
char buffer[PATH_MAX]; // buffer for labels
Group* o; // generic pointer
this->begin();
// Top level icon
Group* system = (Group*)add_group(_("System"), 0, 0, edelib::Icon::get("tux",edelib::Icon::TINY));
// Home icon
snprintf(buffer,PATH_MAX,_("%s's Home"), getenv("USER"));
o = (Group*)add_group(strdup(buffer), system, 0, edelib::Icon::get("folder_home",edelib::Icon::TINY));
strncpy(buffer,getenv("HOME"),PATH_MAX);
// Home env. var. often doesn't end with slash
make_end_with_slash(buffer);
o->user_data(strdup(buffer));
// Root icon
o = (Group*)add_group(_("Whole disk"), system, 0, edelib::Icon::get("folder_red",edelib::Icon::TINY));
o->user_data(strdup("/"));
num_files=3;
// Read mtab/fstab/whatever
FILE *mtab; // /etc/mtab or /etc/mnttab file
char line[1024]; // Input line
char device[1024], mountpoint[1024], fs[1024];
// mtab doesn't contain removable entries, but we will find another way
// to add them (some day)
mtab = fopen("/etc/mnttab", "r"); // Fairly standard
if (mtab == NULL)
mtab = fopen("/etc/mtab", "r"); // More standard
if (mtab == NULL)
mtab = fopen("/etc/fstab", "r"); // Otherwise fallback to full list
if (mtab == NULL)
mtab = fopen("/etc/vfstab", "r"); // Alternate full list file
while (mtab!= NULL && fgets(line, sizeof(line), mtab) != NULL) {
if (line[0] == '#' || line[0] == '\n')
continue;
if (sscanf(line, "%s%s%s", device, mountpoint, fs) != 3)
continue;
make_end_with_slash(mountpoint);
// Stuff that should be invisible cause we already show it
if (strcmp(mountpoint,"/") == 0) continue; // root
if (strcmp(mountpoint,getenv("HOME")) == 0) continue; // home dir
// Device name without "/dev/"
char *shortdev = strrchr(device,'/');
if (shortdev==NULL) shortdev=device; else shortdev++;
// Go through list of known filesystems
for (int i=0; filesystems[i].id[0] != '\0'; i++) {
if (strcmp(fs, filesystems[i].id) == 0) {
if (filesystems[i].uiname[0] == '\0') break; // skipping this fs
snprintf(buffer, PATH_MAX, filesystems[i].uiname, shortdev);
o = (Group*)add_group(strdup(buffer), system, 0, edelib::Icon::get(filesystems[i].icon, edelib::Icon::TINY));
o->user_data(strdup(mountpoint));
num_files++;
}
}
}
this->end();
system->set_flag(fltk::OPENED);
this->redraw();
return (num_files);
}
// Browser method for opening (expanding) a subtree
// We override this method so we could scan directory tree on demand
bool DirTree::set_item_opened(bool open) {
// Eliminate bogus call
if (!item()) return false;
// This is what we do different from Browser:
//fprintf (stderr, "Children: %d\n",children(current_index(),current_level()+1));
if (open && children(current_index(),current_level()+1)<=0) {
dirent** files;
char* directory = (char*)item()->user_data();
char filename[PATH_MAX];
// NOTE we default to casenumericsort!
int num_files = filename_list(directory, &files, casenumericsort);
Group* current = (Group*)item();
for (int i=0; i<num_files; i++) {
if (files[i]->d_name[0] == '.' && show_hidden_==false) continue;
if (!strcmp(files[i]->d_name,"./") || !strcmp(files[i]->d_name,"../")) continue;
snprintf(filename, PATH_MAX, "%s%s", directory, files[i]->d_name);
//fprintf(stderr, "Testing: %s\n",filename);
if (filename_isdir(filename)) {
// Strip slash from label
char *n = strdup(files[i]->d_name);
n[strlen(n)-1] = '\0';
Group* o = (Group*)add_group(n, current, 0, edelib::Icon::get("folder", edelib::Icon::TINY));
o->user_data(strdup(filename));
}
}
}
return Browser::set_item_opened(open);
}
// Recursively find tree entry whose user_data() (system path)
// contains the largest portion of given path
// Best match is focused, return value tells if perfect match was found
bool DirTree::set_current(const char* path) {
int tree[MAX_TREE_DEPTH];
// Copy of path where we add slash as needed
char mypath[PATH_MAX];
strncpy(mypath,path,PATH_MAX-2);
make_end_with_slash(mypath);
// There is always exactly one toplevel entry - "System"
tree[0]=0;
set_item(tree,1);
bool t = find_best_match(mypath,tree,1);
set_focus();
// Expand current item
set_item_opened(true);
return t;
}
// Recursive function called by set_current()
bool DirTree::find_best_match(const char* path, int* tree, int level) {
uint bestlen=0;
int bestindex=-1;
int n_children = children(tree,level);
// Given entry has no children
// let's forward this result to first caller
if (n_children == -1) return false;
// Look at all children of given entry and find the best match
for (int i=0; i<n_children; i++) {
tree[level]=i;
Widget* w = child(tree,level);
char* p = (char*)w->user_data();
if (strlen(p)>strlen(path)) continue; // too specific
if ((strncmp(path, p, strlen(p)) == 0) && (strlen(p)>bestlen)) {
bestlen=strlen(p);
bestindex=i;
}
}
// No matches found
if (bestindex==-1) return false;
// Focus on best match
tree[level]=bestindex;
goto_index(tree,level);
//char* p = (char*)child(tree,level)->user_data();
//fprintf (stderr, "Found: %s\n", p);
// Is this a perfect match?
if (bestlen == strlen(path)) return true;
// Can the best item be further expanded?
set_item_opened(true);
// Try its children (if none, it will return false)
return find_best_match(path, tree, level+1);
}
//
// End of "$Id: FileBrowser.cxx 5071 2006-05-02 21:57:08Z fabien $".
//

View File

@ -1,94 +0,0 @@
//
// "$Id: FileBrowser.h 4926 2006-04-10 21:03:29Z fabien $"
//
// FileBrowser definitions.
//
// Copyright 1999-2006 by Michael Sweet.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
//
// Include necessary header files...
//
#ifndef edelib_DirTree_h
#define edelib_DirTree_h
#include <fltk/Browser.h>
#include <fltk/filename.h>
//namespace fltk {
//
// FileBrowser class...
//
class DirTree : public fltk::Browser
{
public:
DirTree(int, int, int, int, const char * = 0);
/*float icon_size() const {
return (icon_size_ <0? (2.0f* textsize()) : icon_size_);
}
void icon_size(float f) { icon_size_ = f; redraw(); };*/
// Set given directory as current. Returns false if directory doesn't exist
// (the closest parent directory will be selected)
bool set_current(const char* path);
// Load base directories into widget
int load();
// Browser method for opening (expanding) a subtree
// We override this method so we could scan directory tree on demand
bool set_item_opened(bool);
// adding or inserting a line into the fileBrowser
//void insert(int n, const char* label, fltk::FileIcon* icon);
//void insert(int n, const char* label, void* data){fltk::Menu::insert(n, label,data);}
//void add(const char * line, fltk::FileIcon* icon);
// Return full system path to given item
const char* system_path(int i) const {
return (const char*)child(i)->user_data(); }
// Showing or not showing the hidden files, that's the question:
public:
// sets this flag if you want to see the hidden files in the browser
void show_hidden(bool show) { show_hidden_= show; }
bool show_hidden() const {return show_hidden_;}
private:
bool show_hidden_;
bool find_best_match(const char* path, int* indexes, int level);
};
//}
#endif // !_Fl_File_Browser_H_
//
// End of "$Id: FileBrowser.h 4926 2006-04-10 21:03:29Z fabien $".
//

View File

@ -1,416 +0,0 @@
//
// "$Id: FileBrowser.cxx 5071 2006-05-02 21:57:08Z fabien $"
//
// FileBrowser routines.
//
// Copyright 1999-2006 by Michael Sweet.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
// Contents:
//
// FileBrowser::full_height() - Return the height of the list.
// FileBrowser::item_height() - Return the height of a list item.
// FileBrowser::item_width() - Return the width of a list item.
// FileBrowser::item_draw() - Draw a list item.
// FileBrowser::FileBrowser() - Create a FileBrowser widget.
// FileBrowser::load() - Load a directory into the browser.
// FileBrowser::filter() - Set the filename filter.
//
//
// Include necessary header files...
//
#include "EDE_FileBrowser.h"
#include <fltk/Browser.h>
#include <fltk/Item.h>
#include <fltk/draw.h>
#include <fltk/Color.h>
#include <fltk/Flags.h>
#include <fltk/Font.h>
#include <fltk/string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __CYGWIN__
# include <mntent.h>
#elif defined(WIN32)
# include <windows.h>
# include <direct.h>
// Apparently Borland C++ defines DIRECTORY in <direct.h>, which
// interfers with the FileIcon enumeration of the same name.
# ifdef DIRECTORY
# undef DIRECTORY
# endif // DIRECTORY
#endif // __CYGWIN__
#ifdef __EMX__
# define INCL_DOS
# define INCL_DOSMISC
# include <os2.h>
#endif // __EMX__
// CodeWarrior (__MWERKS__) gets its include paths confused, so we
// temporarily disable this...
#if defined(__APPLE__) && !defined(__MWERKS__)
# include <sys/param.h>
# include <sys/ucred.h>
# include <sys/mount.h>
#endif // __APPLE__ && !__MWERKS__
#include "../edelib2/Icon.h"
#include "../edelib2/Util.h"
#include "../edelib2/MimeType.h"
#include "../edelib2/NLS.h"
#define DEFAULT_ICON "misc-vedran"
#define FOLDER_ICON "folder"
#define UPDIR_ICON "undo"
#include <fltk/run.h>
#include <fltk/Input.h>
#include <fltk/events.h>
#include <fltk/ask.h>
#include <errno.h>
using namespace fltk;
using namespace edelib;
// Event handler for EditBox
int EditBox::handle(int event) {
if (!this->visible()) return parent()->handle(event);
bool above=false;
//fprintf(stderr,"Editbox event: %d (%s)\n",event,event_name(event));
// Change filename
if (event==KEY && (event_key()==ReturnKey || event_key()==KeypadEnter)) {
// split old filename to path and file
char path[PATH_MAX], file[PATH_MAX];
strcpy(path, (char*)editing_->user_data());
if (path[strlen(path)-1] == '/') path[strlen(path)-1]='\0';
char *p = strrchr(path,'/');
if (p==0 || *p=='\0') {
strcpy(file,path);
path[0]='\0';
} else { // usual case
p++;
strcpy(file,p);
*p='\0';
}
if (strlen(file)!=strlen(text()) || strcmp(file,text())!=0) {
// Create new filename
strncat(path, text(), PATH_MAX-strlen(path));
char oldname[PATH_MAX];
strcpy(oldname, (char*)editing_->user_data());
if (rename(oldname, path) == -1) {
alert(tsprintf(_("Could not rename file! Error was:\n\t%s"), strerror(errno)));
} else {
// Update browser
free(editing_->user_data());
editing_->user_data(strdup(path));
const char* l = editing_->label();
editing_->label(tasprintf("%s%s",text(),strchr(l, '\t')));
}
}
above=true;
}
// Hide editbox
if (above || ( event==KEY && event_key()==EscapeKey ) ) {
this->hide();
return 1;
}
Input::handle(event);
}
// We override hide method to ensure certain things done
void EditBox::hide() {
Input::hide();
// Remove box so it doesn't get in the way
this->x(0);
this->y(0);
this->w(0);
this->h(0);
// Return the browser item into "visible" state
if (editing_) {
editing_->textcolor(textcolor());
editing_->redraw();
parent()->take_focus();
}
}
// Column widths and titles
// TODO: make more configurable
const char *labels[] = {_("Name"),_("Type"),_("Size"),_("Date"),0};
int widths[] = {200, 150, 100, 150, 0};
//
// 'FileBrowser::FileBrowser()' - Create a FileBrowser widget.
//
FileBrowser::FileBrowser(int X, // I - Upper-lefthand X coordinate
int Y, // I - Upper-lefthand Y coordinate
int W, // I - Width in pixels
int H, // I - Height in pixels
const char *l) // I - Label text
: Browser(X, Y, W, H, l) {
// Initialize the filter pattern, current directory, and icon size...
pattern_ = "*";
directory_ = "";
//icon_size_ = 12.0f;
filetype_ = BOTH;
show_hidden_ = false;
show_dotdot_ = true;
column_labels(labels);
column_widths(widths);
// Editbox
editbox_ = new EditBox (0, 0, 0, 0);
editbox_->box(BORDER_FRAME);
editbox_->parent(this);
editbox_->hide();
}
//
// 'FileBrowser::load()' - Load a directory into the browser.
//
int // O - Number of files loaded
FileBrowser::load(const char *directory,// I - Directory to load
File_Sort_F *sort) // I - Sort function to use
{
int i; // Looping var
int num_files; // Number of files in directory
int num_dirs; // Number of directories in list
char filename[PATH_MAX]; // Current file
//FileIcon *icon; // Icon to use
// printf("FileBrowser::load(\"%s\")\n", directory);
if (!directory)
return (0);
clear();
directory_ = directory;
if (directory_[0] == '\0')
{
//
// No directory specified; for UNIX list all mount points. For DOS
// list all valid drive letters...
//
// TODO!
fprintf (stderr, "Drive list not implemented yet");
return 0;
}
// Scan directory and store list in **files
dirent **files;
num_files = fltk::filename_list(directory_, &files, sort);
if (num_files <= 0) return (0);
// Allocate array for icons
Item** icon_array = (Item**) malloc (sizeof(Item*) * num_files + 1);
// fill array with zeros, for easier detection if item exists
for (i=0; i<num_files; i++) icon_array[i]=0;
// Show the up directory - "../"
num_dirs = 0;
if (show_dotdot_ && strcmp(directory_,"/") != 0) {
num_dirs++;
Item* o = new Item ( Icon::get ( UPDIR_ICON, Icon::TINY ), "..\tGo up" );
Menu::add(*o);
snprintf(filename, PATH_MAX, "%s../", directory_);
o->user_data(strdup(filename));
}
// Main loop for populating browser
for (i = 0; i < num_files; i ++) {
if (strcmp(files[i]->d_name, "./")==0)
continue;
char *n = files[i]->d_name; // shorter
snprintf(filename, PATH_MAX, "%s%s", directory_, n);
if (strcmp(n, ".")==0 || strcmp(n, "./")==0 || (!show_hidden_ && (n[0]=='.' || n[strlen(n)-1]=='~') ) )
continue;
fltk::check(); //update interface
// Add directory
if (filetype_ != FILES && fltk::filename_isdir(filename)) {
num_dirs ++;
// strip slash from filename
char *fn = strdup(n);
if (fn[strlen(fn)-1] == '/')
fn[strlen(fn)-1] = '\0';
Item* o = new Item ( Icon::get ( FOLDER_ICON,Icon::TINY ), fn);
Menu::insert(*o, num_dirs-1);
o->user_data(strdup(filename)); // we keep full path for callback
icon_array[i]=o;
// Add file
} else if (filetype_ != DIRECTORIES && fltk::filename_match(n, pattern_)) {
Item* o = new Item(Icon::get(DEFAULT_ICON,Icon::TINY), strdup(n));
Menu::add(*o);
o->user_data(strdup(filename)); // we keep full path for callback
icon_array[i]=o;
}
} // end for
this->redraw();
//
// Detect icon mimetypes etc.
//
MimeType *m = new MimeType();
for (i=0; i<num_files; i++) {
// ignored files
if (!icon_array[i]) continue;
fltk::check(); // update interface
// get mime data
snprintf (filename,4095,"%s%s",directory_,files[i]->d_name);
m->set(filename);
// change label to complete data in various tabs
char *label;
if (strncmp(m->id(),"directory",9)==0) {
// Strip slash from filename
char *n = strdup(files[i]->d_name);
n[strlen(n)-1] = '\0';
asprintf(&label, "%s\t%s\t\t%s", n, m->type_string(), nice_time(filename_mtime(filename)));
free(n);
} else
asprintf(&label, "%s\t%s\t%s\t%s", files[i]->d_name, m->type_string(), nice_size(filename_size(filename)), nice_time(filename_mtime(filename)));
icon_array[i]->label(label);
// icon
icon_array[i]->image(m->icon(Icon::TINY));
icon_array[i]->redraw();
free(files[i]);
}
delete m;
free(files);
return (num_files);
}
//
// 'FileBrowser::filter()' - Set the filename filter.
//
// I - Pattern string
void FileBrowser::filter(const char *pattern) {
// If pattern is NULL set the pattern to "*"...
if (pattern) pattern_ = pattern;
else pattern_ = "*";
}
// We override the fltk standard event handling to detect when
// user is clicking on already selected item and show filename editbox
int FileBrowser::handle(int event) {
const int iconspace=20;
// Handle all events in editbox
if (editbox_->visible()) {
if (event == PUSH && !event_inside(Rectangle(editbox_->x(), editbox_->y(), editbox_->w(), editbox_->h())))
editbox_->hide();
else
return editbox_->handle(event);
}
if (event==PUSH && !event_clicks() &&
// Don't accept clicks outside first column:
event_x()<widths[0])
for(int i=0; i<children()-1; i++)
if (event_y()>child(i)->y() &&
// Handle last child
(i==children()-1 || event_y()<child(i+1)->y()) &&
child(i)->flags()&SELECTED &&
// Make sure only one item is selected:
child(i)==item() &&
// Can't rename "up directory"
strcmp(child(i)->label(),"../") != 0) {
// "hide" item
editbox_->textcolor(child(i)->textcolor());
child(i)->textcolor(child(i)->color());
child(i)->throw_focus();
// deselect all
set_item_selected(false);
//deselect();
// Show editbox at item coordinates
editbox_->x(this->x()+child(i)->x()+iconspace);
editbox_->y(child(i)->y());
editbox_->w(150);
editbox_->h(20);
editbox_->show();
// Copy last part of path to editbox
char*p = strdup((char*)child(i)->user_data());
if (p[strlen(p)-1] == '/') p[strlen(p)-1]='\0';
char*q = strrchr(p,'/');
if (q!=0)
editbox_->text(q+1);
else
editbox_->text(p);
free(p);
/*char*p = strdup((char*)this->user_data());
editbox_->text(filename_name(p));*/
editbox_->take_focus();
editbox_->editing(child(i));
return 0;
}
return Browser::handle(event);
}
//
// End of "$Id: FileBrowser.cxx 5071 2006-05-02 21:57:08Z fabien $".
//

View File

@ -1,146 +0,0 @@
//
// "$Id: FileBrowser.h 4926 2006-04-10 21:03:29Z fabien $"
//
// FileBrowser definitions.
//
// Copyright 1999-2006 by Michael Sweet.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
//
// Include necessary header files...
//
#ifndef edelib_FileBrowser_h
#define edelib_FileBrowser_h
#include <fltk/Browser.h>
#include <fltk/filename.h>
#include <fltk/Input.h>
//namespace fltk {
// Class for the little input box used when we edit an item
// FIXME: Why can this box be resized????
// TODO: When editbox appears, select filename part and leave extension not-selected
// (as in Konqueror)
class EditBox : public fltk::Input {
fltk::Widget* editing_;
public:
EditBox(int x, int y, int w, int h, const char* label = 0) : fltk::Input(x,y,w,h,label) , editing_(0) {}
void editing(fltk::Widget*w) { editing_=w; }
int handle (int event);
void hide();
};
/*! \class edelib::FileBrowser
This class can be used as a drop-in replacement for fltk::FileBrowser because
it has much of the same API. In addition, it has the following features:
- uses edelib::MimeType and edelib::Icon to display file icons
- multicolumn view with columns: file name, type, size, date of last
modification and file permissions
- sorting by each column, by clicking on column headers or programmatically
- renaming files by clicking on a already selected file
- drag&drop support
- several other properties for fine tuning of display.
By convention, real filename with full path of each item is stored in its
user_data() so you can easily access it from item callback or using the
const char* system_path(int index) method.
Events that take place on double clicking, dropping files, popup menu etc.
should be implemented in callback, which enables you to create read-write
or read-only widgets as desired (e.g. in file chooser).
*/
//
// FileBrowser class...
//
class FileBrowser : public fltk::Browser
{
int filetype_;
const char *directory_;
//float icon_size_;
const char *pattern_;
EditBox *editbox_;
bool show_dotdot_;
public:
enum { FILES, DIRECTORIES, BOTH };
FileBrowser(int, int, int, int, const char * = 0);
/*float icon_size() const {
return (icon_size_ <0? (2.0f* textsize()) : icon_size_);
}
void icon_size(float f) { icon_size_ = f; redraw(); };*/
void filter(const char *pattern);
const char *filter() const { return (pattern_); };
int load(const char *directory, fltk::File_Sort_F *sort = (fltk::File_Sort_F*) fltk::casenumericsort);
/* float textsize() const { return (fltk::Browser::textsize()); };
void textsize(float s) { fltk::Browser::textsize(s); icon_size_ = (uchar)(3 * s / 2); };*/
int filetype() const { return (filetype_); };
void filetype(int t) { filetype_ = t; };
const char * directory() const {return directory_;}
void show_up_directory(bool t) { show_dotdot_ = t; }
// adding or inserting a line into the fileBrowser
//void insert(int n, const char* label, fltk::FileIcon* icon);
//void insert(int n, const char* label, void* data){fltk::Menu::insert(n, label,data);}
//void add(const char * line, fltk::FileIcon* icon);
// Return full system path to given item
const char* system_path(int i) const { return (const char*)child(i)->user_data(); }
// We override handle for displaying editbox
int handle(int);
// Showing or not showing the hidden files, that's the question:
public:
// sets this flag if you want to see the hidden files in the browser
void show_hidden(bool show) { show_hidden_= show; }
bool show_hidden() const {return show_hidden_;}
private:
bool show_hidden_;
static void editbox_cb(Widget*,void*);
int editing;
};
//}
#endif // !_Fl_File_Browser_H_
//
// End of "$Id: FileBrowser.h 4926 2006-04-10 21:03:29Z fabien $".
//

152
efiler/EDE_FileView.h Normal file
View File

@ -0,0 +1,152 @@
/*
* $Id$
*
* EDE FileView class
* Part of edelib.
* Copyright (c) 2005-2007 EDE Authors.
*
* This program is licenced under terms of the
* GNU General Public Licence version 2 or newer.
* See COPYING for details.
*/
#ifndef EDE_FileView_H
#define EDE_FileView_H
#include <Fl/Fl_Shared_Image.H>
#include <edelib/String.h>
#include <edelib/IconTheme.h>
#include "EDE_Browser.h"
// This class provides the generic FileView class and two
// derived classes called FileIconView and FileDetailsView.
// These classes are interchangeable, so that application
// can just declare FileView* and use.
// FileView is populated with FileItem's.
struct FileItem {
edelib::String name; // just the name
edelib::String icon;
edelib::String size;
edelib::String realpath; // whatever the caller uses to access the file
edelib::String description;
edelib::String date;
edelib::String permissions;
};
class FileDetailsView : public EDE_Browser {
private:
// EDE_Browser* browser; - yada
// internal list of items
/* struct myfileitem {
struct FileItem *item;
myfileitem* previous;
myfileitem* next;
} *firstitem;*/
int findrow(edelib::String realpath) {
for (int i=1; i<=size(); i++) {
char *tmp = (char*)data(i);
if (realpath==tmp) return i;
}
return 0;
}
/* struct myfileitem* finditem(edelib::String realpath) {
if (!firstitem) return;
struct myfileitem* work = firstitem;
do {
if (work->item->realpath == realpath) return work;
} while (work=work->next != 0);
return 0;
}*/
public:
FileDetailsView(int X, int Y, int W, int H, char*label=0) : EDE_Browser(X,Y,W,H,label) {
// browser = new EDE_Browser(X,Y,W,H,label);
// browser->end();
// end();
// resizable(browser->the_scroll());
// resizable(browser->the_group());
// resizable(browser);
const int cw[]={250,200,70,130,100,0};
column_widths(cw);
column_char('\t');
column_header("Name\tType\tSize\tDate\tPermissions");
textsize(12); // FIXME: hack for font size
const SortType st[]={ALPHA_CASE_SORT, ALPHA_CASE_SORT, FILE_SIZE_SORT, DATE_SORT, ALPHA_SORT, NO_SORT};
column_sort_types(st);
when(FL_WHEN_ENTER_KEY_ALWAYS);
//when(FL_WHEN_ENTER_KEY_CHANGED);
//first=0;
}
// ~FileDetailsView() { delete browser; }
void insert(int row, FileItem *item) {
// Construct browser line
edelib::String value;
value = item->name+"\t"+item->description+"\t"+item->size+"\t"+item->date+"\t"+item->permissions;
EDE_Browser::insert(row, value.c_str(), strdup(item->realpath.c_str())); // put realpath into data
fprintf (stderr, "value: %s\n", value.c_str());
// Get icon
edelib::String icon = edelib::IconTheme::get(item->icon.c_str(),edelib::ICON_SIZE_TINY);
if (icon=="") icon = edelib::IconTheme::get("misc",edelib::ICON_SIZE_TINY,edelib::ICON_CONTEXT_MIMETYPE);
set_icon(row, Fl_Shared_Image::get(icon.c_str()));
}
void add(FileItem *item) { insert(size()+1, item); }
// browser->redraw();
/* struct myfileitem* i;
if (!first)
i = first = new myfileitem;
else {
i=first;
while (i->next!=0) i=i->next;
i->next = new myfileitem;
i->next->previous = i;
i=i->next;
}
i->item = item;
i->next = 0;*/
// }
void remove(FileItem *item) {
int row = findrow(item->realpath);
if (row) EDE_Browser::remove(row);
/* struct myfileitem* i = finditem(item->realpath);
if (i) {
i->previous->next = i->next;
i->next->previous = i->previous;
delete i;
}*/
}
void update(FileItem *item) {
int row=findrow(item->realpath);
if (row==0) return;
EDE_Browser::remove(row);
insert(row, item);
/*
//
edelib::String value = item->name + "\t" + item->description + "\t" + item->size + "\t" + item->date + "\t" + item->permissions;
browser->insert(row,value.c_str(),strdup(item->realpath.c_str()));
edelib::String icon = edelib::IconTheme::get(item->icon.c_str(),edelib::ICON_SIZE_TINY);
browser->set_icon(row, Fl_Shared_Image::get(icon.c_str()));
browser->redraw(); // OPTIMIZE
// browser->redraw_line(browser->find_item(row));*/
}
// void clear() { browser->clear(); }
// void callback(Fl_Callback* c) { browser->callback(c); }
};
#endif
/* $Id */

598
efiler/Fl_Icon_Browser.cxx Normal file
View File

@ -0,0 +1,598 @@
// Icon Browser - modified from Fl_Browser.cxx by Vedran Ljubovic
// "$Id: Fl_Icon_Browser.cxx 5190 2006-06-09 16:16:34Z mike $"
//
// Browser widget for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2005 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "Fl_Icon_Browser.h"
// I modified this from the original Forms data to use a linked list
// so that the number of items in the browser and size of those items
// is unlimited. The only problem is that the old browser used an
// index number to identify a line, and it is slow to convert from/to
// a pointer. I use a cache of the last match to try to speed this
// up.
// Also added the ability to "hide" a line. This set's it's height to
// zero, so the Fl_Icon_Browser_ cannot pick it.
#define SELECTED 1
#define NOTDISPLAYED 2
struct FL_BLINE { // data is in a linked list of these
FL_BLINE* prev;
FL_BLINE* next;
void* data;
Fl_Image* icon;
short length; // sizeof(txt)-1, may be longer than string
char flags; // selected, displayed
char txt[1]; // start of allocated array
};
void* Fl_Icon_Browser::item_first() const {return first;}
void* Fl_Icon_Browser::item_next(void* l) const {return ((FL_BLINE*)l)->next;}
void* Fl_Icon_Browser::item_prev(void* l) const {return ((FL_BLINE*)l)->prev;}
int Fl_Icon_Browser::item_selected(void* l) const {
return ((FL_BLINE*)l)->flags&SELECTED;}
void Fl_Icon_Browser::item_select(void* l, int v) {
if (v) ((FL_BLINE*)l)->flags |= SELECTED;
else ((FL_BLINE*)l)->flags &= ~SELECTED;
}
FL_BLINE* Fl_Icon_Browser::find_line(int line) const {
int n; FL_BLINE* l;
if (line == cacheline) return cache;
if (cacheline && line > (cacheline/2) && line < ((cacheline+lines)/2)) {
n = cacheline; l = cache;
} else if (line <= (lines/2)) {
n = 1; l = first;
} else {
n = lines; l = last;
}
for (; n < line && l; n++) l = l->next;
for (; n > line && l; n--) l = l->prev;
((Fl_Icon_Browser*)this)->cacheline = line;
((Fl_Icon_Browser*)this)->cache = l;
return l;
}
int Fl_Icon_Browser::lineno(void* v) const {
FL_BLINE* l = (FL_BLINE*)v;
if (!l) return 0;
if (l == cache) return cacheline;
if (l == first) return 1;
if (l == last) return lines;
if (!cache) {
((Fl_Icon_Browser*)this)->cache = first;
((Fl_Icon_Browser*)this)->cacheline = 1;
}
// assumme it is near cache, search both directions:
FL_BLINE* b = cache->prev;
int bnum = cacheline-1;
FL_BLINE* f = cache->next;
int fnum = cacheline+1;
int n = 0;
for (;;) {
if (b == l) {n = bnum; break;}
if (f == l) {n = fnum; break;}
if (b) {b = b->prev; bnum--;}
if (f) {f = f->next; fnum++;}
}
((Fl_Icon_Browser*)this)->cache = l;
((Fl_Icon_Browser*)this)->cacheline = n;
return n;
}
FL_BLINE* Fl_Icon_Browser::_remove(int line) {
FL_BLINE* ttt = find_line(line);
deleting(ttt);
cacheline = line-1;
cache = ttt->prev;
lines--;
full_height_ -= item_height(ttt);
if (ttt->prev) ttt->prev->next = ttt->next;
else first = ttt->next;
if (ttt->next) ttt->next->prev = ttt->prev;
else last = ttt->prev;
return(ttt);
}
void Fl_Icon_Browser::remove(int line) {
if (line < 1 || line > lines) return;
free(_remove(line));
}
void Fl_Icon_Browser::insert(int line, FL_BLINE* t) {
if (!first) {
t->prev = t->next = 0;
first = last = t;
} else if (line <= 1) {
inserting(first, t);
t->prev = 0;
t->next = first;
t->next->prev = t;
first = t;
} else if (line > lines) {
t->prev = last;
t->prev->next = t;
t->next = 0;
last = t;
} else {
FL_BLINE* n = find_line(line);
inserting(n, t);
t->next = n;
t->prev = n->prev;
t->prev->next = t;
n->prev = t;
}
cacheline = line;
cache = t;
lines++;
full_height_ += item_height(t);
redraw_line(t);
}
void Fl_Icon_Browser::insert(int line, const char* newtext, void* d) {
int l = strlen(newtext);
FL_BLINE* t = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l);
t->length = (short)l;
t->flags = 0;
strcpy(t->txt, newtext);
t->data = d;
t->icon = 0;
insert(line, t);
}
void Fl_Icon_Browser::move(int to, int from) {
if (from < 1 || from > lines) return;
insert(to, _remove(from));
}
void Fl_Icon_Browser::text(int line, const char* newtext) {
if (line < 1 || line > lines) return;
FL_BLINE* t = find_line(line);
int l = strlen(newtext);
if (l > t->length) {
FL_BLINE* n = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l);
replacing(t, n);
cache = n;
n->data = t->data;
n->length = (short)l;
n->flags = t->flags;
n->icon = t->icon;
n->prev = t->prev;
if (n->prev) n->prev->next = n; else first = n;
n->next = t->next;
if (n->next) n->next->prev = n; else last = n;
free(t);
t = n;
}
strcpy(t->txt, newtext);
redraw_line(t);
}
void Fl_Icon_Browser::data(int line, void* d) {
if (line < 1 || line > lines) return;
find_line(line)->data = d;
}
int Fl_Icon_Browser::item_height(void* lv) const {
FL_BLINE* l = (FL_BLINE*)lv;
if (l->flags & NOTDISPLAYED) return 0;
int hmax = 2; // use 2 to insure we don't return a zero!
if (!l->txt[0]) {
// For blank lines set the height to exactly 1 line!
fl_font(textfont(), textsize());
int hh = fl_height();
if (hh > hmax) hmax = hh;
}
else {
const int* i = column_widths();
// do each column separately as they may all set different fonts:
for (char* str = l->txt; str && *str; str++) {
Fl_Font font = textfont(); // default font
int tsize = textsize(); // default size
while (*str==format_char()) {
str++;
switch (*str++) {
case 'l': case 'L': tsize = 24; break;
case 'm': case 'M': tsize = 18; break;
case 's': tsize = 11; break;
case 'b': font = (Fl_Font)(font|FL_BOLD); break;
case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
case 'f': case 't': font = FL_COURIER; break;
case 'B':
case 'C': strtol(str, &str, 10); break;// skip a color number
case 'F': font = (Fl_Font)strtol(str,&str,10); break;
case 'S': tsize = strtol(str,&str,10); break;
case 0: case '@': str--;
case '.': goto END_FORMAT;
}
}
END_FORMAT:
char* ptr = str;
if (ptr && *i++) str = strchr(str, column_char());
else str = NULL;
if((!str && *ptr) || (str && ptr < str)) {
fl_font(font, tsize); int hh = fl_height();
if (hh > hmax) hmax = hh;
}
if (!str || !*str) break;
}
}
if (l->icon && (l->icon->h()+2)>hmax) hmax=l->icon->h()+2; // leave 2px above/below
return hmax; // previous version returned hmax+2!
}
int Fl_Icon_Browser::item_width(void* v) const {
char* str = ((FL_BLINE*)v)->txt;
const int* i = column_widths();
int ww = 0;
while (*i) { // add up all tab-seperated fields
char* e;
e = strchr(str, column_char());
if (!e) break; // last one occupied by text
str = e+1;
ww += *i++;
}
// OK, we gotta parse the string and find the string width...
int tsize = textsize();
Fl_Font font = textfont();
int done = 0;
while (*str == format_char_ && str[1] && str[1] != format_char_) {
str ++;
switch (*str++) {
case 'l': case 'L': tsize = 24; break;
case 'm': case 'M': tsize = 18; break;
case 's': tsize = 11; break;
case 'b': font = (Fl_Font)(font|FL_BOLD); break;
case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
case 'f': case 't': font = FL_COURIER; break;
case 'B':
case 'C': strtol(str, &str, 10); break;// skip a color number
case 'F': font = (Fl_Font)strtol(str, &str, 10); break;
case 'S': tsize = strtol(str, &str, 10); break;
case '.':
done = 1;
break;
case '@':
str--;
done = 1;
}
if (done)
break;
}
if (*str == format_char_ && str[1])
str ++;
FL_BLINE* blind = (FL_BLINE*)v;
if (ww==0 && blind->icon) ww = blind->icon->w();
fl_font(font, tsize);
return ww + int(fl_width(str)) + 6;
}
int Fl_Icon_Browser::full_height() const {
return full_height_;
}
int Fl_Icon_Browser::incr_height() const {
return textsize()+2;
}
void Fl_Icon_Browser::item_draw(void* v, int X, int Y, int W, int H) const {
char* str = ((FL_BLINE*)v)->txt;
const int* i = column_widths();
bool first=true; // for icon
FL_BLINE*blind = (FL_BLINE*)v;
while (W > 6) { // do each tab-seperated field
int w1 = W; // width for this field
char* e = 0; // pointer to end of field or null if none
if (*i) { // find end of field and temporarily replace with 0
e = strchr(str, column_char());
if (e) {*e = 0; w1 = *i++;}
}
// Icon drawing code
if (first) {
first=false;
if (blind->icon != 0) {
blind->icon->draw(X+2,Y+1); // leave 2px left, 1px above
int iconw = blind->icon->w() + 2;
X += iconw; W -= iconw; w1 -= iconw;
}
}
int tsize = textsize();
Fl_Font font = textfont();
Fl_Color lcol = textcolor();
Fl_Align talign = FL_ALIGN_LEFT;
// check for all the @-lines recognized by XForms:
while (*str == format_char() && *++str && *str != format_char()) {
switch (*str++) {
case 'l': case 'L': tsize = 24; break;
case 'm': case 'M': tsize = 18; break;
case 's': tsize = 11; break;
case 'b': font = (Fl_Font)(font|FL_BOLD); break;
case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
case 'f': case 't': font = FL_COURIER; break;
case 'c': talign = FL_ALIGN_CENTER; break;
case 'r': talign = FL_ALIGN_RIGHT; break;
case 'B':
if (!(((FL_BLINE*)v)->flags & SELECTED)) {
fl_color((Fl_Color)strtol(str, &str, 10));
fl_rectf(X, Y, w1, H);
} else strtol(str, &str, 10);
break;
case 'C':
lcol = (Fl_Color)strtol(str, &str, 10);
break;
case 'F':
font = (Fl_Font)strtol(str, &str, 10);
break;
case 'N':
lcol = FL_INACTIVE_COLOR;
break;
case 'S':
tsize = strtol(str, &str, 10);
break;
case '-':
fl_color(FL_DARK3);
fl_line(X+3, Y+H/2, X+w1-3, Y+H/2);
fl_color(FL_LIGHT3);
fl_line(X+3, Y+H/2+1, X+w1-3, Y+H/2+1);
break;
case 'u':
case '_':
fl_color(lcol);
fl_line(X+3, Y+H-1, X+w1-3, Y+H-1);
break;
case '.':
goto BREAK;
case '@':
str--; goto BREAK;
}
}
BREAK:
fl_font(font, tsize);
if (((FL_BLINE*)v)->flags & SELECTED)
lcol = fl_contrast(lcol, selection_color());
if (!active_r()) lcol = fl_inactive(lcol);
fl_color(lcol);
fl_draw(str, X+3, Y, w1-6, H, e ? Fl_Align(talign|FL_ALIGN_CLIP) : talign, 0, 0);
if (!e) break; // no more fields...
*e = column_char(); // put the seperator back
X += w1;
W -= w1;
str = e+1;
}
}
static const int no_columns[1] = {0};
Fl_Icon_Browser::Fl_Icon_Browser(int X, int Y, int W, int H, const char*l)
: Fl_Browser_(X, Y, W, H, l) {
column_widths_ = no_columns;
lines = 0;
full_height_ = 0;
cacheline = 0;
format_char_ = '@';
column_char_ = '\t';
first = last = cache = 0;
}
void Fl_Icon_Browser::lineposition(int line, Fl_Line_Position pos) {
if (line<1) line = 1;
if (line>lines) line = lines;
int p = 0;
FL_BLINE* l;
for (l=first; l && line>1; l = l->next) {
line--; p += item_height(l);
}
if (l && (pos == BOTTOM)) p += item_height (l);
int final = p, X, Y, W, H;
bbox(X, Y, W, H);
switch(pos) {
case TOP: break;
case BOTTOM: final -= H; break;
case MIDDLE: final -= H/2; break;
}
if (final > (full_height() - H)) final = full_height() -H;
position(final);
}
int Fl_Icon_Browser::topline() const {
return lineno(top());
}
void Fl_Icon_Browser::clear() {
for (FL_BLINE* l = first; l;) {
FL_BLINE* n = l->next;
free(l);
l = n;
}
full_height_ = 0;
first = 0;
lines = 0;
new_list();
}
void Fl_Icon_Browser::add(const char* newtext, void* d) {
insert(lines+1, newtext, d);
//Fl_Icon_Browser_::display(last);
}
const char* Fl_Icon_Browser::text(int line) const {
if (line < 1 || line > lines) return 0;
return find_line(line)->txt;
}
void* Fl_Icon_Browser::data(int line) const {
if (line < 1 || line > lines) return 0;
return find_line(line)->data;
}
int Fl_Icon_Browser::select(int line, int v) {
if (line < 1 || line > lines) return 0;
return Fl_Browser_::select(find_line(line), v);
}
int Fl_Icon_Browser::selected(int line) const {
if (line < 1 || line > lines) return 0;
return find_line(line)->flags & SELECTED;
}
void Fl_Icon_Browser::show(int line) {
FL_BLINE* t = find_line(line);
if (t->flags & NOTDISPLAYED) {
t->flags &= ~NOTDISPLAYED;
full_height_ += item_height(t);
if (Fl_Browser_::displayed(t)) redraw_lines();
}
}
void Fl_Icon_Browser::hide(int line) {
FL_BLINE* t = find_line(line);
if (!(t->flags & NOTDISPLAYED)) {
full_height_ -= item_height(t);
t->flags |= NOTDISPLAYED;
if (Fl_Browser_::displayed(t)) redraw_lines();
}
}
void Fl_Icon_Browser::display(int line, int v) {
if (line < 1 || line > lines) return;
if (v) show(line); else hide(line);
}
int Fl_Icon_Browser::visible(int line) const {
if (line < 1 || line > lines) return 0;
return !(find_line(line)->flags&NOTDISPLAYED);
}
int Fl_Icon_Browser::value() const {
return lineno(selection());
}
// SWAP TWO LINES
void Fl_Icon_Browser::swap(FL_BLINE *a, FL_BLINE *b) {
if ( a == b || !a || !b) return; // nothing to do
swapping(a, b);
FL_BLINE *aprev = a->prev;
FL_BLINE *anext = a->next;
FL_BLINE *bprev = b->prev;
FL_BLINE *bnext = b->next;
if ( b->prev == a ) { // A ADJACENT TO B
if ( aprev ) aprev->next = b; else first = b;
b->next = a;
a->next = bnext;
b->prev = aprev;
a->prev = b;
if ( bnext ) bnext->prev = a; else last = a;
} else if ( a->prev == b ) { // B ADJACENT TO A
if ( bprev ) bprev->next = a; else first = a;
a->next = b;
b->next = anext;
a->prev = bprev;
b->prev = a;
if ( anext ) anext->prev = b; else last = b;
} else { // A AND B NOT ADJACENT
// handle prev's
b->prev = aprev;
if ( anext ) anext->prev = b; else last = b;
a->prev = bprev;
if ( bnext ) bnext->prev = a; else last = a;
// handle next's
if ( aprev ) aprev->next = b; else first = b;
b->next = anext;
if ( bprev ) bprev->next = a; else first = a;
a->next = bnext;
}
// Disable cache -- we played around with positions
cacheline = 0;
cache = 0;
}
void Fl_Icon_Browser::swap(int ai, int bi) {
if (ai < 1 || ai > lines || bi < 1 || bi > lines) return;
FL_BLINE* a = find_line(ai);
FL_BLINE* b = find_line(bi);
swap(a,b);
}
void Fl_Icon_Browser::set_icon(int line, Fl_Image* icon) {
if (icon && line>0 && line<=lines) {
// update full_height_
FL_BLINE* bl = find_line(line);
int dh = icon->h() - item_height(bl) + 2; // leave 2px above/below
if (dh>0) full_height_ += dh;
bl->icon=icon;
redraw_line(bl);
}
}
void Fl_Icon_Browser::remove_icon(int line) {
if (line>0 && line<=lines) {
FL_BLINE* bl = find_line(line);
if (!bl->icon) return;
int dh = bl->icon->h()+2; // leave 2px above/below
bl->icon=0;
redraw_line(bl);
// update_full_height_
dh -= item_height(bl);
if (dh>0) full_height_ -= dh;
}
}
//
// End of "$Id: Fl_Icon_Browser.cxx 5190 2006-06-09 16:16:34Z mike $".
//

143
efiler/Fl_Icon_Browser.h Normal file
View File

@ -0,0 +1,143 @@
// Icon Browser - modified from Fl_Browser.h by Vedran Ljubovic
// "$Id: Fl_Browser.H 4288 2005-04-16 00:13:17Z mike $"
//
// Browser header file for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2005 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
// Forms-compatable browser. Probably useful for other
// lists of textual data. Notice that the line numbers
// start from 1, and 0 means "no line".
#ifndef Fl_Icon_Browser_H
#define Fl_Icon_Browser_H
#include <Fl/Fl_Browser_.H>
#include <Fl/Fl_Image.H>
#include <stdio.h>
struct FL_BLINE;
class Fl_Icon_Browser : public Fl_Browser_ {
FL_BLINE *first; // the array of lines
FL_BLINE *last;
FL_BLINE *cache;
int cacheline; // line number of cache
int lines; // Number of lines
int full_height_;
const int* column_widths_;
char format_char_; // alternative to @-sign
char column_char_; // alternative to tab
protected:
// required routines for Fl_Browser_ subclass:
void* item_first() const ;
void* item_next(void*) const ;
void* item_prev(void*) const ;
int item_selected(void*) const ;
void item_select(void*, int);
int item_height(void*) const ;
int item_width(void*) const ;
void item_draw(void*, int, int, int, int) const ;
int full_height() const ;
int incr_height() const ;
FL_BLINE* find_line(int) const ;
FL_BLINE* _remove(int) ;
void insert(int, FL_BLINE*);
int lineno(void*) const ;
void swap(FL_BLINE *a, FL_BLINE *b);
public:
void remove(int);
void add(const char*, void* = 0);
void insert(int, const char*, void* = 0);
void move(int to, int from);
int load(const char* filename);
void swap(int a, int b);
void clear();
int size() const {return lines;}
void size(int W, int H) { Fl_Widget::size(W, H); }
int topline() const ;
enum Fl_Line_Position { TOP, BOTTOM, MIDDLE };
void lineposition(int, Fl_Line_Position);
void topline(int l) { lineposition(l, TOP); }
void bottomline(int l) { lineposition(l, BOTTOM); }
void middleline(int l) { lineposition(l, MIDDLE); }
int select(int, int=1);
int selected(int) const ;
void show(int n);
void show() {Fl_Widget::show();}
void hide(int n);
void hide() {Fl_Widget::hide();}
int visible(int n) const ;
int value() const ;
void value(int v) {select(v);}
const char* text(int) const ;
void text(int, const char*);
void* data(int) const ;
void data(int, void* v);
Fl_Icon_Browser(int, int, int, int, const char* = 0);
~Fl_Icon_Browser() { clear(); }
char format_char() const {return format_char_;}
void format_char(char c) {format_char_ = c;}
char column_char() const {return column_char_;}
void column_char(char c) {column_char_ = c;}
const int* column_widths() const {return column_widths_;}
void column_widths(const int* l) {column_widths_ = l;}
int displayed(int n) const {return Fl_Browser_::displayed(find_line(n));}
void make_visible(int n) {
if (n < 1) Fl_Browser_::display(find_line(1));
else if (n > lines) Fl_Browser_::display(find_line(lines));
else Fl_Browser_::display(find_line(n));
}
// for back compatability only:
void replace(int a, const char* b) {text(a, b);}
void display(int, int=1);
// icon support
void set_icon(int line, Fl_Image* icon);
void remove_icon(int line);
};
#endif
//
// End of "$Id: Fl_Browser.H 4288 2005-04-16 00:13:17Z mike $".
//

360
efiler/Util.cpp Normal file
View File

@ -0,0 +1,360 @@
/*
* $Id$
*
* Library of useful functions
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2000-2006 EDE Authors.
*
* This program is licenced under terms of the
* GNU General Public Licence version 2 or newer.
* See COPYING for details.
*/
#include "Util.h"
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <time.h>
#include <fltk/filename.h>
#ifdef _WIN32
# include <io.h>
# include <direct.h>
# include <windows.h>
# define access(a,b) _access(a,b)
# define mkdir(a,b) _mkdir(a)
# define R_OK 4
#else
# include <unistd.h>
#endif /* _WIN32 */
// From Enumerations.h
#ifdef _WIN32
# undef slash
# define slash '\\'
#else
# undef slash
# define slash '/'
#endif
// End Enumerations.h
//using namespace fltk;
//using namespace edelib;
// Test if path is absolute or relative
int is_path_rooted(const char *fn)
{
#ifdef _WIN32
if (fn[0] == '/' || fn[0] == '.' || fn[0] == '\\' || fn[1]==':')
#else
if (fn[0] == '/' || fn[0] == '.')
#endif
return 1;
return 0;
}
// recursively create a path in the file system
bool make_path( const char *path )
{
if(access(path, 0))
{
const char *s = strrchr( path, slash );
if ( !s ) return 0;
int len = s-path;
char *p = (char*)malloc( len+1 );
memcpy( p, path, len );
p[len] = 0;
make_path( (const char*)p );
free( p );
return ( mkdir( path, 0777 ) == 0 );
}
return true;
}
// create the path needed for file using make_path
bool make_path_for_file( const char *path )
{
const char *s = strrchr( path, slash );
if ( !s ) return false;
int len = s-path;
char *p = (char*)malloc( len+1 );
memcpy( p, path, len );
p[len] = 0;
bool ret=make_path( (const char*)p );
free( p );
return ret;
}
// Cross-platform function for system path
char* get_sys_dir()
{
#ifndef _WIN32
return SYSTEM_PATH;
#else
static char path[PATH_MAX];
HKEY hKey;
if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, &hKey)==ERROR_SUCCESS)
{
DWORD size=4096;
RegQueryValueExW(hKey, L"CommonFilesDir", NULL, NULL, (LPBYTE)path, &size);
RegCloseKey(hKey);
return path;
}
return "C:\\EDE\\";
#endif
}
// Cross-platform function for home directory...
// I don't see the purpose since getenv("HOME") works just fine
/*char* get_homedir() {
char *path = new char[PATH_MAX];
const char *str1;
str1=getenv("HOME");
if (str1) {
memcpy(path, str1, strlen(str1)+1);
return path;
}
return 0;
}*/
// strdupcat() - it's cool to strcat with implied realloc
// -- NOTE: due to use of realloc *always* use strdupcat return value:
// dest = strdupcat(dest,src);
// and *never* use it like:
// strdupcat(dest,src);
char* strdupcat(char *dest, const char *src)
{
if (!dest) {
dest=(char*)malloc(strlen(src));
} else {
dest=(char*)realloc (dest, strlen(dest)+strlen(src)+1);
}
strcat(dest,src);
return dest;
}
// wstrim() - for trimming characters (used in parser)
// parts of former fl_trimleft and fl_trimright from Fl_Util.cpp
char* wstrim(char *string)
{
if(!string)
return NULL;
char *start;
int len = strlen(string);
if (len) {
char *p = string + len;
do {
p--;
if ( !isspace(*p) ) break;
} while ( p != string );
if ( !isspace(*p) ) p++;
*p = 0;
}
for(start = string; *start && isspace (*start); start++);
memmove(string, start, strlen(start) + 1);
return string;
}
const char* twstrim(const char* string)
{
static char buffer[4096];
if (strlen(string)>4095) {
strncpy(buffer,string,4095);
buffer[4095]='\0';
} else
strcpy(buffer,string);
wstrim((char*)buffer);
return (const char*)buffer;
}
// hmmmh?
/*
char* wstrim(const char *string)
{
char *newstring = strdup(string);
return wstrim(newstring);
}*/
// Returns nicely formatted string for byte sizes
const char* nice_size(double size) {
static char buffer[256];
if (size<1024) {
snprintf(buffer,255,"%d B",(int)size);
} else if (size<1024*10) {
snprintf(buffer,255,"%.1f kB",(float)size/1024);
} else if (size<1024*1024) {
snprintf(buffer,255,"%d kB",(int)size/1024);
} else if (size<1024*1024*10) {
snprintf(buffer,255,"%.1f MB",(float)size/(1024*1024));
} else if (size<1024*1024*1024) {
snprintf(buffer,255,"%d MB",(int)size/(1024*1024));
} else if (size<1024*1024*1024*10) {
snprintf(buffer,255,"%.1f GB",(float)size/(1024*1024*1024));
} else {
snprintf(buffer,255,"%d GB",(int)size/(1024*1024*1024));
}
return (const char*) buffer;
}
const char* nice_time(long int epoch) {
static char buffer[256];
const time_t k = (const time_t)epoch;
const struct tm *timeptr = localtime(&k);
// Date/time format should be moved to configuration
snprintf(buffer,255,"%.2d.%.2d.%.4d. %.2d:%.2d", timeptr->tm_mday, timeptr->tm_mon+1, 1900+timeptr->tm_year, timeptr->tm_hour, timeptr->tm_min);
return buffer;
}
// Find in haystack any of needles (divided with separator)
char* strstrmulti(const char *haystack, const char *needles, const char *separator) {
if (!haystack || !needles || (strlen(haystack)==0) || (strlen(needles)==0))
return (char*)haystack; // this means that empty search returns true
char *copy = strdup(needles);
char *token = strtok(copy, separator);
char *result = 0;
do {
if ((result = strstr(haystack,token))) break;
} while ((token = strtok(NULL, separator)));
free (copy);
if (!result && (strcmp(separator,needles+strlen(needles)-strlen(separator))==0))
return (char*)haystack; // again
return result;
}
// vec_from_string() - similar to explode() in PHP or split() in Perl
// adapted from Fl_String_List to use vector
/*std::vector<char*> vec_from_string(const char *str, const char *separator)
{
if(!str) return std::vector<char*> ();
const char *ptr = str;
const char *s = strstr(ptr, separator);
std::vector<char*> retval;
if(s) {
unsigned separator_len = strlen(separator);
do {
unsigned len = s - ptr;
if (len) {
retval.push_back(strndup(ptr,len));
} else {
retval.push_back(NULL);
}
ptr = s + separator_len;
s = strstr(ptr, separator);
}
while(s);
if(*ptr) {
retval.push_back(strdup(ptr));
}
} else {
retval.push_back(strdup(ptr));
}
return retval;
}*/
// Print to a static char[] and return pointer
const char* tsprintf(char *format, ...)
{
static char buffer[4096];
va_list args;
va_start(args, format);
vsnprintf(buffer, 4095, format, args);
va_end(args);
return (const char*)buffer;
}
char* tasprintf(char *format, ...)
{
char buffer[4096];
va_list args;
va_start(args, format);
vsnprintf(buffer, 4095, format, args);
va_end(args);
return strdup(buffer);
}
// This function exists on some OSes and is mentioned in C textbooks
// However, we can just use sprintf instead
/*
char *
itoa(int value, char *string, int radix)
{
char tmp[33];
char *tp = tmp;
int i;
unsigned v;
int sign;
char *sp;
if (radix > 36 || radix <= 1)
{
return 0;
}
sign = (radix == 10 && value < 0);
if (sign)
v = -value;
else
v = (unsigned)value;
while (v || tp == tmp)
{
i = v % radix;
v = v / radix;
if (i < 10)
*tp++ = i+'0';
else
*tp++ = i + 'a' - 10;
}
if (string == 0)
string = (char *)malloc((tp-tmp)+sign+1);
sp = string;
if (sign)
*sp++ = '-';
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
}*/

93
efiler/Util.h Normal file
View File

@ -0,0 +1,93 @@
/*
* $Id$
*
* Library of useful functions
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2000-2006 EDE Authors.
*
* This program is licenced under terms of the
* GNU General Public Licence version 2 or newer.
* See COPYING for details.
*/
#ifndef edelib_Util_h
#define edelib_Util_h
//#include "../edeconf.h"
//namespace edelib {
// Constants
//#define SYSTEM_PATH PREFIX"/share/ede"
#define SYSTEM_PATH "/usr/share/ede"
#define DOC_PATH SYSTEM_PATH"/doc"
// Cross-platform test if path is absolute or relative
int is_path_rooted(const char *fn);
// Recursively create a path in the file system
bool make_path( const char *path );
// Create the path needed for file using make_path
bool make_path_for_file( const char *path );
// Cross-platform function for system files location
char* get_sys_dir();
// strcat() that also does realloc if needed. Useful if
// e.g. you have a loop which grows string in each pass
// -- Note: due to use of realloc *always* use strdupcat return value:
// dest = strdupcat(dest,src);
// and *never* use it like:
// strdupcat(dest,src);
// NOTE this function is not used! Its use is not recommended
char* strdupcat(char *dest, const char *src);
// Whitespace trim (both left and right)
char* wstrim(char *string);
// Version with temporary results (static char[])
const char* twstrim(const char *string);
// Finds in haystack any of strings contained in string "needles". The substrings
// are divided with separator.
// Not actually used...
char* strstrmulti(const char *haystack, const char *needles, const char *separator);
// Returns nicely formatted string for byte sizes e.g. "1.2 kB" for size=1284
const char* nice_size(double size);
// Returns nicely formatted string for date and time given in seconds since
// Epoch. This should be in config
const char* nice_time(long int epoch);
// Create vector from string using separator
//std::vector<char*> vec_from_string(const char *str, const char *separator);
/*! \fn const char* edelib::tsprintf(char* format, ...)
A useful function which executes sprintf() on a static char[] variable big enough to
hold short temporary strings. The variable remains valid until next call.
Use:
run_program(tsprintf(PREFIX"/bin/eiconsconf %s",param));
When setting text values of fltk objects, instead use tasprintf which executes a strdup.
Example:
window->label(tasprintf("%s, version %s",appname,appversion));
*/
const char* tsprintf(char* format, ...);
char* tasprintf(char* format, ...);
//}
#endif

File diff suppressed because it is too large Load Diff