SyntaxHighlighter Evolved and line-height

As you probably know, I’m using SyntaxHighlighter Evolved to post syntax-highlighted code. Some people mailed me, that in some of my posted code the underscores are not visible (although copy&paste works). Well, the culprit is the line-height attribute of the SyntaxHighlighter Evolved cascading stylesheet:

.syntaxhighlighter,
.syntaxhighlighter div,
.syntaxhighlighter code,
.syntaxhighlighter table,
.syntaxhighlighter table td,
.syntaxhighlighter table tr,
.syntaxhighlighter table tbody
{
	margin: 0 !important;
	padding: 0 !important;
	border: 0 !important;
	outline: 0 !important;
	background: none !important;
	text-align: left !important;
	float: none !important;
	vertical-align: baseline !important;
	position: static !important;
	left: auto !important;
	top: auto !important;
	right: auto !important;
	bottom: auto !important;
	height: auto !important;
	width: auto !important;
	line-height: 1.21 !important;
	font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
	font-weight: normal !important;
	font-style: normal !important;
	font-size: 1em !important;
	/*min-height: inherit !important; *//* For IE8, FF & WebKit */
	/*min-height: auto !important;*/ /* For IE7 */
	direction: ltr !important;
}

Simply increasing the line-height from the default 1.1em to 1.21em in wp-content/plugins/syntaxhighlighter/syntaxhighlighter/styles/shCore.css did the trick.

log4j performance

      1 Comment on log4j performance

Log4J is the current de facto standard not only in open source development. It claims to be fast and flexible: speed first, flexibility second. But there are some pitfalls when it comes to the crunch.

The costs of a log request consists of a method invocation and an integer comparison. This is typically about 1-20ns (depending on your processor) per call. However, this does not include the “hidden” costs of parameter construction.
A simple example:

logger.debug("Value: " + x*y);

Regardless of whether the message will actually be logged or not, the parameter construction will cause additional costs. These costs of parameter construction can be quite high and depend on the size of the parameters involved.

