/*
**  EPIwm
**  Copyright (C) 1999 Julien Mulot, Thomas Poindessous, Stephane Rault
**
**  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** init.c
**
** Made by ()
** Login   <mulot_j@epita.fr>
**
** Started on  Thu Dec 31 03:18:14 1998
 ** Last update Sat Oct 28 21:03:56 2000 Julien Mulot
*/


#include "epiwm.h"


void		init_misc()
{
  XIconSize	icon_size;
  
  init_tab_function();  
  gl_scr_info.screen = DefaultScreen(gl_dpy);
  gl_scr_info.root_win = RootWindow(gl_dpy, gl_scr_info.screen);
  gl_scr_info.dpy_width = DisplayWidth(gl_dpy, gl_scr_info.screen);
  gl_scr_info.dpy_height = DisplayHeight(gl_dpy, gl_scr_info.screen);
  gl_scr_info.depth = DefaultDepth(gl_dpy, gl_scr_info.screen);
  gl_menu.grad_type = 0;
  gl_menu.here_prop = 0;
  gl_menu.here_task = 0;
  gl_menu.workspace_type = NONE;
  gl_menu.font_inactive = XCreateGC(gl_dpy, gl_scr_info.root_win, 0, NULL);
  gl_menu.font_active = XCreateGC(gl_dpy, gl_scr_info.root_win, 0, NULL);
  gl_menu.width = MENU_MINI_WIDTH;
  gl_menu.workspace_width = MENU_MINI_WIDTH;
  gl_menu_apps = NULL;
  gl_menu.lngst_str = NULL;
  gl_menu.current_elt = NULL;
  gl_menu.current_menu = NULL;
  gl_menu.current_task = NULL;
  gl_menu.current_prop = NULL;
  gl_menu.current_workspace = NULL;
  gl_menu.auto_menu = 0;
  gl_menu_task = NULL;
  gl_win_move.win = 0;
  gl_win_move.bef = 0;
  gl_win_move.last = 0;
  gl_icon.showed = 1;
  gl_icon.font_active =
    XCreateGC(gl_dpy, gl_scr_info.root_win, 0, NULL);
  gl_icon.font_inactive =
    XCreateGC(gl_dpy, gl_scr_info.root_win, 0, NULL);
  gl_epiwin.titlebar.font_active =
    XCreateGC(gl_dpy, gl_scr_info.root_win, 0, NULL);
  gl_epiwin.titlebar.font_inactive =
    XCreateGC(gl_dpy, gl_scr_info.root_win, 0, NULL);
  gl_epiwin.titlebar.grad_active_type = 0;
  gl_epiwin.titlebar.grad_inactive_type = 0;
  gl_epiwin.titlebar.position = TOP;
  gl_epiwin.titlebar.align = LEFT;
  gl_epiwin.titlebar.align_shape = LEFT;
  gl_epiwin.titlebar.width_mode = NONE;
  gl_epiwin.titlebar.width = 0;
#ifdef	IMLIB
  gl_menu.image_name = NULL;
  gl_icon.image_active = NULL;
  gl_icon.image_inactive = NULL;
  gl_epiwin.titlebar.image_active = NULL;
  gl_epiwin.titlebar.image_inactive = NULL;
  gl_epiwin.titlebar.img_btn_close_active = NULL;
  gl_epiwin.titlebar.img_btn_destroy_active = NULL;
  gl_epiwin.titlebar.img_btn_max_active = NULL;
  gl_epiwin.titlebar.img_btn_shade_active = NULL;
  gl_epiwin.titlebar.img_btn_iconify_active = NULL;
  gl_epiwin.titlebar.img_btn_close_inactive = NULL;
  gl_epiwin.titlebar.img_btn_destroy_inactive = NULL;
  gl_epiwin.titlebar.img_btn_max_inactive = NULL;
  gl_epiwin.titlebar.img_btn_shade_inactive = NULL;
  gl_epiwin.titlebar.img_btn_iconify_inactive = NULL;
  gl_epiwin.titlebar.image_max = 0;
#endif
  gl_epiwin.focus_mode = FOCUS_SLOPPY;
  gl_epiwin.nb_elt = 0;
  gl_epiwin.btn_width = 12;
  gl_epiwin.btn_height = 12;
  gl_epiwin.prop = 0;
  gl_epiwin.first_win_group_list = NULL;
  gl_epiwin.current = NULL;
  gl_epiwin.left_win = NULL;
  gl_epiwin.align_btn_close = NONE;
  gl_epiwin.align_btn_destroy = NONE;
  gl_epiwin.align_btn_iconify = NONE;
  gl_epiwin.align_btn_max = NONE;
  gl_epiwin.align_btn_max_height = NONE;
  gl_epiwin.align_btn_max_width = NONE;
  gl_epiwin.align_btn_shade = NONE;  
  gl_epiwin.virtual_width = 0;
  gl_epiwin.virtual_x = 0;
  gl_epiwin.cursor_position_x = -1;
  gl_epiwin.cursor_position_y = -1;
  gl_workspace_change_percent = 0;
  gl_workspace_cycle = 0;
  menu_pos = NULL;
  gl_apps_prop = NULL;
  gc_black = XCreateGC(gl_dpy, gl_scr_info.root_win, 0, NULL);
  XSetForeground(gl_dpy, gc_black, BlackPixel(gl_dpy,
					      gl_scr_info.screen));
  gl_epiwin.opaque_mvt = 0;
  gl_current_func = NULL;
  icon_size.min_width = 1;
  icon_size.min_height = 1;
  icon_size.max_width = 1152;
  icon_size.max_height = 864;
  icon_size.width_inc = 1;
  icon_size.height_inc = 1;
  XSetIconSizes(gl_dpy, gl_scr_info.root_win, &icon_size, 6);
  gl_icon.position = BOTTOM_LEFT;
  gl_key_list = NULL;
}


