Subject: Matthias's patches

From: Dominik Vogt <[email-masked]>
Date: Thu, 4 Mar 1999 21:50:45 +0100

I've recently cleaned up my mailbox and found a number of                       
patches Matthias Claasen made. I'm unsure what has been or
should be committed. Could you look through this list, please?                            
                                                                                
1) ICCCM focus handling in FvwmPager
2) Window groups. We had some discussion here and some more
   ideas. We should think about that before committing.
3) Menus in FvwmPager.
4) A patch to fix the size of maximized and shaded windows.
5) GTK menu module.
6) Shading as an ICCCM state.
7) FvwmEval module.

Bye

Dominik

--
Dominik Vogt, [email-masked]
Reply-To: [email-masked]

--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Matthias Clasen <[email-masked]>
Date: Fri, 5 Mar 1999 10:08:00 +0100

> 1) ICCCM focus handling in FvwmPager

No, it went in before 2.2, but was taken out since it changed
the behavior of M2 wrt desktop changing

>    ideas. We should think about that before committing.

I want to leave that for 2.4, since it needs a bit more thought

> 3) Menus in FvwmPager.

No, I think this should be done in a cleaner way, by making
the actions bound to mouse buttons in the pager completely 
configurable

> 4) A patch to fix the size of maximized and shaded windows.

This is not exactly what my patch does, but it is in.

> 5) GTK menu module.

This is currently available via ftp from

ftp://peano.mathematik.uni-freiburg.de/pub/fvwm

I keep thinking about extending it to a complete replacement
for all widget-like functionality in fvwm and modules, ie
adding dialogs and WindowList functionality. 

> 6) Shading as an ICCCM state.

No, this has been rejected after some discussion pre-2.2. 
But something related to this went in, a patch to make
shading and maximization truly independent 
("cube of wm-private states").

> 7) FvwmEval module.

No, but I would like to drop this in modules/FvwmEval
if nobody objects.

Matthias
-- 
Matthias Clasen, 
Tel. 0761/203-5606
Email: [email-masked]
Mathematisches Institut, Albert-Ludwigs-Universitaet Freiburg
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Dan Espen <[email-masked]>
Date: Fri, 05 Mar 1999 09:25:41 -0500

> No, but I would like to drop this in modules/FvwmEval

I'd much prefer to see this functionality implemented as support for pasting
in FvwmForm.

--
Dan Espen
444 Hoes Lane  Room RRC 1C-214           E-mail: [email-masked]
Piscataway, NJ 08854                     Phone: (732) 699-5570
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Matthias Clasen <[email-masked]>
Date: Sat, 6 Mar 1999 00:03:08 +0100

> I'd much prefer to see this functionality implemented as support for pasting

OK, I didn't add FvwmEval. This functionality doesn't need a module
anyway. I turned it into a small utility xselection which prints
the content of the X selection to stdout. Use it with PipeRead.

---

From: Brad Giaccio <[email-masked]>
Date: Mon, 8 Mar 1999 08:46:20 -0500

> the content of the X selection to stdout. Use it with PipeRead.

I didn't look to closelly at your patch but this will get the xselection
for you in a script

xprop -root CUT_BUFFER0 | sed 's/^.*=..\(.*\).$/\1/'
 
-- 
--- There are two kinds of knowledge, you either know the answer or
			you know where to find it
		      -Kane, Johnson, and anonymous
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: "Eddy J. Gurney" <[email-masked]>
Date: Mon, 8 Mar 1999 10:08:25 -0500

On Mar 8 at  8:46, Brad Giaccio wrote:
,--
| On Sat, Mar 06, 1999 at 12:03:08AM +0100, Matthias Clasen wrote:
| > > > > 7) FvwmEval module.
| > > >
| > > > No, but I would like to drop this in modules/FvwmEval
| > > > if nobody objects.
| > >
| > > I'd much prefer to see this functionality implemented as support
| > > for pasting in FvwmForm.
| >
| > OK, I didn't add FvwmEval. This functionality doesn't need a module
| > anyway. I turned it into a small utility xselection which prints
| > the content of the X selection to stdout. Use it with PipeRead.
|
| I didn't look to closelly at your patch but this will get the xselection
| for you in a script
|
| xprop -root CUT_BUFFER0 | sed 's/^.*=..\(.*\).$/\1/'
`--
Unfortunately, this is not a good approach to grabbing the selection. Use
of CUT_BUFFER0 is deprecated (at least that is what somebody else
told me), and is currently supported for "backwards compatability"
in some applications like xterm (the most common place).  The above
"xprop" trick does not work for Motif apps like Netscape, Z-Mail, zwgc,
etc. I've hacked together a small C program (`xgetprisel') that gets the
primary X selection (used in Motif apps, xterm, etc.), and if that isn't
set, falls back to CUT_BUFFER0. Maybe this is what FvwmEval does as well;
I haven't looked too closely myself. :-)

