#include /* * $Author: garbled $ * $Date: 2001/01/04 19:58:11 $ * $Revision: 1.1.1.1 $ */ /* * Declare file local prototypes. */ static BINDFN_PROTO(fselectAdjustScrollCB); static BINDFN_PROTO(completeFilenameCB); static BINDFN_PROTO(displayFileInfoCB); static char *expandFilename (char *filename); static void setPWD (CDKFSELECT *fselect); /* * Declare file local variables. */ extern char *GPasteBuffer; DeclareCDKObjects(my_funcs,Fselect); /* * This creates a file selection widget. */ CDKFSELECT *newCDKFselect (CDKSCREEN *cdkscreen, int xplace, int yplace, int height, int width, char *title, char *label, chtype fieldAttribute, chtype fillerChar, chtype highlight, char *dAttribute, char *fAttribute, char *lAttribute, char *sAttribute, boolean Box, boolean shadow) { /* Set up some variables. */ CDKFSELECT *fselect = newCDKObject(CDKFSELECT, &my_funcs); int parentWidth = getmaxx(cdkscreen->window); int parentHeight = getmaxy(cdkscreen->window); int boxWidth = width; int boxHeight = height; int xpos = xplace; int ypos = yplace; int entryWidth, x, labelLen, junk; chtype *chtypeString; /* * If the height is a negative value, the height will * be ROWS-height, otherwise, the height will be the * given height. */ boxHeight = setWidgetDimension (parentHeight, height, 0); /* * If the width is a negative value, the width will * be COLS-width, otherwise, the width will be the * given width. */ boxWidth = setWidgetDimension (parentWidth, width, 0); /* Rejustify the x and y positions if we need to. */ alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight); /* Make sure the box isn't too small. */ boxWidth = MAXIMUM (boxWidth, 15); boxHeight = MAXIMUM (boxHeight, 6); /* Make the file selector window. */ fselect->win = newwin (boxHeight + !!shadow, boxWidth + !!shadow, ypos, xpos); /* Is the window null? */ if (fselect->win == 0) { return (0); } keypad (fselect->win, TRUE); /* Set some variables. */ ScreenOf(fselect) = cdkscreen; fselect->parent = cdkscreen->window; fselect->dirAttribute = copyChar (dAttribute); fselect->fileAttribute = copyChar (fAttribute); fselect->linkAttribute = copyChar (lAttribute); fselect->sockAttribute = copyChar (sAttribute); fselect->highlight = highlight; fselect->fillerCharacter = fillerChar; fselect->fieldAttribute = fieldAttribute; fselect->boxHeight = boxHeight; fselect->boxWidth = boxWidth; fselect->fileCounter = 0; fselect->pwd = 0; fselect->exitType = vNEVER_ACTIVATED; ObjOf(fselect)->box = Box; fselect->shadow = shadow; /* Zero out the contents of the directory listing. */ for (x=0; x < MAX_ITEMS; x++) { fselect->dirContents[x] = 0; } /* Get the present working directory. */ setPWD(fselect); /* Get the contents of the current directory. */ setCDKFselectDirContents (fselect); /* Create the entry field in the selector. */ chtypeString = char2Chtype (label, &labelLen, &junk); freeChtype (chtypeString); entryWidth = boxWidth - labelLen - 2; fselect->entryField = newCDKEntry (cdkscreen, getbegx(fselect->win), getbegy(fselect->win), title, label, fieldAttribute, fillerChar, vMIXED, entryWidth, 0, 512, Box, FALSE); /* Make sure the widget was created. */ if (fselect->entryField == 0) { /* Clean up. */ freeCharList (fselect->dirContents, MAX_ITEMS); freeChar (fselect->pwd); freeChar (fselect->dirAttribute); freeChar (fselect->fileAttribute); freeChar (fselect->linkAttribute); freeChar (fselect->sockAttribute); deleteCursesWindow (fselect->win); return (0); } /* Set the lower left/right characters of the entry field. */ setCDKEntryLLChar (fselect->entryField, ACS_LTEE); setCDKEntryLRChar (fselect->entryField, ACS_RTEE); /* Define the callbacks for the entry field. */ bindCDKObject (vENTRY, fselect->entryField, KEY_UP, fselectAdjustScrollCB, fselect); bindCDKObject (vENTRY, fselect->entryField, KEY_PPAGE, fselectAdjustScrollCB, fselect); bindCDKObject (vENTRY, fselect->entryField, CONTROL('B'), fselectAdjustScrollCB, fselect); bindCDKObject (vENTRY, fselect->entryField, KEY_DOWN, fselectAdjustScrollCB, fselect); bindCDKObject (vENTRY, fselect->entryField, KEY_NPAGE, fselectAdjustScrollCB, fselect); bindCDKObject (vENTRY, fselect->entryField, CONTROL('F'), fselectAdjustScrollCB, fselect); bindCDKObject (vENTRY, fselect->entryField, KEY_TAB, completeFilenameCB, fselect); bindCDKObject (vENTRY, fselect->entryField, CONTROL('^'), displayFileInfoCB, fselect); /* Put the current working directory in the entry field. */ setCDKEntryValue (fselect->entryField, fselect->pwd); /* Create the scrolling list in the selector. */ fselect->scrollField = newCDKScroll (cdkscreen, getbegx(fselect->win), getbegy(fselect->win) + (fselect->entryField)->titleLines + 2, RIGHT, boxHeight - (fselect->entryField)->titleLines - 2, boxWidth, 0, fselect->dirContents, fselect->fileCounter, NONUMBERS, fselect->highlight, Box, FALSE); /* Set the lower left/right characters of the entry field. */ setCDKScrollULChar (fselect->scrollField, ACS_LTEE); setCDKScrollURChar (fselect->scrollField, ACS_RTEE); /* Register this baby. */ registerCDKObject (cdkscreen, vFSELECT, fselect); /* Return the file selector pointer. */ return (fselect); } /* * This erases the file selector from the screen. */ static void _eraseCDKFselect (CDKOBJS *object) { CDKFSELECT * fselect = (CDKFSELECT *)object; eraseCDKScroll (fselect->scrollField); eraseCDKEntry (fselect->entryField); eraseCursesWindow (fselect->win); } /* * This moves the fselect field to the given location. */ static void _moveCDKFselect (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag) { CDKFSELECT *fselect = (CDKFSELECT *)object; /* * If this is a relative move, then we will adjust where we want * to move to. */ if (relative) { xplace += getbegx(fselect->win); yplace += getbegy(fselect->win); } /* Adjust the window if we need to. */ alignxy (WindowOf(fselect), &xplace, &yplace, fselect->boxWidth, fselect->boxHeight); /* Move the window to the new location. */ moveCursesWindow(fselect->win, xplace, yplace); /* Move the sub-widgets. */ /* XXXX */ moveCDKEntry (fselect->entryField, xplace, yplace, relative, FALSE); moveCDKScroll (fselect->scrollField, xplace, yplace, relative, FALSE); /* Redraw the window, if they asked for it. */ if (refresh_flag) { drawCDKFselect (fselect, ObjOf(fselect)->box); } } /* * This draws the file selector widget. */ static void _drawCDKFselect (CDKOBJS *object, boolean Box GCC_UNUSED) { CDKFSELECT *fselect = (CDKFSELECT *)object; /* Draw in the entry field. */ drawCDKEntry (fselect->entryField, ObjOf(fselect->entryField)->box); /* Draw in the scroll field. */ drawCDKScroll (fselect->scrollField, ObjOf(fselect->scrollField)->box); } /* * This means you want to use the given file selector. It takes input * from the keyboard, and when it's done, it fills the entry info * element of the structure with what was typed. */ char *activateCDKFselect (CDKFSELECT *fselect, chtype *actions) { /* Declare local variables. */ chtype input = 0; char *ret = 0; /* Draw the widget. */ drawCDKFselect (fselect, ObjOf(fselect)->box); /* Check if 'actions' is null. */ if (actions == 0) { for (;;) { /* Get the input. */ wrefresh (fselect->entryField->fieldWin); input = wgetch (fselect->entryField->fieldWin); /* Inject the character into the widget. */ ret = injectCDKFselect (fselect, input); if (fselect->exitType != vEARLY_EXIT) { return ret; } } } else { int length = chlen (actions); int x =0; /* Inject each character one at a time. */ for (x=0; x < length; x++) { ret = injectCDKFselect (fselect, actions[x]); if (fselect->exitType != vEARLY_EXIT) { return ret; } } } /* Set the exit type and exit. */ fselect->exitType = vEARLY_EXIT; return 0; } /* * This injects a single character into the file selector. */ char *injectCDKFselect (CDKFSELECT *fselect, chtype input) { /* Declare local variables. */ char *filename; boolean file; /* Let the user play. */ filename = injectCDKEntry (fselect->entryField, input); /* Copy the entry field exitType to the fileselector. */ fselect->exitType = fselect->entryField->exitType; /* If we exited early, make sure we don't interpret it as a file. */ if (fselect->exitType == vEARLY_EXIT || fselect->exitType == vESCAPE_HIT) { return 0; } /* Can we change into the directory? */ file = chdir (filename); chdir (fselect->pwd); /* If it's not a directory, return the filename. */ if (file != 0 && errno == ENOTDIR) { /* It's a regular file, create the full path. */ fselect->pathname = copyChar (filename); /* Return the complete pathname. */ return (fselect->pathname); } else { /* Set the file selector information. */ setCDKFselect (fselect, filename, fselect->fieldAttribute, fselect->fillerCharacter, fselect->highlight, fselect->dirAttribute, fselect->fileAttribute, fselect->linkAttribute, fselect->sockAttribute, ObjOf(fselect)->box); /* Redraw the scrolling list. */ drawCDKScroll (fselect->scrollField, ObjOf(fselect->scrollField)->box); } /* Set the exit type and return a null pointer. */ fselect->exitType = vEARLY_EXIT; return 0; } /* * This function sets the information inside the file selector. */ void setCDKFselect (CDKFSELECT *fselect, char *directory, chtype fieldAttrib, chtype filler, chtype highlight, char *dirAttribute, char *fileAttribute, char *linkAttribute, char *sockAttribute, boolean Box GCC_UNUSED) { /* Declare local variables. */ CDKSCROLL *fscroll = fselect->scrollField; CDKENTRY *fentry = fselect->entryField; char *tempDir = 0; char *mesg[10], newDirectory[2000], temp[100]; int ret; /* Keep the info sent to us. */ fselect->fieldAttribute = fieldAttrib; fselect->fillerCharacter = filler; fselect->highlight = highlight; strcpy (newDirectory, directory); /* Set the attributes of the entry field/scrolling list. */ setCDKEntryFillerChar (fentry, filler); setCDKScrollHighlight (fscroll, highlight); /* Only do the directory stuff if the directory is not null. */ if (directory != 0) { /* Try to expand the directory if it starts with a ~ */ if (directory[0] == '~') { tempDir = expandFilename (directory); if (tempDir != 0) { strcpy (newDirectory, tempDir); freeChar (tempDir); } } /* Change directories. */ ret = chdir (newDirectory); if (ret != 0) { /* Beep at them. */ Beep(); /* Couldn't get into the directory, pop up a little message. */ sprintf (temp, "Could not change into %s", newDirectory); mesg[0] = copyChar (temp); #ifdef HAVE_STRERROR sprintf (temp, "%s", strerror(errno)); mesg[1] = copyChar (temp); #else mesg[1] = copyChar ("Unknown reason."); #endif mesg[2] = copyChar (" "); mesg[3] = copyChar ("Press Any Key To Continue."); /* Pop Up a message. */ popupLabel (ScreenOf(fselect), mesg, 4); /* Clean up some memory. */ freeCharList (mesg, 4); /* Get out of here. */ eraseCDKFselect (fselect); drawCDKFselect (fselect, ObjOf(fselect)->box); return; } } /* * If the information coming in is the same as the information * that is already there, there is no need to destroy it. */ if (fselect->pwd != directory) { setPWD(fselect); } if (fselect->fileAttribute != fileAttribute) { /* Remove the old pointer and set the new value. */ freeChar (fselect->fileAttribute); fselect->fileAttribute = copyChar (fileAttribute); } if (fselect->dirAttribute != dirAttribute) { /* Remove the old pointer and set the new value. */ freeChar (fselect->dirAttribute); fselect->dirAttribute = copyChar (dirAttribute); } if (fselect->linkAttribute != linkAttribute) { /* Remove the old pointer and set the new value. */ freeChar (fselect->linkAttribute); fselect->linkAttribute = copyChar (linkAttribute); } if (fselect->sockAttribute != sockAttribute) { /* Remove the old pointer and set the new value. */ freeChar (fselect->sockAttribute); fselect->sockAttribute = copyChar (sockAttribute); } /* Set the contents of the entry field. */ setCDKEntryValue (fentry, fselect->pwd); drawCDKEntry (fentry, ObjOf(fentry)->box); /* Get the directory contents. */ if (setCDKFselectDirContents (fselect) == 0) { Beep(); return; } /* Set the values in the scrolling list. */ setCDKScrollItems (fscroll, fselect->dirContents, fselect->fileCounter, FALSE); } /* * This creates a list of the files in the current directory. */ int setCDKFselectDirContents (CDKFSELECT *fselect) { /* Declare local variables. */ struct stat fileStat; char *dirList[MAX_ITEMS]; char temp[200], mode; int fileCount; int x = 0; /* Get the directory contents. */ fileCount = getDirectoryContents (fselect->pwd, dirList, MAX_ITEMS); if (fileCount == -1) { /* We couldn't read the directory. Return. */ return 0; } /* Clean out the old directory list. */ freeCharList (fselect->dirContents, fselect->fileCounter); fselect->fileCounter = fileCount; /* Set the properties of the files. */ for (x=0; x < fselect->fileCounter; x++) { /* Stat the file. */ lstat (dirList[x], &fileStat); /* Check the mode. */ mode = ' '; if (((fileStat.st_mode & S_IXUSR) != 0) || ((fileStat.st_mode & S_IXGRP) != 0) || ((fileStat.st_mode & S_IXOTH) != 0)) { mode = '*'; } /* Create the filename. */ switch (mode2Filetype(fileStat.st_mode)) { case 'l': sprintf (temp, "%s%s@", fselect->linkAttribute, dirList[x]); break; case '@': sprintf (temp, "%s%s&", fselect->sockAttribute, dirList[x]); break; case '-': sprintf (temp, "%s%s%c", fselect->fileAttribute, dirList[x], mode); break; case 'd': sprintf (temp, "%s%s/", fselect->dirAttribute, dirList[x]); break; default: sprintf (temp, "%s%c", dirList[x], mode); break; } fselect->dirContents[x] = copyChar (temp); /* Free up this piece of memory. */ freeChar (dirList[x]); } return 1; } char **getCDKFselectDirContents (CDKFSELECT *fselect, int *count) { (*count) = fselect->fileCounter; return fselect->dirContents; } /* * This sets the current directory of the file selector. */ int setCDKFselectDirectory (CDKFSELECT *fselect, char *directory) { /* Declare local variables. */ CDKENTRY *fentry = fselect->entryField; CDKSCROLL *fscroll = fselect->scrollField; int ret; /* * If the directory supplied is the same as what is already * there, return. */ if (fselect->pwd == directory) { return 1; } /* Try to chdir into the given directory. */ ret = chdir (directory); if (ret != 0) { return 0; } setPWD(fselect); /* Set the contents of the entry field. */ setCDKEntryValue (fentry, fselect->pwd); drawCDKEntry (fentry, ObjOf(fentry)->box); /* Get the directory contents. */ if (setCDKFselectDirContents (fselect) == 0) { return 0; } /* Set the values in the scrolling list. */ setCDKScrollItems (fscroll, fselect->dirContents, fselect->fileCounter, FALSE); return 1; } char *getCDKFselectDirectory (CDKFSELECT *fselect) { return fselect->pwd; } /* * This sets the filler character of the entry field. */ void setCDKFselectFillerChar (CDKFSELECT *fselect, chtype filler) { CDKENTRY *fentry = fselect->entryField; fselect->fillerCharacter = filler; setCDKEntryFillerChar (fentry, filler); } chtype getCDKFselectFillerChar (CDKFSELECT *fselect) { return fselect->fillerCharacter; } /* * This sets the highlight bar of the scrolling list. */ void setCDKFselectHighlight (CDKFSELECT *fselect, chtype highlight) { CDKSCROLL *fscroll = (CDKSCROLL *)fselect->scrollField; fselect->highlight = highlight; setCDKScrollHighlight (fscroll, highlight); } chtype getCDKFselectHighlight (CDKFSELECT *fselect) { return fselect->highlight; } /* * This sets the attribute of the directory attribute in the * scrolling list. */ void setCDKFselectDirAttribute (CDKFSELECT *fselect, char *attribute) { /* Make sure they are not one in the same. */ if (fselect->dirAttribute == attribute) { return; } /* Clean out the old attribute, and set the new. */ freeChar (fselect->dirAttribute); fselect->dirAttribute = copyChar (attribute); /* * We need to reset the contents of the scrolling * list using the new attribute. */ setCDKFselectDirContents (fselect); } char *getCDKFselectDirAttribute (CDKFSELECT *fselect) { return fselect->dirAttribute; } /* * This sets the attribute of the link attribute in the * scrolling list. */ void setCDKFselectLinkAttribute (CDKFSELECT *fselect, char *attribute) { /* Make sure they are not one in the same. */ if (fselect->linkAttribute == attribute) { return; } /* Clean out the old attribute, and set the new. */ freeChar (fselect->linkAttribute); fselect->linkAttribute = copyChar (attribute); /* * We need to reset the contents of the scrolling * list using the new attribute. */ setCDKFselectDirContents (fselect); } char *getCDKFselectLinkAttribute (CDKFSELECT *fselect) { return fselect->linkAttribute; } /* * This sets the attribute of the link attribute in the * scrolling list. */ void setCDKFselectSocketAttribute (CDKFSELECT *fselect, char *attribute) { /* Make sure they are not one in the same. */ if (fselect->sockAttribute == attribute) { return; } /* Clean out the old attribute, and set the new. */ freeChar (fselect->sockAttribute); fselect->sockAttribute = copyChar (attribute); /* * We need to reset the contents of the scrolling * list using the new attribute. */ setCDKFselectDirContents (fselect); } char *getCDKFselectSocketAttribute (CDKFSELECT *fselect) { return fselect->sockAttribute; } /* * This sets the attribute of the link attribute in the * scrolling list. */ void setCDKFselectFileAttribute (CDKFSELECT *fselect, char *attribute) { /* Make sure they are not one in the same. */ if (fselect->fileAttribute == attribute) { return; } /* Clean out the old attribute, and set the new. */ freeChar (fselect->fileAttribute); fselect->fileAttribute = copyChar (attribute); /* * We need to reset the contents of the scrolling * list using the new attribute. */ setCDKFselectDirContents (fselect); } char *getCDKFselectFileAttribute (CDKFSELECT *fselect) { return fselect->fileAttribute; } /* * This sets the box attribute of the widget. */ void setCDKFselectBox (CDKFSELECT *fselect, boolean Box) { ObjOf(fselect)->box = Box; } boolean getCDKFselectBox (CDKFSELECT *fselect) { return ObjOf(fselect)->box; } /* * These functions set the drawing characters of the widget. */ void setCDKFselectULChar (CDKFSELECT *fselect, chtype character) { setCDKEntryULChar (fselect->entryField, character); } void setCDKFselectURChar (CDKFSELECT *fselect, chtype character) { setCDKEntryURChar (fselect->entryField, character); } void setCDKFselectLLChar (CDKFSELECT *fselect, chtype character) { setCDKScrollLLChar (fselect->scrollField, character); } void setCDKFselectLRChar (CDKFSELECT *fselect, chtype character) { setCDKScrollLRChar (fselect->scrollField, character); } void setCDKFselectVerticalChar (CDKFSELECT *fselect, chtype character) { setCDKEntryVerticalChar (fselect->entryField, character); setCDKScrollVerticalChar (fselect->scrollField, character); } void setCDKFselectHorizontalChar (CDKFSELECT *fselect, chtype character) { setCDKEntryHorizontalChar (fselect->entryField, character); setCDKScrollHorizontalChar (fselect->scrollField, character); } void setCDKFselectBoxAttribute (CDKFSELECT *fselect, chtype character) { setCDKEntryBoxAttribute (fselect->entryField, character); setCDKScrollBoxAttribute (fselect->scrollField, character); } /* * This sets the background color of the widget. */ void setCDKFselectBackgroundColor (CDKFSELECT *fselect, char *color) { if (color != 0) { setCDKEntryBackgroundColor (fselect->entryField, color); setCDKScrollBackgroundColor (fselect->scrollField, color); } } /* * This destroys the file selector. */ void destroyCDKFselect (CDKFSELECT *fselect) { /* Erase the file selector. */ eraseCDKFselect (fselect); /* Free up the character pointers. */ freeChar (fselect->pwd); freeChar (fselect->pathname); freeChar (fselect->dirAttribute); freeChar (fselect->fileAttribute); freeChar (fselect->linkAttribute); freeChar (fselect->sockAttribute); freeCharList (fselect->dirContents, fselect->fileCounter); /* Destroy the other Cdk objects. */ destroyCDKScroll (fselect->scrollField); destroyCDKEntry (fselect->entryField); /* Free up the window pointers. */ deleteCursesWindow (fselect->win); /* Unregister the object. */ unregisterCDKObject (vFSELECT, fselect); /* Free up the object pointer. */ free (fselect); } /* ******************************** * Callback functions. ******************************** */ /* * This is a callback to the scrolling list which displays information * about the current file. (and the whole directory as well) */ static void displayFileInfoCB (EObjectType objectType GCC_UNUSED, void *object, void *clientData, chtype key GCC_UNUSED) { /* Declare local variables. */ CDKENTRY *entry = (CDKENTRY *)object; CDKFSELECT *fselect = (CDKFSELECT *)clientData; CDKLABEL *infoLabel; struct stat fileStat; struct passwd *pwEnt; struct group *grEnt; char *filename; char *filetype; char *mesg[10]; char temp[100]; char stringMode[15]; int len; int intMode; /* Get the file name. */ filename = fselect->entryField->info; /* Get specific information about the files. */ lstat (filename, &fileStat); /* Determine the file type. */ switch (mode2Filetype(fileStat.st_mode)) { case 'l': filetype = "Symbolic Link"; break; case '@': filetype = "Socket"; break; case '-': filetype = "Regular File"; break; case 'd': filetype = "Directory"; break; case 'c': filetype = "Character Device"; break; case 'b': filetype = "Block Device"; break; case '&': filetype = "FIFO Device"; break; default: filetype = "Unknown"; break; } /* Get the user name and group name. */ pwEnt = getpwuid (fileStat.st_uid); grEnt = getgrgid (fileStat.st_gid); /* Convert the mode_t type to both string and int. */ intMode = mode2Char (stringMode, fileStat.st_mode); /* Create the message. */ sprintf (temp, "Directory : %s", fselect->pwd); mesg[0] = copyChar (temp); sprintf (temp, "Filename : %s", filename); mesg[1] = copyChar (temp); sprintf (temp, "Owner : %s (%d)", pwEnt->pw_name, (int)fileStat.st_uid); mesg[2] = copyChar (temp); sprintf (temp, "Group : %s (%d)", grEnt->gr_name, (int)fileStat.st_gid); mesg[3] = copyChar (temp); sprintf (temp, "Permissions: %s (%o)", stringMode, intMode); mesg[4] = copyChar (temp); sprintf (temp, "Size : %ld bytes", (long) fileStat.st_size); mesg[5] = copyChar (temp); sprintf (temp, "Last Access: %s", ctime (&fileStat.st_atime)); len = (int)strlen (temp); temp[len] = '\0'; temp[len-1] = '\0'; mesg[6] = copyChar (temp); sprintf (temp, "Last Change: %s", ctime (&fileStat.st_ctime)); len = (int)strlen (temp); temp[len] = '\0'; temp[len-1] = '\0'; mesg[7] = copyChar (temp); sprintf (temp, "File Type : %s", filetype); mesg[8] = copyChar (temp); /* Create the pop up label. */ infoLabel = newCDKLabel (entry->obj.screen, CENTER, CENTER, mesg, 9, TRUE, FALSE); drawCDKLabel (infoLabel, TRUE); waitCDKLabel (infoLabel, 0); /* Clean up some memory. */ destroyCDKLabel (infoLabel); freeCharList (mesg, 9); /* Redraw the file selector. */ drawCDKFselect (fselect, ObjOf(fselect)->box); } /* * This tries to complete the filename. */ static void completeFilenameCB (EObjectType objectType GCC_UNUSED, void *object GCC_UNUSED, void *clientData, chtype key GCC_UNUSED) { CDKFSELECT *fselect = (CDKFSELECT *)clientData; CDKSCROLL *scrollp = (CDKSCROLL *)fselect->scrollField; CDKENTRY *entry = (CDKENTRY *)fselect->entryField; char *filename = copyChar (entry->info); char *basename = baseName (filename); char *dirname = dirName (filename); char *dirPWD = dirName (fselect->pwd); char *basePWD = baseName (fselect->pwd); char *newFilename = 0; chtype *tempChtype = 0; char *tempChar = 0; int filenameLen = 0; int currentIndex = 0; int matches = 0; int baseChars = 0; int secondaryMatches = 0; int isDirectory = 0; char *list[MAX_ITEMS], temp[1000]; int Index, pos, ret, j, j2, x; int difference, absoluteDifference; /* Make sure the filename is not null. */ if (filename == 0) { Beep(); return; } filenameLen = (int)strlen (filename); /* If the filename length is equal to zero, just leave. */ if (filenameLen == 0) { Beep(); return; } /* Try to expand the filename if it starts with a ~ */ if (filename[0] == '~') { newFilename = expandFilename (filename); if (newFilename != 0) { freeChar (filename); filename = newFilename; setCDKEntryValue (entry, filename); drawCDKEntry (entry, ObjOf(entry)->box); } } /* Make sure we can change into the directory. */ isDirectory = chdir (filename); chdir (fselect->pwd); /* If we can, change into the directory. */ if (isDirectory == 0) { /* * The basenames of both the present working directory and * the basename of the filename are different. The filename * provided is a directory; therefore we should chdir into * it and reload the file selector. */ setCDKFselect (fselect, filename, fselect->fieldAttribute, fselect->fillerCharacter, fselect->highlight, fselect->dirAttribute, fselect->fileAttribute, fselect->linkAttribute, fselect->sockAttribute, ObjOf(fselect)->box); } else { /* * The basenames of both the present working directory and * the basename of the filename are different. The filename * provided is a file; therefore we should chdir into the * basename of the file and reload the file selector. * Then we should continue to try to complete the filename. * (which is done below) */ setCDKFselect (fselect, dirname, fselect->fieldAttribute, fselect->fillerCharacter, fselect->highlight, fselect->dirAttribute, fselect->fileAttribute, fselect->linkAttribute, fselect->sockAttribute, ObjOf(fselect)->box); /* * Set the entry field with the filename so the current * filename selection shows up. */ setCDKEntryValue (entry, filename); drawCDKEntry (entry, ObjOf(entry)->box); } /* Clean up our pointers. */ freeChar (basename); freeChar (dirname); freeChar (dirPWD); freeChar (basePWD); /* Create the file list. */ for (x=0; x < fselect->fileCounter; x++) { /* We need to remove the special characters from the filenames. */ tempChtype = char2Chtype (fselect->dirContents[x], &j, &j2); tempChar = chtype2Char (tempChtype); /* Create the pathname. */ if (strcmp (fselect->pwd, "/") == 0) { sprintf (temp, "/%s", tempChar); } else { sprintf (temp, "%s/%s", fselect->pwd, tempChar); } list[x] = copyChar (temp); /* Clean up. */ freeChtype (tempChtype); freeChar (tempChar); } /* Look for a unique filename match. */ Index = searchList (list, fselect->fileCounter, filename); /* If the index is less than zero, return we didn't find a match. */ if (Index < 0) { /* Clean up. */ freeCharList (list, fselect->fileCounter); freeChar (filename); Beep(); return; } /* Create the filename of the found file. */ sprintf (temp, "%s", list[Index]); temp[(int)strlen(temp)-1] = '\0'; /* Did we find the last file in the list? */ if (Index == fselect->fileCounter) { /* Set the filename in the entry field. */ setCDKEntryValue (entry, list[Index]); drawCDKEntry (entry, ObjOf(entry)->box); /* Clean up. */ freeCharList (list, fselect->fileCounter); freeChar (filename); return; } /* Move to the current item in the scrolling list. */ difference = Index - scrollp->currentItem; absoluteDifference = abs (difference); if (difference < 0) { for (x=0; x < absoluteDifference; x++) { injectCDKScroll (scrollp, KEY_UP); } } else if (difference > 0) { for (x=0; x < absoluteDifference; x++) { injectCDKScroll (scrollp, KEY_DOWN); } } drawCDKScroll (scrollp, ObjOf(scrollp)->box); /* Ok, we found a match, is the next item similar? */ ret = strncmp (list[Index + 1], filename, filenameLen); if (ret == 0) { currentIndex = Index; baseChars = filenameLen; matches = 0; pos = 0; /* Determine the number of files which match. */ while (currentIndex < fselect->fileCounter) { if (list[currentIndex] != 0) { if (strncmp (list[currentIndex], filename, filenameLen) == 0) { matches++; } } currentIndex++; } /* Start looking for the common base characters. */ for (;;) { secondaryMatches = 0; for (x=Index; x < Index + matches; x++) { if (list[Index][baseChars] == list[x][baseChars]) { secondaryMatches++; } } if (secondaryMatches != matches) { Beep(); break; } /* Inject the character into the entry field. */ injectCDKEntry (fselect->entryField, list[Index][baseChars]); baseChars++; } } else { /* Set the entry field with the found item. */ setCDKEntryValue (entry, temp); drawCDKEntry (entry, ObjOf(entry)->box); } /* Clean up. */ freeCharList (list, fselect->fileCounter); freeChar (filename); } /* * This allows the user to delete a file. */ void deleteFileCB (EObjectType objectType GCC_UNUSED, void *object, void *clientData) { /* Declare local variables. */ CDKSCROLL *fscroll = (CDKSCROLL *)object; CDKFSELECT *fselect = (CDKFSELECT *)clientData; char *buttons[] = {"No", "Yes"}; CDKDIALOG *question; char *mesg[10], *filename, temp[100]; /* Get the filename which is to be deleted. */ filename = chtype2Char (fscroll->item[fscroll->currentItem]); filename[(int)strlen(filename)-1] = '\0'; /* Create the dialog message. */ mesg[0] = "Are you sure you want to delete the file:"; sprintf (temp, "%s?", filename); mesg[1] = copyChar (temp); /* Create the dialog box. */ question = newCDKDialog (ScreenOf(fselect), CENTER, CENTER, mesg, 2, buttons, 2, A_REVERSE, TRUE, TRUE, FALSE); freeCharList (mesg, 2); /* If the said yes then try to nuke it. */ if (activateCDKDialog (question, 0) == 1) { /* If we were successful, reload the scrolling list. */ if (unlink (filename) == 0) { /* Set the file selector information. */ setCDKFselect (fselect, fselect->pwd, fselect->fieldAttribute, fselect->fillerCharacter, fselect->highlight, fselect->dirAttribute, fselect->fileAttribute, fselect->linkAttribute, fselect->sockAttribute, ObjOf(fselect)->box); } else { /* Pop up a message. */ #ifdef HAVE_STRERROR sprintf (temp, "Can't delete file: <%s>", strerror (errno)); #else sprintf (temp, "Can not delete file. Unknown reason."); #endif mesg[0] = copyChar (temp); mesg[1] = " "; mesg[2] = "Press any key to continue."; popupLabel (ScreenOf(fselect), mesg, 3); freeCharList (mesg, 3); } } /* Clean up. */ destroyCDKDialog (question); /* Redraw the file selector. */ drawCDKFselect (fselect, ObjOf(fselect)->box); } /* * This function sets the pre-process function. */ void setCDKFselectPreProcess (CDKFSELECT *fselect, PROCESSFN callback, void *data) { setCDKEntryPreProcess (fselect->entryField, callback, data); setCDKScrollPreProcess (fselect->scrollField, callback, data); } /* * This function sets the post-process function. */ void setCDKFselectPostProcess (CDKFSELECT *fselect, PROCESSFN callback, void *data) { setCDKEntryPostProcess (fselect->entryField, callback, data); setCDKScrollPostProcess (fselect->scrollField, callback, data); } /* * Start of callback functions. */ static void fselectAdjustScrollCB (EObjectType objectType GCC_UNUSED, void *object GCC_UNUSED, void *clientData, chtype key) { CDKFSELECT *fselect = (CDKFSELECT *)clientData; CDKSCROLL *scrollp = (CDKSCROLL *)fselect->scrollField; CDKENTRY *entry = (CDKENTRY *)fselect->entryField; char *current, temp[1024]; int len; /* Move the scrolling list. */ injectCDKScroll (fselect->scrollField, key); /* Get the currently highlighted filename. */ current = chtype2Char (scrollp->item[scrollp->currentItem]); len = (int)strlen (current); current[len-1] = '\0'; /* Are we in the root partition. */ if (strcmp (fselect->pwd, "/") == 0) { sprintf (temp, "/%s", current); } else { sprintf (temp, "%s/%s", fselect->pwd, current); } freeChar (current); /* Set the value in the entry field. */ setCDKEntryValue (entry, temp); drawCDKEntry (entry, ObjOf(entry)->box); } /* * This takes a ~ type account name and returns the full * pathname. */ static char *expandFilename (char *filename) { struct passwd *accountInfo; char accountName[256], pathname[1024], fullPath[2048]; int slashFound = 0; int pos = 0; int len, x; /* Make sure the filename is not null. */ if ((filename == 0) || (len = strlen (filename)) == 0) { return 0; } /* Make sure the first character is a tilde. */ if (filename[0] != '~') { return 0; } /* Find the account name in the filename. */ for (x=1; x < len; x++) { if (filename[x] != '/' && slashFound == 0) { accountName[pos++] = filename[x]; } else { if (slashFound == 0) { accountName[pos] = '\0'; pos = 0; slashFound = 1; } else { pathname[pos++] = filename[x]; } } } /* Determine if the account name has a home directory. */ accountInfo = getpwnam (accountName); if (accountInfo == 0) { return 0; } /* * Construct the full pathname. We do this because someone * may have had a pathname at the end of the account name * and we want to keep it. */ sprintf (fullPath, "%s/%s", accountInfo->pw_dir, pathname); return copyChar (fullPath); } /* * Store the name of the current working directory. */ static void setPWD (CDKFSELECT *fselect) { char buffer[512]; freeChar (fselect->pwd); if (getcwd(buffer, sizeof(buffer)) == 0) strcpy(buffer, "."); fselect->pwd = copyChar(buffer); }