Пример #1
0
void Done(int restart, char *command)
{
  MenuRoot *mr;

#ifndef NON_VIRTUAL
  MoveViewport(0, 0, False);
#endif

  mr = FindPopup("ExitFunction");
  if (mr != NULL)
    ExecuteFunction("Function ExitFunction", NULL, &Event, C_ROOT, -1);

  /* Close all my pipes */
  ClosePipes();

  Reborder();

  if (restart) {
    SaveDesktopState();		/* I wonder why ... */

    /* Really make sure that the connection is closed and cleared! */
    XSelectInput(dpy, Scr.Root, 0);
    XSync(dpy, 0);
    XCloseDisplay(dpy);

    {
      char *my_argv[10];
      int i, done, j;

      i = 0;
      j = 0;
      done = 0;
      while ((g_argv[j] != NULL) && (i < 8)) {
	if (strcmp(g_argv[j], "-s") != 0) {
	  my_argv[i] = g_argv[j];
	  i++;
	  j++;
	} else
	  j++;
      }
      if (strstr(command, "fvwm") != NULL)
	my_argv[i++] = "-s";
      while (i < 10)
	my_argv[i++] = NULL;

      /* really need to destroy all windows, explicitly,
       * not sleep, but this is adequate for now */
      sleep(1);
      ReapChildren();
      execvp(command, my_argv);
    }
    fvwm_msg(ERR, "Done", "Call of '%s' failed!!!!", command);
    execvp(g_argv[0], g_argv);	/* that _should_ work */
    fvwm_msg(ERR, "Done", "Call of '%s' failed!!!!", g_argv[0]);
  } else {
    XCloseDisplay(dpy);
    exit(0);
  }
}
Пример #2
0
void usage(void)
{
#if 0
  fvwm_msg(INFO, "usage", "\nFvwm95 Version %s Usage:\n\n", VERSION);
  fvwm_msg(INFO, "usage",
	   "  %s [-d dpy] [-debug] [-f config_cmd] [-s] [-blackout] [-version] [-h]\n",
	   g_argv[0]);
#else
  fprintf(stderr, "\nFvwm95 Version %s Usage:\n\n", VERSION);
  fprintf(stderr,
	  "  %s [-d dpy] [-debug] [-f config_cmd] [-s] [-blackout] [-version] [-h]\n\n",
	  g_argv[0]);
#endif
}
Пример #3
0
SetupButtons()
{
  XWindowAttributes root_attr;
  XpmAttributes xpm_attributes;

  XGetWindowAttributes(dpy, Scr.Root, &root_attr);
  xpm_attributes.colormap = root_attr.colormap;
  xpm_attributes.closeness = 40000;
  xpm_attributes.valuemask =
      XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;

  if (XpmCreatePixmapFromData(dpy, Scr.Root, sysmenu_xpm,
			      &Scr.button_pixmap[0], &Scr.button_mask[0],
			      &xpm_attributes) != XpmSuccess) {
    fvwm_msg(ERR, "SetupButtons", "Can't make system menu button");
    return;
  }

  if (XpmCreatePixmapFromData(dpy, Scr.Root, close_xpm,
			      &Scr.button_pixmap[1], &Scr.button_mask[1],
			      &xpm_attributes) != XpmSuccess) {
    fvwm_msg(ERR, "SetupButtons", "Can't make close button");
    return;
  }

  if (XpmCreatePixmapFromData(dpy, Scr.Root, normalize_xpm,
			      &Scr.button_pixmap[2], &Scr.button_mask[2],
			      &xpm_attributes) != XpmSuccess) {
    fvwm_msg(ERR, "SetupButtons", "Can't make maximized-state button");
    return;
  }

  if (XpmCreatePixmapFromData(dpy, Scr.Root, maximize_xpm,
			      &Scr.button_pixmap[3], &Scr.button_mask[3],
			      &xpm_attributes) != XpmSuccess) {
    fvwm_msg(ERR, "SetupButtons", "Can't make maximize button");
    return;
  }

  if (XpmCreatePixmapFromData(dpy, Scr.Root, minimize_xpm,
			      &Scr.button_pixmap[5], &Scr.button_mask[5],
			      &xpm_attributes) != XpmSuccess) {
    fvwm_msg(ERR, "SetupButtons", "Can't make minimize button");
    return;
  }

  Scr.button_width = xpm_attributes.width + 3;
  Scr.button_height = xpm_attributes.height + 3;
}
Пример #4
0
void CMD_AddToMenu(F_CMD_ARGS)
{
	MenuRoot *mr;
	MenuRoot *mrPrior;
	char *token, *rest,*item;

	token = PeekToken(action, &rest);
	if (!token)
	{
		return;
	}
	mr = menus_find_menu(token);
	if (mr && MR_MAPPED_COPIES(mr) != 0)
	{
		fvwm_msg(ERR,"add_item_to_menu", "menu %s is in use", token);
		return;
	}
	mr = FollowMenuContinuations(menus_find_menu(token), &mrPrior);
	if (mr == NULL)
	{
		mr = NewMenuRoot(token);
	}

	/* Set + state to last menu */
	set_last_added_item(ADDED_MENU, mr);

	rest = GetNextToken(rest, &item);
	AddToMenu(mr, item, rest, True /* pixmap scan */, True, False);
	if (item)
	{
		free(item);
	}

	return;
}
Пример #5
0
void CMD_EwmhBaseStruts(F_CMD_ARGS)
{
	int val[4];

	if (GetIntegerArguments(action, NULL, val, 4) != 4 ||
	    val[0] < 0 || val[1] < 0 || val[2] < 0 || val[3] < 0)
	{
		fvwm_msg(ERR,"CMD_EwmhBaseStruts",
			 "EwmhBaseStruts needs four positive arguments");
		return;
	}

	if (ewmhc.BaseStrut.left != val[0] ||
	    ewmhc.BaseStrut.right != val[1] ||
	    ewmhc.BaseStrut.top != val[2] ||
	    ewmhc.BaseStrut.bottom != val[3])
	{
		ewmhc.BaseStrut.left   = val[0];
		ewmhc.BaseStrut.right  = val[1];
		ewmhc.BaseStrut.top    = val[2];
		ewmhc.BaseStrut.bottom = val[3];
		ewmh_ComputeAndSetWorkArea();
		ewmh_HandleDynamicWorkArea();
	}
}
Пример #6
0
static void parse_simple_tint(
	colorset_t *cs, char *args, char **tint, int supplied_color,
	int *changed, int *percent, char *cmd)
{
	char *rest;
	static char *name = "parse_colorset (tint)";

	*changed = False;
	rest = get_simple_color(args, tint, cs, supplied_color, 0, NULL);
	if (!(cs->color_flags & supplied_color))
	{
		/* restore to default */
		*percent = 0;
		*changed = True;
		cs->color_flags &= ~(supplied_color);
	}
	else if (!GetIntegerArguments(rest, NULL, percent, 1))
	{
		fvwm_msg(WARN, name,
			 "%s must have two arguments a color and an integer",
			 cmd);
		return;
	}
	*changed = True;
	if (*percent > 100)
	{
		*percent = 100;
	}
	else if (*percent < 0)
	{
		*percent = 0;
	}
}
Пример #7
0
void CMD_ChangeMenuStyle(F_CMD_ARGS)
{
	char *name = NULL;
	char *menuname = NULL;
	MenuStyle *ms = NULL;
	MenuRoot *mr = NULL;

	name = PeekToken(action, &action);
	if (name == NULL)
	{
		fvwm_msg(ERR,"ChangeMenuStyle",
			 "needs at least two parameters");
		return;
	}

	ms = menustyle_find(name);
	if (ms == NULL)
	{
		fvwm_msg(ERR,"ChangeMenuStyle", "cannot find style %s", name);
		return;
	}

	menuname = PeekToken(action, &action);
	while (menuname && *menuname)
	{
		mr = menus_find_menu(menuname);
		if (mr == NULL)
		{
			fvwm_msg(ERR, "ChangeMenuStyle", "cannot find menu %s",
				 menuname);
			break;
		}
		if (MR_MAPPED_COPIES(mr) != 0)
		{
			fvwm_msg(ERR, "ChangeMenuStyle", "menu %s is in use",
				 menuname);
		}
		else
		{
			MR_STYLE(mr) = ms;
			MR_IS_UPDATED(mr) = 1;
		}
		menuname = PeekToken(action, &action);
	}

	return;
}
Пример #8
0
XErrorHandler FvwmErrorHandler(Display *dpy, XErrorEvent *event)
{
  extern int last_event_type;

  /* some errors are acceptable, mostly they're caused by 
   * trying to update a lost  window */
  if ((event->error_code == BadWindow)
      || (event->request_code == X_GetGeometry)
      || (event->error_code == BadDrawable)
      || (event->request_code == X_SetInputFocus)
      || (event->request_code == X_GrabButton)
      || (event->request_code == X_ChangeWindowAttributes)
      || (event->request_code == X_InstallColormap))
    return 0;


  fvwm_msg(ERR, "FvwmErrorHandler", "*** internal error ***");
  fvwm_msg(ERR, "FvwmErrorHandler", "Request %d, Error %d, EventType: %d",
	   event->request_code, event->error_code, last_event_type);
  return 0;
}
Пример #9
0
void CMD_DestroyMenuStyle(F_CMD_ARGS)
{
	MenuStyle *ms = NULL;
	char *name = NULL;

	name = PeekToken(action, NULL);
	if (name == NULL)
	{
		fvwm_msg(ERR,"DestroyMenuStyle", "needs one parameter");
		return;
	}

	ms = menustyle_find(name);
	if (ms == NULL)
	{
		return;
	}
	else if (ms == menustyle_get_default_style())
	{
		fvwm_msg(ERR,"DestroyMenuStyle",
			 "cannot destroy default menu style. "
			 "To reset the default menu style use\n  %s",
			 DEFAULT_MENU_STYLE);
		return;
	}
	else if (ST_USAGE_COUNT(ms) != 0)
	{
		fvwm_msg(ERR, "DestroyMenuStyle", "menu style %s is in use",
			 name);
		return;
	}
	else
	{
		menustyle_free(ms);
	}
	menus_remove_style_from_menus(ms);

	return;
}
Пример #10
0
void CMD_EwmhNumberOfDesktops(F_CMD_ARGS)
{
	int val[2];
	int num;

	num = GetIntegerArguments(action, NULL, val, 2);
	if ((num != 1 && num != 2) || val[0] < 1 ||
	    (num == 2 && val[1] < val[0] && val[1] != 0))
	{
		fvwm_msg(ERR,"EwmhNumberOfDesktops",
			 "Bad arguments to EwmhNumberOfDesktops");
		return;
	}

	if (num == 2 && ewmhc.MaxDesktops != val[1])
	{
		ewmhc.MaxDesktops = val[1];
		num = 3;
	}
	else if (num == 1 && ewmhc.MaxDesktops != 0)
	{
		ewmhc.MaxDesktops = 0;
		num = 3;
	}

	if (ewmhc.NumberOfDesktops != val[0])
	{
		ewmhc.NumberOfDesktops = val[0];
		num = 3;
	}

	if (num == 3)
	{
		ewmhc.NeedsToCheckDesk = True;
		EWMH_SetNumberOfDesktops();
	}
}
Пример #11
0
void SetDeskPageBackground(const Command *c)
{
	Display *dpy2 = NULL;
	Window root2 = None;
	int screen2;
	Pixmap pix = None;

	current_colorset = -1;

	/* FvwmBacker bg preperation */
	switch (c->type)
	{
	case 1: /* solid colors */
	case 2: /* colorset */
		dpy2 =  XOpenDisplay(displayName);
		if (!dpy2)
		{
			fvwm_msg(ERR, "FvwmBacker",
				 "Fail to create a forking dpy, Exit!");
			exit(2);
		}
		screen2 = DefaultScreen(dpy2);
		root2 = RootWindow(dpy2, screen2);
		if (RetainPixmap)
		{
			XSetCloseDownMode(dpy2, RetainPermanent);
		}
		XGrabServer(dpy2);
		DeleteRootAtoms(dpy2, root2);
		switch (c->type)
		{
		case 2:
			current_colorset = c->colorset;
			/* Process a colorset */
			if (CSET_IS_TRANSPARENT(c->colorset))
			{
				fvwm_msg(ERR,"FvwmBacker", "You cannot "
					 "use a transparent colorset as "
					 "background!");
				XUngrabServer(dpy2);
				XCloseDisplay(dpy2);
				return;
			}
			else if (Pdepth != DefaultDepth(dpy2, screen2))
			{
				fvwm_msg(ERR,"FvwmBacker", "You cannot "
					 "use a colorset background if\n"
					 "the fvwm depth is not equal "
					 "to the root depth!");
				XUngrabServer(dpy2);
				XCloseDisplay(dpy2);
				return;
			}
			else if (RetainPixmap)
			{
				pix = CreateBackgroundPixmap(
					dpy2, root2, MyDisplayWidth,
					MyDisplayHeight,
					&Colorset[c->colorset],
					DefaultDepth(dpy2, screen2),
					DefaultGC(dpy2, screen2), False);
				if (pix != None)
				{
					XSetWindowBackgroundPixmap(
						dpy2, root2, pix);
					XClearWindow(dpy2, root2);
				}
			}
			else
			{
				SetWindowBackground(
					dpy2, root2, MyDisplayWidth,
					MyDisplayHeight,
					&Colorset[c->colorset],
					DefaultDepth(dpy2, screen2),
					DefaultGC(dpy2, screen2), True);
			}
			break;
		case 1: /* Process a solid color request */
			if (RetainPixmap)
			{
				GC gc;
				XGCValues xgcv;

				xgcv.foreground = c->solidColor;
				gc = fvwmlib_XCreateGC(
					dpy2, root2, GCForeground,
					&xgcv);
				pix = XCreatePixmap(
					dpy2, root2, 1, 1,
					DefaultDepth(dpy2, screen2));
				XFillRectangle(
					dpy2, pix, gc, 0, 0, 1, 1);
				XFreeGC(dpy2, gc);
			}
			XSetWindowBackground(dpy2, root2, c->solidColor);
			XClearWindow(dpy2, root2);
			break;
		}
		SetRootAtoms(dpy2, root2, pix);
		XUngrabServer(dpy2);
		XCloseDisplay(dpy2); /* this XSync, Ungrab, ...etc */
		break;
	case -1:
	case 0:
	default:
		if(c->cmdStr != NULL)
		{
			SendFvwmPipe(fvwm_fd, c->cmdStr, (unsigned long)0);
		}
		break;
	}
}
Пример #12
0
/****************************************************************************
 *
 *  Parses a mouse or key binding
 *
 ****************************************************************************/
