1 /* 2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "awt_List.h" 27 #include "awt_Canvas.h" 28 #include "awt_Dimension.h" 29 #include "awt_Toolkit.h" 30 #include "awt_Window.h" 31 32 #include "ComCtl32Util.h" 33 34 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. 35 */ 36 37 /***********************************************************************/ 38 // struct for _AddItems() method 39 struct AddItemsStruct { 40 jobject list; 41 jobjectArray items; 42 jint index; 43 jint width; 44 }; 45 // struct for _DelItems() method 46 struct DelItemsStruct { 47 jobject list; 48 jint start, end; 49 }; 50 // struct for _IsSelected(), _Select(), _Deselect() and _MakeVisible() methods 51 struct SelectElementStruct { 52 jobject list; 53 jint index; 54 }; 55 // struct for _SetMultipleSelections() method 56 struct SetMultipleSelectionsStruct { 57 jobject list; 58 jboolean on; 59 }; 60 /************************************************************************ 61 * AwtList methods 62 */ 63 64 AwtList::AwtList() { 65 isMultiSelect = FALSE; 66 isWrapperPrint = FALSE; 67 } 68 69 AwtList::~AwtList() 70 { 71 } 72 73 LPCTSTR AwtList::GetClassName() { 74 return TEXT("LISTBOX"); 75 } 76 77 /* Create a new AwtList object and window. */ 78 AwtList* AwtList::Create(jobject peer, jobject parent) 79 { 80 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 81 82 jobject target = NULL; 83 AwtList* c = NULL; 84 85 try { 86 if (env->EnsureLocalCapacity(1) < 0) { 87 return NULL; 88 } 89 90 PDATA pData; 91 AwtCanvas* awtParent; 92 JNI_CHECK_PEER_GOTO(parent, done); 93 94 awtParent = (AwtCanvas*)pData; 95 JNI_CHECK_NULL_GOTO(awtParent, "null awtParent", done); 96 97 /* target is Hjava_awt_List * */ 98 target = env->GetObjectField(peer, AwtObject::targetID); 99 JNI_CHECK_NULL_GOTO(target, "null target", done); 100 101 c = new AwtList(); 102 103 { 104 105 /* 106 * NOTE: WS_CLIPCHILDREN is excluded so that repaint requests 107 * from Java will pass through the wrap to the native listbox. 108 */ 109 DWORD wrapStyle = WS_CHILD | WS_CLIPSIBLINGS; 110 DWORD wrapExStyle = 0; 111 112 DWORD style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL | 113 LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | LBS_OWNERDRAWFIXED; 114 DWORD exStyle = WS_EX_CLIENTEDGE; 115 116 /* 117 * NOTE: WS_VISIBLE is always set for the listbox. Listbox 118 * visibility is controlled by toggling the wrap's WS_VISIBLE bit. 119 */ 120 style |= WS_VISIBLE; 121 122 if (GetRTL()) { 123 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; 124 if (GetRTLReadingOrder()) 125 exStyle |= WS_EX_RTLREADING; 126 } 127 128 jint x = env->GetIntField(target, AwtComponent::xID); 129 jint y = env->GetIntField(target, AwtComponent::yID); 130 jint width = env->GetIntField(target, AwtComponent::widthID); 131 jint height = env->GetIntField(target, AwtComponent::heightID); 132 133 c->CreateHWnd(env, L"", style, exStyle, 134 x, y, width, height, 135 awtParent->GetHWnd(), 136 NULL, 137 ::GetSysColor(COLOR_WINDOWTEXT), 138 ::GetSysColor(COLOR_WINDOW), 139 peer 140 ); 141 142 /* suppress inheriting awtParent's color. */ 143 c->m_backgroundColorSet = TRUE; 144 c->UpdateBackground(env, target); 145 } 146 } catch (...) { 147 env->DeleteLocalRef(target); 148 throw; 149 } 150 151 done: 152 env->DeleteLocalRef(target); 153 return c; 154 } 155 156 void AwtList::SetDragCapture(UINT flags) 157 { 158 // don't want to interfere with other controls 159 if (::GetCapture() == NULL) { 160 ::SetCapture(GetListHandle()); 161 } 162 } 163 164 void AwtList::ReleaseDragCapture(UINT flags) 165 { 166 if ((::GetCapture() == GetListHandle()) && ((flags & ALL_MK_BUTTONS) == 0)) { 167 ::ReleaseCapture(); 168 } 169 } 170 171 void AwtList::Reshape(int x, int y, int w, int h) 172 { 173 AwtComponent::Reshape(x, y, w, h); 174 175 /* 176 HWND hList = GetListHandle(); 177 if (hList != NULL) { 178 long flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS; 179 /* 180 * Fix for bug 4046446. 181 * / 182 SetWindowPos(hList, 0, 0, 0, w, h, flags); 183 } 184 */ 185 } 186 187 //Netscape : Override the AwtComponent method so we can set the item height 188 //for each item in the list. Modified by echawkes to avoid race condition. 189 190 void AwtList::SetFont(AwtFont* font) 191 { 192 DASSERT(font != NULL); 193 if (font->GetAscent() < 0) 194 { 195 AwtFont::SetupAscent(font); 196 } 197 HANDLE hFont = font->GetHFont(); 198 SendListMessage(WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0)); 199 200 HDC hDC = ::GetDC(GetHWnd()); 201 202 TEXTMETRIC tm; 203 VERIFY(::SelectObject(hDC, hFont) != NULL); 204 VERIFY(::GetTextMetrics(hDC, &tm)); 205 206 ::ReleaseDC(GetHWnd(), hDC); 207 208 long h = tm.tmHeight + tm.tmExternalLeading; 209 // Listbox is LBS_OWNERDRAWFIXED so the items have the same height 210 VERIFY(SendListMessage(LB_SETITEMHEIGHT, 0, MAKELPARAM(h, 0)) != LB_ERR); 211 VERIFY(::RedrawWindow(GetHWnd(), NULL, NULL, RDW_INVALIDATE |RDW_FRAME |RDW_ERASE)); 212 } 213 214 void AwtList::SetMultiSelect(BOOL ms) { 215 if (ms == isMultiSelect) { 216 return; 217 } 218 219 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 220 221 /* Copy current box's contents to string array */ 222 const int nCount = GetCount(); 223 LPTSTR * strings = new LPTSTR[nCount]; 224 int i; 225 226 for(i = 0; i < nCount; i++) { 227 LRESULT len = SendListMessage(LB_GETTEXTLEN, i); 228 LPTSTR text = NULL; 229 try { 230 text = new TCHAR[len + 1]; 231 } catch (std::bad_alloc&) { 232 // free char * already allocated 233 for (int j = 0; j < i; j++) { 234 delete [] strings[j]; 235 } 236 delete [] strings; 237 throw; 238 } 239 240 VERIFY(SendListMessage(LB_GETTEXT, i, (LPARAM)text) != LB_ERR); 241 strings[i] = text; 242 } 243 244 // index for selected item after multi-select mode change 245 int toSelect = SendListMessage(LB_GETCURSEL); 246 if (!isMultiSelect) 247 { 248 // MSDN: for single-select lists LB_GETCURSEL returns 249 // index of selected item or LB_ERR if no item is selected 250 if (toSelect == LB_ERR) 251 { 252 toSelect = -1; 253 } 254 } 255 else 256 { 257 // MSDN: for multi-select lists LB_GETCURSEL returns index 258 // of the focused item or 0 if no items are selected; if 259 // some item has focus and is not selected then LB_GETCURSEL 260 // return its index, so we need IsItemSelected too 261 if ((toSelect == LB_ERR) || 262 (SendListMessage(LB_GETSELCOUNT) == 0) || 263 (IsItemSelected(toSelect) == 0)) 264 { 265 toSelect = -1; 266 } 267 } 268 269 isMultiSelect = ms; 270 271 HWND parentHWnd = GetParent()->GetHWnd(); 272 273 /* Save old list box's attributes */ 274 RECT rect; 275 GetWindowRect(GetListHandle(), &rect); 276 MapWindowPoints(0, parentHWnd, (LPPOINT)&rect, 2); 277 278 HANDLE font = (HANDLE)SendListMessage(WM_GETFONT); 279 LRESULT itemHeight = SendListMessage(LB_GETITEMHEIGHT, 0); 280 DWORD style = ::GetWindowLong(GetListHandle(), GWL_STYLE) | WS_VSCROLL | WS_HSCROLL; 281 if (isMultiSelect) { 282 style |= LBS_MULTIPLESEL; 283 } else { 284 style &= ~LBS_MULTIPLESEL; 285 } 286 DWORD exStyle = ::GetWindowLong(GetListHandle(), GWL_EXSTYLE); 287 288 jobject peer = GetPeer(env); 289 290 UnsubclassHWND(); 291 AwtToolkit::DestroyComponentHWND(m_hwnd); 292 CreateHWnd(env, L"", style, exStyle, 293 rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 294 parentHWnd, 295 NULL, 296 ::GetSysColor(COLOR_WINDOWTEXT), 297 ::GetSysColor(COLOR_WINDOW), 298 peer); 299 300 SendListMessage(WM_SETFONT, (WPARAM)font, (LPARAM)FALSE); 301 SendListMessage(LB_SETITEMHEIGHT, 0, MAKELPARAM(itemHeight, 0)); 302 SendListMessage(LB_RESETCONTENT); 303 for (i = 0; i < nCount; i++) { 304 InsertString(i, strings[i]); 305 delete [] strings[i]; 306 } 307 delete[] strings; 308 if (toSelect != -1) { 309 Select(toSelect); 310 } 311 312 AdjustHorizontalScrollbar(); 313 } 314 315 /* 316 * There currently is no good place to cache java.awt.Dimension field 317 * ids. If this method gets called a lot, one such place should be found. 318 * -- br 07/18/97. 319 */ 320 jobject AwtList::PreferredItemSize(JNIEnv *env) 321 { 322 jobject peer = GetPeer(env); 323 jobject dimension = JNU_CallMethodByName(env, NULL, peer, "preferredSize", 324 "(I)Ljava/awt/Dimension;", 325 1).l; 326 327 DASSERT(!safe_ExceptionOccurred(env)); 328 if (dimension == NULL) { 329 return NULL; 330 } 331 /* This size is too big for each item height. */ 332 (env)->SetIntField(dimension, AwtDimension::heightID, GetFontHeight(env)); 333 334 return dimension; 335 } 336 337 // Every time something gets added to the list, we increase the max width 338 // of items that have ever been added. If it surpasses the width of the 339 // listbox, we show the scrollbar. When things get deleted, we shrink 340 // the scroll region back down and hide the scrollbar, if needed. 341 void AwtList::AdjustHorizontalScrollbar() 342 { 343 // The border width is added to the horizontal extent to ensure that we 344 // can view all of the text when we move the horz. scrollbar to the end. 345 int cxBorders = GetSystemMetrics( SM_CXBORDER ) * 2; 346 RECT rect; 347 VERIFY(::GetClientRect(GetListHandle(), &rect)); 348 LRESULT iHorzExt = SendListMessage(LB_GETHORIZONTALEXTENT, 0, 0L ) - cxBorders; 349 if ( (m_nMaxWidth > rect.left) // if strings wider than listbox 350 || (iHorzExt != m_nMaxWidth) ) // or scrollbar not needed anymore. 351 { 352 SendListMessage(LB_SETHORIZONTALEXTENT, m_nMaxWidth + cxBorders, 0L); 353 } 354 } 355 356 // This function goes through all strings in the list to find the width, 357 // in pixels, of the longest string in the list. 358 void AwtList::UpdateMaxItemWidth() 359 { 360 m_nMaxWidth = 0; 361 362 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 363 if (env->EnsureLocalCapacity(2) < 0) 364 return; 365 366 HDC hDC = ::GetDC(GetHWnd()); 367 368 jobject self = GetPeer(env); 369 DASSERT(self); 370 371 /* target is java.awt.List */ 372 jobject target = env->GetObjectField(self, AwtObject::targetID); 373 jobject font = GET_FONT(target, self); 374 375 int nCount = GetCount(); 376 for ( int i=0; i < nCount; i++ ) 377 { 378 jstring jstr = GetItemString( env, target, i ); 379 SIZE size = AwtFont::getMFStringSize( hDC, font, jstr ); 380 if ( size.cx > m_nMaxWidth ) 381 m_nMaxWidth = size.cx; 382 env->DeleteLocalRef( jstr ); 383 } 384 385 // free up the shared DC and release local refs 386 ::ReleaseDC(GetHWnd(), hDC); 387 env->DeleteLocalRef( target ); 388 env->DeleteLocalRef( font ); 389 390 // Now adjust the horizontal scrollbar extent 391 AdjustHorizontalScrollbar(); 392 } 393 394 MsgRouting 395 AwtList::WmSize(UINT type, int w, int h) 396 { 397 AdjustHorizontalScrollbar(); 398 return AwtComponent::WmSize(type, w, h); 399 } 400 401 MsgRouting 402 AwtList::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo) 403 { 404 AwtComponent::DrawListItem((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), drawInfo); 405 return mrConsume; 406 } 407 408 MsgRouting 409 AwtList::OwnerMeasureItem(UINT /*ctrlId*/, MEASUREITEMSTRUCT& measureInfo) 410 { 411 AwtComponent::MeasureListItem((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), measureInfo); 412 return mrConsume; 413 } 414 415 MsgRouting 416 AwtList::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) 417 { 418 if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) { 419 retVal = HTCLIENT; 420 return mrConsume; 421 } 422 return AwtComponent::WmNcHitTest(x, y, retVal); 423 } 424 425 MsgRouting 426 AwtList::WmMouseUp(UINT flags, int x, int y, int button) 427 { 428 MsgRouting result = mrDoDefault; 429 // if this list is in the modal blocked window, this message should be consumed, 430 // however AwtComponent::WmMouseUp must be called anyway 431 if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) { 432 result = mrConsume; 433 } else { 434 if (button == LEFT_BUTTON) { 435 WmCommand(0, GetListHandle(), LBN_SELCHANGE); 436 } 437 } 438 MsgRouting compResult = AwtComponent::WmMouseUp(flags, x, y, button); 439 return (result == mrConsume) ? result : compResult; 440 } 441 442 MsgRouting 443 AwtList::WmMouseDown(UINT flags, int x, int y, int button) 444 { 445 MsgRouting mrResult = AwtComponent::WmMouseDown(flags, x, y, button); 446 447 if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) 448 { 449 return mrConsume; 450 } 451 452 /* 453 * As we consume WM_LBUTONDOWN the list won't trigger ActionEvent by double click. 454 * We trigger it ourselves. (see also 6240202) 455 */ 456 int clickCount = GetClickCount(); 457 if (button == LEFT_BUTTON && clickCount >= 2 && clickCount % 2 == 0) { 458 WmCommand(0, GetListHandle(), LBN_DBLCLK); 459 } 460 return mrResult; 461 } 462 463 MsgRouting 464 AwtList::WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, HBRUSH& retBrush) 465 { 466 DASSERT(ctlColor == CTLCOLOR_LISTBOX); 467 DASSERT(hCtrl == GetListHandle()); 468 ::SetBkColor(hDC, GetBackgroundColor()); 469 ::SetTextColor(hDC, GetColor()); 470 retBrush = GetBackgroundBrush(); 471 return mrConsume; 472 } 473 474 BOOL AwtList::IsFocusingMouseMessage(MSG *pMsg) 475 { 476 return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK; 477 } 478 479 MsgRouting AwtList::HandleEvent(MSG *msg, BOOL synthetic) 480 { 481 if (IsFocusingMouseMessage(msg)) { 482 LONG item = static_cast<LONG>(SendListMessage(LB_ITEMFROMPOINT, 0, msg->lParam)); 483 if (item != LB_ERR) { 484 if (isMultiSelect) { 485 if (IsItemSelected(item)) { 486 Deselect(item); 487 } else { 488 Select(item); 489 } 490 } else { 491 Select(item); 492 } 493 } 494 delete msg; 495 return mrConsume; 496 } 497 if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN) { 498 WmNotify(LBN_DBLCLK); 499 } 500 return AwtComponent::HandleEvent(msg, synthetic); 501 } 502 503 // Fix for 4665745. 504 // Override WmPrint to catch when the list control (not wrapper) should 505 // operate WM_PRINT to be compatible with the "smooth scrolling" feature. 506 MsgRouting AwtList::WmPrint(HDC hDC, LPARAM flags) 507 { 508 if (!isWrapperPrint && 509 (flags & PRF_CLIENT) && 510 (GetStyleEx() & WS_EX_CLIENTEDGE)) 511 { 512 int nOriginalDC = ::SaveDC(hDC); 513 DASSERT(nOriginalDC != 0); 514 // Save a copy of the DC for WmPrintClient 515 VERIFY(::SaveDC(hDC)); 516 DefWindowProc(WM_PRINT, (WPARAM) hDC, 517 (flags & (PRF_CLIENT | PRF_CHECKVISIBLE | PRF_ERASEBKGND))); 518 VERIFY(::RestoreDC(hDC, nOriginalDC)); 519 520 flags &= ~PRF_CLIENT; 521 } 522 523 return AwtComponent::WmPrint(hDC, flags); 524 } 525 526 MsgRouting 527 AwtList::WmNotify(UINT notifyCode) 528 { 529 if (notifyCode == LBN_SELCHANGE || notifyCode == LBN_DBLCLK) { 530 /* Fixed an asserion failure when clicking on an empty List. */ 531 int nCurrentSelection = SendListMessage(LB_GETCURSEL); 532 if (nCurrentSelection != LB_ERR && GetCount() > 0) { 533 if (notifyCode == LBN_SELCHANGE) { 534 DoCallback("handleListChanged", "(I)V", nCurrentSelection); 535 } 536 else if (notifyCode == LBN_DBLCLK) { 537 DoCallback("handleAction", "(IJI)V", nCurrentSelection, 538 ::JVM_CurrentTimeMillis(NULL, 0), 539 (jint)AwtComponent::GetJavaModifiers()); 540 } 541 } 542 } 543 return mrDoDefault; 544 } 545 546 BOOL AwtList::InheritsNativeMouseWheelBehavior() {return true;} 547 548 jint AwtList::_GetMaxWidth(void *param) 549 { 550 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 551 552 jobject self = (jobject)param; 553 554 jint result = 0; 555 AwtList *l = NULL; 556 557 PDATA pData; 558 JNI_CHECK_PEER_GOTO(self, ret); 559 l = (AwtList *)pData; 560 if (::IsWindow(l->GetHWnd())) 561 { 562 result = l->GetMaxWidth(); 563 } 564 ret: 565 env->DeleteGlobalRef(self); 566 567 return result; 568 } 569 570 void AwtList::_UpdateMaxItemWidth(void *param) 571 { 572 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 573 574 jobject self = (jobject)param; 575 576 AwtList *l = NULL; 577 578 PDATA pData; 579 JNI_CHECK_PEER_GOTO(self, ret); 580 l = (AwtList *)pData; 581 if (::IsWindow(l->GetHWnd())) 582 { 583 l->UpdateMaxItemWidth(); 584 } 585 ret: 586 env->DeleteGlobalRef(self); 587 } 588 589 void AwtList::_AddItems(void *param) 590 { 591 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 592 593 AddItemsStruct *ais = (AddItemsStruct *)param; 594 jobject self = ais->list; 595 jobjectArray items = ais->items; 596 jint index = ais->index; 597 jint width = ais->width; 598 599 int badAlloc = 0; 600 AwtList *l = NULL; 601 602 PDATA pData; 603 JNI_CHECK_PEER_GOTO(self, ret); 604 JNI_CHECK_NULL_GOTO(items, "null items", ret); 605 l = (AwtList*)pData; 606 if (::IsWindow(l->GetHWnd())) 607 { 608 int itemCount = env->GetArrayLength(items); 609 if (itemCount > 0) 610 { 611 AwtList* l = (AwtList*)pData; 612 l->SendListMessage(WM_SETREDRAW, (WPARAM)FALSE, 0); 613 for (jsize i=0; i < itemCount; i++) 614 { 615 LPTSTR itemPtr = NULL; 616 jstring item = (jstring)env->GetObjectArrayElement(items, i); 617 if (env->ExceptionCheck()) goto ret; 618 if (item == NULL) goto next_item; 619 itemPtr = (LPTSTR)JNU_GetStringPlatformChars(env, item, 0); 620 if (itemPtr == NULL) 621 { 622 badAlloc = 1; 623 } 624 else 625 { 626 l->InsertString(index+i, itemPtr); 627 JNU_ReleaseStringPlatformChars(env, item, itemPtr); 628 } 629 env->DeleteLocalRef(item); 630 next_item: 631 ; 632 } 633 l->SendListMessage(WM_SETREDRAW, (WPARAM)TRUE, 0); 634 l->InvalidateList(NULL, TRUE); 635 l->CheckMaxWidth(width); 636 } 637 } 638 ret: 639 env->DeleteGlobalRef(self); 640 env->DeleteGlobalRef(items); 641 642 delete ais; 643 644 if (badAlloc) 645 { 646 throw std::bad_alloc(); 647 } 648 } 649 650 void AwtList::_DelItems(void *param) 651 { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 652 653 DelItemsStruct *dis = (DelItemsStruct *)param; 654 jobject self = dis->list; 655 jint start = dis->start; 656 jint end = dis->end; 657 658 AwtList *l = NULL; 659 660 PDATA pData; 661 JNI_CHECK_PEER_GOTO(self, ret); 662 l = (AwtList*)pData; 663 if (::IsWindow(l->GetHWnd())) 664 { 665 int count = l->GetCount(); 666 667 if (start == 0 && end == count) 668 { 669 l->SendListMessage(LB_RESETCONTENT); 670 } 671 else 672 { 673 for (int i = start; i <= end; i++) 674 { 675 l->SendListMessage(LB_DELETESTRING, start); 676 } 677 } 678 679 l->UpdateMaxItemWidth(); 680 } 681 ret: 682 env->DeleteGlobalRef(self); 683 684 delete dis; 685 } 686 687 void AwtList::_Select(void *param) 688 { 689 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 690 691 SelectElementStruct *ses = (SelectElementStruct *)param; 692 jobject self = ses->list; 693 jint index = ses->index; 694 695 AwtList *l = NULL; 696 697 PDATA pData; 698 JNI_CHECK_PEER_GOTO(self, ret); 699 l = (AwtList*)pData; 700 if (::IsWindow(l->GetHWnd())) 701 { 702 l->Select(index); 703 } 704 ret: 705 env->DeleteGlobalRef(self); 706 707 delete ses; 708 } 709 710 void AwtList::_Deselect(void *param) 711 { 712 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 713 714 SelectElementStruct *ses = (SelectElementStruct *)param; 715 jobject self = ses->list; 716 jint index = ses->index; 717 718 AwtList *l = NULL; 719 720 PDATA pData; 721 JNI_CHECK_PEER_GOTO(self, ret); 722 l = (AwtList*)pData; 723 if (::IsWindow(l->GetHWnd())) 724 { 725 l->Deselect(index); 726 } 727 ret: 728 env->DeleteGlobalRef(self); 729 730 delete ses; 731 } 732 733 void AwtList::_MakeVisible(void *param) 734 { 735 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 736 737 SelectElementStruct *ses = (SelectElementStruct *)param; 738 jobject self = ses->list; 739 jint index = ses->index; 740 741 AwtList *l = NULL; 742 743 PDATA pData; 744 JNI_CHECK_PEER_GOTO(self, ret); 745 l = (AwtList*)pData; 746 if (::IsWindow(l->GetHWnd())) 747 { 748 l->SendListMessage(LB_SETTOPINDEX, index); 749 } 750 ret: 751 env->DeleteGlobalRef(self); 752 753 delete ses; 754 } 755 756 jboolean AwtList::_IsSelected(void *param) 757 { 758 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 759 760 SelectElementStruct *ses = (SelectElementStruct *)param; 761 jobject self = ses->list; 762 jint index = ses->index; 763 764 jboolean result = JNI_FALSE; 765 AwtList *l = NULL; 766 767 PDATA pData; 768 JNI_CHECK_PEER_GOTO(self, ret); 769 l = (AwtList*)pData; 770 if (::IsWindow(l->GetHWnd())) 771 { 772 result = l->IsItemSelected(index); 773 } 774 ret: 775 env->DeleteGlobalRef(self); 776 777 delete ses; 778 779 return result; 780 } 781 782 void AwtList::_SetMultipleSelections(void *param) 783 { 784 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 785 786 SetMultipleSelectionsStruct *sms = (SetMultipleSelectionsStruct *)param; 787 jobject self = sms->list; 788 jboolean on = sms->on; 789 790 AwtList *l = NULL; 791 792 PDATA pData; 793 JNI_CHECK_PEER_GOTO(self, ret); 794 l = (AwtList*)pData; 795 if (::IsWindow(l->GetHWnd())) 796 { 797 AwtToolkit::GetInstance().SendMessage(WM_AWT_LIST_SETMULTISELECT, 798 (WPARAM)self, on); 799 } 800 ret: 801 env->DeleteGlobalRef(self); 802 803 delete sms; 804 } 805 806 /************************************************************************ 807 * WListPeer native methods 808 * 809 * This class seems to have numerous bugs in it, but they are all bugs 810 * which were present before conversion to JNI. -br. 811 */ 812 813 extern "C" { 814 815 /* 816 * Class: sun_awt_windows_WListPeer 817 * Method: getMaxWidth 818 * Signature: ()I 819 */ 820 JNIEXPORT jint JNICALL 821 Java_sun_awt_windows_WListPeer_getMaxWidth(JNIEnv *env, jobject self) 822 { 823 TRY; 824 825 jobject selfGlobalRef = env->NewGlobalRef(self); 826 827 return (jint)AwtToolkit::GetInstance().SyncCall( 828 (void *(*)(void *))AwtList::_GetMaxWidth, 829 (void *)selfGlobalRef); 830 // selfGlobalRef is deleted in _GetMaxWidth 831 832 CATCH_BAD_ALLOC_RET(0); 833 } 834 835 /* 836 * Class: sun_awt_windows_WListPeer 837 * Method: updateMaxItemWidth 838 * Signature: ()V 839 */ 840 JNIEXPORT void JNICALL 841 Java_sun_awt_windows_WListPeer_updateMaxItemWidth(JNIEnv *env, jobject self) 842 { 843 TRY; 844 845 jobject selfGlobalRef = env->NewGlobalRef(self); 846 847 AwtToolkit::GetInstance().SyncCall(AwtList::_UpdateMaxItemWidth, 848 (void *)selfGlobalRef); 849 // selfGlobalRef is deleted in _UpdateMaxItemWidth 850 851 CATCH_BAD_ALLOC; 852 } 853 854 /* 855 * Class: sun_awt_windows_WListPeer 856 * Method: addItems 857 * Signature: ([Ljava/lang/String;II)V 858 */ 859 JNIEXPORT void JNICALL 860 Java_sun_awt_windows_WListPeer_addItems(JNIEnv *env, jobject self, 861 jobjectArray items, jint index, jint width) 862 { 863 TRY; 864 865 AddItemsStruct *ais = new AddItemsStruct; 866 ais->list = env->NewGlobalRef(self); 867 ais->items = (jobjectArray)env->NewGlobalRef(items); 868 ais->index = index; 869 ais->width = width; 870 871 AwtToolkit::GetInstance().SyncCall(AwtList::_AddItems, ais); 872 // global refs and ais are deleted in _AddItems() 873 874 CATCH_BAD_ALLOC; 875 } 876 877 /* 878 * Class: sun_awt_windows_WListPeer 879 * Method: delItems 880 * Signature: (II)V 881 */ 882 JNIEXPORT void JNICALL 883 Java_sun_awt_windows_WListPeer_delItems(JNIEnv *env, jobject self, 884 jint start, jint end) 885 { 886 TRY; 887 888 DelItemsStruct *dis = new DelItemsStruct; 889 dis->list = env->NewGlobalRef(self); 890 dis->start = start; 891 dis->end = end; 892 893 AwtToolkit::GetInstance().SyncCall(AwtList::_DelItems, dis); 894 // global ref and dis are deleted in _DelItems 895 896 CATCH_BAD_ALLOC; 897 } 898 899 /* 900 * Class: sun_awt_windows_WListPeer 901 * Method: select 902 * Signature: (I)V 903 */ 904 JNIEXPORT void JNICALL 905 Java_sun_awt_windows_WListPeer_select(JNIEnv *env, jobject self, 906 jint pos) 907 { 908 TRY; 909 910 SelectElementStruct *ses = new SelectElementStruct; 911 ses->list = env->NewGlobalRef(self); 912 ses->index = pos; 913 914 AwtToolkit::GetInstance().SyncCall(AwtList::_Select, ses); 915 // global ref and ses are deleted in _Select 916 917 CATCH_BAD_ALLOC; 918 } 919 920 /* 921 * Class: sun_awt_windows_WListPeer 922 * Method: deselect 923 * Signature: (I)V 924 */ 925 JNIEXPORT void JNICALL 926 Java_sun_awt_windows_WListPeer_deselect(JNIEnv *env, jobject self, 927 jint pos) 928 { 929 TRY; 930 931 PDATA pData; 932 JNI_CHECK_PEER_RETURN(self); 933 934 SelectElementStruct *ses = new SelectElementStruct; 935 ses->list = env->NewGlobalRef(self); 936 ses->index = pos; 937 938 AwtToolkit::GetInstance().SyncCall(AwtList::_Deselect, ses); 939 // global ref and ses are deleted in _Deselect 940 941 CATCH_BAD_ALLOC; 942 } 943 944 /* 945 * Class: sun_awt_windows_WListPeer 946 * Method: makeVisible 947 * Signature: (I)V 948 */ 949 JNIEXPORT void JNICALL 950 Java_sun_awt_windows_WListPeer_makeVisible(JNIEnv *env, jobject self, 951 jint pos) 952 { 953 TRY; 954 955 SelectElementStruct *ses = new SelectElementStruct; 956 ses->list = env->NewGlobalRef(self); 957 ses->index = pos; 958 959 AwtToolkit::GetInstance().SyncCall(AwtList::_MakeVisible, ses); 960 // global ref and ses are deleted in _MakeVisible 961 962 CATCH_BAD_ALLOC; 963 } 964 965 /* 966 * Class: sun_awt_windows_WListPeer 967 * Method: setMultipleSelections 968 * Signature: (Z)V 969 */ 970 JNIEXPORT void JNICALL 971 Java_sun_awt_windows_WListPeer_setMultipleSelections(JNIEnv *env, jobject self, 972 jboolean on) 973 { 974 TRY; 975 976 SetMultipleSelectionsStruct *sms = new SetMultipleSelectionsStruct; 977 sms->list = env->NewGlobalRef(self); 978 sms->on = on; 979 980 AwtToolkit::GetInstance().SyncCall(AwtList::_SetMultipleSelections, sms); 981 // global ref and sms are deleted in AwtList::_SetMultipleSelections 982 983 CATCH_BAD_ALLOC; 984 } 985 986 /* 987 * Class: sun_awt_windows_WListPeer 988 * Method: create 989 * Signature: (Lsun/awt/windows/WComponentPeer;)V 990 */ 991 JNIEXPORT void JNICALL 992 Java_sun_awt_windows_WListPeer_create(JNIEnv *env, jobject self, 993 jobject parent) 994 { 995 TRY; 996 997 PDATA pData; 998 JNI_CHECK_PEER_RETURN(parent); 999 AwtToolkit::CreateComponent(self, parent, 1000 (AwtToolkit::ComponentFactory)AwtList::Create); 1001 JNI_CHECK_PEER_CREATION_RETURN(self); 1002 1003 CATCH_BAD_ALLOC; 1004 } 1005 1006 /* 1007 * Class: sun_awt_windows_WListPeer 1008 * Method: isSelected 1009 * Signature: (I)Z 1010 */ 1011 JNIEXPORT jboolean JNICALL 1012 Java_sun_awt_windows_WListPeer_isSelected(JNIEnv *env, jobject self, 1013 jint index) 1014 { 1015 TRY; 1016 1017 SelectElementStruct *ses = new SelectElementStruct; 1018 ses->list = env->NewGlobalRef(self); 1019 ses->index = index; 1020 1021 return (jboolean)AwtToolkit::GetInstance().SyncCall( 1022 (void *(*)(void *))AwtList::_IsSelected, ses); 1023 // global ref and ses are deleted in _IsSelected 1024 1025 CATCH_BAD_ALLOC_RET(FALSE); 1026 } 1027 1028 } /* extern "C" */