/*-
 * Copyright (c) 2001 Jordan DeLong
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the author nor the names of contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#include "wm.h"

/* number of steps for zoomrects and for window birth */
#define NUM_RECTS	10

/*
 * draws a few lines representing a window: call again with same parms to erase (GXxor).
 * We take a rectangle to draw as, _and_ a client structure.  the client structure gives us
 * information about the decoration spacing for the client's sides, and the rect is what to
 * draw.  this is so we don't have to change the x,y,wid,hei in the client struct.
 */
void draw_winbox(screen_t *screen, client_t *client, int x, int y, int width, int height)
{
	XSegment segs[8];
	dgroup_t *dgroup;
	int nsegs = 0;
	int lw, od;
	int dx, dy, dwidth, dheight;

	width--;
	height--;
	dgroup = client->dgroup;
	y += dgroup->top_space;
	x += dgroup->left_space;
	lw = options.linewidth / 2;
	od = options.linewidth % 2 == 0 ? 0 : 1;

	segs[nsegs].x1 = x - lw;			/* top left to top right */
	segs[nsegs].y1 = y;
	segs[nsegs].x2 = x + width + lw + od;
	segs[nsegs].y2 = y;
    nsegs++;

	segs[nsegs].x1 = x + width;			/* top right to bottom right */
	segs[nsegs].y1 = y + lw + od;
	segs[nsegs].x2 = x + width;
	segs[nsegs].y2 = y + height - lw;
    nsegs++;

	segs[nsegs].x1 = x + width + lw + od;	/* bottom right to bottom left */
	segs[nsegs].y1 = y + height;
	segs[nsegs].x2 = x - lw;
	segs[nsegs].y2 = y + height;
    nsegs++;

	segs[nsegs].x1 = x;				/* bottom left to top left */
	segs[nsegs].y1 = y + height - lw;
	segs[nsegs].x2 = x;
	segs[nsegs].y2 = y + lw + od;
    nsegs++;

    if( options.rep_style ==  WINDOW_GRID )
    {
       segs[nsegs].x1 = x + lw + od;		/* first horiz midsegment */
       segs[nsegs].y1 = y + (height / 3);
       segs[nsegs].x2 = x + width - lw;
       segs[nsegs].y2 = y + (height / 3);
       nsegs++;

       segs[nsegs].x1 = x + (width / 3);		/* first vert midsegment */
       segs[nsegs].y1 = y + lw + od;
       segs[nsegs].x2 = x + (width / 3);
       segs[nsegs].y2 = y + height - lw;
       nsegs++;

       segs[nsegs].x1 = x + lw + od;		/* second horiz midsegment */
       segs[nsegs].y1 = y + (2 * (height / 3));
       segs[nsegs].x2 = x + width - lw;
       segs[nsegs].y2 = y + (2 * (height / 3));
       nsegs++;

       segs[nsegs].x1 = x + (2 * (width / 3));	/* second vert midsegment */
       segs[nsegs].y1 = y + lw + od;
       segs[nsegs].x2 = x + (2 * (width / 3));
       segs[nsegs].y2 = y + height - lw;
       nsegs++;
    }

#if 0
	/* this did an X across the windows; needed 6 segs */
	segs[nsegs].x1 = x;			/* top left to bottom right */
	segs[nsegs].y1 = y;
	segs[nsegs].x2 = x + width;
	segs[nsegs].y2 = y + height;
    nsegs++;

	segs[nsegs].x1 = x;			/* bottom left to top right */
	segs[nsegs].y1 = y + height;
	segs[nsegs].x2 = x + width;
	segs[nsegs].y2 = y;
    nsegs++;
#endif

	/* draw the segments for the winbox */
	XDrawSegments(display, screen->root, screen->xorgc, segs, nsegs);

	/* draw border at size of the window decoration */
	dx = x - (dgroup->left_space ? dgroup->left_space : 1);
	dy = y - (dgroup->top_space ? dgroup->top_space : 1);
	dwidth = width + (dgroup->left_space ? dgroup->left_space : 1)
		+ (dgroup->right_space ? dgroup->right_space : 1);
	dheight = height + (dgroup->top_space ? dgroup->top_space : 1)
		+ (dgroup->bottom_space ? dgroup->bottom_space : 1);
	XDrawRectangle(display, screen->root, screen->xorgc, dx, dy, dwidth, dheight);
}

