Saturday, October 27, 2007

Using VMWare as a Cross-Platform Virtualization Platform

As part of my Microsoft Windows XP Quit Date strategy, I have been looking into using VMWare as a replacement technology for my Microsoft Virtual PC images.

I started using Virtual PC as a replacement for my dual-boot setup. I still have a dual-boot (actually a tri-boot setup), but I rarely, if ever, use it. The problem is that everything that I do need is on my Windows XP, NTFS-formatted, C: drive. NTFS-formatted drives are not writable from Linux, so when I boot into SUSE or Ubuntu, I feel like I can't update the files that I need to update or use software that I need to use.

As a result, I set up a SUSE 10.1 Virtual PC image. I don't use the GUI. Although GNOME looks awesome when I boot directly into SUSE or Ubuntu instead of Windows, the GUI is somewhat restrictive in Virtual PC. Instead of 1280x1024 screen resolutions, I'm limited to 1024x768.

Since starting my new job back in February, I've become extremely comfortable working from a Linux command prompt. In fact, I'm so comfortable at the command prompt that I feel lost when I try to do something using the GUI. Come to think of it, I don't even think we have the GUIs installed on our servers at work!

The main advantage that this gives me is a powerful development environment. I run Apache on the Virtual PC image, and I use this configuration to locally host development environments for websites that I am working on.


The NavCalendar Application



For example, I'm working on a Calendar application for Edúcate Ya. I'm building it in PHP. I chose PHP because their website is already built using PHP, and by using this technology I can get this application to market quicker than I would using some other technology. I host the development environment at http://dev.educateya.org locally on my Virtual PC image, and I created an entry in my Windows host file that maps the local IP address of the Virtual PC image to that host name. (The host file is located at C:\WINDOWS\system32\drivers\etc, and if this is the first time opening the file, one entry will be present by default. The default entry maps the host name "localhost" to the loop back IP address 127.0.0.1).

I configured Apache using Virtual Hosting. I created a configuration file mapping the IP address of the VMImage and port 80 to the hostname dev.educateya.org. After restarting Apache in Linux, and flushing the Windows DNS cache by running "ifconfig /flushdns", I was able to view the development version of the website on my local network.

In addition, this configuration gives me the ability to view the website on any computer on my network as long as the host file is mapped with the IP address and host name. This means the Virtual PC image could run on a server instead of my local PC, which would free up some memory used by the Virtual PC image!


Migrating to another Operating System



I've strayed from my point. I have, however, provided some insight into how I use virtualization technology and why it would interfere with my productivity should I lose the ability to boot my SUSE image. Virtual PC only runs on Windows. It can run many operating systems. I've successfully run Windows 3.1, Windows XP Home, Windows XP Pro, Windows Server 2003, Ubuntu 6.0.6, SUSE 10.1, several Knoppix versions, and FreeDOS. Currently, I only depend on the SUSE image although I have used the other operating systems as test platforms on several occasions.

As I mentioned, Virtual PC can run several operating systems, but it can only run on Windows 2000, XP, and Vista. Since I want to move toward software that runs on multiple platforms, I've been looking at VMWare. I use VMWare Player at work to run a Linux environment on a Windows XP machine in much the same manner as I do at home, and it works great! One of my coworkers also ran a Linux VMWare image on his Ubuntu desktop. Therefore, I know firsthand that it's cross-compatible with both Windows and Linux, and I know how the software works.

But what I recently discovered this-morning was something that is quite common in many open source software packages. VMWare offers users the ability to convert Virtual PC images to VMWare images! This is awesome! I don't have to go through the time-consuming process of reinstalling SUSE 10.1 on a VMImage and configuring it the way I want! Using the VMWare Converter, Virtual PC users can convert an image to VMware format!

After getting more hard drive space, this will be the next step in preparing to quit using Microsoft Windows XP.

Running dual-boot setups concurrently



While writing this piece, I stumbled upon an article that describes how to Run an Existing Windows Installation on Ubuntu with VMware Player. The author does not describe why these steps work, but he does outline the steps required to configure VMWare Player and the Windows installation. Personally, I wouldn't try these steps on a production machine, as having a third-party tool control Windows is not supported by Microsoft. Of course, neither are dual-boot setups, but I've never had an issue with dual-boot setups. Also, with a dual-boot setup, the operating system is not controlled by a third-party process. However, by following these instructions, you'll be allowing a third-party tool to control the environment that Windows runs in.

