mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
Beginning of work on efiler fltk1.x
This commit is contained in:
parent
a569d78563
commit
6cf2769599
527
efiler/EDE_Browser.cpp
Normal file
527
efiler/EDE_Browser.cpp
Normal 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
186
efiler/EDE_Browser.h
Normal 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$".
|
||||
//
|
||||
|
@ -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 $".
|
||||
//
|
@ -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 $".
|
||||
//
|
@ -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 $".
|
||||
//
|
@ -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
152
efiler/EDE_FileView.h
Normal 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
598
efiler/Fl_Icon_Browser.cxx
Normal 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
143
efiler/Fl_Icon_Browser.h
Normal 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
360
efiler/Util.cpp
Normal 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
93
efiler/Util.h
Normal 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
|
1021
efiler/efiler.cpp
1021
efiler/efiler.cpp
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user