O artigo de Alexis Bingessner,
“Text Rendering Hates You”, publicado há um mês
, é muito próximo a mim.
Em 2017, eu estava desenvolvendo um editor de texto interativo em um navegador. Insatisfeito com as bibliotecas ContentEditable existentes, pensei: “Ei, redescobri a seleção de texto! Isso é difícil? Eu era jovem. Ingênuo. Imaginei que poderia lidar com isso em duas semanas. De fato, uma tentativa de resolver esse problema levou vários anos da minha vida, incluindo um ano de trabalho remunerado da manhã até a noite para desenvolver um editor de texto para o novo sistema operacional.
No trabalho, tive a sorte de aprender muito com
mentores com vasta experiência neste campo . Eu ouvi muitas, muitas histórias assustadoras. Incluindo um engenheiro que deu suporte a um aplicativo Windows com uma implementação personalizada de um campo de texto - e queria mudar de uma API de entrada de texto desatualizada para uma nova versão. Aqui está uma
lista de interfaces de entrada
de texto nesta nova versão:

É isso mesmo, 128 interfaces para inserir texto. Tenho quase certeza de que existem oito (8!) Tipos diferentes de bloqueios para corrigir problemas de simultaneidade, embora eu honestamente não tenha lido a documentação deles, não me cite sobre isso. Esse engenheiro, um ano e meio (em tempo integral!), Modificou seu editor, mas no final falhou e permaneceu na API antiga.
Digitar é difícil.
Alexis às vezes menciona a seleção de texto, mas sua experiência pessoal está mais relacionada à renderização. Como pessoa, por outro lado, posso acrescentar alguns pontos sobre a entrada.
Movimento vertical do cursor
Eu já cobri isso em um
artigo anterior , mas podemos repetir rapidamente aqui.
Neste exemplo, se você pressionar para cima, o cursor vai para o início da linha, antes da palavra
hello . Até agora, tudo é bastante razoável. Mas se você pressionar para cima e depois para baixo, o cursor primeiro pulará na frente do
olá e depois permanecerá depois de
alguns .
Isso pode não parecer muito lógico. Você pergunta por que ele pula para a direita? Bem, com movimentos verticais, cada cursor lembra a posição
x em pixels e só é atualizada quando pressionada à esquerda ou à direita, e não para cima e para baixo. O mesmo comportamento impede que os cursores se movam para a esquerda ao se mover verticalmente através de linhas curtas.
Proximidade
Ok, agora sabemos que, quando selecionamos o texto, temos
duas partes de estado: o byte offset dentro da linha e a coordenada
x em pixels, mencionados acima. O problema foi resolvido? Bem, não.
Considere duas posições de cursor em uma linha muito longa:
Como
loooooooooong é uma palavra, duas posições do cursor têm
exatamente o mesmo deslocamento de bytes na string . Não há nova linha entre eles, pois a linha é suavemente quebrada. Nossos cursores precisam de um pouco mais que lhes diga para qual linha ir. A maioria dos sistemas chama isso de afinidade de bit. Também é usado em texto bidirecional misto, sobre o qual falaremos em breve.
Modificadores de Emoji
Suponha que eu envie uma mensagem para um amigo. Para expressar meus sentimentos, quero adicionar um emoji engraçado. Entro na área de texto um polegar para cima,
a
letra e um emoji modificador para o tom de pele. É assim:
Ah, eu não queria escrever uma carta. Defino o cursor após ele e clique em Backspace. O que vai acontecer? Eu vi várias opções, dependendo do editor.