To avoid the parameter construction costs:

      if(logger.isDebugEnabled() {
        logger.debug("Value: " + x*y);
      }
  

This will not incur the cost of parameter construction if debugging is disabled. On the other hand, if the logger is debug-enabled, it will incur twice the cost of evaluating whether the logger is enabled or not: once in debugEnabled and once in debug. This is an insignificant overhead because evaluating a logger takes about 1% of the time it takes to actually log.

So if speed is a real issue, you should double-check your logging statements for “hidden” costs.

Resources:
http://logging.apache.org/log4j/1.2/manual.html

sSMTP revaliases, aliases and mail.rc

      16 Comments on sSMTP revaliases, aliases and mail.rc

I already wrote about sending mails with ssmtp, a simple alternative to sendmail. But since I got a few questions (and I tend to forget myself) how to use ssmtp’s revaliases-file, here is a short reminder:

/etc/revaliases, allows you to map a local user to a specific ‘From:’ address on outbound mail and to route that mail through a specific mailhub. But it will not rewrite the ‘To:’ address according to the local user who should receive the mail.

Usually, you would add aliases to /etc/aliases to ensure that a local user (receiving a mail) is mapped to a valid eMail address. But as the documentation clearly says (if you actually read it), ssmtp does not use /etc/aliases.

The solution turns out to be letting mail handle the alias – which is done by configuring aliases in /etc/mail.rc

set ask askcc append dot save crt
ignore Received Message-Id Resent-Message-Id Status Mail-From Return-Path Via Delivered-To
alias root root<yourname@domain.com>
alias localuser localuser<yourname@domain.com>

You can test it with with:

# echo test | mail -s "testing ssmtp" localuser

The mail will actually be delivered to yourname@domain.com (since ‘localuser’ is mapped to this address in /etc/mail.rc).

Enjoy!

Resources:
http://www.linux.com/archive/feature/132006
http://greybeardedgeek.net/?p=17

Find empty folders on Linux

      No Comments on Find empty folders on Linux

Well, there is no native command (at least, afaik), but you can use find to easily identify empty folders (which maybe helpful for maintenance, etc.):

# find /path -type d -empty

Find empty folder and list

# find /path -type d -empty -exec ls -ld {} \;

Find empty folder and save as temporary file

# find /path -type d -empty -exec ls -ld >> /tmp/savefiles.txt {} \;

Find empty folder and delete

# find /path -type d -empty -exec rmdir {} \;

See also find manpage

Making MythTV work with pulseaudio in Fedora 12

If you run mythfrontend 0.22 from RPMfusion, it will automatically try to disable pulseaudio and use the default ALSA output instead. This leads (in most cases) to no audio output at all.

Changing mythtv’s audio output device in the frontend (Utilities/Setup -> Setup -> General -> Audio System -> Audio Output Device) from ‘ALSA:default’ to ‘ALSA:spdif’ worked for me, but then the volume control (internal as well as external) was broken.

But you can easily tell mythtv to stop disabling pulseaudio by setting EXPERIMENTALLY_ALLOW_PULSE_AUDIO=1 in your environment before running mythfrontend.

For example, add an export statement to your .bashrc

echo "export EXPERIMENTALLY_ALLOW_PULSE_AUDIO=1" >> ~/.bashrc

(Of course, if you use another shell, YMMV!)

Set mythtv’s default audio output device to ‘ALSA:default’ and the volume control to Master (instead of PCM) and voilà, sound!

Rearrange Thunderbird accounts

      No Comments on Rearrange Thunderbird accounts

Unfortunately, the Folderpane Tools-plugin I used for rearranging my accounts in Thunderbird isn’t TB3 compatible (yet?!). Although it claims to work with all Thunderbird versions starting from 1.0 it just throws out parsing errors with the current Tunderbird beta.

But the plugin doesn’t do any magic tricks, of course. It simply reorders the accounts in the corresponding preferences file prefs.js. Open the file (usually located in with ~/.thunderbird/[profileName]/prefs.js) with your favourite editor and look for a line like

user_pref("mail.accountmanager.accounts", "account1,account2...

Rearrange the accounts manually and your done.

Note: You may want to close Thunderbird and make a backup of the file before editing it. Just in case…

Resources:
https://addons.mozilla.org/en-US/thunderbird/addon/258
http://advancingsf.blogspot.com/2006/11/reorder-accounts-in-thunderbird.html

FileWriter, XML and UTF-8

      1 Comment on FileWriter, XML and UTF-8

Deep down in the Java-API:

http://java.sun.com/javase/6/docs/api/java/io/FileWriter.html

Convenience class for writing character files. The constructors of this class assume that the default character encoding and the default byte-buffer size are acceptable. To specify these values yourself, construct an OutputStreamWriter on a FileOutputStream.

So, if you want to write you XML-Document to a file, for the love of god, don’t use the FileWriter like this:

        BufferedWriter bufout = new BufferedWriter(new FileWriter(OUTFILE));
        bufout.write(out);
        bufout.close();

or you might end up with an XML-file that has a UTF-16 header (encoding="UTF-16") but is encoded completely differently (plain ASCII?! Not sure…).

Insted, use

                OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(OUTFILE),"UTF-16");
                out.write(s);
                out.close();

Resources:
http://www.malcolmhardie.com/weblogs/angus/2004/10/23/java-filewriter-xml-and-utf-8/

Quickly zooming a BufferedImage

      No Comments on Quickly zooming a BufferedImage

If you don’t need a scaled instance of your BufferedImage in the memory, you can use “on-the-fly scaling”. For example, this custom JComponent can be used to display a BufferedImage and zoom it with the setScaleFactor(..)-method

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JComponent;

public class ZoomableImage extends JComponent {

    private float scaleFactor;
    
    private BufferedImage originalImage;

    public ZoomableImage() {
        this.scaleFactor = 1;
        this.setSize(0, 0);
    }

    public void setImage(BufferedImage image) {
        this.originalImage = image;
        this.setSize(image.getWidth(), image.getHeight());
        //setSize does repainting, no need to call repaint()
        //this.repaint();
    }

    public void setScaleFactor(float scaleFactor) {
        this.scaleFactor = scaleFactor;
        this.repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        if (this.originalImage != null) {
            Graphics2D g2 = (Graphics2D) g;
            int newW = (int) (originalImage.getWidth() * scaleFactor);
            int newH = (int) (originalImage.getHeight() * scaleFactor);
            this.setPreferredSize(new Dimension(newW, newH));
            this.revalidate();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    //RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
                    //RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            g2.drawImage(originalImage, 0, 0, newW, newH, null);
        }
    }
}

For some benchmarking on the different RenderingHints values see Chris Campbell’s great article The Perils of Image.getScaledInstance()

Resources:
http://java.sun.com/docs/books/tutorial/2d/advanced/quality.html
http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

Dynamically Changing the Size of a JScrollPane’s Client

In short: setSize(..) doesn’t work at all, you’ll need setPreferredSize(..) followed by revalidate()

if (changed) {
    //Update client's preferred size because
    //the area taken up by the graphics has
    //gotten larger or smaller (if cleared).
    drawingArea.setPreferredSize(/* the new size */);

    //Let the scroll pane know to update itself
    //and its scroll bars.
    drawingArea.revalidate();
}

Resources:
http://java.sun.com/docs/books/tutorial/uiswing/components/scrollpane.html#update