/* Capture X-Window errors */
XErrorHandler	handler(Display *gl_dpy, XErrorEvent *err_event)
{
  if ((err_event->request_code == X_ChangeWindowAttributes) &&
      (err_event->error_code == BadAccess))
    {
      fprintf(stderr, "Another Window Manager is running...\n");
      exit(ERROR);
    }
  else
    {
      /*      fprintf(stderr, "Yeesss, an ERROR : %d %d \n",
	      err_event->error_code,
	      err_event->request_code);*/
      return (0);
    }
}


/* just open the display ;) */
void	init_display()
{
  if ((gl_dpy = XOpenDisplay(gl_display_name)) == NULL)
    {
      fprintf(stderr, "\nEPIwm can not open display %s\n\n",
	      XDisplayName(gl_display_name));
      help();
      exit(ERROR);
    }
#ifdef	  IMLIB
  gl_imlib_data = Imlib_init(gl_dpy);
#endif
  XSetErrorHandler((XErrorHandler) handler);
}


/*
  void		set_font(font, val_font, color)
  XFontStruct	**font;
  char		*val_font;
  GC		*color;
  {
  *font = XLoadQueryFont(gl_dpy, val_font);
  XSetFont(gl_dpy, *color, (*font)->fid);
  }
*/


#ifdef	  IMLIB
void	init_image(char *image, char **image_dest)
{
  if (!strncmp(image, "~/", 2))
    {
      *image_dest = 
	(char *) xmalloc(sizeof (char) * (strlen(image)
					  + strlen(getenv("HOME"))));
      strcpy(*image_dest, getenv("HOME"));
      strcat(*image_dest, cut_str(image, "~"));
    }
  else
    {
      *image_dest = (char *) xmalloc(sizeof (char) * (strlen(image) + 1));
      strcpy(*image_dest, image);
    }
}
#endif


/* Initialization of the colors of fonts */
void		init_font_color(GC *font, char *color)
{
  XColor	exact_color;
  XColor	tmp_color;
  
  XAllocNamedColor(gl_dpy,
		   XDefaultColormap(gl_dpy, gl_scr_info.screen),
		   color, &tmp_color, &exact_color);
  XSetForeground(gl_dpy, *font, tmp_color.pixel);
}


/* Initialization of the colors of windows */
void		init_color(char *color, XColor *color_dest)
{
  XColor	exact_color;
  
  XAllocNamedColor(gl_dpy, XDefaultColormap(gl_dpy, gl_scr_info.screen),
		   color, color_dest, &exact_color);
}


