Exemple #1
0
/**
 * Compares two FileItems.
 *
 * Based on 'ustricmp' of Allegro. It makes sure that eg "foo.bar"
 * comes before "foo-1.bar", and also that "foo9.bar" comes before
 * "foo10.bar".
 */
int FileItem::compare(const FileItem& that) const
{
  if (IS_FOLDER(this)) {
    if (!IS_FOLDER(&that))
      return -1;
  }
  else if (IS_FOLDER(&that))
    return 1;

  {
    int c1, c2;
    int x1, x2;
    char *t1, *t2;
    const char* s1 = this->displayname.c_str();
    const char* s2 = that.displayname.c_str();

    for (;;) {
      c1 = utolower(ugetxc(&s1));
      c2 = utolower(ugetxc(&s2));

      if ((c1 >= '0') && (c1 <= '9') && (c2 >= '0') && (c2 <= '9')) {
        x1 = ustrtol(s1 - ucwidth(c1), &t1, 10);
        x2 = ustrtol(s2 - ucwidth(c2), &t2, 10);
        if (x1 != x2)
          return x1 - x2;
        else if (t1 - s1 != t2 - s2)
          return (t2 - s2) - (t1 - s1);
        s1 = t1;
        s2 = t2;
      }
      else if (c1 != c2) {
        if (!c1)
          return -1;
        else if (!c2)
          return 1;
        else if (c1 == '.')
          return -1;
        else if (c2 == '.')
          return 1;
        return c1 - c2;
      }

      if (!c1)
        return 0;
    }
  }

  return -1;
}
Exemple #2
0
std::string make_utf8_seq(int codepoint) {
    int num_bytes = ucwidth(codepoint);
    char byte_sequence[num_bytes + 1]; // +1 for terminating 0
    usetc(byte_sequence, codepoint);
    byte_sequence[num_bytes] = 0;
    return std::string(byte_sequence);
}
/* ustrfilecmp:
  *  ustricmp for filenames: makes sure that eg "foo.bar" comes before
  *  "foo-1.bar", and also that "foo9.bar" comes before "foo10.bar".
  */
static int ustrfilecmp(AL_CONST char *s1, AL_CONST char *s2)
{
    int c1, c2;
    int x1, x2;
    char *t1, *t2;
    
    for(;;)
    {
        c1 = utolower(ugetxc(&s1));
        c2 = utolower(ugetxc(&s2));
        
        if((c1 >= '0') && (c1 <= '9') && (c2 >= '0') && (c2 <= '9'))
        {
            x1 = ustrtol(s1 - ucwidth(c1), &t1, 10);
            x2 = ustrtol(s2 - ucwidth(c2), &t2, 10);
            
            if(x1 != x2)
                return x1 - x2;
            else if(t1 - s1 != t2 - s2)
                return (t2 - s2) - (t1 - s1);
                
            s1 = t1;
            s2 = t2;
        }
        else if(c1 != c2)
        {
            if(!c1)
                return -1;
            else if(!c2)
                return 1;
            else if(c1 == '.')
                return -1;
            else if(c2 == '.')
                return 1;
                
            return c1 - c2;
        }
        
        if(!c1)
            return 0;
    }
}
/* be_sys_find_resource:
 *  This is the same of the unix resource finder; it looks into the
 *  home directory and in /etc.
 */