One interesting difference between the "Primary Selection" (preferred)
and CUT_BUFFER0 is that once a selection in an app that uses the
"Primary Selection" method is de-selected, it is no longer available
for pasting (try in with Netscape. Hilight something, paste it into an
xterm. Now de-select it and try pasting it into an xterm -- you should
get the last thing you selected in an xterm; I do anyway.) This is in
contrast to the CUT_BUFFER0 approach, where even after you have de-selected
the text, you can still paste it.

As I said, xterm uses both the Primary Selection and CUT_BUFFER0, so it is
not really a good "general" test case, even though it is very prevalent.

Eddy

---

From: Matthias Clasen <[email-masked]>
Date: Mon, 8 Mar 1999 18:00:34 +0100

> xprop -root CUT_BUFFER0 | sed 's/^.*=..\(.*\).$/\1/'

Almost. It turns out that xprop converts newlines in string properties
in "\n". I just couldn't come up with a sed command that would replace
"\n" with a newline. sed -e 'y/\\n/\
/' complains about "strings for y command are different lengths",
and sed -e 'y/\\n/  \
/' replaces all occurrances of "n" by two spaces and a newline!
sed -e 's/\(.*\)\\n\(.*\)/\1\
\2/g' replaces only one occurrance of "\n" by a newline.

An ugly solution is:

PipeRead "echo -e `xprop -root CUT_BUFFER0 | sed \'s/^.*=..\\(.*\\).$/\\1/\'`"

ie feeding the output of the sed command through echo -e to convert
"\n" to newlines.

Matthias

---

From: Matthias Clasen <[email-masked]>
Date: Mon, 8 Mar 1999 18:16:31 +0100

> I haven't looked too closely myself. :-)

I tried to achieve something like that; but to be honest, I just copied
the code for getting the contents of the selection/cut buffer from
FvwmTalk, so I cannot really say if it gets it right with the primary 
selection.

