Пра Дед — II

Как некоторые уже догадались, фотография в предыдущем сообщении — фотомонтаж. :) Были использованы фрагменты юзерпикчи одного из лжеюзеров. В качестве подсказки, я оставил зашифрованное в тексте послание: попробуйте прочитать только большие буквы в сообщении, несложный приём, который я впервые увидел у лжеюзера tema.

2 комментария

Пра Дед

Папин дед, 1935 год. Из семейного фотоальбома. Захар Журавлёв. У меня ощущение, что я знаю в кого я пошёл лицом. :)

Пра (3.9Кб)

6 комментариев

Масло конопляное

Масло конопляное (22Кб)

Воистину, магазин «Эрком», который находится рядом с нашим офисом — лавка чудес. :) Купил там недавно «Масло конопляное. Нерафинированое. Изготовлено из плодов растения Cannabis satuva». Интересно, если по дороге домой меня, в силу каких-либо причин, остановит милиция, смогу ли я, до того как мне отобъют почки, объяснить, что это вполне легальный продукт? :)

10 комментариев

Наскальная живопись

Кружка (13.6Kb)

Эта «наскальная живопись» — причудливый пейзаж, созданный в моей кружке смесью черничного сока, настоя каркаде и зеленого чая «порох».

2 комментария

А вчера…

Вчера купили с savannavita два балона со взбитыми сливками… Итог — масса удовольствия и лёгкий приступ тошноты от массы съеденых на голодный желудок сливок. :)

Оставить комментарий

Казанская Венеция

Вчера выпало очень много снега, а утром всё это попыталось растаять. Очень похоже на раннюю весну…

Казань превратилась в некое подобие Венеции — пусть грязной и заваленной мокрым снегом, но со своими «Камазами»-гондолами, бороздящими улицы-каналы, пешеходами, лениво соображающими через какой мост из досок, снега и фанерных ящиков перебраться на другую сторону и мутными потоками талого снега, уносящими окурки, собачье дерьмо и арбузные корки.

2 комментария

Заколдованные буквы

Меня окружают Люди, Которые Думают, Что Знают Меня. Одни говорят: «какой ты A, но совсем не B и не C». Другие утверждают: «ты определённо B и, к тому же, C, но никак не A». «Ты не A,.. ты или B, или C» — размышляют третьи. И только я один знаю, что я — D.

16 комментариев

Воплощение

В ответ на собственные мысли, простимулированный сообщением от savannavita, распечатал на листе формата A4 подходящим шрифтом и цветом «Распространителям — просьба не беспокоить» и повесил на соседнюю дверь. :)

Оставить комментарий

Занятые люди — II

Помню, своё первое сообщение в ЖЖ я написал о некой бумажке на двери соседней фирмы. В бумаге настоятельно просили не беспокоить распространителей и рекламных агентов. За дверью фирмы ни одного человека занимающегося подобной деятельностью не было и, кстати, так и не появилось. Смысл же бумаги сводился, как легко догадаться, к просьбе, адресованной распространителям, не беспокоить людей сидящих за дверью.

Бумажка проболталась на двери несколько месяцев, затем исчезла. Видимо, с её исчезновением интерес к фирме со стороны разного рода агентов стал вновь составлять проблему, потому что вскоре бумажка вернулась в новой ипостаси. На этот раз состаялась попытка переосмысления фразы и вот, что получилось в итоге:

Не беспокоить (16Kb)

Какая забота о распространителях! Я уже начинаю подумывать о том, чтобы предложить им свои услуги в оформлении следующей версии…

3 комментария

Тем временем внутри…

Когда от прежних чувств остаётся пепелище, замок новой любви возрождается на прежних руинах или возникает, как бы из ничего, на новом месте?

Оставить комментарий

Про Это

Секс для меня — средство глубокого проникновения в человека.

Оставить комментарий

Беда с этим хлебцами

Хлебцы (16Кб)

Сколько же всякого гамна надо намешать с этим хлебцами, чтобы добиться улучшения их вкусовых качеств! Вы только вообразите себе дикую смесь из сгущеного молока, мёда, варенья, сыра, колбасы, бульёна, молочных продуктов, кофе и чая. Лишь эта смесь способна улучшить их вкусовые качества.

2 комментария

Дурацкий вопрос

