Ángel Ortega III

Un naufragio personal

El chico que volvió — Lista de temas

Gustav Mahler — Feierlich und gemessen (Sinfonía nº 1, III)
Supertramp — Take The Long Way Home
The Cure — Boys Don't Cry
New Order — True Faith
Siouxsie and the Banshees — Israel
Bauhaus — Bela Lugosi's Dead
The Scavengers — Violence
Severed Heads — Dead Eyes Opened
Warpaint — Elephants
Apollo Sunshine — We Are Born When We Die
The Bolshoi — A Way II
Ann Hell — The Triumph of Death
George McCrae — Rock You Baby
Joe Dassin — Et Si Tu N'Existais Pas
Counting Crows — Mr. Jones
Laura Branigan — Self Control
Plastic Bertrand — Ça Plane Pour Moi
The Rolling Stones — Sympathy for the Devil
The Cranberries — Promises
Skin — Kill Everything
Giacomo Puccini — Intermezzo (Manon Lescaut)

A function to decode utf-8 in streaming mode

This is my C language function to decode utf-8 into wide characters, a byte at a time. It also detects encoding errors.

/**
 * mpdm_utf8_to_wc - Converts from utf8 to wchar (streaming).
 * @w: convert wide char
 * @s: temporal state
 * @c: char read from stream
 *
 * Converts a stream of utf8 characters to wide char ones. The input
 * stream is read one byte at a time from @c and composed into @w
 * until a Unicode codepoint is ready. The @s integer keeps an internal
 * state change and must be set to 0 before the stream is read. It
 * detects encoding errors; in this case, the special Unicode
 * char U+FFFD is returned.
 *
 * When 0 is returned, a new wide char is available into @w. If
 * the stream is interrupted in the middle of a multibyte character,
 * the @s state variable will not be 0.
 */
int mpdm_utf8_to_wc(wchar_t *w, int *s, char c)
{
    if (!*s && (c & 0x80) == 0) { /* 1 byte char */
        *w = c;
    }
    else
    if (!*s && (c & 0xe0) == 0xc0) { /* 2 byte char */
        *w = (c & 0x1f) << 6; *s = 1;
    }
    else
    if (!*s && (c & 0xf0) == 0xe0) { /* 3 byte char */
        *w = (c & 0x0f) << 12; *s = 2;
    }
    else
    if (!*s && (c & 0xf8) == 0xf0) { /* 4 byte char */
        *w = (c & 0x07) << 18; *s = 3;
    }
    else
    if (*s && (c & 0xc0) == 0x80) { /* continuation byte */
        switch (*s) {
        case 3: *w |= (c & 0x3f) << 12; break;
        case 2: *w |= (c & 0x3f) << 6;  break;
        case 1: *w |= (c & 0x3f);       break;
        }

        (*s)--;
    }
    else {
        *w = L'\xfffd';
        *s = 0;
    }

    return *s;
}

Sobre la creación de canales de Telegram

Hace unos días investigué para un amigo cómo crear y usar canales de Telegram y le envié este email contándole lo que he averiguado. Lo adjunto aquí para que no se pierda:

Hola. He investigado sobre los canales de Telegram y cómo automatizarlo. Como siempre todo es complicado y confuso. Te lo cuento aquí porque mañana seguro que se me ha olvidado.

Lo primero es crear un canal. Eso ya lo has hecho.

Lo segundo es crear un bot. Es una especie de usuario de Telegram que no es un usuario pero que puede postear en canales. Para crearlo hay que hablar con otro bot que se llama BotFather. Ahí hay que darle comandos tipo IRC para crear tu bot (sí, es así de confuso). Hay que mandarle el mensaje /newbot y él (como en un chat robótico) te pide el nombre del bot y el nombre del usuario del bot (no sé muy bien cuál es la diferencia ni por qué hacen falta dos nombres y por qué no puedes ponerle el mismo). Después de esto te da una cadena de texto mágica que es un identificador autenticado del bot para poder postear desde fuera.

