/* 
 *  WindowMaker window manager
 * 
 *  Copyright (c) 1997 Alfredo K. Kojima
 * 
 *  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.
 */
#include "wconfig.h"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>

#include "generic/wwmlib.h"
#include "WindowMaker.h"
#include "GNUstep.h"
#include "version.h"
#include "screen.h"
#include "wcore.h"
#include "window.h"
#include "funcs.h"


extern *DisplayName;

#ifdef USECPP
static void
putdef(char *line, char *name, char *value)
{
    if (!value) {
	wWarning(_("could not define value for %s for cpp"), name);
	return;
    }
    strcat(line, name);
    strcat(line, value);
}



static void
putidef(char *line, char *name, int value)
{
    char tmp[64];
    sprintf(tmp, "%i", value);
    strcat(line, name);
    strcat(line, tmp);
}


static char*
username()
{
    char *tmp;
    
    tmp = getlogin();
    if (!tmp) {
	struct passwd *user;

	user = getpwuid(getuid());
	if (!user) {
	    wSysError(_("could not get password entry for UID %i"), getuid());
	    return NULL;
	}
	if (!user->pw_name) {
	    return NULL;
	} else {
	    return user->pw_name;
	}
    }
    return tmp;
}
       
char *
MakeCPPArgs(char *path)
{
    int i;
    char buffer[MAXLINE], *buf, *line;
    char version[64];
    Visual *visual;
    
    line = wmalloc(MAXLINE);
    *line = 0;
    i=1;
    if ((buf=getenv("HOSTNAME"))!=NULL) {
	if (buf[0]=='(') {
	    wWarning(_("your machine is misconfigured. HOSTNAME is set to %s"),
		     buf);
	} else 
	  putdef(line, " -DHOST=", buf);
    } else if ((buf=getenv("HOST"))!=NULL) {
	if (buf[0]=='(') {
	    wWarning(_("your machine is misconfigured. HOST is set to %s"),
		     buf);
	} else 
	  putdef(line, " -DHOST=", buf);
    }
    buf = username();
    if (buf)
      putdef(line, " -DUSER=", buf);
    putidef(line, " -DUID=", getuid());
    buf = XDisplayName(DisplayString(dpy));
    putdef(line, " -DDISPLAY=", buf);
    putidef(line, " -DMAJ_VERSION=", MAJ_VERSION);
    putidef(line, " -DMIN_VERSION=", MIN_VERSION);
    sprintf(version, "%d.%d.%d", MAJ_VERSION, MIN_VERSION, SUBMIN_VERSION);
    putdef(line, " -DWM_VERSION=", version);
    
    visual = DefaultVisual(dpy, DefaultScreen(dpy));
    putidef(line, " -DVISUAL=", visual->class);
    
    putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy)));

    putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy)));
    putidef(line, " -DSCR_HEIGHT=", 
	    HeightOfScreen(DefaultScreenOfDisplay(dpy)));

    strcpy(buffer, path);    
    buf = strrchr(buffer, '/');
    if (buf) *buf = 0; /* trunc filename */
    putdef(line, " -I", buffer);
    
#undef arg
#ifdef DEBUG
    puts("CPP ARGS");
    puts(line);
#endif
    return line;
}
#endif /* USECPP */


WWindow*
NextFocusWindow(WScreen *scr)
{
    WWindow *tmp, *wwin, *closest, *min;
    Window d;
    
    wwin = scr->focused_window;
    tmp = wwin->prev;
    closest = NULL;
    min = wwin;
    d = 0xffffffff;
    while (tmp) {
	if ((tmp->flags.mapped || tmp->flags.shaded) 
	    && tmp->window_flags.focusable) {
	    if (min->client_win > tmp->client_win)
	      min = tmp;
	    if (tmp->client_win > wwin->client_win
		&& (!closest
		    || (tmp->client_win - wwin->client_win) < d)) {
		closest = tmp;
		d = tmp->client_win - wwin->client_win;
	    }
	}
	tmp = tmp->prev;
    }
    if (!closest||closest==wwin)
      return min;
    return closest;
}


WWindow*
PrevFocusWindow(WScreen *scr)
{
    WWindow *tmp, *wwin, *closest, *max;
    Window d;
    
    wwin = scr->focused_window;
    tmp = wwin->prev;
    closest = NULL;
    max = wwin;
    d = 0xffffffff;
    while (tmp) {
	if ((tmp->flags.mapped || tmp->flags.shaded)
	    && tmp->window_flags.focusable) {
	    if (max->client_win < tmp->client_win)
	      max = tmp;
	    if (tmp->client_win < wwin->client_win
		&& (!closest
		    || (wwin->client_win - tmp->client_win) < d)) {
		closest = tmp;
		d = wwin->client_win - tmp->client_win;
	    }
	}
	tmp = tmp->prev;
    }
    if (!closest||closest==wwin)
      return max;
    return closest;
}

#if 1
/*
 *  XFetchName Wrapper
 *
 */

