#!/bin/sh 

# Some time ago, Martin Kraemer <Martin.Kraemer@mch.sni.de> posted an
# incomplete script to convert fvwm-1 'rc' files to fvwm-2. I've just
# recently fixed and enhanced that script; it's complete (or nearly
# so) now. This should help if you choose to convert.
# 
# I've also made a couple of other minor changes to make life easier
# for our users here: I changed the default initialization from "Read
# .fvwmrc" to "Read .fvwm2rc" (in fvwm/fvwmc), and I installed fvwm 2
# as "fvwm2". With these changes, users can easily convert at their
# leisure.
# 
# Herewith the script. It's using GNU awk (gawk), but will run with
# any "new" awk (nawk on Suns (SunOS 4, Solaris), awk on most other
# systems). If you do not use gawk, it will be case-sensitive (the
# case of the fvwm commands must match those in the script
# exactly). With gawk, it'll be case-insensitive.

# It's not perfect: some old commands slip through, especially in the
# context of Mouse and Key commands.  But it provides a good basis on
# which to go further.

#
# Convert fvwm 1.x configuration file to 2.2 configuration file
#
# Originally written by Martin Kraemer <Martin.Kraemer@mch.sni.de>
# Corrected, extended, and modified by Grant McDorman <grant@isgtec.com>
# 24 May 95
# Additional corrections and extensions by Bill Oswald <wamo@vnet.ibm.com>
# 8 Mar 96 thru 18 Jul 96
# Minor corrections to make it easier to customize by Charles Hines 08/01/96
# Further minor corrections by Julian Gilbey <jdg@debian.org> based on those
# of Austin Donnelly <and1000@debian.org>, 1 Mar 1999
# Further major corrections by Julian Gilbey <jdg@debian.org>, 3 Mar 1999
# and minor corrections March - May 1999.
# Correct some major gaffs: Julian Gilbey, January 2000, with thanks to
# Victor Meghesan <victorm@genesys.ro>

echo "fvwmrc-to-fvwm2rc" >&2

# gawk has IGNORECASE, so we use it if possible.
if [ -n `command -v gawk 2>/dev/null` ]
then
   AWK=`command -v gawk`
elif [ -x /usr/bin/gawk ]
then
   AWK=/usr/bin/gawk
elif [ -n `command -v awk 2>/dev/null` ]
then
   AWK=`command -v awk`
elif [ -x /usr/bin/awk ]
then
   AWK=/usr/bin/awk
fi

if [ ! -x $AWK ];then
   echo "Can't find any awk, cannot run!" >&2
   exit 1
fi

source=${1:-$HOME/.fvwmrc}
if [ ! -r $source ] ; then
	echo "Can't find source file $source, giving up" >&2
	exit 1
fi

dest=${2:-$HOME/.fvwm2rc}
if [ "$dest" != "-" ] ;then
	echo "Output to $dest" >&2
	if [ -f $dest ] ; then
	  echo "Saving existing $dest as $dest.bak" >&2
	  cp -p $dest $dest.bak || { echo "Couldn't save; aborting" >&2; exit 1; }
	else
	  cp -p $source $dest 2>/dev/null  # try to preserve permissions
	fi
	exec >$dest || { echo "Couldn't write to $dest, aborting" >&2; exit 1; }
	TTY=`tty`
	if [ ! -w "$TTY" ] ;then
	  TTY=/dev/stderr
	fi
else
	TTY=/dev/stderr
fi
if [ ! -w "$TTY" ] ;then
	TTY=/dev/null
fi

cat $source | $AWK '
BEGIN   {
        printf ("# Trying to compile an old .fvwrc to the new fvwm-2.xx Format\n");
	TRUE=1; FALSE=0;

	IGNORECASE=TRUE;

	hiforecolor="";             dflt["hiforecolor"] = "black";
	hibackcolor="";             dflt["hibackcolor"] = "CadetBlue";
	hilightcolor = FALSE;

	stdforecolor="";            dflt["stdforecolor"] = "black";
	stdbackcolor="";            dflt["stdbackcolor"] = "grey70";

	inpopup=FALSE;
	infunction=FALSE;
	prefix="";

        placement = FALSE;           dflt["placement"] = "ActivePlacement, DumbPlacement"
}

