/* Copyright (c) 2000 Linus Nilsson <d96ln@efd.lth.se> */

#include "yawm.h"
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

#define EDGE_SPACE (opt_bw + 1)
#define FONT_YOFF (TASKBAR_HEIGHT/2 - opt_bw/2 + (font->ascent+font->descent)/2)

void draw_bartime(char *thestring) {
	if (!thestring) {
	       debug("The argument to draw_bartime was NULL!\n");
		exit(1);
	}
	/* Add double buffering later */
	XClearArea(child_dpy, taskbar,
		   DisplayWidth(child_dpy, 0) - 
		   XTextWidth(font, thestring, strlen(thestring)) - EDGE_SPACE,
		   TASKBAR_HEIGHT/2 - (font->ascent + font->descent)/2, 
		   XTextWidth(font, thestring, strlen(thestring)),
		   (font->ascent + font->descent),
		   False);
	XDrawString(child_dpy, taskbar, taskbar_focus_fg_gc,
		    DisplayWidth(child_dpy, 0) - opt_bw - 4 -
		    XTextWidth(font, thestring, strlen(thestring)) - 
		    EDGE_SPACE, 
		    FONT_YOFF,
		    thestring, strlen(thestring)); 
	XSync(child_dpy, False);
}

int count_tasks(void) {
	Client *c = (Client *) malloc (sizeof(Client));
	int n = 0;

	for (c = head_client; c; c = c->next) {
		n++;	
	}
	
	return n;
}

void draw_tasks(void) {
	char *tasks_string = (char *) malloc(1024);
	Client *c = (Client *) malloc (sizeof(Client));
	int offset = opt_bw + 1;
	
	debug("entered draw_tasks()\n");
	for (c = head_client; c != NULL; c = c->next) {
		debug("loop1");
		if (!c->window) {
			remove_client(c, 0);
		}
		else {
			XFetchName(dpy, c->window, &c->barname);
			redraw(c);
		}
	}
	
	while (find_width() > DisplayWidth(dpy, 0) - 200 && 
	       count_tasks() <= MAX_CLIENTS_ON_TASKBAR &&
	       (c ? strcmp(c->barname, "...") != 0 : 1)) {
		debug("loop2");
		c = find_client_with_longest_name();
		dec_barname(find_client_with_longest_name());
	}
	       
	XClearArea(dpy, taskbar, opt_bw, opt_bw,
		   DisplayWidth(dpy, 0) - 200,
		   TASKBAR_HEIGHT - 2*opt_bw, False);

	if (count_tasks() <= MAX_CLIENTS_ON_TASKBAR) { 
		for (c = head_client; c; c = c->next) {
			debug("loop3");
			if (c->barname) sprintf(tasks_string, "%s", c->barname);
			if (!tasks_string) {
				debug("tasks_string is NULL in draw_tasks!\n");
				exit(1);
			}
			if (offset + XTextWidth(font, tasks_string, 
						strlen(tasks_string)) + 
			    2*SPACE < DisplayWidth(dpy, 0) - 200) {
				if (c->minimized) {
					XDrawString(dpy, taskbar,
						    hidden_string_gc,
						    offset + SPACE,
						    FONT_YOFF,
						    tasks_string,
						    strlen(tasks_string));
				}
				else if (tasks_string && c == focused_client) {
					XDrawString(dpy, taskbar, 
					            taskbar_focus_fg_gc,
					    	    offset + SPACE,
					            FONT_YOFF,
					            tasks_string,
					            strlen(tasks_string));
				}
				else {
					XDrawString(dpy, taskbar, 
					            normal_string_gc,
					    	    offset + SPACE,
					            FONT_YOFF,
					            tasks_string,
					            strlen(tasks_string));
				}
				XDrawRectangle(dpy, taskbar, border_gc, 
					       offset,
					       SPACE, 
					       XTextWidth(font, tasks_string, 
							  strlen(tasks_string))
					       + 2*SPACE, font->ascent + 
					       font->descent + 2*SPACE);
				c->left_offset = offset;
				offset += XTextWidth(font, tasks_string, 
						     strlen(tasks_string)) + 
					3*SPACE + 1;
				c->right_offset = offset;
			}
			else {
				break;
			}
		}
	}
	else { 
		XDrawString(dpy, taskbar, focus_string_gc,
			    offset + SPACE,
			    FONT_YOFF,
			    "Too many tasks to show on taskbar",
			    strlen("Too many tasks to show on taskbar"));
	}
	XSync(dpy, False);
}

