57 m_bIgnoreEnChange = FALSE;
58 m_bCanUndo = FALSE;
59 m_hEditCtrl = NULL;
60 m_lHDeltaAccum = 0;
61 m_lVDeltaAccum = 0;
62 }
63
64 AwtTextArea::~AwtTextArea()
65 {
66 }
67
68 void AwtTextArea::Dispose()
69 {
70 if (m_hEditCtrl != NULL) {
71 VERIFY(::DestroyWindow(m_hEditCtrl));
72 m_hEditCtrl = NULL;
73 }
74 AwtTextComponent::Dispose();
75 }
76
77 LPCTSTR AwtTextArea::GetClassName() {
78 static BOOL richedLibraryLoaded = FALSE;
79 if (!richedLibraryLoaded) {
80 JDK_LoadSystemLibrary("RICHED20.DLL");
81 richedLibraryLoaded = TRUE;
82 }
83 return RICHEDIT_CLASS;
84 }
85
86 /* Create a new AwtTextArea object and window. */
87 AwtTextArea* AwtTextArea::Create(jobject peer, jobject parent)
88 {
89 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
90
91 jobject target = NULL;
92 AwtTextArea* c = NULL;
93
94 try {
95 if (env->EnsureLocalCapacity(1) < 0) {
96 return NULL;
97 }
98
99 PDATA pData;
100 AwtCanvas* awtParent;
101 JNI_CHECK_PEER_GOTO(parent, done);
102
103 awtParent = (AwtCanvas*)pData;
104 JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
105
106 target = env->GetObjectField(peer, AwtObject::targetID);
107 JNI_CHECK_NULL_GOTO(target, "null target", done);
108
109 c = new AwtTextArea();
110
111 {
112 /* Adjust style for scrollbar visibility and word wrap */
113 DWORD scroll_style;
114 jint scrollbarVisibility =
115 env->GetIntField(target, AwtTextArea::scrollbarVisibilityID);
116
117 switch (scrollbarVisibility) {
118 case java_awt_TextArea_SCROLLBARS_NONE:
119 scroll_style = ES_AUTOVSCROLL;
120 break;
121 case java_awt_TextArea_SCROLLBARS_VERTICAL_ONLY:
122 scroll_style = WS_VSCROLL | ES_AUTOVSCROLL;
123 break;
124 case java_awt_TextArea_SCROLLBARS_HORIZONTAL_ONLY:
125 scroll_style = WS_HSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL;
126 break;
127 case java_awt_TextArea_SCROLLBARS_BOTH:
128 scroll_style = WS_VSCROLL | WS_HSCROLL |
129 ES_AUTOVSCROLL | ES_AUTOHSCROLL;
130 break;
131 }
132
133 /*
134 * Specify ES_DISABLENOSCROLL - RichEdit control style to disable
135 * scrollbars instead of hiding them when not needed.
136 */
137 DWORD style = WS_CHILD | WS_CLIPSIBLINGS | ES_LEFT | ES_MULTILINE |
138 ES_WANTRETURN | scroll_style | ES_DISABLENOSCROLL;
139 DWORD exStyle = WS_EX_CLIENTEDGE;
140 if (GetRTL()) {
141 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
142 if (GetRTLReadingOrder())
143 exStyle |= WS_EX_RTLREADING;
144 }
145
146 jint x = env->GetIntField(target, AwtComponent::xID);
147 jint y = env->GetIntField(target, AwtComponent::yID);
148 jint width = env->GetIntField(target, AwtComponent::widthID);
149 jint height = env->GetIntField(target, AwtComponent::heightID);
150
151 c->CreateHWnd(env, L"", style, exStyle,
152 x, y, width, height,
153 awtParent->GetHWnd(),
154 reinterpret_cast<HMENU>(static_cast<INT_PTR>(
155 awtParent->CreateControlID())),
156 ::GetSysColor(COLOR_WINDOWTEXT),
157 ::GetSysColor(COLOR_WINDOW),
158 peer);
159
160 // Fix for 4753116.
161 // If it is not win95 (we are using Richedit 2.0)
162 // we set plain text mode, in which the control is
163 // similar to a standard edit control:
164 // - The text in a plain text control can have only
165 // one format.
166 // - The user cannot paste rich text formats, such as RTF
167 // or embedded objects into a plain text control.
168 // - Rich text mode controls always have a default
169 // end-of-document marker or carriage return,
170 // to format paragraphs.
171 // kdm@sparc.spb.su
172 c->SendMessage(EM_SETTEXTMODE, TM_PLAINTEXT, 0);
173
174 c->m_backgroundColorSet = TRUE;
175 /* suppress inheriting parent's color. */
176 c->UpdateBackground(env, target);
177 c->SendMessage(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN,
178 MAKELPARAM(1, 1));
179 /*
180 * Fix for BugTraq Id 4260109.
181 * Set the text limit to the maximum.
182 * Use EM_EXLIMITTEXT for RichEdit controls.
183 * For some reason RichEdit 1.0 becomes read-only if the
184 * specified limit is greater than 0x7FFFFFFD.
185 */
186 c->SendMessage(EM_EXLIMITTEXT, 0, 0x7FFFFFFD);
187
188 /* Unregister RichEdit built-in drop target. */
189 VERIFY(::RevokeDragDrop(c->GetHWnd()) != DRAGDROP_E_INVALIDHWND);
190
191 /* To enforce CF_TEXT format for paste operations. */
192 VERIFY(c->SendMessage(EM_SETOLECALLBACK, 0,
193 (LPARAM)&GetOleCallback()));
194
195 c->SendMessage(EM_SETEVENTMASK, 0, ENM_CHANGE);
196 }
197 } catch (...) {
198 env->DeleteLocalRef(target);
199 throw;
200 }
201
202 done:
203 env->DeleteLocalRef(target);
204
205 return c;
206 }
207
208 void AwtTextArea::EditSetSel(CHARRANGE &cr) {
209 // Fix for 5003402: added restoring/hiding selection to enable automatic scrolling
210 SendMessage(EM_HIDESELECTION, FALSE, TRUE);
211 SendMessage(EM_EXSETSEL, 0, reinterpret_cast<LPARAM>(&cr));
212 SendMessage(EM_HIDESELECTION, TRUE, TRUE);
213 // 6417581: force expected drawing
214 if (IS_WINVISTA && cr.cpMin == cr.cpMax) {
215 ::InvalidateRect(GetHWnd(), NULL, TRUE);
216 }
217 }
218
219 void AwtTextArea::EditGetSel(CHARRANGE &cr) {
220 SendMessage(EM_EXGETSEL, 0, reinterpret_cast<LPARAM>(&cr));
221 }
222
223 LONG AwtTextArea::EditGetCharFromPos(POINT& pt) {
224 return static_cast<LONG>(SendMessage(EM_CHARFROMPOS, 0,
225 reinterpret_cast<LPARAM>(&pt)));
226 }
227
228 /* Count how many '\n's are there in jStr */
229 size_t AwtTextArea::CountNewLines(JNIEnv *env, jstring jStr, size_t maxlen)
230 {
231 size_t nNewlines = 0;
232
233 if (jStr == NULL) {
234 return nNewlines;
235 }
236 /*
237 * Fix for BugTraq Id 4260109.
238 * Don't use TO_WSTRING since it allocates memory on the stack
239 * causing stack overflow when the text is very long.
240 */
241 size_t length = env->GetStringLength(jStr) + 1;
242 WCHAR *string = new WCHAR[length];
243 env->GetStringRegion(jStr, 0, static_cast<jsize>(length - 1), reinterpret_cast<jchar*>(string));
244 string[length-1] = '\0';
245 for (size_t i = 0; i < maxlen && i < length - 1; i++) {
246 if (string[i] == L'\n') {
247 nNewlines++;
248 }
249 }
250 delete[] string;
251 return nNewlines;
252 }
253
254 BOOL AwtTextArea::InheritsNativeMouseWheelBehavior() {return true;}
255
256 MsgRouting
257 AwtTextArea::PreProcessMsg(MSG& msg)
258 {
259 MsgRouting mr = mrPassAlong;
260 static BOOL bPassAlongWmLButtonUp = TRUE;
261
262 if (msg.message == WM_LBUTTONDBLCLK) {
263 bPassAlongWmLButtonUp = FALSE;
264 }
265
266 /*
267 * For some reason RichEdit 1.0 filters out WM_LBUTTONUP after
268 * WM_LBUTTONDBLCLK. To work around this "feature" we send WM_LBUTTONUP
269 * directly to the window procedure and consume instead of passing it
270 * to the next hook.
271 */
272 if (msg.message == WM_LBUTTONUP && bPassAlongWmLButtonUp == FALSE) {
273 SendMessage(WM_LBUTTONUP, msg.wParam, msg.lParam);
274 bPassAlongWmLButtonUp = TRUE;
275 mr = mrConsume;
276 }
277
278 if (mr == mrPassAlong) {
279 mr = AwtComponent::PreProcessMsg(msg);
280 }
281
282 return mr;
283 }
284
285 LRESULT
286 AwtTextArea::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
287
288 LRESULT retValue = 0;
289 MsgRouting mr = mrDoDefault;
290
291 switch (message) {
292 case WM_PRINTCLIENT:
293 {
294 FORMATRANGE fr;
295 HDC hPrinterDC = (HDC)wParam;
296 int nHorizRes = ::GetDeviceCaps(hPrinterDC, HORZRES);
297 int nVertRes = ::GetDeviceCaps(hPrinterDC, VERTRES);
298 int nLogPixelsX = ::GetDeviceCaps(hPrinterDC, LOGPIXELSX);
299 int nLogPixelsY = ::GetDeviceCaps(hPrinterDC, LOGPIXELSY);
300
301 // Ensure the printer DC is in MM_TEXT mode.
302 ::SetMapMode ( hPrinterDC, MM_TEXT );
303
783 } else {
784 *delta_accum = 0;
785 }
786 }
787 delete msg;
788 return mrConsume;
789 // 4417236: end of fix
790 }
791
792 /*
793 * Store the 'synthetic' parameter so that the WM_PASTE security check
794 * happens only for synthetic events.
795 */
796 m_synthetic = synthetic;
797 returnVal = AwtComponent::HandleEvent(msg, synthetic);
798 m_synthetic = FALSE;
799
800 return returnVal;
801 }
802
803 /*
804 * WM_CTLCOLOR is not sent by rich edit controls.
805 * Use EM_SETCHARFORMAT and EM_SETBKGNDCOLOR to set
806 * respectively foreground and background color.
807 */
808 void AwtTextArea::SetColor(COLORREF c) {
809 AwtComponent::SetColor(c);
810
811 CHARFORMAT cf;
812 memset(&cf, 0, sizeof(cf));
813 cf.cbSize = sizeof(cf);
814 cf.dwMask = CFM_COLOR;
815
816 cf.crTextColor = ::IsWindowEnabled(GetHWnd()) ? GetColor() : ::GetSysColor(COLOR_3DSHADOW);
817
818 /*
819 * The documentation for EM_GETCHARFORMAT is not exactly
820 * correct. It appears that wParam has the same meaning
821 * as for EM_SETCHARFORMAT. Our task is to secure that
822 * all the characters in the control have the required
823 * formatting. That's why we use SCF_ALL.
824 */
825 VERIFY(SendMessage(EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf));
826 VERIFY(SendMessage(EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf));
827 }
828
829 /*
830 * In responce to EM_SETBKGNDCOLOR rich edit changes
831 * its bg color and repaints itself so we don't need
832 * to force repaint.
833 */
834 void AwtTextArea::SetBackgroundColor(COLORREF c) {
835 AwtComponent::SetBackgroundColor(c);
836 SendMessage(EM_SETBKGNDCOLOR, (WPARAM)FALSE, (LPARAM)GetBackgroundColor());
837 }
838
839 /*
840 * Disabled edit control has grayed foreground.
841 * Disabled RichEdit 1.0 control has original foreground.
842 * Thus we have to set grayed foreground manually.
843 */
844 void AwtTextArea::Enable(BOOL bEnable)
845 {
846 AwtComponent::Enable(bEnable);
847
848 SetColor(GetColor());
849 }
850
851
852 /* Fix for 4776535, 4648702
853 * If width is 0 or 1 Windows hides the horizontal scroll bar even
854 * if the WS_HSCROLL style is set. It is a bug in Windows.
855 * As a workaround we should set an initial width to 2.
856 * kdm@sparc.spb.su
857 */
858 void AwtTextArea::Reshape(int x, int y, int w, int h)
859 {
860 if (w < 2) {
861 w = 2;
862 }
863 AwtTextComponent::Reshape(x, y, w, h);
864 }
865
866 LONG AwtTextArea::getJavaSelPos(LONG orgPos)
867 {
868 long wlen;
869 long pos = orgPos;
870 long cur = 0;
1031 // global refs and rts are deleted in _ReplaceText()
1032
1033 CATCH_BAD_ALLOC;
1034 }
1035
1036 /*
1037 * Class: sun_awt_windows_WTextAreaPeer
1038 * Method: insertText
1039 * Signature: (Ljava/lang/String;I)V
1040 */
1041 JNIEXPORT void JNICALL
1042 Java_sun_awt_windows_WTextAreaPeer_insertText(JNIEnv *env, jobject self,
1043 jstring text, jint pos)
1044 {
1045 Java_sun_awt_windows_WTextAreaPeer_replaceText(env, self, text, pos, pos);
1046 }
1047
1048 } /* extern "C" */
1049
1050
1051 AwtTextArea::OleCallback AwtTextArea::sm_oleCallback;
1052
1053 /************************************************************************
1054 * Inner class OleCallback definition.
1055 */
1056
1057 AwtTextArea::OleCallback::OleCallback() {
1058 m_refs = 0;
1059 AddRef();
1060 }
1061
1062 STDMETHODIMP
1063 AwtTextArea::OleCallback::QueryInterface(REFIID riid, LPVOID * ppvObj) {
1064
1065 TRY;
1066
1067 if (::IsEqualIID(riid, IID_IUnknown)) {
1068 *ppvObj = (void __RPC_FAR *__RPC_FAR)(IUnknown*)this;
1069 AddRef();
1070 return S_OK;
1071 } else if (::IsEqualIID(riid, IID_IRichEditOleCallback)) {
1072 *ppvObj = (void __RPC_FAR *__RPC_FAR)(IRichEditOleCallback*)this;
1073 AddRef();
1074 return S_OK;
1075 } else {
1076 *ppvObj = NULL;
1077 return E_NOINTERFACE;
1078 }
1079
1080 CATCH_BAD_ALLOC_RET(E_OUTOFMEMORY);
1081 }
1082
1083 STDMETHODIMP_(ULONG)
1084 AwtTextArea::OleCallback::AddRef() {
1085 return ++m_refs;
1086 }
1087
1088 STDMETHODIMP_(ULONG)
1089 AwtTextArea::OleCallback::Release() {
1090 int refs;
1091
1092 if ((refs = --m_refs) == 0) delete this;
1093
1094 return (ULONG)refs;
1095 }
1096
1097 STDMETHODIMP
1098 AwtTextArea::OleCallback::GetNewStorage(LPSTORAGE FAR * ppstg) {
1099 return E_NOTIMPL;
1100 }
1101
1102 STDMETHODIMP
1103 AwtTextArea::OleCallback::GetInPlaceContext(LPOLEINPLACEFRAME FAR * ppipframe,
1104 LPOLEINPLACEUIWINDOW FAR* ppipuiDoc,
1105 LPOLEINPLACEFRAMEINFO pipfinfo)
1106 {
1107 return E_NOTIMPL;
1108 }
1109
1110 STDMETHODIMP
1111 AwtTextArea::OleCallback::ShowContainerUI(BOOL fShow) {
1112 return E_NOTIMPL;
1113 }
1114
1115 STDMETHODIMP
1116 AwtTextArea::OleCallback::QueryInsertObject(LPCLSID pclsid,
1117 LPSTORAGE pstg,
1118 LONG cp) {
1119 return NOERROR;
1120 }
1121
1122 STDMETHODIMP
1123 AwtTextArea::OleCallback::DeleteObject(LPOLEOBJECT poleobj) {
1124 return NOERROR;
1125 }
1126
1127 STDMETHODIMP
1128 AwtTextArea::OleCallback::QueryAcceptData(LPDATAOBJECT pdataobj,
1129 CLIPFORMAT *pcfFormat,
1130 DWORD reco,
1131 BOOL fReally,
1132 HGLOBAL hMetaPict) {
1133 if (reco == RECO_PASTE) {
1134 // If CF_TEXT format is available edit controls will select it,
1135 // otherwise if it is CF_UNICODETEXT is available it will be
1136 // selected, otherwise if CF_OEMTEXT is available it will be selected.
1137 if (::IsClipboardFormatAvailable(CF_TEXT)) {
1138 *pcfFormat = CF_TEXT;
1139 } else if (::IsClipboardFormatAvailable(CF_UNICODETEXT)) {
1140 *pcfFormat = CF_UNICODETEXT;
1141 } else if (::IsClipboardFormatAvailable(CF_OEMTEXT)) {
1142 *pcfFormat = CF_OEMTEXT;
1143 } else {
1144 // Don't allow rich edit to paste clipboard data
1145 // in other formats.
1146 *pcfFormat = CF_TEXT;
1147 }
1148 }
1149
1150 return NOERROR;
1151 }
1152
1153 STDMETHODIMP
1154 AwtTextArea::OleCallback::ContextSensitiveHelp(BOOL fEnterMode) {
1155 return NOERROR;
1156 }
1157
1158 STDMETHODIMP
1159 AwtTextArea::OleCallback::GetClipboardData(CHARRANGE *pchrg,
1160 DWORD reco,
1161 LPDATAOBJECT *ppdataobj) {
1162 return E_NOTIMPL;
1163 }
1164
1165 STDMETHODIMP
1166 AwtTextArea::OleCallback::GetDragDropEffect(BOOL fDrag,
1167 DWORD grfKeyState,
1168 LPDWORD pdwEffect) {
1169
1170 return E_NOTIMPL;
1171 }
1172
1173
1174 STDMETHODIMP
1175 AwtTextArea::OleCallback::GetContextMenu(WORD seltype,
1176 LPOLEOBJECT lpoleobj,
1177 CHARRANGE FAR * lpchrg,
1178 HMENU FAR * lphmenu) {
1179 return E_NOTIMPL;
1180 }
|
57 m_bIgnoreEnChange = FALSE;
58 m_bCanUndo = FALSE;
59 m_hEditCtrl = NULL;
60 m_lHDeltaAccum = 0;
61 m_lVDeltaAccum = 0;
62 }
63
64 AwtTextArea::~AwtTextArea()
65 {
66 }
67
68 void AwtTextArea::Dispose()
69 {
70 if (m_hEditCtrl != NULL) {
71 VERIFY(::DestroyWindow(m_hEditCtrl));
72 m_hEditCtrl = NULL;
73 }
74 AwtTextComponent::Dispose();
75 }
76
77 /* Create a new AwtTextArea object and window. */
78 AwtTextArea* AwtTextArea::Create(jobject peer, jobject parent)
79 {
80 return (AwtTextArea*) AwtTextComponent::Create(peer, parent, true);
81 }
82
83 void AwtTextArea::EditSetSel(CHARRANGE &cr) {
84 // Fix for 5003402: added restoring/hiding selection to enable automatic scrolling
85 SendMessage(EM_HIDESELECTION, FALSE, TRUE);
86 SendMessage(EM_EXSETSEL, 0, reinterpret_cast<LPARAM>(&cr));
87 SendMessage(EM_HIDESELECTION, TRUE, TRUE);
88 // 6417581: force expected drawing
89 if (IS_WINVISTA && cr.cpMin == cr.cpMax) {
90 ::InvalidateRect(GetHWnd(), NULL, TRUE);
91 }
92 }
93
94 void AwtTextArea::EditGetSel(CHARRANGE &cr) {
95 SendMessage(EM_EXGETSEL, 0, reinterpret_cast<LPARAM>(&cr));
96 }
97
98 /* Count how many '\n's are there in jStr */
99 size_t AwtTextArea::CountNewLines(JNIEnv *env, jstring jStr, size_t maxlen)
100 {
101 size_t nNewlines = 0;
102
103 if (jStr == NULL) {
104 return nNewlines;
105 }
106 /*
107 * Fix for BugTraq Id 4260109.
108 * Don't use TO_WSTRING since it allocates memory on the stack
109 * causing stack overflow when the text is very long.
110 */
111 size_t length = env->GetStringLength(jStr) + 1;
112 WCHAR *string = new WCHAR[length];
113 env->GetStringRegion(jStr, 0, static_cast<jsize>(length - 1), reinterpret_cast<jchar*>(string));
114 string[length-1] = '\0';
115 for (size_t i = 0; i < maxlen && i < length - 1; i++) {
116 if (string[i] == L'\n') {
117 nNewlines++;
118 }
119 }
120 delete[] string;
121 return nNewlines;
122 }
123
124 BOOL AwtTextArea::InheritsNativeMouseWheelBehavior() {return true;}
125
126
127 LRESULT
128 AwtTextArea::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
129
130 LRESULT retValue = 0;
131 MsgRouting mr = mrDoDefault;
132
133 switch (message) {
134 case WM_PRINTCLIENT:
135 {
136 FORMATRANGE fr;
137 HDC hPrinterDC = (HDC)wParam;
138 int nHorizRes = ::GetDeviceCaps(hPrinterDC, HORZRES);
139 int nVertRes = ::GetDeviceCaps(hPrinterDC, VERTRES);
140 int nLogPixelsX = ::GetDeviceCaps(hPrinterDC, LOGPIXELSX);
141 int nLogPixelsY = ::GetDeviceCaps(hPrinterDC, LOGPIXELSY);
142
143 // Ensure the printer DC is in MM_TEXT mode.
144 ::SetMapMode ( hPrinterDC, MM_TEXT );
145
625 } else {
626 *delta_accum = 0;
627 }
628 }
629 delete msg;
630 return mrConsume;
631 // 4417236: end of fix
632 }
633
634 /*
635 * Store the 'synthetic' parameter so that the WM_PASTE security check
636 * happens only for synthetic events.
637 */
638 m_synthetic = synthetic;
639 returnVal = AwtComponent::HandleEvent(msg, synthetic);
640 m_synthetic = FALSE;
641
642 return returnVal;
643 }
644
645
646 /* Fix for 4776535, 4648702
647 * If width is 0 or 1 Windows hides the horizontal scroll bar even
648 * if the WS_HSCROLL style is set. It is a bug in Windows.
649 * As a workaround we should set an initial width to 2.
650 * kdm@sparc.spb.su
651 */
652 void AwtTextArea::Reshape(int x, int y, int w, int h)
653 {
654 if (w < 2) {
655 w = 2;
656 }
657 AwtTextComponent::Reshape(x, y, w, h);
658 }
659
660 LONG AwtTextArea::getJavaSelPos(LONG orgPos)
661 {
662 long wlen;
663 long pos = orgPos;
664 long cur = 0;
825 // global refs and rts are deleted in _ReplaceText()
826
827 CATCH_BAD_ALLOC;
828 }
829
830 /*
831 * Class: sun_awt_windows_WTextAreaPeer
832 * Method: insertText
833 * Signature: (Ljava/lang/String;I)V
834 */
835 JNIEXPORT void JNICALL
836 Java_sun_awt_windows_WTextAreaPeer_insertText(JNIEnv *env, jobject self,
837 jstring text, jint pos)
838 {
839 Java_sun_awt_windows_WTextAreaPeer_replaceText(env, self, text, pos, pos);
840 }
841
842 } /* extern "C" */
843
844
|