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

Revision 1511, 53.1 KB checked in by philmoz, 2 years ago (diff)

Merge recent changes from main trunk to reyalp-flt branch.

  • 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    STD_DIR           *d;
211    struct STD_dirent *de;
212    static struct STD_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 = safe_opendir("A/");
220    else
221        d = safe_opendir(dir);
222/* //remove for platf independedncy. looks like sequence above is safe
223#else
224    d = safe_opendir(dir);
225#endif
226*/
227    if (d) {
228        de = safe_readdir(d);
229        while (de) {
230            if (de->d_name[0] != 0xE5 /* deleted entry */ && (de->d_name[0]!='.' || de->d_name[1]!=0)) {
231                *ptr = malloc(sizeof(struct fitem));
232                if (*ptr) {
233                    (*ptr)->n = count;
234                    (*ptr)->name = malloc(strlen(de->d_name)+1);
235                    if ((*ptr)->name)
236                        strcpy((*ptr)->name, de->d_name);
237                    sprintf(buf, "%s/%s", dir, de->d_name);
238                    if (safe_stat(buf, &st)==0) {
239                        (*ptr)->attr=st.st_attrib;
240                        (*ptr)->size=st.st_size;
241                        (*ptr)->mtime=st.st_mtime;
242                    } else {
243                        (*ptr)->attr=(de->d_name[0]=='.' && de->d_name[1]=='.' && de->d_name[2]==0)?DOS_ATTR_DIRECTORY:0xFF;
244                        (*ptr)->size=(*ptr)->mtime=0;
245                    }
246                    (*ptr)->marked=0;
247                    (*ptr)->prev=prev;
248                    prev=*ptr;
249                    ptr = &((*ptr)->next);
250                    ++count;
251                }   
252            }
253            de = safe_readdir(d);
254        }
255        safe_closedir(d);
256    }
257    *ptr=NULL;
258   
259    if (count) {
260        // sort
261        ptr=malloc(count*sizeof(struct fitem*));
262        if (ptr) {
263            prev=head;
264            count=0;
265            while (prev) {
266                ptr[count++]=prev;
267                prev=prev->next;
268            }
269           
270            qsort(ptr, count, sizeof(struct fitem*), fselect_sort_nothumb);
271           
272            for (i=0; i<count-1; ++i) {
273                ptr[i]->n=i;
274                ptr[i]->next=ptr[i+1];
275                ptr[i+1]->prev=ptr[i];
276            }
277            ptr[0]->prev=ptr[count-1]->next=NULL;
278            ptr[count-1]->n=count-1;
279            head=ptr[0];
280
281            free(ptr);
282        }
283    }
284
285    top = selected = head;
286}
287
288//-------------------------------------------------------------------
289// Set flag to control how the erase/redraw happens when the set key
290// is pressed.
291// 0 - screen erase & mode restore done after call to fselect_on_select
292// 1 - screen erase & mode restore done before call to fselect_on_select
293// Needed for text reader to work correctly and to stop intermittent
294// crashes when selecting fonts (hack - whole gui/kbd system needs an overhaul).
295void gui_fselect_set_key_redraw(int n)
296{
297    set_key_redraw_mode = n;
298}
299
300//-------------------------------------------------------------------
301// Attempt to set startup directory (and file) based on input 'dir'
302// Note: 'dir' may be a directory name or a file name (including path)
303// Returns 1 if valid directory/file found, 0 otherwise
304int gui_fselect_find_start_dir(const char* dir)
305{
306    selected_file[0] = 0;
307    strcpy(current_dir, dir);
308
309    // Make sure there is something left to check
310    while (strlen(current_dir) > 0)
311    {
312        struct STD_stat st;
313        // check if input 'dir' exists
314        if (safe_stat(current_dir,&st) == 0)     
315        {
316            // exists - check if it is a directory or file
317            if (st.st_attrib & DOS_ATTR_DIRECTORY)
318            {
319                // Directory and exists so all good
320                return 1;
321            }
322            else
323            {
324                // 'dir' is a file, extract filename to 'selected_file' and remove from 'current_dir'
325                char *p = strrchr(current_dir,'/');
326                strcpy(selected_file, p+1);
327                *p = 0;
328                return 1;
329            }
330        }
331        else
332        {
333            // could not find 'dir' - try one level up
334            char *p = strrchr(current_dir,'/');
335            if (p) *p = 0;
336            else return 0;
337        }
338    }
339
340    return 0;
341}
342
343//-------------------------------------------------------------------
344void gui_fselect_init(int title, const char* prev_dir, const char* default_dir, void (*on_select)(const char *fn))
345{
346    int i;
347   
348    int chars_width = NAME_FONT_SIZE + SIZE_FONT_SIZE + TIME_FONT_SIZE;
349    main_w = SPACING/*N*/+SPACING+TAB_DIVIDER+SPACING/*S*/+SPACING+TAB_DIVIDER+SPACING/*T*/+SPACING+SCROLLBAR+chars_width;
350    main_h = HEAD_FONT_LINES + TAB_DIVIDER + BODY_FONT_LINES + TAB_DIVIDER + FOOT_FONT_LINES;
351    main_x = (screen_width - main_w) >> 1;
352    main_y = (screen_height - main_h) >> 1;
353   
354    head_x = body_x = foot_x = main_x;
355    head_w = body_w = foot_w = main_w;   
356    head_y = main_y;
357    head_h = HEAD_FONT_LINES;   
358    body_y = head_y + head_h + TAB_DIVIDER;
359    body_h = BODY_FONT_LINES;
360    foot_y = body_y + body_h + TAB_DIVIDER;
361    foot_h = FOOT_FONT_LINES;
362   
363    fselect_title = lang_str(title);
364
365    // Try and set start directory, and optionally selected file, from inputs
366    if (!gui_fselect_find_start_dir(prev_dir))
367        if (!gui_fselect_find_start_dir(default_dir))
368            gui_fselect_find_start_dir("A");
369
370    max_dir_len = NAME_SIZE + SIZE_SIZE + SPACING;
371    gui_fselect_read_dir(current_dir);
372    top = selected = head;
373
374    // Find selected file if it exists in list
375    if (selected_file[0])
376    {
377        struct fitem *p = head;
378        while (p)
379        {
380            if (strcmp(p->name,selected_file) == 0)
381            {
382                break;
383            }
384            p = p->next;
385            fselect_goto_next(1);
386        }
387        if (!p) selected_file[0] = 0;
388    }
389
390    fselect_on_select = on_select;
391    marked_operation = MARKED_OP_NONE;
392    gui_fselect_mode_old = gui_get_mode();
393    gui_fselect_redraw = 2;
394    gui_set_mode((unsigned int)&GUI_MODE_FSELECT_MODULE);
395    gui_fselect_set_key_redraw(0);
396}
397
398//-------------------------------------------------------------------
399char* gui_fselect_result() {
400    if (selected_file[0])
401        return selected_file;
402    else
403        return NULL;
404}
405
406//-------------------------------------------------------------------
407void gui_fselect_draw_initial() {
408    int title_font_size;
409    int i;
410
411    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
412    title_font_size = strlen(fselect_title) * FONT_WIDTH;
413    draw_string(head_x+((head_w-title_font_size)>>1), head_y, fselect_title, MAKE_COLOR(COLOR_BLACK, COLOR_WHITE)); //title text
414   
415    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
416    draw_line(body_x, body_y-1, body_x+body_w-1, body_y-1, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE)); //border head-body
417    draw_line(foot_x, foot_y-1, foot_x+foot_w-1, foot_y-1, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE)); //border body-foot   
418}
419
420//-------------------------------------------------------------------
421void gui_fselect_draw(int enforce_redraw) {
422    int i, j, off_name_x, off_size_x, off_time_x, off_body_x, off_body_y;
423    struct fitem  *ptr;
424    char buf[100];
425    struct tm *time;
426    unsigned long sum_size;
427    color cl_markered = ((mode_get()&MODE_MASK) == MODE_REC)?COLOR_YELLOW:0x66;
428    color cl_marked, cl_selected;
429
430        if ( enforce_redraw )
431                gui_fselect_redraw = 2;
432
433    if (gui_fselect_redraw) {
434        if (gui_fselect_redraw == 2)
435            gui_fselect_draw_initial();
436
437        off_body_y = 0;
438        off_name_x = body_x+SPACING;
439        off_size_x = off_name_x+NAME_FONT_SIZE+SPACING+TAB_DIVIDER+SPACING;
440        off_time_x = off_size_x+SIZE_FONT_SIZE+SPACING+TAB_DIVIDER+SPACING;
441        off_body_x = off_time_x+TIME_FONT_SIZE+SPACING;
442
443        sum_size = 0;
444        for (i=0, ptr=top; i<BODY_LINES && ptr; ++i, ptr=ptr->next) {
445       
446            cl_marked = MAKE_COLOR((ptr==selected)?COLOR_RED:COLOR_GREY, (ptr->marked)?cl_markered:COLOR_WHITE);
447            cl_selected = (ptr==selected)?MAKE_COLOR(COLOR_RED, COLOR_RED):MAKE_COLOR(COLOR_GREY, COLOR_GREY);
448       
449            // print name
450            for (j=0; j<NAME_SIZE && ptr->name[j]; ++j)
451                buf[j] = ptr->name[j];
452               
453            if (j==NAME_SIZE && ptr->name[j]) buf[NAME_SIZE-1] = '~'; // too long name
454           
455            if (ptr->attr & DOS_ATTR_DIRECTORY && ptr->attr != 0xFF) { //?
456                if (j<NAME_SIZE) {
457                    buf[j++]='/';
458                } else {
459                    buf[NAME_SIZE-2]='~';
460                    buf[NAME_SIZE-1]='/';
461                }
462            }
463            for (; j<NAME_SIZE && (buf[j++]=' ');); //fill upto NAME_SIZE
464            buf[NAME_SIZE] = 0; // eos
465           
466            off_body_y = body_y+(i*FONT_HEIGHT);
467            draw_filled_rect(body_x, off_body_y, off_name_x-1, off_body_y+FONT_HEIGHT-1, cl_selected);
468            draw_string(off_name_x, off_body_y, buf, cl_marked);
469            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);
470           
471            // print size or <Dir>
472            if (ptr->attr & DOS_ATTR_DIRECTORY) {
473                if (ptr->attr == 0xFF) {
474                    sprintf(buf, "  ???  ");
475                } else if (ptr->name[0] == '.' && ptr->name[1] == '.' && ptr->name[2] == 0) {
476                    sprintf(buf, "<UpDir>");
477                } else {
478                    sprintf(buf, "< Dir >");
479                }
480            } else {
481                if (ptr->size < 1024)
482                    sprintf(buf, "%5d b", ptr->size); // " 1023 b"
483                else if (ptr->size < 1024*1024)
484                    sprintf(buf, "%3ld,%1d k", ptr->size/1024, (ptr->size%1024*10)/1024); // "999,9 k"
485                else if (ptr->size < 1024*1024*1024)
486                    sprintf(buf, "%3ld,%ld M", ptr->size/(1024*1024), (ptr->size%(1024*1024)*10)/(1024*1024) ); // "999,9 M"
487                else
488                    sprintf(buf, "%31d,%ld G", ptr->size/(1024*1024*1024), (ptr->size%(1024*1024*1024)*10)/(1024*1024*1024)); // "999.9 G"
489                   
490                if (ptr->marked)
491                  sum_size += ptr->size;
492            }
493            buf[SIZE_SIZE] = 0;
494            //tab divider
495            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);
496            draw_filled_rect(off_size_x-SPACING, off_body_y, off_size_x-1, off_body_y+FONT_HEIGHT-1, cl_selected);           
497            draw_string(off_size_x, off_body_y, buf, cl_marked);
498            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);           
499           
500            // print modification time
501            if (ptr->mtime) {
502                time = localtime(&(ptr->mtime));
503                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);
504            } else {
505                sprintf(buf, "%14s", "");
506            }
507            buf[TIME_SIZE] = 0;
508            //tab divider
509            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);
510            draw_filled_rect(off_time_x-SPACING, off_body_y, off_time_x-1, off_body_y+FONT_HEIGHT-1, cl_selected);
511            draw_string(off_time_x, off_body_y, buf, cl_marked);           
512            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);
513        }
514
515        //fill the rest of body
516        off_body_y += FONT_HEIGHT;
517        if (i>0 && i<BODY_LINES) {
518            draw_filled_rect(body_x, off_body_y, body_x+body_w-1, body_y+body_h-1, MAKE_COLOR(COLOR_GREY, COLOR_GREY));
519        }
520       
521       // scrollbar
522        draw_filled_rect(off_body_x, body_y, off_body_x+SCROLLBAR-1, body_y+body_h-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK));
523        if (count>BODY_LINES) {
524            i = BODY_FONT_LINES - 1;
525            j = i*BODY_LINES/count;
526            if (j<20) j=20;
527            i = (i-j)*selected->n/(count-1);
528            draw_filled_rect(off_body_x, body_y+i, off_body_x+SCROLLBAR-2, body_y+i+j, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE));
529        }
530
531        //footer
532        i = strlen(current_dir);
533        if (i > max_dir_len) {
534          strncpy(buf, current_dir+i-max_dir_len, max_dir_len);
535          buf[0] = '.';
536          buf[1] = '.';         
537        } else {
538          strcpy(buf, current_dir);         
539        }
540        buf[max_dir_len] = 0;
541        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       
542        draw_string(off_name_x, foot_y, buf, MAKE_COLOR(COLOR_GREY, COLOR_WHITE)); //current dir
543       
544        if (sum_size) {
545          sprintf(buf, "%d b", sum_size); //selected size
546        } else {
547          unsigned int fr, tot;
548          fr = GetFreeCardSpaceKb(); tot = GetTotalCardSpaceKb();
549          if (fr < 1024*1024)
550            sprintf(buf, "%dM (%d%%)", fr/1024, tot? fr*100/tot: 0);
551          else
552            sprintf(buf, "%d.%dG (%d%%)", fr/(1024*1024), (fr%(10240))/100, tot? fr*100/tot: 0);
553        }
554        draw_string(foot_x+foot_w-strlen(buf)*FONT_WIDTH-BORDER, foot_y, buf, MAKE_COLOR(COLOR_GREY, COLOR_WHITE)); // free space
555        gui_fselect_redraw = 0;
556    }
557}
558
559//-------------------------------------------------------------------
560static void fselect_delete_file_cb(unsigned int btn) {
561    if (btn==MBOX_BTN_YES) {
562        started();
563        sprintf(selected_file, "%s/%s", current_dir, selected->name);
564        remove(selected_file);
565        finished();
566        selected_file[0]=0;
567        gui_fselect_read_dir(current_dir);
568    }
569    gui_fselect_redraw = 2;
570}
571
572static void fselect_purge_cb(unsigned int btn) {
573
574   STD_DIR             *d,  *d2,  *d3,  *d4;
575   struct STD_dirent   *de, *de2, *de3, *de4;
576   struct fitem    *ptr, *ptr2;
577   char            sub_dir[20], sub_dir_search[20];
578   char            selected_item[256];
579   int             i, found=0;
580
581   if (btn==MBOX_BTN_YES) {
582       //If selected folder is DCIM (this is to purge all RAW files in any Canon folder)
583       if (selected->name[0] == 'D' && selected->name[1] == 'C' && selected->name[2] == 'I' && selected->name[3] == 'M') {
584           sprintf(current_dir+strlen(current_dir), "/%s", selected->name);
585           d=safe_opendir(current_dir);
586           while ((de=safe_readdir(d)) != NULL) {//Loop to find all Canon folders
587               if (de->d_name[0] != '.' && de->d_name[1] != '.') {//If item is not UpDir
588                   sprintf(sub_dir, "%s/%s", current_dir, de->d_name);
589                   d2=safe_opendir(sub_dir);
590                   while ((de2=safe_readdir(d2)) != NULL) {//Loop to find all the RAW files inside a Canon folder
591                       if (de2->d_name[0] == 'C' || de2->d_name[9] == 'C') {//If file is RAW (Either CRW/CR2 prefix or file extension)
592                           d3=safe_opendir(current_dir);
593                           while ((de3=safe_readdir(d3)) != NULL) {//Loop to find all Canon folders
594                               if (de3->d_name[0] != '.' && de3->d_name[1] != '.') {//If item is not UpDir
595                                   sprintf(sub_dir_search, "%s/%s", current_dir, de3->d_name);
596                                   d4=safe_opendir(sub_dir_search);
597                                   while ((de4=safe_readdir(d4)) != NULL) {//Loop to find a corresponding JPG file inside a Canon folder
598                                       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
599                                           de2->d_name[6] == de4->d_name[6] && de2->d_name[7] == de4->d_name[7] &&
600                                           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
601                                           started();
602                                           found=1;//A JPG file with the same Canon number was found
603                                       }                                 
604                                   }
605                                   safe_closedir(d4);                 
606                               } 
607                           }
608                           safe_closedir(d3);
609                           //If no JPG found, delete RAW file
610                           if (found == 0) {
611                               sprintf(selected_item, "%s/%s", sub_dir, de2->d_name);
612                               remove(selected_item);
613                               finished();
614                           }
615                           else {
616                               found=0;
617                               finished();
618                           }                             
619                       }
620                   }
621                   safe_closedir(d2);
622               }
623           }
624           safe_closedir(d);
625           i=strlen(current_dir);
626           while (current_dir[--i] != '/');
627           current_dir[i]=0;
628       }
629       //If item is a Canon folder (this is to purge all RAW files inside a single Canon folder)
630       else if (selected->name[3] == 'C') {
631           sprintf(current_dir+strlen(current_dir), "/%s", selected->name);
632           d=safe_opendir(current_dir);
633           while ((de=safe_readdir(d)) != NULL) {//Loop to find all the RAW files inside the Canon folder
634               if (de->d_name[0] == 'C' || de->d_name[9] == 'C') {//If file is RAW (Either CRW/CR2 prefix or file extension)
635                   d2=safe_opendir(current_dir);
636                   while ((de2=safe_readdir(d2)) != NULL) {//Loop to find a corresponding JPG file inside the Canon folder
637                       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
638                           de->d_name[6] == de2->d_name[6] && de->d_name[7] == de2->d_name[7] &&
639                           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
640                           started();
641                           found=1;//A JPG file with the same Canon number was found
642                       }                                 
643                   }
644                   safe_closedir(d2);
645                   //If no JPG found, delete RAW file               
646                   if (found == 0) {
647                       sprintf(selected_item, "%s/%s", current_dir, de->d_name);
648                       remove(selected_item);
649                       finished();
650                   }
651                   else {
652                       found=0;
653                       finished();
654                   }
655               }
656           }
657           safe_closedir(d);
658           i=strlen(current_dir);
659           while (current_dir[--i] != '/');
660           current_dir[i]=0;
661       }
662       else {
663           //If inside a Canon folder (files list)
664           for (ptr=head; ptr; ptr=ptr->next) {//Loop to find all the RAW files in the list
665               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
666                   for (ptr2=head; ptr2; ptr2=ptr2->next) {//Loop to find a corresponding JPG file in the list
667                       if (ptr->name[4] == ptr2->name[4] && ptr->name[5] == ptr2->name[5] &&//If the four digits of the Canon number are the same
668                           ptr->name[6] == ptr2->name[6] && ptr->name[7] == ptr2->name[7] &&
669                           ptr2->name[9] == 'J' && !(ptr2->name[0] == 'C' || ptr2->name[9] == 'C')) {//If file is JPG and is not CRW/CR2
670                           started();
671                           found=1;
672                       }
673                   }
674                   //If no JPG found, delete RAW file           
675                   if (found == 0) {
676                       sprintf(selected_file, "%s/%s", current_dir, ptr->name);
677                       remove(selected_file);
678                       finished();
679                   }
680                   else {
681                       found=0;
682                       finished();
683                   }
684               }
685           }
686       }
687       gui_fselect_read_dir(current_dir);
688   }
689   gui_fselect_redraw = 2;
690}
691
692
693//-------------------------------------------------------------------
694static void fselect_delete_folder_cb(unsigned int btn) {
695    STD_DIR           *d;
696    struct STD_dirent *de;
697    int           i;
698
699    if (btn==MBOX_BTN_YES) {
700        sprintf(current_dir+strlen(current_dir), "/%s", selected->name);
701        d = safe_opendir(current_dir);
702        if (d) {
703            de = safe_readdir(d);
704            while (de) {
705                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))) {
706                    started();
707                    sprintf(selected_file, "%s/%s", current_dir, de->d_name);
708                    remove(selected_file);
709                    finished();
710                }
711                de = safe_readdir(d);
712            }
713            safe_closedir(d);
714        }
715        started();
716        remove(current_dir);
717        finished();
718        i=strlen(current_dir);
719        while (current_dir[--i] != '/');
720        current_dir[i]=0;
721        selected_file[0]=0;
722        gui_fselect_read_dir(current_dir);
723    }
724    gui_fselect_redraw = 2;
725}
726
727//-------------------------------------------------------------------
728static void fselect_marked_toggle() {
729    if (selected && selected->attr != 0xFF && !(selected->attr & DOS_ATTR_DIRECTORY)) {
730        selected->marked = !selected->marked;
731    }
732}
733
734//-------------------------------------------------------------------
735static void gui_fselect_marked_free_data() {
736    struct fitem  *ptr = marked_head, *prev;
737
738    while (ptr) {
739        if (ptr->name)
740            free(ptr->name);
741        prev=ptr;
742        ptr=ptr->next;
743        free(prev);
744    }
745    marked_head=NULL;
746    marked_count=0;
747    marked_operation = MARKED_OP_NONE;
748}
749
750//-------------------------------------------------------------------
751static void fselect_marked_copy_list() {
752    gui_fselect_marked_free_data();
753
754    struct fitem  *ptr, **marked_ptr=&marked_head, *prev = NULL;
755
756    for (ptr=head; ptr; ptr=ptr->next) {
757        if (ptr->marked) {
758            *marked_ptr = malloc(sizeof(struct fitem));
759            if (*marked_ptr) {
760                (*marked_ptr)->n = ptr->n;
761                (*marked_ptr)->name = malloc(strlen(ptr->name)+1);
762                if ((*marked_ptr)->name)
763                   strcpy((*marked_ptr)->name, ptr->name);
764                (*marked_ptr)->attr=ptr->attr;
765                (*marked_ptr)->size=ptr->size;
766                (*marked_ptr)->mtime=ptr->mtime;
767                (*marked_ptr)->marked=ptr->marked;
768                (*marked_ptr)->prev=prev;
769                prev=*marked_ptr;
770                marked_ptr = &((*marked_ptr)->next);
771                *marked_ptr=NULL;
772                ++marked_count;
773            }
774        }
775    }
776
777    if (!marked_count)
778        if (selected && selected->attr != 0xFF)
779            if (!(selected->attr & DOS_ATTR_DIRECTORY)) {
780                *marked_ptr = malloc(sizeof(struct fitem));
781                if (*marked_ptr) {
782                    (*marked_ptr)->n = selected->n;
783                    (*marked_ptr)->name = malloc(strlen(selected->name)+1);
784                    if ((*marked_ptr)->name)
785                        strcpy((*marked_ptr)->name, selected->name);
786                    (*marked_ptr)->attr=selected->attr;
787                    (*marked_ptr)->size=selected->size;
788                    (*marked_ptr)->mtime=selected->mtime;
789                    (*marked_ptr)->marked=!(0);
790                    (*marked_ptr)->prev=prev;
791                    prev=*marked_ptr;
792                    marked_ptr = &((*marked_ptr)->next);
793                    *marked_ptr=NULL;
794                    ++marked_count;
795                }
796            }
797
798    sprintf(marked_dir, "%s", current_dir);
799}
800
801//-------------------------------------------------------------------
802static void fselect_marked_paste_cb(unsigned int btn) {
803    struct fitem  *ptr;
804    int ss, sd = 0, fsrc, fdst, i=0;
805    register int *buf;
806    unsigned char fend;
807    static struct utimbuf t;
808
809    if (btn != MBOX_BTN_YES) return;
810
811    if (strcmp(marked_dir, current_dir) != 0) {
812        buf = umalloc(MARKED_BUF_SIZE);
813        if (buf) {
814            for (ptr=marked_head; ptr; ptr=ptr->next) {
815                if (ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
816                    started();
817                    ++i;
818                    if (marked_count)
819                        gui_browser_progress_show(lang_str(LANG_FSELECT_PROGRESS_TITLE),i*100/marked_count);
820                    sprintf(selected_file, "%s/%s", marked_dir, ptr->name);
821                    fsrc = safe_open(selected_file, O_RDONLY, 0777);
822                    if (fsrc>=0) {
823                        sprintf(selected_file, "%s/%s", current_dir, ptr->name);
824                        // trying to open for read to check if file exists
825                        fdst = safe_open(selected_file, O_RDONLY, 0777);
826                        if (fdst<0) {
827                            fdst = safe_open(selected_file, O_WRONLY|STD_O_CREAT, 0777);
828                            if (fdst>=0) {
829                                do {
830                                    ss=read(fsrc, buf, MARKED_BUF_SIZE);
831                                    if (ss>0) sd=write(fdst, buf, ss);
832                                } while (ss>0 && ss==sd);
833                                close(fdst);
834                                t.actime = t.modtime = ptr->mtime;
835                                utime(selected_file, &t);
836                                if (marked_operation == MARKED_OP_CUT && ss==0) {
837                                    close(fsrc); fsrc = -1;
838                                    sprintf(selected_file, "%s/%s", marked_dir, ptr->name);
839                                    remove(selected_file);
840                                }
841                            }
842                        } else {
843                            close(fdst);
844                        }
845                        if (fsrc>=0) close(fsrc);
846                    }
847                    finished();
848                    selected_file[0]=0;
849                }
850            }
851            ufree(buf);
852            if (marked_operation == MARKED_OP_CUT) {
853                gui_fselect_marked_free_data();
854            }
855        }
856        gui_fselect_read_dir(current_dir);
857    }
858    gui_fselect_redraw = 2;
859}
860
861//-------------------------------------------------------------------
862static inline unsigned int fselect_real_marked_count() {
863    struct fitem  *ptr;
864    register unsigned int cnt=0;
865
866    for (ptr=head; ptr; ptr=ptr->next) {
867        if (ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY) && ptr->marked)
868            ++cnt;
869    }
870    return cnt;
871}
872//-------------------------------------------------------------------
873static unsigned int fselect_marked_count() {
874    struct fitem  *ptr;
875    register unsigned int cnt=fselect_real_marked_count();
876
877    if (!cnt) {
878        if (selected && selected->attr != 0xFF && !(selected->attr & DOS_ATTR_DIRECTORY))
879            ++cnt;
880    }
881
882    return cnt;
883}
884
885//-------------------------------------------------------------------
886static void fselect_marked_delete_cb(unsigned int btn) {
887    struct fitem  *ptr;
888    unsigned int del_cnt=0, cnt;
889
890    if (btn != MBOX_BTN_YES) return;
891
892    cnt=fselect_marked_count();
893    for (ptr=head; ptr; ptr=ptr->next)
894        if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
895            started();
896            ++del_cnt;
897            if (cnt)
898                gui_browser_progress_show(lang_str(LANG_FSELECT_PROGRESS_TITLE),del_cnt*100/cnt);
899            sprintf(selected_file, "%s/%s", current_dir, ptr->name);
900            remove(selected_file);
901            finished();
902            selected_file[0]=0;
903        }
904
905    if (del_cnt == 0 && selected) {
906        started();
907        sprintf(selected_file, "%s/%s", current_dir, selected->name);
908        remove(selected_file);
909        finished();
910        selected_file[0]=0;
911    }
912    gui_fselect_read_dir(current_dir);
913    gui_fselect_redraw = 2;
914}
915
916//-------------------------------------------------------------------
917static void fselect_chdk_replace_cb(unsigned int btn) {
918    int ss, sd = 0, fsrc, fdst, i=0;
919    register int *buf;
920    unsigned char fend;
921    static struct utimbuf t;
922
923    if (btn != MBOX_BTN_YES) return;
924
925    buf = umalloc(MARKED_BUF_SIZE);
926    sprintf(selected_file, "%s/%s", current_dir, selected->name);
927    fsrc = safe_open(selected_file, O_RDONLY, 0777);
928    if (fsrc>=0) {
929            strcpy(selected_file,"A/DISKBOOT.BIN");
930            fdst = safe_open(selected_file, O_WRONLY|STD_O_CREAT|STD_O_TRUNC, 0777);
931            if (fdst>=0) {
932                do {
933                    ss=read(fsrc, buf, MARKED_BUF_SIZE);
934                    if (ss>0) sd=write(fdst, buf, ss);
935                } while (ss>0 && ss==sd);
936                close(fdst);
937                t.actime = t.modtime = selected->mtime;
938                utime(selected_file, &t);
939                //shutdown();
940                        gui_browser_progress_show("Please reboot",100);
941            }
942        if (fsrc>=0) close(fsrc);
943    }
944    ufree(buf);
945}
946
947//-------------------------------------------------------------------
948static void fselect_marked_inverse_selection() {
949    struct fitem  *ptr;
950   
951    for (ptr=head; ptr; ptr=ptr->next)
952        if (ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY))
953            ptr->marked = !ptr->marked;
954   
955    gui_fselect_redraw = 2;
956}
957
958//-------------------------------------------------------------------
959void process_raw_files(void){
960 struct fitem *ptr;
961
962 librawop_p=module_rawop_load();
963 if (!librawop_p)
964        return;         //exit if fail
965
966 if ((fselect_marked_count()>1) && librawop_p->raw_merge_start(raw_operation)) {
967   for (ptr=head; ptr; ptr=ptr->next)
968     if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
969       sprintf(selected_file, "%s/%s", current_dir, ptr->name);
970       librawop_p->raw_merge_add_file(selected_file);
971      }
972  librawop_p->raw_merge_end();
973  gui_fselect_read_dir(current_dir);
974 }
975}
976
977static void fselect_subtract_cb(unsigned int btn) {
978    struct fitem *ptr;
979    char *raw_subtract_from;
980    char *raw_subtract_sub;
981    char *raw_subtract_dest;
982    if (btn != MBOX_BTN_YES) return;
983
984        librawop_p=module_rawop_load();
985        if (!librawop_p)
986                return;         //exit if fail
987
988    if(!(raw_subtract_from = malloc(300))) //3x full path
989        return;
990    raw_subtract_sub = raw_subtract_from + 100;
991    raw_subtract_dest = raw_subtract_sub + 100;
992    sprintf(raw_subtract_sub,"%s/%s",current_dir,selected->name);
993    for (ptr=head; ptr; ptr=ptr->next) {
994        if (ptr->marked && ptr->attr != 0xFF &&
995            !(ptr->attr & DOS_ATTR_DIRECTORY) &&
996            ptr->size == hook_raw_size() &&
997            (strcmp(ptr->name,selected->name)) != 0) {
998            sprintf(raw_subtract_from,"%s/%s",current_dir,ptr->name);
999            sprintf(raw_subtract_dest,"%s/%s%s",current_dir,img_prefixes[*conf_sub_batch_prefix],ptr->name+4);
1000            strcpy(raw_subtract_dest + strlen(raw_subtract_dest) - 4,img_exts[*conf_sub_batch_ext]);
1001            // don't let users attempt to write one of the files being read
1002            if( strcmp(raw_subtract_dest,raw_subtract_from) != 0 && strcmp(raw_subtract_dest,raw_subtract_sub) != 0) {
1003                librawop_p->raw_subtract(raw_subtract_from,raw_subtract_sub,raw_subtract_dest);
1004            }
1005        }
1006    }
1007    free(raw_subtract_from);
1008    gui_fselect_read_dir(current_dir);
1009    gui_fselect_redraw = 2;
1010}
1011
1012
1013#define MAX_SUB_NAMES 6
1014static void setup_batch_subtract(void) {
1015    struct fitem *ptr;
1016    int i;
1017    char *p = buf + sprintf(buf,"%s %s\n",selected->name,lang_str(LANG_FSELECT_SUB_FROM));
1018    for (ptr=head, i=0; ptr; ptr=ptr->next) {
1019        if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY) && ptr->size == hook_raw_size()) {
1020            if ( i < MAX_SUB_NAMES ) {
1021                sprintf(p, "%s\n",ptr->name);
1022                // keep a pointer to the one before the end, so we can stick ...and more on
1023                if (i < MAX_SUB_NAMES - 1) {
1024                    p += strlen(p);
1025                }
1026            }
1027            i++;
1028        }
1029    }
1030    if (i > MAX_SUB_NAMES) {
1031//      "...%d more files"
1032        sprintf(p,lang_str(LANG_FSELECT_SUB_AND_MORE),i - (MAX_SUB_NAMES - 1));
1033    }
1034    gui_mbox_init(LANG_FSELECT_SUBTRACT, (int)buf,
1035                  MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_subtract_cb);
1036}
1037//-------------------------------------------------------------------
1038void process_dng_to_raw_files(void){
1039 struct fitem *ptr;
1040 int i=0;
1041   started();
1042   msleep(100);
1043   finished();
1044
1045 if (fselect_real_marked_count()) {
1046   for (ptr=head; ptr; ptr=ptr->next)
1047     if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
1048       sprintf(selected_file, "%s/%s", current_dir, ptr->name);
1049       gui_browser_progress_show(selected_file, (i++)*100/fselect_real_marked_count()) ;
1050       module_convert_dng_to_chdk_raw(selected_file);
1051      }
1052    }
1053 else {
1054   sprintf(selected_file, "%s/%s", current_dir, selected->name);
1055   module_convert_dng_to_chdk_raw(selected_file);
1056 }
1057  gui_fselect_read_dir(current_dir);
1058}
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    case MPOPUP_DNG_TO_CRW:
1141            process_dng_to_raw_files();
1142            break;
1143    }
1144    gui_fselect_redraw = 2;
1145}
1146
1147//-------------------------------------------------------------------
1148void finalize_fselect()
1149{
1150    gui_fselect_free_data();
1151    gui_fselect_marked_free_data();
1152        module_rawop_unload();
1153}
1154
1155static void exit_fselect(char* file)
1156{
1157        finalize_fselect();
1158
1159    if (set_key_redraw_mode)
1160    {
1161        gui_set_mode(gui_fselect_mode_old);
1162        draw_restore();
1163    }
1164    if (fselect_on_select)
1165    {
1166        fselect_on_select(file);
1167        // if called mode will return control to filemanager - we need to redraw it
1168        gui_fselect_redraw = 2;
1169    }
1170    if (!set_key_redraw_mode)
1171    {
1172        gui_set_mode(gui_fselect_mode_old);
1173        draw_restore();
1174    }
1175}
1176
1177//-------------------------------------------------------------------
1178void gui_fselect_kbd_process() {
1179    int i;
1180   
1181    switch (kbd_get_autoclicked_key() | get_jogdial_direction()) {
1182        case JOGDIAL_LEFT:
1183        case KEY_UP:
1184            if (selected) {
1185                if (kbd_is_key_pressed(KEY_SHOOT_HALF)) fselect_goto_prev(4);
1186                else fselect_goto_prev(1);
1187                gui_fselect_redraw = 1;
1188            }
1189            break;
1190        case KEY_DOWN:
1191        case JOGDIAL_RIGHT:
1192            if (selected) {
1193                if (kbd_is_key_pressed(KEY_SHOOT_HALF)) fselect_goto_next(4);
1194                else fselect_goto_next(1);
1195                gui_fselect_redraw = 1;
1196            }
1197            break;
1198        case KEY_ZOOM_OUT:
1199            if (selected) {
1200                fselect_goto_prev(BODY_LINES-1);
1201                gui_fselect_redraw = 1;
1202            }
1203            break;
1204        case KEY_ZOOM_IN:
1205            if (selected) {
1206                fselect_goto_next(BODY_LINES-1);
1207                gui_fselect_redraw = 1;
1208            }
1209            break;
1210        case KEY_RIGHT:
1211            if (selected) {
1212                fselect_marked_toggle();
1213                fselect_goto_next(1);
1214                gui_fselect_redraw = 1;
1215            }
1216            break;
1217        case KEY_LEFT:
1218            if (selected && selected->attr != 0xFF) {
1219                i=MPOPUP_CUT|MPOPUP_COPY|MPOPUP_SELINV;
1220                if (fselect_marked_count() > 0) {
1221                    i |= MPOPUP_DELETE;
1222                    if ( fselect_marked_count()>1 )
1223                        i |=MPOPUP_RAW_ADD|MPOPUP_RAW_AVERAGE;
1224                    // doesn't make sense to subtract from itself!
1225                    if( selected->marked == 0 && fselect_real_marked_count() > 0)
1226                        i |= MPOPUP_SUBTRACT;
1227                }
1228                if (marked_operation == MARKED_OP_CUT || marked_operation == MARKED_OP_COPY)
1229                    i |= MPOPUP_PASTE;
1230                if (!(selected->attr & DOS_ATTR_DIRECTORY) || !(selected->name[0] == '.' && selected->name[1] == '.' && selected->name[2] == 0) ||//If item is not a folder or UpDir
1231                     (selected->name[0] == 'D' && selected->name[1] == 'C' && selected->name[2] == 'I' && selected->name[3] == 'M') ||//If item is DCIM folder
1232                     (selected->name[3] == 'C'))//If item is a DCIM sub folder
1233                    i |= MPOPUP_PURGE;//Display PURGE RAW function in popup menu
1234                if(selected->size == hook_raw_size())
1235                    i |= MPOPUP_RAW_DEVELOP;
1236
1237                                if ( module_convert_dng_to_chdk_raw(0) )        // if dng module exist
1238                if((fselect_marked_count()>1)||(selected->size > hook_raw_size()))
1239                    i |= MPOPUP_DNG_TO_CRW;
1240
1241                if (selected->name[9] == 'B' && selected->name[10] == 'I' && selected->name[11] == 'N') //If item is DCIM folder
1242                    i |= MPOPUP_CHDK_REPLACE;
1243
1244                module_mpopup_init( popup, i, fselect_mpopup_cb, 0);
1245            }
1246            break;
1247        case KEY_SET:
1248            if (selected && selected->attr != 0xFF && gui_fselect_redraw==0) {
1249                if (selected->attr & DOS_ATTR_DIRECTORY) {
1250                    i=strlen(current_dir);
1251                    if (selected->name[0]=='.' && selected->name[1]=='.' && selected->name[2]==0) {
1252                        while (current_dir[--i] != '/');
1253                        current_dir[i]=0;
1254                    } else {
1255                        sprintf(current_dir+i, "/%s", selected->name);
1256                    }
1257                    gui_fselect_read_dir(current_dir);
1258                    gui_fselect_redraw = 1;
1259                } else  {
1260                    sprintf(selected_file, "%s/%s", current_dir, selected->name);
1261                                       
1262                                        char *ext = strchr(selected->name,'.');
1263                    if ( ext && (ext[1]|0x20)=='f' && (ext[2]|0x20)=='l' && (ext[3]|0x20)=='t') {
1264                                        if (!fselect_on_select) {
1265                                exit_fselect(0);
1266                                                module_run(selected_file, 0, 0,0, UNLOAD_IF_ERR);
1267
1268                                                        break;
1269                                                }
1270                                        }
1271
1272                    exit_fselect(selected_file);
1273                                        module_async_unload(module_idx);
1274                }
1275            }
1276            break;
1277        case KEY_ERASE:
1278        case KEY_DISPLAY:
1279            if (selected && selected->attr != 0xFF) {
1280                if (selected->attr & DOS_ATTR_DIRECTORY) {
1281                    if (selected->name[0]!='.' || selected->name[1]!='.' || selected->name[2]!=0)
1282                        gui_mbox_init(LANG_BROWSER_ERASE_DIR_TITLE, LANG_BROWSER_ERASE_DIR_TEXT,
1283                                      MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_delete_folder_cb);
1284                } else {
1285                    gui_mbox_init(LANG_BROWSER_DELETE_FILE_TITLE, LANG_BROWSER_DELETE_FILE_TEXT,
1286                                  MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_delete_file_cb);
1287                }
1288            }
1289            break;
1290        case KEY_MENU:
1291            // just free resource. callback called with NULL ptr
1292            exit_fselect(0);
1293                        module_async_unload(module_idx);
1294            break;
1295    }
1296}
1297
1298
1299
1300// =========  MODULE INIT =================
1301#include "module_load.h"
1302int module_idx=-1;
1303
1304/***************** BEGIN OF AUXILARY PART *********************
1305  ATTENTION: DO NOT REMOVE OR CHANGE SIGNATURES IN THIS SECTION
1306 **************************************************************/
1307
1308void* MODULE_EXPORT_LIST[] = {
1309        /* 0 */ (void*)EXPORTLIST_MAGIC_NUMBER,
1310        /* 1 */ (void*)0
1311                };
1312
1313
1314//---------------------------------------------------------
1315// PURPOSE:   Bind module symbols with chdk.
1316//              Required function
1317// PARAMETERS: pointer to chdk list of export
1318// RETURN VALUE: 1 error, 0 ok
1319//---------------------------------------------------------
1320int _module_loader( void** chdk_export_list )
1321{
1322  if ( (unsigned int)chdk_export_list[0] != EXPORTLIST_MAGIC_NUMBER )
1323     return 1;
1324
1325  tConfigVal configVal;
1326  CONF_BIND_INT(209, conf_sub_batch_prefix);
1327  CONF_BIND_INT(210, conf_sub_batch_ext);
1328
1329  // Try to bind to generic gui mode alias
1330  if (!gui_bind_mode( GUI_MODE_FSELECT, &GUI_MODE_FSELECT_MODULE))
1331        return 1;
1332
1333  return 0;
1334}
1335
1336
1337
1338//---------------------------------------------------------
1339// PURPOSE: Finalize module operations (close allocs, etc)
1340// RETURN VALUE: 0-ok, 1-fail
1341//---------------------------------------------------------
1342int _module_unloader()
1343{
1344        finalize_fselect();
1345
1346        //sanity clean to prevent accidentaly assign/restore guimode to unloaded module
1347        GUI_MODE_FSELECT_MODULE.magicnum = 0;
1348
1349    // Unbind generic alias
1350        gui_bind_mode( GUI_MODE_FSELECT, 0);
1351
1352    return 0;
1353}
1354
1355
1356//---------------------------------------------------------
1357// PURPOSE: Default action for simple modules (direct run)
1358// NOTE: Please comment this function if no default action and this library module
1359//---------------------------------------------------------
1360int _module_run(int moduleidx, int argn, int* arguments)
1361{
1362  module_idx=moduleidx;
1363
1364  if ( argn!=0 && argn!=5 ) {
1365        module_async_unload(moduleidx);
1366    return 1;
1367  }
1368
1369  // Autounloading is unsafe because it should exists to catch finalization of mpopup
1370  module_set_flags(module_idx, MODULE_FLAG_DISABLE_AUTOUNLOAD);
1371
1372  if ( argn == 5 ) {
1373  gui_fselect_init( arguments[0], (const char*) arguments[1], (const char*) arguments[2], (void*)arguments[3]);
1374  gui_fselect_set_key_redraw(arguments[4]);
1375  }
1376  else
1377    gui_fselect_init(LANG_STR_FILE_BROWSER, "A", "A", NULL);
1378
1379  return 0;
1380}
1381
1382
1383/******************** Module Information structure ******************/
1384
1385struct ModuleInfo _module_info = {      MODULEINFO_V1_MAGICNUM,
1386                                                                        sizeof(struct ModuleInfo),
1387
1388                                                                        ANY_CHDK_BRANCH, 0,                     // Requirements of CHDK version
1389                                                                        ANY_PLATFORM_ALLOWED,           // Specify platform dependency
1390                                                                        0,                                                      // flag
1391                                                                        -LANG_MENU_MISC_FILE_BROWSER,   // Module name
1392                                                                        1, 0,                                           // Module version
1393                                                                        0
1394                                                                 };
1395
1396/*************** END OF AUXILARY PART *******************/
Note: See TracBrowser for help on using the repository browser.