Есть ли на свете более дурацкий вопрос, чем «вопрос можно?». Если вопрос уже задан, зачем спрашивать разрешение?

Оставить комментарий

Татарский шрифт своими руками, PHP 4.3.0+GD 2.0.x

Доброе время!

Несмотря на то, что татары перешли некоторое время назад с кириллицы на латиницу, латиница ещё настолько непривычна, что многие до сих пор читают и пишут «по старинке». Соответственно, большинство, за редким исключением, сайтов с информацией на татарском языке, предоставляют её в кириллице и будут предоставлять её ещё долго — не у всех есть время и желание переучиваться на непонятную им латиницу.

А значит, будет открыта проблема представления татарских национальных символов на веб-страницах. В данный момент используются две методики — Unicode и динамические шрифты. Обе имеют довольно существенные ограничения — Unicode поддерживают далеко не все операционные системы, а технология динамических (встроенных) шрифтов вообще своя чуть ли не у каждого производителя браузера.

Упомянутые татарские национальные символы очень похожи на буквы кириллического и латинского алфавитов, условно — «h с хвостиком», «ж с хвостиком», «н с хвостиком», «о с горизонтальной чертой», «укороченная у» и «перевёрнутая е».

Мне пришло в голову попробовать средствами CSS «дорисовать» существующие буквы, чтобы получилось что-то похожее на татарские символы. Помучиться пришлось изрядно, я попробовал несколько вариантов, пока не остановился на относительном позиционировании элементов вкупе с использованием margin.

Другие варианты не сработали — давали отступ после буквы, порождали проблемы с переносом или кросс-браузерной совместимостью. В итоге получилось 6 букв нижнего регистра для шрифта Tahoma 12px.

Opera 6.02, Mozilla 1.2a, Netscape Navigator 7.0 и Microsoft Internet Explorer 6.0 отображают эти буквы нормально:

’h ’ж -o ..э .v ’н

Netscape Navigator 4.80 отобразить не смог, естественно, не отобразят их и неграфические Lynx и Links. Но это не страшно — первый уже вымирает, а последние не отобразят такие буквы и любым другим способом.

Способ имеет свои недостатки — если на текста экране много, Internet Explorer несколько «подтормаживает» при рендеринге, остальные браузеры справляются с этой задачей куда лучше.

Для представления этих символов в кириллице, до перевода их форму пригодную для вывода я использовал сочетания х’, ж’, о’, е’, у’ и н’. Способов автоматического перевода из указанных сочетаний в HTML минимум три: назначить собственный обработчик для HTML-файлов, который будет осуществлять трансляцию, создать в Apache новую раскладку, скажем tat, директивами CharsetDecl и CharsetWideRecodeTable или осуществлять весь вывод через собственные скрипты, не используя статических файлов, например, так как это сделано ниже.

<?php
function Tat_Recode($str)
{
    $trans = array (
    "х'" => '<span style="margin-left:-3;margin-right:0"><span style="position:relative;top:9;left:8">\'</span>h</span>',
    "ж'" => '<span style="margin-left:-3;margin-right:0"><span style="position:relative;top:9;left:11">\'</span>ж</span>',
    "о'" => '<span style="margin-left:-4;margin-right:0"><span style="position:relative;top:0;left:5">-</span>o</span>',
    "е'" => '<span style="margin-left:-7;margin-right:0"><span style="position:relative;top:-1;left:6">.</span><span style="position:relative;top:-2;left:2">.</span>э</span>',
    "у'" => '<span style="margin-left:-4;margin-right:0"><span style="position:relative;top:2;left:5">.</span>v</span>',
    "н'" => '<span style="margin-left:-3;margin-right:0"><span style="position:relative;top:9;left:8">\'</span>н</span>');

    return strtr ($str, $trans);
};
    ob_start(Tat_Recode);
?>
<span style="font-family: Tahoma; font-size: 12px">
Татарстан Президенты Минтимер Ше'ймиев шушы ко'нне'рде' Башкортстан Президенты Мортаза Ре'химовнын' республикада президентлык постын юкка чыгару турында е'йтке'н идеясе ун'аеннан аптырашта калуын белдерде.