The bottom line is that VMWare Player can run a non-virtual installation of Windows, according to the article. I'm not going to try this myself as I don't have a spare PC available, but if anyone has tried this I would love to hear your experiences!

In summary, I've included a list of cross-compatible open source software that I currently use:


Soon, I'll add VMWare to the list.

UPDATE - 7/5/2008: I have configured VMware Player on Ubuntu 8.04 to share a Windows XP VMWare image with Windows XP Pro as an enhancement to a dual-boot setup. Read more about it! It's easy to setup and configure, and you'll be glad you did!

Sunday, October 21, 2007

PHP Navigational Calendar

I'm working on a project for Edúcate Ya that involves placing a calendar on the home page. The idea is that the calendar will be used to display any public events, classes, guided trips, fund raiser events, and anything else of importance that an organization may want to advertise on a web page.


NavCalendar Application - Navigational Calendar



Each event listed on the calendar would be a hyper link to another page on the website that provides more details about the event. I ran a few Google searches to see if I could find something that would fit. There are of course plenty of HTML, JavaScript, and many other types of Calendars to choose from. However, everything I found either was way more than what I was looking for, cost money, or did not have the navigational feature I was looking for.

Many of the calendars were similar to a web-based Microsoft Outlook, which an organization could use to help employees manage group schedules. Not only did these calendars have way too many features, but also they weren't the features we were looking for.

So, I decided to build a Calendar using PHP. I chose PHP because the Edúcate Ya website was built with PHP, so the server is already configured to use PHP. I started working on this towards the end of August. Yesterday, I was able to generate -- using PHP -- a calendar with a list of events that were pulled from an XML data file.

I chose XML because the list of events for Edúcate Ya is small. However, my plan is to retrofit the application with an abstract class that will allow developers to add different data sources, such as a database. I also designed the system so that a front-end controller loads a "view" based on a parameter passed when calling the controller. Anyone who wishes to use this application could simply replace the view with their own by using the API.

The back end functionality is somewhat in place. The implementation doesn't yet fit the architecture, but I wanted to get this to market for Edúcate Ya as soon as possible. So, as many software development projects go, I took some shortcuts. The abstract class representing the data sources is still visible only on paper, and the APIs required to build the view are somewhat tightly coupled. It's not perfect, but it works for me right now.

The actual HTML and CSS need some major overhauling. That is the next step in this process. However, my hope is that the Navigational Calendar may turn out to be useful to others who wish to have a Navigational Calendar on their website. In order to realize this goal, the final step will involve making it easier to build a view. Currently, a developer would have to first build a static HTML calendar, and then integrate it with the HTML-generating PHP code so that the correct month is displayed with the correct data. This also means that I will need to throughly document everything, which is something that I haven't done much of outside of my full-time employment.

I plan to use the open source cross-platform software Gimp to apply the "chrome" for the calendar.

Tuesday, October 16, 2007

The Gmail Dependency

I knew it was going to happen one day, I just wasn't sure exactly when. I knew one day the script would suddenly stop working. Not because code rusts. Or because the code cracked like glass, but because the foundation that it depends on cracked.

Well, it didn't really crack. It's more like what happens when a house settles. It's just digging itself in. Gmail was digging itself in. The developers added a new parameter to the URL that opens the HTML Compose editor. ui=1. If they added it to the end of the URL, it wouldn't have made a difference. But regular expressions care about where certain things are placed. Order doesn't matter in a URL parameter list, so Google developers could put this parameter wherever they wanted.

However, the script stopped working. The regular expression logic asks if the URL matches a specific "include" pattern. For most URLs, nothing happens, the script does nothing. There's no need to use processor power unnecessarily if there is no Gmail HTML content window to paste HTML into. Plus, users may get annoyed if the HTML popped up somewhere unwelcome.

If the URL were to match the pattern, then the code is executed. The HTML is read from an XML data file, as is the Greasemonkey Script. At a specified location in the script, JavaScript variables are generated, which contain the HTML retrieved from the XML file. This re factored JavaScript is then evaluated and dynamically inserted into the HTML content window of Gmail, using a compiled Greasemonkey engine.

An asterisk is all it takes. One small character, just 2 bytes of data, is enough to break functionality.