/* Select cursors for misc events */
void	init_cursor()
{
  gl_epiwin.normal_cursor = XCreateFontCursor(gl_dpy, XC_left_ptr);
  gl_epiwin.resize_W_cursor = XCreateFontCursor(gl_dpy, XC_left_side);
  gl_epiwin.resize_E_cursor = XCreateFontCursor(gl_dpy, XC_right_side);
  gl_epiwin.resize_N_cursor = XCreateFontCursor(gl_dpy, XC_top_side);
  gl_epiwin.resize_S_cursor = XCreateFontCursor(gl_dpy, XC_bottom_side);
  gl_epiwin.resize_NW_cursor = XCreateFontCursor(gl_dpy, XC_top_left_corner);
  gl_epiwin.resize_NE_cursor = XCreateFontCursor(gl_dpy, XC_top_right_corner);
  gl_epiwin.resize_SW_cursor = XCreateFontCursor(gl_dpy,
						 XC_bottom_left_corner);
  gl_epiwin.resize_SE_cursor = XCreateFontCursor(gl_dpy,
						 XC_bottom_right_corner);
  gl_epiwin.target_cursor = XCreateFontCursor(gl_dpy, XC_target);
  gl_epiwin.move_cursor = XCreateFontCursor(gl_dpy, XC_fleur);
  XDefineCursor(gl_dpy, gl_scr_info.root_win, gl_epiwin.normal_cursor);
  gl_epiwin.current_cursor = gl_epiwin.normal_cursor;
}


/* Select types of evenements to exam */
void	init_event()
{
  XSelectInput(gl_dpy, gl_scr_info.root_win,
	       ButtonPressMask | PointerMotionMask |
	       SubstructureNotifyMask | ExposureMask | KeyPressMask
	       | SubstructureRedirectMask);
}


/* capture all windows that already exist */
void		capture_windows()
{
  Window	root;
  Window	parent;
  Window	*children;
  unsigned int	nb_children;
  int		i;
  
  XQueryTree(gl_dpy, RootWindow(gl_dpy, gl_scr_info.screen),
	     &root, &parent, &children, &nb_children);
  for (i = 0; i < nb_children; i++)
    handle_window(children[i]);
  free(children);
}


void		init_gc()
{
  XGCValues	gcv;
  unsigned long	gcm;
  
  gcm = GCFunction | GCPlaneMask | GCGraphicsExposures | GCLineWidth;
  gcv.line_width = 0;
  gcv.function = GXcopy;
  gcv.plane_mask = AllPlanes;
  gcv.graphics_exposures = False;
  gl_epiwin.transmask_gc = XCreateGC(gl_dpy, gl_scr_info.root_win, gcm, &gcv);
  XSetClipMask(gl_dpy, gl_epiwin.transmask_gc, None);
  gc_xor = XCreateGC(gl_dpy, gl_scr_info.root_win, 0, NULL);
  XSetSubwindowMode(gl_dpy, gc_xor, IncludeInferiors);
  XSetForeground(gl_dpy, gc_xor, BlackPixel(gl_dpy, gl_scr_info.screen)
                 ^ WhitePixel(gl_dpy, gl_scr_info.screen));
  XSetFunction(gl_dpy, gc_xor, GXxor);
}


/* initialisation of X */
void	initx()
{
  init_gc();
  init_cursor();
  init_event();
  init_atoms();
#ifdef	__GNOME__
  init_gnome();
#endif
#ifdef	IMLIB
  set_titlebar_btn_size();
#endif
  gl_epiwin.titlebar.space = set_title_position();
  gl_epiwin.prop |= FIRST_START;
  capture_windows();
  gl_epiwin.prop &= ~FIRST_START;
  gl_parent_pid = getpid();
}


char           *cut_str(char *str, char *word)
{
  while (*str == *word)
    {
      word++;
      str++;
    }
  return (str);
}


char		*index_file(char *line, int word_number)
{
  char		*tokens[50];
  static char	tmpstring[LINE_LEN];
  int		i;
  
  for (i = 0; i < 50; i++)
    tokens[i] = NULL;
  i = 0;
  strncpy(tmpstring, line, LINE_LEN);
  tokens[i] = strtok(tmpstring, " ");
  while ((tokens[++i] = strtok(NULL, " ")));
  tokens[i] = NULL;
  return (tokens[word_number]);
}


void	init_config(FILE *file, char *part)
{
  char	line[LINE_LEN];
  
  if (!strcmp(part, "window"))
    window_build(file);
  else if (!strcmp(part, "workspace"))
    workspace_build(file);
  else if (!strcmp(part, "style"))
    style_build(file);
  else if (!strcmp(part, "start"))
    {
      while (fgets(line, LINE_LEN, file) != NULL)
	{
	  if (strlen(line) != 1)
	    line[strlen(line) - 1] = ' ';
	  if ((!strcasecmp(index_file(line, 0), "Init")) && 1)
	    system(cut_str(line, "Init "));
	  if ((!strcasecmp(index_file(line, 0), "Restart")) && 0)
	    system(cut_str(line, "Restart "));
	}
    }
  else if (!strcmp(part, "menu"))
    menu_build(file);
  else if (!strcmp(part, "icons"))
    icon_build(file);
  else if (!strcmp(part, "key"))
    key_build(file);
  fclose(file);
}


