segunda-feira, 24 de dezembro de 2007

Lua-Gtk

A linguagem de programação Lua foi planejada para ser uma linguagem de extensão para aplicações escritas em C.

O lado negativo disso é a linguagem não foi pensada para o desenvolvimento de aplicações totalmente em Lua, mas por outro lado a grande vantagem é que tudo que existe em C pode ser portado para Lua.

Assim, mesmo não havendo um toolkit gráfico padrão para Lua, a biblioteca GTK+ foi portada para Lua, sob o nome Lua-Gtk.

Lua-Gtk implementa perfeitamente a versão 2.x do GTK+, com ênfase na orientação a objetos.

Para quem conhece a biblioteca GTK+, o módulo Lua-Gtk não traz segredo algum. Depois de ter instalado Lua-Gtk, vamos implementar um exemplo «Olá Mundo!» clássico.

Em C, nosso hello.c fica assim:
#include <gtk/gtk.h>

static void hello(GtkWidget *, gpointer);
static gboolean delete_event(GtkWidget *, GdkEvent *, gpointer);

int main(int argc, char **argv) {
GtkWidget *window;
GtkWidget *button;

gtk_init(&argc, &argv);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

g_signal_connect(
G_OBJECT(window), "delete_event",
G_CALLBACK(delete_event), NULL
);
gtk_container_set_border_width (GTK_CONTAINER(window), 10);

button = gtk_button_new_with_label("Hello World");

g_signal_connect(
G_OBJECT(button), "clicked",
G_CALLBACK(hello), NULL
);
g_signal_connect_swapped(
G_OBJECT(button), "clicked",
G_CALLBACK(gtk_widget_destroy), G_OBJECT (window)
);
gtk_container_add(GTK_CONTAINER(window), button);
gtk_widget_show(button);
gtk_widget_show (window);

gtk_main ();
return 0;
}

static void hello(GtkWidget *widget, gpointer data) {
g_print("Hello World\n");
gtk_main_quit();
}

static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
g_print("delete event occurred\n");
return TRUE;
}


Para compilá-lo:
bash$ gcc hello.c -o hello `pkg-config --cflags --libs gtk+-2.0`
bash$ ./hello


A versão Lua, hello.lua é muito parecida, se você comparar linha a linha:
require "gtk"

function hello(widget, data)
print "Hello World"
gtk.main_quit()
end

function delete_event(widget, event, data)
print "dete event occurred"
return true
end

gtk.init(#{...}, {...})

window = gtk.window_new(gtk.GTK_WINDOW_TOPLEVEL)

window:connect("delete_event", delete_event)
window:set_border_width(10)

button = gtk.button_new_with_label("Hello World")

button:connect("clicked", hello)
window:add(button)
button:show()
window:show()

gtk.main()


Para executar:
bash$ lua hello.lua


Fica aqui a dica! Para saber mais, veja o manual de referência.

Se quiserem, depois escrevo mais sobre o assunto.

[]'s
Cacilhas, La Batalema

sábado, 8 de dezembro de 2007

Prettify no Kodumaro

Gente,

Acrescentei Prettify ao Kodumaro.

Prettify é um recurso ECMAScript/CSS para syntax highlighting de códigos em C/C++, Java, Python, Bash, SQL, HTML, XML, CSS, JavaScript e Makefile. Também trabalha bem com Ruby, AWK e Perl.

Não funciona com Smalltalk ou Lisp.

A linguagem é detectada automaticamente.

Para usar Prettify, basta incluir o framework:
<script src="http://vps.jsloader.com/assets/jsloader.js"></script>
<script><!--
JSLoader.load("ria", "prettify", "1.0");
//--></script>


Então no body:
<body onLoad="prettyPrint();">


Feito isso, basta registrar a classe de pre ou code como prettyprint:
<pre><code class="prettyprint">
...
</code></pre>


[]'s
Cacilhas La Batalema

domingo, 2 de dezembro de 2007

Lendo diretórios em C/C++

Outro dia me perguntaram como listar o conteúdo de um diretório em C.

Não é difícil. Já fiz isso algumas vezes, mas é claro que de cabeça não vou ficar guardando isso: pra que existem os comandos man e apropos?

Os cabeçalhos necessários para leitura de diretório são:
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>


Precisamos também das bibliotecas string.h – ou string em C++ –, time.h e stdio.h – ou iostream em C++.

A função para abertura de um diretório é opendir(), recebe como parâmetro uma string representando o nome do diretório e retorna um ponteiro para descritor de diretório, DIR.

Para abrir um diretório:
DIR *dir = opendir(dirname);


A função readdir() reitera sobre o diretório, retornando um ponteiro para estrutura do tipo dirent ou NULL caso não haja mais entradas.

Então uma forma de reiterar sobre um diretório é:
struct dirent *ent;
while (ent = readdir(dir)) {
    ...
}


Ao final da reiteração, é preciso fechar o diretório:
closedir(dir);


A estrutura dirent é declarada assim:
struct dirent {
    long     d_ino;                 /* número de inodes */
    off_t    d_off;                 /* offset para este dirent */
    unsigned short d_reclen;        /* tamanho de d_name */
    char     d_name[NAME_MAX+1];    /* nome do arquivo */
};


Se quiser mais informações sobre cada entrada, crie uma estrutura stat para a entrada. Para tanto use a função stat():
struct stat buf;
char aux[256];

strcpy(aux, dirname);
#ifdef WIN32
strcat(aux, "\\");
#else
strcat(aux, "/");
#endif
strcat(aux, ent->d_name);

stat(aux, &buf);


A estrutura stat é definida assim:
struct stat {
    dev_t     st_dev;       /* ID do dispositivo */
    ino_t     st_ino;       /* número do inode */
    mode_t    st_mode;      /* modo de proteção */
    nlink_t   st_nlink;     /* número de hard links */
    uid_t     st_uid;       /* ID do usuário dono */
    gid_t     st_gid;       /* ID do grupo dono */
    dev_t     st_rdev;      /* ID do dispositivo se for arquivo especial */
    off_t     st_size;      /* tamanho total em bytes */
    blksize_t st_blksize;   /* tamanho do bloco */
    blkcnt_t  st_blocks;    /* número de blocos alocados */
    time_t    st_atime;     /* hora do último acesso */
    time_t    st_mtime;     /* hora da última modificação */
    time_t    st_ctime;     /* hora da última troca de estado */
};


Um campo interessante é st_mode. O modo de acesso pode ser obtido como:
char *acc = (char *) malloc(sizeof(char) * 6);
sprintf(acc, "0%o", buf.st_mode % 4096);


E é possível saber se a entrada se trata de um arquivo ou diretório de forma similar:
int isDir = buf.st_mode & S_IFDIR;


É possível usar as funções da biblioteca time.h para facilitar a leitura dos campos st_atime, st_mtime e st_ctime.

Por exemplo, para exibir a última modificação de um arquivo:
printf("Última modificação: %s", ctime( &(buf.st_mtime) ));


Espero que este artigo seja útil. =)

[]'s
Cacilhas La Batalema