/* xyz */

/*
 * Copyright (c) 1994, 1995, 1997 by Wayne C. Gramlich.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * for any purpose is hereby granted without fee provided that the above
 * copyright notice and this permission are retained.  The author makes
 * no representations about the suitability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 */

/*
 * This file provide a bunch of interface routines for accessing objects
 * of type {Window} from Xlib from STIPPLE code.
 */

#ifndef XLIB_H
#include "xlib.h"
#endif

/* The initial object: */
Xlib_window_struct xlib_window___initial_object = {
    0,
    1,
    &xlib_window___initial_object,
    (Window)0,
    &xlib_screen___initial_object
};
Xlib_window xlib_window___initial = &xlib_window___initial_object;

/*
 * xlib_window___create(screen, win, parent_window)
 *	This routine will allocate a new {Xlib_window} object
 *	and fill it with {screen}, {win}, and {parent_window}.
 *	If {parent_window} is {(Xwlib_window)0} the newly allocated
 *	window will be used as the parent window.
 */
Xlib_window
xlib_window___create(
    Xlib_screen screen,
    Window win,
    Xlib_window parent_window)
{
    Xlib_window window;

    window = (Xlib_window)malloc(sizeof(*window));
    window->closed = 0;
    window->depth = screen->depth;
    window->parent_window =
      (parent_window == (Xlib_window)0) ? window : parent_window;
    window->window = win;
    window->screen = screen;
    return window;
}

/*
 * xlib_window__address_get(window)
 *	This routine will return the address of {window}.
 */
unsigned
xlib_window__address_get(
    Xlib_window window)
{
    return (unsigned)window;
}

/*
 * xlib_window__area_clear(window, x, y, width, height)
 *	This routine will clear the area of {window} specified by {x}, {y},
 *	{width}, andj {height}.
 */
void
xlib_window__area_clear(
    Xlib_window window,
    unsigned x,
    unsigned y,
    unsigned width,
    unsigned height)
{
    Xlib_display display;

    display = window->screen->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else {
	XClearArea(display->display, window->window,
	  x, y, width, height, False);
    }
}

/*
 * xlib_window__close(window)
 *	This routine will make {window} unusable.
 */
void
xlib_window__close(
    Xlib_window window)
{
    window->closed = 1;
    window->parent_window = xlib_window___initial;
    window->window = (Window)0;
    window->screen = xlib_screen___initial;
}

/*
 * xlib_window__closed_get(window)
 *	This routine will return 1 {window} is unusable and 0 otherwise.
 */
int
xlib_window__closed_get(
    Xlib_window window)
{
    return window->closed;
}

/*
 * xlib_window__create(parent_window, x_origin, y_origin, width,
 *   height, border_width, border_pixel, depth, class, visual, attributes)
 *	This routine will return a new child window of {parent_window}
 *	The returned window will have a tenative
 *	height of {height} pixels and a width of {width} pixels with its
 *	upper left corner tennatively placeds at ({x_origin}, {y_origin}).
 *	The window manager is permitted to override the suggested positions.
 *	The window border width will be {border_width} pixels wide.  {depth}
 *	specifies the window depth; a value of 0 causes the depth to match
 *	the depth of {parent_window}.  {visual} specifies the visual to
 *	use; a value of ??@{xlib_visual} causes the default visual to be
 *	used.
 */
Xlib_window
xlib_window__create(
    Xlib_window parent_window,
    unsigned x_origin,
    unsigned y_origin,
    unsigned width,
    unsigned height,
    unsigned border_width,
    unsigned depth,
    unsigned class,
    Xlib_visual visual,
    Xlib_window_attributes window_attributes)
{
    Xlib_display display;
    Xlib_screen screen;
    Xlib_window window;

    screen = parent_window->screen;
    display = screen->display;
    if (display->closed) {
	xlib_display___closed(display);
	window = xlib_window___initial;
    } else {
	Window win;
	Visual *vis;

	if (depth == 0) {
	    depth = CopyFromParent;
	}
	if (visual == xlib_visual___initial) {
	    vis = CopyFromParent;
	} else {
	    vis = visual->visual.visual;
	}
	win = XCreateWindow(display->display, screen->root_window->window,
	  x_origin, y_origin, width, height, border_width, depth, class,
	  vis, window_attributes->mask, &window_attributes->attributes);
	window = xlib_window___create(screen, win, parent_window);
    }
    return window;
}

