#include /* * $Author: garbled $ * $Date: 2001/01/04 20:15:30 $ * $Revision: 1.2 $ */ char *GPasteBuffer = 0; /* * This beeps then flushes the stdout stream. */ void Beep(void) { beep(); fflush (stdout); } /* * This sets a string to the given character. */ void cleanChar (char *s, int len, char character) { int x; for (x=0; x < len; x++) { s[x] = character; } s[--x] = '\0'; } void cleanChtype (chtype *s, int len, chtype character) { int x; for (x=0; x < len; x++) { s[x] = character; } s[--x] = '\0'; } /* * This takes an x and y position and realigns the values iff they sent in * values like CENTER, LEFT, RIGHT, ... */ void alignxy (WINDOW *window, int *xpos, int *ypos, int boxWidth, int boxHeight) { int first, gap, last; first = getbegx(window); last = getmaxx(window); if ((gap = (last - boxWidth)) < 0) gap = 0; last = first + gap; switch (*xpos) { case LEFT: (*xpos) = first; break; case RIGHT: (*xpos) = first + gap; break; case CENTER: (*xpos) = first + (gap / 2); break; } if ((*xpos) > last) (*xpos) = last; else if ((*xpos) < first) (*xpos) = first; first = getbegy(window); last = getmaxy(window); if ((gap = (last - boxHeight)) < 0) gap = 0; last = first + gap; switch (*ypos) { case TOP: (*ypos) = first; break; case BOTTOM: (*ypos) = first + gap; break; case CENTER: (*ypos) = first + (gap/2); break; } if ((*ypos) > last) (*ypos) = last; else if ((*ypos) < first) (*ypos) = first; } /* * This takes a string, a field width and a justifycation type * and returns the justifcation adjustment to make, to fill * the justification requirement. */ int justifyString (int boxWidth, int mesgLength, int justify) { /* * Make sure the message isn't longer than the width. * If it is, return 1. */ if (mesgLength >= boxWidth) { return (0); } /* Try to justify the message. */ if (justify == LEFT) { return (0); } else if (justify == RIGHT) { return ((boxWidth - mesgLength)); } else if (justify == CENTER) { return ((int)((boxWidth - mesgLength) / 2)); } else { return (justify); } } /* * This returns a substring of the given string. */ char *substring (char *string, int start, int width) { char *newstring = 0; int mesglen = 0; int y = 0; int x = 0; int lastchar = 0; /* Make sure the string isn't null. */ if (string == 0) { return 0; } mesglen = (int)strlen (string); /* Make sure we start in the correct place. */ if (start > mesglen) { return (newstring); } /* Create the new string. */ newstring = (char *)malloc (sizeof (char) * (width + 3)); /*cleanChar (newstring, width + 3, '\0');*/ if ((start + width) > mesglen) { lastchar = mesglen; } else { lastchar = width + start; } for (x=start; x<=lastchar; x++) { newstring[y++] = string[x]; } newstring[lastchar + 1] = '\0'; newstring[lastchar + 2] = '\0'; return (newstring); } /* * This frees a string if it is not null. This is a safety * measure. Some compilers let you free a null string. I * don't like that idea. */ void freeChar (char *string) { if (string != 0) free (string); } void freeChtype (chtype *string) { if (string != 0) free (string); } /* * Corresponding list freeing */ void freeCharList (char **list, unsigned size) { while (size-- != 0) { freeChar(list[size]); list[size] = 0; } } /* * This performs a safe copy of a string. This means it adds the null * terminator on the end of the string, like strdup(). */ char *copyChar (char *original) { /* Declare local variables. */ char *newstring; /* Make sure the string is not null. */ if (original == 0) { return 0; } newstring = (char *)malloc (strlen(original) + 1); /* Copy from one to the other. */ strcpy (newstring, original); /* Return the new string. */ return (newstring); } chtype *copyChtype (chtype *original) { /* Declare local variables. */ chtype *newstring; int len, x; /* Make sure the string is not null. */ if (original == 0) { return 0; } /* Create the new string. */ len = chlen (original); newstring = (chtype *)malloc (sizeof(chtype) * (len + 4)); if (newstring == 0) { return (original); } /* Copy from one to the other. */ for (x=0; x < len; x++) { newstring[x] = original[x]; } newstring[len] = '\0'; newstring[len + 1] = '\0'; /* Return the new string. */ return (newstring); } /* * This reads a file and sticks it into the char ** provided. */ int readFile (char *filename, char **array, int maxlines) { FILE *fd; char temp[BUFSIZ]; int lines = 0; size_t len; /* Can we open the file? */ if ((fd = fopen (filename, "r")) == 0) { return (-1); } /* Start reading the file in. */ while ((fgets (temp, sizeof(temp), fd) != 0) && lines < maxlines) { len = strlen (temp); if (temp[len-1] == '\n') { temp[len-1] = '\0'; } array[lines] = copyChar (temp); lines++; } fclose (fd); /* Clean up and return. */ return (lines); } #define DigitOf(c) ((c)-'0') static int parseAttribute(char *string, int from, chtype *mask) { int pair = 0; *mask = 0; switch (string[from + 1]) { case 'B': *mask = A_BOLD; break; case 'D': *mask = A_DIM; break; case 'K': *mask = A_BLINK; break; case 'R': *mask = A_REVERSE; break; case 'S': *mask = A_STANDOUT; break; case 'U': *mask = A_UNDERLINE; break; } if (*mask != 0) { from++; } else if (isdigit((int)string[from + 1]) && isdigit((int)string[from + 2])) { #ifdef HAVE_START_COLOR pair = DigitOf(string[from + 1]) * 10 + DigitOf(string[from + 2]); *mask = COLOR_PAIR(pair); #else *mask = A_BOLD; #endif from += 2; } else if (isdigit((int)string[from + 1])) { #ifdef HAVE_START_COLOR pair = DigitOf(string[from + 1]); *mask = COLOR_PAIR(pair); #else *mask = A_BOLD; #endif from++; } return from; } /* * This function takes a character string, full of format markers * and translates them into a chtype * array. This is better suited * to curses, because curses uses chtype almost exclusively */ chtype *char2Chtype (char *string, int *to, int *align) { chtype *result = 0; chtype attrib; chtype lastChar; chtype mask; int adjust; int from; int insideMarker; int len; int pass; int start; int used; int x; (*to) = 0; *align = LEFT; if (string != 0) { len = (int)strlen(string); used = 0; /* * We make two passes because we may have indents and tabs to expand, and * do not know in advance how large the result will be. */ for (pass = 0; pass < 2; pass++) { if (pass != 0) { if ((result = (chtype *)malloc((used+2) * sizeof(chtype))) == 0) { used = 0; break; } } adjust = 0; attrib = A_NORMAL; lastChar = 0; start = 0; used = 0; x = 3; /* Look for an alignment marker. */ if (!strncmp(string, "", 3)) { (*align) = CENTER; start = 3; } else if (!strncmp(string, "", 3)) { (*align) = RIGHT; start = 3; } else if (!strncmp(string, "", 3)) { start = 3; } else if (!strncmp(string, "= right) { return; } swapIndex (list, left, (left + right)/2); last = left; for (i=left + 1; i <= right; i++) { if (strcmp (list[i], list[left]) < 0) { swapIndex (list, ++last, i); } } swapIndex (list, left, last); quickSort (list, left, last-1); quickSort (list, last + 1, right); #endif } /* * This strips white space off of the given string. */ void stripWhiteSpace (EStripType stripType, char *string) { /* Declare local variables. */ int stringLength = 0; int alphaChar = 0; int x = 0; /* Make sure the string is not null. */ if (string == 0) { return; } /* Get the length of the string. */ stringLength = (int)strlen(string); if (stringLength == 0) { return; } /* Strip the white space from the front. */ if (stripType == vFRONT || stripType == vBOTH) { /* Find the first non-whitespace character. */ while (string[alphaChar] == ' ' || string[alphaChar] == '\t') { alphaChar++; } /* Trim off the white space. */ if (alphaChar != stringLength) { for (x=0; x < (stringLength-alphaChar); x++) { string[x] = string[x + alphaChar]; } string[stringLength-alphaChar] = '\0'; } else { /* Set the string to zero. */ memset (string, 0, stringLength); } } /* Get the length of the string. */ stringLength = (int)strlen(string)-1; /* Strip the space from behind if it was asked for. */ if (stripType == vBACK || stripType == vBOTH) { /* Find the first non-whitespace character. */ while (string[stringLength] == ' ' || string[stringLength] == '\t') { string[stringLength--] = '\0'; } } } static unsigned countChar(char *string, int separator) { unsigned result = 0; int ch; while ((ch = *string++) != 0) { if (ch == separator) result++; } return result; } /* * Split a string into a list of strings. */ char **CDKsplitString(char *string, int separator) { char **result = 0; char *first; char *temp; unsigned item; unsigned need; if (string != 0) { need = countChar(string, separator) + 2; if ((result = (char **)malloc(need * sizeof(char *))) != 0) { item = 0; first = string; for(;;) { while (*string != 0 && *string != separator) string++; need = string - first; if ((temp = (char *)malloc(need+1)) == 0) break; memcpy(temp, first, need); temp[need] = 0; result[item++] = temp; if (*string++ == 0) break; first = string; } result[item] = 0; } } return result; } /* * Count the number of items in a list of strings. */ unsigned CDKcountStrings(char **list) { unsigned result = 0; if (list != 0) { while (*list++ != 0) result++; } return result; } /* * Free a list of strings */ void CDKfreeStrings(char **list) { if (list != 0) { void *base = (void *)list; while (*list != 0) free(*list++); free(base); } } int mode2Filetype (mode_t mode) { static const struct { mode_t mode; char code; } table[] = { #ifdef S_IFBLK { S_IFBLK, 'b' }, /* Block device */ #endif { S_IFCHR, 'c' }, /* Character device */ { S_IFDIR, 'd' }, /* Directory */ { S_IFREG, '-' }, /* Regular file */ #ifdef S_IFLNK { S_IFLNK, 'l' }, /* Socket */ #endif { S_IFSOCK, '@' }, /* Socket */ { S_IFIFO, '&' }, /* Pipe */ }; int filetype = '?'; unsigned n; for (n = 0; n < sizeof(table)/sizeof(table[0]); n++) { if ((mode & S_IFMT) == table[n].mode) { filetype = table[n].code; break; } } return filetype; } /* * This function takes a mode_t type and creates a string represntation * of the permission mode. */ int mode2Char (char *string, mode_t mode) { static struct { mode_t mask; unsigned col; char flag; } table[] = { { S_IRUSR, 1, 'r' }, { S_IWUSR, 2, 'w' }, { S_IXUSR, 3, 'x' }, { S_IRGRP, 4, 'r' }, { S_IWGRP, 5, 'w' }, { S_IXGRP, 6, 'x' }, { S_IROTH, 7, 'r' }, { S_IWOTH, 8, 'w' }, { S_IXOTH, 9, 'x' }, { S_ISUID, 3, 's' }, { S_ISGID, 6, 's' }, #ifdef S_ISVTX { S_ISVTX, 9, 't' }, #endif }; /* Declare local variables. */ int permissions = 0; int filetype = mode2Filetype(mode); unsigned n; /* Clean the string. */ cleanChar (string, 11, '-'); string[11] = '\0'; if (filetype == '?') return -1; for (n = 0; n < sizeof(table)/sizeof(table[0]); n++) { if ((mode & table[n].mask) != 0) { string[table[n].col] = table[n].flag; permissions |= table[n].mask; } } /* Check for unusual permissions. */ if (((mode & S_IXUSR) == 0) && ((mode & S_IXGRP) == 0) && ((mode & S_IXOTH) == 0) && (mode & S_ISUID) != 0) { string[3] = 'S'; } return permissions; } /* * This returns the length of the integer. */ int intlen (int value) { if (value < 0) return 1 + intlen(-value); else if (value >= 10) return 1 + intlen(value/10); return 1; } /* * This opens the current directory and reads the contents. */ int getDirectoryContents (char *directory, char **list, int maxListSize) { /* Declare local variables. */ struct dirent *dirStruct; int counter = 0; DIR *dp; /* Open the directory. */ dp = opendir (directory); /* Could we open the directory? */ if (dp == 0) { return -1; } /* Read the directory. */ while ((dirStruct = readdir (dp)) != 0) { if (counter <= maxListSize) { list[counter++] = copyChar (dirStruct->d_name); } } /* Close the directory. */ closedir (dp); /* Sort the info. */ quickSort (list, 0, counter-1); /* Return the number of files in the directory. */ return counter; } /* * This looks for a subset of a word in the given list. */ int searchList (char **list, int listSize, char *pattern) { /* Declare local variables. */ int len = 0; int Index = -1; int x, ret; /* Make sure the pattern isn't null. */ if (pattern == 0) { return Index; } len = (int)strlen (pattern); /* Cycle through the list looking for the word. */ for (x=0; x < listSize; x++) { /* Do a string compare. */ ret = strncmp (list[x], pattern, len); /* * If 'ret' is less than 0, then the current word is * alphabetically less than the provided word. At this * point we will set the index to the current position. * If 'ret' is greater than 0, then the current word is * alphabettically greater than the given word. We should * return with index, which might contain the last best * match. If they are equal, then we've found it. */ if (ret < 0) { Index = ret; } else if (ret > 0) { return Index; } else { return x; } } return -1; } /* * This function checks to see if a link has been requested. */ int checkForLink (char *line, char *filename) { int len = 0; int fPos = 0; int x = 3; /* Make sure the line isn't null. */ if (line == 0) { return -1; } len = (int)strlen (line); /* Strip out the filename. */ if (line[0] == '<' && line[1] == 'F' && line[2] == '=') { /* Strip out the filename. */ while (x < len) { if (line[x] == '>') { break; } filename[fPos++] = line[x++]; } filename[fPos] = '\0'; return 1; } return 0; } /* * This strips out the filename from the pathname. I would have * used rindex but it seems that not all the C libraries support * it. :( */ char *baseName (char *pathname) { char *base = 0; int pathLen = 0; int pos = 0; int Index = -1; int x = 0; /* Check if the string is null. */ if (pathname == 0) { return 0; } base = copyChar (pathname); pathLen = (int)strlen (pathname); /* Find the last '/' in the pathname. */ x = pathLen - 1; while ((pathname[x] != '\0') && (Index == -1) && (x > 0)) { if (pathname[x] == '/') { Index = x; break; } x--; } /* * If the index is -1, we never found one. Return a pointer * to the string given to us. */ if (Index == -1) { return base; } /* Clean out the base pointer. */ memset (base, '\0', pathLen); /* * We have found an index. Copy from the index to the * end of the string into a new string. */ for (x=Index + 1; x < pathLen; x++) { base[pos++] = pathname[x]; } return base; } /* * This strips out the directory from the pathname. I would have * used rindex but it seems that not all the C libraries support * it. :( */ char *dirName (char *pathname) { char *dir = 0; int pathLen = 0; int x = 0; /* Check if the string is null. */ if (pathname == 0) { return 0; } dir = copyChar (pathname); pathLen = (int)strlen (pathname); /* Starting from the end, look for the first '/' character. */ x = pathLen; while ((dir[x] != '/') && (x > 0)) { dir[x--] = '\0'; } /* Now dir either has nothing or the basename. */ if (dir[0] == '\0') { /* If it has nothing, return nothing. */ return copyChar (""); } /* Otherwise, return the path. */ return dir; } /* * If the dimension is a negative value, the dimension will * be the full height/width of the parent window - the value * of the dimension. Otherwise, the dimension will be the * given value. */ int setWidgetDimension (int parentDim, int proposedDim, int adjustment) { int dimension = 0; /* If the user passed in FULL, return the number of rows. */ if ((proposedDim == FULL) || (proposedDim == 0)) { return parentDim; } /* If they gave a positive value, return it. */ if (proposedDim >= 0) { if (proposedDim >= parentDim) { return parentDim; } return (proposedDim + adjustment); } /* * If they gave a negative value, then return the * dimension of the parent minus the value given. */ dimension = parentDim + proposedDim; /* Just to make sure. */ if (dimension < 0) { return parentDim; } return dimension; } /* * This safely erases a given window. */ void eraseCursesWindow (WINDOW *window) { if (window != 0) { werase (window); wnoutrefresh (window); } } /* * This safely deletes a given window. */ void deleteCursesWindow (WINDOW *window) { if (window != 0) { delwin (window); } } /* * This moves a given window */ void moveCursesWindow (WINDOW *window, int xpos, int ypos) { mvwin (window, ypos, xpos); } /* * Return an integer like 'floor()', which returns a double. */ int floorCDK(double value) { int result = (int)value; if (result > value) /* e.g., value < 0.0 and value is not an integer */ result--; return result; } /* * Return an integer like 'ceil()', which returns a double. */ int ceilCDK(double value) { return -floorCDK(-value); }