$book = '..'?>
include "$book/mh.php"; includeHeader('resfun.html', 'concus.html'); ?>xmh has a long list of action procedures that it runs when you click a mouse button, select a command from a menu, or click a button in a window. These are set in your system's Xmh resource file. You can change the way xmh works by adding entries to your own resource file (like .Xdefaults). For more information, see O'Reilly Media's Volume Four, X Toolkit Intrinsics Programming Manual, Chapter 8, Events, Translations, and Accelerators.
The Table below is an alphabetical list of xmh actions. For a list grouped by function, with longer descriptions, see the section called PROCESSING YOUR MAIL in the xmh(1) manual page.
This section shows how to add and change resource entries for accelerators.
Let's add an accelerator for Compose Message.
The Example below shows the section of the online Xmh resource file that sets accelerators for commands on the Message menu. (You can also get this file from the book's online archive. It's in examples/xmh/X/resources-1.)
Example: Default message menu
accelerators
*messageMenu.Accelerators: #override\n\ Meta<Key>space: XmhViewNextMessage()\n\ :Meta<Key>c: XmhMarkCopy()\n\ :Meta<Key>d: XmhMarkDelete()\n\ :Meta<Key>f: XmhForward()\n\ :Meta<Key>m: XmhMarkMove()\n\ :Meta<Key>n: XmhViewNextMessage()\n\ :Meta<Key>p: XmhViewPreviousMessage()\n\ :Meta<Key>r: XmhReply()\n\ :Meta<Key>u: XmhUnmark()\nThe first line has the name of the resource, *messageMenu.Accelerators. The other lines have entries in pairs, one pair per accelerator. Because each line except the last one ends with a backslash (\) (which is the line continuation character), all of these are part of the same resource entry.
For example, the third line defines the META-C accelerator. When you type META-C, that executes the XmhMarkCopy() action, which marks the selected messages for linking ("copying").
As the Table xmh Release 5 Actions shows, the action for composing a new message is XmhComposeMessage(). You'll want to pick an accelerator key that's not already used. Look through the list in the xmh manual page. Let's say that you choose META-SHIFT-M. You'll need to add a new accelerator/action pair to the resource list.
The order of the accelerators in a resource list doesn't matter. Let's add the new entry at the end. Copy all ten lines of the entry into your resource file (like .Xdefaults) and add a new pair for your new accelerator. I added a continuation character (a backslash (\)) to the end of the last existing line in the previous Example. Then I added the new META-SHIFT-M accelerator on a new line below it. The new lines in the resource file are shown in the next Example. (You can also get it from the book's online archive. Grab examples/xmh/X/resources-2.)
Example: Message menu accelerators with new
ComposeMessage()
*messageMenu.Accelerators: #override\n\ Meta<Key>space: XmhViewNextMessage()\n\ :Meta<Key>c: XmhMarkCopy()\n\ :Meta<Key>d: XmhMarkDelete()\n\ :Meta<Key>f: XmhForward()\n\ :Meta<Key>m: XmhMarkMove()\n\ :Meta<Key>n: XmhViewNextMessage()\n\ :Meta<Key>p: XmhViewPreviousMessage()\n\ :Meta<Key>r: XmhReply()\n\ :Meta<Key>u: XmhUnmark()\n\ :Meta<Key>M: XmhComposeMessage()\n
Restarting xmh will bring in this new accelerator. Try it: type META-SHIFT-M and a composition window should open.
These examples show how to change the labels and actions of two buttons on the composition window buttonbox. They also add a new accelerator.
Accelerator to Send Draft and Close Window
This one defines META-S to send the draft and close the window. It uses two xmh actions. Add the following to your resource file:
Xmh*comp.translations: #override\n\ :Meta<Key>s: XmhSend()XmhCloseView()\nAs you can see, to get more than one action from an accelerator, just list the actions one after the other. This was taken from the Xmh.sample file in the X directory tree -- see that file for many more examples.
Redefine New Headers Button to be Send and Close
The new META-S accelerator in the previous section speeds up a common thing you do from a composition window: send the draft and close the window. Next, let's see how to redefine a much less used button, New Headers, and make the button Send and Close instead.
Here are the two new resource entries for your resource file:
xmh*compButtons.reset.Translations: #override\n\ <Btn1Down>,<Btn1Up>: XmhSend()XmhCloseView()unset()\n xmh*compButtons.reset.label: Send and CloseThose entries do two things:
Figure: Default composition window buttonbox
Figure: Composition window New Headers changed to Send and Close
If you still would like the New Headers button, you can replace the Compose Message button with a New Headers button. I've always thought that New Headers was a misleading name because it removes all changes, not just the header. So I'll also rename New Headers to Start Over. Here are the new resource file entries (they work the same way as the button redefinitions above, but they redefine the fourth button, .compose). You can also get this file from the book's online archive. See examples/xmh/X/resources-6.)
xmh*compButtons.compose.Translations: #override\n\ <Btn1Down>,<Btn1Up>: XmhResetCompose()unset()\n xmh*compButtons.compose.label: Start OverAfter that redefinition, the composition window buttonbox looks like the Figure below.
Figure: Composition window with two buttons redefined
You can set a resource called CommandButtonCount that lets you make completely new buttons on the main window. CommandButtonCount is the number of command buttons to create in a new buttonbox between the Table of Contents and the view areas of the main window. xmh will create these buttons with the names button1, button2, and so on, in a box with the name commandBox. You can specify labels and actions for the buttons in a private resource file.
The Figure below is an example of an uncustomized display.
Figure: Display (not customized yet) with *CommandButtonCount:5
It's made with this single resource file entry:
Xmh*CommandButtonCount:5The default CommandButtonCount is 0, which gives no buttonbox. Now let's fill in the buttonbox. If you're an MH user, too, you may want buttons labeled with the MH command equivalents. If you know those names, this is a good way to get a lot of use out of a small area on the main window. (I like these buttons because sometimes I forget the accelerators.)
After you add entries for the buttons to your resource file, your main windows will look like the Figure after the Example.
Once you see the pattern, the buttons are easy to figure out yourself.
This next Example shows the parts of the resource file entries for the first and fourth buttons. You can also get the whole file from the book's online archive, at examples/xmh/X/resources-3. Putting an exclamation point (!) at the start of a line makes it a comment.
Example: Defining two of the new command
buttons
! !# define the number of buttons in the buttonbox ! Xmh*CommandButtonCount: 12 ! !# 1: left mouse button: "inc" MH command ! Xmh*commandBox.button1.label: inc Xmh*commandBox.button1.translations: #override\n\ <Btn1Down>,<Btn1Up>: XmhIncorporateNewMail()unset() ... ! !# 4: left or right mouse buttons: "rmm" MH command ! Xmh*commandBox.button4.label: rmm Xmh*commandBox.button4.translations: #override\n\ <Btn1Down>,<Btn1Up>: XmhMarkDelete()unset()\n\ <Btn3Down>,<Btn3Up>: XmhMarkDelete()unset()
Figure: Main window with new buttonbox
Notice that the fourth button in the buttonbox can be activated with either the first or the third mouse button.
You can change foreground and background color of new buttons just the way you can change the color of other resources. For example, the following lines would change the colors of the first and last buttons (inc and quit) in the new buttonbox on the main window:
xmh*commandBox.button1.foreground: yellow xmh*commandBox.button1.background: navy xmh*commandBox.button12.foreground: navy xmh*commandBox.button12.background: redUsing color is a nice way to group related buttons.
Here's how to add a button that marks a message for moving directly to a specific folder or subfolder. The folder here is named todo/June (you can use another name, of course).
xmh*commandButtonCount: 1 xmh*commandBox.button1.label: Move to todo/June xmh*commandBox.button1.translations: #override\n\ <Btn1Down>,<Btn1Up>: set() XmhPushFolder()\ XmhPushFolder(todo/June) XmhPopFolder()\ XmhMarkMove() XmhPopFolder() unset()
xmh does some of its work, such as displaying messages, with internal routines. It calls MH commands to do everything else. (According to the xmh Revision 5 manual page, xmh uses at least the following MH commands: inc, msgchk, comp, send, repl, forw, refile, rmm, pick, pack, sort, and scan.) Those MH commands read options from your MH profile file. Some MH profile options are overridden by xmh; you can set the others in your MH profile. For example, you can change the options that scan uses to build the Table of Contents.
Before xmh introduced the XmhShellCommand() action in Release 5, the only way to change MH profile options was with a text editor. Now you can define buttons that call a shell script named edprofile -- and edit your MH profile from a main xmh window.
The details of setting up edprofile are below. The Section A New Buttonbox for the Main Windows shows how to add new buttons to the main window. The Example below has the lines to put in your resource file for making two buttons that change scan. (You can also get this file from the book's online archive. It's in examples/xmh/X/resources-4.)
Example: Changing sort order with
edprofile
Xmh*CommandButtonCount: 2 Xmh*commandBox.button1.label: default toc Xmh*commandBox.button1.translations: #override\ <Btn1Down>,<Btn1Up>: XmhShellCommand(edprofile -v scan --) unset() Xmh*commandBox.button2.label: size toc Xmh*commandBox.button2.translations: #override\ <Btn1Down>,<Btn1Up>: XmhShellCommand(edprofile scan -form scan.size --) unset()The first button, labeled size toc, adds the size of each message to the Table of Contents the next time the folder is rescanned. (The Section scan Format Files explains and shows examples of this.) The button runs the command:
edprofile scan -form scan.size --that changes the MH profile scan entry to look like this:
scan: -form scan.sizeAny switches on that MH profile scan entry before edprofile runs are deleted.
The second button, labeled default toc, will run the command:
edprofile -v scanThe scan entry in the MH profile will be changed to this:
scan:The next time a folder is rescanned, it will have the default format.
Unfortunately, there must be a current or selected message before you run XmhShellComand(). If there's not a message selected, choose any one before you click the button that runs edprofile.
NOTE: edprofile only works with the Release 5 and beyond; these versions have the xmhShellCommand() action.
The command-line syntax of edprofile is:
edprofile [-v] entry [new-value] --Brackets, like [-v], mean that part isn't required. The parts are:
If you don't give a value, edprofile leaves an empty entry (just the name) in the MH profile. Then xmh will use the MH default action of the MH command.
This program is described in the Section Explanation of edprofile.
If you don't want to use the standard xmh editor on your drafts, and you can't use the patches for an external editor explained in the Section Use Another Editor, here's another way. Add the entries shown in the next Example to your resource file. (If you haven't added buttons before, there's help in the Section A New Buttonbox for the Main Windows.) You can also get this file from the book's online archive. See examples/xmh/X/resources-5.)
Example: Button to edit a message with
vi
Xmh*CommandButtonCount: 1 Xmh*commandBox.button1.label: edit vi Xmh*commandBox.button1.translations: #override\ <Btn1Down>,<Btn1Up>: XmhShellCommand(xterm -e vi) unset()The button runs vi in an xterm window; it gives vi the full pathname of the message(s) you select. When you exit vi, the window will close. It's clumsy, but it works. The steps to use the button are:
You can use this same technique to run spell-checking programs or any other UNIX program to help you edit. includeFooter('$Date: 2006-05-31 15:13:43 -0700 (Wed, 31 May 2006) $', 'OReilly: 1991, 1992, 1995'); ?>