xref: /MusicPlayer2/MusicPlayer2/ScintillaEditView.cpp (revision f9763b28e6d019e8b836e436b68c871dc5256bb4)
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