/^[ \t]*#/			{   # Comment, pass it thru
        print $0;
	next;
}

/^[ \t]*$/                            {   # Empty line, pass it thru
	print $0;
	next;
}
	
################ Rename common items ##############
/Restart/ && /fvwm/             {
	gsub("fvwm", "fvwm2"); gsub("fvwm22","fvwm2"); # try to leave paths alone
}
/GoodStuff/                     { gsub("GoodStuff", "FvwmButtons"); }

############ Chop off trailing "&" from Exec commands ##########
/^Exec[ \t]+/ || /[ \t]+Exec[ \t]+/ { gsub ("\&[ \t]*$",""); }

################ Highlight Colors ##############
/^[ \t]*HiBackColor[ \t]*/	{
        dflt["hibackcolor"]=hibackcolor=$2;
	printf ("#!%s (new command=HilightColor)\n", $0);
	if (hibackcolor != "" && hiforecolor != "" && !hilightcolor) {
           printf ("\n#Set the foreground and background color for selected windows\n");
	   printf ("HilightColor   %s %s\n", hiforecolor, hibackcolor);
	   hilightcolor=TRUE;
        } else
	   hilightcolor=FALSE;
        next;
}

/^[ \t]*HiForeColor[ \t]*/	{
        dflt["hiforecolor"]=hiforecolor=$2;
	printf ("#!%s (new command=HilightColor)\n", $0);
	if (hibackcolor != "" && hiforecolor != "" && !hilightcolor) {
           printf ("\n#Set the foreground and background color for selected windows\n");
	   printf ("HilightColor   %s %s\n", hiforecolor, hibackcolor);
	   hilightcolor=TRUE;
        } else
	   hilightcolor=FALSE;
        next;
}


########## Menu Colors, Style and Font ###########
/^[ \t]*MenuForeColor[ \t]*/	{
	printf ("#!%s\n", $0);
	printf ("MenuStyle * Foreground %s\n", $2);
	next;
}

/^[ \t]*MenuBackColor[ \t]*/	{
	printf ("#!%s\n", $0);
	printf ("MenuStyle * Background %s\n", $2);
	next;
}

/^[ \t]*MenuStippleColor[ \t]*/	{
	printf ("#!%s\n", $0);
	printf ("MenuStyle * Greyed %s\n", $2);
	next;
}

/^[ \t]*MWMMenus[ \t]*/		{
	printf ("#!%s\n", $0);
	printf ("MenuStyle * mwm\n");
	next;
}

/^[ \t]*Font[ \t]*/		{
	printf ("#!%s\n", $0);
	printf ("MenuStyle * Font %s\n", $2);
	next;
}


# Translate both old ButtonStyle formats to the new format:
/^[ \t]*ButtonStyle[ \t]*/	{
        if ($2 == ":") {  # new style already
           if (NF != $4+4)
	       print "ERROR: ButtonStyle command incorrect\n" NR ": " $0 >"'$TTY'";
	   printf ("%s %d %d", $1, $3, $4);
	   for (i=5; i<=NF; ++i)
	       printf (" %s", $i);
	   printf ("\n");
	} else {
           print "Note: Conversion of old ButtonStyle; values rounded" \
			>"'$TTY'"
	   printf ("#!         Old line was: %s\n", $0);
	   p=index ($3,"x");
	   x=substr($3,1,p-1)/2;
	   y=substr($3,p+1)/2;
	   printf ("%s %s 5 %dx%d@0 %dx%d@0 %dx%d@0 %dx%d@1 %dx%d@1\n",
		    $1, $2, 50-x,50+y, 50+x,50+y, 50+x,50-y, 50-x,50-y,
		    50-x,50+y);
	}
	next;
}