int be_sys_find_resource(char *dest, AL_CONST char *resource, int size)
{
    char buf[256], tmp[256], *last;
    char *home = getenv("HOME");

    if (home) {
        /* look for ~/file */
        append_filename(buf, uconvert_ascii(home, tmp), resource, sizeof(buf));
        if (exists(buf)) {
            ustrzcpy(dest, size, buf);
            return 0;
        }

        /* if it is a .cfg, look for ~/.filerc */
        if (ustricmp(get_extension(resource), uconvert_ascii("cfg", tmp)) == 0) {
            ustrzcpy(buf, sizeof(buf) - ucwidth(OTHER_PATH_SEPARATOR), uconvert_ascii(home, tmp));
            put_backslash(buf);
            ustrzcat(buf, sizeof(buf), uconvert_ascii(".", tmp));
            ustrzcpy(tmp, sizeof(tmp), resource);
            ustrzcat(buf, sizeof(buf), ustrtok_r(tmp, ".", &last));
            ustrzcat(buf, sizeof(buf), uconvert_ascii("rc", tmp));
            if (file_exists(buf, FA_ARCH | FA_RDONLY | FA_HIDDEN, NULL)) {
                ustrzcpy(dest, size, buf);
                return 0;
            }
        }
    }

    /* look for /etc/file */
    append_filename(buf, uconvert_ascii("/etc/", tmp), resource, sizeof(buf));
    if (exists(buf)) {
        ustrzcpy(dest, size, buf);
        return 0;
    }

    /* if it is a .cfg, look for /etc/filerc */
    if (ustricmp(get_extension(resource), uconvert_ascii("cfg", tmp)) == 0) {
        ustrzcpy(buf, sizeof(buf), uconvert_ascii("/etc/", tmp));
        ustrzcpy(tmp, sizeof(tmp), resource);
        ustrzcat(buf, sizeof(buf), ustrtok_r(tmp, ".", &last));
        ustrzcat(buf, sizeof(buf), uconvert_ascii("rc", tmp));
        if (exists(buf)) {
            ustrzcpy(dest, size, buf);
            return 0;
        }
    }

    return -1;
}
Exemple #5
0
int d_agtk_list_proc(int msg, DIALOG *d, int c)
{
    if (msg == MSG_DRAW) {
        BITMAP *bmp = gui_get_screen();
        int height, listsize, i, len, bar, x, y, w;
        int fg_color, fg, bg;
        char *sel = (char *)d->dp2;
        char s[1024];

        (*(getfuncptr)d->dp)(-1, &listsize);
        height = (d->h-4) / text_height(font);
        bar = (listsize > height);
        w = (bar ? d->w-14 : d->w-3);
        fg_color = (d->flags & D_DISABLED) ? agtk_mg_color : d->fg;

        /* draw box contents */
        for (i=0; i<height; i++) {
            if (d->d2+i < listsize) {
                if (d->d2+i == d->d1) {
                    fg = white;
                    bg = blue;
                }
                else if ((sel) && (sel[d->d2+i])) {
                    fg = white;
                    bg = blue;
                }
                else {
                    fg = black;
                    bg = white;
                }
                usetc(s, 0);
                ustrncat(s, (*(getfuncptr)d->dp)(i+d->d2, NULL), sizeof(s)-ucwidth(0));
                x = d->x + 2;
                y = d->y + 2 + i*text_height(font);
                rectfill(bmp, x, y, x+7, y+text_height(font)-1, bg);
                x += 8;
                len = ustrlen(s);
                while (text_length(font, s) >= MAX(d->w - 1 - (bar ? 22 : 10), 1)) {
                    len--;
                    usetat(s, len, 0);
                }
                textout_ex(bmp, font, s, x, y, fg, bg);
                x += text_length(font, s);
                if (x <= d->x+w)
                    rectfill(bmp, x, y, d->x+w, y+text_height(font)-1, bg);
#if 0
                /* GTK puts a yellow box around the currently selected
                 * item, but it's quite ugly when we emulate it, so
                 * I'm disabling it. --pw
                 */
                if (d->d2+i == d->d1)
                    rect(bmp, x-text_length(font, s)-8, y, d->x+w, y+text_height(font)-1, yellow);
#endif
            }
            else {
                rectfill(bmp, d->x+2,  d->y+2+i*text_height(font),
                         d->x+w, d->y+1+(i+1)*text_height(font), white);
            }
        }

        if (d->y+2+i*text_height(font) <= d->y+d->h-3)
            rectfill(bmp, d->x+2, d->y+2+i*text_height(font),
                     d->x+w, d->y+d->h-3, white);

        /* draw frame, maybe with scrollbar */
        gtk_draw_scrollable_frame(d, listsize, d->d2, height);

        return D_O_K;
    }

    return d_list_proc(msg, d, c);
}
/* jwin_file_select_ex:
  *  Displays the JWin file selector, with the message as caption.
  *  Allows the user to select a file, and stores the selection in the
  *  path buffer, whose length in bytes is given by size and should have
  *  room for at least 80 characters. The files are filtered according to
  *  the file extensions in ext. Passing NULL includes all files, "PCX;BMP"
  *  includes only files with .PCX or .BMP extensions. Returns zero if it
  *  was closed with the Cancel button or non-zero if it was OK'd.
  */
