| ctime: | 2010-09-02 01:01:09 |
| mtime: | 2010-09-02 01:06:44 |
While writing some C code today, I suddenly felt an urge to write something perlish, like:
&important_action() or die("failed!");
I was about to shove this idea away, since C is basically a high-level assembler, but then it occurred to me that it is in fact possible:
...
important_action() || die("failed!");
...
The order of evaluation is guaranteed to be the same as it appears in program's text for &&, ||, ?: and `,' operators. The catch here is that the expression on the right must yield a value, that is, the function die() must be a non-void returning function. Otherwise, the code won't compile, at least it doesn't on GCC. Aww, but the standard UNIX routines, err(3) and errx(3), don't return anything! Wait.. What if we use the comma operator?
...
important_action() || (errx(1, "failed!"), 1);
...
The comma operator yields the expression to it's right, so the || operator is satisfied. The parentheses are needed because the comma operator has the lowest precedence in C.
Of course, this last version will probably confuse the reader instead of clarifying the program... But it's still neat that you can do that.
| ctime: | 2010-08-22 00:33:15 |
| mtime: | 2010-08-22 02:03:00 |
Stumbled upon interesting problem just now.
There is a function in the standard C library on UNIX, inet_ntoa(3), it formats a 'struct in_addr' in human readable form and returns a pointer to a character array.
So I had a line in my program, which looked something like:
snprintf(buf, sizeof buf, "%s:%i", inet_ntoa(sin->sin_addr), (int) ntohs(sin->sin_port));
strlcpy(buf, inet_ntoa(sin->sin_addr), sizeof buf);
I found that in fact, I didn't include one file which was mentioned in inet_ntoa(3) manpage: Without arpa/inet.h: With arpa/inet.h:
...
#NO_APP
movw %ax, -308(%rbp)
movzwl -308(%rbp), %eax
movzwl %ax, %ebx
movq -336(%rbp), %rax
movl 4(%rax), %edi
movl $0, %eax
call inet_ntoa
movl %eax, %ecx
leaq -48(%rbp), %rdi
movl %ebx, %r8d
movl $.LC6, %edx
movl $22, %esi
movl $0, %eax
call snprintf
...
...
#NO_APP
movw %ax, -308(%rbp)
movzwl -308(%rbp), %eax
movzwl %ax, %ebx
movq -336(%rbp), %rax
movl 4(%rax), %edi
call inet_ntoa
movq %rax, %rcx
leaq -48(%rbp), %rdi
movl %ebx, %r8d
movl $.LC6, %edx
movl $22, %esi
movl $0, %eax
call snprintf
...
It works perfectly fine on i386 because both integers and adresses are 32-bits long there.
| ctime: | 2010-07-25 21:57:21 |
| mtime: | 2010-07-25 23:01:26 |
My favourite PDF reader is epdfview, it's a really simple and light-weight program, depends only on GTK2 and Poppler. It does have it's weak spots though. One such weak spot is the lack of history buttons (so that you could go back after clicking a cross-reference link for example). A few days ago I got really fed up with this and decided to add history myself.
The task turned out to be a little more complicated then I anticipated: first of all, after I actually added the buttons and made them work, I realized that when you go back or forth in history, you must also save the position on page and restore it, otherwise, it's not that much better than having no history at all; second of all, the program is done object-orientedly and the way entities communicate with each other -- is basically by notifications, when you look at epdfview's source code, it seems really well-organized and all, but when you're trying to modify it, you stumble upon this fact that, say, you can't just directly call some function to get information you want -- you have to make that other thing call you, and sometimes, there isn't a direct route between where you need the information and where it is located. But then again, maybe I'm just a bad programmer :D
Anyways, here's the modified source code: epdfview-trunk.tar.gz and a screenshot:
P.S. I should really read other people's code more often. Every time I do -- I learn some new neat trick or some good idea. This time, I learned the following trick with assert:
gassert(data && "Invalid argument: data is NULL");
When the assert is triggered, it not only will output the file name and line number where the assertion failed, it might also output a meaningful message.
| ctime: | 2009-11-22 03:04:40 |
| mtime: | 2009-11-22 03:04:40 |

Caught One Piece anime on FujiTV =)
KeyHoleTV is an interesting little program, available for Windows, Mac and Linux, which lets you watch Japanese TV programmes and listen to Japanese radio stations. The quality of sound and picture is far from being 'high', but I guess it's better than nothing at all.
More info:
| ctime: | 2009-11-18 20:56:49 |
| mtime: | 2009-11-19 01:31:52 |
Recently I changed my Firefox usage pattern. Instead of opening FF fullscreen, I now tend to open FF alongside some other window/s, like xterm or gvim.
Naturally, some or even many websites don't quite fit into the little space that is given to them now and so the problem of scrolling the page sideways as well as vertically arises. I remembered a feature called 'Autoscroll' and enabled it. When 'Autosroll' is enabled you can press the middle mouse button (which nowadays is almost always a scrolling-wheel, not a button), drag the mouse and the page scrolls in the direction you drag the mouse.
But as I used autoscroll, little by little, I got frustrated with the 'middle-button'. Scrolling-wheel was not designed to be pressed too often, I would've preffered to use an ordinary button any day.
That's when I remembered that Firefox -- is an open-source browser. I decided to download it's sources and implement the ability to remap mouse buttons arbitrarily.
The first thing I did when I got FF's source was find . -iname '*mouse*'. I found a file with intriguing name, content/events/src/nsDOMMouseEvent.cpp, tried to modify it, but there was no effect.
Then I found widget/src/gtk2/nsWindow.cpp, which is one of the files that interfaces FF with GTK2 and which translates GTK2 events to FF's. At first I tried out to make a hardcoded remap, i.e. changed
...
PRUint16 domButton;
switch (aEvent->button) {
case 1:
domButton = nsMouseEvent::eLeftButton;
break;
case 2:
domButton = nsMouseEvent::eMiddleButton;
break;
case 3:
domButton = nsMouseEvent::eRightButton;
break;
...
in the nsWindow::OnButtonPressEvent function to
...
PRUint16 domButton;
switch (aEvent->button) {
case 1:
domButton = nsMouseEvent::eLeftButton;
break;
case 2:
domButton = nsMouseEvent::eRightButton;
break;
case 3:
domButton = nsMouseEvent::eMiddleButton;
break;
...
It worked, so next I added a new about:config variable, mozilla.widget.mouse-button-map:
The format of the variable... Hm, that'll be a bit hard to explain...
The position in the string, is the GDK button number of the mouse button you want to remap. The number on this position in the string, is also a GDK mouse button number and denotes to which button you want to remap the button! If there is an 'm' on the given position, then it means the previous button will invoke the context menu (Look through the nsWindow::OnButtonPressEvent function, the context menu button is kind of mapped separately). If you don't want to remap the button on this position, put any char there other than [0-9m].
For example, given a value "13m2", the buttons will be remapped in the following way:
And so, now I can autoscroll with the right mouse button =) And I'm also so looking forward to using this on my laptop *types make extract patch*...
Here's the patch: ff_mouse_button_remap.patch.