########## Standard Colors ###########
/^[ \t]*StdForeColor[ \t]*/	{
        dflt["stdforecolor"]=stdforecolor=$2;
	printf ("#!%s (new command=Style \"*\" Color f/b)\n", $0);
	print "Style \"*\" ForeColor " $2;
	next;
}

/^[ \t]*StdBackColor[ \t]*/	{
	dflt["stdbackcolor"]=stdbackcolor=$2;
	printf ("#!%s (new command=Style \"*\" Color f/b)\n", $0);
	print "Style \"*\" BackColor " $2;
	next;
}

########## Icon Related Stuff ##########
/^[ \t]*IconBox[ \t]*/		{ print "Style \"*\" " $0; next; }
/^[ \t]*IconFont[ \t]*/		{ print $0; next; }
/^[ \t]*SuppressIcons[ \t]*/	{ print "Style \"*\" NoIcon"; next; }
/^[ \t]*StickyIcons[ \t]*/	{ print "Style \"*\" StickyIcon"; next; }
/^[ \t]*ModulePath[ \t]*/	{ print "#! (ModulePath command commented out)\n#" $0; next; }
/^[ \t]*PixmapPath[ \t]*/	{ print $0; next; }
/^[ \t]*IconPath[ \t]*/		{ print $0; next; }
# note: Icon must be followed by some white space
/^[ \t]*Icon[ \t]+/		{ printf "Style %s Icon %s\n", $2, $3; next; }

########## MWM hints ##########
/^[ \t]*MWMFunctionHints[ \t]*/	{ printf ("Style \"*\" MWMFunctions\n"); next; }
/^[ \t]*MWMDecor[ \t]*/		{ printf ("Style \"*\" MWMDecor\n"); next; }
/^[ \t]*MWMDecorHints[ \t]*/	{ printf ("Style \"*\" MWMDecor\n"); next; }
/^[ \t]*MWMBorders[ \t]*/	{ printf ("Style \"*\" MWMBorder\n"); next; }
/^[ \t]*MWMButtons[ \t]*/	{ printf ("Style \"*\" MWMButtons\n"); next; }
/^[ \t]*MWMHintOverride[ \t]*/	{ printf ("Style \"*\" HintOverride\n"); next; }

########## Placement & Focus styles ##########
/^[ \t]*RandomPlacement[ \t]*/	{ print "Style \"*\" " $0; placement = TRUE; next; }
/^[ \t]*SmartPlacement[ \t]*/	{ print "Style \"*\" " $0; placement = TRUE; next; }
/^[ \t]*Sticky(Back|Fore)Color[ \t]*/ {
      print "#! " $0 " (not supported in FVWM2)"; next;
}
/^[ \t]*Sticky[ \t]+/		{ printf "Style \"%s\" Sticky\n", $2; next; }
/^[ \t]*NoPPosition[ \t]*/	{ print "Style \"*\" " $0; next; }
/^[ \t]*ClickToFocus[ \t]*/	{ print "Style \"*\" " $0; next; }
/^[ \t]*SloppyFocus[ \t]*/	{ print "Style \"*\" " $0; next; }
/^[ \t]*StaysOnTop[ \t]*/	{ printf "Style \"%s\" StaysOnTop\n", $2; next; }
/^[ \t]*AutoRaise[ \t]*/		{
        print "#! " $0 " (use Module FvwmAuto)";
	print "AddToFunc \"InitFunction\" \"I\" Module FvwmAuto " $2;
	print "AddToFunc \"RestartFunction\" \"I\" Module FvwmAuto " $2;
	next;
}

