### Copyright (C) 1995, 1996, 1997 Jeppe Buk (buk@imada.sdu.dk)
### This program is free software; you can redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation; either version 2 of the License, or
### (at your option) any later version.
###
### This program is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with this program; if not, write to the Free Software
### Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

######################################################################
# Convert a list of contexts/modifiers to a context/modifier string
proc makeContextOrModifier {contextList} {
  set result {}
  foreach var $contextList {
    append result [string index $var 0]
  }
  if {$result == {}} {set result "N"}
  if {[string first "A" $result] != -1 && [string length $result] != 1} {
    set result "A"
  }
  return $result
}

######################################################################
# Make a command be backgrounded
proc makeBg {prog} {
  set result [string trim $prog " \t"]
  if {[string index $result [expr [string length $result] -1]] != "&"} {
    append result " &"
  }
  return $result
}

######################################################################
# Sign an integer
proc signed {val} {
  if {$val == ""} {return ""}
  if {[string index $val 0] != "-"} {return "+$val"
  } else {return $val}
}

######################################################################
# Convert old style X colors #RRGGBB to new style rgb:RR/GG/BB
proc hash2rgb {hash} {
  if {[string index $hash 0] == "#"} {
    set rgb "rgb:[string range $hash 1 2]/[string range $hash 3 4]/[string range $hash 5 6]"
  } else {
    if {[string first " " $hash] != -1} {set rgb \"$hash\"
    } else {set rgb $hash}
  }
  return $rgb
}

######################################################################
# Remove color names consisting of more than one word
proc fixcolors {cols} {
  set result {}
  foreach col $cols {
    if {[llength [lindex $col 0]] == 1} {
      lappend result $col
    }
  }
  return $result
}

