Xpoint
   [напомнить пароль]

Как занести в Clipboard бинарные данные

2004-11-18 16:48:58 [обр] Артем [досье]

Как можно используя javascript/XPCOM занести в clipboard бинарные данные, так чтобы их можно было использовать в других (не XUL) приложениях?
В частности мне нужно при нажатии на картинку скопировать в Clipboard массив из 4 байтов, представляющий идентификатор картинки.

При вызове nsITransferable.setTransferData пытался передавать nsISupportsPRInt64, nsISupportsArray, nsIArray, и даже простой javascript Array, но вне пределов XUL приложения Clipboard как будто не трогали.

Вот один из примеров (последний), в котором я пытался заполнить Clipboard

  var workNum = imageID;

var myArr = new Array();

for(var i=0;i<4; ++i) {

    var b4 = workNum % 256;
    workNum = workNum  >> 8;

    myArr[3-i] = b4;
}

var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
if (!trans) return false;

trans.addDataFlavor("IMAGEID");
trans.setTransferData("IMAGEID",myArr, myArr.length);


var clipid=Components.interfaces.nsIClipboard;
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(clipid);
if (!clip) return false;
clip.setData(trans,null,clipid.kGlobalClipboard);

В Javascript console ошибок нет

спустя 3 часа 31 минуту [обр] Владимир Палант [досье]
Попробуйте закодировать эти байты в строку - String.fromCharCode(myArr[0], myArr[1], myArr[2], myArr[3]).
спустя 3 дня [обр] Артем [досье]

Такой вариант проходит, если учесть, что в результате строка к unicode преобразуется где-то и добавляются лишние 0 байты.
Также возможен и вариант через eval()

  var b4 = (workNum % 256).toString(16);
  workNum = workNum  >> 8;

  var b3 = (workNum % 256).toString(16);
  workNum = workNum  >> 8;

  var b2 = (workNum % 256).toString(16);
  workNum = workNum  >> 8;

  var b1 = (workNum % 256).toString(16);

  if(b4.length < 2) b4 = "0"+b4;
  if(b3.length < 2) b3 = "0"+b3;
  if(b2.length < 2) b2 = "0"+b2;
  if(b1.length < 2) b1 = "0"+b1;

  var e1='"' + "\\u" + b1 + b2 +'"';
  var e2='"' + "\\u" + b3 + b4 +'"';

var copytext=eval(e1)+eval(e2);

var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
if (!str) return false;
str.data=copytext;

trans.addDataFlavor("IMAGEID");
trans.setTransferData("IMAGEID",str,4);

Но при использовании строк в конец в Clipboard неизменно добавляется завершающий \u0000. А его наличие недопустимо для совместимости моего приложения :(

Придется искать другие варианты. Если у кого-нибудь есть идеи - буду рад услышать.
Спасибо!

спустя 22 минуты [обр] Владимир Палант [досье]

Да, JavaScript работает исключительно со строками в Unicode. Но вообще ваш код можно написать гораздо проще и без eval:

var copytext = String.fromCharCode((workNum >> 16) & 0xFFFF, workNum & 0xFFFF);

Нуль в конце строки, конечно, всегда есть, вот только записываться он не должен. Может длина в функции setTransferData() - длина в символах, а не байтах? Тогда trans.setTransferData("IMAGEID",str,2); должен помочь. Надо покопаться в исходниках, иначе долго гадать можно...

спустя 38 минут [обр] Владимир Палант [досье]
Покопался... Получатся, что любые данные преобразовываются в nsISupportsString (с учётом параметра dataLen), после чего эта строка записывается в буфер обмена (уже без учёта dataLen). Боюсь, что от нуля в конце не избавиться - недоделка, система предназначена только для обмена текстовыми данными. Посмотрю, нет ли этого уже на bugzilla.mozilla.org...
спустя 1 час 4 минуты [обр] Владимир Палант [досье]

Не там смотрел. Но результат тот же - Mozilla в данном случае исходит из того, что получил nsISupportedString. Он копирует данные этой строки в буфер обмена, параметр dataLen здесь игнорируется.

В Bugzilla ничего не нашёл.

Powered by POEM™ Engine Copyright © 2002-2005