forked from aburch/simutrans
-
Notifications
You must be signed in to change notification settings - Fork 1
/
clipboard_w32.cc
135 lines (118 loc) · 3.59 KB
/
clipboard_w32.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* Copyright (c) 2010 Knightly
*
* Clipboard functions for copy and paste of text
*
* This file is part of the Simutrans project under the artistic license.
* (see license.txt)
*/
#include <windows.h>
#include <string.h>
#include "simsys.h"
#include "display/simgraph.h"
#include "simdebug.h"
#include "dataobj/translator.h"
#define MAX_SIZE (4096)
static char buffer[MAX_SIZE] = "";
/**
* Copy text to the clipboard
* @param source : pointer to the start of the source text
* @param length : number of character bytes to copy
* @author Knightly
*/
void dr_copy(const char *source, size_t length)
{
const bool has_unicode = translator::get_lang()->utf_encoded;
// for utf-8 strings, convert into utf-16
if( has_unicode ) {
assert( (length<<1)<MAX_SIZE );
utf16 *utf16_buffer = (utf16 *)buffer;
size_t utf16_count = 0;
utf16 char_code;
size_t offset = 0;
while( (char_code=utf8_to_utf16((const utf8*)(source+offset), &offset)) && offset<=length ) {
*utf16_buffer++ = char_code;
++utf16_count;
}
*utf16_buffer = 0;
source = buffer;
length = (utf16_count << 1) + 1;
}
// create a memory block and copy the text
HGLOBAL hText; // handle to the memory block for holding the text
char *pText; // pointer to the start of the memory block
if( (hText=GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,length+1)) && (pText=(char*)GlobalLock(hText)) ) {
while( (length--)>0 ) {
*pText++ = *source++;
}
*pText = 0;
GlobalUnlock(hText);
}
else {
if( hText ) {
GlobalFree(hText);
}
return;
}
// open the clipboard and set the clipboard data
if( OpenClipboard(NULL) ) {
if( EmptyClipboard() ) {
SetClipboardData(has_unicode ? CF_UNICODETEXT : CF_TEXT, hText);
}
CloseClipboard();
}
}
/**
* Paste text from the clipboard
* @param target : pointer to the insertion position in the target text
* @param max_length : maximum number of character bytes which could be inserted
* @return number of character bytes actually inserted -> for cursor advancing
* @author Knightly
*/
size_t dr_paste(char *target, size_t max_length)
{
const bool has_unicode = translator::get_lang()->utf_encoded;
size_t inserted_length = 0;
HGLOBAL hText; // handle to the memory block for holding the text
const char *pText; // pointer to the start of the memory block
if( OpenClipboard(NULL) ) {
if( (hText=GetClipboardData(has_unicode?CF_UNICODETEXT:CF_TEXT)) && (pText=(const char*)GlobalLock(hText)) ) {
// determine the number of bytes to be pasted
if( has_unicode ) {
// convert clipboard text from utf-16 to utf-8
const utf16 *utf16_text = (const utf16 *)pText;
utf8 *utf8_buffer = (utf8 *)buffer;
size_t tmp_length = 0;
size_t byte_count;
while( *utf16_text && tmp_length+(byte_count=utf16_to_utf8(*utf16_text, utf8_buffer))<=max_length ) {
tmp_length += byte_count;
utf8_buffer += byte_count;
++utf16_text;
}
pText = buffer;
max_length = tmp_length;
}
else {
const size_t text_length = strlen(pText);
if( text_length<max_length ) {
max_length = text_length;
}
}
inserted_length = max_length;
// move the text to free up space for inserting the clipboard content
char *target_old_end = target + strlen(target);
char *target_new_end = target_old_end + max_length;
while( target_old_end>=target ) {
*target_new_end-- = *target_old_end--;
}
// insert the clipboard content
while( (max_length--)>0 ) {
*target++ = *pText++;
}
GlobalUnlock(hText);
}
CloseClipboard();
}
// return the inserted length for cursor advancing
return inserted_length;
}