source: branches/reyalp-flt/core/gui_fselect.c @ 1489

Revision 1489, 52.9 KB checked in by tsv, 18 months ago (diff)

Flat branch update.

Added User-friendly module interface.

  • Modules are cleanly integrated into common menu. New module is called on start. It recursively scan module directory and make hierarchical menu for it.
  • Some modules made more standalone (could be used with no values)
  • Remove unneeded options/items

It is possible to organize modules on-build but this will cause problem unaccesibility on old cameras (like scripts/4pack/*)

  • Property svn:eol-style set to native
Line 
1#include "stdlib.h"
2#include "keyboard.h"
3#include "platform.h"
4#include "core.h"
5#include "lang.h"
6#include "gui.h"
7#include "gui_draw.h"
8#include "gui_lang.h"
9#include "gui_mbox.h"
10#include "gui_mpopup.h"
11#include "gui_fselect.h"
12#include "modules.h"
13#include "raw.h"
14#include "conf.h"
15#include "dng.h"
16
17#include "module_load.h"
18
19gui_handler GUI_MODE_FSELECT_MODULE =
20    /*GUI_MODE_FSELECT*/        { gui_fselect_draw,     gui_fselect_kbd_process,    gui_fselect_kbd_process,            0,      GUI_MODE_MAGICNUM };
21
22extern int module_idx;
23
24int *conf_sub_batch_prefix;
25int *conf_sub_batch_ext;
26
27struct librawop_sym* librawop_p;
28
29
30//-------------------------------------------------------------------
31#define HEAD_LINES              1
32#define BODY_LINES              10
33#define FOOT_LINES              1
34#define HEAD_FONT_LINES         HEAD_LINES * FONT_HEIGHT
35#define BODY_FONT_LINES         BODY_LINES * FONT_HEIGHT
36#define FOOT_FONT_LINES         FOOT_LINES * FONT_HEIGHT
37
38#define NAME_SIZE               15 // "FILENAME123 "
39#define SIZE_SIZE               7 // "1000 b|M|G"
40#define TIME_SIZE               14 // "01.01'70 00:00"
41
42#define NAME_FONT_SIZE          NAME_SIZE * FONT_WIDTH
43#define EXTE_FONT_SIZE          EXTE_SIZE * FONT_WIDTH
44#define SIZE_FONT_SIZE          SIZE_SIZE * FONT_WIDTH
45#define TIME_FONT_SIZE          TIME_SIZE * FONT_WIDTH
46
47#define SPACING                 4
48#define TAB_DIVIDER             1
49#define BORDER                  2
50#define SCROLLBAR               4
51
52#define MARKED_OP_NONE          0
53#define MARKED_OP_CUT           1
54#define MARKED_OP_COPY          2
55#define MARKED_BUF_SIZE         0x10000
56
57//-------------------------------------------------------------------
58static char current_dir[100];       // Path for title
59static char marked_dir[100];        // Path for progress box
60static char selected_file[100];     // This full path to current file. So it is return value
61static char buf[100];
62static gui_mode_t gui_fselect_mode_old; // stored previous gui_mode
63
64// basic element of file list
65struct fitem {
66    unsigned int    n;
67    char            *name;
68    unsigned char   attr;
69    unsigned long   size;
70    unsigned long   mtime;
71    unsigned char   marked;
72    struct fitem    *prev, *next;
73};
74static struct fitem *head=NULL;     // head of list<fitem>:  holder of current directory list
75static struct fitem *top;           // ptr to first displayed file (top on the screen)
76static struct fitem *selected;      // ptr to current file (file on cursor)
77static unsigned int count;          // cur_dir_file_list.size()
78static unsigned int max_dir_len;    // just NAME_SIZE+SIZE_SIZE+SPACING
79
80static struct fitem *marked_head=NULL;  // head of list<fitem>:  holder of selected files list (keep independent filelist). made by Cut/Copy
81static unsigned int marked_count;       // marked_file_list.size()
82static char marked_operation;           // info for paste: MARKED_OP_NONE, MARKED_OP_CUT, MARKED_OP_COPY
83
84
85static coord main_x, main_y, main_w, main_h; //main browser window coord (without BORDERs)
86static coord head_x, head_y, head_w, head_h; //header window coord
87static coord body_x, body_y, body_w, body_h; //main body window coord
88static coord foot_x, foot_y, foot_w, foot_h; //footer window coord
89
90static int gui_fselect_redraw;  // flag request fselect redraw: 0-no, 1-only filelist, 2-whole_redraw(incl.border)
91static char *fselect_title;     // Title of fselect window (could be different: Choose Text, Choose Script, etc)
92
93static void (*fselect_on_select)(const char *fn);
94static char raw_operation;      // info for process_raw_files() RAW_OPERATION_AVERAGE, RAW_OPERATION_SUM,
95static int set_key_redraw_mode; // dirty hack: screen erase & mode restore done after(0) or before(1) call to fselect_on_select
96
97// FSelector POPUP
98#define MPOPUP_CUT              0x0001
99#define MPOPUP_COPY             0x0002
100#define MPOPUP_PASTE            0x0004
101#define MPOPUP_DELETE           0x0008
102#define MPOPUP_SELINV           0x0010
103#define MPOPUP_RAW_ADD          0x0020
104#define MPOPUP_RAW_AVERAGE      0x0040
105#define MPOPUP_PURGE            0x0080
106#define MPOPUP_SUBTRACT         0x0100
107#define MPOPUP_RAW_DEVELOP      0x0200
108#define MPOPUP_DNG_TO_CRW       0x0400
109#define MPOPUP_EDITOR           0x0800
110#define MPOPUP_CHDK_REPLACE     0x1000
111
112static struct mpopup_item popup[]= {
113        { MPOPUP_CUT,           LANG_POPUP_CUT    },
114        { MPOPUP_COPY,          LANG_POPUP_COPY   },
115        { MPOPUP_PASTE,         LANG_POPUP_PASTE  },
116        { MPOPUP_DELETE,        LANG_POPUP_DELETE },
117        { MPOPUP_SELINV,        LANG_POPUP_SELINV },
118        { MPOPUP_RAW_ADD,       LANG_POPUP_RAW_SUM},
119        { MPOPUP_RAW_AVERAGE,   LANG_POPUP_RAW_AVERAGE },
120        { MPOPUP_RAW_DEVELOP,   LANG_MENU_RAW_DEVELOP },
121        { MPOPUP_PURGE,         LANG_POPUP_PURGE  },
122        { MPOPUP_SUBTRACT,      LANG_POPUP_SUB_FROM_MARKED  },
123        { MPOPUP_DNG_TO_CRW,    (int)"DNG -> CHDK RAW"},
124        { MPOPUP_EDITOR,        (int)"Edit" },
125        { MPOPUP_CHDK_REPLACE,  (int)"Set this CHDK" },
126        { 0,                                    0 },
127};
128
129//-------------------------------------------------------------------
130static void fselect_goto_prev(int step) {
131    register int j, i;
132
133    for (j=0; j<step; ++j) {
134        if (selected->prev==top && top->prev)
135            top=top->prev;
136        if (selected->prev)
137            selected=selected->prev;
138        else
139        if (step == 1)
140        {
141            for(; selected->next; selected=selected->next);
142            for (i=0, top=selected; i<BODY_LINES-1 && top->prev; ++i, top=top->prev);
143        }
144    }
145}
146
147//-------------------------------------------------------------------
148static void fselect_goto_next(int step) {
149    register int j, i;
150    struct fitem  *ptr;
151
152    for (j=0; j<step; ++j) {
153        for (i=0, ptr=top; i<BODY_LINES-1 && ptr; ++i, ptr=ptr->next);
154        if (i==BODY_LINES-1 && ptr && ptr->prev==selected && ptr->next)
155            top=top->next;
156        if (selected->next)
157            selected=selected->next;
158        else
159        if (step == 1)
160        {
161            for(; top->prev; top = top->prev);
162            selected = top;
163        }
164    }
165}
166
167//-------------------------------------------------------------------
168static void gui_fselect_free_data() {
169    struct fitem  *ptr = head, *prev;
170
171    while (ptr) {
172        if (ptr->name)
173            free(ptr->name);
174        prev = ptr;
175        ptr = ptr->next;
176        free(prev);
177    }
178    head = top = selected = NULL;
179    count = 0;
180}
181
182//-------------------------------------------------------------------
183extern int fselect_sort_nothumb(const void* v1, const void* v2);
184int fselect_sort(const void* v1, const void* v2) {
185    struct fitem *i1=*((struct fitem **)v1), *i2=*((struct fitem **)v2);
186
187    if (i1->attr & DOS_ATTR_DIRECTORY) {
188        if (i2->attr & DOS_ATTR_DIRECTORY) {
189            if (i1->name[0]=='.' && i1->name[1]=='.' && i1->name[2]==0) {
190                return -1;
191            } else if (i2->name[0]=='.' && i2->name[1]=='.' && i2->name[2]==0) {
192                return 1;
193            } else {
194                return strcmp(i1->name, i2->name);
195            }
196        } else {
197            return -1;
198        }
199    } else {
200        if (i2->attr & DOS_ATTR_DIRECTORY) {
201            return 1;
202        } else {
203            return strcmp(i1->name, i2->name);
204        }
205    }
206}
207
208//-------------------------------------------------------------------
209static void gui_fselect_read_dir(const char* dir) {
210    DIR           *d;
211    struct dirent *de;
212    static struct stat   st;
213    struct fitem  **ptr = &head, *prev = NULL;
214    int    i;
215
216    gui_fselect_free_data();
217#ifdef CAM_DRYOS_2_3_R39
218    if(dir[0]=='A' && dir[1]==0)
219        d = opendir("A/");
220    else
221        d = opendir(dir);
222#else
223    d = opendir(dir);
224#endif
225    if (d) {
226        de = readdir(d);
227        while (de) {
228            if (de->d_name[0] != 0xE5 /* deleted entry */ && (de->d_name[0]!='.' || de->d_name[1]!=0)) {
229                *ptr = malloc(sizeof(struct fitem));
230                if (*ptr) {
231                    (*ptr)->n = count;
232                    (*ptr)->name = malloc(strlen(de->d_name)+1);
233                    if ((*ptr)->name)
234                        strcpy((*ptr)->name, de->d_name);
235                    sprintf(buf, "%s/%s", dir, de->d_name);
236                    if (stat(buf, &st)==0) {
237                        (*ptr)->attr=st.st_attrib;
238                        (*ptr)->size=st.st_size;
239                        (*ptr)->mtime=st.st_mtime;
240                    } else {
241                        (*ptr)->attr=(de->d_name[0]=='.' && de->d_name[1]=='.' && de->d_name[2]==0)?DOS_ATTR_DIRECTORY:0xFF;
242                        (*ptr)->size=(*ptr)->mtime=0;
243                    }
244                    (*ptr)->marked=0;
245                    (*ptr)->prev=prev;
246                    prev=*ptr;
247                    ptr = &((*ptr)->next);
248                    ++count;
249                }   
250            }
251            de = readdir(d);
252        }
253        closedir(d);
254    }
255    *ptr=NULL;
256   
257    if (count) {
258        // sort
259        ptr=malloc(count*sizeof(struct fitem*));
260        if (ptr) {
261            prev=head;
262            count=0;
263            while (prev) {
264                ptr[count++]=prev;
265                prev=prev->next;
266            }
267           
268            qsort(ptr, count, sizeof(struct fitem*), fselect_sort_nothumb);
269           
270            for (i=0; i<count-1; ++i) {
271                ptr[i]->n=i;
272                ptr[i]->next=ptr[i+1];
273                ptr[i+1]->prev=ptr[i];
274            }
275            ptr[0]->prev=ptr[count-1]->next=NULL;
276            ptr[count-1]->n=count-1;
277            head=ptr[0];
278
279            free(ptr);
280        }
281    }
282
283    top = selected = head;
284}
285
286//-------------------------------------------------------------------
287// Set flag to control how the erase/redraw happens when the set key
288// is pressed.
289// 0 - screen erase & mode restore done after call to fselect_on_select
290// 1 - screen erase & mode restore done before call to fselect_on_select
291// Needed for text reader to work correctly and to stop intermittent
292// crashes when selecting fonts (hack - whole gui/kbd system needs an overhaul).
293void gui_fselect_set_key_redraw(int n)
294{
295    set_key_redraw_mode = n;
296}
297
298//-------------------------------------------------------------------
299// Attempt to set startup directory (and file) based on input 'dir'
300// Note: 'dir' may be a directory name or a file name (including path)
301// Returns 1 if valid directory/file found, 0 otherwise
302int gui_fselect_find_start_dir(const char* dir)
303{
304    selected_file[0] = 0;
305    strcpy(current_dir, dir);
306
307    // Make sure there is something left to check
308    while (strlen(current_dir) > 0)
309    {
310        struct stat st;
311        // check if input 'dir' exists
312        if (stat(current_dir,&st) == 0)     
313        {
314            // exists - check if it is a directory or file
315            if (st.st_attrib & DOS_ATTR_DIRECTORY)
316            {
317                // Directory and exists so all good
318                return 1;
319            }
320            else
321            {
322                // 'dir' is a file, extract filename to 'selected_file' and remove from 'current_dir'
323                char *p = strrchr(current_dir,'/');
324                strcpy(selected_file, p+1);
325                *p = 0;
326                return 1;
327            }
328        }
329        else
330        {
331            // could not find 'dir' - try one level up
332            char *p = strrchr(current_dir,'/');
333            if (p) *p = 0;
334            else return 0;
335        }
336    }
337
338    return 0;
339}
340
341//-------------------------------------------------------------------
342void gui_fselect_init(int title, const char* prev_dir, const char* default_dir, void (*on_select)(const char *fn))
343{
344    int i;
345   
346    int chars_width = NAME_FONT_SIZE + SIZE_FONT_SIZE + TIME_FONT_SIZE;
347    main_w = SPACING/*N*/+SPACING+TAB_DIVIDER+SPACING/*S*/+SPACING+TAB_DIVIDER+SPACING/*T*/+SPACING+SCROLLBAR+chars_width;
348    main_h = HEAD_FONT_LINES + TAB_DIVIDER + BODY_FONT_LINES + TAB_DIVIDER + FOOT_FONT_LINES;
349    main_x = (screen_width - main_w) >> 1;
350    main_y = (screen_height - main_h) >> 1;
351   
352    head_x = body_x = foot_x = main_x;
353    head_w = body_w = foot_w = main_w;   
354    head_y = main_y;
355    head_h = HEAD_FONT_LINES;   
356    body_y = head_y + head_h + TAB_DIVIDER;
357    body_h = BODY_FONT_LINES;
358    foot_y = body_y + body_h + TAB_DIVIDER;
359    foot_h = FOOT_FONT_LINES;
360   
361    fselect_title = lang_str(title);
362
363    // Try and set start directory, and optionally selected file, from inputs
364    if (!gui_fselect_find_start_dir(prev_dir))
365        if (!gui_fselect_find_start_dir(default_dir))
366            gui_fselect_find_start_dir("A");
367
368    max_dir_len = NAME_SIZE + SIZE_SIZE + SPACING;
369    gui_fselect_read_dir(current_dir);
370    top = selected = head;
371
372    // Find selected file if it exists in list
373    if (selected_file[0])
374    {
375        struct fitem *p = head;
376        while (p)
377        {
378            if (strcmp(p->name,selected_file) == 0)
379            {
380                break;
381            }
382            p = p->next;
383            fselect_goto_next(1);
384        }
385        if (!p) selected_file[0] = 0;
386    }
387
388    fselect_on_select = on_select;
389    marked_operation = MARKED_OP_NONE;
390    gui_fselect_mode_old = gui_get_mode();
391    gui_fselect_redraw = 2;
392    gui_set_mode((unsigned int)&GUI_MODE_FSELECT_MODULE);
393    gui_fselect_set_key_redraw(0);
394}
395
396//-------------------------------------------------------------------
397char* gui_fselect_result() {
398    if (selected_file[0])
399        return selected_file;
400    else
401        return NULL;
402}
403
404//-------------------------------------------------------------------
405void gui_fselect_draw_initial() {
406    int title_font_size;
407    int i;
408
409    draw_filled_rect(head_x, head_y, head_x+head_w-1, head_y+head_h-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK)); //header box
410    title_font_size = strlen(fselect_title) * FONT_WIDTH;
411    draw_string(head_x+((head_w-title_font_size)>>1), head_y, fselect_title, MAKE_COLOR(COLOR_BLACK, COLOR_WHITE)); //title text
412   
413    draw_rect_thick(main_x-BORDER, main_y-BORDER, main_x+main_w+BORDER-1, main_y+main_h+BORDER-1, COLOR_WHITE, BORDER); //border frame
414    draw_line(body_x, body_y-1, body_x+body_w-1, body_y-1, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE)); //border head-body
415    draw_line(foot_x, foot_y-1, foot_x+foot_w-1, foot_y-1, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE)); //border body-foot   
416}
417
418//-------------------------------------------------------------------
419void gui_fselect_draw(int enforce_redraw) {
420    int i, j, off_name_x, off_size_x, off_time_x, off_body_x, off_body_y;
421    struct fitem  *ptr;
422    char buf[100];
423    struct tm *time;
424    unsigned long sum_size;
425    color cl_markered = ((mode_get()&MODE_MASK) == MODE_REC)?COLOR_YELLOW:0x66;
426    color cl_marked, cl_selected;
427
428        if ( enforce_redraw )
429                gui_fselect_redraw = 2;
430
431    if (gui_fselect_redraw) {
432        if (gui_fselect_redraw == 2)
433            gui_fselect_draw_initial();
434
435        off_body_y = 0;
436        off_name_x = body_x+SPACING;
437        off_size_x = off_name_x+NAME_FONT_SIZE+SPACING+TAB_DIVIDER+SPACING;
438        off_time_x = off_size_x+SIZE_FONT_SIZE+SPACING+TAB_DIVIDER+SPACING;
439        off_body_x = off_time_x+TIME_FONT_SIZE+SPACING;
440
441        sum_size = 0;
442        for (i=0, ptr=top; i<BODY_LINES && ptr; ++i, ptr=ptr->next) {
443       
444            cl_marked = MAKE_COLOR((ptr==selected)?COLOR_RED:COLOR_GREY, (ptr->marked)?cl_markered:COLOR_WHITE);
445            cl_selected = (ptr==selected)?MAKE_COLOR(COLOR_RED, COLOR_RED):MAKE_COLOR(COLOR_GREY, COLOR_GREY);
446       
447            // print name
448            for (j=0; j<NAME_SIZE && ptr->name[j]; ++j)
449                buf[j] = ptr->name[j];
450               
451            if (j==NAME_SIZE && ptr->name[j]) buf[NAME_SIZE-1] = '~'; // too long name
452           
453            if (ptr->attr & DOS_ATTR_DIRECTORY && ptr->attr != 0xFF) { //?
454                if (j<NAME_SIZE) {
455                    buf[j++]='/';
456                } else {
457                    buf[NAME_SIZE-2]='~';
458                    buf[NAME_SIZE-1]='/';
459                }
460            }
461            for (; j<NAME_SIZE && (buf[j++]=' ');); //fill upto NAME_SIZE
462            buf[NAME_SIZE] = 0; // eos
463           
464            off_body_y = body_y+(i*FONT_HEIGHT);
465            draw_filled_rect(body_x, off_body_y, off_name_x-1, off_body_y+FONT_HEIGHT-1, cl_selected);
466            draw_string(off_name_x, off_body_y, buf, cl_marked);
467            draw_filled_rect(off_name_x+NAME_FONT_SIZE, off_body_y, off_name_x+NAME_FONT_SIZE+SPACING-1, off_body_y+FONT_HEIGHT-1, cl_selected);
468           
469            // print size or <Dir>
470            if (ptr->attr & DOS_ATTR_DIRECTORY) {
471                if (ptr->attr == 0xFF) {
472                    sprintf(buf, "  ???  ");
473                } else if (ptr->name[0] == '.' && ptr->name[1] == '.' && ptr->name[2] == 0) {
474                    sprintf(buf, "<UpDir>");
475                } else {
476                    sprintf(buf, "< Dir >");
477                }
478            } else {
479                if (ptr->size < 1024)
480                    sprintf(buf, "%5d b", ptr->size); // " 1023 b"
481                else if (ptr->size < 1024*1024)
482                    sprintf(buf, "%3ld,%1d k", ptr->size/1024, (ptr->size%1024*10)/1024); // "999,9 k"
483                else if (ptr->size < 1024*1024*1024)
484                    sprintf(buf, "%3ld,%ld M", ptr->size/(1024*1024), (ptr->size%(1024*1024)*10)/(1024*1024) ); // "999,9 M"
485                else
486                    sprintf(buf, "%31d,%ld G", ptr->size/(1024*1024*1024), (ptr->size%(1024*1024*1024)*10)/(1024*1024*1024)); // "999.9 G"
487                   
488                if (ptr->marked)
489                  sum_size += ptr->size;
490            }
491            buf[SIZE_SIZE] = 0;
492            //tab divider
493            draw_line(off_size_x-TAB_DIVIDER-SPACING, off_body_y, off_size_x-TAB_DIVIDER-SPACING, off_body_y+FONT_HEIGHT-1, COLOR_WHITE);
494            draw_filled_rect(off_size_x-SPACING, off_body_y, off_size_x-1, off_body_y+FONT_HEIGHT-1, cl_selected);           
495            draw_string(off_size_x, off_body_y, buf, cl_marked);
496            draw_filled_rect(off_size_x+SIZE_FONT_SIZE, off_body_y, off_size_x+SIZE_FONT_SIZE+SPACING-1, off_body_y+FONT_HEIGHT-1, cl_selected);           
497           
498            // print modification time
499            if (ptr->mtime) {
500                time = localtime(&(ptr->mtime));
501                sprintf(buf, "%02u.%02u'%02u %02u:%02u", time->tm_mday, time->tm_mon+1, (time->tm_year<100)?time->tm_year:time->tm_year-100, time->tm_hour, time->tm_min);
502            } else {
503                sprintf(buf, "%14s", "");
504            }
505            buf[TIME_SIZE] = 0;
506            //tab divider
507            draw_line(off_time_x-TAB_DIVIDER-SPACING, off_body_y, off_time_x-TAB_DIVIDER-SPACING, off_body_y+FONT_HEIGHT-1, COLOR_WHITE);
508            draw_filled_rect(off_time_x-SPACING, off_body_y, off_time_x-1, off_body_y+FONT_HEIGHT-1, cl_selected);
509            draw_string(off_time_x, off_body_y, buf, cl_marked);           
510            draw_filled_rect(off_time_x+TIME_FONT_SIZE, off_body_y, off_time_x+TIME_FONT_SIZE+SPACING-1, off_body_y+FONT_HEIGHT-1, cl_selected);
511        }
512
513        //fill the rest of body
514        off_body_y += FONT_HEIGHT;
515        if (i>0 && i<BODY_LINES) {
516            draw_filled_rect(body_x, off_body_y, body_x+body_w-1, body_y+body_h-1, MAKE_COLOR(COLOR_GREY, COLOR_GREY));
517        }
518       
519       // scrollbar
520        draw_filled_rect(off_body_x, body_y, off_body_x+SCROLLBAR-1, body_y+body_h-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK));
521        if (count>BODY_LINES) {
522            i = BODY_FONT_LINES - 1;
523            j = i*BODY_LINES/count;
524            if (j<20) j=20;
525            i = (i-j)*selected->n/(count-1);
526            draw_filled_rect(off_body_x, body_y+i, off_body_x+SCROLLBAR-2, body_y+i+j, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE));
527        }
528
529        //footer
530        i = strlen(current_dir);
531        if (i > max_dir_len) {
532          strncpy(buf, current_dir+i-max_dir_len, max_dir_len);
533          buf[0] = '.';
534          buf[1] = '.';         
535        } else {
536          strcpy(buf, current_dir);         
537        }
538        buf[max_dir_len] = 0;
539        draw_filled_rect(foot_x, foot_y, foot_x+foot_w-1, foot_y+foot_h-1, MAKE_COLOR(COLOR_GREY, COLOR_GREY)); //footer box       
540        draw_string(off_name_x, foot_y, buf, MAKE_COLOR(COLOR_GREY, COLOR_WHITE)); //current dir
541       
542        if (sum_size) {
543          sprintf(buf, "%d b", sum_size); //selected size
544        } else {
545          unsigned int fr, tot;
546          fr = GetFreeCardSpaceKb(); tot = GetTotalCardSpaceKb();
547          if (fr < 1024*1024)
548            sprintf(buf, "%dM (%d%%)", fr/1024, tot? fr*100/tot: 0);
549          else
550            sprintf(buf, "%d.%dG (%d%%)", fr/(1024*1024), (fr%(10240))/100, tot? fr*100/tot: 0);
551        }
552        draw_string(foot_x+foot_w-strlen(buf)*FONT_WIDTH-BORDER, foot_y, buf, MAKE_COLOR(COLOR_GREY, COLOR_WHITE)); // free space
553        gui_fselect_redraw = 0;
554    }
555}
556
557//-------------------------------------------------------------------
558static void fselect_delete_file_cb(unsigned int btn) {
559    if (btn==MBOX_BTN_YES) {
560        started();
561        sprintf(selected_file, "%s/%s", current_dir, selected->name);
562        remove(selected_file);
563        finished();
564        selected_file[0]=0;
565        gui_fselect_read_dir(current_dir);
566    }
567    gui_fselect_redraw = 2;
568}
569
570static void fselect_purge_cb(unsigned int btn) {
571
572   DIR             *d,  *d2,  *d3,  *d4;
573   struct dirent   *de, *de2, *de3, *de4;
574   struct fitem    *ptr, *ptr2;
575   char            sub_dir[20], sub_dir_search[20];
576   char            selected_item[256];
577   int             i, found=0;
578
579   if (btn==MBOX_BTN_YES) {
580       //If selected folder is DCIM (this is to purge all RAW files in any Canon folder)
581       if (selected->name[0] == 'D' && selected->name[1] == 'C' && selected->name[2] == 'I' && selected->name[3] == 'M') {
582           sprintf(current_dir+strlen(current_dir), "/%s", selected->name);
583           d=opendir(current_dir);
584           while ((de=readdir(d)) != NULL) {//Loop to find all Canon folders
585               if (de->d_name[0] != '.' && de->d_name[1] != '.') {//If item is not UpDir
586                   sprintf(sub_dir, "%s/%s", current_dir, de->d_name);
587                   d2=opendir(sub_dir);
588                   while ((de2=readdir(d2)) != NULL) {//Loop to find all the RAW files inside a Canon folder
589                       if (de2->d_name[0] == 'C' || de2->d_name[9] == 'C') {//If file is RAW (Either CRW/CR2 prefix or file extension)
590                           d3=opendir(current_dir);
591                           while ((de3=readdir(d3)) != NULL) {//Loop to find all Canon folders
592                               if (de3->d_name[0] != '.' && de3->d_name[1] != '.') {//If item is not UpDir
593                                   sprintf(sub_dir_search, "%s/%s", current_dir, de3->d_name);
594                                   d4=opendir(sub_dir_search);
595                                   while ((de4=readdir(d4)) != NULL) {//Loop to find a corresponding JPG file inside a Canon folder
596                                       if (de2->d_name[4] == de4->d_name[4] && de2->d_name[5] == de4->d_name[5] &&//If the four digits of the Canon number are the same
597                                           de2->d_name[6] == de4->d_name[6] && de2->d_name[7] == de4->d_name[7] &&
598                                           de4->d_name[9] == 'J' && !(de4->d_name[0] == 'C' || de4->d_name[9] == 'C' || de4->d_name[0] == 0xE5)) {//If file is JPG, is not CRW/CR2 and is not a deleted item
599                                           started();
600                                           found=1;//A JPG file with the same Canon number was found
601                                       }                                 
602                                   }
603                                   closedir(d4);                 
604                               } 
605                           }
606                           closedir(d3);
607                           //If no JPG found, delete RAW file
608                           if (found == 0) {
609                               sprintf(selected_item, "%s/%s", sub_dir, de2->d_name);
610                               remove(selected_item);
611                               finished();
612                           }
613                           else {
614                               found=0;
615                               finished();
616                           }                             
617                       }
618                   }
619                   closedir(d2);
620               }
621           }
622           closedir(d);
623           i=strlen(current_dir);
624           while (current_dir[--i] != '/');
625           current_dir[i]=0;
626       }
627       //If item is a Canon folder (this is to purge all RAW files inside a single Canon folder)
628       else if (selected->name[3] == 'C') {
629           sprintf(current_dir+strlen(current_dir), "/%s", selected->name);
630           d=opendir(current_dir);
631           while ((de=readdir(d)) != NULL) {//Loop to find all the RAW files inside the Canon folder
632               if (de->d_name[0] == 'C' || de->d_name[9] == 'C') {//If file is RAW (Either CRW/CR2 prefix or file extension)
633                   d2=opendir(current_dir);
634                   while ((de2=readdir(d2)) != NULL) {//Loop to find a corresponding JPG file inside the Canon folder
635                       if (de->d_name[4] == de2->d_name[4] && de->d_name[5] == de2->d_name[5] &&//If the four digits of the Canon number are the same
636                           de->d_name[6] == de2->d_name[6] && de->d_name[7] == de2->d_name[7] &&
637                           de2->d_name[9] == 'J' && !(de2->d_name[0] == 'C' || de2->d_name[9] == 'C' || de2->d_name[0] == 0xE5)) {//If file is JPG and is not CRW/CR2 and is not a deleted item
638                           started();
639                           found=1;//A JPG file with the same Canon number was found
640                       }                                 
641                   }
642                   closedir(d2);
643                   //If no JPG found, delete RAW file               
644                   if (found == 0) {
645                       sprintf(selected_item, "%s/%s", current_dir, de->d_name);
646                       remove(selected_item);
647                       finished();
648                   }
649                   else {
650                       found=0;
651                       finished();
652                   }
653               }
654           }
655           closedir(d);
656           i=strlen(current_dir);
657           while (current_dir[--i] != '/');
658           current_dir[i]=0;
659       }
660       else {
661           //If inside a Canon folder (files list)
662           for (ptr=head; ptr; ptr=ptr->next) {//Loop to find all the RAW files in the list
663               if ((ptr->name[0] == 'C' || ptr->name[9] == 'C') && !(ptr->marked)) {//If file is RAW (Either CRW/CR2 prefix or file extension) and is not marked
664                   for (ptr2=head; ptr2; ptr2=ptr2->next) {//Loop to find a corresponding JPG file in the list
665                       if (ptr->name[4] == ptr2->name[4] && ptr->name[5] == ptr2->name[5] &&//If the four digits of the Canon number are the same
666                           ptr->name[6] == ptr2->name[6] && ptr->name[7] == ptr2->name[7] &&
667                           ptr2->name[9] == 'J' && !(ptr2->name[0] == 'C' || ptr2->name[9] == 'C')) {//If file is JPG and is not CRW/CR2
668                           started();
669                           found=1;
670                       }
671                   }
672                   //If no JPG found, delete RAW file           
673                   if (found == 0) {
674                       sprintf(selected_file, "%s/%s", current_dir, ptr->name);
675                       remove(selected_file);
676                       finished();
677                   }
678                   else {
679                       found=0;
680                       finished();
681                   }
682               }
683           }
684       }
685       gui_fselect_read_dir(current_dir);
686   }
687   gui_fselect_redraw = 2;
688}
689
690
691//-------------------------------------------------------------------
692static void fselect_delete_folder_cb(unsigned int btn) {
693    DIR           *d;
694    struct dirent *de;
695    int           i;
696
697    if (btn==MBOX_BTN_YES) {
698        sprintf(current_dir+strlen(current_dir), "/%s", selected->name);
699        d = opendir(current_dir);
700        if (d) {
701            de = readdir(d);
702            while (de) {
703                if (de->d_name[0] != 0xE5 /* deleted entry */ && (de->d_name[0]!='.' || (de->d_name[1]!='.' && de->d_name[1]!=0) || (de->d_name[1]=='.' && de->d_name[2]!=0))) {
704                    started();
705                    sprintf(selected_file, "%s/%s", current_dir, de->d_name);
706                    remove(selected_file);
707                    finished();
708                }
709                de = readdir(d);
710            }
711            closedir(d);
712        }
713        started();
714        remove(current_dir);
715        finished();
716        i=strlen(current_dir);
717        while (current_dir[--i] != '/');
718        current_dir[i]=0;
719        selected_file[0]=0;
720        gui_fselect_read_dir(current_dir);
721    }
722    gui_fselect_redraw = 2;
723}
724
725//-------------------------------------------------------------------
726static void fselect_marked_toggle() {
727    if (selected && selected->attr != 0xFF && !(selected->attr & DOS_ATTR_DIRECTORY)) {
728        selected->marked = !selected->marked;
729    }
730}
731
732//-------------------------------------------------------------------
733static void gui_fselect_marked_free_data() {
734    struct fitem  *ptr = marked_head, *prev;
735
736    while (ptr) {
737        if (ptr->name)
738            free(ptr->name);
739        prev=ptr;
740        ptr=ptr->next;
741        free(prev);
742    }
743    marked_head=NULL;
744    marked_count=0;
745    marked_operation = MARKED_OP_NONE;
746}
747
748//-------------------------------------------------------------------
749static void fselect_marked_copy_list() {
750    gui_fselect_marked_free_data();
751
752    struct fitem  *ptr, **marked_ptr=&marked_head, *prev = NULL;
753
754    for (ptr=head; ptr; ptr=ptr->next) {
755        if (ptr->marked) {
756            *marked_ptr = malloc(sizeof(struct fitem));
757            if (*marked_ptr) {
758                (*marked_ptr)->n = ptr->n;
759                (*marked_ptr)->name = malloc(strlen(ptr->name)+1);
760                if ((*marked_ptr)->name)
761                   strcpy((*marked_ptr)->name, ptr->name);
762                (*marked_ptr)->attr=ptr->attr;
763                (*marked_ptr)->size=ptr->size;
764                (*marked_ptr)->mtime=ptr->mtime;
765                (*marked_ptr)->marked=ptr->marked;
766                (*marked_ptr)->prev=prev;
767                prev=*marked_ptr;
768                marked_ptr = &((*marked_ptr)->next);
769                *marked_ptr=NULL;
770                ++marked_count;
771            }
772        }
773    }
774
775    if (!marked_count)
776        if (selected && selected->attr != 0xFF)
777            if (!(selected->attr & DOS_ATTR_DIRECTORY)) {
778                *marked_ptr = malloc(sizeof(struct fitem));
779                if (*marked_ptr) {
780                    (*marked_ptr)->n = selected->n;
781                    (*marked_ptr)->name = malloc(strlen(selected->name)+1);
782                    if ((*marked_ptr)->name)
783                        strcpy((*marked_ptr)->name, selected->name);
784                    (*marked_ptr)->attr=selected->attr;
785                    (*marked_ptr)->size=selected->size;
786                    (*marked_ptr)->mtime=selected->mtime;
787                    (*marked_ptr)->marked=!(0);
788                    (*marked_ptr)->prev=prev;
789                    prev=*marked_ptr;
790                    marked_ptr = &((*marked_ptr)->next);
791                    *marked_ptr=NULL;
792                    ++marked_count;
793                }
794            }
795
796    sprintf(marked_dir, "%s", current_dir);
797}
798
799//-------------------------------------------------------------------
800static void fselect_marked_paste_cb(unsigned int btn) {
801    struct fitem  *ptr;
802    int ss, sd = 0, fsrc, fdst, i=0;
803    register int *buf;
804    unsigned char fend;
805    static struct utimbuf t;
806
807    if (btn != MBOX_BTN_YES) return;
808
809    if (strcmp(marked_dir, current_dir) != 0) {
810        buf = umalloc(MARKED_BUF_SIZE);
811        if (buf) {
812            for (ptr=marked_head; ptr; ptr=ptr->next) {
813                if (ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
814                    started();
815                    ++i;
816                    if (marked_count)
817                        gui_browser_progress_show(lang_str(LANG_FSELECT_PROGRESS_TITLE),i*100/marked_count);
818                    sprintf(selected_file, "%s/%s", marked_dir, ptr->name);
819                    fsrc = open(selected_file, O_RDONLY, 0777);
820                    if (fsrc>=0) {
821                        sprintf(selected_file, "%s/%s", current_dir, ptr->name);
822                        // trying to open for read to check if file exists
823                        fdst = open(selected_file, O_RDONLY, 0777);
824                        if (fdst<0) {
825                            fdst = open(selected_file, O_WRONLY|O_CREAT, 0777);
826                            if (fdst>=0) {
827                                do {
828                                    ss=read(fsrc, buf, MARKED_BUF_SIZE);
829                                    if (ss>0) sd=write(fdst, buf, ss);
830                                } while (ss>0 && ss==sd);
831                                close(fdst);
832                                t.actime = t.modtime = ptr->mtime;
833                                utime(selected_file, &t);
834                                if (marked_operation == MARKED_OP_CUT && ss==0) {
835                                    close(fsrc); fsrc = -1;
836                                    sprintf(selected_file, "%s/%s", marked_dir, ptr->name);
837                                    remove(selected_file);
838                                }
839                            }
840                        } else {
841                            close(fdst);
842                        }
843                        if (fsrc>=0) close(fsrc);
844                    }
845                    finished();
846                    selected_file[0]=0;
847                }
848            }
849            ufree(buf);
850            if (marked_operation == MARKED_OP_CUT) {
851                gui_fselect_marked_free_data();
852            }
853        }
854        gui_fselect_read_dir(current_dir);
855    }
856    gui_fselect_redraw = 2;
857}
858
859//-------------------------------------------------------------------
860static inline unsigned int fselect_real_marked_count() {
861    struct fitem  *ptr;
862    register unsigned int cnt=0;
863
864    for (ptr=head; ptr; ptr=ptr->next) {
865        if (ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY) && ptr->marked)
866            ++cnt;
867    }
868    return cnt;
869}
870//-------------------------------------------------------------------
871static unsigned int fselect_marked_count() {
872    struct fitem  *ptr;
873    register unsigned int cnt=fselect_real_marked_count();
874
875    if (!cnt) {
876        if (selected && selected->attr != 0xFF && !(selected->attr & DOS_ATTR_DIRECTORY))
877            ++cnt;
878    }
879
880    return cnt;
881}
882
883//-------------------------------------------------------------------
884static void fselect_marked_delete_cb(unsigned int btn) {
885    struct fitem  *ptr;
886    unsigned int del_cnt=0, cnt;
887
888    if (btn != MBOX_BTN_YES) return;
889
890    cnt=fselect_marked_count();
891    for (ptr=head; ptr; ptr=ptr->next)
892        if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
893            started();
894            ++del_cnt;
895            if (cnt)
896                gui_browser_progress_show(lang_str(LANG_FSELECT_PROGRESS_TITLE),del_cnt*100/cnt);
897            sprintf(selected_file, "%s/%s", current_dir, ptr->name);
898            remove(selected_file);
899            finished();
900            selected_file[0]=0;
901        }
902
903    if (del_cnt == 0 && selected) {
904        started();
905        sprintf(selected_file, "%s/%s", current_dir, selected->name);
906        remove(selected_file);
907        finished();
908        selected_file[0]=0;
909    }
910    gui_fselect_read_dir(current_dir);
911    gui_fselect_redraw = 2;
912}
913
914//-------------------------------------------------------------------
915static void fselect_chdk_replace_cb(unsigned int btn) {
916    int ss, sd = 0, fsrc, fdst, i=0;
917    register int *buf;
918    unsigned char fend;
919    static struct utimbuf t;
920
921    if (btn != MBOX_BTN_YES) return;
922
923    buf = umalloc(MARKED_BUF_SIZE);
924    sprintf(selected_file, "%s/%s", current_dir, selected->name);
925    fsrc = open(selected_file, O_RDONLY, 0777);
926    if (fsrc>=0) {
927            strcpy(selected_file,"A/DISKBOOT.BIN");
928            fdst = open(selected_file, O_WRONLY|O_CREAT|O_TRUNC, 0777);
929            if (fdst>=0) {
930                do {
931                    ss=read(fsrc, buf, MARKED_BUF_SIZE);
932                    if (ss>0) sd=write(fdst, buf, ss);
933                } while (ss>0 && ss==sd);
934                close(fdst);
935                t.actime = t.modtime = selected->mtime;
936                utime(selected_file, &t);
937                //shutdown();
938                        gui_browser_progress_show("Please reboot",100);
939            }
940        if (fsrc>=0) close(fsrc);
941    }
942    ufree(buf);
943}
944
945//-------------------------------------------------------------------
946static void fselect_marked_inverse_selection() {
947    struct fitem  *ptr;
948   
949    for (ptr=head; ptr; ptr=ptr->next)
950        if (ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY))
951            ptr->marked = !ptr->marked;
952   
953    gui_fselect_redraw = 2;
954}
955
956//-------------------------------------------------------------------
957void process_raw_files(void){
958 struct fitem *ptr;
959
960 librawop_p=module_rawop_load();
961 if (!librawop_p)
962        return;         //exit if fail
963
964 if ((fselect_marked_count()>1) && librawop_p->raw_merge_start(raw_operation)) {
965   for (ptr=head; ptr; ptr=ptr->next)
966     if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
967       sprintf(selected_file, "%s/%s", current_dir, ptr->name);
968       librawop_p->raw_merge_add_file(selected_file);
969      }
970  librawop_p->raw_merge_end();
971  gui_fselect_read_dir(current_dir);
972 }
973}
974
975static void fselect_subtract_cb(unsigned int btn) {
976    struct fitem *ptr;
977    char *raw_subtract_from;
978    char *raw_subtract_sub;
979    char *raw_subtract_dest;
980    if (btn != MBOX_BTN_YES) return;
981
982        librawop_p=module_rawop_load();
983        if (!librawop_p)
984                return;         //exit if fail
985
986    if(!(raw_subtract_from = malloc(300))) //3x full path
987        return;
988    raw_subtract_sub = raw_subtract_from + 100;
989    raw_subtract_dest = raw_subtract_sub + 100;
990    sprintf(raw_subtract_sub,"%s/%s",current_dir,selected->name);
991    for (ptr=head; ptr; ptr=ptr->next) {
992        if (ptr->marked && ptr->attr != 0xFF &&
993            !(ptr->attr & DOS_ATTR_DIRECTORY) &&
994            ptr->size == hook_raw_size() &&
995            (strcmp(ptr->name,selected->name)) != 0) {
996            sprintf(raw_subtract_from,"%s/%s",current_dir,ptr->name);
997            sprintf(raw_subtract_dest,"%s/%s%s",current_dir,img_prefixes[*conf_sub_batch_prefix],ptr->name+4);
998            strcpy(raw_subtract_dest + strlen(raw_subtract_dest) - 4,img_exts[*conf_sub_batch_ext]);
999            // don't let users attempt to write one of the files being read
1000            if( strcmp(raw_subtract_dest,raw_subtract_from) != 0 && strcmp(raw_subtract_dest,raw_subtract_sub) != 0) {
1001                librawop_p->raw_subtract(raw_subtract_from,raw_subtract_sub,raw_subtract_dest);
1002            }
1003        }
1004    }
1005    free(raw_subtract_from);
1006    gui_fselect_read_dir(current_dir);
1007    gui_fselect_redraw = 2;
1008}
1009
1010
1011#define MAX_SUB_NAMES 6
1012static void setup_batch_subtract(void) {
1013    struct fitem *ptr;
1014    int i;
1015    char *p = buf + sprintf(buf,"%s %s\n",selected->name,lang_str(LANG_FSELECT_SUB_FROM));
1016    for (ptr=head, i=0; ptr; ptr=ptr->next) {
1017        if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY) && ptr->size == hook_raw_size()) {
1018            if ( i < MAX_SUB_NAMES ) {
1019                sprintf(p, "%s\n",ptr->name);
1020                // keep a pointer to the one before the end, so we can stick ...and more on
1021                if (i < MAX_SUB_NAMES - 1) {
1022                    p += strlen(p);
1023                }
1024            }
1025            i++;
1026        }
1027    }
1028    if (i > MAX_SUB_NAMES) {
1029//      "...%d more files"
1030        sprintf(p,lang_str(LANG_FSELECT_SUB_AND_MORE),i - (MAX_SUB_NAMES - 1));
1031    }
1032    gui_mbox_init(LANG_FSELECT_SUBTRACT, (int)buf,
1033                  MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_subtract_cb);
1034}
1035//-------------------------------------------------------------------
1036#if DNG_SUPPORT
1037void process_dng_to_raw_files(void){
1038 struct fitem *ptr;
1039 int i=0;
1040   started();
1041   msleep(100);
1042   finished();
1043
1044 if (fselect_real_marked_count()) {
1045   for (ptr=head; ptr; ptr=ptr->next)
1046     if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
1047       sprintf(selected_file, "%s/%s", current_dir, ptr->name);
1048       gui_browser_progress_show(selected_file, (i++)*100/fselect_real_marked_count()) ;
1049       convert_dng_to_chdk_raw(selected_file);
1050      }
1051    }
1052 else {
1053   sprintf(selected_file, "%s/%s", current_dir, selected->name);
1054   convert_dng_to_chdk_raw(selected_file);
1055 }
1056  gui_fselect_read_dir(current_dir);
1057}
1058#endif
1059
1060//-------------------------------------------------------------------
1061static void fselect_mpopup_cb(unsigned int actn) {
1062    switch (actn) {
1063        case MPOPUP_CUT:
1064            fselect_marked_copy_list();
1065            marked_operation=MARKED_OP_CUT;
1066            break;
1067        case MPOPUP_COPY:
1068            fselect_marked_copy_list();
1069            marked_operation=MARKED_OP_COPY;
1070            break;
1071        case MPOPUP_PASTE:
1072            if (marked_operation == MARKED_OP_CUT) {
1073                sprintf(buf, lang_str(LANG_FSELECT_CUT_TEXT), marked_count, marked_dir);
1074                gui_mbox_init(LANG_FSELECT_CUT_TITLE, (int)buf,
1075                              MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_marked_paste_cb);
1076            }
1077            else {
1078                sprintf(buf, lang_str(LANG_FSELECT_COPY_TEXT), marked_count, marked_dir);
1079                gui_mbox_init(LANG_FSELECT_COPY_TITLE, (int)buf,
1080                              MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_marked_paste_cb);
1081            }
1082            break;
1083        case MPOPUP_DELETE:
1084            sprintf(buf, lang_str(LANG_FSELECT_DELETE_TEXT), fselect_marked_count());
1085            gui_mbox_init(LANG_FSELECT_DELETE_TITLE, (int)buf,
1086                          MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_marked_delete_cb);
1087            break;
1088         case MPOPUP_PURGE:
1089           if (selected->name[0] == 'D' && selected->name[1] == 'C' && selected->name[2] == 'I' && selected->name[3] == 'M') {//If selected item is DCIM folder
1090               sprintf(buf, lang_str(LANG_FSELECT_PURGE_DCIM_TEXT), fselect_marked_count());
1091               gui_mbox_init(LANG_FSELECT_PURGE_TITLE, (int)buf,
1092                         MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_purge_cb);
1093           }
1094           else if (selected->name[3] == 'C') {//If selected item is a Canon folder
1095               sprintf(buf, lang_str(LANG_FSELECT_PURGE_CANON_FOLDER_TEXT), fselect_marked_count());
1096               gui_mbox_init(LANG_FSELECT_PURGE_TITLE, (int)buf,
1097                         MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_purge_cb);
1098           }
1099           else if (selected->name[9] == 'C' || selected->name[9] == 'T' || selected->name[9] == 'W' || selected->name[9] == 'J') {//If seleted item is a file produced by the camera
1100               sprintf(buf, lang_str(LANG_FSELECT_PURGE_LIST_TEXT), fselect_marked_count());
1101               gui_mbox_init(LANG_FSELECT_PURGE_TITLE, (int)buf,
1102                         MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_purge_cb);
1103           }
1104           else {
1105               sprintf(buf, lang_str(LANG_FSELECT_PURGE_DISABLED_TEXT), fselect_marked_count());
1106               gui_mbox_init(LANG_FSELECT_PURGE_TITLE, (int)buf,
1107                         MBOX_TEXT_CENTER|MBOX_BTN_OK|MBOX_DEF_BTN1, fselect_purge_cb);
1108           }
1109           break;
1110        case MPOPUP_SELINV:
1111            fselect_marked_inverse_selection();
1112            break;
1113        case MPOPUP_CANCEL:
1114            break;
1115    case MPOPUP_RAW_AVERAGE:
1116        raw_operation=RAW_OPERATION_AVERAGE;
1117            process_raw_files();
1118            break;
1119        case MPOPUP_RAW_ADD:
1120            raw_operation=RAW_OPERATION_SUM;
1121            process_raw_files();
1122            break;
1123        case MPOPUP_RAW_DEVELOP:
1124            sprintf(buf, "%s/%s", current_dir, selected->name);
1125            gui_mbox_init((int)"", LANG_RAW_DEVELOP_MESSAGE, MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
1126            raw_prepare_develop(buf);
1127        break;
1128        case MPOPUP_CHDK_REPLACE:
1129            gui_mbox_init((int)"Replacing CHDK", (int)"Do you want to replace current CHDK with this file",
1130                          MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_chdk_replace_cb);
1131            break;
1132        case MPOPUP_EDITOR:
1133            gui_mbox_init((int)"Editor", (int)"edit", MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
1134            break;
1135        case MPOPUP_SUBTRACT:
1136        {
1137            setup_batch_subtract();
1138            break;
1139        }
1140#if DNG_SUPPORT
1141    case MPOPUP_DNG_TO_CRW:
1142            process_dng_to_raw_files();
1143            break;
1144#endif
1145    }
1146    gui_fselect_redraw = 2;
1147}
1148
1149//-------------------------------------------------------------------
1150void finalize_fselect()
1151{
1152    gui_fselect_free_data();
1153    gui_fselect_marked_free_data();
1154        module_rawop_unload();
1155}
1156
1157static void exit_fselect(char* file)
1158{
1159        finalize_fselect();
1160
1161    if (set_key_redraw_mode)
1162    {
1163        gui_set_mode(gui_fselect_mode_old);
1164        draw_restore();
1165    }
1166    if (fselect_on_select)
1167    {
1168        fselect_on_select(file);
1169        // if called mode will return control to filemanager - we need to redraw it
1170        gui_fselect_redraw = 2;
1171    }
1172    if (!set_key_redraw_mode)
1173    {
1174        gui_set_mode(gui_fselect_mode_old);
1175        draw_restore();
1176    }
1177}
1178
1179//-------------------------------------------------------------------
1180void gui_fselect_kbd_process() {
1181    int i;
1182   
1183    switch (kbd_get_autoclicked_key() | get_jogdial_direction()) {
1184        case JOGDIAL_LEFT:
1185        case KEY_UP:
1186            if (selected) {
1187                if (kbd_is_key_pressed(KEY_SHOOT_HALF)) fselect_goto_prev(4);
1188                else fselect_goto_prev(1);
1189                gui_fselect_redraw = 1;
1190            }
1191            break;
1192        case KEY_DOWN:
1193        case JOGDIAL_RIGHT:
1194            if (selected) {
1195                if (kbd_is_key_pressed(KEY_SHOOT_HALF)) fselect_goto_next(4);
1196                else fselect_goto_next(1);
1197                gui_fselect_redraw = 1;
1198            }
1199            break;
1200        case KEY_ZOOM_OUT:
1201            if (selected) {
1202                fselect_goto_prev(BODY_LINES-1);
1203                gui_fselect_redraw = 1;
1204            }
1205            break;
1206        case KEY_ZOOM_IN:
1207            if (selected) {
1208                fselect_goto_next(BODY_LINES-1);
1209                gui_fselect_redraw = 1;
1210            }
1211            break;
1212        case KEY_RIGHT:
1213            if (selected) {
1214                fselect_marked_toggle();
1215                fselect_goto_next(1);
1216                gui_fselect_redraw = 1;
1217            }
1218            break;
1219        case KEY_LEFT:
1220            if (selected && selected->attr != 0xFF) {
1221                i=MPOPUP_CUT|MPOPUP_COPY|MPOPUP_SELINV;
1222                if (fselect_marked_count() > 0) {
1223                    i |= MPOPUP_DELETE;
1224                    if ( fselect_marked_count()>1 )
1225                        i |=MPOPUP_RAW_ADD|MPOPUP_RAW_AVERAGE;
1226                    // doesn't make sense to subtract from itself!
1227                    if( selected->marked == 0 && fselect_real_marked_count() > 0)
1228                        i |= MPOPUP_SUBTRACT;
1229                }
1230                if (marked_operation == MARKED_OP_CUT || marked_operation == MARKED_OP_COPY)
1231                    i |= MPOPUP_PASTE;
1232                if (!(selected->attr & DOS_ATTR_DIRECTORY) || !(selected->name[0] == '.' && selected->name[1] == '.' && selected->name[2] == 0) ||//If item is not a folder or UpDir
1233                     (selected->name[0] == 'D' && selected->name[1] == 'C' && selected->name[2] == 'I' && selected->name[3] == 'M') ||//If item is DCIM folder
1234                     (selected->name[3] == 'C'))//If item is a DCIM sub folder
1235                    i |= MPOPUP_PURGE;//Display PURGE RAW function in popup menu
1236                if(selected->size == hook_raw_size())
1237                    i |= MPOPUP_RAW_DEVELOP;
1238#if DNG_SUPPORT
1239                if((fselect_marked_count()>1)||(selected->size > hook_raw_size()))
1240                    i |= MPOPUP_DNG_TO_CRW;
1241#endif
1242
1243                if (selected->name[9] == 'B' && selected->name[10] == 'I' && selected->name[11] == 'N') //If item is DCIM folder
1244                    i |= MPOPUP_CHDK_REPLACE;
1245
1246                module_mpopup_init( popup, i, fselect_mpopup_cb, 0);
1247            }
1248            break;
1249        case KEY_SET:
1250            if (selected && selected->attr != 0xFF && gui_fselect_redraw==0) {
1251                if (selected->attr & DOS_ATTR_DIRECTORY) {
1252                    i=strlen(current_dir);
1253                    if (selected->name[0]=='.' && selected->name[1]=='.' && selected->name[2]==0) {
1254                        while (current_dir[--i] != '/');
1255                        current_dir[i]=0;
1256                    } else {
1257                        sprintf(current_dir+i, "/%s", selected->name);
1258                    }
1259                    gui_fselect_read_dir(current_dir);
1260                    gui_fselect_redraw = 1;
1261                } else  {
1262                    sprintf(selected_file, "%s/%s", current_dir, selected->name);
1263                                       
1264                                        char *ext = strchr(selected->name,'.');
1265                    if ( ext && (ext[1]|0x20)=='f' && (ext[2]|0x20)=='l' && (ext[3]|0x20)=='t') {
1266                                        if (!fselect_on_select) {
1267                                exit_fselect(0);
1268                                                module_run(selected_file, 0, 0,0, UNLOAD_IF_ERR);
1269
1270                                                        break;
1271                                                }
1272                                        }
1273
1274                    exit_fselect(selected_file);
1275                                        module_async_unload(module_idx);
1276                }
1277            }
1278            break;
1279      #if CAM_HAS_ERASE_BUTTON
1280        case KEY_ERASE:
1281      #else
1282        case KEY_DISPLAY:
1283      #endif
1284            if (selected && selected->attr != 0xFF) {
1285                if (selected->attr & DOS_ATTR_DIRECTORY) {
1286                    if (selected->name[0]!='.' || selected->name[1]!='.' || selected->name[2]!=0)
1287                        gui_mbox_init(LANG_BROWSER_ERASE_DIR_TITLE, LANG_BROWSER_ERASE_DIR_TEXT,
1288                                      MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_delete_folder_cb);
1289                } else {
1290                    gui_mbox_init(LANG_BROWSER_DELETE_FILE_TITLE, LANG_BROWSER_DELETE_FILE_TEXT,
1291                                  MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_delete_file_cb);
1292                }
1293            }
1294            break;
1295        case KEY_MENU:
1296            // just free resource. callback called with NULL ptr
1297            exit_fselect(0);
1298                        module_async_unload(module_idx);
1299            break;
1300    }
1301}
1302
1303
1304
1305// =========  MODULE INIT =================
1306#include "module_load.h"
1307int module_idx=-1;
1308
1309/***************** BEGIN OF AUXILARY PART *********************
1310  ATTENTION: DO NOT REMOVE OR CHANGE SIGNATURES IN THIS SECTION
1311 **************************************************************/
1312
1313void* MODULE_EXPORT_LIST[] = {
1314        /* 0 */ (void*)EXPORTLIST_MAGIC_NUMBER,
1315        /* 1 */ (void*)0
1316                };
1317
1318
1319//---------------------------------------------------------
1320// PURPOSE:   Bind module symbols with chdk.
1321//              Required function
1322// PARAMETERS: pointer to chdk list of export
1323// RETURN VALUE: 1 error, 0 ok
1324//---------------------------------------------------------
1325int _module_loader( void** chdk_export_list )
1326{
1327  if ( (unsigned int)chdk_export_list[0] != EXPORTLIST_MAGIC_NUMBER )
1328     return 1;
1329
1330  tConfigVal configVal;
1331  CONF_BIND_INT(209, conf_sub_batch_prefix);
1332  CONF_BIND_INT(210, conf_sub_batch_ext);
1333
1334  // Try to bind to generic gui mode alias
1335  if (!gui_bind_mode( GUI_MODE_FSELECT, &GUI_MODE_FSELECT_MODULE))
1336        return 1;
1337
1338  return 0;
1339}
1340
1341
1342
1343//---------------------------------------------------------
1344// PURPOSE: Finalize module operations (close allocs, etc)
1345// RETURN VALUE: 0-ok, 1-fail
1346//---------------------------------------------------------
1347int _module_unloader()
1348{
1349        finalize_fselect();
1350
1351        //sanity clean to prevent accidentaly assign/restore guimode to unloaded module
1352        GUI_MODE_FSELECT_MODULE.magicnum = 0;
1353
1354    // Unbind generic alias
1355        gui_bind_mode( GUI_MODE_FSELECT, 0);
1356
1357    return 0;
1358}
1359
1360
1361//---------------------------------------------------------
1362// PURPOSE: Default action for simple modules (direct run)
1363// NOTE: Please comment this function if no default action and this library module
1364//---------------------------------------------------------
1365int _module_run(int moduleidx, int argn, int* arguments)
1366{
1367  module_idx=moduleidx;
1368
1369  if ( argn!=0 && argn!=5 ) {
1370        module_async_unload(moduleidx);
1371    return 1;
1372  }
1373
1374  // Autounloading is unsafe because it should exists to catch finalization of mpopup
1375  module_set_flags(module_idx, MODULE_FLAG_DISABLE_AUTOUNLOAD);
1376
1377  if ( argn == 5 ) {
1378  gui_fselect_init( arguments[0], (const char*) arguments[1], (const char*) arguments[2], (void*)arguments[3]);
1379  gui_fselect_set_key_redraw(arguments[4]);
1380  }
1381  else
1382    gui_fselect_init(LANG_STR_FILE_BROWSER, "A", "A", NULL);
1383
1384  return 0;
1385}
1386
1387
1388/******************** Module Information structure ******************/
1389
1390struct ModuleInfo _module_info = {      MODULEINFO_V1_MAGICNUM,
1391                                                                        sizeof(struct ModuleInfo),
1392
1393                                                                        ANY_CHDK_BRANCH, 0,                     // Requirements of CHDK version
1394                                                                        ANY_PLATFORM_ALLOWED,           // Specify platform dependency
1395                                                                        0,                                                      // flag
1396                                                                        -LANG_MENU_MISC_FILE_BROWSER,   // Module name
1397                                                                        1, 0,                                           // Module version
1398                                                                        0
1399                                                                 };
1400
1401/*************** END OF AUXILARY PART *******************/
Note: See TracBrowser for help on using the repository browser.