######################################################################
# The builtin commands including help
#
set Builtins {

  Beep
  "Example: 'Beep'. Makes the terminal beep. This command takes no\
 additional arguments."

  ChangeDecor
  "Example: 'ChangeDecor \"Default\"'. Changes the decor of the current\
 window. This command takes the name of a decor as argument. The special\
 decor name Default resets all decor attributes of the window."

  Close
  "Example: 'Close'. Close the current window. This command takes no\
 additional arguments."

  CursorMove
  "Example: 'CursorMove 10 0'. Move the cursor. This command takes two\
 additional arguments meaning the horizontal and vertical distance (in\
 percent of the screen size) to move the cursor."

  Delete
  "Example: 'Delete'. Delete the current window. This command takes no\
 additional arguments."

  Desk
  "Example: 'Desk 0 2'. Change to another desktop. This command takes two\
 additional arguments. If the first argument is non-zero then the next\
 desktop number will be  the  current  desktop  number  plus that number.\
 If the first argument is zero then the new desktop number will be the\
 second argument."

  Destroy
  "Example: 'Destroy'. Remove the current window in a sure but violent way.\
 This command takes no additional arguments."

  DestroyDecor
  "Example: 'DestroyDecor \"Flattened\"'. Deletes a previously defined\
 decor. This command takes the name of a decor as argument."

  DestroyFunc
  "Example: 'DestroyFunc \"PrintFunction\"'. Delete a function definition.\
 This command takes a function name as argument."

  DestroyMenu
  "Example: 'DestroyMenu \"Utilities\"'. Delete a menu definition. This\
 command takes a menu name as argument."

  DestroyModuleConfig
  "Example: 'DestroyModuleConfig FvwmButtons'. Delete module configuration.\
 This command takes a module name as argument."

  Echo
  "Example: 'Echo Beginning style defs...'. Print a message to stderr.\
 This command takes the string to print as argument."

  Exec
  "Example: 'Exec rxvt -fg yellow -bg blue -e /bin/tcsh'. Execute an\
 external command. This command takes the command as argument."

  ExecUseShell
  "Example: 'ExecUseShell /bin/tcsh'. Specify which shell to use in Exec's.\
 If this command is given an argument this will be the shell to use,\
 otherwise FVWM will use the value of \$SHELL."

  Focus
  "Example: 'Focus'. Gives focus to the current window. This command takes\
 no additional arguments."

  Function
  "Example: 'Function MoveOrRaise'. Call a user defined function. This\
 command takes a function name as argument."

  GotoPage 
  "Example: 'GotoPage 0 1'. Move the desktop viewport to another page. This\
 command takes two arguments, the x and y coordinate. Don't use this command\
 in a pop-up menu."

  Iconify
  "Example: 'Iconify -1'. (De)Iconify the current window. If no argument is\
 given this command is a toggle between iconified and normal state. If the\
 optional argument is positive only iconification will be allowed, if it is\
 negative only de-iconification will be allowed."

  KillModule
  "Example: 'KillModule FvwmButtons'. Kill modules (wildcards allowed). This\
 command takes a module name as argument."

  Lower
  "Example: 'Lower'. Lower the current window. This command takes no\
 additional arguments."

  Maximize
  "Example: 'Maximize 0 100'. (Un)Maximize the current window. This command\
 takes two optional arguments meaning the horizontal and vertical percentage\
 of the screen to maximize the window to (zero means don't change the size)."

  Menu
  "Example: 'Menu MainMenu'. Pop up a defined menu (and keep it popped up).\
 This command takes the menu name as argument. An addition argument may be\
 specified, giving a command to execute if the user double-clicked while\
 bringing the menu up."

  Module
  "Example: 'Module FvwmBanner'. Spawn an external Fvwm module. This command\
 takes the module name as argument."

  Move
  "Example: 'Move'. Move the current window. If no arguments are specified\
 the movement will be interactive. If the two optional arguments are specified\
 they will specify the distance to move the window in the x and y direction."

  Next
  "Example 'Next \[Emacs\] Iconify -1'. Perform a command on the next window\
 satisfying conditions. Condition include iconic, !iconic, CurrentDesk,\
 Visible, !Visible, and CurrentScreen. This command takes the conditions in\
 brackets and the command as arguments."

  None
  "Example: 'None \[Emacs\] Exec emacs &'. Perform a command if no windows\
 satisfy the conditions. Conditions and arguments are the same as 'Next'."

  Nop
  "Example: 'Nop'. Do nothing - used for separators in menus"

  PipeRead
  "Example: 'PipeRead /usr/local/bin/create_menu'. Read commands outputted\
 from a program. This command reads commands from standard output of the\
 program given as argument."

  Popup
  "Example: 'Popup \"Window Ops\"'. Call a user defined popup menu. This\
 command takes a menu name as argument."

  Prev
  "Example: 'Prev [Emacs] Iconify'. Perform a command on the previous window\
 satisfying conditions. Conditions and arguments are the same as 'Next'."

  Quit
  "Example: 'Quit'. Quit Fvwm (generally causing X to exit as well). This\
 command takes no additional arguments."

  Raise
  "Example 'Raise'. Raise the current window. This command takes no additional\
 arguments."

  RaiseLower
  "Example 'RaiseLower'. Alternately raise and lower the current window. This\
 command takes no additional arguments."

  Read
  "Example: 'Read $HOME/.userfvwm2rc'. Read commands from a file. This command\
 takes a file name as argument."

  Recapture
  "Example: 'Recapture'. Recapture all windows, causing styles to be\
 up-to-date. This command takes no additional arguments."

  Refresh
  "Example: 'Refresh'. Redraw all windows on the screen. This command takes\
 no additional arguments."

  RefreshWindow
  "Example: 'RefreshWindow'. Redraw the current window. This command takes\
 no additional arguments."

  Resize
  "Example: 'Resize'. Resize the current window. With no arguments the\
 resizing will be interactive. This command takes two optional arguments\
 specifying the new dimensions of the window."

  Restart
  "Example: 'Restart fvwm2'. Restart fvwm (or another window manager). This\
 command takes a window manager program as argument."

  SendToModule
  "Example: 'SendToModule FvwmTalk command'. Send a string to a module. This\
 command takes a module name and a string to send as arguments."

  Scroll
  "Example: 'Scroll 100 0'. Scroll the desktops viewport. This command takes\
 two arguments meaning the horizontal and vertical percentage of the screen\
 to scroll the viewport. If the percentages are multiplied by 1000 then\
 scrolling will wrap around at the edge of the desktop."

  Stick
  "Example: 'Stick'. (Un)Stick the current window. This command takes no\
 additional arguments."

  Title
  "Example: 'Title'. Do nothing - used for titles in menus. This command takes\
 no additional arguments."

  UpdateDecor
  "Example: 'UpdateDecor \"Flattened\"'. Updates decorations of windows\
 using a specific decor. This command takes an (optional) decor name as\
 argument. If no argument is given all windows will be updated."

  Wait
  "Example: 'Wait Emacs'. Wait for a window to come up. This command takes a\
 window name as argument."

  WarpToWindow
  "Example: 'WarpToWindow 50 50'. Warp the cursor to a specified window\
 (x,y). This command takes the horizontal and vertical coordinates as\
 arguments."

  WindowId
  "Example: 'WindowId 0x34567890 Raise'. Run a command on a specified\
 window id. This command takes the window id and a function to run as\
 arguments. This is most useful with functions that receive the window id\
 as an argument (e.g. WindowList's Function arg)."

  WindowList
  "Example: 'WindowList NoGeometry CurrentDesk'. Pops up the window list.\
 The (optional) arguments decide the behavior: NoGeometry (exclude geometry\
 information), Function <func> (run <func> instead of the default),\
 Desk <deskno> (only show windows from desk <deskno>), CurrentDesk (only\
 show windows from the current desk), NoIcons/OnlyIcons (exclude or show\
 only iconified windows), NoNormal (?), NoSticky (exclude sticky windows),\
 NoOnTop (exclude windows wich 'StaysOnTop'), Unsorted (don't sort the list),\
 UseIconName (use icon name - usually shorter than window name)."

  WindowShade
  "Example: 'WindowShade 1'. Toggles the window shade feature for titled\
 windows. Windows in the shaded state only  display a title bar. If no\
 arguments are given, the window shade state is toggled. If the argument is\
 1, the window is forced to the shaded state. If it is 2, then the window\
 is forced to the non-shaded state. Maximized windows and windows without\
 titles cannot be shaded."

  WindowsDesk
  "Example: 'WindowsDesk 2'. Move the selected window to a new desktop. This\
 command takes the new desk no. as argument."
}