Luego tienes que ir al canal y añadir al bot como administrador. Solo funciona si lo haces desde el móvil, desde el ordenador no lo he conseguido. Tienes que buscar el nombre del bot desde la lupa porque no te sale automáticamente tu lista de bots.

Una vez hecho esto un par de veces (a la primera no me ha funcionado), ya le puedes mandar comandos al bot por HTTP para postear en aquellos canales en los que está autorizado. Esto se hace con una query como la que sigue:

 https://api.telegram.org/botIDENTIFICADOR_DEL_BOT/sendMessage?
 chat_id=@CANAL&text=Hola%20caraculo

Esto se puede hacer directamente con el comando curl del Linux o desde algún programa, es una petición HTTP normal.

Eso publica en modo texto. Hay un modo especial HTML que es MUY limitado y solo acepta negrilla, cursiva, enlaces y poco más. Con eso hay que montárselo todo. En concreto, NO acepta <p> para separar líneas ni títulos <h1>, <h2>, etc ni nada de eso, así que hay que hacer una especie de conversión (no es que ignore los tags, es que casca y te rechaza el envío).

Leyendo por ahí he descubierto que el modo HTML sí acepta cortes de párrafo pero hay que meterlos a pelo, es decir, metiendo %0A (ascii del line feed). Para añadir imágenes hay otro truco, que es ponerlas como enlaces (NO como imágenes). Si dejas el texto del enlace vacío o con un espacio lo ignora. La gente dice que le pone un carácter Unicode especial que es el "separador que no ocupa espacio" pero a mí me lo rechaza.

Este comando funciona y genera una entrada más o menos bonita:

 curl 'https://api.telegram.org/botBLA_BLA_BLA/sendMessage?chat_id=@nutriguia
 &parse_mode=HTML&disable_web_page_preview=false&text=
 <b>Title</b>%0AThis is a <i>test</i>. <a href="https://triptico.com/img/mp.png">·</a>'

Así que se podría hacer un programita que instalado en un cron coja, por ejemplo, el feed ATOM o RSS de Nutriguía, magree un poco las entradas, las deje aceptables para el Telegram y las envíe con sendas peticiones HTTP como las que te he comentado arriba.

Quizá alguien ha hecho ya ese programa, no he investigado más allá.

Nada es lo que parece

Esto ocurrió. Un profesor dijo globo ocular. En el margen de un libro yo dibujé esto:

Se lo enseñé a un compañero y dije:

—¿Sabes qué es?

Y él me dijo:

—Pues claro. Una visión global.

The sprites of Freaks!

These are the sprites from the Freaks! 1993 game as animated GIFs for pixel-art lovers to enjoy.

Artwork by Ángel Ortega and Antonio Guerrero.

Tasso, Lamento e Trionfo

Tasso, Lamento e Trionfo es un relato sobre la pérdida, la injusticia y la belleza en el que se narra la lucha por la supervivencia de una institutriz caída en desgracia en los días anteriores al estreno del poema sinfónico que Franz Liszt compuso para conmemorar el centenario del nacimiento de Johann Wolfgang von Goethe.

Está incluido en la antología Tormenta e ímpetu, un libro de Tinta Púrpura Ediciones que toma el surgimiento del romanticismo como inspiración. Esta es la sinopsis:

"Amor y pasión. Sensaciones, sentimientos y emociones desatados. Tormenta e ímpetu. Sturm und Drang. Durante la segunda mitad del siglo XVIII, varios autores se revolvieron contra el racionalismo imperante. Su rechazo al estilo neoclásico del momento provocó el nacimiento de lo que llegaría a ser el Romanticismo. Frente a los fríos y rígidos moldes del neoclasicismo de origen francés, el Sturm und Drang alemán estableció el sentimiento y el yo, en lugar de la razón, como fuentes de inspiración. Esta antología recupera ese espíritu y la actualiza al siglo XXI. Y, ya que tanto Tinta Púrpura como el propio movimiento Sturm und Drang tienen una relación muy estrecha con la música, quisimos que esta antología también lo tenga. Cada uno de sus relatos es un particular homenaje de la palabra escrita a la música que tanto amamos; así como una interpretación personal, apasionada y desatada, de lo que el Romanticismo y, en particular, el Sturm und Drang, es para nosotros."