void	read_config(char *file)
{
  char	path[100];
  char	home[100];
  FILE	*config_file;
  
  strncpy(home, getenv("HOME"), 100);
  if (gl_theme_path)
    sprintf(path, "%s/%s", gl_theme_path, file);
  else
    sprintf(path, "%s/.epiwm/%s", home, file);
  if ((config_file = fopen(path, "r")) == NULL)
    {
      sprintf(path, CONFIG_PATH "/%s", file);
      if ((config_file = fopen(path, "r")) == NULL)
	{
	  fprintf(stderr,
		  "Can not open %s/.epiwm/%s or " CONFIG_PATH "/%s \n"
		  ,home, file, file);
	  exit(ERROR);
	}
    }
  init_config(config_file, file);
}


void	init_atoms()
{
  gl_epiwin.context = XUniqueContext();
  EPIWM_WM_STATE = XInternAtom(gl_dpy, "WM_STATE", False);
  EPIWM_WM_CHANGE_STATE = XInternAtom(gl_dpy, "WM_CHANGE_STATE", False);
  EPIWM_WM_PROTOCOLS = XInternAtom(gl_dpy, "WM_PROTOCOLS", False);
  EPIWM_WM_TAKE_FOCUS = XInternAtom(gl_dpy, "WM_TAKE_FOCUS", False);
  EPIWM_WM_DELETE_WINDOW = XInternAtom(gl_dpy, "WM_DELETE_WINDOW", False);
  EPIWM_WM_SAVE_YOURSELF = XInternAtom(gl_dpy, "WM_SAVE_YOURSELF", False);    
  EPIWM_WM_NAME = XInternAtom(gl_dpy, "WM_NAME", False);
  EPIWM_WM_ICON_NAME = XInternAtom(gl_dpy, "WM_ICON_NAME", False);
  EPIWM_MOTIF_WM_HINTS = XInternAtom(gl_dpy, "_MOTIF_WM_HINTS", False);
}


void		prepare_font()
{
  int		i;
  int		x;
  int		y;
  int		tall;
  GC		temp_gc;
  Pixmap	temp_pixmap;
  XImage	*temp_image;
  char		ff[1];
  
  ff[0] = 0;
  temp_pixmap = XCreatePixmap(gl_dpy, DefaultRootWindow(gl_dpy), 200, 200, 1);
  temp_gc = XCreateGC(gl_dpy, temp_pixmap, 0, NULL);
  XSetFont(gl_dpy, temp_gc, gl_epiwin.titlebar.font->fid);
  for (i = 0; i < 96; i++)
    {
      ff[0] = i + 32;
      gl_fn[i].count = 0;
      gl_fn[i].width = XTextWidth(gl_epiwin.titlebar.font, ff, 1);
      tall = gl_epiwin.titlebar.font->ascent
	+ gl_epiwin.titlebar.font->descent;
      XSetForeground(gl_dpy, temp_gc, 0);
      XFillRectangle(gl_dpy, temp_pixmap, temp_gc, 0, 0, 200, 200);
      XSetForeground(gl_dpy, temp_gc, 1);
      XDrawString(gl_dpy, temp_pixmap, temp_gc, 0,
		  tall - gl_epiwin.titlebar.font->descent, ff, 1);
      temp_image = XGetImage(gl_dpy, temp_pixmap, 0, 0, gl_fn[i].width,
			     tall, 1, XYPixmap);
      for (x = 0; x < gl_fn[i].width; x++)
	{
	  for (y = 0; y < tall; y++)
	    {
	      if (XGetPixel(temp_image, x, y) && gl_fn[i].count < 200)
		{
		  if (gl_epiwin.titlebar.position == RIGHT)
		    {
		      gl_fn[i].points[gl_fn[i].count].x = tall - y;
		      gl_fn[i].points[gl_fn[i].count].y = x;
		    }
		  else
		    {
		      gl_fn[i].points[gl_fn[i].count].x = y;
		      gl_fn[i].points[gl_fn[i].count].y = gl_fn[i].width - x;
		    }
		  gl_fn[i].count++;
		}			
	    }
	}
      XFree(temp_image);
    }
  XFree(temp_gc);
  XFreePixmap(gl_dpy, temp_pixmap);
}


syntax highlighted by Code2HTML, v. 0.9.1