Perhaps you could look a bit closer and tell me how to correct it if
it is broken (or just donate `xgetprisel').

Matthias

---

From: "Eddy J. Gurney" <[email-masked]>
Date: Mon, 8 Mar 1999 12:44:26 -0500

On Mar 8 at 18:16, Matthias Clasen wrote:
,--
| I tried to achieve something like that; but to be honest, I just copied
| the code for getting the contents of the selection/cut buffer from
| FvwmTalk, so I cannot really say if it gets it right with the primary 
| selection.
| 
| Perhaps you could look a bit closer and tell me how to correct it if
| it is broken (or just donate `xgetprisel').
`--
Taking a quick look at FvwmTalk.c, I see this:

/* No primary selection so use the cut buffer. */

So it looks like FvwmTalk is trying to "do the right thing". I'll attach
the source to my `xgetprisel' program that prints the output of the
current selection to stdout in case it is of use to somebody. I have
a context-sensitive selection parser written in Perl (called "Magic"
:-) that uses this tool to get the current selection, analyze it, and
then "do the right thing" (and is bound to the giant "Help" key on
my Sun keyboard). For example, if the current selection starts with
"http://" or if the selection has at least two dots's in it, or if
it has one dot followed by two or three characters, it is probably a URL.
A lot of the other "Magic" stuff is specific to my job, but it is a major
time-saver to say the least... it is great to be able to select a 
URL (or double-click on something like "www.fvwm.org") smack the "Help"
key and jump to that web page!

A long time ago I suggested including a special variable in FVWM2 called
"$selection" that could be used in the rc file. Currently, my .fvwm2rc has
lines like this:

Key Help        A       N       Exec Magic 
Key Help        A       S       Exec Magic -shift 
Key Help        A       C       Exec Magic -ctrl 
Key Help        A       M       Exec Magic -meta 

it would be *great* to not require the `xgetprisel' binary, and just be
able to do something like:

Key Help        A       N       Exec Magic $selection
Key Help        A       S       Exec Magic -shift $selection
etc.

where "$selection" would contain the same thing `xgetprisel' returns...

Eddy

------------------------------------------------------------------------
Excerpt from my `Magic' script for anyone interested:
------------------------------------------------------------------------

#!/usr/local/bin/perl -w

$sel=`xgetprisel`;

#strip out newlines
$sel =~ s/\n//g;

# For convenience, strip leading and trailing spaces
$sel =~ s/^ +//g;
$sel =~ s/ +$//g;

if ($#ARGV < 0) {
    for ($sel) {
    # Selection looks like a URL -- send to Netscape
        /^(https?:\/\/|ftp:\/\/).+/                             and do
            { exec "navigator -display :0.0 -remote 'openURL($sel,newWindow)' &"; };

    # Selection contains: at least two dots OR one dot followed by two or three
    # characters (a top-level domain name) and then a non-word character or the
    # end of then selection -- form URL and send to Netscape
        /^[\w-]+\.[\w-]+\.[\w-]+|^[\w-]+\.\w\w\w?(\W|$)/        and do
            { exec "navigator -display :0.0 -remote 'openURL(http://$sel,newWindow)' &"; };
} elsif ($ARGV[0] eq "-shift") {
} elsif ($ARGV[0] eq "-ctrl") {
} elsif ($ARGV[0] eq "-meta") {
} else {
    print "Magic: Invalid command line option\n";
}

------------------------------------------------------------------------
Finally, the source to `xgetprisel', which I compile as follows:
------------------------------------------------------------------------

LD_RUN_PATH=/usr/X11R6.1/lib gcc -s -O2 -msupersparc -I/usr/X11R6.1/include -L/u/eddy/lib -L/usr/X11R6.1/lib -o xgetprisel xgetprisel.c -lX11 -lsocket -lnsl

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <X11/Xresource.h>

#define kDefaultPropertySize (10240L)

static Display *gDisplay;

static char *MyAlloc(char *str, int size)
{
    char *ret;

    if (size == 0)
	size = 1;

    if (str == (char *)0) {
	ret = malloc((unsigned)size);
    } else {
	ret = realloc(str, (unsigned)size);
    }

    if (ret == (char *)0) {
	XBell(gDisplay, 0);
	XFlush(gDisplay);
	exit(2);
    }
    return ret;
}

/* Request and retrieve a copy of the current selection property */
unsigned char *GetSelection(Display *dpy, Window window, Atom atom)
{
    XEvent event;
    struct timeval timeout = {3, 0};
    fd_set serverFDMask;
    Atom actualType;
    int actualFormat;
    unsigned long numItems, bytesAfter;
    unsigned char *data;
    unsigned char *alreadyGot;
    unsigned long size;

    /* tell the server we want a copy of the selection */
    XConvertSelection(dpy, atom, XA_STRING, XA_STRING, window, CurrentTime);

    FD_ZERO(&serverFDMask);
    FD_SET(ConnectionNumber(dpy), &serverFDMask);

    do {
	int result;

	do {
	    if (XPending(dpy) > 0) {
		result = 1;
	    } else {
		result = select(FD_SETSIZE, &serverFDMask, (fd_set *)0, (fd_set *)0, &timeout);
		if (result == -1 && errno != EINTR) {
		    XBell(dpy, 0);
		    XFlush(dpy);
		    exit(1);
		}
	    }
	} while (result == -1);

	if (result == 0) {
	    return (unsigned char *)0;
	}

	XNextEvent(dpy, &event);
    } while (event.type != SelectionNotify);

    if (event.xselection.property == None) {
	/* Retrieving the selection failed for some reason */
	return (unsigned char *)0;
    }

    if (XGetWindowProperty(dpy, event.xselection.requestor, event.xselection.property, 0L, kDefaultPropertySize, True, AnyPropertyType, &actualType, &actualFormat, &numItems, &bytesAfter, (unsigned char **)&data) != Success) {
	/* The get failed for some reason */
	return (unsigned char *)0;
    }

    if (bytesAfter > 0) {
	alreadyGot = (unsigned char *)MyAlloc(data, numItems + bytesAfter + 1);
	size = numItems;
    } else {
	return data;
    }

    while (bytesAfter > 0) {
	if (XGetWindowProperty(dpy, event.xselection.requestor, event.xselection.property, size / 4, kDefaultPropertySize, True, AnyPropertyType, &actualType, &actualFormat, &numItems, &bytesAfter, (unsigned char **)&data) != Success) {
	    /* The get failed for some reason */
	    return alreadyGot;
	} else {
	    (void)memcpy(alreadyGot + size, data, numItems);
	    size += numItems;
	    XFree(data);
	}
    }

    return alreadyGot;
}

/* Print the primary selection to standard out and return 0. If the
   primary selection is invalid, print CUT_BUFFER0 to standard out and
   return 0. If any errors occur (no selection in either place, for 
   example), return 1. */
int main(int argc, char *argv[])
{
    Window window;
    Atom selectionAtom = (Atom)0;
    unsigned char *currentSelection = (unsigned char *)0;
    int result;
    int	bytes;

    if ((gDisplay = XOpenDisplay((char *)0)) == (Display *)0) {
	fprintf(stderr, "Couldn't open display %s\n", XDisplayName((char *)0));
	exit(1);
    }

    if ((selectionAtom = XInternAtom(gDisplay, "PRIMARY", 1)) != (Atom)0) {
	/* This window never gets mapped - its simply used as an ID */
	window = XCreateSimpleWindow(gDisplay, DefaultRootWindow(gDisplay), 0, 0, 1, 1, 0, 0, 0);

	/* Get the selection */
	if ((currentSelection = GetSelection(gDisplay, window, selectionAtom)) == (unsigned char *)0) {
	    XConvertSelection(gDisplay, XA_PRIMARY, XA_STRING, XA_CUT_BUFFER0,
			XDefaultRootWindow(gDisplay), CurrentTime);
	    currentSelection = XFetchBytes(gDisplay, &bytes);
	}
    }
    
    if (currentSelection == (unsigned char *)0 || *currentSelection == '\0') {
	XBell(gDisplay, 0);
	XFlush(gDisplay);
	result = 1;
    } else {
	/* Print out the selection *without* appending a new line */
	printf("%s", currentSelection);
	result = 0;
    }

    XCloseDisplay(gDisplay);

    return result;
}

---

From: Pete Forman <[email-masked]>
Date: Tue, 9 Mar 1999 10:11:10 GMT

Matthias Clasen writes:
 > > > 
 > > > OK, I didn't add FvwmEval. This functionality doesn't need a
 > > > module anyway. I turned it into a small utility xselection
 > > > which prints the content of the X selection to stdout. Use it
 > > > with PipeRead.
 > > > 
 > > 
 > > I didn't look to closelly at your patch but this will get the
 > > xselection for you in a script
 > > 
 > Almost. It turns out that xprop converts newlines in string
 > properties in "\n". I just couldn't come up with a sed command that
 > would replace "\n" with a newline. sed -e 'y/\\n/\

That is indeed ugly as not all versions of echo support -e.
Here is a solution for sed, wrapped up in an example.

#!/bin/sh
s='abc\\ndef\\nghi'

echo $s | od -c

echo $s | sed 's/\\n/\
/g' | od -c

This results in

0000000    a   b   c   \   n   d   e   f   \   n   g   h   i  \n
0000016
0000000    a   b   c  \n   d   e   f  \n   g   h   i  \n
0000014

-- 
Pete Forman
Western Geophysical
[email-masked]

---

From: Dominik Vogt <[email-masked]>
Date: Tue, 9 Mar 1999 10:34:15 +0100

> Here is a solution for sed, wrapped up in an example.

Unfortonately not all versions of sed support quoting a newline like
this either. Sometimes (e.g. on my HP-UX) you have to say

  sed 's/\\n/\n/g'

Bye

Dominik

-- 
Dominik Vogt, Hewlett-Packard GmbH, Dept. BVS
Herrenberger Str.130, 71034 Boeblingen, Germany
phone: 07031/14-4596, fax: 07031/14-3883, [email-masked]
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Pete Forman <[email-masked]>
Date: Tue, 9 Mar 1999 11:41:29 GMT

> this either. Sometimes (e.g. on my HP-UX) you have to say

Oh dear.  That syntax is no good for my versions of sed.  The
following might be more portable, as well as uglier.  Yes that is a
literal BEL (hex 07) in the sed argument.

#!/bin/sh
s='abc\\ndef\\nghi'

echo $s | od -c

echo $s | sed 's/\\n//g' | tr '\007' '\012' | od -c

The sed argument in hex is 73 2f 5c 5c 6e 2f 07 2f 67.
The tr arguments in hex are 5c 30 30 37 and 5c 30 31 32.

I rather suspect that the bottom line is that a portable shell script
would be too complex.

---

From: Mikhael Goikhman <[email-masked]>
Date: Tue, 9 Mar 1999 19:58:00 +0200 (IST)

> xprop -root CUT_BUFFER0 | sed 's/^.*=..\(.*\).$/\1/'

This is wrong (works for simple cases only).
It doesn't work when a selection has one of these chars: backslash, quote,
newline or equal.
Here is more correct version:

xprop -root CUT_BUFFER0 | sed 's/^CUT_BUFFER0(STRING) = "\(.*\)"$/\1/' \
 | sed 's/\\n/^G/g' | sed 's/\\\(["\\]\)/\1/g' | tr '\007' '\012'

where ^G is BEL (hex 07) (type ^V ^G in the shell).
This must work with any version of sed and with any shell.

Migo.

---

From: Pete Forman <[email-masked]>
Date: Wed, 10 Mar 1999 11:29:16 GMT

> This must work with any version of sed and with any shell.

Why use three sed processes?  Either of the following should work.

xprop -root CUT_BUFFER0 | sed -e 's/^CUT_BUFFER0(STRING) = "\(.*\)"$/\1/' \
 -e 's/\\n//g' -e 's/\\\(["\\]\)/\1/g' | tr '\007' '\012'

xprop -root CUT_BUFFER0 |
  sed 's/^CUT_BUFFER0(STRING) = "\(.*\)"$/\1/;s/\\n//g;s/\\\(["\\]\)/\1/g' |
  tr '\007' '\012'

On the second, append trailing backslashes if using csh.