void ParseBindEntry(XEvent *eventp,Window w,FvwmWindow *tmp_win,
		    unsigned long junk, char *tline,int* Module, Bool fKey)
{
  char *action,context[20],modifiers[20],key[20],*ptr, *token;
  Binding *temp;
  int button,i,min,max;
  int n1=0,n2=0,n3=0;
  KeySym keysym;
  KeySym tkeysym;
  int contexts;
  int mods;
  int maxmods;
  int m;

  /* tline points after the key word "Mouse" or "Key" */
  ptr = GetNextToken(tline, &token);
  if(token != NULL)
  {
    if (fKey)
      n1 = sscanf(token,"%19s",key);
    else
      n1 = sscanf(token,"%d",&button);
    free(token);
  }

  ptr = GetNextToken(ptr,&token);
  if(token != NULL)
  {
    n2 = sscanf(token,"%19s",context);
    free(token);
  }

  action = GetNextToken(ptr,&token);
  if(token != NULL)
  {
    n3 = sscanf(token,"%19s",modifiers);
    free(token);
  }

  if((n1 != 1)||(n2 != 1)||(n3 != 1))
  {
    fvwm_msg(ERR,"ParseBindEntry","Syntax error in line %s",tline);
    return;
  }

  find_context(context,&contexts,win_contexts,tline);
  find_context(modifiers,&mods,key_modifiers,tline);

  if (fKey)
    {
      /*
       * Don't let a 0 keycode go through, since that means AnyKey to the
       * XGrabKey call in GrabKeys().
       */
      if ((keysym = XStringToKeysym(key)) == NoSymbol ||
	  (XKeysymToKeycode(dpy, keysym)) == 0)
	return;
    }

  /*
  ** strip leading whitespace from action if necessary
  */
  while (*action && (*action == ' ' || *action == '\t'))
    action++;

  /*
  ** is this an unbind request?
  */
  if (!action || action[0] == '-')
  {
    if (fKey)
      remove_binding(contexts,mods,0,keysym,0);
    else
      remove_binding(contexts,mods,button,0,1);
    return;
  }

  if (!fKey)
    {
      int j;

      if((contexts != C_ALL) && (contexts & C_LALL))
	{
	  /* check for nr_left_buttons */
	  i=0;
	  j=(contexts &C_LALL)/C_L1;
	  while(j>0)
	    {
	      i++;
	      j=j>>1;
	    }
	  if(Scr.nr_left_buttons <i)
	    Scr.nr_left_buttons = i;
	}
Пример #13
0
/* translate a colorset spec into a colorset structure */
void parse_colorset(int n, char *line)
{
	int i;
	int w;
	int h;
	int tmp;
	int percent;
	colorset_t *cs;
	char *optstring;
	char *args;
	char *option;
	char *tmp_str;
	char *fg = NULL;
	char *bg = NULL;
	char *hi = NULL;
	char *sh = NULL;
	char *fgsh = NULL;
	char *tint = NULL;
	char *fg_tint = NULL;
	char *bg_tint = NULL;
	char *icon_tint = NULL;
	Bool have_pixels_changed = False;
	Bool has_icon_pixels_changed = False;
	Bool has_fg_changed = False;
	Bool has_bg_changed = False;
	Bool has_sh_changed = False;
	Bool has_hi_changed = False;
	Bool has_fgsh_changed = False;
	Bool has_fg_alpha_changed = False;
	Bool has_tint_changed = False;
	Bool has_fg_tint_changed = False;
	Bool has_bg_tint_changed = False;
	Bool has_icon_tint_changed = False;
	Bool has_pixmap_changed = False;
	Bool has_shape_changed = False;
	Bool has_image_alpha_changed = False;
	Bool pixmap_is_a_bitmap = False;
	Bool do_reload_pixmap = False;
	Bool is_server_grabbed = False;
	XColor color;
	XGCValues xgcv;
	static char *name = "parse_colorset";
	Window win = Scr.NoFocusWin;
	static GC gc = None;

	/* initialize statics */
	if (gc == None)
	{
		gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv);
	}

	/* make sure it exists and has sensible contents */
	alloc_colorset(n);
	cs = &Colorset[n];

	/*** Parse the options ***/
	while (line && *line)
	{
		/* Read next option specification delimited by a comma or \0.
		 */
		line = GetQuotedString(
			line, &optstring, ",", NULL, NULL, NULL);
		if (!optstring)
			break;
		args = GetNextToken(optstring, &option);
		if (!option)
		{
			free(optstring);
			break;
		}

		switch((i = GetTokenIndex(option, csetopts, 0, NULL)))
		{
		case 0: /* Foreground */
		case 1: /* Fore */
		case 2: /* fg */
			get_simple_color(
				args, &fg, cs, FG_SUPPLIED, FG_CONTRAST,
				"contrast");
			has_fg_changed = True;
			break;
		case 3: /* Background */
		case 4: /* Back */
		case 5: /* bg */
			get_simple_color(
				args, &bg, cs, BG_SUPPLIED, BG_AVERAGE,
				"average");
			has_bg_changed = True;
			break;
		case 6: /* Hilight */
		case 7: /* Hilite */
		case 8: /* hi */
			get_simple_color(args, &hi, cs, HI_SUPPLIED, 0, NULL);
			has_hi_changed = True;
			break;
		case 9: /* Shadow */
		case 10: /* Shade */
		case 11: /* sh */
			get_simple_color(args, &sh, cs, SH_SUPPLIED, 0, NULL);
			has_sh_changed = True;
			break;
		case 12: /* fgsh */
			get_simple_color(
				args, &fgsh, cs, FGSH_SUPPLIED, 0,NULL);
			has_fgsh_changed = True;
			break;
		case 13: /* fg_alpha */
		case 14: /* fgAlpha */
			if (GetIntegerArguments(args, NULL, &tmp, 1))
			{
				if (tmp > 100)
					tmp = 100;
				else if (tmp < 0)
					tmp = 0;
			}
			else
			{
				tmp = 100;
			}
			if (tmp != cs->fg_alpha_percent)
			{
				cs->fg_alpha_percent = tmp;
				has_fg_alpha_changed = True;
			}
			break;
		case 15: /* TiledPixmap */
		case 16: /* Pixmap */
		case 17: /* AspectPixmap */
			has_pixmap_changed = True;
			free_colorset_background(cs, True);
			tmp_str = PeekToken(args, &args);
			if (tmp_str)
			{
				CopyString(&cs->pixmap_args, tmp_str);
				do_reload_pixmap = True;
				cs->gradient_type = 0;
				/* set the flags */
				if (csetopts[i][0] == 'T')
				{
					cs->pixmap_type = PIXMAP_TILED;
				}
				else if (csetopts[i][0] == 'A')
				{
					cs->pixmap_type = PIXMAP_STRETCH_ASPECT;
				}
				else
				{
					cs->pixmap_type = PIXMAP_STRETCH;
				}
			}
			/* the pixmap is build later */
			break;
		case 18: /* Shape */
		case 19: /* TiledShape */
		case 20: /* AspectShape */
			parse_shape(win, cs, i, args, &has_shape_changed);
			break;
		case 21: /* Plain */
			has_pixmap_changed = True;
			free_colorset_background(cs, True);
			break;
		case 22: /* NoShape */
			has_shape_changed = True;
			if (cs->shape_mask)
			{
				add_to_junk(cs->shape_mask);
				cs->shape_mask = None;
			}
			break;
		case 23: /* Transparent */

			/* This is only allowable when the root depth == fvwm
			 * visual depth otherwise bad match errors happen,
			 * it may be even more restrictive but my tests (on
			 * exceed 6.2) show that only == depth is necessary */

			if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy))))
			{
				fvwm_msg(
					ERR, name, "can't do Transparent "
					"when root_depth!=fvwm_depth");
				break;
			}
			has_pixmap_changed = True;
			free_colorset_background(cs, True);
			cs->pixmap = ParentRelative;
			cs->pixmap_type = PIXMAP_STRETCH;
			break;
		case 24: /* RootTransparent */
			if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy))))
			{
				fvwm_msg(
					ERR, name, "can't do RootTransparent "
					"when root_depth!=fvwm_depth");
				break;
			}
			free_colorset_background(cs, True);
			has_pixmap_changed = True;
			cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE;
			do_reload_pixmap = True;
			tmp_str = PeekToken(args, &args);
			if (StrEquals(tmp_str, "buffer"))
			{
				cs->allows_buffered_transparency = True;
			}
			else
			{
				cs->allows_buffered_transparency = False;
			}
			cs->is_maybe_root_transparent = True;
			break;
		case 25: /* Tint */
		case 26: /* PixmapTint */
		case 27: /* ImageTint */
		case 28: /* TintMask */
			parse_simple_tint(
				cs, args, &tint, TINT_SUPPLIED,
				&has_tint_changed, &percent, "tint");
			if (has_tint_changed)
			{
				cs->tint_percent = percent;
			}
			break;
		case 29: /* NoTint */
			has_tint_changed = True;
			cs->tint_percent = 0;
			cs->color_flags &= ~TINT_SUPPLIED;
			break;
		case 30: /* fgTint */
			parse_simple_tint(
				cs, args, &fg_tint, FG_TINT_SUPPLIED,
				&has_fg_tint_changed, &percent, "fgTint");
			if (has_fg_tint_changed)
			{
				cs->fg_tint_percent = percent;
			}
			break;
		case 31: /* bgTint */
			parse_simple_tint(
				cs, args, &bg_tint, BG_TINT_SUPPLIED,
				&has_bg_tint_changed, &percent, "bgTint");
			if (has_bg_tint_changed)
			{
				cs->bg_tint_percent = percent;
			}
			break;
		case 32: /* dither */
			if (cs->pixmap_args || cs->gradient_args)
			{
				has_pixmap_changed = True;
				do_reload_pixmap = True;
			}
			cs->dither = True;
			break;
		case 33: /* nodither */
			if (cs->pixmap_args || cs->gradient_args)
			{
				has_pixmap_changed = True;
				do_reload_pixmap = True;
			}
			cs->dither = False;
			break;
		case 34: /* Alpha */
		case 35: /* PixmapAlpha */
		case 36: /* ImageAlpha */
			if (GetIntegerArguments(args, NULL, &tmp, 1))
			{
				if (tmp > 100)
					tmp = 100;
				else if (tmp < 0)
					tmp = 0;
			}
			else
			{
				tmp = 100;
			}
			if (tmp != cs->image_alpha_percent)
			{
				has_image_alpha_changed = True;
				cs->image_alpha_percent = tmp;
			}
			break;
                /* dither icon is not dynamic (yet) maybe a bad opt: default
		 * to False ? */
		case 37: /* ditherIcon */
			cs->do_dither_icon = True;
			break;
		case 38: /* DoNotDitherIcon */
			cs->do_dither_icon = False;
			break;
		case 39: /* IconTint */
			parse_simple_tint(
				cs, args, &icon_tint, ICON_TINT_SUPPLIED,
				&has_icon_tint_changed, &percent, "IconTint");
			if (has_icon_tint_changed)
			{
				cs->icon_tint_percent = percent;
				has_icon_pixels_changed = True;
			}
			break;
		case 40: /* NoIconTint */
			has_icon_tint_changed = True;
			if (cs->icon_tint_percent != 0)
			{
				has_icon_pixels_changed = True;
			}
			cs->icon_tint_percent = 0;
			break;
		case 41: /* IconAlpha */
			if (GetIntegerArguments(args, NULL, &tmp, 1))
			{
				if (tmp > 100)
					tmp = 100;
				else if (tmp < 0)
					tmp = 0;
			}
			else
			{
				tmp = 100;
			}
			if (tmp != cs->icon_alpha_percent)
			{
				has_icon_pixels_changed = True;
				cs->icon_alpha_percent = tmp;
			}
			break;
		default:
			/* test for ?Gradient */
			if (option[0] && StrEquals(&option[1], "Gradient"))
			{
				cs->gradient_type = toupper(option[0]);
				if (!IsGradientTypeSupported(cs->gradient_type))
					break;
				has_pixmap_changed = True;
				free_colorset_background(cs, True);
				CopyString(&cs->gradient_args, args);
				do_reload_pixmap = True;
				if (cs->gradient_type == V_GRADIENT)
				{
					cs->pixmap_type = PIXMAP_STRETCH_Y;
				}
				else if (cs->gradient_type == H_GRADIENT)
					cs->pixmap_type = PIXMAP_STRETCH_X;
				else
					cs->pixmap_type = PIXMAP_STRETCH;
			}
			else
			{
				fvwm_msg(
					WARN, name, "bad colorset pixmap "
					"specifier %s %s", option, line);
			}
			break;
		} /* switch */

		if (option)
		{
			free(option);
			option = NULL;
		}
		free(optstring);
		optstring = NULL;
	} /* while (line && *line) */

	/*
	 * ---------- change the "pixmap" tint colour ----------
	 */
	if (has_tint_changed)
	{
		/* user specified colour */
		if (tint != NULL)
		{
			Pixel old_tint = cs->tint;
			PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True);
			cs->tint = GetColor(tint);
			if (old_tint != cs->tint)
			{
				have_pixels_changed = True;
			}
		}
		else if (tint == NULL)
		{
			/* default */
			Pixel old_tint = cs->tint;
			PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True);
			cs->tint = GetColor(black);
			if (old_tint != cs->tint)
			{
				have_pixels_changed = True;
			}
		}
	}

	/*
	 * reload the gradient if the tint or the alpha have changed.
	 * Do this too if we need to recompute the bg average and the
	 * gradient is tinted (perforemence issue).
	 */
	if ((has_tint_changed || has_image_alpha_changed ||
	     (has_bg_changed && (cs->color_flags & BG_AVERAGE) &&
	      cs->tint_percent > 0)) && cs->gradient_args)
	{
		do_reload_pixmap = True;
	}

	/*
	 * reset the pixmap if the tint or the alpha has changed
	 */
	if (!do_reload_pixmap &&
	    (has_tint_changed || has_image_alpha_changed  ||
	     (has_bg_changed && cs->alpha_pixmap != None)))
	{
		if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE ||
		    cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN)
		{
			do_reload_pixmap = True;
		}
		else if (cs->picture != NULL && cs->pixmap)
		{
			XSetClipMask(dpy, gc, cs->picture->mask);
			reset_cs_pixmap(cs, gc);
			XSetClipMask(dpy, gc, None);
			has_pixmap_changed = True;
		}
	}

	/*
	 * (re)build the pixmap or the gradient
	 */
	if (do_reload_pixmap)
	{
		free_colorset_background(cs, False);
		has_pixmap_changed = True;
		if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE ||
		    cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN)
		{
			cs->pixmap_type = 0;
			if (root_pic.pixmap)
			{
				cs->pixmap = root_pic.pixmap;
				cs->width = root_pic.width;
				cs->height = root_pic.height;
				cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE;
#if 0
				fprintf(stderr,"Cset %i LoadRoot 0x%lx\n",
					n, cs->pixmap);
#endif
			}
		}
		else if (cs->pixmap_args)
		{
			parse_pixmap(win, gc, cs, &pixmap_is_a_bitmap);
		}
		else if (cs->gradient_args)
		{
			cs->pixmap = CreateGradientPixmapFromString(
				dpy, win, gc, cs->gradient_type,
				cs->gradient_args, &w, &h, &cs->pixels,
				&cs->nalloc_pixels, cs->dither);
			cs->width = w;
			cs->height = h;
		}
		has_pixmap_changed = True;
	}

	if (cs->picture != NULL && cs->picture->depth != Pdepth)
	{
		pixmap_is_a_bitmap = True;
	}

	/*
	 * ---------- change the background colour ----------
	 */
	if (has_bg_changed ||
	    (has_pixmap_changed && (cs->color_flags & BG_AVERAGE) &&
	     cs->pixmap != None &&
	     cs->pixmap != ParentRelative &&
	     !pixmap_is_a_bitmap))
	{
		Bool do_set_default_background = False;
		Pixmap average_pix = None;

		if (cs->color_flags & BG_AVERAGE)
		{
			if (cs->picture != NULL && cs->picture->picture != None)
			{
				average_pix = cs->picture->picture;
			}
			else if (cs->pixmap != ParentRelative)
			{
				average_pix = cs->pixmap;
			}

			if (average_pix == root_pic.pixmap)
			{
				int w;
				int h;
				XID dummy;

				MyXGrabServer(dpy);
				is_server_grabbed = True;
				if (!XGetGeometry(
				    dpy, average_pix, &dummy,
				    (int *)&dummy, (int *)&dummy,
				    (unsigned int *)&w, (unsigned int *)&h,
				    (unsigned int *)&dummy,
				    (unsigned int *)&dummy))
				{
					average_pix = None;
				}
				else
				{
					if (w != cs->width || h != cs->height)
					{
						average_pix = None;
					}
				}
				if (average_pix == None)
				{
					MyXUngrabServer(dpy);
					is_server_grabbed = False;
				}
			}
		}

		/* note: no average for bitmap */
		if ((cs->color_flags & BG_AVERAGE) && average_pix)
		{
			/* calculate average background color */
			XColor *colors;
			XImage *image;
			XImage *mask_image = None;
			unsigned int i, j, k = 0;
			unsigned long red = 0, blue = 0, green = 0;
			unsigned long tred, tblue, tgreen;
			double dred = 0.0, dblue = 0.0, dgreen = 0.0;

			has_bg_changed = True;
			/* create an array to store all the pixmap colors in */
			/* Note: this may allocate a lot of memory:
			 * cs->width * cs->height * 12 and then the rest of the
			 * procedure can take a lot of times */
			colors = (XColor *)safemalloc(
				cs->width * cs->height * sizeof(XColor));
			/* get the pixmap and mask into an image */
			image = XGetImage(
				dpy, average_pix, 0, 0, cs->width, cs->height,
				AllPlanes, ZPixmap);
			if (cs->mask != None)
			{
				mask_image = XGetImage(
					dpy, cs->mask, 0, 0, cs->width,
					cs->height, AllPlanes, ZPixmap);
			}
			if (is_server_grabbed == True)
			{
				MyXUngrabServer(dpy);
			}
			if (image != None && mask_image != None)
			{
				/* only fetch the pixels that are not masked
				 * out */
				for (i = 0; i < cs->width; i++)
				{
					for (j = 0; j < cs->height; j++)
					{
						if (
							cs->mask == None ||
							XGetPixel(
								mask_image, i,
								j) == 0)
						{
							colors[k++].pixel =
								XGetPixel(
									image,
									i, j);
						}
					}
				}
			}
			if (image != None)
			{
				XDestroyImage(image);
			}
			if (mask_image != None)
			{
				XDestroyImage(mask_image);
			}
			if (k == 0)
			{
				do_set_default_background = True;
			}
			else
			{
				/* look them all up, XQueryColors() can't
				 * handle more than 256 */
				for (i = 0; i < k; i += 256)
				{
					XQueryColors(
						dpy, Pcmap, &colors[i],
						min(k - i, 256));
				}
				/* calculate average, add overflows in a double
				 * .red is short, red is long */
				for (i = 0; i < k; i++)
				{
					tred = red;
					red += colors[i].red;
					if (red < tred)
					{
						dred += (double)tred;
						red = colors[i].red;
					}
					tgreen = green;
					green += colors[i].green;
					if (green < tgreen)
					{
						dgreen += (double)tgreen;
						green = colors[i].green;
					}
					tblue = blue;
					blue += colors[i].blue;
					if (blue < tblue)
					{
						dblue += (double)tblue;
						blue = colors[i].blue;
					}
				}
				dred += red;
				dgreen += green;
				dblue += blue;
				/* get it */
				color.red = dred / k;
				color.green = dgreen / k;
				color.blue = dblue / k;
				{
					Pixel old_bg = cs->bg;

					PictureFreeColors(
						dpy, Pcmap, &cs->bg, 1, 0,
						True);
					PictureAllocColor(
						dpy, Pcmap, &color, True);
					cs->bg = color.pixel;
					if (old_bg != cs->bg)
					{
						have_pixels_changed = True;
					}
				}
			}
			free(colors);
		} /* average */
		else if ((cs->color_flags & BG_SUPPLIED) && bg != NULL)
		{
			/* user specified colour */
			Pixel old_bg = cs->bg;

			PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True);
			cs->bg = GetColor(bg);
			if (old_bg != cs->bg)
			{
				have_pixels_changed = True;
			}
		} /* user specified */
		else if (bg == NULL && has_bg_changed)
		{
			/* default */
			do_set_default_background = True;
		} /* default */
		if (do_set_default_background)
		{
			Pixel old_bg = cs->bg;

			PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True);
			cs->bg = GetColor(white);
			if (old_bg != cs->bg)
			{
				have_pixels_changed = True;
			}
			has_bg_changed = True;
		}

		if (has_bg_changed)
		{
			/* save the bg color for tinting */
			cs->bg_saved = cs->bg;
		}
	} /* has_bg_changed */


	/*
	 * ---------- setup the bg tint colour ----------
	 */
	if (has_bg_tint_changed && cs->bg_tint_percent > 0 && bg_tint != NULL)
	{
		PictureFreeColors(dpy, Pcmap, &cs->bg_tint, 1, 0, True);
		cs->bg_tint = GetColor(bg_tint);
	}

	/*
	 * ---------- tint the bg colour ----------
	 */
	if (has_bg_tint_changed || (has_bg_changed && cs->bg_tint_percent > 0))
	{
		if (cs->bg_tint_percent == 0)
		{
			Pixel old_bg = cs->bg;

			PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True);
			cs->bg = cs->bg_saved;
			if (old_bg != cs->bg)
			{
				have_pixels_changed = True;
				has_bg_changed = True;
			}
		}
		else
		{
			Pixel old_bg = cs->bg;

			PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True);
			cs->bg = GetTintedPixel(
				cs->bg_saved, cs->bg_tint, cs->bg_tint_percent);
			if (old_bg != cs->bg)
			{
				have_pixels_changed = True;
				has_bg_changed = True;
			}
		}
	}

	/*
	 * ---------- setup the fg tint colour ----------
	 */
	if (has_fg_tint_changed && cs->fg_tint_percent > 0 && fg_tint != NULL)
	{
		PictureFreeColors(dpy, Pcmap, &cs->fg_tint, 1, 0, True);
		cs->fg_tint = GetColor(fg_tint);
	}

	/*
	 * ---------- change the foreground colour ----------
	 */
	if (has_fg_changed ||
	    (has_bg_changed && (cs->color_flags & FG_CONTRAST)))
	{
		if (cs->color_flags & FG_CONTRAST)
		{
			Pixel old_fg = cs->fg;

			/* calculate contrasting foreground color */
			color.pixel = cs->bg;
			XQueryColor(dpy, Pcmap, &color);
			color.red = (color.red > 32767) ? 0 : 65535;
			color.green = (color.green > 32767) ? 0 : 65535;
			color.blue = (color.blue > 32767) ? 0 : 65535;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			PictureAllocColor(dpy, Pcmap, &color, True);
			cs->fg = color.pixel;
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		} /* contrast */
		else if ((cs->color_flags & FG_SUPPLIED) && fg != NULL)
		{
			/* user specified colour */
			Pixel old_fg = cs->fg;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			cs->fg = GetColor(fg);
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		} /* user specified */
		else if (fg == NULL)
		{
			/* default */
			Pixel old_fg = cs->fg;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			cs->fg = GetColor(black);
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		}

		/* save the fg color for tinting */
		cs->fg_saved = cs->fg;

	} /* has_fg_changed */

	/*
	 * ---------- tint the foreground colour ----------
	 */
	if (has_fg_tint_changed || (has_fg_changed && cs->fg_tint_percent > 0))
	{
		if (cs->fg_tint_percent == 0)
		{

			Pixel old_fg = cs->fg;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			cs->fg = cs->fg_saved;
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		}
		else
		{
			Pixel old_fg = cs->fg;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			cs->fg = GetTintedPixel(
				cs->fg_saved, cs->fg_tint,
				cs->fg_tint_percent);
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		}
	}


	/*
	 * ---------- change the hilight colour ----------
	 */
	if (has_hi_changed ||
	    (has_bg_changed && !(cs->color_flags & HI_SUPPLIED)))
	{
		has_hi_changed = 1;
		if ((cs->color_flags & HI_SUPPLIED) && hi != NULL)
		{
			/* user specified colour */
			Pixel old_hilite = cs->hilite;

			PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True);
			cs->hilite = GetColor(hi);
			if (old_hilite != cs->hilite)
			{
					have_pixels_changed = True;
			}
		} /* user specified */
		else if (hi == NULL)
		{
			Pixel old_hilite = cs->hilite;

			PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True);
			cs->hilite = GetHilite(cs->bg);
			if (old_hilite != cs->hilite)
			{
				have_pixels_changed = True;
			}
		}
	} /* has_hi_changed */

	/*
	 * ---------- change the shadow colour ----------
	 */
	if (has_sh_changed ||
	    (has_bg_changed && !(cs->color_flags & SH_SUPPLIED)))
	{
		has_sh_changed = 1;
		if ((cs->color_flags & SH_SUPPLIED) && sh != NULL)
		{
			/* user specified colour */
			Pixel old_shadow = cs->shadow;

			PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True);
			cs->shadow = GetColor(sh);
			if (old_shadow != cs->shadow)
			{
				have_pixels_changed = True;
			}
		} /* user specified */
		else if (sh == NULL)
		{
			Pixel old_shadow = cs->shadow;

			PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True);
			cs->shadow = GetShadow(cs->bg);
			if (old_shadow != cs->shadow)
			{
				have_pixels_changed = True;
			}
		}
	} /* has_sh_changed */

	/*
	 * ---------- change the shadow foreground colour ----------
	 */
	if (has_fgsh_changed ||
	    ((has_fg_changed || has_bg_changed) &&
	     !(cs->color_flags & FGSH_SUPPLIED)))
	{
		has_fgsh_changed = 1;
		if ((cs->color_flags & FGSH_SUPPLIED) && fgsh != NULL)
		{
			/* user specified colour */
			Pixel old_fgsh = cs->fgsh;

			PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True);
			cs->fgsh = GetColor(fgsh);
			if (old_fgsh != cs->fgsh)
			{
				have_pixels_changed = True;
			}
		} /* user specified */
		else if (fgsh == NULL)
		{
			Pixel old_fgsh = cs->fgsh;

			PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True);
			cs->fgsh = GetForeShadow(cs->fg, cs->bg);
			if (old_fgsh != cs->fgsh)
			{
				have_pixels_changed = True;
			}
		}
	} /* has_fgsh_changed */

	/*
	 * ------- the pixmap is a bitmap: create here cs->pixmap -------
	 */
	if (cs->picture != None && pixmap_is_a_bitmap &&
	    (has_pixmap_changed || has_bg_changed))
	{
		cs->pixmap = XCreatePixmap(
			dpy, win, cs->width, cs->height, Pdepth);
		XSetBackground(dpy, gc, cs->bg);
		XSetForeground(dpy, gc, cs->fg);
		reset_cs_pixmap(cs, gc);
	}

	/*
	 * ------- change the masked out parts of the background pixmap -------
	 */
	if (cs->pixmap != None && cs->pixmap != ParentRelative &&
	    (!CSETS_IS_TRANSPARENT_ROOT(cs)||
	     cs->allows_buffered_transparency) &&
	    (cs->mask != None || cs->alpha_pixmap != None ||
	     cs->image_alpha_percent < 100 || cs->tint_percent > 0) &&
	    (has_pixmap_changed || has_bg_changed || has_image_alpha_changed
	     || has_tint_changed))
	{
		/* Now that we know the background colour we can update the
		 * pixmap background. */
		FvwmRenderAttributes fra;
		Pixmap temp, mask, alpha;

		memset(&fra, 0, sizeof(fra));
		temp = XCreatePixmap(dpy, win, cs->width, cs->height, Pdepth);
		if (cs->picture != NULL)
		{
			mask = cs->picture->mask;
			alpha = cs->picture->alpha;
		}
		else
		{
			mask = None;
			alpha = None;
		}
		XSetForeground(dpy, gc, cs->bg);
		XFillRectangle(
			dpy, temp, gc, 0, 0, cs->width, cs->height);

		fra.mask = FRAM_HAVE_ADDED_ALPHA | FRAM_HAVE_TINT;
		fra.added_alpha_percent = cs->image_alpha_percent;
		fra.tint = cs->tint;
		fra.tint_percent = cs->tint_percent;
		PGraphicsRenderPixmaps(
			dpy, win, cs->pixmap, mask, alpha, Pdepth, &fra,
			temp, gc, Scr.MonoGC, Scr.AlphaGC,
			0, 0, cs->width, cs->height,
			0, 0, cs->width, cs->height, False);
		if (cs->pixmap != root_pic.pixmap)
		{
			add_to_junk(cs->pixmap);
		}
		cs->pixmap = temp;
		has_pixmap_changed = True;
		if (CSETS_IS_TRANSPARENT_ROOT(cs))
		{
			cs->pixmap_type = PIXMAP_ROOT_PIXMAP_TRAN;
		}
	} /* has_pixmap_changed */


	/*
	 * ---------- change the icon tint colour ----------
	 */
	if (has_icon_tint_changed)
	{
		/* user specified colour */
		if (icon_tint != NULL)
		{
			Pixel old_tint = cs->icon_tint;
			PictureFreeColors(
				dpy, Pcmap, &cs->icon_tint, 1, 0, True);
			cs->icon_tint = GetColor(icon_tint);
			if (old_tint != cs->icon_tint)
			{
				has_icon_pixels_changed = True;
			}
		}
		else
		{
			/* default */
			Pixel old_tint = cs->icon_tint;
			PictureFreeColors(
				dpy, Pcmap, &cs->icon_tint, 1, 0, True);
			cs->icon_tint = GetColor(black);
			if (old_tint != cs->icon_tint)
			{
				has_icon_pixels_changed = True;
			}
		}
	}

	/*
	 * ---------- send new colorset to fvwm and clean up ----------
	 */
	/* make sure the server has this to avoid races */
	XSync(dpy, False);

	/* inform modules of the change */
	if (have_pixels_changed || has_pixmap_changed || has_shape_changed ||
	    has_fg_alpha_changed || has_icon_pixels_changed)
	{
		BroadcastColorset(n);
	}

	if (fg)
	{
		free(fg);
	}
	if (bg)
	{
		free(bg);
	}
	if (hi)
	{
		free(hi);
	}
	if (sh)
	{
		free(sh);
	}
	if (fgsh)
	{
		free(fgsh);
	}
	if (tint)
	{
		free(tint);
	}
	if (fg_tint)
	{
		free(fg_tint);
	}
	if (bg_tint)
	{
		free(bg_tint);
	}
	if (icon_tint)
	{
		free(icon_tint);
	}
	return;
}
Пример #14
0
static void menu_func(F_CMD_ARGS, Bool fStaysUp)
{
	struct MenuRoot *menu;
	char *ret_action = NULL;
	struct MenuOptions mops;
	char *menu_name = NULL;
	struct MenuParameters mp;
	struct MenuReturn mret;
	FvwmWindow * const fw = exc->w.fw;
	const Window w = exc->w.w;
	const exec_context_t *exc2;

	memset(&mops, 0, sizeof(mops));
	memset(&mret, 0, sizeof(MenuReturn));
	action = GetNextToken(action,&menu_name);
	action = get_menu_options(
		action, w, fw, NULL, NULL, NULL, &mops);
	while (action && *action && isspace((unsigned char)*action))
	{
		action++;
	}
	if (action && *action == 0)
	{
		action = NULL;
	}
	menu = menus_find_menu(menu_name);
	if (menu == NULL)
	{
		if (menu_name)
		{
			fvwm_msg(ERR,"menu_func","No such menu %s",menu_name);
			free(menu_name);
		}
		return;
	}
	if (menu_name &&
	    set_repeat_data(
		    menu_name, (fStaysUp) ? REPEAT_MENU : REPEAT_POPUP,NULL))
	{
		free(menu_name);
	}

	memset(&mp, 0, sizeof(mp));
	mp.menu = menu;
	exc2 = exc_clone_context(exc, NULL, 0);
	mp.pexc = &exc2;
	MR_IS_TEAR_OFF_MENU(menu) = 0;
	mp.flags.has_default_action = (action != NULL);
	mp.flags.is_sticky = fStaysUp;
	mp.flags.is_submenu = False;
	mp.flags.is_already_mapped = False;
	mp.flags.is_triggered_by_keypress =
		(exc->x.etrigger->type == KeyPress);
	mp.pops = &mops;
	mp.ret_paction = &ret_action;
	do_menu(&mp, &mret);
	if (mret.rc == MENU_DOUBLE_CLICKED && action)
	{
		execute_function(cond_rc, exc2, action, 0);
	}
	if (ret_action != NULL)
	{
		free(ret_action);
	}
	exc_destroy_context(exc2);

	return;
}
Пример #15
0
/* Process a style command.  First built up in a temp area.
   If valid, added to the list in a malloced area. */