/* draw zooming rectangles:  the second rect is the destination */
void draw_zoomrects(screen_t *screen, client_t *client, int x1, int y1, int width1, int height1,
		int x2, int y2, int width2, int height2, int usewinbox) {
	float xinc, yinc, widthinc, heightinc;
	float x, y, width, height;
	int i;

	xinc = (x2 - x1) / NUM_RECTS;
	yinc = (y2 - y1) / NUM_RECTS;
	widthinc = (width2 - width1) / NUM_RECTS;
	heightinc = (height2 - height1) / NUM_RECTS;

	x = x1;
	y = y1;
	width = width1;
	height = height1;

	for (i = 0; i < NUM_RECTS; i++) {
		if (usewinbox)
			draw_winbox(screen, client, (int) x, (int) y, (int) width, (int) height);
		else
			XDrawRectangle(display, screen->root, screen->xorgc, (int) x, (int) y, (int) width, (int) height);
		XSync(display, 0);
		usleep(options.anim_delay);
		if (usewinbox)
			draw_winbox(screen, client, (int) x, (int) y, (int) width, (int) height);
		else
			XDrawRectangle(display, screen->root, screen->xorgc, (int) x, (int) y, (int) width, (int) height);

		x += xinc;
		y += yinc;
		width += widthinc;
		height += heightinc;
	}

#if 0
	if (usewinbox)
		draw_winbox(screen, client, x2, y2, width2, height2);
	else
		XDrawRectangle(display, screen->root, screen->xorgc, x2, y2, width2, height2);
	XSync(display, 0);
	usleep(options.anim_delay);
	if (usewinbox)
		draw_winbox(screen, client, x2, y2, width2, height2);
	else
		XDrawRectangle(display, screen->root, screen->xorgc, x2, y2, width2, height2);
#endif
}

void show_position( int action, /* update==1, stop==0 */
                    int size, /* as in "resize" */
                    screen_t *screen,
                    client_t *client,
                    int x,
                    int y,
                    int width,
                    int height )
{
   char label[1024];
   int xpad, ypad;
   int twidth, theight;
   int xloc, yloc;
   int client_width, client_height;

#ifdef I18N
   XFontSetExtents *extent;

   extent = XExtentsOfFontSet(titlefont);
#endif
   if( action == 0 )
   {
      if( client && client->flags.internal == 0 )
      {
         XUnmapWindow( display, screen->gwin);
         screen->gwin_mapped = 0;
      }
   }
   else
   {
      if( client && client->flags.internal == 0 )
      {
         if( size )
         {
            sprintf(label, "W: %4d x H: %4d", width, height);
         }
         else
         {
            sprintf(label, "X: %4d x Y: %4d", x, y);
         }

         XClearWindow(display, screen->gwin );

         xpad = 10;
         ypad = 2;
         twidth = decor_measurestring( label ) + xpad;
         theight = decor_measureheight() + ypad;

         client_width = client->width;
         client_height = client->height;

         log( 1, "x: %d y: %d", x , y );

         if( client->flags.shaded )
         {
             log( 1, "w: %d h: %d sw: %d sh: %d\n",
                  width, height, client->save_width, client->save_height );
             client_height = client->save_height;
         }

         /* if we are not larger than the window itself, center ourselves ... */
         if( size )
         {
            xloc = client->x + (client_width - twidth) / 2;
            yloc = client->y + (client_height - theight) / 2;
         }
         else
         {
            xloc = client_width < twidth ? 0 : x + (client_width - twidth) / 2;
            yloc = client_height < theight ? 0 : y + (client_height - theight) / 2;
         }

         /* would we draw outside the screen's dimensions ? */
         if( xloc + twidth > screen->width)
         {
            xloc = screen->width - twidth;
         }

         if( yloc + theight > screen->height )
         {
            yloc = screen->height - theight;
         }

         XMoveResizeWindow( display,
                            screen->gwin,
                            xloc,
                            yloc,
                            twidth,
                            theight );
#ifdef I18N
         XmbDrawString( display,
                        screen->gwin,
                        titlefont,
                        client->screen->titlegc,
                        client->dgroup->title_x,
                        client->dgroup->title_y + (extent->max_logical_extent.height * 4 / 5),
                        label, strlen(label));
#else
         XDrawString( display,
                      screen->gwin,
                      client->screen->titlegc,
                      5 /* could be configurable, padding */,
                      1 + titlefont->ascent,
                      label,
                      strlen(label) );
#endif

         if( !screen->gwin_mapped )
         {
            XMapWindow(display, screen->gwin);
            screen->gwin_mapped = 1;
         }

         XRaiseWindow(display, screen->gwin);
      }
   }
}