int find_width(void) {
	char *tasks_string = (char *) malloc(1024);
	int offset = opt_bw + 1;
	Client *c = (Client *) malloc (sizeof(Client));

	for (c = head_client; c != NULL; c = c->next) {
		debug("find width loop\n");
		if (c->barname) {
			sprintf(tasks_string, "%s", c->barname);
		}
		offset += XTextWidth(font, tasks_string, 
				     strlen(tasks_string)) + 3*SPACE ;
	}
	return offset;
}

Client * find_client_with_longest_name() {
	int longest_so_far = 0;
	Client *c = (Client *) malloc (sizeof(Client));
	Client *long_c = (Client *) malloc (sizeof(Client));
	
	for (c = head_client; c; c = c->next) {
		if (strlen(c->barname) > longest_so_far) {
			long_c = c;
			longest_so_far = strlen(c->barname);
		}
	}
	return long_c;
}

void dec_barname(Client *c) {
	if (!c) {
		debug("c was NULL in dec_barname()\n");
		exit(1);
	}
	if (strlen(c->barname) >= 4) {
		c->barname[strlen(c->barname)-1] = '\0';
		c->barname[strlen(c->barname)-1] = '.';
		c->barname[strlen(c->barname)-2] = '.';
		c->barname[strlen(c->barname)-3] = '.';
	}
}

/* Do initial setup of the taskbar */
void start_taskbar(void) {
	GC taskbar_gc;
	XSetWindowAttributes p_attr;

	p_attr.override_redirect = True;
	p_attr.background_pixel = taskbar_bg.pixel;
	p_attr.border_pixel = bd.pixel;
	p_attr.backing_store = Always;
	p_attr.event_mask = ChildMask | ButtonPressMask | ExposureMask 
		| CWBackingPixel | CWBackPixel | EnterWindowMask | KeyPressMask;
	taskbar = XCreateWindow(dpy, 
				root,
				0, 
				DisplayHeight(dpy, 0) - TASKBAR_HEIGHT - 2*opt_bw,
				DisplayWidth(dpy, 0) - 4, //width
				TASKBAR_HEIGHT,
				opt_bw, 
				DefaultDepth(dpy, screen), 
				InputOutput, 
				CopyFromParent,
				CWOverrideRedirect |CWBorderPixel|CWEventMask|
				CWBackPixel|CWBackingStore, &p_attr);
	XSelectInput(dpy, taskbar, ChildMask | ColormapChangeMask | 
		     EnterWindowMask | LeaveWindowMask | PropertyChangeMask | 
		     KeyPressMask| ButtonPressMask);
	XMapWindow(dpy, taskbar);	

	taskbar_gc = XCreateGC(dpy, taskbar, 0, NULL);	
	XSync(dpy, False);
}

/* This function name is fucked up. Need to change it */
void taskbar_start(void) {	
	pid_t child_pid;
	time_t mytime_t;
	struct tm *mytm;
	char *time_string = malloc(1024);
	char *full_string = malloc(1024);

	child_pid = fork();
	if (child_pid == -1) {
		debug("Unable to fork()!\n");
		exit(1);
	}
	else if (child_pid == 0) {
		/* We need a seperate Display to avoid race conditions */
		child_dpy = XOpenDisplay(opt_display);
		while (1) {
			mytime_t = time(NULL);
			mytm = localtime(&mytime_t);
			strftime(time_string, 1024, STRFTIME_STRING, 
				 mytm);
			sprintf(full_string, "%s", //current_desk,
				time_string);	
			draw_bartime(full_string);
			sleep(60);
		}
	}
}


syntax highlighted by Code2HTML, v. 0.9.1