• R/O
  • SSH
  • HTTPS

ttssh2: Commit


Commit MetaInfo

Revision6456 (tree)
Time2016-08-01 18:01:30
Authordoda

Log Message

クリップボードの内容に改行が含まれているかの確認を、CBStartPaste() の 中から行うようにした。

確認をクリップボードにアクセスするのではなく、CBStartPaste() でコピー した領域をチェックするようにした。
他のクリップボードの内容確認/加工を行う場合を考えた場合、この形式の方が 統一性が取れていいと思う。

変更によってダイアログの(変更)内容をクリップボードに書き戻さなくなったが、 この書き戻しの挙動は必要?

・クリップボードに余計な干渉はしないという観点からは書き戻さない方がよさそう。
・複数回繰り返して貼り付ける場合は、毎回ダイアログでの編集が必要となる。

この点に関しては書き戻した方が便利。

CBStartPaste() でのコピー先の領域を GlobalAlloc() で確保する必要はある?
以前はクリップボードのデータを直接読む場合も有ったので互換性のある確保の仕方が必要だったが、
現在は完全に切り離されたので、malloc() で確保したり、GlobalAlloc() を使うにしても、
GMEM_FIXED で固定メモリにする方が扱い易くないか?

Change Summary

Incremental Difference

--- trunk/teraterm/teraterm/clipboar.c (revision 6455)
+++ trunk/teraterm/teraterm/clipboar.c (revision 6456)
@@ -37,6 +37,8 @@
3737
3838 static HFONT DlgClipboardFont;
3939
40+static LRESULT CALLBACK OnClipboardDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp);
41+
4042 PCHAR CBOpen(LONG MemSize)
4143 {
4244 if (MemSize==0) {
@@ -154,6 +156,105 @@
154156 return TRUE;
155157 }
156158
159+// ファイルに定義された文字列が、textに含まれるかを調べる。
160+BOOL search_dict(char *filename, char *text)
161+{
162+ BOOL ret = FALSE;
163+ FILE *fp = NULL;
164+ char buf[256];
165+ int len;
166+
167+ if (filename == NULL || filename[0] == '\0')
168+ return FALSE;
169+
170+ if ((fp = fopen(filename, "r")) == NULL)
171+ return FALSE;
172+
173+ // TODO: 一行が256byteを超えている場合の考慮
174+ while (fgets(buf, sizeof(buf), fp) != NULL) {
175+ len = strlen(buf);
176+ if (len <= 1) {
177+ continue;
178+ }
179+ if (buf[len - 1] == '\n') {
180+ buf[len - 1] = '\0';
181+ }
182+ if (strstr(text, buf)) { // hit
183+ ret = 1;
184+ break;
185+ }
186+ }
187+
188+ fclose(fp);
189+
190+ return (ret);
191+}
192+
193+/*
194+ * クリップボードの内容を確認し、貼り付けを行うか確認ダイアログを出す。
195+ *
196+ * 返り値:
197+ * TRUE -> 問題なし、貼り付けを実施
198+ * FALSE -> 貼り付け中止
199+ */
200+BOOL CheckClipboardContent(BOOL AddCR, BOOL Bracketed)
201+{
202+ int pos;
203+ int ret = IDOK;
204+ BOOL confirm = FALSE;
205+
206+ if (!ts.ConfirmChangePaste) {
207+ return TRUE;
208+ }
209+
210+/*
211+ * ConfirmChangePasteCR の挙動問題
212+ * 以下の動作で問題ないか。
213+ *
214+ * ChangePasteCR !ChangePasteCR
215+ * AddCR !AddCR AddCR !AddCR
216+ * 改行あり o o x(2) o
217+ * 改行無し o(1) x x x
218+ *
219+ * ChangePasteCR は AddCR の時に確認を行うか(1で確認する)という設定だが、
220+ * !ChangePasteCR の時を考えると、AddCR の時は常に CR が入っているのに
221+ * 確認を行わない事から 2 の場合でも確認は不用という意思表示ともとれる。
222+ * 2 の動作はどちらがいいか?
223+ */
224+
225+ if (AddCR) {
226+ if (ts.ConfirmChangePasteCR) {
227+ confirm = TRUE;
228+ }
229+ }
230+ else {
231+ pos = strcspn(CBMemPtr, "\r\n"); // 改行が含まれていたら
232+ if (CBMemPtr[pos] != '\0') {
233+ confirm = TRUE;
234+ }
235+ }
236+
237+ // 辞書をサーチする
238+ if (!confirm && search_dict(ts.ConfirmChangePasteStringFile, CBMemPtr)) {
239+ confirm = TRUE;
240+ }
241+
242+ if (confirm) {
243+ ret = DialogBox(hInst, MAKEINTRESOURCE(IDD_CLIPBOARD_DIALOG),
244+ HVTWin, (DLGPROC)OnClipboardDlgProc);
245+ /*
246+ * 以前はダイアログの内容をクリップボードに書き戻していたけれど、必要?
247+ */
248+ }
249+
250+ if (ret == IDOK) {
251+ return TRUE;
252+ }
253+ else {
254+ return FALSE;
255+ }
256+}
257+
157258 #define BracketStartLen (sizeof(BracketStart)-1)
158259 #define BracketEndLen (sizeof(BracketEnd)-1)
159260 void CBStartPaste(HWND HWin, BOOL AddCR, BOOL Bracketed)
@@ -257,6 +358,11 @@
257358 return;
258359 }
259360
361+ if (!CheckClipboardContent(AddCR, Bracketed)) {
362+ CBEndPaste();
363+ return;
364+ }
365+
260366 // AddCR / Bracket 用の領域があるかの確認、無ければ追加確保
261367 StrLen = strlen(CBMemPtr);
262368 BuffLen = StrLen + 1; // strlen + NUL
@@ -633,15 +739,11 @@
633739 return hMem;
634740 }
635741
636-static char *ClipboardPtr = NULL;
637-static int PasteCanceled = 0;
638-
639742 static LRESULT CALLBACK OnClipboardDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
640743 {
641744 LOGFONT logfont;
642745 HFONT font;
643746 char uimsg[MAX_UIMSG];
644- //char *p;
645747 POINT p;
646748 RECT rc_dsk, rc_dlg;
647749 int dlg_height, dlg_width;
@@ -653,14 +755,6 @@
653755
654756 switch (msg) {
655757 case WM_INITDIALOG:
656-#if 0
657- for (p = ClipboardPtr; *p ; p++) {
658- char buf[20];
659- _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%02x ", *p);
660- OutputDebugString(buf);
661- }
662-#endif
663-
664758 font = (HFONT)SendMessage(hDlgWnd, WM_GETFONT, 0, 0);
665759 GetObject(font, sizeof(LOGFONT), &logfont);
666760 if (get_lang_font("DLG_TAHOMA_FONT", hDlgWnd, &logfont, &DlgClipboardFont, ts.UILanguageFile)) {
@@ -682,7 +776,7 @@
682776 get_lang_msg("BTN_OK", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
683777 SetDlgItemText(hDlgWnd, IDOK, ts.UIMsg);
684778
685- SendMessage(GetDlgItem(hDlgWnd, IDC_EDIT), WM_SETTEXT, 0, (LPARAM)ClipboardPtr);
779+ SendMessage(GetDlgItem(hDlgWnd, IDC_EDIT), WM_SETTEXT, 0, (LPARAM)CBMemPtr);
686780
687781 DispConvScreenToWin(CursorX, CursorY, &p.x, &p.y);
688782 ClientToScreen(HVTWin, &p);
@@ -760,21 +854,46 @@
760854 switch (LOWORD(wp)) {
761855 case IDOK:
762856 {
763- int len = SendMessage(GetDlgItem(hDlgWnd, IDC_EDIT), WM_GETTEXTLENGTH, 0, 0);
857+ unsigned len = SendMessage(GetDlgItem(hDlgWnd, IDC_EDIT), WM_GETTEXTLENGTH, 0, 0);
764858 HGLOBAL hMem;
765- char *buf;
859+ INT_PTR result = IDCANCEL;
766860
767- hMem = GlobalAlloc(GMEM_MOVEABLE, len + 1);
768- if (hMem) {
769- buf = GlobalLock(hMem);
770- SendMessage(GetDlgItem(hDlgWnd, IDC_EDIT), WM_GETTEXT, len + 1, (LPARAM)buf);
771- GlobalUnlock(hMem);
861+ if (CBMemHandle == NULL) {
862+ CBMemHandle = GlobalAlloc(GHND, len+1);
863+ }
864+ else if (GlobalSize(CBMemHandle) <= len) {
865+ if (CBMemPtr) {
866+ GlobalUnlock(CBMemHandle);
867+ CBMemPtr = NULL;
868+ }
869+ hMem = GlobalReAlloc(CBMemHandle, len+1, 0);
870+ if (hMem) {
871+ CBMemHandle = hMem;
872+ CBMemPtr = GlobalLock(CBMemHandle);
873+ }
874+ else {
875+ /*
876+ * メモリが確保できなかった場合はどうするべきか。
877+ *
878+ * ダイアログで書き換えが行われた場合を考えると
879+ * キャンセル扱いにする方が無難だが、大抵は書き換えを
880+ * 行わないと思われるので、その場合は旧領域の内容を
881+ * 貼り付けた方が親切。
882+ *
883+ * 取りあえずは安全側に倒し、旧領域を開放して貼り付けが
884+ * 行われないようにする。
885+ */
886+ GlobalFree(CBMemHandle);
887+ CBMemHandle = NULL;
888+ }
889+ }
772890
773- if (! CBSetClipboard(hDlgWnd, hMem)) {
774- // クリップボードへのセットが失敗した時は hMem を破棄する
775- // 成功した場合はクリップボードが所持しているので、破棄してはいけない
776- GlobalFree(hMem);
891+ if (CBMemHandle) {
892+ if (CBMemPtr == NULL) {
893+ CBMemPtr = GlobalLock(CBMemHandle);
777894 }
895+ SendMessage(GetDlgItem(hDlgWnd, IDC_EDIT), WM_GETTEXT, GlobalSize(CBMemHandle), (LPARAM)CBMemPtr);
896+ result = IDOK;
778897 }
779898
780899 if (DlgClipboardFont != NULL) {
@@ -782,13 +901,11 @@
782901 }
783902
784903 DestroyWindow(hStatus);
785- EndDialog(hDlgWnd, IDOK);
904+ EndDialog(hDlgWnd, result);
786905 }
787906 break;
788907
789908 case IDCANCEL:
790- PasteCanceled = 1;
791-
792909 if (DlgClipboardFont != NULL) {
793910 DeleteObject(DlgClipboardFont);
794911 }
@@ -801,13 +918,6 @@
801918 return FALSE;
802919 }
803920
804-#if 0
805- case WM_CLOSE:
806- PasteCanceled = 1;
807- EndDialog(hDlgWnd, 0);
808- return TRUE;
809-#endif
810-
811921 case WM_SIZE:
812922 {
813923 // 再配置
@@ -871,150 +981,3 @@
871981 }
872982 return TRUE;
873983 }
874-
875-// ファイルに定義された文字列が、textに含まれるかを調べる。
876-static int search_clipboard(char *filename, char *text)
877-{
878- int ret = 0; // no hit
879- FILE *fp = NULL;
880- char buf[256];
881- int len;
882-
883- if (filename == NULL || filename[0] == '\0')
884- goto error;
885-
886- fp = fopen(filename, "r");
887- if (fp == NULL)
888- goto error;
889-
890- // TODO: 一行が256byteを超えている場合の考慮
891- while (fgets(buf, sizeof(buf), fp) != NULL) {
892- len = strlen(buf);
893- if (buf[len - 1] == '\n')
894- buf[len - 1] = '\0';
895- if (buf[0] == '\0')
896- continue;
897- if (strstr(text, buf)) { // hit
898- ret = 1;
899- break;
900- }
901- }
902-
903-error:
904- if (fp)
905- fclose(fp);
906-
907- return (ret);
908-}
909-
910-
911-//
912-// クリップボードに改行コードが含まれていたら、確認ダイアログを表示する。
913-// クリップボードの変更も可能。
914-//
915-// return 0: Cancel
916-// 1: Paste OK
917-//
918-// (2008.2.3 yutaka)
919-//
920-int CBStartPasteConfirmChange(HWND HWin, BOOL AddCR)
921-{
922- UINT Cf;
923- HANDLE hText;
924- char *pText;
925- int pos;
926- int ret = 0;
927- BOOL confirm = FALSE;
928- HANDLE wide_hText;
929- LPWSTR wide_buf;
930- int mb_len;
931-
932- if (!ts.ConfirmChangePaste)
933- return 1;
934-
935- if (! cv.Ready)
936- goto error;
937- if (TalkStatus!=IdTalkKeyb)
938- goto error;
939-
940- if (IsClipboardFormatAvailable(CF_UNICODETEXT))
941- Cf = CF_UNICODETEXT;
942- else if (IsClipboardFormatAvailable(CF_TEXT))
943- Cf = CF_TEXT;
944- else if (IsClipboardFormatAvailable(CF_OEMTEXT))
945- Cf = CF_OEMTEXT;
946- else
947- goto error;
948-
949- if (!OpenClipboard(HWin))
950- goto error;
951-
952- if (Cf == CF_UNICODETEXT) {
953- wide_hText = GetClipboardData(CF_UNICODETEXT);
954- if (wide_hText != NULL) {
955- wide_buf = GlobalLock(wide_hText);
956- mb_len = WideCharToMultiByte(CP_ACP, 0, wide_buf, -1, NULL, 0, NULL, NULL);
957- ClipboardPtr = (char *)calloc(sizeof(char), mb_len);
958- WideCharToMultiByte(CP_ACP, 0, wide_buf, -1, ClipboardPtr, mb_len, NULL, NULL);
959- GlobalUnlock(wide_hText);
960- }
961- else {
962- CloseClipboard();
963- goto error;
964- }
965- }
966- else {
967- hText = GetClipboardData(Cf);
968- if (hText != NULL) {
969- pText = (char *)GlobalLock(hText);
970- ClipboardPtr = (char *)calloc(sizeof(char), strlen(pText)+1);
971- memcpy(ClipboardPtr, pText, strlen(pText));
972- GlobalUnlock(hText);
973- }
974- else {
975- CloseClipboard();
976- goto error;
977- }
978- }
979- CloseClipboard();
980-
981- if (AddCR) {
982- if (ts.ConfirmChangePasteCR) {
983- confirm = TRUE;
984- }
985- }
986- else {
987- pos = strcspn(ClipboardPtr, "\r\n"); // 改行が含まれていたら
988- if (ClipboardPtr[pos] != '\0' || AddCR) {
989- confirm = TRUE;
990- }
991- }
992-
993- // 辞書をサーチする
994- if (!confirm && search_clipboard(ts.ConfirmChangePasteStringFile, ClipboardPtr)) {
995- confirm = TRUE;
996- }
997-
998- if (confirm) {
999- PasteCanceled = 0;
1000- ret = DialogBox(hInst, MAKEINTRESOURCE(IDD_CLIPBOARD_DIALOG),
1001- HVTWin, (DLGPROC)OnClipboardDlgProc);
1002- if (ret == 0 || ret == -1) {
1003- ret = GetLastError();
1004- }
1005-
1006- if (PasteCanceled) {
1007- ret = 0;
1008- goto error;
1009- }
1010- }
1011-
1012- ret = 1;
1013-
1014-error:
1015- if (ClipboardPtr != NULL) {
1016- free(ClipboardPtr);
1017- ClipboardPtr = NULL;
1018- }
1019- return (ret);
1020-}
--- trunk/teraterm/teraterm/clipboar.h (revision 6455)
+++ trunk/teraterm/teraterm/clipboar.h (revision 6456)
@@ -17,7 +17,6 @@
1717 void CBSend();
1818 void CBEcho();
1919 void CBEndPaste();
20-int CBStartPasteConfirmChange(HWND HWin, BOOL AddCR);
2120
2221 #ifdef __cplusplus
2322 }
--- trunk/teraterm/teraterm/vtwin.cpp (revision 6455)
+++ trunk/teraterm/teraterm/vtwin.cpp (revision 6456)
@@ -941,12 +941,10 @@
941941 }
942942
943943 if (Paste) {
944- if (CBStartPasteConfirmChange(HVTWin, FALSE)) {
945- CBStartPaste(HVTWin, FALSE, BracketedPasteMode());
946- // スクロール位置をリセット
947- if (WinOrgY != 0) {
948- DispVScroll(SCROLL_BOTTOM, 0);
949- }
944+ CBStartPaste(HVTWin, FALSE, BracketedPasteMode());
945+ // スクロール位置をリセット
946+ if (WinOrgY != 0) {
947+ DispVScroll(SCROLL_BOTTOM, 0);
950948 }
951949 }
952950 }
@@ -4439,12 +4437,10 @@
44394437 void CVTWindow::OnEditPaste()
44404438 {
44414439 // add confirm (2008.2.4 yutaka)
4442- if (CBStartPasteConfirmChange(HVTWin, FALSE)) {
4443- CBStartPaste(HVTWin, FALSE, BracketedPasteMode());
4444- // スクロール位置をリセット
4445- if (WinOrgY != 0) {
4446- DispVScroll(SCROLL_BOTTOM, 0);
4447- }
4440+ CBStartPaste(HVTWin, FALSE, BracketedPasteMode());
4441+ // スクロール位置をリセット
4442+ if (WinOrgY != 0) {
4443+ DispVScroll(SCROLL_BOTTOM, 0);
44484444 }
44494445 }
44504446
@@ -4451,12 +4447,10 @@
44514447 void CVTWindow::OnEditPasteCR()
44524448 {
44534449 // add confirm (2008.3.11 maya)
4454- if (CBStartPasteConfirmChange(HVTWin, TRUE)) {
4455- CBStartPaste(HVTWin, TRUE, BracketedPasteMode());
4456- // スクロール位置をリセット
4457- if (WinOrgY != 0) {
4458- DispVScroll(SCROLL_BOTTOM, 0);
4459- }
4450+ CBStartPaste(HVTWin, TRUE, BracketedPasteMode());
4451+ // スクロール位置をリセット
4452+ if (WinOrgY != 0) {
4453+ DispVScroll(SCROLL_BOTTOM, 0);
44604454 }
44614455 }
44624456
Show on old repository browser