蛙蛙请教:把一段c算法代码转换成c#代码。
这是一段剪贴板的数据转换算法代码,请帮忙把UTF8ToHtml转换成c#代码,我转了一下,根本不能用。
再帮忙写下注释,简单说一下原理,谢谢。
原文如下:
I was working on a project where I had to paste into textbox HTML, copied from the Browser. A quick search on "HTML Clipboard Format" in MSDN gives you an article that thoroughly explained how HTML is kept in the Clipboard. Unfortunately, this article tells you that it's kept in UTF-8 format without explaining how to convert from UTF-8 back to HTML. So I had do some research on my own.
UTF-8 is the format that allows using Unicode characters in ASCII text by embedding a special token, &#code;, into the text, where the code is Unicode code (in decimal format) for the symbol. For some symbols there are special names. An example " " is " "... You can jump to the specification if you need more examples.
Here is a UTF8ToHtml function, which converts from UTF-8 to HTML. The algorithm is not explained, but you can read more about it here.
//utf8 - pointer to UTF8 formatted text. dwSize - size of UTF8 text; ptr is the pointer to Output buffer.
//The OnClickedPastehtml is the handler for BN_CLICK event of the button in Dialog box. IDC_TEXT is the multiline text box.
void
UTF8ToHtml(BYTE
*
utf8, DWORD dwSize, CHAR
*
ptr )
{
int code;
BYTE *end = utf8 + dwSize;
while( utf8 < end )
{
code = 0;
if( (*utf8 & 0xF0) == 0xF0 )
{
code = (((*utf8)&0x0F) << 18) | (((*(utf8+1))
& 0x7F)<<12) | (((*(utf8+2)) & 0x7F)<<6)
| ((*(utf8+3)) & 0x7F );
utf8+=3;
}
else
{
if( (*utf8 & 0xE0) == 0xE0 )
{
code = (((*utf8)&0x1F) << 12) | (((*(utf8+1))
& 0x7F)<<6 ) | ((*(utf8+2)) & 0x7F );
utf8+=2;
}
else
{
if( (*utf8 & 0xC0) == 0xC0 )
{
code = (((*utf8)&0x3F) << 6) | ((*(utf8+1)) & 0x7F) ;
utf8+=1;
}
}
}
if( code == 0 )
{
*ptr = *utf8;
}
else
{
char s[10];
switch(code)
{
case 160:
strcpy(s, "& ");
break;
case 34:
strcpy(s, "&");
break;
case 36:
strcpy( s, "&&");
break;
case 60:
strcpy( s, "&<");
break;
case 62:
strcpy( s, "&>");
break;
default:
sprintf( s, "&#%d;", code );
break;
}
strcpy( ptr, s );
ptr += strlen(s)-1;
}
utf8++;
ptr++;
}
*ptr = 0;
}
LRESULT CDialog::OnClickedPastehtml( WORD wNotifyCode,
WORD wID,
HWND hWndCtl,
BOOL
&
bHandled)
{
if (!OpenClipboard() )
return 0;
UINT uHtmlFormat = RegisterClipboardFormat("HTML Format");
UINT uFormat = uHtmlFormat;
if( IsClipboardFormatAvailable( uHtmlFormat ) == FALSE )
{
if( IsClipboardFormatAvailable( CF_TEXT ) == FALSE )
return 0;
uFormat = CF_TEXT;
}
HGLOBAL hglb;
LPTSTR lptstr;
hglb = GetClipboardData(uFormat);
if (hglb != NULL)
{
lptstr = (LPTSTR)GlobalLock(hglb);
if (lptstr != NULL)
{
char *ptr1 = strstr( lptstr, "<!--StartFragment-->");
if( ptr1 != 0 )
{
ptr1 += 20;
char * ptr2 = strstr( lptstr, "<!--EndFragment-->");
int iSize = (ptr2 - ptr1);
char * tmp = (char*)_alloca( iSize *2);
UTF8ToHtml((BYTE*)ptr1, iSize, tmp );
//memcpy(tmp, ptr1, iSize );
//tmp[iSize] = 0;
SetDlgItemText(IDC_TEXT, tmp );
}
else
SetDlgItemText(IDC_TEXT, lptstr );
GlobalUnlock(hglb);
}
}
CloseClipboard();
return 0;
}
这是我转换的代码
private
void
FTopMost_DragDrop(
object
sender, DragEventArgs e)
{
strCont = e.Data.GetData(DataFormats.Html, true).ToString();
int start = strCont.IndexOf("<!--StartFragment-->");
int end = strCont.IndexOf("<!--EndFragment-->");
string s = strCont.Substring(start + 20, end - start - 20);
FNewPost f = new FNewPost();
f.HTML = UTF8ToHtml(s);
f.Show();
f.Activate();
}
string
UTF8ToHtml(
string
utf8)
{
string ptr = null;
int code;
for (int i = 0; i < utf8.Length; i++ )
{
code = 0;
if ((utf8[i]) == 0xF0)
{
code = (((utf8[i]) & 0x0F) << 18) | ((((utf8[i] + 1)) & 0x7F) << 12) | ((((utf8[i] + 2)) & 0x7F) << 6) | (((utf8[i] + 3)) & 0x7F);
i += 3;
}
else
{
if ((utf8[i]) == 0xE0)
{
code = (((utf8[i]) & 0x1F) << 12) | ((((utf8[i] + 1)) & 0x7F) << 6) | (((utf8[i] + 2)) & 0x7F);
i += 2;
}
else
{
if ((utf8[i]) == 0xC0)
{
code = (((utf8[i]) & 0x3F) << 6) | (((utf8[i] + 1)) & 0x7F);
i += 1;
}
}
}
if (code == 0)
{
ptr += utf8[i];
}
else
{
string s = null;
switch (code)
{
case 160:
s = "& ";
break;
case 34:
s = "&";
break;
case 36:
s = "&&";
break;
case 60:
s = "&<";
break;
case 62:
s = "&>";
break;
default:
//sprintf( s, "&#%d;", code );
s = "&" + code.ToString();
break;
}
ptr += s;
}
}
return ptr;
}
这是一段剪贴板数据,当然这里没有中文
Version:0.9
StartHTML:71
EndHTML:170
StartFragment:140
EndFragment:160
StartSelection:140
EndSelection:160
<!
DOCTYPE
>
<
HTML
>
<
HEAD
>
<
TITLE
>
The HTML Clipboard
</
TITLE
>
<
BASE
HREF
="http://sample/specs"
>
</
HEAD
>
<
BODY
>
<!--
StartFragment
-->
<
P
>
The Fragment
</
P
>
<!--
EndFragment
-->
</
BODY
>
</
HTML
>
代码是改好了(在zswang的指点下),如下。改动处是“byte[] utf8bytes = Encoding.Default.GetBytes(utf8);”这句。
但问题还是没有解决,我想大概原理是这样的,剪贴板的数据在复制HTML的时候是utf-8的,而windows剪贴板在获取剪贴板数据的时候用默认编码进行了解码,默认编码是根据当前系统的代码页来决定的,所以出来是乱码。所以我们要用默认编码把它编码回去,编码成字节数组,其实这时候是utf-8的数组,不过有些数据已经破坏了,因为操作系统在用默认编码解码UTF-8的时候可能已经丢失数据了,所以再编码回去数据也不全了。我们再用utf-8把编码回去的字节解码,有一部分中文能出来,而有一些中文却出不来,具体的规律我没有研究出来,昨天看了下linux下的utf-8 faq,有些地方还是没看懂,回头再细看。
string
UTF8ToHtml(
string
utf8)
{
string
ptr
=
null
;
try
{
int
code;
byte
[] utf8bytes
=
Encoding.Default.GetBytes(utf8);
for
(
int
i
=
0
; i
<
utf8bytes.Length; i
++
)
{
code
=
0
;
if
((utf8bytes[i]
&
0xF0
)
==
0xF0
)
{
code
=
((utf8bytes[i]
&
0x0F
)
<<
18
)
|
((utf8bytes[i
+
1
]
&
0x7F
)
<<
12
)
|
((utf8bytes[i
+
2
]
&
0x7F
)
<<
6
)
|
(utf8bytes[i
+
3
]
&
0x7F
);
i
+=
3
;
}
else
{
if
((utf8bytes[i]
&
0xE0
)
==
0xE0
)
{
code
=
((utf8bytes[i]
&
0x1F
)
<<
12
)
|
((utf8bytes[i
+
1
]
&
0x7F
)
<<
6
)
|
(utf8bytes[i
+
2
]
&
0x7F
);
i
+=
2
;
}
else
{
if
((utf8bytes[i])
==
0xC0
)
{
code
=
(((utf8bytes[i])
&
0x3F
)
<<
6
)
|
((utf8bytes[i
+
1
])
&
0x7F
);
i
+=
1
;
}
}
}
if
(code
==
0
)
{
ptr
+=
(
char
)utf8bytes[i];
}
else
{
string
s
=
null
;
switch
(code)
{
case
160
:
s
=
"
&
"
;
break
;
case
34
:
s
=
"
&
"
;
break
;
case
36
:
s
=
"
&&
"
;
break
;
case
60
:
s
=
"
&<
"
;
break
;
case
62
:
s
=
"
&>
"
;
break
;
default
:
//
sprintf( s, "&#%d;", code );
s
=
"
&#
"
+
code.ToString()
+
"
;
"
;
break
;
}
ptr
+=
s;
}
}
}
catch
(Exception ex)
{
throw
ex;
}
return
ptr;
}
最后感觉这个思路是错的,这个问题没解,所以换了个思路,在拖拽事件里把推拽的数据重新放入剪贴板,然后在弹出窗口的WebBrowser里用ole命令执行粘贴命令把拖拽的数据粘贴到WebBrowser里,经测试,这样做数据不会丢失,因为从IE里拖动数据到另一个设计模式的HTML文档里,中文不会丢失,所以想到了这个思路,具体看下面代码。
在被拖拽的窗口写以下代码
private
void
FTopMost_DragDrop(
object
sender, DragEventArgs e)
{
Clipboard.SetDataObject(e.Data);
}
新窗口里
private
void
webEdit_DocumentCompleted(
object
sender, WebBrowserDocumentCompletedEventArgs e)
{
webEdit.Document.ExecCommand("Paste", false, null);
}