int jwin_file_select_ex(AL_CONST char *message, char *path, AL_CONST char *ext, int size, int width, int height, FONT *title_font)
{
    static attrb_state_t default_attrb_state[ATTRB_MAX] = DEFAULT_ATTRB_STATE;
    int ret;
    char *p;
    char tmp[32];
    ASSERT(message);
    ASSERT(path);
    
    if(title_font)
    {
        file_selector[0].dp2=title_font;
    }
    
    if(width == OLD_FILESEL_WIDTH)
        width = 304;
        
#ifdef HAVE_DIR_LIST
        
    if(height == OLD_FILESEL_HEIGHT)
        height = 160;
        
#else
        
    if(height == OLD_FILESEL_HEIGHT)
        height = 188;
        
#endif
        
    /* for fs_dlist_proc() */
    ASSERT(size >= 4 * uwidth_max(U_CURRENT));
    
    usetc(updir, 0);
    file_selector[FS_WIN].dp = (char *)message;
    file_selector[FS_EDIT].d1 = size/uwidth_max(U_CURRENT) - 1;
    file_selector[FS_EDIT].dp = path;
    file_selector[FS_OK].dp = (void*)get_config_text("OK");
    file_selector[FS_CANCEL].dp = (void*)get_config_text("Cancel");
    
    /* Set default attributes. */
    memcpy(attrb_state, default_attrb_state, sizeof(default_attrb_state));
    
    /* Parse extension string. */
//  if (ext)// && ugetc(ext))
    {
        parse_extension_string(ext);
    }
    
    if(!ugetc(path))
    {
    
#ifdef HAVE_DIR_LIST
    
        int drive = _al_getdrive();
        
#else
        
        int drive = 0;
#endif
        
        _al_getdcwd(drive, path, size - ucwidth(OTHER_PATH_SEPARATOR));
        fix_filename_case(path);
        fix_filename_slashes(path);
        put_backslash(path);
    }
    
    clear_keybuf();
    
    do
    {
    }
    while(gui_mouse_b());
    
    file_selector[FS_TYPES].proc = fs_dummy_proc;
    enlarge_file_selector(width, height);
    ret = popup_zqdialog(file_selector, FS_EDIT);
    
    if(fext)
    {
        zc_free(fext);
        fext = NULL;
    }
    
    if(fext_p)
    {
        _al_free(fext_p);
        fext_p = NULL;
    }
    
    if((ret == FS_CANCEL) || (ret == FS_WIN) || (!ugetc(get_filename(path))))
        return FALSE;
        
    p = get_extension(path);
    
    if((!ugetc(p)) && (ext) && (!ustrpbrk(ext, uconvert_ascii(" ,;", tmp))))
    {
        size -= ((long)(size_t)p - (long)(size_t)path + ucwidth('.'));
        
        if(size >= uwidth_max(U_CURRENT) + ucwidth(0))          /* do not end with '.' */
        {
            p += usetc(p, '.');
            ustrzcpy(p, size, ext);
        }
    }
    
    return TRUE;
}
/* parse_extension_string:
  *  Parses the extension string, possibly containing attribute characters.
  */