void ProcessNewStyle(XEvent *eventp,
                     Window w,
                     FvwmWindow *tmp_win,
                     unsigned long context,
                     char *text,
                     int *Module)
{
    char *line;
    char *restofline,*tmp;
    name_list *nptr;
    int butt;                             /* work area for button number */
    int num,i;
    /*  RBW - 11/02/1998  */
    int tmpno1 = -1, tmpno2 = -1, tmpno3 = -1, spargs = 0;
    /**/

    name_list tname;                      /* temp area to build name list */
    int len = 0;
    icon_boxes *which = 0;                /* which current boxes to chain to */
    int is_quoted;                        /* for parsing args with quotes */

    memset(&tname, 0, sizeof(name_list)); /* init temp name_list area */

    restofline = GetNextToken(text,&tname.name); /* parse style name */
    /* in case there was no argument! */
    if((tname.name == NULL)||(restofline == NULL))/* If no name, or blank cmd */
    {
        if (tname.name)
            free(tname.name);
        return;                             /* drop it. */
    }

    SKIPSPACE;                            /* skip over white space */
    line = restofline;

    if(restofline == NULL)
    {
        free(tname.name);
        return;
    }
    while((*restofline != 0)&&(*restofline != '\n'))
    {
        SKIPSPACE;                          /* skip white space */
        /* It might make more sense to capture the whole word, fix its
           case, and use strcmp, but there aren't many caseless compares
           because of this "switch" on the first letter. */
        switch (tolower(restofline[0]))
        {
        case 'a':
            if(ITIS("ACTIVEPLACEMENT"))
            {
                SKIP("ACTIVEPLACEMENT");
                tname.on_flags |= RANDOM_PLACE_FLAG;
            }
            break;
        case 'b':
            if(ITIS("BACKCOLOR"))
            {
                SKIP("BACKCOLOR");
                GETWORD;
                if(len > 0)
                {
                    tname.BackColor = safemalloc(len+1);
                    strncpy(tname.BackColor,restofline,len);
                    tname.BackColor[len] = 0;
                    tname.off_flags |= BACK_COLOR_FLAG;
                }
                restofline = tmp;
            }
            else if (ITIS("BUTTON"))
            {
                SKIP("BUTTON");
                butt = -1; /* just in case sscanf fails */
                sscanf(restofline,"%d",&butt);
                GETWORD;
                restofline = tmp;
                SKIPSPACE;
                if (butt == 0) butt = 10;
                if (butt > 0 && butt <= 10)
                    tname.on_buttons |= (1<<(butt-1));
            }
            else if(ITIS("BorderWidth"))
            {
                SKIP("BorderWidth");
                tname.off_flags |= BW_FLAG;
                sscanf(restofline,"%d",&tname.border_width);
                GETWORD;
                restofline = tmp;
                SKIPSPACE;
            }
            break;
        case 'c':
            if(ITIS("COLOR"))
            {
                SKIP("COLOR");
                SKIPSPACE;
                tmp = restofline;
                len = 0;
                while((tmp != NULL)&&(*tmp != 0)&&(*tmp != ',')&&
                        (*tmp != '\n')&&(*tmp != '/')&&(!isspace(*tmp)))
                {
                    tmp++;
                    len++;
                }
                if(len > 0)
                {
                    tname.ForeColor = safemalloc(len+1);
                    strncpy(tname.ForeColor,restofline,len);
                    tname.ForeColor[len] = 0;
                    tname.off_flags |= FORE_COLOR_FLAG;
                }

                while(isspace(*tmp))tmp++;
                if(*tmp == '/')
                {
                    tmp++;
                    while(isspace(*tmp))tmp++;
                    restofline = tmp;
                    len = 0;
                    while((tmp != NULL)&&(*tmp != 0)&&(*tmp != ',')&&
                            (*tmp != '\n')&&(*tmp != '/')&&(!isspace(*tmp)))
                    {
                        tmp++;
                        len++;
                    }
                    if(len > 0)
                    {
                        tname.BackColor = safemalloc(len+1);
                        strncpy(tname.BackColor,restofline,len);
                        tname.BackColor[len] = 0;
                        tname.off_flags |= BACK_COLOR_FLAG;
                    }
                }
                restofline = tmp;
            }
            else if(ITIS("CirculateSkipIcon"))
            {
                SKIP("CirculateSkipIcon");
                tname.off_flags |= CIRCULATE_SKIP_ICON_FLAG;
            }
            else if(ITIS("CirculateHitIcon"))
            {
                SKIP("CirculateHitIcon");
                tname.on_flags |= CIRCULATE_SKIP_ICON_FLAG;
            }
            else if(ITIS("CLICKTOFOCUS"))
            {
                SKIP("CLICKTOFOCUS");
                tname.off_flags |= CLICK_FOCUS_FLAG;
                tname.on_flags |= SLOPPY_FOCUS_FLAG;
            }
            else if(ITIS("CirculateSkip"))
            {
                SKIP("CirculateSkip");
                tname.off_flags |= CIRCULATESKIP_FLAG;
            }
            else if(ITIS("CirculateHit"))
            {
                SKIP("CirculateHit");
                tname.on_flags |= CIRCULATESKIP_FLAG;
            }
            break;
        case 'd':
            if(ITIS("DecorateTransient"))
            {
                SKIP("DecorateTransient");
                tname.off_flags |= DECORATE_TRANSIENT_FLAG;
            }
            else if(ITIS("DUMBPLACEMENT"))
            {
                SKIP("DUMBPLACEMENT");
                tname.on_flags |= SMART_PLACE_FLAG;
            }
            break;
        case 'e':
            break;
        case 'f':
            if(ITIS("FORECOLOR"))
            {
                SKIP("FORECOLOR");
                GETWORD;
                if(len > 0)
                {
                    tname.ForeColor = safemalloc(len+1);
                    strncpy(tname.ForeColor,restofline,len);
                    tname.ForeColor[len] = 0;
                    tname.off_flags |= FORE_COLOR_FLAG;
                }
                restofline = tmp;
            }
            else if(ITIS("FVWMBUTTONS"))
            {
                SKIP("FVWMBUTTONS");
                tname.on_flags |= MWM_BUTTON_FLAG;
            }
            else if(ITIS("FVWMBORDER"))
            {
                SKIP("FVWMBORDER");
                tname.on_flags |= MWM_BORDER_FLAG;
            }
            else if(ITIS("FocusFollowsMouse"))
            {
                SKIP("FocusFollowsMouse");
                tname.on_flags |= CLICK_FOCUS_FLAG;
                tname.on_flags |= SLOPPY_FOCUS_FLAG;
            }
            break;
        case 'g':
            break;
        case 'h':
            if(ITIS("HINTOVERRIDE"))
            {
                SKIP("HINTOVERRIDE");
                tname.off_flags |= MWM_OVERRIDE_FLAG;
            }
            else if(ITIS("HANDLES"))
            {
                SKIP("HANDLES");
                tname.on_flags |= NOBORDER_FLAG;
            }
            else if(ITIS("HandleWidth"))
            {
                SKIP("HandleWidth");
                tname.off_flags |= NOBW_FLAG;
                sscanf(restofline,"%d",&tname.resize_width);
                GETWORD;
                restofline = tmp;
                SKIPSPACE;
            }
            break;
        case 'i':
            if(ITIS("IconTitle"))
            {
                SKIP("IconTitle");
                tname.on_flags |= NOICON_TITLE_FLAG;
            }
            else if(ITIS("IconBox"))
            {
                icon_boxes *IconBoxes = 0;
                SKIP("IconBox");              /* Skip over word "IconBox" */
                IconBoxes = (icon_boxes *)safemalloc(sizeof(icon_boxes));
                memset(IconBoxes, 0, sizeof(icon_boxes)); /* clear it */
                IconBoxes->IconGrid[0] = 3;   /* init grid x */
                IconBoxes->IconGrid[1] = 3;   /* init grid y */
                /* try for 4 numbers x y x y */
                num = sscanf(restofline,"%d%d%d%d",
                             &IconBoxes->IconBox[0],
                             &IconBoxes->IconBox[1],
                             &IconBoxes->IconBox[2],
                             &IconBoxes->IconBox[3]);
                if (num == 4) {               /* if 4 numbers */
                    for(i=0; i<num; i++) {
                        SKIPSPACE;
                        if (*restofline == '-') { /* If leading minus sign */
                            if (i == 0 || i == 2) { /* if a width */
                                IconBoxes->IconBox[i] += Scr.MyDisplayWidth;
                            } else {                  /* it must be a height */
                                IconBoxes->IconBox[i] += Scr.MyDisplayHeight;
                            } /* end width/height */
                        } /* end leading minus sign */
                        while((!isspace(*restofline))&&(*restofline!= 0)&&
                                (*restofline != ',')&&(*restofline != '\n'))
                            restofline++;
                    }
                    /* Note: here there is no test for valid co-ords, use geom */
                } else {                   /* Not 4 numeric args dje */
                    char geom_string[25];    /* bigger than =32767x32767+32767+32767 */
                    int geom_flags;
                    GETWORD;                    /* read in 1 word w/o advancing */
                    if(len > 0 && len < 24) {   /* if word found, not too long */
                        strncpy(geom_string,restofline,len); /* copy and null term */
                        geom_string[len] = 0;     /* null terminate it */
                        geom_flags=XParseGeometry(geom_string,
                                                  &IconBoxes->IconBox[0],
                                                  &IconBoxes->IconBox[1], /* x/y */
                                                  &IconBoxes->IconBox[2],
                                                  &IconBoxes->IconBox[3]); /* width/ht */
                        if (IconBoxes->IconBox[2] == 0) { /* zero width ind invalid */
                            fvwm_msg(ERR,"ProcessNewStyle",
                                     "IconBox requires 4 numbers or geometry! Invalid string <%s>.",
                                     geom_string);
                            free(IconBoxes);        /* Drop the box */
                            IconBoxes = 0;          /* forget about it */
                        } else {                  /* got valid iconbox geom */
                            if (geom_flags&XNegative) {
                                IconBoxes->IconBox[0] = Scr.MyDisplayWidth /* screen width */
                                                        + IconBoxes->IconBox[0] /* neg x coord */
                                                        - IconBoxes->IconBox[2] -2; /* width - 2 */
                            }
                            if (geom_flags&YNegative) {
                                IconBoxes->IconBox[1] = Scr.MyDisplayHeight /* scr height */
                                                        + IconBoxes->IconBox[1] /* neg y coord */
                                                        - IconBoxes->IconBox[3] -2; /* height - 2 */
                            }
                            IconBoxes->IconBox[2] +=
                                IconBoxes->IconBox[0]; /* x + wid = right x */
                            IconBoxes->IconBox[3] +=
                                IconBoxes->IconBox[1]; /* y + height = bottom y */
                        } /* end icon geom worked */
                    } else {                    /* no word or too long */
                        fvwm_msg(ERR,"ProcessNewStyle",
                                 "IconBox requires 4 numbers or geometry! Too long (%d).",
                                 len);
                        free(IconBoxes);          /* Drop the box */
                        IconBoxes = 0;            /* forget about it */
                    } /* end word found, not too long */
                    restofline = tmp;           /* got word, move past it */
                } /* end not 4 args */
                /* If we created an IconBox, put it in the chain. */
                if (IconBoxes != 0) {         /* If no error */
                    if (tname.IconBoxes == 0) { /* If first one */
                        tname.IconBoxes = IconBoxes; /* chain to root */
                    } else {                    /* else not first one */
                        which->next = IconBoxes;  /* add to end of chain */
                    } /* end not first one */
                    which = IconBoxes;          /* new current box. save for grid */
                } /* end no error */
            } /* end iconbox parameter */
            else if(ITIS("ICONGRID")) {
                SKIP("ICONGRID");
                SKIPSPACE;                    /* skip whitespace after keyword */
                /* The grid always affects the prior iconbox */
                if (which == 0) {             /* If no current box */
                    fvwm_msg(ERR,"ProcessNewStyle",
                             "IconGrid must follow an IconBox in same Style command");
                } else {                      /* have a place to grid */
                    num = sscanf(restofline,"%hd%hd", /* 2 shorts */
                                 &which->IconGrid[0],
                                 &which->IconGrid[1]);
                    if (num != 2
                            || which->IconGrid[0] < 1
                            || which->IconGrid[1] < 1) {
                        fvwm_msg(ERR,"ProcessNewStyle",
                                 "IconGrid needs 2 numbers > 0. Got %d numbers. x=%d y=%d!",
                                 num, (int)which->IconGrid[0], (int)which->IconGrid[1]);
                        which->IconGrid[0] = 3;   /* reset grid x */
                        which->IconGrid[1] = 3;   /* reset grid y */
                    } else {                    /* it worked */
                        GETWORD;                  /* swallow word */
                        restofline = tmp;
                        GETWORD;                  /* swallow word */
                        restofline = tmp;
                    } /* end bad grid */
                } /* end place to grid */
            } else if(ITIS("ICONFILL")) {   /* direction to fill iconbox */
                SKIP("ICONFILL");
                SKIPSPACE;                    /* skip whitespace after keyword */
                /* The fill always affects the prior iconbox */
                if (which == 0) {             /* If no current box */
                    fvwm_msg(ERR,"ProcessNewStyle",
                             "IconFill must follow an IconBox in same Style command");
                } else {                      /* have a place to fill */
                    unsigned char IconFill_1;   /* first  type direction parsed */
                    unsigned char IconFill_2;   /* second type direction parsed */
                    GETWORD;                    /* read in word for length */
                    if (Get_TBLR(restofline,&IconFill_1) == 0) { /* top/bot/lft/rgt */
                        fvwm_msg(ERR,"ProcessNewStyle",
                                 "IconFill must be followed by T|B|R|L, found %.*s.",
                                 len, restofline); /* its wrong */
                    } else {                    /* first word valid */
                        restofline = tmp;         /* swallow it */
                        SKIPSPACE;                /* skip space between words */
                        GETWORD;                  /* read in second word */
                        if (Get_TBLR(restofline,&IconFill_2) == 0) {/* top/bot/lft/rgt */
                            fvwm_msg(ERR,"ProcessNewStyle",
                                     "IconFill must be followed by T|B|R|L, found %.*s.",
                                     len, restofline); /* its wrong */
                        } else if ((IconFill_1&ICONFILLHRZ)==(IconFill_2&ICONFILLHRZ)) {
                            fvwm_msg(ERR,"ProcessNewStyle",
                                     "IconFill must specify a horizontal and vertical direction.");
                        } else {                  /* Its valid! */
                            which->IconFlags |= IconFill_1; /* merge in flags */
                            IconFill_2 &= ~ICONFILLHRZ; /* ignore horiz in 2nd arg */
                            which->IconFlags |= IconFill_2; /* merge in flags */
                        } /* end second word valid */
                    } /* end first word valid */
                    restofline = tmp;           /* swallow first or second word */
                } /* end have a place to fill */
            } /* end iconfill */
            else if(ITIS("ICON"))
            {
                SKIP("ICON");
                GETWORD;
                if(len > 0)
                {
                    tname.value = safemalloc(len+1);
                    strncpy(tname.value,restofline,len);
                    tname.value[len] = 0;
                    tname.off_flags |= ICON_FLAG;
                    tname.on_flags |= SUPPRESSICON_FLAG;
                }
                else
                    tname.on_flags |= SUPPRESSICON_FLAG;
                restofline = tmp;
            }
            break;
        case 'j':
            break;
        case 'k':
            break;
        case 'l':
            if(ITIS("LENIENCE"))
            {
                SKIP("LENIENCE");
                tname.off_flags |= LENIENCE_FLAG;
            }
            break;
        case 'm':
            if(ITIS("MWMBUTTONS"))
            {
                SKIP("MWMBUTTONS");
                tname.off_flags |= MWM_BUTTON_FLAG;
            }
#ifdef MINI_ICONS
            else if (ITIS("MINIICON"))
            {
                SKIP("MINIICON");
                GETWORD;
                if(len > 0)
                {
                    tname.mini_value = safemalloc(len+1);
                    strncpy(tname.mini_value,restofline,len);
                    tname.mini_value[len] = 0;
                    tname.off_flags |= MINIICON_FLAG;
                }
                restofline = tmp;
            }
#endif
            else if(ITIS("MWMBORDER"))
            {
                SKIP("MWMBORDER");
                tname.off_flags |= MWM_BORDER_FLAG;
            }
            else if(ITIS("MWMDECOR"))
            {
                SKIP("MWMDECOR");
                tname.off_flags |= MWM_DECOR_FLAG;
            }
            else if(ITIS("MWMFUNCTIONS"))
            {
                SKIP("MWMFUNCTIONS");
                tname.off_flags |= MWM_FUNCTIONS_FLAG;
            }
            else if(ITIS("MOUSEFOCUS"))
            {
                SKIP("MOUSEFOCUS");
                tname.on_flags |= CLICK_FOCUS_FLAG;
                tname.on_flags |= SLOPPY_FOCUS_FLAG;
            }
            break;
        case 'n':
            if(ITIS("NoIconTitle"))
            {
                SKIP("NoIconTitle");
                tname.off_flags |= NOICON_TITLE_FLAG;
            }
            else if(ITIS("NOICON"))
            {
                SKIP("NOICON");
                tname.off_flags |= SUPPRESSICON_FLAG;
            }
            else if(ITIS("NOTITLE"))
            {
                SKIP("NOTITLE");
                tname.off_flags |= NOTITLE_FLAG;
            }
            else if(ITIS("NoPPosition"))
            {
                SKIP("NoPPosition");
                tname.off_flags |= NO_PPOSITION_FLAG;
            }
            else if(ITIS("NakedTransient"))
            {
                SKIP("NakedTransient");
                tname.on_flags |= DECORATE_TRANSIENT_FLAG;
            }
            else if(ITIS("NODECORHINT"))
            {
                SKIP("NODECORHINT");
                tname.on_flags |= MWM_DECOR_FLAG;
            }
            else if(ITIS("NOFUNCHINT"))
            {
                SKIP("NOFUNCHINT");
                tname.on_flags |= MWM_FUNCTIONS_FLAG;
            }
            else if(ITIS("NOOVERRIDE"))
            {
                SKIP("NOOVERRIDE");
                tname.on_flags |= MWM_OVERRIDE_FLAG;
            }
            else if(ITIS("NOHANDLES"))
            {
                SKIP("NOHANDLES");
                tname.off_flags |= NOBORDER_FLAG;
            }
            else if(ITIS("NOLENIENCE"))
            {
                SKIP("NOLENIENCE");
                tname.on_flags |= LENIENCE_FLAG;
            }
            else if (ITIS("NOBUTTON"))
            {
                SKIP("NOBUTTON");

                butt = -1; /* just in case sscanf fails */
                sscanf(restofline,"%d",&butt);
                GETWORD;
                SKIPSPACE;

                if (butt == 0) butt = 10;
                if (butt > 0 && butt <= 10)
                    tname.off_buttons |= (1<<(butt-1));
                restofline = tmp;
            }
            else if(ITIS("NOOLDECOR"))
            {
                SKIP("NOOLDECOR");
                tname.on_flags |= OL_DECOR_FLAG;
            }
            break;
        case 'o':
            if(ITIS("OLDECOR"))
            {
                SKIP("OLDECOR");
                tname.off_flags |= OL_DECOR_FLAG;
            }
            break;
        case 'p':
            break;
        case 'q':
            break;
        case 'r':
            if(ITIS("RANDOMPLACEMENT"))
            {
                SKIP("RANDOMPLACEMENT");
                tname.off_flags |= RANDOM_PLACE_FLAG;
            }
            break;
        case 's':
            if(ITIS("SMARTPLACEMENT"))
            {
                SKIP("SMARTPLACEMENT");
                tname.off_flags |= SMART_PLACE_FLAG;
            }
            else if(ITIS("SkipMapping"))
            {
                SKIP("SkipMapping");
                tname.off_flags |= SHOW_MAPPING;
            }
            else if(ITIS("ShowMapping"))
            {
                SKIP("ShowMapping");
                tname.on_flags |= SHOW_MAPPING;
            }
            else if(ITIS("StickyIcon"))
            {
                SKIP("StickyIcon");
                tname.off_flags |= STICKY_ICON_FLAG;
            }
            else if(ITIS("SlipperyIcon"))
            {
                SKIP("SlipperyIcon");
                tname.on_flags |= STICKY_ICON_FLAG;
            }
            else if(ITIS("SLOPPYFOCUS"))
            {
                SKIP("SLOPPYFOCUS");
                tname.on_flags |= CLICK_FOCUS_FLAG;
                tname.off_flags |= SLOPPY_FOCUS_FLAG;
            }
            else if(ITIS("StartIconic"))
            {
                SKIP("StartIconic");
                tname.off_flags |= START_ICONIC_FLAG;
            }
            else if(ITIS("StartNormal"))
            {
                SKIP("StartNormal");
                tname.on_flags |= START_ICONIC_FLAG;
            }
            else if(ITIS("StaysOnTop"))
            {
                SKIP("StaysOnTop");
                tname.off_flags |= STAYSONTOP_FLAG;
            }
            else if(ITIS("StaysPut"))
            {
                SKIP("StaysPut");
                tname.on_flags |= STAYSONTOP_FLAG;
            }
            else if(ITIS("Sticky"))
            {
                tname.off_flags |= STICKY_FLAG;
                SKIP("Sticky");
            }
            else if(ITIS("Slippery"))
            {
                tname.on_flags |= STICKY_FLAG;
                SKIP("Slippery");
            }
            else if(ITIS("STARTSONDESK"))
            {
                SKIP("STARTSONDESK");
                tname.off_flags |= STARTSONDESK_FLAG;
                /*  RBW - 11/02/1998  */
                spargs = sscanf(restofline,"%d",&tmpno1);
                if (spargs == 1)
                {
                    /*  RBW - 11/20/1998 - allow for the special case of -1  */
                    tname.Desk = (tmpno1 > -1) ? tmpno1 + 1 : tmpno1;
                }
                else
                {
                    tname.off_flags &= ~STARTSONDESK_FLAG;
                    fvwm_msg(ERR,"ProcessNewStyle",
                             "bad StartsOnDesk arg: %s", restofline);
                }
                /**/
                GETWORD;
                restofline = tmp;
                SKIPSPACE;
            }
            /*  RBW - 11/02/1998
                StartsOnPage is like StartsOnDesk-Plus
            */
            else if(ITIS("STARTSONPAGE"))
            {
                SKIP("STARTSONPAGE");
                tname.off_flags |= STARTSONDESK_FLAG;
                spargs = sscanf(restofline,"%d %d %d", &tmpno1, &tmpno2, &tmpno3);

                if (spargs == 1 || spargs == 3)
                {
                    /*  We have a desk no., with or without page.  */
                    /*  RBW - 11/20/1998 - allow for the special case of -1  */
                    tname.Desk = (tmpno1 > -1) ? tmpno1 + 1 : tmpno1;  /*  Desk is now actual + 1  */
                    /*  Bump past desk no.    */
                    GETWORD;
                    restofline = tmp;
                    SKIPSPACE;
                }

                if (spargs == 2 || spargs == 3)
                {
                    if (spargs == 3)
                    {
                        /*  RBW - 11/20/1998 - allow for the special case of -1  */
                        tname.PageX = (tmpno2 > -1) ? tmpno2 + 1 : tmpno2;
                        tname.PageY = (tmpno3 > -1) ? tmpno3 + 1 : tmpno3;
                    }
                    else
                    {
                        tname.PageX       =  (tmpno1 > -1) ? tmpno1 + 1 : tmpno1;
                        tname.PageY       =  (tmpno2 > -1) ? tmpno2 + 1 : tmpno2;
                    }
                    /*  Bump past next 2 args.    */
                    GETWORD;
                    restofline = tmp;
                    SKIPSPACE;
                    GETWORD;
                    restofline = tmp;
                    SKIPSPACE;

                }
                if (spargs < 1 || spargs > 3)
                {
                    tname.off_flags &= ~STARTSONDESK_FLAG;
                    fvwm_msg(ERR,"ProcessNewStyle",
                             "bad StartsOnPage args: %s", restofline);
                }

            }
            /**/
            else if(ITIS("STARTSANYWHERE"))
            {
                SKIP("STARTSANYWHERE");
                tname.on_flags |= STARTSONDESK_FLAG;
            }
            break;
        case 't':
            if(ITIS("TITLE"))
            {
                SKIP("TITLE");
                tname.on_flags |= NOTITLE_FLAG;
            }
            break;
        case 'u':
            if(ITIS("UsePPosition"))
            {
                SKIP("UsePPosition");
                tname.on_flags |= NO_PPOSITION_FLAG;
            }
#ifdef USEDECOR
            if(ITIS("UseDecor"))
            {
                SKIP("UseDecor");
                GETQUOTEDWORD;
                if (len > 0)
                {
                    tname.Decor = safemalloc(len+1);
                    strncpy(tname.Decor,restofline,len);
                    tname.Decor[len] = 0;
                }
                restofline = tmp;
            }
#endif
            else if(ITIS("UseStyle"))
            {
                SKIP("UseStyle");
                GETQUOTEDWORD;
                if (len > 0) {
                    int hit = 0;
                    /* changed to accum multiple Style definitions ([email protected]) */
                    for ( nptr = Scr.TheList; nptr; nptr = nptr->next ) {
                        if (!strncasecmp(restofline,nptr->name,len)) { /* match style */
                            if (!hit) {             /* first match */
                                char *save_name;
                                save_name = tname.name;
                                memcpy((void*)&tname, (const void*)nptr, sizeof(name_list)); /* copy everything */
                                tname.next = 0;       /* except the next pointer */
                                tname.name = save_name; /* and the name */
                                hit = 1;              /* set not first match */
                            } else {                /* subsequent match */
                                tname.off_flags     |= nptr->off_flags;
                                tname.on_flags      &= ~(nptr->on_flags);
                                tname.off_buttons   |= nptr->off_buttons;
                                tname.on_buttons    &= ~(nptr->on_buttons);
                                if(nptr->value) tname.value = nptr->value;
#ifdef MINI_ICONS
                                if(nptr->mini_value) tname.mini_value = nptr->mini_value;
#endif
#ifdef USEDECOR
                                if(nptr->Decor) tname.Decor = nptr->Decor;
#endif
                                if(nptr->off_flags & STARTSONDESK_FLAG)
                                    /*  RBW - 11/02/1998  */
                                {
                                    tname.Desk = nptr->Desk;
                                    tname.PageX = nptr->PageX;
                                    tname.PageY = nptr->PageY;
                                }
                                /**/
                                if(nptr->off_flags & BW_FLAG)
                                    tname.border_width = nptr->border_width;
                                if(nptr->off_flags & NOBW_FLAG)
                                    tname.resize_width = nptr->resize_width;
                                if(nptr->off_flags & FORE_COLOR_FLAG)
                                    tname.ForeColor = nptr->ForeColor;
                                if(nptr->off_flags & BACK_COLOR_FLAG)
                                    tname.BackColor = nptr->BackColor;
                                tname.IconBoxes = nptr->IconBoxes; /* use same chain */
                            } /* end hit/not hit */
                        } /* end found matching style */
                    } /* end looking at all styles */
                    restofline = tmp;           /* move forward one word */
                    if (!hit) {
                        tmp=safemalloc(500);
                        strlcat(tmp,"UseStyle: ", 500);
                        strlcat(tmp,restofline-len,500);
                        strlcat(tmp," style not found!",500);
                        fvwm_msg(ERR,"ProcessNewStyle",tmp);
                        free(tmp);
                    }
                }
                while(isspace(*restofline)) restofline++;
            }
            break;
        case 'v':
            break;
        case 'w':
            if(ITIS("WindowListSkip"))
            {
                SKIP("WindowListSkip");
                tname.off_flags |= LISTSKIP_FLAG;
            }
            else if(ITIS("WindowListHit"))
            {
                SKIP("WindowListHit");
                tname.on_flags |= LISTSKIP_FLAG;
            }
            break;
        case 'x':
            break;
        case 'y':
            break;
        case 'z':
            break;
        default:
            break;
        }

        SKIPSPACE;
        if(*restofline == ',')
            restofline++;
        else if((*restofline != 0)&&(*restofline != '\n'))
        {
            fvwm_msg(ERR,"ProcessNewStyle",
                     "bad style command: %s", restofline);
            /* Can't return here since all malloced memory will be lost. Ignore rest
             * of line instead. */
            break;
        }
    } /* end while still stuff on command */

    /* capture default icons */
    if(strcmp(tname.name,"*") == 0)
    {
        if(tname.off_flags & ICON_FLAG)
            Scr.DefaultIcon = tname.value;
        tname.off_flags &= ~ICON_FLAG;
        tname.value = NULL;
    }
    AddToList(&tname);                /* add temp name list to list */
}
Пример #16
0
/*
 * Change by PRB ([email protected]), 31/10/93.  Prepend a hot key
 * specifier to each item in the list.  This means allocating the
 * memory for each item (& freeing it) rather than just using the window
 * title directly. */
