Subject: FVWM: WindowList feature, SortLastWord

From: David Fries <[email-masked]>
Date: Sat, 18 May 2002 17:35:41 -0500

I made a patch and put up a web page (patch included).
http://fries.net/~david/fvwm/

I noticed that a good number of the programs out there list the name
of the program as the last word on their title.  I wanted a way to
group programs in the WindowList.  The Alphabetic option to WindowList
can't do this since it always starts at the beginning of the title, so
I added an option SortLastWord which when used with the Alphabetic
option will sort the entries based on the last word and then start at
the front if the last word matches.  

The patch is applied against today's fvwm CVS tree.  I do have a
couple questions.  I used the variable pscratch in the WindowList, but
I wasn't sure if I had to do anything special becides freeing the
memory before I exited, or do I need to zero it last?

What's the difference between safemalloc and malloc and do I need to
check to see if it succeeded?

Does it sound reasonable to require Alphabetic to use SortLastWord?

If someone could answer my questions I'll attack the gtk version as
well as the fvwm man page and then submit it again.

-- 
		+---------------------------------+
		|      David Fries                |
		|      [email-masked]        |
		| http://fries.net/~david/pgp.txt |
		+---------------------------------+
Index: fvwm/windowlist.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/windowlist.c,v
retrieving revision 1.59
diff -u -r1.59 windowlist.c
--- fvwm/windowlist.c	2002/04/30 11:17:16	1.59
+++ fvwm/windowlist.c	2002/05/18 20:01:04
@@ -59,22 +59,42 @@
 #define NO_DESK_SORT            (1<<6)
 #define SHOW_ICONNAME           (1<<7)
 #define SHOW_ALPHABETIC         (1<<8)
-#define SHOW_INFONOTGEO         (1<<9)
-#define NO_DESK_NUM             (1<<10)
-#define NO_CURRENT_DESK_TITLE   (1<<11)
-#define TITLE_FOR_ALL_DESKS     (1<<12)
-#define NO_NUM_IN_DESK_TITLE    (1<<13)
+#define SHOW_SORT_LASTWORD	(1<<9)
+#define SHOW_INFONOTGEO         (1<<10)
+#define NO_DESK_NUM             (1<<11)
+#define NO_CURRENT_DESK_TITLE   (1<<12)
+#define TITLE_FOR_ALL_DESKS     (1<<13)
+#define NO_NUM_IN_DESK_TITLE    (1<<14)
 #define SHOW_EVERYTHING (SHOW_GEOMETRY | SHOW_ALLDESKS | SHOW_NORMAL | SHOW_ICONIC | SHOW_STICKY)
 
 /* Function to compare window title names
+ * pscratch will contain the name to compare
+ * At the time of writing it could be one of visible_icon_name, visible_name
+ * 	and the added last word of one of the two so we can sort on the
+ * 	program name when the program name is the last word of the title.
+ * 05-18-2002 David Fries <[email-masked]>
  */
 static int globalFlags;
+static int winCompareLast(const  FvwmWindow **a, const  FvwmWindow **b)
+{
+	int result=strcasecmp((char*)((*a)->pscratch),(char*)((*b)->pscratch));
+	/* If we have an ordering with just the last word go with it. */
+	if(result)
+		return result;
+
+	/* compare the full name */
+	if(globalFlags & SHOW_ICONNAME)
+		return strcasecmp((*a)->visible_icon_name,
+			(*b)->visible_icon_name);
+	return strcasecmp((*a)->visible_name, (*b)->visible_name);
+}
+static int winCompareReverseLast(const  FvwmWindow **a, const  FvwmWindow **b)
+{
+  return -winCompareLast(a, b);
+}
 static int winCompare(const  FvwmWindow **a, const  FvwmWindow **b)
 {
-  if(globalFlags & SHOW_ICONNAME)
-    return strcasecmp((*a)->visible_icon_name,(*b)->visible_icon_name);
-  else
-    return strcasecmp((*a)->visible_name,(*b)->visible_name);
+    return strcasecmp((char*)((*a)->pscratch),(char*)((*b)->pscratch));
 }
 static int winCompareReverse(const  FvwmWindow **a, const  FvwmWindow **b)
 {
@@ -222,6 +242,10 @@
         flags &= ~SHOW_ALPHABETIC;
       else if (StrEquals(tok,"Alphabetic"))
         flags |= SHOW_ALPHABETIC;
+      else if (StrEquals(tok,"NotSortLastWord"))
+        flags &= ~SHOW_SORT_LASTWORD;
+      else if (StrEquals(tok,"SortLastWord"))
+        flags |= SHOW_SORT_LASTWORD;
       else if (StrEquals(tok,"ReverseOrder"))
         do_reverse_sort_order = True;
       else if (StrEquals(tok,"CurrentAtEnd"))
@@ -348,7 +372,6 @@
   }
   globalFlags = flags;
 
