/* * XPilot NG XP-MapEdit, a map editor for xp maps. Copyright (C) 1993 by * * Aaron Averill * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Modifications: * 1996: * Robert Templeman * 1997: * William Docter */ #include "xpmapedit.h" int screennum, root_width, root_height; Display *display; GC T_Back_GC, T_Fore_GC, T_Hlgt_GC, T_Shdw_GC; XFontStruct *T_Font; Atom ProtocolAtom; Atom KillAtom; char *T_Background = COLOR_BACKGROUND, *T_Highlight = COLOR_HIGHLIGHT, *T_Foreground = COLOR_FOREGROUND, *T_Shadow = COLOR_SHADOW; /***************************************************************************/ /* T_ConnectToServer */ /* Arguments : */ /* display_name */ /* Purpose : Open connection to X server and set global variables display, */ /* screennum, root_width, and root_height. Get toolkit GCs and */ /* font. */ /***************************************************************************/ void T_ConnectToServer(char *display_name) { if (display_name == NULL) { display_name = getenv("DISPLAY"); } if ((display = XOpenDisplay(display_name)) == NULL) { fprintf(stderr, "cannot connect to X server %s\n", XDisplayName(display_name)); exit(-1); } screennum = DefaultScreen(display); root_width = DisplayWidth(display, screennum); root_height = DisplayHeight(display, screennum); T_GetGC(&T_Fore_GC, T_Foreground); T_GetGC(&T_Back_GC, T_Background); T_GetGC(&T_Hlgt_GC, T_Highlight); T_GetGC(&T_Shdw_GC, T_Shadow); T_FontInit(&T_Font, "9x15"); ProtocolAtom = XInternAtom(display, "WM_PROTOCOLS", False); KillAtom = XInternAtom(display, "WM_DELETE_WINDOW", False); } /***************************************************************************/ /* T_CloseServerConnection */ /* Arguments : */ /* Purpose : Close X server connection, unload toolkit font and free GCs. */ /***************************************************************************/ void T_CloseServerConnection(void) { XUnloadFont(display, T_Font->fid); XFreeGC(display, T_Back_GC); XFreeGC(display, T_Fore_GC); XFreeGC(display, T_Hlgt_GC); XFreeGC(display, T_Shdw_GC); XCloseDisplay(display); } /***************************************************************************/ /* T_SetToolkitFont */ /* Arguments : */ /* font */ /* Purpose : Unload old toolkit font and load a new one with the name */ /* specified in the argument font. */ /***************************************************************************/ void T_SetToolkitFont(char *font) { XUnloadFont(display, T_Font->fid); T_FontInit(&T_Font, font); } /***************************************************************************/ /* T_GetGC */ /* Arguments : */ /* gc */ /* foreground */ /* Purpose : Set up a GC with the specified foreground color name, line */ /* width 0. Return integer pixel value of allocated color. */ /***************************************************************************/ int T_GetGC(GC * gc, char *foreground) { XGCValues values; unsigned long valuemask; XColor color; Colormap colormap; colormap = DefaultColormap(display, screennum); if (!(XParseColor(display, colormap, foreground, &color))) { color.pixel = WhitePixel(display, screennum); } else { if (!(XAllocColor(display, colormap, &color))) { color.pixel = WhitePixel(display, screennum); } } values.foreground = color.pixel; values.background = BlackPixel(display, screennum); values.line_width = 1; values.graphics_exposures = False; valuemask = GCForeground | GCBackground | GCLineWidth; *gc = XCreateGC(display, RootWindow(display, screennum), valuemask, &values); return color.pixel; } /***************************************************************************/ /* T_FontInit */ /* Arguments : */ /* fontinfo */ /* fontname */ /* Purpose : Load a font with the specified name into fontinfo. Return 0 */ /* if successful. If not, load font "9x15" and return 1. */ /***************************************************************************/ int T_FontInit(XFontStruct ** fontinfo, char *fontname) { if ((*fontinfo = XLoadQueryFont(display, fontname)) == NULL) { *fontinfo = XLoadQueryFont(display, "9x15"); fprintf(stderr, "Could not find font %s, using 9x15\n", fontname); return 1; } return 0; } /***************************************************************************/ /* T_MakeWindow */ /* Arguments : */ /* x */ /* y */ /* width */ /* height */ /* fg */ /* bg */ /* Purpose : Create a simple window with the specified x,y,width, and */ /* height. Set background and foreground to bg and fg. Set */ /* window hints such that the window cannot be resized. */ /***************************************************************************/ Window T_MakeWindow(int x, int y, int width, int height, char *fg, char *bg) { Window window; XColor color; Colormap colormap; int fgpixel, bgpixel; colormap = DefaultColormap(display, screennum); if (!(XParseColor(display, colormap, fg, &color))) { color.pixel = WhitePixel(display, screennum); } else { if (!(XAllocColor(display, colormap, &color))) { color.pixel = WhitePixel(display, screennum); } } fgpixel = color.pixel; if (!(XParseColor(display, colormap, bg, &color))) { color.pixel = BlackPixel(display, screennum); } else { if (!(XAllocColor(display, colormap, &color))) { color.pixel = BlackPixel(display, screennum); } } bgpixel = color.pixel; window = XCreateSimpleWindow(display, RootWindow(display, screennum), x, y, width, height, 4, fgpixel, bgpixel); T_SetWindowSizeLimits(window, width, height, width, height, 0, 0); XSetWMProtocols(display, window, &KillAtom, 1); return window; } /***************************************************************************/ /* T_SetWindowName */ /* Arguments : */ /* window */ /* windowname */ /* iconname */ /* Purpose : Sets window and icon name hints for window. */ /***************************************************************************/ void T_SetWindowName(Window window, char windowname[], char iconname[]) { XTextProperty windowName, iconName; if (XStringListToTextProperty(&windowname, 1, &windowName) == 0) { fprintf(stderr, "structure allocation for windowName failed.\n"); exit(-1); } if (XStringListToTextProperty(&iconname, 1, &iconName) == 0) { fprintf(stderr, "structure allocation for iconName failed.\n"); exit(-1); } XSetWMName(display, window, &windowName); XSetWMIconName(display, window, &iconName); XFree(windowName.value); XFree(iconName.value); } /***************************************************************************/ /* T_SetWindowSizeLimits */ /* Arguments : */ /* window */ /* minwidth */ /* minheight */ /* maxwidth */ /* maxheight */ /* aspectx */ /* aspecty */ /* Purpose : Sets size hints for window. */ /***************************************************************************/ void T_SetWindowSizeLimits(Window window, int minwidth, int minheight, int maxwidth, int maxheight, int aspectx, int aspecty) { XSizeHints *sizeh; /* Allocate memory for hints */ if (!(sizeh = XAllocSizeHints())) { fprintf(stderr, "failure allocating memory\n"); exit(-1); } sizeh->flags = PPosition | PSize; if ((maxwidth != 0) && (maxheight != 0)) { sizeh->flags = sizeh->flags | PMaxSize; sizeh->max_width = maxwidth; sizeh->max_height = maxheight; } if ((minwidth != 0) && (minheight != 0)) { sizeh->flags = sizeh->flags | PMinSize; sizeh->min_width = minwidth; sizeh->min_height = minheight; } if ((aspectx != 0) && (aspecty != 0)) { sizeh->flags = sizeh->flags | PAspect; sizeh->max_aspect.x = aspectx; sizeh->min_aspect.x = aspectx; sizeh->max_aspect.y = aspecty; sizeh->min_aspect.y = aspecty; } XSetWMNormalHints(display, window, sizeh); free(sizeh); } /***************************************************************************/ /* T_ClearArea */ /* Arguments : */ /* win */ /* x */ /* y */ /* width */ /* height */ /* Purpose : Fills window area with toolkit foreground color. */ /***************************************************************************/ void T_ClearArea(Window win, int x, int y, int width, int height) { XFillRectangle(display, win, T_Fore_GC, x, y, width, height); } /***************************************************************************/ /* T_DrawButton */ /* Arguments : */ /* win */ /* x */ /* y */ /* width */ /* height */ /* zheight */ /* clear */ /* Purpose : Draw a button on window win at x,y,width,height. Argument */ /* zheight may be RAISED or LOWERED. If clear is set, clear */ /* button area before drawing button. */ /***************************************************************************/ void T_DrawButton(Window win, int x, int y, int width, int height, int zheight, int clear) { if (clear) { XFillRectangle(display, win, T_Fore_GC, x, y, width + 1, height + 1); } if (zheight == RAISED) { XDrawLine(display, win, T_Hlgt_GC, x, y, x + width, y); XDrawLine(display, win, T_Hlgt_GC, x, y, x, y + height); XDrawLine(display, win, T_Back_GC, x, y + height, x + width, y + height); XDrawLine(display, win, T_Back_GC, x + width, y, x + width, y + height); } else { XDrawLine(display, win, T_Back_GC, x, y, x + width, y); XDrawLine(display, win, T_Back_GC, x, y, x, y + height); XDrawLine(display, win, T_Hlgt_GC, x, y + height, x + width, y + height); XDrawLine(display, win, T_Hlgt_GC, x + width, y, x + width, y + height); } } /***************************************************************************/ /* T_PopButton */ /* Arguments : */ /* win */ /* x */ /* y */ /* width */ /* height */ /* zheight */ /* Purpose : Move a button up or down depending on zheight. Copies area */ /* inside button up or down and redraws button border. */ /***************************************************************************/ void T_PopButton(Window win, int x, int y, int width, int height, int zheight) { if (zheight == RAISED) { XCopyArea(display, win, win, T_Fore_GC, x + 2, y + 2, width - 2, height - 2, x + 1, y + 1); } else { XCopyArea(display, win, win, T_Fore_GC, x + 1, y + 1, width - 2, height - 2, x + 2, y + 2); } T_DrawButton(win, x, y, width, height, zheight, 0); } /***************************************************************************/ /* T_DrawTextButton */ /* Arguments : */ /* win */ /* x */ /* y */ /* width */ /* height */ /* zheight */ /* string */ /* Purpose : Draw a button with a label string centered. */ /***************************************************************************/ void T_DrawTextButton(Window win, int x, int y, int width, int height, int zheight, char *string) { T_DrawButton(win, x, y, width, height, zheight, 1); if (string != NULL) T_DrawString(win, x + zheight, y + zheight, width, height, BKGR, string, JUSTIFY_CENTER, CROP_RIGHT, -1); } /***************************************************************************/ /* T_DrawString */ /* Arguments : */ /* win */ /* x */ /* y */ /* width */ /* height */ /* gc */ /* string */ /* justify */ /* crop */ /* cursorpos */ /* Purpose : Draw a string on win at x,y,width,height. gc may be a GC or */ /* the constant BKGR. justify may be one of the constants */ /* JUSTIFY_LEFT,JUSTIFY_RIGHT, or JUSTIFY_CENTER. crop may be */ /* CROP_RIGHT or CROP_LEFT. A cursor will be drawn under the */ /* character at curpos unless cursorpos is negative. */ /***************************************************************************/ void T_DrawString(Window win, int x, int y, int width, int height, GC gc, char *string, int justify, int crop, int cursorpos) { int length, c; c = cursorpos; XSetFont(display, gc, T_Font->fid); if (height < (T_Font->ascent + T_Font->descent)) return; length = strlen(string); /* crop the left side of the string until the cursor is in view */ if (cursorpos >= 0) { while ((XTextWidth(T_Font, string, c)) > width) { length--; string++; c--; } } /* crop the left or right side until the string fits */ while ((XTextWidth(T_Font, string, length)) > width) { length--; string += crop; } if (justify == JUSTIFY_CENTER) { x += width / 2 - XTextWidth(T_Font, string, length) / 2; } else if (justify == JUSTIFY_RIGHT) { x += width - XTextWidth(T_Font, string, length); } y = y + height / 2 + (T_Font->ascent + T_Font->descent) * 0.35; XDrawString(display, win, gc, x, y, string, length); if (cursorpos < 0) { return; } else if (cursorpos > length) { cursorpos = length; } XDrawString(display, win, gc, (int) (x + XTextWidth(T_Font, string, cursorpos) - XTextWidth(T_Font, CURSOR_CHAR, 1) / 2), (int) (y + (T_Font->ascent + T_Font->descent) * .7), CURSOR_CHAR, 1); } /***************************************************************************/ /* T_DrawText */ /* Arguments : */ /* win */ /* x */ /* y */ /* width */ /* height */ /* gc */ /* text */ /* Purpose : Draw text on win at x,y,width,height, splitting lines at */ /* word boundaries and newlines. gc may be a GC or the */ /* constant BKGR. */ /***************************************************************************/ void T_DrawText(Window win, int x, int y, int width, int height, GC gc, char *text) { int length, last, h, line; char *draw, *next, *curr; XSetFont(display, gc, T_Font->fid); h = (T_Font->ascent + T_Font->descent); draw = next = curr = text; length = last = line = 0; while ((*curr) != '\0') { while ((XTextWidth(T_Font, draw, length + 1) < width) && ((*curr) != '\0') && ((*curr) != '\n')) { length++; curr++; if ((*curr) == ' ') { last = length; next = curr; next++; } } if (last == 0) { last = length; next = curr; } if (((*curr) == '\n') || ((*curr) == '\0')) { last = length; next = curr; if ((*curr) == '\n') { next++; } } XDrawString(display, win, gc, x, (int) (y + line * h + .7 * h), draw, last); draw = curr = next; length = last = 0; line++; } }