void do_windowList(XEvent *eventp,Window w,FvwmWindow *tmp_win,
		unsigned long context, char *action,int *Module)
{
  MenuRoot *mr;
  MenuItem *miExecuteAction;
  FvwmWindow *t;
  FvwmWindow **windowList;
  int numWindows;
  int ii;
  char tname[80] = "";
  char loc[40],*name=NULL;
  int dwidth,dheight;
  char tlabel[50]="";
  int last_desk_done = INT_MIN;
  int last_desk_displayed = INT_MIN;
  int next_desk = 0;
  char *t_hot=NULL;		/* Menu label with hotkey added */
  char scut = '0';		/* Current short cut key */
  char *line=NULL,*tok=NULL;
  int desk = Scr.CurrentDesk;
  int flags = SHOW_EVERYTHING;
  char *func=NULL;
  char *tfunc=NULL;
  char *default_action = NULL;
  MenuStatus menu_retval;
  XEvent *teventp;
  MenuOptions mops;
  size_t hotlen;

  mops.flags.allflags = 0;
  if (action && *action)
  {
    /* parse postitioning args */
    action = GetMenuOptions(action,w,tmp_win,NULL,&mops);
    line = action;
    /* parse options */
    while (line && *line)
    {
      line = GetNextOption(line, &tok);
      if (!tok)
	break;

      if (StrEquals(tok,"Function"))
      {
        line = GetNextOption(line, &func);
      }
      else if (StrEquals(tok,"Desk"))
      {
	free(tok);
        line = GetNextOption(line, &tok);
	if (tok)
	{
	  desk = atoi(tok);
	  flags &= ~SHOW_ALLDESKS;
	}
      }
      else if (StrEquals(tok,"CurrentDesk"))
      {
        desk = Scr.CurrentDesk;
        flags &= ~SHOW_ALLDESKS;
      }
      else if (StrEquals(tok,"NotAlphabetic"))
        flags &= ~SHOW_ALPHABETIC;
      else if (StrEquals(tok,"Alphabetic"))
        flags |= SHOW_ALPHABETIC;
      else if (StrEquals(tok,"NoDeskSort"))
        flags |= NO_DESK_SORT;
      else if (StrEquals(tok,"UseIconName"))
        flags |= SHOW_ICONNAME;
      else if (StrEquals(tok,"NoGeometry"))
        flags &= ~SHOW_GEOMETRY;
      else if (StrEquals(tok,"Geometry"))
        flags |= SHOW_GEOMETRY;
      else if (StrEquals(tok,"NoIcons"))
        flags &= ~SHOW_ICONIC;
      else if (StrEquals(tok,"Icons"))
        flags |= SHOW_ICONIC;
      else if (StrEquals(tok,"OnlyIcons"))
        flags = SHOW_ICONIC;
      else if (StrEquals(tok,"NoNormal"))
        flags &= ~SHOW_NORMAL;
      else if (StrEquals(tok,"Normal"))
        flags |= SHOW_NORMAL;
      else if (StrEquals(tok,"OnlyNormal"))
        flags = SHOW_NORMAL;
      else if (StrEquals(tok,"NoSticky"))
        flags &= ~SHOW_STICKY;
      else if (StrEquals(tok,"Sticky"))
        flags |= SHOW_STICKY;
      else if (StrEquals(tok,"OnlySticky"))
        flags = SHOW_STICKY;
      else if (StrEquals(tok,"NoOnTop"))
        flags &= ~SHOW_ONTOP;
      else if (StrEquals(tok,"OnTop"))
        flags |= SHOW_ONTOP;
      else if (StrEquals(tok,"OnlyOnTop"))
        flags = SHOW_ONTOP;
      else if (!line || !*line)
	default_action = strdup(tok);
      else
      {
        fvwm_msg(ERR,"WindowList","Unknown option '%s'",tok);
      }
      if (tok)
        free(tok);
    }
  }

  globalFlags = flags;
  if (flags & SHOW_GEOMETRY)
  {
    snprintf(tlabel,sizeof(tlabel),"Desk: %d\tGeometry",desk);
  }
  else
  {
    snprintf(tlabel,sizeof(tlabel),"Desk: %d",desk);
  }
  mr=NewMenuRoot(tlabel, False);
  AddToMenu(mr, tlabel, "TITLE", FALSE, FALSE);

  numWindows = 0;
  for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
  {
    numWindows++;
  }
  windowList = malloc(numWindows*sizeof(t));
  if (windowList == NULL)
  {
    return;
  }
  /* get the windowlist starting from the current window (if any)*/
  if ((t = Scr.Focus) == NULL) t = Scr.FvwmRoot.next;
  for (ii = 0; ii < numWindows; ii++)
  {
    windowList[ii] = t;
    if (t->next)
      t = t->next;
    else
      t = Scr.FvwmRoot.next;
  }

  /* Do alphabetic sort */
  if (flags & SHOW_ALPHABETIC)
    qsort(windowList,numWindows,sizeof(t),
	  (int(*)(const void*,const void*))winCompare);

  while(next_desk != INT_MAX)
  {
    /* Sort window list by desktop number */
    if((flags & SHOW_ALLDESKS) && !(flags & NO_DESK_SORT))
    {
      /* run through the windowlist finding the first desk not already processed */
      next_desk = INT_MAX;
      for (ii = 0; ii < numWindows; ii++)
      {
        t = windowList[ii];
        if((t->Desk >last_desk_done)&&(t->Desk < next_desk))
          next_desk = t->Desk;
      }
    }
    if(!(flags & SHOW_ALLDESKS))
    {
      /* if only doing one desk and it hasn't been done */
      if(last_desk_done  == INT_MIN)
        next_desk = desk; /* select the desk */
      else
        next_desk = INT_MAX; /* flag completion */
    }
    if(flags & NO_DESK_SORT)
      next_desk = INT_MAX; /* only go through loop once */

    last_desk_done = next_desk;
    for (ii = 0; ii < numWindows; ii++)
    {
      t = windowList[ii];
      if(((t->Desk == next_desk) || (flags & NO_DESK_SORT)) &&
         (!(t->flags & WINDOWLISTSKIP)))
      {
        if (!(flags & SHOW_ICONIC) && (t->flags & ICONIFIED))
          continue; /* don't want icons - skip */
        if (!(flags & SHOW_STICKY) && (t->flags & STICKY))
          continue; /* don't want sticky ones - skip */
        if (!(flags & SHOW_ONTOP) && (t->flags & ONTOP))
          continue; /* don't want ontop ones - skip */
        if (!(flags & SHOW_NORMAL) &&
            !((t->flags & ICONIFIED) ||
              (t->flags & STICKY) ||
              (t->flags & ONTOP)))
          continue; /* don't want "normal" ones - skip */

        /* put a seperator between desks, but not at the top */
        if (t->Desk != last_desk_displayed)
        {
          if (last_desk_displayed != INT_MIN)
            AddToMenu(mr, NULL, NULL, FALSE, FALSE);
          last_desk_displayed = t->Desk;
        }

        if(flags & SHOW_ICONNAME)
          name = t->icon_name;
        else
          name = t->name;
	hotlen = strlen(name) + strlen(tname) + 48;
        t_hot = safemalloc(hotlen);
        snprintf(t_hot, hotlen, "&%c.  %s", scut, name); /* Generate label */
        if (scut++ == '9') scut = 'A';	/* Next shortcut key */

        if (flags & SHOW_GEOMETRY)
        {
          tname[0]=0;
          if(t->flags & ICONIFIED)
	    strlcpy(tname, "(", sizeof(tname));
          snprintf(loc, sizeof(loc), "%d:",t->Desk);
          strlcat(tname, loc, sizeof(tname));

          dheight = t->frame_height - t->title_height - 2*t->boundary_width;
          dwidth = t->frame_width - 2*t->boundary_width;

          dwidth -= t->hints.base_width;
          dheight -= t->hints.base_height;

          dwidth /= t->hints.width_inc;
          dheight /= t->hints.height_inc;

          snprintf(loc, sizeof(loc), "%d", dwidth);
          strlcat(tname, loc,sizeof(tname));
          snprintf(loc, sizeof(loc), "x%d", dheight);
          strlcat(tname, loc,sizeof(tname));
          if(t->frame_x >=0)
	    snprintf(loc, sizeof(loc), "+%d", t->frame_x);
          else
	    snprintf(loc, sizeof(loc), "%d", t->frame_x);
          strlcat(tname, loc, sizeof(tname));
          if(t->frame_y >=0)
	    snprintf(loc, sizeof(loc), "+%d", t->frame_y);
          else
	    snprintf(loc, sizeof(loc), "%d", t->frame_y);
          strlcat(tname, loc, sizeof(tname));

          if (t->flags & STICKY)
	    strlcat(tname, " S", sizeof(tname));
          if (t->flags & ONTOP)
	    strlcat(tname, " T", sizeof(tname));
          if (t->flags & ICONIFIED)
	    strlcat(tname, ")", sizeof(tname));
          strlcat(t_hot,"\t",hotlen);
          strlcat(t_hot,tname,hotlen);
        }
        if (!func)
        {
          tfunc = safemalloc(40);
          snprintf(tfunc,40,"WindowListFunc %ld",t->w);
        }
        else
	{
	  size_t funclen = strlen(func) + 32;
          tfunc = safemalloc(funclen);
          snprintf(tfunc,funclen,"%s %ld",func,t->w);
	  free(func);
	  func = NULL;
	}
        AddToMenu(mr, t_hot, tfunc, FALSE, FALSE);
        free(tfunc);
#ifdef MINI_ICONS
        /* Add the title pixmap */
        if (t->mini_icon) {
          mr->last->lpicture = t->mini_icon;
          t->mini_icon->count++; /* increase the cache count!!
                                    otherwise the pixmap will be
                                    eventually removed from the
                                    cache by DestroyMenu */
        }
#endif
        if (t_hot)
          free(t_hot);
      }
    }
  }

  if (func)
    free(func);
  free(windowList);
  MakeMenu(mr);
  if (!default_action && eventp && eventp->type == KeyPress)
    teventp = (XEvent *)1;
  else
    teventp = eventp;
  menu_retval = do_menu(mr, NULL, &miExecuteAction, 0, TRUE, teventp, &mops);
  DestroyMenu(mr);
  if (menu_retval == MENU_DOUBLE_CLICKED && default_action && *default_action)
    ExecuteFunction(default_action,tmp_win,eventp,context,*Module);
  if (default_action != NULL)
    free(default_action);
}
Пример #17
0
static void execute_complex_function(
	cond_rc_t *cond_rc, const exec_context_t *exc, char *action,
	Bool *desperate, Bool has_ref_window_moved)
{
	cond_rc_t tmp_rc;
	cfunc_action_t type = CF_MOTION;
	char c;
	FunctionItem *fi;
	Bool Persist = False;
	Bool HaveDoubleClick = False;
	Bool HaveHold = False;
	Bool NeedsTarget = False;
	Bool ImmediateNeedsTarget = False;
	int do_allow_unmanaged = FUNC_ALLOW_UNMANAGED;
	int do_allow_unmanaged_immediate = FUNC_ALLOW_UNMANAGED;
	char *arguments[11], *taction;
	char *func_name;
	int x, y ,i;
	XEvent d;
	FvwmFunction *func;
	static int depth = 0;
	const exec_context_t *exc2;
	exec_context_changes_t ecc;
	exec_context_change_mask_t mask;
	int trigger_evtype;
	int button;
	XEvent *te;

	if (cond_rc == NULL)
	{
		condrc_init(&tmp_rc);
		cond_rc = &tmp_rc;
	}
	cond_rc->rc = COND_RC_OK;
	mask = 0;
	d.type = 0;
	ecc.w.fw = exc->w.fw;
	ecc.w.w = exc->w.w;
	ecc.w.wcontext = exc->w.wcontext;
	/* find_complex_function expects a token, not just a quoted string */
	func_name = PeekToken(action, &taction);
	if (!func_name)
	{
		return;
	}
	func = find_complex_function(func_name);
	if (func == NULL)
	{
		if (*desperate == 0)
		{
			fvwm_msg(
				ERR, "ComplexFunction", "No such function %s",
				action);
		}
		return;
	}
	if (!depth)
	{
		Scr.flags.is_executing_complex_function = 1;
	}
	depth++;
	*desperate = 0;
	/* duplicate the whole argument list for use as '$*' */
	if (taction)
	{
		arguments[0] = safestrdup(taction);
		/* strip trailing newline */
		if (arguments[0][0])
		{
			int l= strlen(arguments[0]);

			if (arguments[0][l - 1] == '\n')
			{
				arguments[0][l - 1] = 0;
			}
		}
		/* Get the argument list */
		for (i = 1; i < 11; i++)
		{
			taction = GetNextToken(taction, &arguments[i]);
		}
	}
	else
	{
		for (i = 0; i < 11; i++)
		{
			arguments[i] = NULL;
		}
	}
	/* In case we want to perform an action on a button press, we
	 * need to fool other routines */
	te = exc->x.elast;
	if (te->type == ButtonPress)
	{
		trigger_evtype = ButtonRelease;
	}
	else
	{
		trigger_evtype = te->type;
	}
	func->use_depth++;

	for (fi = func->first_item; fi != NULL; fi = fi->next_item)
	{
		if (fi->flags & FUNC_NEEDS_WINDOW)
		{
			NeedsTarget = True;
			do_allow_unmanaged &= fi->flags;
			if (fi->condition == CF_IMMEDIATE)
			{
				do_allow_unmanaged_immediate &= fi->flags;
				ImmediateNeedsTarget = True;
				break;
			}
		}
	}

	if (ImmediateNeedsTarget)
	{
		if (DeferExecution(
			    &ecc, &mask, CRS_SELECT, trigger_evtype,
			    do_allow_unmanaged_immediate))
		{
			func->use_depth--;
			__cf_cleanup(&depth, arguments, cond_rc);
			return;
		}
		NeedsTarget = False;
	}
	else
	{
		ecc.w.w = (ecc.w.fw) ? FW_W_FRAME(ecc.w.fw) : None;
		mask |= ECC_W;
	}

	/* we have to grab buttons before executing immediate actions because
	 * these actions can move the window away from the pointer so that a
	 * button release would go to the application below. */
	if (!GrabEm(CRS_NONE, GRAB_NORMAL))
	{
		func->use_depth--;
		fvwm_msg(
			ERR,
			"ComplexFunction", "Grab failed in function %s,"
			" unable to execute immediate action", action);
		__cf_cleanup(&depth, arguments, cond_rc);
		return;
	}
	exc2 = exc_clone_context(exc, &ecc, mask);
	__run_complex_function_items(
		cond_rc, CF_IMMEDIATE, func, exc2, arguments,
		has_ref_window_moved);
	exc_destroy_context(exc2);
	for (fi = func->first_item;
	     fi != NULL && cond_rc->break_levels == 0;
	     fi = fi->next_item)
	{
		/* c is already lowercase here */
		c = fi->condition;
		switch (c)
		{
		case CF_IMMEDIATE:
			break;
		case CF_DOUBLE_CLICK:
			HaveDoubleClick = True;
			Persist = True;
			break;
		case CF_HOLD:
			HaveHold = True;
			Persist = True;
			break;
		default:
			Persist = True;
			break;
		}
	}

	if (!Persist || cond_rc->break_levels != 0)
	{
		func->use_depth--;
		__cf_cleanup(&depth, arguments, cond_rc);
		UngrabEm(GRAB_NORMAL);
		return;
	}

	/* Only defer execution if there is a possibility of needing
	 * a window to operate on */
	if (NeedsTarget)
	{
		if (DeferExecution(
			    &ecc, &mask, CRS_SELECT, trigger_evtype,
			    do_allow_unmanaged))
		{
			func->use_depth--;
			__cf_cleanup(&depth, arguments, cond_rc);
			UngrabEm(GRAB_NORMAL);
			return;
		}
	}

	te = (mask & ECC_ETRIGGER) ? ecc.x.etrigger : exc->x.elast;
	switch (te->xany.type)
	{
	case ButtonPress:
	case ButtonRelease:
		x = te->xbutton.x_root;
		y = te->xbutton.y_root;
		button = te->xbutton.button;
		/* Take the click which started this fuction off the
		 * Event queue.  -DDN- Dan D Niles [email protected] */
		FCheckMaskEvent(dpy, ButtonPressMask, &d);
		break;
	default:
		if (FQueryPointer(
			    dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y,
			    &JunkX, &JunkY, &JunkMask) == False)
		{
			/* pointer is on a different screen */
			x = 0;
			y = 0;
		}
		button = 0;
		break;
	}

	/* Wait and see if we have a click, or a move */
	/* wait forever, see if the user releases the button */
	type = CheckActionType(x, y, &d, HaveHold, True, &button);
	if (type == CF_CLICK)
	{
		int button2;

		/* If it was a click, wait to see if its a double click */
		if (HaveDoubleClick)
		{
			type = CheckActionType(
				x, y, &d, True, False, &button2);
			switch (type)
			{
			case CF_HOLD:
			case CF_MOTION:
			case CF_CLICK:
				if (button == button2)
				{
					type = CF_DOUBLE_CLICK;
				}
				else
				{
					type = CF_CLICK;
				}
				break;
			case CF_TIMEOUT:
				type = CF_CLICK;
				break;
			default:
				/* can't happen */
				break;
			}
		}
	}
	else if (type == CF_TIMEOUT)
	{
		type = CF_HOLD;
	}

	/* some functions operate on button release instead of presses. These
	 * gets really weird for complex functions ... */
	if (d.type == ButtonPress)
	{
		d.type = ButtonRelease;
		if (d.xbutton.button > 0 &&
		    d.xbutton.button <= NUMBER_OF_MOUSE_BUTTONS)
		{
			d.xbutton.state &=
				(~(Button1Mask >> (d.xbutton.button - 1)));
		}
Пример #18
0
static void __execute_function(
	cond_rc_t *cond_rc, const exec_context_t *exc, char *action,
	FUNC_FLAGS_TYPE exec_flags, char *args[], Bool has_ref_window_moved)
{
	static int func_depth = 0;
	cond_rc_t *func_rc = NULL;
	cond_rc_t dummy_rc;
	Window w;
	int j;
	char *function;
	char *taction;
	char *trash;
	char *trash2;
	char *expaction = NULL;
	char *arguments[11];
	const func_t *bif;
	Bool set_silent;
	Bool must_free_string = False;
	Bool must_free_function = False;
	Bool do_keep_rc = False;
	/* needed to be able to avoid resize to use moved windows for base */
	extern Window PressedW;
	Window dummy_w;

	if (!action)
	{
		return;
	}
	/* ignore whitespace at the beginning of all config lines */
	action = SkipSpaces(action, NULL, 0);
	if (!action || action[0] == 0)
	{
		/* impossibly short command */
		return;
	}
	if (action[0] == '#')
	{
		/* a comment */
		return;
	}

	func_depth++;
	if (func_depth > MAX_FUNCTION_DEPTH)
	{
		fvwm_msg(
			ERR, "__execute_function",
			"Function '%s' called with a depth of %i, "
			"stopping function execution!",
			action, func_depth);
		func_depth--;
		return;
	}
	if (args)
	{
		for (j = 0; j < 11; j++)
		{
			arguments[j] = args[j];
		}
	}
	else
	{
		for (j = 0; j < 11; j++)
		{
			arguments[j] = NULL;
		}
	}

	if (exc->w.fw == NULL || IS_EWMH_DESKTOP(FW_W(exc->w.fw)))
	{
		if (exec_flags & FUNC_IS_UNMANAGED)
		{
			w = exc->w.w;
		}
		else
		{
			w = Scr.Root;
		}
	}
	else
	{
		FvwmWindow *tw;

		w = GetSubwindowFromEvent(dpy, exc->x.elast);
		if (w == None)
		{
			w = exc->x.elast->xany.window;
		}
		tw = NULL;
		if (w != None)
		{
			if (XFindContext(
				 dpy, w, FvwmContext, (caddr_t *)&tw) ==
			    XCNOENT)
			{
				tw = NULL;
			}
		}
		if (w == None || tw != exc->w.fw)
		{
			w = FW_W(exc->w.fw);
		}
	}

	set_silent = False;
	if (action[0] == '-')
	{
		exec_flags |= FUNC_DONT_EXPAND_COMMAND;
		action++;
	}

	taction = action;
	/* parse prefixes */
	trash = PeekToken(taction, &trash2);
	while (trash)
	{
		if (StrEquals(trash, PRE_SILENT))
		{
			if (Scr.flags.are_functions_silent == 0)
			{
				set_silent = 1;
				Scr.flags.are_functions_silent = 1;
			}
			taction = trash2;
			trash = PeekToken(taction, &trash2);
		}
		else if (StrEquals(trash, PRE_KEEPRC))
		{
			do_keep_rc = True;
			taction = trash2;
			trash = PeekToken(taction, &trash2);
		}
		else
		{
			break;
		}
	}
	if (taction == NULL)
	{
		if (set_silent)
		{
			Scr.flags.are_functions_silent = 0;
		}
		func_depth--;
		return;
	}
	if (cond_rc == NULL || do_keep_rc == True)
	{
		condrc_init(&dummy_rc);
		func_rc = &dummy_rc;
	}
	else
	{
		func_rc = cond_rc;
	}

	GetNextToken(taction, &function);
	if (function)
	{
		char *tmp = function;
		function = expand_vars(
			function, arguments, False, False, func_rc, exc);
		free(tmp);
	}
	if (function && function[0] != '*')
	{
#if 1
		/* DV: with this piece of code it is impossible to have a
		 * complex function with embedded whitespace that begins with a
		 * builtin function name, e.g. a function "echo hello". */
		/* DV: ... and without it some of the complex functions will
		 * fail */
		char *tmp = function;

		while (*tmp && !isspace(*tmp))
		{
			tmp++;
		}
		*tmp = 0;
#endif
		bif = find_builtin_function(function);
		must_free_function = True;
	}
	else
	{
		bif = NULL;
		if (function)
		{
			free(function);
		}
		function = "";
	}

	if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor &&
	    (!bif || !(bif->flags & FUNC_DECOR)))
	{
		fvwm_msg(
			ERR, "__execute_function",
			"Command can not be added to a decor; executing"
			" command now: '%s'", action);
	}

	if (!(exec_flags & FUNC_DONT_EXPAND_COMMAND))
	{
		expaction = expand_vars(
			taction, arguments, (bif) ?
			!!(bif->flags & FUNC_ADD_TO) :
			False, (taction[0] == '*'), func_rc, exc);
		if (func_depth <= 1)
		{
			must_free_string = set_repeat_data(
				expaction, REPEAT_COMMAND, bif);
		}
		else
		{
			must_free_string = True;
		}
	}
	else
	{
		expaction = taction;
	}

#ifdef FVWM_COMMAND_LOG
	fvwm_msg(INFO, "LOG", "%c: %s", (char)exc->type, expaction);
#endif

	/* Note: the module config command, "*" can not be handled by the
	 * regular command table because there is no required white space after
	 * the asterisk. */
	if (expaction[0] == '*')
	{
		if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor)
		{
			fvwm_msg(
				WARN, "__execute_function",
				"Command can not be added to a decor;"
				" executing command now: '%s'", expaction);
		}

		/* process a module config command */
		ModuleConfig(expaction);
	}
	else
	{
		const exec_context_t *exc2;
		exec_context_changes_t ecc;
		exec_context_change_mask_t mask;

		mask = (w != exc->w.w) ? ECC_W : 0;
		ecc.w.fw = exc->w.fw;
		ecc.w.w = w;
		ecc.w.wcontext = exc->w.wcontext;
		if (bif && bif->func_t != F_FUNCTION)
		{
			char *runaction;
			Bool rc = False;

			runaction = SkipNTokens(expaction, 1);
			if ((bif->flags & FUNC_NEEDS_WINDOW) &&
			    !(exec_flags & FUNC_DONT_DEFER))
			{
				rc = DeferExecution(
					&ecc, &mask, bif->cursor,
					exc->x.elast->type,
					(bif->flags & FUNC_ALLOW_UNMANAGED));
			}
			else if ((bif->flags & FUNC_NEEDS_WINDOW) &&
				 !__context_has_window(
					 exc,
					 bif->flags & FUNC_ALLOW_UNMANAGED))
			{
				/* no context window and not allowed to defer,
				 * skip command */
				rc = True;
			}
			if (rc == False)
			{
				exc2 = exc_clone_context(exc, &ecc, mask);
				if (has_ref_window_moved &&
				    (bif->func_t == F_ANIMATED_MOVE ||
				     bif->func_t == F_MOVE ||
				     bif->func_t == F_RESIZE ||
				     bif->func_t == F_RESIZEMOVE ||
				     bif->func_t == F_RESIZE_MAXIMIZE ||
				     bif->func_t == F_RESIZEMOVE_MAXIMIZE))
				{
					dummy_w = PressedW;
					PressedW = None;
					bif->action(func_rc, exc2, runaction);
					PressedW = dummy_w;
				}
				else
				{
					bif->action(func_rc, exc2, runaction);
				}
				exc_destroy_context(exc2);
			}
		}
		else
		{
			Bool desperate = 1;
			char *runaction;

			if (bif)
			{
				/* strip "function" command */
				runaction = SkipNTokens(expaction, 1);
			}
			else
			{
				runaction = expaction;
			}
			exc2 = exc_clone_context(exc, &ecc, mask);
			execute_complex_function(
				func_rc, exc2, runaction, &desperate,
				has_ref_window_moved);
			if (!bif && desperate)
			{
				if (executeModuleDesperate(
					    func_rc, exc, runaction) == NULL &&
				    *function != 0 && !set_silent)
				{
					fvwm_msg(
						ERR, "__execute_function",
						"No such command '%s'",
						function);
				}
			}
			exc_destroy_context(exc2);
		}
	}

	if (set_silent)
	{
		Scr.flags.are_functions_silent = 0;
	}
	if (cond_rc != NULL)
	{
		cond_rc->break_levels = func_rc->break_levels;
	}
	if (must_free_string)
	{
		free(expaction);
	}
	if (must_free_function)
	{
		free(function);
	}
	func_depth--;

	return;
}
Пример #19
0
void executeModule(XEvent * eventp, Window w, FvwmWindow * tmp_win,
		   unsigned long context, char *action, int *Module)
{
  int fvwm_to_app[2], app_to_fvwm[2];
  int i, val, nargs = 0;
  char *cptr;
  char *args[20];
  char *arg1 = NULL;
  char arg2[20];
  char arg3[20];
  char arg5[20];
  char arg6[20];
  extern char *ModulePath;
  extern char *fvwm_file;
  Window win;

  if (eventp->type != KeyPress)
    UngrabEm();

  if (action == NULL)
    return;

  if (tmp_win)
    win = tmp_win->w;
  else
    win = None;

  /* If we execute a module, don't wait for buttons to come up,
   * that way, a pop-up menu could be implemented */
  *Module = 0;

  action = GetNextToken(action, &cptr);

  arg1 = findIconFile(cptr, ModulePath, X_OK);
  if (arg1 == NULL) {
    if (cptr != NULL) {
      fvwm_msg(ERR, "executeModule",
	       "No such module %s%s", ModulePath, cptr);

      free(cptr);
    }
    return;
  }

  /* Look for an available pipe slot */
  for (i = 0; (i < npipes) && (writePipes[i] >= 0); ++i);

  if (i >= npipes) {
    fvwm_msg(ERR, "executeModule", "Too many Accessories!");
    if (cptr != NULL)
      free(cptr);
    return;
  }

  /* I want one-ended pipes, so I open two two-ended pipes,
   * and close one end of each. I need one ended pipes so that
   * I can detect when the module crashes/malfunctions */
  if (pipe(fvwm_to_app) != 0) {
    fvwm_msg(ERR, "executeModule", "Failed to open pipe");
    return;
  }
  if (pipe(app_to_fvwm) != 0) {
    fvwm_msg(ERR, "executeModule", "Failed to open pipe2");
    if (cptr != NULL)
      free(cptr);
    close(fvwm_to_app[0]);
    close(fvwm_to_app[1]);
    return;
  }

  pipeName[i] = stripcpy(cptr);
  sprintf(arg2, "%d", app_to_fvwm[1]);
  sprintf(arg3, "%d", fvwm_to_app[0]);
  sprintf(arg5, "%lx", (unsigned long) win);
  sprintf(arg6, "%lx", (unsigned long) context);
  args[0] = arg1;
  args[1] = arg2;
  args[2] = arg3;
  if (fvwm_file != NULL)
    args[3] = fvwm_file;
  else
    args[3] = "none";
  args[4] = arg5;
  args[5] = arg6;
  nargs = 6;
  while ((action != NULL) && (nargs < 20) && (strlen(args[nargs - 1]) > 0)) {
    args[nargs] = 0;
    action = GetNextToken(action, &args[nargs]);
    nargs++;
  }
  if (strlen(args[nargs - 1]) <= 0) {
    nargs--;
    if (args[nargs] != NULL)
      free(args[nargs]);
  }
  args[nargs] = 0;

  /* Try vfork instead of fork. The man page says that vfork is better! */
  /* Also, had to change exit to _exit() */
  /* Not everyone has vfork! */
  val = fork();
  if (val > 0) {
    /* This fork remains running fvwm */
    /* close appropriate descriptors from each pipe so
     * that fvwm will be able to tell when the app dies */
    close(app_to_fvwm[1]);
    close(fvwm_to_app[0]);

    /* add these pipes to fvwm's active pipe list */
    writePipes[i] = fvwm_to_app[1];
    readPipes[i] = app_to_fvwm[0];
    pipeOn[i] = -1;
    PipeMask[i] = MAX_MASK;
    free(arg1);
    pipeQueue[i] = NULL;

    /* make the PositiveWrite pipe non-blocking. Don't want to jam up
       fvwm because of an uncooperative module */
    fcntl(writePipes[i], F_SETFL, O_NDELAY);
    /* Mark the pipes close-on exec so other programs
     * won`t inherit them */
    if (fcntl(readPipes[i], F_SETFD, 1) == -1)
      fvwm_msg(ERR, "executeModule", "module close-on-exec failed");
    if (fcntl(writePipes[i], F_SETFD, 1) == -1)
      fvwm_msg(ERR, "executeModule", "module close-on-exec failed");
    for (i = 6; i < nargs; i++) {
      if (args[i] != 0)
	free(args[i]);
    }

    if (cptr != NULL)
      free(cptr);
  } else if (val == 0) {
    /* this is  the child */
    /* this fork execs the module */
    close(fvwm_to_app[1]);
    close(app_to_fvwm[0]);

    execvp(arg1, args);
    fvwm_msg(ERR, "executeModule", "Execution of module failed: %s", arg1);
    perror("");
    close(app_to_fvwm[1]);
    close(fvwm_to_app[0]);
    exit(1);
  } else {
    fvwm_msg(ERR, "executeModule", "Fork failed");
    free(arg1);
  }
  return;
}
Пример #20
0
void HandleModuleInput(Window w, int channel)
{
  char text[256];
  int size;
  int cont, n;

  /* Already read a (possibly NULL) window id from the pipe,
   * Now read an fvwm bultin command line */
  n = read(readPipes[channel], &size, sizeof(size));
  if (n < sizeof(size)) {
    KillModule(channel, 1);
    return;
  }

  if (size > 255) {
    fvwm_msg(ERR, "HandleModuleInput",
	     "Module command is too big (%d)", (void *) size);
    size = 255;
  }

  pipeOn[channel] = 1;

  n = read(readPipes[channel], text, size);
  if (n < size) {
    KillModule(channel, 2);
    return;
  }

  text[n] = 0;
  n = read(readPipes[channel], &cont, sizeof(cont));
  if (n < sizeof(cont)) {
    KillModule(channel, 3);
    return;
  }
  if (cont == 0) {
    KillModule(channel, 4);
  }
  if (strlen(text) > 0) {
    extern int Context;
    FvwmWindow *tmp_win;

    /* first, check to see if module config line */
    if (text[0] == '*') {
      AddToModList(text);
      return;
    }

    /* perhaps the module would like us to kill it? */
    if (strncasecmp(text, "KillMe", 6) == 0) {
      KillModule(channel, 12);
      return;
    }


    /*Event.xany.type = ButtonRelease; hmmm... */
    /* If a module does XUngrabPointer(), it can now get proper Popups */
    if (strncasecmp(text, "popup", 5) == 0)
      Event.xany.type = ButtonPress;
    else
      Event.xany.type = ButtonRelease;
    Event.xany.window = w;

    if ((w == None) ||
        (XFindContext(dpy, w, FvwmContext, (caddr_t *) &tmp_win) == XCNOENT)) {
      tmp_win = NULL;
      w = None;
    }
    if (tmp_win) {
      Event.xbutton.button = 1;
      Event.xbutton.x_root = tmp_win->frame_x;
      Event.xbutton.y_root = tmp_win->frame_y;
      Event.xbutton.x = 0;
      Event.xbutton.y = 0;
      Event.xbutton.subwindow = None;
    } else {
      Event.xbutton.button = 1;
      Event.xbutton.x_root = 0;
      Event.xbutton.y_root = 0;
      Event.xbutton.x = 0;
      Event.xbutton.y = 0;
      Event.xbutton.subwindow = None;
    }
    Context = GetContext(tmp_win, &Event, &w);
    ExecuteFunction(text, tmp_win, &Event, Context, channel);
    SendPacket(channel, M_FUNCTION_END, 1, 0, 0, 0, 0, 0, 0, 0);
  }
  return;
}
Пример #21
0
/*
 * Change by PRB ([email protected]), 31/10/93.  Prepend a hot key
 * specifier to each item in the list.  This means allocating the
 * memory for each item (& freeing it) rather than just using the window
 * title directly. */