static void parse_extension_string(AL_CONST char *ext)
{
    attrb_state_t state;
    char ext_tokens[32], attrb_char[32];
    char *last, *p, *attrb_p;
    int c, c2, i;
    
    i = 0;
    fext_size = 0;
    fext_p = NULL;
    attrb_p = NULL;
    
    if(!ext)
        return;
        
    fext = ustrdup(ext);
    
    /* Tokenize the extension string and record the pointers to the
      * beginning of each token in a dynamically growing array.
      * ???? We rely on the implementation of ustrtok_r() which writes
      * null characters in the string to delimit the tokens. Yuck.
      */
    c = usetc(ext_tokens, ' ');
    c += usetc(ext_tokens+c, ',');
    c += usetc(ext_tokens+c, ';');
    usetc(ext_tokens+c, 0);
    
    p = ustrtok_r(fext, ext_tokens, &last);
    
    if(p == NULL || !ugetc(p))
        return;
        
    do
    {
        /* Set of attribute characters. */
        if(ugetc(p) == '/')
        {
            attrb_p = p + ucwidth('/');
            continue;
        }
        
        /* Dynamically grow the array if needed. */
        if(i >= fext_size)
        {
            fext_size = (fext_size ? fext_size*2 : 2);
            fext_p = (char **)_al_sane_realloc(fext_p, fext_size * sizeof(char *));
        }
        
        /* Record a pointer to the beginning of the token. */
        fext_p[i++] = p;
        
    }
    while((p = ustrtok_r(NULL, ext_tokens, &last))!=NULL);
    
    /* This is the meaningful size now. */
    fext_size = i;
    
    if(attrb_p)
    {
        state = ATTRB_SET;
        c = usetc(attrb_char, 'r');
        c += usetc(attrb_char+c, 'h');
        c += usetc(attrb_char+c, 's');
        c += usetc(attrb_char+c, 'd');
        c += usetc(attrb_char+c, 'a');
        c += usetc(attrb_char+c, '+');
        c += usetc(attrb_char+c, '-');
        usetc(attrb_char+c, 0);
        
        /* Scan the string. */
        while((c = utolower(ugetx(&attrb_p)))!=0)
        {
            p = attrb_char;
            
            for(i = 0; (c2 = ugetx(&p))!=0; i++)
            {
                if(c == c2)
                {
                    if(i < ATTRB_MAX)
                        attrb_state[i] = state;
                    else
                        state = (i == ATTRB_MAX) ? ATTRB_SET : ATTRB_UNSET;
                        
                    break;
                }
            }
        }
    }
}
/* fs_flist_putter:
  *  Callback routine for for_each_file() to fill the file selector listbox.
  */
static int fs_flist_putter(AL_CONST char *str, int attrib, void *check_attrib)
{
    char *s, *ext, *name;
    int c, c2;
    
    s = get_filename(str);
    fix_filename_case(s);
    
    if(!(attrib & FA_DIREC))
    {
        /* Check if file extension matches. */
        if(fext_p)
        {
            ext = get_extension(s);
            
            for(c=0; c<fext_size; c++)
            {
                if(ustricmp(ext, fext_p[c]) == 0)
                    goto Next;
            }
            
            return 0;
        }
        
Next:

        /* Check if file attributes match. */
        if(check_attrib)
        {
            for(c=0; c<ATTRB_MAX; c++)
            {
                if((attrb_state[c] == ATTRB_SET) && (!(attrib & attrb_flag[c])))
                    return 0;
                    
                if((attrb_state[c] == ATTRB_UNSET) && (attrib & attrb_flag[c]))
                    return 0;
            }
        }
    }
    
    if((flist->size < FLIST_SIZE) && ((ugetc(s) != '.') || (ugetat(s, 1))))
    {
        int size = ustrsizez(s) + ((attrib & FA_DIREC) ? ucwidth(OTHER_PATH_SEPARATOR) : 0);
        name = (char *) zc_malloc(size);
        
        if(!name)
            return -1;
            
        ustrzcpy(name, size, s);
        
        if(attrib & FA_DIREC)
            put_backslash(name);
            
        /* Sort alphabetically with directories first. */
        for(c=0; c<flist->size; c++)
        {
            if(ugetat(flist->name[c], -1) == OTHER_PATH_SEPARATOR)
            {
                if(attrib & FA_DIREC)
                    if(ustrfilecmp(name, flist->name[c]) < 0)
                        break;
            }
            else
            {
                if(attrib & FA_DIREC)
                    break;
                    
                if(ustrfilecmp(name, flist->name[c]) < 0)
                    break;
            }
        }
        
        /* Shift in preparation for inserting the new entry. */
        for(c2=flist->size; c2>c; c2--)
            flist->name[c2] = flist->name[c2-1];
            
        /* Insert the new entry. */
        flist->name[c] = name;
        flist->size++;
    }
    
    return 0;
}
/* fs_edit_proc:
  *  Dialog procedure for the file selector editable string.
  */