«Мортаза Гобе'йдулла улы Ре'химовнын' республикада хакимият структурасын у'зге'рту'ге' кагылышлы те'къдимне'ре ж'авапларга караганда ку'бре'к сораулар тудыра, х'е'м минде' гене' ту'гел", - диде М.Ше'ймиев пе'нж'еше'мбе ко'нне "Интерфакста бирге'н интервьюсында. Анын' фикеренче', Башкортстан ж'ите'кчесенен' бу фикерне нигезле'ве "бик каршылыклы».

«е'мма мондый белдеру'ле'рнен' се'бе'бе нинди булуга карамастан, бу очракта мин шуны гына е'йте' алам: аларны Татарстан Президентынын' белдерме'ве е'йбе'т», — диде М.Ше'ймиев.

</span>
<?
ob_end_flush();
?>

Скрипт средствами PHP 4 перехватывает весь вывод и пропускает его через функцию Tat_Recode, которая осуществляет необходимые замены. Думаю, метод пригодится для представления букв и на других языках. Как осуществляется изготовление отдельной буквы можно легко понять, взглянув на HTML-код.

Если вы попробовали скомпилировать PHP 4.2.0 или 4.3.0pre1 с GD-2.0.x, то уже, наверняка, знаете какие сообщения об ошибке появятся на экране, стоит сделать make. Патчей, исправляющих эту ситуацию на сайте PHP я не нашел, а поставить GD очень хотелось, поэтому пришлось исправлять ситуацию самостоятельно.

Дело состоит, видимо, в различиях GD API, описанного в документации и реального положения дел. В документации утверждается, что структура gdIOCtx содержит, помимо всего прочего метод free, который используют два файла из дистрибутива PHP: gd.c и gd_ctx.c. На самом же деле метод free в gdIOCtx не описан, зато там содержится gd_free, который с успехом выполняет требуемые функции.

Таким образом, чтобы скомпилировать текущую версию PHP с GD-2.0.x вам нужно руками заменить слово free на gd_free в тех местах, где компилятор указывает на ошибку. Результат работы утилиты diff ниже.

[root@x gd]# diff gd.old.c gd.c 
1036c1036
<          io_ctx->free(io_ctx);
---
>          io_ctx->gd_free(io_ctx);
1039c1039
<          io_ctx->free(io_ctx);
---
>          io_ctx->gd_free(io_ctx);
1216c1216
<        io_ctx->free(io_ctx);
---
>        io_ctx->gd_free(io_ctx);

[root@x gd]# diff gd_ctx.c gd_ctx.old.c 
70c70
<        ctx->gd_free = _php_image_output_ctxfree;
---
>        ctx->free = _php_image_output_ctxfree;
98c98
<       ctx->gd_free(ctx);
---
>       ctx->free(ctx);

Загадка для программистов от Dead Emotion. У меня Perl’e получилась одна строка кода. :)

есть текстовый файл, довольно большой, настолько, что целиком в доступную память не влезет, количество строк в нем заранее не известно. собственно задача — вывести случайную строку из этого файла, зачитав его только один раз. (с вероятностью 1/n, где n — количество строк в этом самом файле)

Письмо от Fedor «FAx» Axenoff.

Спасибо за чистилку JPEG!!!

Знаешь какая ещё проблема в мире дизайна?
нет и не будет конвертора угробищного Corel Draw формата в что либо
типа EPS\AI. С самим CDR всё может и сложно, но вот его CMX\CCX\CXX
картинки — вполне должны конвертиться, если с этим разобраться.

Я слышал что кто-то с этим ковырялся и сказал что сделать можно, но
для этого потребуются все dll Corel-овских фильтров. Да хрен с ними,
пусть будут — лишь бы конвертил. Официальные кореловцы мне сказали что
конвертора не будет никогда и это их маркетинговые соображения.

Не то что бы я как то сильно не любил Корел (Ну да, я заказал себе
майку «Corel Killer» и что с того? 8-)) но все шлют макеты именно в
нём, а его поставить на машину — как продать родину. 8-)

ps. Я пользуюсь XaraX или AI.
pss. Это отнюдь не «заказ». Если у самого нет желания — просто умомяни
на сайте — может кто возьмётся… 8-/

У меня, к сожалению, нет времени, чтобы реализовать такой конвертор, может быть кто-то возьмётся или может быть кто-нибудь видел что-то подобное на просторах интернета? Формат CMX Corel распространяет свободно, описание EPS тоже есть.

