src/windows/native/sun/windows/awt_TextField.cpp

Print this page




  25 
  26 #include "awt_Toolkit.h"
  27 #include "awt_TextField.h"
  28 #include "awt_TextComponent.h"
  29 #include "awt_Canvas.h"
  30 
  31 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
  32  */
  33 
  34 /***********************************************************************/
  35 // struct for _SetEchoChar() method
  36 struct SetEchoCharStruct {
  37     jobject textfield;
  38     jchar echoChar;
  39 };
  40 /************************************************************************
  41  * AwtTextField methods
  42  */
  43 
  44 AwtTextField::AwtTextField()
  45     : m_initialRescrollFlag( true )
  46 {
  47 }
  48 
  49 /* Create a new AwtTextField object and window.   */
  50 AwtTextField* AwtTextField::Create(jobject peer, jobject parent)
  51 {
  52     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
  53 
  54     jobject target = NULL;
  55     AwtTextField* c = NULL;
  56 
  57     try {
  58         PDATA pData;
  59         AwtCanvas* awtParent;
  60         JNI_CHECK_PEER_GOTO(parent, done);
  61         awtParent = (AwtCanvas*)pData;
  62 
  63         JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done);
  64 
  65         target = env->GetObjectField(peer, AwtObject::targetID);
  66         JNI_CHECK_NULL_GOTO(target, "null target", done);
  67 
  68         c = new AwtTextField();
  69 
  70         {
  71             DWORD style = WS_CHILD | WS_CLIPSIBLINGS |
  72                 ES_LEFT | ES_AUTOHSCROLL;
  73             DWORD exStyle = WS_EX_CLIENTEDGE;
  74             if (GetRTL()) {
  75                 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
  76                 if (GetRTLReadingOrder())
  77                     exStyle |= WS_EX_RTLREADING;
  78             }
  79 
  80             jint x = env->GetIntField(target, AwtComponent::xID);
  81             jint y = env->GetIntField(target, AwtComponent::yID);
  82             jint width = env->GetIntField(target, AwtComponent::widthID);
  83             jint height = env->GetIntField(target, AwtComponent::heightID);
  84 
  85             c->CreateHWnd(env, L"", style, exStyle,
  86                           x, y, width, height,
  87                           awtParent->GetHWnd(),
  88                           reinterpret_cast<HMENU>(static_cast<INT_PTR>(
  89                 awtParent->CreateControlID())),
  90                           ::GetSysColor(COLOR_WINDOWTEXT),
  91                           ::GetSysColor(COLOR_WINDOW),
  92                           peer);
  93 
  94             c->m_backgroundColorSet = TRUE;
  95             /* suppress inheriting parent's color. */
  96             c->UpdateBackground(env, target);
  97             c->SendMessage(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN,
  98                            MAKELPARAM(1, 1));
  99             /*
 100              * Fix for BugTraq Id 4260109.
 101              * Set the text limit to the maximum.
 102              */
 103             c->SendMessage(EM_SETLIMITTEXT);
 104 
 105         }
 106     } catch (...) {
 107         env->DeleteLocalRef(target);
 108         throw;
 109     }
 110 
 111 done:
 112     env->DeleteLocalRef(target);
 113 
 114     return c;
 115 }
 116 
 117 void AwtTextField::EditSetSel(CHARRANGE &cr) {
 118     SendMessage(EM_SETSEL, cr.cpMin, cr.cpMax);
 119 }




 120 
 121 LONG AwtTextField::EditGetCharFromPos(POINT& pt) {
 122     return static_cast<LONG>(SendMessage(EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y)));
 123 }
 124 
 125 LRESULT AwtTextField::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
 126 {
 127     if (message == WM_UNDO || message == EM_UNDO || message == EM_CANUNDO) {
 128         if (GetWindowLong(GetHWnd(), GWL_STYLE) & ES_READONLY) {
 129             return FALSE;
 130         }
 131     }
 132     return AwtTextComponent::WindowProc(message, wParam, lParam);
 133 }
 134 
 135 MsgRouting
 136 AwtTextField::HandleEvent(MSG *msg, BOOL synthetic)
 137 {
 138     MsgRouting returnVal;
 139     /*
 140      * RichEdit 1.0 control starts internal message loop if the
 141      * left mouse button is pressed while the cursor is not over
 142      * the current selection or the current selection is empty.


 145      * this behavior we process the relevant mouse messages
 146      * by ourselves.
 147      * By consuming WM_MOUSEMOVE messages we also don't give
 148      * the RichEdit control a chance to recognize a drag gesture
 149      * and initiate its own drag-n-drop operation.
 150      *
 151      * The workaround also allows us to implement synthetic focus mechanism.
 152      */
 153     if (IsFocusingMouseMessage(msg)) {
 154 
 155         LONG lCurPos = EditGetCharFromPos(msg->pt);
 156 
 157         /*
 158          * NOTE: Plain EDIT control always clears selection on mouse
 159          * button press. We are clearing the current selection only if
 160          * the mouse pointer is not over the selected region.
 161          * In this case we sacrifice backward compatibility
 162          * to allow dnd of the current selection.
 163          */
 164         if (msg->message == WM_LBUTTONDBLCLK) {



 165             SetStartSelectionPos(static_cast<LONG>(SendMessage(
 166                 EM_FINDWORDBREAK, WB_MOVEWORDLEFT, lCurPos)));
 167             SetEndSelectionPos(static_cast<LONG>(SendMessage(
 168                 EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, lCurPos)));





 169         } else {
 170             SetStartSelectionPos(lCurPos);
 171             SetEndSelectionPos(lCurPos);
 172         }
 173         CHARRANGE cr;
 174         cr.cpMin = GetStartSelectionPos();
 175         cr.cpMax = GetEndSelectionPos();
 176         EditSetSel(cr);
 177 
 178         delete msg;
 179         return mrConsume;
 180     } else if (msg->message == WM_LBUTTONUP) {
 181 
 182         /*
 183          * If the left mouse button is pressed on the selected region
 184          * we don't clear the current selection. We clear it on button
 185          * release instead. This is to allow dnd of the current selection.
 186          */
 187         if (GetStartSelectionPos() == -1 && GetEndSelectionPos() == -1) {
 188             CHARRANGE cr;


 288 
 289     SetEchoCharStruct *secs = (SetEchoCharStruct *)param;
 290     jobject self = secs->textfield;
 291     jchar echo = secs->echoChar;
 292 
 293     AwtTextField *c = NULL;
 294 
 295     PDATA pData;
 296     JNI_CHECK_PEER_GOTO(self, ret);
 297     c = (AwtTextField *)pData;
 298     if (::IsWindow(c->GetHWnd()))
 299     {
 300         c->SendMessage(EM_SETPASSWORDCHAR, echo);
 301         // Fix for 4307281: force redraw so that changes will take effect
 302         VERIFY(::InvalidateRect(c->GetHWnd(), NULL, FALSE));
 303     }
 304 ret:
 305     env->DeleteGlobalRef(self);
 306 
 307     delete secs;
 308 }
 309 
 310 void AwtTextField::Reshape(int x, int y, int w, int h)
 311 {
 312     AwtTextComponent::Reshape( x, y, w, h );
 313 
 314     // Another option would be to call this
 315     // after WM_SIZE notification is handled
 316     initialRescroll();
 317 }
 318 
 319 
 320 // Windows' Edit control features:
 321 // (i) if text selection is set while control's width or height is 0,
 322 //   text is scrolled oddly.
 323 // (ii) if control's size is changed, text seems never be automatically
 324 //   rescrolled.
 325 //
 326 // This method is designed for the following scenario: AWT spawns Edit
 327 // control with 0x0 dimensions, then sets text selection, then resizes the
 328 // control (couple of times). This might cause text appear undesirably scrolled.
 329 // So we reset/set selection again to rescroll text. (see also CR 6480547)
 330 void AwtTextField::initialRescroll()
 331 {
 332     if( ! m_initialRescrollFlag ) {
 333         return;
 334     }
 335 
 336     ::RECT r;
 337     BOOL ok = ::GetClientRect( GetHWnd(), &r );
 338     if( ! ok || r.right==0 || r.bottom==0 ) {
 339         return;
 340     }
 341 
 342     m_initialRescrollFlag = false;
 343 
 344     DWORD start, end;
 345     SendMessage( EM_GETSEL, (WPARAM)&start, (LPARAM)&end );
 346     SendMessage( EM_SETSEL, (WPARAM)0, (LPARAM)0 );
 347     SendMessage( EM_SETSEL, (WPARAM)start, (LPARAM)end );
 348 }
 349 
 350 
 351 /************************************************************************
 352  * WTextFieldPeer native methods
 353  */
 354 
 355 extern "C" {
 356 
 357 /*
 358  * Class:     sun_awt_windows_WTextFieldPeer
 359  * Method:    create
 360  * Signature: (Lsun/awt/windows/WComponentPeer;)V
 361  */
 362 JNIEXPORT void JNICALL
 363 Java_sun_awt_windows_WTextFieldPeer_create(JNIEnv *env, jobject self,
 364                                            jobject parent)
 365 {
 366     TRY;
 367 




  25 
  26 #include "awt_Toolkit.h"
  27 #include "awt_TextField.h"
  28 #include "awt_TextComponent.h"
  29 #include "awt_Canvas.h"
  30 
  31 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
  32  */
  33 
  34 /***********************************************************************/
  35 // struct for _SetEchoChar() method
  36 struct SetEchoCharStruct {
  37     jobject textfield;
  38     jchar echoChar;
  39 };
  40 /************************************************************************
  41  * AwtTextField methods
  42  */
  43 
  44 AwtTextField::AwtTextField()

  45 {
  46 }
  47 
  48 /* Create a new AwtTextField object and window.   */
  49 AwtTextField* AwtTextField::Create(jobject peer, jobject parent)
  50 {
  51     return (AwtTextField*) AwtTextComponent::Create(peer, parent, false);






























































  52 }
  53 
  54 void AwtTextField::EditSetSel(CHARRANGE &cr) {
  55     SendMessage(EM_EXSETSEL, 0, reinterpret_cast<LPARAM>(&cr));
  56 
  57     // 6417581: force expected drawing
  58     if (IS_WINVISTA && cr.cpMin == cr.cpMax) {
  59         ::InvalidateRect(GetHWnd(), NULL, TRUE);
  60     }
  61 


  62 }
  63 
  64 LRESULT AwtTextField::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  65 {
  66     if (message == WM_UNDO || message == EM_UNDO || message == EM_CANUNDO) {
  67         if (GetWindowLong(GetHWnd(), GWL_STYLE) & ES_READONLY) {
  68             return FALSE;
  69         }
  70     }
  71     return AwtTextComponent::WindowProc(message, wParam, lParam);
  72 }
  73 
  74 MsgRouting
  75 AwtTextField::HandleEvent(MSG *msg, BOOL synthetic)
  76 {
  77     MsgRouting returnVal;
  78     /*
  79      * RichEdit 1.0 control starts internal message loop if the
  80      * left mouse button is pressed while the cursor is not over
  81      * the current selection or the current selection is empty.


  84      * this behavior we process the relevant mouse messages
  85      * by ourselves.
  86      * By consuming WM_MOUSEMOVE messages we also don't give
  87      * the RichEdit control a chance to recognize a drag gesture
  88      * and initiate its own drag-n-drop operation.
  89      *
  90      * The workaround also allows us to implement synthetic focus mechanism.
  91      */
  92     if (IsFocusingMouseMessage(msg)) {
  93 
  94         LONG lCurPos = EditGetCharFromPos(msg->pt);
  95 
  96         /*
  97          * NOTE: Plain EDIT control always clears selection on mouse
  98          * button press. We are clearing the current selection only if
  99          * the mouse pointer is not over the selected region.
 100          * In this case we sacrifice backward compatibility
 101          * to allow dnd of the current selection.
 102          */
 103         if (msg->message == WM_LBUTTONDBLCLK) {
 104             jchar echo = SendMessage(EM_GETPASSWORDCHAR);
 105 
 106             if(echo == 0){ 
 107               SetStartSelectionPos(static_cast<LONG>(SendMessage(
 108                   EM_FINDWORDBREAK, WB_MOVEWORDLEFT, lCurPos)));
 109               SetEndSelectionPos(static_cast<LONG>(SendMessage(
 110                   EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, lCurPos)));
 111             }else{
 112               SetStartSelectionPos(0);
 113               SetEndSelectionPos(GetTextLength());
 114             }
 115 
 116         } else {
 117             SetStartSelectionPos(lCurPos);
 118             SetEndSelectionPos(lCurPos);
 119         }
 120         CHARRANGE cr;
 121         cr.cpMin = GetStartSelectionPos();
 122         cr.cpMax = GetEndSelectionPos();
 123         EditSetSel(cr);
 124 
 125         delete msg;
 126         return mrConsume;
 127     } else if (msg->message == WM_LBUTTONUP) {
 128 
 129         /*
 130          * If the left mouse button is pressed on the selected region
 131          * we don't clear the current selection. We clear it on button
 132          * release instead. This is to allow dnd of the current selection.
 133          */
 134         if (GetStartSelectionPos() == -1 && GetEndSelectionPos() == -1) {
 135             CHARRANGE cr;


 235 
 236     SetEchoCharStruct *secs = (SetEchoCharStruct *)param;
 237     jobject self = secs->textfield;
 238     jchar echo = secs->echoChar;
 239 
 240     AwtTextField *c = NULL;
 241 
 242     PDATA pData;
 243     JNI_CHECK_PEER_GOTO(self, ret);
 244     c = (AwtTextField *)pData;
 245     if (::IsWindow(c->GetHWnd()))
 246     {
 247         c->SendMessage(EM_SETPASSWORDCHAR, echo);
 248         // Fix for 4307281: force redraw so that changes will take effect
 249         VERIFY(::InvalidateRect(c->GetHWnd(), NULL, FALSE));
 250     }
 251 ret:
 252     env->DeleteGlobalRef(self);
 253 
 254     delete secs;








































 255 }
 256 
 257 
 258 /************************************************************************
 259  * WTextFieldPeer native methods
 260  */
 261 
 262 extern "C" {
 263 
 264 /*
 265  * Class:     sun_awt_windows_WTextFieldPeer
 266  * Method:    create
 267  * Signature: (Lsun/awt/windows/WComponentPeer;)V
 268  */
 269 JNIEXPORT void JNICALL
 270 Java_sun_awt_windows_WTextFieldPeer_create(JNIEnv *env, jobject self,
 271                                            jobject parent)
 272 {
 273     TRY;
 274