/* Copyright (C) 1999 Southern Gold Development * * 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 "gview.h" /* Generic function for reading a line, terminated by \n from a file into * an allocated buffer. */ char *getLine(FILE *file) { char *tmp, in; int cnt = 0, retIn; if (feof(file)) return NULL; tmp = g_malloc(sizeof(char) * MAX_BUFF); retIn = fread((void *) &in, sizeof(char), 1, file); if (retIn != 1) { g_free(tmp); return NULL; } while ((in != '\n') && (cnt < MAX_BUFF)) { tmp[cnt] = in; cnt++; retIn = fread((void *) &in, sizeof(char), 1, file); if (retIn != 1) { g_free(tmp); return NULL; } } if (cnt == MAX_BUFF) { g_free(tmp); return NULL; } tmp[cnt] = '\0'; return tmp; } gint matchType(const gchar *fname, const gchar *reg) { regex_t *match, hold; regmatch_t results[1]; gint res; match = &hold; res = regcomp(match, reg+1, REG_EXTENDED | REG_ICASE); res = regexec(match, fname, 1, results, 0); regfree(match); return (res == 0); } void runExtern(sgview *view, const gchar *fname) { GList *list; sgtype *ent; gchar *app, **args, *tmpH; gint res, dx, scnt, cnt; list = view->extTools; res = FALSE; app = NULL; while ((!res) && (list->data)) { ent = (sgtype *) list->data; res = matchType(fname, ent->regex); if (res) app = ent->app; list = list->next; } if (app) { dx = fork(); if (dx == 0) { dx = fork(); if (dx == 0) { cnt = 0; for (scnt = 0; scnt < strlen(app); scnt++) { if (app[scnt] == ' ') { cnt++; } } cnt+= 3; args = g_malloc(sizeof(gchar *) * cnt); args[cnt - 1] = NULL; args[cnt - 2] = (gchar *) fname; if (cnt == 3) { args[0] = app; } else { tmpH = strsep(&app, " "); scnt = 0; while (tmpH) { args[scnt] = tmpH; tmpH = strsep(&app, " "); scnt++; } } execvp(args[0], args); _exit(0); } else { _exit(0); } } else { dx = wait(NULL); } } return; } void getExternal(sgview *view) { GList *extList; sgtype *extEnt; FILE *fHnd; gchar *buff, *home, *fName, *app, *extL, *regex, *work, *tmpR; extList = g_list_alloc(); extList->data = NULL; home = getenv("HOME"); fName = g_strconcat(home, "/.gview_assoc", NULL); fHnd = fopen(fName, "rb"); if (fHnd) { buff = getLine(fHnd); while (buff) { work = index(buff, ':'); work[0] = '\0'; extL = g_strdup(work+1); home = extL; extEnt = g_malloc(sizeof(sgtype)); extEnt->app = g_strdup(buff); regex = NULL; app = strsep(&extL, ","); while (app) { tmpR = g_strconcat("|\\.", app, regex, NULL); if (regex) g_free(regex); regex = tmpR; app = strsep(&extL, ","); } extEnt->regex = regex; extList = g_list_prepend(extList, (gpointer) extEnt); g_free(home); g_free(buff); buff = getLine(fHnd); } fclose(fHnd); } g_free(fName); view->extTools = extList; } void genRegexComp(sgview *view) { GList *list; sgtype *ext; gchar *patt, *fpatt, *hold; regex_t *regC; gint res; list = view->extTools; patt = NULL; while (list->data) { ext = (sgtype *) list->data; hold = g_strconcat(ext->regex, patt, NULL); if (patt) g_free(patt); patt = hold; list = list->next; } fpatt = g_strconcat(MATCH_REGEX, patt, NULL); regC = g_malloc(sizeof(regex_t)); res = regcomp(regC, fpatt, REG_EXTENDED | REG_ICASE); view->isImg = regC; if (patt) { regC = g_malloc(sizeof(regex_t)); res = regcomp(regC, patt+1, REG_EXTENDED | REG_ICASE); view->isExt = regC; g_free(patt); } else view->isExt = NULL; g_free(fpatt); } gshort getDepth(const gchar *path) { gshort cnt, depth; depth = -1; cnt = 0; while (path[cnt] != '\0') { if (path[cnt] == '/') { depth++; } cnt++; } return depth; } gint valcomp(gconstpointer a, gconstpointer b) { return strcmp((const char *) a, (const char *) b); } gint isImage(const sgview *view, const gchar *fname) { regmatch_t results[1]; gint res; res = regexec(view->isImg, fname, 1, results, 0); return (res == 0); } gint isExtern(const sgview *view, const gchar *fname) { regmatch_t results[1]; gint res; res = 1; if (view->isExt) res = regexec(view->isExt, fname, 1, results, 0); return (res == 0); } void gloaddir(sgview *view) { DIR *dir; gchar *data[4], *fqpn, *fname; struct dirent *file; struct stat buff; gint err, cnt; gshort depth; GList *dlist, *flist, *wlist; /* Fix currPath if broken */ if (view->currPath[strlen(view->currPath) - 1] != '/') { fname = g_strconcat(view->currPath, "/", NULL); g_free(view->currPath); view->currPath = fname; fname = NULL; } dir = opendir(view->currPath); if (!dir) return; /* store current directory position in the tree */ depth = getDepth(view->currPath); if (depth < MAX_DIR_STACK) { if (depth > view->depth) view->upDir[view->depth] = GTK_CLIST(view->clist)->focus_row; else { view->upDir[view->depth] = 0; } if (view->upDir[view->depth] == -1) { view->upDir[view->depth] = 0; } } /* First load all entries that are directories */ view->currFocus = -2; dlist = g_list_alloc(); dlist->data = ""; file = readdir(dir); while (file) { if ((strcmp(file->d_name, ".") != 0) && (strcmp(file->d_name, "..") != 0)) { fqpn = g_strconcat(view->currPath, file->d_name, NULL); err = stat(fqpn, &buff); if (buff.st_mode & S_IFDIR) if (!((strncmp (file->d_name, ".", 1) == 0) && (view->statCh & 0x01))) dlist = g_list_insert_sorted(dlist, (gpointer) fqpn, (GCompareFunc) valcomp); } file = readdir(dir); } dlist->data = NULL; /* Next, reset the dir handle and load all image files */ rewinddir(dir); flist = g_list_alloc(); flist->data = ""; file = readdir(dir); while (file) { if ((strcmp(file->d_name, ".") != 0) && (strcmp(file->d_name, "..") != 0) && (isImage(view, file->d_name))) { fqpn = g_strconcat(view->currPath, file->d_name, NULL); err = stat(fqpn, &buff); if (!(buff.st_mode & S_IFDIR)) flist = g_list_insert_sorted(flist, (gpointer) fqpn, (GCompareFunc) valcomp); } file = readdir(dir); } flist->data = NULL; closedir(dir); gtk_entry_set_text(GTK_ENTRY (view->dirlabel), view->currPath); gtk_clist_freeze(GTK_CLIST (view->clist)); gtk_clist_clear(GTK_CLIST (view->clist)); data[0] = _(".. (parent)"); data[1] = ""; data[2] = ""; data[3] = ""; /* Now insert all the entries into the clist, sorted and with directories first */ gtk_clist_append(GTK_CLIST (view->clist), data); data[1] = g_malloc(sizeof(gchar) * 20); wlist = dlist; while (wlist) { if (wlist->data) { err = stat((gchar *) wlist->data, &buff); strftime(data[1], 19, "%d %b %Y %Hh%M", localtime(&(buff.st_mtime))); fname = rindex((gchar *) wlist->data, '/'); fname++; if (!((strncmp(fname, ".", 1) == 0) && (view->statCh & 0x01))) { data[0] = g_strconcat(fname, "/", NULL); data[2] = ""; data[3] = ""; gtk_clist_append(GTK_CLIST(view->clist), data); } g_free(wlist->data); } wlist = wlist->next; } g_list_free(dlist); wlist = flist; while (wlist) { if (wlist->data) { err = stat((gchar *) wlist->data, &buff); strftime(data[1], 19, "%d %b %Y %Hh%M", localtime(&(buff.st_mtime))); fname = rindex((gchar *) wlist->data, '/'); fname++; data[0] = g_strdup(fname); data[2] = g_strdup_printf("%d kB", (int) buff.st_size / 1024); data[3] = NULL; if (strstr(fname, ".jpg") || strstr(fname, ".JPG") || strstr(fname, ".jpeg") || strstr(fname, ".JPEG")) data[3] = "JPEG"; if (strstr(fname, ".gif") || strstr(fname, ".GIF")) data[3] = "GIF"; if (strstr(fname, ".png") || strstr(fname, ".PNG")) data[3] = "PNG"; if (strstr(fname, ".bmp") || strstr(fname, ".BMP")) data[3] = "BMP"; if (strstr(fname, ".xpm") || strstr(fname, ".XPM")) data[3] = "XPM"; if (strstr(fname, ".tif") || strstr(fname, ".TIF") || strstr(fname, ".tiff") || strstr(fname, ".TIFF")) data[3] = "TIFF"; if (strstr(fname, ".ppm") || strstr(fname, ".PPM")) data[3] = "PPM"; if (strstr(fname, ".ps") || strstr(fname, ".PS")) data[3] = "PS"; if (isExtern(view, fname)) data[3] = "EXT"; if (data[3]) gtk_clist_append(GTK_CLIST (view->clist), data); g_free(data[0]); g_free(data[2]); g_free(wlist->data); } wlist = wlist->next; } g_list_free(flist); g_free(data[1]); gtk_clist_thaw(GTK_CLIST (view->clist)); if (depth < MAX_DIR_STACK) { view->depth = depth; gtk_clist_select_row(GTK_CLIST (view->clist), view->upDir[depth], 0); GTK_CLIST (view->clist)->focus_row = view->upDir[depth]; gtk_clist_moveto(GTK_CLIST (view->clist), view->upDir[depth], 0, 0.5, 0.5); } else { gtk_clist_select_row(GTK_CLIST (view->clist), 0, 0); GTK_CLIST (view->clist)->focus_row = 0; gtk_clist_moveto(GTK_CLIST (view->clist), 0, 0, 0.5, 0.5); } for (cnt = view->depth + 1; cnt < MAX_DIR_STACK; cnt++) view->upDir[cnt] = 0; } void unlinkFile(sgview *view, const gchar *file) { gchar *wdir; wdir = g_strconcat(view->currPath, file, NULL); unlink(wdir); g_free(wdir); } void delFile(GtkWidget *widget, gpointer data) { ren *delD; gchar *file; GList *selList; gint row, cnt; delD = (ren *) data; if (GTK_CLIST (delD->view->clist)->focus_row == -1) return; cnt = 0; row = GTK_CLIST (delD->view->clist)->focus_row; if (GTK_CLIST (delD->view->clist)->selection) { selList = GTK_CLIST (delD->view->clist)->selection; while (selList) { gtk_clist_get_text(GTK_CLIST (delD->view->clist), (int) selList->data, 0, &file); if ((strcmp(file, _(".. (parent)")) != 0) && (file[strlen(file) - 1] != '/')) { unlinkFile(delD->view, file); cnt++; } selList = selList->next; } } else { gtk_clist_get_text(GTK_CLIST (delD->view->clist), GTK_CLIST(delD->view->clist)->focus_row, 0, &file); if ((strcmp(file, _(".. (parent)")) != 0) && (file[strlen(file) - 1] != '/')) { unlinkFile(delD->view, file); cnt++; } } gloaddir(delD->view); row -= (cnt - 1); if (row >= GTK_CLIST (delD->view->clist)->rows) row--; gtk_clist_freeze(GTK_CLIST (delD->view->clist)); gtk_clist_unselect_row(GTK_CLIST (delD->view->clist), 0, 0); gtk_clist_select_row(GTK_CLIST (delD->view->clist), row, 0); gtk_clist_moveto(GTK_CLIST (delD->view->clist), row, 0, 0.5, 0.5); GTK_CLIST (delD->view->clist)->focus_row = row; gtk_clist_thaw(GTK_CLIST (delD->view->clist)); gtk_widget_destroy(delD->rsp); } void cancelFile(GtkWidget *widget, gpointer data) { gtk_widget_destroy(((ren *)data)->rsp); } void killFile (GtkWidget *widget, gpointer data) { ren *delD; delD = (ren *)data; delD->view = NULL; g_free(delD); } void menuDelete(GtkWidget *widget, gpointer data) { sgview *view; GtkWidget *rsp, *hbox, *fix, *lbl; ren *delD; view = (sgview *) data; if (GTK_CLIST (view->clist)->focus_row == -1) return; delD = g_malloc(sizeof(ren)); delD->view = view; rsp = gtk_window_new(GTK_WINDOW_DIALOG); delD->rsp = rsp; gtk_window_set_title(GTK_WINDOW (rsp), _("Delete File?")); gtk_window_set_policy(GTK_WINDOW (rsp), FALSE, FALSE, FALSE); gtk_window_set_position(GTK_WINDOW (rsp), GTK_WIN_POS_MOUSE); gtk_widget_set_usize(GTK_WIDGET (rsp), 160, 80); gtk_window_set_modal(GTK_WINDOW (rsp), TRUE); gtk_signal_connect(GTK_OBJECT (rsp), "destroy", (GtkSignalFunc) killFile, (gpointer) delD); gtk_container_border_width(GTK_CONTAINER (rsp), 5); fix = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER (rsp), fix); if (GTK_CLIST (view->clist)->selection) { if ((GTK_CLIST (view->clist)->selection->next) || (GTK_CLIST (view->clist)->selection->prev)) lbl = gtk_label_new(_("Are you sure you want\nto delete these files?")); else lbl = gtk_label_new(_("Are you sure you want\nto delete this file?")); } else { lbl = gtk_label_new(_("Are you sure you want\nto delete this file?")); } gtk_widget_set_usize(GTK_WIDGET (lbl), 150, 40); gtk_fixed_put(GTK_FIXED (fix), lbl, 0, 0); gtk_widget_show(lbl); hbox = gtk_hbox_new(TRUE, 10); gtk_widget_set_usize(GTK_WIDGET (hbox), 150, 25); gtk_fixed_put(GTK_FIXED (fix), hbox, 0, 45); GTK_WINDOW (rsp)->focus_widget = gAddButtonBox(view, (gpointer) delD, GTK_BOX (hbox), _("Yes"), _("Delete this file"), (GtkSignalFunc) delFile); gAddButtonBox(view, (gpointer) delD, GTK_BOX (hbox), _("No"), _("Cancel file delete"), (GtkSignalFunc) cancelFile); gtk_widget_show(hbox); gtk_widget_show(fix); gtk_widget_show(rsp); } gint renFile(const gchar *old, const gchar *new, const gchar *path) { gchar *infile, *outfile; int res; infile = g_strconcat(path, old, NULL); outfile = g_strconcat(path, new, NULL); res = rename(infile, outfile); g_free(infile); g_free(outfile); return res; } void renameFile(GtkWidget *widget, gpointer data); gint renameKey(GtkWidget *widget, GdkEventKey *event, gpointer data) { ren *renD; renD = (ren *) data; switch (event->keyval) { case GDK_Return: case GDK_KP_Enter: renameFile(widget, data); break; case GDK_Escape: gtk_widget_destroy(renD->rsp); break; default: break; } return TRUE; } void renameFile(GtkWidget *widget, gpointer data) { ren *renD; gchar *nfile, *file; gint cnt, pos, res; renD = (ren *) data; gtk_clist_get_text(GTK_CLIST (renD->view->clist), GTK_CLIST(renD->view->clist)->focus_row, 0, &file); nfile = gtk_entry_get_text(GTK_ENTRY (renD->ent)); renFile(file, nfile, renD->view->currPath); gloaddir(renD->view); pos = -1; for (cnt = 0; cnt < GTK_CLIST (renD->view->clist)->rows; cnt++) { res = gtk_clist_get_text(GTK_CLIST (renD->view->clist), cnt, 0, &file); if (res == 1) { if (strcmp(nfile, file) == 0) { pos = cnt; break; } } } if (pos != -1) { gtk_clist_freeze(GTK_CLIST (renD->view->clist)); gtk_clist_unselect_row(GTK_CLIST (renD->view->clist), GTK_CLIST (renD->view->clist)->focus_row, 0); GTK_CLIST (renD->view->clist)->focus_row = pos; gtk_clist_moveto(GTK_CLIST (renD->view->clist), pos, 0, 0.5, 0.5); gtk_clist_select_row(GTK_CLIST (renD->view->clist), pos, 0); gtk_clist_thaw(GTK_CLIST (renD->view->clist)); } gtk_widget_destroy(renD->rsp); } void renDestroy(GtkWidget *widget, gpointer data) { ren *renD; renD = (ren *) data; renD->view = NULL; g_free(renD); } void menuRename(GtkWidget *widget, gpointer data) { sgview *view; ren *renD; gchar *file; GtkWidget *win, *ent, *fix, *hbox; view = (sgview *) data; if (GTK_CLIST (view->clist)->focus_row == -1) return; gtk_clist_get_text(GTK_CLIST (view->clist), GTK_CLIST(view->clist)->focus_row, 0, &file); renD = g_malloc(sizeof(ren) * 1); renD->view = view; win = gtk_window_new(GTK_WINDOW_DIALOG); renD->rsp = win; gtk_window_set_title(GTK_WINDOW (win), _("Rename File")); gtk_window_set_policy(GTK_WINDOW (win), FALSE, FALSE, FALSE); gtk_container_border_width(GTK_CONTAINER (win), 5); gtk_widget_set_usize(GTK_WIDGET (win), 160, 70); gtk_window_set_modal(GTK_WINDOW (win), TRUE); gtk_window_set_position(GTK_WINDOW (win), GTK_WIN_POS_MOUSE); gtk_signal_connect(GTK_OBJECT (win), "destroy", (GtkSignalFunc) renDestroy, (gpointer) renD); fix = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER (win), fix); ent = gtk_entry_new(); renD->ent = ent; gtk_widget_set_usize(GTK_WIDGET (ent), 150, 24); gtk_entry_set_text(GTK_ENTRY (ent), file); gtk_entry_select_region(GTK_ENTRY (ent), 0, -1); gtk_entry_set_editable(GTK_ENTRY (ent), TRUE); gtk_entry_set_position(GTK_ENTRY (ent), strlen(file)); gtk_fixed_put(GTK_FIXED (fix), ent, 0, 5); gtk_signal_connect(GTK_OBJECT (ent), "key_press_event", (GtkSignalFunc) renameKey, (gpointer) renD); gtk_widget_show(ent); hbox = gtk_hbox_new(TRUE, 10); gtk_widget_set_usize(GTK_WIDGET (hbox), 150, 25); gtk_fixed_put(GTK_FIXED (fix), hbox, 0, 35); gAddButtonBox(view, (gpointer) renD, GTK_BOX (hbox), _("Rename"), _("Rename file"), (GtkSignalFunc) renameFile); gAddButtonBox(view, (gpointer) renD, GTK_BOX (hbox), _("Cancel"), _("Cancel file rename"), (GtkSignalFunc) cancelFile); gtk_widget_show(hbox); gtk_widget_show(fix); gtk_widget_show(win); gtk_window_set_focus(GTK_WINDOW (win), GTK_WIDGET (ent)); } void sortRel(gchar **work) { gchar *currPwd, *twrk, *pwrk, *hold; gint cnt; currPwd = g_malloc(sizeof(gchar) * MAX_BUFF); getcwd(currPwd, MAX_BUFF); twrk = g_strdup(*work); hold = twrk; twrk += 3; cnt = 1; while (strncmp(twrk, "..", 2) == 0) { cnt++; twrk += 3; } while (cnt > 0) { pwrk = rindex(currPwd, '/'); if (pwrk) pwrk[0] = '\0'; cnt--; } *work = NULL; *work = g_strconcat(currPwd, "/", twrk, NULL); g_free(currPwd); }