HTML Multiple Reply Signatures for Gmail is dependent on the functionality of Google's Gmail interface. The URL change was an easy fix, but should Google decide to perform a major overhaul of the Gmail interface, the HTML Multiple reply Signatures for Gmail scripts and Firefox Extension would reach the end of their useful lives. Better Gmail, and many other Firefox extensions built around Gmail's interface, such as Gspace, may also be rendered useless.

Manage Email Signatures in HTML Multiple Reply Signatures For Gmail
- Click the "Edit" button.


HTML Multiple Reply Signatures for Gmail

- Add the asterisk where indicated by the highlighting.


For all of the do-it-yourselfers, I highlighted the area where I had to make the change. If you're using one of the Greasemonkey scripts, the Firefox Extension, or another type of HTML Signature injector script that recently broke, you can fix it by making sure that highlighted asterisk is added to the included URL or regular expression. That's right! Even if you're using another Gmail HTML injector script other than one that I created, you can fix it yourself by editing the include URL list and correcting any errors!


Of course, if you find that you would rather get a new, updated copy, all of the links in the menu on this website reflect the updated URL changes. Since installing or reinstalling the scripts should fix the problem, you could just download a new copy and reinstall it.

Thursday, October 11, 2007

Nested-Nested Quotes

Larry Wakeman of Memory Pharmaceuticals recently sent me a reminder about a follow-up article that I forgot to write. Back in April, I addressed the concept of quotes within quotes within quotes and how to handle this phenomenon.

Any programmer who has ever had to write Greasemonkey scripts, as well as to perform any type of server-side or client-side programming has or will encounter this particular problem. For example, a JavaScript function that generates HTML that contains attributes that refer to JavaScript functions that take strings as parameters, will require some cleverness on the part of the developer, especially if the parameter passed into the JavaScript function is determined at the time the HTML is generated:


<html>
     <head>
     </head>
     <body>
         <script type="text/javascript">

    function alertParameter(stringParameter) {
         alert(stringParameter);
    }

    var topLevel = "test";

    function generateHTML(topLevel) {
         document.write("<a href=\"#\" onclick=\"alertParameter('"+topLevel+"')\">Click this link to see the result</a>");
    }

    generateHTML(topLevel);
        </script>

    </body>
</html>



Here is a breakdown of the above process: The text "document.write" is what I refer to as top level. This is the actual command that outputs the string of text included within the outer quotes. The outer quotes are the quotes that wrap the text inside the parenthesis of the document.write method.


document.write(" /* These quotes are the outer quotes */ ");


Note that there are two types of quotes: Single quotes and double quotes. We can use either to represent the outer quotes. For this example, I chose double quotes. The first set of inner quotes, like the outer quotes, can also be double or single quotes. However, if the inner quote is the same as the outer quote, then the inner quote must be escaped. Consider the following example:

Nested JavaScript Quotes Example 1



document.write("<div onclick=\"alert('ht')\">click me</div>");


The above example is the same as the following example:

Nested JavaScript Quotes Example 2



document.write("<div onclick='alert(\"ht\")'>click me</div>");


Also, to demonstrate that we can use single-quotes as the outer quotes, check out this example:

Nested JavaScript Quotes Example 3



document.write('<div onclick="alert(\'ht\')">click me<div>');


Take a careful look at the above three JavaScript nested quote examples. Understanding this concept is a prerequisite to understanding deeper JavaScript nested quotes.

As I mentioned, the outer quote can be either a double or single quote, and the first inner quote can be either a double or a single quote independent of the choice made for the outer quote. In Example 1, I used double quotes for both the outer and inner quote, whereas in Examples 2 and 3 I alternated between single and double quotes. For convenience, here is Example 1 again:

Nested JavaScript Quotes Example 1



document.write("<div onclick=\"alert('ht')\">click me</div>");


