1 // ScintillaEditView.cpp: 实现文件
2 //
3
4 #include "stdafx.h"
5 #include "ScintillaEditView.h"
6 #include "Common.h"
7 #include "MusicPlayer2.h"
8
9
10 // CScintillaEditView
11
IMPLEMENT_DYNCREATE(CScintillaEditView,CView)12 IMPLEMENT_DYNCREATE(CScintillaEditView, CView)
13
14 CScintillaEditView::CScintillaEditView()
15 {
16
17 }
18
~CScintillaEditView()19 CScintillaEditView::~CScintillaEditView()
20 {
21 }
22
BEGIN_MESSAGE_MAP(CScintillaEditView,CView)23 BEGIN_MESSAGE_MAP(CScintillaEditView, CView)
24 ON_WM_PAINT()
25 ON_WM_RBUTTONUP()
26 ON_MESSAGE(WM_TABLET_QUERYSYSTEMGESTURESTATUS, &CScintillaEditView::OnTabletQuerysystemgesturestatus)
27 END_MESSAGE_MAP()
28
29
30 // CScintillaEditView 绘图
31
32 void CScintillaEditView::OnDraw(CDC* pDC)
33 {
34 CDocument* pDoc = GetDocument();
35 // TODO: 在此添加绘制代码
36 }
37
38
39 // CScintillaEditView 诊断
40
41 #ifdef _DEBUG
AssertValid() const42 void CScintillaEditView::AssertValid() const
43 {
44 CView::AssertValid();
45 }
46
47 #ifndef _WIN32_WCE
Dump(CDumpContext & dc) const48 void CScintillaEditView::Dump(CDumpContext& dc) const
49 {
50 CView::Dump(dc);
51 }
52
53 #endif
54 #endif //_DEBUG
55
56
SetTextW(const wstring & text)57 void CScintillaEditView::SetTextW(const wstring& text)
58 {
59 m_change_notification_enable = false; //确保正在执行SetText时不响应文本改变消息
60 bool is_read_onle = IsReadOnly();
61 //执行设置文件前,如果编辑器的只读的,则取消只读
62 if (is_read_onle)
63 SetReadOnly(false);
64 int size = WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.size(), NULL, 0, NULL, NULL);
65 if (size > 0)
66 {
67 char* str = new char[size + 1];
68 WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.size(), str, size, NULL, NULL);
69 SendMessage(SCI_SETTEXT, size, (LPARAM)str);
70 delete[] str;
71 }
72 else
73 {
74 SendMessage(SCI_SETTEXT, 0, (LPARAM)"");
75 }
76 //恢复只读状态
77 if (is_read_onle)
78 SetReadOnly(true);
79 m_change_notification_enable = true;
80 }
81
GetTextW(wstring & text)82 void CScintillaEditView::GetTextW(wstring& text)
83 {
84 text.clear();
85 int size{};
86 const wchar_t* str_unicode = GetTextW(size);
87 if (size == 0)
88 return;
89 text.assign(str_unicode, size);
90 delete[] str_unicode;
91 }
92
GetTextW(int & size)93 const wchar_t* CScintillaEditView::GetTextW(int& size)
94 {
95 auto length = SendMessage(SCI_GETLENGTH);
96 char* buf = new char[length + 1];
97 SendMessage(SCI_GETTEXT, length + 1, reinterpret_cast<LPARAM>(buf));
98
99 size = MultiByteToWideChar(CP_UTF8, 0, buf, length, NULL, 0);
100 if (size <= 0) return nullptr;
101 wchar_t* str_unicode = new wchar_t[size + 1];
102 MultiByteToWideChar(CP_UTF8, 0, buf, length, str_unicode, size);
103 //text.assign(str_unicode, size);
104 //delete[] str_unicode;
105 delete[] buf;
106 return str_unicode;
107 }
108
GetText(int & size)109 const char * CScintillaEditView::GetText(int & size)
110 {
111 size = SendMessage(SCI_GETLENGTH);
112 char* buf = new char[size + 1];
113 SendMessage(SCI_GETTEXT, size + 1, reinterpret_cast<LPARAM>(buf));
114 return buf;
115 }
116
GetText(int start,int end)117 std::string CScintillaEditView::GetText(int start, int end)
118 {
119 if (start == end)
120 return std::string();
121 Sci_TextRange text_range;
122 //获取选中范围
123 text_range.chrg.cpMin = start;
124 text_range.chrg.cpMax = end;
125 if (text_range.chrg.cpMax < text_range.chrg.cpMin)
126 std::swap(text_range.chrg.cpMin, text_range.chrg.cpMax);
127 //选中范围长度
128 int length = text_range.chrg.cpMax - text_range.chrg.cpMin;
129 //初始化接收字符串缓冲区
130 char* buff = new char[length + 1];
131 text_range.lpstrText = buff;
132 //获取选中部分文本
133 SendMessage(SCI_GETTEXTRANGE, 0, (LPARAM)&text_range);
134 std::string str_selected(buff, length);
135 delete[] buff;
136 return str_selected;
137 }
138
SetFontFace(const wchar_t * font_face)139 void CScintillaEditView::SetFontFace(const wchar_t* font_face)
140 {
141 string str_font_face = CCommon::UnicodeToStr(font_face, CodeType::UTF8_NO_BOM);
142 SendMessage(SCI_STYLESETFONT, STYLE_DEFAULT, (sptr_t)str_font_face.c_str());
143 }
144
SetFontSize(int font_size)145 void CScintillaEditView::SetFontSize(int font_size)
146 {
147 SendMessage(SCI_STYLESETSIZE, STYLE_DEFAULT, font_size);
148 }
149
SetTabSize(int tab_size)150 void CScintillaEditView::SetTabSize(int tab_size)
151 {
152 SendMessage(SCI_SETTABWIDTH, tab_size);
153 }
154
SetSel(int start,int end,const wstring & edit_str)155 void CScintillaEditView::SetSel(int start, int end, const wstring& edit_str)
156 {
157 int byte_start = CharactorPosToBytePos(start, edit_str.c_str(), edit_str.size());
158 int byte_end = CharactorPosToBytePos(end, edit_str.c_str(), edit_str.size());
159 int length = SendMessage(SCI_GETLENGTH);
160 if (start >= static_cast<int>(edit_str.size()))
161 byte_start = length;
162 if (end >= static_cast<int>(edit_str.size()))
163 byte_end = length;
164 SendMessage(SCI_SETSEL, byte_start, byte_end);
165 }
166
GetSel(int & start,int & end)167 void CScintillaEditView::GetSel(int & start, int & end)
168 {
169 int byte_start = SendMessage(SCI_GETANCHOR);
170 int byte_end = SendMessage(SCI_GETCURRENTPOS);
171 if (byte_end < byte_start)
172 std::swap(byte_start, byte_end);
173 int size{};
174 const char* str = GetText(size);
175 start = BytePosToCharactorPos(byte_start, str, size);
176 end = BytePosToCharactorPos(byte_end, str, size);
177 delete[] str;
178 }
179
SetBackgroundColor(COLORREF color)180 void CScintillaEditView::SetBackgroundColor(COLORREF color)
181 {
182 m_background_color = color;
183 //SendMessage(SCI_STYLESETBACK, STYLE_DEFAULT, m_background_color);
184 }
185
SetReadOnly(bool read_only)186 void CScintillaEditView::SetReadOnly(bool read_only)
187 {
188 SendMessage(SCI_SETREADONLY, read_only);
189 }
190
IsReadOnly()191 bool CScintillaEditView::IsReadOnly()
192 {
193 return (SendMessage(SCI_GETREADONLY) != 0);
194 }
195
Undo()196 void CScintillaEditView::Undo()
197 {
198 SendMessage(SCI_UNDO);
199 }
200
Redo()201 void CScintillaEditView::Redo()
202 {
203 SendMessage(SCI_REDO);
204 }
205
Cut()206 void CScintillaEditView::Cut()
207 {
208 SendMessage(SCI_CUT);
209 }
210
Copy()211 void CScintillaEditView::Copy()
212 {
213 SendMessage(SCI_COPY);
214 }
215
Paste()216 void CScintillaEditView::Paste()
217 {
218 SendMessage(SCI_PASTE);
219 }
220
SelectAll()221 void CScintillaEditView::SelectAll()
222 {
223 SendMessage(SCI_SELECTALL);
224 }
225
EmptyUndoBuffer()226 void CScintillaEditView::EmptyUndoBuffer()
227 {
228 SendMessage(SCI_EMPTYUNDOBUFFER);
229 }
230
SetWordWrap(bool word_wrap)231 void CScintillaEditView::SetWordWrap(bool word_wrap)
232 {
233 SendMessage(SCI_SETWRAPMODE, word_wrap ? SC_WRAP_WORD : SC_WRAP_NONE);
234 }
235
236
IsEditChangeNotificationEnable()237 bool CScintillaEditView::IsEditChangeNotificationEnable()
238 {
239 return m_change_notification_enable;
240 }
241
CanUndo()242 bool CScintillaEditView::CanUndo()
243 {
244 return (SendMessage(SCI_CANUNDO) != 0);
245 }
246
CanRedo()247 bool CScintillaEditView::CanRedo()
248 {
249 return (SendMessage(SCI_CANREDO) != 0);
250 }
251
CanPaste()252 bool CScintillaEditView::CanPaste()
253 {
254 return (SendMessage(SCI_CANPASTE) != 0);
255 }
256
IsSelectionEmpty()257 bool CScintillaEditView::IsSelectionEmpty()
258 {
259 int anchor = SendMessage(SCI_GETANCHOR);
260 int current_pos = SendMessage(SCI_GETCURRENTPOS);
261 return anchor == current_pos;
262 }
263
IsModified()264 bool CScintillaEditView::IsModified()
265 {
266 return (SendMessage(SCI_GETMODIFY) != 0);
267 }
268
SetSavePoint()269 void CScintillaEditView::SetSavePoint()
270 {
271 SendMessage(SCI_SETSAVEPOINT);
272 }
273
SetLineNumberWidth(int width)274 void CScintillaEditView::SetLineNumberWidth(int width)
275 {
276 m_line_number_width = width;
277 }
278
ShowLineNumber(bool show)279 void CScintillaEditView::ShowLineNumber(bool show)
280 {
281 if (show)
282 SendMessage(SCI_SETMARGINWIDTHN, SCINTILLA_MARGIN_LINENUMBER, m_line_number_width);
283 else
284 SendMessage(SCI_SETMARGINWIDTHN, SCINTILLA_MARGIN_LINENUMBER, 0);
285 }
286
SetLineNumberColor(COLORREF color)287 void CScintillaEditView::SetLineNumberColor(COLORREF color)
288 {
289 //SendMessage(SCI_STYLESETFORE, STYLE_LINENUMBER, color);
290 m_line_number_color = color;
291 }
292
GetZoom()293 int CScintillaEditView::GetZoom()
294 {
295 return SendMessage(SCI_GETZOOM);
296 }
297
SetZoom(int zoom)298 void CScintillaEditView::SetZoom(int zoom)
299 {
300 SendMessage(SCI_SETZOOM, zoom);
301 }
302
SetEolMode(eEolMode eolMode)303 void CScintillaEditView::SetEolMode(eEolMode eolMode)
304 {
305 int mode = 0;
306 switch (eolMode)
307 {
308 case EOL_CRLF:
309 mode = SC_EOL_CRLF;
310 break;
311 case EOL_CR:
312 mode = SC_EOL_CR;
313 break;
314 case EOL_LF:
315 mode = SC_EOL_LF;
316 break;
317 default:
318 break;
319 }
320 SendMessage(SCI_SETEOLMODE, mode);
321 }
322
GetEolMode()323 CScintillaEditView::eEolMode CScintillaEditView::GetEolMode()
324 {
325 int mode = SendMessage(SCI_GETEOLMODE);
326 switch (mode)
327 {
328 case SC_EOL_CR:
329 return EOL_CR;
330 case SC_EOL_LF:
331 return EOL_LF;
332 default:
333 return EOL_CRLF;
334 break;
335 }
336 }
337
ConvertEolMode(eEolMode eolMode)338 void CScintillaEditView::ConvertEolMode(eEolMode eolMode)
339 {
340 int mode = 0;
341 switch (eolMode)
342 {
343 case EOL_CRLF:
344 mode = SC_EOL_CRLF;
345 break;
346 case EOL_CR:
347 mode = SC_EOL_CR;
348 break;
349 case EOL_LF:
350 mode = SC_EOL_LF;
351 break;
352 default:
353 break;
354 }
355 SendMessage(SCI_CONVERTEOLS, mode);
356 }
357
SetViewEol(bool show)358 void CScintillaEditView::SetViewEol(bool show)
359 {
360 SendMessage(SCI_SETVIEWEOL, show);
361 }
362
GetFirstVisibleLine()363 int CScintillaEditView::GetFirstVisibleLine()
364 {
365 return SendMessage(SCI_GETFIRSTVISIBLELINE);
366 }
367
SetFirstVisibleLine(int line)368 void CScintillaEditView::SetFirstVisibleLine(int line)
369 {
370 SendMessage(SCI_SETFIRSTVISIBLELINE, line);
371 }
372
SetLexer(int lexer)373 void CScintillaEditView::SetLexer(int lexer)
374 {
375 SendMessage(SCI_SETLEXER, lexer);
376 }
377
SetKeywords(int id,const char * keywords)378 void CScintillaEditView::SetKeywords(int id, const char* keywords)
379 {
380 SendMessage(SCI_SETKEYWORDS, id, (sptr_t)keywords);
381 }
382
SetSyntaxColor(int id,COLORREF color)383 void CScintillaEditView::SetSyntaxColor(int id, COLORREF color)
384 {
385 SendMessage(SCI_STYLESETFORE, id, color);
386 }
387
SetSyntaxFontStyle(int id,bool bold,bool italic)388 void CScintillaEditView::SetSyntaxFontStyle(int id, bool bold, bool italic)
389 {
390 SendMessage(SCI_STYLESETBOLD, id, bold);
391 SendMessage(SCI_STYLESETITALIC, id, italic);
392 }
393
SetLexerNormalText()394 void CScintillaEditView::SetLexerNormalText()
395 {
396 SetLexer(SCLEX_NULL);
397 SendMessage(SCI_STYLESETFORE, STYLE_DEFAULT, RGB(0, 0, 0));
398 SendMessage(SCI_STYLESETBACK, STYLE_DEFAULT, m_background_color);
399 SendMessage(SCI_STYLESETBOLD, STYLE_DEFAULT, 0);
400 SendMessage(SCI_STYLESETBOLD, STYLE_DEFAULT, 0);
401 SendMessage(SCI_STYLECLEARALL);
402
403 SendMessage(SCI_STYLESETFORE, STYLE_LINENUMBER, m_line_number_color);
404 }
405
JudgeEolMode(const wstring & str)406 CScintillaEditView::eEolMode CScintillaEditView::JudgeEolMode(const wstring& str)
407 {
408 size_t index = str.find(L"\r\n");
409 if (index != wstring::npos)
410 return EOL_CRLF;
411
412 index = str.find(L'\n');
413 if (index != wstring::npos)
414 return EOL_LF;
415
416 index = str.find(L'\r');
417 if (index != wstring::npos)
418 return EOL_CR;
419
420 return EOL_CRLF;
421
422 }
423
CharactorPosToBytePos(int pos,const wchar_t * str,size_t size)424 int CScintillaEditView::CharactorPosToBytePos(int pos, const wchar_t * str, size_t size)
425 {
426 if (pos >= static_cast<int>(size))
427 return size;
428 else
429 return WideCharToMultiByte(CP_UTF8, 0, str, pos, NULL, 0, NULL, NULL);
430 }
431
BytePosToCharactorPos(int pos,const char * str,size_t size)432 int CScintillaEditView::BytePosToCharactorPos(int pos, const char * str, size_t size)
433 {
434 if (pos >= static_cast<int>(size))
435 return size;
436 else
437 return MultiByteToWideChar(CP_UTF8, 0, str, pos, NULL, 0);
438 }
439
440
SetContextMenu(CMenu * pMenu,CWnd * pMenuOwner)441 void CScintillaEditView::SetContextMenu(CMenu* pMenu, CWnd* pMenuOwner)
442 {
443 if (pMenu != nullptr)
444 {
445 // 这里当前没有使用,使用的是Scintilla的默认右键菜单
446 // 我改了SCI_USEPOPUP的处理,使用lParam传递string table
447 // 如果真的要SendMessage(SCI_USEPOPUP, SC_POPUP_NEVER);记得改回去
448 m_pMenu = pMenu;
449 m_pContextMenuOwner = pMenuOwner;
450 SendMessage(SCI_USEPOPUP, SC_POPUP_NEVER);
451 }
452
453 }
454
GetLinePos(int line,int & start,int & end)455 void CScintillaEditView::GetLinePos(int line, int& start, int& end)
456 {
457 start = SendMessage(SCI_POSITIONFROMLINE, line);
458 end = SendMessage(SCI_GETLINEENDPOSITION, line);
459 int doc_length = SendMessage(SCI_GETLENGTH);
460 if (start < 0 && start > doc_length)
461 start = 0;
462 if (end < 0 || end > doc_length)
463 end = doc_length;
464 }
465
GetCurLinePos(int & start,int & end)466 void CScintillaEditView::GetCurLinePos(int& start, int& end)
467 {
468 int cur_pos = SendMessage(SCI_GETCURRENTPOS);
469 int cur_line = SendMessage(SCI_LINEFROMPOSITION, cur_pos);
470 GetLinePos(cur_line, start, end);
471 }
472
SetLexerLyric(ColorTable theme_color)473 void CScintillaEditView::SetLexerLyric(ColorTable theme_color)
474 {
475 //设置LRC歌词的语法解析
476 SetLexerNormalText();
477 SetLexer(SCLEX_LYRIC);
478 SetKeywords(0, "ar ti al by id");
479 SetSyntaxColor(SCE_LYRIC_TIMETAG, theme_color.dark1_5);
480 SetSyntaxColor(SCE_LYRIC_TIME_TAG_KEYWORD, theme_color.dark1_5);
481 SetSyntaxFontStyle(SCE_LYRIC_TIME_TAG_KEYWORD, true, false);
482 SetSyntaxColor(SCE_LYRIC_SEPARATOR, theme_color.light1);
483 SetSyntaxColor(SCE_LYRIC_TRANSLATION, theme_color.dark2_5);
484
485 //设置当前行背景色
486 SendMessage(SCI_SETCARETLINEVISIBLE, TRUE);
487 SendMessage(SCI_SETCARETLINEBACK, theme_color.light3);
488 }
489
GetCurrentLineText()490 std::string CScintillaEditView::GetCurrentLineText()
491 {
492 int start{}, end{};
493 GetCurLinePos(start, end);
494 return GetText(start, end);
495 }
496
GetCurrentLineTextW()497 std::wstring CScintillaEditView::GetCurrentLineTextW()
498 {
499 return CCommon::StrToUnicode(GetCurrentLineText(), CodeType::UTF8_NO_BOM);
500 }
501
502 // CScintillaEditView 消息处理程序
503
504
PreCreateWindow(CREATESTRUCT & cs)505 BOOL CScintillaEditView::PreCreateWindow(CREATESTRUCT& cs)
506 {
507 // TODO: 在此添加专用代码和/或调用基类
508 cs.lpszClass = _T("Scintilla");
509
510
511 return CView::PreCreateWindow(cs);
512 }
513
514
OnPaint()515 void CScintillaEditView::OnPaint()
516 {
517 //CPaintDC dc(this); // device context for painting
518 // TODO: 在此处添加消息处理程序代码
519 // 不为绘图消息调用 CView::OnPaint()
520 Default();
521 }
522
523
PreSubclassWindow()524 void CScintillaEditView::PreSubclassWindow()
525 {
526 // TODO: 在此添加专用代码和/或调用基类
527
528 CView::PreSubclassWindow();
529 }
530
531
OnInitialUpdate()532 void CScintillaEditView::OnInitialUpdate()
533 {
534 CView::OnInitialUpdate();
535
536 const auto& str_table = theApp.m_str_table.GetScintillaStrMap();
537 SendMessage(SCI_USEPOPUP, SC_POPUP_ALL, reinterpret_cast<LPARAM>(&str_table)); // 设置右键菜单为启用,并传递string table
538
539 SendMessage(SCI_SETCODEPAGE, SC_CP_UTF8); //总是使用Unicode
540 SendMessage(SCI_SETMARGINTYPEN, SCINTILLA_MARGIN_LINENUMBER, SC_MARGIN_NUMBER);
541
542 SendMessage(SCI_SETSCROLLWIDTH, 100);
543 SendMessage(SCI_SETSCROLLWIDTHTRACKING, TRUE);
544 }
545
546
OnRButtonUp(UINT nFlags,CPoint point)547 void CScintillaEditView::OnRButtonUp(UINT nFlags, CPoint point)
548 {
549 // TODO: 在此添加消息处理程序代码和/或调用默认值
550
551 if (m_pMenu != nullptr)
552 {
553 CPoint point1;
554 GetCursorPos(&point1);
555 m_pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point1.x, point1.y, m_pContextMenuOwner);
556 }
557
558
559 CView::OnRButtonUp(nFlags, point);
560 }
561
562
OnTabletQuerysystemgesturestatus(WPARAM wParam,LPARAM lParam)563 afx_msg LRESULT CScintillaEditView::OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam)
564 {
565 return 0;
566 }
567