void CMD_WindowList(F_CMD_ARGS)
{
	struct MenuRoot *mr;
	struct MenuParameters mp;
	char* ret_action = NULL;
	FvwmWindow *t;
	FvwmWindow **windowList;
	FvwmWindow **iconifiedList = NULL;
	int numWindows;
	int ii;
	char tname[128];
	char loc[64];
	char *name=NULL;
	Bool free_name = False;
	int dwidth;
	int dheight;
	char *tlabel;
	int last_desk_done = INT_MIN;
	int last_desk_displayed = INT_MIN;
	int next_desk = 0;
	char *t_hot=NULL;             /* Menu label with hotkey added */
	char scut = '0';              /* Current short cut key */
	char *opts=NULL;
	char *tok=NULL;
	int desk = Scr.CurrentDesk;
	unsigned long flags = SHOW_DEFAULT;
	char *func = NULL;
	char *ffunc = NULL;
	char *tfunc = NULL;
	char *default_action = NULL;
	MenuReturn mret;
	MenuOptions mops;
	int low_layer = 0;  /* show all layers by default */
	int high_layer = INT_MAX;
	int max_label_width = 0;
	int skiplist_mode = 0; /* do not show skiplist by default */
	Bool use_hotkey = True;
	KeyCode old_sor_keycode;
	char sor_default_keyname[8] = { 'M', 'e', 't', 'a', '_', 'L' };
	char *sor_keyname = sor_default_keyname;
	/* Condition vars. */
	Bool use_condition = False;
	Bool current_at_end = False;
	Bool iconified_at_end = False;
	int ic = 0;
	int ij;
	WindowConditionMask mask;
	char *cond_flags;
	Bool first_desk = True;
	Bool empty_menu = True;
	Bool was_get_menu_opts_called = False;
	FvwmWindow * const fw = exc->w.fw;
	const Window w = exc->w.w;
	const exec_context_t *exc2;

	memset(&mops, 0, sizeof(mops));
	memset(&mret, 0, sizeof(MenuReturn));
	/* parse postitioning args - must call this even if no action is given
	 * because it sets the xinerama screen origin */
	if (action && *action)
	{
		/* Look for condition - CreateFlagString returns NULL if no '('
		 * or '[' */
		cond_flags = CreateFlagString(action, &action);
		if (cond_flags)
		{
			/* Create window mask */
			use_condition = True;
			DefaultConditionMask(&mask);

			/* override for Current [] */
			mask.my_flags.use_circulate_hit = 1;
			mask.my_flags.use_circulate_hit_icon = 1;

			CreateConditionMask(cond_flags, &mask);
			free(cond_flags);
		}
		opts = get_menu_options(
			action, w, fw, NULL, NULL, NULL, &mops);
		was_get_menu_opts_called = True;

		/* parse options */
		while (opts && *opts)
		{
			opts = GetNextSimpleOption(opts, &tok);
			if (!tok)
			{
				break;
			}

			if (StrEquals(tok,"NoHotkeys"))
			{
				use_hotkey = False;
			}
			else if (StrEquals(tok,"Function"))
			{
				opts = GetNextSimpleOption(opts, &func);
			}
			else if (StrEquals(tok,"Desk"))
			{
				free(tok);
				opts = GetNextSimpleOption(opts, &tok);
				if (tok)
				{
					desk = atoi(tok);
					flags &= ~SHOW_ALLDESKS;
				}
			}
			else if (StrEquals(tok,"CurrentDesk"))
			{
				desk = Scr.CurrentDesk;
				flags &= ~SHOW_ALLDESKS;
			}
			else if (StrEquals(tok,"NotAlphabetic"))
			{
				flags &= ~SHOW_ALPHABETIC;
			}
			else if (StrEquals(tok,"Alphabetic"))
			{
				flags |= SHOW_ALPHABETIC;
			}
			else if (StrEquals(tok,"SortByClass"))
			{
				flags |= SORT_BYCLASS;
			}
			else if (StrEquals(tok,"SortByResource"))
			{
				flags |= SORT_BYRESOURCE;
			}
			else if (StrEquals(tok,"ReverseOrder"))
			{
				flags |= SORT_REVERSE;
			}
			else if (StrEquals(tok,"CurrentAtEnd"))
			{
				current_at_end = True;
			}
			else if (StrEquals(tok,"IconifiedAtEnd"))
			{
				iconified_at_end = True;
			}
			else if (StrEquals(tok,"NoDeskSort"))
			{
				flags |= NO_DESK_SORT;
			}
			else if (StrEquals(tok,"ShowPage"))
			{
				flags |= SHOW_PAGE_X | SHOW_PAGE_Y;
			}
			else if (StrEquals(tok,"ShowPageX"))
			{
				flags |= SHOW_PAGE_X;
			}
			else if (StrEquals(tok,"ShowPageY"))
			{
				flags |= SHOW_PAGE_Y;
			}
			else if (StrEquals(tok,"ShowScreen"))
			{
				flags |= SHOW_SCREEN;
			}
			else if (StrEquals(tok,"UseIconName"))
			{
				flags |= SHOW_ICONNAME;
			}
			else if (StrEquals(tok,"NoGeometry"))
			{
				flags &= ~SHOW_GEOMETRY;
				flags &= ~SHOW_INFONOTGEO;
			}
			else if (StrEquals(tok,"NoGeometryWithInfo"))
			{
				flags &= ~SHOW_GEOMETRY;
				flags |= SHOW_INFONOTGEO;
			}
			else if (StrEquals(tok,"Geometry"))
			{
				flags |= SHOW_GEOMETRY;
				flags &= ~SHOW_INFONOTGEO;
			}
			else if (StrEquals(tok,"NoIcons"))
			{
				flags &= ~SHOW_ICONIC;
			}
			else if (StrEquals(tok,"Icons"))
			{
				flags |= SHOW_ICONIC;
			}
			else if (StrEquals(tok,"OnlyIcons"))
			{
				flags = SHOW_ICONIC;
			}
			else if (StrEquals(tok,"NoNormal"))
			{
				flags &= ~SHOW_NORMAL;
			}
			else if (StrEquals(tok,"Normal"))
			{
				flags |= SHOW_NORMAL;
			}
			else if (StrEquals(tok,"OnlyNormal"))
			{
				flags = SHOW_NORMAL;
			}
			else if (StrEquals(tok,"NoSticky"))
			{
				flags &= ~(SHOW_STICKY_ACROSS_PAGES);
				flags &= ~(SHOW_STICKY_ACROSS_DESKS);
			}
			else if (StrEquals(tok,"NoStickyPage"))
			{
				flags &= ~(SHOW_STICKY_ACROSS_PAGES);
			}
			else if (StrEquals(tok,"NoStickyDesk"))
			{
				flags &= ~(SHOW_STICKY_ACROSS_DESKS);
			}
			else if (StrEquals(tok,"Sticky"))
			{
				flags |= SHOW_STICKY_ACROSS_PAGES;
				flags |= SHOW_STICKY_ACROSS_DESKS;
			}
			else if (StrEquals(tok,"StickyPage"))
			{
				flags |= SHOW_STICKY_ACROSS_PAGES;
			}
			else if (StrEquals(tok,"StickyDesk"))
			{
				flags |= SHOW_STICKY_ACROSS_DESKS;
			}
			else if (StrEquals(tok,"OnlySticky"))
			{
				flags = SHOW_STICKY_ACROSS_PAGES;
				flags = SHOW_STICKY_ACROSS_DESKS;
			}
			else if (StrEquals(tok,"OnlyStickyPage"))
			{
				flags = SHOW_STICKY_ACROSS_PAGES;
			}
			else if (StrEquals(tok,"OnlyStickyDesk"))
			{
				flags = SHOW_STICKY_ACROSS_DESKS;
			}
			else if (StrEquals(tok,"UseListSkip"))
			{
				/* deprecated as of 02-May-2007 (SS) */
				fprintf(stderr, "UseListSkip is deprecated. Please use \"UseSkipList\".\n");
				skiplist_mode = 1;
			}
			else if (StrEquals(tok,"UseSkipList"))
			{
				skiplist_mode = 1;
			}
			else if (StrEquals(tok,"OnlyListSkip"))
			{
				/* deprecated as of 02-May-2007 (SS) */
				fprintf(stderr, "OnlyListSkip is deprecated. Please use \"OnlySkipList\".\n");
				skiplist_mode = 2;
			}
			else if (StrEquals(tok,"OnlySkipList"))
			{
				skiplist_mode = 2;
			}
			else if (StrEquals(tok,"NoDeskNum"))
			{
				flags |= NO_DESK_NUM;
			}
			else if (StrEquals(tok,"NoLayer"))
			{
				flags |= NO_LAYER;
			}
			else if (StrEquals(tok,"NoCurrentDeskTitle"))
			{
				flags |= NO_CURRENT_DESK_TITLE;
			}
			else if (StrEquals(tok,"TitleForAllDesks"))
			{
				flags |= TITLE_FOR_ALL_DESKS;
			}
			else if (StrEquals(tok,"NoNumInDeskTitle"))
			{
				flags |= NO_NUM_IN_DESK_TITLE;
			}
			/* these are a bit dubious, but we should keep the
			 * OnTop options for compatibility */
			else if (StrEquals(tok, "NoOnTop"))
			{
				if (high_layer >= Scr.TopLayer)
				{
					high_layer = Scr.TopLayer - 1;
				}
			}
			else if (StrEquals(tok, "OnTop"))
			{
				if (high_layer < Scr.TopLayer)
				{
					high_layer = Scr.TopLayer;
				}
			}
			else if (StrEquals(tok, "OnlyOnTop"))
			{
				high_layer = low_layer = Scr.TopLayer;
			}
			else if (StrEquals(tok, "NoOnBottom"))
			{
				if (low_layer <= Scr.BottomLayer)
				{
					low_layer = Scr.BottomLayer - 1;
				}
			}
			else if (StrEquals(tok, "OnBottom"))
			{
				if (low_layer > Scr.BottomLayer)
				{
					low_layer = Scr.BottomLayer;
				}
			}
			else if (StrEquals(tok, "OnlyOnBottom"))
			{
				high_layer = low_layer = Scr.BottomLayer;
			}
			else if (StrEquals(tok, "Layer"))
			{
				free(tok);
				opts = GetNextSimpleOption(opts, &tok);
				if (tok)
				{
					low_layer = high_layer = atoi(tok);
					free(tok);
					opts = GetNextSimpleOption(opts, &tok);
					if (tok)
					{
						high_layer = atoi(tok);
					}
				}
			}
			else if (StrEquals(tok, "SelectOnRelease"))
			{
				if (sor_keyname != sor_default_keyname)
				{
					free(sor_keyname);
				}
				sor_keyname = NULL;
				opts = GetNextSimpleOption(opts, &sor_keyname);
			}
			else if (StrEquals(tok, "MaxLabelWidth"))
			{
				char *wid;

				opts = GetNextSimpleOption(opts, &wid);
				if (wid)
				{
					max_label_width = atoi(wid);
					if (max_label_width < 1)
					{
						max_label_width = 1;
					}
					free(wid);
				}
			}
			else if (!opts || !*opts)
			{
				default_action = safestrdup(tok);
			}
			else
			{
				fvwm_msg(
					ERR, "WindowList","Unknown option '%s'",
					tok);
			}
			if (tok)
			{
				free(tok);
			}
		}
	}
	if (was_get_menu_opts_called == False)
	{
		opts = get_menu_options(
			action, w, fw, NULL, NULL, NULL, &mops);
	}

	tlabel = get_desk_title(desk, flags, True);
	mr = NewMenuRoot(tlabel);
	if (!(flags & NO_CURRENT_DESK_TITLE))
	{
		AddToMenu(mr, tlabel, "TITLE", False, False, False);
		empty_menu = False;
	}
	free(tlabel);

	numWindows = 0;
	for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
	{
		numWindows++;
	}
	windowList = malloc(numWindows*sizeof(t));
	if (windowList == NULL)
	{
		return;
	}
	if (iconified_at_end)
	{
		iconifiedList = malloc(numWindows*sizeof(t));
		if (iconifiedList == NULL)
		{
			free(windowList);
			return;
		}
	}
	/* get the windowlist starting from the current window (if any)*/
	t = get_focus_window();
	if (t == NULL)
	{
		t = Scr.FvwmRoot.next;
	}
	else if (current_at_end)
	{
		if (t->next)
		{
			t = t->next;
		}
		else
		{
			t = Scr.FvwmRoot.next;
		}
	}
	for (ii = 0; ii < numWindows; ii++)
	{
		if (flags & SORT_REVERSE)
		{
			windowList[numWindows - ii - 1] = t;
		}
		else if (iconified_at_end && IS_ICONIFIED(t))
		{
			iconifiedList[ic++] = t;
		}
		else
		{
			windowList[ii - ic] = t;
		}
		if (t->next)
		{
			t = t->next;
		}
		else
		{
			t = Scr.FvwmRoot.next;
		}
	}
	if (iconified_at_end && ic > 0)
	{
		if (current_at_end && ii > ic)
		{
			windowList[numWindows - 1] = windowList[--ii - ic];
		}
		for (ij = 0; ij < ic; ij++)
		{
			windowList[ij + (ii - ic)] = iconifiedList[ij];
		}
	}

	/* Do alphabetic sort */
	if (flags & (SHOW_ALPHABETIC | SORT_BYCLASS | SORT_BYRESOURCE))
	{
		/* This will be compare or compareReverse if a reverse order
		 * is selected. */
		int (*sort)(const FvwmWindow **a, const FvwmWindow **b);

		switch (flags & (SHOW_ALPHABETIC | SHOW_ICONNAME | \
			SORT_BYCLASS | SORT_BYRESOURCE))
		{
		case SHOW_ALPHABETIC:
			compare = visibleCompare;
			break;
		case SHOW_ALPHABETIC | SHOW_ICONNAME:
			compare = iconCompare;
			break;
		/* Sorting based on class name produces an alphabetic
		 * order so the keyword alphabetic is redundant. */
		case SORT_BYCLASS:
		case SORT_BYCLASS | SHOW_ALPHABETIC:
			compare = classCompare;
			break;
		case SORT_BYCLASS | SHOW_ICONNAME:
		case SORT_BYCLASS | SHOW_ICONNAME | SHOW_ALPHABETIC:
			compare = classIconCompare;
			break;
		case SORT_BYRESOURCE:
		case SORT_BYRESOURCE | SORT_BYCLASS:
		case SORT_BYRESOURCE | SORT_BYCLASS | SHOW_ALPHABETIC:
			compare = resourceCompare;
			break;
		case SORT_BYRESOURCE | SHOW_ICONNAME:
		case SORT_BYRESOURCE | SHOW_ICONNAME | SORT_BYCLASS:
		case SORT_BYRESOURCE | SHOW_ICONNAME | SORT_BYCLASS | \
		SHOW_ALPHABETIC:
			compare = resourceIconCompare;
			break;

		/* All current cases are covered, but if something
		 * changes in the future we leave compare valid even if
		 * it isn't what is expected. */
		default:
			compare = visibleCompare;
			break;
		}

		if ( flags & SORT_REVERSE )
		{
			sort = compareReverse;
		}
		else
		{
			sort = compare;
		}
		qsort(windowList, numWindows, sizeof(t),
		      (int(*)(const void*, const void*))sort);
	}

	while(next_desk != INT_MAX)
	{
		/* Sort window list by desktop number */
		if ((flags & SHOW_ALLDESKS) && !(flags & NO_DESK_SORT))
		{
			/* run through the windowlist finding the first desk
			 * not already processed */
			next_desk = INT_MAX;
			for (ii = 0; ii < numWindows; ii++)
			{
				t = windowList[ii];
				if (t->Desk >last_desk_done &&
				    t->Desk < next_desk)
				{
					next_desk = t->Desk;
				}
			}
		}
		if (!(flags & SHOW_ALLDESKS))
		{
			/* if only doing one desk and it hasn't been done */
			if (last_desk_done  == INT_MIN)
				next_desk = desk; /* select the desk */
			else
				next_desk = INT_MAX; /* flag completion */
		}
		if (flags & NO_DESK_SORT)
			next_desk = INT_MAX; /* only go through loop once */

		last_desk_done = next_desk;
		for (ii = 0; ii < numWindows; ii++)
		{
			t = windowList[ii];
			if (t->Desk != next_desk && !(flags & NO_DESK_SORT))
			{
				continue;
			}
			if (skiplist_mode == 0 && DO_SKIP_WINDOW_LIST(t))
			{
				/* don't want skiplist windows - skip */
				continue;
			}
			if (skiplist_mode == 2 && !DO_SKIP_WINDOW_LIST(t))
			{
				/* don't want no skiplist one - skip */
				continue;
			}
			if (use_condition && !MatchesConditionMask(t, &mask))
			{
				/* doesn't match specified condition */
				continue;
			}
			if (!(flags & SHOW_ICONIC) && (IS_ICONIFIED(t)))
			{
				/* don't want icons - skip */
				continue;
			}
			if (!(flags & SHOW_STICKY_ACROSS_PAGES) &&
			    (IS_STICKY_ACROSS_PAGES(t)))
			{
				/* don't want sticky ones - skip */
				continue;
			}
			if (!(flags & SHOW_STICKY_ACROSS_DESKS) &&
			    (IS_STICKY_ACROSS_DESKS(t)))
			{
				/* don't want sticky ones - skip */
				continue;
			}
			if (!(flags & SHOW_NORMAL) &&
			    !(IS_ICONIFIED(t) ||
			      IS_STICKY_ACROSS_PAGES(t) ||
			      IS_STICKY_ACROSS_DESKS(t)))
			{
				/* don't want "normal" ones - skip */
				continue;
			}
			if (get_layer(t) < low_layer ||
			    get_layer(t) > high_layer)
			{
				/* don't want this layer */
				continue;
			}

			empty_menu = False;
			/* add separator between desks when geometry
			 * shown but not at the top*/
			if (t->Desk != last_desk_displayed)
			{
				if (last_desk_displayed != INT_MIN)
				{
					if (((flags & SHOW_GEOMETRY) ||
					     (flags & SHOW_INFONOTGEO)) &&
					    !(flags & TITLE_FOR_ALL_DESKS))
					{
						AddToMenu(
							mr, NULL, NULL, False,
							False, False);
					}
					if (flags & TITLE_FOR_ALL_DESKS)
					{
						tlabel = get_desk_title(
							t->Desk, flags, False);
						AddToMenu(
							mr, tlabel, "TITLE",
							False, False, False);
						free(tlabel);
					}
				}
				last_desk_displayed = t->Desk;
			}
			if (first_desk && flags & TITLE_FOR_ALL_DESKS)
			{
				tlabel = get_desk_title(t->Desk, flags, False);
				AddToMenu(
					mr, tlabel, "TITLE", False, False,
					False);
				free(tlabel);
			}
			first_desk = False;

			if (flags & SHOW_ICONNAME)
			{
				name = t->visible_icon_name;
			}
			else
			{
				name = t->visible_name;
			}

			free_name = False;
			if (!name)
			{
				name = "NULL_NAME";
			}
			else if (max_label_width > 0 &&
				 strlen(name) > max_label_width)
			{
				name = strdup(name);
				name[max_label_width] = '\0';
				free_name = True;
			}

			t_hot = safemalloc(strlen(name) + 80);
			if (use_hotkey)
			{
				/* Generate label */
				sprintf(t_hot, "&%c. ", scut);
			}
			else
			{
				*t_hot = 0;
			}
			if (!(flags & SHOW_INFONOTGEO))
			{
				strcat(t_hot, name);
			}
			if (*t_hot == 0)
			{
				strcpy(t_hot, " ");
			}

			/* Next shortcut key */
			if (scut == '9')
			{
				scut = 'A';
			}
			else if (scut == 'Z')
			{
				scut = '0';
			}
			else
			{
				scut++;
			}

			if (flags & SHOW_INFONOTGEO)
			{
				tname[0]=0;
				if (!IS_ICONIFIED(t) &&
				    !(flags & NO_DESK_NUM))
				{
					sprintf(loc,"%d:", t->Desk);
					strcat(tname,loc);
				}
				if (IS_ICONIFIED(t))
				{
					strcat(tname, "(");
				}
				strcat(t_hot,"\t");
				strcat(t_hot,tname);
				strcat(t_hot, name);
				if (IS_ICONIFIED(t))
				{
					strcat(t_hot, ")");
				}
			}
			else if (flags & SHOW_GEOMETRY)
			{
				size_borders b;

				tname[0]=0;
				if (IS_ICONIFIED(t))
				{
					strcpy(tname, "(");
				}
				if (!(flags & NO_DESK_NUM))
				{
					sprintf(loc, "%d", t->Desk);
					strcat(tname, loc);
				}
				if (flags & SHOW_SCREEN)
				{
					fscreen_scr_arg fscr;
					int scr;

					fscr.xypos.x =
						Scr.Vx + t->g.frame.x +
						t->g.frame.width / 2;
					fscr.xypos.y =
						Scr.Vy + t->g.frame.y +
						t->g.frame.height / 2;
					scr = FScreenGetScrId(
						&fscr, FSCREEN_XYPOS);
					sprintf(loc, "@%d", scr);
					strcat(tname, loc);
				}
				if (flags & SHOW_PAGE_X)
				{
					sprintf(loc, "+%d",
						(Scr.Vx + t->g.frame.x +
						 t->g.frame.width / 2) /
						Scr.MyDisplayWidth);
					strcat(tname, loc);
				}
				if (flags & SHOW_PAGE_Y)
				{
					sprintf(loc, "+%d",
						(Scr.Vy + t->g.frame.y +
						 t->g.frame.height/2) /
						Scr.MyDisplayHeight);
					strcat(tname, loc);
				}
				if (!(flags & NO_LAYER))
				{
					sprintf(loc, "(%d)",
						(get_layer(t)));
					strcat(tname, loc);
				}
				strcat(tname, ":");
				get_window_borders(t, &b);
				dheight = t->g.frame.height -
					b.total_size.height;
				dwidth = t->g.frame.width -
					b.total_size.width;

				dwidth = (dwidth - t->hints.base_width)
					  /t->orig_hints.width_inc;
				dheight = (dheight - t->hints.base_height)
					  /t->orig_hints.height_inc;

				sprintf(loc,"%d",dwidth);
				strcat(tname, loc);
				sprintf(loc,"x%d",dheight);
				strcat(tname, loc);
				if (t->g.frame.x >=0)
				{
					sprintf(loc,"+%d",t->g.frame.x);
				}
				else
				{
					sprintf(loc,"%d",t->g.frame.x);
				}
				strcat(tname, loc);
				if (t->g.frame.y >=0)
				{
					sprintf(loc,"+%d",t->g.frame.y);
				}
				else
				{
					sprintf(loc,"%d",t->g.frame.y);
				}
				strcat(tname, loc);

				if (IS_STICKY_ACROSS_PAGES(t) ||
				    IS_STICKY_ACROSS_DESKS(t))
				{
					strcat(tname, " S");
				}
				if (IS_ICONIFIED(t))
				{
					strcat(tname, ")");
				}
				strcat(t_hot,"\t");
				strcat(t_hot,tname);
			}
			ffunc = func ? func : "WindowListFunc";
			tfunc = safemalloc(strlen(ffunc) + 36);
			/* support two ways for now: window context
			 * (new) and window id param (old) */
			sprintf(tfunc, "WindowId %lu %s %lu",
				FW_W(t), ffunc, FW_W(t));
			AddToMenu(
				mr, t_hot, tfunc, False, False, False);
			free(tfunc);
			/* Add the title pixmap */
			if (FMiniIconsSupported && t->mini_icon)
			{
				MI_MINI_ICON(MR_LAST_ITEM(mr))[0] =
					t->mini_icon;
				/* increase the cache count. Otherwise the
				 * pixmap will be eventually removed from the
				 * cache by DestroyMenu */
				t->mini_icon->count++;
			}
			if (t_hot)
			{
				free(t_hot);
			}
			if (free_name)
			{
				free(name);
			}
		}
	}

	if (empty_menu)
	{
		/* force current desk title */
		tlabel = get_desk_title(desk, flags, True);
		AddToMenu(mr, tlabel, "TITLE", False, False, False);
		free(tlabel);
	}

	if (func)
	{
		free(func);
	}
	free(windowList);
	if (iconified_at_end)
	{
		free(iconifiedList);
	}
	/* Use the WindowList menu style if there is one */
	change_mr_menu_style(mr, "WindowList");

	/* Activate select_on_release style */
	old_sor_keycode = MST_SELECT_ON_RELEASE_KEY(mr);
	if (sor_keyname &&
	    (!MST_SELECT_ON_RELEASE_KEY(mr) ||
	     sor_keyname != sor_default_keyname))
	{
		MST_SELECT_ON_RELEASE_KEY(mr) =
			XKeysymToKeycode(
				dpy, FvwmStringToKeysym(dpy, sor_keyname));
	}

	memset(&mp, 0, sizeof(mp));
	mp.menu = mr;
	exc2 = exc_clone_context(exc, NULL, 0);
	mp.pexc = &exc2;
	mp.flags.has_default_action = (default_action && *default_action != 0);
	mp.flags.is_sticky = 1;
	mp.flags.is_submenu = 0;
	mp.flags.is_already_mapped = 0;
	mp.flags.is_triggered_by_keypress =
		(!default_action && exc->x.etrigger->type == KeyPress);
	mp.pops = &mops;
	mp.ret_paction = &ret_action;
	do_menu(&mp, &mret);
	/* Restore old menu style */
	MST_SELECT_ON_RELEASE_KEY(mr) = old_sor_keycode;
	if (ret_action)
	{
		free(ret_action);
	}
	DestroyMenu(mr, False, False);
	if (mret.rc == MENU_DOUBLE_CLICKED &&
	    default_action && *default_action)
	{
		execute_function(cond_rc, exc2, default_action, 0);
	}
	if (default_action != NULL)
	{
		free(default_action);
	}
	if (use_condition)
	{
		FreeConditionMask(&mask);
	}
	if (sor_keyname && sor_keyname != sor_default_keyname)
	{
		free(sor_keyname);
	}
	exc_destroy_context(exc2);

	return;
}
Пример #22
0
int main(int argc, char **argv)
{
  unsigned long valuemask;		/* mask for create windows */
  XSetWindowAttributes attributes;	/* attributes for create windows */
  void InternUsefulAtoms(void);
  void InitVariables(void);
  int  i, len;
  extern int x_fd;
  char *display_string;
  char message[255];
  Bool single = False;
  Bool option_error = FALSE;
  MenuRoot *mr;

  g_argv = argv;
  g_argc = argc;

  OpenConsole();
  DBUG("main", "Entered, about to parse args");

  for (i = 1; i < argc; i++) {
    if (strncasecmp(argv[i], "-debug", 6) == 0) {
      debugging = True;
    } else if (strncasecmp(argv[i], "-s", 2) == 0) {
      single = True;
    } else if (strncasecmp(argv[i], "-d", 2) == 0) {
      if (++i >= argc)
	usage();
      display_name = argv[i];
    } else if (strncasecmp(argv[i], "-f", 2) == 0) {
      if (++i >= argc)
	usage();
      config_command = (char *) malloc(6 + strlen(argv[i]));
      strcpy(config_command, "Read ");
      strcat(config_command, argv[i]);
      free_config_command = True;
    } else if (strncasecmp(argv[i], "-cmd", 4) == 0) {
      if (++i >= argc)
	usage();
      config_command = argv[i];
    } else if (strncasecmp(argv[i], "-file", 5) == 0) {
      if (++i >= argc)
	usage();
      output_file = argv[i];
    } else if (strncasecmp(argv[i], "-h", 2) == 0) {
      usage();
      exit(0);
    } else if (strncasecmp(argv[i], "-blackout", 9) == 0) {
      Blackout = True;
    } else if (strncasecmp(argv[i], "-version", 8) == 0) {
      fvwm_msg(INFO, "main", "Fvwm95 Version %s compiled on %s at %s\n",
	       VERSION, __DATE__, __TIME__);
    } else {
      fvwm_msg(ERR, "main", "Unknown option: `%s'\n", argv[i]);
      option_error = TRUE;
    }
  }

  DBUG("main", "Done parsing args");

  if (option_error) {
    usage();
  }

  DBUG("main", "Installing signal handlers");

  newhandler(SIGINT);
  newhandler(SIGHUP);
  newhandler(SIGQUIT);
  newhandler(SIGTERM);
  signal(SIGUSR1, Restart);
  signal(SIGPIPE, DeadPipe);

  ReapChildren();

  if (!(dpy = XOpenDisplay(display_name))) {
    fvwm_msg(ERR, "main", "can't open display %s",
	     XDisplayName(display_name));
    exit(1);
  }
  Scr.screen = DefaultScreen(dpy);
  Scr.NumberOfScreens = ScreenCount(dpy);

  master_pid = getpid();

  if (!single) {
    int myscreen = 0;
    char *cp;

    strcpy(message, XDisplayString(dpy));

    XCloseDisplay(dpy);

    for (i = 1; i < Scr.NumberOfScreens; i++) {
      if (fork() == 0) {
	myscreen = i;
	break;
      }
    }
    /*
     * Truncate the string 'whatever:n.n' to 'whatever:n',
     * and then append the screen number.
     */
    cp = strchr(message, ':');
    if (cp != NULL) {
      cp = strchr(cp, '.');
      if (cp != NULL)
	*cp = '\0';		/* truncate at display part */
    }
    sprintf(message + strlen(message), ".%d", myscreen);
    dpy = XOpenDisplay(message);
    Scr.screen = myscreen;
    Scr.NumberOfScreens = ScreenCount(dpy);
  }

  x_fd = XConnectionNumber(dpy);
  fd_width = GetFdWidth();

  if (fcntl(x_fd, F_SETFD, 1) == -1) {
    fvwm_msg(ERR, "main", "close-on-exec failed");
    exit(1);
  }

  /*  Add a DISPLAY entry to the environment, in case we were started
   *  with fvwm -display term:0.0
   */
  len = strlen(XDisplayString(dpy));
  display_string = safemalloc(len + 10);
  sprintf(display_string, "DISPLAY=%s", XDisplayString(dpy));
  putenv(display_string);

  /* Add a HOSTDISPLAY environment variable, which is the same as
   * DISPLAY, unless display = :0.0 or unix:0.0, in which case the full
   * host name will be used for ease in networking . */

  /* Note: Can't free the rdisplay_string after putenv, because it
   * becomes part of the environment! */

  if (strncmp(display_string, "DISPLAY=:", 9) == 0) {
    char client[MAXHOSTNAME], *rdisplay_string;

    mygethostname(client, MAXHOSTNAME);
    rdisplay_string = safemalloc(len + 14 + strlen(client));
    sprintf(rdisplay_string, "HOSTDISPLAY=%s:%s", client,
	    &display_string[9]);
    putenv(rdisplay_string);
  } else if (strncmp(display_string, "DISPLAY=unix:", 13) == 0) {
    char client[MAXHOSTNAME], *rdisplay_string;

    mygethostname(client, MAXHOSTNAME);
    rdisplay_string = safemalloc(len + 14 + strlen(client));
    sprintf(rdisplay_string, "HOSTDISPLAY=%s:%s", client,
	    &display_string[13]);
    putenv(rdisplay_string);
  } else {
    char *rdisplay_string;

    rdisplay_string = safemalloc(len + 14);
    sprintf(rdisplay_string, "HOSTDISPLAY=%s", XDisplayString(dpy));
    putenv(rdisplay_string);
  }

  Scr.Root = RootWindow(dpy, Scr.screen);
  if (Scr.Root == None) {
    fvwm_msg(ERR, "main", "Screen %d is not a valid screen",
	     (char *) Scr.screen);
    exit(1);
  }

#ifdef SHAPE
  ShapesSupported =
      XShapeQueryExtension(dpy, &ShapeEventBase, &ShapeErrorBase);
#endif	/* SHAPE */

  InternUsefulAtoms();

  /* Make sure property priority colors is empty */
  XChangeProperty(dpy, Scr.Root, _XA_MIT_PRIORITY_COLORS,
		  XA_CARDINAL, 32, PropModeReplace, NULL, 0);

  XSetErrorHandler((XErrorHandler) CatchRedirectError);
  XSetIOErrorHandler((XIOErrorHandler) CatchFatal);

  XSelectInput(dpy, Scr.Root,
	       LeaveWindowMask | EnterWindowMask | PropertyChangeMask |
	       SubstructureRedirectMask | KeyPressMask |
	       SubstructureNotifyMask |
	       ButtonPressMask | ButtonReleaseMask);

  XSync(dpy, 0);

  XSetErrorHandler((XErrorHandler) FvwmErrorHandler);

  BlackoutScreen();

  CreateCursors();
  InitVariables();
  InitEventHandlerJumpTable();
  initModules();

  InitPictureCMap(dpy, Scr.Root);	/* for the pixmap cache... */

  Scr.gray_bitmap =
      XCreateBitmapFromData(dpy, Scr.Root, g_bits, g_width, g_height);

  DBUG("main", "Setting up rc file defaults...");
  SetRCDefaults();

  DBUG("main", "Running config_command...");
  ExecuteFunction(config_command, NULL, &Event, C_ROOT, -1);
  DBUG("main", "Done running config_command");

/*
  CaptureAllWindows();
  MakeMenus();
*/

#if 0	/* this seems to cause problems for FvwmCpp/M4 startup actually */
  /* if not a direct 'Read', we'll capture all windows here, in case cmd
     fails we'll still have defaults */
  if (strncasecmp(config_command, "Read", 4) != 0 &&
      strncasecmp(config_command, "PipeRead", 8) != 0) {
    /* so if cmd (FvwmM4/Cpp most likely) fails, we can still have
       borders & stuff... */
    StartupStuff();
  }
#endif	/* 0 */

  if (free_config_command) {
    free(config_command);
  }

  if (Scr.d_depth < 2) {
    Scr.gray_pixmap =
	XCreatePixmapFromBitmapData(dpy, Scr.Root, g_bits, g_width,
				    g_height, Scr.WinColors.fore,
				    Scr.WinColors.back, Scr.d_depth);
    Scr.light_gray_pixmap =
	XCreatePixmapFromBitmapData(dpy, Scr.Root, l_g_bits, l_g_width,
				    l_g_height, Scr.WinColors.fore,
				    Scr.WinColors.back, Scr.d_depth);
  }

  /* create a window which will accept the keyboard focus when no other 
     windows have it */
  attributes.event_mask = KeyPressMask | FocusChangeMask;
  attributes.override_redirect = True;
  Scr.NoFocusWin = XCreateWindow(dpy, Scr.Root, -10, -10, 10, 10, 0, 0,
				 InputOnly, CopyFromParent,
				 CWEventMask | CWOverrideRedirect,
				 &attributes);
  XMapWindow(dpy, Scr.NoFocusWin);

  SetMWM_INFO(Scr.NoFocusWin);

  XSetInputFocus(dpy, Scr.NoFocusWin, RevertToParent, CurrentTime);

  XSync(dpy, 0);
  if (debugging)
    XSynchronize(dpy, 1);

  Scr.SizeStringWidth = XTextWidth(Scr.StdFont.font,
				   " +8888 x +8888 ", 15);
  attributes.border_pixel = Scr.WinColors.fore;
  attributes.background_pixel = Scr.WinColors.back;
  attributes.bit_gravity = NorthWestGravity;
  attributes.save_under = True;
  valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity | CWSaveUnder);

  /* create the window for coordinates */
  Scr.SizeWindow = XCreateWindow(dpy, Scr.Root,
				 Scr.MyDisplayWidth / 2 -
				 (Scr.SizeStringWidth +
				  SIZE_HINDENT * 2) / 2,
				 Scr.MyDisplayHeight / 2 -
				 (Scr.StdFont.height +
				  SIZE_VINDENT * 2) / 2,
				 (unsigned int) (Scr.SizeStringWidth +
						 SIZE_HINDENT * 2),
				 (unsigned int) (Scr.StdFont.height +
						 SIZE_VINDENT * 2),
				 (unsigned int) 0, 0,
				 (unsigned int) CopyFromParent,
				 (Visual *) CopyFromParent,
				 valuemask, &attributes);