static int fs_edit_proc(int msg, DIALOG *d, int c)
{
    char *s = (char *) d->dp;
    int size = (d->d1 + 1) * uwidth_max(U_CURRENT);           /* of s (in bytes) */
    int list_size;
    int found = 0;
    char b[1024], tmp[16];
    int ch, attr;
    int i;
    
    if(msg == MSG_START)
    {
        canonicalize_filename(b, s, sizeof(b));
        ustrzcpy(s, size, b);
    }
    
    if(msg == MSG_KEY)
    {
        if((!ugetc(s)) || (ugetat(s, -1) == DEVICE_SEPARATOR))
            ustrzcat(s, size, uconvert_ascii("./", tmp));
            
        canonicalize_filename(b, s, sizeof(b));
        ustrzcpy(s, size - ucwidth(OTHER_PATH_SEPARATOR), b);
        
        ch = ugetat(s, -1);
        
        if((ch != '/') && (ch != OTHER_PATH_SEPARATOR))
        {
            if(file_exists(s, FA_RDONLY | FA_HIDDEN | FA_DIREC, &attr))
            {
                if(attr & FA_DIREC)
                    put_backslash(s);
                else
                    return D_CLOSE;
            }
            else
                return D_CLOSE;
        }
        
        object_message(file_selector+FS_FILES, MSG_START, 0);
        
        /* did we `cd ..' ? */
        if(ustrlen(updir))
        {
            /* now we have to find a directory name equal to updir */
            for(i = 0; i<flist->size; i++)
            {
                if(!ustrcmp(updir, flist->name[i]))                 /* we got it ! */
                {
                    file_selector[FS_FILES].d1 = i;
                    /* we have to know the number of visible lines in the filelist */
                    /* -1 to avoid an off-by-one problem */
                    list_size = (file_selector[FS_FILES].h-4) / text_height(font) - 1;
                    
                    if(i>list_size)
                        file_selector[FS_FILES].d2 = i-list_size;
                    else
                        file_selector[FS_FILES].d2 = 0;
                        
                    found = 1;
                    break;                                            /* ok, our work is done... */
                }
            }
            
            /* by some strange reason, we didn't find the old directory... */
            if(!found)
            {
                file_selector[FS_FILES].d1 = 0;
                file_selector[FS_FILES].d2 = 0;
            }
        }
        
        /* and continue... */
        object_message(file_selector+FS_FILES, MSG_DRAW, 0);
        object_message(d, MSG_START, 0);
        object_message(d, MSG_DRAW, 0);
        
        return D_O_K;
    }
    
    int allegro_lfn = ALLEGRO_LFN; //removes compiler warning
    
    if(msg == MSG_UCHAR)
    {
        if((c >= 'a') && (c <= 'z'))
        {
            if(!allegro_lfn)
                c = utoupper(c);
        }
        else if(c == '/')
        {
            c = OTHER_PATH_SEPARATOR;
        }
        else if(allegro_lfn)
        {
            if((c > 127) || (c < 32))
                return D_O_K;
        }
        else
        {
            if((c != OTHER_PATH_SEPARATOR) && (c != '_') &&
                    (c != DEVICE_SEPARATOR) && (c != '.') &&
                    ((c < 'A') || (c > 'Z')) && ((c < '0') || (c > '9')))
                return D_O_K;
        }
    }
    
    //   return _gui_edit_proc(msg, d, c);
    return jwin_edit_proc(msg, d, c);
}
Exemple #10
0
/* fs_flist_putter:
 *  Callback routine for for_each_file() to fill the file selector listbox.
 */
