Friday, February 26, 2010

Check out Java project from CVS to Eclipse


Step 1:
Start Eclipse.
Select menu "File|Import...".

Step 2:
The "Import" dialog pops up.
Select "CVS|Projects from CVS".
Click "Next".

Step 3:
Select "Create a new repository location".
Click "Next" to add the CVS repository location.
or
Select "Use existing repository location:".
Select the wanted repository location from the list.

Click "Next".

Step 4:
Select "Use an existing module (this will allow you to browse the modules in the repository)".
Choose the module you want to check out.
Click "Next".

Step 5:
Select "Check out as a project configured using the New Project Wizard".
Check "Checkout subfolders".
Click "Next".

Step 6:
Select "HEAD" if check out from CVS trunk.
or
Select the wanted branch under "Branches". If the wanted branch is not listed, click "Configure Tags..." to add the branch.
Click "Finish".

Step 7:
New project wizard pops up.
Select "Java Project".
Click "Next"

Step 8:
Generate a "Project Name" for the new project.
In "Contents" section, choose "Create new project in workspace".
Leave the rest as default.
Click "Finish".
The module will be checked out from CVS into Eclipse workspace.

Thursday, February 25, 2010

How to change the options/preferences of a Mozilla Firefox/Thunderbird extension


Most of the extensions of Mozilla Firefox or Mozilla Thunderbird have "Options" dialogs. To open the "Options" dialog, you can:

Step 1: click the "Tools" button in the menu bar;

Step 2: select the "Add-ons" item;


Step 3: select the "Extensions" icon;

Step 4: select the extension you want and the "Options" button will show up;

Step 5: click the "Options" to open the dialog.

 

Wednesday, February 24, 2010

Detect memory allocation failure in C++


In C++, we use "new" to allocate a piece of memory. There are chances that the allocation may fail. Upon the failure of allocating memory, the developer may want to do some clean-up or logging. You may see this piece of code in some old programs:
char *p = new char[buffer_size];
if (!p) {
   // error handling ...
}
It worked in the last century, but not any more. The problem of this piece of code is that with the modern C++ compiler, the "error handling" part will never get hit. If the memory allocation fails, an exception would be thrown and the rest of code after the "new" would not run. Try it with this little program:
#include <iostream>
using namespace std;
int main()
{
   long buffer_size = 0x7fffffff;

   char *p = new char[buffer_size];

   if (p)
      cout << "OK" << endl;
   else
      cout << "Bad" << endl;

   return 0;
}
You could not see the printout of "Bad". Instead, the output would be:
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted
To add error handling, we need to capture this exception:
try {
   char *p = new char[buffer_size];
}
catch (std::bad_alloc) {
   // error handling ...
}
If you prefer to the old behavior of "new", you can still use the "nothrow" version of "new":
char *p = new(std::nothrow) char[buffer_size];
if (!p) {
   // error handling ...
}
However, it is no recommended.

Tuesday, February 23, 2010

Porting Firefox extension to Thunderbird


After I published the Autohide Tabbar Firefox extension, some positive comments were received. Thank you! It encourages me to keep improving it. One of the comments was asking whether the Autohide Tabbar extension could be added to Mozilla Thunderbird. I looked into Thunderbird and found out that since version 3, tabs were introduced. After some more investigations, it was discovered that porting a Mozilla Firefox extension to Thunderbird is easy.

First, just making a little changes on files install.rdf and chrome.manifest, you could install your Firefox extension on Thunderbird. Use the Autohide Tabbar extension as an example. In file install.rdf, look for the "em:targetApplication" block. What you already have is for Firefox. You can add another "em:targetApplication" block for Thunderbird right after it:
        <!-- Firefox -->
        <em:targetApplication>
            <Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>3.0</em:minVersion>
                <em:maxVersion>3.6.*</em:maxVersion>
            </Description>
        </em:targetApplication>

        <!-- Thunderbird -->
        <em:targetApplication>
            <Description>
                <em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
                <em:minVersion>3.0</em:minVersion>
                <em:maxVersion>3.0.*</em:maxVersion>
            </Description>
        </em:targetApplication>
In file chrome.manifest, you need to add a new overlay for Thunderbird. As we know, browser.xul is to be overlay-ed for Firefox. For Thunderbird, we would overlay messenger.xul. We also add the application ID at the end. {ec8030f7-c20a-464f-9b0e-13a3a9e97384} is the application ID of Firefox and {3550f703-e582-4d05-9a08-453d09bdfdc6} is that of Thunderbird. The Autohide Tabbar extension overlays messenger.xul with autohidetabbar_t.xul, which is a clone of autohidetabbar.xul, which is for Firefox. If your extension needs no extra code changes for Thunderbird, you do not even need to clone your XXX.xul file to XXX_t.xul. Just use the same XXX.xul file for both overlay.
      overlay chrome://browser/content/browser.xul chrome://ahtb12/content/autohidetabbar.xul   application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
      overlay chrome://messenger/content/messenger.xul chrome://ahtb12/content/autohidetabbar_t.xul   application={3550f703-e582-4d05-9a08-453d09bdfdc6}
