17d8a9cc2Snia/* 27d8a9cc2Snia * Copyright 1988 by Evans & Sutherland Computer Corporation, 37d8a9cc2Snia * Salt Lake City, Utah 47d8a9cc2Snia * Portions Copyright 1989 by the Massachusetts Institute of Technology 57d8a9cc2Snia * Cambridge, Massachusetts 6645f5050Syouri * 77d8a9cc2Snia * Copyright 1992 Claude Lecommandeur. 8645f5050Syouri */ 9645f5050Syouri 10645f5050Syouri/*********************************************************************** 11645f5050Syouri * 12645f5050Syouri * $XConsortium: util.c,v 1.47 91/07/14 13:40:37 rws Exp $ 13645f5050Syouri * 14645f5050Syouri * utility routines for twm 15645f5050Syouri * 167d8a9cc2Snia * 28-Oct-87 Thomas E. LaStrange File created 17645f5050Syouri * 18645f5050Syouri * Do the necessary modification to be integrated in ctwm. 19645f5050Syouri * Can no longer be used for the standard twm. 20645f5050Syouri * 21645f5050Syouri * 22-April-92 Claude Lecommandeur. 22645f5050Syouri * 23645f5050Syouri * Changed behavior of DontMoveOff/MoveOffResistance to allow 24645f5050Syouri * moving a window off screen less than #MoveOffResistance pixels. 25645f5050Syouri * New code will no longer "snap" windows to #MoveOffResistance 26645f5050Syouri * pixels off screen and instead movements will just be stopped and 27645f5050Syouri * then resume once movement of #MoveOffResistance have been attempted. 28645f5050Syouri * 297d8a9cc2Snia * 15-December-02 Bjorn Knutsson 30645f5050Syouri * 31645f5050Syouri ***********************************************************************/ 32645f5050Syouri 337d8a9cc2Snia#include "ctwm.h" 34645f5050Syouri 35645f5050Syouri#include <stdio.h> 367d8a9cc2Snia#include <stdlib.h> 377d8a9cc2Snia#include <string.h> 387d8a9cc2Snia#include <strings.h> 39645f5050Syouri 40645f5050Syouri#include <signal.h> 41645f5050Syouri#include <sys/time.h> 42645f5050Syouri 437d8a9cc2Snia#include "animate.h" 447d8a9cc2Snia#include "add_window.h" 457d8a9cc2Snia#include "cursor.h" 467d8a9cc2Snia#include "drawing.h" 477d8a9cc2Snia#include "gram.tab.h" 487d8a9cc2Snia#include "iconmgr.h" 497d8a9cc2Snia#include "icons.h" 507d8a9cc2Snia#include "image.h" 517d8a9cc2Snia#include "screen.h" 527d8a9cc2Snia#include "util.h" 537d8a9cc2Snia#include "vscreen.h" 547d8a9cc2Snia#include "win_decorations.h" 557d8a9cc2Snia#include "win_resize.h" 56645f5050Syouri 57645f5050Syouri 587d8a9cc2Snia/* Handle for debug tracing */ 597d8a9cc2SniaFILE *tracefile = NULL; 60645f5050Syouri 61645f5050Syouri 627d8a9cc2Snia/* 637d8a9cc2Snia * Rewrite this, possibly in terms of replace_substr(). Alternately, the 647d8a9cc2Snia * places it's being used might be better served by being preprocessed 657d8a9cc2Snia * into arrays anyway. 66645f5050Syouri */ 677d8a9cc2Sniachar *ExpandFilePath(char *path) 68645f5050Syouri{ 697d8a9cc2Snia char *ret, *colon, *p; 707d8a9cc2Snia int len; 71645f5050Syouri 727d8a9cc2Snia len = 0; 737d8a9cc2Snia p = path; 747d8a9cc2Snia while((colon = strchr(p, ':'))) { 757d8a9cc2Snia len += colon - p + 1; 767d8a9cc2Snia if(*p == '~') { 777d8a9cc2Snia len += HomeLen - 1; 787d8a9cc2Snia } 797d8a9cc2Snia p = colon + 1; 80645f5050Syouri } 817d8a9cc2Snia if(*p == '~') { 827d8a9cc2Snia len += HomeLen - 1; 83645f5050Syouri } 847d8a9cc2Snia len += strlen(p); 857d8a9cc2Snia ret = malloc(len + 1); 867d8a9cc2Snia *ret = 0; 87645f5050Syouri 887d8a9cc2Snia p = path; 897d8a9cc2Snia while((colon = strchr(p, ':'))) { 907d8a9cc2Snia *colon = '\0'; 917d8a9cc2Snia if(*p == '~') { 927d8a9cc2Snia strcat(ret, Home); 937d8a9cc2Snia strcat(ret, p + 1); 947d8a9cc2Snia } 957d8a9cc2Snia else { 967d8a9cc2Snia strcat(ret, p); 977d8a9cc2Snia } 987d8a9cc2Snia *colon = ':'; 997d8a9cc2Snia strcat(ret, ":"); 1007d8a9cc2Snia p = colon + 1; 101645f5050Syouri } 1027d8a9cc2Snia if(*p == '~') { 1037d8a9cc2Snia strcat(ret, Home); 1047d8a9cc2Snia strcat(ret, p + 1); 105645f5050Syouri } 1067d8a9cc2Snia else { 1077d8a9cc2Snia strcat(ret, p); 1087d8a9cc2Snia } 1097d8a9cc2Snia return ret; 110645f5050Syouri} 111645f5050Syouri 112645f5050Syouri/*********************************************************************** 113645f5050Syouri * 114645f5050Syouri * Procedure: 1157d8a9cc2Snia * ExpandFilename - expand the tilde character to HOME 1167d8a9cc2Snia * if it is the first character of the filename 117645f5050Syouri * 118645f5050Syouri * Returned Value: 1197d8a9cc2Snia * a pointer to the new name 120645f5050Syouri * 121645f5050Syouri * Inputs: 1227d8a9cc2Snia * name - the filename to expand 123645f5050Syouri * 124645f5050Syouri *********************************************************************** 1257d8a9cc2Snia * 1267d8a9cc2Snia * Currently only used in one place in image_bitmap.c. I've left this 1277d8a9cc2Snia * here instead of moving it into images at the moment on the assumption 1287d8a9cc2Snia * that there might be other places in the codebase where it's useful. 129645f5050Syouri */ 1307d8a9cc2Sniachar * 1317d8a9cc2SniaExpandFilename(const char *name) 132645f5050Syouri{ 1337d8a9cc2Snia char *newname; 134645f5050Syouri 1357d8a9cc2Snia /* If it doesn't start with ~/ then it's not our concern */ 1367d8a9cc2Snia if(name[0] != '~' || name[1] != '/') { 1377d8a9cc2Snia return strdup(name); 138645f5050Syouri } 139645f5050Syouri 1407d8a9cc2Snia asprintf(&newname, "%s/%s", Home, &name[1]); 141645f5050Syouri 1427d8a9cc2Snia return newname; 143645f5050Syouri} 144645f5050Syouri 145645f5050Syouri 146df1c27a6Snia 147df1c27a6Snia/* 148df1c27a6Snia * Some color utils 149df1c27a6Snia */ 150df1c27a6Snia/** 151df1c27a6Snia * Get info from the server about a given color. 152df1c27a6Snia */ 1537d8a9cc2Sniavoid 1547d8a9cc2SniaGetColor(int kind, Pixel *what, const char *name) 155645f5050Syouri{ 1567d8a9cc2Snia XColor color; 1577d8a9cc2Snia Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c; 158645f5050Syouri 159df1c27a6Snia // If we have no valid X connection (generally means a --cfgchk or 160df1c27a6Snia // similar run; wont' happen in normal operations), just stub out. 161df1c27a6Snia if(dpy == NULL) { 162df1c27a6Snia *what = 0; 163df1c27a6Snia return; 164df1c27a6Snia } 165df1c27a6Snia 1667d8a9cc2Snia#ifndef TOM 1677d8a9cc2Snia if(!Scr->FirstTime) { 1687d8a9cc2Snia return; 169645f5050Syouri } 1708ae3b938Sjmcneill#endif 171645f5050Syouri 1727d8a9cc2Snia if(Scr->Monochrome != kind) { 1737d8a9cc2Snia return; 174645f5050Syouri } 175645f5050Syouri 1767d8a9cc2Snia if(! XParseColor(dpy, cmap, name, &color)) { 1777d8a9cc2Snia fprintf(stderr, "%s: invalid color name \"%s\"\n", ProgramName, name); 1787d8a9cc2Snia return; 179645f5050Syouri } 1807d8a9cc2Snia if(! XAllocColor(dpy, cmap, &color)) { 1817d8a9cc2Snia /* if we could not allocate the color, let's see if this is a 1827d8a9cc2Snia * standard colormap 1837d8a9cc2Snia */ 1847d8a9cc2Snia XStandardColormap *stdcmap = NULL; 185645f5050Syouri 1867d8a9cc2Snia if(! XParseColor(dpy, cmap, name, &color)) { 1877d8a9cc2Snia fprintf(stderr, "%s: invalid color name \"%s\"\n", ProgramName, name); 1887d8a9cc2Snia return; 1897d8a9cc2Snia } 190645f5050Syouri 1917d8a9cc2Snia /* 1927d8a9cc2Snia * look through the list of standard colormaps (check cache first) 1937d8a9cc2Snia */ 1947d8a9cc2Snia if(Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps && 1957d8a9cc2Snia (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap == 1967d8a9cc2Snia cmap)) { 1977d8a9cc2Snia stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]); 1987d8a9cc2Snia } 1997d8a9cc2Snia else { 2007d8a9cc2Snia StdCmap *sc; 2017d8a9cc2Snia 2027d8a9cc2Snia for(sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 2037d8a9cc2Snia int i; 2047d8a9cc2Snia 2057d8a9cc2Snia for(i = 0; i < sc->nmaps; i++) { 2067d8a9cc2Snia if(sc->maps[i].colormap == cmap) { 2077d8a9cc2Snia Scr->StdCmapInfo.mru = sc; 2087d8a9cc2Snia Scr->StdCmapInfo.mruindex = i; 2097d8a9cc2Snia stdcmap = &(sc->maps[i]); 2107d8a9cc2Snia goto gotit; 2117d8a9cc2Snia } 2127d8a9cc2Snia } 2137d8a9cc2Snia } 2147d8a9cc2Snia } 215645f5050Syouri 2167d8a9cc2Sniagotit: 2177d8a9cc2Snia if(stdcmap) { 2187d8a9cc2Snia color.pixel = (stdcmap->base_pixel + 2197d8a9cc2Snia ((Pixel)(((float)color.red / 65535.0) * 2207d8a9cc2Snia stdcmap->red_max + 0.5) * 2217d8a9cc2Snia stdcmap->red_mult) + 2227d8a9cc2Snia ((Pixel)(((float)color.green / 65535.0) * 2237d8a9cc2Snia stdcmap->green_max + 0.5) * 2247d8a9cc2Snia stdcmap->green_mult) + 2257d8a9cc2Snia ((Pixel)(((float)color.blue / 65535.0) * 2267d8a9cc2Snia stdcmap->blue_max + 0.5) * 2277d8a9cc2Snia stdcmap->blue_mult)); 2287d8a9cc2Snia } 2297d8a9cc2Snia else { 2307d8a9cc2Snia fprintf(stderr, "%s: unable to allocate color \"%s\"\n", 2317d8a9cc2Snia ProgramName, name); 2327d8a9cc2Snia return; 2337d8a9cc2Snia } 234645f5050Syouri } 235645f5050Syouri 2367d8a9cc2Snia *what = color.pixel; 2377d8a9cc2Snia return; 238645f5050Syouri} 239645f5050Syouri 240df1c27a6Snia 241df1c27a6Snia/** 242df1c27a6Snia * Try and create a 'shaded' version of a color for prettier UI. 243df1c27a6Snia */ 244df1c27a6Sniavoid 245df1c27a6SniaGetShadeColors(ColorPair *cp) 246645f5050Syouri{ 2477d8a9cc2Snia XColor xcol; 2487d8a9cc2Snia Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c; 2497d8a9cc2Snia bool save; 2507d8a9cc2Snia float clearfactor; 2517d8a9cc2Snia float darkfactor; 2527d8a9cc2Snia char clearcol [32], darkcol [32]; 253645f5050Syouri 254df1c27a6Snia // If we have no valid X connection (generally means a --cfgchk or 255df1c27a6Snia // similar run; wont' happen in normal operations), just stub out. 256df1c27a6Snia if(dpy == NULL) { 257df1c27a6Snia cp->shadc = 0; 258df1c27a6Snia cp->shadd = 0; 259df1c27a6Snia return; 260df1c27a6Snia } 261df1c27a6Snia 2627d8a9cc2Snia clearfactor = (float) Scr->ClearShadowContrast / 100.0; 2637d8a9cc2Snia darkfactor = (100.0 - (float) Scr->DarkShadowContrast) / 100.0; 2647d8a9cc2Snia xcol.pixel = cp->back; 2657d8a9cc2Snia XQueryColor(dpy, cmap, &xcol); 266645f5050Syouri 2677d8a9cc2Snia sprintf(clearcol, "#%04x%04x%04x", 2687d8a9cc2Snia xcol.red + (unsigned short)((65535 - xcol.red) * clearfactor), 2697d8a9cc2Snia xcol.green + (unsigned short)((65535 - xcol.green) * clearfactor), 2707d8a9cc2Snia xcol.blue + (unsigned short)((65535 - xcol.blue) * clearfactor)); 2717d8a9cc2Snia sprintf(darkcol, "#%04x%04x%04x", 2727d8a9cc2Snia (unsigned short)(xcol.red * darkfactor), 2737d8a9cc2Snia (unsigned short)(xcol.green * darkfactor), 2747d8a9cc2Snia (unsigned short)(xcol.blue * darkfactor)); 275645f5050Syouri 2767d8a9cc2Snia save = Scr->FirstTime; 2777d8a9cc2Snia Scr->FirstTime = true; 2787d8a9cc2Snia GetColor(Scr->Monochrome, &cp->shadc, clearcol); 2797d8a9cc2Snia GetColor(Scr->Monochrome, &cp->shadd, darkcol); 2807d8a9cc2Snia Scr->FirstTime = save; 281645f5050Syouri} 282645f5050Syouri 283df1c27a6Snia 284df1c27a6Snia 285df1c27a6Snia/* 286df1c27a6Snia * Various font utils 287df1c27a6Snia */ 288df1c27a6Snia/** 289df1c27a6Snia * Try adjusting a font's height. Used in drawing the icon manager. 290df1c27a6Snia */ 2917d8a9cc2Sniabool 2927d8a9cc2SniaUpdateFont(MyFont *font, int height) 293645f5050Syouri{ 2947d8a9cc2Snia int prev = font->avg_height; 2957d8a9cc2Snia font->avg_fheight = (font->avg_fheight * font->avg_count + height) 2967d8a9cc2Snia / (font->avg_count + 1); 2977d8a9cc2Snia font->avg_count++; 2987d8a9cc2Snia /* Arbitrary limit. */ 2997d8a9cc2Snia if(font->avg_count >= 256) { 3007d8a9cc2Snia font->avg_count = 256; 3017d8a9cc2Snia } 3027d8a9cc2Snia font->avg_height = (int)(font->avg_fheight + 0.5); 3037d8a9cc2Snia /* fprintf (stderr, "Updating avg with %d(%d) + %d -> %d(%f)\n", 3047d8a9cc2Snia * prev, font->avg_count, height, 3057d8a9cc2Snia * font->avg_height, font->avg_fheight); */ 3067d8a9cc2Snia return (prev != font->avg_height); 307645f5050Syouri} 308645f5050Syouri 309df1c27a6Snia 310df1c27a6Snia/** 311df1c27a6Snia * Load up fontsets from the X server. Only used by CreateFonts() below. 312df1c27a6Snia */ 313df1c27a6Sniastatic void 314df1c27a6SniaGetFont(MyFont *font) 315645f5050Syouri{ 3167d8a9cc2Snia char *deffontname = "fixed,*"; 3177d8a9cc2Snia char **missing_charset_list_return; 3187d8a9cc2Snia int missing_charset_count_return; 3197d8a9cc2Snia char *def_string_return; 3207d8a9cc2Snia XFontSetExtents *font_extents; 3217d8a9cc2Snia XFontStruct **xfonts; 3227d8a9cc2Snia char **font_names; 3237d8a9cc2Snia int i; 3247d8a9cc2Snia int ascent; 3257d8a9cc2Snia int descent; 3267d8a9cc2Snia int fnum; 3277d8a9cc2Snia char *basename2; 3287d8a9cc2Snia 329df1c27a6Snia // In special cases where we have no dpy, I don't think we're going 330df1c27a6Snia // to need details here, so just leave things untouched. We may need 331df1c27a6Snia // to stub in some magic values; deal with that when we run into the 332df1c27a6Snia // case. 333df1c27a6Snia if(dpy == NULL) { 334df1c27a6Snia return; 335df1c27a6Snia } 336df1c27a6Snia 3377d8a9cc2Snia if(font->font_set != NULL) { 3387d8a9cc2Snia XFreeFontSet(dpy, font->font_set); 3397d8a9cc2Snia } 3407d8a9cc2Snia 3417d8a9cc2Snia asprintf(&basename2, "%s,*", font->basename); 3427d8a9cc2Snia if((font->font_set = XCreateFontSet(dpy, basename2, 3437d8a9cc2Snia &missing_charset_list_return, 3447d8a9cc2Snia &missing_charset_count_return, 3457d8a9cc2Snia &def_string_return)) == NULL) { 3467d8a9cc2Snia fprintf(stderr, "Failed to get fontset %s\n", basename2); 3477d8a9cc2Snia if(Scr->DefaultFont.basename) { 3487d8a9cc2Snia deffontname = Scr->DefaultFont.basename; 3497d8a9cc2Snia } 3507d8a9cc2Snia if((font->font_set = XCreateFontSet(dpy, deffontname, 3517d8a9cc2Snia &missing_charset_list_return, 3527d8a9cc2Snia &missing_charset_count_return, 3537d8a9cc2Snia &def_string_return)) == NULL) { 3547d8a9cc2Snia fprintf(stderr, "%s: unable to open fonts \"%s\" or \"%s\"\n", 3557d8a9cc2Snia ProgramName, font->basename, deffontname); 3567d8a9cc2Snia exit(1); 3577d8a9cc2Snia } 3587d8a9cc2Snia } 3597d8a9cc2Snia free(basename2); 3607d8a9cc2Snia font_extents = XExtentsOfFontSet(font->font_set); 361645f5050Syouri 3627d8a9cc2Snia fnum = XFontsOfFontSet(font->font_set, &xfonts, &font_names); 3637d8a9cc2Snia for(i = 0, ascent = 0, descent = 0; i < fnum; i++) { 3647d8a9cc2Snia ascent = MaxSize(ascent, (*xfonts)->ascent); 3657d8a9cc2Snia descent = MaxSize(descent, (*xfonts)->descent); 3667d8a9cc2Snia xfonts++; 3677d8a9cc2Snia } 368645f5050Syouri 3697d8a9cc2Snia font->height = font_extents->max_logical_extent.height; 3707d8a9cc2Snia font->y = ascent; 3717d8a9cc2Snia font->ascent = ascent; 3727d8a9cc2Snia font->descent = descent; 3737d8a9cc2Snia font->avg_height = 0; 3747d8a9cc2Snia font->avg_fheight = 0.0; 3757d8a9cc2Snia font->avg_count = 0; 376645f5050Syouri} 377645f5050Syouri 378645f5050Syouri 379df1c27a6Snia/** 380df1c27a6Snia * Load up our various defined fonts 381df1c27a6Snia */ 382df1c27a6Sniavoid 383df1c27a6SniaCreateFonts(ScreenInfo *scr) 384df1c27a6Snia{ 385df1c27a6Snia#define LOADFONT(fld) (GetFont(&scr->fld##Font)) 386df1c27a6Snia LOADFONT(TitleBar); 387df1c27a6Snia LOADFONT(Menu); 388df1c27a6Snia LOADFONT(Icon); 389df1c27a6Snia LOADFONT(Size); 390df1c27a6Snia LOADFONT(IconManager); 391df1c27a6Snia LOADFONT(Default); 392df1c27a6Snia LOADFONT(workSpaceMgr.window); 393df1c27a6Snia#undef LOADFONT 394df1c27a6Snia 395df1c27a6Snia scr->HaveFonts = true; 396df1c27a6Snia} 397df1c27a6Snia 398df1c27a6Snia 399df1c27a6Snia 4007d8a9cc2Snia#if 0 4017d8a9cc2Sniastatic void move_to_head(TwmWindow *t) 402645f5050Syouri{ 4037d8a9cc2Snia if(t == NULL) { 4047d8a9cc2Snia return; 4057d8a9cc2Snia } 4067d8a9cc2Snia if(Scr->FirstWindow == t) { 4077d8a9cc2Snia return; 4087d8a9cc2Snia } 409645f5050Syouri 4107d8a9cc2Snia /* Unlink t from current position */ 4117d8a9cc2Snia if(t->prev) { 4127d8a9cc2Snia t->prev->next = t->next; 4137d8a9cc2Snia } 4147d8a9cc2Snia if(t->next) { 4157d8a9cc2Snia t->next->prev = t->prev; 4167d8a9cc2Snia } 417645f5050Syouri 4187d8a9cc2Snia /* Re-link t at head */ 4197d8a9cc2Snia t->next = Scr->FirstWindow; 4207d8a9cc2Snia if(Scr->FirstWindow != NULL) { 4217d8a9cc2Snia Scr->FirstWindow->prev = t; 4227d8a9cc2Snia } 4237d8a9cc2Snia t->prev = NULL; 4247d8a9cc2Snia Scr->FirstWindow = t; 425645f5050Syouri} 426645f5050Syouri 4277d8a9cc2Snia/* 4287d8a9cc2Snia * Moves window 't' after window 'after'. 4297d8a9cc2Snia * 4307d8a9cc2Snia * If 'after' == NULL, puts it at the head. 4317d8a9cc2Snia * If 't' == NULL, does nothing. 4327d8a9cc2Snia * If the 't' is already after 'after', does nothing. 4337d8a9cc2Snia */ 434645f5050Syouri 4357d8a9cc2Sniavoid move_to_after(TwmWindow *t, TwmWindow *after) 4367d8a9cc2Snia{ 4377d8a9cc2Snia if(after == NULL) { 4387d8a9cc2Snia move_to_head(t); 4397d8a9cc2Snia return; 4407d8a9cc2Snia } 4417d8a9cc2Snia if(t == NULL) { 4427d8a9cc2Snia return; 4437d8a9cc2Snia } 4447d8a9cc2Snia if(after->next == t) { 4457d8a9cc2Snia return; 4467d8a9cc2Snia } 4477d8a9cc2Snia 4487d8a9cc2Snia /* Unlink t from current position */ 4497d8a9cc2Snia if(t->prev) { 4507d8a9cc2Snia t->prev->next = t->next; 4517d8a9cc2Snia } 4527d8a9cc2Snia if(t->next) { 4537d8a9cc2Snia t->next->prev = t->prev; 4547d8a9cc2Snia } 4557d8a9cc2Snia 4567d8a9cc2Snia /* Re-link t after 'after' */ 4577d8a9cc2Snia t->next = after->next; 4587d8a9cc2Snia if(after->next) { 4597d8a9cc2Snia after->next->prev = t; 4607d8a9cc2Snia } 4617d8a9cc2Snia t->prev = after; 4627d8a9cc2Snia after->next = t; 4637d8a9cc2Snia} 4647d8a9cc2Snia#endif 4657d8a9cc2Snia 4667d8a9cc2Snia 467df1c27a6Snia 468df1c27a6Snia/** 469df1c27a6Snia * Backend for f.rescuewindows 470df1c27a6Snia */ 4717d8a9cc2Sniavoid RescueWindows(void) 4727d8a9cc2Snia{ 4737d8a9cc2Snia TwmWindow *twm_win = Scr->FirstWindow; 4747d8a9cc2Snia 4757d8a9cc2Snia while(twm_win) { 4767d8a9cc2Snia VirtualScreen *vs = twm_win->vs; 4777d8a9cc2Snia if(vs) { 4787d8a9cc2Snia /* 4797d8a9cc2Snia * Check if this window seems completely out of sight. 4807d8a9cc2Snia */ 4817d8a9cc2Snia int x = twm_win->frame_x; 4827d8a9cc2Snia int y = twm_win->frame_y; 4837d8a9cc2Snia int w = twm_win->frame_width; 4847d8a9cc2Snia int h = twm_win->frame_height; 4857d8a9cc2Snia int bw = twm_win->frame_bw; 4867d8a9cc2Snia int fullw = w + 2 * bw; 4877d8a9cc2Snia int fullh = h + 2 * bw; 4887d8a9cc2Snia int old_x = x, old_y = y; 4897d8a9cc2Snia struct Icon *i; 4907d8a9cc2Snia 4917d8a9cc2Snia#define MARGIN 20 4927d8a9cc2Snia 4937d8a9cc2Snia if(x >= vs->w - MARGIN) { 4947d8a9cc2Snia x = vs->w - fullw; 4957d8a9cc2Snia } 4967d8a9cc2Snia if(y >= vs->h - MARGIN) { 4977d8a9cc2Snia y = vs->h - fullh; 4987d8a9cc2Snia } 4997d8a9cc2Snia if((x + fullw <= MARGIN)) { 5007d8a9cc2Snia x = 0; 5017d8a9cc2Snia } 5027d8a9cc2Snia if((y + fullh <= MARGIN)) { 5037d8a9cc2Snia y = 0; 5047d8a9cc2Snia } 5057d8a9cc2Snia 5067d8a9cc2Snia if(x != old_x || y != old_y) { 5077d8a9cc2Snia SetupWindow(twm_win, x, y, w, h, -1); 5087d8a9cc2Snia } 5097d8a9cc2Snia 5107d8a9cc2Snia /* 5117d8a9cc2Snia * If there is an icon, check it too. 5127d8a9cc2Snia */ 5137d8a9cc2Snia i = twm_win->icon; 5147d8a9cc2Snia if(i != NULL) { 5157d8a9cc2Snia x = i->w_x; 5167d8a9cc2Snia y = i->w_y; 5177d8a9cc2Snia w = i->w_width; 5187d8a9cc2Snia h = i->w_height; 5197d8a9cc2Snia old_x = x; 5207d8a9cc2Snia old_y = y; 5217d8a9cc2Snia 5227d8a9cc2Snia if(x >= vs->w - MARGIN) { 5237d8a9cc2Snia x = vs->w - w; 5247d8a9cc2Snia } 5257d8a9cc2Snia if(y >= vs->h - MARGIN) { 5267d8a9cc2Snia y = vs->h - h; 5277d8a9cc2Snia } 5287d8a9cc2Snia if((x + w <= MARGIN)) { 5297d8a9cc2Snia x = 0; 5307d8a9cc2Snia } 5317d8a9cc2Snia if((y + h <= MARGIN)) { 5327d8a9cc2Snia y = 0; 5337d8a9cc2Snia } 5347d8a9cc2Snia 5357d8a9cc2Snia if(x != old_x || y != old_y) { 5367d8a9cc2Snia XMoveWindow(dpy, i->w, x, y); 5377d8a9cc2Snia i->w_x = x; 5387d8a9cc2Snia i->w_y = y; 5397d8a9cc2Snia } 5407d8a9cc2Snia } 5417d8a9cc2Snia#undef MARGIN 5427d8a9cc2Snia } 5437d8a9cc2Snia twm_win = twm_win->next; 5447d8a9cc2Snia } 545645f5050Syouri} 546645f5050Syouri 547df1c27a6Snia 548df1c27a6Snia 549df1c27a6Snia/** 550df1c27a6Snia * Backend for f.trace 551df1c27a6Snia */ 552df1c27a6Sniavoid 553df1c27a6SniaDebugTrace(char *file) 554645f5050Syouri{ 5557d8a9cc2Snia if(!file) { 5567d8a9cc2Snia return; 5577d8a9cc2Snia } 5587d8a9cc2Snia if(tracefile) { 5597d8a9cc2Snia fprintf(stderr, "stop logging events\n"); 5607d8a9cc2Snia if(tracefile != stderr) { 5617d8a9cc2Snia fclose(tracefile); 5627d8a9cc2Snia } 5637d8a9cc2Snia tracefile = NULL; 5647d8a9cc2Snia } 5657d8a9cc2Snia else { 5667d8a9cc2Snia if(strcmp(file, "stderr")) { 5677d8a9cc2Snia tracefile = fopen(file, "w"); 5687d8a9cc2Snia } 5697d8a9cc2Snia else { 5707d8a9cc2Snia tracefile = stderr; 5717d8a9cc2Snia } 5727d8a9cc2Snia fprintf(stderr, "logging events to : %s\n", file); 5737d8a9cc2Snia } 574645f5050Syouri} 575645f5050Syouri 576645f5050Syouri 577df1c27a6Snia 5787d8a9cc2Snia/* 5797d8a9cc2Snia * A safe strncpy(), which always ensures NUL-termination. 5807d8a9cc2Snia * 5817d8a9cc2Snia * XXX This is really just a slightly pessimized implementation of 5827d8a9cc2Snia * strlcpy(). Maybe we should use that instead, with a local 5837d8a9cc2Snia * implementation for systems like glibc-users that lack it? 5847d8a9cc2Snia */ 5857d8a9cc2Sniavoid 5867d8a9cc2Sniasafe_strncpy(char *dest, const char *src, size_t size) 587645f5050Syouri{ 5887d8a9cc2Snia strncpy(dest, src, size - 1); 5897d8a9cc2Snia dest[size - 1] = '\0'; 590645f5050Syouri} 591