source: trunk/core/gui_fselect.c @ 651

Revision 651, 41.2 KB checked in by phyrephox, 4 years ago (diff)

/* this is a blind comitt, as my environment seems to be fucked up */

  • 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 "raw_merge.h"
13#include "raw.h"
14#include "conf.h"
15
16//-------------------------------------------------------------------
17#define HEAD_LINES              1
18#define BODY_LINES              10
19#define FOOT_LINES              1
20#define HEAD_FONT_LINES         HEAD_LINES * FONT_HEIGHT
21#define BODY_FONT_LINES         BODY_LINES * FONT_HEIGHT
22#define FOOT_FONT_LINES         FOOT_LINES * FONT_HEIGHT
23
24#define NAME_SIZE               15 // "FILENAME123 "
25#define SIZE_SIZE               7 // "1000 b|M|G"
26#define TIME_SIZE               14 // "01.01'70 00:00"
27
28#define NAME_FONT_SIZE          NAME_SIZE * FONT_WIDTH
29#define EXTE_FONT_SIZE          EXTE_SIZE * FONT_WIDTH
30#define SIZE_FONT_SIZE          SIZE_SIZE * FONT_WIDTH
31#define TIME_FONT_SIZE          TIME_SIZE * FONT_WIDTH
32
33#define SPACING                 4
34#define TAB_DIVIDER             1
35#define BORDER                  2
36#define SCROLLBAR               4
37
38#define MARKED_OP_NONE          0
39#define MARKED_OP_CUT           1
40#define MARKED_OP_COPY          2
41#define MARKED_BUF_SIZE         0x10000
42
43//-------------------------------------------------------------------
44static char current_dir[100], selected_file[100];
45static char buf[100];
46static char marked_dir[100];
47static enum Gui_Mode    gui_fselect_mode_old;
48struct fitem {
49    unsigned int    n;
50    char            *name;
51    unsigned char   attr;
52    unsigned long   size;
53    unsigned long   mtime;
54    unsigned char   marked;
55    struct fitem    *prev, *next;
56};
57static struct fitem *head=NULL, *top, *selected;
58static unsigned int count, max_dir_len;
59static struct fitem *marked_head=NULL;
60static unsigned int marked_count;
61static char marked_operation;
62static coord main_x, main_y, main_w, main_h; //main browser window coord (without BORDERs)
63static coord head_x, head_y, head_w, head_h; //header window coord
64static coord body_x, body_y, body_w, body_h; //main body window coord
65static coord foot_x, foot_y, foot_w, foot_h; //footer window coord
66static int gui_fselect_redraw;
67static char *fselect_title;
68static void (*fselect_on_select)(const char *fn);
69static char raw_operation;
70
71//-------------------------------------------------------------------
72static void gui_fselect_free_data() {
73    struct fitem  *ptr = head, *prev;
74
75    while (ptr) {
76        if (ptr->name)
77            free(ptr->name);
78        prev = ptr;
79        ptr = ptr->next;
80        free(prev);
81    }
82    head = top = selected = NULL;
83    count = 0;
84}
85
86//-------------------------------------------------------------------
87extern int fselect_sort_nothumb(const void* v1, const void* v2);
88int fselect_sort(const void* v1, const void* v2) {
89    struct fitem *i1=*((struct fitem **)v1), *i2=*((struct fitem **)v2);
90
91    if (i1->attr & DOS_ATTR_DIRECTORY) {
92        if (i2->attr & DOS_ATTR_DIRECTORY) {
93            if (i1->name[0]=='.' && i1->name[1]=='.' && i1->name[2]==0) {
94                return -1;
95            } else if (i2->name[0]=='.' && i2->name[1]=='.' && i2->name[2]==0) {
96                return 1;
97            } else {
98                return strcmp(i1->name, i2->name);
99            }
100        } else {
101            return -1;
102        }
103    } else {
104        if (i2->attr & DOS_ATTR_DIRECTORY) {
105            return 1;
106        } else {
107            return strcmp(i1->name, i2->name);
108        }
109    }
110}
111
112//-------------------------------------------------------------------
113static void gui_fselect_read_dir(const char* dir) {
114    DIR           *d;
115    struct dirent *de;
116    static struct stat   st;
117    struct fitem  **ptr = &head, *prev = NULL;
118    int    i;
119
120    gui_fselect_free_data();
121
122    d = opendir(dir);
123    if (d) {
124        de = readdir(d);
125        while (de) {
126            if (de->name[0] != 0xE5 /* deleted entry */ && (de->name[0]!='.' || de->name[1]!=0)) {
127                *ptr = malloc(sizeof(struct fitem));
128                if (*ptr) {
129                    (*ptr)->n = count;
130                    (*ptr)->name = malloc(strlen(de->name)+1);
131                    if ((*ptr)->name)
132                        strcpy((*ptr)->name, de->name);
133                    sprintf(buf, "%s/%s", dir, de->name);
134                    if (stat(buf, &st)==0) {
135                        (*ptr)->attr=st.st_attrib;
136                        (*ptr)->size=st.st_size;
137                        (*ptr)->mtime=st.st_mtime;
138                    } else {
139                        (*ptr)->attr=(de->name[0]=='.' && de->name[1]=='.' && de->name[2]==0)?DOS_ATTR_DIRECTORY:0xFF;
140                        (*ptr)->size=(*ptr)->mtime=0;
141                    }
142                    (*ptr)->marked=0;
143                    (*ptr)->prev=prev;
144                    prev=*ptr;
145                    ptr = &((*ptr)->next);
146                    ++count;
147                }   
148            }
149            de = readdir(d);
150        }
151        closedir(d);
152    }
153    *ptr=NULL;
154   
155    if (count) {
156        // sort
157        ptr=malloc(count*sizeof(struct fitem*));
158        if (ptr) {
159            prev=head;
160            count=0;
161            while (prev) {
162                ptr[count++]=prev;
163                prev=prev->next;
164            }
165           
166            qsort(ptr, count, sizeof(struct fitem*), fselect_sort_nothumb);
167           
168            for (i=0; i<count-1; ++i) {
169                ptr[i]->n=i;
170                ptr[i]->next=ptr[i+1];
171                ptr[i+1]->prev=ptr[i];
172            }
173            ptr[0]->prev=ptr[count-1]->next=NULL;
174            ptr[count-1]->n=count-1;
175            head=ptr[0];
176
177            free(ptr);
178        }
179    }
180
181    top = selected = head;
182}
183
184//-------------------------------------------------------------------
185void gui_fselect_init(int title, const char* dir, void (*on_select)(const char *fn)) {
186    int i;
187   
188    int chars_width = NAME_FONT_SIZE + SIZE_FONT_SIZE + TIME_FONT_SIZE;
189    main_w = SPACING/*N*/+SPACING+TAB_DIVIDER+SPACING/*S*/+SPACING+TAB_DIVIDER+SPACING/*T*/+SPACING+SCROLLBAR+chars_width;
190    main_h = HEAD_FONT_LINES + TAB_DIVIDER + BODY_FONT_LINES + TAB_DIVIDER + FOOT_FONT_LINES;
191    main_x = (screen_width - main_w) >> 1;
192    main_y = (screen_height - main_h) >> 1;
193   
194    head_x = body_x = foot_x = main_x;
195    head_w = body_w = foot_w = main_w;   
196    head_y = main_y;
197    head_h = HEAD_FONT_LINES;   
198    body_y = head_y + head_h + TAB_DIVIDER;
199    body_h = BODY_FONT_LINES;
200    foot_y = body_y + body_h + TAB_DIVIDER;
201    foot_h = FOOT_FONT_LINES;
202   
203    fselect_title = lang_str(title);
204    strcpy(current_dir, dir);
205    max_dir_len = NAME_SIZE + SIZE_SIZE + SPACING;
206    gui_fselect_read_dir(current_dir);
207    top = selected = head;
208    selected_file[0] = 0;
209    fselect_on_select = on_select;
210    marked_operation = MARKED_OP_NONE;
211    gui_fselect_mode_old = gui_get_mode();
212    gui_fselect_redraw = 2;
213    gui_set_mode(GUI_MODE_FSELECT);
214}
215
216//-------------------------------------------------------------------
217char* gui_fselect_result() {
218    if (selected_file[0])
219        return selected_file;
220    else
221        return NULL;
222}
223
224//-------------------------------------------------------------------
225void gui_fselect_draw_initial() {
226    int title_font_size;
227    int i;
228
229    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
230    title_font_size = strlen(fselect_title) * FONT_WIDTH;
231    draw_string(head_x+((head_w-title_font_size)>>1), head_y, fselect_title, MAKE_COLOR(COLOR_BLACK, COLOR_WHITE)); //title text
232   
233    for (i = 1; i <= BORDER; i++)
234      draw_rect(main_x-i, main_y-i, main_x+main_w+i-1, main_y+main_h+i-1, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE)); //border frame
235    draw_line(body_x, body_y-1, body_x+body_w-1, body_y-1, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE)); //border head-body
236    draw_line(foot_x, foot_y-1, foot_x+foot_w-1, foot_y-1, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE)); //border body-foot   
237}
238
239//-------------------------------------------------------------------
240void gui_fselect_draw() {
241    int i, j, off_name_x, off_size_x, off_time_x, off_body_x, off_body_y;
242    struct fitem  *ptr;
243    char buf[100];
244    struct tm *time;
245    unsigned long sum_size;
246    color cl_markered = ((mode_get()&MODE_MASK) == MODE_REC)?COLOR_YELLOW:0x66;
247    color cl_marked, cl_selected;
248
249    if (gui_fselect_redraw) {
250        if (gui_fselect_redraw == 2)
251            gui_fselect_draw_initial();
252
253        off_body_y = 0;
254        off_name_x = body_x+SPACING;
255        off_size_x = off_name_x+NAME_FONT_SIZE+SPACING+TAB_DIVIDER+SPACING;
256        off_time_x = off_size_x+SIZE_FONT_SIZE+SPACING+TAB_DIVIDER+SPACING;
257        off_body_x = off_time_x+TIME_FONT_SIZE+SPACING;
258
259        sum_size = 0;
260        for (i=0, ptr=top; i<BODY_LINES && ptr; ++i, ptr=ptr->next) {
261       
262            cl_marked = MAKE_COLOR((ptr==selected)?COLOR_RED:COLOR_GREY, (ptr->marked)?cl_markered:COLOR_WHITE);
263            cl_selected = (ptr==selected)?MAKE_COLOR(COLOR_RED, COLOR_RED):MAKE_COLOR(COLOR_GREY, COLOR_GREY);
264       
265            // print name
266            for (j=0; j<NAME_SIZE && ptr->name[j]; ++j)
267                buf[j] = ptr->name[j];
268               
269            if (j==NAME_SIZE && ptr->name[j]) buf[NAME_SIZE-1] = '~'; // too long name
270           
271            if (ptr->attr & DOS_ATTR_DIRECTORY && ptr->attr != 0xFF) { //?
272                if (j<NAME_SIZE) {
273                    buf[j++]='/';
274                } else {
275                    buf[NAME_SIZE-2]='~';
276                    buf[NAME_SIZE-1]='/';
277                }
278            }
279            for (; j<NAME_SIZE && (buf[j++]=' ');); //fill upto NAME_SIZE
280            buf[NAME_SIZE] = 0; // eos
281           
282            off_body_y = body_y+(i*FONT_HEIGHT);
283            draw_filled_rect(body_x, off_body_y, off_name_x-1, off_body_y+FONT_HEIGHT-1, cl_selected);
284            draw_string(off_name_x, off_body_y, buf, cl_marked);
285            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);
286           
287            // print size or <Dir>
288            if (ptr->attr & DOS_ATTR_DIRECTORY) {
289                if (ptr->attr == 0xFF) {
290                    sprintf(buf, "  ???  ");
291                } else if (ptr->name[0] == '.' && ptr->name[1] == '.' && ptr->name[2] == 0) {
292                    sprintf(buf, "<UpDir>");
293                } else {
294                    sprintf(buf, "< Dir >");
295                }
296            } else {
297                if (ptr->size < 1024)
298                    sprintf(buf, "%5d b", ptr->size); // " 1023 b"
299                else if (ptr->size < 1024*1024)
300                    sprintf(buf, "%3ld,%1d k", ptr->size/1024, (ptr->size%1024*10)/1024); // "999,9 k"
301                else if (ptr->size < 1024*1024*1024)
302                    sprintf(buf, "%3ld,%ld M", ptr->size/(1024*1024), (ptr->size%(1024*1024)*10)/(1024*1024) ); // "999,9 M"
303                else
304                    sprintf(buf, "%31d,%ld G", ptr->size/(1024*1024*1024), (ptr->size%(1024*1024*1024)*10)/(1024*1024*1024)); // "999.9 G"
305                   
306                if (ptr->marked)
307                  sum_size += ptr->size;
308            }
309            buf[SIZE_SIZE] = 0;
310            //tab divider
311            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);
312            draw_filled_rect(off_size_x-SPACING, off_body_y, off_size_x-1, off_body_y+FONT_HEIGHT-1, cl_selected);           
313            draw_string(off_size_x, off_body_y, buf, cl_marked);
314            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);           
315           
316            // print modification time
317            if (ptr->mtime) {
318                time = localtime(&(ptr->mtime));
319                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);
320            } else {
321                sprintf(buf, "%14s", "");
322            }
323            buf[TIME_SIZE] = 0;
324            //tab divider
325            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);
326            draw_filled_rect(off_time_x-SPACING, off_body_y, off_time_x-1, off_body_y+FONT_HEIGHT-1, cl_selected);
327            draw_string(off_time_x, off_body_y, buf, cl_marked);           
328            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);
329        }
330
331        //fill the rest of body
332        off_body_y += FONT_HEIGHT;
333        if (i>0 && i<BODY_LINES) {
334            draw_filled_rect(body_x, off_body_y, body_x+body_w-1, body_y+body_h-1, MAKE_COLOR(COLOR_GREY, COLOR_GREY));
335        }
336       
337       // scrollbar
338        draw_filled_rect(off_body_x, body_y, off_body_x+SCROLLBAR-1, body_y+body_h-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK));
339        if (count>BODY_LINES) {
340            i = BODY_FONT_LINES - 1;
341            j = i*BODY_LINES/count;
342            if (j<20) j=20;
343            i = (i-j)*selected->n/(count-1);
344            draw_filled_rect(off_body_x, body_y+i, off_body_x+SCROLLBAR-2, body_y+i+j, MAKE_COLOR(COLOR_WHITE, COLOR_WHITE));
345        }
346
347        //footer
348        i = strlen(current_dir);
349        if (i > max_dir_len) {
350          strncpy(buf, current_dir+i-max_dir_len, max_dir_len);
351          buf[0] = '.';
352          buf[1] = '.';         
353        } else {
354          strcpy(buf, current_dir);         
355        }
356        buf[max_dir_len] = 0;
357        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       
358        draw_string(off_name_x, foot_y, buf, MAKE_COLOR(COLOR_GREY, COLOR_WHITE)); //current dir
359       
360        if (sum_size) {
361          sprintf(buf, "%d b", sum_size); //selected size
362        } else {
363          unsigned int fr, tot;
364          fr = GetFreeCardSpaceKb(); tot = GetTotalCardSpaceKb();
365          if (fr < 1024*1024)
366            sprintf(buf, "%dM (%d%%)", fr/1024, tot? fr*100/tot: 0);
367          else
368            sprintf(buf, "%d.%dG (%d%%)", fr/(1024*1024), (fr%(10240))/100, tot? fr*100/tot: 0);
369        }
370        draw_string(foot_x+foot_w-strlen(buf)*FONT_WIDTH-BORDER, foot_y, buf, MAKE_COLOR(COLOR_GREY, COLOR_WHITE)); // free space
371        gui_fselect_redraw = 0;
372    }
373}
374
375//-------------------------------------------------------------------
376static void fselect_delete_file_cb(unsigned int btn) {
377    if (btn==MBOX_BTN_YES) {
378        started();
379        sprintf(selected_file, "%s/%s", current_dir, selected->name);
380        remove(selected_file);
381        finished();
382        selected_file[0]=0;
383        gui_fselect_read_dir(current_dir);
384    }
385    gui_fselect_redraw = 2;
386}
387
388static void fselect_purge_cb(unsigned int btn) {
389
390   DIR             *d,  *d2,  *d3,  *d4;
391   struct dirent   *de, *de2, *de3, *de4;
392   struct fitem    *ptr, *ptr2;
393   char            sub_dir[20], sub_dir_search[20];
394   char            selected_item[256];
395   int             i, found=0;
396
397   if (btn==MBOX_BTN_YES) {
398       //If selected folder is DCIM (this is to purge all RAW files in any Canon folder)
399       if (selected->name[0] == 'D' && selected->name[1] == 'C' && selected->name[2] == 'I' && selected->name[3] == 'M') {
400           sprintf(current_dir+strlen(current_dir), "/%s", selected->name);
401           d=opendir(current_dir);
402           while ((de=readdir(d)) != NULL) {//Loop to find all Canon folders
403               if (de->name[0] != '.' && de->name[1] != '.') {//If item is not UpDir
404                   sprintf(sub_dir, "%s/%s", current_dir, de->name);
405                   d2=opendir(sub_dir);
406                   while ((de2=readdir(d2)) != NULL) {//Loop to find all the RAW files inside a Canon folder
407                       if (de2->name[0] == 'C' || de2->name[9] == 'C') {//If file is RAW (Either CRW/CR2 prefix or file extension)
408                           d3=opendir(current_dir);
409                           while ((de3=readdir(d3)) != NULL) {//Loop to find all Canon folders
410                               if (de3->name[0] != '.' && de3->name[1] != '.') {//If item is not UpDir
411                                   sprintf(sub_dir_search, "%s/%s", current_dir, de3->name);
412                                   d4=opendir(sub_dir_search);
413                                   while ((de4=readdir(d4)) != NULL) {//Loop to find a corresponding JPG file inside a Canon folder
414                                       if (de2->name[4] == de4->name[4] && de2->name[5] == de4->name[5] &&//If the four digits of the Canon number are the same
415                                           de2->name[6] == de4->name[6] && de2->name[7] == de4->name[7] &&
416                                           de4->name[9] == 'J' && !(de4->name[0] == 'C' || de4->name[9] == 'C' || de4->name[0] == 0xE5)) {//If file is JPG, is not CRW/CR2 and is not a deleted item
417                                           started();
418                                           found=1;//A JPG file with the same Canon number was found
419                                       }                                 
420                                   }
421                                   closedir(d4);                 
422                               } 
423                           }
424                           closedir(d3);
425                           //If no JPG found, delete RAW file
426                           if (found == 0) {
427                               sprintf(selected_item, "%s/%s", sub_dir, de2->name);
428                               remove(selected_item);
429                               finished();
430                           }
431                           else {
432                               found=0;
433                               finished();
434                           }                             
435                       }
436                   }
437                   closedir(d2);
438               }
439           }
440           closedir(d);
441           i=strlen(current_dir);
442           while (current_dir[--i] != '/');
443           current_dir[i]=0;
444       }
445       //If item is a Canon folder (this is to purge all RAW files inside a single Canon folder)
446       else if (selected->name[3] == 'C') {
447           sprintf(current_dir+strlen(current_dir), "/%s", selected->name);
448           d=opendir(current_dir);
449           while ((de=readdir(d)) != NULL) {//Loop to find all the RAW files inside the Canon folder
450               if (de->name[0] == 'C' || de->name[9] == 'C') {//If file is RAW (Either CRW/CR2 prefix or file extension)
451                   d2=opendir(current_dir);
452                   while ((de2=readdir(d2)) != NULL) {//Loop to find a corresponding JPG file inside the Canon folder
453                       if (de->name[4] == de2->name[4] && de->name[5] == de2->name[5] &&//If the four digits of the Canon number are the same
454                           de->name[6] == de2->name[6] && de->name[7] == de2->name[7] &&
455                           de2->name[9] == 'J' && !(de2->name[0] == 'C' || de2->name[9] == 'C' || de2->name[0] == 0xE5)) {//If file is JPG and is not CRW/CR2 and is not a deleted item
456                           started();
457                           found=1;//A JPG file with the same Canon number was found
458                       }                                 
459                   }
460                   closedir(d2);
461                   //If no JPG found, delete RAW file               
462                   if (found == 0) {
463                       sprintf(selected_item, "%s/%s", current_dir, de->name);
464                       remove(selected_item);
465                       finished();
466                   }
467                   else {
468                       found=0;
469                       finished();
470                   }
471               }
472           }
473           closedir(d);
474           i=strlen(current_dir);
475           while (current_dir[--i] != '/');
476           current_dir[i]=0;
477       }
478       else {
479           //If inside a Canon folder (files list)
480           for (ptr=head; ptr; ptr=ptr->next) {//Loop to find all the RAW files in the list
481               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
482                   for (ptr2=head; ptr2; ptr2=ptr2->next) {//Loop to find a corresponding JPG file in the list
483                       if (ptr->name[4] == ptr2->name[4] && ptr->name[5] == ptr2->name[5] &&//If the four digits of the Canon number are the same
484                           ptr->name[6] == ptr2->name[6] && ptr->name[7] == ptr2->name[7] &&
485                           ptr2->name[9] == 'J' && !(ptr2->name[0] == 'C' || ptr2->name[9] == 'C')) {//If file is JPG and is not CRW/CR2
486                           started();
487                           found=1;
488                       }
489                   }
490                   //If no JPG found, delete RAW file           
491                   if (found == 0) {
492                       sprintf(selected_file, "%s/%s", current_dir, ptr->name);
493                       remove(selected_file);
494                       finished();
495                   }
496                   else {
497                       found=0;
498                       finished();
499                   }
500               }
501           }
502       }
503       gui_fselect_read_dir(current_dir);
504   }
505   gui_fselect_redraw = 2;
506}
507
508
509//-------------------------------------------------------------------
510static void fselect_delete_folder_cb(unsigned int btn) {
511    DIR           *d;
512    struct dirent *de;
513    int           i;
514
515    if (btn==MBOX_BTN_YES) {
516        sprintf(current_dir+strlen(current_dir), "/%s", selected->name);
517        d = opendir(current_dir);
518        if (d) {
519            de = readdir(d);
520            while (de) {
521                if (de->name[0] != 0xE5 /* deleted entry */ && (de->name[0]!='.' || (de->name[1]!='.' && de->name[1]!=0) || (de->name[1]=='.' && de->name[2]!=0))) {
522                    started();
523                    sprintf(selected_file, "%s/%s", current_dir, de->name);
524                    remove(selected_file);
525                    finished();
526                }
527                de = readdir(d);
528            }
529            closedir(d);
530        }
531        started();
532        remove(current_dir);
533        finished();
534        i=strlen(current_dir);
535        while (current_dir[--i] != '/');
536        current_dir[i]=0;
537        selected_file[0]=0;
538        gui_fselect_read_dir(current_dir);
539    }
540    gui_fselect_redraw = 2;
541}
542
543//-------------------------------------------------------------------
544static void fselect_goto_prev(int step) {
545    register int j, i;
546
547    for (j=0; j<step; ++j) {
548        if (selected->prev==top && top->prev)
549            top=top->prev;
550        if (selected->prev)
551            selected=selected->prev;
552                else
553                if (step == 1)
554                {
555                        for(; selected->next; selected=selected->next);
556                        for (i=0, top=selected; i<BODY_LINES-1 && top->prev; ++i, top=top->prev);
557                }
558    }
559}
560
561//-------------------------------------------------------------------
562static void fselect_goto_next(int step) {
563    register int j, i;
564    struct fitem  *ptr;
565
566    for (j=0; j<step; ++j) {
567        for (i=0, ptr=top; i<BODY_LINES-1 && ptr; ++i, ptr=ptr->next);
568        if (i==BODY_LINES-1 && ptr && ptr->prev==selected && ptr->next)
569            top=top->next;
570        if (selected->next)
571            selected=selected->next;
572                else
573                if (step == 1)
574                {
575                        for(; top->prev; top = top->prev);
576                        selected = top;
577                }
578    }
579}
580
581//-------------------------------------------------------------------
582static void fselect_marked_toggle() {
583    if (selected && selected->attr != 0xFF && !(selected->attr & DOS_ATTR_DIRECTORY)) {
584        selected->marked = !selected->marked;
585    }
586}
587
588//-------------------------------------------------------------------
589static void gui_fselect_marked_free_data() {
590    struct fitem  *ptr = marked_head, *prev;
591
592    while (ptr) {
593        if (ptr->name)
594            free(ptr->name);
595        prev=ptr;
596        ptr=ptr->next;
597        free(prev);
598    }
599    marked_head=NULL;
600    marked_count=0;
601    marked_operation = MARKED_OP_NONE;
602}
603
604//-------------------------------------------------------------------
605static void fselect_marked_copy_list() {
606    gui_fselect_marked_free_data();
607
608    struct fitem  *ptr, **marked_ptr=&marked_head, *prev = NULL;
609
610    for (ptr=head; ptr; ptr=ptr->next) {
611        if (ptr->marked) {
612            *marked_ptr = malloc(sizeof(struct fitem));
613            if (*marked_ptr) {
614                (*marked_ptr)->n = ptr->n;
615                (*marked_ptr)->name = malloc(strlen(ptr->name)+1);
616                if ((*marked_ptr)->name)
617                   strcpy((*marked_ptr)->name, ptr->name);
618                (*marked_ptr)->attr=ptr->attr;
619                (*marked_ptr)->size=ptr->size;
620                (*marked_ptr)->mtime=ptr->mtime;
621                (*marked_ptr)->marked=ptr->marked;
622                (*marked_ptr)->prev=prev;
623                prev=*marked_ptr;
624                marked_ptr = &((*marked_ptr)->next);
625                *marked_ptr=NULL;
626                ++marked_count;
627            }
628        }
629    }
630
631    if (!marked_count)
632        if (selected && selected->attr != 0xFF)
633            if (!(selected->attr & DOS_ATTR_DIRECTORY)) {
634                *marked_ptr = malloc(sizeof(struct fitem));
635                if (*marked_ptr) {
636                    (*marked_ptr)->n = selected->n;
637                    (*marked_ptr)->name = malloc(strlen(selected->name)+1);
638                    if ((*marked_ptr)->name)
639                        strcpy((*marked_ptr)->name, selected->name);
640                    (*marked_ptr)->attr=selected->attr;
641                    (*marked_ptr)->size=selected->size;
642                    (*marked_ptr)->mtime=selected->mtime;
643                    (*marked_ptr)->marked=!(0);
644                    (*marked_ptr)->prev=prev;
645                    prev=*marked_ptr;
646                    marked_ptr = &((*marked_ptr)->next);
647                    *marked_ptr=NULL;
648                    ++marked_count;
649                }
650            }
651
652    sprintf(marked_dir, "%s", current_dir);
653}
654
655//-------------------------------------------------------------------
656static void fselect_marked_paste_cb(unsigned int btn) {
657    struct fitem  *ptr;
658    int ss, sd = 0, fsrc, fdst, i=0;
659    register int *buf;
660    unsigned char fend;
661    static struct utimbuf t;
662
663    if (btn != MBOX_BTN_YES) return;
664
665    if (strcmp(marked_dir, current_dir) != 0) {
666        buf = umalloc(MARKED_BUF_SIZE);
667        if (buf) {
668            for (ptr=marked_head; ptr; ptr=ptr->next) {
669                if (ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
670                    started();
671                    ++i;
672                    if (marked_count)
673                        gui_browser_progress_show(lang_str(LANG_FSELECT_PROGRESS_TITLE),i*100/marked_count);
674                    sprintf(selected_file, "%s/%s", marked_dir, ptr->name);
675                    fsrc = open(selected_file, O_RDONLY, 0777);
676                    if (fsrc>=0) {
677                        sprintf(selected_file, "%s/%s", current_dir, ptr->name);
678                        // trying to open for read to check if file exists
679                        fdst = open(selected_file, O_RDONLY, 0777);
680                        if (fdst<0) {
681                            fdst = open(selected_file, O_WRONLY|O_CREAT, 0777);
682                            if (fdst>=0) {
683                                do {
684                                    ss=read(fsrc, buf, MARKED_BUF_SIZE);
685                                    if (ss>0) sd=write(fdst, buf, ss);
686                                } while (ss>0 && ss==sd);
687                                close(fdst);
688                                t.actime = t.modtime = ptr->mtime;
689                                utime(selected_file, &t);
690                                if (marked_operation == MARKED_OP_CUT && ss==0) {
691                                    close(fsrc); fsrc = -1;
692                                    sprintf(selected_file, "%s/%s", marked_dir, ptr->name);
693                                    remove(selected_file);
694                                }
695                            }
696                        } else {
697                            close(fdst);
698                        }
699                        if (fsrc>=0) close(fsrc);
700                    }
701                    finished();
702                    selected_file[0]=0;
703                }
704            }
705            ufree(buf);
706            if (marked_operation == MARKED_OP_CUT) {
707                gui_fselect_marked_free_data();
708            }
709        }
710        gui_fselect_read_dir(current_dir);
711    }
712    gui_fselect_redraw = 2;
713}
714
715//-------------------------------------------------------------------
716static inline unsigned int fselect_real_marked_count() {
717    struct fitem  *ptr;
718    register unsigned int cnt=0;
719
720    for (ptr=head; ptr; ptr=ptr->next) {
721        if (ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY) && ptr->marked)
722            ++cnt;
723    }
724    return cnt;
725}
726//-------------------------------------------------------------------
727static unsigned int fselect_marked_count() {
728    struct fitem  *ptr;
729    register unsigned int cnt=fselect_real_marked_count();
730
731    if (!cnt) {
732        if (selected && selected->attr != 0xFF && !(selected->attr & DOS_ATTR_DIRECTORY))
733            ++cnt;
734    }
735
736    return cnt;
737}
738
739//-------------------------------------------------------------------
740static void fselect_marked_delete_cb(unsigned int btn) {
741    struct fitem  *ptr;
742    unsigned int del_cnt=0, cnt;
743
744    if (btn != MBOX_BTN_YES) return;
745
746    cnt=fselect_marked_count();
747    for (ptr=head; ptr; ptr=ptr->next)
748        if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
749            started();
750            ++del_cnt;
751            if (cnt)
752                gui_browser_progress_show(lang_str(LANG_FSELECT_PROGRESS_TITLE),del_cnt*100/cnt);
753            sprintf(selected_file, "%s/%s", current_dir, ptr->name);
754            remove(selected_file);
755            finished();
756            selected_file[0]=0;
757        }
758
759    if (del_cnt == 0 && selected) {
760        started();
761        sprintf(selected_file, "%s/%s", current_dir, selected->name);
762        remove(selected_file);
763        finished();
764        selected_file[0]=0;
765    }
766    gui_fselect_read_dir(current_dir);
767    gui_fselect_redraw = 2;
768}
769
770//-------------------------------------------------------------------
771static void fselect_marked_inverse_selection() {
772    struct fitem  *ptr;
773   
774    for (ptr=head; ptr; ptr=ptr->next)
775        if (ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY))
776            ptr->marked = !ptr->marked;
777   
778    gui_fselect_redraw = 2;
779}
780
781//-------------------------------------------------------------------
782void process_raw_files(void){
783 struct fitem *ptr;
784 if ((fselect_marked_count()>1) && raw_merge_start(raw_operation)) {
785   for (ptr=head; ptr; ptr=ptr->next)
786     if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY)) {
787       sprintf(selected_file, "%s/%s", current_dir, ptr->name);
788       raw_merge_add_file(selected_file);
789      }
790  raw_merge_end();
791  gui_fselect_read_dir(current_dir);
792 }
793}
794
795static void fselect_subtract_cb(unsigned int btn) {
796    struct fitem *ptr;
797    char *raw_subtract_from;
798    char *raw_subtract_sub;
799    char *raw_subtract_dest;
800    if (btn != MBOX_BTN_YES) return;
801
802    if(!(raw_subtract_from = malloc(300))) //3x full path
803        return;
804    raw_subtract_sub = raw_subtract_from + 100;
805    raw_subtract_dest = raw_subtract_sub + 100;
806    sprintf(raw_subtract_sub,"%s/%s",current_dir,selected->name);
807    for (ptr=head; ptr; ptr=ptr->next) {
808        if (ptr->marked && ptr->attr != 0xFF &&
809            !(ptr->attr & DOS_ATTR_DIRECTORY) &&
810            ptr->size == hook_raw_size() &&
811            (strcmp(ptr->name,selected->name)) != 0) {
812            sprintf(raw_subtract_from,"%s/%s",current_dir,ptr->name);
813            sprintf(raw_subtract_dest,"%s/%s%s",current_dir,img_prefixes[conf.sub_batch_prefix],ptr->name+4);
814            strcpy(raw_subtract_dest + strlen(raw_subtract_dest) - 4,img_exts[conf.sub_batch_ext]);
815                        // don't let users attempt to write one of the files being read
816                        if( strcmp(raw_subtract_dest,raw_subtract_from) != 0 && strcmp(raw_subtract_dest,raw_subtract_sub) != 0) {
817                raw_subtract(raw_subtract_from,raw_subtract_sub,raw_subtract_dest);
818                        }
819        }
820    }
821    free(raw_subtract_from);
822    gui_fselect_read_dir(current_dir);
823    gui_fselect_redraw = 2;
824}
825
826
827#define MAX_SUB_NAMES 6
828static void setup_batch_subtract(void) {
829    struct fitem *ptr;
830    int i;
831    char *p = buf + sprintf(buf,"%s %s\n",selected->name,lang_str(LANG_FSELECT_SUB_FROM));
832    for (ptr=head, i=0; ptr; ptr=ptr->next) {
833        if (ptr->marked && ptr->attr != 0xFF && !(ptr->attr & DOS_ATTR_DIRECTORY) && ptr->size == hook_raw_size()) {
834            if ( i < MAX_SUB_NAMES ) {
835                sprintf(p, "%s\n",ptr->name);
836                // keep a pointer to the one before the end, so we can stick ...and more on
837                if (i < MAX_SUB_NAMES - 1) {
838                    p += strlen(p);
839                }
840            }
841            i++;
842        }
843    }
844    if (i > MAX_SUB_NAMES) {
845//      "...%d more files"
846        sprintf(p,lang_str(LANG_FSELECT_SUB_AND_MORE),i - (MAX_SUB_NAMES - 1));
847    }
848    gui_mbox_init(LANG_FSELECT_SUBTRACT, (int)buf,
849                  MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_subtract_cb);
850}
851
852//-------------------------------------------------------------------
853static void fselect_mpopup_cb(unsigned int actn) {
854    switch (actn) {
855        case MPOPUP_CUT:
856            fselect_marked_copy_list();
857            marked_operation=MARKED_OP_CUT;
858            break;
859        case MPOPUP_COPY:
860            fselect_marked_copy_list();
861            marked_operation=MARKED_OP_COPY;
862            break;
863        case MPOPUP_PASTE:
864            if (marked_operation == MARKED_OP_CUT) {
865                sprintf(buf, lang_str(LANG_FSELECT_CUT_TEXT), marked_count, marked_dir);
866                gui_mbox_init(LANG_FSELECT_CUT_TITLE, (int)buf,
867                              MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_marked_paste_cb);
868            }
869            else {
870                sprintf(buf, lang_str(LANG_FSELECT_COPY_TEXT), marked_count, marked_dir);
871                gui_mbox_init(LANG_FSELECT_COPY_TITLE, (int)buf,
872                              MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_marked_paste_cb);
873            }
874            break;
875        case MPOPUP_DELETE:
876            sprintf(buf, lang_str(LANG_FSELECT_DELETE_TEXT), fselect_marked_count());
877            gui_mbox_init(LANG_FSELECT_DELETE_TITLE, (int)buf,
878                          MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_marked_delete_cb);
879            break;
880         case MPOPUP_PURGE:
881           if (selected->name[0] == 'D' && selected->name[1] == 'C' && selected->name[2] == 'I' && selected->name[3] == 'M') {//If selected item is DCIM folder
882               sprintf(buf, lang_str(LANG_FSELECT_PURGE_DCIM_TEXT), fselect_marked_count());
883               gui_mbox_init(LANG_FSELECT_PURGE_TITLE, (int)buf,
884                         MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_purge_cb);
885           }
886           else if (selected->name[3] == 'C') {//If selected item is a Canon folder
887               sprintf(buf, lang_str(LANG_FSELECT_PURGE_CANON_FOLDER_TEXT), fselect_marked_count());
888               gui_mbox_init(LANG_FSELECT_PURGE_TITLE, (int)buf,
889                         MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_purge_cb);
890           }
891           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
892               sprintf(buf, lang_str(LANG_FSELECT_PURGE_LIST_TEXT), fselect_marked_count());
893               gui_mbox_init(LANG_FSELECT_PURGE_TITLE, (int)buf,
894                         MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_purge_cb);
895           }
896           else {
897               sprintf(buf, lang_str(LANG_FSELECT_PURGE_DISABLED_TEXT), fselect_marked_count());
898               gui_mbox_init(LANG_FSELECT_PURGE_TITLE, (int)buf,
899                         MBOX_TEXT_CENTER|MBOX_BTN_OK|MBOX_DEF_BTN1, fselect_purge_cb);
900           }
901           break;
902        case MPOPUP_SELINV:
903            fselect_marked_inverse_selection();
904            break;
905        case MPOPUP_CANCEL:
906            break;
907        case MPOPUP_RAW_AVERAGE:
908            raw_operation=RAW_OPERATION_AVERAGE;
909            process_raw_files();
910            break;
911        case MPOPUP_RAW_ADD:
912            raw_operation=RAW_OPERATION_SUM;
913            process_raw_files();
914            break;
915                case MPOPUP_RAW_DEVELOP:
916            sprintf(buf, "%s/%s", current_dir, selected->name);
917            gui_mbox_init((int)"", LANG_RAW_DEVELOP_MESSAGE, MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
918            raw_prepare_develop(buf);
919                break;
920        case MPOPUP_SUBTRACT:
921        {
922            setup_batch_subtract();
923            break;
924        }
925    }
926    gui_fselect_redraw = 2;
927}
928
929//-------------------------------------------------------------------
930void gui_fselect_kbd_process() {
931    int i;
932   
933    switch (kbd_get_autoclicked_key() | get_jogdial_direction()) {
934        case JOGDIAL_LEFT:
935        case KEY_UP:
936            if (selected) {
937                                if (kbd_is_key_pressed(KEY_SHOOT_HALF)) fselect_goto_prev(4);
938                else fselect_goto_prev(1);
939                gui_fselect_redraw = 1;
940            }
941            break;
942        case KEY_DOWN:
943        case JOGDIAL_RIGHT:
944            if (selected) {
945                if (kbd_is_key_pressed(KEY_SHOOT_HALF)) fselect_goto_next(4);
946                                else fselect_goto_next(1);
947                gui_fselect_redraw = 1;
948            }
949            break;
950        case KEY_ZOOM_OUT:
951            if (selected) {
952                fselect_goto_prev(BODY_LINES-1);
953                gui_fselect_redraw = 1;
954            }
955            break;
956        case KEY_ZOOM_IN:
957            if (selected) {
958                fselect_goto_next(BODY_LINES-1);
959                gui_fselect_redraw = 1;
960            }
961            break;
962        case KEY_RIGHT:
963            if (selected) {
964                fselect_marked_toggle();
965                fselect_goto_next(1);
966                gui_fselect_redraw = 1;
967            }
968            break;
969        case KEY_LEFT:
970            if (selected && selected->attr != 0xFF) {
971                i=MPOPUP_CUT|MPOPUP_COPY|MPOPUP_SELINV|MPOPUP_RAW_ADD|MPOPUP_RAW_AVERAGE;
972                if (fselect_marked_count() > 0) {
973                    i |= MPOPUP_DELETE;
974                    // doesn't make sense to subtract from itself!
975                    if( selected->marked == 0 && fselect_real_marked_count() > 0)
976                        i |= MPOPUP_SUBTRACT;
977                }
978                if (marked_operation == MARKED_OP_CUT || marked_operation == MARKED_OP_COPY)
979                    i |= MPOPUP_PASTE;
980                if (!(selected->attr & DOS_ATTR_DIRECTORY) || !(selected->name[0] == '.' && selected->name[1] == '.' && selected->name[2] == 0) ||//If item is not a folder or UpDir
981                     (selected->name[0] == 'D' && selected->name[1] == 'C' && selected->name[2] == 'I' && selected->name[3] == 'M') ||//If item is DCIM folder
982                     (selected->name[3] == 'C'))//If item is a DCIM sub folder
983                    i |= MPOPUP_PURGE;//Display PURGE RAW function in popup menu
984                if(selected->size == hook_raw_size())
985                    i |= MPOPUP_RAW_DEVELOP;
986                gui_mpopup_init(i, fselect_mpopup_cb);
987            }
988            break;
989        case KEY_SET:
990            if (selected && selected->attr != 0xFF && gui_fselect_redraw==0) {
991                if (selected->attr & DOS_ATTR_DIRECTORY) {
992                    i=strlen(current_dir);
993                    if (selected->name[0]=='.' && selected->name[1]=='.' && selected->name[2]==0) {
994                        while (current_dir[--i] != '/');
995                        current_dir[i]=0;
996                    } else {
997                        sprintf(current_dir+i, "/%s", selected->name);
998                    }
999                    gui_fselect_read_dir(current_dir);
1000                    gui_fselect_redraw = 1;
1001                } else  {
1002                    sprintf(selected_file, "%s/%s", current_dir, selected->name);
1003                    gui_fselect_free_data();
1004                    gui_fselect_marked_free_data();
1005                    gui_set_mode(gui_fselect_mode_old);
1006                    draw_restore();
1007                    if (fselect_on_select)
1008                        fselect_on_select(selected_file);
1009                }
1010            }
1011            break;
1012      #if CAM_HAS_ERASE_BUTTON
1013        case KEY_ERASE:
1014      #else
1015        case KEY_DISPLAY:
1016      #endif
1017            if (selected && selected->attr != 0xFF) {
1018                if (selected->attr & DOS_ATTR_DIRECTORY) {
1019                    if (selected->name[0]!='.' || selected->name[1]!='.' || selected->name[2]!=0)
1020                        gui_mbox_init(LANG_BROWSER_ERASE_DIR_TITLE, LANG_BROWSER_ERASE_DIR_TEXT,
1021                                      MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_delete_folder_cb);
1022                } else {
1023                    gui_mbox_init(LANG_BROWSER_DELETE_FILE_TITLE, LANG_BROWSER_DELETE_FILE_TEXT,
1024                                  MBOX_TEXT_CENTER|MBOX_BTN_YES_NO|MBOX_DEF_BTN2, fselect_delete_file_cb);
1025                }
1026            }
1027            break;
1028        case KEY_MENU:
1029            gui_fselect_free_data();
1030            gui_fselect_marked_free_data();
1031            gui_set_mode(gui_fselect_mode_old);
1032            draw_restore();
1033            if (fselect_on_select)
1034                fselect_on_select(NULL);
1035            break;
1036    }
1037}
1038
1039//-------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.