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