пятница, 28 августа 2009 г.

boost 1.40

Тихо и незаметно вчера вышла очередная версия библиотеки boost. Список изменений небольшой, в основном затронута библиотека Asio.

Changing wallpaper on Linux programmatically

Для тех, кто хочет начать работать с GNOME, но не знает с чего начать, вот задачка — поменять обои рабочего стола. Это я так пытаюсь подойти к проблеме поддержки разных обоев для двух мониторов (точнее, монитора и HD телевизора в моем случае). В KDE с этим проблем нет, но в GNOME такой настройки нет. Оказалось, что сделать это несложно. Проблемой я собирался заняться давно, но преодолеть лень и написать код меня сподвигнул этот вопрос.

Нам понадобятся: Ubuntu, любимый текстовый редактор, пакет build-essentials, libglib-2.0-dev, libgconf2-dev и консоль. Думаю, что ставить пакеты все умеют (кто не умеет — читать тут).

В текстовом редакторе создаем файл следующего содержания:
// bkgmanage.c
#include <glib.h>
#include <gconf/gconf-client.h>
#include <stdio.h>

typedef enum {
  WALLPAPER_ALIGN_TILED     = 0,
  WALLPAPER_ALIGN_CENTERED  = 1,
  WALLPAPER_ALIGN_STRETCHED = 2,
  WALLPAPER_ALIGN_SCALED    = 3,
  WALLPAPER_NONE            = 4
} WallpaperAlign;

gboolean set_as_wallpaper( const gchar *image_path, WallpaperAlign align )
{
  GConfClient *client;
  char        *options = "none";

  client = gconf_client_get_default();

  // TODO: проверить, что image_path является файлом и вообще существует
  if ( image_path == NULL ) options = "none";
  else {
    gconf_client_set_string( client, 
      "/desktop/gnome/background/picture_filename",
      image_path,
      NULL );
      
    switch ( align ) {
      case WALLPAPER_ALIGN_TILED: options = "wallpaper"; break;
      case WALLPAPER_ALIGN_CENTERED: options = "centered"; break;
      case WALLPAPER_ALIGN_STRETCHED: options = "stretched"; break;
      case WALLPAPER_ALIGN_SCALED: options = "scaled"; break;
      case WALLPAPER_NONE: options = "none"; break;
    }
  }

  gboolean result = gconf_client_set_string( client, 
    "/desktop/gnome/background/picture_options", 
    options,
    NULL);
  g_object_unref( G_OBJECT(client) );

  return result;
}

int main(int argc, const char* argv[])
{
  if ( argc > 1 ) {
    printf( "Setting %s as wallpaper... ", argv[1] );
    if ( set_as_wallpaper( argv[1], WALLPAPER_ALIGN_STRETCHED ) ) printf( "Ok\n" );
    else printf( "Failed\n" );
  } else printf( "Usage: ./bkgmanage <filename>\n" );

  return 0;
}
gconf — это библиотека для управлением аналогом реестра в GNOME. С помощью неё и исправляется параметр /desktop/gnome/background/picture_filename для замены картинки, а также /desktop/gnome/background/picture_options для определения параметров отображения этой картинки. Изменения вступают в силу мгновенно.

Сборка указанного выше файла тоже не составляет труда. Достаточно в консоли ввести:
gcc -Wall -g `pkg-config --libs --cflags glib-2.0 gconf-2.0` bkgmanage.c -o bkgmanage
Тут pkg-config возвращает все необходимые пути к include-файлам и библиотеки, необходимые для линковки, что очень удобно. В результате получается исполняемый файл bkgmanage.

Далее, остается сделать GUI для удобного выбора картинок для каждого монитора с последующей склейкой в один файл. Пока не решил какой фреймворк для этого выбрать — основная идея, что хочется писать на С++, но Qt имеет слишком много зависимостей, которые в GNOME по умолчанию отсутствуют...

четверг, 6 августа 2009 г.

Trigraph sequences in C++

C++ стандарт в части 2.3/1 утверждает, что перед началом любой обработки кода все вхождения трех символов, указанных в таблице, будут заменены на один соответствующий символ.
----------------------------------------------------------------------------
| trigraph | replacement | trigraph | replacement | trigraph | replacement |
----------------------------------------------------------------------------
| ??=      | #           | ??(      | [           | ??<      | {           |
| ??/      | \           | ??)      | ]           | ??>      | }           |
| ??’      | ˆ           | ??!      | |           | ??-      | ˜           |
----------------------------------------------------------------------------
На практике это означает, что если даже в строковой константе встретится такая последовательность, то последствия могут оказаться неожиданными. Например, такой код:
printf( "What??!\n" )
Выдаст пользователю такой текст:
What|
Помимо этого есть такая же таблица для пар символов, которая делает следующий код вполне корректной программой на С++:
%:include <stdio.h>

%:ifndef BUFSIZE
%:define BUFSIZE  512
%:endif

void copy(char d<::>, const char s<::>, int len)
<%
while (len-- >= 0)
<%
d<:len:> = s<:len:>;
%>
%>
Стандарт поддерживает эти символы для совместимости, т.к. на очень старом железе в Европе не было части символов. Интересно, что в будущем стандарте С+x0 было предложено отказаться от поддержки триграфов, однако, этого видимо не произойдет. Подробнее тут.

Для современных разработчиков пользы это этой фичи языка C++ толку никакого, но знать и помнить о ней нужно, чтобы понимать что происходит.