#ifndef NON_VIRTUAL
  initPanFrames();
#endif

  XGrabServer(dpy);

#ifndef NON_VIRTUAL
  checkPanFrames();
#endif
  XUngrabServer(dpy);
  UnBlackoutScreen();
  DBUG("main", "Entering HandleEvents loop...");
  HandleEvents();
  DBUG("main", "Back from HandleEvents loop?  Exiting...");

  return 0;
}
Пример #23
0
void CMD_ReadWriteColors(F_CMD_ARGS)
{
	fvwm_msg(WARN, "CMD_ReadWriteColors", "ReadWriteColors is obsolete");

	return;
}
Пример #24
0
XErrorHandler CatchRedirectError(Display *dpy, XErrorEvent *event)
{
  fvwm_msg(ERR, "CatchRedirectError", "another WM is running");
  exit(1);
}
Пример #25
0
static void parse_pixmap(
	Window win, GC gc, colorset_t *cs, Bool *pixmap_is_a_bitmap)
{
	static char *name = "parse_colorset(pixmap)";
	FvwmPictureAttributes fpa;

	/* dither */
	fpa.mask = 0;
	if (cs->dither)
	{
		fpa.mask = FPAM_DITHER;
	}

	/* read filename */
	if (!cs->pixmap_args)
	{
		return;
	}
	/* load the file */
	cs->picture = PCacheFvwmPicture(dpy, win, NULL, cs->pixmap_args, fpa);
	if (cs->picture == NULL)
	{
		fvwm_msg(ERR, name, "can't load picture %s", cs->pixmap_args);
		return;
	}
	if (cs->picture->depth != Pdepth)
	{
		*pixmap_is_a_bitmap = True;
		cs->pixmap = None; /* build cs->pixmap later */
	}
	/* copy the picture pixmap into the public structure */
	cs->width = cs->picture->width;
	cs->height = cs->picture->height;
	cs->alpha_pixmap = cs->picture->alpha;

	if (!*pixmap_is_a_bitmap)
	{
		cs->pixmap = XCreatePixmap(dpy, win,
					   cs->width, cs->height,
					   Pdepth);
		XSetClipMask(dpy, gc, cs->picture->mask);
		XCopyArea(dpy, cs->picture->picture, cs->pixmap, gc,
			  0, 0, cs->width, cs->height, 0, 0);
		XSetClipMask(dpy, gc, None);
	}
	if (cs->pixmap)
	{
		if (cs->picture->mask != None)
		{
			/* make an inverted copy of the mask */
			cs->mask = XCreatePixmap(dpy, win,
						 cs->width, cs->height,
						 1);
			if (cs->mask)
			{
				XCopyArea(dpy, cs->picture->mask, cs->mask,
					  Scr.MonoGC,
					  0, 0, cs->width, cs->height, 0, 0);
				/* Invert the mask. We use it to draw the
				 * background. */
				XSetFunction(dpy, Scr.MonoGC, GXinvert);
				XFillRectangle(dpy, cs->mask, Scr.MonoGC,
					       0, 0, cs->width, cs->height);
				XSetFunction(dpy, Scr.MonoGC, GXcopy);
			}
		}
	}
}
Пример #26
0
/*****************************************************************************
 *
 * Builtin which determines if the button press was a click or double click...
 *
 ****************************************************************************/