########## Decoration styles ##########
/^[ \t]*BorderWidth[ \t]*/	{ print "Style \"*\" " $0; next; }
/^[ \t]*HandleWidth[ \t]*/	{ print "Style \"*\" " $0; next; }
/^[ \t]*DecorateTransients[ \t]*/ { print "Style \"*\" DecorateTransient"; next; }
/^[ \t]*XORvalue[ \t]*/		{ print $0; next; }
/^[ \t]*BoundaryWidth[ \t]*/	{ printf "Style \"*\" HandleWidth %s\n", $2; next; }
/^[ \t]*NoBoundaryWidth[ \t]*/	{ print "Style \"*\" BorderWidth " $2; next; }
/^[ \t]*NoTitle[ \t]*/		{ print "Style \"*\" " $0; next; }
/^[ \t]*NoBorder[ \t]*/		{ print "Style \"*\" " $0; next; }



########## Etc ##########
/^[ \t]*Lenience[ \t]*/		{ print "Style \"*\" " $0; next; }
/^[ \t]*Style[ \t]*/		{ print $0; next; }
# Key keyname context mods (Exec|Module|Restart) ...
#  used to be followed by a "name"; it is no longer
/^[ \t]*Key[ \t]+[^ \t]+[ \t]+[^ \t]+[ \t]+[^ \t]+[ \t]+(Exec|Module|Restart)[ \t]+\"/  {
	# not going to handle escaped quotes
	label=$6;
	first=7;
	quoted=substr(label, 1, 1)=="\"" &&
		substr(label, length(label), 1)!="\"";
	for (i=7;i<=NF && quoted;i++) {
		label=$i;
		quoted=substr(label, length(label), 1)!="\"";
		first=i + 1;
	}
	printf ("%s %s %s %s %s", $1, $2, $3, $4, $5);
	for (i=first; i<=NF; ++i)
		printf (" %s", $i);
	printf ("\n");
	next;
}
# Any other Key command
/^[ \t]*Key[ \t]*/		{ print $0; next; }

# Similarly with Mouse commands
/^[ \t]*Mouse[ \t]+[^ \t]+[ \t]+[^ \t]+[ \t]+[^ \t]+[ \t]+(Exec|Module|Restart)[ \t]+\"/  {
	# not going to handle escaped quotes
	label=$6;
	first=7;
	quoted=substr(label, 1, 1)=="\"" &&
		substr(label, length(label), 1)!="\"";
	for (i=7;i<=NF && quoted;i++) {
		label=$i;
		quoted=substr(label, length(label), 1)!="\"";
		first=i + 1;
	}
	printf ("%s %s %s %s %s", $1, $2, $3, $4, $5);
	for (i=first; i<=NF; ++i)
		printf (" %s", $i);
	printf ("\n");
	next;
}

/^[ \t]*Mouse[ \t]*/		{ print $0; next; }
# This is probably not necessary
# /^[ \t]*Mouse[ \t]*/		{
# 		 if (sub("[ \t]Pop[uU]p[ \t]", " Menu ")) {
# 			  if (!warn["Mouse"]) {
# 			 print "Note: Setting mouse bindings to sticky menus">"'$TTY'";
# 			 warn["Mouse"] = TRUE;
# 			  }
# 			  sub("$", " Nop");
# 		 }
# 		 print $0; next;
# }

/^[ \t]*WindowListSkip[ \t]*/	{ printf "Style %s WindowListSkip\n", $2; next; }
/^[ \t]*WindowFont[ \t]*/	{ print $0; next; }
/^[ \t]*ClickTime[ \t]*/	{ print $0; next; }
/^[ \t]*OpaqueMove[ \t]*/	{ print "OpaqueMoveSize " $2; next; }
/^[ \t]*EdgeScroll[ \t]*/	{ print $0; next; }
/^[ \t]*EdgeResistance[ \t]*/	{ print $0; next; }
/^[ \t]*DeskTopSize[ \t]*/	{ print $0; next; }
/^[ \t]*DeskTopScale[ \t]*/	{
	printf ("#!%s (new command=*FvwmPagerDeskTopScale <scale>)\n", $0);
	print "*FvwmPagerDeskTopScale " $2;
	next;
}