El libro se puede comprar en Amazon.

On selecting text in the Minimum Profit Text Editor

As this is a question I have to answer periodically here are my final words on it.

The Minimum Profit Text Editor has three selection modes: "movement", "block" and "vertical".

The "movement" one is the way of selecting text that is implemented everywhere and is somewhat of a standard: by pressing the shift key and using any of the movement actions (left, right, word left, word right, up, down, page up, page down, beginning of line, end of line, beginning of document or end of document) or by left clicking and dragging with the mouse. Additionally, you can right-click and drag to extend the selection. Once the block is marked any movement key deselects it. Typing something replaces the selection. Hitting del or backspace erases the selected text. Though this mode is what new users expect, it works weakly on non-GUI interfaces because of lacking or defective support in the underlying libraries and systems.

The "block" selection mode is an older style one (and the first one that MP had): by pressing a key (f9 by default) you mark the beginning or end of the marked text. The selection survives any movement (indeed, it's the only way block selection can be done, by moving to another place and marking the other end) and you can extend the block above or below whenever you want. Replacing and erasing works as expected. Additionally, most operations like search, replace, etc. only apply to the marked text if there is one (this is very useful). The selection only disappears when copying, erasing, replacing, mouse-clicking or unmarking (by pressing the f8 key). This is the way I copy and paste; I never use the standard way (I know you don't care).

The "vertical" selection mode also works by marking the beginning or the end of the block, but the selection forms a square shape (x, y to x', y') instead of a line-flow one. By default it's done by hitting ctrl-b. The selection can also be extended repeatedly. As in "block" mode, marked text is disabled after copying or by pressing f8. I never use this option and never did (it was implemented by a fellow programmer).

I agree that the "movement", "block" and "vertical" terms are a sloppy way to describe the operations they do.

Camino sobre cuchillas

Camino sobre cuchillas
y la tierra es polvorienta y cáustica
los árboles secos delimitan
esta senda de vacío y hambre
y la muerte no llega

El cielo es severo
y es como una puerta cerrada
sus goznes están sellados
con un emplasto de lágrimas y cenizas
y la muerte no llega

Perdí mi alma en el bosque de espinas
y ahora soy solo la muda de piel de mí mismo
los carroñeros me ignoran
y clamo a la espuma de las nubes
y la muerte no llega

Dejo atrás fantasmas perdidos
la desidia y el abandono llenan sus cuencas
como yo tapan sus heridas con palabras vanas
pero la vida se perdió en lágrimas
y la muerte no llega

Este páramo es interminable y frío
hay puentes rotos y ciénagas
lo sobrevuela el arcángel distante
que arrancó mi razón con sus zarpas
y la muerte no llega

Enterré el miedo en una cuneta
y lancé los sueños a la acequia
esa corriente enferma que rebosa
en el mar eterno sin lluvia
y la muerte no llega

Hay laúdes y tambores pisoteados
y la muerte no llega
mis pies se deshicieron en el filo
y la muerte no llega
caminé sobre cuchillas
y nada queda de mi mismo
solo la desazón y la sed
porque nunca llega

Este páramo soy yo
vencido y desolado
yo rompí los puentes y envenené los pozos
y quizá entregué mi razón
al ángel abominable que oscurece la llanura
y ya no recuerdo nada
porque acaso me rendí hace tiempo
y solo soy un paria
arrastrado sobre cristales rotos
porque solo tengo una esperanza
un deseo, una fiebre,
un dolor, un proyecto,
que nunca llega.

(nov 2018)