📄 fileselect.c
字号:
/* * fileselect.c - SDL widget set in C * * Copyright 2004 by Jeffery L. Post * theposts<AT>pacbell<DOT>net * Version 0.0.3 - 11/26/04 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <dirent.h>#include <sys/stat.h>#include <unistd.h>#include <string.h>#include <ctype.h>#include <errno.h>#include "widgets.h"#define MAX_LEN 256#define DEFAULT_FS_WIDTH 500#define DIRLIST_X_OFFSET 10#define DIRLIST_Y_OFFSET 40#define FILELIST_Y_OFFSET 40typedef struct fileList { char *name; struct fileList *next;} FILELIST;extern SDL_Surface *screen;// Prototypesvoid cancelCB(SDL_Event *event, BUTTON *b);void okCB(SDL_Event *event, BUTTON *b);void dirEntryCB(SDL_Event *event, BUTTON *b);void dirSliderCB(SDL_Event *event, VSLIDER *vs);void fileEntryCB(SDL_Event *event, BUTTON *b);void fileSliderCB(SDL_Event *event, VSLIDER *vs);void adjustFileSlider(int amount);FILELIST *getDirectories(void);FILELIST *getFiles(char *pattern[]);void freeList(FILELIST *list);int getListCount(FILELIST *list);int ismatch(char *pattern, char *string);FILELIST *sortList(FILELIST *list);FILELIST *mergeList(FILELIST *a, FILELIST *b);// Global varsint maxWinWidth;int maxWinHeight;char *wildcardName[] = { "*.*", NULL};char currentDir[256];char *selectedFile = NULL;FILELIST *dirList, *fileList;FILELIST *list;LABEL *lab = NULL;BUTTON *btn = NULL;TEXTBOX *dirBox = NULL;VSLIDER *dirSlider = NULL;TEXTBOX *fileBox = NULL;VSLIDER *fileSlider = NULL;BUTTON *cancelBtn = NULL;BUTTON *okBtn = NULL;int fileCount, dirCount;int fileListXOffset;int ListWidth;int ListHeight;int pageCount;bool closeFS;int lastActive = 0;int dirIndex;int dirOffset;int fileIndex;int fileOffset;char currentFileName[256];char currentDirName[256];char **filePattern;FILELIST *listHead, *listTail;int listTerminator = -2;WINDOW *filesel = NULL;//// Select file widget.// template is a wildcard spec, or NULL for all files.// path is directory to search, or NULL for current directory.//// Returns a string with the filename selected by the user,// NULL if no file was selected, or -1 if main screen exited// while in the file selector.//char *fileSelect(char *pattern[], char *path){ int x, w; SDL_Event event; closeFS = FALSE; dirIndex = -1; fileIndex = -1; selectedFile = NULL; fileCount = dirCount = 0; dirOffset = fileOffset = 0; if (!pattern) filePattern = wildcardName; else filePattern = pattern; getcwd(currentDir, 255); if (!filesel) { maxWinWidth = screen->w; maxWinHeight = screen->h; if (maxWinWidth > DEFAULT_FS_WIDTH + 20) w = DEFAULT_FS_WIDTH; else w = maxWinWidth - 20; filesel = newWindow(10, 10, w, maxWinHeight - 20, black, lgray, white, gray); ListHeight = filesel->h - (DIRLIST_Y_OFFSET + 10) - FONT_HEIGHT; ListWidth = w / 2 - 40; fileListXOffset = w / 2 + 6; pageCount = ListHeight / FONT_HEIGHT - 3; lab = newLabel(0, 0, black, lgray, white, gray, currentDir); lab->w = filesel->w; addLabel(filesel, lab, TRUE); btn = newButton(DIRLIST_X_OFFSET, DIRLIST_Y_OFFSET - (FONT_HEIGHT + 3), black, lgray, white, gray, " Directories "); addButton(filesel, btn, TRUE); btn = newButton(fileListXOffset, FILELIST_Y_OFFSET - (FONT_HEIGHT + 3), black, lgray, white, gray, " Files "); addButton(filesel, btn, TRUE); dirBox = newTextBox(DIRLIST_X_OFFSET, DIRLIST_Y_OFFSET, ListWidth, ListHeight, black, white, lgray, gray); attachCallBack(dirBox, SDL_MOUSEBUTTONDOWN, (void *) &dirEntryCB); fileBox = newTextBox(fileListXOffset, FILELIST_Y_OFFSET, ListWidth, ListHeight, black, white, lgray, gray); attachCallBack(fileBox, SDL_MOUSEBUTTONDOWN, (void *) &fileEntryCB); addTextBox(filesel, dirBox); addTextBox(filesel, fileBox); dirSlider = newVSlider(DIRLIST_X_OFFSET + ListWidth + 5, DIRLIST_Y_OFFSET + 1, 15, ListHeight - 2, lgray, lgray, white, gray, 0, 0); attachCallBack(dirSlider, SDL_MOUSEBUTTONDOWN, (void *) &dirSliderCB); attachCallBack(dirSlider, SDL_MOUSEMOTION, (void *) &dirSliderCB); attachCallBack(dirSlider, SLIDER_AUTO_CALLBACK, (void *) &dirSliderCB); addVSlider(filesel, dirSlider); fileSlider = newVSlider(fileListXOffset + ListWidth + 5, FILELIST_Y_OFFSET + 1, 15, ListHeight - 2, lgray, lgray, white, gray, 0, 0); attachCallBack(fileSlider, SDL_MOUSEBUTTONDOWN, (void *) &fileSliderCB); attachCallBack(fileSlider, SDL_MOUSEMOTION, (void *) &fileSliderCB); attachCallBack(fileSlider, SLIDER_AUTO_CALLBACK, (void *) &fileSliderCB); addVSlider(filesel, fileSlider); x = DIRLIST_X_OFFSET + ListWidth / 2 - 5 * FONT_WIDTH; cancelBtn = newButton(x, maxWinHeight - (FONT_HEIGHT * 3), black, lgray, white, black, " Cancel "); attachCallBack(cancelBtn, SDL_MOUSEBUTTONDOWN, (void *) &cancelCB); x = fileListXOffset + ListWidth / 2 - 4 * FONT_WIDTH; okBtn = newButton(x, maxWinHeight - (FONT_HEIGHT * 3), black, lgray, white, black, " Ok "); attachCallBack(okBtn, SDL_MOUSEBUTTONDOWN, (void *) &okCB); addButton(filesel, cancelBtn, TRUE); addButton(filesel, okBtn, TRUE); listHead = (FILELIST *) malloc(sizeof(FILELIST)); listHead->name = NULL; listHead->next = NULL; listTail = (FILELIST *) malloc(sizeof(FILELIST)); listTail->name = (char *) &listTerminator; listTail->next = listTail; } fileSlider->position = 0; dirSlider->position = 0; dirList = getDirectories(); if (dirList) { dirCount = getListCount(dirList); dirSlider->range = dirCount; if (dirCount < 20) dirSlider->change = 1; else dirSlider->change = 20; if (dirCount) { dirList = sortList(dirList); list = dirList; while (list) { addText(dirBox, list->name); list = list->next; } } } fileList = getFiles(filePattern); if (fileList) { fileCount = getListCount(fileList); fileSlider->range = fileCount; if (fileCount < 20) fileSlider->change = 1; else fileSlider->change = 20; if (fileCount) { fileList = sortList(fileList); list = fileList; while (list) { addText(fileBox, list->name); list = list->next; } } } popUpWidget(filesel); updateScreen(); while (!closeFS) { SDL_UpdateRect(screen, 0, 0, 0, 0); if (!SDL_PollEvent(NULL)) SDL_WaitEvent(NULL); while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_MOUSEBUTTONDOWN: processCB(&event); break; case SDL_MOUSEBUTTONUP: processCB(&event); dirSlider->drag = FALSE; dirSlider->state = MOUSE_NOT_IN_SLIDER; fileSlider->drag = FALSE; fileSlider->state = MOUSE_NOT_IN_SLIDER; if (!closeFS) { popUpWidget(filesel); updateScreen(); } break; case SDL_MOUSEMOTION: processCB(&event); SDL_UpdateRect(screen, 0, 0, 0, 0); while (SDL_PollEvent(&event)) { if (event.type != SDL_MOUSEMOTION) { if (event.type == SDL_MOUSEBUTTONUP) { dirSlider->drag = FALSE; dirSlider->state = MOUSE_NOT_IN_SLIDER; fileSlider->drag = FALSE; fileSlider->state = MOUSE_NOT_IN_SLIDER; if (!closeFS) { popUpWidget(filesel); updateScreen(); } } SDL_PushEvent(&event); break; } } break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_UP: adjustFileSlider(-1); break; case SDLK_DOWN: adjustFileSlider(1); break; case SDLK_PAGEUP: adjustFileSlider(-pageCount); break; case SDLK_PAGEDOWN: adjustFileSlider(pageCount); break; default: break; } break; case TIMER_EVENT: if (!closeFS && (topWidget == dirSlider || topWidget == fileSlider)) processCB(&event); break; case SDL_QUIT: closeFS = TRUE; selectedFile = (char *) -1; pushDownWidget(filesel); break; } } } if (fileList) freeList(fileList); if (dirList) freeList(dirList); removeTList(dirBox); removeTList(fileBox); pushDownWidget(filesel); return selectedFile;}void adjustFileSlider(int amount){ int pos, pc, loc; int *offset, *count; VSLIDER *vs; TEXTBOX *box; if (((WIDGET *) topWidget)->p.type == AlertType) return; if (!lastActive) { vs = fileSlider; box = fileBox; offset = (int *) &fileOffset; count = (int *) &fileCount; } else { vs = dirSlider; box = dirBox; offset = (int *) &dirOffset; count = (int *) &dirCount; } loc = *offset + amount; if (loc < 0) loc = 0; else if (loc >= *count) loc = *count - 1; *offset = loc; pc = (loc * 100) / *count; pos = (pc * vs->h) / 100; vs->position = pos; setTListEntry(box, loc); showWidget(box); showWidget(vs);}void cancelCB(SDL_Event *event, BUTTON *b){ if (((WIDGET *) topWidget)->p.type == AlertType) return; closeFS = TRUE; pushDownWidget(filesel); selectedFile = NULL;}void okCB(SDL_Event *event, BUTTON *b){ if (((WIDGET *) topWidget)->p.type == AlertType) return; closeFS = TRUE; pushDownWidget(filesel); if (fileIndex >= 0) { strcpy(currentFileName, currentDir); strcat(currentFileName, "/"); strcat(currentFileName, getText(fileBox, fileIndex + 1)); selectedFile = (char *) ¤tFileName; } else selectedFile = NULL;}void dirSliderCB(SDL_Event *event, VSLIDER *vs){ int loc; if (((WIDGET *) topWidget)->p.type == AlertType) return; lastActive = 1; loc = dirSlider->offset; if (loc < 0) loc = 0; else if (loc >= dirCount) loc = dirCount - 1; setTListEntry(dirBox, loc); dirOffset = loc;}void fileSliderCB(SDL_Event *event, VSLIDER *vs){ int loc; if (((WIDGET *) topWidget)->p.type == AlertType) return; lastActive = 0; loc = fileSlider->offset; if (loc < 0) loc = 0; else if (loc >= fileCount) loc = fileCount - 1; setTListEntry(fileBox, loc); fileOffset = loc;}void dirEntryCB(SDL_Event *event, BUTTON *b){ int x, y, xlim, ylim, mx, my, index; if (((WIDGET *) topWidget)->p.type == AlertType) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -