Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 31b65c1

Browse files
Treat HTML as a text format on the clipboard
... instead of data. This matches the behaviour of the plain text clipboard format and is easier to work with. It also fixes incorrect character encoding assumptions when retrieving the clipboard contents as LiveCode styled text arrays. Data access to HTML on the clipboard is still available via rawClipboardData.
1 parent d759db4 commit 31b65c1

File tree

3 files changed

+97
-64
lines changed

3 files changed

+97
-64
lines changed

engine/src/clipboard.cpp

Lines changed: 70 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -371,14 +371,21 @@ bool MCClipboard::AddLiveCodeStyledText(MCDataRef p_pickled_text)
371371
if (t_success && (t_type_string = m_clipboard->GetKnownTypeString(kMCRawClipboardKnownTypeHTML)) != NULL)
372372
{
373373
// This type is optional as it may not be a faithful representation
374-
MCAutoDataRef t_html(ConvertStyledTextToHTML(p_pickled_text));
374+
MCAutoStringRef t_html(ConvertStyledTextToHTML(p_pickled_text));
375375
if (*t_html != NULL)
376376
{
377-
MCAutoDataRef t_encoded;
378-
t_encoded = m_clipboard->EncodeHTMLFragmentForTransfer(*t_html);
379-
t_success = *t_encoded != nil;
377+
// All platforms accept UTF-8 as an encoding for HTML on the clipboard
378+
MCAutoDataRef t_html_utf8;
379+
t_success = MCStringEncode(*t_html, kMCStringEncodingUTF8, false, &t_html_utf8);
380+
380381
if (t_success)
381-
t_success = t_item->AddRepresentation(t_type_string, *t_encoded);
382+
{
383+
MCAutoDataRef t_encoded;
384+
t_encoded = m_clipboard->EncodeHTMLFragmentForTransfer(*t_html_utf8);
385+
t_success = *t_encoded != nil;
386+
if (t_success)
387+
t_success = t_item->AddRepresentation(t_type_string, *t_encoded);
388+
}
382389
}
383390
}
384391

@@ -404,14 +411,14 @@ bool MCClipboard::AddLiveCodeStyledTextArray(MCArrayRef p_styled_text)
404411
return AddLiveCodeStyledText(*t_pickled_text);
405412
}
406413

407-
bool MCClipboard::AddHTMLText(MCDataRef p_html_data)
414+
bool MCClipboard::AddHTMLText(MCStringRef p_html_string)
408415
{
409416
// Adding HTML to the clipboard is done by converting the HTML to LiveCode's
410417
// internal styled-text format and then adding it to the clipboard in that
411418
// format.
412419
//
413420
// This is a lossy process but preserves legacy behaviour.
414-
MCAutoDataRef t_pickled_text(ConvertHTMLToStyledText(p_html_data));
421+
MCAutoDataRef t_pickled_text(ConvertHTMLToStyledText(p_html_string));
415422
if (*t_pickled_text == NULL)
416423
return false;
417424

@@ -453,10 +460,15 @@ bool MCClipboard::AddRTF(MCDataRef p_rtf)
453460
return t_item->AddRepresentation(t_type_string, p_rtf);
454461
}
455462

456-
bool MCClipboard::AddHTML(MCDataRef p_html)
463+
bool MCClipboard::AddHTML(MCStringRef p_html)
457464
{
458465
AutoLock t_lock(this);
459466

467+
// All platforms support UTF-8 as a text encoding for HTML on the clipboard
468+
MCAutoDataRef t_html_utf8;
469+
if (!MCStringEncode(p_html, kMCStringEncodingUTF8, false, &t_html_utf8))
470+
return false;
471+
460472
// Clear the contents if the clipboard contains external data
461473
if (m_clipboard->IsExternalData())
462474
Clear();
@@ -465,10 +477,10 @@ bool MCClipboard::AddHTML(MCDataRef p_html)
465477
MCAutoRefcounted<MCRawClipboardItem> t_item = GetItem();
466478
if (t_item == NULL)
467479
return false;
468-
480+
469481
// Encode the HTML in the required format for the clipboard
470482
MCAutoDataRef t_encoded;
471-
t_encoded = m_clipboard->EncodeHTMLFragmentForTransfer(p_html);
483+
t_encoded = m_clipboard->EncodeHTMLFragmentForTransfer(*t_html_utf8);
472484
if (*t_encoded == nil)
473485
return false;
474486

@@ -477,7 +489,7 @@ bool MCClipboard::AddHTML(MCDataRef p_html)
477489
if (t_type_string == NULL)
478490
return false;
479491

480-
return t_item->AddRepresentation(t_type_string, p_html);
492+
return t_item->AddRepresentation(t_type_string, *t_encoded);
481493
}
482494

483495
bool MCClipboard::AddPNG(MCDataRef p_png)
@@ -966,21 +978,15 @@ bool MCClipboard::CopyAsLiveCodeStyledText(MCDataRef& r_pickled_text) const
966978
}
967979

968980
// Could not grab as either styled text or RTF. Try with HTML.
969-
MCAutoDataRef t_html;
970-
if (CopyAsData(kMCRawClipboardKnownTypeHTML, &t_html))
981+
MCAutoStringRef t_html;
982+
if (CopyAsHTML(&t_html))
971983
{
972-
MCAutoDataRef t_decodedhtml;
973-
t_decodedhtml.Reset(m_clipboard->DecodeTransferredHTML(*t_html));
974-
975-
if (*t_decodedhtml != nil)
984+
// Convert to LiveCode styled text
985+
MCDataRef t_pickled_text = ConvertHTMLToStyledText(*t_html);
986+
if (t_pickled_text != NULL)
976987
{
977-
// Convert to LiveCode styled text
978-
MCDataRef t_pickled_text = ConvertHTMLToStyledText(*t_decodedhtml);
979-
if (t_pickled_text != NULL)
980-
{
981-
r_pickled_text = t_pickled_text;
982-
return true;
983-
}
988+
r_pickled_text = t_pickled_text;
989+
return true;
984990
}
985991
}
986992

@@ -1036,7 +1042,7 @@ bool MCClipboard::CopyAsRTFText(MCDataRef& r_rtf) const
10361042
return true;
10371043
}
10381044

1039-
bool MCClipboard::CopyAsHTMLText(MCDataRef& r_html) const
1045+
bool MCClipboard::CopyAsHTMLText(MCStringRef& r_html) const
10401046
{
10411047
AutoLock t_lock(this);
10421048

@@ -1046,11 +1052,12 @@ bool MCClipboard::CopyAsHTMLText(MCDataRef& r_html) const
10461052
if (!CopyAsLiveCodeStyledText(&t_pickled_text))
10471053
return false;
10481054

1049-
MCDataRef t_html = ConvertStyledTextToHTML(*t_pickled_text);
1050-
if (t_html == NULL)
1055+
MCAutoStringRef t_html;
1056+
t_html.Give(ConvertStyledTextToHTML(*t_pickled_text));
1057+
if (*t_html == nil)
10511058
return false;
10521059

1053-
r_html = t_html;
1060+
r_html = t_html.Take();
10541061
return true;
10551062
}
10561063

@@ -1059,18 +1066,24 @@ bool MCClipboard::CopyAsRTF(MCDataRef& r_rtf_data) const
10591066
return CopyAsData(kMCRawClipboardKnownTypeRTF, r_rtf_data);
10601067
}
10611068

1062-
bool MCClipboard::CopyAsHTML(MCDataRef& r_html_data) const
1069+
bool MCClipboard::CopyAsHTML(MCStringRef& r_html) const
10631070
{
10641071
MCAutoDataRef t_data;
10651072
if (!CopyAsData(kMCRawClipboardKnownTypeHTML, &t_data))
10661073
return false;
10671074

1068-
MCDataRef t_decoded = nil;
1069-
t_decoded = m_clipboard->DecodeTransferredHTML(*t_data);
1070-
if (t_decoded == nil)
1075+
MCAutoDataRef t_decoded;
1076+
t_decoded.Give(m_clipboard->DecodeTransferredHTML(*t_data));
1077+
if (*t_decoded == nil)
1078+
return false;
1079+
1080+
// Convert the decoded HTML data into a string
1081+
MCStringEncoding t_encoding = GuessHTMLEncoding(*t_decoded);
1082+
MCAutoStringRef t_html_string;
1083+
if (!MCStringDecode(*t_decoded, t_encoding, false, &t_html_string))
10711084
return false;
10721085

1073-
r_html_data = t_decoded;
1086+
r_html = t_html_string.Take();
10741087
return true;
10751088
}
10761089

@@ -1286,7 +1299,7 @@ MCStringRef MCClipboard::ConvertStyledTextToText(MCDataRef p_pickled_text)
12861299
return MCValueRetain(*t_text);
12871300
}
12881301

1289-
MCDataRef MCClipboard::ConvertStyledTextToHTML(MCDataRef p_pickled_text)
1302+
MCStringRef MCClipboard::ConvertStyledTextToHTML(MCDataRef p_pickled_text)
12901303
{
12911304
// Turn the pickled text into a StyledText object
12921305
MCObject *t_object = MCObject::unpickle(p_pickled_text, MCtemplatefield -> getstack());
@@ -1305,8 +1318,14 @@ MCDataRef MCClipboard::ConvertStyledTextToHTML(MCDataRef p_pickled_text)
13051318
delete t_object;
13061319
if (!t_success)
13071320
return NULL;
1308-
1309-
return MCValueRetain(*t_html);
1321+
1322+
// Convert the HTML into a string
1323+
// exportashtmltext always returns native-encoded data (where non-ASCII chars are entity-encoded)
1324+
MCAutoStringRef t_html_string;
1325+
if (!MCStringDecode(*t_html, kMCStringEncodingNative, false, &t_html_string))
1326+
return nil;
1327+
1328+
return t_html_string.Take();
13101329
}
13111330

13121331
MCDataRef MCClipboard::ConvertStyledTextToRTF(MCDataRef p_pickled_text)
@@ -1365,10 +1384,10 @@ MCDataRef MCClipboard::ConvertRTFToStyledText(MCDataRef p_rtf_data)
13651384
return t_pickled_text;
13661385
}
13671386

1368-
MCDataRef MCClipboard::ConvertHTMLToStyledText(MCDataRef p_html_data)
1387+
MCDataRef MCClipboard::ConvertHTMLToStyledText(MCStringRef p_html_string)
13691388
{
13701389
// Turn the HTML into paragraphs
1371-
MCParagraph *t_paragraphs = MCtemplatefield->importhtmltext(p_html_data);
1390+
MCParagraph *t_paragraphs = MCtemplatefield->importhtmltext(p_html_string);
13721391
if (t_paragraphs == NULL)
13731392
return NULL;
13741393

@@ -1510,3 +1529,16 @@ MCClipboard* MCClipboard::CreateSystemDragboard()
15101529
t_dragboard->Clear();
15111530
return t_dragboard;
15121531
}
1532+
1533+
MCStringEncoding MCClipboard::GuessHTMLEncoding(MCDataRef p_html_data)
1534+
{
1535+
// All of our platforms (seem to) use UTF-8 as the text encoding for HTML
1536+
// data transferred via the clipboard. Windows guarantees this; for Mac and
1537+
// Linux the situation is unclear (but various places in the engine seem to
1538+
// assume this anyway).
1539+
//
1540+
// If it turns out that non-UTF-8 HTML gets passed via the clipboard, this
1541+
// function should be updated to detect it if possible.
1542+
1543+
return kMCStringEncodingUTF8;
1544+
}