/*
 * xlib_window__depth_get(window)
 *	This routine will return the depth associated with {window}.
 */
unsigned
xlib_window__depth_get(
    Xlib_window window)
{
    return window->depth;
}

/*
 * xlib_window__external__initialize()
 *	This routine will "initialize" the {xlib_window} external
 *	code.
 */
void
xlib_window__external__initialize(void)
{
    assert(xlib_window___initial == &xlib_window___initial_object);
}

/*
 * xlib_window__height_get(window)
 *	This routine will return the height of {window} is pixels.
 */
unsigned
xlib_window__height_get(
    Xlib_window window)
{
    unsigned height;

    height = 0;
    assert(0);
    return height;
}

/*
 * xlib_window__input_mask_set(window, input_mask)
 *	This routine will set the input mask for {window} to
 *	{input_mask}.
 */
void
xlib_window__input_mask_set(
    Xlib_window window,
    Xlib_input_mask input_mask)
{
    Xlib_display display;

    display = window->screen->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else {
	XSelectInput(display->display, window->window, input_mask->mask);
    }
}

/*
 * xlib_window__map(window)
 *	This procedure will cause {window} to become visible on the screen.
 */
void
xlib_window__map(
    Xlib_window window)
{
    Xlib_display display;

    display = window->screen->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else {
	XMapWindow(display->display, window->window);
    }
}

/*
 * xlib_window__parent_window_get(window)
 *	This routine will return the parent window associated with {window}.
 */
Xlib_window
xlib_window__parent_window_get(
    Xlib_window window)
{
    return window->parent_window;
}

/*
 * Xlib_window__line_draw(window, gc, x1, y1, x2, y2)
 *	This procedure will draw a line from ({x1}, {y1}) to ({x2}, {y2})
 *	using graphics context {gc} into {window}.
 */
void
xlib_window__line_draw(
    Xlib_window window,
    Xlib_gc gc,
    unsigned x1,
    unsigned y1,
    unsigned x2,
    unsigned y2)
{
    Xlib_display display;

    display = window->screen->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else if (window->screen != gc-> screen) {
	xlib_errors___add(display->errors, "GC does not match window");
    } else {
	XDrawLine(display->display, window->window, gc->gc,
	  x1, y1, x2, y2);
    }
}

/*
 * Xlib_window__rectangle_draw(window, gc, x, y, width, height)
 *	This procedure will draw a rectangle at ({x}, {y}) of
 *	width {widht} and height {height] using graphics context
 *	{gc} into {window}.
 */
void
xlib_window__rectangle_draw(
    Xlib_window window,
    Xlib_gc gc,
    unsigned x,
    unsigned y,
    unsigned width,
    unsigned height)
{
    Xlib_display display;

    display = window->screen->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else if (window->screen != gc-> screen) {
	xlib_errors___add(display->errors, "GC does not match window");
    } else {
	XDrawRectangle(display->display, window->window, gc->gc,
	  x, y, width, height);
    }
}

/*
 * Xlib_window__rectangle_fill(window, gc, x, y, width, height)
 *	This procedure will draw a rectangle at ({x}, {y}) of
 *	width {width} and height {height] using graphics context
 *	{gc} into {window}.
 */
void
xlib_window__rectangle_fill(
    Xlib_window window,
    Xlib_gc gc,
    unsigned x,
    unsigned y,
    unsigned width,
    unsigned height)
{
    Xlib_display display;

    display = window->screen->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else if (window->screen != gc-> screen) {
	xlib_errors___add(display->errors, "GC does not match window");
    } else {
	XFillRectangle(display->display, window->window, gc->gc,
	  x, y, width + 1, height + 1);	/* The manual says to add 1! */
    }
}

/*
 * xlib_window__simple_create(parent_window, x_origin, y_origin, width,
 *   height, border_width, border_pixel, background_pixel)
 *	This routine will return a new child window of {parent_window}.
 *	The returned window will have a tenative
 *	height of {height} pixels and a width of {width} pixels with its
 *	upper left corner tennatively placeds at ({x_origin}, {y_origin}).
 *	The window manager is permitted to override the suggested positions.
 *	The window border width will be {border_width} pixels wide with
 *	a color of {border_pixel}.  The background color of the window
 *	will be {background_pixel}.  The cursor, number of planes, etc.
 *	are copied from the parent window.
 */
