Neither one nor Many

 
April 16 2011

I like both equally but am a little more familiar with git. Although now I prefer bitbucket over github due to private repositories being free img1. Actually I think currently mercurial tool support on windows seems better too (I didn't expect TortoiseHG to be so neat, as I had only used Tortoise CVS in the past, and I didn't like it, but thats probably due to the nature of CVS).

Some notes, small annoyances I encountered on my system and how I fixed them.

  • Git usage on Windows Vista notes
  • Git removing contents permanently from repository
  • Converting from Git to Mercurial
  • Mercurial through proxy
Blog Comments (0)
 
April 8 2011

I'm actually using Adam Pash' mouser for a few years now on vimkeys with a small patch to improve the performance. A few days ago me and Marijn Koesen talked about an OSX / platform independent version. We used to talk about this before, but now being familiar with wxWidgets I realised creating a clone in C++ was probably easy.

My first windows-only version used a simple timer and a few tricks to prevent keypresses from escaping to the active window. The current version is now improved, and no longer uses a timer. I was also able to minimize an artifact the original mouser also had with the flickering of the blue shapes; it is really fast and transparency appears not to slow it down either (it did on my PC with the original mouser).

The only thing missing is multiple-monitor support at this moment, but give us a few days. Having only one monitor isn't helping img1.

EDIT 11-04-2010: A nice SuperMouser milestone day: Marijn added undo key 'U'. I added multiple monitor support for windows, 'M' key. The latter in need of some testing (I tested it by hardcode-dividing my screen into two halfs).

Marijn Koesen is collaborating and also adding OSX support. The GTK2 version is coming soon. And multiple-monitor support currently has highest priority.

It's all on github for download. The binary for windows is on github as well.

Roadmap:

  • 80% Multiple monitor support (working on it)
  • 100% Undo history key (for correcting mistakes)
  • 0% Remember settings in config.
  • 80% OSX compatibility
  • 60% GTK2 compatibility
C++ Comments (0)
 
March 27 2011

    

    

Blog Comments (1)
 
March 2 2011

