S010's homepagehttp://www.s010.lv/Blog[Blog] Fun with C operatorshttp://www.s010.lv/main.php?aid=97While 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.

]]>
Blog[Blog] C function declarations on AMD64http://www.s010.lv/main.php?aid=96Stumbled 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));

The program would crash every time it reached this line, somewhere deep inside libc, in strlen call. In an attempt to figure out what's going on, I started experimenting. At some point, I ended up with

strlcpy(buf, inet_ntoa(sin->sin_addr), sizeof buf);

when I tried to compile the program, the compiler issued a warning that I was supposedly trying to pass strlcpy() an integer instead of a pointer as the second argument. And then it struck me, maybe I didn't include some header file which contained the declaration for inet_ntoa(), so the C compiler assumed the function to be of type 'int'. On AMD64, the addresses are 64-bits long whereas the C-type 'int' is 32-bits long.

I found that in fact, I didn't include one file which was mentioned in inet_ntoa(3) manpage: . So I included it and the program started working. Then I took a look at what assembler code the compiler was generating, out of interest, and what do you know...

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.

]]>
Blog[Blog] History buttons for epdfviewhttp://www.s010.lv/main.php?aid=95My 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.

]]>
Blog[Blog] KeyHoleTV: peeking on Japanese TV and radio programmeshttp://www.s010.lv/main.php?aid=92 Image Hosted by ImageShack.us
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:

]]>
Blog[Blog] Firefox: remapping mouse buttonshttp://www.s010.lv/main.php?aid=90Recently 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:

Free Image Hosting at www.ImageShack.us

And wrote a function, which when the Firefox starts up, parses this variable, if it's present, and maps the buttons accordingly.

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:

  1. left mouse button -- will be remapped to left mouse button =)
  2. middle mouse button -- will be remapped to right mouse button and it will also invoke context menu when pressed
  3. right mouse button -- will be remapped to left mouse button
The scrolling function of the mouse will stay as it was, because scrolling is processed separately.

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.

]]>
Blog[Blog] Introductionhttp://www.s010.lv/main.php?aid=89In this blog I'll try to tell tall tales of my adventures in the IT world.

My main interest is programming. Favourite operating system: OpenBSD. Favourite language: C.

OpenBSD is installed on 3 of my four computers: my main PC (also has Vista), my laptop and my home server which hosts this page. The fourth computer runs MS-DOS and Windows 98 :D

]]>
Software[Software] cwm(1)http://www.s010.lv/main.php?aid=78I decided to start using OpenBSD's calmwm(1) at work, where I have a Linux box. So I checked out the latest source and naturally it didn't compile straight away. Here it is if you're a linuxoid and you want to try cwm out too and you don't want to waste a few hours playing with Makefile, searching for missing files and implementing several lacking library functions: http://s010.lv/files/cwm_linux_20091109.tar.gz

]]>
RecycleBin[RecycleBin] op.shhttp://www.s010.lv/main.php?aid=77Here's a nice little shell script, it's an analog to GUI's double-click concept.

Example usage: op doc1.pdf pic1.jpg ...

http://s010.lv/files/op.sh

Will add a more thorough description later xD

]]>
Misc[Misc] Namie's Naturehttp://www.s010.lv/main.php?aid=76I'm a big fan of a Japanese pop singer, Namie Amuro. Here's a little chillout fan video I put together. For the most part, footage is from the NEVER END PV. Beautiful song...

]]>
Hardware[Hardware] 4x4 LED matrixhttp://www.s010.lv/main.php?aid=73One day I came up with an idea of making a 4x4 LED matrix which would connect to LPT port. This is my first self-made, real device. Before that, I only assembeled various little thingies, like binary counters, on a breadboard, which weren't intended for usage but rather for one-time demonstration.

One thing that served as an additional impulse for making the device, was the fact that I finally found out how to work with the input/output ports on OpenBSD: to enable access to I/O ports, use i386_set_ioperm(2) or i386_iopl(2) system calls, to read/write the ports use the C wrappers for in and out machine instructions (#include ).

Components I used: standard logic integreted circuits, namely, two 74HC373 (a latch) and one 74HC04 (the NOT gate); sixteen 220 Ohm resistors and sixteen LEDs.

The principles behind it are as follows: since the LPT port has only 8 data lines, we cannot obviously operate on all the 16 LEDs at the same time. So we need to either switch between them very fast, or we need to find a way to preserve the information on the one half of the LEDs while we are working with the other half. I chose the second option, because it is easier to program, and because with the first method — the computer would need to run in an endless loop and that would consume CPU power and... Well, I just felt like the second method would be more appropriate.

Soldering time: around... 10 hours. Those small wires were a real nuisance :-D
Programming time: around 4 hours.

Planning how to arrange elements:

Free Image Hosting at www.ImageShack.us


The plastic coating on wires melted ofcourse:

Free Image Hosting at www.ImageShack.us


Consturction complete:

Free Image Hosting at www.ImageShack.us


Free Image Hosting at www.ImageShack.us


The back:

Free Image Hosting at www.ImageShack.us


Schematics:

Free Image Hosting at www.ImageShack.us


Here is a video of the device, demonsrating a scrolling "HELLO WORLD" string:


Source code of the program that does that: 4x4_led_matrix.tar.gz.

usage: ./ledmtrx [-t delay] [-s || -b || -d || -r || -D] data -t delay -- delay for scrolling or substituting display modes, see below -s -- default mode, scroll text; 'data' is the text to scroll -b -- display text by substituting chars; 'data' is the text to display -d -- display an individual char; gedatati is the char -r -- raw; 'data' is an unsigned short value to write to the matrix -D -- display a demo; 'data' is ignored

Making this device was really fun! I will use it for at least two other programming projects I have in mind ;-)

]]>