Added std:: prefix to Windows build and a few files
BUG=#392
TEST=unittest
REF_BUG=71969651
REF_CL=182312682
REF_TIME=2018-01-18T13:37:36+09:00
REF_TIME_RAW=1516250256 +0900
Hiroyuki Komatsu
6 years ago
70 | 70 | } |
71 | 71 | |
72 | 72 | void MockJNIEnv::ClearArrayMap() { |
73 | for (map<jbyteArray, pair<jsize, jbyte*> >::iterator iter = | |
73 | for (std::map<jbyteArray, pair<jsize, jbyte*> >::iterator iter = | |
74 | 74 | byte_array_map_.begin(); |
75 | 75 | iter != byte_array_map_.end(); ++iter) { |
76 | 76 | delete iter->first; |
133 | 133 | << "_data_wordtype[] = {\n"; |
134 | 134 | output_stream_format_flags_ = output_stream_->flags(); |
135 | 135 | // Set the output format in the form of "0x000012340000ABCD". |
136 | output_stream_->setf(ios_base::hex, ios_base::basefield); | |
137 | output_stream_->setf(ios_base::uppercase); | |
138 | output_stream_->setf(ios_base::right); | |
136 | output_stream_->setf(std::ios_base::hex, std::ios_base::basefield); | |
137 | output_stream_->setf(std::ios_base::uppercase); | |
138 | output_stream_->setf(std::ios_base::right); | |
139 | 139 | output_stream_format_fill_ = output_stream_->fill('0'); |
140 | 140 | // Put the prefix "0x" by ourselves, otherwise it becomes "0X". |
141 | output_stream_->unsetf(ios_base::showbase); | |
141 | output_stream_->unsetf(std::ios_base::showbase); | |
142 | 142 | word_buffer_ = 0; |
143 | 143 | #else |
144 | 144 | *output_stream_ << "const char k" << var_name_base_ << "_data[] =\n"; |
238 | 238 | char * const buf = reinterpret_cast<char *>(&word_buffer_); |
239 | 239 | const size_t kWordSize = sizeof word_buffer_; |
240 | 240 | while (begin < end) { |
241 | size_t output_length = min(static_cast<size_t>(end - begin), | |
242 | kWordSize - output_count_ % kWordSize); | |
241 | size_t output_length = std::min(static_cast<size_t>(end - begin), | |
242 | kWordSize - output_count_ % kWordSize); | |
243 | 243 | for (size_t i = 0; i < output_length; ++i) { |
244 | 244 | buf[output_count_ % kWordSize + i] = *begin++; |
245 | 245 | } |
275 | 275 | |
276 | 276 | #ifdef MOZC_CODEGEN_BYTEARRAY_STREAM_USES_WORD_ARRAY |
277 | 277 | void WriteWordBuffer() { |
278 | *output_stream_ << "0x" << setw(2 * sizeof word_buffer_) << word_buffer_; | |
278 | *output_stream_ << "0x" << std::setw(2 * sizeof word_buffer_) | |
279 | << word_buffer_; | |
279 | 280 | word_buffer_ = 0; |
280 | 281 | } |
281 | 282 | #endif |
286 | 287 | std::basic_ostream<char> *output_stream_; |
287 | 288 | codegenstream::StreamOwner own_output_stream_; |
288 | 289 | #ifdef MOZC_CODEGEN_BYTEARRAY_STREAM_USES_WORD_ARRAY |
289 | ios_base::fmtflags output_stream_format_flags_; | |
290 | std::ios_base::fmtflags output_stream_format_flags_; | |
290 | 291 | char output_stream_format_fill_; |
291 | 292 | #endif |
292 | 293 | |
318 | 319 | // A call to |OpenVarDef| must precede any output to the instance. |
319 | 320 | void OpenVarDef(const string &var_name_base) { |
320 | 321 | if (!streambuf_.OpenVarDef(var_name_base)) { |
321 | this->setstate(ios_base::failbit); | |
322 | this->setstate(std::ios_base::failbit); | |
322 | 323 | } |
323 | 324 | } |
324 | 325 | |
327 | 328 | // unless |OpenVarDef| is called with a different variable name. |
328 | 329 | void CloseVarDef() { |
329 | 330 | if (!streambuf_.CloseVarDef()) { |
330 | this->setstate(ios_base::failbit); | |
331 | this->setstate(std::ios_base::failbit); | |
331 | 332 | } |
332 | 333 | } |
333 | 334 |
141 | 141 | |
142 | 142 | // Returns the pipe name of the GoogleCrashHandler.exe or |
143 | 143 | // GoogleCrashHandler64.exe running as a system user. |
144 | wstring GetCrashHandlerPipeName() { | |
145 | wstring pipe_name = kGoogleCrashHandlerPipePrefix; | |
144 | std::wstring GetCrashHandlerPipeName() { | |
145 | std::wstring pipe_name = kGoogleCrashHandlerPipePrefix; | |
146 | 146 | pipe_name.append(kSystemPrincipalSid); |
147 | 147 | pipe_name.append(kGoogleCrashHandlerPipePostfix); |
148 | 148 | return pipe_name; |
268 | 268 | FileUtil::CreateDirectory(acrashdump_directory); |
269 | 269 | } |
270 | 270 | |
271 | wstring crashdump_directory; | |
271 | std::wstring crashdump_directory; | |
272 | 272 | Util::UTF8ToWide(acrashdump_directory, &crashdump_directory); |
273 | 273 | |
274 | 274 | google_breakpad::ExceptionHandler::FilterCallback filter_callback = |
50 | 50 | } |
51 | 51 | |
52 | 52 | InputFileStream::InputFileStream(const char* filename, |
53 | ios_base::openmode mode) | |
53 | std::ios_base::openmode mode) | |
54 | 54 | : std::istream(nullptr) { |
55 | 55 | init(&string_buffer_); |
56 | 56 | InputFileStream::open(filename, mode); |
57 | 57 | } |
58 | 58 | |
59 | void InputFileStream::open(const char* filename, ios_base::openmode mode) { | |
59 | void InputFileStream::open(const char* filename, std::ios_base::openmode mode) { | |
60 | 60 | string buffer; |
61 | 61 | const bool ret = PepperFileUtil::ReadBinaryFile(filename, &buffer); |
62 | 62 | if (ret) { |
63 | 63 | string_buffer_.sputn(buffer.c_str(), buffer.length()); |
64 | 64 | } else { |
65 | setstate(ios_base::failbit); | |
65 | setstate(std::ios_base::failbit); | |
66 | 66 | } |
67 | 67 | } |
68 | 68 | |
75 | 75 | } |
76 | 76 | |
77 | 77 | OutputFileStream::OutputFileStream(const char* filename, |
78 | ios_base::openmode mode) | |
78 | std::ios_base::openmode mode) | |
79 | 79 | : ostream(), |
80 | 80 | write_done_(false) { |
81 | 81 | init(&string_buffer_); |
86 | 86 | close(); |
87 | 87 | } |
88 | 88 | |
89 | void OutputFileStream::open(const char* filename, ios_base::openmode mode) { | |
89 | void OutputFileStream::open(const char* filename, | |
90 | std::ios_base::openmode mode) { | |
90 | 91 | filename_ = filename; |
91 | 92 | } |
92 | 93 | |
107 | 108 | namespace { |
108 | 109 | |
109 | 110 | #ifdef OS_WIN |
110 | wstring ToPlatformString(const char* filename) { | |
111 | std::wstring ToPlatformString(const char* filename) { | |
111 | 112 | // Since Windows uses UTF-16 for internationalized file names, we should |
112 | 113 | // convert the encoding of the given |filename| from UTF-8 to UTF-16. |
113 | 114 | // NOTE: To avoid circular dependency, |Util::UTF8ToWide| shouldn't be used |
126 | 127 | InputFileStream::InputFileStream() {} |
127 | 128 | |
128 | 129 | InputFileStream::InputFileStream(const char* filename, |
129 | ios_base::openmode mode) { | |
130 | std::ios_base::openmode mode) { | |
130 | 131 | InputFileStream::open(filename, mode); |
131 | 132 | } |
132 | 133 | |
133 | void InputFileStream::open(const char* filename, ios_base::openmode mode) { | |
134 | void InputFileStream::open(const char* filename, std::ios_base::openmode mode) { | |
134 | 135 | std::ifstream::open(ToPlatformString(filename), mode); |
135 | 136 | } |
136 | 137 | |
137 | 138 | OutputFileStream::OutputFileStream() {} |
138 | 139 | |
139 | 140 | OutputFileStream::OutputFileStream(const char* filename, |
140 | ios_base::openmode mode) { | |
141 | std::ios_base::openmode mode) { | |
141 | 142 | OutputFileStream::open(filename, mode); |
142 | 143 | } |
143 | 144 | |
144 | void OutputFileStream::open(const char* filename, ios_base::openmode mode) { | |
145 | void OutputFileStream::open(const char* filename, | |
146 | std::ios_base::openmode mode) { | |
145 | 147 | std::ofstream::open(ToPlatformString(filename), mode); |
146 | 148 | } |
147 | 149 | #endif // MOZC_USE_PEPPER_FILE_IO |
48 | 48 | public: |
49 | 49 | InputFileStream(); |
50 | 50 | explicit InputFileStream(const char* filename, |
51 | ios_base::openmode mode = ios_base::in); | |
51 | std::ios_base::openmode mode = std::ios_base::in); | |
52 | 52 | // Opens the file and reads the all data to string_buffer_. |
53 | void open(const char* filename, ios_base::openmode mode = ios_base::in); | |
53 | void open(const char* filename, ios_base::openmode mode = std::ios_base::in); | |
54 | 54 | // Do nothing. |
55 | 55 | // Note: Error handling after close() is not correctly implemented. |
56 | 56 | // TODO(horo) Implement error handling correctly. |
74 | 74 | public: |
75 | 75 | OutputFileStream(); |
76 | 76 | explicit OutputFileStream(const char* filename, |
77 | ios_base::openmode mode = ios_base::in); | |
77 | std::ios_base::openmode mode = std::ios_base::in); | |
78 | 78 | ~OutputFileStream(); |
79 | 79 | // Sets filename_. |
80 | void open(const char* filename, ios_base::openmode mode = ios_base::in); | |
80 | void open(const char* filename, ios_base::openmode mode = std::ios_base::in); | |
81 | 81 | // Write the data to the file using Pepper FileIO. |
82 | 82 | // Note: Error handling after close() is not correctly implemented. |
83 | 83 | // TODO(horo) Implement error handling correctly. |
106 | 106 | public: |
107 | 107 | InputFileStream(); |
108 | 108 | explicit InputFileStream(const char* filename, |
109 | ios_base::openmode mode = ios_base::in); | |
109 | std::ios_base::openmode mode = std::ios_base::in); | |
110 | 110 | |
111 | 111 | // Opens the specified file. |
112 | 112 | // This function is a wrapper function for the ifstream::open() function |
113 | 113 | // to change the encoding of the specified file name from UTF-8 to its native |
114 | 114 | // one before calling the ifstream::open() function. |
115 | void open(const char* filename, ios_base::openmode mode = ios_base::in); | |
115 | void open(const char* filename, | |
116 | std::ios_base::openmode mode = std::ios_base::in); | |
116 | 117 | |
117 | 118 | // Helper functions to load the entire content of a file into string. |
118 | 119 | void ReadToString(string *s); |
126 | 127 | public: |
127 | 128 | OutputFileStream(); |
128 | 129 | explicit OutputFileStream(const char* filename, |
129 | ios_base::openmode mode = ios_base::out); | |
130 | std::ios_base::openmode mode = std::ios_base::out); | |
130 | 131 | |
131 | 132 | // Opens the specified file. |
132 | 133 | // This function is a wrapper function for the ofstream::open() function |
133 | 134 | // to change the encoding of the specified file name from UTF-8 to its native |
134 | 135 | // one before calling the ofstream::open() function. |
135 | void open(const char* filename, ios_base::openmode mode = ios_base::out); | |
136 | void open(const char* filename, | |
137 | std::ios_base::openmode mode = std::ios_base::out); | |
136 | 138 | |
137 | 139 | private: |
138 | 140 | virtual void UnusedKeyMethod(); // go/definekeymethod |
86 | 86 | if (!FileUtil::FileExists(filename)) { |
87 | 87 | return; |
88 | 88 | } |
89 | wstring wide_filename; | |
89 | std::wstring wide_filename; | |
90 | 90 | Util::UTF8ToWide(filename, &wide_filename); |
91 | 91 | const DWORD kDropAttributes = |
92 | 92 | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY; |
101 | 101 | |
102 | 102 | bool FileUtil::CreateDirectory(const string &path) { |
103 | 103 | #if defined(OS_WIN) |
104 | wstring wide; | |
104 | std::wstring wide; | |
105 | 105 | return (Util::UTF8ToWide(path, &wide) > 0 && |
106 | 106 | ::CreateDirectoryW(wide.c_str(), nullptr) != 0); |
107 | 107 | #elif defined(OS_NACL) // OS_WIN |
113 | 113 | |
114 | 114 | bool FileUtil::RemoveDirectory(const string &dirname) { |
115 | 115 | #ifdef OS_WIN |
116 | wstring wide; | |
116 | std::wstring wide; | |
117 | 117 | return (Util::UTF8ToWide(dirname, &wide) > 0 && |
118 | 118 | ::RemoveDirectoryW(wide.c_str()) != 0); |
119 | 119 | #elif defined(OS_NACL) // OS_WIN |
126 | 126 | bool FileUtil::Unlink(const string &filename) { |
127 | 127 | #ifdef OS_WIN |
128 | 128 | StripWritePreventingAttributesIfExists(filename); |
129 | wstring wide; | |
129 | std::wstring wide; | |
130 | 130 | return (Util::UTF8ToWide(filename, &wide) > 0 && |
131 | 131 | ::DeleteFileW(wide.c_str()) != 0); |
132 | 132 | #elif defined(MOZC_USE_PEPPER_FILE_IO) |
138 | 138 | |
139 | 139 | bool FileUtil::FileExists(const string &filename) { |
140 | 140 | #ifdef OS_WIN |
141 | wstring wide; | |
141 | std::wstring wide; | |
142 | 142 | return (Util::UTF8ToWide(filename, &wide) > 0 && |
143 | 143 | ::GetFileAttributesW(wide.c_str()) != -1); |
144 | 144 | #elif defined(MOZC_USE_PEPPER_FILE_IO) |
151 | 151 | |
152 | 152 | bool FileUtil::DirectoryExists(const string &dirname) { |
153 | 153 | #ifdef OS_WIN |
154 | wstring wide; | |
154 | std::wstring wide; | |
155 | 155 | if (Util::UTF8ToWide(dirname, &wide) <= 0) { |
156 | 156 | return false; |
157 | 157 | } |
170 | 170 | #ifdef OS_WIN |
171 | 171 | namespace { |
172 | 172 | |
173 | bool TransactionalMoveFile(const wstring &from, const wstring &to) { | |
173 | bool TransactionalMoveFile(const std::wstring &from, const std::wstring &to) { | |
174 | 174 | const DWORD kTimeout = 5000; // 5 sec. |
175 | 175 | ScopedHandle handle(::CreateTransaction( |
176 | 176 | nullptr, 0, 0, 0, 0, kTimeout, nullptr)); |
228 | 228 | return false; |
229 | 229 | } |
230 | 230 | |
231 | wstring wfilename; | |
231 | std::wstring wfilename; | |
232 | 232 | Util::UTF8ToWide(filename, &wfilename); |
233 | 233 | |
234 | 234 | const DWORD original_attributes = ::GetFileAttributesW(wfilename.c_str()); |
249 | 249 | } |
250 | 250 | |
251 | 251 | #ifdef OS_WIN |
252 | wstring wto; | |
252 | std::wstring wto; | |
253 | 253 | Util::UTF8ToWide(to, &wto); |
254 | 254 | StripWritePreventingAttributesIfExists(to); |
255 | 255 | #endif // OS_WIN |
270 | 270 | ofs.close(); |
271 | 271 | |
272 | 272 | #ifdef OS_WIN |
273 | wstring wfrom; | |
273 | std::wstring wfrom; | |
274 | 274 | Util::UTF8ToWide(from, &wfrom); |
275 | 275 | ::SetFileAttributesW(wto.c_str(), ::GetFileAttributesW(wfrom.c_str())); |
276 | 276 | #endif // OS_WIN |
301 | 301 | |
302 | 302 | bool FileUtil::AtomicRename(const string &from, const string &to) { |
303 | 303 | #ifdef OS_WIN |
304 | wstring fromw, tow; | |
304 | std::wstring fromw, tow; | |
305 | 305 | Util::UTF8ToWide(from, &fromw); |
306 | 306 | Util::UTF8ToWide(to, &tow); |
307 | 307 | |
384 | 384 | bool FileUtil::GetModificationTime(const string &filename, |
385 | 385 | FileTimeStamp *modified_at) { |
386 | 386 | #if defined (OS_WIN) |
387 | wstring wide; | |
387 | std::wstring wide; | |
388 | 388 | if (!Util::UTF8ToWide(filename, &wide)) { |
389 | 389 | return false; |
390 | 390 | } |
133 | 133 | FILE_ATTRIBUTE_TEMPORARY, |
134 | 134 | }; |
135 | 135 | |
136 | wstring wfilepath; | |
136 | std::wstring wfilepath; | |
137 | 137 | Util::UTF8ToWide(filepath, &wfilepath); |
138 | 138 | for (size_t i = 0; i < arraysize(kTestAttributeList); ++i) { |
139 | 139 | SCOPED_TRACE(Util::StringPrintf("AttributeTest %zd", i)); |
156 | 156 | |
157 | 157 | EXPECT_FALSE(FileUtil::HideFile(filename)); |
158 | 158 | |
159 | wstring wfilename; | |
159 | std::wstring wfilename; | |
160 | 160 | Util::UTF8ToWide(filename.c_str(), &wfilename); |
161 | 161 | |
162 | 162 | CreateTestFile(filename, "test data"); |
266 | 266 | CreateTestFile(from, test_label); |
267 | 267 | |
268 | 268 | const TestData &kData = kTestDataList[i]; |
269 | wstring wfrom, wto; | |
269 | std::wstring wfrom, wto; | |
270 | 270 | Util::UTF8ToWide(from.c_str(), &wfrom); |
271 | 271 | Util::UTF8ToWide(to.c_str(), &wto); |
272 | 272 | EXPECT_NE(FALSE, |
355 | 355 | CreateTestFile(from, test_label); |
356 | 356 | |
357 | 357 | const TestData &kData = kTestDataList[i]; |
358 | wstring wfrom, wto; | |
358 | std::wstring wfrom, wto; | |
359 | 359 | Util::UTF8ToWide(from.c_str(), &wfrom); |
360 | 360 | Util::UTF8ToWide(to.c_str(), &wto); |
361 | 361 | EXPECT_NE(FALSE, |
67 | 67 | // return iter->first; |
68 | 68 | // } |
69 | 69 | // }; |
70 | // vector<pair<int, double> > data; | |
70 | // std::vector<pair<int, double> > data; | |
71 | 71 | // : |
72 | 72 | // // To find the first element whose first is 5. |
73 | 73 | // typedef IteratorAdapter<vector<pair<int, double> >, FirstAdapter> |
74 | 74 | // FirstIterator; |
75 | // vector<pair<int, double> >::const_iterator iter = | |
75 | // std::vector<pair<int, double> >::const_iterator iter = | |
76 | 76 | // find(FirstIterator(data.begin()), FirstIterator(data.end()), 5).base(); |
77 | 77 | // |
78 | 78 | // Below, two utilities are provided, AdapterBase class and MakeIteratorAdapter |
85 | 85 | // return iter->first; |
86 | 86 | // } |
87 | 87 | // }; |
88 | // vector<pair<int, double> > data; | |
89 | // vector<pair<int, double> >::const_iterator iter = | |
88 | // std::vector<pair<int, double> > data; | |
89 | // std::vector<pair<int, double> >::const_iterator iter = | |
90 | 90 | // find(MakeIteratorAdapter(data.begin(), FirstAdapter()), |
91 | 91 | // MakeIteratorAdapter(data.end(), FirstAdapter()), 5).base(); |
92 | 92 | // |
80 | 80 | return false; |
81 | 81 | } |
82 | 82 | |
83 | wstring filename_wide; | |
83 | std::wstring filename_wide; | |
84 | 84 | if (Util::UTF8ToWide(filename, &filename_wide) <= 0) { |
85 | 85 | return false; |
86 | 86 | } |
76 | 76 | return; |
77 | 77 | } |
78 | 78 | #ifdef OS_WIN |
79 | wstring wfilename; | |
79 | std::wstring wfilename; | |
80 | 80 | Util::UTF8ToWide(filename_, &wfilename); |
81 | 81 | if (!::SetFileAttributesW(wfilename.c_str(), FILE_ATTRIBUTE_NORMAL)) { |
82 | 82 | LOG(ERROR) << "Cannot make writable: " << filename_; |
769 | 769 | |
770 | 770 | bool PepperFileSystem::SyncMmapToFile() { |
771 | 771 | scoped_lock lock(&mutex_); |
772 | for (set<MmapSyncInterface*>::iterator it = mmap_set_.begin(); | |
772 | for (std::set<MmapSyncInterface*>::iterator it = mmap_set_.begin(); | |
773 | 773 | it != mmap_set_.end(); ++it) { |
774 | 774 | (*it)->SyncToFile(); |
775 | 775 | } |
90 | 90 | } |
91 | 91 | |
92 | 92 | #ifdef OS_WIN |
93 | wstring wurl; | |
93 | std::wstring wurl; | |
94 | 94 | Util::UTF8ToWide(url, &wurl); |
95 | 95 | return WinUtil::ShellExecuteInSystemDir(L"open", wurl.c_str(), nullptr); |
96 | 96 | #endif |
111 | 111 | bool Process::SpawnProcess(const string &path, |
112 | 112 | const string& arg, size_t *pid) { |
113 | 113 | #ifdef OS_WIN |
114 | wstring wpath; | |
114 | std::wstring wpath; | |
115 | 115 | Util::UTF8ToWide(path, &wpath); |
116 | 116 | wpath = L"\"" + wpath + L"\""; |
117 | 117 | if (!arg.empty()) { |
118 | wstring warg; | |
118 | std::wstring warg; | |
119 | 119 | Util::UTF8ToWide(arg, &warg); |
120 | 120 | wpath += L" "; |
121 | 121 | wpath += warg; |
93 | 93 | return false; |
94 | 94 | } |
95 | 95 | |
96 | wstring wfilename; | |
96 | std::wstring wfilename; | |
97 | 97 | Util::UTF8ToWide(filename_, &wfilename); |
98 | 98 | const DWORD kAttribute = |
99 | 99 | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | |
160 | 160 | |
161 | 161 | private: |
162 | 162 | Mutex mutex_; |
163 | map<string, string> lock_map_; | |
163 | std::map<string, string> lock_map_; | |
164 | 164 | DISALLOW_COPY_AND_ASSIGN(NamedLockManager); |
165 | 165 | }; |
166 | 166 |
218 | 218 | // See http://b/2301066 for details. |
219 | 219 | const string user_dir = SystemUtil::GetUserProfileDirectory(); |
220 | 220 | |
221 | wstring dir; | |
221 | std::wstring dir; | |
222 | 222 | Util::UTF8ToWide(user_dir, &dir); |
223 | 223 | ScopedHandle dir_handle(::CreateFile(dir.c_str(), |
224 | 224 | READ_CONTROL | WRITE_DAC, |
150 | 150 | if (FAILED(result)) { |
151 | 151 | return result; |
152 | 152 | } |
153 | wstring path = config; | |
154 | const wstring::size_type local_pos = path.find(L"\\Packages\\"); | |
155 | if (local_pos == wstring::npos) { | |
153 | std::wstring path = config; | |
154 | const std::wstring::size_type local_pos = path.find(L"\\Packages\\"); | |
155 | if (local_pos == std::wstring::npos) { | |
156 | 156 | return E_FAIL; |
157 | 157 | } |
158 | 158 | path.erase(local_pos); |
183 | 183 | return E_UNEXPECTED; |
184 | 184 | } |
185 | 185 | |
186 | wstring wpath = task_mem_buffer; | |
186 | std::wstring wpath = task_mem_buffer; | |
187 | 187 | ::CoTaskMemFree(task_mem_buffer); |
188 | 188 | |
189 | 189 | string path; |
52 | 52 | |
53 | 53 | HKEY created_key; |
54 | 54 | bool reg_create_key_ex_called; |
55 | wstring created_key_path; | |
55 | std::wstring created_key_path; | |
56 | 56 | bool reg_set_value_ex_called; |
57 | wstring written_value_name; | |
58 | wstring written_value; | |
57 | std::wstring written_value_name; | |
58 | std::wstring written_value; | |
59 | 59 | DWORD written_type; |
60 | 60 | bool reg_close_key_called; |
61 | 61 | }; |
62 | 62 | |
63 | 63 | static void SetUpTestCase() { |
64 | vector<WinAPITestHelper::HookRequest> requests; | |
64 | std::vector<WinAPITestHelper::HookRequest> requests; | |
65 | 65 | requests.push_back( |
66 | 66 | DEFINE_HOOK("advapi32.dll", RegCreateKeyExW, HookRegCreateKeyExW)); |
67 | 67 | requests.push_back( |
110 | 110 | call_result_->reg_set_value_ex_called = true; |
111 | 111 | call_result_->written_value_name = value_name; |
112 | 112 | call_result_->written_value = |
113 | wstring(reinterpret_cast<const wchar_t*>(data)); | |
113 | std::wstring(reinterpret_cast<const wchar_t*>(data)); | |
114 | 114 | call_result_->written_type = type; |
115 | 115 | return ERROR_SUCCESS; |
116 | 116 | } |
802 | 802 | return num_chars; |
803 | 803 | } |
804 | 804 | |
805 | int Util::UTF8ToWide(StringPiece input, wstring *output) { | |
805 | int Util::UTF8ToWide(StringPiece input, std::wstring *output) { | |
806 | 806 | const size_t output_length = WideCharsLen(input); |
807 | 807 | if (output_length == 0) { |
808 | 808 | return 0; |
836 | 836 | return result; |
837 | 837 | } |
838 | 838 | |
839 | int Util::WideToUTF8(const wstring &input, string *output) { | |
839 | int Util::WideToUTF8(const std::wstring &input, string *output) { | |
840 | 840 | return WideToUTF8(input.c_str(), output); |
841 | 841 | } |
842 | 842 | #endif // OS_WIN |
228 | 228 | static size_t WideCharsLen(StringPiece src); |
229 | 229 | // Converts the encoding of the specified string from UTF-8 to UTF-16, and |
230 | 230 | // vice versa. |
231 | static int UTF8ToWide(StringPiece input, wstring *output); | |
231 | static int UTF8ToWide(StringPiece input, std::wstring *output); | |
232 | 232 | static int WideToUTF8(const wchar_t *input, string *output); |
233 | static int WideToUTF8(const wstring &input, string *output); | |
233 | static int WideToUTF8(const std::wstring &input, string *output); | |
234 | 234 | #endif // OS_WIN |
235 | 235 | |
236 | 236 | // Extracts a substring range, where both start and length are in terms of |
1647 | 1647 | |
1648 | 1648 | TEST(UtilTest, UTF8ToWide) { |
1649 | 1649 | const string input_utf8 = "abc"; |
1650 | wstring output_wide; | |
1650 | std::wstring output_wide; | |
1651 | 1651 | Util::UTF8ToWide(input_utf8, &output_wide); |
1652 | 1652 | |
1653 | 1653 | string output_utf8; |
1663 | 1663 | string output_utf8; |
1664 | 1664 | Util::WideToUTF8(input_wide, &output_utf8); |
1665 | 1665 | |
1666 | wstring output_wide; | |
1666 | std::wstring output_wide; | |
1667 | 1667 | Util::UTF8ToWide(output_utf8, &output_wide); |
1668 | 1668 | |
1669 | 1669 | EXPECT_EQ("\360\240\256\237", output_utf8); |
48 | 48 | } |
49 | 49 | |
50 | 50 | #ifdef OS_WIN |
51 | wstring Version::GetMozcVersionW() { | |
52 | wstring version; | |
51 | std::wstring Version::GetMozcVersionW() { | |
52 | std::wstring version; | |
53 | 53 | Util::UTF8ToWide(version::kMozcVersion, &version); |
54 | 54 | return version; |
55 | 55 | } |
40 | 40 | static string GetMozcVersion(); |
41 | 41 | |
42 | 42 | #ifdef OS_WIN |
43 | // Get current mozc version (former called MOZC_VERSION) by wstring | |
44 | static wstring GetMozcVersionW(); | |
43 | // Get current mozc version (former called MOZC_VERSION) by std::wstring | |
44 | static std::wstring GetMozcVersionW(); | |
45 | 45 | #endif |
46 | 46 | |
47 | 47 | static int GetMozcVersionMajor(); |
98 | 98 | class HookTargetInfo { |
99 | 99 | public: |
100 | 100 | explicit HookTargetInfo( |
101 | const vector<WinAPITestHelper::HookRequest> &requests) { | |
101 | const std::vector<WinAPITestHelper::HookRequest> &requests) { | |
102 | 102 | for (size_t i = 0; i < requests.size(); ++i) { |
103 | 103 | const auto &request = requests[i]; |
104 | 104 | HMODULE module_handle = nullptr; |
147 | 147 | } |
148 | 148 | |
149 | 149 | private: |
150 | map<string, map<FunctionPointer, FunctionPointer>> info_; | |
150 | std::map<string, std::map<FunctionPointer, FunctionPointer>> info_; | |
151 | 151 | }; |
152 | 152 | |
153 | 153 | class PortableExecutableImage { |
285 | 285 | |
286 | 286 | class WinAPITestHelper::RestoreInfo { |
287 | 287 | public: |
288 | vector<ThunkRewriter> rewrites; | |
288 | std::vector<ThunkRewriter> rewrites; | |
289 | 289 | }; |
290 | 290 | |
291 | 291 | WinAPITestHelper::HookRequest::HookRequest( |
299 | 299 | // static |
300 | 300 | WinAPITestHelper::RestoreInfoHandle WinAPITestHelper::DoHook( |
301 | 301 | HMODULE target_module, |
302 | const vector<WinAPITestHelper::HookRequest> &requests) { | |
302 | const std::vector<WinAPITestHelper::HookRequest> &requests) { | |
303 | 303 | const HookTargetInfo target_info(requests); |
304 | 304 | |
305 | 305 | // Following code skips some data validations as this code is only used in |
50 | 50 | // recovery from such cases are not trivial. |
51 | 51 | // |
52 | 52 | // Example: |
53 | // vector<WinAPITestHelper::HookRequest> requests; | |
53 | // std::vector<WinAPITestHelper::HookRequest> requests; | |
54 | 54 | // requests.push_back( |
55 | 55 | // DEFINE_HOOK("kernel32.dll", GetVersion, GetVersionHook)); |
56 | 56 | // requests.push_back( |
100 | 100 | // Since this code is designed to be used in unit test, this method |
101 | 101 | // causes critical failure and stops execution when something fails. |
102 | 102 | static RestoreInfoHandle DoHook(HMODULE target_module, |
103 | const vector<HookRequest> &requests); | |
103 | const std::vector<HookRequest> &requests); | |
104 | 104 | |
105 | 105 | // Restores the API hooks. |backup_info| cannot be used after this method |
106 | 106 | // is called. |
40 | 40 | } |
41 | 41 | |
42 | 42 | TEST(WinAPITestHelperTest, BasicTest) { |
43 | vector<WinAPITestHelper::HookRequest> requests; | |
43 | std::vector<WinAPITestHelper::HookRequest> requests; | |
44 | 44 | requests.push_back(DEFINE_HOOK("kernel32.dll", GetVersion, GetVersionHook)); |
45 | 45 | |
46 | 46 | auto restore_info = WinAPITestHelper::DoHook( |
177 | 177 | DISALLOW_COPY_AND_ASSIGN(ScopedLocalFreeInvoker); |
178 | 178 | }; |
179 | 179 | |
180 | bool GetUserSid(wstring *token_user_sid, wstring *token_primary_group_sid) { | |
180 | bool GetUserSid(std::wstring *token_user_sid, | |
181 | std::wstring *token_primary_group_sid) { | |
181 | 182 | DCHECK(token_user_sid); |
182 | 183 | DCHECK(token_primary_group_sid); |
183 | 184 | token_user_sid->clear(); |
219 | 220 | return true; |
220 | 221 | } |
221 | 222 | |
222 | wstring Allow(const wstring &access_right, const wstring &account_sid) { | |
223 | return (wstring(L"(") + SDDL_ACCESS_ALLOWED + L";;" + | |
223 | std::wstring Allow(const std::wstring &access_right, | |
224 | const std::wstring &account_sid) { | |
225 | return (std::wstring(L"(") + SDDL_ACCESS_ALLOWED + L";;" + | |
224 | 226 | access_right + L";;;" + account_sid + L")"); |
225 | 227 | } |
226 | 228 | |
227 | wstring Deny(const wstring &access_right, const wstring &account_sid) { | |
228 | return (wstring(L"(") + SDDL_ACCESS_DENIED + L";;" + | |
229 | std::wstring Deny(const std::wstring &access_right, | |
230 | const std::wstring &account_sid) { | |
231 | return (std::wstring(L"(") + SDDL_ACCESS_DENIED + L";;" + | |
229 | 232 | access_right + L";;;" + account_sid + L")"); |
230 | 233 | } |
231 | 234 | |
232 | wstring MandatoryLevel(const wstring &mandatory_label, | |
233 | const wstring &integrity_levels) { | |
234 | return (wstring(L"(") + SDDL_MANDATORY_LABEL + L";;" + | |
235 | std::wstring MandatoryLevel(const std::wstring &mandatory_label, | |
236 | const std::wstring &integrity_levels) { | |
237 | return (std::wstring(L"(") + SDDL_MANDATORY_LABEL + L";;" + | |
235 | 238 | mandatory_label + L";;;" + integrity_levels + L")"); |
236 | 239 | } |
237 | 240 | |
257 | 260 | |
258 | 261 | } // namespace |
259 | 262 | |
260 | wstring WinSandbox::GetSDDL(ObjectSecurityType shareble_object_type, | |
261 | const wstring &token_user_sid, | |
262 | const wstring &token_primary_group_sid, | |
263 | std::wstring WinSandbox::GetSDDL(ObjectSecurityType shareble_object_type, | |
264 | const std::wstring &token_user_sid, | |
265 | const std::wstring &token_primary_group_sid, | |
263 | 266 | bool is_windows_8_or_later) { |
264 | 267 | // See http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/e92502b1-0b9f-4e02-9d72-e4e47e924a8f/ |
265 | 268 | // for how to acess named objects from an AppContainer. |
266 | 269 | |
267 | wstring dacl; | |
268 | wstring sacl; | |
270 | std::wstring dacl; | |
271 | std::wstring sacl; | |
269 | 272 | switch (shareble_object_type) { |
270 | 273 | case WinSandbox::kSharablePipe: |
271 | 274 | // Strip implicit owner rights |
402 | 405 | break; |
403 | 406 | } |
404 | 407 | |
405 | wstring sddl; | |
408 | std::wstring sddl; | |
406 | 409 | // Owner SID |
407 | 410 | sddl += ((SDDL_OWNER SDDL_DELIMINATOR) + token_user_sid); |
408 | 411 | // Primary Group SID |
436 | 439 | return reinterpret_cast<SID*>(const_cast<BYTE*>(sid_)); |
437 | 440 | } |
438 | 441 | |
439 | wstring Sid::GetName() const { | |
442 | std::wstring Sid::GetName() const { | |
440 | 443 | wchar_t *ptr = nullptr; |
441 | 444 | Sid temp_sid(GetPSID()); |
442 | 445 | ConvertSidToStringSidW(temp_sid.GetPSID(), &ptr); |
443 | wstring name = ptr; | |
446 | std::wstring name = ptr; | |
444 | 447 | ::LocalFree(ptr); |
445 | 448 | return name; |
446 | 449 | } |
447 | 450 | |
448 | wstring Sid::GetAccountName() const { | |
451 | std::wstring Sid::GetAccountName() const { | |
449 | 452 | wchar_t *ptr = nullptr; |
450 | 453 | DWORD name_size = 0; |
451 | 454 | DWORD domain_name_size = 0; |
461 | 464 | unique_ptr<wchar_t[]> name_buffer(new wchar_t[name_size]); |
462 | 465 | ::LookupAccountSid(nullptr, temp_sid.GetPSID(), name_buffer.get(), |
463 | 466 | &name_size, nullptr, &domain_name_size, &name_use); |
464 | return wstring(L"/") + name_buffer.get(); | |
467 | return std::wstring(L"/") + name_buffer.get(); | |
465 | 468 | } |
466 | 469 | unique_ptr<wchar_t[]> name_buffer(new wchar_t[name_size]); |
467 | 470 | unique_ptr<wchar_t[]> domain_name_buffer(new wchar_t[domain_name_size]); |
468 | 471 | ::LookupAccountSid(nullptr, temp_sid.GetPSID(), name_buffer.get(), &name_size, |
469 | 472 | domain_name_buffer.get(), &domain_name_size, &name_use); |
470 | const wstring domain_name = wstring(domain_name_buffer.get()); | |
471 | const wstring user_name = wstring(name_buffer.get()); | |
473 | const std::wstring domain_name = std::wstring(domain_name_buffer.get()); | |
474 | const std::wstring user_name = std::wstring(name_buffer.get()); | |
472 | 475 | return domain_name + L"/" + user_name; |
473 | 476 | } |
474 | 477 | |
476 | 479 | bool WinSandbox::MakeSecurityAttributes( |
477 | 480 | ObjectSecurityType shareble_object_type, |
478 | 481 | SECURITY_ATTRIBUTES *security_attributes) { |
479 | wstring token_user_sid; | |
480 | wstring token_primary_group_sid; | |
482 | std::wstring token_user_sid; | |
483 | std::wstring token_primary_group_sid; | |
481 | 484 | if (!GetUserSid(&token_user_sid, &token_primary_group_sid)) { |
482 | 485 | return false; |
483 | 486 | } |
484 | 487 | |
485 | const wstring &sddl = GetSDDL( | |
488 | const std::wstring &sddl = GetSDDL( | |
486 | 489 | shareble_object_type, token_user_sid, token_primary_group_sid, |
487 | 490 | SystemUtil::IsWindows8OrLater()); |
488 | 491 | |
810 | 813 | const string &arg, |
811 | 814 | const SecurityInfo &info, |
812 | 815 | DWORD *pid) { |
813 | wstring wpath; | |
816 | std::wstring wpath; | |
814 | 817 | Util::UTF8ToWide(path, &wpath); |
815 | 818 | wpath = L"\"" + wpath + L"\""; |
816 | 819 | if (!arg.empty()) { |
817 | wstring warg; | |
820 | std::wstring warg; | |
818 | 821 | Util::UTF8ToWide(arg, &warg); |
819 | 822 | wpath += L" "; |
820 | 823 | wpath += warg; |
923 | 926 | }; |
924 | 927 | |
925 | 928 | // Returns all the 'TokenGroups' information of the specified |token_handle|. |
926 | vector<SidAndAttributes> GetAllTokenGroups(HANDLE token_handle) { | |
927 | vector<SidAndAttributes> result; | |
929 | std::vector<SidAndAttributes> GetAllTokenGroups(HANDLE token_handle) { | |
930 | std::vector<SidAndAttributes> result; | |
928 | 931 | ScopedTokenInfo<TokenGroups, TOKEN_GROUPS> all_token_groups(token_handle); |
929 | 932 | if (all_token_groups.get() == nullptr) { |
930 | 933 | return result; |
937 | 940 | return result; |
938 | 941 | } |
939 | 942 | |
940 | vector<SidAndAttributes> FilterByHavingAttribute( | |
941 | const vector<SidAndAttributes> &source, DWORD attribute) { | |
942 | vector<SidAndAttributes> result; | |
943 | std::vector<SidAndAttributes> FilterByHavingAttribute( | |
944 | const std::vector<SidAndAttributes> &source, DWORD attribute) { | |
945 | std::vector<SidAndAttributes> result; | |
943 | 946 | for (size_t i = 0; i < source.size(); ++i) { |
944 | 947 | if (source[i].HasAttribute(attribute)) { |
945 | 948 | result.push_back(source[i]); |
948 | 951 | return result; |
949 | 952 | } |
950 | 953 | |
951 | vector<SidAndAttributes> FilterByNotHavingAttribute( | |
952 | const vector<SidAndAttributes> &source, DWORD attribute) { | |
953 | vector<SidAndAttributes> result; | |
954 | std::vector<SidAndAttributes> FilterByNotHavingAttribute( | |
955 | const std::vector<SidAndAttributes> &source, DWORD attribute) { | |
956 | std::vector<SidAndAttributes> result; | |
954 | 957 | for (size_t i = 0; i < source.size(); ++i) { |
955 | 958 | if (!source[i].HasAttribute(attribute)) { |
956 | 959 | result.push_back(source[i]); |
960 | 963 | } |
961 | 964 | |
962 | 965 | template <size_t NumExceptions> |
963 | vector<Sid> FilterSidExceptFor( | |
964 | const vector<SidAndAttributes> &source_sids, | |
966 | std::vector<Sid> FilterSidExceptFor( | |
967 | const std::vector<SidAndAttributes> &source_sids, | |
965 | 968 | const WELL_KNOWN_SID_TYPE (&exception_sids)[NumExceptions]) { |
966 | vector<Sid> result; | |
969 | std::vector<Sid> result; | |
967 | 970 | // find logon_sid. |
968 | 971 | for (size_t i = 0; i < source_sids.size(); ++i) { |
969 | 972 | bool in_the_exception_list = false; |
985 | 988 | } |
986 | 989 | |
987 | 990 | template <size_t NumExceptions> |
988 | vector<LUID> FilterPrivilegesExceptFor( | |
989 | const vector<LUID_AND_ATTRIBUTES> &source_privileges, | |
991 | std::vector<LUID> FilterPrivilegesExceptFor( | |
992 | const std::vector<LUID_AND_ATTRIBUTES> &source_privileges, | |
990 | 993 | const wchar_t *(&exception_privileges)[NumExceptions]) { |
991 | vector<LUID> result; | |
994 | std::vector<LUID> result; | |
992 | 995 | for (size_t i = 0; i < source_privileges.size(); ++i) { |
993 | 996 | bool in_the_exception_list = false; |
994 | 997 | for (size_t j = 0; j < NumExceptions; ++j) { |
1019 | 1022 | return Optional<SidAndAttributes>(SidAndAttributes(sid, attributes)); |
1020 | 1023 | } |
1021 | 1024 | |
1022 | vector<LUID_AND_ATTRIBUTES> GetPrivileges(HANDLE token) { | |
1023 | vector<LUID_AND_ATTRIBUTES> result; | |
1025 | std::vector<LUID_AND_ATTRIBUTES> GetPrivileges(HANDLE token) { | |
1026 | std::vector<LUID_AND_ATTRIBUTES> result; | |
1024 | 1027 | ScopedTokenInfo<TokenPrivileges, TOKEN_PRIVILEGES> token_privileges(token); |
1025 | 1028 | if (token_privileges.get() == nullptr) { |
1026 | 1029 | return result; |
1036 | 1039 | bool CreateRestrictedTokenImpl(HANDLE effective_token, |
1037 | 1040 | WinSandbox::TokenLevel security_level, |
1038 | 1041 | ScopedHandle *restricted_token) { |
1039 | const vector<Sid> sids_to_disable = | |
1042 | const std::vector<Sid> sids_to_disable = | |
1040 | 1043 | WinSandbox::GetSidsToDisable(effective_token, security_level); |
1041 | const vector<LUID> privileges_to_disable = | |
1044 | const std::vector<LUID> privileges_to_disable = | |
1042 | 1045 | WinSandbox::GetPrivilegesToDisable(effective_token, security_level); |
1043 | const vector<Sid> sids_to_restrict = | |
1046 | const std::vector<Sid> sids_to_restrict = | |
1044 | 1047 | WinSandbox::GetSidsToRestrict(effective_token, security_level); |
1045 | 1048 | |
1046 | 1049 | if ((sids_to_disable.size() == 0) && |
1061 | 1064 | } |
1062 | 1065 | |
1063 | 1066 | unique_ptr<SID_AND_ATTRIBUTES[]> sids_to_disable_array; |
1064 | vector<Sid> sids_to_disable_array_buffer = sids_to_disable; | |
1067 | std::vector<Sid> sids_to_disable_array_buffer = sids_to_disable; | |
1065 | 1068 | { |
1066 | 1069 | const size_t size = sids_to_disable.size(); |
1067 | 1070 | if (size > 0) { |
1087 | 1090 | } |
1088 | 1091 | |
1089 | 1092 | unique_ptr<SID_AND_ATTRIBUTES[]> sids_to_restrict_array; |
1090 | vector<Sid> sids_to_restrict_array_buffer = sids_to_restrict; | |
1093 | std::vector<Sid> sids_to_restrict_array_buffer = sids_to_restrict; | |
1091 | 1094 | { |
1092 | 1095 | const size_t size = sids_to_restrict.size(); |
1093 | 1096 | if (size > 0) { |
1202 | 1205 | |
1203 | 1206 | } // namespace |
1204 | 1207 | |
1205 | vector<Sid> WinSandbox::GetSidsToDisable(HANDLE effective_token, | |
1208 | std::vector<Sid> WinSandbox::GetSidsToDisable(HANDLE effective_token, | |
1206 | 1209 | TokenLevel security_level) { |
1207 | const vector<SidAndAttributes> all_token_groups = | |
1210 | const std::vector<SidAndAttributes> all_token_groups = | |
1208 | 1211 | GetAllTokenGroups(effective_token); |
1209 | 1212 | const Optional<SidAndAttributes> current_user_sid = |
1210 | 1213 | GetUserSid(effective_token); |
1211 | const vector<SidAndAttributes> normal_tokens = | |
1214 | const std::vector<SidAndAttributes> normal_tokens = | |
1212 | 1215 | FilterByNotHavingAttribute( |
1213 | 1216 | FilterByNotHavingAttribute(all_token_groups, SE_GROUP_LOGON_ID), |
1214 | 1217 | SE_GROUP_INTEGRITY); |
1215 | 1218 | |
1216 | vector<Sid> sids_to_disable; | |
1219 | std::vector<Sid> sids_to_disable; | |
1217 | 1220 | switch (security_level) { |
1218 | 1221 | case USER_UNPROTECTED: |
1219 | 1222 | case USER_RESTRICTED_SAME_ACCESS: |
1255 | 1258 | return sids_to_disable; |
1256 | 1259 | } |
1257 | 1260 | |
1258 | vector<LUID> WinSandbox::GetPrivilegesToDisable(HANDLE effective_token, | |
1261 | std::vector<LUID> WinSandbox::GetPrivilegesToDisable(HANDLE effective_token, | |
1259 | 1262 | TokenLevel security_level ) { |
1260 | const vector<LUID_AND_ATTRIBUTES> all_privileges = | |
1263 | const std::vector<LUID_AND_ATTRIBUTES> all_privileges = | |
1261 | 1264 | GetPrivileges(effective_token); |
1262 | 1265 | |
1263 | vector<LUID> privileges_to_disable; | |
1266 | std::vector<LUID> privileges_to_disable; | |
1264 | 1267 | switch (security_level) { |
1265 | 1268 | case USER_UNPROTECTED: |
1266 | 1269 | case USER_RESTRICTED_SAME_ACCESS: |
1289 | 1292 | return privileges_to_disable; |
1290 | 1293 | } |
1291 | 1294 | |
1292 | vector<Sid> WinSandbox::GetSidsToRestrict(HANDLE effective_token, | |
1295 | std::vector<Sid> WinSandbox::GetSidsToRestrict(HANDLE effective_token, | |
1293 | 1296 | TokenLevel security_level) { |
1294 | const vector<SidAndAttributes> all_token_groups = | |
1297 | const std::vector<SidAndAttributes> all_token_groups = | |
1295 | 1298 | GetAllTokenGroups(effective_token); |
1296 | 1299 | const Optional<SidAndAttributes> current_user_sid = |
1297 | 1300 | GetUserSid(effective_token); |
1298 | const vector<SidAndAttributes> token_logon_session = | |
1301 | const std::vector<SidAndAttributes> token_logon_session = | |
1299 | 1302 | FilterByHavingAttribute(all_token_groups, SE_GROUP_LOGON_ID); |
1300 | 1303 | |
1301 | vector<Sid> sids_to_restrict; | |
1304 | std::vector<Sid> sids_to_restrict; | |
1302 | 1305 | switch (security_level) { |
1303 | 1306 | case USER_UNPROTECTED: |
1304 | 1307 | sids_to_restrict.clear(); |
1307 | 1310 | if (current_user_sid.has_value()) { |
1308 | 1311 | sids_to_restrict.push_back(current_user_sid.value().sid()); |
1309 | 1312 | } |
1310 | const vector<SidAndAttributes> tokens = | |
1313 | const std::vector<SidAndAttributes> tokens = | |
1311 | 1314 | FilterByNotHavingAttribute(all_token_groups, SE_GROUP_INTEGRITY); |
1312 | 1315 | for (size_t i = 0; i < tokens.size(); ++i) { |
1313 | 1316 | sids_to_restrict.push_back(tokens[i].sid()); |
1430 | 1433 | } |
1431 | 1434 | |
1432 | 1435 | bool WinSandbox::EnsureAllApplicationPackagesPermisssion( |
1433 | const wstring &file_name) { | |
1436 | const std::wstring &file_name) { | |
1434 | 1437 | // Get "All Application Packages" group SID. |
1435 | 1438 | const ATL::CSid all_application_packages( |
1436 | 1439 | Sid(WinBuiltinAnyPackageSid).GetPSID()); |
48 | 48 | explicit Sid(WELL_KNOWN_SID_TYPE type); |
49 | 49 | const SID *GetPSID() const; |
50 | 50 | SID *GetPSID(); |
51 | wstring GetName() const; | |
52 | wstring GetAccountName() const; | |
51 | std::wstring GetName() const; | |
52 | std::wstring GetAccountName() const; | |
53 | 53 | |
54 | 54 | private: |
55 | 55 | BYTE sid_[SECURITY_MAX_SID_SIZE]; |
160 | 160 | // |security_level|. These methods emulates CreateRestrictedToken |
161 | 161 | // method in the Chromium sandbox library. |
162 | 162 | // http://src.chromium.org/viewvc/chrome/trunk/src/sandbox/src/restricted_token_utils.cc?view=markup |
163 | static vector<Sid> GetSidsToDisable(HANDLE effective_token, | |
163 | static std::vector<Sid> GetSidsToDisable(HANDLE effective_token, | |
164 | 164 | TokenLevel security_level); |
165 | static vector<LUID> GetPrivilegesToDisable(HANDLE effective_token, | |
165 | static std::vector<LUID> GetPrivilegesToDisable(HANDLE effective_token, | |
166 | 166 | TokenLevel security_level); |
167 | static vector<Sid> GetSidsToRestrict(HANDLE effective_token, | |
167 | static std::vector<Sid> GetSidsToRestrict(HANDLE effective_token, | |
168 | 168 | TokenLevel security_level); |
169 | 169 | |
170 | 170 | // Returns true if a restricted token handle is successfully assigned into |
191 | 191 | // - FILE_EXECUTE |
192 | 192 | // - READ_CONTROL |
193 | 193 | // - SYNCHRONIZE |
194 | static bool EnsureAllApplicationPackagesPermisssion(const wstring &file_name); | |
194 | static bool EnsureAllApplicationPackagesPermisssion( | |
195 | const std::wstring &file_name); | |
195 | 196 | |
196 | 197 | protected: |
197 | 198 | // Returns SDDL for given |shareble_object_type|. |
198 | 199 | // This method is placed here for unit testing. |
199 | static wstring GetSDDL(ObjectSecurityType shareble_object_type, | |
200 | const wstring &token_user_sid, | |
201 | const wstring &token_primary_group_sid, | |
200 | static std::wstring GetSDDL(ObjectSecurityType shareble_object_type, | |
201 | const std::wstring &token_user_sid, | |
202 | const std::wstring &token_primary_group_sid, | |
202 | 203 | bool is_windows_8_or_later); |
203 | 204 | |
204 | 205 | private: |
44 | 44 | DISALLOW_IMPLICIT_CONSTRUCTORS(TestableWinSandbox); |
45 | 45 | }; |
46 | 46 | |
47 | void VerifySidContained(const vector<Sid> sids, | |
47 | void VerifySidContained(const std::vector<Sid> sids, | |
48 | 48 | WELL_KNOWN_SID_TYPE expected_well_known_sid) { |
49 | 49 | Sid expected_sid(expected_well_known_sid); |
50 | 50 | for (size_t i = 0; i < sids.size(); ++i) { |
63 | 63 | &process_token_ret); |
64 | 64 | ScopedHandle process_token(process_token_ret); |
65 | 65 | |
66 | const vector<Sid> lockdown = WinSandbox::GetSidsToDisable( | |
66 | const std::vector<Sid> lockdown = WinSandbox::GetSidsToDisable( | |
67 | 67 | process_token.get(), WinSandbox::USER_LOCKDOWN); |
68 | const vector<Sid> restricted = WinSandbox::GetSidsToDisable( | |
68 | const std::vector<Sid> restricted = WinSandbox::GetSidsToDisable( | |
69 | 69 | process_token.get(), WinSandbox::USER_RESTRICTED); |
70 | const vector<Sid> limited = WinSandbox::GetSidsToDisable( | |
70 | const std::vector<Sid> limited = WinSandbox::GetSidsToDisable( | |
71 | 71 | process_token.get(), WinSandbox::USER_LIMITED); |
72 | const vector<Sid> interactive = WinSandbox::GetSidsToDisable( | |
72 | const std::vector<Sid> interactive = WinSandbox::GetSidsToDisable( | |
73 | 73 | process_token.get(), WinSandbox::USER_INTERACTIVE); |
74 | const vector<Sid> non_admin = WinSandbox::GetSidsToDisable( | |
74 | const std::vector<Sid> non_admin = WinSandbox::GetSidsToDisable( | |
75 | 75 | process_token.get(), WinSandbox::USER_NON_ADMIN); |
76 | const vector<Sid> restricted_same_access = WinSandbox::GetSidsToDisable( | |
76 | const std::vector<Sid> restricted_same_access = WinSandbox::GetSidsToDisable( | |
77 | 77 | process_token.get(), WinSandbox::USER_RESTRICTED_SAME_ACCESS); |
78 | const vector<Sid> unprotect = WinSandbox::GetSidsToDisable( | |
78 | const std::vector<Sid> unprotect = WinSandbox::GetSidsToDisable( | |
79 | 79 | process_token.get(), WinSandbox::USER_UNPROTECTED); |
80 | 80 | |
81 | 81 | EXPECT_TRUE(restricted.size() == lockdown.size()); |
96 | 96 | &process_token_ret); |
97 | 97 | ScopedHandle process_token(process_token_ret); |
98 | 98 | |
99 | const vector<LUID> lockdown = WinSandbox::GetPrivilegesToDisable( | |
99 | const std::vector<LUID> lockdown = WinSandbox::GetPrivilegesToDisable( | |
100 | 100 | process_token.get(), WinSandbox::USER_LOCKDOWN); |
101 | const vector<LUID> restricted = WinSandbox::GetPrivilegesToDisable( | |
101 | const std::vector<LUID> restricted = WinSandbox::GetPrivilegesToDisable( | |
102 | 102 | process_token.get(), WinSandbox::USER_RESTRICTED); |
103 | const vector<LUID> limited = WinSandbox::GetPrivilegesToDisable( | |
103 | const std::vector<LUID> limited = WinSandbox::GetPrivilegesToDisable( | |
104 | 104 | process_token.get(), WinSandbox::USER_LIMITED); |
105 | const vector<LUID> interactive = WinSandbox::GetPrivilegesToDisable( | |
105 | const std::vector<LUID> interactive = WinSandbox::GetPrivilegesToDisable( | |
106 | 106 | process_token.get(), WinSandbox::USER_INTERACTIVE); |
107 | const vector<LUID> non_admin = WinSandbox::GetPrivilegesToDisable( | |
107 | const std::vector<LUID> non_admin = WinSandbox::GetPrivilegesToDisable( | |
108 | 108 | process_token.get(), WinSandbox::USER_NON_ADMIN); |
109 | const vector<LUID> restricted_same_access = | |
109 | const std::vector<LUID> restricted_same_access = | |
110 | 110 | WinSandbox::GetPrivilegesToDisable( |
111 | 111 | process_token.get(), WinSandbox::USER_RESTRICTED_SAME_ACCESS); |
112 | const vector<LUID> unprotect = WinSandbox::GetPrivilegesToDisable( | |
112 | const std::vector<LUID> unprotect = WinSandbox::GetPrivilegesToDisable( | |
113 | 113 | process_token.get(), WinSandbox::USER_UNPROTECTED); |
114 | 114 | |
115 | 115 | EXPECT_EQ(0, restricted_same_access.size()); |
122 | 122 | &process_token_ret); |
123 | 123 | ScopedHandle process_token(process_token_ret); |
124 | 124 | |
125 | const vector<Sid> lockdown = WinSandbox::GetSidsToRestrict( | |
125 | const std::vector<Sid> lockdown = WinSandbox::GetSidsToRestrict( | |
126 | 126 | process_token.get(), WinSandbox::USER_LOCKDOWN); |
127 | const vector<Sid> restricted = WinSandbox::GetSidsToRestrict( | |
127 | const std::vector<Sid> restricted = WinSandbox::GetSidsToRestrict( | |
128 | 128 | process_token.get(), WinSandbox::USER_RESTRICTED); |
129 | const vector<Sid> limited = WinSandbox::GetSidsToRestrict( | |
129 | const std::vector<Sid> limited = WinSandbox::GetSidsToRestrict( | |
130 | 130 | process_token.get(), WinSandbox::USER_LIMITED); |
131 | const vector<Sid> interactive = WinSandbox::GetSidsToRestrict( | |
131 | const std::vector<Sid> interactive = WinSandbox::GetSidsToRestrict( | |
132 | 132 | process_token.get(), WinSandbox::USER_INTERACTIVE); |
133 | const vector<Sid> non_admin = WinSandbox::GetSidsToRestrict( | |
133 | const std::vector<Sid> non_admin = WinSandbox::GetSidsToRestrict( | |
134 | 134 | process_token.get(), WinSandbox::USER_NON_ADMIN); |
135 | const vector<Sid> restricted_same_access = WinSandbox::GetSidsToRestrict( | |
135 | const std::vector<Sid> restricted_same_access = WinSandbox::GetSidsToRestrict( | |
136 | 136 | process_token.get(), WinSandbox::USER_RESTRICTED_SAME_ACCESS); |
137 | const vector<Sid> unprotect = WinSandbox::GetSidsToRestrict( | |
137 | const std::vector<Sid> unprotect = WinSandbox::GetSidsToRestrict( | |
138 | 138 | process_token.get(), WinSandbox::USER_UNPROTECTED); |
139 | 139 | |
140 | 140 | EXPECT_EQ(1, lockdown.size()); |
148 | 148 | const wchar_t kDummyUserSID[] = L"S-8"; |
149 | 149 | const wchar_t kDummyGroupSID[] = L"S-9"; |
150 | 150 | |
151 | wstring GetSDDLForVista(WinSandbox::ObjectSecurityType type) { | |
151 | std::wstring GetSDDLForVista(WinSandbox::ObjectSecurityType type) { | |
152 | 152 | return TestableWinSandbox::GetSDDL( |
153 | 153 | type, kDummyUserSID, kDummyGroupSID, false); |
154 | 154 | } |
155 | 155 | |
156 | wstring GetSDDLForWin8(WinSandbox::ObjectSecurityType type) { | |
156 | std::wstring GetSDDLForWin8(WinSandbox::ObjectSecurityType type) { | |
157 | 157 | return TestableWinSandbox::GetSDDL( |
158 | 158 | type, kDummyUserSID, kDummyGroupSID, true); |
159 | 159 | } |
85 | 85 | |
86 | 86 | } // namespace |
87 | 87 | |
88 | HMODULE WinUtil::LoadSystemLibrary(const wstring &base_filename) { | |
89 | wstring fullpath = SystemUtil::GetSystemDir(); | |
88 | HMODULE WinUtil::LoadSystemLibrary(const std::wstring &base_filename) { | |
89 | std::wstring fullpath = SystemUtil::GetSystemDir(); | |
90 | 90 | fullpath += L"\\"; |
91 | 91 | fullpath += base_filename; |
92 | 92 | |
102 | 102 | return module; |
103 | 103 | } |
104 | 104 | |
105 | HMODULE WinUtil::LoadMozcLibrary(const wstring &base_filename) { | |
106 | wstring fullpath; | |
105 | HMODULE WinUtil::LoadMozcLibrary(const std::wstring &base_filename) { | |
106 | std::wstring fullpath; | |
107 | 107 | Util::UTF8ToWide(SystemUtil::GetServerDirectory(), &fullpath); |
108 | 108 | fullpath += L"\\"; |
109 | 109 | fullpath += base_filename; |
120 | 120 | return module; |
121 | 121 | } |
122 | 122 | |
123 | HMODULE WinUtil::GetSystemModuleHandle(const wstring &base_filename) { | |
124 | wstring fullpath = SystemUtil::GetSystemDir(); | |
123 | HMODULE WinUtil::GetSystemModuleHandle(const std::wstring &base_filename) { | |
124 | std::wstring fullpath = SystemUtil::GetSystemDir(); | |
125 | 125 | fullpath += L"\\"; |
126 | 126 | fullpath += base_filename; |
127 | 127 | |
137 | 137 | } |
138 | 138 | |
139 | 139 | HMODULE WinUtil::GetSystemModuleHandleAndIncrementRefCount( |
140 | const wstring &base_filename) { | |
141 | wstring fullpath = SystemUtil::GetSystemDir(); | |
140 | const std::wstring &base_filename) { | |
141 | std::wstring fullpath = SystemUtil::GetSystemDir(); | |
142 | 142 | fullpath += L"\\"; |
143 | 143 | fullpath += base_filename; |
144 | 144 | |
181 | 181 | } |
182 | 182 | |
183 | 183 | bool WinUtil::SystemEqualString( |
184 | const wstring &lhs, const wstring &rhs, bool ignore_case) { | |
184 | const std::wstring &lhs, const std::wstring &rhs, bool ignore_case) { | |
185 | 185 | // We assume a string instance never contains NUL character in principle. |
186 | 186 | // So we will raise an error to notify the unexpected situation in debug |
187 | 187 | // builds. In production, however, we will admit such an instance and |
188 | 188 | // silently trim it at the first NUL character. |
189 | const wstring::size_type lhs_null_pos = lhs.find_first_of(L'\0'); | |
190 | const wstring::size_type rhs_null_pos = rhs.find_first_of(L'\0'); | |
189 | const std::wstring::size_type lhs_null_pos = lhs.find_first_of(L'\0'); | |
190 | const std::wstring::size_type rhs_null_pos = rhs.find_first_of(L'\0'); | |
191 | 191 | DCHECK_EQ(lhs.npos, lhs_null_pos) |
192 | 192 | << "|lhs| should not contain NUL character."; |
193 | 193 | DCHECK_EQ(rhs.npos, rhs_null_pos) |
194 | 194 | << "|rhs| should not contain NUL character."; |
195 | const wstring &lhs_null_trimmed = lhs.substr(0, lhs_null_pos); | |
196 | const wstring &rhs_null_trimmed = rhs.substr(0, rhs_null_pos); | |
195 | const std::wstring &lhs_null_trimmed = lhs.substr(0, lhs_null_pos); | |
196 | const std::wstring &rhs_null_trimmed = rhs.substr(0, rhs_null_pos); | |
197 | 197 | |
198 | 198 | const int compare_result = ::CompareStringOrdinal( |
199 | 199 | lhs_null_trimmed.data(), lhs_null_trimmed.size(), |
417 | 417 | } |
418 | 418 | |
419 | 419 | bool WinUtil::GetFileSystemInfoFromPath( |
420 | const wstring &path, BY_HANDLE_FILE_INFORMATION *info) { | |
420 | const std::wstring &path, BY_HANDLE_FILE_INFORMATION *info) { | |
421 | 421 | // no read access is required. |
422 | 422 | ScopedHandle handle(::CreateFileW( |
423 | 423 | path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
432 | 432 | return !!::GetFileInformationByHandle(handle.get(), info); |
433 | 433 | } |
434 | 434 | |
435 | bool WinUtil::AreEqualFileSystemObject(const wstring &left_path, | |
436 | const wstring &right_path) { | |
435 | bool WinUtil::AreEqualFileSystemObject(const std::wstring &left_path, | |
436 | const std::wstring &right_path) { | |
437 | 437 | BY_HANDLE_FILE_INFORMATION left_info = {}; |
438 | 438 | if (!GetFileSystemInfoFromPath(left_path, &left_info)) { |
439 | 439 | return false; |
446 | 446 | (left_info.nFileIndexHigh == right_info.nFileIndexHigh); |
447 | 447 | } |
448 | 448 | |
449 | bool WinUtil::GetNtPath(const wstring &dos_path, wstring *nt_path) { | |
449 | bool WinUtil::GetNtPath(const std::wstring &dos_path, std::wstring *nt_path) { | |
450 | 450 | if (nt_path == nullptr) { |
451 | 451 | return false; |
452 | 452 | } |
483 | 483 | return true; |
484 | 484 | } |
485 | 485 | |
486 | bool WinUtil::GetProcessInitialNtPath(DWORD pid, wstring *nt_path) { | |
486 | bool WinUtil::GetProcessInitialNtPath(DWORD pid, std::wstring *nt_path) { | |
487 | 487 | if (nt_path == nullptr) { |
488 | 488 | return false; |
489 | 489 | } |
46 | 46 | // If the function succeeds, the return value is a handle to the module. |
47 | 47 | // You should call FreeLibrary with the handle. |
48 | 48 | // If the function fails, the return value is NULL. |
49 | static HMODULE LoadSystemLibrary(const wstring &base_filename); | |
49 | static HMODULE LoadSystemLibrary(const std::wstring &base_filename); | |
50 | 50 | |
51 | 51 | // Load a DLL which has the specified base-name and is located in the |
52 | 52 | // Mozc server directory. |
53 | 53 | // If the function succeeds, the return value is a handle to the module. |
54 | 54 | // You should call FreeLibrary with the handle. |
55 | 55 | // If the function fails, the return value is NULL. |
56 | static HMODULE LoadMozcLibrary(const wstring &base_filename); | |
56 | static HMODULE LoadMozcLibrary(const std::wstring &base_filename); | |
57 | 57 | |
58 | 58 | // If a DLL which has the specified base-name and located in the system |
59 | 59 | // directory is loaded in the caller process, retrieve its module handle. |
61 | 61 | // without incrementing its reference count so that you should not call |
62 | 62 | // FreeLibrary with the handle. |
63 | 63 | // If the function fails, the return value is NULL. |
64 | static HMODULE GetSystemModuleHandle(const wstring &base_filename); | |
64 | static HMODULE GetSystemModuleHandle(const std::wstring &base_filename); | |
65 | 65 | |
66 | 66 | // A variant ot GetSystemModuleHandle except that this method increments |
67 | 67 | // reference count of the target DLL. |
68 | 68 | static HMODULE GetSystemModuleHandleAndIncrementRefCount( |
69 | const wstring &base_filename); | |
69 | const std::wstring &base_filename); | |
70 | 70 | |
71 | 71 | // Retrieve whether the calling thread hold loader lock or not. |
72 | 72 | // Return true if the state is retrieved successfully. |
86 | 86 | // Although this function ignores the rest part of given string when NUL |
87 | 87 | // character is found, you should not pass such a string in principle. |
88 | 88 | static bool SystemEqualString( |
89 | const wstring &lhs, const wstring &rhs, bool ignore_case); | |
89 | const std::wstring &lhs, const std::wstring &rhs, bool ignore_case); | |
90 | 90 | |
91 | 91 | // Returns true if succeeds to determine whether the current process has |
92 | 92 | // a process token which seems to be one for service process. Otherwise, |
123 | 123 | |
124 | 124 | // Returns true if |info| is filled with a valid file information that |
125 | 125 | // describes |path|. |path| can be a directory or a file. |
126 | static bool GetFileSystemInfoFromPath(const wstring &path, | |
126 | static bool GetFileSystemInfoFromPath(const std::wstring &path, | |
127 | 127 | BY_HANDLE_FILE_INFORMATION *info); |
128 | 128 | |
129 | 129 | // Returns true if |left_path| and |right_path| are the same file system |
130 | 130 | // object. This method takes hard-link into consideration. |
131 | 131 | // Returns false if either |left_path| or |right_path| does not exist even |
132 | 132 | // when |left_path| == |right_path|. |
133 | static bool AreEqualFileSystemObject(const wstring &left_path, | |
134 | const wstring &right_path); | |
133 | static bool AreEqualFileSystemObject(const std::wstring &left_path, | |
134 | const std::wstring &right_path); | |
135 | 135 | |
136 | 136 | // Returns true if the file or directory specified by |dos_path| exists and |
137 | 137 | // its NT path is retrieved as |nt_path|. This function can work only on |
138 | 138 | // Vista and later. |
139 | static bool GetNtPath(const wstring &dos_path, wstring *nt_path); | |
139 | static bool GetNtPath(const std::wstring &dos_path, std::wstring *nt_path); | |
140 | 140 | |
141 | 141 | // Returns true if the process specified by |pid| exists and its *initial* |
142 | 142 | // NT path is retrieved as |nt_path|. Note that even when the process path is |
143 | 143 | // renamed after the process is launched, the *initial* path is retrieved. |
144 | 144 | // This is important when MSI changes paths of executables. |
145 | static bool GetProcessInitialNtPath(DWORD pid, wstring *nt_path); | |
145 | static bool GetProcessInitialNtPath(DWORD pid, std::wstring *nt_path); | |
146 | 146 | |
147 | 147 | // Returns true if input settings is shared among applications on Windows 8. |
148 | 148 | // Returns false otherwise. |
37 | 37 | |
38 | 38 | namespace { |
39 | 39 | |
40 | bool LooksLikeNtPath(const wstring &nt_path) { | |
40 | bool LooksLikeNtPath(const std::wstring &nt_path) { | |
41 | 41 | const wchar_t kPrefix[] = L"\\Device\\"; |
42 | 42 | |
43 | return nt_path.find(kPrefix) != wstring::npos; | |
43 | return nt_path.find(kPrefix) != std::wstring::npos; | |
44 | 44 | } |
45 | 45 | |
46 | 46 | } // namespace |
156 | 156 | TEST(WinUtilTest, SystemEqualStringTestForNUL) { |
157 | 157 | { |
158 | 158 | const wchar_t kTestBuffer[] = L"abc"; |
159 | const wstring test_string1(kTestBuffer); | |
160 | const wstring test_string2(kTestBuffer, | |
159 | const std::wstring test_string1(kTestBuffer); | |
160 | const std::wstring test_string2(kTestBuffer, | |
161 | 161 | kTestBuffer + arraysize(kTestBuffer)); |
162 | 162 | |
163 | 163 | EXPECT_EQ(3, test_string1.size()); |
169 | 169 | } |
170 | 170 | { |
171 | 171 | const wchar_t kTestBuffer[] = L"abc\0def"; |
172 | const wstring test_string1(kTestBuffer); | |
173 | const wstring test_string2(kTestBuffer, | |
172 | const std::wstring test_string1(kTestBuffer); | |
173 | const std::wstring test_string2(kTestBuffer, | |
174 | 174 | kTestBuffer + arraysize(kTestBuffer)); |
175 | 175 | |
176 | 176 | EXPECT_EQ(3, test_string1.size()); |
184 | 184 | #endif // DEBUG |
185 | 185 | |
186 | 186 | TEST(WinUtilTest, AreEqualFileSystemObjectTest) { |
187 | const wstring system_dir = SystemUtil::GetSystemDir(); | |
188 | const wstring notepad = system_dir + L"\\notepad.exe"; | |
189 | const wstring notepad_with_prefix = L"\\\\?\\" + notepad; | |
187 | const std::wstring system_dir = SystemUtil::GetSystemDir(); | |
188 | const std::wstring notepad = system_dir + L"\\notepad.exe"; | |
189 | const std::wstring notepad_with_prefix = L"\\\\?\\" + notepad; | |
190 | 190 | const wchar_t kThisFileNeverExists[] = L"/this/file/never/exists"; |
191 | 191 | |
192 | 192 | EXPECT_TRUE(WinUtil::AreEqualFileSystemObject(system_dir, system_dir)) |
203 | 203 | } |
204 | 204 | |
205 | 205 | TEST(WinUtilTest, GetNtPath) { |
206 | const wstring system_dir = SystemUtil::GetSystemDir(); | |
207 | const wstring notepad = system_dir + L"\\notepad.exe"; | |
206 | const std::wstring system_dir = SystemUtil::GetSystemDir(); | |
207 | const std::wstring notepad = system_dir + L"\\notepad.exe"; | |
208 | 208 | const wchar_t kThisFileNeverExists[] = L"/this/file/never/exists"; |
209 | 209 | |
210 | wstring nt_system_dir; | |
210 | std::wstring nt_system_dir; | |
211 | 211 | EXPECT_TRUE(WinUtil::GetNtPath(system_dir, &nt_system_dir)) |
212 | 212 | << "Can work against a directory."; |
213 | 213 | EXPECT_TRUE(LooksLikeNtPath(nt_system_dir)); |
215 | 215 | EXPECT_FALSE(WinUtil::GetNtPath(system_dir, nullptr)) |
216 | 216 | << "Must fail against a NULL argument."; |
217 | 217 | |
218 | wstring nt_notepad; | |
218 | std::wstring nt_notepad; | |
219 | 219 | EXPECT_TRUE(WinUtil::GetNtPath(notepad, &nt_notepad)) |
220 | 220 | << "Can work against a file."; |
221 | 221 | EXPECT_TRUE(LooksLikeNtPath(nt_notepad)); |
222 | 222 | |
223 | 223 | EXPECT_TRUE(nt_system_dir != nt_notepad); |
224 | 224 | |
225 | wstring nt_not_exists = L"foo"; | |
225 | std::wstring nt_not_exists = L"foo"; | |
226 | 226 | EXPECT_FALSE(WinUtil::GetNtPath(kThisFileNeverExists, &nt_not_exists)) |
227 | 227 | << "Must fail against non-exist file."; |
228 | 228 | EXPECT_TRUE(nt_not_exists.empty()) |
230 | 230 | } |
231 | 231 | |
232 | 232 | TEST(WinUtilTest, GetProcessInitialNtPath) { |
233 | wstring nt_path; | |
233 | std::wstring nt_path; | |
234 | 234 | EXPECT_TRUE(WinUtil::GetProcessInitialNtPath(::GetCurrentProcessId(), |
235 | 235 | &nt_path)); |
236 | 236 | EXPECT_TRUE(LooksLikeNtPath(nt_path)); |
403 | 403 | void GetPosList(Json::Value *response) { |
404 | 404 | (*response)["event"]["posList"] = Json::Value(Json::arrayValue); |
405 | 405 | Json::Value *pos_list = &(*response)["event"]["posList"]; |
406 | vector<string> tmp_pos_vec; | |
406 | std::vector<string> tmp_pos_vec; | |
407 | 407 | user_pos_->GetPOSList(&tmp_pos_vec); |
408 | 408 | for (int i = 0; i < tmp_pos_vec.size(); ++i) { |
409 | 409 | (*pos_list)[i] = Json::Value(Json::objectValue); |
864 | 864 | if (mode == "administration_dialog") { |
865 | 865 | #ifdef OS_WIN |
866 | 866 | const string &path = mozc::SystemUtil::GetToolPath(); |
867 | wstring wpath; | |
867 | std::wstring wpath; | |
868 | 868 | Util::UTF8ToWide(path, &wpath); |
869 | 869 | wpath = L"\"" + wpath + L"\""; |
870 | 870 | // Run administration dialog with UAC. |
283 | 283 | |
284 | 284 | #ifdef OS_WIN |
285 | 285 | // Reset the file attributes since it may contain FILE_ATTRIBUTE_READONLY. |
286 | wstring wdest_path; | |
286 | std::wstring wdest_path; | |
287 | 287 | Util::UTF8ToWide(dest_path, &wdest_path); |
288 | 288 | ::SetFileAttributesW(wdest_path.c_str(), FILE_ATTRIBUTE_NORMAL); |
289 | 289 | #endif // OS_WIN |
74 | 74 | HKEY dummy = NULL; |
75 | 75 | HKEY &result = (result_key != NULL ? *result_key : dummy); |
76 | 76 | if (HKEY_CURRENT_USER == key) { |
77 | if (wstring(kOmahaUsageKey) == sub_key) { | |
77 | if (std::wstring(kOmahaUsageKey) == sub_key) { | |
78 | 78 | result = kHKCU_ClientState; |
79 | 79 | return true; |
80 | 80 | } |
81 | 81 | } else if (HKEY_LOCAL_MACHINE == key) { |
82 | if (wstring(kOmahaUsageKey) == sub_key) { | |
82 | if (std::wstring(kOmahaUsageKey) == sub_key) { | |
83 | 83 | result = kHKLM_ClientState; |
84 | 84 | return true; |
85 | } else if (wstring(kOmahaUsageKeyForEveryone) == sub_key) { | |
85 | } else if (std::wstring(kOmahaUsageKeyForEveryone) == sub_key) { | |
86 | 86 | result = kHKLM_ClientStateMedium; |
87 | 87 | return true; |
88 | 88 | } |
137 | 137 | }; |
138 | 138 | typedef PropertySelector<Id> Property; |
139 | 139 | RegistryEmulator() { |
140 | vector<WinAPITestHelper::HookRequest> requests; | |
140 | std::vector<WinAPITestHelper::HookRequest> requests; | |
141 | 141 | requests.push_back( |
142 | 142 | DEFINE_HOOK("advapi32.dll", RegCreateKeyExW, TestRegCreateKeyExW)); |
143 | 143 | requests.push_back( |
228 | 228 | static LSTATUS WINAPI TestRegSetValueExW( |
229 | 229 | HKEY key, LPCWSTR value_name, DWORD reserved, DWORD type, |
230 | 230 | const BYTE *data, DWORD num_data) { |
231 | if (type != REG_DWORD || wstring(kSendStatsName) != value_name) { | |
231 | if (type != REG_DWORD || std::wstring(kSendStatsName) != value_name) { | |
232 | 232 | // Do nothing for other cases. |
233 | 233 | return ERROR_SUCCESS; |
234 | 234 | } |
251 | 251 | static LSTATUS WINAPI TestRegQueryValueExW( |
252 | 252 | HKEY key, LPCWSTR value_name, LPDWORD reserved, LPDWORD type, |
253 | 253 | LPBYTE data, LPDWORD num_data) { |
254 | if (wstring(kSendStatsName) != value_name) { | |
254 | if (std::wstring(kSendStatsName) != value_name) { | |
255 | 255 | return ERROR_SUCCESS; |
256 | 256 | } |
257 | 257 | if (!HasUsagestatsValue(key)) { |
262 | 262 | return ERROR_SUCCESS; |
263 | 263 | } |
264 | 264 | static LSTATUS WINAPI TestRegDeleteValueW(HKEY key, LPCWSTR value_name) { |
265 | if (wstring(kSendStatsName) != value_name) { | |
265 | if (std::wstring(kSendStatsName) != value_name) { | |
266 | 266 | return ERROR_SUCCESS; |
267 | 267 | } |
268 | 268 | if (!HasUsagestatsValue(key)) { |
29 | 29 | |
30 | 30 | MAJOR=2 |
31 | 31 | MINOR=23 |
32 | BUILD=2792 | |
32 | BUILD=2793 | |
33 | 33 | REVISION=102 |
34 | 34 | # This version represents the version of Mozc IME engine (converter, predictor, |
35 | 35 | # etc.). This version info is included both in the Mozc server and in the Mozc |
63 | 63 | return false; |
64 | 64 | } |
65 | 65 | |
66 | unique_ptr<wchar_t[]> wide(new wchar_t[wide_length + 1]); | |
66 | std::unique_ptr<wchar_t[]> wide(new wchar_t[wide_length + 1]); | |
67 | 67 | if (MultiByteToWideChar(CP_932, MB_ERR_INVALID_CHARS, input.data(), |
68 | 68 | input.size(), wide.get(), |
69 | 69 | wide_length + 1) != wide_length) { |
241 | 241 | } |
242 | 242 | |
243 | 243 | private: |
244 | vector<IMEWRD> buf_; | |
244 | std::vector<IMEWRD> buf_; | |
245 | 245 | ScopedIFEDictionary dic_; |
246 | 246 | map<int, string> pos_map_; |
247 | 247 | HRESULT result_; |
47 | 47 | #include "gui/base/win_util.h" |
48 | 48 | #include "ipc/window_info.pb.h" |
49 | 49 | |
50 | #ifdef OS_WIN | |
51 | using std::unique_ptr; | |
52 | #endif // OS_WIN | |
53 | ||
54 | 50 | namespace mozc { |
55 | 51 | namespace gui { |
56 | 52 | namespace { |
57 | 53 | bool ReadWindowInfo(const string &lock_name, |
58 | 54 | ipc::WindowInfo *window_info) { |
59 | 55 | #ifdef OS_WIN |
60 | wstring wfilename; | |
56 | std::wstring wfilename; | |
61 | 57 | mozc::Util::UTF8ToWide(lock_name, &wfilename); |
62 | 58 | { |
63 | 59 | mozc::ScopedHandle handle( |
82 | 78 | return false; |
83 | 79 | } |
84 | 80 | |
85 | unique_ptr<char[]> buf(new char[size]); | |
81 | std::unique_ptr<char[]> buf(new char[size]); | |
86 | 82 | |
87 | 83 | DWORD read_size = 0; |
88 | 84 | if (!::ReadFile(handle.get(), buf.get(), |
68 | 68 | } |
69 | 69 | |
70 | 70 | { |
71 | wstring mozc_tool_path_wide; | |
71 | std::wstring mozc_tool_path_wide; | |
72 | 72 | Util::UTF8ToWide(SystemUtil::GetToolPath(), &mozc_tool_path_wide); |
73 | 73 | hr = link->SetPath(mozc_tool_path_wide.c_str()); |
74 | 74 | if (FAILED(hr)) { |
78 | 78 | } |
79 | 79 | |
80 | 80 | { |
81 | wstring argument_wide; | |
81 | std::wstring argument_wide; | |
82 | 82 | Util::UTF8ToWide(argument, &argument_wide); |
83 | 83 | hr = link->SetArguments(argument_wide.c_str()); |
84 | 84 | if (FAILED(hr)) { |
94 | 94 | } |
95 | 95 | |
96 | 96 | { |
97 | wstring item_title_wide; | |
97 | std::wstring item_title_wide; | |
98 | 98 | Util::UTF8ToWide(item_title, &item_title_wide); |
99 | 99 | PROPVARIANT prop_variant; |
100 | 100 | hr = ::InitPropVariantFromString(item_title_wide.c_str(), &prop_variant); |
252 | 252 | LOG(ERROR) << "Could not find the exsisting window."; |
253 | 253 | } |
254 | 254 | const CWindow window(info.found_window_handle); |
255 | wstring window_title_wide; | |
255 | std::wstring window_title_wide; | |
256 | 256 | { |
257 | 257 | CString buf; |
258 | 258 | window.GetWindowTextW(buf); |
310 | 310 | // can return |true| |
311 | 311 | if (ERROR_SUCCESS == result && |
312 | 312 | num_chars < arraysize(data) && |
313 | wstring(data) == kIMEHotKeyEntryData) { | |
313 | std::wstring(data) == kIMEHotKeyEntryData) { | |
314 | 314 | return true; |
315 | 315 | } |
316 | 316 |
43 | 43 | WindowsSelectionHandler::~WindowsSelectionHandler() {} |
44 | 44 | |
45 | 45 | void WindowsSelectionHandler::Select(const QString &str) { |
46 | vector<INPUT> inputs; | |
46 | std::vector<INPUT> inputs; | |
47 | 47 | for (int i = 0; i < str.size(); ++i) { |
48 | 48 | INPUT input = { 0 }; |
49 | 49 | KEYBDINPUT kb = { 0 }; |
63 | 63 | using mozc::user_dictionary::UserDictionaryCommandStatus; |
64 | 64 | using mozc::user_dictionary::UserDictionarySession; |
65 | 65 | using mozc::user_dictionary::UserDictionaryStorage; |
66 | #ifdef OS_WIN | |
67 | using std::unique_ptr; | |
68 | #endif // OS_WIN | |
69 | 66 | |
70 | 67 | namespace { |
71 | 68 | const int kSessionTimeout = 100000; |
74 | 71 | |
75 | 72 | QString GetEnv(const char *envname) { |
76 | 73 | #if defined(OS_WIN) |
77 | wstring wenvname; | |
74 | std::wstring wenvname; | |
78 | 75 | mozc::Util::UTF8ToWide(envname, &wenvname); |
79 | 76 | const DWORD buffer_size = |
80 | 77 | ::GetEnvironmentVariable(wenvname.c_str(), NULL, 0); |
81 | 78 | if (buffer_size == 0) { |
82 | 79 | return ""; |
83 | 80 | } |
84 | unique_ptr<wchar_t[]> buffer(new wchar_t[buffer_size]); | |
81 | std::unique_ptr<wchar_t[]> buffer(new wchar_t[buffer_size]); | |
85 | 82 | const DWORD num_copied = |
86 | 83 | ::GetEnvironmentVariable(wenvname.c_str(), buffer.get(), buffer_size); |
87 | 84 | if (num_copied > 0) { |
103 | 103 | server_thread_main.SetJoinable(true); |
104 | 104 | server_thread_main.Start("IpcMain"); |
105 | 105 | |
106 | vector<mozc::MultiConnections> cons(FLAGS_num_threads); | |
106 | std::vector<mozc::MultiConnections> cons(FLAGS_num_threads); | |
107 | 107 | for (size_t i = 0; i < cons.size(); ++i) { |
108 | 108 | cons[i].SetJoinable(true); |
109 | 109 | cons[i].Start("MultiConnections"); |
70 | 70 | #include "ipc/ipc.h" |
71 | 71 | #include "ipc/ipc.pb.h" |
72 | 72 | |
73 | #ifdef OS_WIN | |
74 | using std::unique_ptr; | |
75 | #endif // OS_WIn | |
76 | ||
77 | 73 | namespace mozc { |
78 | 74 | namespace { |
79 | 75 | |
333 | 329 | |
334 | 330 | #ifdef OS_WIN |
335 | 331 | { |
336 | wstring expected_server_ntpath; | |
337 | const map<string, wstring>::const_iterator it = | |
332 | std::wstring expected_server_ntpath; | |
333 | const std::map<string, std::wstring>::const_iterator it = | |
338 | 334 | expected_server_ntpath_cache_.find(server_path); |
339 | 335 | if (it != expected_server_ntpath_cache_.end()) { |
340 | 336 | expected_server_ntpath = it->second; |
341 | 337 | } else { |
342 | wstring wide_server_path; | |
338 | std::wstring wide_server_path; | |
343 | 339 | Util::UTF8ToWide(server_path, &wide_server_path); |
344 | 340 | if (WinUtil::GetNtPath(wide_server_path, &expected_server_ntpath)) { |
345 | 341 | // Caches the relationship from |server_path| to |
353 | 349 | return false; |
354 | 350 | } |
355 | 351 | |
356 | wstring actual_server_ntpath; | |
352 | std::wstring actual_server_ntpath; | |
357 | 353 | if (!WinUtil::GetProcessInitialNtPath(pid, &actual_server_ntpath)) { |
358 | 354 | return false; |
359 | 355 | } |
464 | 460 | // Special code for Windows, |
465 | 461 | // we want to pass FILE_SHRED_DELETE flag for CreateFile. |
466 | 462 | #ifdef OS_WIN |
467 | wstring wfilename; | |
463 | std::wstring wfilename; | |
468 | 464 | Util::UTF8ToWide(filename, &wfilename); |
469 | 465 | |
470 | 466 | { |
493 | 489 | return false; |
494 | 490 | } |
495 | 491 | |
496 | unique_ptr<char[]> buf(new char[size]); | |
492 | std::unique_ptr<char[]> buf(new char[size]); | |
497 | 493 | |
498 | 494 | DWORD read_size = 0; |
499 | 495 | if (!::ReadFile(handle.get(), buf.get(), |
133 | 133 | uint32 server_pid_; // cache for pid of server_path |
134 | 134 | time_t last_modified_; |
135 | 135 | #ifdef OS_WIN |
136 | map<string, wstring> expected_server_ntpath_cache_; | |
136 | std::map<string, std::wstring> expected_server_ntpath_cache_; | |
137 | 137 | #endif // OS_WIN |
138 | 138 | }; |
139 | 139 |
101 | 101 | #ifdef OS_WIN |
102 | 102 | NamedEventListener::NamedEventListener(const char *name) |
103 | 103 | : is_owner_(false), handle_(NULL) { |
104 | wstring event_path; | |
104 | std::wstring event_path; | |
105 | 105 | Util::UTF8ToWide(NamedEventUtil::GetEventPath(name), &event_path); |
106 | 106 | |
107 | 107 | handle_ = ::OpenEventW(EVENT_ALL_ACCESS, false, |
219 | 219 | |
220 | 220 | NamedEventNotifier::NamedEventNotifier(const char *name) |
221 | 221 | : handle_(NULL) { |
222 | wstring event_path; | |
222 | std::wstring event_path; | |
223 | 223 | Util::UTF8ToWide(NamedEventUtil::GetEventPath(name), &event_path); |
224 | 224 | handle_ = ::OpenEventW(EVENT_MODIFY_STATE, false, |
225 | 225 | event_path.c_str()); |
54 | 54 | mozc::TestProcessWatchDog dog; |
55 | 55 | |
56 | 56 | string line; |
57 | vector<string> fields; | |
57 | std::vector<string> fields; | |
58 | 58 | |
59 | 59 | while (getline(cin, line)) { |
60 | 60 | fields.clear(); |
60 | 60 | size_t GetNumberOfProcessors() { |
61 | 61 | // thread-safety is not required. |
62 | 62 | static size_t num = CPUStats().GetNumberOfProcessors(); |
63 | return max(num, static_cast<size_t>(1)); | |
63 | return std::max(num, static_cast<size_t>(1)); | |
64 | 64 | } |
65 | 65 | |
66 | 66 | // Least significant bit of OVERLAPPED::hEvent can be used for special |
106 | 106 | mutex_name += "."; |
107 | 107 | mutex_name += ipc_channel_name; |
108 | 108 | mutex_name += ".ipc"; |
109 | wstring wmutex_name; | |
109 | std::wstring wmutex_name; | |
110 | 110 | Util::UTF8ToWide(mutex_name, &wmutex_name); |
111 | 111 | |
112 | 112 | LPSECURITY_ATTRIBUTES security_attributes_ptr = nullptr; |
483 | 483 | } |
484 | 484 | |
485 | 485 | // Create a named pipe. |
486 | wstring wserver_address; | |
486 | std::wstring wserver_address; | |
487 | 487 | Util::UTF8ToWide(server_address, &wserver_address); |
488 | 488 | HANDLE handle = ::CreateNamedPipe(wserver_address.c_str(), |
489 | 489 | PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | |
715 | 715 | if (!manager->LoadPathName() || !manager->GetPathName(&server_address)) { |
716 | 716 | continue; |
717 | 717 | } |
718 | wstring wserver_address; | |
718 | std::wstring wserver_address; | |
719 | 719 | Util::UTF8ToWide(server_address, &wserver_address); |
720 | 720 | |
721 | 721 | if (GetNumberOfProcessors() == 1) { |
234 | 234 | uc.dwUrlPathLength = sizeof(UrlPath); |
235 | 235 | uc.dwExtraInfoLength = sizeof(ExtraInfo); |
236 | 236 | |
237 | wstring wurl; | |
237 | std::wstring wurl; | |
238 | 238 | Util::UTF8ToWide(url, &wurl); |
239 | 239 | |
240 | 240 | if (!::InternetCrackUrlW(wurl.c_str(), 0, 0, &uc)) { |
264 | 264 | return false; |
265 | 265 | } |
266 | 266 | |
267 | wstring uri = UrlPath; | |
267 | std::wstring uri = UrlPath; | |
268 | 268 | if (uc.dwExtraInfoLength != 0) { |
269 | 269 | uri += uc.lpszExtraInfo; |
270 | 270 | } |
295 | 295 | |
296 | 296 | for (size_t i = 0; i < option.headers.size(); ++i) { |
297 | 297 | const string header = option.headers[i] + "\r\n"; |
298 | wstring wheader; | |
298 | std::wstring wheader; | |
299 | 299 | Util::UTF8ToWide(header, &wheader); |
300 | 300 | if (!::HttpAddRequestHeadersW(handle.get(), wheader.c_str(), -1, |
301 | 301 | HTTP_ADDREQ_FLAG_ADD | |
172 | 172 | // than 10. Thus, this linear order algorithm is fast enough. |
173 | 173 | // Theoretically, we can construct a trie of strings in |subsequent_chars_| |
174 | 174 | // to get more performance but it's overkill here. |
175 | // TODO(noriyukit): vector<string> would be better than set<string>. To | |
176 | // this end, we need to fix Comopser as well. | |
175 | // TODO(noriyukit): std::vector<string> would be better than set<string>. | |
176 | // To this end, we need to fix Comopser as well. | |
177 | 177 | const StringPiece rest = ClippedSubstr(key, original_key_len_); |
178 | 178 | for (const string &chr : *subsequent_chars_) { |
179 | 179 | if (Util::StartsWith(rest, chr)) { |
158 | 158 | |
159 | 159 | // Retrieves the display string from the specified candidate for the specified |
160 | 160 | // column and returns it. |
161 | wstring GetDisplayStringByColumn( | |
161 | std::wstring GetDisplayStringByColumn( | |
162 | 162 | const commands::Candidates::Candidate &candidate, |
163 | 163 | COLUMN_TYPE column_type) { |
164 | wstring display_string; | |
164 | std::wstring display_string; | |
165 | 165 | |
166 | 166 | switch (column_type) { |
167 | 167 | case COLUMN_SHORTCUT: |
179 | 179 | if (candidate.has_annotation()) { |
180 | 180 | const commands::Annotation &annotation = candidate.annotation(); |
181 | 181 | if (annotation.has_prefix()) { |
182 | wstring annotation_prefix; | |
182 | std::wstring annotation_prefix; | |
183 | 183 | mozc::Util::UTF8ToWide(annotation.prefix(), &annotation_prefix); |
184 | 184 | display_string = annotation_prefix + display_string; |
185 | 185 | } |
186 | 186 | if (annotation.has_suffix()) { |
187 | wstring annotation_suffix; | |
187 | std::wstring annotation_suffix; | |
188 | 188 | mozc::Util::UTF8ToWide(annotation.suffix(), &annotation_suffix); |
189 | 189 | display_string += annotation_suffix; |
190 | 190 | } |
475 | 475 | |
476 | 476 | // Calculate the size to display a label string. |
477 | 477 | if (candidates_->footer().has_label()) { |
478 | wstring footer_label; | |
478 | std::wstring footer_label; | |
479 | 479 | mozc::Util::UTF8ToWide(candidates_->footer().label(), |
480 | 480 | &footer_label); |
481 | 481 | const Size label_string_size = text_renderer_->MeasureString( |
482 | 482 | TextRenderer::FONTSET_FOOTER_LABEL, |
483 | 483 | L" " + footer_label + L" "); |
484 | 484 | footer_size.width += label_string_size.width; |
485 | footer_size.height = max(footer_size.height, label_string_size.height); | |
485 | footer_size.height = std::max(footer_size.height, | |
486 | label_string_size.height); | |
486 | 487 | } else if (candidates_->footer().has_sub_label()) { |
487 | 488 | // Currently the sub label will not be shown unless (main) label is |
488 | 489 | // absent. |
489 | 490 | // TODO(yukawa): Refactor the layout system for the footer. |
490 | wstring footer_sub_label; | |
491 | std::wstring footer_sub_label; | |
491 | 492 | mozc::Util::UTF8ToWide(candidates_->footer().sub_label(), |
492 | 493 | &footer_sub_label); |
493 | 494 | const Size label_string_size = text_renderer_->MeasureString( |
494 | 495 | TextRenderer::FONTSET_FOOTER_SUBLABEL, |
495 | 496 | L" " + footer_sub_label + L" "); |
496 | 497 | footer_size.width += label_string_size.width; |
497 | footer_size.height = max(footer_size.height, label_string_size.height); | |
498 | footer_size.height = std::max(footer_size.height, | |
499 | label_string_size.height); | |
498 | 500 | } |
499 | 501 | |
500 | 502 | // Calculate the size to display a index string. |
501 | 503 | if (candidates_->footer().index_visible()) { |
502 | wstring index_guide_string; | |
504 | std::wstring index_guide_string; | |
503 | 505 | mozc::Util::UTF8ToWide(GetIndexGuideString(*candidates_), |
504 | 506 | &index_guide_string); |
505 | 507 | const Size index_guide_size = text_renderer_->MeasureString( |
506 | 508 | TextRenderer::FONTSET_FOOTER_INDEX, index_guide_string); |
507 | 509 | footer_size.width += index_guide_size.width; |
508 | footer_size.height = max(footer_size.height, index_guide_size.height); | |
510 | footer_size.height = std::max(footer_size.height, | |
511 | index_guide_size.height); | |
509 | 512 | } |
510 | 513 | |
511 | 514 | // Calculate the size to display a Footer logo. |
512 | 515 | if (!footer_logo_.IsNull()) { |
513 | 516 | if (candidates_->footer().logo_visible()) { |
514 | 517 | footer_size.width += footer_logo_display_size_.width; |
515 | footer_size.height = max(footer_size.height, | |
516 | footer_logo_display_size_.height); | |
518 | footer_size.height = std::max(footer_size.height, | |
519 | footer_logo_display_size_.height); | |
517 | 520 | } else if (footer_size.height > 0) { |
518 | 521 | // Ensure the footer height is greater than the Footer logo height |
519 | 522 | // even if the Footer logo is absent. This hack prevents the footer |
520 | 523 | // from changing its height too frequently. |
521 | footer_size.height = max(footer_size.height, | |
522 | footer_logo_display_size_.height); | |
524 | footer_size.height = std::max(footer_size.height, | |
525 | footer_logo_display_size_.height); | |
523 | 526 | } |
524 | 527 | } |
525 | 528 | |
527 | 530 | // one page. |
528 | 531 | if (candidates_->candidate_size() < candidates_->size()) { |
529 | 532 | // We use FONTSET_CANDIDATE for calculating the minimum width. |
530 | wstring minimum_width_as_wstring; | |
533 | std::wstring minimum_width_as_wstring; | |
531 | 534 | mozc::Util::UTF8ToWide( |
532 | 535 | kMinimumCandidateAndDescriptionWidthAsString, |
533 | 536 | &minimum_width_as_wstring); |
557 | 560 | for (size_t i = 0; i < candidates_->candidate_size(); ++i) { |
558 | 561 | const commands::Candidates::Candidate &candidate = |
559 | 562 | candidates_->candidate(i); |
560 | const wstring shortcut = | |
563 | const std::wstring shortcut = | |
561 | 564 | GetDisplayStringByColumn(candidate, COLUMN_SHORTCUT); |
562 | const wstring description = | |
565 | const std::wstring description = | |
563 | 566 | GetDisplayStringByColumn(candidate, COLUMN_DESCRIPTION); |
564 | const wstring candidate_string = | |
567 | const std::wstring candidate_string = | |
565 | 568 | GetDisplayStringByColumn(candidate, COLUMN_CANDIDATE); |
566 | 569 | |
567 | 570 | if (!shortcut.empty()) { |
568 | wstring text; | |
571 | std::wstring text; | |
569 | 572 | text.push_back(L' '); // put a space for padding |
570 | 573 | text.append(shortcut); |
571 | 574 | text.push_back(L' '); // put a space for padding |
575 | 578 | } |
576 | 579 | |
577 | 580 | if (!candidate_string.empty()) { |
578 | wstring text; | |
581 | std::wstring text; | |
579 | 582 | text.append(candidate_string); |
580 | 583 | |
581 | 584 | const Size rendering_size = text_renderer_->MeasureString( |
584 | 587 | } |
585 | 588 | |
586 | 589 | if (!description.empty()) { |
587 | wstring text; | |
590 | std::wstring text; | |
588 | 591 | text.append(description); |
589 | 592 | text.push_back(L' '); // put a space for padding |
590 | 593 | const Size rendering_size = text_renderer_->MeasureString( |
658 | 661 | const COLUMN_TYPE column_type = kColumnTypes[type_index]; |
659 | 662 | const TextRenderer::FONT_TYPE font_type = kFontTypes[type_index]; |
660 | 663 | |
661 | vector<TextRenderingInfo> display_list; | |
664 | std::vector<TextRenderingInfo> display_list; | |
662 | 665 | for (size_t i = 0; i < candidates_->candidate_size(); ++i) { |
663 | 666 | const commands::Candidates::Candidate &candidate = |
664 | 667 | candidates_->candidate(i); |
665 | const wstring display_string = | |
668 | const std::wstring display_string = | |
666 | 669 | GetDisplayStringByColumn(candidate, column_type); |
667 | 670 | const Rect text_rect = |
668 | 671 | table_layout_->GetCellRect(i, column_type); |
787 | 790 | |
788 | 791 | int right_used = 0; |
789 | 792 | if (candidates_->footer().index_visible()) { |
790 | wstring index_guide_string; | |
793 | std::wstring index_guide_string; | |
791 | 794 | mozc::Util::UTF8ToWide(GetIndexGuideString(*candidates_), |
792 | 795 | &index_guide_string); |
793 | 796 | const Size index_guide_size = text_renderer_->MeasureString( |
806 | 809 | footer_content_rect.Top(), |
807 | 810 | footer_content_rect.Width() - left_used - right_used, |
808 | 811 | footer_content_rect.Height()); |
809 | wstring footer_label; | |
812 | std::wstring footer_label; | |
810 | 813 | mozc::Util::UTF8ToWide(candidates_->footer().label(), &footer_label); |
811 | 814 | text_renderer_->RenderText(dc, |
812 | 815 | L" " + footer_label + L" ", |
813 | 816 | label_rect, |
814 | 817 | TextRenderer::FONTSET_FOOTER_LABEL); |
815 | 818 | } else if (candidates_->footer().has_sub_label()) { |
816 | wstring footer_sub_label; | |
819 | std::wstring footer_sub_label; | |
817 | 820 | mozc::Util::UTF8ToWide(candidates_->footer().sub_label(), |
818 | 821 | &footer_sub_label); |
819 | 822 | const Rect label_rect(left_used, |
820 | 823 | footer_content_rect.Top(), |
821 | 824 | footer_content_rect.Width() - left_used - right_used, |
822 | 825 | footer_content_rect.Height()); |
823 | const wstring text = L" " + footer_sub_label + L" "; | |
826 | const std::wstring text = L" " + footer_sub_label + L" "; | |
824 | 827 | text_renderer_->RenderText(dc, |
825 | 828 | text, |
826 | 829 | label_rect, |
196 | 196 | Destroy(); |
197 | 197 | } |
198 | 198 | |
199 | virtual void UpdateLayout(const vector<CompositionWindowLayout> &layouts) { | |
199 | virtual void UpdateLayout( | |
200 | const std::vector<CompositionWindowLayout> &layouts) { | |
200 | 201 | // Create windows if needed. |
201 | 202 | if (line_windows_.size() < layouts.size()) { |
202 | 203 | const size_t num_windows = layouts.size() - line_windows_.size(); |
253 | 254 | } |
254 | 255 | |
255 | 256 | private: |
256 | vector<CompositionLineWindow *> line_windows_; | |
257 | std::vector<CompositionLineWindow *> line_windows_; | |
257 | 258 | DISALLOW_COPY_AND_ASSIGN(CompositionWindowListImpl); |
258 | 259 | }; |
259 | 260 | } // namespace |
51 | 51 | virtual void Destroy() = 0; |
52 | 52 | virtual void Hide() = 0; |
53 | 53 | virtual void UpdateLayout( |
54 | const vector<CompositionWindowLayout> &layouts) = 0; | |
54 | const std::vector<CompositionWindowLayout> &layouts) = 0; | |
55 | 55 | |
56 | 56 | static CompositionWindowList *CreateInstance(); |
57 | 57 |
59 | 59 | const uint32 kMaxBitmapHeight = 16384; |
60 | 60 | |
61 | 61 | bool ConvertMain() { |
62 | wstring wide_src; | |
62 | std::wstring wide_src; | |
63 | 63 | mozc::Util::UTF8ToWide(FLAGS_src, &wide_src); |
64 | 64 | std::unique_ptr<Gdiplus::Bitmap> image( |
65 | 65 | Gdiplus::Bitmap::FromFile(wide_src.c_str())); |
230 | 230 | SetTimer(kTimerEventFading, kFadingOutInterval); |
231 | 231 | break; |
232 | 232 | case kTimerEventFading: |
233 | alpha_ = max(static_cast<int>(alpha_) - kFadingOutAlphaDelta, 0); | |
233 | alpha_ = std::max(static_cast<int>(alpha_) - kFadingOutAlphaDelta, 0); | |
234 | 234 | if (alpha_ == 0) { |
235 | 235 | KillTimer(kTimerEventFading); |
236 | 236 | } |
320 | 320 | CPoint top_left_; |
321 | 321 | BYTE alpha_; |
322 | 322 | double dpi_scaling_; |
323 | vector<Sprite> sprites_; | |
323 | std::vector<Sprite> sprites_; | |
324 | 324 | |
325 | 325 | DISALLOW_COPY_AND_ASSIGN(WindowImpl); |
326 | 326 | }; |
170 | 170 | infostyle.caption_background_color().g(), |
171 | 171 | infostyle.caption_background_color().b())); |
172 | 172 | |
173 | wstring caption_str; | |
173 | std::wstring caption_str; | |
174 | 174 | const Rect caption_rect( |
175 | 175 | infostyle.window_border() + infostyle.caption_padding() |
176 | 176 | + caption_style.left_padding(), |
221 | 221 | infostyle.row_rect_padding() * 2; |
222 | 222 | const Information &info = usages.information(row); |
223 | 223 | |
224 | wstring title_str; | |
224 | std::wstring title_str; | |
225 | 225 | mozc::Util::UTF8ToWide(info.title(), &title_str); |
226 | 226 | const Size title_size = text_renderer_->MeasureStringMultiLine( |
227 | 227 | TextRenderer::FONTSET_INFOLIST_TITLE, title_str, title_width); |
228 | 228 | |
229 | wstring desc_str; | |
229 | std::wstring desc_str; | |
230 | 230 | mozc::Util::UTF8ToWide(info.description(), &desc_str); |
231 | 231 | const Size desc_size = text_renderer_->MeasureStringMultiLine( |
232 | 232 | TextRenderer::FONTSET_INFOLIST_DESCRIPTION, desc_str, desc_width); |
221 | 221 | } |
222 | 222 | } |
223 | 223 | |
224 | virtual Size MeasureString(FONT_TYPE font_type, const wstring &str) const { | |
224 | virtual Size MeasureString(FONT_TYPE font_type, | |
225 | const std::wstring &str) const { | |
225 | 226 | const auto previous_font = mem_dc_.SelectFont(render_info_[font_type].font); |
226 | 227 | CRect rect; |
227 | 228 | mem_dc_.DrawTextW(str.c_str(), str.length(), &rect, |
231 | 232 | } |
232 | 233 | |
233 | 234 | virtual Size MeasureStringMultiLine( |
234 | FONT_TYPE font_type, const wstring &str, const int width) const { | |
235 | FONT_TYPE font_type, const std::wstring &str, const int width) const { | |
235 | 236 | const auto previous_font = mem_dc_.SelectFont(render_info_[font_type].font); |
236 | 237 | CRect rect(0, 0, width, 0); |
237 | 238 | mem_dc_.DrawTextW(str.c_str(), str.length(), &rect, |
241 | 242 | } |
242 | 243 | |
243 | 244 | virtual void RenderText(CDCHandle dc, |
244 | const wstring &text, | |
245 | const std::wstring &text, | |
245 | 246 | const Rect &rect, |
246 | 247 | FONT_TYPE font_type) const { |
247 | vector<TextRenderingInfo> infolist; | |
248 | std::vector<TextRenderingInfo> infolist; | |
248 | 249 | infolist.push_back(TextRenderingInfo(text, rect)); |
249 | 250 | RenderTextList(dc, infolist, font_type); |
250 | 251 | } |
251 | 252 | |
252 | virtual void RenderTextList(CDCHandle dc, | |
253 | const vector<TextRenderingInfo> &display_list, | |
254 | FONT_TYPE font_type) const { | |
253 | virtual void RenderTextList( | |
254 | CDCHandle dc, | |
255 | const std::vector<TextRenderingInfo> &display_list, | |
256 | FONT_TYPE font_type) const { | |
255 | 257 | const auto &render_info = render_info_[font_type]; |
256 | 258 | const auto old_font = dc.SelectFont(render_info.font); |
257 | 259 | const auto previous_color = dc.SetTextColor(render_info.color); |
272 | 274 | DWORD style; |
273 | 275 | CFont font; |
274 | 276 | }; |
275 | unique_ptr<RenderInfo[]> render_info_; | |
277 | std::unique_ptr<RenderInfo[]> render_info_; | |
276 | 278 | mutable CDC mem_dc_; |
277 | 279 | |
278 | 280 | DISALLOW_COPY_AND_ASSIGN(GdiTextRenderer); |
349 | 351 | } |
350 | 352 | |
351 | 353 | // Retrieves the bounding box for a given string. |
352 | virtual Size MeasureString(FONT_TYPE font_type, const wstring &str) const { | |
354 | virtual Size MeasureString(FONT_TYPE font_type, | |
355 | const std::wstring &str) const { | |
353 | 356 | return MeasureStringImpl(font_type, str, 0, false); |
354 | 357 | } |
355 | 358 | |
356 | virtual Size MeasureStringMultiLine(FONT_TYPE font_type, const wstring &str, | |
359 | virtual Size MeasureStringMultiLine(FONT_TYPE font_type, | |
360 | const std::wstring &str, | |
357 | 361 | const int width) const { |
358 | 362 | return MeasureStringImpl(font_type, str, width, true); |
359 | 363 | } |
360 | 364 | |
361 | virtual void RenderText(CDCHandle dc, const wstring &text, | |
365 | virtual void RenderText(CDCHandle dc, const std::wstring &text, | |
362 | 366 | const Rect &rect, FONT_TYPE font_type) const { |
363 | vector<TextRenderingInfo> infolist; | |
367 | std::vector<TextRenderingInfo> infolist; | |
364 | 368 | infolist.push_back(TextRenderingInfo(text, rect)); |
365 | 369 | RenderTextList(dc, infolist, font_type); |
366 | 370 | } |
367 | 371 | |
368 | virtual void RenderTextList(CDCHandle dc, | |
369 | const vector<TextRenderingInfo> &display_list, | |
370 | FONT_TYPE font_type) const { | |
372 | virtual void RenderTextList( | |
373 | CDCHandle dc, | |
374 | const std::vector<TextRenderingInfo> &display_list, | |
375 | FONT_TYPE font_type) const { | |
371 | 376 | const size_t kMaxTrial = 3; |
372 | 377 | size_t trial = 0; |
373 | 378 | while (true) { |
390 | 395 | } |
391 | 396 | |
392 | 397 | HRESULT RenderTextListImpl(CDCHandle dc, |
393 | const vector<TextRenderingInfo> &display_list, | |
398 | const std::vector<TextRenderingInfo> &display_list, | |
394 | 399 | FONT_TYPE font_type) const { |
395 | 400 | CRect total_rect; |
396 | 401 | for (const auto &item : display_list) { |
397 | 402 | const auto &item_rect = ToCRect(item.rect); |
398 | total_rect.right = max(total_rect.right, item_rect.right); | |
399 | total_rect.bottom = max(total_rect.bottom, item_rect.bottom); | |
403 | total_rect.right = std::max(total_rect.right, item_rect.right); | |
404 | total_rect.bottom = std::max(total_rect.bottom, item_rect.bottom); | |
400 | 405 | } |
401 | 406 | HRESULT hr = S_OK; |
402 | 407 | hr = dc_render_target_->BindDC(dc, &total_rect); |
434 | 439 | return dc_render_target_->EndDraw(); |
435 | 440 | } |
436 | 441 | |
437 | Size MeasureStringImpl(FONT_TYPE font_type, const wstring &str, | |
442 | Size MeasureStringImpl(FONT_TYPE font_type, const std::wstring &str, | |
438 | 443 | const int width, bool use_width) const { |
439 | 444 | HRESULT hr = S_OK; |
440 | 445 | const FLOAT kLayoutLimit = 100000.0f; |
489 | 494 | return nullptr; |
490 | 495 | } |
491 | 496 | length += 1; // for NUL. |
492 | unique_ptr<wchar_t[]> family_name(new wchar_t[length]); | |
497 | std::unique_ptr<wchar_t[]> family_name(new wchar_t[length]); | |
493 | 498 | hr = localized_family_names->GetString(0, family_name.get(), length); |
494 | 499 | if (FAILED(hr)) { |
495 | 500 | return nullptr; |
549 | 554 | CComPtr<IDWriteFactory> dwrite_factory_; |
550 | 555 | mutable CComPtr<ID2D1DCRenderTarget> dc_render_target_; |
551 | 556 | CComPtr<IDWriteGdiInterop> dwrite_interop_; |
552 | vector<RenderInfo> render_info_; | |
557 | std::vector<RenderInfo> render_info_; | |
553 | 558 | |
554 | 559 | DISALLOW_COPY_AND_ASSIGN(DirectWriteTextRenderer); |
555 | 560 | }; |
48 | 48 | |
49 | 49 | // text-rect pair for batch text rendering. |
50 | 50 | struct TextRenderingInfo { |
51 | wstring text; | |
51 | std::wstring text; | |
52 | 52 | Rect rect; |
53 | TextRenderingInfo(const wstring &str, const Rect &r) : | |
53 | TextRenderingInfo(const std::wstring &str, const Rect &r) : | |
54 | 54 | text(str), rect(r) { |
55 | 55 | } |
56 | 56 | }; |
82 | 82 | virtual void OnThemeChanged() = 0; |
83 | 83 | |
84 | 84 | // Retrieves the bounding box for a given string. |
85 | virtual Size MeasureString(FONT_TYPE font_type, const wstring &str) const = 0; | |
85 | virtual Size MeasureString(FONT_TYPE font_type, | |
86 | const std::wstring &str) const = 0; | |
86 | 87 | virtual Size MeasureStringMultiLine(FONT_TYPE font_type, |
87 | const wstring &str, | |
88 | const std::wstring &str, | |
88 | 89 | const int width) const = 0; |
89 | 90 | // Renders the given |text|. |
90 | 91 | virtual void RenderText(WTL::CDCHandle dc, |
91 | const wstring &text, | |
92 | const std::wstring &text, | |
92 | 93 | const Rect &rect, |
93 | 94 | FONT_TYPE font_type) const = 0; |
94 | virtual void RenderTextList(WTL::CDCHandle dc, | |
95 | const vector<TextRenderingInfo> &display_list, | |
96 | FONT_TYPE font_type) const = 0; | |
95 | virtual void RenderTextList( | |
96 | WTL::CDCHandle dc, | |
97 | const std::vector<TextRenderingInfo> &display_list, | |
98 | FONT_TYPE font_type) const = 0; | |
97 | 99 | }; |
98 | 100 | |
99 | 101 | } // namespace win32 |
102 | 102 | log_font->lfQuality = win_log_font.quality(); |
103 | 103 | log_font->lfPitchAndFamily = win_log_font.pitch_and_family(); |
104 | 104 | |
105 | wstring face_name; | |
105 | std::wstring face_name; | |
106 | 106 | mozc::Util::UTF8ToWide(win_log_font.face_name(), &face_name); |
107 | 107 | |
108 | 108 | // Although the result of mozc::Util::UTF8ToWide never contains any null |
82 | 82 | win_log_font.set_pitch_and_family(FF_SCRIPT); |
83 | 83 | |
84 | 84 | LOGFONT log_font = { }; |
85 | wstring too_long_face_name(L' ', arraysize(log_font.lfFaceName)); | |
85 | std::wstring too_long_face_name(L' ', arraysize(log_font.lfFaceName)); | |
86 | 86 | string face_name; |
87 | 87 | mozc::Util::WideToUTF8(too_long_face_name, &face_name); |
88 | 88 | win_log_font.set_face_name(face_name); |
224 | 224 | // Returns PixelType as a quick determination. If kUnknown is returned, you |
225 | 225 | // need to investigate the pixel type more precisely. |
226 | 226 | PixelType GetPixelTypeInternalFast(int x, int y) const { |
227 | const double frame = max(corner_radius_, frame_thickness_); | |
227 | const double frame = std::max(corner_radius_, frame_thickness_); | |
228 | 228 | if ((left_ + frame) < x && |
229 | 229 | (x + 1) < (left_ + width_ - frame) && |
230 | 230 | (top_ + frame) < y && |
374 | 374 | |
375 | 375 | // Core logic to render 1-bit text glyphs for sub-pixel rendering. Caller takes |
376 | 376 | // the ownerships of the returned pointers. |
377 | vector<TextLabel::BinarySubdivisionalPixel *> Get1bitGlyph( | |
377 | std::vector<TextLabel::BinarySubdivisionalPixel *> Get1bitGlyph( | |
378 | 378 | double left, |
379 | 379 | double top, |
380 | 380 | double width, |
388 | 388 | const int pix_width = bounding_rect.Width(); |
389 | 389 | const int pix_height = bounding_rect.Height(); |
390 | 390 | |
391 | vector<TextLabel::BinarySubdivisionalPixel *> pixels; | |
391 | std::vector<TextLabel::BinarySubdivisionalPixel *> pixels; | |
392 | 392 | pixels.resize(pix_width * pix_height, nullptr); |
393 | 393 | if (text.empty()) { |
394 | 394 | return pixels; |
426 | 426 | dc.CreateCompatibleDC(nullptr); |
427 | 427 | CBitmapHandle old_bitmap = dc.SelectBitmap(dib); |
428 | 428 | |
429 | wstring wide_fontname; | |
429 | std::wstring wide_fontname; | |
430 | 430 | Util::UTF8ToWide(fontname, &wide_fontname); |
431 | 431 | CLogFont logfont; |
432 | 432 | logfont.lfWeight = FW_NORMAL; |
451 | 451 | CRect rect(lefttop, size); |
452 | 452 | dc.SetBkMode(TRANSPARENT); |
453 | 453 | dc.SetTextColor(RGB(255, 255, 255)); |
454 | wstring wide_text; | |
454 | std::wstring wide_text; | |
455 | 455 | Util::UTF8ToWide(text, &wide_text); |
456 | 456 | dc.DrawTextW(wide_text.c_str(), wide_text.size(), &rect, |
457 | 457 | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX | DT_CENTER); |
573 | 573 | HBITMAP BalloonImage::CreateInternal(const BalloonImageInfo &info, |
574 | 574 | POINT *tail_offset, |
575 | 575 | SIZE *size, |
576 | vector<ARGBColor> *arbg_buffer) { | |
576 | std::vector<ARGBColor> *arbg_buffer) { | |
577 | 577 | // Base point. You can set arbitrary position. |
578 | 578 | const double kLeft = 10.0; |
579 | 579 | const double kTop = 10.0; |
580 | 580 | |
581 | 581 | const Balloon balloon( |
582 | kLeft, kTop, max(info.rect_width, 0.0), max(info.rect_height, 0.0), | |
583 | max(info.frame_thickness, 0.0), max(info.corner_radius, 0.0), | |
584 | max(info.tail_height, 0.0), max(info.tail_width, 0.0), | |
582 | kLeft, kTop, | |
583 | std::max(info.rect_width, 0.0), std::max(info.rect_height, 0.0), | |
584 | std::max(info.frame_thickness, 0.0), std::max(info.corner_radius, 0.0), | |
585 | std::max(info.tail_height, 0.0), std::max(info.tail_width, 0.0), | |
585 | 586 | info.frame_color, info.inside_color, info.tail_direction); |
586 | 587 | |
587 | 588 | const TextLabel label(kLeft + info.frame_thickness, |
616 | 617 | GaussianBlur blur(info.blur_sigma); |
617 | 618 | |
618 | 619 | const int begin_x = |
619 | rect.Left() - max(blur.cutoff_length() - info.blur_offset_x, 0); | |
620 | rect.Left() - std::max(blur.cutoff_length() - info.blur_offset_x, 0); | |
620 | 621 | const int begin_y = |
621 | rect.Top() - max(blur.cutoff_length() - info.blur_offset_y, 0); | |
622 | rect.Top() - std::max(blur.cutoff_length() - info.blur_offset_y, 0); | |
622 | 623 | const int end_x = |
623 | rect.Right() + max(blur.cutoff_length() + info.blur_offset_x, 0); | |
624 | rect.Right() + std::max(blur.cutoff_length() + info.blur_offset_x, 0); | |
624 | 625 | const int end_y = |
625 | rect.Bottom() + max(blur.cutoff_length() + info.blur_offset_y, 0); | |
626 | rect.Bottom() + std::max(blur.cutoff_length() + info.blur_offset_y, 0); | |
626 | 627 | |
627 | 628 | const int bmp_width = end_x - begin_x; |
628 | 629 | const int bmp_height = end_y - begin_y; |
680 | 681 | const int offset_y_; |
681 | 682 | }; |
682 | 683 | |
683 | const double normalized_blur_alpha = min(max(info.blur_alpha, 0.0), 1.0); | |
684 | const double normalized_blur_alpha = | |
685 | std::min(std::max(info.blur_alpha, 0.0), 1.0); | |
684 | 686 | Accessor accessor(frame_buffer, -info.blur_offset_x, -info.blur_offset_y); |
685 | 687 | for (int y = begin_y; y < begin_y + bmp_height; ++y) { |
686 | 688 | for (int x = begin_x; x < begin_x + bmp_width; ++x) { |
156 | 156 | const BalloonImageInfo &info, |
157 | 157 | POINT *tail_offset, |
158 | 158 | SIZE *size, |
159 | vector<ARGBColor> *arbg_buffer); | |
159 | std::vector<ARGBColor> *arbg_buffer); | |
160 | 160 | |
161 | 161 | private: |
162 | 162 | DISALLOW_IMPLICIT_CONSTRUCTORS(BalloonImage); |
245 | 245 | static size_t GetIndex(const Fraction2D &offset); |
246 | 246 | |
247 | 247 | // A bit vector that indicates each sub-pixel is filled or not. |
248 | bitset<kTotalPixels> filled_; | |
248 | std::bitset<kTotalPixels> filled_; | |
249 | 249 | std::unique_ptr<ColorType[]> colors_; |
250 | 250 | ColorType single_color_; |
251 | 251 | |
284 | 284 | MatrixElement(); |
285 | 285 | MatrixElement(int x, int y, double c); |
286 | 286 | }; |
287 | typedef vector<MatrixElement> Matrix; | |
287 | typedef std::vector<MatrixElement> Matrix; | |
288 | 288 | |
289 | 289 | size_t GetMatrixLength() const; |
290 | 290 | |
324 | 324 | // output the result to SubdivisionalPixel storage. |
325 | 325 | class TextLabel { |
326 | 326 | public: |
327 | typedef bitset<SubdivisionalPixel::kDivision * SubdivisionalPixel::kDivision> | |
327 | typedef | |
328 | std::bitset<SubdivisionalPixel::kDivision * SubdivisionalPixel::kDivision> | |
328 | 329 | BinarySubdivisionalPixel; |
329 | 330 | |
330 | 331 | TextLabel(double left, |
345 | 346 | const Rect &bounding_rect() const; |
346 | 347 | |
347 | 348 | private: |
348 | const vector<BinarySubdivisionalPixel *> pixels_; | |
349 | const std::vector<BinarySubdivisionalPixel *> pixels_; | |
349 | 350 | const Rect bounding_rect_; |
350 | 351 | const RGBColor text_color_; |
351 | 352 |
106 | 106 | |
107 | 107 | static void BalloonImageTest::SaveTestImage( |
108 | 108 | const TestableBalloonImage::BalloonImageInfo &info, |
109 | const wstring filename) { | |
109 | const std::wstring filename) { | |
110 | 110 | CPoint tail_offset; |
111 | 111 | CSize size; |
112 | vector<ARGBColor> buffer; | |
112 | std::vector<ARGBColor> buffer; | |
113 | 113 | CBitmap dib = TestableBalloonImage::CreateInternal( |
114 | 114 | info, &tail_offset, &size, &buffer); |
115 | 115 | |
190 | 190 | } |
191 | 191 | |
192 | 192 | private: |
193 | static bool GetEncoderClsid(const wstring format, CLSID *clsid) { | |
193 | static bool GetEncoderClsid(const std::wstring format, CLSID *clsid) { | |
194 | 194 | UINT num_codecs = 0; |
195 | 195 | UINT codecs_buffer_size = 0; |
196 | 196 | Gdiplus::GetImageEncodersSize(&num_codecs, &codecs_buffer_size); |
198 | 198 | return false; |
199 | 199 | } |
200 | 200 | |
201 | unique_ptr<uint8[]> codesc_buffer(new uint8[codecs_buffer_size]); | |
201 | std::unique_ptr<uint8[]> codesc_buffer(new uint8[codecs_buffer_size]); | |
202 | 202 | Gdiplus::ImageCodecInfo *codecs = |
203 | 203 | reinterpret_cast<Gdiplus::ImageCodecInfo *>(codesc_buffer.get()); |
204 | 204 | |
304 | 304 | |
305 | 305 | CPoint actual_tail_offset; |
306 | 306 | CSize actual_size; |
307 | vector<ARGBColor> actual_buffer; | |
307 | std::vector<ARGBColor> actual_buffer; | |
308 | 308 | CBitmap dib = TestableBalloonImage::CreateInternal( |
309 | 309 | info, &actual_tail_offset, &actual_size, &actual_buffer); |
310 | 310 | |
311 | 311 | EXPECT_EQ(tail["output"]["tail_offset_x"].asInt(), actual_tail_offset.x); |
312 | 312 | EXPECT_EQ(tail["output"]["tail_offset_y"].asInt(), actual_tail_offset.y); |
313 | 313 | |
314 | wstring wide_path; | |
314 | std::wstring wide_path; | |
315 | 315 | Util::UTF8ToWide(expected_image_path, &wide_path); |
316 | 316 | |
317 | 317 | Gdiplus::Bitmap bitmap(wide_path.c_str()); |
431 | 431 | return true; |
432 | 432 | } |
433 | 433 | |
434 | wstring ComposePreeditText(const commands::Preedit &preedit, | |
434 | std::wstring ComposePreeditText(const commands::Preedit &preedit, | |
435 | 435 | string *preedit_utf8, |
436 | vector<int> *segment_indices, | |
437 | vector<CharacterRange> *segment_ranges) { | |
436 | std::vector<int> *segment_indices, | |
437 | std::vector<CharacterRange> *segment_ranges) { | |
438 | 438 | if (preedit_utf8 != NULL) { |
439 | 439 | preedit_utf8->clear(); |
440 | 440 | } |
444 | 444 | if (segment_ranges != NULL) { |
445 | 445 | segment_ranges->clear(); |
446 | 446 | } |
447 | wstring value; | |
447 | std::wstring value; | |
448 | 448 | int total_characters = 0; |
449 | 449 | for (size_t segment_index = 0; segment_index < preedit.segment_size(); |
450 | 450 | ++segment_index) { |
451 | 451 | const commands::Preedit::Segment &segment = preedit.segment(segment_index); |
452 | wstring segment_value; | |
452 | std::wstring segment_value; | |
453 | 453 | mozc::Util::UTF8ToWide(segment.value(), &segment_value); |
454 | 454 | value.append(segment_value); |
455 | 455 | if (preedit_utf8 != NULL) { |
474 | 474 | |
475 | 475 | bool CalcLayoutWithTextWrappingInternal( |
476 | 476 | CDCHandle dc, |
477 | const wstring &str, | |
477 | const std::wstring &str, | |
478 | 478 | const int maximum_line_length, |
479 | 479 | const int initial_offset, |
480 | vector<LineLayout> *line_layouts) { | |
480 | std::vector<LineLayout> *line_layouts) { | |
481 | 481 | DCHECK(line_layouts != NULL); |
482 | 482 | if (initial_offset < 0 || maximum_line_length <= 0 || |
483 | 483 | maximum_line_length < initial_offset) { |
557 | 557 | } else { |
558 | 558 | CSize line_size; |
559 | 559 | int allowable_chars_for_confirmation = 0; |
560 | unique_ptr<int[]> size_buffer(new int[allowable_chars]); | |
560 | std::unique_ptr<int[]> size_buffer(new int[allowable_chars]); | |
561 | 561 | result = dc.GetTextExtentExPoint( |
562 | 562 | layout.text.c_str(), |
563 | 563 | layout.text.size(), |
741 | 741 | } |
742 | 742 | |
743 | 743 | // This method is not const to implement Win32WindowInterface. |
744 | virtual bool GetWindowClassName(HWND window_handle, wstring *class_name) { | |
744 | virtual bool GetWindowClassName(HWND window_handle, | |
745 | std::wstring *class_name) { | |
745 | 746 | if (class_name == NULL) { |
746 | 747 | return false; |
747 | 748 | } |
783 | 784 | }; |
784 | 785 | |
785 | 786 | struct WindowInfo { |
786 | wstring class_name; | |
787 | std::wstring class_name; | |
787 | 788 | CRect window_rect; |
788 | 789 | CPoint client_area_offset; |
789 | 790 | CSize client_area_size; |
884 | 885 | |
885 | 886 | // This method wraps API call of GetAncestor/GA_ROOT. |
886 | 887 | virtual HWND GetRootWindow(HWND window_handle) { |
887 | const map<HWND, HWND>::const_iterator it = root_map_.find(window_handle); | |
888 | const std::map<HWND, HWND>::const_iterator it = | |
889 | root_map_.find(window_handle); | |
888 | 890 | if (it == root_map_.end()) { |
889 | 891 | return window_handle; |
890 | 892 | } |
892 | 894 | } |
893 | 895 | |
894 | 896 | // This method is not const to implement Win32WindowInterface. |
895 | virtual bool GetWindowClassName(HWND window_handle, wstring *class_name) { | |
897 | virtual bool GetWindowClassName(HWND window_handle, | |
898 | std::wstring *class_name) { | |
896 | 899 | if (class_name == NULL) { |
897 | 900 | return false; |
898 | 901 | } |
934 | 937 | } |
935 | 938 | |
936 | 939 | virtual HWND RegisterWindow( |
937 | const wstring &class_name, const RECT &window_rect, | |
940 | const std::wstring &class_name, const RECT &window_rect, | |
938 | 941 | const POINT &client_area_offset, const SIZE &client_area_size, |
939 | 942 | double scale_factor) { |
940 | 943 | const HWND hwnd = GetNextWindowHandle(); |
968 | 971 | return &(window_map_.find(hwnd)->second); |
969 | 972 | } |
970 | 973 | |
971 | map<HWND, WindowInfo> window_map_; | |
972 | map<HWND, HWND> root_map_; | |
974 | std::map<HWND, WindowInfo> window_map_; | |
975 | std::map<HWND, HWND> root_map_; | |
973 | 976 | |
974 | 977 | DISALLOW_COPY_AND_ASSIGN(WindowPositionEmulatorImpl); |
975 | 978 | }; |
1665 | 1668 | |
1666 | 1669 | bool LayoutManager::CalcLayoutWithTextWrapping( |
1667 | 1670 | const LOGFONTW &font, |
1668 | const wstring &text, | |
1671 | const std::wstring &text, | |
1669 | 1672 | int maximum_line_length, |
1670 | 1673 | int initial_offset, |
1671 | vector<LineLayout> *line_layouts) { | |
1674 | std::vector<LineLayout> *line_layouts) { | |
1672 | 1675 | if (line_layouts == NULL) { |
1673 | 1676 | return false; |
1674 | 1677 | } |
1761 | 1764 | // more easily. |
1762 | 1765 | bool LayoutManager::LayoutCompositionWindow( |
1763 | 1766 | const commands::RendererCommand &command, |
1764 | vector<CompositionWindowLayout> *composition_window_layouts, | |
1767 | std::vector<CompositionWindowLayout> *composition_window_layouts, | |
1765 | 1768 | CandidateWindowLayout *candidate_layout) const { |
1766 | 1769 | if (composition_window_layouts != NULL) { |
1767 | 1770 | composition_window_layouts->clear(); |
1929 | 1932 | } |
1930 | 1933 | |
1931 | 1934 | string preedit_utf8; |
1932 | vector<int> segment_indices; | |
1933 | vector<CharacterRange> segment_lengths; | |
1934 | const wstring composition_text = ComposePreeditText( | |
1935 | std::vector<int> segment_indices; | |
1936 | std::vector<CharacterRange> segment_lengths; | |
1937 | const std::wstring composition_text = ComposePreeditText( | |
1935 | 1938 | preedit, &preedit_utf8, &segment_indices, &segment_lengths); |
1936 | 1939 | DCHECK_EQ(composition_text.size(), segment_indices.size()); |
1937 | 1940 | DCHECK_EQ(preedit.segment_size(), segment_lengths.size()); |
1938 | vector<mozc::renderer::win32::LineLayout> layouts; | |
1941 | std::vector<mozc::renderer::win32::LineLayout> layouts; | |
1939 | 1942 | bool result = false; |
1940 | 1943 | { |
1941 | 1944 | const int offset = is_vertical |
2133 | 2136 | continue; |
2134 | 2137 | } |
2135 | 2138 | const int segment_begin = |
2136 | max(segment_lengths[segment_index].begin, total_characters) - | |
2139 | std::max(segment_lengths[segment_index].begin, total_characters) - | |
2137 | 2140 | total_characters; |
2138 | 2141 | const int segment_end = |
2139 | min(segment_lengths[segment_index].begin + | |
2142 | std::min(segment_lengths[segment_index].begin + | |
2140 | 2143 | segment_lengths[segment_index].length, |
2141 | 2144 | next_total_characters) - total_characters; |
2142 | 2145 | if (segment_begin >= segment_end) { |
2200 | 2203 | // Initialize the |exclusion_area| with invalid data. These values will |
2201 | 2204 | // be updated to be valid at the first turn of the next for-loop. |
2202 | 2205 | // For example, |exclusion_area.left| will be updated as follows. |
2203 | // exclusion_area.left = min(exclusion_area.left, | |
2204 | // numeric_limits<int>::max()); | |
2205 | CRect exclusion_area(numeric_limits<int>::max(), | |
2206 | numeric_limits<int>::max(), | |
2207 | numeric_limits<int>::min(), | |
2208 | numeric_limits<int>::min()); | |
2206 | // exclusion_area.left = std::min(exclusion_area.left, | |
2207 | // std::numeric_limits<int>::max()); | |
2208 | CRect exclusion_area(std::numeric_limits<int>::max(), | |
2209 | std::numeric_limits<int>::max(), | |
2210 | std::numeric_limits<int>::min(), | |
2211 | std::numeric_limits<int>::min()); | |
2209 | 2212 | |
2210 | 2213 | for (size_t i = 0; i < composition_window_layouts->size(); ++i) { |
2211 | 2214 | const CompositionWindowLayout &layout = composition_window_layouts->at(i); |
2213 | 2216 | text_area_in_screen_coord.OffsetRect( |
2214 | 2217 | layout.window_position_in_screen_coordinate.left, |
2215 | 2218 | layout.window_position_in_screen_coordinate.top); |
2216 | exclusion_area.left = min(exclusion_area.left, | |
2217 | text_area_in_screen_coord.left); | |
2218 | exclusion_area.top = min(exclusion_area.top, | |
2219 | text_area_in_screen_coord.top); | |
2220 | exclusion_area.right = max(exclusion_area.right, | |
2221 | text_area_in_screen_coord.right); | |
2222 | exclusion_area.bottom = max(exclusion_area.bottom, | |
2223 | text_area_in_screen_coord.bottom); | |
2219 | exclusion_area.left = std::min(exclusion_area.left, | |
2220 | text_area_in_screen_coord.left); | |
2221 | exclusion_area.top = std::min(exclusion_area.top, | |
2222 | text_area_in_screen_coord.top); | |
2223 | exclusion_area.right = std::max(exclusion_area.right, | |
2224 | text_area_in_screen_coord.right); | |
2225 | exclusion_area.bottom = std::max(exclusion_area.bottom, | |
2226 | text_area_in_screen_coord.bottom); | |
2224 | 2227 | } |
2225 | 2228 | |
2226 | 2229 | CPoint cursor_pos; |
2537 | 2540 | return COMPATIBILITY_MODE_NONE; |
2538 | 2541 | } |
2539 | 2542 | |
2540 | wstring class_name; | |
2543 | std::wstring class_name; | |
2541 | 2544 | if (!window_position_->GetWindowClassName(target_window, &class_name)) { |
2542 | 2545 | return COMPATIBILITY_MODE_NONE; |
2543 | 2546 | } |
62 | 62 | }; |
63 | 63 | |
64 | 64 | struct LineLayout { |
65 | wstring text; | |
65 | std::wstring text; | |
66 | 66 | int line_length; |
67 | 67 | int line_width; |
68 | 68 | int line_start_offset; |
69 | vector<CharacterRange> character_positions; | |
69 | std::vector<CharacterRange> character_positions; | |
70 | 70 | LineLayout(); |
71 | 71 | }; |
72 | 72 | |
83 | 83 | RECT caret_rect; |
84 | 84 | POINT base_position; |
85 | 85 | LOGFONT log_font; |
86 | wstring text; | |
87 | vector<SegmentMarkerLayout> marker_layouts; | |
86 | std::wstring text; | |
87 | std::vector<SegmentMarkerLayout> marker_layouts; | |
88 | 88 | CompositionWindowLayout(); |
89 | 89 | }; |
90 | 90 | |
215 | 215 | virtual HWND GetRootWindow(HWND window_handle) = 0; |
216 | 216 | |
217 | 217 | // This method wraps API call of GetClassName. |
218 | virtual bool GetWindowClassName(HWND window_handle, wstring *class_name) = 0; | |
218 | virtual bool GetWindowClassName(HWND window_handle, | |
219 | std::wstring *class_name) = 0; | |
219 | 220 | }; |
220 | 221 | |
221 | 222 | // This class implements WindowPositionInterface and emulates APIs |
229 | 230 | // WindowPositionInterface with this dummy handle. You need not to release |
230 | 231 | // the returned handle. |
231 | 232 | virtual HWND RegisterWindow( |
232 | const wstring &class_name, const RECT &window_rect, | |
233 | const std::wstring &class_name, const RECT &window_rect, | |
233 | 234 | const POINT &client_area_offset, const SIZE &client_area_size, |
234 | 235 | double scale_factor) = 0; |
235 | 236 | |
292 | 293 | // displayed. |
293 | 294 | bool LayoutCompositionWindow( |
294 | 295 | const commands::RendererCommand &command, |
295 | vector<CompositionWindowLayout> *composition_window_layouts, | |
296 | std::vector<CompositionWindowLayout> *composition_window_layouts, | |
296 | 297 | CandidateWindowLayout* candidate_layout) const; |
297 | 298 | |
298 | 299 | // Returns compatibility bits for given target application. |
418 | 419 | // LineLayout: Layout information for each split line. |
419 | 420 | static bool CalcLayoutWithTextWrapping( |
420 | 421 | const LOGFONTW &font, |
421 | const wstring &text, | |
422 | const std::wstring &text, | |
422 | 423 | int maximum_line_length, |
423 | 424 | int initial_offset, |
424 | vector<LineLayout> *line_layouts); | |
425 | std::vector<LineLayout> *line_layouts); | |
425 | 426 | |
426 | 427 | std::unique_ptr<SystemPreferenceInterface> system_preference_; |
427 | 428 | std::unique_ptr<WindowPositionInterface> window_position_; |
143 | 143 | } while (false) |
144 | 144 | |
145 | 145 | WindowPositionEmulator *CreateWindowEmulator( |
146 | const wstring &class_name, const RECT &window_rect, | |
146 | const std::wstring &class_name, const RECT &window_rect, | |
147 | 147 | const POINT &client_area_offset, const SIZE &client_area_size, |
148 | 148 | double scale_factor, HWND *hwnd) { |
149 | 149 | WindowPositionEmulator *emulator = WindowPositionEmulator::Create(); |
164 | 164 | } |
165 | 165 | |
166 | 166 | WindowPositionEmulator *CreateWindowEmulatorWithClassName( |
167 | const wstring &class_name, HWND *hwnd) { | |
167 | const std::wstring &class_name, HWND *hwnd) { | |
168 | 168 | const CPoint kClientOffset(8, 42); |
169 | 169 | const CSize kClientSize(2000, 1000); |
170 | 170 | const CRect kWindowRect(500, 500, 2516, 1550); |
284 | 284 | } |
285 | 285 | |
286 | 286 | static CLogFont GetFont(bool is_proportional, bool is_vertical) { |
287 | wstring font_face; | |
287 | std::wstring font_face; | |
288 | 288 | Util::UTF8ToWide((is_proportional ? GetPropotionalFontFaceForTest() |
289 | 289 | : GetMonospacedFontFaceForTest()), |
290 | 290 | &font_face); |
320 | 320 | return SystemPreferenceFactory::CreateMock(font); |
321 | 321 | } |
322 | 322 | |
323 | static wstring GetTestMessageWithCompositeGlyph(int num_repeat) { | |
324 | wstring message; | |
323 | static std::wstring GetTestMessageWithCompositeGlyph(int num_repeat) { | |
324 | std::wstring message; | |
325 | 325 | for (size_t i = 0; i < num_repeat; ++i) { |
326 | 326 | // "ぱ" |
327 | 327 | message += L'\u3071'; |
330 | 330 | return message; |
331 | 331 | } |
332 | 332 | |
333 | static wstring GetTestMessageForMonospaced() { | |
334 | wstring w_path; | |
333 | static std::wstring GetTestMessageForMonospaced() { | |
334 | std::wstring w_path; | |
335 | 335 | const char kMessage[] = "熊本県阿蘇郡南阿蘇村大字中松南阿蘇水の生まれる里白水高原駅"; |
336 | wstring w_message; | |
336 | std::wstring w_message; | |
337 | 337 | Util::UTF8ToWide(kMessage, &w_message); |
338 | 338 | return w_message; |
339 | 339 | } |
340 | 340 | |
341 | static wstring GetTestMessageForProportional() { | |
342 | wstring w_path; | |
341 | static std::wstring GetTestMessageForProportional() { | |
342 | std::wstring w_path; | |
343 | 343 | const char kMessage[] = |
344 | 344 | "This open-source project originates from Google 日本語入力."; |
345 | wstring w_message; | |
345 | std::wstring w_message; | |
346 | 346 | Util::UTF8ToWide(kMessage, &w_message); |
347 | 347 | return w_message; |
348 | 348 | } |
1022 | 1022 | EXPECT_TRUE(emulator->ClientToScreen(hwnd, &point)); |
1023 | 1023 | EXPECT_EQ(kWindowRect.TopLeft() + kClientOffset, point); |
1024 | 1024 | |
1025 | wstring class_name; | |
1025 | std::wstring class_name; | |
1026 | 1026 | EXPECT_TRUE(emulator->GetWindowClassName(hwnd, &class_name)); |
1027 | 1027 | EXPECT_EQ(kWindowClassName, class_name); |
1028 | 1028 | } |
1053 | 1053 | EXPECT_TRUE(emulator->ClientToScreen(hwnd, &point)); |
1054 | 1054 | EXPECT_EQ(kWindowRect.TopLeft() + kClientOffset, point); |
1055 | 1055 | |
1056 | wstring class_name; | |
1056 | std::wstring class_name; | |
1057 | 1057 | EXPECT_TRUE(emulator->GetWindowClassName(hwnd, &class_name)); |
1058 | 1058 | EXPECT_EQ(kWindowClassName, class_name); |
1059 | 1059 | } |
1062 | 1062 | TEST_F(Win32RendererUtilTest, HorizontalProportional) { |
1063 | 1063 | const CLogFont &logfont = GetFont(true, false); |
1064 | 1064 | |
1065 | vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1065 | std::vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1066 | 1066 | bool result = true; |
1067 | 1067 | |
1068 | const wstring &message = GetTestMessageForProportional(); | |
1068 | const std::wstring &message = GetTestMessageForProportional(); | |
1069 | 1069 | |
1070 | 1070 | // Check if the |initial_offset| works as expected. |
1071 | 1071 | result = LayoutManager::CalcLayoutWithTextWrapping( |
1120 | 1120 | TEST_F(Win32RendererUtilTest, VerticalProportional) { |
1121 | 1121 | const CLogFont &logfont = GetFont(true, true); |
1122 | 1122 | |
1123 | vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1123 | std::vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1124 | 1124 | bool result = true; |
1125 | 1125 | |
1126 | const wstring &message = GetTestMessageForProportional(); | |
1126 | const std::wstring &message = GetTestMessageForProportional(); | |
1127 | 1127 | |
1128 | 1128 | // Check if the |initial_offset| works as expected. |
1129 | 1129 | result = LayoutManager::CalcLayoutWithTextWrapping( |
1178 | 1178 | TEST_F(Win32RendererUtilTest, HorizontalMonospaced) { |
1179 | 1179 | const CLogFont &logfont = GetFont(false, false); |
1180 | 1180 | |
1181 | vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1181 | std::vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1182 | 1182 | bool result = true; |
1183 | 1183 | |
1184 | const wstring &message = GetTestMessageForMonospaced(); | |
1184 | const std::wstring &message = GetTestMessageForMonospaced(); | |
1185 | 1185 | |
1186 | 1186 | // Check if the |initial_offset| works as expected. |
1187 | 1187 | result = LayoutManager::CalcLayoutWithTextWrapping( |
1236 | 1236 | TEST_F(Win32RendererUtilTest, VerticalMonospaced) { |
1237 | 1237 | const CLogFont &logfont = GetFont(false, true); |
1238 | 1238 | |
1239 | vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1239 | std::vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1240 | 1240 | bool result = true; |
1241 | 1241 | |
1242 | const wstring &message = GetTestMessageForMonospaced(); | |
1242 | const std::wstring &message = GetTestMessageForMonospaced(); | |
1243 | 1243 | |
1244 | 1244 | // Check if the |initial_offset| works as expected. |
1245 | 1245 | result = LayoutManager::CalcLayoutWithTextWrapping( |
1294 | 1294 | TEST_F(Win32RendererUtilTest, HorizontalProportionalCompositeGlyph) { |
1295 | 1295 | const CLogFont &logfont = GetFont(true, false); |
1296 | 1296 | |
1297 | vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1297 | std::vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1298 | 1298 | bool result = true; |
1299 | 1299 | |
1300 | const wstring &message = GetTestMessageWithCompositeGlyph(1); | |
1300 | const std::wstring &message = GetTestMessageWithCompositeGlyph(1); | |
1301 | 1301 | |
1302 | 1302 | result = LayoutManager::CalcLayoutWithTextWrapping( |
1303 | 1303 | logfont, message, 200, 100, &line_layouts); |
1314 | 1314 | TEST_F(Win32RendererUtilTest, VerticalProportionalCompositeGlyph) { |
1315 | 1315 | const CLogFont &logfont = GetFont(true, true); |
1316 | 1316 | |
1317 | vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1317 | std::vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1318 | 1318 | bool result = true; |
1319 | 1319 | |
1320 | const wstring &message = GetTestMessageWithCompositeGlyph(1); | |
1320 | const std::wstring &message = GetTestMessageWithCompositeGlyph(1); | |
1321 | 1321 | result = LayoutManager::CalcLayoutWithTextWrapping( |
1322 | 1322 | logfont, message, 200, 100, &line_layouts); |
1323 | 1323 | EXPECT_TRUE(result); |
1333 | 1333 | TEST_F(Win32RendererUtilTest, HorizontalMonospacedCompositeGlyph) { |
1334 | 1334 | const CLogFont &logfont = GetFont(false, false); |
1335 | 1335 | |
1336 | vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1336 | std::vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1337 | 1337 | bool result = true; |
1338 | 1338 | |
1339 | const wstring &message = GetTestMessageWithCompositeGlyph(1); | |
1339 | const std::wstring &message = GetTestMessageWithCompositeGlyph(1); | |
1340 | 1340 | |
1341 | 1341 | result = LayoutManager::CalcLayoutWithTextWrapping( |
1342 | 1342 | logfont, message, 200, 100, &line_layouts); |
1353 | 1353 | TEST_F(Win32RendererUtilTest, VerticalMonospacedCompositeGlyph) { |
1354 | 1354 | const CLogFont &logfont = GetFont(false, true); |
1355 | 1355 | |
1356 | vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1356 | std::vector<mozc::renderer::win32::LineLayout> line_layouts; | |
1357 | 1357 | bool result = true; |
1358 | 1358 | |
1359 | const wstring &message = GetTestMessageWithCompositeGlyph(1); | |
1359 | const std::wstring &message = GetTestMessageWithCompositeGlyph(1); | |
1360 | 1360 | |
1361 | 1361 | result = LayoutManager::CalcLayoutWithTextWrapping( |
1362 | 1362 | logfont, message, 200, 100, &line_layouts); |
1379 | 1379 | HWND hwnd = nullptr; |
1380 | 1380 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
1381 | 1381 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
1382 | vector<CompositionWindowLayout> layouts; | |
1382 | std::vector<CompositionWindowLayout> layouts; | |
1383 | 1383 | CandidateWindowLayout candidate_layout; |
1384 | 1384 | |
1385 | 1385 | CLogFont logfont; |
1406 | 1406 | 0, 0, 0, 0, 0, 0, logfont, layout); |
1407 | 1407 | { |
1408 | 1408 | const char kMsg[] = "これは"; |
1409 | wstring msg; | |
1409 | std::wstring msg; | |
1410 | 1410 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1411 | 1411 | EXPECT_EQ(msg, layout.text); |
1412 | 1412 | } |
1424 | 1424 | 0, 0, 646, 0, 647, 49, logfont, layout); |
1425 | 1425 | { |
1426 | 1426 | const char kMsg[] = "、Google日本語入力のTestです"; |
1427 | wstring msg; | |
1427 | std::wstring msg; | |
1428 | 1428 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1429 | 1429 | EXPECT_EQ(msg, layout.text); |
1430 | 1430 | } |
1500 | 1500 | HWND hwnd = nullptr; |
1501 | 1501 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
1502 | 1502 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
1503 | vector<CompositionWindowLayout> layouts; | |
1503 | std::vector<CompositionWindowLayout> layouts; | |
1504 | 1504 | CandidateWindowLayout candidate_layout; |
1505 | 1505 | CLogFont logfont; |
1506 | 1506 | |
1526 | 1526 | 0, 0, 0, 0, 0, 0, logfont, layout); |
1527 | 1527 | { |
1528 | 1528 | const char kMsg[] = "これは、Go"; |
1529 | wstring msg; | |
1529 | std::wstring msg; | |
1530 | 1530 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1531 | 1531 | EXPECT_EQ(msg, layout.text); |
1532 | 1532 | } |
1550 | 1550 | 0, 0, 540, 0, 541, 49, logfont, layout); |
1551 | 1551 | { |
1552 | 1552 | const char kMsg[] = "ogle日本語入力のTestです"; |
1553 | wstring msg; | |
1553 | std::wstring msg; | |
1554 | 1554 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1555 | 1555 | EXPECT_EQ(msg, layout.text); |
1556 | 1556 | } |
1624 | 1624 | HWND hwnd = nullptr; |
1625 | 1625 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
1626 | 1626 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
1627 | vector<CompositionWindowLayout> layouts; | |
1627 | std::vector<CompositionWindowLayout> layouts; | |
1628 | 1628 | CandidateWindowLayout candidate_layout; |
1629 | 1629 | CLogFont logfont; |
1630 | 1630 | |
1652 | 1652 | 51, 0, 0, 0, 0, 0, logfont, layout); |
1653 | 1653 | { |
1654 | 1654 | const char kMsg[] = "これは"; |
1655 | wstring msg; | |
1655 | std::wstring msg; | |
1656 | 1656 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1657 | 1657 | EXPECT_EQ(msg, layout.text); |
1658 | 1658 | } |
1670 | 1670 | 51, 0, 0, 0, 0, 0, logfont, layout); |
1671 | 1671 | { |
1672 | 1672 | const char kMsg[] = "、Google日本語入"; |
1673 | wstring msg; | |
1673 | std::wstring msg; | |
1674 | 1674 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1675 | 1675 | EXPECT_EQ(msg, layout.text); |
1676 | 1676 | } |
1694 | 1694 | 51, 0, 0, 270, 51, 271, logfont, layout); |
1695 | 1695 | { |
1696 | 1696 | const char kMsg[] = "力のTestです"; |
1697 | wstring msg; | |
1697 | std::wstring msg; | |
1698 | 1698 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1699 | 1699 | EXPECT_EQ(msg, layout.text); |
1700 | 1700 | } |
1765 | 1765 | HWND hwnd = nullptr; |
1766 | 1766 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
1767 | 1767 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
1768 | vector<CompositionWindowLayout> layouts; | |
1768 | std::vector<CompositionWindowLayout> layouts; | |
1769 | 1769 | CandidateWindowLayout candidate_layout; |
1770 | 1770 | CLogFont logfont; |
1771 | 1771 | |
1793 | 1793 | 51, 0, 0, 0, 0, 0, logfont, layout); |
1794 | 1794 | { |
1795 | 1795 | const char kMsg[] = "これは、Goo"; |
1796 | wstring msg; | |
1796 | std::wstring msg; | |
1797 | 1797 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1798 | 1798 | EXPECT_EQ(msg, layout.text); |
1799 | 1799 | } |
1817 | 1817 | 51, 0, 0, 0, 0, 0, logfont, layout); |
1818 | 1818 | { |
1819 | 1819 | const char kMsg[] = "gle日本語入力のTe"; |
1820 | wstring msg; | |
1820 | std::wstring msg; | |
1821 | 1821 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1822 | 1822 | EXPECT_EQ(msg, layout.text); |
1823 | 1823 | } |
1841 | 1841 | 51, 0, 0, 127, 51, 128, logfont, layout); |
1842 | 1842 | { |
1843 | 1843 | const char kMsg[] = "stです"; |
1844 | wstring msg; | |
1844 | std::wstring msg; | |
1845 | 1845 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1846 | 1846 | EXPECT_EQ(msg, layout.text); |
1847 | 1847 | } |
1909 | 1909 | HWND hwnd = nullptr; |
1910 | 1910 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
1911 | 1911 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
1912 | vector<CompositionWindowLayout> layouts; | |
1912 | std::vector<CompositionWindowLayout> layouts; | |
1913 | 1913 | CandidateWindowLayout candidate_layout; |
1914 | 1914 | CLogFont logfont; |
1915 | 1915 | |
1935 | 1935 | 0, 0, 0, 0, 0, 0, logfont, layout); |
1936 | 1936 | { |
1937 | 1937 | const char kMsg[] = "これは"; |
1938 | wstring msg; | |
1938 | std::wstring msg; | |
1939 | 1939 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1940 | 1940 | EXPECT_EQ(msg, layout.text); |
1941 | 1941 | } |
1953 | 1953 | 0, 0, 646, 0, 647, 54, logfont, layout); |
1954 | 1954 | { |
1955 | 1955 | const char kMsg[] = "、Google日本語入力のTestです"; |
1956 | wstring msg; | |
1956 | std::wstring msg; | |
1957 | 1957 | mozc::Util::UTF8ToWide(kMsg, &msg); |
1958 | 1958 | EXPECT_EQ(msg, layout.text); |
1959 | 1959 | } |
2030 | 2030 | HWND hwnd = nullptr; |
2031 | 2031 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2032 | 2032 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2033 | vector<CompositionWindowLayout> layouts; | |
2033 | std::vector<CompositionWindowLayout> layouts; | |
2034 | 2034 | CandidateWindowLayout candidate_layout; |
2035 | 2035 | CLogFont logfont; |
2036 | 2036 | |
2056 | 2056 | 0, 0, 0, 0, 0, 0, logfont, layout); |
2057 | 2057 | { |
2058 | 2058 | const char kMsg[] = "これは、Go"; |
2059 | wstring msg; | |
2059 | std::wstring msg; | |
2060 | 2060 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2061 | 2061 | EXPECT_EQ(msg, layout.text); |
2062 | 2062 | } |
2080 | 2080 | 0, 0, 539, 0, 540, 54, logfont, layout); |
2081 | 2081 | { |
2082 | 2082 | const char kMsg[] = "ogle日本語入力のTestです"; |
2083 | wstring msg; | |
2083 | std::wstring msg; | |
2084 | 2084 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2085 | 2085 | EXPECT_EQ(msg, layout.text); |
2086 | 2086 | } |
2154 | 2154 | HWND hwnd = nullptr; |
2155 | 2155 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2156 | 2156 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2157 | vector<CompositionWindowLayout> layouts; | |
2157 | std::vector<CompositionWindowLayout> layouts; | |
2158 | 2158 | CandidateWindowLayout candidate_layout; |
2159 | 2159 | CLogFont logfont; |
2160 | 2160 | |
2182 | 2182 | 56, 0, 0, 0, 0, 0, logfont, layout); |
2183 | 2183 | { |
2184 | 2184 | const char kMsg[] = "これは"; |
2185 | wstring msg; | |
2185 | std::wstring msg; | |
2186 | 2186 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2187 | 2187 | EXPECT_EQ(msg, layout.text); |
2188 | 2188 | } |
2200 | 2200 | 56, 0, 0, 0, 0, 0, logfont, layout); |
2201 | 2201 | { |
2202 | 2202 | const char kMsg[] = "、Google日本語入"; |
2203 | wstring msg; | |
2203 | std::wstring msg; | |
2204 | 2204 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2205 | 2205 | EXPECT_EQ(msg, layout.text); |
2206 | 2206 | } |
2224 | 2224 | 56, 0, 0, 269, 56, 270, logfont, layout); |
2225 | 2225 | { |
2226 | 2226 | const char kMsg[] = "力のTestです"; |
2227 | wstring msg; | |
2227 | std::wstring msg; | |
2228 | 2228 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2229 | 2229 | EXPECT_EQ(msg, layout.text); |
2230 | 2230 | } |
2295 | 2295 | HWND hwnd = nullptr; |
2296 | 2296 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2297 | 2297 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2298 | vector<CompositionWindowLayout> layouts; | |
2298 | std::vector<CompositionWindowLayout> layouts; | |
2299 | 2299 | CandidateWindowLayout candidate_layout; |
2300 | 2300 | CLogFont logfont; |
2301 | 2301 | |
2323 | 2323 | 56, 0, 0, 0, 0, 0, logfont, layout); |
2324 | 2324 | { |
2325 | 2325 | const char kMsg[] = "これは、Go"; |
2326 | wstring msg; | |
2326 | std::wstring msg; | |
2327 | 2327 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2328 | 2328 | EXPECT_EQ(msg, layout.text); |
2329 | 2329 | } |
2347 | 2347 | 56, 0, 0, 0, 0, 0, logfont, layout); |
2348 | 2348 | { |
2349 | 2349 | const char kMsg[] = "ogle日本語入力のT"; |
2350 | wstring msg; | |
2350 | std::wstring msg; | |
2351 | 2351 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2352 | 2352 | EXPECT_EQ(msg, layout.text); |
2353 | 2353 | } |
2371 | 2371 | 56, 0, 0, 151, 56, 152, logfont, layout); |
2372 | 2372 | { |
2373 | 2373 | const char kMsg[] = "estです"; |
2374 | wstring msg; | |
2374 | std::wstring msg; | |
2375 | 2375 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2376 | 2376 | EXPECT_EQ(msg, layout.text); |
2377 | 2377 | } |
2439 | 2439 | HWND hwnd = nullptr; |
2440 | 2440 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2441 | 2441 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2442 | vector<CompositionWindowLayout> layouts; | |
2442 | std::vector<CompositionWindowLayout> layouts; | |
2443 | 2443 | CandidateWindowLayout candidate_layout; |
2444 | 2444 | CLogFont logfont; |
2445 | 2445 | |
2465 | 2465 | 0, 0, 781, 0, 782, 49, logfont, layout); |
2466 | 2466 | { |
2467 | 2467 | const char kMsg[] = "これは、Google日本語入力のTestです"; |
2468 | wstring msg; | |
2468 | std::wstring msg; | |
2469 | 2469 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2470 | 2470 | EXPECT_EQ(msg, layout.text); |
2471 | 2471 | } |
2498 | 2498 | HWND hwnd = nullptr; |
2499 | 2499 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2500 | 2500 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2501 | vector<CompositionWindowLayout> layouts; | |
2501 | std::vector<CompositionWindowLayout> layouts; | |
2502 | 2502 | CandidateWindowLayout candidate_layout; |
2503 | 2503 | CLogFont logfont; |
2504 | 2504 | |
2524 | 2524 | 0, 0, 781, 0, 782, 54, logfont, layout); |
2525 | 2525 | { |
2526 | 2526 | const char kMsg[] = "これは、Google日本語入力のTestです"; |
2527 | wstring msg; | |
2527 | std::wstring msg; | |
2528 | 2528 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2529 | 2529 | EXPECT_EQ(msg, layout.text); |
2530 | 2530 | } |
2557 | 2557 | HWND hwnd = nullptr; |
2558 | 2558 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2559 | 2559 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2560 | vector<CompositionWindowLayout> layouts; | |
2560 | std::vector<CompositionWindowLayout> layouts; | |
2561 | 2561 | CandidateWindowLayout candidate_layout; |
2562 | 2562 | CLogFont logfont; |
2563 | 2563 | |
2585 | 2585 | 51, 0, 0, 0, 0, 0, logfont, layout); |
2586 | 2586 | { |
2587 | 2587 | const char kMsg[] = "これは、Google日"; |
2588 | wstring msg; | |
2588 | std::wstring msg; | |
2589 | 2589 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2590 | 2590 | EXPECT_EQ(msg, layout.text); |
2591 | 2591 | } |
2612 | 2612 | 51, 0, 0, 0, 0, 0, logfont, layout); |
2613 | 2613 | { |
2614 | 2614 | const char kMsg[] = "本語入力のTestで"; |
2615 | wstring msg; | |
2615 | std::wstring msg; | |
2616 | 2616 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2617 | 2617 | EXPECT_EQ(msg, layout.text); |
2618 | 2618 | } |
2633 | 2633 | 51, 0, 0, 45, 51, 46, logfont, layout); |
2634 | 2634 | { |
2635 | 2635 | const char kMsg[] = "す"; |
2636 | wstring msg; | |
2636 | std::wstring msg; | |
2637 | 2637 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2638 | 2638 | EXPECT_EQ(msg, layout.text); |
2639 | 2639 | } |
2654 | 2654 | HWND hwnd = nullptr; |
2655 | 2655 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2656 | 2656 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2657 | vector<CompositionWindowLayout> layouts; | |
2657 | std::vector<CompositionWindowLayout> layouts; | |
2658 | 2658 | CandidateWindowLayout candidate_layout; |
2659 | 2659 | CLogFont logfont; |
2660 | 2660 | |
2682 | 2682 | 56, 0, 0, 0, 0, 0, logfont, layout); |
2683 | 2683 | { |
2684 | 2684 | const char kMsg[] = "これは、Google日"; |
2685 | wstring msg; | |
2685 | std::wstring msg; | |
2686 | 2686 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2687 | 2687 | EXPECT_EQ(msg, layout.text); |
2688 | 2688 | } |
2709 | 2709 | 56, 0, 0, 0, 0, 0, logfont, layout); |
2710 | 2710 | { |
2711 | 2711 | const char kMsg[] = "本語入力のTestで"; |
2712 | wstring msg; | |
2712 | std::wstring msg; | |
2713 | 2713 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2714 | 2714 | EXPECT_EQ(msg, layout.text); |
2715 | 2715 | } |
2730 | 2730 | 56, 0, 0, 45, 56, 46, logfont, layout); |
2731 | 2731 | { |
2732 | 2732 | const char kMsg[] = "す"; |
2733 | wstring msg; | |
2733 | std::wstring msg; | |
2734 | 2734 | mozc::Util::UTF8ToWide(kMsg, &msg); |
2735 | 2735 | EXPECT_EQ(msg, layout.text); |
2736 | 2736 | } |
2749 | 2749 | HWND hwnd = nullptr; |
2750 | 2750 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2751 | 2751 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2752 | vector<CompositionWindowLayout> layouts; | |
2752 | std::vector<CompositionWindowLayout> layouts; | |
2753 | 2753 | |
2754 | 2754 | RendererCommand command; |
2755 | 2755 | CandidateWindowLayout candidate_layout; |
2780 | 2780 | HWND hwnd = nullptr; |
2781 | 2781 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2782 | 2782 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2783 | vector<CompositionWindowLayout> layouts; | |
2783 | std::vector<CompositionWindowLayout> layouts; | |
2784 | 2784 | |
2785 | 2785 | RendererCommand command; |
2786 | 2786 | CandidateWindowLayout candidate_layout; |
2813 | 2813 | HWND hwnd = nullptr; |
2814 | 2814 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2815 | 2815 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2816 | vector<CompositionWindowLayout> layouts; | |
2816 | std::vector<CompositionWindowLayout> layouts; | |
2817 | 2817 | |
2818 | 2818 | RendererCommand command; |
2819 | 2819 | CandidateWindowLayout candidate_layout; |
2845 | 2845 | HWND hwnd = nullptr; |
2846 | 2846 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2847 | 2847 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2848 | vector<CompositionWindowLayout> layouts; | |
2848 | std::vector<CompositionWindowLayout> layouts; | |
2849 | 2849 | |
2850 | 2850 | RendererCommand command; |
2851 | 2851 | CandidateWindowLayout candidate_layout; |
2877 | 2877 | HWND hwnd = nullptr; |
2878 | 2878 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2879 | 2879 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2880 | vector<CompositionWindowLayout> layouts; | |
2880 | std::vector<CompositionWindowLayout> layouts; | |
2881 | 2881 | |
2882 | 2882 | RendererCommand command; |
2883 | 2883 | CandidateWindowLayout candidate_layout; |
2916 | 2916 | HWND hwnd = nullptr; |
2917 | 2917 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2918 | 2918 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2919 | vector<CompositionWindowLayout> layouts; | |
2919 | std::vector<CompositionWindowLayout> layouts; | |
2920 | 2920 | |
2921 | 2921 | RendererCommand command; |
2922 | 2922 | CandidateWindowLayout candidate_layout; |
2949 | 2949 | HWND hwnd = nullptr; |
2950 | 2950 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2951 | 2951 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2952 | vector<CompositionWindowLayout> layouts; | |
2952 | std::vector<CompositionWindowLayout> layouts; | |
2953 | 2953 | |
2954 | 2954 | RendererCommand command; |
2955 | 2955 | CandidateWindowLayout candidate_layout; |
2984 | 2984 | HWND hwnd = nullptr; |
2985 | 2985 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
2986 | 2986 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
2987 | vector<CompositionWindowLayout> layouts; | |
2987 | std::vector<CompositionWindowLayout> layouts; | |
2988 | 2988 | |
2989 | 2989 | RendererCommand command; |
2990 | 2990 | CandidateWindowLayout candidate_layout; |
3018 | 3018 | HWND hwnd = nullptr; |
3019 | 3019 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
3020 | 3020 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
3021 | vector<CompositionWindowLayout> layouts; | |
3021 | std::vector<CompositionWindowLayout> layouts; | |
3022 | 3022 | |
3023 | 3023 | RendererCommand command; |
3024 | 3024 | CandidateWindowLayout candidate_layout; |
3052 | 3052 | HWND hwnd = nullptr; |
3053 | 3053 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
3054 | 3054 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
3055 | vector<CompositionWindowLayout> layouts; | |
3055 | std::vector<CompositionWindowLayout> layouts; | |
3056 | 3056 | |
3057 | 3057 | RendererCommand command; |
3058 | 3058 | CandidateWindowLayout candidate_layout; |
3096 | 3096 | HWND hwnd = nullptr; |
3097 | 3097 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
3098 | 3098 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
3099 | vector<CompositionWindowLayout> layouts; | |
3099 | std::vector<CompositionWindowLayout> layouts; | |
3100 | 3100 | CandidateWindowLayout candidate_layout; |
3101 | 3101 | CLogFont logfont; |
3102 | 3102 | |
3131 | 3131 | HWND hwnd = nullptr; |
3132 | 3132 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
3133 | 3133 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
3134 | vector<CompositionWindowLayout> layouts; | |
3134 | std::vector<CompositionWindowLayout> layouts; | |
3135 | 3135 | CandidateWindowLayout candidate_layout; |
3136 | 3136 | CLogFont logfont; |
3137 | 3137 | |
3163 | 3163 | HWND hwnd = nullptr; |
3164 | 3164 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
3165 | 3165 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
3166 | vector<CompositionWindowLayout> layouts; | |
3166 | std::vector<CompositionWindowLayout> layouts; | |
3167 | 3167 | |
3168 | 3168 | RendererCommand command; |
3169 | 3169 | CandidateWindowLayout candidate_layout; |
3202 | 3202 | HWND hwnd = nullptr; |
3203 | 3203 | LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(), |
3204 | 3204 | CreateWindowEmulatorWithDPIScaling(1.0, &hwnd)); |
3205 | vector<CompositionWindowLayout> layouts; | |
3205 | std::vector<CompositionWindowLayout> layouts; | |
3206 | 3206 | CandidateWindowLayout candidate_layout; |
3207 | 3207 | |
3208 | 3208 | CLogFont logfont; |
3232 | 3232 | 0, 0, 0, 0, 0, 0, logfont, layout); |
3233 | 3233 | { |
3234 | 3234 | const char kMsg[] = "これは"; |
3235 | wstring msg; | |
3235 | std::wstring msg; | |
3236 | 3236 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3237 | 3237 | EXPECT_EQ(msg, layout.text); |
3238 | 3238 | } |
3250 | 3250 | 0, 0, 646, 0, 647, 49, logfont, layout); |
3251 | 3251 | { |
3252 | 3252 | const char kMsg[] = "、Google日本語入力のTestです"; |
3253 | wstring msg; | |
3253 | std::wstring msg; | |
3254 | 3254 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3255 | 3255 | EXPECT_EQ(msg, layout.text); |
3256 | 3256 | } |
3355 | 3355 | command.mutable_application_info(), false, 0, 0, 0, 0, hwnd); |
3356 | 3356 | |
3357 | 3357 | CandidateWindowLayout candidate_layout; |
3358 | vector<CompositionWindowLayout> layouts; | |
3358 | std::vector<CompositionWindowLayout> layouts; | |
3359 | 3359 | bool result = false; |
3360 | 3360 | |
3361 | 3361 | layouts.clear(); |
3378 | 3378 | 0, 0, 0, 0, 0, 0, default_font, layout); |
3379 | 3379 | { |
3380 | 3380 | const char kMsg[] = "これは、Google日本語入力のTest"; |
3381 | wstring msg; | |
3381 | std::wstring msg; | |
3382 | 3382 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3383 | 3383 | EXPECT_EQ(msg, layout.text); |
3384 | 3384 | } |
3408 | 3408 | 0, 0, 30, 0, 31, 18, default_font, layout); |
3409 | 3409 | { |
3410 | 3410 | const char kMsg[] = "です"; |
3411 | wstring msg; | |
3411 | std::wstring msg; | |
3412 | 3412 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3413 | 3413 | EXPECT_EQ(msg, layout.text); |
3414 | 3414 | } |
3470 | 3470 | false, 34, 0, 36, 14, hwnd); |
3471 | 3471 | |
3472 | 3472 | CandidateWindowLayout candidate_layout; |
3473 | vector<CompositionWindowLayout> layouts; | |
3473 | std::vector<CompositionWindowLayout> layouts; | |
3474 | 3474 | bool result = false; |
3475 | 3475 | |
3476 | 3476 | layouts.clear(); |
3493 | 3493 | 259, 0, 260, 18, default_font, layout); |
3494 | 3494 | { |
3495 | 3495 | const char kMsg[] = "これは、Google日本語入力のTestです"; |
3496 | wstring msg; | |
3496 | std::wstring msg; | |
3497 | 3497 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3498 | 3498 | EXPECT_EQ(msg, layout.text); |
3499 | 3499 | } |
3585 | 3585 | true, 2, 1, 3, 19, child_window); |
3586 | 3586 | |
3587 | 3587 | CandidateWindowLayout candidate_layout; |
3588 | vector<CompositionWindowLayout> layouts; | |
3588 | std::vector<CompositionWindowLayout> layouts; | |
3589 | 3589 | bool result = false; |
3590 | 3590 | |
3591 | 3591 | layouts.clear(); |
3608 | 3608 | 0, 0, 0, 0, default_font, layout); |
3609 | 3609 | { |
3610 | 3610 | const char kMsg[] = "これは、Google"; |
3611 | wstring msg; | |
3611 | std::wstring msg; | |
3612 | 3612 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3613 | 3613 | EXPECT_EQ(msg, layout.text); |
3614 | 3614 | } |
3632 | 3632 | 0, 0, 0, 0, default_font, layout); |
3633 | 3633 | { |
3634 | 3634 | const char kMsg[] = "日本語入力のTes"; |
3635 | wstring msg; | |
3635 | std::wstring msg; | |
3636 | 3636 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3637 | 3637 | EXPECT_EQ(msg, layout.text); |
3638 | 3638 | } |
3653 | 3653 | 35, 0, 36, 18, default_font, layout); |
3654 | 3654 | { |
3655 | 3655 | const char kMsg[] = "tです"; |
3656 | wstring msg; | |
3656 | std::wstring msg; | |
3657 | 3657 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3658 | 3658 | EXPECT_EQ(msg, layout.text); |
3659 | 3659 | } |
3686 | 3686 | EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT( |
3687 | 3687 | command.application_info().composition_font(), &logfont)); |
3688 | 3688 | |
3689 | vector<CompositionWindowLayout> layouts; | |
3689 | std::vector<CompositionWindowLayout> layouts; | |
3690 | 3690 | CandidateWindowLayout candidate_layout; |
3691 | 3691 | EXPECT_TRUE(layout_mgr.LayoutCompositionWindow( |
3692 | 3692 | command, &layouts, &candidate_layout)); |
3701 | 3701 | layout); |
3702 | 3702 | { |
3703 | 3703 | const char kMsg[] = "𠮟咤𠮟咤𠮟咤𠮟咤"; |
3704 | wstring msg; | |
3704 | std::wstring msg; | |
3705 | 3705 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3706 | 3706 | EXPECT_EQ(msg, layout.text); |
3707 | 3707 | } |
3744 | 3744 | command.application_info().composition_font(), &logfont)); |
3745 | 3745 | logfont.lfOrientation = 2700; |
3746 | 3746 | |
3747 | vector<CompositionWindowLayout> layouts; | |
3747 | std::vector<CompositionWindowLayout> layouts; | |
3748 | 3748 | CandidateWindowLayout candidate_layout; |
3749 | 3749 | EXPECT_TRUE(layout_mgr.LayoutCompositionWindow( |
3750 | 3750 | command, &layouts, &candidate_layout)); |
3759 | 3759 | 0, 360, 51, 361, logfont, layout); |
3760 | 3760 | { |
3761 | 3761 | const char kMsg[] = "𠮟咤𠮟咤𠮟咤𠮟咤"; |
3762 | wstring msg; | |
3762 | std::wstring msg; | |
3763 | 3763 | mozc::Util::UTF8ToWide(kMsg, &msg); |
3764 | 3764 | EXPECT_EQ(msg, layout.text); |
3765 | 3765 | } |
147 | 147 | |
148 | 148 | bool Win32Server::AsyncExecCommand(string *proto_message) { |
149 | 149 | // Take the ownership of |proto_message|. |
150 | unique_ptr<string> proto_message_owner(proto_message); | |
150 | std::unique_ptr<string> proto_message_owner(proto_message); | |
151 | 151 | scoped_lock l(&mutex_); |
152 | 152 | if (message_ == *proto_message_owner.get()) { |
153 | 153 | // This is exactly the same to the previous message. Theoretically it is |
169 | 169 | ApplicationInfo::ShowCompositionWindow); |
170 | 170 | |
171 | 171 | CandidateWindowLayout candidate_layout; |
172 | vector<CompositionWindowLayout> layouts; | |
172 | std::vector<CompositionWindowLayout> layouts; | |
173 | 173 | if (show_composition) { |
174 | 174 | if (!layout_manager_->LayoutCompositionWindow( |
175 | 175 | command, &layouts, &candidate_layout)) { |
365 | 365 | // If SHOW_INFOLIST_IMMEDIATELY flag is set, we should show the InfoList |
366 | 366 | // without delay. See the comment of SHOW_INFOLIST_IMMEDIATELY in |
367 | 367 | // win32_renderer_util.h or b/5824433 for details. |
368 | uint32 maximum_delay = numeric_limits<int32>::max(); | |
368 | uint32 maximum_delay = std::numeric_limits<int32>::max(); | |
369 | 369 | if ((mode & SHOW_INFOLIST_IMMEDIATELY) == SHOW_INFOLIST_IMMEDIATELY) { |
370 | 370 | maximum_delay = 0; |
371 | 371 | } |
372 | 372 | |
373 | const uint32 hide_window_delay = min(maximum_delay, kHideWindowDelay); | |
373 | const uint32 hide_window_delay = std::min(maximum_delay, kHideWindowDelay); | |
374 | 374 | if (candidates.has_focused_index() && candidates.candidate_size() > 0) { |
375 | 375 | const int focused_row = |
376 | 376 | candidates.focused_index() - candidates.candidate(0).index(); |
377 | 377 | if (candidates.candidate_size() >= focused_row && |
378 | 378 | candidates.candidate(focused_row).has_information_id()) { |
379 | 379 | const uint32 raw_delay = |
380 | max(static_cast<uint32>(0), | |
380 | std::max(static_cast<uint32>(0), | |
381 | 381 | command.output().candidates().usages().delay()); |
382 | const uint32 delay = min(maximum_delay, raw_delay); | |
382 | const uint32 delay = std::min(maximum_delay, raw_delay); | |
383 | 383 | infolist_window_->DelayShow(delay); |
384 | 384 | } else { |
385 | 385 | infolist_window_->DelayHide(hide_window_delay); |
661 | 661 | const size_t j_max = std::min(next_seg->candidates_size(), kCandidateSize); |
662 | 662 | |
663 | 663 | // Cache the results for the next segment |
664 | std::vector<int> next_seg_ok(j_max); // Avoiding vector<bool> | |
664 | std::vector<int> next_seg_ok(j_max); // Avoiding std::vector<bool> | |
665 | 665 | std::vector<std::vector<string> > normalized_string(j_max); |
666 | 666 | |
667 | 667 | // Reuse |nexts| in the loop as this method is performance critical. |
77 | 77 | }; |
78 | 78 | |
79 | 79 | // This function serializes a given message (any type of protobuf message) |
80 | // as a wstring encoded by base64. | |
80 | // as a std::wstring encoded by base64. | |
81 | 81 | // Returns true if succeeds. |
82 | 82 | bool SerializeToBase64WString(const ::google::protobuf::Message &message, |
83 | wstring *dest) { | |
83 | std::wstring *dest) { | |
84 | 84 | if (dest == NULL) { |
85 | 85 | return false; |
86 | 86 | } |
111 | 111 | } |
112 | 112 | |
113 | 113 | // This function deserializes a message (any type of protobuf message) |
114 | // from the given wstring. This wstring should be generated by | |
114 | // from the given std::wstring. This wstring should be generated by | |
115 | 115 | // SerializeToBase64WString. |
116 | 116 | // Returns true if succeeds |
117 | bool DeserializeFromBase64WString(const wstring &src, | |
117 | bool DeserializeFromBase64WString(const std::wstring &src, | |
118 | 118 | ::google::protobuf::Message *message) { |
119 | 119 | if (message == NULL) { |
120 | 120 | return false; |
200 | 200 | } |
201 | 201 | |
202 | 202 | bool StartServiceInternal(const ScopedSCHandle &service_handle, |
203 | const vector<wstring> &arguments) { | |
203 | const std::vector<wstring> &arguments) { | |
204 | 204 | if (arguments.size() <= 0) { |
205 | 205 | if (!::StartService(service_handle.get(), 0, NULL)) { |
206 | 206 | LOG(ERROR) << "StartService failed: " << ::GetLastError(); |
260 | 260 | SERVICE_REQUIRED_PRIVILEGES_INFO privileges_info = {}; |
261 | 261 | // |SERVICE_REQUIRED_PRIVILEGES_INFO::pmszRequiredPrivileges| needs to be |
262 | 262 | // terminated with two L'\0's. |
263 | wstring required_privileges(SE_INC_BASE_PRIORITY_NAME); | |
263 | std::wstring required_privileges(SE_INC_BASE_PRIORITY_NAME); | |
264 | 264 | required_privileges.push_back(L'\0'); |
265 | 265 | required_privileges.push_back(L'\0'); |
266 | 266 | // |SERVICE_REQUIRED_PRIVILEGES_INFO::pmszRequiredPrivileges| needs to be |
327 | 327 | // load type is not DISABLED. |
328 | 328 | if (state.running() && !now_running && |
329 | 329 | (state.load_type() != cache_service::Win32ServiceState::DISABLED)) { |
330 | vector<wstring> arguments(state.arguments_size()); | |
330 | std::vector<wstring> arguments(state.arguments_size()); | |
331 | 331 | arguments.resize(state.arguments_size()); |
332 | 332 | for (size_t i = 0; i < state.arguments_size(); ++i) { |
333 | 333 | if (Util::UTF8ToWide(state.arguments(i), &arguments[i]) <= 0) { |
432 | 432 | return kMozcCacheServiceName; |
433 | 433 | } |
434 | 434 | |
435 | wstring CacheServiceManager::GetUnquotedServicePath() { | |
435 | std::wstring CacheServiceManager::GetUnquotedServicePath() { | |
436 | 436 | const string lock_service_path = |
437 | 437 | FileUtil::JoinPath(SystemUtil::GetServerDirectory(), |
438 | 438 | kMozcCacheServiceExeName); |
439 | wstring wlock_service_path; | |
439 | std::wstring wlock_service_path; | |
440 | 440 | if (Util::UTF8ToWide(lock_service_path, &wlock_service_path) <= 0) { |
441 | 441 | return L""; |
442 | 442 | } |
443 | 443 | return wlock_service_path; |
444 | 444 | } |
445 | 445 | |
446 | wstring CacheServiceManager::GetQuotedServicePath() { | |
446 | std::wstring CacheServiceManager::GetQuotedServicePath() { | |
447 | 447 | return L"\"" + GetUnquotedServicePath() + L"\""; |
448 | 448 | } |
449 | 449 | |
512 | 512 | ::Sleep(200); // wait for 0.2sec |
513 | 513 | } |
514 | 514 | |
515 | return StartServiceInternal(service_handle, vector<wstring>()); | |
515 | return StartServiceInternal(service_handle, std::vector<wstring>()); | |
516 | 516 | } |
517 | 517 | |
518 | 518 | bool CacheServiceManager::HasEnoughMemory() { |
520 | 520 | kMinimumRequiredMemorySizeForInstall; |
521 | 521 | } |
522 | 522 | |
523 | bool CacheServiceManager::BackupStateAsString(wstring *result) { | |
523 | bool CacheServiceManager::BackupStateAsString(std::wstring *result) { | |
524 | 524 | if (result == NULL) { |
525 | 525 | return false; |
526 | 526 | } |
573 | 573 | return true; |
574 | 574 | } |
575 | 575 | |
576 | bool CacheServiceManager::RestoreStateFromString(const wstring &serialized) { | |
576 | bool CacheServiceManager::RestoreStateFromString( | |
577 | const std::wstring &serialized) { | |
577 | 578 | cache_service::Win32ServiceState state; |
578 | 579 | if (!DeserializeFromBase64WString(serialized, &state)) { |
579 | 580 | return false; |
50 | 50 | static const wchar_t *GetServiceName(); |
51 | 51 | |
52 | 52 | // Return the unquoted path to the cache service exe file. |
53 | static wstring GetUnquotedServicePath(); | |
53 | static std::wstring GetUnquotedServicePath(); | |
54 | 54 | |
55 | 55 | // Return the quoted path to the cache service exe file. |
56 | static wstring GetQuotedServicePath(); | |
56 | static std::wstring GetQuotedServicePath(); | |
57 | 57 | |
58 | 58 | // Enable the autostart of the cache service. |
59 | 59 | // Fails if the cache service is not installed. |
78 | 78 | static bool HasEnoughMemory(); |
79 | 79 | |
80 | 80 | // Return true if the current status of the serivice is successfully |
81 | // serialized into the specified wstring instance. | |
81 | // serialized into the specified std::wstring instance. | |
82 | 82 | // You can assume that the serialized data consists of ASCII printable |
83 | 83 | // characters. |
84 | 84 | // If the cache service is not installed, default settings is returned |
86 | 86 | static bool BackupStateAsString(wstring *buffer); |
87 | 87 | |
88 | 88 | // Return true if the previous status of the service is successfully |
89 | // restored from the specified wstring instance. | |
89 | // restored from the specified std::wstring instance. | |
90 | 90 | // This function may start the service if needed. |
91 | static bool RestoreStateFromString(const wstring &buffer); | |
91 | static bool RestoreStateFromString(const std::wstring &buffer); | |
92 | 92 | |
93 | 93 | // Return true if: |
94 | 94 | // - The cache service is not installed. |
63 | 63 | LogMessageImpl(_T(__FILE__), __LINE__, message, ::GetLastError()) |
64 | 64 | #endif |
65 | 65 | |
66 | wstring GetMappedFileNameByAddress(LPVOID address) { | |
66 | std::wstring GetMappedFileNameByAddress(LPVOID address) { | |
67 | 67 | wchar_t path[MAX_PATH]; |
68 | 68 | const int length = ::GetMappedFileName(::GetCurrentProcess(), address, |
69 | 69 | path, arraysize(path)); |
71 | 71 | LOG_WIN32_ERROR(L"GetMappedFileName failed."); |
72 | 72 | return L""; |
73 | 73 | } |
74 | return wstring(path, length); | |
74 | return std::wstring(path, length); | |
75 | 75 | } |
76 | 76 | |
77 | 77 | // This function scans each section of a given mapped image section and |
91 | 91 | // MEMORY_BASIC_INFORMATION::Type should be MEM_IMAGE. |
92 | 92 | |
93 | 93 | // Store the source filename. |
94 | const wstring &filename = ::GetMappedFileNameByAddress(address); | |
94 | const std::wstring &filename = ::GetMappedFileNameByAddress(address); | |
95 | 95 | if (filename.empty()) { |
96 | 96 | return false; |
97 | 97 | } |
179 | 179 | // See http://b/2470180 for the whole story. |
180 | 180 | bool VerifyPrivilegeRestrictionIfNeeded(DWORD dwArgc, LPTSTR *lpszArgv) { |
181 | 181 | bool verify_privilege = false; |
182 | const wstring test_mode = L"--verify_privilege_restriction"; | |
182 | const std::wstring test_mode = L"--verify_privilege_restriction"; | |
183 | 183 | for (size_t i = 0; i < dwArgc; ++i) { |
184 | 184 | if (test_mode == lpszArgv[i]) { |
185 | 185 | verify_privilege = true; |
193 | 193 | const string temp_path = |
194 | 194 | mozc::FileUtil::JoinPath(mozc::SystemUtil::GetServerDirectory(), |
195 | 195 | "delete_me.txt"); |
196 | wstring wtemp_path; | |
196 | std::wstring wtemp_path; | |
197 | 197 | mozc::Util::UTF8ToWide(temp_path, &wtemp_path); |
198 | 198 | const HANDLE temp_file = ::CreateFileW( |
199 | 199 | wtemp_path.c_str(), |
272 | 272 | STOP_SERVICE_AND_EXIT_FUNCTION(); |
273 | 273 | } |
274 | 274 | |
275 | wstring server_path; | |
275 | std::wstring server_path; | |
276 | 276 | mozc::Util::UTF8ToWide(mozc::SystemUtil::GetServerPath(), &server_path); |
277 | 277 | |
278 | 278 | mozc::ScopedHandle file_handle(::CreateFile(server_path.c_str(), |
40 | 40 | |
41 | 41 | string line; |
42 | 42 | while (getline(cin, line)) { |
43 | vector<string> fields; | |
43 | std::vector<string> fields; | |
44 | 44 | mozc::Util::SplitStringUsing(line, "\t ", &fields); |
45 | 45 | if (fields[0] == "i") { |
46 | 46 | cache.Insert(fields[1], fields[2]); |
56 | 56 | LOG(INFO) << "value_size=" << s.value_size(); |
57 | 57 | |
58 | 58 | string line; |
59 | vector<string> fields; | |
59 | std::vector<string> fields; | |
60 | 60 | while (getline(cin, line)) { |
61 | 61 | fields.clear(); |
62 | 62 | mozc::Util::SplitStringUsing(line, "\t ", &fields); |
30 | 30 | // example: |
31 | 31 | // |
32 | 32 | // UploadUtil uploader; |
33 | // vector<pair<string, string> > params; | |
33 | // std::vector<pair<string, string> > params; | |
34 | 34 | // params.push_back(make_pair("hl", "ja")); |
35 | 35 | // params.push_back(make_pair("v", "0.0.0.0")); |
36 | 36 | // uploader.SetHeader("Daily", 100, params); |
46 | 46 | using ::ATL::CComQIPtr; |
47 | 47 | using ::ATL::CComVariant; |
48 | 48 | |
49 | string UTF16ToUTF8(const wstring &str) { | |
49 | string UTF16ToUTF8(const std::wstring &str) { | |
50 | 50 | string utf8; |
51 | 51 | Util::WideToUTF8(str, &utf8); |
52 | 52 | return utf8; |
56 | 56 | if (bstr == nullptr) { |
57 | 57 | return ""; |
58 | 58 | } |
59 | return UTF16ToUTF8(wstring(bstr, ::SysStringLen(bstr))); | |
59 | return UTF16ToUTF8(std::wstring(bstr, ::SysStringLen(bstr))); | |
60 | 60 | } |
61 | 61 | |
62 | 62 | string RoleToString(const CComVariant &role) { |
262 | 262 | return info; |
263 | 263 | } |
264 | 264 | |
265 | vector<AccessibleObject> AccessibleObject::GetChildren() const { | |
266 | vector<AccessibleObject> result; | |
265 | std::vector<AccessibleObject> AccessibleObject::GetChildren() const { | |
266 | std::vector<AccessibleObject> result; | |
267 | 267 | if (!container_) { |
268 | 268 | result; |
269 | 269 | } |
275 | 275 | return result; |
276 | 276 | } |
277 | 277 | |
278 | vector<CComVariant> buffer; | |
278 | std::vector<CComVariant> buffer; | |
279 | 279 | buffer.resize(num_children); |
280 | 280 | |
281 | 281 | LONG num_fetched = 0; |
51 | 51 | AccessibleObject(ATL::CComPtr<IAccessible> container, int32 child_id); |
52 | 52 | |
53 | 53 | AccessibleObjectInfo GetInfo() const; |
54 | vector<AccessibleObject> GetChildren() const; | |
54 | std::vector<AccessibleObject> GetChildren() const; | |
55 | 55 | AccessibleObject GetParent() const; |
56 | 56 | AccessibleObject GetFocus() const; |
57 | 57 | bool GetWindowHandle(HWND *window_handle) const; |
60 | 60 | BrowserInfo::BrowserType g_browser_type_ = BrowserInfo::kBrowserTypeUnknown; |
61 | 61 | bool g_browser_type_initialized_ = false; |
62 | 62 | |
63 | wstring GetProcessModuleName() { | |
63 | std::wstring GetProcessModuleName() { | |
64 | 64 | if (g_exe_module_name_len_ == 0) { |
65 | 65 | return L""; |
66 | 66 | } |
67 | return wstring(g_exe_module_name_, g_exe_module_name_len_); | |
67 | return std::wstring(g_exe_module_name_, g_exe_module_name_len_); | |
68 | 68 | } |
69 | 69 | |
70 | 70 | } // namespace |
84 | 84 | const auto &direct_mode_keys = |
85 | 85 | KeyInfoUtil::ExtractSortedDirectModeKeys(config); |
86 | 86 | const size_t size_to_be_copied = |
87 | min(direct_mode_keys.size(), kMaxDirectModeKeys); | |
87 | std::min(direct_mode_keys.size(), kMaxDirectModeKeys); | |
88 | 88 | snapshot.num_direct_mode_keys = size_to_be_copied; |
89 | 89 | for (size_t i = 0; i < size_to_be_copied; ++i) { |
90 | 90 | snapshot.direct_mode_keys[i] = direct_mode_keys[i]; |
47 | 47 | bool use_kana_input; |
48 | 48 | bool use_keyboard_to_change_preedit_method; |
49 | 49 | bool use_mode_indicator; |
50 | vector<KeyInformation> direct_mode_keys; | |
50 | std::vector<KeyInformation> direct_mode_keys; | |
51 | 51 | Info(); |
52 | 52 | }; |
53 | 53 |
64 | 64 | void VKBackBasedDeleter::BeginDeletion(int deletion_count, |
65 | 65 | const mozc::commands::Output &output, |
66 | 66 | const InputState &ime_state) { |
67 | vector<INPUT> inputs; | |
67 | std::vector<INPUT> inputs; | |
68 | 68 | |
69 | 69 | wait_queue_->clear(); |
70 | 70 | *pending_ime_state_ = InputState(); |
76 | 76 | unicode_buffer_num_elements, flags); |
77 | 77 | } |
78 | 78 | |
79 | virtual UINT SendInput(const vector<INPUT> &inputs) { | |
79 | virtual UINT SendInput(const std::vector<INPUT> &inputs) { | |
80 | 80 | last_send_input_data_ = inputs; |
81 | 81 | return inputs.size(); |
82 | 82 | } |
97 | 97 | async_key_state_ = async_key_state; |
98 | 98 | } |
99 | 99 | |
100 | const vector<INPUT> &last_send_input_data() const { | |
100 | const std::vector<INPUT> &last_send_input_data() const { | |
101 | 101 | return last_send_input_data_; |
102 | 102 | } |
103 | 103 | |
108 | 108 | private: |
109 | 109 | KeyboardStatus key_state_; |
110 | 110 | KeyboardStatus async_key_state_; |
111 | vector<INPUT> last_send_input_data_; | |
111 | std::vector<INPUT> last_send_input_data_; | |
112 | 112 | DISALLOW_COPY_AND_ASSIGN(KeyboardMock); |
113 | 113 | }; |
114 | 114 | |
179 | 179 | // Expect three pairs of VK_BACK [down/up] for deleting proceeding characters |
180 | 180 | // and one pair of VK_BACK [down/up] as a sentinel key event where pending |
181 | 181 | // output and ime state wiil be applied. |
182 | const vector<INPUT> inputs = keyboard_mock->last_send_input_data(); | |
182 | const std::vector<INPUT> inputs = keyboard_mock->last_send_input_data(); | |
183 | 183 | EXPECT_EQ(8, inputs.size()); |
184 | 184 | EXPECT_EQ(VK_BACK, inputs[0].ki.wVk); |
185 | 185 | EXPECT_EQ(VK_BACK, inputs[1].ki.wVk); |
57 | 57 | DWORD g_tls_index = TLS_OUT_OF_INDEXES; |
58 | 58 | HMODULE g_module_handle = nullptr; |
59 | 59 | |
60 | string UTF16ToUTF8(const wstring &str) { | |
60 | string UTF16ToUTF8(const std::wstring &str) { | |
61 | 61 | string utf8; |
62 | 62 | Util::WideToUTF8(str, &utf8); |
63 | 63 | return utf8; |
76 | 76 | copied_len_without_null + 1 > buffer_len) { |
77 | 77 | return ""; |
78 | 78 | } |
79 | return UTF16ToUTF8(wstring(buffer.get(), copied_len_without_null)); | |
79 | return UTF16ToUTF8(std::wstring(buffer.get(), copied_len_without_null)); | |
80 | 80 | } |
81 | 81 | |
82 | 82 | string GetWindowClassNameAsUTF8(HWND window_handle) { |
88 | 88 | copied_len_without_null + 1 > kBufferLen) { |
89 | 89 | return ""; |
90 | 90 | } |
91 | return UTF16ToUTF8(wstring(buffer.get(), copied_len_without_null)); | |
91 | return UTF16ToUTF8(std::wstring(buffer.get(), copied_len_without_null)); | |
92 | 92 | } |
93 | 93 | |
94 | 94 | DWORD GetProcessIdFromWindow(HWND window_handle) { |
101 | 101 | |
102 | 102 | void FillWindowInfo( |
103 | 103 | HWND window_handle, |
104 | vector<FocusHierarchyObserver::WindowInfo> *window_hierarchy) { | |
104 | std::vector<FocusHierarchyObserver::WindowInfo> *window_hierarchy) { | |
105 | 105 | if (window_handle == nullptr) { |
106 | 106 | // error |
107 | 107 | window_hierarchy->clear(); |
138 | 138 | void FillAccessibleInfo( |
139 | 139 | AccessibleObject accessible, |
140 | 140 | HWND focused_window_handle, |
141 | vector<AccessibleObjectInfo> *hierarchy) { | |
141 | std::vector<AccessibleObjectInfo> *hierarchy) { | |
142 | 142 | if (!accessible.IsValid()) { |
143 | 143 | return; |
144 | 144 | } |
167 | 167 | |
168 | 168 | class ThreadLocalInfo { |
169 | 169 | public: |
170 | vector<AccessibleObjectInfo> ui_hierarchy() const { | |
170 | std::vector<AccessibleObjectInfo> ui_hierarchy() const { | |
171 | 171 | return ui_hierarchy_; |
172 | 172 | } |
173 | vector<FocusHierarchyObserver::WindowInfo> window_hierarchy() const { | |
173 | std::vector<FocusHierarchyObserver::WindowInfo> window_hierarchy() const { | |
174 | 174 | return window_hierarchy_; |
175 | 175 | } |
176 | 176 | string root_window_name() const { |
325 | 325 | |
326 | 326 | int ref_count_; |
327 | 327 | HWINEVENTHOOK hook_handle_; |
328 | vector<AccessibleObjectInfo> ui_hierarchy_; | |
329 | vector<FocusHierarchyObserver::WindowInfo> window_hierarchy_; | |
328 | std::vector<AccessibleObjectInfo> ui_hierarchy_; | |
329 | std::vector<FocusHierarchyObserver::WindowInfo> window_hierarchy_; | |
330 | 330 | string root_window_name_; |
331 | 331 | }; |
332 | 332 | |
367 | 367 | virtual bool IsAbailable() const { |
368 | 368 | return ThreadLocalInfo::Self() != nullptr; |
369 | 369 | } |
370 | virtual vector<AccessibleObjectInfo> GetUIHierarchy() const { | |
370 | virtual std::vector<AccessibleObjectInfo> GetUIHierarchy() const { | |
371 | 371 | auto *self = ThreadLocalInfo::Self(); |
372 | 372 | if (self == nullptr) { |
373 | return vector<AccessibleObjectInfo>(); | |
373 | return std::vector<AccessibleObjectInfo>(); | |
374 | 374 | } |
375 | 375 | return self->ui_hierarchy(); |
376 | 376 | } |
377 | virtual vector<WindowInfo> GetWindowHierarchy() const { | |
377 | virtual std::vector<WindowInfo> GetWindowHierarchy() const { | |
378 | 378 | auto *self = ThreadLocalInfo::Self(); |
379 | 379 | if (self == nullptr) { |
380 | return vector<FocusHierarchyObserver::WindowInfo>(); | |
380 | return std::vector<FocusHierarchyObserver::WindowInfo>(); | |
381 | 381 | } |
382 | 382 | return self->window_hierarchy(); |
383 | 383 | } |
407 | 407 | virtual bool IsAbailable() const { |
408 | 408 | return false; |
409 | 409 | } |
410 | virtual vector<AccessibleObjectInfo> GetUIHierarchy() const { | |
411 | return vector<AccessibleObjectInfo>(); | |
412 | } | |
413 | virtual vector<WindowInfo> GetWindowHierarchy() const { | |
414 | return vector<WindowInfo>(); | |
410 | virtual std::vector<AccessibleObjectInfo> GetUIHierarchy() const { | |
411 | return std::vector<AccessibleObjectInfo>(); | |
412 | } | |
413 | virtual std::vector<WindowInfo> GetWindowHierarchy() const { | |
414 | return std::vector<WindowInfo>(); | |
415 | 415 | } |
416 | 416 | virtual string GetRootWindowName() const { |
417 | 417 | return ""; |
54 | 54 | |
55 | 55 | virtual void SyncFocusHierarchy() = 0; |
56 | 56 | virtual bool IsAbailable() const = 0; |
57 | virtual vector<AccessibleObjectInfo> GetUIHierarchy() const = 0; | |
58 | virtual vector<WindowInfo> GetWindowHierarchy() const = 0; | |
57 | virtual std::vector<AccessibleObjectInfo> GetUIHierarchy() const = 0; | |
58 | virtual std::vector<WindowInfo> GetWindowHierarchy() const = 0; | |
59 | 59 | virtual string GetRootWindowName() const = 0; |
60 | 60 | |
61 | 61 | static FocusHierarchyObserver *Create(); |
73 | 73 | } |
74 | 74 | } // namespace |
75 | 75 | |
76 | bool ReconvertString::Compose(const wstring &preceding_text, | |
77 | const wstring &preceding_composition, | |
78 | const wstring &target, | |
79 | const wstring &following_composition, | |
80 | const wstring &following_text, | |
76 | bool ReconvertString::Compose(const std::wstring &preceding_text, | |
77 | const std::wstring &preceding_composition, | |
78 | const std::wstring &target, | |
79 | const std::wstring &following_composition, | |
80 | const std::wstring &following_text, | |
81 | 81 | RECONVERTSTRING *reconvert_string) { |
82 | 82 | if (reconvert_string == nullptr) { |
83 | 83 | return false; |
206 | 206 | } |
207 | 207 | |
208 | 208 | bool ReconvertString::Decompose(const RECONVERTSTRING *reconvert_string, |
209 | wstring *preceding_text, | |
210 | wstring *preceding_composition, | |
211 | wstring *target, | |
212 | wstring *following_composition, | |
213 | wstring *following_text) { | |
209 | std::wstring *preceding_text, | |
210 | std::wstring *preceding_composition, | |
211 | std::wstring *target, | |
212 | std::wstring *following_composition, | |
213 | std::wstring *following_text) { | |
214 | 214 | if (reconvert_string == nullptr) { |
215 | 215 | return false; |
216 | 216 | } |
346 | 346 | |
347 | 347 | bool ReconvertString::EnsureCompositionIsNotEmpty( |
348 | 348 | RECONVERTSTRING *reconvert_string) { |
349 | wstring preceding_text; | |
350 | wstring preceding_composition; | |
351 | wstring target; | |
352 | wstring following_composition; | |
353 | wstring following_text; | |
349 | std::wstring preceding_text; | |
350 | std::wstring preceding_composition; | |
351 | std::wstring target; | |
352 | std::wstring following_composition; | |
353 | std::wstring following_text; | |
354 | 354 | if (!ReconvertString::Decompose( |
355 | 355 | reconvert_string, &preceding_text, &preceding_composition, |
356 | 356 | &target, &following_composition, &following_text)) { |
60 | 60 | // Returns true if given substrings are copied into |reconvert_string|. |
61 | 61 | // The caller is responsible for allocating enough memory for |
62 | 62 | // |reconvert_string|. |
63 | static bool Compose(const wstring &preceding_text, | |
64 | const wstring &preceding_composition, | |
65 | const wstring &target, | |
66 | const wstring &following_composition, | |
67 | const wstring &following_text, | |
63 | static bool Compose(const std::wstring &preceding_text, | |
64 | const std::wstring &preceding_composition, | |
65 | const std::wstring &target, | |
66 | const std::wstring &following_composition, | |
67 | const std::wstring &following_text, | |
68 | 68 | RECONVERTSTRING *reconvert_string); |
69 | 69 | |
70 | 70 | // Returns true if substrings are copied from |reconvert_string|. |
71 | 71 | static bool Decompose(const RECONVERTSTRING *reconvert_string, |
72 | wstring *preceding_text, | |
73 | wstring *preceding_composition, | |
74 | wstring *target, | |
75 | wstring *following_composition, | |
76 | wstring *following_text); | |
72 | std::wstring *preceding_text, | |
73 | std::wstring *preceding_composition, | |
74 | std::wstring *target, | |
75 | std::wstring *following_composition, | |
76 | std::wstring *following_text); | |
77 | 77 | |
78 | 78 | // Returns true if the given |reconvert_string| is valid. |
79 | 79 | static bool Validate(const RECONVERTSTRING *reconvert_string); |
37 | 37 | namespace { |
38 | 38 | struct FixedReconvertString : public RECONVERTSTRING { |
39 | 39 | BYTE buffer[4096]; |
40 | void Initialize(const wstring &entire_string, | |
40 | void Initialize(const std::wstring &entire_string, | |
41 | 41 | size_t padding_bytes) { |
42 | 42 | dwSize = sizeof(FixedReconvertString); |
43 | 43 | dwVersion = 0; |
163 | 163 | expected_following_text, \ |
164 | 164 | actual_reconvert_string) \ |
165 | 165 | do { \ |
166 | wstring actual_precedeing_text; \ | |
167 | wstring actual_preceding_composition; \ | |
168 | wstring actual_target; \ | |
169 | wstring actual_following_composition; \ | |
170 | wstring actual_following_text; \ | |
166 | std::wstring actual_precedeing_text; \ | |
167 | std::wstring actual_preceding_composition; \ | |
168 | std::wstring actual_target; \ | |
169 | std::wstring actual_following_composition; \ | |
170 | std::wstring actual_following_text; \ | |
171 | 171 | EXPECT_TRUE(ReconvertString::Decompose( \ |
172 | 172 | &(actual_reconvert_string), \ |
173 | 173 | &actual_precedeing_text, \ |
186 | 186 | |
187 | 187 | #define EXPECT_DECOMPOSE_FAIL(actual_reconvert_string) \ |
188 | 188 | do { \ |
189 | wstring actual_precedeing_text; \ | |
190 | wstring actual_preceding_composition; \ | |
191 | wstring actual_target; \ | |
192 | wstring actual_following_composition; \ | |
193 | wstring actual_following_text; \ | |
189 | std::wstring actual_precedeing_text; \ | |
190 | std::wstring actual_preceding_composition; \ | |
191 | std::wstring actual_target; \ | |
192 | std::wstring actual_following_composition; \ | |
193 | std::wstring actual_following_text; \ | |
194 | 194 | EXPECT_FALSE(ReconvertString::Decompose( \ |
195 | 195 | &(actual_reconvert_string), \ |
196 | 196 | &actual_precedeing_text, \ |
588 | 588 | FixedReconvertString reconvert_string; |
589 | 589 | reconvert_string.Initialize(L"", 10); |
590 | 590 | |
591 | wstring following_text; | |
591 | std::wstring following_text; | |
592 | 592 | following_text += L'\0'; |
593 | 593 | // "つづく" |
594 | 594 | following_text += L"\u3064\u3065\u304F"; |
65 | 65 | const wchar_t kPreloadKeyName[] = L"Keyboard Layout\\Preload"; |
66 | 66 | const wchar_t kPreloadTopValueName[] = L"1"; |
67 | 67 | |
68 | typedef map<unsigned int, DWORD> PreloadValueMap; | |
68 | typedef std::map<unsigned int, DWORD> PreloadValueMap; | |
69 | 69 | |
70 | 70 | // Converts an unsigned integer to a wide string. |
71 | wstring utow(unsigned int i) { | |
72 | wstringstream ss; | |
71 | std::wstring utow(unsigned int i) { | |
72 | std::wstringstream ss; | |
73 | 73 | ss << i; |
74 | 74 | return ss.str(); |
75 | 75 | } |
76 | 76 | |
77 | wstring GetSystemRegKeyName(const KeyboardLayoutID &klid) { | |
78 | return wstring(kRegKeyboardLayouts) + L"\\" + klid.ToString(); | |
77 | std::wstring GetSystemRegKeyName(const KeyboardLayoutID &klid) { | |
78 | return std::wstring(kRegKeyboardLayouts) + L"\\" + klid.ToString(); | |
79 | 79 | } |
80 | 80 | |
81 | 81 | // Set the layout display name with the Registry String Redirection format |
85 | 85 | // http://blogs.msdn.com/michkap/archive/2007/01/05/1387397.aspx |
86 | 86 | // http://blogs.msdn.com/michkap/archive/2007/08/25/4564548.aspx |
87 | 87 | // http://msdn.microsoft.com/en-us/library/dd374120.aspx |
88 | HRESULT SetLayoutDisplayName(const KeyboardLayoutID &klid, | |
89 | const wstring &layout_display_name_resource_path, | |
90 | int layout_display_name_resource_id) { | |
88 | HRESULT SetLayoutDisplayName( | |
89 | const KeyboardLayoutID &klid, | |
90 | const std::wstring &layout_display_name_resource_path, | |
91 | int layout_display_name_resource_id) { | |
91 | 92 | if (!klid.has_id()) { |
92 | 93 | return E_FAIL; |
93 | 94 | } |
94 | 95 | |
95 | const wstring &key_name = GetSystemRegKeyName(klid); | |
96 | const std::wstring &key_name = GetSystemRegKeyName(klid); | |
96 | 97 | |
97 | 98 | CRegKey keybord_layout_key; |
98 | 99 | LRESULT result = keybord_layout_key.Open( |
129 | 130 | // folder as a system folder, so it will refuse to install our IME. The |
130 | 131 | // solution here is to combine the 64-bit System32 folder and our filename |
131 | 132 | // to make ImmInstallIME happy. |
132 | wstring GetFullPathForSystem(const string& basename) { | |
133 | std::wstring GetFullPathForSystem(const string& basename) { | |
133 | 134 | string system_dir; |
134 | 135 | if (Util::WideToUTF8(SystemUtil::GetSystemDir(), &system_dir) <= 0) { |
135 | 136 | return L""; |
137 | 138 | |
138 | 139 | const string fullpath = FileUtil::JoinPath(system_dir, basename); |
139 | 140 | |
140 | wstring wfullpath; | |
141 | std::wstring wfullpath; | |
141 | 142 | if (Util::UTF8ToWide(fullpath, &wfullpath) <= 0) { |
142 | 143 | return L""; |
143 | 144 | } |
178 | 179 | } |
179 | 180 | |
180 | 181 | const int ivalue_name = _wtoi(value_name); |
181 | const wstring wvalue(reinterpret_cast<wchar_t*>(value), | |
182 | const std::wstring wvalue(reinterpret_cast<wchar_t*>(value), | |
182 | 183 | (value_length / sizeof(wchar_t)) - 1); |
183 | 184 | KeyboardLayoutID klid(wvalue); |
184 | 185 | if (!klid.has_id()) { |
203 | 204 | return index; |
204 | 205 | } |
205 | 206 | |
206 | wstring ToWideString(const string &str) { | |
207 | wstring wide; | |
207 | std::wstring ToWideString(const string &str) { | |
208 | std::wstring wide; | |
208 | 209 | if (Util::UTF8ToWide(str, &wide) <= 0) { |
209 | 210 | return L""; |
210 | 211 | } |
240 | 241 | } |
241 | 242 | } // namespace |
242 | 243 | |
243 | HRESULT ImmRegistrar::Register(const wstring &ime_filename, | |
244 | const wstring &layout_name, | |
245 | const wstring &layout_display_name_resource_path, | |
246 | int layout_display_name_resource_id, | |
247 | HKL* hkl) { | |
244 | HRESULT ImmRegistrar::Register( | |
245 | const std::wstring &ime_filename, | |
246 | const std::wstring &layout_name, | |
247 | const std::wstring &layout_display_name_resource_path, | |
248 | int layout_display_name_resource_id, | |
249 | HKL* hkl) { | |
248 | 250 | HKL dummy_hkl = nullptr; |
249 | 251 | if (hkl == nullptr) { |
250 | 252 | hkl = &dummy_hkl; |
265 | 267 | |
266 | 268 | IMEPROW dummy_ime_property = { 0 }; |
267 | 269 | |
268 | const wstring &fullpath( | |
269 | wstring(SystemUtil::GetSystemDir()) + L"\\" + ime_filename); | |
270 | const std::wstring &fullpath( | |
271 | std::wstring(SystemUtil::GetSystemDir()) + L"\\" + ime_filename); | |
270 | 272 | |
271 | 273 | // The path name of IME has hard limit. (http://b/2072809) |
272 | 274 | if (fullpath.size() + 1 > arraysize(dummy_ime_property.szName)) { |
316 | 318 | } |
317 | 319 | |
318 | 320 | // Uninstall module by deleting a registry key under kRegKeyboardLayouts. |
319 | HRESULT ImmRegistrar::Unregister(const wstring &ime_filename) { | |
321 | HRESULT ImmRegistrar::Unregister(const std::wstring &ime_filename) { | |
320 | 322 | const KeyboardLayoutID &klid = GetKLIDFromFileName(ime_filename); |
321 | 323 | if (!klid.has_id()) { |
322 | 324 | // already unregistered? |
356 | 358 | return S_OK; |
357 | 359 | } |
358 | 360 | |
359 | bool ImmRegistrar::IsIME(HKL hkl, const wstring &ime_filename) { | |
361 | bool ImmRegistrar::IsIME(HKL hkl, const std::wstring &ime_filename) { | |
360 | 362 | if (hkl == nullptr) { |
361 | 363 | return false; |
362 | 364 | } |
371 | 373 | return WinUtil::SystemEqualString(buf, ime_filename, true); |
372 | 374 | } |
373 | 375 | |
374 | wstring ImmRegistrar::GetFileNameForIME() { | |
376 | std::wstring ImmRegistrar::GetFileNameForIME() { | |
375 | 377 | return ToWideString(mozc::kIMEFile); |
376 | 378 | } |
377 | 379 | |
380 | 382 | } |
381 | 383 | |
382 | 384 | KeyboardLayoutID ImmRegistrar::GetKLIDFromFileName( |
383 | const wstring &ime_filename) { | |
385 | const std::wstring &ime_filename) { | |
384 | 386 | if (ime_filename.empty()) { |
385 | 387 | return KeyboardLayoutID(); |
386 | 388 | } |
410 | 412 | |
411 | 413 | // Note that |value_name_length| does not contain NUL character. |
412 | 414 | const KeyboardLayoutID klid( |
413 | wstring(value_name, value_name + value_name_length)); | |
415 | std::wstring(value_name, value_name + value_name_length)); | |
414 | 416 | |
415 | 417 | if (!klid.has_id()) { |
416 | 418 | continue; |
434 | 436 | |
435 | 437 | const ULONG filename_length = (filename_length_including_null - 1); |
436 | 438 | // Note that |filename_length| does not contain NUL character. |
437 | const wstring target_basename( | |
439 | const std::wstring target_basename( | |
438 | 440 | filename_buffer, filename_buffer + filename_length); |
439 | 441 | |
440 | 442 | // TODO(yukawa): Support short filename. See b/2977730 |
445 | 447 | return KeyboardLayoutID(); |
446 | 448 | } |
447 | 449 | |
448 | wstring ImmRegistrar::GetFullPathForIME() { | |
450 | std::wstring ImmRegistrar::GetFullPathForIME() { | |
449 | 451 | return GetFullPathForSystem(mozc::kIMEFile); |
450 | 452 | } |
451 | 453 | |
452 | wstring ImmRegistrar::GetLayoutName() { | |
453 | wstring layout_name; | |
454 | std::wstring ImmRegistrar::GetLayoutName() { | |
455 | std::wstring layout_name; | |
454 | 456 | // We use English name here as culture-invariant layout name. |
455 | 457 | if (Util::UTF8ToWide(kProductNameInEnglish, &layout_name) <= 0) { |
456 | 458 | return L""; |
501 | 503 | for (PreloadValueMap::iterator i = preload_values.begin(); |
502 | 504 | i != preload_values.end(); |
503 | 505 | ++i) { |
504 | const wstring& value_name = utow((*i).first); | |
506 | const std::wstring& value_name = utow((*i).first); | |
505 | 507 | const KeyboardLayoutID target_klid((*i).second); |
506 | 508 | result = preload_key.DeleteValue(value_name.c_str()); |
507 | 509 | if ((*i).first == preload_index) { |
508 | 510 | continue; |
509 | 511 | } |
510 | const wstring& new_value_name = utow((*i).first - 1); | |
512 | const std::wstring& new_value_name = utow((*i).first - 1); | |
511 | 513 | preload_key.SetStringValue(new_value_name.c_str(), |
512 | 514 | target_klid.ToString().c_str()); |
513 | 515 | } |
45 | 45 | public: |
46 | 46 | // Installs module to the system as an IME. |
47 | 47 | // Returns registered HKL to hkl. |
48 | static HRESULT Register(const wstring &ime_filename, | |
49 | const wstring &layout_name, | |
50 | const wstring &layout_display_name_resource_path, | |
48 | static HRESULT Register(const std::wstring &ime_filename, | |
49 | const std::wstring &layout_name, | |
50 | const std::wstring &layout_display_name_resource_path, | |
51 | 51 | int layout_display_name_resource_id, |
52 | 52 | HKL *hkl); |
53 | 53 | |
54 | 54 | // Uninstalls module from the system. |
55 | static HRESULT Unregister(const wstring &ime_filename); | |
55 | static HRESULT Unregister(const std::wstring &ime_filename); | |
56 | 56 | |
57 | 57 | // Returns true if given |hkl| is an IME which consists of |ime_filename|. |
58 | static bool IsIME(HKL hkl, const wstring &ime_filename); | |
58 | static bool IsIME(HKL hkl, const std::wstring &ime_filename); | |
59 | 59 | |
60 | 60 | // Returns a file name of the IME file. |
61 | static wstring GetFileNameForIME(); | |
61 | static std::wstring GetFileNameForIME(); | |
62 | 62 | |
63 | 63 | // Returns a full path to the IME file. |
64 | 64 | // Returns an empty string if it fails to compose a fullpath. |
65 | static wstring GetFullPathForIME(); | |
65 | static std::wstring GetFullPathForIME(); | |
66 | 66 | |
67 | 67 | // Returns a KILD for the IME file. |
68 | 68 | static KeyboardLayoutID GetKLIDForIME(); |
69 | 69 | |
70 | 70 | // Returns a layout name of the IME file. |
71 | 71 | // Returns an empty string if it fails to compose a layout name. |
72 | static wstring GetLayoutName(); | |
72 | static std::wstring GetLayoutName(); | |
73 | 73 | |
74 | 74 | // Returns a resource ID of a layout display name. |
75 | 75 | static int GetLayoutDisplayNameResourceId(); |
76 | 76 | |
77 | 77 | // Returns a KILD for the given ime file specified by |ime_file| |
78 | static KeyboardLayoutID GetKLIDFromFileName(const wstring &ime_file); | |
78 | static KeyboardLayoutID GetKLIDFromFileName(const std::wstring &ime_file); | |
79 | 79 | |
80 | 80 | // Add key to the preload if not exist. |
81 | 81 | // Returns S_OK if operation completes successfully. |
115 | 115 | return E_OUTOFMEMORY; |
116 | 116 | } |
117 | 117 | |
118 | const wstring &profile = wstring(L"0x0411:") + clsid + profile_id; | |
118 | const std::wstring &profile = std::wstring(L"0x0411:") + clsid + profile_id; | |
119 | 119 | if (!::InstallLayoutOrTip(profile.c_str(), 0)) { |
120 | 120 | DLOG(ERROR) << "InstallLayoutOrTip failed"; |
121 | 121 | return false; |
167 | 167 | return false; |
168 | 168 | } |
169 | 169 | |
170 | const wstring id(profile.szId); | |
170 | const std::wstring id(profile.szId); | |
171 | 171 | // A valid |profile.szId| should consists of language ID (LANGID) and |
172 | 172 | // keyboard layout ID (KILD) as follows. |
173 | 173 | // <LangID 1>:<KLID 1> |
212 | 212 | return false; |
213 | 213 | } |
214 | 214 | |
215 | const wstring &profile_list = L"0x0411:0x" + mozc_klid.ToString(); | |
215 | const std::wstring &profile_list = L"0x0411:0x" + mozc_klid.ToString(); | |
216 | 216 | if (!::SetDefaultLayoutOrTip(profile_list.c_str(), 0)) { |
217 | 217 | DLOG(ERROR) << "SetDefaultLayoutOrTip failed"; |
218 | 218 | return false; |
254 | 254 | // Wait for "MSCTF.AsmCacheReady.<desktop name><session #>" event signal to |
255 | 255 | // work around b/5765783. |
256 | 256 | bool ImeUtil::WaitForAsmCacheReady(uint32 timeout_msec) { |
257 | wstring event_name; | |
257 | std::wstring event_name; | |
258 | 258 | if (Util::UTF8ToWide(SystemUtil::GetMSCTFAsmCacheReadyEventName(), |
259 | 259 | &event_name) == 0) { |
260 | 260 | LOG(ERROR) << "Failed to compose event name."; |
59 | 59 | bool prefer_kana_input; |
60 | 60 | bool use_mode_indicator; |
61 | 61 | bool use_romaji_key_to_toggle_input_style; |
62 | vector<KeyInformation> direct_mode_keys; | |
62 | std::vector<KeyInformation> direct_mode_keys; | |
63 | 63 | InputBehavior(); |
64 | 64 | }; |
65 | 65 |
198 | 198 | } |
199 | 199 | |
200 | 200 | // [Overrides] |
201 | virtual UINT SendInput(const vector<INPUT> &inputs) { | |
201 | virtual UINT SendInput(const std::vector<INPUT> &inputs) { | |
202 | 202 | if (inputs.size() < 1) { |
203 | 203 | return 0; |
204 | 204 | } |
131 | 131 | __in UINT wFlags) = 0; |
132 | 132 | |
133 | 133 | // Injection point for SendInput API. |
134 | virtual UINT SendInput(const vector<INPUT> &inputs) = 0; | |
134 | virtual UINT SendInput(const std::vector<INPUT> &inputs) = 0; | |
135 | 135 | |
136 | 136 | static Win32KeyboardInterface *CreateDefault(); |
137 | 137 | }; |
62 | 62 | : id_(kDefaultKLID), |
63 | 63 | has_id_(false) {} |
64 | 64 | |
65 | KeyboardLayoutID::KeyboardLayoutID(const wstring &text) | |
65 | KeyboardLayoutID::KeyboardLayoutID(const std::wstring &text) | |
66 | 66 | : id_(kDefaultKLID), |
67 | 67 | has_id_(false) { |
68 | 68 | Parse(text); |
72 | 72 | : id_(id), |
73 | 73 | has_id_(true) {} |
74 | 74 | |
75 | bool KeyboardLayoutID::Parse(const wstring &text) { | |
75 | bool KeyboardLayoutID::Parse(const std::wstring &text) { | |
76 | 76 | clear_id(); |
77 | 77 | |
78 | 78 | if (text.size() != kTextLength) { |
85 | 85 | } |
86 | 86 | |
87 | 87 | DWORD id = 0; |
88 | wstringstream ss; | |
88 | std::wstringstream ss; | |
89 | 89 | ss << text; |
90 | ss >> hex >> id; | |
90 | ss >> std::hex >> id; | |
91 | 91 | set_id(id); |
92 | 92 | return true; |
93 | 93 | } |
94 | 94 | |
95 | wstring KeyboardLayoutID::ToString() const { | |
95 | std::wstring KeyboardLayoutID::ToString() const { | |
96 | 96 | CHECK(has_id()) << "ID is not set."; |
97 | 97 | wchar_t buffer[KL_NAMELENGTH]; |
98 | 98 | const HRESULT result = |
54 | 54 | |
55 | 55 | // Initializes an instance with a KLID in text form. |
56 | 56 | // |id_| remains 'cleared' if |text| is an invalid text form. |
57 | explicit KeyboardLayoutID(const wstring &text); | |
57 | explicit KeyboardLayoutID(const std::wstring &text); | |
58 | 58 | |
59 | 59 | // Initializes an instance with a KLID in integer form. |
60 | 60 | explicit KeyboardLayoutID(DWORD id); |
61 | 61 | |
62 | 62 | // Returns true unless |text| does not have an invalid text form. |
63 | 63 | // When this method returns false, it behaves as if |clear_id()| was called. |
64 | bool Parse(const wstring &text); | |
64 | bool Parse(const std::wstring &text); | |
65 | 65 | |
66 | 66 | // Returns KLID in text form. |
67 | 67 | // You cannot call this method when |has_id()| returns false. |
68 | wstring ToString() const; | |
68 | std::wstring ToString() const; | |
69 | 69 | |
70 | 70 | // Returns KLID in integer form. |
71 | 71 | // You cannot call this method when |has_id()| returns false. |
46 | 46 | KeyboardLayoutID klid(0); |
47 | 47 | EXPECT_TRUE(klid.has_id()); |
48 | 48 | EXPECT_EQ(0x00000000, klid.id()); |
49 | EXPECT_EQ(wstring(L"00000000"), klid.ToString()); | |
49 | EXPECT_EQ(std::wstring(L"00000000"), klid.ToString()); | |
50 | 50 | } |
51 | 51 | |
52 | 52 | // constructor for the text form. |
54 | 54 | KeyboardLayoutID klid(L"00000000"); |
55 | 55 | EXPECT_TRUE(klid.has_id()); |
56 | 56 | EXPECT_EQ(0x00000000, klid.id()); |
57 | EXPECT_EQ(wstring(L"00000000"), klid.ToString()); | |
57 | EXPECT_EQ(std::wstring(L"00000000"), klid.ToString()); | |
58 | 58 | } |
59 | 59 | |
60 | 60 | { |
69 | 69 | klid.set_id(1); |
70 | 70 | EXPECT_TRUE(klid.has_id()); |
71 | 71 | EXPECT_EQ(0x00000001, klid.id()); |
72 | EXPECT_EQ(wstring(L"00000001"), klid.ToString()); | |
72 | EXPECT_EQ(std::wstring(L"00000001"), klid.ToString()); | |
73 | 73 | |
74 | 74 | // Can copy the instance. |
75 | 75 | KeyboardLayoutID another_klid(L"00000002"); |
76 | 76 | klid = another_klid; |
77 | 77 | EXPECT_TRUE(klid.has_id()); |
78 | 78 | EXPECT_EQ(0x00000002, klid.id()); |
79 | EXPECT_EQ(wstring(L"00000002"), klid.ToString()); | |
79 | EXPECT_EQ(std::wstring(L"00000002"), klid.ToString()); | |
80 | 80 | } |
81 | 81 | } |
82 | 82 | |
86 | 86 | EXPECT_TRUE(klid.Parse(L"E0220411")); |
87 | 87 | EXPECT_TRUE(klid.has_id()); |
88 | 88 | EXPECT_EQ(0xE0220411, klid.id()); |
89 | EXPECT_EQ(wstring(L"E0220411"), klid.ToString()); | |
89 | EXPECT_EQ(std::wstring(L"E0220411"), klid.ToString()); | |
90 | 90 | |
91 | 91 | EXPECT_TRUE(klid.Parse(L"e0220411")); |
92 | 92 | EXPECT_EQ(0xE0220411, klid.id()); |
93 | 93 | EXPECT_TRUE(klid.has_id()); |
94 | EXPECT_EQ(wstring(L"E0220411"), klid.ToString()); // should be capitalised | |
94 | // This should be capitalised | |
95 | EXPECT_EQ(std::wstring(L"E0220411"), klid.ToString()); | |
95 | 96 | |
96 | 97 | // Do not reject any KLID unless it has an invalid text form. |
97 | 98 | // The caller is responsible for checking the existence of this KLID in the |
99 | 100 | EXPECT_TRUE(klid.Parse(L"00000000")); |
100 | 101 | EXPECT_TRUE(klid.has_id()); |
101 | 102 | EXPECT_EQ(0x00000000, klid.id()); |
102 | EXPECT_EQ(wstring(L"00000000"), klid.ToString()); | |
103 | EXPECT_EQ(std::wstring(L"00000000"), klid.ToString()); | |
103 | 104 | |
104 | 105 | // Invalid text form. Should be rejected. |
105 | 106 | EXPECT_FALSE(klid.Parse(L"123")); |
124 | 125 | klid.set_id(0xE0220411); |
125 | 126 | EXPECT_TRUE(klid.has_id()); |
126 | 127 | EXPECT_EQ(0xE0220411, klid.id()); |
127 | EXPECT_EQ(wstring(L"E0220411"), klid.ToString()); | |
128 | EXPECT_EQ(std::wstring(L"E0220411"), klid.ToString()); | |
128 | 129 | |
129 | 130 | klid.set_id(0x00000123); |
130 | 131 | EXPECT_TRUE(klid.has_id()); |
131 | 132 | EXPECT_EQ(0x00000123, klid.id()); |
132 | EXPECT_EQ(wstring(L"00000123"), klid.ToString()); | |
133 | EXPECT_EQ(std::wstring(L"00000123"), klid.ToString()); | |
133 | 134 | |
134 | 135 | // Do not reject any KLID because the integer form never be invalid as |
135 | 136 | // opposed to text form. |
138 | 139 | klid.set_id(0xFFFFFFFF); |
139 | 140 | EXPECT_TRUE(klid.has_id()); |
140 | 141 | EXPECT_EQ(0xFFFFFFFF, klid.id()); |
141 | EXPECT_EQ(wstring(L"FFFFFFFF"), klid.ToString()); | |
142 | EXPECT_EQ(std::wstring(L"FFFFFFFF"), klid.ToString()); | |
142 | 143 | } |
143 | 144 | } // namespace win32 |
144 | 145 | } // namespace mozc |
325 | 325 | }; |
326 | 326 | |
327 | 327 | void ClearModifyerKeyIfNeeded( |
328 | const KeyEvent *key, set<KeyEvent::ModifierKey> *modifiers) { | |
328 | const KeyEvent *key, std::set<KeyEvent::ModifierKey> *modifiers) { | |
329 | 329 | if (key == nullptr) { |
330 | 330 | return; |
331 | 331 | } |
393 | 393 | const KeyboardStatus &keyboard_status, |
394 | 394 | Win32KeyboardInterface *keyboard, |
395 | 395 | commands::KeyEvent *key, |
396 | set<KeyEvent::ModifierKey> *modifer_keys) { | |
396 | std::set<KeyEvent::ModifierKey> *modifer_keys) { | |
397 | 397 | if (key == nullptr) { |
398 | 398 | return false; |
399 | 399 | } |
955 | 955 | // Since Mozc protocol requires tricky conditions for modifiers, using set |
956 | 956 | // container makes the the main part of key event conversion simple rather |
957 | 957 | // than using vector-like container. |
958 | set<KeyEvent::ModifierKey> modifiers; | |
958 | std::set<KeyEvent::ModifierKey> modifiers; | |
959 | 959 | const bool result = ConvertToKeyEventMain( |
960 | 960 | virtual_key, |
961 | 961 | scan_code, |
972 | 972 | } |
973 | 973 | |
974 | 974 | // Updates |modifier_keys| field based on the returned set of modifier keys. |
975 | for (set<KeyEvent::ModifierKey>::const_iterator i = modifiers.begin(); | |
975 | for (std::set<KeyEvent::ModifierKey>::const_iterator i = modifiers.begin(); | |
976 | 976 | i != modifiers.end(); ++i) { |
977 | 977 | key->add_modifier_keys(*i); |
978 | 978 | } |
165 | 165 | bool start_server_called_; |
166 | 166 | uint32 server_protocol_version_; |
167 | 167 | string response_; |
168 | map<int, int> error_map_; | |
168 | std::map<int, int> error_map_; | |
169 | 169 | }; |
170 | 170 | |
171 | 171 | class KeyboardMock : public Win32KeyboardInterface { |
201 | 201 | return JapaneseKeyboardLayoutEmulator::ToUnicode( |
202 | 202 | wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff, wFlags); |
203 | 203 | } |
204 | virtual UINT SendInput(const vector<INPUT> &input) { | |
204 | virtual UINT SendInput(const std::vector<INPUT> &input) { | |
205 | 205 | // Not implemented. |
206 | 206 | return 0; |
207 | 207 | } |
266 | 266 | mozc::config::ConfigHandler::SetConfig(default_config_); |
267 | 267 | } |
268 | 268 | |
269 | vector<KeyInformation> GetDefaultDirectModeKeys() const { | |
269 | std::vector<KeyInformation> GetDefaultDirectModeKeys() const { | |
270 | 270 | return KeyInfoUtil::ExtractSortedDirectModeKeys(default_config_); |
271 | 271 | } |
272 | 272 | |
273 | vector<KeyInformation> GetDirectModeKeysCtrlJToEnableIME() const { | |
273 | std::vector<KeyInformation> GetDirectModeKeysCtrlJToEnableIME() const { | |
274 | 274 | config::Config config; |
275 | 275 | config.CopyFrom(default_config_); |
276 | 276 | |
284 | 284 | return KeyInfoUtil::ExtractSortedDirectModeKeys(config); |
285 | 285 | } |
286 | 286 | |
287 | vector<KeyInformation> GetDirectModeKeysCtrlBackslashToEnableIME() const { | |
287 | std::vector<KeyInformation> | |
288 | GetDirectModeKeysCtrlBackslashToEnableIME() const { | |
288 | 289 | config::Config config; |
289 | 290 | config.CopyFrom(default_config_); |
290 | 291 |
77 | 77 | |
78 | 78 | bool MigrationUtil::IsFullTIPAvailable() { |
79 | 79 | const LANGID kLANGJaJP = MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN); |
80 | vector<LayoutProfileInfo> profile_list; | |
80 | std::vector<LayoutProfileInfo> profile_list; | |
81 | 81 | if (!UninstallHelper::GetInstalledProfilesByLanguage(kLANGJaJP, |
82 | 82 | &profile_list)) { |
83 | 83 | return false; |
161 | 161 | continue; |
162 | 162 | } |
163 | 163 | |
164 | const wstring id(profile.szId); | |
164 | const std::wstring id(profile.szId); | |
165 | 165 | // A valid |profile.szId| should consists of language ID (LANGID) and |
166 | 166 | // keyboard layout ID (KILD) as follows. |
167 | 167 | // <LangID 1>:<KLID 1> |
194 | 194 | return false; |
195 | 195 | } |
196 | 196 | |
197 | const wstring &profile = wstring(L"0x0411:") + clsid + profile_id; | |
197 | const std::wstring &profile = | |
198 | std::wstring(L"0x0411:") + clsid + profile_id; | |
198 | 199 | if (!::SetDefaultLayoutOrTip(profile.c_str(), 0)) { |
199 | 200 | DLOG(ERROR) << "SetDefaultLayoutOrTip failed"; |
200 | 201 | return false; |
63 | 63 | } // namespace |
64 | 64 | |
65 | 65 | // Writes a REG_SZ channel name into "ap" in Mozc's client state key. |
66 | bool OmahaUtil::WriteChannel(const wstring &value) { | |
66 | bool OmahaUtil::WriteChannel(const std::wstring &value) { | |
67 | 67 | CRegKey key; |
68 | 68 | LONG result = OpenClientStateKey(&key, KEY_READ | KEY_WRITE); |
69 | 69 | if (ERROR_SUCCESS != result) { |
77 | 77 | } |
78 | 78 | |
79 | 79 | // Reads a REG_SZ channel name from "ap" in Mozc's client state key. |
80 | wstring OmahaUtil::ReadChannel() { | |
80 | std::wstring OmahaUtil::ReadChannel() { | |
81 | 81 | CRegKey key; |
82 | 82 | LONG result = OpenClientStateKey(&key, KEY_READ); |
83 | 83 | if (ERROR_SUCCESS != result) { |
89 | 89 | if (ERROR_SUCCESS != result) { |
90 | 90 | return L""; |
91 | 91 | } |
92 | return wstring(buf); | |
92 | return std::wstring(buf); | |
93 | 93 | } |
94 | 94 | |
95 | 95 | bool OmahaUtil::ClearOmahaError() { |
109 | 109 | return true; |
110 | 110 | } |
111 | 111 | |
112 | bool OmahaUtil::WriteOmahaError(const wstring &ui_message, | |
113 | const wstring &header) { | |
112 | bool OmahaUtil::WriteOmahaError(const std::wstring &ui_message, | |
113 | const std::wstring &header) { | |
114 | 114 | CRegKey key; |
115 | 115 | LONG result = OpenClientStateKey(&key, KEY_READ | KEY_WRITE); |
116 | 116 | if (ERROR_SUCCESS != result) { |
122 | 122 | } |
123 | 123 | |
124 | 124 | // Leaves Mozc version in addition to UI message for customer support. |
125 | const wstring &message = header.length() > 0 ? header + L"\r\n" + ui_message | |
126 | : ui_message; | |
125 | const std::wstring &message = | |
126 | header.length() > 0 ? header + L"\r\n" + ui_message : ui_message; | |
127 | 127 | |
128 | 128 | // This message will be displayed by Omaha meta installer in the error |
129 | 129 | // dialog. |
47 | 47 | public: |
48 | 48 | // Writes the channel name specified by |value| for Omaha. |
49 | 49 | // Returns true if the operation completed successfully. |
50 | static bool WriteChannel(const wstring &value); | |
50 | static bool WriteChannel(const std::wstring &value); | |
51 | 51 | |
52 | 52 | // Reads the channel name for Omaha. |
53 | 53 | // Returns an empty string if there is no entry or fails to retrieve the |
54 | 54 | // channel name. |
55 | static wstring ReadChannel(); | |
55 | static std::wstring ReadChannel(); | |
56 | 56 | |
57 | 57 | // Clears the registry entry to specify error message for Omaha. |
58 | 58 | // Returns true if the operation completed successfully. |
60 | 60 | |
61 | 61 | // Writes the registry entry for Omaha to show some error messages. |
62 | 62 | // Returns true if the operation completed successfully. |
63 | static bool WriteOmahaError(const wstring &ui_message, const wstring &header); | |
63 | static bool WriteOmahaError(const std::wstring &ui_message, | |
64 | const std::wstring &header); | |
64 | 65 | |
65 | 66 | // Clears the registry entry for the channel name. |
66 | 67 | // Returns true if the operation completed successfully. |
62 | 62 | const HKEY KRegKey_NotFound = INT2HKEY(100); |
63 | 63 | #undef INT2HKEY |
64 | 64 | |
65 | bool IsEqualInLowercase(const wstring &lhs, const wstring &rhs) { | |
65 | bool IsEqualInLowercase(const std::wstring &lhs, const std::wstring &rhs) { | |
66 | 66 | return WinUtil::SystemEqualString(lhs, rhs, true); |
67 | 67 | } |
68 | 68 | |
115 | 115 | has_##field_name##_ = true; \ |
116 | 116 | return &##field_name##_; \ |
117 | 117 | } |
118 | DEFINE_FIELD(wstring, ap_value) | |
118 | DEFINE_FIELD(std::wstring, ap_value) | |
119 | 119 | DEFINE_FIELD(DWORD, installer_result) |
120 | DEFINE_FIELD(wstring, installer_result_ui_string) | |
120 | DEFINE_FIELD(std::wstring, installer_result_ui_string) | |
121 | 121 | #undef DEFINE_FIELD |
122 | 122 | |
123 | 123 | private: |
124 | 124 | bool omaha_client_state_key_exists_; |
125 | 125 | bool has_ap_value_; |
126 | wstring ap_value_; | |
126 | std::wstring ap_value_; | |
127 | 127 | bool has_installer_result_; |
128 | 128 | DWORD installer_result_; |
129 | 129 | bool has_installer_result_ui_string_; |
130 | wstring installer_result_ui_string_; | |
130 | std::wstring installer_result_ui_string_; | |
131 | 131 | }; |
132 | 132 | |
133 | 133 | typedef PropertySelector<Id> Property; |
134 | 134 | |
135 | 135 | RegistryEmulator() { |
136 | vector<WinAPITestHelper::HookRequest> requests; | |
136 | std::vector<WinAPITestHelper::HookRequest> requests; | |
137 | 137 | requests.push_back( |
138 | 138 | DEFINE_HOOK("advapi32.dll", RegCreateKeyExW, TestRegCreateKeyExW)); |
139 | 139 | requests.push_back( |
216 | 216 | |
217 | 217 | static LSTATUS UpdateString(const wchar_t *value_name, |
218 | 218 | const wchar_t *src, DWORD num_data) { |
219 | wstring *target = nullptr; | |
219 | std::wstring *target = nullptr; | |
220 | 220 | if (IsEqualInLowercase(value_name, kRegEntryNameForChannel)) { |
221 | 221 | target = property()->mutable_ap_value(); |
222 | 222 | } else if (IsEqualInLowercase( |
234 | 234 | const size_t null_char_index = total_size_in_tchar - 1; |
235 | 235 | EXPECT_EQ(L'\0', src[null_char_index]); |
236 | 236 | const size_t total_length_without_null = total_size_in_tchar - 1; |
237 | const wstring value(src, src + total_length_without_null); | |
237 | const std::wstring value(src, src + total_length_without_null); | |
238 | 238 | target->assign(value); |
239 | 239 | } else { |
240 | 240 | target->assign(L""); |
308 | 308 | |
309 | 309 | static LSTATUS QueryString(const wchar_t *value_name, DWORD *type, |
310 | 310 | wchar_t *dest, DWORD *num_data) { |
311 | wstring value; | |
311 | std::wstring value; | |
312 | 312 | if (IsEqualInLowercase(value_name, kRegEntryNameForChannel)) { |
313 | 313 | if (!property()->has_ap_value()) { |
314 | 314 | return ERROR_FILE_NOT_FOUND; |
42 | 42 | const size_t kMaxReadingChars = 512; |
43 | 43 | |
44 | 44 | void UTF8ToSJIS(StringPiece input, string *output) { |
45 | wstring utf16; | |
45 | std::wstring utf16; | |
46 | 46 | Util::UTF8ToWide(input, &utf16); |
47 | 47 | if (utf16.empty()) { |
48 | 48 | output->clear(); |
73 | 73 | |
74 | 74 | } // namespace |
75 | 75 | |
76 | wstring StringUtil::KeyToReading(StringPiece key) { | |
76 | std::wstring StringUtil::KeyToReading(StringPiece key) { | |
77 | 77 | string katakana; |
78 | 78 | Util::HiraganaToKatakana(key, &katakana); |
79 | 79 | |
119 | 119 | if (output_length_without_null != actual_output_length_without_null) { |
120 | 120 | return L""; |
121 | 121 | } |
122 | return wstring(wide_output.get(), actual_output_length_without_null); | |
122 | return std::wstring(wide_output.get(), actual_output_length_without_null); | |
123 | 123 | } |
124 | 124 | |
125 | 125 | string StringUtil::KeyToReadingA(StringPiece key) { |
128 | 128 | return ret; |
129 | 129 | } |
130 | 130 | |
131 | wstring StringUtil::ComposePreeditText(const commands::Preedit &preedit) { | |
132 | wstring value; | |
131 | std::wstring StringUtil::ComposePreeditText(const commands::Preedit &preedit) { | |
132 | std::wstring value; | |
133 | 133 | for (int i = 0; i < preedit.segment_size(); ++i) { |
134 | wstring segment_value; | |
134 | std::wstring segment_value; | |
135 | 135 | mozc::Util::UTF8ToWide(preedit.segment(i).value(), &segment_value); |
136 | 136 | value.append(segment_value); |
137 | 137 | } |
49 | 49 | // http://msdn.microsoft.com/en-us/library/ms629017(VS.85).aspx |
50 | 50 | // This function only supports conversion of Japanese characters (characters |
51 | 51 | // covered by code page 932). |
52 | static wstring KeyToReading(StringPiece key); | |
52 | static std::wstring KeyToReading(StringPiece key); | |
53 | 53 | |
54 | 54 | // Returns a UTF8 string converted from the result of KeyToReading. |
55 | 55 | // This function is mainly for unittest. |
56 | 56 | static string KeyToReadingA(StringPiece key); |
57 | 57 | |
58 | 58 | // Joins all segment strings in |preedit| and returns it. |
59 | static wstring ComposePreeditText(const mozc::commands::Preedit &preedit); | |
59 | static std::wstring ComposePreeditText( | |
60 | const mozc::commands::Preedit &preedit); | |
60 | 61 | }; |
61 | 62 | |
62 | 63 | } // namespace win32 |
128 | 128 | logfont.lfCharSet = DEFAULT_CHARSET; |
129 | 129 | logfont.lfHeight = bitmap_height; |
130 | 130 | logfont.lfQuality = NONANTIALIASED_QUALITY; |
131 | wstring wide_fontname; | |
131 | std::wstring wide_fontname; | |
132 | 132 | Util::UTF8ToWide(fontname, &wide_fontname); |
133 | 133 | const errno_t error = wcscpy_s(logfont.lfFaceName, wide_fontname.c_str()); |
134 | 134 | if (error != 0) { |
146 | 146 | dc.SetBkMode(OPAQUE); |
147 | 147 | dc.SetBkColor(kBackgroundColor); |
148 | 148 | dc.SetTextColor(kForegroundColor); |
149 | wstring wide_text; | |
149 | std::wstring wide_text; | |
150 | 150 | Util::UTF8ToWide(text, &wide_text); |
151 | 151 | CRect rect(0, 0, bitmap_width, bitmap_height); |
152 | 152 | dc.FillSolidRect(rect, kBackgroundColor); |
216 | 216 | // 4-byte alignment. Here we need to do alignment conversion. |
217 | 217 | const size_t mask_buffer_stride = (bitmap_width + 0x0f) / 16 * 2; |
218 | 218 | const size_t mask_buffer_size = mask_buffer_stride * bitmap_width; |
219 | unique_ptr<uint8[]> mask_buffer(new uint8[mask_buffer_size]); | |
219 | std::unique_ptr<uint8[]> mask_buffer(new uint8[mask_buffer_size]); | |
220 | 220 | for (size_t y = 0; y < bitmap_height; ++y) { |
221 | 221 | for (size_t x = 0; x < bitmap_width; ++x) { |
222 | 222 | const uint8 *src_line_start = |
115 | 115 | return HRESULT_FROM_WIN32(result); |
116 | 116 | } |
117 | 117 | |
118 | wstring description; | |
118 | std::wstring description; | |
119 | 119 | mozc::Util::UTF8ToWide(mozc::kProductNameInEnglish, &description); |
120 | 120 | |
121 | 121 | result = key.SetStringValue(nullptr, description.c_str(), REG_SZ); |
192 | 192 | if (result == S_OK) { |
193 | 193 | // We use English name here as culture-invariant description. |
194 | 194 | // Localized name is specified later by SetLanguageProfileDisplayName. |
195 | wstring description; | |
195 | std::wstring description; | |
196 | 196 | mozc::Util::UTF8ToWide(mozc::kProductNameInEnglish, &description); |
197 | 197 | |
198 | 198 | result = profiles->AddLanguageProfile(TsfProfile::GetTextServiceGuid(), |
58 | 58 | |
59 | 59 | namespace { |
60 | 60 | |
61 | typedef map<int, DWORD> PreloadOrderToKLIDMap; | |
61 | typedef std::map<int, DWORD> PreloadOrderToKLIDMap; | |
62 | 62 | |
63 | 63 | // Windows NT 6.0, 6.1 and 6.2 |
64 | 64 | const CLSID CLSID_IMJPTIP = { |
84 | 84 | const uint32 kWaitForAsmCacheReadyEventTimeout = 10000; // 10 sec. |
85 | 85 | |
86 | 86 | // Converts an unsigned integer to a wide string. |
87 | wstring utow(unsigned int i) { | |
88 | wstringstream ss; | |
87 | std::wstring utow(unsigned int i) { | |
88 | std::wstringstream ss; | |
89 | 89 | ss << i; |
90 | 90 | return ss.str(); |
91 | 91 | } |
92 | 92 | |
93 | wstring GetIMEFileNameFromKeyboardLayout( | |
93 | std::wstring GetIMEFileNameFromKeyboardLayout( | |
94 | 94 | const CRegKey &key, const KeyboardLayoutID &klid) { |
95 | 95 | CRegKey subkey; |
96 | 96 | LONG result = subkey.Open(key, klid.ToString().c_str(), KEY_READ); |
109 | 109 | } |
110 | 110 | |
111 | 111 | const ULONG filename_length = (filename_length_including_null - 1); |
112 | const wstring filename(filename_buffer); | |
112 | const std::wstring filename(filename_buffer); | |
113 | 113 | |
114 | 114 | // Note that |filename_length| does not contain NUL character. |
115 | 115 | DCHECK_EQ(filename_length, filename.size()); |
116 | 116 | return filename; |
117 | 117 | } |
118 | 118 | |
119 | bool GenerateKeyboardLayoutList(vector<KeyboardLayoutInfo> *keyboard_layouts) { | |
119 | bool GenerateKeyboardLayoutList( | |
120 | std::vector<KeyboardLayoutInfo> *keyboard_layouts) { | |
120 | 121 | if (keyboard_layouts == nullptr) { |
121 | 122 | return false; |
122 | 123 | } |
145 | 146 | |
146 | 147 | // Note that |value_name_length| does not contain NUL character. |
147 | 148 | const KeyboardLayoutID klid( |
148 | wstring(value_name, value_name + value_name_length)); | |
149 | std::wstring(value_name, value_name + value_name_length)); | |
149 | 150 | |
150 | 151 | if (!klid.has_id()) { |
151 | 152 | continue; |
159 | 160 | return true; |
160 | 161 | } |
161 | 162 | |
162 | bool GenerateKeyboardLayoutMap(map<DWORD, wstring> *keyboard_layouts) { | |
163 | bool GenerateKeyboardLayoutMap( | |
164 | std::map<DWORD, std::wstring> *keyboard_layouts) { | |
163 | 165 | if (keyboard_layouts == nullptr) { |
164 | 166 | return false; |
165 | 167 | } |
166 | vector<KeyboardLayoutInfo> keyboard_layout_list; | |
168 | std::vector<KeyboardLayoutInfo> keyboard_layout_list; | |
167 | 169 | if (!GenerateKeyboardLayoutList(&keyboard_layout_list)) { |
168 | 170 | return false; |
169 | 171 | } |
176 | 178 | return true; |
177 | 179 | } |
178 | 180 | |
179 | wstring GetIMEFileName(HKL hkl) { | |
181 | std::wstring GetIMEFileName(HKL hkl) { | |
180 | 182 | const UINT num_chars_without_null = ::ImmGetIMEFileName(hkl, nullptr, 0); |
181 | 183 | const size_t num_chars_with_null = num_chars_without_null + 1; |
182 | 184 | unique_ptr<wchar_t[]> buffer(new wchar_t[num_chars_with_null]); |
184 | 186 | ::ImmGetIMEFileName(hkl, buffer.get(), num_chars_with_null); |
185 | 187 | |
186 | 188 | // |num_copied| does not include terminating null character. |
187 | return wstring(buffer.get(), buffer.get() + num_copied); | |
189 | return std::wstring(buffer.get(), buffer.get() + num_copied); | |
188 | 190 | } |
189 | 191 | |
190 | 192 | bool GetInstalledProfilesByLanguageForTSF( |
191 | 193 | LANGID langid, |
192 | vector<LayoutProfileInfo> *installed_profiles) { | |
194 | std::vector<LayoutProfileInfo> *installed_profiles) { | |
193 | 195 | ScopedCOMInitializer com_initializer; |
194 | 196 | if (FAILED(com_initializer.error_code())) { |
195 | 197 | return false; |
243 | 245 | |
244 | 246 | bool GetInstalledProfilesByLanguageForIMM32( |
245 | 247 | LANGID langid, |
246 | vector<LayoutProfileInfo> *installed_profiles) { | |
247 | vector<KeyboardLayoutInfo> keyboard_layouts; | |
248 | std::vector<LayoutProfileInfo> *installed_profiles) { | |
249 | std::vector<KeyboardLayoutInfo> keyboard_layouts; | |
248 | 250 | if (!GenerateKeyboardLayoutList(&keyboard_layouts)) { |
249 | 251 | DLOG(ERROR) << "GenerateKeyboardLayoutList failed."; |
250 | 252 | return false; |
302 | 304 | } |
303 | 305 | |
304 | 306 | const int ivalue_name = _wtoi(value_name); |
305 | const wstring wvalue(reinterpret_cast<wchar_t*>(value), | |
307 | const std::wstring wvalue(reinterpret_cast<wchar_t*>(value), | |
306 | 308 | (value_length / sizeof(wchar_t)) - 1); |
307 | 309 | KeyboardLayoutID klid(wvalue); |
308 | 310 | if (!klid.has_id()) { |
313 | 315 | return true; |
314 | 316 | } |
315 | 317 | |
316 | wstring GUIDToString(const GUID &guid) { | |
318 | std::wstring GUIDToString(const GUID &guid) { | |
317 | 319 | wchar_t buffer[256]; |
318 | 320 | const int character_length_with_null = |
319 | 321 | ::StringFromGUID2(guid, buffer, arraysize(buffer)); |
323 | 325 | |
324 | 326 | const size_t character_length_without_null = |
325 | 327 | character_length_with_null - 1; |
326 | return wstring(buffer, buffer + character_length_without_null); | |
327 | } | |
328 | ||
329 | wstring LANGIDToString(LANGID langid) { | |
328 | return std::wstring(buffer, buffer + character_length_without_null); | |
329 | } | |
330 | ||
331 | std::wstring LANGIDToString(LANGID langid) { | |
330 | 332 | wchar_t buffer[5]; |
331 | 333 | HRESULT hr = ::StringCchPrintf(buffer, arraysize(buffer), L"%04x", langid); |
332 | 334 | if (FAILED(hr)) { |
457 | 459 | return true; |
458 | 460 | } |
459 | 461 | |
460 | bool GetActiveKeyboardLayouts(vector<HKL> *keyboard_layouts) { | |
462 | bool GetActiveKeyboardLayouts(std::vector<HKL> *keyboard_layouts) { | |
461 | 463 | if (keyboard_layouts == nullptr) { |
462 | 464 | return false; |
463 | 465 | } |
554 | 556 | // function unloads any active IME if it is included in |ime_filenames|. |
555 | 557 | // If |exclude| is false, this function unloads any active IME unless it is |
556 | 558 | // included in |ime_filenames|. |
557 | void UnloadActivatedKeyboardMain(const vector<wstring> &ime_filenames, | |
559 | void UnloadActivatedKeyboardMain(const std::vector<std::wstring> &ime_filenames, | |
558 | 560 | bool exclude) { |
559 | vector<HKL> loaded_layouts; | |
561 | std::vector<HKL> loaded_layouts; | |
560 | 562 | if (!GetActiveKeyboardLayouts(&loaded_layouts)) { |
561 | 563 | return; |
562 | 564 | } |
563 | 565 | for (size_t i = 0; i < loaded_layouts.size(); ++i) { |
564 | 566 | const HKL hkl = loaded_layouts[i]; |
565 | const wstring ime_filename = GetIMEFileName(hkl); | |
567 | const std::wstring ime_filename = GetIMEFileName(hkl); | |
566 | 568 | if (ime_filename.empty()) { |
567 | 569 | continue; |
568 | 570 | } |
580 | 582 | } |
581 | 583 | |
582 | 584 | void UnloadProfilesForVista( |
583 | const vector<LayoutProfileInfo> &profiles_to_be_removed) { | |
584 | vector <wstring> ime_filenames; | |
585 | const std::vector<LayoutProfileInfo> &profiles_to_be_removed) { | |
586 | std::vector<std::wstring> ime_filenames; | |
585 | 587 | for (size_t i = 0; i < profiles_to_be_removed.size(); ++i) { |
586 | 588 | ime_filenames.push_back(profiles_to_be_removed[i].ime_filename); |
587 | 589 | } |
626 | 628 | return true; |
627 | 629 | } |
628 | 630 | |
629 | bool IsEqualPreload(const PreloadOrderToKLIDMap ¤t_preload_map, | |
630 | const vector<KeyboardLayoutInfo> &new_preload_layouts) { | |
631 | bool IsEqualPreload( | |
632 | const PreloadOrderToKLIDMap ¤t_preload_map, | |
633 | const std::vector<KeyboardLayoutInfo> &new_preload_layouts) { | |
631 | 634 | if (current_preload_map.size() != new_preload_layouts.size()) { |
632 | 635 | return false; |
633 | 636 | } |
649 | 652 | |
650 | 653 | // Currently only keyboard layouts which have IME filename are supported. |
651 | 654 | bool RemoveHotKeyForIME( |
652 | const vector<KeyboardLayoutInfo> &layouts_to_be_removed) { | |
655 | const std::vector<KeyboardLayoutInfo> &layouts_to_be_removed) { | |
653 | 656 | bool succeeded = true; |
654 | 657 | for (DWORD id = IME_HOTKEY_DSWITCH_FIRST; id <= IME_HOTKEY_DSWITCH_LAST; |
655 | 658 | ++id) { |
663 | 666 | if (hkl == nullptr) { |
664 | 667 | continue; |
665 | 668 | } |
666 | const wstring ime_name = GetIMEFileName(hkl); | |
669 | const std::wstring ime_name = GetIMEFileName(hkl); | |
667 | 670 | for (size_t i = 0; i < layouts_to_be_removed.size(); ++i) { |
668 | 671 | const KeyboardLayoutInfo &layout = layouts_to_be_removed[i]; |
669 | 672 | if (layout.ime_filename.empty()) { |
686 | 689 | |
687 | 690 | // Currently this function is Mozc-specific. |
688 | 691 | // TODO(yukawa): Generalize this function for any IME. |
689 | void RemoveHotKeyForVista(const vector<LayoutProfileInfo> &installed_profiles) { | |
690 | vector<KeyboardLayoutInfo> hotkey_remove_targets; | |
692 | void RemoveHotKeyForVista( | |
693 | const std::vector<LayoutProfileInfo> &installed_profiles) { | |
694 | std::vector<KeyboardLayoutInfo> hotkey_remove_targets; | |
691 | 695 | for (size_t i = 0; i < installed_profiles.size(); ++i) { |
692 | 696 | const LayoutProfileInfo &profile = installed_profiles[i]; |
693 | 697 | if (!profile.is_tip && WinUtil::SystemEqualString( |
723 | 727 | // Currently this function is Mozc-specific. |
724 | 728 | // TODO(yukawa): Generalize this function for any IME and/or TIP. |
725 | 729 | bool UninstallHelper::GetNewEnabledProfileForVista( |
726 | const vector<LayoutProfileInfo> ¤t_profiles, | |
727 | const vector<LayoutProfileInfo> &installed_profiles, | |
730 | const std::vector<LayoutProfileInfo> ¤t_profiles, | |
731 | const std::vector<LayoutProfileInfo> &installed_profiles, | |
728 | 732 | LayoutProfileInfo *current_default, |
729 | 733 | LayoutProfileInfo *new_default, |
730 | vector<LayoutProfileInfo> *removed_profiles) { | |
734 | std::vector<LayoutProfileInfo> *removed_profiles) { | |
731 | 735 | if (current_default == nullptr) { |
732 | 736 | return false; |
733 | 737 | } |
795 | 799 | |
796 | 800 | bool UninstallHelper::GetInstalledProfilesByLanguage( |
797 | 801 | LANGID langid, |
798 | vector<LayoutProfileInfo> *installed_profiles) { | |
802 | std::vector<LayoutProfileInfo> *installed_profiles) { | |
799 | 803 | if (installed_profiles == nullptr) { |
800 | 804 | return false; |
801 | 805 | } |
817 | 821 | } |
818 | 822 | |
819 | 823 | bool UninstallHelper::GetCurrentProfilesForVista( |
820 | vector<LayoutProfileInfo> *current_profiles) { | |
824 | std::vector<LayoutProfileInfo> *current_profiles) { | |
821 | 825 | if (current_profiles == nullptr) { |
822 | 826 | return false; |
823 | 827 | } |
824 | 828 | current_profiles->clear(); |
825 | 829 | |
826 | map<DWORD, wstring> keyboard_layouts; | |
830 | std::map<DWORD, std::wstring> keyboard_layouts; | |
827 | 831 | if (!GenerateKeyboardLayoutMap(&keyboard_layouts)) { |
828 | 832 | return false; |
829 | 833 | } |
856 | 860 | } |
857 | 861 | |
858 | 862 | if ((src.dwProfileType & LOTP_KEYBOARDLAYOUT) == LOTP_KEYBOARDLAYOUT) { |
859 | const wstring id(src.szId); | |
863 | const std::wstring id(src.szId); | |
860 | 864 | // A valid |profile.szId| should consists of language ID (LANGID) and |
861 | 865 | // keyboard layout ID (KILD) as follows. |
862 | 866 | // <LangID 1>:<KLID 1> |
886 | 890 | } |
887 | 891 | |
888 | 892 | bool UninstallHelper::RemoveProfilesForVista( |
889 | const vector<LayoutProfileInfo> &profiles_to_be_removed) { | |
893 | const std::vector<LayoutProfileInfo> &profiles_to_be_removed) { | |
890 | 894 | if (profiles_to_be_removed.size() == 0) { |
891 | 895 | // Nothing to do. |
892 | 896 | return true; |
893 | 897 | } |
894 | 898 | |
895 | const wstring &profile_string = ComposeProfileStringForVista( | |
899 | const std::wstring &profile_string = ComposeProfileStringForVista( | |
896 | 900 | profiles_to_be_removed); |
897 | 901 | |
898 | 902 | const BOOL result = ::InstallLayoutOrTipUserReg( |
901 | 905 | return result != FALSE; |
902 | 906 | } |
903 | 907 | |
904 | wstring UninstallHelper::ComposeProfileStringForVista( | |
905 | const vector<LayoutProfileInfo> &profiles) { | |
906 | wstringstream ss; | |
908 | std::wstring UninstallHelper::ComposeProfileStringForVista( | |
909 | const std::vector<LayoutProfileInfo> &profiles) { | |
910 | std::wstringstream ss; | |
907 | 911 | for (size_t i = 0; i < profiles.size(); ++i) { |
908 | 912 | const LayoutProfileInfo &info = profiles[i]; |
909 | 913 | if (i != 0) { |
910 | 914 | ss << L";"; |
911 | 915 | } |
912 | 916 | |
913 | const wstring &langid_string = LANGIDToString(info.langid); | |
917 | const std::wstring &langid_string = LANGIDToString(info.langid); | |
914 | 918 | if (langid_string.empty()) { |
915 | 919 | continue; |
916 | 920 | } |
917 | 921 | |
918 | 922 | if (info.is_tip) { |
919 | const wstring &clsid_string = GUIDToString(info.clsid); | |
920 | const wstring &guid_string = GUIDToString(info.profile_guid); | |
923 | const std::wstring &clsid_string = GUIDToString(info.clsid); | |
924 | const std::wstring &guid_string = GUIDToString(info.profile_guid); | |
921 | 925 | if (clsid_string.empty() || guid_string.empty()) { |
922 | 926 | continue; |
923 | 927 | } |
945 | 949 | DLOG(ERROR) << "EnableAndBroadcastNewLayout failed."; |
946 | 950 | } |
947 | 951 | |
948 | vector<LayoutProfileInfo> profile_list; | |
952 | std::vector<LayoutProfileInfo> profile_list; | |
949 | 953 | profile_list.push_back(new_default); |
950 | const wstring profile_string = ComposeProfileStringForVista(profile_list); | |
954 | const std::wstring profile_string = | |
955 | ComposeProfileStringForVista(profile_list); | |
951 | 956 | if (profile_string.empty()) { |
952 | 957 | return false; |
953 | 958 | } |
968 | 973 | } |
969 | 974 | |
970 | 975 | bool UninstallHelper::RestoreUserIMEEnvironmentForVista(bool broadcast_change) { |
971 | vector<LayoutProfileInfo> installed_profiles; | |
976 | std::vector<LayoutProfileInfo> installed_profiles; | |
972 | 977 | if (!GetInstalledProfilesByLanguage(kLANGJaJP, &installed_profiles)) { |
973 | 978 | return false; |
974 | 979 | } |
975 | 980 | |
976 | 981 | RemoveHotKeyForVista(installed_profiles); |
977 | 982 | |
978 | vector<LayoutProfileInfo> current_profiles; | |
983 | std::vector<LayoutProfileInfo> current_profiles; | |
979 | 984 | if (!GetCurrentProfilesForVista(¤t_profiles)) { |
980 | 985 | return false; |
981 | 986 | } |
982 | 987 | LayoutProfileInfo current_default; |
983 | 988 | LayoutProfileInfo new_default; |
984 | vector<LayoutProfileInfo> removed_profiles; | |
989 | std::vector<LayoutProfileInfo> removed_profiles; | |
985 | 990 | if (!GetNewEnabledProfileForVista(current_profiles, installed_profiles, |
986 | 991 | ¤t_default, &new_default, |
987 | 992 | &removed_profiles)) { |
44 | 44 | struct KeyboardLayoutInfo { |
45 | 45 | KeyboardLayoutInfo(); |
46 | 46 | DWORD klid; |
47 | wstring ime_filename; | |
47 | std::wstring ime_filename; | |
48 | 48 | }; |
49 | 49 | |
50 | 50 | struct LayoutProfileInfo { |
53 | 53 | CLSID clsid; |
54 | 54 | GUID profile_guid; |
55 | 55 | DWORD klid; |
56 | wstring ime_filename; | |
56 | std::wstring ime_filename; | |
57 | 57 | bool is_default; |
58 | 58 | bool is_tip; |
59 | 59 | bool is_enabled; |
87 | 87 | // retrieved in successful. |
88 | 88 | static bool GetInstalledProfilesByLanguage( |
89 | 89 | LANGID langid, |
90 | vector<LayoutProfileInfo> *installed_profiles); | |
90 | std::vector<LayoutProfileInfo> *installed_profiles); | |
91 | 91 | |
92 | 92 | private: |
93 | 93 | // This function is the main part of RestoreUserIMEEnvironmentMain for |
97 | 97 | // Returns true if both new enabled profiles and new default profile are |
98 | 98 | // successfully determined. |
99 | 99 | static bool GetNewEnabledProfileForVista( |
100 | const vector<LayoutProfileInfo> ¤t_profiles, | |
101 | const vector<LayoutProfileInfo> &installed_profiles, | |
100 | const std::vector<LayoutProfileInfo> ¤t_profiles, | |
101 | const std::vector<LayoutProfileInfo> &installed_profiles, | |
102 | 102 | LayoutProfileInfo *current_default, |
103 | 103 | LayoutProfileInfo *new_default, |
104 | vector<LayoutProfileInfo> *removed_profiles); | |
104 | std::vector<LayoutProfileInfo> *removed_profiles); | |
105 | 105 | |
106 | 106 | // Returns true if the list of keyboard layout and TIP for the current user |
107 | 107 | // is retrieved in successful. |
108 | 108 | static bool GetCurrentProfilesForVista( |
109 | vector<LayoutProfileInfo> *current_profiles); | |
109 | std::vector<LayoutProfileInfo> *current_profiles); | |
110 | 110 | |
111 | 111 | // Returns true if the list of keyboard layout and TIP for the current user |
112 | 112 | // is updated with the specified list as |profiles_to_be_removed|. |
113 | 113 | static bool RemoveProfilesForVista( |
114 | const vector<LayoutProfileInfo> &profiles_to_be_removed); | |
114 | const std::vector<LayoutProfileInfo> &profiles_to_be_removed); | |
115 | 115 | |
116 | 116 | // Returns true if |profile| is set as the new default IME or TIP. |
117 | 117 | static bool SetDefaultForVista( |
121 | 121 | // Returns a string in which the list of profile information specified in |
122 | 122 | // |profiles| is encoded. See input_dll.h for the format. |
123 | 123 | // Returns an empty string if fails. |
124 | static wstring ComposeProfileStringForVista( | |
125 | const vector<LayoutProfileInfo> &profiles); | |
124 | static std::wstring ComposeProfileStringForVista( | |
125 | const std::vector<LayoutProfileInfo> &profiles); | |
126 | 126 | |
127 | 127 | FRIEND_TEST(UninstallHelperTest, BasicCaseForVista); |
128 | 128 | FRIEND_TEST(UninstallHelperTest, BasicCaseForWin8); |
51 | 51 | |
52 | 52 | const DWORD kJapaneseKLID = 0xE0200411; |
53 | 53 | |
54 | wstring ToWideString(const string &str) { | |
55 | wstring wide; | |
54 | std::wstring ToWideString(const string &str) { | |
55 | std::wstring wide; | |
56 | 56 | if (mozc::Util::UTF8ToWide(str, &wide) <= 0) { |
57 | 57 | return L""; |
58 | 58 | } |
66 | 66 | // 2. Set Google Japanese Input as the default IME. |
67 | 67 | // 3. Uninstall Google Japanese Input. |
68 | 68 | // -> MS-IME should be the default IME. |
69 | vector<LayoutProfileInfo> current_profiles; | |
69 | std::vector<LayoutProfileInfo> current_profiles; | |
70 | 70 | { |
71 | 71 | // Full IMM32 version of Google Japanese Input. |
72 | 72 | LayoutProfileInfo info; |
94 | 94 | current_profiles.push_back(info); |
95 | 95 | } |
96 | 96 | |
97 | vector<LayoutProfileInfo> installed_profiles; | |
97 | std::vector<LayoutProfileInfo> installed_profiles; | |
98 | 98 | installed_profiles = current_profiles; |
99 | 99 | |
100 | 100 | LayoutProfileInfo current_default; |
101 | 101 | LayoutProfileInfo new_default; |
102 | vector<LayoutProfileInfo> removed_profiles; | |
102 | std::vector<LayoutProfileInfo> removed_profiles; | |
103 | 103 | |
104 | 104 | EXPECT_TRUE(UninstallHelper::GetNewEnabledProfileForVista( |
105 | 105 | current_profiles, |
120 | 120 | // 2. Set Google Japanese Input (IMM32) as the default IME. |
121 | 121 | // 3. Uninstall Google Japanese Input. |
122 | 122 | // -> MS-IME should be the default IME. |
123 | vector<LayoutProfileInfo> current_profiles; | |
123 | std::vector<LayoutProfileInfo> current_profiles; | |
124 | 124 | { |
125 | 125 | // Full IMM32 version of Google Japanese Input. |
126 | 126 | LayoutProfileInfo info; |
161 | 161 | current_profiles.push_back(info); |
162 | 162 | } |
163 | 163 | |
164 | vector<LayoutProfileInfo> installed_profiles; | |
164 | std::vector<LayoutProfileInfo> installed_profiles; | |
165 | 165 | installed_profiles = current_profiles; |
166 | 166 | |
167 | 167 | LayoutProfileInfo current_default; |
168 | 168 | LayoutProfileInfo new_default; |
169 | vector<LayoutProfileInfo> removed_profiles; | |
169 | std::vector<LayoutProfileInfo> removed_profiles; | |
170 | 170 | |
171 | 171 | EXPECT_TRUE(UninstallHelper::GetNewEnabledProfileForVista( |
172 | 172 | current_profiles, |
187 | 187 | // only their availability is checked. |
188 | 188 | // TODO(yukawa): Use API hook to inject mock result. |
189 | 189 | TEST(UninstallHelperTest, LoadKeyboardProfilesTest) { |
190 | vector<LayoutProfileInfo> installed_profiles; | |
190 | std::vector<LayoutProfileInfo> installed_profiles; | |
191 | 191 | EXPECT_TRUE(UninstallHelper::GetInstalledProfilesByLanguage( |
192 | 192 | kLANGJaJP, &installed_profiles)); |
193 | 193 | |
194 | vector<LayoutProfileInfo> current_profiles; | |
194 | std::vector<LayoutProfileInfo> current_profiles; | |
195 | 195 | EXPECT_TRUE(UninstallHelper::GetCurrentProfilesForVista( |
196 | 196 | ¤t_profiles)); |
197 | 197 | } |
198 | 198 | |
199 | 199 | TEST(UninstallHelperTest, ComposeProfileStringForVistaTest) { |
200 | vector<LayoutProfileInfo> profiles; | |
200 | std::vector<LayoutProfileInfo> profiles; | |
201 | 201 | { |
202 | 202 | LayoutProfileInfo info; |
203 | 203 | info.langid = kLANGJaJP; |
213 | 213 | info.is_tip = true; |
214 | 214 | profiles.push_back(info); |
215 | 215 | } |
216 | const wstring &profile_string = | |
216 | const std::wstring &profile_string = | |
217 | 217 | UninstallHelper::ComposeProfileStringForVista(profiles); |
218 | 218 | EXPECT_EQ(L"0411:E0220411;0411:{03B5835F-F03C-411B-9CE2-AA23E1171E36}" |
219 | 219 | L"{A76C93D9-5523-4E90-AAFA-4DB112F9AC76}", |
49 | 49 | using ATL::CStringW; |
50 | 50 | using std::unique_ptr; |
51 | 51 | |
52 | wstring SafeGetWindowText(HWND window_handle) { | |
52 | std::wstring SafeGetWindowText(HWND window_handle) { | |
53 | 53 | if (!::IsWindow(window_handle)) { |
54 | return wstring(); | |
54 | return std::wstring(); | |
55 | 55 | } |
56 | 56 | |
57 | 57 | const int text_len_without_null = GetWindowTextLength(window_handle); |
58 | 58 | if (text_len_without_null <= 0) { |
59 | return wstring(); | |
59 | return std::wstring(); | |
60 | 60 | } |
61 | 61 | |
62 | 62 | const size_t buffer_len = text_len_without_null + 1; |
66 | 66 | window_handle, buffer.get(), buffer_len); |
67 | 67 | |
68 | 68 | if (copied_len_without_null <= 0) { |
69 | return wstring(); | |
69 | return std::wstring(); | |
70 | 70 | } |
71 | 71 | |
72 | return wstring(buffer.get(), copied_len_without_null); | |
72 | return std::wstring(buffer.get(), copied_len_without_null); | |
73 | 73 | } |
74 | 74 | |
75 | 75 | } // namespace |
76 | 76 | |
77 | wstring WindowUtil::GetWindowClassName(HWND window_handle) { | |
77 | std::wstring WindowUtil::GetWindowClassName(HWND window_handle) { | |
78 | 78 | // Maximum length of WindowClass is assumed to be 256. |
79 | 79 | // http://msdn.microsoft.com/en-us/library/ms633576.aspx |
80 | 80 | wchar_t buffer[256 + 1] = {}; |
83 | 83 | if (num_copied_without_null + 1 >= arraysize(buffer)) { |
84 | 84 | return L""; |
85 | 85 | } |
86 | return wstring(buffer, num_copied_without_null); | |
86 | return std::wstring(buffer, num_copied_without_null); | |
87 | 87 | } |
88 | 88 | |
89 | 89 | // static |
41 | 41 | public: |
42 | 42 | // Returns the window class name of |window_handle|. |
43 | 43 | // Returns an empty string when fails to retrieve the class name. |
44 | static wstring GetWindowClassName(HWND window_handle); | |
44 | static std::wstring GetWindowClassName(HWND window_handle); | |
45 | 45 | |
46 | 46 | // Returns true if the target window specified by |window_handle| can be |
47 | 47 | // successfully configured to receive an incoming message from lower |
41 | 41 | } // namespace |
42 | 42 | |
43 | 43 | int RunRegisterIME(int argc, char *argv[]) { |
44 | const wstring ime_path = ImmRegistrar::GetFullPathForIME(); | |
44 | const std::wstring ime_path = ImmRegistrar::GetFullPathForIME(); | |
45 | 45 | if (ime_path.empty()) { |
46 | 46 | return kErrorLevelGeneralError; |
47 | 47 | } |
48 | const wstring ime_filename = ImmRegistrar::GetFileNameForIME(); | |
48 | const std::wstring ime_filename = ImmRegistrar::GetFileNameForIME(); | |
49 | 49 | |
50 | const wstring layout_name = ImmRegistrar::GetLayoutName(); | |
50 | const std::wstring layout_name = ImmRegistrar::GetLayoutName(); | |
51 | 51 | if (layout_name.empty()) { |
52 | 52 | return kErrorLevelGeneralError; |
53 | 53 | } |
67 | 67 | int RunUnregisterIME(int argc, char *argv[]) { |
68 | 68 | UninstallHelper::RestoreUserIMEEnvironmentMain(); |
69 | 69 | |
70 | const wstring ime_filename = ImmRegistrar::GetFileNameForIME(); | |
70 | const std::wstring ime_filename = ImmRegistrar::GetFileNameForIME(); | |
71 | 71 | if (ime_filename.empty()) { |
72 | 72 | return kErrorLevelGeneralError; |
73 | 73 | } |
83 | 83 | |
84 | 84 | HMODULE g_module = nullptr; |
85 | 85 | |
86 | wstring GetMozcComponentPath(const string &filename) { | |
86 | std::wstring GetMozcComponentPath(const string &filename) { | |
87 | 87 | const string path = mozc::SystemUtil::GetServerDirectory() + "\\" + filename; |
88 | wstring wpath; | |
88 | std::wstring wpath; | |
89 | 89 | mozc::Util::UTF8ToWide(path, &wpath); |
90 | 90 | return wpath; |
91 | 91 | } |
93 | 93 | // Retrieves the value for an installer property. |
94 | 94 | // Returns an empty string if a property corresponding to |name| is not found or |
95 | 95 | // error occurs. |
96 | wstring GetProperty(MSIHANDLE msi, const wstring &name) { | |
96 | std::wstring GetProperty(MSIHANDLE msi, const std::wstring &name) { | |
97 | 97 | DWORD num_buf = 0; |
98 | 98 | // Obtains the size of the property's string, without null termination. |
99 | 99 | // Note: |MsiGetProperty()| requires non-null writable buffer. |
111 | 111 | return L""; |
112 | 112 | } |
113 | 113 | |
114 | return wstring(buf.get()); | |
115 | } | |
116 | ||
117 | bool SetProperty(MSIHANDLE msi, const wstring &name, const wstring &value) { | |
114 | return std::wstring(buf.get()); | |
115 | } | |
116 | ||
117 | bool SetProperty( | |
118 | MSIHANDLE msi, const std::wstring &name, const std::wstring &value) { | |
118 | 119 | if (MsiSetProperty(msi, name.c_str(), value.c_str()) != ERROR_SUCCESS) { |
119 | 120 | return false; |
120 | 121 | } |
141 | 142 | } |
142 | 143 | #endif |
143 | 144 | |
144 | wstring FormatMessageByResourceId(int resourceID, ...) { | |
145 | std::wstring FormatMessageByResourceId(int resourceID, ...) { | |
145 | 146 | wchar_t format_message[4096]; |
146 | 147 | { |
147 | 148 | const int length = ::LoadString(g_module, resourceID, format_message, |
169 | 170 | return buffer; |
170 | 171 | } |
171 | 172 | |
172 | wstring GetVersionHeader() { | |
173 | std::wstring GetVersionHeader() { | |
173 | 174 | return FormatMessageByResourceId(IDS_FORMAT_VERSION_INFO, |
174 | 175 | mozc::Version::GetMozcVersionW().c_str()); |
175 | 176 | } |
194 | 195 | mozc::Version::GetMozcVersionW().c_str(), function, line); |
195 | 196 | ::OutputDebugStringW(log); |
196 | 197 | #endif |
197 | const wstring &message = | |
198 | const std::wstring &message = | |
198 | 199 | FormatMessageByResourceId(IDS_FORMAT_FUNCTION_AND_LINE, |
199 | 200 | function, line); |
200 | 201 | return OmahaUtil::WriteOmahaError(message, GetVersionHeader()); |
366 | 367 | DEBUG_BREAK_FOR_DEBUGGER(); |
367 | 368 | // store the CHANNEL value specified in the command line argument for |
368 | 369 | // WriteApValue. |
369 | const wstring channel = GetProperty(msi_handle, L"CHANNEL"); | |
370 | const std::wstring channel = GetProperty(msi_handle, L"CHANNEL"); | |
370 | 371 | if (!channel.empty()) { |
371 | 372 | if (!SetProperty(msi_handle, L"WriteApValue", channel)) { |
372 | 373 | LOG_ERROR_FOR_OMAHA(); |
375 | 376 | } |
376 | 377 | |
377 | 378 | // store the original ap value for WriteApValueRollback. |
378 | const wstring ap_value = OmahaUtil::ReadChannel(); | |
379 | const std::wstring ap_value = OmahaUtil::ReadChannel(); | |
379 | 380 | if (!SetProperty(msi_handle, L"WriteApValueRollback", ap_value.c_str())) { |
380 | 381 | LOG_ERROR_FOR_OMAHA(); |
381 | 382 | return ERROR_INSTALL_FAILURE; |
382 | 383 | } |
383 | 384 | |
384 | 385 | // store the current settings of the cache service. |
385 | wstring backup; | |
386 | std::wstring backup; | |
386 | 387 | if (!mozc::CacheServiceManager::BackupStateAsString(&backup)) { |
387 | 388 | LOG_ERROR_FOR_OMAHA(); |
388 | 389 | return ERROR_INSTALL_FAILURE; |
404 | 405 | // "RestoreServiceState" and "RestoreServiceStateRollback" |
405 | 406 | UINT __stdcall RestoreServiceState(MSIHANDLE msi_handle) { |
406 | 407 | DEBUG_BREAK_FOR_DEBUGGER(); |
407 | const wstring &backup = GetProperty(msi_handle, L"CustomActionData"); | |
408 | const std::wstring &backup = GetProperty(msi_handle, L"CustomActionData"); | |
408 | 409 | if (!mozc::CacheServiceManager::RestoreStateFromString(backup)) { |
409 | 410 | return ERROR_INSTALL_FAILURE; |
410 | 411 | } |
424 | 425 | |
425 | 426 | UINT __stdcall WriteApValue(MSIHANDLE msi_handle) { |
426 | 427 | DEBUG_BREAK_FOR_DEBUGGER(); |
427 | const wstring channel = GetProperty(msi_handle, L"CustomActionData"); | |
428 | const std::wstring channel = GetProperty(msi_handle, L"CustomActionData"); | |
428 | 429 | if (channel.empty()) { |
429 | 430 | // OK. Does not change ap value when CustomActionData is not found. |
430 | 431 | return ERROR_SUCCESS; |
440 | 441 | |
441 | 442 | UINT __stdcall WriteApValueRollback(MSIHANDLE msi_handle) { |
442 | 443 | DEBUG_BREAK_FOR_DEBUGGER(); |
443 | const wstring ap_value = GetProperty(msi_handle, L"CustomActionData"); | |
444 | const std::wstring ap_value = GetProperty(msi_handle, L"CustomActionData"); | |
444 | 445 | if (ap_value.empty()) { |
445 | 446 | // The ap value did not originally exist so attempt to delete the value. |
446 | 447 | if (!OmahaUtil::ClearChannel()) { |
461 | 462 | UINT __stdcall InstallIME(MSIHANDLE msi_handle) { |
462 | 463 | DEBUG_BREAK_FOR_DEBUGGER(); |
463 | 464 | |
464 | const wstring ime_path = | |
465 | const std::wstring ime_path = | |
465 | 466 | mozc::win32::ImmRegistrar::GetFullPathForIME(); |
466 | 467 | if (ime_path.empty()) { |
467 | 468 | LOG_ERROR_FOR_OMAHA(); |
468 | 469 | return ERROR_INSTALL_FAILURE; |
469 | 470 | } |
470 | const wstring ime_filename = | |
471 | const std::wstring ime_filename = | |
471 | 472 | mozc::win32::ImmRegistrar::GetFileNameForIME(); |
472 | 473 | |
473 | const wstring layout_name = mozc::win32::ImmRegistrar::GetLayoutName(); | |
474 | const std::wstring layout_name = mozc::win32::ImmRegistrar::GetLayoutName(); | |
474 | 475 | if (layout_name.empty()) { |
475 | 476 | LOG_ERROR_FOR_OMAHA(); |
476 | 477 | return ERROR_INSTALL_FAILURE; |
497 | 498 | |
498 | 499 | UINT __stdcall UninstallIME(MSIHANDLE msi_handle) { |
499 | 500 | DEBUG_BREAK_FOR_DEBUGGER(); |
500 | const wstring ime_filename = | |
501 | const std::wstring ime_filename = | |
501 | 502 | mozc::win32::ImmRegistrar::GetFileNameForIME(); |
502 | 503 | if (ime_filename.empty()) { |
503 | 504 | return ERROR_INSTALL_FAILURE; |
517 | 518 | mozc::ScopedCOMInitializer com_initializer; |
518 | 519 | |
519 | 520 | #if defined(_M_X64) |
520 | const wstring &path = GetMozcComponentPath(mozc::kMozcTIP64); | |
521 | const std::wstring &path = GetMozcComponentPath(mozc::kMozcTIP64); | |
521 | 522 | #elif defined(_M_IX86) |
522 | const wstring &path = GetMozcComponentPath(mozc::kMozcTIP32); | |
523 | const std::wstring &path = GetMozcComponentPath(mozc::kMozcTIP32); | |
523 | 524 | #else |
524 | 525 | #error "Unsupported CPU architecture" |
525 | 526 | #endif // _M_X64, _M_IX86, and others |
255 | 255 | } |
256 | 256 | info->offsets.push_back(offset); |
257 | 257 | |
258 | wstring value; | |
258 | std::wstring value; | |
259 | 259 | if (mozc::Util::UTF8ToWide(candidate_list.candidates(i).value(), &value) == |
260 | 260 | 0) { |
261 | 261 | value.clear(); |
364 | 364 | |
365 | 365 | HIMCC CandidateInfoUtil::Update(HIMCC current_handle, |
366 | 366 | const mozc::commands::Output &output, |
367 | vector<UIMessage> *messages) { | |
367 | std::vector<UIMessage> *messages) { | |
368 | 368 | CandidateInfo info; |
369 | 369 | Convert(output, &info); |
370 | 370 |
58 | 58 | DWORD count; |
59 | 59 | DWORD selection; |
60 | 60 | bool show_candidate; |
61 | vector<DWORD> offsets; | |
62 | vector<wchar_t> text_buffer; | |
61 | std::vector<DWORD> offsets; | |
62 | std::vector<wchar_t> text_buffer; | |
63 | 63 | }; |
64 | 64 | |
65 | 65 | class CandidateInfoUtil { |
83 | 83 | // of the returned handle either way. |
84 | 84 | static HIMCC Update(HIMCC current_handle, |
85 | 85 | const mozc::commands::Output &output, |
86 | vector<UIMessage> *messages); | |
86 | std::vector<UIMessage> *messages); | |
87 | 87 | |
88 | 88 | private: |
89 | 89 | static bool Convert(const mozc::commands::Output &output, |
134 | 134 | reinterpret_cast<const BYTE *>(header_) + |
135 | 135 | header_->dwOffset[candidate_list_no]); |
136 | 136 | } |
137 | const wstring GetCandidateString(int candidate_list_no, | |
137 | const std::wstring GetCandidateString(int candidate_list_no, | |
138 | 138 | int candidate_index) const { |
139 | 139 | const CANDIDATELIST *list = GetList(candidate_list_no); |
140 | 140 | DCHECK_GE(candidate_index, 0); |
455 | 455 | } |
456 | 456 | } |
457 | 457 | |
458 | string ToUTF8(const wstring &wstr) { | |
458 | string ToUTF8(const std::wstring &wstr) { | |
459 | 459 | string result; |
460 | 460 | Util::WideToUTF8(wstr, &result); |
461 | 461 | return result; |
81 | 81 | } |
82 | 82 | |
83 | 83 | bool CompositionString::Update( |
84 | const mozc::commands::Output &output, vector<UIMessage> *messages) { | |
84 | const mozc::commands::Output &output, std::vector<UIMessage> *messages) { | |
85 | 85 | CompositionString prev_composition; |
86 | 86 | ::CopyMemory(&prev_composition, this, sizeof(CompositionString)); |
87 | 87 | |
135 | 135 | |
136 | 136 | HRESULT result = S_OK; |
137 | 137 | |
138 | wstring result_string; | |
138 | std::wstring result_string; | |
139 | 139 | mozc::Util::UTF8ToWide(output.result().value(), &result_string); |
140 | 140 | result = ::StringCchCopyN(result_, |
141 | 141 | arraysize(result_), |
159 | 159 | if (output.result().has_key()) { |
160 | 160 | // Reading string should be stored as half-width katakana like |
161 | 161 | // other major IMEs. See b/1793283 for details. |
162 | const wstring &reading_string = | |
162 | const std::wstring &reading_string = | |
163 | 163 | StringUtil::KeyToReading(output.result().key()); |
164 | 164 | result = ::StringCchCopyN(result_reading_, |
165 | 165 | arraysize(result_reading_), |
193 | 193 | |
194 | 194 | const mozc::commands::Preedit &preedit = output.preedit(); |
195 | 195 | |
196 | vector<BYTE> reading_attributes; | |
197 | vector<DWORD> reading_clauses; | |
196 | std::vector<BYTE> reading_attributes; | |
197 | std::vector<DWORD> reading_clauses; | |
198 | 198 | reading_clauses.push_back(0); |
199 | 199 | |
200 | vector<BYTE> composition_attributes; | |
201 | vector<DWORD> composition_clauses; | |
200 | std::vector<BYTE> composition_attributes; | |
201 | std::vector<DWORD> composition_clauses; | |
202 | 202 | composition_clauses.push_back(0); |
203 | 203 | |
204 | wstring reading_string; | |
205 | wstring composition_string; | |
204 | std::wstring reading_string; | |
205 | std::wstring composition_string; | |
206 | 206 | |
207 | 207 | // As filed in b/2962397, we should use ATTR_CONVERTED as default |
208 | 208 | // attribute when the preedit state is 'Convert' ("変換") or 'Prediction' |
220 | 220 | if (segment.has_key()) { |
221 | 221 | // Reading string should be stored as half-width katakana like |
222 | 222 | // other major IMEs. See b/1793283 for details. |
223 | const wstring &segment_reading = | |
223 | const std::wstring &segment_reading = | |
224 | 224 | StringUtil::KeyToReading(segment.key()); |
225 | 225 | reading_string.append(segment_reading); |
226 | 226 | for (size_t i = 0; i < segment_reading.size(); ++i) { |
239 | 239 | reading_clauses.push_back(reading_string.size()); |
240 | 240 | DCHECK(segment.has_value()); |
241 | 241 | { |
242 | wstring segment_composition; | |
242 | std::wstring segment_composition; | |
243 | 243 | mozc::Util::UTF8ToWide(segment.value(), &segment_composition); |
244 | 244 | composition_string.append(segment_composition); |
245 | 245 | preedit_utf8.append(segment.value()); |
52 | 52 | public: |
53 | 53 | bool Initialize(); |
54 | 54 | bool Update(const mozc::commands::Output &output, |
55 | vector<UIMessage> *messages); | |
55 | std::vector<UIMessage> *messages); | |
56 | 56 | |
57 | 57 | // Returns |focused_character_index_|, which represents the index of wide |
58 | 58 | // character where suggest/predict/candidate window is aligned. |
65 | 65 | const BYTE *addr = reinterpret_cast<const BYTE*>(&composition); |
66 | 66 | const wchar_t *string_start = |
67 | 67 | reinterpret_cast<const wchar_t *>(addr + offset); |
68 | const wstring wstr(string_start, string_start + length); | |
68 | const std::wstring wstr(string_start, string_start + length); | |
69 | 69 | string str; |
70 | 70 | Util::WideToUTF8(wstr.c_str(), &str); |
71 | 71 | return str; |
486 | 486 | segment->set_value("が"); |
487 | 487 | segment->set_value_length(1); |
488 | 488 | |
489 | vector<UIMessage> messages; | |
489 | std::vector<UIMessage> messages; | |
490 | 490 | EXPECT_TRUE(compstr.Update(output, &messages)); |
491 | 491 | EXPECT_EQ(2, messages.size()); |
492 | 492 | |
540 | 540 | output.mutable_status()->set_activated(true); |
541 | 541 | output.mutable_status()->set_mode(mozc::commands::HIRAGANA); |
542 | 542 | |
543 | vector<UIMessage> messages; | |
543 | std::vector<UIMessage> messages; | |
544 | 544 | EXPECT_TRUE(compstr.Update(output, &messages)); |
545 | 545 | EXPECT_EQ(2, messages.size()); |
546 | 546 | |
587 | 587 | result->set_value("が"); |
588 | 588 | result->set_type(mozc::commands::Result::STRING); |
589 | 589 | |
590 | vector<UIMessage> messages; | |
590 | std::vector<UIMessage> messages; | |
591 | 591 | EXPECT_TRUE(compstr.Update(output, &messages)); |
592 | 592 | EXPECT_EQ(2, messages.size()); |
593 | 593 | |
642 | 642 | output.mutable_status()->set_activated(true); |
643 | 643 | output.mutable_status()->set_mode(mozc::commands::HIRAGANA); |
644 | 644 | |
645 | vector<UIMessage> messages; | |
645 | std::vector<UIMessage> messages; | |
646 | 646 | EXPECT_TRUE(compstr.Update(output, &messages)); |
647 | 647 | EXPECT_EQ(3, messages.size()); |
648 | 648 | |
707 | 707 | segment->set_value("が"); |
708 | 708 | segment->set_value_length(1); |
709 | 709 | |
710 | vector<UIMessage> messages; | |
710 | std::vector<UIMessage> messages; | |
711 | 711 | EXPECT_TRUE(compstr.Update(output, &messages)); |
712 | 712 | EXPECT_EQ(1, messages.size()); |
713 | 713 | |
751 | 751 | CompositionString compstr; |
752 | 752 | EXPECT_TRUE(compstr.Initialize()); |
753 | 753 | |
754 | vector<UIMessage> messages; | |
754 | std::vector<UIMessage> messages; | |
755 | 755 | EXPECT_TRUE(compstr.Update(output, &messages)); |
756 | 756 | EXPECT_EQ(2, messages.size()); |
757 | 757 | |
805 | 805 | CompositionString compstr; |
806 | 806 | EXPECT_TRUE(compstr.Initialize()); |
807 | 807 | |
808 | vector<UIMessage> messages; | |
808 | std::vector<UIMessage> messages; | |
809 | 809 | EXPECT_TRUE(compstr.Update(output, &messages)); |
810 | 810 | EXPECT_EQ(2, messages.size()); |
811 | 811 | |
871 | 871 | // conversion. |
872 | 872 | FillOutputForConversion(&output, 0, false); |
873 | 873 | { |
874 | vector<UIMessage> messages; | |
874 | std::vector<UIMessage> messages; | |
875 | 875 | EXPECT_TRUE(compstr.Update(output, &messages)); |
876 | 876 | EXPECT_EQ(2, messages.size()); |
877 | 877 | |
930 | 930 | // Second conversion |
931 | 931 | FillOutputForConversion(&output, 1, true); |
932 | 932 | { |
933 | vector<UIMessage> messages; | |
933 | std::vector<UIMessage> messages; | |
934 | 934 | EXPECT_TRUE(compstr.Update(output, &messages)); |
935 | 935 | EXPECT_EQ(1, messages.size()); |
936 | 936 | |
1023 | 1023 | status->set_mode(commands::HIRAGANA); |
1024 | 1024 | } |
1025 | 1025 | |
1026 | vector<UIMessage> messages; | |
1026 | std::vector<UIMessage> messages; | |
1027 | 1027 | EXPECT_TRUE(compstr.Update(output, &messages)); |
1028 | 1028 | |
1029 | 1029 | // Here, |focused_character_index_| != Preedit::highlighted_position() |
125 | 125 | |
126 | 126 | bool UpdateCompositionString(HIMC himc, |
127 | 127 | const commands::Output &output, |
128 | vector<UIMessage> *messages) { | |
128 | std::vector<UIMessage> *messages) { | |
129 | 129 | ScopedHIMC<InputContext> context(himc); |
130 | 130 | |
131 | 131 | // When the string is inserted from Tablet Input Panel, MSCTF shrinks the |
150 | 150 | MessageQueue *message_queue) { |
151 | 151 | ScopedHIMC<InputContext> context(himc); |
152 | 152 | ScopedHIMCC<PrivateContext> private_context(context->hPrivate); |
153 | vector<UIMessage> messages; | |
153 | std::vector<UIMessage> messages; | |
154 | 154 | |
155 | 155 | if (!UpdateCompositionString(himc, output, &messages)) { |
156 | 156 | return false; |
183 | 183 | return false; |
184 | 184 | } |
185 | 185 | |
186 | wstring preceding_composition; | |
187 | wstring target_text; | |
188 | wstring following_composition; | |
186 | std::wstring preceding_composition; | |
187 | std::wstring target_text; | |
188 | std::wstring following_composition; | |
189 | 189 | if (!ReconvertString::Decompose( |
190 | 190 | reconvert_string, nullptr, &preceding_composition, |
191 | 191 | &target_text, &following_composition, nullptr)) { |
193 | 193 | return false; |
194 | 194 | } |
195 | 195 | |
196 | const wstring total_composition = | |
196 | const std::wstring total_composition = | |
197 | 197 | preceding_composition + target_text + following_composition; |
198 | 198 | |
199 | 199 | // Like other Japanese IMEs (MS-IME, ATOK), Mozc does not support |
200 | 200 | // reconversion when the composition string contains any embedded object |
201 | 201 | // because it is too complicated to restore the original state when the |
202 | 202 | // reconversion is canceled. See b/3406434 for details. |
203 | if (total_composition.find(kObjectReplacementCharacter) != wstring::npos) { | |
203 | if (total_composition.find(kObjectReplacementCharacter) != | |
204 | std::wstring::npos) { | |
204 | 205 | return false; |
205 | 206 | } |
206 | 207 | |
214 | 215 | } |
215 | 216 | |
216 | 217 | bool QueryDocumentFeed(HIMC himc, |
217 | wstring *preceding_text, | |
218 | wstring *following_text) { | |
218 | std::wstring *preceding_text, | |
219 | std::wstring *following_text) { | |
219 | 220 | LRESULT result = ::ImmRequestMessageW(himc, IMR_DOCUMENTFEED, 0); |
220 | 221 | if (result == 0) { |
221 | 222 | // IMR_DOCUMENTFEED is not supported. |
255 | 256 | } |
256 | 257 | context->clear_preceding_text(); |
257 | 258 | context->clear_following_text(); |
258 | wstring preceding_text; | |
259 | wstring following_text; | |
259 | std::wstring preceding_text; | |
260 | std::wstring following_text; | |
260 | 261 | if (!QueryDocumentFeed(himc, &preceding_text, &following_text)) { |
261 | 262 | return; |
262 | 263 | } |
453 | 454 | } |
454 | 455 | |
455 | 456 | void ImeCore::SortIMEMessages( |
456 | const vector<UIMessage> &composition_messages, | |
457 | const vector<UIMessage> &candidate_messages, | |
457 | const std::vector<UIMessage> &composition_messages, | |
458 | const std::vector<UIMessage> &candidate_messages, | |
458 | 459 | bool previous_open_status, |
459 | 460 | DWORD previous_conversion_mode, |
460 | 461 | bool next_open_status, |
461 | 462 | DWORD next_conversion_mode, |
462 | vector<UIMessage> *sorted_messages) { | |
463 | std::vector<UIMessage> *sorted_messages) { | |
463 | 464 | DCHECK(sorted_messages); |
464 | 465 | sorted_messages->clear(); |
465 | 466 | |
480 | 481 | } |
481 | 482 | |
482 | 483 | // Notify IMN_CLOSECANDIDATE. |
483 | vector<UIMessage> other_candidate_messages; | |
484 | std::vector<UIMessage> other_candidate_messages; | |
484 | 485 | for (vector<UIMessage>::const_iterator it = candidate_messages.begin(); |
485 | 486 | it != candidate_messages.end(); ++it) { |
486 | 487 | const bool is_close_candidate = ((it->message() == WM_IME_NOTIFY) && |
494 | 495 | |
495 | 496 | // Notify all composition UI messages except for WM_IME_ENDCOMPOSITION. |
496 | 497 | // Typically WM_IME_STARTCOMPOSITION / WM_IME_COMPOSITION will be handled. |
497 | vector<UIMessage> end_composition_messages; | |
498 | std::vector<UIMessage> end_composition_messages; | |
498 | 499 | for (vector<UIMessage>::const_iterator it = composition_messages.begin(); |
499 | 500 | it != composition_messages.end(); ++it) { |
500 | 501 | if (it->message() == WM_IME_ENDCOMPOSITION) { |
626 | 627 | context->fOpen = next_state.open ? TRUE : FALSE; |
627 | 628 | context->fdwConversion = next_state.logical_conversion_mode; |
628 | 629 | |
629 | vector<UIMessage> composition_messages; | |
630 | std::vector<UIMessage> composition_messages; | |
630 | 631 | if (!UpdateCompositionString(himc, output, &composition_messages)) { |
631 | 632 | return false; |
632 | 633 | } |
633 | 634 | |
634 | vector<UIMessage> candidate_messages; | |
635 | std::vector<UIMessage> candidate_messages; | |
635 | 636 | context->hCandInfo = |
636 | 637 | mozc::win32::CandidateInfoUtil::Update(context->hCandInfo, |
637 | 638 | output, &candidate_messages); |
643 | 644 | // In order to minimize the risk of application compatibility problem, |
644 | 645 | // we might want to send these messages in the the same order to MS-IME. |
645 | 646 | // See b/3488848 for details. |
646 | vector<UIMessage> sorted_messages; | |
647 | std::vector<UIMessage> sorted_messages; | |
647 | 648 | SortIMEMessages(composition_messages, |
648 | 649 | candidate_messages, |
649 | 650 | previous_open, |
211 | 211 | // - [WM_IME_ENDCOMPOSITION] |
212 | 212 | // - [IMN_SETOPENSTATUS for IME-Off] |
213 | 213 | static void SortIMEMessages( |
214 | const vector<UIMessage> &composition_messages, | |
215 | const vector<UIMessage> &candidate_messages, | |
214 | const std::vector<UIMessage> &composition_messages, | |
215 | const std::vector<UIMessage> &candidate_messages, | |
216 | 216 | bool previous_open_status, |
217 | 217 | DWORD previous_conversion_mode, |
218 | 218 | bool next_open_status, |
219 | 219 | DWORD next_conversion_mode, |
220 | vector<UIMessage> *sorted_messages); | |
220 | std::vector<UIMessage> *sorted_messages); | |
221 | 221 | |
222 | 222 | // Internal use only. |
223 | 223 | // This method implements main part of UpdateContext. Note that this method |
127 | 127 | bool start_server_called_; |
128 | 128 | uint32 server_protocol_version_; |
129 | 129 | string response_; |
130 | map<int, int> error_map_; | |
130 | std::map<int, int> error_map_; | |
131 | 131 | }; |
132 | 132 | |
133 | 133 | class MockClient : public client::Client { |
380 | 380 | TEST(ImeCoreTest, TemporalConversionModeMessageOrderTest) { |
381 | 381 | // "Hankaku/Zenkaku" |
382 | 382 | { |
383 | vector<UIMessage> composition_messages; | |
384 | vector<UIMessage> candidate_messages; | |
385 | ||
386 | vector<UIMessage> sorted_messages; | |
383 | std::vector<UIMessage> composition_messages; | |
384 | std::vector<UIMessage> candidate_messages; | |
385 | ||
386 | std::vector<UIMessage> sorted_messages; | |
387 | 387 | ImeCore::SortIMEMessages(composition_messages, |
388 | 388 | candidate_messages, |
389 | 389 | false, |
399 | 399 | |
400 | 400 | // "(Shift +)G" |
401 | 401 | { |
402 | vector<UIMessage> composition_messages; | |
402 | std::vector<UIMessage> composition_messages; | |
403 | 403 | composition_messages.push_back(kMsgStartComposition); |
404 | 404 | composition_messages.push_back(kMsgCompositionUpdate); |
405 | 405 | |
406 | vector<UIMessage> candidate_messages; | |
407 | ||
408 | vector<UIMessage> sorted_messages; | |
406 | std::vector<UIMessage> candidate_messages; | |
407 | ||
408 | std::vector<UIMessage> sorted_messages; | |
409 | 409 | ImeCore::SortIMEMessages(composition_messages, |
410 | 410 | candidate_messages, |
411 | 411 | true, |
424 | 424 | |
425 | 425 | // "Hankaku/Zenkaku" |
426 | 426 | { |
427 | vector<UIMessage> composition_messages; | |
427 | std::vector<UIMessage> composition_messages; | |
428 | 428 | composition_messages.push_back(kMsgCompositionResult); |
429 | 429 | composition_messages.push_back(kMsgEndComposition); |
430 | vector<UIMessage> candidate_messages; | |
431 | ||
432 | vector<UIMessage> sorted_messages; | |
430 | std::vector<UIMessage> candidate_messages; | |
431 | ||
432 | std::vector<UIMessage> sorted_messages; | |
433 | 433 | ImeCore::SortIMEMessages(composition_messages, |
434 | 434 | candidate_messages, |
435 | 435 | true, |
452 | 452 | TEST(ImeCoreTest, CompositionMessageOrderTest) { |
453 | 453 | // "Hankaku/Zenkaku" |
454 | 454 | { |
455 | vector<UIMessage> composition_messages; | |
456 | vector<UIMessage> candidate_messages; | |
457 | ||
458 | vector<UIMessage> sorted_messages; | |
455 | std::vector<UIMessage> composition_messages; | |
456 | std::vector<UIMessage> candidate_messages; | |
457 | ||
458 | std::vector<UIMessage> sorted_messages; | |
459 | 459 | ImeCore::SortIMEMessages(composition_messages, |
460 | 460 | candidate_messages, |
461 | 461 | false, |
471 | 471 | |
472 | 472 | // "(Shift +)G" |
473 | 473 | { |
474 | vector<UIMessage> composition_messages; | |
474 | std::vector<UIMessage> composition_messages; | |
475 | 475 | composition_messages.push_back(kMsgStartComposition); |
476 | 476 | composition_messages.push_back(kMsgCompositionUpdate); |
477 | 477 | |
478 | vector<UIMessage> candidate_messages; | |
479 | ||
480 | vector<UIMessage> sorted_messages; | |
478 | std::vector<UIMessage> candidate_messages; | |
479 | ||
480 | std::vector<UIMessage> sorted_messages; | |
481 | 481 | ImeCore::SortIMEMessages(composition_messages, |
482 | 482 | candidate_messages, |
483 | 483 | true, |
496 | 496 | |
497 | 497 | // "o" |
498 | 498 | { |
499 | vector<UIMessage> composition_messages; | |
499 | std::vector<UIMessage> composition_messages; | |
500 | 500 | composition_messages.push_back(kMsgCompositionUpdate); |
501 | 501 | |
502 | vector<UIMessage> candidate_messages; | |
503 | ||
504 | vector<UIMessage> sorted_messages; | |
502 | std::vector<UIMessage> candidate_messages; | |
503 | ||
504 | std::vector<UIMessage> sorted_messages; | |
505 | 505 | ImeCore::SortIMEMessages(composition_messages, |
506 | 506 | candidate_messages, |
507 | 507 | true, |
518 | 518 | |
519 | 519 | // "Enter" |
520 | 520 | { |
521 | vector<UIMessage> composition_messages; | |
521 | std::vector<UIMessage> composition_messages; | |
522 | 522 | composition_messages.push_back(kMsgCompositionResult); |
523 | 523 | composition_messages.push_back(kMsgEndComposition); |
524 | 524 | |
525 | vector<UIMessage> candidate_messages; | |
526 | ||
527 | vector<UIMessage> sorted_messages; | |
525 | std::vector<UIMessage> candidate_messages; | |
526 | ||
527 | std::vector<UIMessage> sorted_messages; | |
528 | 528 | ImeCore::SortIMEMessages(composition_messages, |
529 | 529 | candidate_messages, |
530 | 530 | true, |
543 | 543 | |
544 | 544 | // "Hankaku/Zenkaku" |
545 | 545 | { |
546 | vector<UIMessage> composition_messages; | |
547 | vector<UIMessage> candidate_messages; | |
548 | ||
549 | vector<UIMessage> sorted_messages; | |
546 | std::vector<UIMessage> composition_messages; | |
547 | std::vector<UIMessage> candidate_messages; | |
548 | ||
549 | std::vector<UIMessage> sorted_messages; | |
550 | 550 | ImeCore::SortIMEMessages(composition_messages, |
551 | 551 | candidate_messages, |
552 | 552 | true, |
566 | 566 | TEST(ImeCoreTest, CandidateMessageOrderTest) { |
567 | 567 | // "Hankaku/Zenkaku" |
568 | 568 | { |
569 | vector<UIMessage> composition_messages; | |
570 | vector<UIMessage> candidate_messages; | |
571 | ||
572 | vector<UIMessage> sorted_messages; | |
569 | std::vector<UIMessage> composition_messages; | |
570 | std::vector<UIMessage> candidate_messages; | |
571 | ||
572 | std::vector<UIMessage> sorted_messages; | |
573 | 573 | ImeCore::SortIMEMessages(composition_messages, |
574 | 574 | candidate_messages, |
575 | 575 | false, |
585 | 585 | |
586 | 586 | // "a" |
587 | 587 | { |
588 | vector<UIMessage> composition_messages; | |
588 | std::vector<UIMessage> composition_messages; | |
589 | 589 | composition_messages.push_back(kMsgStartComposition); |
590 | 590 | composition_messages.push_back(kMsgCompositionUpdate); |
591 | 591 | |
592 | vector<UIMessage> candidate_messages; | |
593 | ||
594 | vector<UIMessage> sorted_messages; | |
592 | std::vector<UIMessage> candidate_messages; | |
593 | ||
594 | std::vector<UIMessage> sorted_messages; | |
595 | 595 | ImeCore::SortIMEMessages(composition_messages, |
596 | 596 | candidate_messages, |
597 | 597 | true, |
609 | 609 | |
610 | 610 | // "Space" |
611 | 611 | { |
612 | vector<UIMessage> composition_messages; | |
612 | std::vector<UIMessage> composition_messages; | |
613 | 613 | composition_messages.push_back(kMsgCompositionUpdate); |
614 | 614 | |
615 | vector<UIMessage> candidate_messages; | |
616 | ||
617 | vector<UIMessage> sorted_messages; | |
615 | std::vector<UIMessage> candidate_messages; | |
616 | ||
617 | std::vector<UIMessage> sorted_messages; | |
618 | 618 | ImeCore::SortIMEMessages(composition_messages, |
619 | 619 | candidate_messages, |
620 | 620 | true, |
631 | 631 | |
632 | 632 | // "Space" |
633 | 633 | { |
634 | vector<UIMessage> composition_messages; | |
634 | std::vector<UIMessage> composition_messages; | |
635 | 635 | composition_messages.push_back(kMsgCompositionUpdate); |
636 | 636 | |
637 | vector<UIMessage> candidate_messages; | |
637 | std::vector<UIMessage> candidate_messages; | |
638 | 638 | candidate_messages.push_back(kMsgOpenCandidate); |
639 | 639 | |
640 | vector<UIMessage> sorted_messages; | |
640 | std::vector<UIMessage> sorted_messages; | |
641 | 641 | ImeCore::SortIMEMessages(composition_messages, |
642 | 642 | candidate_messages, |
643 | 643 | true, |
655 | 655 | |
656 | 656 | // "Space" |
657 | 657 | { |
658 | vector<UIMessage> composition_messages; | |
658 | std::vector<UIMessage> composition_messages; | |
659 | 659 | composition_messages.push_back(kMsgCompositionUpdate); |
660 | 660 | |
661 | vector<UIMessage> candidate_messages; | |
661 | std::vector<UIMessage> candidate_messages; | |
662 | 662 | candidate_messages.push_back(kMsgChangeCandidate); |
663 | 663 | |
664 | vector<UIMessage> sorted_messages; | |
664 | std::vector<UIMessage> sorted_messages; | |
665 | 665 | ImeCore::SortIMEMessages(composition_messages, |
666 | 666 | candidate_messages, |
667 | 667 | true, |
679 | 679 | |
680 | 680 | // "i" |
681 | 681 | { |
682 | vector<UIMessage> composition_messages; | |
682 | std::vector<UIMessage> composition_messages; | |
683 | 683 | composition_messages.push_back(kMsgCompositionResultAndUpdate); |
684 | 684 | |
685 | vector<UIMessage> candidate_messages; | |
685 | std::vector<UIMessage> candidate_messages; | |
686 | 686 | candidate_messages.push_back(kMsgCloseCandidate); |
687 | 687 | |
688 | vector<UIMessage> sorted_messages; | |
688 | std::vector<UIMessage> sorted_messages; | |
689 | 689 | ImeCore::SortIMEMessages(composition_messages, |
690 | 690 | candidate_messages, |
691 | 691 | true, |
122 | 122 | const size_t kMaxCharsForRegisterWord = 64; |
123 | 123 | |
124 | 124 | // If given string is too long, returns an empty string instead. |
125 | wstring GetStringIfWithinLimit(const wchar_t *src, size_t size_limit) { | |
125 | std::wstring GetStringIfWithinLimit(const wchar_t *src, size_t size_limit) { | |
126 | 126 | if (src == nullptr) { |
127 | return wstring(); | |
127 | return std::wstring(); | |
128 | 128 | } |
129 | 129 | for (size_t i = 0; i < size_limit; ++i) { |
130 | 130 | if (src[i] == L'\0') { |
131 | return wstring(src, i); | |
132 | } | |
133 | } | |
134 | return wstring(); | |
131 | return std::wstring(src, i); | |
132 | } | |
133 | } | |
134 | return std::wstring(); | |
135 | 135 | } |
136 | 136 | |
137 | 137 | void SetEnveronmentVariablesForWordRegisterDialog( |
138 | const wstring &word_value, const wstring &word_reading) { | |
139 | wstring word_value_env_name; | |
140 | wstring word_reading_env_name; | |
138 | const std::wstring &word_value, const std::wstring &word_reading) { | |
139 | std::wstring word_value_env_name; | |
140 | std::wstring word_reading_env_name; | |
141 | 141 | mozc::Util::UTF8ToWide( |
142 | 142 | mozc::kWordRegisterEnvironmentName, &word_value_env_name); |
143 | 143 | mozc::Util::UTF8ToWide( |
410 | 410 | // According to the document, the buffer is guaranteed to be greater |
411 | 411 | // than or equal to 64 characters in Windows NT. |
412 | 412 | // http://msdn.microsoft.com/en-us/library/dd318166.aspx |
413 | wstring name; | |
413 | std::wstring name; | |
414 | 414 | mozc::Util::UTF8ToWide(mozc::kProductNameInEnglish, &name); |
415 | 415 | wchar_t *dest = static_cast<wchar_t *>(data); |
416 | 416 | const HRESULT result = ::StringCchCopyN( |
1046 | 1046 | // Generate NotifyUpdateUI message if not exists. |
1047 | 1047 | { |
1048 | 1048 | bool has_ui_message = false; |
1049 | const vector<TRANSMSG> &messages = message_queue.messages(); | |
1049 | const std::vector<TRANSMSG> &messages = message_queue.messages(); | |
1050 | 1050 | for (size_t i = 0; i < messages.size(); ++i) { |
1051 | 1051 | const TRANSMSG &msg = messages[i]; |
1052 | 1052 | if (msg.message == WM_IME_NOTIFY && |
1093 | 1093 | |
1094 | 1094 | // Retrieves word registration data. |
1095 | 1095 | const REGISTERWORD *reg_word = static_cast<REGISTERWORD *>(data); |
1096 | const wstring word = GetStringIfWithinLimit(reg_word->lpWord, | |
1096 | const std::wstring word = GetStringIfWithinLimit(reg_word->lpWord, | |
1097 | 1097 | kMaxCharsForRegisterWord); |
1098 | const wstring reading = GetStringIfWithinLimit(reg_word->lpReading, | |
1098 | const std::wstring reading = GetStringIfWithinLimit(reg_word->lpReading, | |
1099 | 1099 | kMaxCharsForRegisterWord); |
1100 | 1100 | |
1101 | 1101 | SetEnveronmentVariablesForWordRegisterDialog(word, reading); |
85 | 85 | size_t size() const; |
86 | 86 | ImeLangBarMenuData* data(size_t i); |
87 | 87 | private: |
88 | vector<ImeLangBarMenuData> data_; | |
88 | std::vector<ImeLangBarMenuData> data_; | |
89 | 89 | }; |
90 | 90 | |
91 | 91 | MIDL_INTERFACE(IIDSTR_IMozcLangBarMenu) |
160 | 160 | return true; |
161 | 161 | } |
162 | 162 | |
163 | const vector<TRANSMSG> &MessageQueue::messages() const { | |
163 | const std::vector<TRANSMSG> &MessageQueue::messages() const { | |
164 | 164 | return messages_; |
165 | 165 | } |
166 | 166 |
58 | 58 | // Send the messages to context if not attached to a message list. |
59 | 59 | bool Send(); |
60 | 60 | |
61 | const vector<TRANSMSG> &messages() const; | |
61 | const std::vector<TRANSMSG> &messages() const; | |
62 | 62 | |
63 | 63 | private: |
64 | 64 | HIMC himc_; |
65 | 65 | LPTRANSMSGLIST transmsg_; |
66 | vector<TRANSMSG> messages_; | |
66 | std::vector<TRANSMSG> messages_; | |
67 | 67 | int transmsg_count_; |
68 | 68 | |
69 | 69 | DISALLOW_COPY_AND_ASSIGN(MessageQueue); |
201 | 201 | const bool show_suggest_window = |
202 | 202 | ui_visibility_tracker.IsSuggestWindowVisible(); |
203 | 203 | |
204 | vector<wstring> candidate_list; | |
204 | std::vector<wstring> candidate_list; | |
205 | 205 | DWORD focused_index = 0; |
206 | 206 | if (!context.IsEmpty() && context.GetOpenStatus()) { |
207 | 207 | // Copy the last output. |
52 | 52 | |
53 | 53 | class CandidateStringImpl : public ITfCandidateString { |
54 | 54 | public: |
55 | CandidateStringImpl(ULONG index, const wstring &value) | |
55 | CandidateStringImpl(ULONG index, const std::wstring &value) | |
56 | 56 | : index_(index), |
57 | 57 | value_(value) { |
58 | 58 | } |
111 | 111 | |
112 | 112 | TipRefCount ref_count_; |
113 | 113 | const ULONG index_; |
114 | const wstring value_; | |
114 | const std::wstring value_; | |
115 | 115 | |
116 | 116 | DISALLOW_COPY_AND_ASSIGN(CandidateStringImpl); |
117 | 117 | }; |
118 | 118 | |
119 | 119 | class EnumTfCandidatesImpl : public IEnumTfCandidates { |
120 | 120 | public: |
121 | explicit EnumTfCandidatesImpl(const vector<wstring> &candidates) | |
121 | explicit EnumTfCandidatesImpl(const std::vector<wstring> &candidates) | |
122 | 122 | : candidates_(candidates), |
123 | 123 | current_(0) { |
124 | 124 | } |
209 | 209 | |
210 | 210 | TipRefCount ref_count_; |
211 | 211 | |
212 | vector<wstring> candidates_; | |
212 | std::vector<wstring> candidates_; | |
213 | 213 | size_t current_; |
214 | 214 | |
215 | 215 | DISALLOW_COPY_AND_ASSIGN(EnumTfCandidatesImpl); |
217 | 217 | |
218 | 218 | class CandidateListImpl : public ITfCandidateList { |
219 | 219 | public: |
220 | CandidateListImpl(const vector<wstring> &candidates, | |
220 | CandidateListImpl(const std::vector<wstring> &candidates, | |
221 | 221 | TipCandidateListCallback *callback) |
222 | 222 | : candidates_(candidates), |
223 | 223 | callback_(callback) { |
305 | 305 | } |
306 | 306 | |
307 | 307 | TipRefCount ref_count_; |
308 | vector<wstring> candidates_; | |
308 | std::vector<wstring> candidates_; | |
309 | 309 | unique_ptr<TipCandidateListCallback> callback_; |
310 | 310 | |
311 | 311 | DISALLOW_COPY_AND_ASSIGN(CandidateListImpl); |
317 | 317 | } |
318 | 318 | |
319 | 319 | // static |
320 | ITfCandidateList *TipCandidateList::New(const vector<wstring> &candidates, | |
320 | ITfCandidateList *TipCandidateList::New(const std::vector<wstring> &candidates, | |
321 | 321 | TipCandidateListCallback *callback) { |
322 | 322 | return new CandidateListImpl(candidates, callback); |
323 | 323 | } |
49 | 49 | class TipCandidateListCallback { |
50 | 50 | public: |
51 | 51 | virtual ~TipCandidateListCallback(); |
52 | virtual void OnFinalize(size_t index, const wstring &candidate) = 0; | |
52 | virtual void OnFinalize(size_t index, const std::wstring &candidate) = 0; | |
53 | 53 | }; |
54 | 54 | |
55 | 55 | class TipCandidateList { |
59 | 59 | // is called with CAND_FINALIZED. TipCandidateList will take the |
60 | 60 | // ownership of |callback|. |callback| can be nullptr. |
61 | 61 | // Caller must maintain the reference count of the returned object. |
62 | static ITfCandidateList *New(const vector<wstring> &candidates, | |
62 | static ITfCandidateList *New(const std::vector<wstring> &candidates, | |
63 | 63 | TipCandidateListCallback *callback); |
64 | 64 | static const IID& GetIID(); |
65 | 65 |
72 | 72 | candidate_.clear(); |
73 | 73 | } |
74 | 74 | |
75 | void OnFinalize(size_t index, const wstring &candidate) { | |
75 | void OnFinalize(size_t index, const std::wstring &candidate) { | |
76 | 76 | on_finalize_called_ = true; |
77 | 77 | index_ = index; |
78 | 78 | candidate_ = candidate; |
86 | 86 | return index_; |
87 | 87 | } |
88 | 88 | |
89 | const wstring &candidate() const { | |
89 | const std::wstring &candidate() const { | |
90 | 90 | return candidate_; |
91 | 91 | } |
92 | 92 | |
93 | 93 | private: |
94 | 94 | bool on_finalize_called_; |
95 | 95 | size_t index_; |
96 | wstring candidate_; | |
96 | std::wstring candidate_; | |
97 | 97 | DISALLOW_COPY_AND_ASSIGN(MockCallbackResult); |
98 | 98 | }; |
99 | 99 | |
106 | 106 | |
107 | 107 | private: |
108 | 108 | // TipCandidateListCallback overrides: |
109 | virtual void OnFinalize(size_t index, const wstring &candidate) { | |
109 | virtual void OnFinalize(size_t index, const std::wstring &candidate) { | |
110 | 110 | result_->OnFinalize(index, candidate); |
111 | 111 | } |
112 | 112 | |
114 | 114 | DISALLOW_COPY_AND_ASSIGN(MockCallback); |
115 | 115 | }; |
116 | 116 | |
117 | wstring ToWStr(const CComBSTR &bstr) { | |
118 | return wstring(static_cast<const wchar_t *>(bstr), bstr.Length()); | |
117 | std::wstring ToWStr(const CComBSTR &bstr) { | |
118 | return std::wstring(static_cast<const wchar_t *>(bstr), bstr.Length()); | |
119 | 119 | } |
120 | 120 | |
121 | 121 | AssertionResult ExpectCandidateString(ULONG expected_index, |
122 | const wstring &expected_text, | |
122 | const std::wstring &expected_text, | |
123 | 123 | CComPtr<ITfCandidateString> candiate) { |
124 | 124 | if (candiate == nullptr) { |
125 | 125 | return AssertionFailure() << "|actual| should be non-null"; |
144 | 144 | return AssertionFailure() << "ITfCandidateString::GetString failed." |
145 | 145 | << " hr = " << hr; |
146 | 146 | } |
147 | const wstring wstr(ToWStr(str)); | |
147 | const std::wstring wstr(ToWStr(str)); | |
148 | 148 | if (expected_text != wstr) { |
149 | 149 | return AssertionFailure() << "expected: " << expected_text |
150 | 150 | << ", actual: " << wstr; |
159 | 159 | TEST(TipCandidateListTest, EmptyCandiate) { |
160 | 160 | MockCallbackResult result; |
161 | 161 | |
162 | vector<wstring> empty; | |
162 | std::vector<wstring> empty; | |
163 | 163 | CComPtr<ITfCandidateList> candidate_list( |
164 | 164 | TipCandidateList::New(empty, new MockCallback(&result))); |
165 | 165 | ASSERT_NE(nullptr, candidate_list); |
193 | 193 | TEST(TipCandidateListTest, NonEmptyCandiates) { |
194 | 194 | MockCallbackResult result; |
195 | 195 | |
196 | vector<wstring> source; | |
196 | std::vector<wstring> source; | |
197 | 197 | for (wchar_t c = L'A'; c < L'Z'; ++c) { |
198 | source.push_back(wstring(c, 1)); | |
198 | source.push_back(std::wstring(c, 1)); | |
199 | 199 | } |
200 | 200 | CComPtr<ITfCandidateList> candidate_list( |
201 | 201 | TipCandidateList::New(source, new MockCallback(&result))); |
86 | 86 | |
87 | 87 | TipDisplayAttribute::TipDisplayAttribute(const GUID &guid, |
88 | 88 | const TF_DISPLAYATTRIBUTE &attribute, |
89 | const wstring &description) | |
89 | const std::wstring &description) | |
90 | 90 | : guid_(guid), |
91 | 91 | description_(description) { |
92 | 92 | ::CopyMemory(&original_attribute_, &attribute, sizeof(original_attribute_)); |
64 | 64 | protected: |
65 | 65 | TipDisplayAttribute(const GUID &guid, |
66 | 66 | const TF_DISPLAYATTRIBUTE &attribute, |
67 | const wstring &description); | |
67 | const std::wstring &description); | |
68 | 68 | |
69 | 69 | private: |
70 | 70 | TipRefCount ref_count_; |
71 | 71 | GUID guid_; |
72 | 72 | TF_DISPLAYATTRIBUTE original_attribute_; |
73 | wstring description_; | |
73 | std::wstring description_; | |
74 | 74 | TF_DISPLAYATTRIBUTE attribute_; |
75 | 75 | |
76 | 76 | DISALLOW_COPY_AND_ASSIGN(TipDisplayAttribute); |
48 | 48 | public: |
49 | 49 | TestableTipDisplayAttribute(const GUID &guid, |
50 | 50 | const TF_DISPLAYATTRIBUTE &attribute, |
51 | const wstring &description) | |
51 | const std::wstring &description) | |
52 | 52 | : TipDisplayAttribute(guid, attribute, description) { |
53 | 53 | } |
54 | 54 | }; |
203 | 203 | // This function is called back by the TSF thread manager when an edit |
204 | 204 | // request is granted. |
205 | 205 | virtual STDMETHODIMP DoEditSession(TfEditCookie read_cookie) { |
206 | vector<InputScope> input_scopes; | |
206 | std::vector<InputScope> input_scopes; | |
207 | 207 | CComPtr<ITfRange> selection_range; |
208 | 208 | TfActiveSelEnd active_sel_end = TF_AE_NONE; |
209 | 209 | if (SUCCEEDED(TipRangeUtil::GetDefaultSelection( |
726 | 726 | return S_OK; |
727 | 727 | } |
728 | 728 | |
729 | const wstring &text() const { | |
729 | const std::wstring &text() const { | |
730 | 730 | return text_; |
731 | 731 | } |
732 | 732 | |
734 | 734 | TipRefCount ref_count_; |
735 | 735 | CComPtr<TipTextService> text_service_; |
736 | 736 | CComPtr<ITfRange> range_; |
737 | wstring text_; | |
737 | std::wstring text_; | |
738 | 738 | |
739 | 739 | DISALLOW_COPY_AND_ASSIGN(SyncGetTextEditSessionImpl); |
740 | 740 | }; |
745 | 745 | class AsyncSetTextEditSessionImpl : public ITfEditSession { |
746 | 746 | public: |
747 | 747 | AsyncSetTextEditSessionImpl(TipTextService *text_service, |
748 | const wstring &text, | |
748 | const std::wstring &text, | |
749 | 749 | ITfRange *range) |
750 | 750 | : text_service_(text_service), |
751 | 751 | text_(text), |
781 | 781 | private: |
782 | 782 | TipRefCount ref_count_; |
783 | 783 | CComPtr<TipTextService> text_service_; |
784 | const wstring text_; | |
784 | const std::wstring text_; | |
785 | 785 | CComPtr<ITfRange> range_; |
786 | 786 | |
787 | 787 | DISALLOW_COPY_AND_ASSIGN(AsyncSetTextEditSessionImpl); |
1020 | 1020 | // Stop reconversion when any embedded object is found because we cannot |
1021 | 1021 | // easily restore it. See b/3406434 |
1022 | 1022 | if (info.selected_text.find(static_cast<wchar_t>(TS_CHAR_EMBEDDED)) != |
1023 | wstring::npos) { | |
1023 | std::wstring::npos) { | |
1024 | 1024 | // embedded object is found. |
1025 | 1025 | return false; |
1026 | 1026 | } |
1093 | 1093 | |
1094 | 1094 | bool TipEditSession::GetTextSync(TipTextService *text_service, |
1095 | 1095 | ITfRange *range, |
1096 | wstring *text) { | |
1096 | std::wstring *text) { | |
1097 | 1097 | CComPtr<ITfContext> context; |
1098 | 1098 | if (FAILED(range->GetContext(&context))) { |
1099 | 1099 | return false; |
1116 | 1116 | |
1117 | 1117 | // static |
1118 | 1118 | bool TipEditSession::SetTextAsync(TipTextService *text_service, |
1119 | const wstring &text, | |
1119 | const std::wstring &text, | |
1120 | 1120 | ITfRange *range) { |
1121 | 1121 | CComPtr<ITfContext> context; |
1122 | 1122 | if (FAILED(range->GetContext(&context))) { |
108 | 108 | // Begins a sync edit session to retrieve the text from |range|. |
109 | 109 | static bool GetTextSync(TipTextService *text_service, |
110 | 110 | ITfRange *range, |
111 | wstring *text); | |
111 | std::wstring *text); | |
112 | 112 | |
113 | 113 | // Begins an async edit session to set |text| to |range|. |
114 | 114 | static bool SetTextAsync(TipTextService *text_service, |
115 | const wstring &text, | |
115 | const std::wstring &text, | |
116 | 116 | ITfRange *range); |
117 | 117 | |
118 | 118 | private: |
86 | 86 | return result; |
87 | 87 | } |
88 | 88 | |
89 | const wstring &canonical_reading_string = | |
89 | const std::wstring &canonical_reading_string = | |
90 | 90 | StringUtil::KeyToReading(reading_string_utf8); |
91 | 91 | CComVariant reading(CComBSTR(canonical_reading_string.c_str())); |
92 | 92 | result = reading_property->SetValue(write_cookie, range, &reading); |
177 | 177 | return nullptr; |
178 | 178 | } |
179 | 179 | |
180 | wstring result_text; | |
180 | std::wstring result_text; | |
181 | 181 | Util::UTF8ToWide(output.result().value(), &result_text); |
182 | 182 | |
183 | wstring composition_text; | |
183 | std::wstring composition_text; | |
184 | 184 | TipRangeUtil::GetText(composition_range, write_cookie, &composition_text); |
185 | 185 | |
186 | 186 | // Make sure that |composition_text| begins with |result_text| so that |
249 | 249 | return result; |
250 | 250 | } |
251 | 251 | if (is_empty != TRUE) { |
252 | wstring str; | |
252 | std::wstring str; | |
253 | 253 | TipRangeUtil::GetText(composition_range, write_cookie, &str); |
254 | 254 | result = composition_range->SetText(write_cookie, 0, L"", 0); |
255 | 255 | if (FAILED(result)) { |
297 | 297 | } |
298 | 298 | |
299 | 299 | const Preedit &preedit = output.preedit(); |
300 | const wstring &preedit_text = StringUtil::ComposePreeditText(preedit); | |
300 | const std::wstring &preedit_text = StringUtil::ComposePreeditText(preedit); | |
301 | 301 | result = composition_range->SetText( |
302 | 302 | write_cookie, 0, preedit_text.c_str(), preedit_text.size()); |
303 | 303 | if (FAILED(result)) { |
359 | 359 | var.lVal = attribute; |
360 | 360 | result = display_attribute->SetValue(write_cookie, segment_range, &var); |
361 | 361 | if (segment.has_key()) { |
362 | const wstring &reading_string = StringUtil::KeyToReading(segment.key()); | |
362 | const std::wstring &reading_string = | |
363 | StringUtil::KeyToReading(segment.key()); | |
363 | 364 | CComVariant reading(CComBSTR(reading_string.c_str())); |
364 | 365 | result = reading_property->SetValue( |
365 | 366 | write_cookie, segment_range, &reading); |
520 | 521 | if (FAILED(result)) { |
521 | 522 | return result; |
522 | 523 | } |
523 | vector<InputScope> input_scopes; | |
524 | std::vector<InputScope> input_scopes; | |
524 | 525 | result = TipRangeUtil::GetInputScopes( |
525 | 526 | selection_range, write_cookie, &input_scopes); |
526 | 527 | TipInputModeManager *input_mode_manager = |
61 | 61 | |
62 | 62 | TipInputModeManagerImpl::StatePair TipInputModeManagerImpl::GetOverriddenState( |
63 | 63 | const StatePair &base_state, |
64 | const vector<InputScope> &input_scopes) { | |
64 | const std::vector<InputScope> &input_scopes) { | |
65 | 65 | if (input_scopes.empty()) { |
66 | 66 | return base_state; |
67 | 67 | } |
68 | vector<ConversionMode> states; | |
68 | std::vector<ConversionMode> states; | |
69 | 69 | for (size_t i = 0; i < input_scopes.size(); ++i) { |
70 | 70 | const InputScope input_scope = input_scopes[i]; |
71 | 71 | switch (input_scope) { |
132 | 132 | StatePair mozc_state; |
133 | 133 | StatePair tsf_state; |
134 | 134 | IndicatorVisibilityTracker indicator_visibility_tracker; |
135 | vector<InputScope> input_scope; | |
135 | std::vector<InputScope> input_scope; | |
136 | 136 | }; |
137 | 137 | |
138 | 138 | // For Mode Indicator. |
233 | 233 | TipInputModeManager::Action TipInputModeManager::OnSetFocus( |
234 | 234 | bool system_open_close_mode, |
235 | 235 | DWORD system_conversion_mode, |
236 | const vector<InputScope> &input_scopes) { | |
236 | const std::vector<InputScope> &input_scopes) { | |
237 | 237 | const StatePair prev_effective = state_->mozc_state; |
238 | 238 | |
239 | 239 | state_->indicator_visibility_tracker.OnMoveFocusedWindow(); |
240 | 240 | |
241 | vector<InputScope> new_input_scopes = input_scopes; | |
241 | std::vector<InputScope> new_input_scopes = input_scopes; | |
242 | 242 | Dedup(&new_input_scopes); |
243 | 243 | |
244 | 244 | state_->tsf_state.open_close = system_open_close_mode; |
307 | 307 | |
308 | 308 | TipInputModeManager::Action |
309 | 309 | TipInputModeManager::OnChangeInputScope( |
310 | const vector<InputScope> &input_scopes) { | |
310 | const std::vector<InputScope> &input_scopes) { | |
311 | 311 | const StatePair prev_effective = state_->mozc_state; |
312 | 312 | |
313 | vector<InputScope> new_input_scopes = input_scopes; | |
313 | std::vector<InputScope> new_input_scopes = input_scopes; | |
314 | 314 | Dedup(&new_input_scopes); |
315 | 315 | if (new_input_scopes == state_->input_scope) { |
316 | 316 | // The same input scope is specified. Use the previous mode. |
63 | 63 | }; |
64 | 64 | |
65 | 65 | protected: |
66 | static StatePair GetOverriddenState(const StatePair &base_state, | |
67 | const vector<InputScope> &input_scopes); | |
66 | static StatePair GetOverriddenState( | |
67 | const StatePair &base_state, | |
68 | const std::vector<InputScope> &input_scopes); | |
68 | 69 | }; |
69 | 70 | |
70 | 71 | // In TSF, IME open/close mode and conversion mode are managed per thread not |
114 | 115 | DWORD mozc_visible_mode); |
115 | 116 | Action OnSetFocus(bool system_open_close_mode, |
116 | 117 | DWORD system_conversion_mode, |
117 | const vector<InputScope> &input_scopes); | |
118 | const std::vector<InputScope> &input_scopes); | |
118 | 119 | Action OnChangeOpenClose(bool new_open_close_mode); |
119 | 120 | Action OnChangeConversionMode(DWORD new_conversion_mode); |
120 | Action OnChangeInputScope(const vector<InputScope> &input_scopes); | |
121 | Action OnChangeInputScope(const std::vector<InputScope> &input_scopes); | |
121 | 122 | |
122 | 123 | // Returns IME open/close state that is visible from Mozc session. |
123 | 124 | bool GetEffectiveOpenClose() const; |
61 | 61 | TEST(TipInputModeManagerImplTest, GetOverriddenState) { |
62 | 62 | // Check if input scopes for turning off IME temporarily. |
63 | 63 | { |
64 | vector<InputScope> input_scope_off; | |
64 | std::vector<InputScope> input_scope_off; | |
65 | 65 | input_scope_off.push_back(IS_NUMBER); |
66 | 66 | input_scope_off.push_back(IS_EMAIL_SMTPEMAILADDRESS); |
67 | 67 | { |
84 | 84 | |
85 | 85 | // Check if input scopes for turning on IME temporarily. |
86 | 86 | { |
87 | vector<InputScope> input_scope_full_hiragana; | |
87 | std::vector<InputScope> input_scope_full_hiragana; | |
88 | 88 | input_scope_full_hiragana.push_back(IS_HIRAGANA); |
89 | 89 | { |
90 | 90 | const StatePair state = |
116 | 116 | // If there are multiple input scopes and they are not aggregatable, use the |
117 | 117 | // original state as is. |
118 | 118 | { |
119 | vector<InputScope> input_scope_invalid; | |
119 | std::vector<InputScope> input_scope_invalid; | |
120 | 120 | input_scope_invalid.push_back(IS_HIRAGANA); |
121 | 121 | input_scope_invalid.push_back(IS_KATAKANA_FULLWIDTH); |
122 | 122 | { |
155 | 155 | input_mode_manager.OnInitialize(false, kNativeHiragana); |
156 | 156 | |
157 | 157 | // SetFocus (Off + Hiragana) |
158 | vector<InputScope> input_scope_empty; | |
158 | std::vector<InputScope> input_scope_empty; | |
159 | 159 | auto action = input_mode_manager.OnSetFocus( |
160 | 160 | false, kNativeHiragana, input_scope_empty); |
161 | 161 | EXPECT_EQ(TipInputModeManager::kDoNothing, action); |
192 | 192 | input_mode_manager.OnInitialize(false, kNativeHiragana); |
193 | 193 | |
194 | 194 | // SetFocus (Off + Hiragana) |
195 | vector<InputScope> input_scope_empty; | |
195 | std::vector<InputScope> input_scope_empty; | |
196 | 196 | auto action = input_mode_manager.OnSetFocus( |
197 | 197 | false, kNativeHiragana, input_scope_empty); |
198 | 198 | EXPECT_EQ(TipInputModeManager::kDoNothing, action); |
227 | 227 | input_mode_manager.OnInitialize(false, kNativeHiragana); |
228 | 228 | |
229 | 229 | // SetFocus (Off + Hiragana) |
230 | vector<InputScope> input_scope_empty; | |
230 | std::vector<InputScope> input_scope_empty; | |
231 | 231 | auto action = input_mode_manager.OnSetFocus( |
232 | 232 | false, kNativeHiragana, input_scope_empty); |
233 | 233 | EXPECT_EQ(TipInputModeManager::kDoNothing, action); |
236 | 236 | EXPECT_EQ(TipInputModeManager::kHiragana, |
237 | 237 | input_mode_manager.GetEffectiveConversionMode()); |
238 | 238 | |
239 | vector<InputScope> input_scope_full_katakana; | |
239 | std::vector<InputScope> input_scope_full_katakana; | |
240 | 240 | input_scope_full_katakana.push_back(IS_KATAKANA_FULLWIDTH); |
241 | 241 | |
242 | 242 | // InputScope: IS_KATAKANA_FULLWIDTH |
253 | 253 | |
254 | 254 | // InputScope: IS_EMAIL_SMTPEMAILADDRESS |
255 | 255 | // This should change the mode and make indicator visible. |
256 | vector<InputScope> input_scope_email; | |
256 | std::vector<InputScope> input_scope_email; | |
257 | 257 | input_scope_email.push_back(IS_EMAIL_SMTPEMAILADDRESS); |
258 | 258 | action = input_mode_manager.OnChangeInputScope(input_scope_email); |
259 | 259 | EXPECT_EQ(TipInputModeManager::kUpdateUI, action); |
269 | 269 | |
270 | 270 | // InputScope: IS_NUMBER |
271 | 271 | // This should not change the mode and keep indicator invisible. |
272 | vector<InputScope> input_scope_number; | |
272 | std::vector<InputScope> input_scope_number; | |
273 | 273 | input_scope_number.push_back(IS_NUMBER); |
274 | 274 | action = input_mode_manager.OnChangeInputScope(input_scope_number); |
275 | 275 | EXPECT_EQ(TipInputModeManager::kDoNothing, action); |
551 | 551 | return E_NOINTERFACE; |
552 | 552 | } |
553 | 553 | |
554 | void TipLangBarButton::SetDescription(const wstring &description) { | |
554 | void TipLangBarButton::SetDescription(const std::wstring &description) { | |
555 | 555 | ::StringCchCopy(item_info_.szDescription, |
556 | 556 | arraysize(item_info_.szDescription), |
557 | 557 | description.c_str()); |
95 | 95 | TipLangBarMenuData* data(size_t i); |
96 | 96 | |
97 | 97 | private: |
98 | vector<TipLangBarMenuData> data_; | |
98 | std::vector<TipLangBarMenuData> data_; | |
99 | 99 | }; |
100 | 100 | |
101 | 101 | MIDL_INTERFACE(IIDSTR_IMozcLangBarItem) |
171 | 171 | |
172 | 172 | // Update the item description. The caller is also responsible for calling |
173 | 173 | // OnUpdate method to notify the change to the system. |
174 | void SetDescription(const wstring &description); | |
174 | void SetDescription(const std::wstring &description); | |
175 | 175 | |
176 | 176 | // Returns the i-th data in the language bar menu. |
177 | 177 | // Returns NULL if i is out of bounds. |
291 | 291 | // Represents the index of the selected menu item. |
292 | 292 | UINT menu_selected_; |
293 | 293 | bool disabled_; |
294 | wstring description_for_enabled_; | |
294 | std::wstring description_for_enabled_; | |
295 | 295 | TipLangBarMenuData menu_data_for_disabled_; |
296 | 296 | }; |
297 | 297 |
126 | 126 | return E_INVALIDARG; |
127 | 127 | } |
128 | 128 | *candidate_list = nullptr; |
129 | wstring query; | |
129 | std::wstring query; | |
130 | 130 | if (!TipEditSession::GetTextSync(text_service_, range, &query)) { |
131 | 131 | return E_FAIL; |
132 | 132 | } |
58 | 58 | |
59 | 59 | private: |
60 | 60 | // The TipQueryProvider interface methods. |
61 | virtual bool Query(const wstring &query, | |
61 | virtual bool Query(const std::wstring &query, | |
62 | 62 | QueryType type, |
63 | vector<wstring> *result) { | |
63 | std::vector<wstring> *result) { | |
64 | 64 | if (type == kReconversion) { |
65 | 65 | return ReconvertQuery(query, result); |
66 | 66 | } |
67 | 67 | return SimpleQuery(query, result); |
68 | 68 | } |
69 | 69 | |
70 | bool SimpleQuery(const wstring &query, | |
71 | vector<wstring> *result) { | |
70 | bool SimpleQuery(const std::wstring &query, | |
71 | std::vector<wstring> *result) { | |
72 | 72 | { |
73 | 73 | KeyEvent key_event; |
74 | 74 | string utf8_query; |
88 | 88 | const auto &candidates = output.all_candidate_words(); |
89 | 89 | for (size_t i = 0; i < candidates.candidates_size(); ++i) { |
90 | 90 | const auto &utf8 = candidates.candidates(i).value(); |
91 | wstring wide; | |
91 | std::wstring wide; | |
92 | 92 | Util::UTF8ToWide(utf8, &wide); |
93 | 93 | result->push_back(wide); |
94 | 94 | } |
102 | 102 | return true; |
103 | 103 | } |
104 | 104 | |
105 | bool ReconvertQuery(const wstring &query, | |
106 | vector<wstring> *result) { | |
105 | bool ReconvertQuery(const std::wstring &query, | |
106 | std::vector<wstring> *result) { | |
107 | 107 | { |
108 | 108 | string utf8_query; |
109 | 109 | Util::WideToUTF8(query, &utf8_query); |
118 | 118 | const auto &candidates = output.all_candidate_words(); |
119 | 119 | for (size_t i = 0; i < candidates.candidates_size(); ++i) { |
120 | 120 | const auto &utf8 = candidates.candidates(i).value(); |
121 | wstring wide; | |
121 | std::wstring wide; | |
122 | 122 | Util::UTF8ToWide(utf8, &wide); |
123 | 123 | result->push_back(wide); |
124 | 124 | } |
51 | 51 | kDefault, |
52 | 52 | kReconversion, |
53 | 53 | }; |
54 | virtual bool Query(const wstring &query, | |
54 | virtual bool Query(const std::wstring &query, | |
55 | 55 | QueryType type, |
56 | vector<wstring> *result) = 0; | |
56 | std::vector<wstring> *result) = 0; | |
57 | 57 | }; |
58 | 58 | |
59 | 59 | } // namespace tsf |
95 | 95 | } |
96 | 96 | |
97 | 97 | HRESULT TipRangeUtil::GetText( |
98 | ITfRange *range, TfEditCookie edit_cookie, wstring *text) { | |
98 | ITfRange *range, TfEditCookie edit_cookie, std::wstring *text) { | |
99 | 99 | if (range == nullptr) { |
100 | 100 | return E_INVALIDARG; |
101 | 101 | } |
154 | 154 | |
155 | 155 | HRESULT TipRangeUtil::GetInputScopes(ITfRange *range, |
156 | 156 | TfEditCookie read_cookie, |
157 | vector<InputScope> *input_scopes) { | |
157 | std::vector<InputScope> *input_scopes) { | |
158 | 158 | if (input_scopes == nullptr) { |
159 | 159 | return E_FAIL; |
160 | 160 | } |
60 | 60 | // Retrieves the text from |range| into |text|. |
61 | 61 | // Returns the general result code. |
62 | 62 | static HRESULT GetText( |
63 | ITfRange *range, TfEditCookie edit_cookie, wstring *text); | |
63 | ITfRange *range, TfEditCookie edit_cookie, std::wstring *text); | |
64 | 64 | |
65 | 65 | // Retrieves the input scopes from |range| into |input_scopes|. |
66 | 66 | // Returns the general result code. |
67 | 67 | static HRESULT GetInputScopes(ITfRange *range, |
68 | 68 | TfEditCookie read_cookie, |
69 | vector<InputScope> *input_scopes); | |
69 | std::vector<InputScope> *input_scopes); | |
70 | 70 | |
71 | 71 | // Checks whether or not |range_test| becomes a subset of |range_cover|. |
72 | 72 | static bool IsRangeCovered(TfEditCookie edit_cookie, |
73 | 73 | |
74 | 74 | private: |
75 | 75 | // TipCandidateListCallback overrides: |
76 | virtual void OnFinalize(size_t index, const wstring &candidate) { | |
76 | virtual void OnFinalize(size_t index, const std::wstring &candidate) { | |
77 | 77 | TipEditSession::SetTextAsync(text_service_, candidate, range_); |
78 | 78 | } |
79 | 79 | |
169 | 169 | } |
170 | 170 | |
171 | 171 | if (info.selected_text.find(static_cast<wchar_t>(TS_CHAR_EMBEDDED)) != |
172 | wstring::npos) { | |
172 | std::wstring::npos) { | |
173 | 173 | // embedded object is found. |
174 | 174 | *convertable = FALSE; |
175 | 175 | *new_range = nullptr; |
195 | 195 | if (!provider) { |
196 | 196 | return E_FAIL; |
197 | 197 | } |
198 | wstring query; | |
198 | std::wstring query; | |
199 | 199 | if (!TipEditSession::GetTextSync(text_service_, range, &query)) { |
200 | 200 | return E_FAIL; |
201 | 201 | } |
277 | 277 | &halt_cond))) { |
278 | 278 | return E_FAIL; |
279 | 279 | } |
280 | wstring total_string; | |
280 | std::wstring total_string; | |
281 | 281 | if (FAILED(TipRangeUtil::GetText( |
282 | 282 | preceeding_range, edit_cookie, &total_string))) { |
283 | 283 | return E_FAIL; |
353 | 353 | return false; |
354 | 354 | } |
355 | 355 | |
356 | wstring preceding_text; | |
357 | wstring preceding_composition; | |
358 | wstring target; | |
359 | wstring following_composition; | |
360 | wstring following_text; | |
356 | std::wstring preceding_text; | |
357 | std::wstring preceding_composition; | |
358 | std::wstring target; | |
359 | std::wstring following_composition; | |
360 | std::wstring following_text; | |
361 | 361 | if (!ReconvertString::Decompose( |
362 | 362 | reconvert_string, &preceding_text, &preceding_composition, &target, |
363 | 363 | &following_composition, &following_text)) { |
513 | 513 | } |
514 | 514 | |
515 | 515 | bool TipSurroundingTextUtil::MeasureCharactersBackward( |
516 | const wstring &text, | |
516 | const std::wstring &text, | |
517 | 517 | size_t characters_in_ucs4, |
518 | 518 | size_t *characters_in_utf16) { |
519 | 519 | if (characters_in_utf16 == nullptr) { |
50 | 50 | struct TipSurroundingTextInfo { |
51 | 51 | TipSurroundingTextInfo(); |
52 | 52 | |
53 | wstring preceding_text; | |
54 | wstring selected_text; | |
55 | wstring following_text; | |
53 | std::wstring preceding_text; | |
54 | std::wstring selected_text; | |
55 | std::wstring following_text; | |
56 | 56 | bool has_preceding_text; |
57 | 57 | bool has_selected_text; |
58 | 58 | bool has_following_text; |
108 | 108 | // Returns true if |text| has more than |characters_in_ucs4| characters. |
109 | 109 | // When succeeds, the last |*characters_in_utf16| characters in |text| |
110 | 110 | // can be measured as |characters_in_ucs4| in the unit of UCS4. |
111 | static bool MeasureCharactersBackward(const wstring &text, | |
111 | static bool MeasureCharactersBackward(const std::wstring &text, | |
112 | 112 | size_t characters_in_ucs4, |
113 | 113 | size_t *characters_in_utf16); |
114 | 114 | }; |
39 | 39 | TEST(TipSurroundingTextUtilTest, MeasureCharactersBackward) { |
40 | 40 | { |
41 | 41 | const char kSource[] = "abcde"; |
42 | wstring source; | |
42 | std::wstring source; | |
43 | 43 | Util::UTF8ToWide(kSource, &source); |
44 | 44 | size_t characters_in_utf16 = 0; |
45 | 45 | EXPECT_TRUE(TipSurroundingTextUtil::MeasureCharactersBackward( |
59 | 59 | } |
60 | 60 | { |
61 | 61 | const char kSource[] = "𠮟咤"; |
62 | wstring source; | |
62 | std::wstring source; | |
63 | 63 | Util::UTF8ToWide(kSource, &source); |
64 | 64 | size_t characters_in_utf16 = 0; |
65 | 65 | EXPECT_TRUE(TipSurroundingTextUtil::MeasureCharactersBackward( |
338 | 338 | if (visible_index >= list.candidates_size()) { |
339 | 339 | return E_FAIL; |
340 | 340 | } |
341 | wstring wide_text; | |
341 | std::wstring wide_text; | |
342 | 342 | Util::UTF8ToWide(list.candidates(visible_index).value(), &wide_text); |
343 | 343 | *text = CComBSTR(wide_text.size(), wide_text.data()).Detach(); |
344 | 344 | return S_OK; |
122 | 122 | void CalcLayout(const Candidates &candidates, |
123 | 123 | const TextRenderer &text_renderer, |
124 | 124 | TableLayout *table_layout, |
125 | vector<wstring> *candidate_strings) { | |
125 | std::vector<wstring> *candidate_strings) { | |
126 | 126 | table_layout->Initialize(candidates.candidate_size(), NUMBER_OF_COLUMNS); |
127 | 127 | |
128 | 128 | table_layout->SetWindowBorder(kWindowBorder); |
142 | 142 | table_layout->EnsureCellSize(COLUMN_GAP1, gap1_size); |
143 | 143 | |
144 | 144 | for (size_t i = 0; i < candidates.candidate_size(); ++i) { |
145 | wstring candidate_string; | |
145 | std::wstring candidate_string; | |
146 | 146 | const Candidate &candidate = candidates.candidate(i); |
147 | 147 | if (candidate.has_value()) { |
148 | 148 | mozc::Util::UTF8ToWide(candidate.value(), &candidate_string); |
150 | 150 | if (candidate.has_annotation()) { |
151 | 151 | const commands::Annotation &annotation = candidate.annotation(); |
152 | 152 | if (annotation.has_prefix()) { |
153 | wstring annotation_prefix; | |
153 | std::wstring annotation_prefix; | |
154 | 154 | mozc::Util::UTF8ToWide(annotation.prefix(), &annotation_prefix); |
155 | 155 | candidate_string = annotation_prefix + candidate_string; |
156 | 156 | } |
157 | 157 | if (annotation.has_suffix()) { |
158 | wstring annotation_suffix; | |
158 | std::wstring annotation_suffix; | |
159 | 159 | mozc::Util::UTF8ToWide(annotation.suffix(), &annotation_suffix); |
160 | 160 | candidate_string += annotation_suffix; |
161 | 161 | } |
179 | 179 | CBitmapHandle RenderImpl(const Candidates &candidates, |
180 | 180 | const TableLayout &table_layout, |
181 | 181 | const TextRenderer &text_renderer, |
182 | const vector<wstring> &candidate_strings) { | |
182 | const std::vector<wstring> &candidate_strings) { | |
183 | 183 | const int width = table_layout.GetTotalSize().width; |
184 | 184 | const int height = table_layout.GetTotalSize().height; |
185 | 185 | |
217 | 217 | const TextRenderer::FONT_TYPE font_type = |
218 | 218 | TextRenderer::FONTSET_CANDIDATE; |
219 | 219 | |
220 | vector<TextRenderingInfo> display_list; | |
220 | std::vector<TextRenderingInfo> display_list; | |
221 | 221 | for (size_t i = 0; i < candidate_strings.size(); ++i) { |
222 | const wstring &candidate_string = candidate_strings[i]; | |
222 | const std::wstring &candidate_string = candidate_strings[i]; | |
223 | 223 | const Rect &text_rect = |
224 | 224 | table_layout.GetCellRect(i, column_type); |
225 | 225 | display_list.push_back(TextRenderingInfo(candidate_string, text_rect)); |
273 | 273 | const renderer::win32::TextRenderer *text_renderer, |
274 | 274 | renderer::TableLayout *table_layout, |
275 | 275 | SIZE *size, int *left_align_offset) { |
276 | vector<wstring> candidate_strings; | |
276 | std::vector<wstring> candidate_strings; | |
277 | 277 | CalcLayout(candidates, *text_renderer, table_layout, &candidate_strings); |
278 | 278 | |
279 | 279 | const Size &total_size = table_layout->GetTotalSize(); |