Тема: Третий байт или то, как не надо писать программы.
Расскажу-ка я небольшую историю, которая произошла с одним известным вам человеком.
Создал этот человек игру, назвал её Toribash. В ней были идеи, которых до этого не было в других играх, и эта игра стала популярна в некоторых кругах. Но не об этом разговор, а о третьем байте. В той игре было множество багов, но разработчик был настолько ленив, что не исправлял их годами. Игра и так приносит деньги, какой смысл париться? Был в игре и тот самый баг, о котором я хочу вам рассказать. Этот баг как раз связан с этим самым третьим байтом.
Как и в каждой мультиплеерной игре, в этой игре был чат. Но иногда случалось так, что поле чата само закрывалось, а при повторном открытии его там оказывался тот же текст, какой и был до закрытия, но была и одна проблема, которую не понять без знания некоторых основ.
Внутреннее представление текста, который находится в поле чата, использует кодировку UTF-8. В этой кодировке один символ имеет длину от одного до четырёх байт (в этом есть свои преимущества, например, остаётся полная совместимость с ASCII кодировкой, текст, использующий только символы из ASCII занимает ровно столько же байт, сколько и оригинальный текст в той кодировке). Не буду вникать в подробности о системе кодирования байт в UTF-8, не об этом разговор идёт.
Так вот, позиция курсора в том самом поле указывает на номер байта, который соответствует символу перед курсором. Всё вроде бы просто, если бы все символы были бы длиной в одинаковое количество байт. Но проблема в том, что так не всегда бывает. Как и было указано выше, при использовании только ASCII всё просто, мы смещаем эту позицию на один байт влево или вправо и мы получаем номер байта, который соответствует нужному символу. Если длина символа больше одного байта, то приходится подсчитывать, какова длина в байтах следующего или предыдущего символа и смещать указатель на нужное число байт. Требует дополнительной работы, но всё равно вполне реально осуществить. Тут и выходит на сцену наш третий байт.
При том самом беспричинном исчезновении поля и его обратного открытия указатель на символ, который следует перед курсором, сбрасывается в позицию 3. Вроде бы ничего, всё нормально, курсор просто становится перед третьим символом. Но вспомним, что этот указатель указывает на байты, а не символы, поэтому при использовании символов, находящихся все диапазона ASCII, этот указатель может указывать внутрь символа, а не на границу между символами, что не слишком хорошо. При дальнейшем наборе текста эти символы вставляются внутрь другого символа. Очевидно, что это приводит к каким-то неприятным последствиям, что и выходит на самом деле. Вместо вводимого текста появляются какие-то случайные символы, а в некоторых случаях игра вылетает. Это происходит из-за того, что Toribash при попытке отрисовки совсем уж непонятных символов вылетает, а такие символы как раз и возникают, когда проявляет себя этот баг. Единственным решением, которое вам поможет, если у вас произошла такая ситуация, когда курсор указывает внутрь символа, является или нажатие клавиш Home/End (нажатие этих клавиш переводит курсор в начало или конец строки, а в таких случаях курсор, естественно, не будет указывать внутрь символа, что нам как раз и необходимо), или просто отправка такого сообщения (это сбросит и текст в чате, и позицию курсора в начальные значения, что является самым простым решением).
Такие вот дела.

Slot: Родина это не килька в томате.