engine/src/clipboard.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ class MCClipboard :
100100
bool AddLiveCodeStyledText(MCDataRef p_picked_text);
101101
bool AddLiveCodeStyledTextArray(MCArrayRef p_styled_text);
102102
bool AddRTFText(MCDataRef p_rtf_data);
103-
bool AddHTMLText(MCDataRef p_html_data);
103+
bool AddHTMLText(MCStringRef p_html_string);
104104
bool AddRTF(MCDataRef p_rtf_data);
105-
bool AddHTML(MCDataRef p_html_data);
105+
bool AddHTML(MCStringRef p_html_string);
106106
bool AddPNG(MCDataRef p_png);
107107
bool AddGIF(MCDataRef p_gif);
108108
bool AddJPEG(MCDataRef p_jpeg);
@@ -142,10 +142,10 @@ class MCClipboard :
142142
bool CopyAsLiveCodeObjects(MCDataRef& r_objects) const;
143143
bool CopyAsLiveCodeStyledText(MCDataRef& r_pickled_text) const;
144144
bool CopyAsLiveCodeStyledTextArray(MCArrayRef& r_style_array) const;
145-
bool CopyAsRTFText(MCDataRef& r_rtf_data) const; // Round-tripped via a field object
146-
bool CopyAsHTMLText(MCDataRef& r_html_data) const; // Round-tripped via a field object
145+
bool CopyAsRTFText(MCDataRef& r_rtf_data) const; // Round-tripped via a field object
146+
bool CopyAsHTMLText(MCStringRef& r_html_string) const; // Round-tripped via a field object
147147
bool CopyAsRTF(MCDataRef& r_rtf_data) const;
148-
bool CopyAsHTML(MCDataRef& r_html_data) const;
148+
bool CopyAsHTML(MCStringRef& r_html_string) const;
149149
bool CopyAsPNG(MCDataRef& r_png_data) const;
150150
bool CopyAsGIF(MCDataRef& r_gif_data) const;
151151
bool CopyAsJPEG(MCDataRef& r_jpeg_data) const;
@@ -212,10 +212,10 @@ class MCClipboard :
212212
// Various utility functions for format conversion
213213
static MCStringRef ConvertStyledTextToText(MCDataRef p_pickled_text);
214214
static MCDataRef ConvertStyledTextToRTF(MCDataRef p_pickled_text);
215-
static MCDataRef ConvertStyledTextToHTML(MCDataRef p_pickled_text);
215+
static MCStringRef ConvertStyledTextToHTML(MCDataRef p_pickled_text);
216216
static MCArrayRef ConvertStyledTextToStyledTextArray(MCDataRef p_pickled_text);
217217
static MCDataRef ConvertRTFToStyledText(MCDataRef p_rtf_data);
218-
static MCDataRef ConvertHTMLToStyledText(MCDataRef p_html_data);
218+
static MCDataRef ConvertHTMLToStyledText(MCStringRef p_html_string);
219219
static MCDataRef ConvertStyledTextArrayToStyledText(MCArrayRef p_styles);
220220
static MCDataRef ConvertTextToStyledText(MCStringRef p_text);
221221

@@ -225,6 +225,10 @@ class MCClipboard :
225225

226226
// Utility function for adding text representations
227227
bool AddTextToItem(MCRawClipboardItem* p_item, MCStringRef p_string);
228+
229+
// Utility function that examines an HTML fragment to guess its encoding
230+
// Defaults to UTF-8 if it can't be automatically determined
231+
static MCStringEncoding GuessHTMLEncoding(MCDataRef p_html_data);
228232

229233
// Private utility class for clipboard locking
230234
class AutoLock;

engine/src/exec-pasteboard.cpp

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ bool MCPasteboardCopyAsTypeForLegacyClipboard(const MCClipboard* p_clipboard, MC
369369
else if (p_as_type == TRANSFER_TYPE_HTML_TEXT)
370370
{
371371
// Copy as the round-tripped form of HTML
372-
return p_clipboard->CopyAsHTMLText((MCDataRef&)r_value);
372+
return p_clipboard->CopyAsHTMLText((MCStringRef&)r_value);
373373
}
374374
}
375375