Basically, after changing install.rdf and chrome.manifest, you can try your extension on Thunderbird. If the extension is a simple one, it may work and your job is done. Our Autohide Tabbar extension uses elements specifically for Firefox, so it did not work right after. Then we have to go to the next step.

We do not want our changes for Thunderbird impacts the functions on Firefox, so we clone autohidetabbar.xul and autohidetabbar.js to autohidetabbar_t.xul and autohidetabbar_t.js and make the changes for Thunderbird on the new ones. Those changes are specifically for this extension, so I would not give the details here. If you are interested, you can download both the old version and the new version to check out their differences.

Both the flavors of the Autohide Tabbar extension share the same Options dialog, default preferences, locale between Firefox and Thunderbird. We do not need more works to port them. However, you may want to carefully exam the labels, descriptions and printouts to make sure they do not mention Firefox only.

Friday, February 19, 2010

JavaScript: trim leading or trailing spaces from a string


There is no built-in function to remove leading or trailing spaces from a string in JavaScript. To do that, we can use the replace() method of the String object.

The syntax of String's replace() method is:
string.replace(regexp/substr,newstring);
The first parameter can be a regular expression. The second parameter is a new string to replace what the regular expression matches in the string. So to trim the leading or trailing spaces, we can do this:
mystring = mystring.replace(/^\s+|\s+$/g, "");
The first parameter /^\s+|\s+$/g is a regular expression that matches the leading or trailing white-space characters. Let us break it down to see what it means:
  • \s matches a white-space character;
  • + matches the preceding element one or more times, so \s+ matches 1 or more white-space characters;
  • ^ matches the starting position of the string, so ^\s+ matches 1 or more leading white-space characters;
  • $ matches the ending position of the string, so \s+$ matches 1 or more trailing white-space characters;
  • | means or, so ^\s+|\s+$ matches 1 or more leading or trailing white-space characters;
  • /.../ means search;
  • g means global, so it will continue and search for the trailing white-space characters after it have found the leading white-space characters.
When a pattern is found in mystring, i.e. leading or trailing white-space characters are found, they will be replaced with an empty string "". The result? They are trimmed.

Thursday, February 18, 2010

GNU C++ compiler (g++) does not like the typical hello-world program


In some old text books or web sites, you can see the standard or traditional "hello world" program like this:
#include <iostream.h>
main()
{
   cout << "Hello World!" << endl;
}
If you use the latest GNU C++ compiler to build this program, you will get a warning.
$ g++ helloworld.cpp 
In file included from /usr/include/c++/4.2/backward/iostream.h:31,
                 from helloworld.cpp:1:
/usr/include/c++/4.2/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
The executable is generated with the deprecated header. To get off the warning message, you should include <iostream> instead of <iostream.h>, as what the warning message suggests. It is important to use the new header if you are writing new code because the deprecated headers are for the backward compatibility of the old code and they may not be fully supported. Let us replace the header and re-compile.
#include <iostream>
main()
{
   cout << "Hello World!" << endl;
}
We are sorry to see that it gets worse. The compiler refuses to build the program.
$ g++ helloworld.cpp 
helloworld.cpp: In function 'int main()':
helloworld.cpp:4: error: 'cout' was not declared in this scope
helloworld.cpp:4: error: 'endl' was not declared in this scope
GNU C++ uses namespace to avoid naming collisions. 'cout' and 'end' are defined in the 'std' namespace. To use them, simply add the 'std' namespace to your program.
#include <iostream>
using namespace std;
main()
{
   cout << "Hello World!" << endl;
}
Now the code can be compiled. But they are not perfect yet. If you turn on all the warning options of g++, you can see there are still warnings.
$ g++ -Wall helloworld.cpp 
helloworld.cpp:3: warning: ISO C++ forbids declaration of 'main' with no type
GNU C++ encourages you to explicitly declare the main() function with a return type of int. So the final code will become:
#include <iostream>
using namespace std;
int main()
{
  cout << "Hello World!" << endl;
  return 0;
}
In conclusion, GNU C++ is stricter in the syntax. For an old program like in this example, we need to check three things.
  • Use the new C++ header;
  • Use the proper namespace;
  • Explicitly declare function type and explicitly return if the type is not 'void'.

Sunday, February 7, 2010

Linux: EADDRNOTAVAIL (Address not available) error


If you are running many TCP client programs on your machine and these programs do not specify ports when they make connections to the server, the system would assign temporary ports for them. When a connection is closed, the port will be returned to the system for reuse. The temporary ports have a limited range. When the allowed connections are exhausted, the program could get an error when it tries to make any new connections. The error number it generates would be EADDRNOTAVAIL (Address not available).