-
   tlabel = get_desk_title(desk, flags, True);
   mr = NewMenuRoot(tlabel);
   if (!(flags & NO_CURRENT_DESK_TITLE))
@@ -412,16 +435,77 @@
   /* Do alphabetic sort */
   if (flags & SHOW_ALPHABETIC)
   {
-    if (do_reverse_sort_order)
-    {
-      qsort(windowList,numWindows,sizeof(t),
-	    (int(*)(const void*,const void*))winCompareReverse);
-    }
-    else
-    {
-      qsort(windowList,numWindows,sizeof(t),
-	    (int(*)(const void*,const void*))winCompare);
-    }
+  	if (flags & SHOW_SORT_LASTWORD )
+	{
+		int offset;
+		int length;
+		const char * src;
+		for( ii=0; ii<numWindows; ii++)
+		{
+			offset=0;
+			length=0;
+
+			if(flags & SHOW_ICONNAME)
+				src=windowList[ii]->visible_icon_name;
+			else
+				src=windowList[ii]->visible_name;
+
+			for( ij=0; src[ij]; ij++)
+			{
+				if(src[ij]==' ')
+				{
+					/* After the space */
+					offset=ij+1;
+					length=0;
+				}
+				else
+					length++;
+			}
+			windowList[ii]->pscratch=safemalloc(length+1);
+
+			if(flags & SHOW_ICONNAME)
+				strcpy(windowList[ii]->pscratch, offset+
+					windowList[ii]->visible_icon_name);
+			else
+				strcpy(windowList[ii]->pscratch, offset+
+					windowList[ii]->visible_name);
+		}
+		if (do_reverse_sort_order)
+		{
+			qsort(windowList,numWindows,sizeof(t),
+				(int(*)(const void*,const void*))
+					winCompareReverseLast);
+		}
+		else
+		{
+			qsort(windowList,numWindows,sizeof(t),
+				(int(*)(const void*,const void*))
+					winCompareLast);
+		}
+		for( ii=0; ii<numWindows; ii++)
+			free(windowList[ii]->pscratch);
+	}
+	else
+	{
+		if(flags & SHOW_ICONNAME)
+			for( ii=0; ii<numWindows; ii++)
+				windowList[ii]->pscratch=
+					windowList[ii]->visible_icon_name;
+		else
+			for( ii=0; ii<numWindows; ii++)
+				windowList[ii]->pscratch=
+					windowList[ii]->visible_name;
+		if (do_reverse_sort_order)
+		{
+			qsort(windowList,numWindows,sizeof(t),
+			  (int(*)(const void*,const void*))winCompareReverse);
+		}
+		else
+		{
+			qsort(windowList,numWindows,sizeof(t),
+				(int(*)(const void*,const void*))winCompare);
+		}
+	}
   }
 
   while(next_desk != INT_MAX)

---

From: David Fries <[email-masked]>
Date: Sat, 18 May 2002 19:33:01 -0500

Ok, so I really didn't need any dynamic memory.  Everything else still
applies, comments?

+++ fvwm/windowlist.c	2002/05/19 00:26:38

-
@@ -412,16 +435,63 @@
+			windowList[ii]->pscratch=src+offset;

---

From: Mikhael Goikhman <[email-masked]>
Date: Sun, 19 May 2002 01:23:30 +0000

> the front if the last word matches.  

Well, you may already separate applications (and sorts them) depending on
their patterns using FvwmIconMan. See also FvwmIconMan Transient option.

Another note, other WindowList boolean options don't have their opposites,
so NotSortLastWord (a better name is SortLastWordOff) is not needed.

> memory before I exited, or do I need to zero it last?

It is better to avoid hacks, but it seems that pscratch usage is ok here.

> check to see if it succeeded?

This is a difference, you don't need to check its status.

> Does it sound reasonable to require Alphabetic to use SortLastWord?

Not to me. Most of programs (all that I use) don't put their name at the
end, some put it at the beginning. This would break Alphabetic completely.

> well as the fvwm man page and then submit it again.

If you mean FvwmGtk, it is currently broken in cvs, but there is also
FvwmWinList. :-)

Post new patches to fvwm-workers. Quoting old patches is not needed.

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

---

From: Mikhael Goikhman <[email-masked]>
Date: Sun, 19 May 2002 02:20:30 +0000

On 19 May 2002 01:23:30 +0000, Mikhael Goikhman wrote:
> 
> If you mean FvwmGtk, it is currently broken in cvs

I just fixed it from crash, but there are no mini icons.

Regards,
Mikhael.