It may seem confusing at first as to how this is possible, until you see the output in the browser source (of the generated HTML, that is. I'll go into more detail on this later):


<div onclick="alert('hi')">click me</div>


The outer quotes don't appear in the generated HTML. Those were top level quotes. They served only to wrap what was being generated. As you can see, the escaped double-quotes render as actual quotes, and cause absolutely no conflict.

Nested JavaScript Quotes Example 4



document.write('<div onclick="alert(\'ht\')">click me</div>');


Example 4 produces the same output! Except in example 4 it is the single quotes that must be escaped, as this time single quotes represent the outer quotes.


JavaScript Inner, inner quotes



By this point, it should be quite apparent that there are several combinations of outer and inner quotes that can be combined without causing a non-terminated string literal error. However, after choosing an outer and an inner quote, choices become much more limited. Instead, from this point forward, nested quotes must alternate between single and double quotes. Below is an example:


<html>
     <head>
     </head>
     <body>
         <script type="text/javascript">

    function alertParameter(stringParameter) {
         alert(stringParameter);
    }

    var topLevel = "test";

    function generateHTML(topLevel) {
         document.write("<a href=\"#\" onclick=\"alertParameter('Say \\'Hello World\\'')\">Click this link to see the result</a>");
    }

    generateHTML(topLevel);
    </script>

    </body>
</html>


You may have noticed that the previous paragraph contains a sentence with strikethrough styling. After trying the example I was going to try, I realized that the rule that the quotes must alternate is not necessarily true. I'll explain, but first, here is the output when clicking the link:

Say 'Hello World'

Definition of literal quote: This is a quote that represents a quote as text in a string. A quote that marks the beginning or end of a string is a non-literal quote, and it is not part of the actual text. A non-literal quote can be represented as a literal quote by escaping it with a backslash (\) character.

Since the outer quote is a double quote, the inner quotes are literal quotes in the string. If the outer quotes were single quotes, then double quotes would be literal. As a result, I can place as may single quotes in a row as I want without affecting the String. However, this will affect not what occurs with the output, but what occurs with the output of the output:

(" ... onclick=\"alertParameter('Say \\'Hello World\\'')\"> ... ")

Outer quote = " (This marks the beginning and end of the string)
Inner quote = \" (Escaped as to not flag "beginning/end of string")
Third-tier quote = ' (Literal quote)
Fourth-tier quote = \\' (Literal quote that will be generated as an escaped outer quote)

This is what really makes this JavaScript nesting quote process complicated. As I mentioned, the single quote is a literal quote. This means the string treats it as a normal character. However, in the HTML -- in the output that is -- the single quote becomes an outer quote. The single quotes around 'Hello World' are literal quotes in the JavaScript code, but in the HTML, these single quotes are inner quotes that must be escaped. However, using a single \' would simply result in a '. So the trick is to escape the slash. Thus, a document.write("\\'"); would produce a \' in the HTML, and this would be resolved to a ' if processed again.

Essentially, you must take two things into consideration when dealing with escaping a quote in JavaScript. If it needs to be escaped in the inner string, then you must think one level deep. It helps to move backwards. Write your desired output first, and then go through and "wrap it" with the tools that would generate it:


<script type="text/javascript">document.write("<a href=\"#\" onclick=\"alert('Say \\'Hello World\\'');\">click here</a>");</script>


I want to dynamically generate this embedded JavaScript from the server with PHP. So I'll first verify that this works in between the body HTML tags of a PHP document. It does indeed work. Next, I'll wrap it with a PHP echo statement:


<? echo "<script type=\"text/javascript\">document.write(\"<a href=\\\"#\\\" onclick=\\\"alert('Say \\\\'Hello World\\\\'');\\\">click here</a> \");</script>'"; ?>


Escaping JavaScript quotes is recursive. After wrapping the PHP echo around the JavaScript with double quotes as outer quotes, I then had to escape the previous outer quotes. I then had to escape the inner-inner double quotes not once, but twice. Once to escape the backslash used to escape the quote, and once to escape the quote so that PHP wouldn't treat it as the end of the string. What I found most interesting is that the single quote used as the outer wrapper of the alert text was ignored during the PHP wrapping process because it is a literal quote. However, the innermost single quote had to have two backslashes added -- once to add another backslash and once to escape that backslash! Each time a wrapper is added, an escaped special character must be escaped again because during each iteration, a backslash escapes a backslash!

In summary, I'm not sure if this little exercise will be of any practical use. Perhaps it would be a good problem solving exercise during an employment interview to see how good a programmer is at dealing with complex layers of abstraction. Perhaps a situation will arise where one actually needs to generate different JavaScript functions based on different criteria. I can't think of any examples other than the Multiple HTML Reply Signatures Embedder for Gmail Greasemonkey script that I wrote, and sometimes I think that there may have been an easier way to generate a dynamic-drop down list in Gmail without having to nest quotes in JavaScript. Bottom line -- I'm not sure. However, if this has proved helpful, please share your story with me!

Sunday, October 7, 2007

Update for HTML Multiple Reply Signatures for Gmail

10/09/07 UPDATE: Due to a change made to the Gmail URL structure, the HTML Multiple Reply Signatures Extension suddenly stopped working. I've updated the URL to reflect the newest, working version.


There have been some problems with the Firefox Extension that can make inserting HTML signatures in Gmail somewhat of a hassle. However, in spite of these issues, people have been downloading and using it. To my surprise and pleasure, I've received quite a bit of positive feedback. For those of you who have given me feedback, thank you! In order to address some of the issues that you've had and to accommodate some requests I've received, I've updated the extension, which can be downloaded by clicking on the following link:

Multiple HTML Reply Signatures Extension 1.0.2

Multiple HTML Reply Signatures Extension 1.0.2.1


Multiple HTML Reply Signatures Extension 1.0.2.2


I've added multi-line functionality to the editor, so you won't have to type the HTML all on one line. In addition, this should make it much easier to paste HTML directly into the editor. This was causing the script to not function when HTML was pasted, since HTML is typically not written all on one line.

HTML Multiple Reply Signatures for Gmail Email Signature Editor

I also added an update notification to the new version. Firefox Extensions support update notifications through RDF, but since my hosting provider doesn't respond to RDF requests with "text/rdf" like an Apache server would, I was forced to create a hack that uses a regular expression to check the version number against my server. The cool thing about my custom version of update notifications is that the HTML Multiple Reply Signatures for Gmail extension will simply insert a "Click here to update" button in the tool bar.

HTML Multiple Reply Signatures for Gmail Updates

It's not the most elegant way to notify users of an update, but I absolutely hate popup windows. This tool bar button is very unobtrusive. An image or a logo would be cool, but that's not my specialty so for now, it's plain text.

I started looking into the issue of why quotes won't work in the extension. This is turning out to be a lot more complicated and will take a lot more time to resolve. The problem is that the quotes have been escaped so many times that I think the strings aren't being parsed correctly. For now, you must enter your attributes without quotes like I've done below:

<a href=http://blog.opensourceopportunities.com style=color:orange>Blog</a>

Oh, I recently discovered that ampersand codes weren't supported. That has also been fixed. You can now use &nbsp; in your HTML, if needed.

I'll continue to fix bugs in this extension. The quotes are a big one, but not easily fixed. As always, if you have any problems, questions, concerns, or suggestions, please email me and I'll respond as quickly as I can.

Friday, October 5, 2007

Gedit and Open Source Text Editors

I found this article on the GNOME default text editor, Gedit to be quite interesting. I was impressed by the functionality that it provided when I used it in both SUSE and Ubuntu while I was working on a Firefox Extension.

The editor is actually more powerful than I gave it credit for. Micah Carrick, the author of the article, uses the editor as an Integrated Development Environment! Apparently, there are plugins that come with Gedit by default that allow you to customize and extend the functionality of the editor. In just a few short steps, you can import a file tree, connect to an FTP site, or instantly insert XHTML, CSS, PHP, and other code simply by clicking on items in a tag list!

Is tab completion something that you find helpful or perhaps necessary? There is a plug in for that as well. Apparently, there is also an embedded terminal that supports ssh connections. Although I'm happy with Putty in Windows or the default terminal in Linux, this could be useful if you prefer to integrate your tools into one application.


Vi



Although Gedit is open source, I'm disappointed that it isn't available for Windows. One thing that really makes an application stand out is cross-platform compatibility. I'm not just a proponent for open source software; I'm a supporter of open source software that runs on multiple platforms because it promotes freedom of choice. This cross-compatibility is part of my Microsoft Quit Date strategy.

In terms of text editors, I prefer Vi. Not only does it come standard with every single Linux distribution out there, but also it's available for Windows! I use it both at work and at home, and it makes editing code much easier when I'm away from a Linux terminal. The most beautiful thing about Vi is that if I'm sitting in front of an open Linux terminal, I can edit any text file, anywhere I want. If I'm editing a file located on a computer in India, I can do so. While the terminal does respond a little slower, quickly editing a file would be difficult using an Integrated Development Environment.

The main problem with using an IDE is that you have to configure it. It doesn't work right out of the box. While tools like Vi have a very steep learning curve, I can move from one computer to another and pick up working right where I left off with nothing more than a Linux terminal and a VPN connection.

Of course, the main thing I like about Vi is that I can do so many things without ever having to take my hands away from the keyboard.

Although I like Gedit, the fact remains that it's not available in Windows. Since declaring my quit date, I haven't started using any new cross-platform tools. However, I realize that in terms of text-editors, I've already started this process by using Vi.

Tuesday, October 2, 2007

The Microsoft Quit Date

I think I need to set a quit date. I've been talking about doing it for some time now. Eventually, the time for talk will be over, and it will be time for action.

As I previously mentioned, I may be in the market for another computer in the near future. This could happen anytime between now and 2009. I want to set up a server. That may involve setting up a Linux box. It could involve using this PC as the server, which means I'll put Linux on this PC and who knows what on the new computer.

I currently use Windows XP Professional. Overall, I don't mind using Windows XP. First, I'm familiar with it, so my opinion of it is somewhat biased. Second, I recall how often Windows Millennium would crash, and I realize that in comparison, Windows XP is far superior.

What concerns me is DRM. It's a joke. I've read the articles and the arguments and how there is one group of people who use "freedom" as their argument against DRM, and I've read arguments from those who use the word "ownership" in their arguments in support of DRM.

I agree with the point that those who make investments in a creative work with their time, energy, sweat, blood, and tears should be able to receive compensation for their efforts. However, Microsoft doesn't care about that. They may claim they do, but that's just marketing. The reason for "caring" so much is for consumer lock in. Microsoft is not performing a selfless act when they implement encryption algorithms that force us to use Windows Media Player. I can see right through that. DRM is merely a smoke screen -- a cover -- for a technical monopoly.

There are other ways to ensure consumer freedoms while also ensuring that consumers are free to use whatever media they choose. Microsoft hires some of the smartest people in the world. Why didn't they invent a method for ensuring that encrypted music could be played on a variety of platforms?

I'll save the details of what they could have done for a later post, for now, let's stick to the topic: The Quit Date.

Eventually, Microsoft will stop supporting Windows XP. At this time, I will have two choices. (1) Upgrade to Windows Vista, or (2) upgrade to a Linux distribution. Both choices will involve learning a new operating system, both will involve dealing with issues of backward compatibility, and both will involve some form of trade-off.

I think the best thing to do to prepare for a Microsoft Windows XP quit date is to migrate to software that will run on all three operating systems. This will ensure that, when the time comes to make the decision, I will be able to make a decision that won't be based on the difficulty of switching from one operating system to another. I'll have the freedom to choose Linux, stick with XP, or if I happen to go temporarily insane -- I can choose Vista! Of course, I've heard a lot of positive remarks about the Mac book Pro, so I just might go that direction as well.

Below are just some of the things we can do to prepare for the time when this decision must be made:

- Use Firefox

Firefox is compatible with Linux, Windows, and the Mac. So any tools I've become comfortable with will be available no matter what operating system I use.

- Use OpenOffice

OpenOffice is not as good as the newest version of Microsoft Office 2007, but there is a trade off. Using MS Office, you effectively lock yourself in to their technology. If you can get by using OpenOffice, I would highly recommend it, as it works on Macs, Windows machines, and Linux.

- Use Mozilla Thunderbird

Currently, I still use Microsoft Outlook. Why? Because I used it in college with the Microsoft Exchange server that their IT department installed. I was "locked-in". Unlocking myself will involve moving all data in Outlook to another client. But with
some advance notice, I think I can move this data to Thunderbird by my quit date. Why use Thunderbird, you ask? Same reason I'm using Firefox. Cross-platform compatibility!

I could keep adding items to the list, but I'm not. Instead of being exhaustive, I'll reduce the list to two items that summarize simplifying the migration process:

- Use software that is compatible with multiple operating systems.
- Buy hardware that works on both Linux and Windows

With a desktop PC, I think this is an easier feat. I've never had problems with Ethernet and Linux; however, I have never been able to connect to my network through a wireless network card using Linux. I haven't tried in about 8 months so perhaps this isn't a problem anymore, but I'm sure there are other types of hardware the Linux community has not yet been able to reverse-engineer in order to develop a driver.

I'm thinking I'll give myself six months to switch everything over and become less dependent on my current operating system. So, by the first day of Spring, I'll be able to make my decision.
Google