/^[ \t]*FvwmButtons[ \t]*/	{
	sub("[ 	]Swallow[ 	]*[^ 	]*", "& Exec");
	print $0;
	if (length($0) > 199)
	{
	    print "Warning: line" NR "too long" >"'$TTY'";
	    print ">> " $0 >"'$TTY'";
	}
	if (!warn["GoodStuff"])
	{
	    print "Note: GoodStuff renamed to FvwmButtons" >"'$TTY'";
	    print "Note: FvwmButtons syntax may now be wrong; please check!" >"'$TTY'";
	    warn["GoodStuff"]=TRUE;
	}
	next;
}

/^\*/				{
        # other Module Configuration commands are passed thru
	print $0;
	next;
}

# hack: Modules spawned outside of a function, menu, or popup cannot have leading whitespace.
# add these to the initfunction
/^Module[ \t]*/                 { printf "AddToFunc \"InitFunction\" \"I\" %s \n", $0; next; }

# hack: function declarations cannot have leading whitespace
/^Function[ \t]*/		{
	if (inpopup)
	   print "ERROR: EndPopup missing\n" NR ": " $0 >"'$TTY'";
	inpopup=FALSE;
	if (infunction)
	   print "ERROR: EndFunction missing\n" NR ": " $0 >"'$TTY'";
	infunction=TRUE;
	prefix="AddToFunc " $2;
	next;
}

/^[ \t]*EndFunction[ \t]*/	{
        if (!infunction)
           print "ERROR: EndFunction outside of function" >"'$TTY'";
	infunction=FALSE;
	prefix="";
	next;
}

# hack: popup declarations cannot have leading whitespace
/^Popup/                        {
        if (inpopup) 
	   print "ERROR: EndPopup missing\n" NR ": " $0 >"'$TTY'";
        if (infunction)
	   print "ERROR: EndFunction missing\n" NR ": " $0 >"'$TTY'";
        infunction=FALSE;
	inpopup=TRUE;

	label=$2;
	if (index($2, "\"") == 1) {
	   # not going to handle escaped quotes
	   first=3;
	   quoted=substr(label, 1, 1)=="\"" &&
	      substr(label, length(label), 1)!="\"";
	   for (i=3;i<=NF && quoted;i++) {
	      label=label " " $i;
	      quoted=substr(label, length(label), 1)!="\"";
	      first=i + 1;
	   }
	}

	prefix="AddToMenu " label;
	next;
}

/^[ \t]*EndPopup[ \t]*/		{
        if (!inpopup)
	   print "ERROR: EndPopup outside of popup\n" NR ": " $0 >"'$TTY'";
        inpopup=FALSE;
	prefix="";
	next;
}



########## Deleted Commands ##########
/^[ \t]*DontMoveOff[ \t]*/	||
/^[ \t]*BackingStore[ \t]*/	||
/^[ \t]*AppsBackingStore[ \t]*/	||
/^[ \t]*SaveUnders[ \t]*/	||
/^[ \t]*StubbornIcons[ \t]*/	||
/^[ \t]*StubbornIconPlacement[ \t]*/ ||
/^[ \t]*StubbornPlacement[ \t]*/     ||
/^[ \t]*Cursor[ \t]*/		{ 
	print "#! " $0 " [deleted]";
	if (warned[$1]==FALSE) {
	   print "Warning: " $1 " not in Fvwm2, command dropped" >"'$TTY'";
	   warned[$1] = TRUE;
	}
	next;
}

