/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * * (c) Copyright 1993, 1994 Hewlett-Packard Company * * (c) Copyright 1993, 1994 International Business Machines Corp. * * (c) Copyright 1993, 1994 Sun Microsystems, Inc. * * (c) Copyright 1993, 1994 Novell, Inc. * */ /******************************<+>************************************* ********************************************************************** ** ** File: dthello.c ** ** Project: HP Visual User Environment ** ** Description: ** ----------- ** This file implements the startup transition for the DT ** environment ** ** ********************************************************************** ** ** (c) Copyright 1990, 1991, 1992 Hewlett-Packard Company ** All rights reserved ** ********************************************************************** ******************************<+>*************************************/ /* * Notes on conditional compilation: * * AUTO_TOP If defined, the dthello window will automatically * raise itself over any window that obscures it. * * BLOCK_CENTER_FILES * If defined, dthello will center the text from * input files as a block as opposed to line-by-line. */ /* * Included Files: */ #include #include #include #include #include #include #include #include #include #include #include
#include #include #ifndef NO_MESSAGE_CATALOG # include #endif #include
#include "dthello.h" #ifndef NO_MESSAGE_CATALOG # define GETMESSAGE(set, number, string) GetMessage(set, number, string) #else # define GETMESSAGE(set, number, string) string #endif #if !defined(NL_CAT_LOCALE) #define NL_CAT_LOCALE 0 #endif /* * Globals */ Window welcome; /* Welcome window ID */ Display *dpy; /* X server connection */ struct globalStruct vhGD; int x_offset = 0; /* for left-justifying text */ int box_line_width = 0; /* for drawing a box */ XFontSet fontset; /* Font descriptor for ILS */ unsigned long textHeight; /* Font size parameters */ unsigned long fg, bg; /* Pixel values */ Boolean colorSuccess = True; /* Success at allocating colors */ XGCValues gcv; /* Struct for creating GC */ unsigned int totalHeight; /* total Height used for text */ unsigned int displayHeight; /* height of display in pixels */ int maxWidth; /* max width of lines read in from file */ unsigned int displayWidth; /* width of display in pixels */ GC gc; /* GC to draw with */ static XrmOptionDescRec optTable[] = { {"-font", "*vfont", XrmoptionSepArg, (XtPointer) NULL}, {"-fnt", "*vfont", XrmoptionSepArg, (XtPointer) NULL}, }; static int noptTable = sizeof(optTable)/sizeof(optTable[0]); ArgSpec argSpecs[] = { {"-bground", 8}, /* background color */ #define BG_ARG 0 {"-fground", 8}, /* foreground color */ #define FG_ARG 1 {"-string", 7}, /* string to display */ #define STRING_ARG 2 {"-fnt", 4}, /* font to use */ #define FONT_ARG 3 {"-timeout", 8}, /* timeout amount in seconds*/ #define TIME_ARG 4 {"-file", 5}, /* file */ #define FILE_ARG 5 }; char *ppchFileNames[MAX_FILES]; /* names of files to print */ unsigned char *ppchText[MAX_LINES]; /* text lines to print out */ int numFiles; /* number of files to print */ int numLines; /* number of text lines to print out */ #ifdef BLOCK_CENTER_FILES int centerLines; /* number of text lines to print centered */ #endif /* BLOCK_CENTER_FILES */ char *progName; /* who we are */ char *fontArg; /* font argument */ int sizeFontArg; char *stringArg; /* string argument */ int sizeStringArg; char *bgArg; /* background argument */ int sizeBgArg; char *fgArg; /* foreground argument */ int sizeFgArg; char *xoffsetArg; /* text x_offset argument */ int sizeXoffsetArg; char *timeArg; /* timeout argument, in seconds */ int sizeTimeArg; int sizeFileArg; Boolean Done; /* while painting text */ static VhResourceEntry restable[] = { { vNbackground, vCBackground, &bgArg, &sizeBgArg }, { vNforeground, vCForeground, &fgArg, &sizeFgArg }, { vNfont, vCFont, &fontArg, &sizeFontArg }, { vNxoffset, vCXoffset, &xoffsetArg, &sizeXoffsetArg }, { vNstring, vCString, &stringArg, &sizeStringArg }, { vNfile, vCFile, &ppchFileNames[0], &sizeFileArg }, { vNtimeout, vCTimeout, &timeArg, &sizeTimeArg }, }; void Usage(void) { fprintf(stderr, (char *) GETMESSAGE (4, 4, "usage: %s [-display ] [-bground ] [-fground ]\n"), progName); fprintf(stderr, "%s", (char *) GETMESSAGE (4, 5, "\t[-font ] [-string ] [-timeout ] [-file ]\n")); } /*************************************<->************************************* * * main (argc, argv) * * * Description: * ----------- * This is the main routine that does almost all the work. * * Inputs: * ------ * argc = Std C argument count * argv = Std C argument vector * * Outputs: * -------- * Exit code * * Comments: * --------- * This works by creating an override-redirect window the size of * the screen and painting a message on it. At the same time, a * 1x1 window is created that will be picked up by the window * manager. When the window manager reparents the little window, * this program exits. * * Synopsis: * --------- * dthello [-display ] [-fground ] [-bground ] * [-font ] [-string ] [-file ] * [-timeout ] * *************************************<->***********************************/ int main (int argc, char **argv) { Window wmwin; /* Window ID for wm */ XEvent event; /* Event received */ unsigned long mask; /* mask for window attribs */ XSetWindowAttributes xwa; /* Set Window Attribute struct */ int argn; /* temp for parsing args */ XColor colorDef; /* for parsing/allocating colors */ Colormap colormap; /* color map of screen */ Atom xaMwmHints; /* mwm hints atom */ PropMotifWmHints mwmHints; /* mwm hints structure */ Visual *pdv; /* X visual structure */ FILE *fp; /* file pointer */ int i; /* loop index */ char *default_string; /* default message */ XtAppContext appcontext; char *def_str; char **missing_clist; int missing_count; XFontSetExtents *extents; XtSetLanguageProc( NULL, NULL, NULL ); /* * Initialization */ /* * Set up NLSPATH, app-defaults, etc. for this DT client. */ _DtEnvControl(DT_ENV_SET); /* * Process command line arguments */ progName = argv[0]; /* fontArg = DEFAULT_FONT; */ bgArg = NULL; fgArg = NULL; timeArg = DEFAULT_TIME; numFiles = 0; sizeFileArg = 0; /* * Initialize Toolkit, open display */ XtToolkitInitialize(); appcontext = XtCreateApplicationContext(); dpy = XtOpenDisplay (appcontext, NULL, argv[0], DTHELLO_CLASS_NAME, optTable, noptTable, (int *)(&argc), argv); if (dpy == NULL) { setlocale(LC_ALL, ""); fprintf(stderr, (char *) GETMESSAGE(4, 1, "%s: can't open display\n"), progName); exit(1); } default_string = strdup ( ((char *)GETMESSAGE(2, 3, "Starting the\nCommon Desktop Environment\n\n"))); stringArg = default_string; /* * Find appropriate default font * and offset from the left side of the screen */ switch (_DtGetDisplayResolution(dpy, XDefaultScreen(dpy))) { case LOW_RES_DISPLAY: fontArg = DEFAULT_FONT_SMALL; x_offset = DEFAULT_XOFFSET_SMALL; box_line_width = BOX_LINE_WIDTH_SMALL; break; case MED_RES_DISPLAY: fontArg = DEFAULT_FONT_MEDIUM; x_offset = DEFAULT_XOFFSET_MEDIUM; box_line_width = BOX_LINE_WIDTH_MEDIUM; break; case HIGH_RES_DISPLAY: fontArg = DEFAULT_FONT_LARGE; x_offset = DEFAULT_XOFFSET_LARGE; box_line_width = BOX_LINE_WIDTH_LARGE; break; default: fontArg = DEFAULT_FONT_SMALL; x_offset = DEFAULT_XOFFSET_SMALL; box_line_width = BOX_LINE_WIDTH_SMALL; break; } /* * Fetch resources */ VhGetResources (dpy, progName, DTHELLO_CLASS, restable, XtNumber(restable)); /* assign the x_offset to the value set in the resource list if given by the user */ /* RK 11.06.93 */ if( xoffsetArg != NULL) x_offset = atoi(xoffsetArg); if (x_offset < 0) { x_offset = -x_offset; } if (sizeFileArg != 0) { numFiles = 1; } /* * Parse remaining command line arguments */ for (argn = 1; argn < argc; argn++) { if ((*argv[argn] == '-') && (argn+1 < argc)) { if (ArgMatch (argv[argn], BG_ARG)) { bgArg = argv[++argn]; continue; } else if (ArgMatch (argv[argn], FG_ARG)) { fgArg = argv[++argn]; continue; } else if (ArgMatch (argv[argn], STRING_ARG)) { stringArg = argv[++argn]; continue; } else if (ArgMatch (argv[argn], FONT_ARG)) { fontArg = argv[++argn]; continue; } else if (ArgMatch (argv[argn], TIME_ARG)) { timeArg = argv[++argn]; if (atoi(timeArg) <= 0) { fprintf (stderr, (char *) GETMESSAGE(4, 2, "%s: timeout must be positive\n"), argv[0]); timeArg = DEFAULT_TIME; } continue; } else if (ArgMatch (argv[argn], FILE_ARG)) { argn++; if (numFiles < MAX_FILES) { ppchFileNames[numFiles] = (char *) argv[argn]; numFiles++; } else { fprintf(stderr, (char *) GETMESSAGE(4, 3, "%1$s: Maxiumum of %2$d files allowed, skipping %3$s\n"), argv[0], MAX_FILES, argv[argn]); } continue; } else { Usage(); exit(1); } } else { Usage(); exit(1); } } displayHeight = XDisplayHeight (dpy, XDefaultScreen(dpy)); displayWidth = XDisplayWidth (dpy, XDefaultScreen(dpy)); /* * Set default fg/bg colors if not specified. * (adjust for low-color systems) */ pdv = XDefaultVisual(dpy, XDefaultScreen(dpy)); /* * Set default colors if not specified on command line. */ if ((XDefaultDepth(dpy, XDefaultScreen(dpy)) <= 4) || (pdv->class == StaticGray) || (pdv->class == GrayScale)) { /* * B&W, GrayScale, or low-color systems */ if (!bgArg) { bgArg = DEFAULT_LOW_BG; } if (!fgArg) { fgArg = DEFAULT_LOW_FG; } } else { /* * Medium- to High-color systems */ if (!bgArg) { bgArg = DEFAULT_BG; } if (!fgArg) { fgArg = DEFAULT_FG; } } /* * Load the font. */ if ((fontset = XCreateFontSet(dpy, fontArg, &missing_clist, &missing_count, &def_str)) == NULL) { fprintf(stderr, (char *) GETMESSAGE (4, 6, "%1$s: display %2$s doesn't know font %3$s\n"), argv[0], DisplayString(dpy), fontArg); if ((fontset = XCreateFontSet(dpy, DEFAULT_FONT, &missing_clist, &missing_count, &def_str)) == NULL) { fprintf(stderr, (char *) GETMESSAGE (4, 6, "%1$s: display %2$s doesn't know font %3$s\n"), argv[0], DisplayString(dpy), DEFAULT_FONT); } if ((NULL == fontset) && (fontset = XCreateFontSet(dpy, FIXED_FONT, &missing_clist, &missing_count, &def_str)) == NULL) { fprintf(stderr, (char *) GETMESSAGE (4, 6, "%1$s: display %2$s doesn't know font %3$s\n"), argv[0], DisplayString(dpy), FIXED_FONT); exit(1); } } extents = XExtentsOfFontSet(fontset); textHeight = extents->max_ink_extent.height; /* * Print the copyright file by default if no other file * specified */ #ifdef DEFAULT_FILE if (numFiles == 0) { ppchFileNames[numFiles] = (char *) DEFAULT_FILE; numFiles = 1; } #endif /* * Break the text string up into separate lines * and place into message buffer. */ SeparateTextLines ((unsigned char *)stringArg); #ifdef BLOCK_CENTER_FILES centerLines = numLines; #endif /* BLOCK_CENTER_FILES */ for (i = 0; i < numFiles; i++) { maxWidth = 0; if (!(fp = fopen ((char *)ppchFileNames[i], "r"))) { fprintf (stderr, (char *) GETMESSAGE (4, 7, "%1$s: unable to open file %2$s\n"), argv[0], ppchFileNames[i]); } else { /* * read in lines */ ReadInTextLines (fp, fontset, (unsigned int *)&maxWidth); } } /* * Get the colors */ colormap = XDefaultColormap (dpy, XDefaultScreen(dpy)); /* * Get background color */ if (!XParseColor (dpy, colormap, bgArg, &colorDef)) { /* failed to get background color, try low color default */ colorSuccess = False; fprintf(stderr, (char *) GETMESSAGE (4, 8, "%1$s: can't set background to %2$s, using %3$s.\n"), argv[0], bgArg, DEFAULT_LOW_BG); XParseColor (dpy, colormap, DEFAULT_LOW_BG, &colorDef); } XAllocColor (dpy, colormap, &colorDef); bg = colorDef.pixel; /* * Get foreground color */ if (!XParseColor (dpy, colormap, fgArg, &colorDef)) { /* failed to get foreground color, try low color default */ colorSuccess = False; fprintf(stderr, (char *) GETMESSAGE (4, 9, "%1$s: can't set foreground to %2$s, using %3$s.\n"), argv[0], fgArg, DEFAULT_LOW_FG); XParseColor (dpy, colormap, DEFAULT_LOW_FG, &colorDef); } XAllocColor (dpy, colormap, &colorDef); fg = colorDef.pixel; /* * Create 1x1 window to catch reparenting action of window manager * Request no mwm decoration to reduce flash. * Request no mwm functions to avoid icon in icon box. */ wmwin = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0, bg, bg); xaMwmHints = XInternAtom (dpy, _XA_MOTIF_WM_HINTS, 0); mwmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; mwmHints.decorations = 0; mwmHints.functions = 0; XChangeProperty (dpy, wmwin, xaMwmHints, xaMwmHints, 32, PropModeReplace, (unsigned char *) &mwmHints, sizeof(PropMotifWmHints)/sizeof(long)); XSelectInput (dpy, wmwin, StructureNotifyMask); XMapWindow(dpy, wmwin); /* * Create override-redirect window for display of transition * message. */ welcome = XCreateSimpleWindow (dpy, DefaultRootWindow (dpy), 0, 0, displayWidth, displayHeight, 0, bg, bg); mask = CWOverrideRedirect | CWEventMask | CWCursor; xwa.override_redirect = 1; #ifdef AUTO_TOP xwa.event_mask = ExposureMask | VisibilityChangeMask; #else /* AUTO_TOP */ xwa.event_mask = ExposureMask; #endif /* AUTO_TOP */ xwa.cursor = _DtGetHourGlassCursor(dpy); XChangeWindowAttributes (dpy, welcome, mask, &xwa); XMapWindow(dpy, welcome); /* * Event loop for painting text */ Done = True; while (Done) { /* * Get the next event */ /* XNextEvent(dpy, &event); */ XtAppNextEvent(appcontext, &event); if (event.type == Expose && event.xexpose.window == welcome && event.xexpose.count == 0) { /* * Remove any other pending Expose events from the queue */ while (XCheckTypedEvent(dpy, Expose, &event)); /* * Create the GC for drawing the box and painting the text. */ gcv.foreground = fg; gcv.background = bg; gc = XCreateGC(dpy, welcome, (GCForeground | GCBackground), &gcv); XClearWindow(dpy, welcome); DrawBox(); PaintText(); XFlush(dpy); Done = False; } } /* end while */ /* * set up the timeout */ signal (SIGALRM, (void (*)()) CatchAlarm); alarm (atoi(timeArg)); /* * Event loop */ while (True) { /* * Get the next event */ /* XNextEvent(dpy, &event); */ XtAppNextEvent(appcontext, &event); if (event.type == ReparentNotify && event.xany.window == wmwin) { /* * this is our cue...exit, stage left */ alarm(0); break; } else { /* normal color serving process */ XtDispatchEvent(&event); } } /* end while */ exit(0); } /*************************************<->************************************* * * ArgMatch (pch, arn) * * * Description: * ----------- * This function determines if a string matches a predefined switch. * * Inputs: * ------ * pch = candidate string * arn = number of switch we are trying to match. * * Outputs: * -------- * Return = True if match succeeds. * * Comments: * --------- * Would need work to be localized. * *************************************<->***********************************/ int ArgMatch (char *pch, int arn) { int rval = False; if (!strncmp(pch, argSpecs[arn].name, argSpecs[arn].len)) { rval = True; } return (rval); } /*************************************<->************************************* * * SkipWhitespace (*pch) * * * Description: * ----------- * This procedure scans a string and returns a pointer to the first * non-whitespace character. * * Inputs: * ------ * pch = pointer to string to scan * * Outputs: * -------- * Return = pointer to first non-white character * * Comments: * --------- * Skips blanks and horizontal tabs. * *************************************<->***********************************/ unsigned char * SkipWhitespace (unsigned char *pch) { int chlen; if (pch) { while ((*pch != '\0') && ((chlen = mblen ((char *)pch, MB_CUR_MAX)) == 1) && ((*pch == '\t') || (*pch == ' '))) { pch += chlen; } } return (pch); } /*************************************<->************************************* * * KillNewlines (*pch) * * * Description: * ----------- * This procedure scans a string and replaces the first newline * with a NULL. * * Inputs: * ------ * pch = pointer to string to scan * * Outputs: * -------- * pch = modified * * Comments: * --------- * *************************************<->***********************************/ void KillNewlines (unsigned char *pch) { int chlen; if (pch) { while (*pch != '\0') { if (((chlen = mblen ((char *)pch, MB_CUR_MAX)) == 1) && (*pch == '\n')) { *pch = '\0'; break; } pch += chlen; } } } /*************************************<->************************************* * * ReadInTextLines (fp, font, pMaxWidth) * * * Description: * ----------- * This procedure reads in lines from a file for the message to * display. * * Inputs: * ------ * pchIn = pointer to message string * font = font structure to be used to print with * pMaxWidth = width of largest line * * Outputs: * -------- * Return = none * modifies global numLines * * Comments: * --------- * Global data ppchText is modified by this routine to contain * copies of the text lines from pchIn. pchIn is not modified. * *************************************<->***********************************/ void ReadInTextLines (FILE *fp, XFontSet fontset, unsigned int *pMaxWidth) { unsigned int width; int allowedLines; /* count the number of lines in the file */ allowedLines = (displayHeight - (2 * box_line_width))/ textHeight; while (numLines < allowedLines) { ppchText[numLines] = (unsigned char *) malloc (1+MAX_COLUMNS); if (!ppchText[numLines] || !fgets ((char *)ppchText[numLines], MAX_COLUMNS, fp)) { break; } KillNewlines (ppchText[numLines]); #ifndef BLOCK_CENTER_FILES ppchText[numLines] = SkipWhitespace (ppchText[numLines]); #endif /* not BLOCK_CENTER_FILES */ width = XmbTextEscapement(fontset, (char *)(ppchText[numLines]), strlen((char *)ppchText[numLines])); if (width > *pMaxWidth) { *pMaxWidth = width; } numLines++; } } /*************************************<->************************************* * * SeparateTextLines (pchIn) * * * Description: * ----------- * This procedure takes a message string and separates it into * text lines based on the presence of new line characters. * * Inputs: * ------ * pchIn = pointer to message string * * Outputs: * -------- * Return = none * * Comments: * --------- * Global data ppchText is modified by this routine to contain * copies of the text lines from pchIn. pchIn is not modified. * *************************************<->***********************************/ void SeparateTextLines (unsigned char *pchIn) { unsigned char *pch, *pch1, *pch2; unsigned char *pchInEnd; int i, chlen = 0; /* count the number of new line characters in the string */ numLines = 1; for (pch = pchIn; *pch; ) { if (((chlen = mblen ((char *)pch, MB_CUR_MAX)) == 1) && (*pch == '\n')) { numLines++; } pch += chlen; } if ((chlen == 1) && (*(pch-1) == '\n')) { numLines--; /* don't count terminating newline */ } pch2 = pch1 = pchIn; pchInEnd = pchIn + strlen((char *)pchIn); for (i = 0; (i < numLines) && (pch1 < pchInEnd); i++) { while ((*pch2 != '\0') && !(((chlen = mblen ((char *)pch2, MB_CUR_MAX)) == 1) && (*pch2 == '\n'))) { pch2 += chlen; } if (*pch2 == '\n') { *pch2 = '\0'; } ppchText[i] = (unsigned char *) malloc (1+strlen ((char *)pch1)); if (ppchText[i]) { strcpy ((char *)ppchText[i], (char *)pch1); } else { fprintf (stderr, (char *) GETMESSAGE (4, 10, "%s: Insufficient memory (SeparateTextLines)\n"), progName); exit (1); } /* advance pointers */ pch1 = ++pch2; } } /*************************************<->************************************* * * CatchAlarm (sig) * * * Description: * ----------- * This function catches the SIG_ALRM signal generated when the * timer expires. * * Inputs: * ------ * sig = signal number * * Outputs: * -------- * Return = none * * Comments: * --------- * *************************************<->***********************************/ void CatchAlarm ( int sig) { /* timer expired, exit */ exit(0); } #ifndef NO_MESSAGE_CATALOG /***************************************************************************** * * Function: GetMessage * * Parameters: * * int set - The message catalog set number. * * int n - The message number. * * char *s - The default message if the message is not * retrieved from a message catalog. * * Returns: the string for set 'set' and number 'n'. * *****************************************************************************/ char * GetMessage( int set, int n, char *s ) { char *msg; char *lang; nl_catd catopen(); char *catgets(); static int first = 1; static nl_catd nlmsg_fd; if ( first ) { first = 0; lang = (char *) getenv ("LANG"); if (!lang || !(strcmp (lang, "C"))) /* * If LANG is not set or if LANG=C, then there * is no need to open the message catalog - just * return the built-in string "s". */ nlmsg_fd = (nl_catd)-1; else nlmsg_fd = catopen("dthello", NL_CAT_LOCALE); } msg=catgets(nlmsg_fd,set,n,s); return (msg); } #endif /*************************************<->************************************* * * void VhGetResources * * * Description: * ----------- * Gets the resources for the client * * * Inputs: * ------ * * Outputs: * ------- * * Comments: * -------- * *************************************<->***********************************/ void VhGetResources(Display *dpy, char *name, char *class, VhResourceEntry *res, int num) { #define INIT_SIZE 256 #define SRCH_SIZE 20 int i; XrmValue xrmv; XrmQuark Qtype, Qstring, Qname, Qclass; XrmQuark Qnres[4], Qcres[4]; XrmHashTable searchList[SRCH_SIZE]; /* * We only deal with string-type resources */ Qstring = XrmStringToQuark (XtRString); /* * Get resource search list for "dthello" */ XrmStringToQuarkList (name, Qnres); XrmStringToQuarkList (class, Qcres); if (XrmQGetSearchList(XtDatabase(dpy), Qnres, Qcres, searchList, SRCH_SIZE)) { /* * Look for all resources at this level */ for (i = 0; i < num; i++) { Qname = XrmStringToQuark (res[i].resname); Qclass = XrmStringToQuark (res[i].resclass); if ((XrmQGetSearchResource (searchList, Qname, Qclass, &Qtype, &xrmv)) && (Qtype == Qstring)) { *(res[i].ppvalue) = (char *) xrmv.addr; *res[i].size = (int) xrmv.size; } } } } void PaintText( void ) { int i, x, y; XFontSetExtents *extents; /* * Paint the string onto the screen */ y = (displayHeight - totalHeight) / 2; if (y < 0) { y = 0; } /* adjust origin by font metric */ extents = XExtentsOfFontSet(fontset); y += -(extents->max_logical_extent.y); x = box_line_width + x_offset; for (i = 0; i < numLines; i++) { /* draw the string */ XmbDrawString (dpy, welcome, fontset, gc, x, y, (char *)(ppchText[i]), strlen((char *)ppchText[i])); /* move to next "line" */ y += textHeight; } } void DrawBox( void ) { int LTX, LTY, RTX, RTY, LBX, LBY, RBX, RBY; int L_middle; /* pixels to the midpoint of the line width */ Boolean useDecoration = True; /* compute the height of the font */ totalHeight = textHeight * numLines; /* * Set limits */ if ((( 2 * box_line_width ) + x_offset + maxWidth) > displayWidth) { useDecoration = False; x_offset = 0; } if (!useDecoration) return; L_middle = box_line_width / 2; /******************************************************** +----------------------------------------------+ | (LTX, LTY) (RTX, RTY) | | | | (Draw counterclockwise, beginning from | | top left.) | | | | | | | | | | | | | | (LBX, LBY) (RBX, RBY) | +----------------------------------------------+ ********************************************************/ LTX = 0; LTY = 0; RTX = displayWidth; RTY = 0; LBX = 0; LBY = displayHeight; RBX = displayWidth ; RBY = displayHeight; XSetLineAttributes(dpy, gc, box_line_width, LineSolid, CapButt, JoinMiter); XDrawLine(dpy, welcome, gc, LTX, LTY + L_middle, RTX, RTY + L_middle); XDrawLine(dpy, welcome, gc, RTX - L_middle, RTY, RBX - L_middle, RBY); XDrawLine(dpy, welcome, gc, RBX, RBY - L_middle, LBX, LBY - L_middle); XDrawLine(dpy, welcome, gc, LBX + L_middle, LBY, LTX + L_middle, LTY); } int Xestrcmp(const char * const s1, const char * const s2) { if (s1 == s2) return 0; { const char * p1 = (s1) ? s1 : ""; const char * p2 = (s2) ? s2 : ""; return strcmp((char *)p1, (char *)p2); } } /************** eof ******************/