Пишите!

Оставить комментарий

Лимон

Иллюстрация не сохранилась Лимон

Это не ручка маленькая, это лимон такой большой. Мутант был куплен мной сегодня в магазине «Эрком» по улице Космонавтов, причём даже сами продавцы были весьма удивлены его внешним видом; таких там ещё много. Вечером планируется дегустация этой жертвы космической радиации.

6 комментариев

Программа CSV SQL Monitor

Некоторое время назад, испробовав различные программы для обработки логов Squid, я убедился, что ни одна из них не отвечает моим требованиям и написал свою. Простенький, однозадачный вариант на языке Perl. В качестве базы данных я выбрал модуль для Perl, который позволяет делать SQL-запросы к файлу в формате CSV (Comma Separated Values).

Это уже потом я узнал, что в CSV SQL нет агрегатных функций, LIMIT, да и скорость работы модуля оставляет желать лучшего и переписал всё с использованием DB_File::Lock и fork. Но от времён, когда я использовал CSV у меня осталась программа, которую я написал для удобства работы с SQL-запросами.

Назвал я её незатейливо — CSV SQL monitor, текущая версия 1.06. Возможно, кому-то пригодится, мало ли какие задачи придётся решать.

Итак, CSV SQL monitor. Для функционирования требуются модули Term::ReadLine (лучше Term::ReadLine::Gnu), Text::Tabs, Cwd, DBI и DBD::CSV. При запуске можно указать необязательный параметр — местоположение каталога с CSV-файлами, если этот параметр не указан этим этим каталогом считается рабочий каталог программы. Все файлы в нём считаются таблицами, к которым, при ограничениях описанных ниже, можно делать запросы.

Скриншот терминала с SQL-запросом SELECT * FROM passwd LIMIT 1; и выводом таблицы с данными пользователя root (uid=0, gid=0, home=/root, shell=/bin/bash).
CSV SQL monitor

SQL-команды полностью идентичны обычному SQL за исключением накладываемых модулем DBD::CSV ограничений. В мониторе вместе с SELECT-запросом можно использоваться LIMIT — его я эмулирую, пропуская и возвращая указанное число строк. LIMIT работает в режиме MySQL, т. е. команда

SELECT * FROM file LIMIT 1,2

Пропустив одну, покажет две строки, с условием, конечно, что в файле есть хотя бы 3 строки данных. Кроме того, я реализовал ряд специфических команд, которые позволяют получить кое-какую информацию или сконфигурировать модуль DBD::CSV по своему усмотрению:

SHOW TABLES
Показывает имена «таблиц» в каталоге, указанном как каталог с CSV-файлами.

BIND TABLE <имя таблицы> <имя файла>
Так как файлы у вас могут называться как угодно (например, «my document.csv»), а SQL не допускает использование имен таблиц с пробелами, точками и другими подобными символами, но использовать эти файлы в качестве таблиц всё равно нужно, Monitor позволяет «привязать» к «неудобному» имени любое другое, которые SQL примет как удовлетворяющее стандартам.

BIND TABLE log log.txt

VAR FOR <имя таблицы> <имя переменной > <значение переменной>
Позволяет настроить некоторые специфические параметры для таблиц, например, символ, который будет считаться разделителем строк или полей. Подробнее о значении каждого параметра можно прочитать в документации по DBD::CSV, а я лишь приведу пример, который позволит понять, каким образом удалось получить картинку, как не скриншоте.

Я использовал три команды:
VAR FOR passwd eol \\n
VAR FOR passwd sep_char :
VAR FOR passwd col_names name,pass,uid,gid,comment,home,shell

После чего, можно спокойно назначать каталог /etc рабочим и делать запросы к таблице passwd (для людей, не знакомых с Unix, сделаю пояснение: в файле /etc/passwd Unix, в традиционной конфигурации, хранит основные данные о пользователях). Если требуется удалить какое-либо значение, можно просто ввести undef вместо значения переменной.

Кстати, отсюда можно увидеть, что все экранирующие слеши (\) должны быть экранированы таким же слешем, чтобы отличать случаи их упоминания от специальных команд, речь о которых пойдет ниже.

