#include #include #include #include #include #include #include #include #include "pickfile.h" #include "directory.h" #define FILELIST_TYPE 2 #define EDITING_FOCUS "yz/gui/editing_focus" char *path_to_item(int it); struct item_info *dirInfos = 0; char *from = 0; int dScroll = 0; int numDirItems = 0, allDirItems = 0, numVDirItems = 0; int iSelected = 0; static DIR *d = 0; int pdAllocated = 0; filelist_t theList = {FILELIST_TYPE, 1, 0}; reset_directory_data() { filelist_t theList2 = {FILELIST_TYPE, 1, 0}; theList = theList2; dirInfos = 0; from = 0; dScroll = 0; numDirItems = allDirItems = numVDirItems = iSelected = pdAllocated = 0; d = 0; } switch_to_directory(char *dpath) { release_directory(); if(pdAllocated)free(pickerDir); pickerDir = dpath; pdAllocated = 1; dScroll = 0; get_directory(); } dir_selectable_handler(int (*sel)(struct item_info*)) { theList.selectable = sel; } release_directory() { if(!d)return; closedir(d); d = 0; if(dirInfos)free((char*)dirInfos); dirInfos = 0; numDirItems = numVDirItems = allDirItems = 0; } int is_item_visible(int i) { if(!strcmp(dirInfos[i].de.d_name, ".."))return 1; if(dirInfos[i].de.d_name[0]=='.')return 0; return 1; } int di_compare(const void *a, const void *b) { return strcmp(((struct item_info*)a)->de.d_name, ((struct item_info*)b)->de.d_name); } get_directory() { struct dirent *de; int i; char *ipath = 0; yzUpdateBuffer(YZ_BUFFER_BACK); d = opendir(pickerDir); if(!d) { perror("opendir"); printf("/../error"); exit(-1); } numDirItems = 0; allDirItems = 8; dirInfos = (struct item_info*)malloc(sizeof(struct item_info)*allDirItems); if(!dirInfos)goto nomem; while(de = readdir(d)) { if((numDirItems+1) > allDirItems) { allDirItems *= 2; dirInfos = realloc(dirInfos, sizeof(struct item_info)*allDirItems); if(!dirInfos) { nomem: perror("realloc"); printf("/../error"); exit(-1); } } dirInfos[numDirItems++].de = *de; ipath = path_to_item(numDirItems-1); stat(ipath, &dirInfos[numDirItems-1].st); free(ipath); if(is_item_visible(numDirItems-1))numVDirItems++; } qsort(dirInfos, numDirItems, sizeof(struct item_info), di_compare); iSelected = 0; while(iSelected < numDirItems && !is_item_visible(iSelected)) iSelected++; if(iSelected>=numDirItems)iSelected = 0; clear_list(); draw_list(0, 216); if(from) { for(i=0;i218)y2=218; for(pass=0;pass<2;pass++){k=0; for(i=0;i(y2))break; if(i == iSelected) { if(theList.focused)yzPenColor(40000, 40000, 56000); else yzPenColor(54000, 54000, 54000); } else yzPenColor(65535, 65535, 65535); if(pass==0) yzRect(21, 31+k*18 - dScroll*18, 379, 31+k*18 - dScroll*18 + 20); switch(dirInfos[i].de.d_type) { case DT_REG: b = 0; yzPenColor(0, 0, 0); break; case DT_DIR: b = 1; yzPenColor(0, 0, 45000); break; default: b = 0; yzPenColor(40000, 20000, 20000); break; } if(pass==1) { yzText(20 + 5, 30 + y + 2, dirInfos[i].de.d_name); if(b)yzText(21 + 5, 30 + y + 2, dirInfos[i].de.d_name); sprintf(sizestr, "%zd", (size_t)dirInfos[i].st.st_size); yzText(290 + 5, 30 + y, sizestr); if(b)yzText(291 + 5, 30 + y, sizestr); yzPenColor(0, 0, 0); yzLine(290, 30+y-13, 290, 30+y+5); } k++; }} } is_selectable(int i) { if(!is_item_visible(i))return 0; if(theList.selectable)return theList.selectable(&dirInfos[i]); return 1; } next_selectable(int i) { int k; k = i++; while(i=numDirItems)return k; else return i; } prev_selectable(int i) { int k; k = i--; while(i>=0 && !is_selectable(i))i--; if(i<0)return k; else return i; } int vis_index(int i) { int k = 0, j; for(j=0;j=numDirItems)return; if(i<0)return; vsel = vis_index(iSelected); yold = y_pos(vsel); ynew = y_pos(vis_index(i)); iSelected = i; vsel = vis_index(iSelected); yzBufferMode(YZ_BUFFER_BACK); if((vsel-dScroll)>=0 && (vsel-dScroll)<12) { } else { if((vsel-dScroll)<0)dScroll = vsel-sby; else dScroll = vsel-11+sby; if(dScroll>(numVDirItems-12))dScroll = numVDirItems-12; if(dScroll<0)dScroll = 0; } clear_list(); draw_list(0, 216); yzUpdateBuffer(YZ_BUFFER_FRONT); yzBufferMode(YZ_BUFFER_BOTH); } directory_key(int key) { set_editing_selection(); switch(key) { case YZ_KEYCODE_DOWN_ARROW: set_selection(next_selectable(iSelected), 5); break; case YZ_KEYCODE_UP_ARROW: set_selection(prev_selectable(iSelected), 5); break; case '\n': case 3: if(open_selection()) return 1; break; } return 0; } char *path_to_item(int it) { char *p, *t; if(strcmp(dirInfos[it].de.d_name, "..")) { p = malloc(strlen(pickerDir)+strlen(dirInfos[it].de.d_name)+2); strcpy(p, pickerDir); if(p[strlen(p)-1]!='/')strcat(p, "/"); strcat(p, dirInfos[it].de.d_name); from = 0; } else { p = malloc(strlen(pickerDir)+1); strcpy(p, pickerDir); t = p + strlen(p) - 1; while(t>p && *t!='/')t--; if(t>p) { *t = 0; from = t+1; // the part after the '/' } else { if(p[1])from = p+2; p[0] = '/'; p[1] = 0; } } return p; } set_editing_selection() { yzPutWindowData(EDITING_FOCUS, &theList); } select_dir() { set_editing_selection(); theList.focused = 1; clear_list(); draw_list(0, 216); } deselect_dir() { if(yzGetWindowData(EDITING_FOCUS) == &theList) yzPutWindowData(EDITING_FOCUS, 0); theList.focused = 0; clear_list(); draw_list(0, 216); } open_selection() { char *newDir; set_editing_selection(); newDir = path_to_item(iSelected); if(dirInfos[iSelected].de.d_type == DT_DIR) { switch_to_directory(newDir); return 0; } else { pickerFile = newDir; return 1; } } long long mtime() { struct timeval tv; gettimeofday(&tv, 0); return ((long long)tv.tv_sec*1000 + tv.tv_usec/1000); } directory_click(int x, int y) { int i, r, s, is_double = 0; static long long lclick = 0; long long ltime = 0, ntime; if(y<30)return 0; if(y>=250)return 0; if(x<20)return 0; if(x>=380)return 0; set_editing_selection(); ntime = mtime(); if(ntime - lclick < 400){is_double = 1;lclick = 0;} else lclick = ntime; do { y -= 30; y -= 13; if(y>0)y = (y+9)/18; else y = (y-9)/18; ntime = mtime(); if(y<=0 || y>=11) { s=1; if(y<-2 || y>15) { if(ntime < (ltime + 100))continue; } else if(ntime < (ltime+250))continue; ltime = ntime; } else s = 0; i = vis_to_ind(y+dScroll); if(y<=0 && i==-1)i=vis_to_ind(0); if(y>=11 && i==-1)i=vis_to_ind(numVDirItems-1); if(s && !is_selectable(i)) { if(y>=11)i = next_selectable(i); else i = prev_selectable(i); } if(!is_selectable(i)){is_double=0;i = -1;} if(i==-1){}//printf("ERROR: invisible item clicked\n"); else if(r || s) { set_selection(i, 0); } } while(!is_double && (r=yzQueryPointer(&x, &y)) < 3); if(is_double)return open_selection(); return 0; }