PureText

5 Stars Homepage -- Download
v2.0

PureText solves one of those annoying little problems that is so small and so ingrained that you don't even stop to consider the possiblility that there might even be a solution. Copy a chunk of richly formatted text from one application to another, and all the formatting that existed in the first application is carried over. When I'm copying text, 99% of the time I simply want the text, not all the formatting. Of course applications provide a way of removing the formatting, but jeez, why go through all that hassle? PureText to the rescue!

  • A single 13k executable with no installation required
  • PureText only removes rich formatting from text
  • Unicode support when running on Windows NT/2K/XP/2003/Vista
  • User definable hotkeys
  • Optionally autostart with Windows
  • Just sits quietly in the taskbar, waiting...
Continue reading...

Matching brackets puzzler

Matching brackets is an interesting interview puzzle, but only in so far as getting the basic approach down. Once you work out that you need to retain some form of queue of unmatched open brackets, you're done. The rest is all syntax, minutiae, and testing.

So an interview with this question shouldn't really be asking for working code. The basic algorithm, or approach should be enough. Really, you want to see if the person can think. If you're looking for specific language skills, then using this kind of test is going to fail miserably, since it doesn't represent a big enough portion of any language to be valid.

However, it looked fun, so I took this opportunity to learn some PHP. Getting a working solution took 2 hours. Most of that was discovering some weird things about PHP arrays, which was my first implementation, and then some odd things about the PHP functions.

The basic approach took about a minute of thinking. My first thought was to numerically weigh each bracket type, so '(' and ')' were 1, '{' and '}' were 2, '[' and ']' were 4, etc. Then simply accumalate totals moving throught the string. I quickly realized that would be easy to trick though. Plus it was over-thinking the problem.

All we really need is to track the open brackets, and if we find a closing bracket it needs to match the very last open bracket on our list. If it does match, remove the open bracket from the list.

Anyway, enough talk here's the solution and some test cases.

Update: As usual boundary cases are the tricky ones. I now check for spurious single characters at the end of the string by making sure we have an even number of characters.

function brackets ($t) {
   $open = '({<[';
   $close = ')}>]';
 
   $valid = (strlen($t)%2 == 0);
   for ($i=0; ($valid && $i<strlen($t)); $i++) {
      $curr = substr($t,$i,1);
      if ( strpos($open, $curr) === false ) {
         if ( $valid = ($i!=0 && (strpos($open,substr($prev,-1)) === strpos($close,$curr)) ))
           $prev = substr($prev,0,-1);
      } else
        $prev .= $curr;
   }
   return $valid;
}
 
function test_brackets () {
   $arr = array (
      '(', ']', '(]', ')', ']', ')(', '][', '()(', '(p', 'p(', 'p()', '()p', '({<)>}', // FAILS
      '', '()', '[]', '[]<>', '(())', '[](<>)', '[]<>({<<()>>})', '([](<{}>))' //SUCCEED
   );
 
   for ($x=0; $x<count($arr); $x++) {
      $out .= $x.'] '. $arr[$x]. ': '. ( brackets($arr[$x]) ? 'valid' : 'invalid'). '<br>';
   }
   return $out;
}

lClock

4 Stars Homepage -- Skins -- Download
v1.62b

lClock is a replacement for the standard Windows taskbar clock. Despite it's mere 3-star rating, lClock has remained on my PC in daily use for 5 years. It's pretty much a one-trick pony, but it does that trick very well. It provides complete control over the look of the taskbar clock. Along with tClockEx, lClock is destined to become a classic. The taskbar clock is now yours to control!

The Need
There's not much you can do with the standard Windows taskbar clock. It's a clock.
Taskbar clock

Hover the cursor over it and you get the date. Double-click and you get a calendar. Whoo. Not. There are no options that let you see the date, none to change the font, or format the time.

Try switching the Windows taskbar vertically, and now tell me the time. No can do, baby.
Taskbar clock

The Good
Enter lClock. All your vertical taskbars are belong to us!
lClock -- vertical

lClock was originally created to mimic the look of the then new Longhorn (aka Vista) taskbar clock which got a nice new face-lift. Apart from looking nice, lClock provides total control over every element of the date and time: you can choose colors, fonts, sizes, and positions for each element, for that precision you never knew you needed!

Continue reading...

Allowing uploads of all file types in Drupal

I just switched the site over from b2evolution to Drupal. In migrating posts I needed to attach some javascript files to a blog-entry. As a security measure Drupal renames files with executable extensions "php|pl|py|cgi|asp|js", appending an underscore and a ".TXT" extension. That's reasonable. What's odd is that there is no setting to provide an override, either to specific users, or site-wide.

My initial question asking if there was a setting to override this security feature met with limited response, so a bit of research later here's what I came up with.

Continue reading...

Using Subversion on a pre-existing directory

There are plenty of tutorials explaining how to setup Subversion on a Windows machine. Not so many good tutorials on how to actually use Subversion in the real world. In the rel world you sometimes need to apply Subversion to a bunch of files and folders that already exist. Applying Subversion to an already existing directory is more obfuscated than it needs to be. The user manual would have you believe that you need to Import, delete the directory, do a Checkout.

But what if you don't want to Import all files and sub-folders? It's the kind of thing you need to do very rarely, but when you do, it's always a pain to remember exactly the best way to go about it. But it's actually pretty simple: the key is to use SVN Add files rather than the SVN Import functionality.

Continue reading...

Firefox 3 beta 3, working for me...

I've been using Firefox for a long time, and liked it a lot. Recently that long honey moon period started to wane. Firefox 2.x has some pretty annoying performance and memory management issues, regularly chewing up 700-800Mb of memory (on a 1Gb machine), and hitting 90-100% CPU resource. Admittedly I have 4-5 windows open, with 10-20 tabs in each, and a bunch of extensions installed, so I run it hard, but none the less, the problems are there. I was also sick of fan-boys explaining away issues (even refusing to admit there were problems), with comments like "it's the extensions, duuude", or "what do you expect with so many windows, duuude". Neither of these are reasons for chewing up all resources on a machine. Opera was starting to look mighty shiny.

Continue reading...

Running a Verizon ActionTec behind Smoothwall

Here's how to hook up a Verizon ActionTec wireless router behind a Smoothwall firewall; actually this should work for getting the ActionTec to work behind pretty much any firewall. The ActionTec menu structure is not well described, and so this took a while to figure out -- and when I did it was ridiculously easy.

There were two keys in getting this to work. One was to recognize that the ActionTec and the Smoothwall firewall needed to be on different sub-nets. (Although I admit to not understanding why this is the case.) The second was to realize that the the only settings you need to change on the ActionTec are under "Network (Home/Office)" -- you do not need to change the "Broadband Connection Ethernet/Coax" settings, despite what the ActionTec error message might indicate.

  1. Set the firewall's IP to something other than the usual 192.168.1.x; I used 192.168.1.2 for example. I also set the firewall to act as a DCHP server, with a range of 192.168.2.50-99 -- this is not required, but makes it easier to setup the ActionTec.
  2. On the ActionTec under My Network->Network Connections, goto the "Network (Home/Office)" settings and change the IP address to a different sub-net; I used 192.168.1.1.
  3. On the same settings page mid-way down, enter the DNS Server using the IP of your Smoothwall (in my case that was 192.168.2.1).
  4. Not required, but you likely want to IP addresses automatically assigned on your LAN, so change "IP Address Distribution" to "DHCP Server" and specify a range of something like 192.168.1.50-99.

That's it. Hope that helps.

jqTOC: jQuery meets Table of Contents

A jQuery plugin that creates a table of contents for all header elements within the parent DOM element provided. (Based on original jqPageContent by Dimitri Spassov.)

By default, jqTOC produces a fixed, floating div box with the title "Content", in the top right of the browser window. When the box is clicked a new div will display a list of all H1, H2, H3 elements within scope of the parameter element. Each TOC element is a clickable link to the title in the document.

Start and end heading levels can be specified. All heading levels 1, 2, 3, is the default.

Continue reading...

Lyceum blog list widget

Save this widget in either the plugins or the systemplugins directory to display a list of all blogs in the sidebar. Make sure you remove the ".txt" extension -- it needs to be simply ".php".

Installing Lyceum with Clean URLs

28-Aug-06: Updated .htaccess code.

I was looking for a way to allow multiple blogs sharing the same installation. The setup I was looking for needed to have:

  1. The blog software installed in it's own directory. Cluttering the root up with files is simply not a good idea. Separation of Concerns is a good thing at all levels.
  2. Have users access their blogs using nice memorable URL, and to have links within the blog use a clean URL format. Something like username.domain.com is friendly. This is not friendly: username.blogs.domain.com.
  3. I wanted to use other software on this domain, so I did not want to use or set a document root. Doing this pretty much prevents any other software being installed at the root level on that domain.
Continue reading...