@@ -1359,20 +1359,17 @@ void MCPasteboardSetClipboardOrDragDataLegacy(MCExecContext& ctxt, MCNameRef p_i
13591359
{
13601360
// For backwards compatibility, HTML can be added to the
13611361
// clipboard as either data or text.
1362-
if (MCValueGetTypeCode(p_data) == kMCValueTypeCodeData)
1363-
t_success = t_clipboard->AddHTML(static_cast<MCDataRef>(p_data));
1362+
if (MCValueGetTypeCode(p_data) != kMCValueTypeCodeString)
1363+
{
1364+
// Legacy behaviour: treat data as native-encoded text
1365+
MCAutoStringRef t_html;
1366+
t_success = ctxt.ConvertToString(p_data, &t_html);
1367+
if (t_success)
1368+
t_success = t_clipboard->AddHTMLText(*t_html);
1369+
}
13641370
else
13651371
{
1366-
// If it is a string, encode it into the native encoding
1367-
// then add as data. This probably should be ASCII but we've
1368-
// always used the native encoding here...
1369-
MCAutoStringRef t_string;
1370-
MCAutoDataRef t_data;
1371-
t_success = ctxt.ConvertToString(p_data, &t_string);
1372-
if (t_success)
1373-
t_success = MCStringEncode(*t_string, kMCStringEncodingNative, false, &t_data);
1374-
if (t_success)
1375-
t_success = t_clipboard->AddHTML(*t_data);
1372+
t_success = t_clipboard->AddHTMLText(static_cast<MCStringRef>(p_data));
13761373
}
13771374

13781375
break;
@@ -1591,7 +1588,7 @@ void MCPasteboardGetFullClipboardOrDragData(MCExecContext& ctxt, MCNameRef p_ind
15911588
break;
15921589

15931590
case TRANSFER_TYPE_HTML_TEXT:
1594-
p_clipboard->CopyAsHTMLText((MCDataRef&)&t_data);
1591+
p_clipboard->CopyAsHTMLText((MCStringRef&)&t_data);
15951592
break;
15961593

15971594
case TRANSFER_TYPE_STYLED_TEXT:
@@ -1607,7 +1604,7 @@ void MCPasteboardGetFullClipboardOrDragData(MCExecContext& ctxt, MCNameRef p_ind
16071604
break;
16081605

16091606
case TRANSFER_TYPE_HTML:
1610-
p_clipboard->CopyAsHTML((MCDataRef&)&t_data);
1607+
p_clipboard->CopyAsHTML((MCStringRef&)&t_data);
16111608
break;
16121609

16131610
case TRANSFER_TYPE_IMAGE:
@@ -1692,8 +1689,8 @@ void MCPasteboardSetFullClipboardOrDragData(MCExecContext& ctxt, MCNameRef p_ind
16921689
break;
16931690

16941691
case TRANSFER_TYPE_HTML_TEXT:
1695-
if (ctxt.ConvertToData(p_value, &t_data))
1696-
t_success = p_clipboard->AddHTMLText(*t_data);
1692+
if (ctxt.ConvertToString(p_value, &t_string))
1693+
t_success = p_clipboard->AddHTMLText(*t_string);
16971694
break;
16981695

16991696
case TRANSFER_TYPE_RTF_TEXT:
@@ -1717,8 +1714,8 @@ void MCPasteboardSetFullClipboardOrDragData(MCExecContext& ctxt, MCNameRef p_ind
17171714
break;
17181715

17191716
case TRANSFER_TYPE_HTML:
1720-
if (ctxt.ConvertToData(p_value, &t_data))
1721-
t_success = p_clipboard->AddHTML(*t_data);
1717+
if (ctxt.ConvertToString(p_value, &t_string))
1718+
t_success = p_clipboard->AddHTML(*t_string);
17221719
break;
17231720

17241721
case TRANSFER_TYPE_IMAGE:

0 commit comments

Comments
 (0)