Xlib_window
xlib_window__simple_create(
    Xlib_window parent_window,
    unsigned x_origin,
    unsigned y_origin,
    unsigned width,
    unsigned height,
    unsigned border_width,
    Xlib_pixel border_pixel,
    Xlib_pixel background_pixel)
{
    Xlib_display display;
    Xlib_screen screen;
    Xlib_window window;

    screen = parent_window->screen;
    display = screen->display;
    if (display->closed) {
	xlib_display___closed(display);
	window = xlib_window___initial;
    } else {
	Window win;

	win = XCreateSimpleWindow(display->display,
	  screen->root_window->window, x_origin, y_origin, width, height,
	  border_width, (unsigned)border_pixel, (unsigned)background_pixel);
	window = xlib_window___create(screen, win, parent_window);
    }
    return window;
}

/*
 * xlib_window__standard_properties_set(window, window_name,
 *   icon_name, icon_pixmap, arguments, size_hints)
 *	This procedure will set the standard properties for {window}
 *	to be {window_name}, {icon_name}, {icon_pixmap}, {arguments}, and
 *	{size_hints}.
 */
void
xlib_window__standard_properties_set(
    Xlib_window window,
    String window_name,
    String icon_name,
    Xlib_pixmap icon_pixmap,
    Vec(String) arguments,
    Xlib_size_hints size_hints)
{
    Xlib_display display;
    Xlib_screen screen;

    screen = window->screen;
    display = screen->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else if (icon_pixmap->screen != screen) {
	xlib_errors___add(display->errors, "Icon icompatible with window");
    } else if (size_hints == xlib_size_hints___initial) {
	xlib_errors___add(display->errors, "Using ??@xlib_size_hints");
    } else {
	Str window_str;
	Str icon_str;

	window_str = string__unix_string(window_name);
	icon_str = string__unix_string(icon_name);
	XSetStandardProperties(display->display, window->window,
	  window_str, icon_str, icon_pixmap->pixmap, (char **)0, 0,
	  size_hints);
    }
}

/*
 * xlib_window__subwindows_map(window)
 *	This procedure will cause the subwindows of {window} to become
 *	visible on the screen.
 */
void
xlib_window__subwindows_map(
    Xlib_window window)
{
    Xlib_display display;

    display = window->screen->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else {
	XMapSubwindows(display->display, window->window);
    }
}

/*
 * xlib_window__width_get(window)
 *	This routine will return the width of {window} is pixels.
 */
unsigned
xlib_window__width_get(
    Xlib_window window)
{
    unsigned width;

    width = 0;
    assert(0);
    return width;
}

/*
 * xlib_window__window_manager_properties_set(window, window_name, icon_name,
 *    arguments, size_hints, wm_hints, class, name)
 *	This procedure will set the window manager properties of {window}
 *	to contain {window_name}, {icon_name}, {arguments}, {size_hints},
 *	{wm_hints}, {resource_class}, and {resource_name}.
 */
void
xlib_window__window_manager_properties_set(
    Xlib_window window,
    String window_name,
    String icon_name,
    Vec(String) arguments,
    Xlib_size_hints size_hints,
    Xlib_wm_hints wm_hints,
    String resource_class,
    String resource_name)
{
    Xlib_display display;

    display = window->screen->display;
    if (display->closed) {
	xlib_display___closed(display);
    } else {
	XClassHint class_hints;
	XTextProperty icon_name_property;
	Str icon_name_str;
	XTextProperty window_name_property;
	Str window_name_str;

	icon_name_str = string__unix_string(icon_name);
	assert(XStringListToTextProperty(&icon_name_str,
	  1, &icon_name_property) != 0);
	window_name_str = string__unix_string(window_name);
	assert(XStringListToTextProperty(&window_name_str,
	  1, &window_name_property) != 0);
	class_hints.res_name = string__unix_string(resource_name);
	class_hints.res_class = string__unix_string(resource_class);

	XSetWMProperties(display->display, window->window,
	  &window_name_property, &icon_name_property, (char **)0, 0,
	  size_hints, &wm_hints->wm_hints, &class_hints);
    }
}

/*
 * xlib_window__window_number_get(window)
 *	This procedure will return the window number associated with {window}.
 */
unsigned
xlib_window__window_number_get(
    Xlib_window window)
{
    return window->window;
}

/*
 * xlib_window__screen_get(xlib_window)
 *	This routine will return the {xlib_screen} associated with {window}.
 */
Xlib_screen
xlib_window__screen_get(
    Xlib_window window)
{
    return window->screen;
}