static void fs_flist_putter(AL_CONST char *str, int attrib, int param)
{
   char ext_tokens[32];
   char *s, *ext, *tok, *name;
   char tmp[512], tmp2[32];
   int c, c2, i, k, sign;

   /* attribute flags (rhsda order)
    * 0 = not required, 1 = must be set, -1 = must be unset
    */
   int attr_flag[5+5] = {
      0, -1, -1, 0, 0,
      FA_RDONLY, FA_HIDDEN, FA_SYSTEM, FA_DIREC, FA_ARCH
   };

   c = usetc(ext_tokens, ' ');
   c += usetc(ext_tokens+c, ',');
   c += usetc(ext_tokens+c, ';');
   usetc(ext_tokens+c, 0);

   s = get_filename(str);
   fix_filename_case(s);

   if (fext) {
      ustrcpy(tmp, fext);
      ustrtok(tmp, ext_tokens);
      c = (ustrtok(NULL, ext_tokens) ? 1 : 0);
      if (!c) {
	 if (!ustrchr(fext, '/'))
	    c = 1;
      }

      if (c && (!(attrib & FA_DIREC))) {
	 ustrcpy(tmp, fext);
	 ext = get_extension(s);
	 tok = ustrtok(tmp, ext_tokens);

	 while (tok) {
	    if (ustricmp(ext, tok) == 0)
	       break;

	    tok = ustrtok(NULL, ext_tokens);
	 }

	 if (!tok)
	    return;
      }

      c = usetc(ext_tokens, ' ');
      c += usetc(ext_tokens+c, ',');
      c += usetc(ext_tokens+c, ';');
      c += usetc(ext_tokens+c, '/');
      usetc(ext_tokens+c, 0);

      ustrcpy(tmp, fext);
      tok = ustrchr(tmp, '/');

      if (tok)
	 tok = ustrtok(tok, ext_tokens);

      if (tok) {
	 sign = 1;
	 c = usetc(tmp2, 'r');
	 c += usetc(tmp2+c, 'h');
	 c += usetc(tmp2+c, 's');
	 c += usetc(tmp2+c, 'd');
	 c += usetc(tmp2+c, 'a');
	 c += usetc(tmp2+c, '+');
	 c += usetc(tmp2+c, '-');
	 usetc(tmp2+c, 0);

	 /* scan the string */
	 i = 0;
	 while ((c = utolower(ugetat(tok, i)))) {
	    k = 0;
	    while ((c2 = ugetat(tmp2, k))!=0) {
	       if (c == c2) {
		  if (k<5) {
		     attr_flag[k] = sign;
		     break;
		  }
		  else
		     sign = (k==5) ? 1 : -1;
	       }
	       k++;
	    }
	    i++;
	 }
      }
   }

   /* check if file attributes match */
   if (!(attr_flag[3+5] & attrib)) {
      /* if not a directory, we check all attributes except FA_DIREC */
      for (c=0; c<5; c++) {
	 if (c == 3)
	    continue;
	 if ((attr_flag[c] == 1) && (!(attrib & attr_flag[c+5])))
	    return;
	 if ((attr_flag[c] == -1) && (attrib & attr_flag[c+5]))
	    return;
      }
   }
   else {
      /* if a directory, we check only FA_DIREC */
      if (attr_flag[3] == -1)
	 return;
   }

   if ((flist->size < FLIST_SIZE) && ((ugetc(s) != '.') || (ugetat(s, 1)))) {
      name = malloc(ustrsizez(s) + ((attrib & FA_DIREC) ? ucwidth(OTHER_PATH_SEPARATOR) : 0));
      if (!name)
	 return;

      for (c=0; c<flist->size; c++) {
	 if (ugetat(flist->name[c], -1) == OTHER_PATH_SEPARATOR) {
	    if (attrib & FA_DIREC)
	       if (ustrfilecmp(s, flist->name[c]) < 0)
		  break;
	 }
	 else {
	    if (attrib & FA_DIREC)
	       break;
	    if (ustrfilecmp(s, flist->name[c]) < 0)
	       break;
	 }
      }

      for (c2=flist->size; c2>c; c2--)
	 flist->name[c2] = flist->name[c2-1];

      flist->name[c] = name;
      ustrcpy(flist->name[c], s);

      if (attrib & FA_DIREC)
	 put_backslash(flist->name[c]);

      flist->size++;
   }
}