X воздерживается от определения фиксированных типов данных для данных выделения или фиксированного числа выделений. Выделения идентифицируются X-“атомами”, которые представляют собой уникальные 29-битные идентификаторы, выдаваемые X-сервером для строковых имён. Эта сложность скрыта Emacs: когда Lisp предоставляет символ, имя которого совпадает с именем атома, Emacs запросит эти идентификаторы без дополнительного вмешательства.
Когда программа “устанавливает” выделение в X, она фактически делает себя “владельцем” выделения — X-сервер затем будет направлять запросы на выделение этой программе, которая обязана ответить запрашивающему клиенту данными выделения.
Аналогично, программа не “получает” данные выделения от X-сервера. Вместо этого её запросы на выделение отправляются клиенту, окно которого последним заявляло о праве собственности на выделение, и ожидается, что он ответит запрошенными данными.
Каждый запрос выделения включает три параметра:
gui-get-selection.
Владелец выделения отвечает, передавая запросчику последовательность байт, 16-битных слов или 32-битных слов, а также другой атом, идентифицирующий тип этих слов. После запроса выделения Emacs затем применяет собственную интерпретацию формата данных и типа данных для преобразования данных, переданных владельцем выделения, в представление Lisp, которое возвращает gui-get-selection.
Emacs преобразует данные выделения, состоящие из любой последовательности байт, в однобайтовую строку, содержащую эти байты; данные, состоящие из одного 16-битного или 32-битного слова, — в беззнаковое число; а данные, состоящие из нескольких таких слов, — в вектор беззнаковых чисел. Исключениями из этого общего правила являются случаи, когда Emacs применяет особую обработку для данных от следующих целей преобразования:
INTEGER16-битные или 32-битные слова этого типа рассматриваются как знаковые, а не беззнаковые целые числа. Если в данных выделения несколько слов, возвращается вектор; в противном случае возвращается само целое число.
ATOM32-битные слова этого типа рассматриваются как X-атомы и возвращаются (по отдельности или в виде векторов) как символы Lisp по идентифицируемым ими именам. Недействительные атомы заменяются на nil.
COMPOUND_TEXTUTF8_STRINGSTRINGВ однобайтовые строки, полученные в результате запроса этих типов данных, будет помещено свойство текста foreign-selection, установленное в тип данных выделения.
Каждый владелец выделения должен возвращать как минимум две цели выделения: TARGETS, которая возвращает количество атомов, описывающих цели выделения, поддерживаемые владельцем, и MULTIPLE, используемую для внутренних целей X-клиентами. Владелец выделения может поддерживать любое количество других целей, некоторые из которых могут быть стандартизированы Руководством по соглашениям межклиентского взаимодействия консорциума X, в то время как другие, такие как UTF8_STRING, предполагалось стандартизировать проектом XFree86, но их стандартизация так и не была завершена.
Запросы на определённую цель выделения по соглашению могут возвращать данные в определённом типе, а могут возвращать данные в одном из нескольких типов, в зависимости от того, что удобнее для владельца выделения; последний тип цели выделения называется полиморфной целью. В ответ на запрос цель выделения также может не возвращать никаких данных, после чего владелец выделения выполняет некоторое действие как побочный эффект. Цели, на которые отвечают таким образом, называются целями с побочным эффектом.
Вот некоторые цели выделения, поведение которых в целом соответствует стандарту при запросе из выделений CLIPBOARD, PRIMARY или SECONDARY.
ADOBE_PORTABLE_DOCUMENT_FORMATЭта цель возвращает данные в формате “Portable Document Format” компании Adobe Systems в виде строки.
APPLE_PICTЭта цель возвращает данные в формате изображений “PICT”, используемом на компьютерах Macintosh, в виде строки.
BACKGROUNDBITMAPCOLORMAPFOREGROUNDВместе эти четыре цели возвращают целочисленные данные, необходимые для использования растрового изображения, хранящегося на X-сервере: значение пикселя цвета фона растрового изображения, X-идентификатор растрового изображения, цветовую карту, в которой выделены фон и передний план, и значение пикселя цвета переднего плана растрового изображения.
CHARACTER_POSITIONЭта цель возвращает два беззнаковых 32-битных целых числа типа SPAN, описывающих начальную и конечную позиции данных выделения в текстовом поле, содержащем их, в байтах.
COMPOUND_TEXTЭта цель возвращает строку типа COMPOUND_TEXT в многобайтовой системе кодирования текста консорциума X.
DELETEЭта цель ничего не возвращает, но в качестве побочного эффекта удаляет содержимое выделения из любого текстового поля, содержащего его.
DRAWABLEPIXMAPЭта цель возвращает список беззнаковых 32-битных целых чисел, каждое из которых соответствует X-серверному объекту для рисования или пиксельной карте.
ENCAPSULATED_POSTSCRIPT_ADOBE_EPSЭта цель возвращает строку, содержащую инкапсулированный код Postscript.
FILE_NAMEЭта цель возвращает строку, содержащую одно или несколько имён файлов, разделённых символами NULL.
HOST_NAMEЭта цель возвращает строку, содержащую полное доменное имя машины, на которой работает владелец выделения.
USERЭта цель возвращает строку, содержащую имя пользователя машины, на которой работает владелец выделения.
LENGTHЭта цель возвращает беззнаковое 32-битное или 16-битное целое число, содержащее длину данных выделения.
LINE_NUMBERЭта цель возвращает два беззнаковых 32-битных целых числа типа SPAN, описывающих номера строк, соответствующих начальной и конечной позициям данных выделения в текстовом поле, содержащем их.
MODULEЭта цель возвращает имя любой функции, содержащей данные выделения. Её запрашивают в основном текстовые редакторы.
STRINGЭта цель возвращает данные выделения в виде строки типа STRING, закодированной в формате ISO Latin-1, с символами новой строки Unix.
C_STRINGЭта цель возвращает данные выделения в виде “C-строки”. Это интерпретировалось как необработанные данные выделения в любой кодировке, используемой владельцем, либо завершённые нулевым байтом, либо нет, либо ASCII-строка, которая может быть завершена, а может и нет.
UTF8_STRINGЭта цель возвращает данные выделения в виде строки типа UTF8_STRING, закодированной в UTF-8, с неопределённым форматом окончания строк.
TIMESTAMPЭта цель возвращает время X-сервера, когда владелец выделения вступил во владение выделением, в виде 16-битного или 32-битного слова типа CARDINAL.
TEXTЭта полиморфная цель возвращает данные выделения в виде строки — либо COMPOUND_TEXT, STRING, C_STRING, либо UTF8_STRING, в зависимости от того, какой тип данных удобен для владельца выделения.
Когда запрос на цели STRING, COMPOUND_TEXT или UTF8_STRING выполняется с использованием функции gui-get-selection, и ни selection-coding-system, ни next-selection-coding-system не установлены, результирующие строки декодируются соответствующими кодировками для этих целей: iso-8859-1, compound-text-with-extensions и utf-8 соответственно.
В дополнение к указанным выше целям (и многим другим целям, используемым различными программами для своих собственных нужд), несколько популярных программ и наборов инструментов определили свои собственные типы данных выделения, не обращаясь к соответствующим органам по стандартизации X. Эти цели обычно называются по аналогии с такими MIME-типами, как text/html или image/jpeg; известно, что они возвращают следующие формы данных:
file:// (или, возможно, разделённые новой строкой или NUL списки URI), идентифицирующие файлы в соответствующем формате.
Эти цели выделения впервые были использованы Netscape, но теперь предлагаются всеми видами программ, особенно основанными на последних версиях наборов инструментов GTK+ или Qt.
Emacs также способен выступать в роли владельца выделения. Когда вызывается gui-set-selection, предоставленные данные выделения записываются внутренне, и Emacs получает право собственности на устанавливаемое выделение.
Список соответствий целей выделения функциям “преобразователя выделения”. Когда получен запрос выделения, Emacs ищет преобразователь выделения, относящийся к запрошенной цели выделения.
Преобразователи выделения вызываются с тремя аргументами: символ, соответствующий атому, идентифицирующему запрашиваемое выделение; запрашиваемая цель выделения; и значение, установленное с помощью gui-set-selection. Возвращаемые ими значения должны быть либо cons-ячейками из символов, обозначающих тип данных, и чисел, символов, векторов чисел или символов, либо cdr таких cons-ячеек сами по себе.
Если значение преобразователя выделения является специальным символом NULL, тип данных, возвращаемый запросчику, устанавливается в NULL, и данные в ответ не отправляются.
Если такое значение является строкой, это должна быть однобайтовая строка; если тип данных явно не указан, данные передаются запросчику с типом STRING.
Если это символ, извлекается его “атом”, и он передаётся запросчику как 32-битное значение — если тип данных не указан, его типом является ATOM.
Если это число от -32769 до 32768, оно передаётся запросчику как 16-битное значение — если тип данных не указан, его типом является INTEGER.
Если это любое другое число, оно считается 32-битным значением. Даже если возвращаемое число беззнаковое, запросчик будет обрабатывать слова типа INTEGER как знаковые. Чтобы вернуть беззнаковое значение, укажите вместо этого тип CARDINAL.
Если это вектор символов или чисел, ответ запросчику будет списком из нескольких атомов или чисел. Тип данных, возвращаемый, если он явно не задан, соответствует типу первого элемента списка.
По умолчанию Emacs настроен с преобразователями выделения для следующих целей выделения:
TEXTЭтот преобразователь выделения возвращает данные выделения в виде:
C_STRING, если содержимое выделения не содержит многобайтовых символов или содержит “сырые 8-битные байты” (см. Текстовые представления).
STRING, если содержимое выделения может быть представлено как текст ISO-Latin-1.
COMPOUND_TEXT, если содержимое выделения может быть закодировано в составной текстовой кодировке консорциума X, а selection-coding-system или next-selection-coding-system установлены в кодировку, свойство :mime-charset которой равно x-ctext.
UTF8_STRING в противном случае.
COMPOUND_TEXTЭтот преобразователь выделения возвращает данные выделения в виде строки типа COMPOUND_TEXT.
STRINGЭтот преобразователь выделения возвращает данные выделения в виде строки типа STRING, закодированной в формате ISO-Latin-1.
UTF8_STRINGЭтот преобразователь выделения возвращает данные выделения в формате UTF-8.
text/plaintext/plain;charset=utf-8text/uri-listtext/x-xdnd-usernameXmTRANSFER_SUCCESSXmTRANSFER_FAILUREFILE_DT_NETFILEЭти преобразователи выделения используются для внутренних целей во время операций перетаскивания и недоступны для выделений, отличных от XdndSelection.
TARGETSЭтот преобразователь выделения возвращает список атомов по одному для каждой цели выделения, понимаемой Emacs.
MULTIPLEЭтот преобразователь выделения реализован в коде C и используется для эффективной передачи запросов выделения, которые одновременно указывают несколько целей выделения.
LENGTHЭтот преобразователь выделения возвращает длину данных выделения в байтах.
DELETEЭтот преобразователь выделения используется для внутренних целей во время операций перетаскивания.
FILE_NAMEЭтот преобразователь выделения возвращает имя файла буфера, содержащего данные выделения.
CHARACTER_POSITIONЭтот преобразователь выделения возвращает символьные позиции каждого конца выделения в буфере, содержащем данные выделения.
LINE_NUMBERCOLUMN_NUMBERЭтот преобразователь выделения возвращает номера строк и столбцов каждого конца выделения в буфере, содержащем данные выделения.
OWNER_OSЭтот преобразователь выделения возвращает имя операционной системы, на которой работает Emacs.
HOST_NAMEЭтот преобразователь выделения возвращает полное доменное имя машины, на которой работает Emacs.
USERЭтот преобразователь выделения возвращает имя пользователя учётной записи, под которой работает Emacs.
CLASSNAMEЭти преобразователи выделения возвращают класс ресурсов и имя, используемые Emacs.
INTEGERЭтот преобразователь выделения возвращает целочисленное значение без изменений.
SAVE_TARGETS_EMACS_INTERNALЭти преобразователи выделения используются для внутренних целей.
За исключением INTEGER, все преобразователи выделения ожидают, что данные, предоставленные gui-set-selection, будут одним из следующих:
(beg end buf), где beg и end — это два маркера или наложения, описывающие границы данных выделения в буфере buf.