📄 libpg_dirview.c
字号:
/* Set up the default directory in it's own directory context */ pgEnterContext(); dirview_setdir(&dat); /* If we have a field, focus it first */ if (dat.wFile) pgFocus(dat.wFile); for (;;) { evt = *pgGetEvent(); /* Buttons... */ if (evt.from==wCancel) break; else if (evt.from==wOk) { struct stat st; /* Put together a full path for the final file name */ if (dat.wFile) dat.sFileName = pgGetWidget(dat.wFile,PG_WP_TEXT); dirview_fullpath(pgGetString(dat.sFileName)); /* Validate it */ if (stat(dirview_buf,&st) && (flags & (PG_FILE_MUSTEXIST | PG_FILE_MUSTREAD | PG_FILE_MUSTWRITE))) { pgMessageDialog("Error","The selected file does not exist",0); continue; } if (flags & PG_FILE_MUSTREAD) { int file = open(dirview_buf,O_RDONLY); if (file<0) { pgMessageDialogFmt("Error",0,"Error reading file:\n%s", strerror (errno)); continue; } close(file); } if (flags & PG_FILE_MUSTWRITE) { int file = open(dirview_buf,O_RDWR); if (file<0) { pgMessageDialogFmt("Error",0,"Error writing file:\n%s", strerror (errno)); continue; } close(file); } /* Good! We're all done */ break; } else if (evt.from==wUp) { /* Go up one level: chop off the slash until we have only one */ p = strrchr(dirview_dir,'/'); if (p && p[1]) { if (p==dirview_dir) p[1] = 0; else p[0] = 0; dirview_setdir(&dat); } } else if (evt.from==dat.wDirectory && evt.type==PG_WE_PNTR_DOWN)#if 0 dirview_pathmenu(&dat);#else ;#endif /* 'Tis a file we hope? */ else if (pgGetPayload(evt.from)==FILETAG) { /* File or directory? */ if (pgGetWidget(evt.from,PG_WP_FONT)==dat.fDirectory) { /* Directory => Follow the directory */ dirview_fullpath(pgGetString(pgGetWidget(evt.from,PG_WP_TEXT))); strcpy(dirview_dir,dirview_buf); dirview_setdir(&dat); /* No valid file */ dat.sFileName = 0; } else { /* File => Select the file */ dat.sFileName = pgGetWidget(evt.from, PG_WP_TEXT); if (dat.wFile) pgSetWidget(dat.wFile,PG_WP_TEXT,dat.sFileName,0); } } } /* Destroy the directory context and dialog context */ pgLeaveContext(); pgLeaveContext(); /* Don't have to return much, eh? */ if (evt.from==wCancel) return NULL; /* Return the assembled full path */ return dirview_buf;}/*****************************************************************************/typedef enum { NONE, QUIT, RELOAD,} NextAction;/*****************************************************************************/static NextAction next_action = NONE;static intlocation_activate(struct pgEvent *evt){ ENTER("location_activate"); const char* str = pgGetString(pgGetWidget(evt->from,PG_WP_TEXT)); DPRINTF(">>> location is [%s]\n", str); next_action = RELOAD; LEAVE; return 0;}/*****************************************************************************/#define FREE(var) { if(var) free((void*)(var)); var=0; }#define REASSIGN(var, val) { FREE(var); var=val; }// TODO: pack these in instance variablesstatic const char* this_url = 0;static const LpgdvProtocol* this_protocol = 0;static const char* this_username = 0;static const char* this_password = 0;static const char* this_host = 0;static int this_port = 0;static const char* this_dir = 0;static void * this_pdata = 0;/*****************************************************************************/static voiddir_leave_old(void){ ENTER("dir_leave_old()"); if(this_protocol && this_dir) { DPRINTF("leaving [%s]\n", this_dir); this_protocol->dir_leave_f(this_pdata, this_dir); } FREE(this_dir); LEAVE;}static voidsite_leave_old(void){ ENTER("site_leave_old()"); dir_leave_old(); if(this_protocol && this_host) { DPRINTF("leaving [%s]:%d\n", this_host, this_port); this_protocol->site_leave_f(this_pdata, this_host, this_port); } FREE(this_host); this_port = 0; FREE(this_username); FREE(this_password); LEAVE;}static voidprotocol_leave_old(void){ ENTER("protocol_leave_old()"); site_leave_old(); if(this_protocol) { DPRINTF("leaving [%s]\n", this_protocol->name); this_protocol->protocol_uninit_f(this_pdata); } this_protocol = 0; LEAVE;}static intprotocol_enter_new(const LpgdvProtocol* protocol){ ENTER("protocol_enter_new()"); int res = 0; if(protocol) { DPRINTF("entering [%s]\n", protocol->name); this_pdata = protocol->protocol_init_f(); this_protocol = 0; FREE(this_username); FREE(this_password); FREE(this_host); FREE(this_dir); this_port = 0; if(this_pdata) { this_protocol = protocol; res = 1; } } LEAVE; return res;}static intsite_enter_new(const char* site_name, int port, const char* username, const char* password){ ENTER("site_enter_new()"); int res = 0; if(site_name && this_protocol) { DPRINTF("entering [%s];%d\n", site_name, port); DPRINTF("login: usr=[%s] pwd=[%s]\n", username?username:"<>", password?password:"<>"); res = this_protocol->site_enter_f(this_pdata, site_name, port, username, password); FREE(this_username); FREE(this_password); FREE(this_host); FREE(this_dir); this_port = 0; if(res) { this_host = strdup(site_name); this_port = port; this_username = strdup(username); this_password = strdup(password); } } LEAVE; return res;}static intdir_enter_new(const char* dir_name){ ENTER("dir_enter_new()"); int res = 0; if(dir_name && this_protocol) { DPRINTF("entering [%s]\n", dir_name); res = this_protocol->dir_enter_f(this_pdata, dir_name); this_dir = res ? strdup(dir_name) : 0; } LEAVE; return res;}/*****************************************************************************/static LpgdvStatusreload(const char* url, char** corrected_url, Parameters* params){ ENTER("reload()"); LpgdvStatus status = LPGDV_OK; char* url_copy = 0; const char* protocol_name; const char* address; char* p; const LpgdvProtocol *protocol; LpgdvSplittedUrl su; int ok; const char* dir_name = 0; const char* item_name = 0; LpgdvMimeTypeId mt_id; if(url==0 || strlen(url)==0) { DPRINTF("empty url\n"); status = LPGDV_ERROR_INVALID_URL; goto done; } /* check against previous url */ if(this_url && !strcmp(url, this_url)) { DPRINTF("same url\n"); goto done; } /* remember this url */ REASSIGN(this_url, strdup(url)); DPRINTF("url = [%s]\n", url); /* split url into protocol an address */ url_copy = strdup(url); p = strchr(url_copy, ':'); if(p) { *p = 0; protocol_name = url_copy; address = p+1; } else if(params->protocol_default){ protocol_name = params->protocol_default; address = url_copy; } else { protocol_name = 0; } protocol = lpgdv_protocol_find(protocol_name); if(protocol==0) { WARNF("libpgdirview: "__FILE__": warning: unknown protocol: %s\n", protocol_name); status = LPGDV_ERROR_UNKNOWN_PROTOCOL; goto done; } DPRINTF("protocol = [%s]\n", protocol->name); DPRINTF("address = [%s]\n", address); ok = lpgdv_protocol_split_url(address, protocol, &su); if(!ok) { WARNF("warning: lpgdv_protocol_split_url() failed\n"); status = LPGDV_ERROR_INVALID_URL; goto done; } DPRINTF("URL[%s] splitted:\n", url); DPRINTF(" username = [%s]\n", su.username ? su.username : "<>"); DPRINTF(" password = [%s]\n", su.password ? su.password : "<>"); DPRINTF(" host = [%s]\n", su.host ? su.host : "<>"); DPRINTF(" port = %d\n", su.port); DPRINTF(" path = [%s]\n", su.path ? su.path : "<>"); DPRINTF(" arguments = [%s]\n", su.arguments ? su.arguments : "<>"); REASSIGN(dir_name, protocol->getdirname_f(su.path)); REASSIGN(item_name, protocol->getitemname_f(su.path)); DPRINTF(" dir = [%s]\n", dir_name ? dir_name : "<>"); DPRINTF(" item = [%s]\n", item_name ? item_name : "<>"); mt_id = lpgdv_mime_type_id_of(item_name, -1); DPRINTF("object=[%s] id=%d mime-type=[%s]\n", item_name ? item_name : "<>", mt_id, lpgdv_mime_type_name_of(mt_id)); /* another protocol ? */ if(this_protocol==0 || this_protocol!=protocol) { protocol_leave_old(); protocol_enter_new(protocol); } /* another host ? */ if(protocol->has_host) { if(this_host==0 || !protocol->is_same_site_f(this_host, su.host) || this_port != su.port) { site_leave_old(); site_enter_new(su.host, su.port, su.username, su.password); } } /* another dir ? */ DPRINTF(":::[%s][%s]\n", this_dir, dir_name); if(this_dir==0 || !protocol->is_same_dir_f(this_dir, dir_name)) { dir_leave_old(); dir_enter_new(dir_name); } /* TODO: - init protocol - enter site - enter dir - call function that browse dir for each item - leave dir - leave site - uninit protocol */ //#warning todo ... done: FREE(url_copy); FREE(dir_name); FREE(item_name); LEAVE; return status;}/*****************************************************************************//* Main function */const char *dirview(const char *view_name, const char *url, ...){ pghandle wTB, wOk, wCancel, wUp; struct pgEvent evt; struct filepickdata dat; int w,h; char *p; Parameters* params = 0; MenuItemParams* menu_item_params = 0; ColumnParams* column_params = 0; LpgdvStatus status; { va_list va; va_start(va, url); status = va_parse_params(¶ms, &menu_item_params, &column_params, va); va_end(va); } dump_params(params); dump_menuitemparams(params->menu_items_nb, menu_item_params); dump_columnparams(params->columns_nb, column_params); /********* Set up dialog box and top-level widgets */ pgEnterContext(); { /* Size the dialog box ourselves */ pgEnterContext(); { pgSizeText(&w,&h,pgNewFont(NULL,0,PG_FSTYLE_DEFAULT | PG_FSTYLE_FLUSH), pgNewString("a")); /* A good metric */ } pgLeaveContext(); /* Special fonts for directories and links */ dat.fDirectory = pgNewFont(NULL,0,PG_FSTYLE_DEFAULT | PG_FSTYLE_BOLD); dat.fLink = pgNewFont(NULL,0,PG_FSTYLE_DEFAULT | PG_FSTYLE_ITALIC); dat.fHeading = pgNewFont(NULL,0,PG_FSTYLE_DEFAULT | PG_FSTYLE_BOLD | PG_FSTYLE_UNDERLINE); /* Make containers for the directory and file. They are ok without * containers, but it looks better putting them in toolbars. */ if(params->location_visible) { wTB = pgNewWidget(PG_WIDGET_TOOLBAR,0,0); pgSetWidget(PGDEFAULT, PG_WP_SIDE,PG_S_BOTTOM, 0); } dat.wDirectory = pgNewWidget(PG_WIDGET_TOOLBAR,0,0); pgSetWidget(PGDEFAULT, PG_WP_SIDE,PG_S_TOP, 0); dat.wScroll = pgNewWidget(PG_WIDGET_SCROLL,0,0); dat.wFileList = pgNewWidget(PG_WIDGET_BOX,0,0); pgSetWidget(PGDEFAULT, PG_WP_SIDE,PG_S_ALL, 0); pgSetWidget(dat.wScroll, PG_WP_BIND,dat.wFileList, 0); /* Put the file and directory in their toolbars */ /* if (flags & PG_FILE_FIELD) { dat.wFile = pgNewWidget(PG_WIDGET_FIELD,PG_DERIVE_INSIDE,wTB); pgSetWidget(PGDEFAULT, PG_WP_SIDE,PG_S_ALL, 0); if (deffile) pgSetWidget(PGDEFAULT,PG_WP_TEXT,pgNewString(deffile),0); } */ if(!params->list_do_include_parent) { /* [..] button */ wUp = pgNewWidget(PG_WIDGET_BUTTON, PG_DERIVE_INSIDE,dat.wDirectory); pgSetWidget(PGDEFAULT, PG_WP_TEXT,pgNewString(".."), 0); } /* Title bar */ if(params->title_is_visible) { dat.wDirectory = params->list_do_include_parent ? pgNewWidget(PG_WIDGET_BUTTON, PG_DERIVE_INSIDE,dat.wDirectory) : pgNewWidget(PG_WIDGET_BUTTON, 0,0); pgSetWidget(PGDEFAULT, PG_WP_SIDE,PG_S_ALL, PG_WP_EXTDEVENTS,PG_EXEV_PNTR_DOWN, 0); if(params->title) { pgSetWidget(PGDEFAULT, PG_WP_TEXT,pgNewString(params->title), 0); } } /* url */ if(params->location_visible) { dat.wFile = pgNewWidget(params->location_visible==EDITABLE ? PG_WIDGET_FIELD : PG_WIDGET_LABEL, PG_DERIVE_INSIDE,wTB); pgSetWidget(PGDEFAULT, PG_WP_SIDE, PG_S_ALL, 0); if(params->location_visible==EDITABLE) { pgBind(PGDEFAULT,PG_WE_ACTIVATE,&location_activate,NULL); } if(url) { pgSetWidget(PGDEFAULT,PG_WP_TEXT,pgNewString(url),0); } } //pgEventLoop(); next_action = RELOAD; /* initial load */ do { switch(next_action) { case NONE: break; case RELOAD: { const char* loc = url; if(dat.wFile) loc = pgGetString(pgGetWidget(dat.wFile,PG_WP_TEXT)); reload(loc, 0, params); } break; } pgDispatchEvent(pgGetEvent()); } while (next_action != QUIT); } pgLeaveContext(); /* Store picker data */ return dirview_buf;}/* The End */// main lib function call args:// - instance_name// - user_data// - fd_handler(fd, user_data, lib_data)// - taglist//// additional function calls:// - int handle_fd(fd)//// functions handlers can call:// - reparse_taglist(this, taglist)//// app messages:// - set_location(str)// - select_item(num)// - unselect_item(num)// - select_all// - unselect_all// - click(num)// - quit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -