From cf813db2428ec77de88b06996712aad48de04219 Mon Sep 17 00:00:00 2001 From: maxim nikonov Date: Fri, 6 Feb 2026 12:36:28 +0500 Subject: wip --- examples/table-sort.cxx | 168 +++++++++++++++++++++++++++++++++--------------- lib/libfltk.a | Bin 2237328 -> 2237328 bytes lib/libfltk_forms.a | Bin 32888 -> 32888 bytes lib/libfltk_gl.a | Bin 212440 -> 212440 bytes lib/libfltk_images.a | Bin 268000 -> 268000 bytes lib/libfltk_jpeg.a | Bin 305416 -> 305416 bytes lib/libfltk_png.a | Bin 287384 -> 287384 bytes lib/libfltk_z.a | Bin 103976 -> 103976 bytes 8 files changed, 115 insertions(+), 53 deletions(-) diff --git a/examples/table-sort.cxx b/examples/table-sort.cxx index f979693f9..94c885ffa 100644 --- a/examples/table-sort.cxx +++ b/examples/table-sort.cxx @@ -31,9 +31,6 @@ #include #include #include -#include -#include -#include // STL sort #define MARGIN 20 @@ -43,7 +40,8 @@ // /-C -- disable 1000's separator in file sizes // /A-D -- don't show directories # define DIRCMD "dir /-C /A-D" - static std::vector G_header = { "Date", "Time", "Size", "Filename" }; + static const char *G_header[] = { "Date", "Time", "Size", "Filename" }; + static int G_header_count = 4; # ifdef _MSC_VER # define popen _popen # define pclose _pclose @@ -51,7 +49,8 @@ #else /* _WIN32 */ // UNIX # define DIRCMD "ls -l" - static std::vector G_header = { "Perms", "#L", "Own", "Group", "Size", "Date", "", "", "Filename" }; + static const char *G_header[] = { "Perms", "#L", "Own", "Group", "Size", "Date", "", "", "Filename" }; + static int G_header_count = 9; #endif /* _WIN32 */ // Font face/sizes for header and rows @@ -61,38 +60,81 @@ #define ROW_FONTSIZE 16 // A single row of columns -class Row { -public: - std::vector cols; +struct Row { + char **cols; + int cols_count; + int cols_alloc; }; -// Sort class to handle sorting column using std::sort -class SortColumn { - int _col, _reverse; -public: - SortColumn(int col, int reverse) { - _col = col; - _reverse = reverse; +static void row_init(Row *r) { + r->cols = 0; + r->cols_count = 0; + r->cols_alloc = 0; +} + +static void row_free(Row *r) { + int i; + for (i = 0; i < r->cols_count; i++) { + free(r->cols[i]); } - bool operator()(const Row &a, const Row &b) { - const char *ap = ( _col < (int)a.cols.size() ) ? a.cols[_col].c_str() : "", - *bp = ( _col < (int)b.cols.size() ) ? b.cols[_col].c_str() : ""; - if ( isdigit(*ap) && isdigit(*bp) ) { // cheezy detection of numeric data - // Numeric sort - int av=0; sscanf(ap, "%d", &av); - int bv=0; sscanf(bp, "%d", &bv); - return( _reverse ? av < bv : bv < av ); - } else { - // Alphabetic sort - return( _reverse ? strcmp(ap, bp) > 0 : strcmp(ap, bp) < 0 ); - } + free(r->cols); + r->cols = 0; + r->cols_count = 0; + r->cols_alloc = 0; +} + +static void row_push(Row *r, const char *s) { + if (r->cols_count >= r->cols_alloc) { + int new_alloc = r->cols_alloc ? r->cols_alloc * 2 : 16; + r->cols = (char **)realloc(r->cols, new_alloc * sizeof(char *)); + r->cols_alloc = new_alloc; } -}; + r->cols[r->cols_count++] = strdup(s); +} + +static void row_append_last(Row *r, const char *s) { + if (r->cols_count > 0) { + char *old = r->cols[r->cols_count - 1]; + size_t oldlen = strlen(old); + size_t slen = strlen(s); + char *newstr = (char *)malloc(oldlen + 1 + slen + 1); + memcpy(newstr, old, oldlen); + newstr[oldlen] = ' '; + memcpy(newstr + oldlen + 1, s, slen + 1); + free(old); + r->cols[r->cols_count - 1] = newstr; + } +} + +// Global sort state for qsort +static int g_sort_col = 0; +static int g_sort_reverse = 0; + +static int row_compare(const void *a, const void *b) { + const Row *ra = (const Row *)a; + const Row *rb = (const Row *)b; + const char *ap = (g_sort_col < ra->cols_count) ? ra->cols[g_sort_col] : ""; + const char *bp = (g_sort_col < rb->cols_count) ? rb->cols[g_sort_col] : ""; + int result; + if (isdigit((unsigned char)*ap) && isdigit((unsigned char)*bp)) { + // Numeric sort + int av = 0, bv = 0; + sscanf(ap, "%d", &av); + sscanf(bp, "%d", &bv); + result = bv - av; + } else { + // Alphabetic sort + result = strcmp(ap, bp); + } + return g_sort_reverse ? -result : result; +} // Derive a custom class from Fl_Table_Row class MyTable : public Fl_Table_Row { private: - std::vector rowdata_; // data in each row + Row *rowdata_; + int rowdata_count_; + int rowdata_alloc_; int sort_reverse_; int sort_lastcol_; @@ -101,19 +143,28 @@ private: protected: void draw_cell(TableContext context, int R=0, int C=0, // table cell drawing - int X=0, int Y=0, int W=0, int H=0) FL_OVERRIDE; + int X=0, int Y=0, int W=0, int H=0); void sort_column(int col, int reverse=0); // sort table by a column void draw_sort_arrow(int X,int Y,int W,int H); public: // Ctor MyTable(int x, int y, int w, int h, const char *l=0) : Fl_Table_Row(x,y,w,h,l) { + rowdata_ = 0; + rowdata_count_ = 0; + rowdata_alloc_ = 0; sort_reverse_ = 0; sort_lastcol_ = -1; end(); callback(event_callback, (void*)this); } - ~MyTable() { } // Dtor + ~MyTable() { + int i; + for (i = 0; i < rowdata_count_; i++) { + row_free(&rowdata_[i]); + } + free(rowdata_); + } void load_command(const char *cmd); // Load the output of a command into table void autowidth(int pad); // Automatically set column widths to data void resize_window(); // Resize parent window to size of table @@ -121,7 +172,9 @@ public: // Sort a column up or down void MyTable::sort_column(int col, int reverse) { - std::sort(rowdata_.begin(), rowdata_.end(), SortColumn(col, reverse)); + g_sort_col = col; + g_sort_reverse = reverse; + qsort(rowdata_, rowdata_count_, sizeof(Row), row_compare); redraw(); } @@ -152,16 +205,16 @@ void MyTable::draw_sort_arrow(int X,int Y,int W,int H) { // Handle drawing all cells in table void MyTable::draw_cell(TableContext context, int R, int C, int X, int Y, int W, int H) { const char *s = ""; - if ( R < (int)rowdata_.size() && C < (int)rowdata_[R].cols.size() ) - s = rowdata_[R].cols[C].c_str(); + if ( R < rowdata_count_ && C < rowdata_[R].cols_count ) + s = rowdata_[R].cols[C]; switch ( context ) { case CONTEXT_COL_HEADER: fl_push_clip(X,Y,W,H); { fl_draw_box(FL_THIN_UP_BOX, X,Y,W,H, FL_BACKGROUND_COLOR); - if ( C < (int)G_header.size() ) { + if ( C < G_header_count ) { fl_font(HEADER_FONTFACE, HEADER_FONTSIZE); fl_color(FL_BLACK); - fl_draw(G_header[C].c_str(), X+2,Y,W,H, FL_ALIGN_LEFT, 0, 0); // +2=pad left + fl_draw(G_header[C], X+2,Y,W,H, FL_ALIGN_LEFT, 0, 0); // +2=pad left // Draw sort arrow if ( C == sort_lastcol_ ) { draw_sort_arrow(X,Y,W,H); @@ -190,17 +243,17 @@ void MyTable::draw_cell(TableContext context, int R, int C, int X, int Y, int W, // Automatically set column widths to widest data in each column void MyTable::autowidth(int pad) { - int w, h; + int w, h, c, r; // Initialize all column widths to header width fl_font(HEADER_FONTFACE, HEADER_FONTSIZE); - for ( int c = 0; c < (int)G_header.size(); c++ ) { - w=0; fl_measure(G_header[c].c_str(), w, h, 0); // pixel width of header text + for ( c = 0; c < G_header_count; c++ ) { + w=0; fl_measure(G_header[c], w, h, 0); // pixel width of header text col_width(c, w+pad); } fl_font(ROW_FONTFACE, ROW_FONTSIZE); - for ( int r=0; r<(int)rowdata_.size(); r++ ) { - for ( int c=0; c<(int)rowdata_[r].cols.size(); c++ ) { - w=0; fl_measure(rowdata_[r].cols[c].c_str(), w, h, 0); // pixel width of row text + for ( r=0; r col_width(c)) col_width(c, w + pad); } } @@ -210,9 +263,10 @@ void MyTable::autowidth(int pad) { // Resize parent window to size of table void MyTable::resize_window() { + int t; // Determine exact outer width of table with all columns visible int width = 2; // width of table borders - for ( int t=0; tw(); // include width of scrollbar width += MARGIN*2; if ( width < 200 || width > Fl::w() ) return; @@ -222,9 +276,10 @@ void MyTable::resize_window() { // Load table with output of 'cmd' void MyTable::load_command(const char *cmd) { char s[512]; + int line; FILE *fp = popen(cmd, "r"); cols(0); - for ( int line=0; fgets(s, sizeof(s)-1, fp); line++ ) { + for ( line=0; fgets(s, sizeof(s)-1, fp); line++ ) { #ifdef _WIN32 // WINDOWS if (s[0] == '\n' || s[0] == ' ') continue; // ignore header/footer lines @@ -233,30 +288,37 @@ void MyTable::load_command(const char *cmd) { if ( line==0 && strncmp(s,"total ",6)==0) continue; #endif // Add a new row - Row newrow; rowdata_.push_back(newrow); - std::vector &rc = rowdata_.back().cols; + if (rowdata_count_ >= rowdata_alloc_) { + int new_alloc = rowdata_alloc_ ? rowdata_alloc_ * 2 : 64; + rowdata_ = (Row *)realloc(rowdata_, new_alloc * sizeof(Row)); + rowdata_alloc_ = new_alloc; + } + row_init(&rowdata_[rowdata_count_]); + rowdata_count_++; + Row *rc = &rowdata_[rowdata_count_ - 1]; // Break line into separate word 'columns' char *ss; + int t; const char *delim = " \t\n"; - for(int t=0; (t==0)?(ss=strtok(s,delim)):(ss=strtok(NULL,delim)); t++) { + for(t=0; (t==0)?(ss=strtok(s,delim)):(ss=strtok(0,delim)); t++) { #ifdef _WIN32 // DIR: Some systems show meridiem field, some don't (24hr time) if (t==2 && (strcmp(ss,"AM")==0 || strcmp(ss,"PM")==0)) { - rc.back() = rc.back() + std::string(" ") + std::string(ss); - continue; + row_append_last(rc, ss); + continue; } #endif - rc.push_back(ss); // char* -> std::string + row_push(rc, ss); } // Keep track of max # columns - if ( (int)rc.size() > cols() ) { - cols((int)rc.size()); + if ( rc->cols_count > cols() ) { + cols(rc->cols_count); } } pclose(fp); // How many rows we loaded - rows((int)rowdata_.size()); + rows(rowdata_count_); // Auto-calculate widths, with 20 pixel padding autowidth(20); } diff --git a/lib/libfltk.a b/lib/libfltk.a index de1158f66..9d91f3b79 100644 Binary files a/lib/libfltk.a and b/lib/libfltk.a differ diff --git a/lib/libfltk_forms.a b/lib/libfltk_forms.a index 186fe7d5a..61f6afc56 100644 Binary files a/lib/libfltk_forms.a and b/lib/libfltk_forms.a differ diff --git a/lib/libfltk_gl.a b/lib/libfltk_gl.a index 39fb66bbd..24513da24 100644 Binary files a/lib/libfltk_gl.a and b/lib/libfltk_gl.a differ diff --git a/lib/libfltk_images.a b/lib/libfltk_images.a index e4d795a01..bfe2f505f 100644 Binary files a/lib/libfltk_images.a and b/lib/libfltk_images.a differ diff --git a/lib/libfltk_jpeg.a b/lib/libfltk_jpeg.a index fdec046a3..c1f41f080 100644 Binary files a/lib/libfltk_jpeg.a and b/lib/libfltk_jpeg.a differ diff --git a/lib/libfltk_png.a b/lib/libfltk_png.a index c100ff8de..b649fd665 100644 Binary files a/lib/libfltk_png.a and b/lib/libfltk_png.a differ diff --git a/lib/libfltk_z.a b/lib/libfltk_z.a index 516b0adaa..3d2e08a91 100644 Binary files a/lib/libfltk_z.a and b/lib/libfltk_z.a differ -- cgit v1.2.3