Специальные команды нужны, чтобы сообщить «Монитору», что именно вы хотите, чтобы он сделал. Думаю, они будут хорошо знакомы всем, кто хотя бы раз использовал mysql-монитор, работающий из командной строки. Специальные команды используются либо в конце SQL-запроса, либо сами по себе, для выполнения каких-либо действий. Все они (кроме ;) начинаются с экранирующего слеша.

Примеры использования специальных команд:
SHOW TABLES\G
\r /etc

Полный список этих команд вы, в любой момент, можете получить командами \? или \h, я приведу их тут с подробной расшифровкой их действия.

\h или \? — как я уже сказал, позволяет получить список всех доступных специальных команд.

\c — очищает буфер команды. Если вы набрали какую-то SQL-команду, но не запустили её на выполнение, она будет сохраняться в буфере до тех пор, пока вы её не выполните (командами ;, \g или \G) или не очистите буфер командой \c.

\r [<каталог>] — закрывает текущее соединение с каталогом и открывает новое. С аргументом «каталог» действие аналогично команде \u.

\g — выполнить текущий SQL-запрос. Синоним этой команды — ;.

\G — выполнить текущий SQL-запрос и вывести результат вертикально. Что это такое я объяснять не буду — достаточно один раз применить эту команду, чтобы понять о чём идёт речь. :)

\u <каталог> — сменить каталог с CSV-файлами.

\q — выйти из Монитора.

Если вы используете модуль Term::ReadLine::Gnu, вам будет доступны такие возможности как пролистывание команд (стрелки «вверх» и «вниз») и автодополнение команд.

Автодополнение команд я постарался сделать зависимым от контекста. Так, если вы введете S и нажмёте Tab, то получите список из двух команд — SELECT и SHOW TABLES, далее, если ввести ещё и E и нажать Tab строка дополнится до SELECT . В нужном месте Tab выведет вам список файлов в текущей директории, в случае команды VAR FOR покажет список её параметров и так далее.

Конечно, я не учитывал все случаи, но Tab существенно облегчит вам жизнь во многих случаях. Кстати, если вы связали (BIND TABLE) какое-то имя файла с каким-либо именем таблицы, Tab (так же, как и
SHOW TABLES) покажет вам имя таблицы, а не имя файла.

Скачать CSV SQL Monitor можно у меня со страницы. Объём в архиве — 2,8КБ, язык — Perl.

Пишите!

Оставить комментарий

География Ехо

Иллюстрация не сохранилась Кусок карты Ехо

Это — кусок карты мира Ехо, мира придуманного писательницей, пишущей под псевдонимом «Макс Фрай». Представляю себе, как главному герою Максу, который попал в Ехо, рассказывают о географии этого мира: «А это, Макс, у нас Вуки, нах, а это — горы, нах».

10 комментариев

Фантасты были правы

Сегодня моему автоответчику позвонили два автоинформатора — телефонной сети и кабельного телевидения. Собеседники остались довольны друг другом.

Оставить комментарий

99 бутылок: NSIS, Photoshop JavaScript

Сериал «99 бутылок пива» продолжается. Сегодня — 36 и 37-я серии, на сцене языки программирования инсталлятора фирмы Nullsoft и JavaScript for Adobe Photoshop.

36. Nullsoft (SuperPiMP|Scriptable) Install System. NSIS — настраиваемый инсталлятор от компании «Nullsoft», позволяющий создать пакет для инсталляции и деинсталляции вашего собственного продукта. Выходной файл представляет собой обычную программу. Для сжатия данных NSIS может использовать алгоритмы Zip и Bzip2, так что весь код получается довольно компактным.

Весь процесс установки и удаления продукта описывается на собственном языке программирования, где есть опции управления внешним видом инсталлятора, команды использования внешних плагинов, поддержки нескольких языков, команды предпроцессора и собственно язык с поддержкой функций, секций, ветвления, файлового ввода-вывода. Язык поддерживает так же несложную обработку событий в виде callback-функций с зарезервированными именами.

Я использовал версию 2.0b2. Язык инсталлятора крайне простой, поэтому не поддерживает локальных переменных и параметров у пользовательских функций — вместо них приходится использовать глобальные пользовательские переменные (их 20 штук) или стек. Кстати, и параметры плагинам передаются именно через стек.