- Mau # 1 pode parecer certo. Mas é assim que um editor de texto funciona com suporte à renderização de emoji herdada, por exemplo, Texto Sublime. Isso é ruim porque o emoji de dedo claro é codificado como um dedo amarelo, seguido imediatamente por um modificador de tom de pele. Eles não são combinados em um símbolo, conforme o esperado. Mesmo se eu copiar o dedo leve de outro aplicativo, ele ainda não será exibido corretamente, como aqui.
- Mau # 2 é o que o Chrome 77 faz na barra de endereços. Não nas páginas da web, mas apenas na barra de endereço. Isso não é um problema de renderização, pois o emoji de copiar e colar com tons de pele funciona. Em vez disso, o Chrome exclui a letra e, tendo notado o modificador após a letra, também a exclui. Opa
- O número 3 ruim corresponde à especificação Unicode de como os emojis devem ser mesclados. Mas isso é incompreensível para os usuários e, a propósito, você precisa mover o cursor para que ele não fique preso no meio do emoji.
Todas as opções são ruins, então você pode assumir que provavelmente existe uma quarta opção. Existe! Muitos editores, como o TextEdit, nem permitem que você coloque o cursor após a letra, pois o modificador de tom de pele é considerado uma unidade única com o caractere anterior. Isso faz sentido no contexto de emoji e até funciona bem nesse caso, mas e se o modificador for indicado pelo primeiro caractere na string?
Agora o modificador altera o caractere de nova linha. O TextEdit não permitirá que você coloque o cursor no início da segunda linha! Pessoalmente, considero esta decisão "também ruim".
Você também deve ter notado que o polegar para cima se tornou o polegar para baixo. Eu mesmo fiz isso para refletir meus sentimentos sobre toda a situação.
A propósito, o TextEdit especificamente torna o cursor na primeira linha
muito buggy. Por exemplo, adivinhe o que acontece se eu pressionar
4
aqui?
Sim Você também pode pensar que há espaços entre os números. Eles não estão lá.
Texto bidirecional
Alexis menciona seleções divididas em texto bidirecional misto, como neste exemplo de TextEdit:
Isso realmente faz sentido, já que o idioma árabe nas linhas é codificado da direita para a esquerda, de modo que a seleção parece ser dividida, mas bytes é um intervalo contínuo.
Portanto, é um pouco surpreendente que possamos obter essa seleção:
Sim, é visualmente contínuo, mas separado por bytes. Sim, é ruim. Alguns editores fazem isso se você selecionar texto com as teclas de seta em vez do mouse. Uma alternativa é trocar as teclas esquerda / direita dentro do texto pela direção da direita para a esquerda, o que também é ruim. Não há boas opções aqui.
Como bônus, tente entender o que está acontecendo aqui:
Senhor ... eu não quero comentar sobre isso.
A coisa sobre métodos de entrada
O software que converte pressionamentos de teclas em entrada é chamado de método de entrada ou editor de métodos de entrada. Para o alfabeto latino, esse não é um software muito interessante, pois cada pressionamento de tecla está diretamente associado à inserção de um caractere. Mas em muitos scripts, os caracteres não se encaixam no teclado, então você precisa ser criativo. Por exemplo, em alguns métodos de entrada para o idioma chinês, o usuário digita sons - e obtém uma lista de caracteres semelhantes no som:
Às vezes, esse campo é chamado de região de composição e geralmente aparece
acima do texto sublinhado . Às vezes, o método de entrada precisa estilizá-lo. Por exemplo, o método de entrada japonês no Android usa a cor de fundo para criar uma área de compartilhamento de frases:
(Obrigado a Shae pela captura de tela!)Todas essas seleções e áreas de composição interagem com o texto bidirecional? Não vamos pensar sobre isso.
Os métodos de entrada devem funcionar em qualquer lugar,
mesmo dentro do terminal :
Nada irá para o Vim até que um caractere chinês seja selecionado na lista. Você provavelmente pensa: "Mas como isso funciona no modo de comando do Vim?" Não é muito bom. É por isso que, na Internet, a entrada de texto e as teclas são eventos separados. No console, eles se misturam, causando problemas.
Este é apenas um exemplo de muitos métodos diferentes de entrada de texto. (Não se esqueça dos métodos de entrada sem teclado, como voz e escrita!) Felizmente, o sistema operacional fornece todos esses métodos. Mas, infelizmente, sua caixa de texto deve falar o protocolo geral de entrada de texto usado por todos esses métodos. Para Windows, essas são as 128 interfaces listadas no início do artigo. Em outros sistemas operacionais, as interfaces são mais simples, mas ainda são difíceis de implementar.
Você também pode observar que o método de entrada é um processo separado; portanto, o método de entrada e o aplicativo podem fazer alterações no estado do campo de texto. Este é realmente um protocolo de edição paralela. O Windows resolve o problema com oito (8!) Tipos de bloqueios. Embora manter um bloqueio nos limites do processo possa parecer duvidoso, a maioria das outras plataformas tenta usar heurísticas imperfeitas para corrigir problemas de simultaneidade. Ou eles apenas esperam que a condição da corrida não aconteça. Na minha experiência, a oração não é um primitivo muito eficaz do paralelismo.
Por que tudo é tão complicado?
Jonathan Blow, em uma palestra sobre degradação de software, menciona o
editor de texto Ken Thompson , que ele escreveu em uma semana. A maior parte do código deste artigo é introduzida aleatoriamente complexidade. O Windows realmente precisa de 128 interfaces e 8 tipos de bloqueios para entrada de texto? De jeito nenhum. Os erros no TextEdit são o resultado de um modelo de edição complexo? Sim A dispersão de bugs nos programas modernos é algo com que se preocupar? Pelo menos para mim é.
No entanto, o editor de Ken Thompson também era muito, muito mais simples do que esperamos dos editores de texto modernos. O Unicode suporta quase todas as línguas vivas do mundo (existem cerca de 7.000) e muitas outras estão mortas. Existem scripts diferentes, instruções de texto e métodos de entrada, cada um dos quais impõe restrições complexas (e em alguns casos insolúveis) a qualquer editor. Mas ele também deve suportar leitores de tela.
Uma enorme complexidade acumula-se
inevitavelmente e, neste artigo, apenas a tocamos um pouco. Este é um verdadeiro milagre da programação: você pode simplesmente colocar
<textarea>
em uma página da web - e fornecer instantaneamente entrada de texto para todos os usuários da Internet ao redor do mundo.