⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libpg_dirview.c

📁 The major functionality added in this release includes: - Rootless mode in X11 - Widget Templt
💻 C
📖 第 1 页 / 共 3 页
字号:
    return 1;        /* The rest depends on the user-defined filter */  return (*dat->filefilter)(name,dat->pattern);}/*****************************************************************************//* Given a filename, constructs it's full path in dirview_buf * careful to avoid overflowing any buffers.  */static voiddirview_fullpath(const char *file){  int len = strlen(dirview_dir);  strcpy(dirview_buf,dirview_dir);  if (len<(FILEMAX-1) && dirview_buf[len-1]!='/') {    strcat(dirview_buf,"/");    len--;  }  strncat(dirview_buf,file,FILEMAX-1-len);}/*****************************************************************************//* Utility to populate the dialog box with the current directory's files */static voiddirview_setdir(struct filepickdata *dat){  DIR *d;  struct dirent *arthur;     /* Dirent, Arthur Dirent... */  struct stat st;  struct filenode *names, *p;  int total = 0, count, i;  int itemheight;  char *s;  pghandle font;  pghandle wNameBoxP, wSizeBoxP, wXyzBoxP;  char buf[20];  /* Clear the directory context */  pgLeaveContext();  pgEnterContext();  /* Scroll back to the top */  pgSetWidget(dat->wScroll,	      PG_WP_VALUE,0,	      0);    /* Set the directory button's text. We don't need to use replacetext here   * because clearing the context also takes care of this string handle.   *   * Use strrchr() to display only the last directory name in the path   */  s = strrchr(dirview_dir,'/');  if (s[1]) s++;  pgSetWidget(dat->wDirectory,PG_WP_TEXT,pgNewString(s),0);  /* Select the relevant entries, store them, and sort them. This is just   * like what scandir() does, but scandir doesn't allow passing extra   * data to the selection function. I suppose another reason to avoid   * scandir() is that uClibc doesn't yet implement it correctly...   */  /* first just count the files... */  d = opendir(dirview_dir);  if (!d) return;  while (readdir(d))    total++;  rewinddir(d);  /* ... so we can allocate the array */  names = malloc(sizeof(struct filenode) * total);  if (!names) {    closedir(d);    return;  }  /* Now copy all the relevant directory entries */  count = 0;  p = names;  while (count<total && (arthur = readdir(d))) {    dirview_fullpath(arthur->d_name);    lstat(dirview_buf,&st);        if (dirview_filter(dat,arthur->d_name,&st)) {          /* We want this file, so store it */      memcpy(&p->st,&st,sizeof(st));      p->name[NAMEMAX-1] = 0;      strncpy(p->name,arthur->d_name,NAMEMAX-1);      p++;      count++;    }  }  closedir(d);  if (!count) {    /* No items? It's like a "this page intentionally left blank" message */    pgNewWidget(PG_WIDGET_LABEL,PG_DERIVE_INSIDE,dat->wFileList);    pgSetWidget(PGDEFAULT,		PG_WP_SIDE,PG_S_ALL,		PG_WP_TEXT,pgNewString("(no visible files)"),		0);  }  else {    /* Normal item drawing stuff... */    /* Get the height for list items */    itemheight = pgThemeLookup(PGTH_O_LISTITEM,PGTH_P_HEIGHT);     /* Sort them */    qsort(names,count,sizeof(struct filenode),&dirview_compare);        /* Make Columns */    wNameBoxP = pgNewWidget(PG_WIDGET_BOX,PG_DERIVE_INSIDE,dat->wFileList);    pgSetWidget(PGDEFAULT,		PG_WP_TRANSPARENT,1,		PG_WP_SIDE,PG_S_LEFT,		0);    wSizeBoxP = pgNewWidget(PG_WIDGET_BOX,0,0);    pgSetWidget(PGDEFAULT,		PG_WP_TRANSPARENT,1,		PG_WP_SIDE,PG_S_LEFT,		0);    wXyzBoxP = pgNewWidget(PG_WIDGET_BOX,0,0);    pgSetWidget(PGDEFAULT,		PG_WP_TRANSPARENT,1,		PG_WP_SIDE,PG_S_LEFT,		0);    /* Column headings */    wNameBoxP = pgNewWidget(PG_WIDGET_LABEL,PG_DERIVE_INSIDE,wNameBoxP);    pgSetWidget(PGDEFAULT,		PG_WP_TRANSPARENT,0,		PG_WP_FONT,dat->fHeading,		PG_WP_TEXT,pgNewString("Name"),		PG_WP_ALIGN,PG_A_LEFT,		PG_WP_SIZE,itemheight,		0);        wSizeBoxP = pgNewWidget(PG_WIDGET_LABEL,PG_DERIVE_INSIDE,wSizeBoxP);    pgSetWidget(PGDEFAULT,		PG_WP_TRANSPARENT,0,		PG_WP_FONT,dat->fHeading,		PG_WP_TEXT,pgNewString("Size"),		PG_WP_ALIGN,PG_A_LEFT,		PG_WP_SIZE,itemheight,		0);    wXyzBoxP = pgNewWidget(PG_WIDGET_LABEL,PG_DERIVE_INSIDE,wXyzBoxP);    pgSetWidget(PGDEFAULT,		PG_WP_TRANSPARENT,0,		PG_WP_FONT,dat->fHeading,		PG_WP_TEXT,pgNewString("Xyz"),		PG_WP_ALIGN,PG_A_LEFT,		PG_WP_SIZE,itemheight,		0);        /* List all the items */    for (p=names,i=0;i<count;p++,i++) {            /* Normally we'd use the default font, but directories and links       * get special fonts       */      font = 0;      if (S_ISLNK(p->st.st_mode))	font = dat->fLink;      /*       * IMPORTANT: Directory must override link for directory symlinks       *            to be followed. Currently the event loop checks the font       *            to see if an item is a file or directory       */      if (S_ISDIR(p->st.st_mode))	font = dat->fDirectory;            /* Create the file name widget */      wNameBoxP = pgNewWidget(PG_WIDGET_LISTITEM,PG_DERIVE_AFTER,wNameBoxP);      pgSetWidget(PGDEFAULT,		  PG_WP_TEXT,pgNewString(p->name),		  PG_WP_ALIGN,PG_A_LEFT,		  PG_WP_FONT,font,		  0);      pgSetPayload(PGDEFAULT,FILETAG);            /* Listitems normally have PG_EXEV_TOGGLE and PG_EXEV_EXCLUSIVE turned       * on. This makes them work basically like a radio button would.       * They automatically turn off other listitems in the same container,       * and they send an activate event when the mouse is pressed down.       *       * For directories, we don't care about hilighting (because we will redraw       * it all anyway) and we want an activate when the mouse is released       * after being pressed. In other words, a normal button.       * If it's a directory, turn off all the EXEVs       */      if (font == dat->fDirectory)	pgSetWidget(PGDEFAULT,		    PG_WP_EXTDEVENTS,0,		    0);            /* FIXME: We'd like some icons here to indicate file type...       * The icons themselves could be stored in a theme.       * Determining file types might be more complex.       */            /* Make a more human-readable size */       if (font)                                 /* Non-normal file? */	strcpy(buf," -");      else if (p->st.st_size > 1048576)         /* Megabytes? */	sprintf(buf,"%d.%02d M",		p->st.st_size / 1048576,		(p->st.st_size / 10485) % 100);      else if (p->st.st_size > 1024)            /* Kilobytes? */	sprintf(buf,"%d.%02d K",		p->st.st_size / 1024,		(p->st.st_size / 10) % 100);      else                                      /* Bytes? */	sprintf(buf,"%d",p->st.st_size);            /* Add another widget for size */      wSizeBoxP = pgNewWidget(PG_WIDGET_LISTITEM,PG_DERIVE_AFTER,wSizeBoxP);      pgSetWidget(PGDEFAULT,		  PG_WP_TEXT,pgNewString(buf),		  PG_WP_ALIGN,PG_A_LEFT,		  PG_WP_SIZE,itemheight,		  PG_WP_TRANSPARENT,0,		  PG_WP_STATE,PGTH_O_LISTITEM,		  0);      /* Add another widget for Xyz */      wXyzBoxP = pgNewWidget(PG_WIDGET_LISTITEM,PG_DERIVE_AFTER,wXyzBoxP);      pgSetWidget(PGDEFAULT,		  PG_WP_TEXT,pgNewString("Xyz"),		  PG_WP_ALIGN,PG_A_LEFT,		  PG_WP_SIZE,itemheight,		  PG_WP_TRANSPARENT,0,		  PG_WP_STATE,PGTH_O_LISTITEM,		  //PG_WP_ON,1,		  0);    }  }  /* Free the memory! */  free(names);}/*****************************************************************************/static int va_count_tag(LpgdvTag tag, va_list va){  int nb = 0;  for (;;) {    int t = va_arg(va, int);    int v = va_arg(va, int);    if(t==0 && v==0) break;    if(t==tag) ++nb;  }  return nb;}Parameters params;static LpgdvStatusva_parse_params(Parameters* *params,		MenuItemParams* *menu_item_params,		ColumnParams* *column_params,		va_list va){  LpgdvStatus status = LPGDV_OK;  int current_menu_item = -1;  int current_column = -1;  LpgdvColumnRenderF last_render_f = 0;  *params = 0;  *menu_item_params = 0;  *column_params = 0;  /* alloc mem for params */  *params = malloc(sizeof(Parameters));  if(*params == 0) {    status = LPGDV_ERROR_MEMORY;    goto done;  }  memset(*params, 0, sizeof(Parameters));  /* count the number of menu items */  (*params)->menu_items_nb = va_count_tag(LPGDV_MENU_ITEM_ADD, va);  /* count the number of columns */  (*params)->columns_nb = va_count_tag(LPGDV_COLUMN_ADD, va);  /* alloc mem */  if((*params)->menu_items_nb) {    size_t size = (*params)->menu_items_nb * sizeof(MenuItemParams);    *menu_item_params = malloc(size);    if(*menu_item_params) memset(*menu_item_params, 0, size);    else {      status = LPGDV_ERROR_MEMORY;      goto done;    }  }  if((*params)->columns_nb) {    size_t size = (*params)->columns_nb * sizeof(ColumnParams);    *column_params = malloc(size);    if(*column_params) memset(*column_params, 0, size);    else {      status = LPGDV_ERROR_MEMORY;      goto done;    }  }  /* parse tags */  for (;;) {    int tag = va_arg(va, int);    void* val = va_arg(va, void*);    if(tag==0 && val==0) break;    switch(tag) {    case LPGDV_TITLE:      (*params)->title = (const char*)val;      break;    case LPGDV_TITLE_VISIBLE:      (*params)->title_is_visible = (int)val;      break;    case LPGDV_LOCATION_VISIBLE:      (*params)->location_visible = (int)val;      break;    case LPGDV_LIST_HEADER_VISIBLE:      (*params)->list_is_header_visible = (int)val;      break;    case LPGDV_LIST_SORT_BY_COL_NR:      (*params)->list_sort_by_col_nr = (int)val;      break;    case LPGDV_LIST_INCLUDE_PARENT:      (*params)->list_do_include_parent = (int)val;      break;    case LPGDV_LIST_SORT:      (*params)->list_sort = (int)val;      break;    case LPGDV_LIST_GROUP:      (*params)->list_group = (int)val;      break;    case LPGDV_COLUMN_ADD:      current_column++;      (*column_params)[current_column].name = (const char*)val;      (*column_params)[current_column].column_render = last_render_f;      break;    case LPGDV_COLUMN_PLACE:      if(current_column<0) break;      (*column_params)[current_column].place = (int)val;      break;    case LPGDV_COLUMN_PLACE_AT:      if(current_column<0) break;      (*column_params)[current_column].place_at = (int)val;      break;    case LPGDV_COLUMN_RENDER_FUNC:      if(current_column<0) break;      (*column_params)[current_column].column_render = (LpgdvColumnRenderF)val;      last_render_f = (LpgdvColumnRenderF)val;      break;    case LPGDV_COLUMN_RENDER_PAYLOAD:      if(current_column<0) break;      (*column_params)[current_column].payload = (void*)val;      break;    case LPGDV_SELECTION_CHANGE_FUNC:      (*params)->selection_changed = (LpgdvSelectionChangedF)val;      break;    case LPGDV_ITEM_FOCUS_FUNC:      (*params)->item_focused = (LpgdvItemFocusedF)val;      break;    case LPGDV_ITEM_CLICK_FUNC:      (*params)->item_clicked = (LpgdvItemClickedF)val;      break;    case LPGDV_MENU_TITLE:      (*params)->menu_title = (const char*)val;      break;    case LPGDV_MENU_RENDERING:      (*params)->menu_rendering = (int)val;      break;    case LPGDV_MENU_ITEM_ADD:      current_menu_item++;      (*menu_item_params)[current_menu_item].name = (const char*)val;      break;    case LPGDV_MENU_ITEM_ENABLE_FUNC:      if(current_menu_item<0) break;      (*menu_item_params)[current_menu_item]	.menu_item_enable = (LpgdvMenuItemEnableF)val;      break;    case LPGDV_MENU_ITEMS_ENABLE_FUNC:      if(current_menu_item<0) break;      (*menu_item_params)	[current_menu_item].menu_items_enable = (LpgdvMenuItemsEnableF)val;      break;    case LPGDV_PROTOCOL_DEFAULT:      (*params)->protocol_default = (const char*)val;    case LPGDV_BROWSE_SITE_ENTER_FUNC:      (*params)->browse_site_enter = (LpgdvBrowseSiteEnterF)val;      break;    case LPGDV_BROWSE_SITE_LEAVE_FUNC:      (*params)->browse_site_leave = (LpgdvBrowseSiteLeaveF)val;      break;    case LPGDV_BROWSE_DIR_ENTER_FUNC:      (*params)->browse_dir_enter = (LpgdvBrowseDirEnterF)val;      break;    case LPGDV_BROWSE_DIR_LEAVE_FUNC:      (*params)->browse_dir_leave = (LpgdvBrowseDirLeaveF)val;      break;    case LPGDV_BROWSE_ITEM_NEXT_FUNC:      (*params)->browse_item_next = (LpgdvBrowseItemNextF)val;      break;    }  } done:  if(status!=LPGDV_OK) {    if(*params) free(*params);    if(*menu_item_params) free(*menu_item_params);    if(*column_params) free(*column_params);  }  return status;# undef BEFORE_VA}/*****************************************************************************//* Example Main function *//* this contains a lot of Micah's file dialog code, as example. It will   eventually disappear and serve as inspiration in the displets code.*/const char *_dirview(pgfilter filefilter, const char *pattern,		    const char *deffile, int flags, const char *title) {  pghandle wTB, wOk, wCancel, wUp;  struct pgEvent evt;  struct filepickdata dat;  int w,h;  char *p;  /* If this is the first invocation, use the current directory */  if (!dirview_dir[0])    getcwd(dirview_dir,FILEMAX);  /* Store picker data */  memset(&dat,0,sizeof(dat));  dat.flags = flags;  dat.filefilter = filefilter;  dat.pattern = pattern;  /********* Set up dialog box and top-level widgets */  pgEnterContext();  /* Size the dialog box ourselves. On a handheld this should   * be basically as large as possible. Just forcing it to take   * the whole screen at 1280x1024 would be a little awkward.   * Since using absolute coordinates would be a Bad Thing, size   * it relative to the default font.   *   * Usually the letter 'a' is 6x10 pixels, so multiplying by 66x40 would   * make the dialog box about 400x400. That will suck up the whole   * screen on 320x240 or 240x320 or smaller handhelds, but on a   * desktop-sized screen it will look very reasonable.   * Measuring relative to a font is useful, but make sure to use the   * PG_FSTYLE_FLUSH flag!   */  pgEnterContext();  pgSizeText(&w,&h,pgNewFont(NULL,0,PG_FSTYLE_DEFAULT | PG_FSTYLE_FLUSH),			     pgNewString("a"));  /* A good metric */  pgLeaveContext();#if 0  pgNewPopup(w*66,h*40);  pgNewWidget(PG_WIDGET_LABEL,0,0);  pgSetWidget(PGDEFAULT,	      PG_WP_TEXT,pgNewString(title),	      PG_WP_TRANSPARENT,0,	      /* The PG_WP_STATE property is fun :) */	      PG_WP_STATE,PGTH_O_LABEL_DLGTITLE,	      0);#endif  /* 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.   */  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);  }  wUp = pgNewWidget(PG_WIDGET_BUTTON,		    PG_DERIVE_INSIDE,dat.wDirectory);  pgSetWidget(PGDEFAULT,	      PG_WP_TEXT,pgNewString(".."),	      0);  dat.wDirectory = pgNewWidget(PG_WIDGET_BUTTON,0,0);  pgSetWidget(PGDEFAULT,	      PG_WP_SIDE,PG_S_ALL,	      PG_WP_EXTDEVENTS,PG_EXEV_PNTR_DOWN,	      0);  /********** Widgets */  wCancel = pgNewWidget(PG_WIDGET_BUTTON,PG_DERIVE_INSIDE,wTB);  pgSetWidget(PGDEFAULT,	      PG_WP_SIDE,PG_S_RIGHT,	      PG_WP_TEXT,pgNewString("Cancel"),	      PG_WP_HOTKEY,PGKEY_ESCAPE,	      PG_WP_BITMAP,pgThemeLookup(PGTH_O_POPUP_MESSAGEDLG,					 PGTH_P_ICON_CANCEL),	      PG_WP_BITMASK,pgThemeLookup(PGTH_O_POPUP_MESSAGEDLG,					  PGTH_P_ICON_CANCEL_MASK),	      0);  wOk = pgNewWidget(PG_WIDGET_BUTTON,PG_DERIVE_INSIDE,wTB);  pgSetWidget(PGDEFAULT,	      PG_WP_SIDE,PG_S_RIGHT,	      PG_WP_TEXT,pgNewString((flags&PG_FILE_SAVEBTN) ? 				     "Save" : "Open"),	      PG_WP_HOTKEY,PGKEY_RETURN,	      PG_WP_BITMAP,pgThemeLookup(PGTH_O_POPUP_MESSAGEDLG,					 PGTH_P_ICON_OK),	      PG_WP_BITMASK,pgThemeLookup(PGTH_O_POPUP_MESSAGEDLG,					  PGTH_P_ICON_OK_MASK),	      0);  /********** Run the dialog */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -