#include /* * $Author: tom $ * $Date: 2005/04/24 15:08:17 $ * $Revision: 1.198 $ */ #define L_MARKER '<' #define R_MARKER '>' 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) { if (s != 0) { int x; for (x=0; x < len; x++) { s[x] = character; } s[--x] = '\0'; } } void cleanChtype (chtype *s, int len, chtype character) { if (s != 0) { 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; default: if ((*xpos) > last) (*xpos) = last; else if ((*xpos) < first) (*xpos) = first; break; } 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; default: if ((*ypos) > last) { (*ypos) = last; } else if ((*ypos) < first) { (*ypos) = first; } break; } } /* * This takes a string, a field width and a justification type * and returns the 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 0. */ if (mesgLength >= boxWidth) return (0); /* Try to justify the message. */ if (justify == LEFT) return (0); if (justify == RIGHT) return boxWidth - mesgLength; if (justify == CENTER) return ((int)((boxWidth - mesgLength) / 2)); return (justify); } /* * 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) { freeChecked (string); } void freeChtype (chtype *string) { freeChecked (string); } /* * Corresponding list freeing */ void freeCharList (char **list, unsigned size) { if (list != 0) { while (size-- != 0) { freeChar(list[size]); list[size] = 0; } } } void freeChtypeList (chtype **list, unsigned size) { if (list != 0) { while (size-- != 0) { freeChtype(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) { char *newstring = 0; if (original != 0) { if ((newstring = typeMallocN(char, strlen(original) + 1)) != 0) strcpy (newstring, original); } return (newstring); } chtype *copyChtype (chtype *original) { chtype *newstring = 0; if (original != 0) { int len = chlen (original); int x; if ((newstring = typeMallocN(chtype, len + 4)) != 0) { for (x=0; x < len; x++) { newstring[x] = original[x]; } newstring[len] = '\0'; newstring[len + 1] = '\0'; } else { newstring = original; } } return (newstring); } /* * This reads a file and sticks it into the char *** provided. */ int CDKreadFile (char *filename, char ***array) { FILE *fd; char temp[BUFSIZ]; unsigned lines = 0; unsigned used = 0; /* Can we open the file? */ if ((fd = fopen (filename, "r")) == 0) { return (-1); } while ((fgets (temp, sizeof(temp), fd) != 0)) { size_t len = strlen(temp); if (len != 0 && temp[len-1] == '\n') temp[--len] = '\0'; used = CDKallocStrings(array, temp, lines++, used); } fclose (fd); return (lines); } #define DigitOf(c) ((c)-'0') static int encodeAttribute(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(CharOf(string[from + 1])) && isdigit(CharOf(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(CharOf(string[from + 1]))) { #ifdef HAVE_START_COLOR pair = DigitOf(string[from + 1]); *mask = COLOR_PAIR(pair); #else *mask = A_BOLD; #endif from++; } return from; } /* * The reverse of encodeAttribute() * Well almost. If attributes such as bold and underline are combined in * the same string, we do not necessarily reconstruct them in the same order. * Also, alignment markers and tabs are lost. */ static unsigned decodeAttribute(char *string, unsigned from, chtype oldattr, chtype newattr) { static const struct { int code; chtype mask; } table[] = { { 'B', A_BOLD }, { 'D', A_DIM }, { 'K', A_BLINK }, { 'R', A_REVERSE }, { 'S', A_STANDOUT }, { 'U', A_UNDERLINE }, }; char temp[80]; char *result = (string != 0) ? string : temp; char *base = result; chtype tmpattr = oldattr & A_ATTRIBUTES; newattr &= A_ATTRIBUTES; if (tmpattr != newattr) { while (tmpattr != newattr) { unsigned n; bool found = FALSE; for (n = 0; n < sizeof(table)/sizeof(table[0]); ++n) { if ((table[n].mask & tmpattr) != (table[n].mask & newattr)) { found = TRUE; *result++ = L_MARKER; if (table[n].mask & tmpattr) { *result++ = '!'; tmpattr &= ~(table[n].mask); } else { *result++ = '/'; tmpattr |= (table[n].mask); } *result++ = table[n].code; break; } } #ifdef HAVE_START_COLOR if ((tmpattr & A_COLOR) != (newattr & A_COLOR)) { int oldpair = PAIR_NUMBER(tmpattr); int newpair = PAIR_NUMBER(newattr); if (!found) { found = TRUE; *result++ = L_MARKER; } if (newpair == 0) { *result++ = '!'; sprintf(result, "%d", oldpair); } else { *result++ = '/'; sprintf(result, "%d", newpair); } result += strlen(result); tmpattr &= ~A_COLOR; newattr &= ~A_COLOR; } #endif if (found) *result++ = R_MARKER; else break; } } return from + (result - base); } /* * 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 && *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 = typeMallocN(chtype, used + 2)) == 0) { used = 0; break; } } adjust = 0; attrib = A_NORMAL; lastChar = 0; start = 0; used = 0; x = 3; /* Look for an alignment marker. */ if (*string == L_MARKER) { if (string[1] == 'C' && string[2] == R_MARKER) { (*align) = CENTER; start = 3; } else if (string[1] == 'R' && string[2] == R_MARKER) { (*align) = RIGHT; start = 3; } else if (string[1] == 'L' && string[2] == R_MARKER) { start = 3; } else if (string[1] == 'B' && string[2] == '=') { /* Set the item index value in the string. */ if (result != 0) { result[0] = ' '; result[1] = ' '; result[2] = ' '; } /* Pull out the bullet marker. */ while (string[x] != R_MARKER && string[x] != 0) { if (result != 0) result[x] = string[x] | A_BOLD; x++; } adjust = 1; /* Set the alignment variables. */ start = x; used = x; } else if (string[1] == 'I' && string[2] == '=') { from = 2; x = 0; while (string[++from] != R_MARKER && string[from] != 0) { if (isdigit(CharOf(string[from]))) { adjust = (adjust * 10) + DigitOf(string[from]); x++; } } start = x + 4; } } while (adjust-- > 0) { if (result != 0) result[used] = ' '; used++; } /* Set the format marker boolean to false. */ insideMarker = FALSE; /* Start parsing the character string. */ for (from = start; from < len; from++) { /* Are we inside a format marker? */ if (! insideMarker) { if (string[from] == L_MARKER && (string[from + 1] == '/' || string[from + 1] == '!' || string[from + 1] == '#')) { insideMarker = TRUE; } else if (string[from] == '\\' && string[from + 1] == L_MARKER) { from++; if (result != 0) result[used] = CharOf(string[from]) | attrib; used++; from++; } else if (string[from] == '\t') { do { if (result != 0) result[used] = ' '; used++; } while (used & 7); } else { if (result != 0) result[used] = CharOf(string[from]) | attrib; used++; } } else { switch (string[from]) { case R_MARKER: insideMarker = 0; break; case '#': { lastChar = 0; switch(string[from + 2]) { case 'L': switch (string[from + 1]) { case 'L': lastChar = ACS_LLCORNER; break; case 'U': lastChar = ACS_ULCORNER; break; case 'H': lastChar = ACS_HLINE; break; case 'V': lastChar = ACS_VLINE; break; case 'P': lastChar = ACS_PLUS; break; } break; case 'R': switch (string[from + 1]) { case 'L': lastChar = ACS_LRCORNER; break; case 'U': lastChar = ACS_URCORNER; break; } break; case 'T': switch (string[from + 1]) { case 'T': lastChar = ACS_TTEE; break; case 'R': lastChar = ACS_RTEE; break; case 'L': lastChar = ACS_LTEE; break; case 'B': lastChar = ACS_BTEE; break; } break; case 'A': switch (string[from + 1]) { case 'L': lastChar = ACS_LARROW; break; case 'R': lastChar = ACS_RARROW; break; case 'U': lastChar = ACS_UARROW; break; case 'D': lastChar = ACS_DARROW; break; } break; default: if (string[from + 1] == 'D' && string[from + 2] == 'I') lastChar = ACS_DIAMOND; else if (string[from + 1] == 'C' && string[from + 2] == 'B') lastChar = ACS_CKBOARD; else if (string[from + 1] == 'D' && string[from + 2] == 'G') lastChar = ACS_DEGREE; else if (string[from + 1] == 'P' && string[from + 2] == 'M') lastChar = ACS_PLMINUS; else if (string[from + 1] == 'B' && string[from + 2] == 'U') lastChar = ACS_BULLET; else if (string[from + 1] == 'S' && string[from + 2] == '1') lastChar = ACS_S1; else if (string[from + 1] == 'S' && string[from + 2] == '9') lastChar = ACS_S9; } if (lastChar != 0) { adjust = 1; from += 2; if (string[from + 1] == '(') /* Check for a possible numeric modifier. */ { from++; adjust = 0; while (string[++from] != ')' && string[from] != 0) { if (isdigit(CharOf(string[from]))) { adjust = (adjust * 10) + DigitOf(string[from]); } } } } for (x=0; x < adjust; x++) { if (result != 0) result[used] = lastChar | attrib; used++; } break; } case '/': from = encodeAttribute(string, from, &mask); attrib = attrib | mask; break; case '!': from = encodeAttribute(string, from, &mask); attrib = attrib & ~mask; break; } } } if (result != 0) { result[used] = 0; result[used + 1] = 0; } /* * If there are no characters, put the attribute into the * the first character of the array. */ if (used == 0 && result != 0) { result[0] = attrib; } } *to = used; } return result; } /* * This determines the length of a chtype string */ int chlen (chtype *string) { int result = 0; if (string != 0) { while (string[result] != 0) result++; } return (result); } /* * Compare a regular string to a chtype string */ int cmpStrChstr(char *str, chtype *chstr) { int r = 0; if (!str && !chstr) return 0; if (!str) return 1; if (!chstr) return -1; while (!r && *str && *chstr) { r = *str - CharOf(*chstr); ++str; ++chstr; } if (r) return r; else if (! *str) return -1; else if (! *chstr) return 1; return 0; } void chstrncpy(char *dest, chtype *src, int maxcount) { int i = 0; while (i < maxcount && *src) *dest++ = CharOf(*src++); *dest = '\0'; } /* * This returns a pointer to char * of a chtype * * Formatting codes are omitted. */ char *chtype2Char (chtype *string) { char *newstring = 0; if (string != 0) { int len = chlen(string); int x; if ((newstring = typeMallocN(char, len + 1)) != 0) { for (x=0; x < len; x++) { newstring[x] = (char)CharOf(string[x]); } newstring[len] = '\0'; } } return (newstring); } /* * This returns a pointer to char * of a chtype * * Formatting codes are embedded. */ char *chtype2String (chtype *string) { char *newstring = 0; if (string != 0) { int pass; int len = chlen(string); for (pass = 0; pass < 2; ++pass) { int x; unsigned need = 0; for (x = 0; x < len; ++x) { need = decodeAttribute(newstring, need, (x > 0) ? string[x-1] : 0, string[x]); if (newstring != 0) newstring[need] = CharOf(string[x]); ++need; } if (pass) newstring[need] = 0; ++need; if (!pass) { if ((newstring = typeMallocN(char, need)) == 0) break; } } } return (newstring); } /* * This takes a character pointer and returns the equivalent * display type. */ EDisplayType char2DisplayType (char *string) { static const struct { const char *name; EDisplayType code; } table[] = { { "CHAR", vCHAR }, { "HCHAR", vHCHAR }, { "INT", vINT }, { "HINT", vHINT }, { "UCHAR", vUCHAR }, { "LCHAR", vLCHAR }, { "UHCHAR", vUHCHAR }, { "LHCHAR", vLHCHAR }, { "MIXED", vMIXED }, { "HMIXED", vHMIXED }, { "UMIXED", vUMIXED }, { "LMIXED", vLMIXED }, { "UHMIXED", vUHMIXED }, { "LHMIXED", vLHMIXED }, { "VIEWONLY", vVIEWONLY }, { 0, vINVALID }, }; /* Make sure we cover our bases... */ if (string != 0) { int n; for (n = 0; table[n].name != 0; n++) { if (!strcmp(string, table[n].name)) return table[n].code; } } return (EDisplayType)vINVALID; } static int comparSort (const void *a, const void *b) { return strcmp(*(const char *const*)a, (* (const char *const*) b)); } void sortList (char *list[], int length) { if (length > 1) qsort(list, (unsigned) length, sizeof(list[0]), comparSort); } /* * This strips white space from the given string. */ void stripWhiteSpace (EStripType stripType, char *string) { /* Declare local variables. */ unsigned stringLength = 0; unsigned alphaChar = 0; unsigned x; /* Make sure the string is not null. */ if (string != 0 && (stringLength = strlen(string)) != 0) { /* Strip leading whitespace */ if (stripType == vFRONT || stripType == vBOTH) { /* Find the first non-whitespace character. */ while (string[alphaChar] == ' ' || string[alphaChar] == '\t') { alphaChar++; } for (x = alphaChar; x <= stringLength; ++x) string[x - alphaChar] = string[x]; } /* Strip trailing whitespace */ if (stripType == vBACK || stripType == vBOTH) { stringLength = strlen(string); while (stringLength-- != 0 && (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 && *string != 0) { need = countChar(string, separator) + 2; if ((result = typeMallocN(char *, need)) != 0) { item = 0; first = string; for(;;) { while (*string != 0 && *string != separator) string++; need = string - first; if ((temp = typeMallocN(char, 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; } /* * Add a new string to a list. Keep a null pointer on the end so we can use * CDKfreeStrings() to deallocate the whole list. */ unsigned CDKallocStrings(char ***list, char *item, unsigned length, unsigned used) { unsigned need = 1; while (need < length + 2) need *= 2; if (need > used) { used = need; if (*list == 0) { *list = typeMallocN(char *, used); } else { *list = typeReallocN(char *, *list, used); } } (*list)[length++] = copyChar(item); (*list)[length] = 0; return used; } /* * 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, terminated by a null pointer. */ void CDKfreeStrings(char **list) { if (list != 0) { void *base = (void *)list; while (*list != 0) free(*list++); free(base); } } /* * Free a list of chtype-strings, terminated by a null pointer. */ void CDKfreeChtypes(chtype **list) { if (list != 0) { void *base = (void *)list; while (*list != 0) freeChtype(*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 #ifdef S_IFSOCK { S_IFSOCK, '@' }, /* Socket */ #endif { 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 CDKgetDirectoryContents (char *directory, char ***list) { /* Declare local variables. */ struct dirent *dirStruct; int counter = 0; DIR *dp; unsigned used = 0; /* 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 (strcmp(dirStruct->d_name, ".")) used = CDKallocStrings(list, dirStruct->d_name, counter++, used); } /* Close the directory. */ closedir (dp); /* Sort the info. */ sortList (*list, counter); /* 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. */ unsigned len; int Index = -1; int x, ret; /* Make sure the pattern isn't null. */ if (pattern != 0) { len = 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 alphabetically 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) Index = x; break; } } } return Index; } /* * 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] == L_MARKER && line[1] == 'F' && line[2] == '=') { /* Strip out the filename. */ while (x < len) { if (line[x] == R_MARKER) { break; } if (fPos < CDK_PATHMAX) filename[fPos++] = line[x]; ++x; } } filename[fPos] = '\0'; return (fPos != 0); } /* * Returns the filename portion of the given pathname, i.e., after the last * slash. */ char *baseName (char *pathname) { char *base = 0; unsigned pathLen; unsigned x; if (pathname != 0 && *pathname != '\0' && (base = copyChar (pathname)) != 0) { if ((pathLen = strlen (pathname)) != 0) { for (x = pathLen - 1; x != 0; --x) { /* Find the last '/' in the pathname. */ if (pathname[x] == '/') { strcpy(base, pathname + x + 1); break; } } } } return base; } /* * Returns the directory for the given pathname, i.e., the part before the * last slash. */ char *dirName (char *pathname) { char *dir = 0; unsigned pathLen; unsigned x; /* Check if the string is null. */ if (pathname != 0 && (dir = copyChar (pathname)) != 0 && (pathLen = strlen (pathname)) != 0) { x = pathLen; while ((dir[x] != '/') && (x > 0)) { dir[x--] = '\0'; } } 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 parent's size. */ if ((proposedDim == FULL) || (proposedDim == 0)) { dimension = parentDim; } else { /* If they gave a positive value, return it. */ if (proposedDim >= 0) { if (proposedDim >= parentDim) dimension = parentDim; else dimension = (proposedDim + adjustment); } else { /* * If they gave a negative value, then return the * dimension of the parent plus the value given. */ dimension = parentDim + proposedDim; /* Just to make sure. */ if (dimension < 0) dimension = parentDim; } } return dimension; } /* * This safely erases a given window. */ void eraseCursesWindow (WINDOW *window) { if (window != 0) { werase (window); wrefresh (window); } } /* * This safely deletes a given window. */ void deleteCursesWindow (WINDOW *window) { if (window != 0) { eraseCursesWindow (window); delwin (window); } } /* * This moves a given window (if we're able to set the window's beginning). * We do not use mvwin(), because it does (usually) not move subwindows. */ void moveCursesWindow (WINDOW *window, int xdiff, int ydiff) { if (window != 0) { int xpos, ypos; getbegyx(window, ypos, xpos); if (setbegyx(window, ypos, xpos) != ERR) { xpos += xdiff; ypos += ydiff; werase(window); (void) setbegyx(window, ypos, xpos); } else { Beep(); } } } /* * 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); } /* * Compatibility for different versions of curses. */ #if !(defined(HAVE_GETBEGX) && defined(HAVE_GETBEGY)) int getbegx(WINDOW *win) { int y, x; getbegyx(win, y, x); return x; } int getbegy(WINDOW *win) { int y, x; getbegyx(win, y, x); return y; } #endif #if !(defined(HAVE_GETMAXX) && defined(HAVE_GETMAXY)) int getmaxx(WINDOW *win) { int y, x; getmaxyx(win, y, x); return x; } int getmaxy(WINDOW *win) { int y, x; getmaxyx(win, y, x); return y; } #endif