######################################################################
# Helpers for the fvwmIconMan function below
proc maybeCb {pf cb name} {
  if {$cb == 1} {
    CheckBox ${pf}_cb$name -text Overload \
	-help "Check this option if you want to overload the global"\
	"settings you've specified."
  }
}

proc maybeFrame {pf cb name wList} {
  if {$cb == 1} {set widgets [concat ${pf}_cb$name $wList]
  } else {set widgets $wList}
  eval Frame ${pf}_fr$name -entries $widgets
}

proc maybeNo {str no} {
  if {$no != -1} {
    return ${str}${no}*
  } else {
    return $str
  }
}

######################################################################
# Create FvwmIconMan widgets (pf = prefix, cb = useCheckBox)
proc fvwmIconMan {pf cb} {

  # Resolution
  maybeCb $pf $cb Res
  Label ${pf}_lbRes -text "Resolution:" \
      -help "The resolution specifies which windows will be"\
      "displayed. The three possibilities are 'Global' meaning that all"\
      "valid windows will be displayed, 'Desk' meaning that windows on"\
      "the current desk will be displayed and 'Page' meaning that"\
      "windows on the current page only will be displayed."
  Radio ${pf}_rdRes -entryhelp {
    global "All valid windows will be displayed."
    desk   "Windows on the current desk will be displayed."
    page   "Windows on the current page will be diaplayed."
  }
  maybeFrame $pf $cb Res [list ${pf}_lbRes ${pf}_rdRes]
  if {$cb == 1} {
    Change \
	"if {\$changeElm == \"${pf}_cbRes\"} { \
           if {\$${pf}_cbRes == 1} { \
             Enable ${pf}_rdRes \
           } else { \
             Disable ${pf}_rdRes \
           } \
         }"
  }

  # ShowTitle
  maybeCb $pf $cb ShT
  Label ${pf}_lbShT -text "What to show:" \
      -help "Here you configure if the window name or the icon name"\
      "should be used as text on the buttons."
  Radio ${pf}_rdShT -entryhelp {
    "Icon name" "Use icon name as text on buttons."
    "Window name" "Use window name as text on buttons."
  }
  maybeFrame $pf $cb ShT [list ${pf}_lbShT ${pf}_rdShT]
  if {$cb == 1} {
    Change \
	"if {\$changeElm == \"${pf}_cbShT\"} { \
           if {\$${pf}_cbShT == 1} { \
             Enable ${pf}_rdShT \
           } else { \
             Disable ${pf}_rdShT \
           } \
         }"
  }

  # FollowFocus
  maybeCb $pf $cb FoF
  Label ${pf}_lbFoF -text "Reflect focus:" \
      -help "Here you specify if the button appearance should reflect"\
      "which window currently has the input focus."
  Radio ${pf}_rdFoF -entryhelp {
    No  "Ignore current focus."
    Yes "Reflect current focus."
  }
  maybeFrame $pf $cb FoF [list ${pf}_lbFoF ${pf}_rdFoF]
  if {$cb == 1} {
    Change \
	"if {\$changeElm == \"${pf}_cbFoF\"} { \
           if {\$${pf}_cbFoF == 1} { \
             Enable ${pf}_rdFoF \
           } else { \
             Disable ${pf}_rdFoF \
           } \
         }"
  }

  # SortIcons
  maybeCb $pf $cb Srt
  Label ${pf}_lbSrt -text "Sort buttons:" \
      -help "Here you specify if the buttons should be sorted."
  Radio ${pf}_rdSrt -entryhelp {
    No  "Don't sort the buttons."
    Yes "Sort the buttons."
  } -default Yes
  maybeFrame $pf $cb Srt [list ${pf}_lbSrt ${pf}_rdSrt]
  if {$cb == 1} {
    Change \
	"if {\$changeElm == \"${pf}_cbSrt\"} { \
           if {\$${pf}_cbSrt == 1} { \
             Enable ${pf}_rdSrt \
           } else { \
             Disable ${pf}_rdSrt \
           } \
         }"
  }

  # Geometry
  Label ${pf}_lbGeo -text "Specify geometry:" \
      -help "Here you can specify the size and location of the window."
  Int ${pf}_GeoW -text "Width"
  Int ${pf}_GeoH -text "Height"
  Int ${pf}_GeoX -text "X-pos"
  Int ${pf}_GeoY -text "Y-pos"
  Frame ${pf}_frGeo -entries ${pf}_lbGeo ${pf}_GeoW ${pf}_GeoH ${pf}_GeoX \
      ${pf}_GeoY
  Change "\
     if {\$changeElm == \"${pf}_GeoW\" && \$${pf}_GeoW == \"-\"} { \
       set ${pf}_GeoW \"\" \
     } \
     elseif {\$changeElm == \"${pf}_GeoH\" && \$${pf}_GeoH == \"-\"} { \
       set ${pf}_GeoH \"\" \
     }"

  # Font
  CheckBox ${pf}_cbFnt -text "Specify font:" \
      -help "Check this button if you want to set the font used for"\
      "button titles."
  Command ${pf}_cmFnt \
      -default "fixed" \
      -setvalue "buttonSetText \$widget \$${pf}_cmFnt" \
      -invoke "FontWidget \$${pf}_cmFnt 0" \
      -disable {$widget configure -text "Not set"
	$widget configure -font fixed} \
      -enable "buttonSetText \$widget \$${pf}_cmFnt" \
      -help "In this widget you can set the font to use for button titles."
  Frame ${pf}_frFnt -entries [list ${pf}_cbFnt ${pf}_cmFnt]
  Change \
      "if {\$changeElm == \"${pf}_cbFnt\"} { \
         if {\$${pf}_cbFnt == 1} { \
           Enable ${pf}_cmFnt \
         } else { \
           Disable ${pf}_cmFnt \
         } \
       }"

  # Default color
  CheckBox ${pf}_cbCol -text "Specify default color:" -help "Check this"\
      "button if you want to specify the default colors of buttons."
  Command ${pf}_cmColF \
      -text "foreground" \
      -default [list black 0] \
      -setvalue "\
	\$widget configure -bg \[lindex \$${pf}_cmColF 0\] -text \"      \"" \
      -invoke "ColorWidget \$colorList \[lindex \$${pf}_cmColF 0\] \
		   \[lindex \$${pf}_cmColF 1\]" \
      -disable {$widget configure -relief flat } \
      -enable {$widget configure -relief raised } \
      -help "In this widget you can set the default foreground color."
  Command ${pf}_cmColB \
      -text "background" \
      -default [list "white" 0] \
      -setvalue "\
	\$widget configure -bg \[lindex \$${pf}_cmColB 0\] -text \"      \"" \
      -invoke "ColorWidget \$colorList \[lindex \$${pf}_cmColB 0\] \
		   \[lindex \$${pf}_cmColB 1\]" \
      -disable {$widget configure -relief flat } \
      -enable {$widget configure -relief raised } \
      -help "In this widget you can set the default background color."
  Frame ${pf}_frCol -entries ${pf}_cbCol ${pf}_cmColF ${pf}_cmColB
  Change "\
    if {\$changeElm == \"${pf}_cbCol\"} { \
      if {\$${pf}_cbCol == 1} {Enable ${pf}_cmColF ${pf}_cmColB \
      } else {Disable ${pf}_cmColF ${pf}_cmColB} \
    }"

  # Buttons
  CheckBox ${pf}_cbBut -help "Check this option if you want to change the"\
      "button's appearance."
  Label ${pf}_lbBut -label:width 16 -label:justify left -label:relief groove
  Menu ${pf}_mnBut -text Style -entries {up flat down} -button:width 5
  CheckBox ${pf}_cbButC -text Specify -help "Check this option if you"\
      "want to specify colors as well as style."
  Command ${pf}_cmButF \
      -text "foreground\ncolor" \
      -default [list black 0] \
      -setvalue "\
	\$widget configure -bg \[lindex \$${pf}_cmButF 0\] -text \"      \"" \
      -invoke "ColorWidget \$colorList \[lindex \$${pf}_cmButF 0\] \
		   \[lindex \$${pf}_cmButF 1\]" \
      -disable {$widget configure -relief flat } \
      -inactive {$widget configure -text "      "} \
      -enable {$widget configure -relief raised } \
      -help "In this widget you can set the default foreground color."
  Command ${pf}_cmButB \
      -text "background\ncolor" \
      -default [list "white" 0] \
      -setvalue "\
	\$widget configure -bg \[lindex \$${pf}_cmButB 0\] -text \"      \"" \
      -invoke "ColorWidget \$colorList \[lindex \$${pf}_cmButB 0\] \
		   \[lindex \$${pf}_cmButB 1\]" \
      -disable {$widget configure -relief flat } \
      -inactive {$widget configure -text "      "} \
      -enable {$widget configure -relief raised } \
      -help "In this widget you can set the default background color."

  Change "\
    if {\$changeElm == \"${pf}_cbBut\"} { \
      if {\$${pf}_cbBut == 1} {Enable ${pf}_mnBut ${pf}_cbButC} \n \
      if {\$${pf}_cbBut == 1 && \$${pf}_cbButC == 1} { \
        Enable ${pf}_cmButF ${pf}_cmButB \
      } \n \
      if {\$${pf}_cbBut == 0} { \
        Disable ${pf}_mnBut ${pf}_cbButC ${pf}_cmButF ${pf}_cmButB \
      } \
    }"

  ExtEntry ${pf}_frBut -entries ${pf}_cbBut ${pf}_lbBut ${pf}_mnBut \
      ${pf}_cbButC ${pf}_cmButF ${pf}_cmButB -count 4 -maxentries 4 \
      -noscissor 1 -default {
    {0 "Plain button"}
    {0 "Selected button"}
    {0 "Focus button"}
    {0 "Focus & Selected"}
  }

  Change "\
    if {\$changeElm == \"${pf}_cbButC\"} { \
      if {\$${pf}_cbButC == 1} {Enable ${pf}_cmButF ${pf}_cmButB \
      } else {Disable ${pf}_cmButF ${pf}_cmButB} \
    }"

  Window ${pf}_LnF -text "Look-and-Feel of Buttons" \
      -entries ${pf}_frCol ${pf}_frBut \
      -help "Configuration of fonts, colors and styles of buttons are"\
      "done in this window."

  # (Dont)Show
  CheckBox ${pf}_cbClShw -text Class \
      -help "Check this if the pattern you enter must match the windows"\
      "class (as found with FvwmIdent)."
  CheckBox ${pf}_cbRsShw -text Resource \
      -help "Check this if the pattern you enter must match the windows"\
      "resource string (as found with FvwmIdent)."
  CheckBox ${pf}_cbTlShw -text Title \
      -help "Check this if the pattern you enter must match the windows"\
      "title (the text in the title bar)."
  CheckBox ${pf}_cbIcShw -text Icon \
      -help "Check this if the pattern you enter must match the windows"\
      "icon name (as found with FvwmIdent)."
  Entry ${pf}_enShw -text "Pattern:" \
      -help "Enter the name you wish to match - wildcards (*,?) are"\
      "allowed."
  ExtEntry ${pf}_eeShw -entries ${pf}_cbClShw ${pf}_cbRsShw ${pf}_cbTlShw \
      ${pf}_cbIcShw ${pf}_enShw -text "What to include in the manager:" \
      -help "Here you can enter a number of windows to include in the"\
      "icon manager. If you don't enter any, the default is to show all"\
      "windows."

  CheckBox ${pf}_cbClDsh -text Class \
      -help "Check this if the pattern you enter must match the windows"\
      "class (as found with FvwmIdent)."
  CheckBox ${pf}_cbRsDsh -text Resource \
      -help "Check this if the pattern you enter must match the windows"\
      "resource string (as found with FvwmIdent)."
  CheckBox ${pf}_cbTlDsh -text Title \
      -help "Check this if the pattern you enter must match the windows"\
      "title (the text in the title bar)."
  CheckBox ${pf}_cbIcDsh -text Icon \
      -help "Check this if the pattern you enter must match the windows"\
      "icon name (as found with FvwmIdent)."
  Entry ${pf}_enDsh -text "Pattern:" \
      -help "Enter the name you wish to match - wildcards (*,?) are"\
      "allowed."
  ExtEntry ${pf}_eeDsh -entries ${pf}_cbClDsh ${pf}_cbRsDsh ${pf}_cbTlDsh \
      ${pf}_cbIcDsh ${pf}_enDsh -text "What to exclude from the manager:" \
      -help "Here you can enter a number of windows to exclude from the"\
      "icon manager. If you don't enter any, the default is to show all"\
      "windows."

  # Actions
  Label ${pf}_idxAct -text "Description:" -label:relief groove
  Radio ${pf}_rdAct -text "Choose the type of event" -entries \
      Key Mouse Select \
      -help "Key- and mouse bindings mean the same as with normal Fvwm2"\
      "bindings. 'Select' events happen when the mouse enters an"\
      "icon manager button."

  ComboBox ${pf}_ksAct -text "Keysym" -entries \
      Left Right Up Down \
      F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 L1 L2 L3 L4 L5 L6 L7 L8 L9 L10 \
      a b c d e f g h i j k l m n o p q r s t u v w x y z \
      A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
      -packFrame:anchor nw \
      -help "Select a keysym from the list, if the desired keysym isn't" \
      "present you can enter it yourself."

  Menu ${pf}_mbAct -text "Button no" -entries { Any 1 2 3 } \
      -packFrame:anchor nw \
      -help "Select which mouse button to bind to."

  Frame ${pf}_kmAct -entries  ${pf}_ksAct ${pf}_mbAct
  
  ListBox ${pf}_mdAct -text "Modifier" -entries \
      Any Control Shift Meta 1mod 2mod 3mod 4mod 5mod \
      -width 8 \
      -selectmode multiple \
      -help "Select the modifier(s) to press."

  Change "\
      if {\$changeElm == \"${pf}_rdAct\"} { \
        if {\$${pf}_rdAct(name) == \"Key\"} { \
	  Disable ${pf}_mbAct \n \
          Enable ${pf}_ksAct \n \
          Enable ${pf}_mdAct \
        } elseif {\$${pf}_rdAct(name) == \"Mouse\"} { \
	  Disable ${pf}_ksAct \n \
          Enable ${pf}_mbAct \n \
          Enable ${pf}_mdAct \
        } else { \
	  Disable ${pf}_ksAct \n \
          Disable ${pf}_mbAct \n \
          Disable ${pf}_mdAct \
	} \
      } \n \
      if {\$changeElm == \"${pf}_rdAct\" || \
          \$changeElm == \"${pf}_ksAct\" || \
          \$changeElm == \"${pf}_mbAct\" || \
          \$changeElm == \"${pf}_mdAct\"} { \
        set ${pf}_idxAct \$${pf}_rdAct(name) \n \
	switch \$${pf}_rdAct(name) \
	  Key    { append ${pf}_idxAct \
	           \" \[makeContextOrModifier \$${pf}_mdAct(name)\]\" \n \
		   append ${pf}_idxAct \" \$${pf}_ksAct\" \
		 } \
          Mouse  { append ${pf}_idxAct \
	           \" \[makeContextOrModifier \$${pf}_mdAct(name)\]\" \n \
		   append ${pf}_idxAct \" \$${pf}_mbAct(name)\" \
		 } \
  }"

  Menu ${pf}_fctAct -text "Command" -entryhelp {
    lowermanager "Lower all manager windows."
    raisemanager "Raise all manager windows."
    selectbutton "Select the button specified by the parameters."
    sendcommand  "Send an Fvwm2 command to the window specified."
    quit         "Quit FvwmIconMan."
    warp         "Warp the cursor to the window specified."
  }

  Menu ${pf}_manAct -text "Manager" -entryhelp {
    select   "Currently selected manager."
    focus    "Manager holding the focused window."
    absolute "Specify manager as an absolute integer."
  }
  Int ${pf}_manAddAct -help "Here you can add or subtract an integer"\
      "from the value given in the menu. If you select 'select' in the"\
      "menu and enter '-1' here, the manager specified will be the one"\
      "before the currently selected. If you select 'absolute' in the"\
      "menu, you must specify an integer."

  Menu ${pf}_buwAct -text "Button/window" -entryhelp {
    select   "Currently selected button/window."
    focus    "Currently focused button/window."
    absolute "Specify button/window as an absolute integer."
  }

  Int ${pf}_buwAddAct -help "Here you can add or subtract an integer"\
      "from the value given in the menu. If you select 'select' in the"\
      "menu and enter '-1' here, the button/window specified will be the"\
      "one before the currently selected. If you select 'absolute' in the"\
      "menu, you must specify an integer."

  Frame ${pf}_frActAct -entries ${pf}_manAct ${pf}_manAddAct ${pf}_buwAct \
      ${pf}_buwAddAct

  global Builtins
  Label ${pf}_bcLabAct -text "Fvwm2 function" \
      -help "Select a built-in function to call from this menu"
  ComboBox ${pf}_bcAct -noedit 1 -default Beep -entryhelp $Builtins \
      -help "Select a built-in function to call from this menu"
  Frame ${pf}_frBcAct -orient top -entries ${pf}_bcLabAct ${pf}_bcAct

  Label ${pf}_argLabAct -text "Arguments" \
      -help "Any additional arguments are entered here (the syntax is your" \
      "responsibility) - see help for the individual commands."
  Entry ${pf}_argAct \
      -help "Any additional arguments are entered here (the syntax is your" \
      "responsibility) - see help for the individual commands."
  Frame ${pf}_frArgAct -orient top -entries ${pf}_argLabAct ${pf}_argAct
  Frame ${pf}_comAct -entries ${pf}_frBcAct ${pf}_frArgAct

  ExtEntry ${pf}_eeAct -orient top -entries ${pf}_idxAct ${pf}_rdAct \
      ${pf}_kmAct ${pf}_mdAct ${pf}_fctAct ${pf}_frActAct ${pf}_comAct \
      -index ${pf}_idxAct \
      -count 1

  Change "\
    if {\$changeElm == \"${pf}_fctAct\"} { \
      switch \$${pf}_fctAct(name) \
        \"lowermanager\" {Disable ${pf}_frActAct ${pf}_comAct} \
        \"raisemanager\" {Disable ${pf}_frActAct ${pf}_comAct} \
        \"selectbutton\" {Enable ${pf}_frActAct; Disable ${pf}_comAct} \
        \"sendcommand\"  {Enable ${pf}_frActAct ${pf}_comAct} \
        \"quit\"         {Disable ${pf}_frActAct ${pf}_comAct} \
        \"warp\"         {Enable ${pf}_frActAct; Disable ${pf}_comAct} \
    }"

  Window ${pf}_wnAct -text "Actions to events" -entries \
      ${pf}_eeAct \
      -help "On this page you bind actions to key, mouse and select events."

  # Frame with all widgets.
  Frame ${pf}_frame -orient top -entries ${pf}_frRes ${pf}_frShT \
      ${pf}_frFoF ${pf}_frSrt ${pf}_frGeo ${pf}_frFnt ${pf}_eeShw \
      ${pf}_eeDsh ${pf}_wnAct ${pf}_LnF
}

