?? rfsel.c
字號:
/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The file selector. * * By Shawn Hargreaves. * * Guilherme Silveira and Theuzifan Sumachingun both independently * modified it to only list valid drive letters. * * Peter Pavlovic modified it not to list the logical drives, such * as the b: drive assigned as a logical drive for a: on single * floppy disk drive equipped systems and improved the browsing * through directories. * * Peter Wang and Eric Botcazou modified it to stretch to screen and * font sizes. * * See readme.txt for copyright information. */#include <allegro.h>// These 2 files must be included before raine.h because of a collision !!!#if defined ALLEGRO_WINDOWS #include "winalleg.h"#endif#include <errno.h>#include <stdlib.h>#include <string.h>#ifndef RAINE_UNIX#ifndef RAINE_WIN32#include <unistd.h>#endif#endif#include <sys/stat.h>#include <limits.h>#include <ctype.h>#include <fcntl.h>#ifdef DJGPP#include <dir.h>#endif#include "raine.h"#include "rgui.h"#include "rguiproc.h"#ifndef _USE_LFN#define _USE_LFN 0#endif#if (DEVICE_SEPARATOR != 0) && (DEVICE_SEPARATOR != '\0') #define HAVE_DIR_LIST#endifstatic int fs_edit_proc(int, DIALOG *, int );static int fs_flist_proc(int, DIALOG *, int );static char *fs_flist_getter(int, int *);#ifdef HAVE_DIR_LISTstatic int fs_dlist_proc(int, DIALOG *, int );static char *fs_dlist_getter(int, int *);#endif#define FLIST_SIZE 2048typedef struct FLIST{ char dir[512]; int size; char *name[FLIST_SIZE];} FLIST;static FLIST *flist = NULL;static char updir[1024];static char *fext = NULL;DIALOG file_selector[] ={#ifdef HAVE_DIR_LIST /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ { d_raine_window_proc,0, 0, 305, 161, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 0, 0, 0, 0, NULL }, { x_ctext_proc, 152, 1, 1, 1, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 0, 0, 0, 0, NULL, NULL, NULL }, { x_raine_button_proc,8, 128, 48, 16, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 'O', D_EXIT, 0, 0, "&Okay" }, { x_raine_button_proc,64, 128, 48, 16, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 27, D_EXIT, 0, 0, "Cancel" }, { fs_edit_proc, 8, 116, 248, 8, GUI_COL_TEXT_1, 253, 0, 0, 79, 0, NULL }, { fs_flist_proc, 80, 20, 176, 92, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 0, D_EXIT, 0, 0, fs_flist_getter }, { fs_dlist_proc, 8, 20, 64, 92, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 0, D_EXIT, 0, 0, fs_dlist_getter }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },#else { d_raine_window_proc,0, 0, 305, 161, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 0, 0, 0, 0, NULL }, { x_ctext_proc, 152, 1, 1, 1, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 0, 0, 0, 0, NULL, NULL, NULL }, { x_raine_button_proc,8, 128, 48, 16, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 'O', D_EXIT, 0, 0, "&Okay" }, { x_raine_button_proc,64, 128, 48, 16, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 27, D_EXIT, 0, 0, "Cancel" }, { fs_edit_proc, 8, 116, 248, 8, GUI_COL_TEXT_1, 253, 0, 0, 79, 0, NULL }, { fs_flist_proc, 80, 20, 176, 92, GUI_COL_TEXT_1, GUI_BOX_COL_MIDDLE, 0, D_EXIT, 0, 0, fs_flist_getter }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },#endif { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }};#define FS_FRAME 0#define FS_MESSAGE 1#define FS_OK 2#define FS_CANCEL 3#define FS_EDIT 4#define FS_FILES 5#ifdef HAVE_DIR_LIST /* not all platforms need a directory list */#define FS_DISKS 6#define FS_YIELD 7/* drive_exists: * Checks whether the specified drive is valid. */static int drive_exists(int x){ #ifdef ALLEGRO_DOS /* DOS implementation */ unsigned int old; int ret = FALSE; __dpmi_regs r; /* get actual drive */ r.h.ah = 0x19; __dpmi_int(0x21, &r); old = r.h.al; /* see if drive x is assigned as a valid drive */ r.h.ah = 0x0E; r.h.dl = x; __dpmi_int(0x21, &r); r.h.ah = 0x19; __dpmi_int(0x21, &r); if (r.h.al == x) { /* ok, now check if it is a logical drive or not... */ r.x.ax = 0x440E; r.h.bl = x+1; __dpmi_int(0x21, &r); if ((r.x.flags & 1) || /* call failed */ (r.h.al == 0) || /* has no logical drives */ (r.h.al == (x+1))) /* not a logical drive */ ret = TRUE; } /* now we set the old drive */ r.h.ah = 0x0E; r.h.dl = old; __dpmi_int(0x21, &r); return ret; #elif defined ALLEGRO_WINDOWS /* Windows implementation */ return GetLogicalDrives() & (1 << x); #elif defined ALLEGRO_MPW /* MacOs implementation */ return GetLogicalDrives() & (1 << x); #else /* unknown platform */ return TRUE; #endif}/* count_disks: * Counts the number of valid drives. */static int count_disks(){ int c, i; c = 0; for (i=0; i<26; i++) if (drive_exists(i)) c++; return c;}/* get_x_drive: * Returns the drive letter matching the specified list index. */static int get_x_drive(int index){ int c, i; c = 0; for (i=0; i<26; i++) { if (drive_exists(i)) { c++; if (c==index) return i; } } return -1;}/* fs_dlist_getter: * Listbox data getter routine for the file selector disk list. */static char *fs_dlist_getter(int index, int *list_size){ static char d[8]; int pos, c; if (index < 0) { if (list_size) *list_size = count_disks(); return NULL; } c = 'A' + get_x_drive(index+1); if ((c < 'A') || (c > 'Z')) c = 'C'; pos = usetc(d, c); pos += usetc(d+pos, DEVICE_SEPARATOR); pos += usetc(d+pos, OTHER_PATH_SEPARATOR); usetc(d+pos, 0); return d;}/* fs_dlist_proc: * Dialog procedure for the file selector disk list. */static int fs_dlist_proc(int msg, DIALOG *d, int c){ char *s = file_selector[FS_EDIT].dp; int ret, i, temp; if (msg == MSG_START) { d->d1 = d->d2 = 0; temp = utoupper(ugetc(s)); if (((temp >= 'A') && (temp <= 'Z')) && (ugetat(s, 1) == DEVICE_SEPARATOR)) { temp -= 'A'; for (i=0; i<temp; i++) if (drive_exists(i)) d->d1++; } } ret = d_text_list_proc(msg, d, c); if (ret == D_CLOSE) { temp = 'A' + get_x_drive(d->d1+1); if ((temp < 'A') || (temp > 'Z')) temp = 'C'; s += usetc(s, temp); s += usetc(s, DEVICE_SEPARATOR); s += usetc(s, OTHER_PATH_SEPARATOR); usetc(s, 0); scare_mouse(); SEND_MESSAGE(file_selector+FS_FILES, MSG_START, 0); SEND_MESSAGE(file_selector+FS_FILES, MSG_DRAW, 0); SEND_MESSAGE(file_selector+FS_EDIT, MSG_START, 0); SEND_MESSAGE(file_selector+FS_EDIT, MSG_DRAW, 0); unscare_mouse(); return D_O_K; } return ret;}#else#define FS_YIELD 6#endif /* HAVE_DIR_LIST *//* fs_edit_proc: * Dialog procedure for the file selector editable string. */static int fs_edit_proc(int msg, DIALOG *d, int c){ char *s = d->dp; int list_size; int found = 0; char b[512]; int ch, attr; int i; if (msg == MSG_START) { fix_filename_path(b, s, sizeof(b)); ustrcpy(s, b); } if (msg == MSG_KEY) { if ((!ugetc(s)) || (ugetat(s, -1) == DEVICE_SEPARATOR)) ustrcat(s, uconvert_ascii("./", NULL)); fix_filename_path(b, s, sizeof(b)); ustrcpy(s, 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; } scare_mouse(); SEND_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... */ SEND_MESSAGE(file_selector+FS_FILES, MSG_DRAW, 0); SEND_MESSAGE(d, MSG_START, 0); SEND_MESSAGE(d, MSG_DRAW, 0); unscare_mouse(); return D_O_K; } 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 x_edit_proc(msg, d, c); }/* 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; }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -