Monday, June 25, 2012

Wallpapering the Galaxy

I recently bought a "Samsung Galaxy Nexus gt-19250m". So far I'm enjoying the phone, but one of the things that drove me crazy was trying to figure out the proper size for the wallpaper image.  Allow me to save you that burden.

The Nexus's physical screen is 720 pixels wide by 1280 pixels high. Only half of the wallpaper's width is displayed at a time, whereas the entire height is displayed. Grinding the math gives an optimal wallpaper size of (720 * 2) x 1280, or 1440 x 1280.

Unfortunately, it's not as easy as that. Although the Nexus screen is, in fact, 1280 pixels high, the top 98 pixels are covered by the notification area and the bottom 48 pixels are covered by the soft keys. Griding that math again gives us 1280 - (98 + 48) or 1134 pixels.

Long story short:

To make a wallpaper image that won't get cropped or stretched, you need to create a 1440 x 1280 pixel image, with the actual visible part of the image is 1440 x 1134 pixels, and shifted down 98 pixels from the top.

Monday, August 1, 2011

Hey Unix, How About a Date?

The Problem.

I needed a way to warn users that their passwords were about to expire. To give them a sporting chance, I wanted to give them 2 weeks warning.

I could get the current date with no problem. Getting the password expire date was a bit of a pain, but I could figure it out. The hard part was figuring out how close to the 2 week warning date they were.

In a nut shell, doing math with dates is a royal pain. You have abstract concepts like “July 4th” permanently glued to a large spinning rock which is whizzing around the Sun.

Also, certain concepts that we're used to, such as 1 + 1 = 2, don't always hold up when doing date math. January 31st + 2 months = March 31st. No surprise. How about January + 1 month. That would be February 28th? Or would it be March 3rd (31 days after January 31st)? Add a month to February 28th and you get March 28th. March 31st doesn't equal March
28th. Oh boy!

The Simple (Linux) Solution
.

The most common way to deal with dates is to convert them to a number, do some math, and then convert the number back to a date. Unix (and Linux) system time is based on this concept. Unix dates are implemented as the number of seconds since the January 1st, 1970. In Unix parlance 1/1/1970 is called “the epoch”.

If you have a version of Unix that uses the GNU version of the date command (almost all versions of Linux do), then date math becomes trivial. The date command can convert to and from the epoch with relative ease.

To convert “August 1st 2011” to seconds from the epoch use:

date -u -d "8/1/2011" +%s

You should get 1312156800.

To convert it back use:

date -u -d "1970-01-01 1312156800 seconds" '+%m/%d/%Y'

You should get “08/01/2011”.

The problem here is 2 fold:

One, you're limited to dates between 1970 and 2038 for 32 bit computers. If you have a 24 bit computer then you're good until somewhere around the year 292,277,026,296 so it's not really a restriction.

The second problem is that most older OS's aren't running GNU date. They have their own propriety versions of date that won't let you work with arbitrary dates.

What I needed was a date converter that would work on many versions of *old* Unix. Things like Solaris 5 and HP-UX 10. These are nasty little beasts that barely have Bourne shell. I also wasn't allowed to add more advanced scripting languages to the system so Perl and Python solutions were both out.

I poked around on the Internet tubes and found a dearth of solutions. Most of them used other languages. Some gave example code that didn't handle leap years properly. Others were built around precomputed tables.

Time to step up to the plate.

My Solution.

Below is my solution. Its date format is the number of days after January 1st, 1582. That's the beginning of the Gregorian calendar and very few of my users are that old.

Internally it's mostly AWK scripts glued together by Bourne shell. It can handle dates up to 1/1/9794 and can probably go higher. I've tested it and think it's pretty bullet proof.

#!/bin/sh -

# Convert a date to/from the number of days after 1/1/1582 using only
# basic Unix commands. By "basic" I mean commands available on an
# HP-UX 10 box.
#
# 1/1/1582 is the start of the Gregorian calendar.

# Note: The Gregorian rules for leap years is:
#
# If the year is a factor of 400
# It's a leap year.
# Else If the year is a factor of 100
# It's not a leap year.
# Else If the year is a factor of 4
# It's a leap year
# Else
# It's not a leap year.

# This mostly uses awk because awk is much faster than using raw
# Bourne shell.

# To get a date from the Unix "seconds from the epoch" time use
# int($utime / (24 * 60 * 60)) + date_as_days(1970 1 1)
#
# date_as_days(1970 1 1) = 141714 by the way.

#
# Return the number of days in the previous months.
#
# For example the second entry is the number of days in January. The
# third entry is the combined number of days in January and
# February.
#
# The only parameter is the 4 digit year.
#
days_prev_month()
{
  echo $1 | awk '{
    year = $1

    # Pick the number of days depending of whether its a leap year.
    if ((year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)) {
      print "0 31 60 91 121 152 182 213 244 274 305 335 366"
    } else {
      print "0 31 59 90 120 151 181 212 243 273 304 334 365"
    }
  }'
}

#
# Convert a date in to the number of days after 1/1/1582.
#
# The parameters are YYYY MM DD.
#
date_as_days()
{
  dad_month=$2; dad_day=$3

  # Get the number of days consumed by the years and the number of
  # days remaining in the current year.
  set - `echo $1 | awk '{
    year = $1

    # The modern calendar started in 1582.
    year_days = int((year - 1581) * 365.25) - 365

    cents = int((year - 1501) / 100)
    year_days -= cents

    cents_400 = int((cents + 3) / 4)
    year_days += cents_400

    print year, year_days
  }'`
  dad_year=$1; dad_year_days=$2

  # Now add the month and day contributions.
  days_prev_month $dad_year | awk "
    BEGIN { day=$dad_day; month=$dad_month; year_days=$dad_year_days }"'
    { whole_month_days=$month
      print year_days + whole_month_days + day - 1 }'
}

#
# Take the number of days since 1/1/1582 and convert it to
# year, month, day
#
days_as_date()
{
  df_days=$1

  # This awk script computes the year contributions to the date
  # and removes the effects of those years from df_days.
  set - `
  echo $df_days | awk '{
    df_days = $1;

    # The first 400 year leap year in the Gregorian calendar is
    # 1600 so we normalize our calculations from the first block
    # of 400 years that ends on 1600. That year is 1201.
    # There are 139157 days between 1/1/1201 and 1/1/1582
    #
    # Note: We use 1201, not 1200 because we want the leap year to be the
    # *last* year of the 400, 100 or 4 year block.
    n_days = df_days + 139157

    # There is one leap year every 4 years.
    days_per_quad_year = (365 * 4) + 1
    # Years that end in 00 arent leap years.
    days_per_cent = (days_per_quad_year * 25) - 1
    # Unless its divisible evenly by 400.
    days_per_quad_cent = (days_per_cent * 4) + 1

    # Calculate the contributions of each year block.
    quad_cents = int(n_days / days_per_quad_cent)
    n_days -= quad_cents * days_per_quad_cent

    cents = int(n_days / days_per_cent)
    if (cents == 4) { cents = 3 }
    n_days -= cents * days_per_cent

    quad_years = int(n_days / days_per_quad_year)
    n_days -= quad_years * days_per_quad_year

    years = int(n_days / 365)
    if (years == 4) { years = 3 }
    n_days -= years * 365

    df_year = 1201 + (400 * quad_cents) + (100 * cents) \
      + (4 * quad_years) + years

    print n_days, df_year
  }'`
  df_n_days=$1; df_year=$2

  # Get the day and month from the given year.
  set - `days_prev_month $df_year | awk "
    BEGIN{n_days=$df_n_days}"'
    { df_month = 1
      while (n_days >= $df_month) {
        df_whole_month_days = $df_month
        df_month++
      }
      df_day = 1 + n_days - df_whole_month_days
      print (df_month - 1), df_day }'`

  df_month=$1; df_day=$2

  echo $df_year $df_month $df_day
}

# Some test code. Feed it a number and get back a date.
# Feed it a m/d/yyyy date and get back a number.
#
# Note the complete lack of error checks.
if echo "$1" | egrep '/' >/dev/null 2>&1; then
  set - `echo $1 | tr '/' ' '`
  date_as_days $3 $1 $2
else
  days_as_date $1 | awk '{ printf "%02d/%02d/%02d\n", $2, $3, $1 }'
fi

Sunday, June 19, 2011

Python, GTK, GL and Incantation.

In computer terms, an “incantation” is a problem that can easily be solved if you know the proper mystical invocation. An incantation is especially annoying if it's something that has to have been done many times before, but no one as bothered to tell we mere mortals how they did it.

Linux suffers incantation at a near mystical level. People who write library code seem to take a sadistic pleasure in not telling people how to use said library.

I ran in to this in spades when I tried to use Python to hook up the OpenGL graphics library to the GTK widget system. I didn't have too much trouble finding examples of hooking GTK to Python, the PyGtk libraries are full of examples. I didn't have too much trouble finding OpenGL examples in Python. Search for “PyOpenGL Demo” and you'll probably find what you need.

My problem came from trying to hook Python, Gtk and OpenGL together as one big happy family. I couldn't find one complete example on the net. I could find some pieces, but no complete example.

To make a long story short, I finally found enough pieces, and read enough source code to have a pretty good idea of how to get the job done. In true Linux fashion it turns out to be pretty easy. The documented code is at my website. Hopefully there is now one less incantation in the world.

Monday, November 8, 2010

Hideous Bloat and Active Links.

By popular demand I've expanded my Emacs wiki from one function to an unwieldy two. The second function will scamper through a buffer and list all the active links found.

I use the same regexp that I did in the previous article so it links on CamelCase. To change the link style you just change the regexp. If you end up writing too many support functions then you may want to use that "variable" thing that all the cool kids are talking about.

The Code



(defun list-active-links (link-re &optional is-active-link-p)
"Scan a buffer looking for links and list all the active links.

LINK-RE is a regular expression which matches the link text.
IS-ACTIVE-LINK-P is an optional function which takes the link text and
returns true if the link is active. If not provided, `file-exists-p' is
used."
(let ((buffer-name "*ActiveLinks*")
(found-links ()))

(if (not is-active-link-p)
(setq is-active-link-p 'file-exists-p))

;; Gather up all the potential links and whether they're active.
(save-excursion
(goto-char (point-min))
(while (re-search-forward link-re nil t)
(let ((link-text (match-string-no-properties 0)))
;; If the link hasn't been checked, then save its value
;; and whether or not it has an existing destination.
(if (not (assoc link-text found-links))
(setq found-links
(cons (cons link-text
(funcall is-active-link-p link-text))
found-links))))))

;; Now list out the active links.
(if (get-buffer buffer-name)
(kill-buffer buffer-name))
(switch-to-buffer-other-window buffer-name)
(let ((active-links
;; Remove any links that don't have an associated file.
(delq nil (mapcar (lambda (x) (and (cdr x) (car x)))
found-links))))
(insert "#\n# The following links have destinations.\n#\n")
(save-excursion
(insert (mapconcat 'identity (sort active-links 'string<) "\n")))
(not-modified)
(message "%d matches found." (length active-links)))))

(defun check-active-links ()
(interactive)
(let ((link-re "\\<[A-Z][a-z]+\\([A-Z][a-z]+\\)+\\>"))
(list-active-links link-re)
;; Note: At this point we're in the "*ActiveLinks* buffer.
(set (make-local-variable 'link-to-re) link-re)
(local-set-key
(kbd "C-c C-o")
(lambda ()
(interactive)
(link-to link-to-re "\\<")))))

Sunday, November 7, 2010

Emacs, the Wiki and the Idiot.

Sir C.A.R. (Tony) Hoare once wrote:
Inside every large problem, is a small problem—struggling to get out.
Someone else, stealing from H. L. Mencken, changed it to:
Inside every large problem, is a small problem—struggling to get out. The solution to that problem is simple, elegant and wrong.
I tend to agree with the Thief. The simple reality is that many problems don't have elegant solutions, try as we may to find them. I ran into this when I tried to come up with a simple personal wiki. Enjoy my exploits.

Dale Writes a Wiki


I think the wiki is one of the great software concepts of the last decade or so. That's not hyperbole, I really think that making it easy to link documents together, in a casual and non-invasive way, is a brilliant and under-appreciated concept.

Most wikis are web based. This makes sense if you want the world to have access to the pages. I was looking more for a personal solution.

There are personal wikis that are stand alone applications, but most of them use a special format for your data. This strikes me as, well, stupid. Why would I lock up my data in a special format when a directory of text files should easily get the job done?

I do a lot of my text editing in Emacs, so I started looking around for an wiki based in Emacs. There are a few, but most of them are either unsupported, too elaborate or too invasive. I wanted a way to link text from any kind of file, not just wiki files. I wanted to be able to link comments in source code to documentation files to cake recipes if that's what works best. I also wanted it to leave the rest of my Emacs environment alone. I didn't want to enter Wiki-Mode just to put links in a Perl program. I wanted to stay in Perl mode.

The joy of being a programmer is, if you can't find it, you can always write it. That's what I started out to do.

At first I decided to play with [[bracket style links]]. Emacs Org Mode uses them and I like much about Org Mode, so I tried to emulate its style.

The attempts where not too successful. I pulled out some of Org Mode's handler code and started playing with it. It's pretty invasive and doesn't work well with old versions of Emacs. I use an old version of Emacs at work, and I wanted something small and easy to understand.

My next idea was to write my own bracket style linking library. At it's heart it would grab the text between [[]], convert it into a file name and then open the resulting file name. 194 lines of Elisp later and I had a working minor mode. It could open files, web pages, internal links and even run commands. I was very happy with it. It was reasonably small and reasonably easy to understand and reasonably noninvasive.

Because I'm a professional, I started to document my results. The problem is, I'm a little bit insane. Sometimes, when I'm working on a project, a little idiot voice calls from the fog of experience and tells me what I'm doing is wrong. The Idiot never tells me what's right, it just picks at the back of my head until I accept, eventually, that my perfectly working code is "wrong". Arg!

The more I documented, the louder the Idiot got. I got so frustrated that I put the code aside. I'm a big believer in documentation by Idiot. You take your code and ignore it for a few weeks or even months. Then you come back and try to read it. Every time to look at a bit of code and say "What idiot wrote this?" you either re-factor or document. Maybe the Idiot could figure out what I couldn't.

The Idiot was insidious. It would go away for a week or so and then come out of the shadows to jeer hints. It asked questions that I should have asked. Do I need brackets? Do I need to open web pages and run commands from links? Are my needs the needs of others? What's more important, abstract power or agility? What is the DAO of the problem? Why won't you see it!?

This went for over a month. Part of me was trying to find the right solution. Part of me wanted me to finish what I had and get on with my life.

Then, on a Sunday night, as a long work day loomed ahead, I was laying in my bed with my beloved wife and Charlie the metal eating dog. From nowhere, it came to me. All I really want is a way to take the word under the cursor and open a file with the same name. Then it came to me. What I really want is a way to grab an arbitrary blob of text under the cursor and then open up a file based on the text. Then it came to me. What I really want is a way to grab an arbitrary blob of text under the cursor and do something with it. The Idiot had spoken!

It's a cliche, but I really wanted to leap out of bed and start hacking away. Alas, the days of 12 hour hackfests followed by 10 hour workdays are a thing of the past. I had to go to sleep or I would die at my desk. I had to go to work or I would be thrown into the street. I had to get this program written or I would crack up.

After work I lit in to my task. One of the greatest pleasures in programming is simplifying. The more I wrote, the smaller the program became. Irrelevance fell like rain. I was beginning to understand. By the end, the entire program is 15 lines long. 24 lines if you include the code to hook it up to the key of your choice.

It was simple, elegant and worked like a charm. The Thief was wrong. The Idiot stopped jeering.

Hooking Up the One Function Wiki

The simple solution is to take the text at the end of this article and append it to your .emacs.el file.

To test it, fire up Emacs, and type "This is CamelCase text.". Move your cursor to the link text "CamelCase" and type C-cC-o. It should open up the file "CamelCase".

If you want to use other link styles besides CamelCase or want to open files in different way, read the documentation. Doing things like opening files in a specific directory or opening "CamelCase.txt" are trivial to implement. You just need to do a little Elisp programming and away you go!

The Text to Append.

(defun link-to(link-re link-start-re &optional handle-link)
"Grab the \"link\" under the cursor and open a file based on that link.

LINK-RE is a regular expression which matches the link text.
LINK-START-RE is a regular expression which matches the beginning, or text
just before the link.
HANDLE-LINK is an optional function which takes the link text and opens the
link. If not provided, `find-file' is called with the link text.

This function is usually called via local-set-key with mode specific
regular expressions.

This example will grab a CamelCase link and open a file with the same
name.

(global-set-key (kbd \"C-c C-o\")
(lambda ()
(interactive)
(link-to
\"<[A-Z][a-z]+\\\\([A-Z][a-z]+\\\\)+>\"
\"<\"))) Note: The \"<>\"s above should have \"\\\" in front of them, but emacs
thinks I want to print a key map when I try to include them in the help
text.

This example will grab an alphabetic string and do a google query on it.

(global-set-key (kbd \"C-c C-o\")
(lambda ()
(interactive)
(link-to
\"[a-z]+\" \"[^a-z]\")
(lambda (x)
(browse-url
(concat \"http://www.google.com/search?q=\" x)))))"
(let ((here (point)) link-text
(case-fold-search nil))
(save-excursion
(or (re-search-backward link-start-re nil t)
(goto-char (point-min)))
(unless (re-search-forward link-re nil t)
(error "No tag found to end of file"))
(setq link-text (match-string-no-properties 0))
(if (or (< (point) here)
(> (- (point) (length link-text)) here))
(error "No tag found under cursor")))
(if handle-link
(funcall handle-link link-text)
(find-file link-text))))

(global-set-key
(kbd "C-c C-o")
(lambda ()
""
(interactive)
(link-to
"\\<[A-Z][a-z]+\\([A-Z][a-z]+\\)+\\>" "\\<"
;; This regexp pair matches file names.
;;"[a-zA-Z0-9/~_][a-zA-Z0-9/._]*[a-zA-Z0-9]" "[^a-zA-Z0-9/.~_]"
;; This will open text files in your ~/Wiki directory.
;;(lambda (x) (find-file (concat "~/Wiki/" x ".txt")))
)))

Thursday, September 2, 2010

Reading Web Pages From the Android SD Card

Android 1.6 (Donut) tries to make it impossible to read web pages from the SD memory card. Fortunately there is a flaw in their security that lets a user create a specially formatted URL that allows access. This technique may work for other versions of Android but I've only tested it on 1.6.

This is an easy hack. The only skill required is the ability to drag and drop files from the computer to the phone and to connect to this web page via the Android.

Terminology

For the sake of simplicity the Android based phone is just going to be called the Android. It reads easier.

Local files are the files on the Android SD card. Any references to "the card" mean the Android SD card.

The Desktop is the computer that will be used to edit files and drag and drop the files to and from the Android.

"The browser" is the browser on the Android.

Overview

A web page is created on a computer and moved to an arbitrary, but known spot on the Android SD card. A special URL is entered in the Android browser which points to the page. The page is made into a book mark by bypassing the bookmark editor. The web page can then be edited to point to any other location on the SD card.

The Direct Way

This way is direct, but it involves a bit of typing on the Android keyboard. Most people find the longer way easier to get correct.

Put a web page the SD card. This example will use the file webpages/index.html.

Open the browser and type in the URL content://com.android.htmlfileprovider/sdcard/webpages/index.html.

If index.html shows up in the browser, go to the section "Saving as a Book Mark". If not, check the URL spelling and file location. If the problem can't be solved, use the longer way.

The Longer But Less Fussy Way

This way requires creating a web page on the desktop and the ability to drag a file from the desktop to the Android.

Open an editor ("notepad" will do) and paste the following text:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Found the sd card!</title>
</head>
<body>
<h1>It worked!</h1>
<ul>
<li><a href="content://com.android.htmlfileprovider/sdcard/foo.html">Self reference.</a></li>
<li><a href="webpages/index.html">Relative links work also.</a></li>
<li><a href="http://upcracky.blogspot.com">An external link.</a></li>
</ul>
</body>
</html>


Save the file as "foo.html". This is just a temporary file and the name has to be "foo.html" or the rest of the steps won't work.

Copy foo.html to the top level directory of the SD card.

Unhook the Android from the Desktop.

Connect to this blog entry via the Android browser and click on this URL. foo.html should be displayed in the browser.

Saving the Bookmark

While display the web page in the browser, press the menu key. Select "Bookmarks". Select "History". Select "Today". Find the entry for "Found the SD Card!" and click on the star symbol on the right. The bookmark will be added to the browser with no further intervention.

Do not use the "Edit bookmark" option. Just opening the book mark editor with this book mark may corrupt the link and it will stop working.

Changing the Name of the Bookmark

Since the bookmark can't be directly edited, some cleverness is required to move the SD web page and/or change the name of the bookmark.

First create a new web page and install it on the SD card in any arbitrary folder. Edit foo.html and add a link to the new page relative to this page. Bring up foo.html via the previous book mark. Click on the link to the new page. Bookmark the new file.

Once the new page is safely bookmarked, foo.html and it's bookmark can be deleted.

Limitations

The one quirk that hasn't been figured out is how to jump to the middle of a local web page. Links such as bar.html work fine. Links such as bar.html#middle give an error.

Sunday, August 29, 2010