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:
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
|
1025
efiler/efiler.cpp
1025
efiler/efiler.cpp
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user