/* * XMapEdit, the XPilot Map Editor. 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 to XMapEdit * 1996: * Robert Templeman * 1997: * William Docter * * $Id: T_Toolkit.c,v 5.0 2001/04/07 20:01:00 dik Exp $ */ #include "T_Toolkit.h" #include "default_colors.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; #ifdef MONO char *T_Background = COLOR_BACKGROUND, *T_Foreground = COLOR_FOREGROUND; #else char *T_Background = COLOR_BACKGROUND, *T_Highlight = COLOR_HIGHLIGHT, *T_Foreground = COLOR_FOREGROUND, *T_Shadow = COLOR_SHADOW; #endif /***************************************************************************/ /* 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); #ifndef MONO T_GetGC(&T_Hlgt_GC, T_Highlight); T_GetGC(&T_Shdw_GC, T_Shadow); #endif 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); #ifndef MONO XFreeGC(display, T_Hlgt_GC); XFreeGC(display, T_Shdw_GC); #endif 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) { #ifdef MONO XFillRectangle(display,win,T_Back_GC,x,y,width,height); #else XFillRectangle(display,win,T_Fore_GC,x,y,width,height); #endif } /***************************************************************************/ /* 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) { #ifdef MONO if ( clear ) { XFillRectangle(display, win, T_Back_GC, x, y, width+1, height+1); } XDrawRectangle(display, win, T_Fore_GC, x, y, width, height); if ( zheight == RAISED ) { XDrawRectangle(display, win, T_Back_GC, x+1, y+1, width-2, height-2); } else { XDrawRectangle(display, win, T_Fore_GC, x+1, y+1, width-2, height-2); } #else 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); } #endif } /***************************************************************************/ /* 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) { #ifdef MONO XCopyArea(display,win,win,T_Fore_GC,x+2,y+2,width-3,height-3,x+1,y+1); XDrawRectangle(display, win, T_Back_GC, x+1, y+1, width-3, height-3); #else XCopyArea(display,win,win,T_Fore_GC,x+2,y+2,width-2,height-2,x+1,y+1); #endif } 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) != (char) NULL ) { while ( (XTextWidth(T_Font,draw,length+1) < width) && ((*curr) != (char) NULL) && ((*curr) != '\n') ) { length++; curr++; if ((*curr) == ' ') { last = length; next = curr; next++; } } if (last == 0) { last = length; next = curr; } if ( ((*curr) == '\n') || ((*curr) == (char) NULL) ) { 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++; } }