void ComplexFunction(XEvent * eventp, Window w, FvwmWindow * tmp_win,
                     unsigned long context, char *action, int *Module)
{
    char type = MOTION;
    char c;
    MenuItem *mi;
    Bool Persist = False;
    Bool HaveDoubleClick = False;
    Bool NeedsTarget = False;
    char *arguments[10], *junk, *taction;
    int x, y, i;
    XEvent d, *ev;
    MenuRoot *mr;
    extern Bool desperate;

    mr = FindPopup(action);
    if (mr == NULL) {
        if (!desperate)
            fvwm_msg(ERR, "ComplexFunction", "No such function %s", action);
        return;
    }
    desperate = 0;
    /* Get the argument list */
    /* First entry in action is the function-name, ignore it */
    action = GetNextToken(action, &junk);
    if (junk != NULL)
        free(junk);
    for (i = 0; i < 10; i++)
        action = GetNextToken(action, &arguments[i]);
    /* These built-ins require a selected window
     * The function code is >= 100 and < 1000
     * F_RESIZE
     * F_MOVE
     * F_ICONIFY
     * F_RAISE
     * F_LOWER
     * F_DESTROY
     * F_DELETE
     * F_STICK
     * F_RAISELOWER
     * F_MAXIMIZE
     * F_FOCUS
     *
     * These do not:
     * The function code is < 100
     * F_NOP
     * F_TITLE
     * F_BEEP
     * F_SCROLL
     * F_MOVECURSOR
     * F_RESTART
     * F_EXEC
     * F_REFRESH
     * F_GOTO_PAGE
     * F_TOGGLE_PAGE
     * F_CIRCULATE_UP
     * F_CIRCULATE_DOWN
     * F_WARP
     * F_DESK
     * F_MODULE
     * F_POPUP
     * F_QUIT
     * F_WINDOWLIST
     * F_FUNCTION
     * F_SEND_WINDOW_LIST
     */
    ev = eventp;
    /* In case we want to perform an action on a button press, we
     * need to fool other routines */
    if (eventp->type == ButtonPress)
        eventp->type = ButtonRelease;
    mi = mr->first;
    while (mi != NULL) {
        /* make lower case */
        c = *(mi->item);
        if ((mi->func_type >= 100) && (mi->func_type < 1000))
            NeedsTarget = True;
        if (isupper(c))
            c = tolower(c);
        if (c == DOUBLE_CLICK) {
            HaveDoubleClick = True;
            Persist = True;
        } else if (c == IMMEDIATE) {
            if (tmp_win)
                w = tmp_win->frame;
            else
                w = None;
            taction = expand(mi->action, arguments, tmp_win);
            ExecuteFunction(taction, tmp_win, eventp, context, -2);
            free(taction);
        } else
            Persist = True;
        mi = mi->next;
    }

    if (!Persist) {
        for (i = 0; i < 10; i++)
            if (arguments[i] != NULL)
                free(arguments[i]);
        return;
    }

    /* Only defer execution if there is a possibility of needing
     * a window to operate on */
    if (NeedsTarget) {
        if (DeferExecution
                (eventp, &w, &tmp_win, &context, SELECT, ButtonPress)) {
            WaitForButtonsUp();
            for (i = 0; i < 10; i++)
                if (arguments[i] != NULL)
                    free(arguments[i]);
            return;
        }
    }

    if (!GrabEm(SELECT)) {
        XBell(dpy, Scr.screen);
        for (i = 0; i < 10; i++)
            if (arguments[i] != NULL)
                free(arguments[i]);
        return;
    }
    XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild,
                  &x, &y, &JunkX, &JunkY, &JunkMask);


    /* Wait and see if we have a click, or a move */
    /* wait 100 msec, see if the user releases the button */
    if (IsClick(x, y, ButtonReleaseMask, &d)) {
        ev = &d;
        type = CLICK;
    }

    /* If it was a click, wait to see if its a double click */
    if ((HaveDoubleClick) && (type == CLICK) &&
            (IsClick(x, y, ButtonPressMask, &d))) {
        type = ONE_AND_A_HALF_CLICKS;
        ev = &d;
    }
    if ((HaveDoubleClick) && (type == ONE_AND_A_HALF_CLICKS) &&
            (IsClick(x, y, ButtonReleaseMask, &d))) {
        type = DOUBLE_CLICK;
        ev = &d;
    }
    /* some functions operate on button release instead of
     * presses. These gets really weird for complex functions ... */
    if (ev->type == ButtonPress)
        ev->type = ButtonRelease;

    mi = mr->first;
    while (mi != NULL) {
        /* make lower case */
        c = *(mi->item);
        if (isupper(c))
            c = tolower(c);
        if (c == type) {
            if (tmp_win)
                w = tmp_win->frame;
            else
                w = None;
            taction = expand(mi->action, arguments, tmp_win);
            ExecuteFunction(taction, tmp_win, ev, context, -2);
            free(taction);
        }
        mi = mi->next;
    }
    WaitForButtonsUp();
    UngrabEm();
    for (i = 0; i < 10; i++)
        if (arguments[i] != NULL)
            free(arguments[i]);
}
Пример #27
0
static void parse_shape(Window win, colorset_t *cs, int i, char *args,
			int *has_shape_changed)
{
	char *token;
	static char *name = "parse_colorset(shape)";
	FvwmPicture *picture;
	FvwmPictureAttributes fpa;

	if (!FHaveShapeExtension)
	{
		cs->shape_mask = None;
		return;
	}

	/* read filename */
	token = PeekToken(args, &args);
	*has_shape_changed = True;
	if (cs->shape_mask)
	{
		add_to_junk(cs->shape_mask);
		cs->shape_mask = None;
	}

	/* set the flags */
	if (csetopts[i][0] == 'T')
	{
		cs->shape_type = SHAPE_TILED;
	}
	else if (csetopts[i][0] == 'A')
	{
		cs->shape_type = SHAPE_STRETCH_ASPECT;
	}
	else
	{
		cs->shape_type = SHAPE_STRETCH;
	}
	fpa.mask = FPAM_NO_ALPHA;

	/* try to load the shape mask */
	if (!token)
	{
		return;
	}

	/* load the shape mask */
	picture = PCacheFvwmPicture(dpy, win, NULL, token, fpa);
	if (!picture)
	{
		fvwm_msg(ERR, name, "can't load picture %s", token);
	}
	else if (picture->depth != 1 && picture->mask == None)
	{
		fvwm_msg(ERR, name, "shape pixmap must be of depth 1");
		SafeDestroyPicture(dpy, picture);
	}
	else
	{
		Pixmap mask;

		/* okay, we have what we want */
		if (picture->mask != None)
		{
			mask = picture->mask;
		}
		else
		{
			mask = picture->picture;
		}
		cs->shape_width = picture->width;
		cs->shape_height = picture->height;

		if (mask != None)
		{
			cs->shape_mask = XCreatePixmap(
				dpy, mask, picture->width, picture->height, 1);
			if (cs->shape_mask != None)
			{
				XCopyPlane(dpy, mask, cs->shape_mask,
					   Scr.MonoGC, 0, 0, picture->width,
					   picture->height, 0, 0, 1);
			}
		}
	}
	if (picture)
	{
		SafeDestroyPicture(dpy, picture);
		picture = None;
	}
	return;
}