Все имена переменных начинаются с доллара, программист для своих собственных целей может использовать лишь двадцать переменных — $0..$9, $R0..$R9, переменные не типизированы, в строках выполняется интерполяция, в качестве ограничителей строк подходят любые кавычки. Ветвление выполняется командами сравнения, которые в качестве аргумента принимают три ссылки, по одной из которых происходит переход в зависимости от результата сравнения.

Операции с числами так же выглядят несколько неожиданно. Вообще, даже прочитав полностью документацию, без примеров достаточно просто оставить без внимания некоторые возможности, которые становятся очевидными при просмотре примеров. Так что будете писать инсталлятор для своего продукта — загляните ещё и в примеры.

В любом случае, NSIS — достаточно надежный продукт, появился он не один год назад и используется, например, для инсталляции достаточно известного проигрывателя WinAMP.

Программа, выводящая песню о пиве (beer.nsi)

; Beer song.  Written by Evgeny Stepanischev
Name "Beer song"
Caption "Beer song"
OutFile "beer99.exe"
BrandingText "Beer song (Evgeny Stepanischev)"
ShowInstDetails show

!macro c
    StrCpy $2 ""
    Call PrintBeer
!macroend

Function PrintBeer
    IntCmp $1 0 no "" ""
    StrCpy $2 "$2$1"
    Goto +2
no:
    StrCpy $2 "$2No"
    StrCpy $2 "$2 bottle"
    IntCmp $1 1 nos "" ""
    StrCpy $2 "$2s"
nos:
    StrCpy $2 "$2 of beer"
FunctionEnd

Section ""
    StrCpy $1 99

loop:
    !insertmacro c
    StrCpy $2 "$2 on the wall, "
    Call PrintBeer
    DetailPrint "$2."
    DetailPrint "Take one and pass around,"
    IntOp $1 $1 - 1

    !insertmacro c
    DetailPrint "$2 on the wall."
    DetailPrint ""
    IntCmp $1 0 "" loop loop

    DetailPrint "No more bottles of beer..."
    DetailPrint "Go to the store and buy some more..."
    DetailPrint "99 bottles of beer."

SectionEnd

37. JavaScript for Adobe Photoshop (Photoshop 7.0 Scripting plug-in v.1.0.2a). В Adobe Photoshop с версии 7.0 появились полноценные скриптовые языки. Если верить руководству можно использовать три языка — JavaScript, VBScript и AppleScript.

Описывать JavaScript не интересно — базовые конструкции стандартные, добавлены лишь специфические объекты для управления всем тем, что есть в Photoshop, соответственно и объектная модель отличается от той, что принята, например, в браузерах.

Одним словом — полное управление всем, до чего можно дотянуться в бесконечных меню и опциях Adobe Photoshop (включая фильтры), из скриптового языка. Грандиозные возможности для дизайнеров, пробующих себя в программировании, или программистов, пытающихся заняться дизайном. :)

Программа, выводящая песню о пиве (beer.js)

preferences.rulerUnits = Units.POINTS
preferences.typeUnits  = TypeUnits.POINTS

var docRef = documents.add(640, 480)
displayDialogs = DialogModes.NO

var textColor = new SolidColor
textColor.rgb.red = textColor.rgb.green = textColor.rgb.blue  = 0

var TextLayer = docRef.artLayers.add()
TextLayer.kind = LayerKind.TEXT;

TextLayer.textItem.font     = "Tahoma"
TextLayer.textItem.position = Array(10, 10)
TextLayer.textItem.size     = 12
TextLayer.textItem.color    = textColor

var content = ''

function WriteLn(str)
{
    content += '\r'+str
}

function PrintBeer(n)
{
    return (n ? n : 'No') + ' bottle' + (n-1 ? 's' : '') + ' of beer'
}

for (i = 99; i>0;)
{
    WriteLn (PrintBeer(i) + ' on the wall, '+PrintBeer(i)+'.')
    WriteLn ('Take one and pass around,')
    WriteLn (PrintBeer(--i) + ' on the wall.')
    WriteLn ('')
}

WriteLn ('No more bottles of beer...')
WriteLn ('Go to the store and buy some more...')
WriteLn ('99 bottles of beer.')

TextLayer.textItem.contents = content
docRef = textColor = TextLayer = null


Оставить комментарий