Status MyXFetchName(dpy, win, winname)
Display *dpy;
Window win;
char **winname;
{
    XTextProperty text;
    char **list;
    int nitems;
    Status status_ret;
 
    if (XGetWMName(dpy, win, &text) != 0) {
	if (text.value) {
	    text.nitems = strlen((char*)text.value);
	    if (text.value[0] == '\0') {
		*winname = (char*)text.value;
		return 1;
	    }
	}
	status_ret = XmbTextPropertyToTextList(dpy,&text,&list,&nitems);
	if (status_ret == Success && *list && nitems > 0) {
	    *winname = *list;
	    return 1;
	} else if (status_ret > Success) {
	    *winname = (char *)text.value;
	    return 1;
	} else
	  *winname = NULL;
    } else
      *winname = NULL;
    return 0;  
}

/*
 *  XGetIconName Wrapper
 *
 */

Status MyXGetIconName(dpy, win, iconname)
Display *dpy;
Window win;
char **iconname;
{
    Atom actual_type;
    int actual_format;
    unsigned long nitems, bytesafter;
    char **list;
    int num;
    XTextProperty text_prop;
    Status status_ret;

    if (XGetWindowProperty(dpy, win, XA_WM_ICON_NAME, 0L, 200L, False,
			   AnyPropertyType, &actual_type, &actual_format, 
			   &nitems, &bytesafter, (unsigned char **) iconname)
	== Success && actual_type != None) {
	text_prop.value = (unsigned char*)*iconname;
	text_prop.encoding = actual_type;
	text_prop.format = actual_format;
	text_prop.nitems = nitems;
	if (text_prop.value && text_prop.value[0] == '\0') {
	    *iconname = (char*)text_prop.value;
	    return 1;
	}
	status_ret = XmbTextPropertyToTextList(dpy, &text_prop, &list, &num);
	if (status_ret == Success && num > 0 && *list) {
	    *iconname = *list;
	    return 1;
	} else if (status_ret > Success) {
	    *iconname = (char *)text_prop.value;
	    return 1;
	} else 
	  *iconname = NULL;
    } else
      *iconname = NULL;
    return 0;
}
#endif /* I18N_MB */



void
SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y,
	    int steps, int delay)
{
    float dx, dy, x=from_x, y=from_y;
    XEvent event;

    dx = (float)(to_x-from_x) / (float)steps;
    dy = (float)(to_y-from_y) / (float)steps;
    if (dx == 0.0 && to_x != from_x) x = to_x;
    if (dy == 0.0 && to_y != from_y) y = to_y;
    while ((int)x != to_x || (int)y != to_y) {
	if (XCheckMaskEvent(dpy, ExposureMask, &event)) {
	    DispatchEvent(&event);
	}
	x += dx;
	y += dy;
	if ((dx<0 && (int)x < to_x)
	    || (dx>0 && (int)x > to_x))
	  x = (float)to_x;
	if ((dy<0 && (int)y < to_y)
	    || (dy>0 && (int)y > to_y))
	  y = (float)to_y;
	XMoveWindow(dpy, win, (int)x, (int)y);
	XFlush(dpy);
	if (delay>0)
	  wmsleep(delay);
    }
    XMoveWindow(dpy, win, to_x, to_y);
}


char*
ShrinkString(WFont *font, char *string, int width)
{
    int w, w1=0;
    int p;
    char *pos;
    char *text;
    int p1, p2, t;

#ifdef I18N_MB
    return strdup(string);
#else
    p = strlen(string);
    w = MyTextWidth(font->font, string, p);
    text = wmalloc(strlen(string)+8);
    strcpy(text, string);
    if (w<=width)
      return text;

    pos = strchr(text, ' ');
    if (!pos)
      pos = strchr(text, ':');

    if (pos) {
	*pos = 0;
	p = strlen(text);
	w1=MyTextWidth(font->font, text, p);
	if (w1>width) {
	    w1 = 0;
	    p = 0;
	    *pos = ' ';
	    *text = 0;
	} else {
	    *pos = 0;
	    width -= w1;
	    p++;
	}
	string += p;
	p=strlen(string);
    } else {
	*text=0;
    }
    strcat(text, "...");
    width -= MyTextWidth(font->font, "...", 3);
    
    pos = string;
    p1=0;
    p2=p;
    t = (p2-p1)/2;
    while (p2>p1 && p1!=t) {
	w = MyTextWidth(font->font, &string[p-t], t);
	if (w>width) {
	    p2 = t;
	    t = p1+(p2-p1)/2;
	} else if (w<width) {
	    p1 = t;
	    t = p1+(p2-p1)/2;
	} else 
	  p2=p1=t;
    }
    strcat(text, &string[p-p1]);
    return text;
#endif /* I18N_MB */
}


char*
FindImage(char *paths, char *file)
{
    char *tmp, *path;
    
    tmp = strrchr(file, ':');
    if (tmp) {
	*tmp = 0;
	path = find_file(paths, file);
	*tmp = ':';
    }
    if (!tmp || !path) {
	path = find_file(paths, file);
    }
    return path;
}