In such case, you can check the range of the temporary ports with:
      cat /proc/sys/net/ipv4/ip_local_port_range

The command returns two numbers, such as
      1024 4999

The first number is the minimum and the second one is the maximum value of the temporary port. In this example, we have 3976 ports that can be used.

You can check how many TCP and UDP are used on your machine by running command:
      netstat -an | grep -e tcp -e udp | wc -l

Although the result includes the ports used by the TCP/UDP servers running on your machines and other ports specified outside the ip_local_port_range, it gives you a sense of how heavy the network ports are used. Usually, those ports used by TCP/UDP servers should not be too many. If you are having dozens of thousands of ports opened on your machine, that could be the reason why you are getting error EADDRNOTAVAIL (Address not available).

You may then consider increase the value of ip_local_port_range. To do that, run this command as root:
      echo "32768 61000" >/proc/sys/net/ipv4/ip_local_port_range

To make the change permanent on each boot, you can make some changes on the configuration file /etc/sysctl.conf. Just add this line to the end of the file:
      net.ipv4.ip_local_port_range = 32768 61000

To verify the result, after rebooting, run:
      cat /proc/sys/net/ipv4/ip_local_port_range

Friday, February 5, 2010

Firefox Extension: Invert Input


Note: Online help of the old version 1 can be found here.
Note: Online help of the old version 2 can be found here.

No matter what reason you want to invert your input to the browser, you can do it with this extension now. It can invert the input of a text field or a password field.

After you input something into a text box, right click your mouse to pop up the context menu where you can see an item of "Invert Input". Click it and the text will be reversed. If the input is a password, your input is masked with stars by the browser so you cannot tell directly whether the password has been inverted. But you can know it by the color. The background color of the password box will be changed to navy color to indicate that the text has been reversed. If you do the inverting again, the text will return to original, but the color of the font will be set to navy with a white background color. This reminds you that you have run even times of the function to make it return to the original.

If you prefer keyboard shortcuts, you can use Ctrl-Shift-i to invert the input while the cursor is in that text box. The shortcut key is configurable via the Options dialog. Please see the Options section below.

You can also add the "Invert Input" button to your tool bar (see this post for how to add a button to the tool bar). Click into the text box you want to invert first. And then click on the "Invert Input" button to invert the text inside the focused text box.


Open inverted URL

To answer the request from some users, a new option to open inverted URL is added since version 2.0. To use it, you must first enable it on the Options dialog (See the Options section). Then you can highlight the inverted URL and right-click to select "Open Inverted Link" from the context menu. The inverted URL will be opened in a new tab.


If you right-click on a link and choose "Open Inverted Link", the address of the link will also be reversed and opened in a new tab.


Download/Installation
https://addons.mozilla.org/en-US/firefox/addon/72674/


Options
By default, the text is inverted line by line if there are multiple lines. For example,
line one
line two
line three

will be inverted into
eno enil
owt enil
eerht enil

If you want to invert the whole thing from top to bottom without considering line breaks, you can go to the Options dialog and uncheck the option of "Invert line by line". The result will be changed into
eerht enil
owt enil
eno enil


In version 2.0, a new option "Handle inverted link" is added. By checking it, you enable the "Open Inverted Link" on the context menu when you right-click a highlighted text, or when you right-click on a link. The highlighted text or the address of the link will be reversed and opened in a new tab.

You can enable, disable or change the hot key. The default one is Ctrl+Shift+i. But this combination conflicts with a new hot key of Firefox 4. In the Options dialog, you can select a new letter or change the combination of the functional keys.

Click here to see how to open the "Options" dialog.

Wednesday, February 3, 2010

Linux: create a CVS repository on local machine


CVS is usually set up as client/server model to let developers from different locations work concurrently and submit their code to a central place for sharing. If you are the only developer and work on some small projects by yourself, you don't need to build such a complicated system. With several simple steps, you can use CVS on a stand-alone machine.

* Create a directory for the CVS repository to keep all the history of your work.
      mkdir -p /home/user1/cvs_repository

* Set some enviromental variables: CVSROOT tells where the repository is. EDITOR tells which editor you prefer.
      export CVSROOT=:local:/home/user1/cvs_repository
      export EDITOR=vi

* Initialize the repository.
      cvs init

* Set up an empty project in the repository. You can also import your existing project in this step, but you would still need to check out the project into a work directory for further development.
      mkdir -p /home/user1/empty_dir
      cd /home/user1/empty_dir
      cvs import myprojects vtag rtag
      cd ..
      rmdir empty_dir

* Set up a work directory for the project, and check out the project which is empty yet.
      mkdir -p /home/user1/work_dir
      cd /home/user1/work_dir
      cvs co myprojects

* Add directories and files to the project. Check in the changes into the CVS repository.
      mkdir project1
      cvs add project1
      cvs ci
      cd project1
      vi file1.txt
      cvs ci
 
Get This <