Probably lots of them on the internet, but I made one myself (don't ask me why) Just searched for some encode and decode functions w/google codesearch, then added a simple main().

Usage: base64conv.exe [OPTION] [SOURCE] [DEST]
 where [OPTION] is either --to-base64 or --from-base64,
  [SOURCE] is the file to convert
  [DEST] is the target/output file (will be overwritten)

Examples: base64conv.exe --to-base64 somefile.exe somefile.txt
          base64conv.exe --from-base64 somefile.txt somefile.exe
(something like ./base64conv on linux)

Here you have it:

/*
   base64.cpp and base64.h

   Copyright (C) 2004-2008 Rene Nyffenegger

   This source code is provided 'as-is', without any express or implied
   warranty. In no event will the author be held liable for any damages
   arising from the use of this software.

   Permission is granted to anyone to use this software for any purpose,
   including commercial applications, and to alter it and redistribute it
   freely, subject to the following restrictions:

   1. The origin of this source code must not be misrepresented; you must not
      claim that you wrote the original source code. If you use this source code
      in a product, an acknowledgment in the product documentation would be
      appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original source code.

   3. This notice may not be removed or altered from any source distribution.

   Rene Nyffenegger rene.nyffenegger@adp-gmbh.ch

*/

#include <iostream>

static const char base64_chars[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/";

static char *
    base64_encode(const unsigned char *input, int length)
{
    /* http://www.adp-gmbh.ch/cpp/common/base64.html */
    int i=0, j=0, s=0;
    unsigned char char_array_3[3], char_array_4[4];

    int b64len = (length+2 - ((length+2)%3))*4/3;
    char *b64str = new char[b64len + 1];

    while (length--) {
        char_array_3[i++] = *(input++);
        if (i == 3) {
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for (i = 0; i < 4; i++)
                b64str[s++] = base64_chars[char_array_4[i]];

            i = 0;
        }
    }
    if (i) {
        for (j = i; j < 3; j++)
            char_array_3[j] = '\0';

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;

        for (j = 0; j < i + 1; j++)
            b64str[s++] = base64_chars[char_array_4[j]];

        while (i++ < 3)
            b64str[s++] = '=';
    }
    b64str[b64len] = '\0';

    return b64str;
}

static inline bool is_base64(unsigned char c) {
    return (isalnum(c) || (c == '+') || (c == '/'));
}

static unsigned char *
    base64_decode(const char *input, int length, int *outlen)
{
    int i = 0;
    int j = 0;
    int r = 0;
    int idx = 0;
    unsigned char char_array_4[4], char_array_3[3];
    unsigned char *output = new unsigned char[length*3/4];

    while (length-- && input[idx] != '=') {
        //skip invalid or padding based chars
        if (!is_base64(input[idx])) {
            idx++;
            continue;
        }
        char_array_4[i++] = input[idx++];
        if (i == 4) {
            for (i = 0; i < 4; i++)
                char_array_4[i] = strchr(base64_chars, char_array_4[i]) - base64_chars;

            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

            for (i = 0; (i < 3); i++)
                output[r++] = char_array_3[i];
            i = 0;
        }
    }

    if (i) {
        for (j = i; j <4; j++)
            char_array_4[j] = 0;

        for (j = 0; j <4; j++)
            char_array_4[j] = strchr(base64_chars, char_array_4[j]) - base64_chars;

        char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
        char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
        char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

        for (j = 0; (j < i - 1); j++)
            output[r++] = char_array_3[j];
    }

    *outlen = r;

    return output;
}


/**
 * This is the interface I added to these two convert functions, 
 *  that were originally written by Rene Nyffenegger.
 * Found them via google codesearch, specifically in
 *  http://jacksms.googlecode.com/svn/base64.cpp and
 *  http://jacksms.googlecode.com/svn/base64.hh
 * 2011, Ray Burgemeestre.
 */
#include <string>
#include <fstream>

using namespace std;

void display_usage(const char *programname)
{
    cerr << "Usage: " << programname << " [OPTION] [SOURCE] [DEST]" << endl
         << " where [OPTION] is either --to-base64 or --from-base64," << endl
         << "  [SOURCE] is the file to convert" << endl
         << "  [DEST] is the target/output file (will be overwritten)" << endl
         << "" << endl
         << "Examples: base64conv.exe --to-base64 somefile.exe somefile.txt" << endl
         << "          base64conv.exe --from-base64 somefile.txt somefile.exe" << endl
         << "(something like ./base64conv on linux)" << endl;
}

int main(int argc, char *argv[]) 
{
    enum Arguments { PROGRAM, OPTION, SOURCE, DEST, ARGS_LEN };
    if (argc != ARGS_LEN) {
        display_usage(argv[PROGRAM]);
        return -1;
    } else {
        char *sourcedata = NULL;
        ifstream::pos_type sourcedataLen = 0;
        ifstream sourcefile (argv[SOURCE], ios::in|ios::binary|ios::ate);
        if (sourcefile.is_open()) {
            sourcedataLen = sourcefile.tellg();
            sourcedata = new char [static_cast<int>(sourcedataLen)];
            sourcefile.seekg(0, ios::beg);
            sourcefile.read(sourcedata, sourcedataLen);
            sourcefile.close();
            cout << "source file " << argv[SOURCE] << " loaded" << endl;
        } else {
            cerr << "unable to open source file, " << argv[SOURCE] << endl;
            return -1;
        }

        if (strcmp(argv[OPTION], "--to-base64") == 0) {
            cout << "converting to base64" << endl;
            char *base64string = base64_encode(reinterpret_cast<unsigned char *>(sourcedata), 
                static_cast<int>(sourcedataLen));
            ofstream outputfile(argv[DEST], ios::out|ios::binary|ios::ate);
            if (outputfile.is_open()) {
                outputfile.write (base64string, strlen(base64string));
                outputfile.close();
                cout << "base64 string written to dest file, " << argv[DEST] << endl;
            } else {
                cerr << "unable to open dest file, ", argv[DEST];
                return -1;
            }
        }
        else if (strcmp(argv[OPTION], "--from-base64") == 0) {
            cout << "converting from base64" << endl;
            int outlen = 0;
            unsigned char *decodedbase64string= base64_decode(sourcedata, 
                static_cast<int>(sourcedataLen), &outlen);
            ofstream outputfile(argv[DEST], ios::out|ios::binary|ios::ate);
            if (outputfile.is_open()) {
                outputfile.write(reinterpret_cast<const char *>(decodedbase64string), outlen);
                outputfile.close();
                cout << "decoded base64 string written to dest file, " << argv[DEST] << endl;
            } else {
                cerr << "unable to open dest file, ", argv[DEST];
                return -1;
            }
        } else {
            display_usage(argv[PROGRAM]);
            cerr << "@@ invalid [OPTION] specified.";
            return -1;
        }
        delete[] sourcedata;
    }
}
C++ Comments (0)
 
February 27 2011

If you need to protect yourself from yourself, like I needed to do. Then this simple notepad replacement executable may be for you img1. Click here to download. What it does is:

  • Always instantiates exactly one blank/new/untitled notepad instance at a time.
  • The untitled stuff is kept in a user configurable file. So you are not constantly bothered with a Save as dialog..
  • Easily 'dispatch' selections within your notepad to separate files.
  • When called to open a file, does open a new editor for that file. That editor is configurable.
  • Supports better CTRL+Z, CTRL+Y than default notepad.
  • Supports CTRL+F and search next with F3.
  • (For goto-line with CTRL+G you'll have to dispatch the text to another editor!)

When you own New text document (1).txt until New text document (19).txt, asdf.txt, jlksdjflkajsd.txt, etc., on your desktop. Then you have the same problem I had: using notepads for storing temporary buffers and things like that. With this replacement you are forced to keep just one buffer, which is automatically saved with CTRL+S. And when you do want to keep specific stuff, you select that text and CTRL+D (dispatch to file).

To install it you need to do the following:

  • Disable UAC (on Vista for example)
  • Reboot the system
  • Execute a batch file like the following. Got this copy from here.

Here's the copy (it is included in my .zip). This is not the same script I used, but my guess is it'll probably work:

@echo off

takeown /f c:\windows\syswow64\notepad.exe
cacls c:\windows\syswow64\notepad.exe /G Administrators:F

takeown /f c:\windows\system32\notepad.exe
cacls c:\windows\system32\notepad.exe /G Administrators:F

takeown /f c:\windows\notepad.exe
cacls c:\windows\notepad.exe /G Administrators:F

copy c:\windows\syswow64\notepad.exe c:\windows\syswow64\notepad.exe.backup
copy c:\windows\system32\notepad.exe c:\windows\system32\notepad.exe.backup
copy c:\windows\notepad.exe c:\windows\notepad.exe.backup

rem this has to be executed from within the installation dir.
copy notepad.exe c:\windows\syswow64\notepad.exe
copy notepad.exe c:\windows\system32\notepad.exe
copy notepad.exe c:\windows\notepad.exe

You can read the INSTALL file in the .zip bundle for details.

Example configuration

; configuration for notepad.exe replacement
editor=C:\Program Files\Vim\vim72\gvim.exe
file=C:\temp.txt
title=Untitled
maximized=0
C++ Comments (0)
 
February 24 2011

These are some examples of rendered frames by the starcry rendering engine.

StarcryPublic Comments (0)
 
January 15 2011

When navigating directories, every now and then pushd . and popd just aren't sufficient. When directory structures tend to become quite deep, I get really annoyed with typing change-directory’s and wish I had some bookmarks. That's why some time while ago I created a simple tool for usage within (GNU) screen: CTRL+X pops up a menu for selecting common directories and files ("bookmarks"!). This makes switching between those long directory structures a lot more pleasant img1!

Create bookmarks file

// Configuration file ($HOME/.launcher)
[
   {"Websites, configuration" : [
      {"dir" : "/srv/www/vhosts/ray.burgemeestre.net"},
      {"dir" : "/srv/www/vhosts/www.burgemeestre.net"},
      {"dir" : "/usr/local/src/mongoose/am"},
      {"dir" : "/usr/local/src/mongoose/am/output/ray-blog-burgemeestre-net"},
      {"file" : "/etc/apache2/vhosts.d/www-burgemeestre-net.conf"},
      {"file" : "/etc/apache2/vhosts.d/ray-blog-burgemeestre-net.conf"},
      {"file" : "/etc/apache2/vhosts.d/ray-burgemeestre-net.conf"}
   ]},
   {"Common Lisp" : [
      {"dir" : "/var/chroot/lispbot/home/trigen"},
      {"file" : "/var/chroot/lispbot/home/trigen/bot.lisp"}
   ]},
   {"C++ projects" : [
      {"dir" : "/usr/local/src/launcher"},
      {"dir" : "/usr/local/src/launcher/src"},
      {"file" : "/usr/local/src/launcher/src/parser.cpp"}
   ]}
]

Use in screen with C-x

Choosing a directory in the menu opens it in a new screen tab. Choosing a file opens a new menu which allows you to dispatch it to specific editors or e-mail it (options currently all hardcoded in the source).

Installation

Most of the code is still from 2007, but these last two days I refactored the code a bit. And added some build scripts. (Needless to say I didn't get to implementing all features I had in mind.) It's all on github for download.

It installs /usr/local/bin/launcher and two helper bash scripts (/usr/local/bin/launch_scr.sh and /usr/local/bin/launch_scr2.sh). You bind it to screen in your .screenrc with this line: bindkey ^x exec /usr/local/bin/launch_scr.sh.

(Also for your .screenrc I recommend using a caption if you don't already with: caption always "%{Yb} %D %Y-%02m-%02d %0c %{k}|%{G} %l %{k}|%{W} %-w%{+b}%n %t%{-b}%+w")

C++ Comments (0)
 
January 14 2011

Just wanted to use the 'in practice' part because it sounds so cool img1. At work I used to have some cool tricks I'd use at customers (test-environments) or local setups to debug. One of my favourite snippets I use all the time is the following.

Record and re-create requests..

/**
 * Debug helper function for logging and restoring requests. Do not use in 
 * production environments.
 *
 * - Logs the URL and request data.
 * - With __STATE_DEBUGGER__ parameter in the URL it displays a listing
 *   of logged requests.
 * - Clicking an item in that listing, re-creates that request.
 *
 * I know it is usually not good practice to have *one* function do multiple 
 * things. Make sure you know what you're doing ;)
 * 
 * @param writableDirectory directory for saving the requests in files
 * @return void (call it solely for it's side-effects ;-))
 */
function statedebugger($writableDirectory = '/tmp')
{
    if (!is_dir($writableDirectory) || !is_writable($writableDirectory)) {
        trigger_error('parameter writableDirectory needs to exist and be
            writable', E_USER_ERROR);
    }
    $indexFile = $writableDirectory . '/index.txt';
    if (!isset($_GET['__STATE_DEBUGGER__'])) {
        // Write state file for request
        $stateFileName = tempnam($writableDirectory, 'p');
        $fd = fopen($stateFileName, 'wb');
        fwrite($fd, serialize(array($_SERVER, $_GET, $_POST, $_REQUEST,
            !isset($_SESSION) ? array() : $_SESSION)));
        fclose($fd);
        // Rewrite index
        $indexFileContents = file_exists($indexFile) ?
            file_get_contents($indexFile) : '';
        $fd = fopen($indexFile, 'wb');
        fwrite($fd, implode(array($indexFileContents, //INEFFICIENT
            $stateFileName, ' ', $_SERVER['REQUEST_URI'], "\n")));
        fclose($fd);
    } else {
        if (!isset($_GET['set_state'])) {
            // Show index/listing of states
            $indexFileLines = array_reverse(explode("\n",
                file_get_contents($indexFile)));
            foreach ($indexFileLines as $line)  {
                if (empty($line))
                    continue;
                list($filename, $requestUri) = explode(" ", $line);
                printf("<a href=\"%s%s__STATE_DEBUGGER__&set_state=%s\">%s</a><br/>\n",
                    $requestUri, (strpos($requestUri, "?") === FALSE ? "?" :
                                    "&"), $filename, $requestUri);
            }
            exit(0);
        } else {
            // Restore a specific state
            list ($_SERVER, $_GET, $_POST, $_REQUEST, $_SESSION) =
                unserialize(file_get_contents($_GET['set_state'])); //DANGEROUS
        }
    }
}
statedebugger('E:/TPSC/htdocs/CRMS-Test/webframe/templates_c/');

Just paste that in the config, or whatever global headerfile (your software probably has), and it logs all requests to some specified directory. Usually when something goes wrong within a very specific context (a specific user with rights, session variables, page, ..), it would be nice to just log the requests (e.g. with post data), and use that information to re-create the (failing) request. So you can keep pressing F5 in your browser window while fixing the bug. This function does that. Also this can be especially useful when debugging AJAX requests, i.e. without firebug, or you can let the user create the very specific context (with privileges and user settings) that causes some failure, and in that way create the test-case.

(Add __STATE_DEBUGGER__ to the URL as a parameter, and it will show a listing with clickable requests. Clicking redirects to that page and initializes it with the recorded $_GET, $_POST, $_SESSION, ...)

(By the way I didn't bother to make this very secure (see file_get_contents($_GET['set_state']) for example), because this should only be used when debugging. This could easily be improved with some numerical parameters, optional descriptions, limit to fixed number of requests...)

Webdevelopment Comments (0)
 
November 26 2010

One of the reasons I was using allegro for my project was that they already had (apparantly) a lot of blending modes available. You have set_blender_alpha(), set_blender_hue(), set_blender_color(), but these are not the same as in photoshop. I got some unexpected behaviour from these, and I will edit this post later and elaborate on that some more.

Most of them ignore the r, g, b parameters as well. So it appears they were a big disappointment. By the way, a quick glance at the Allegro 5 source made me think they aren't implemented there either.

That's why I did a quick search and found someone who already collected macro's for all photoshop blending types. By Nathan Moinvaziri. Today, or I should say yesterday (now at 3:17am), I implemented some wrapper functions around it that make it available to allegro, with an API that looks and feels the same as allegro.

I put it on github with a demo program. From the README:

Put al_blend.h in your project somewhere and include it.  Or put it in the
allegro include directory, i.e. /usr/local/src/allegro/include or
C:\allegro\include.

Now instead of using the allegro blenders with getpixel() and putpixel(), you
can use put_blended_pixel().

    put_blended_pixel(): 
        Writes a pixel into a bitmap with specific blender.

    Description:
        void put_blended_pixel(BITMAP *bmp, int x, int y, int color,
            (*blender_func)(int &basecolor, int &blendcolor)); 

    Example:
        put_blended_pixel(screen, x, y, somecolor, blender_lighten);

Available blenders are: blender_darken, blender_multiply, blender_average, blender_add, blender_subtract, blender_difference, blender_negation, blender_screen, blender_exclusion, blender_overlay, blender_softlight, blender_hardlight, blender_colordodge, blender_colorburn, blender_lineardodge, blender_linearburn, blender_linearlight, blender_vividlight, blender_pinlight, blender_hardmix, blender_reflect, blender_glow, blender_phoenix, blender_hue, blender_saturation, blender_color, blender_luminosity,

C++ Comments (0)
 
November 26 2010

There are a few things I figured out how to do, and I seem to use them on a regular basis. For these snippets I have to search through my projects every now and then, to find them, and it would be a lot easier if I kept them somewhere listed. Hopefully you will find something useful as well.

Clearing a sizer

I usually make master/detail screens where the detail list is a vertical sizer with stuff on it. Usually a panel with more stuff on it. Every now and then you may want to clear it. I use:

while (theSizer->GetChildren().GetCount() > 0) {
    theSizer->GetItem(static_cast<size_t>(0))->DeleteWindows();
    theSizer->Remove(0);
}

// populate the sizer again maybe

sizerChangelogItems->Layout();

You might want to surround the code with Freeze() and Thaw() for performance.

Hiding and showing a panel on an AUI frame

This is more of a note I keep forgetting about: Instead of calling the Hide() and Show() on the window (panel) itself (which compiles). Use the following:

someWindow->GetAuiManager().GetPane(someWindow->splitterwindow1).Show(false);
someWindow->GetAuiManager().GetPane(someWindow->panel1).Show(true);

someWindow->GetAuiManager().Update();

Using dropdowns with object data.

I use wxChoice a lot, I especially like that the items themselves can refer to anything. Typically how I initialize a choicebox:

wxChoice *choice = ...;
Object *someObject = ...;
for (...) {
    choice->Append("object 1", (void *)someObject);
}
choice->SetStringSelection("object 1");

Then usually I have an event that triggers on the selection of an item in the choicebox. In the event I first get the wxChoice, then cast the client data for the selected item to the object pointed to:

void SomeWindow::OnChoiceSelected( wxCommandEvent& event )
{
    wxChoice *choice = static_cast<wxChoice *>(event.GetEventObject());
    Object *someObject = static_cast<Object *>(choice->GetClientData(choice->GetSelection()));
    if (someObject != NULL) {
        //...
    }
}

Directory functions

wxString resdir(RESOURCE_DIR);
if (!::wxDirExists(resdir)) {
    throw std::runtime_error("resources dir not found");      
}
wxDir dir(resdir);
if ( !dir.IsOpened() ) {
    throw std::runtime_error("resources directory could not be opened");
}
wxString filename;
bool cont = dir.GetFirst(&filename);
while ( cont ) {
    int lastdot = filename.Find('.', true);
    if (lastdot != wxNOT_FOUND) {
        wxString name(filename.SubString(0, lastdot - 1));
        wxString ext(filename.SubString(lastdot + 1, filename.Length()));
        if (!ext.compare(_T("cpp"))) {
            ...
        } else {
            ...
        }
    }
    cont = dir.GetNext(&filename);
}

Write to file function

wxFile article(markdownfilename, wxFile::write);
if (!article.IsOpened()) {
    throw std::runtime_error("main.md could not be opened for writing");
}
article.Write(textctrlArticleBody->GetValue());
article.Close();
C++ Comments (0)

Paging
Page 1
Page 2
Page 3
Page 4
Page 5
Page 6
Page 7
Page 8 <<<< You are Here!
Page 9
Author:
Ray Burgemeestre
february 23th, 1984

Topics:
C++, Linux, Webdev

Other interests:
Music, Art, Zen