proc fvwmIconManSave {pf no} {
  global ___pf
  set ___pf $pf
  global ___no
  set ___no $no
  uplevel 1 {
    # Resolution
    if {$___no != -1} {
      if {[set ${___pf}_cbRes] == 1} {
	print "*FvwmIconMan*${___no}*resolution\t[set ${___pf}_rdRes(name)]"
      }
    } else {
      if {[set ${___pf}_rdRes(name)] != "global"} {
	print "*FvwmIconMan*resolution\t[set ${___pf}_rdRes(name)]"
      }
    }
    # Show title
    if {$___no != -1} {
      if {[set ${___pf}_cbShT] == 1} {
	set result "*FvwmIconMan*${___no}*showtitle\t"
	if {[set ${___pf}_rdRes(index)] == 0} {
	  append result "false"
	} else {
	  append result "true"
	}
	print $result
      }
    } else {
      if {[set ${___pf}_rdShT(index)] == 1} {
	print "*FvwmIconMan*showtitle\ttrue"
      }
    }
    # Follow focus
    if {$___no != -1} {
      if {[set ${___pf}_cbFoF] == 1} {
	set result "*FvwmIconMan*${___no}*followfocus\t"
	if {[set ${___pf}_rdRes(index)] == 0} {
	  append result "false"
	} else {
	  append result "true"
	}
	print $result
      }
    } else {
      if {[set ${___pf}_rdFoF(index)] == 1} {
	print "*FvwmIconMan*followfocus\ttrue"
      }
    }
    # Sort buttons
    if {$___no != -1} {
      if {[set ${___pf}_cbSrt] == 1} {
	set result "*FvwmIconMan*${___no}*sort\t"
	if {[set ${___pf}_rdRes(index)] == 0} {
	  append result "false"
	} else {
	  append result "true"
	}
	print $result
      }
    } else {
      if {[set ${___pf}_rdSrt(index)] == 0} {
	print "*FvwmIconMan*followfocus\tfalse"
      }
    }

    ##################################################
    # No checkboxes from here...

    # Geometry
    if {[set ${___pf}_GeoW] != "" || [set ${___pf}_GeoX] != ""} {
      set result "[maybeNo "*FvwmIconMan*" $___no]geometry\t"
      if {[set ${___pf}_GeoW] != ""} {
	append result [set ${___pf}_GeoW]x[set ${___pf}_GeoH]
      }
      if {[set ${___pf}_GeoX] != ""} {
	append result [signed [set ${___pf}_GeoX]][signed [set ${___pf}_GeoY]]
      }
      print $result
    }
    # Font
    if {[set ${___pf}_cbFnt] == 1} {
      print "[maybeNo "*FvwmIconMan*" $___no]font\t[set ${___pf}_cmFnt]"
    }
    # Show
    set result ""
    forevery ${___pf}_eeShw {
      if {[set ${___pf}_cbClShw] == 1} {
	if {[set ${___pf}_enShw] != ""} {
	  append result " class=\"[set ${___pf}_enShw]\""
	}
      }
      if {[set ${___pf}_cbRsShw] == 1} {
	if {[set ${___pf}_enShw] != ""} {
	  append result " resource=\"[set ${___pf}_enShw]\""
	}
      }
      if {[set ${___pf}_cbTlShw] == 1} {
	if {[set ${___pf}_enShw] != ""} {
	  append result " title=\"[set ${___pf}_enShw]\""
	}
      }
      if {[set ${___pf}_cbIcShw] == 1} {
	if {[set ${___pf}_enShw] != ""} {
	  append result " icon=\"[set ${___pf}_enShw]\""
	}
      }
    }
    if {$result != ""} {
      print \
	"[maybeNo "*FvwmIconMan*" $___no]show\t[string range $result 1 end]"
    }
    # Don't show
    set result ""
    forevery ${___pf}_eeDsh {
      if {[set ${___pf}_cbClDsh] == 1} {
	if {[set ${___pf}_enDsh] != ""} {
	  append result " class=\"[set ${___pf}_enDsh]\""
	}
      }
      if {[set ${___pf}_cbRsDsh] == 1} {
	if {[set ${___pf}_enDsh] != ""} {
	  append result " resource=\"[set ${___pf}_enDsh]\""
	}
      }
      if {[set ${___pf}_cbTlDsh] == 1} {
	if {[set ${___pf}_enDsh] != ""} {
	  append result " title=\"[set ${___pf}_enDsh]\""
	}
      }
      if {[set ${___pf}_cbIcDsh] == 1} {
	if {[set ${___pf}_enDsh] != ""} {
	  append result " icon=\"[set ${___pf}_enDsh]\""
	}
      }
    }
    if {$result != ""} {
      print \
      "[maybeNo "*FvwmIconMan*" $___no]dontshow\t[string range $result 1 end]"
    }
    # Buttons
    if {[set ${___pf}_cbCol] == 1} {
      print "[maybeNo "*FvwmIconMan*" $___no]foreground\t[hash2rgb [lindex [set ${___pf}_cmColF] 0]]"
      print "[maybeNo "*FvwmIconMan*" $___no]background\t[hash2rgb [lindex [set ${___pf}_cmColB] 0]]"
    }
    forevery ${___pf}_frBut {
      if {[set ${___pf}_cbBut] == 1} {
	set result [maybeNo "*FvwmIconMan*" $___no]
	switch [set ${___pf}_lbBut] \
	    "Plain button" {
	      append result "plainbutton\t[set ${___pf}_mnBut(name)]"
	    } \
	    "Selected button" {
	      append result "selectbutton\t[set ${___pf}_mnBut(name)]"
	    } \
	    "Focus button" {
	      append result "focusbutton\t[set ${___pf}_mnBut(name)]"
	    } \
	    "Focus & Selected" {
	      append result "focusandselectbutton\t[set ${___pf}_mnBut(name)]"
	    }
	if {[set ${___pf}_cbButC] == 1} {
	  append result " [hash2rgb [lindex [set ${___pf}_cmButF] 0]]"
	  append result " [hash2rgb [lindex [set ${___pf}_cmButB] 0]]"
	}
	print $result
      }
    }
    # Actions
    forevery ${___pf}_eeAct {
      set result "[maybeNo "*FvwmIconMan*" $___no]action\t"
      switch [set ${___pf}_rdAct(name)] \
	  Key {
	    if {[set ${___pf}_ksAct] == ""} {
	      error "You must specify keysym in FvwmIconMan key actions."
	    }
	    append result " Key [set ${___pf}_ksAct] "
	    append result [makeContextOrModifier [set ${___pf}_mdAct(name)]]
	  } \
	  Mouse {
	    append result " Mouse [string index [set ${___pf}_mbAct(name)] 0] "
	    append result [makeContextOrModifier [set ${___pf}_mdAct(name)]]
	  } \
	  Select {
	    append result " Select"
	  }
      append result " [set ${___pf}_fctAct(name)]"
      switch [set ${___pf}_fctAct(name)] \
	  selectbutton {
	    if {[set ${___pf}_manAct(name)] != "absolute"} {
	      append result " [set ${___pf}_manAct(name)]"
	      append result " [signed [set ${___pf}_manAddAct]]"
	    }
	    if {[set ${___pf}_buwAct(name)] != "absolute"} {
	      append result " [set ${___pf}_buwAct(name)]"
	      append result " [signed [set ${___pf}_buwAddAct]]"
	    }
	  } \
	  sendcommand {
	    if {[set ${___pf}_manAct(name)] != "absolute"} {
	      append result " [set ${___pf}_manAct(name)]"
	      append result " [signed [set ${___pf}_manAddAct]]"
	    }
	    if {[set ${___pf}_buwAct(name)] != "absolute"} {
	      append result " [set ${___pf}_buwAct(name)]"
	      append result " [signed [set ${___pf}_buwAddAct]]"
	    }
	    append result " [set ${___pf}_bcAct]"
	    if {[set ${___pf}_argAct] != ""} {
	      append result " [set ${___pf}_argAct]"
	    }
	  } \
	  warp {
	    if {[set ${___pf}_manAct(name)] != "absolute"} {
	      append result " [set ${___pf}_manAct(name)]"
	      append result " [signed [set ${___pf}_manAddAct]]"
	    }
	    if {[set ${___pf}_buwAct(name)] != "absolute"} {
	      append result " [set ${___pf}_buwAct(name)]"
	      append result " [signed [set ${___pf}_buwAddAct]]"
	    }
	  }
      print $result
    }
  }
}

proc funcWithArgs {funcName} {
  set argList {ChangeDecor CursorMove Desk DestroyDecor DestroyFunc
    DestroyMenu DestroyModuleConfig Echo Exec ExecUseShell Function GotoPage
    Iconify KillModule Maximize Menu Module Move Next None PipeRead Popup
    Prev Read Resize Restart SendToModule Scroll UpdateDecor Wait
    WarpToWindow WindowId WindowList WindowShade WindowsDesk}
  if {[lsearch $argList $funcName] != -1} {
    return 1
  } else {
    return 0
  }
}