/^[ \t]*Pager[ \t]*/		{
	print "#! " $0 " [deleted]";
	print "#! An FvwmPager config to emulate builtin pager would be as follows:"
	print "# *FvwmPagerBack SlateGrey";
	print "# *FvwmPagerFore Black";
	print "# *FvwmPagerFont none";
	print "# *FvwmPagerHilight SlateBlue4";
	print "# *FvwmPagerGeometry <xsize> <ysize>";
	print "# *FvwmPagerSmallFont -*-times-medium-r-*-*-*-80-*-*-*-*-*-*";
	print "# *FvwmPagerDeskTopScale 32";
	print "# #! Now start pager";
	print "# Module FvwmPager 0 0";
	if (warned[$1]==FALSE) {
           print "Warning: " $1 " omitted, internal pager is obsolete (use FvwmPager)" >"'$TTY'";
	   warned[$1] = TRUE;
	}
	next;
}

/^[ \t]*PagingDefault[ \t]*/	||
/^[ \t]*TogglePage[ \t]*/	{
        print "#! " $0 " (use EdgeScroll 0 0)"; next;
	print "Warning: " $1 " not in Fvwm2, use EdgeScroll">"'$TTY'";
}

########## Old Internal Pager Colors ###########
/^[ \t]*PagerForeColor[ \t]*/	||
/^[ \t]*PagerBackColor[ \t]*/	{
	printf ("#!%s (new command=Style FvwmPager Color fore_color/back_color)\n", $0);
	if (warned[$1]==FALSE) {
           print "Warning: " $1 " omitted, internal pager is obsolete (use FvwmPager)" >"'$TTY'";
	   warned[$1] = TRUE;
	}
	next;
}

########## Sticky Colors ###########
/^[ \t]*StickyForeColor[ \t]*/	{
	printf ("#!%s (no sticky foreground color in fvwm2)\n", $0);
	if (warned[$1]==FALSE) {
	   print "Warning: StickyForeColor not in fvwm2, omitted" > "'$TTY'"
           print "         Use the Style command to assign each sticky window the same ForeColor" > "'$TTY'"
        }
	next;
}

/^[ \t]*StickyBackColor[ \t]*/	{
	printf ("#!%s (no sticky background color in fvwm2)\n", $0);
	if (warned[$1]==FALSE) {
	   print "Warning: StickyBackColor not in fvwm2, omitted" >"'$TTY'"
           print "         Use the Style command to assign each sticky window the same BackColor" > "'$TTY'"
        }
	next;
}


{
    if (infunction) {
        #gsub("[ 	]PopUp[ 	]", " "); }
	if ($2 == "\"Motion\"")
	    context="\"M\"";
	else if ($2 == "\"Click\"")
	    context="\"C\"";
	else if ($2 == "\"DoubleClick\"")
	    context="\"D\"";
	else if ($2 == "\"Immediate\"")
	    context="\"I\"";
	else context=$2;
		printf "%s", prefix " " context " " $1;
	for (i=3; i<=NF; ++i)
	    printf (" %s", $i);
	printf ("\n");
	prefix="+             ";
	next;
    } else if (inpopup) {
	# not going to handle escaped quotes
	label=$2;
	first=3;
	quoted=substr(label, 1, 1)=="\"" &&
		substr(label, length(label), 1)!="\"";
	for (i=3;i<=NF && quoted;i++) {
	    label=label " " $i;
	    quoted=substr(label, length(label), 1)!="\"";
	    first=i + 1;
	}
	printf ("%s %s %s", prefix, label, $1);
	for (i=first; i<=NF; ++i)
	    printf (" %s", $i);
	printf ("\n");
	prefix="+             ";
	next;
    }

    if (warned[$1]==FALSE) {
	printf ("#!Warning: Keyword \"%s\" not handled yet\n", $1);
	warned[$1]=TRUE;
	print "Warning: Unknown keyword "$1" passed through">"'$TTY'";
    }
    print $0;
    next;
}

END {
    if (!hilightcolor) {
	printf ("\n#Set the foreground and background color for selected windows\n");
	printf ("HilightColor   %s %s\n", dflt["hiforecolor"], dflt["hibackcolor"]);
    }
    if (!placement) {
        printf "# overide default RandomPlacement and SmartPlacement Styles\n";
        printf "Style \"*\" %s\n", dflt["placement"];
    }
}
'
exit

