1 /* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
2 Copyright (C) 2006 and later, Cockos, Inc.
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
21 This file provides basic windows APIs for handling windows, as well as the stubs to enable swell-dlggen to work.
26 #ifndef SWELL_PROVIDED_BY_APP
28 #import <Cocoa/Cocoa.h>
29 #import <objc/objc-runtime.h>
32 #include "../ptrlist.h"
34 #include "../wdlcstring.h"
36 #include "swell-dlggen.h"
38 #define SWELL_INTERNAL_MERGESORT_IMPL
39 #define SWELL_INTERNAL_HTREEITEM_IMPL
40 #include "swell-internal.h"
42 static bool SWELL_NeedModernListViewHacks()
47 // only needed on 32 bit yosemite as of 10.10.3, but who knows when it will be necessary elsewhere
48 return SWELL_GetOSXVersion() >= 0x10a0;
52 static LRESULT sendSwellMessage(id obj, UINT uMsg, WPARAM wParam, LPARAM lParam)
54 if (obj && [obj respondsToSelector:@selector(onSwellMessage:p1:p2:)])
55 return [(SWELL_hwndChild *)obj onSwellMessage:uMsg p1:wParam p2:lParam];
58 static void InvalidateSuperViews(NSView *view);
59 #define STANDARD_CONTROL_NEEDSDISPLAY_IMPL \
60 - (void)setNeedsDisplay:(BOOL)flag \
62 [super setNeedsDisplay:flag]; \
63 if (flag) InvalidateSuperViews(self); \
65 - (void)setNeedsDisplayInRect:(NSRect)rect \
67 [super setNeedsDisplayInRect:rect]; \
68 InvalidateSuperViews(self); \
72 int g_swell_want_nice_style = 1;
73 static void *SWELL_CStringToCFString_FilterPrefix(const char *str)
76 while (str[c] && str[c] != '&' && c++<1024);
77 if (!str[c] || c>=1024 || strlen(str)>=1024) return SWELL_CStringToCFString(str);
88 return SWELL_CStringToCFString(buf);
92 static int _nsStringSearchProc(const void *_a, const void *_b)
94 NSString *a=(NSString *)_a;
95 NSString *b = (NSString *)_b;
96 return (int)[a compare:b];
98 static int _nsMenuSearchProc(const void *_a, const void *_b)
100 NSString *a=(NSString *)_a;
101 NSMenuItem *b = (NSMenuItem *)_b;
102 return (int)[a compare:[b title]];
104 static int _listviewrowSearchFunc(const void *_a, const void *_b, const void *ctx)
106 const char *a = (const char *)_a;
107 SWELL_ListView_Row *row = (SWELL_ListView_Row *)_b;
109 if (!row || !(b=row->m_vals.Get(0))) b="";
112 static int _listviewrowSearchFunc2(const void *_a, const void *_b, const void *ctx)
114 const char *a = (const char *)_a;
115 SWELL_ListView_Row *row = (SWELL_ListView_Row *)_b;
117 if (!row || !(b=row->m_vals.Get(0))) b="";
121 // modified bsearch: returns place item SHOULD be in if it's not found
122 static NSInteger arr_bsearch_mod(void *key, NSArray *arr, int (*compar)(const void *, const void *))
124 const NSInteger nmemb = [arr count];
125 NSInteger p,lim,base=0;
127 for (lim = nmemb; lim != 0; lim >>= 1) {
128 p = base + (lim >> 1);
129 int cmp = compar(key, [arr objectAtIndex:p]);
130 if (cmp == 0) return (p);
131 if (cmp > 0) { /* key > p: move right */
132 // check to see if key is less than p+1, if it is, we're done
134 if (base >= nmemb || compar(key,[arr objectAtIndex:base])<=0) return base;
136 } /* else move left */
142 template<class T> static int ptrlist_bsearch_mod(void *key, WDL_PtrList<T> *arr, int (*compar)(const void *, const void *, const void *ctx), void *ctx)
144 const int nmemb = arr->GetSize();
147 for (lim = nmemb; lim != 0; lim >>= 1) {
148 p = base + (lim >> 1);
149 int cmp = compar(key, arr->Get(p),ctx);
150 if (cmp == 0) return (p);
151 if (cmp > 0) { /* key > p: move right */
152 // check to see if key is less than p+1, if it is, we're done
154 if (base >= nmemb || compar(key,arr->Get(base),ctx)<=0) return base;
156 } /* else move left */
162 @implementation SWELL_TabView
163 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
165 -(void)setNotificationWindow:(id)dest
169 -(id)getNotificationWindow
177 -(void) setTag:(NSInteger)tag
181 - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem
185 NMHDR nm={(HWND)self,(UINT_PTR)[self tag],TCN_SELCHANGE};
186 SendMessage((HWND)m_dest,WM_NOTIFY,nm.idFrom,(LPARAM)&nm);
192 @implementation SWELL_ProgressView
193 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
199 -(void) setTag:(NSInteger)tag
203 -(LRESULT)onSwellMessage:(UINT)msg p1:(WPARAM)wParam p2:(LPARAM)lParam
205 if (msg == PBM_SETRANGE)
207 [self setMinValue:LOWORD(lParam)];
208 [self setMaxValue:HIWORD(lParam)];
210 else if (msg==PBM_SETPOS)
212 [self setDoubleValue:(double)wParam];
213 [self stopAnimation:self];
215 else if (msg==PBM_DELTAPOS)
217 [self incrementBy:(double)wParam];
224 @implementation SWELL_ListViewCell
225 -(NSColor *)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
227 if ([controlView isKindOfClass:[SWELL_ListView class]] && ((SWELL_ListView *)controlView)->m_selColors) return nil;
228 if ([controlView isKindOfClass:[SWELL_TreeView class]] && ((SWELL_TreeView *)controlView)->m_selColors) return nil;
229 return [super highlightColorWithFrame:cellFrame inView:controlView];
233 @implementation SWELL_StatusCell
236 if ((self=[super initTextCell:@""]))
242 -(void)setStatusImage:(NSImage *)img
246 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
250 // [controlView lockFocus];
251 int w=wdl_min(cellFrame.size.width, cellFrame.size.height);
252 [status drawInRect:NSMakeRect(cellFrame.origin.x,cellFrame.origin.y,w,cellFrame.size.height) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
253 // [controlView unlockFocus];
255 cellFrame.origin.x += cellFrame.size.height + 2.0;
256 cellFrame.size.width -= cellFrame.size.height + 2.0;
257 [super drawWithFrame:cellFrame inView:controlView];
260 -(NSColor *)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
262 if ([controlView isKindOfClass:[SWELL_ListView class]] && ((SWELL_ListView *)controlView)->m_selColors) return nil;
263 return [super highlightColorWithFrame:cellFrame inView:controlView];
268 @implementation SWELL_TreeView
269 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
273 if ((self = [super init]))
275 m_fakerightmouse=false;
276 m_items=new WDL_PtrList<HTREEITEM__>;
284 if (m_items) m_items->Empty(true);
288 [m_selColors release];
292 -(bool) findItem:(HTREEITEM)item parOut:(HTREEITEM__ **)par idxOut:(int *)idx
294 if (!m_items||!item) return false;
295 int x=m_items->Find((HTREEITEM__*)item);
302 for (x = 0; x < m_items->GetSize(); x++)
304 if (m_items->Get(x)->FindItem(item,par,idx)) return true;
310 -(NSInteger) outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
312 if (item == nil) return m_items ? m_items->GetSize() : 0;
313 return ((HTREEITEM__*)[item getValue])->m_children.GetSize();
316 - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
318 if (item==nil) return YES;
319 HTREEITEM__ *it=(HTREEITEM__ *)[item getValue];
321 return it && it->m_haschildren;
324 - (id)outlineView:(NSOutlineView *)outlineView
325 child:(NSInteger)index
328 HTREEITEM__ *row=item ? ((HTREEITEM__*)[item getValue])->m_children.Get(index) : m_items ? m_items->Get(index) : 0;
330 return (id)(row ? row->m_dh : NULL);
333 - (id)outlineView:(NSOutlineView *)outlineView
334 objectValueForTableColumn:(NSTableColumn *)tableColumn
337 if (!item) return @"";
338 HTREEITEM__ *it=(HTREEITEM__ *)[item getValue];
340 if (!it || !it->m_value) return @"";
342 NSString *str=(NSString *)SWELL_CStringToCFString(it->m_value);
344 return [str autorelease];
349 -(void)mouseDown:(NSEvent *)theEvent
351 if (([theEvent modifierFlags] & NSControlKeyMask) && IsRightClickEmulateEnabled())
358 NMCLICK nmlv={{(HWND)self,(UINT_PTR)[self tag], NM_CLICK},};
359 SendMessage((HWND)[self target],WM_NOTIFY,nmlv.hdr.idFrom,(LPARAM)&nmlv);
362 [super mouseDown:theEvent];
366 -(void)mouseDragged:(NSEvent *)theEvent
370 -(void)mouseUp:(NSEvent *)theEvent
372 if (m_fakerightmouse||([theEvent modifierFlags] & NSControlKeyMask)) [self rightMouseUp:theEvent];
373 else [super mouseUp:theEvent];
375 - (void)rightMouseUp:(NSEvent *)theEvent
377 bool wantContext=true;
379 NMCLICK nmlv={{(HWND)self,(UINT_PTR)[self tag], NM_RCLICK},};
380 if (SendMessage((HWND)[self target],WM_NOTIFY,nmlv.hdr.idFrom,(LPARAM)&nmlv)) wantContext=false;
386 SendMessage((HWND)[self target],WM_CONTEXTMENU,(WPARAM)self,(p.x&0xffff)|(p.y<<16));
392 - (void)highlightSelectionInClipRect:(NSRect)theClipRect
396 int a = GetFocus() == (HWND)self ? 0 : 2;
397 if ([m_selColors count] >= a)
399 NSColor *c=[m_selColors objectAtIndex:a];
402 // calculate rect of selected items, combine with theClipRect, and fill these areas with our background (phew!)
404 NSInteger x = [self selectedRow];
407 NSRect r = [self rectOfRow:x];
408 r = NSIntersectionRect(r,theClipRect);
409 if (r.size.height>0 && r.size.width>0)
419 return [super highlightSelectionInClipRect:theClipRect];
431 @implementation SWELL_ListView
432 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
434 -(LONG)getSwellStyle { return style; }
436 -(void)setSwellStyle:(LONG)st
438 bool hdrchg= ((style&LVS_NOCOLUMNHEADER) != (st&LVS_NOCOLUMNHEADER));
440 if ((style&LVS_REPORT) && hdrchg)
442 // todo some crap with NSTableView::setHeaderView, but it's complicated
448 if ((self = [super init]))
453 m_status_imagelist_type=-1;
454 m_status_imagelist=0;
455 m_leftmousemovecnt=0;
456 m_fakerightmouse=false;
459 m_last_shift_clicked_item = m_last_plainly_clicked_item=-1;
462 m_start_item_clickmode=0; // 0=clicked item, 1=clicked image, &2=sent drag message, &4=quickclick mode
463 m_cols = new WDL_PtrList<NSTableColumn>;
464 m_items=new WDL_PtrList<SWELL_ListView_Row>;
470 if (m_items) m_items->Empty(true);
476 [m_selColors release];
480 -(int)getColumnPos:(int)idx // get current position of column that was originally at idx
485 NSTableColumn* col=m_cols->Get(idx);
488 NSArray* arr=[self tableColumns];
491 pos=(int)[arr indexOfObject:col];
498 - (void)highlightSelectionInClipRect:(NSRect)theClipRect
502 int a = GetFocus() == (HWND)self ? 0 : 2;
503 if ([m_selColors count] >= a)
505 NSColor *c=[m_selColors objectAtIndex:a];
508 // calculate rect of selected items, combine with theClipRect, and fill these areas with our background (phew!)
509 bool needfillset=true;
510 NSInteger x = [self rowAtPoint:NSMakePoint(0,theClipRect.origin.y)];
512 const NSInteger n = [self numberOfRows];
515 NSRect r = [self rectOfRow:x];
516 if (r.origin.y >= theClipRect.origin.y + theClipRect.size.height) break;
518 if ([self isRowSelected:x])
520 r = NSIntersectionRect(r,theClipRect);
521 if (r.size.height>0 && r.size.width>0)
523 if (needfillset) { needfillset=false; [c setFill]; }
532 return [super highlightSelectionInClipRect:theClipRect];
534 -(int)getColumnIdx:(int)pos // get original index of column that is currently at position
537 NSArray* arr=[self tableColumns];
538 if (arr && pos>=0 && pos < [arr count])
540 NSTableColumn* col=[arr objectAtIndex:pos];
543 idx=m_cols->Find(col);
549 -(NSInteger)columnAtPoint:(NSPoint)pt
551 int pos=(int)[super columnAtPoint:pt];
552 return (NSInteger) [self getColumnIdx:pos];
556 - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
558 return (!m_lbMode && (style & LVS_OWNERDATA)) ? ownermode_cnt : (m_items ? m_items->GetSize():0);
561 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
566 if (!m_lbMode && (style & LVS_OWNERDATA))
568 HWND tgt=(HWND)[self target];
571 NMLVDISPINFO nm={{(HWND)self, (UINT_PTR)[self tag], LVN_GETDISPINFO}};
572 nm.item.mask=LVIF_TEXT;
573 if (m_status_imagelist_type==LVSIL_STATE) nm.item.mask |= LVIF_STATE;
574 else if (m_status_imagelist_type == LVSIL_SMALL) nm.item.mask |= LVIF_IMAGE;
576 nm.item.iItem=(int)rowIndex;
577 nm.item.iSubItem=m_cols->Find(aTableColumn);
579 nm.item.cchTextMax=sizeof(buf)-1;
581 SendMessage(tgt,WM_NOTIFY,nm.hdr.idFrom,(LPARAM)&nm);
583 if (m_status_imagelist_type == LVSIL_STATE) image_idx=(nm.item.state>>16)&0xff;
584 else if (m_status_imagelist_type == LVSIL_SMALL) image_idx = nm.item.iImage + 1;
585 str=(NSString *)SWELL_CStringToCFString(nm.item.pszText);
590 SWELL_ListView_Row *r=0;
591 if (m_items && m_cols && (r=m_items->Get(rowIndex)))
593 p=r->m_vals.Get(m_cols->Find(aTableColumn));
594 if (m_status_imagelist_type == LVSIL_STATE || m_status_imagelist_type == LVSIL_SMALL)
596 image_idx=r->m_imageidx;
600 str=(NSString *)SWELL_CStringToCFString(p);
602 if (style & LBS_OWNERDRAWFIXED)
604 SWELL_ODListViewCell *cell=[aTableColumn dataCell];
605 if ([cell isKindOfClass:[SWELL_ODListViewCell class]]) [cell setItemIdx:(int)rowIndex];
609 if (!m_lbMode && m_status_imagelist)
611 SWELL_StatusCell *cell=(SWELL_StatusCell*)[aTableColumn dataCell];
612 if ([cell isKindOfClass:[SWELL_StatusCell class]])
614 HICON icon=m_status_imagelist->Get(image_idx-1);
616 if (icon) img=(NSImage *)GetNSImageFromHICON(icon);
617 [cell setStatusImage:img];
621 return [str autorelease];
626 -(void)mouseDown:(NSEvent *)theEvent
628 if (([theEvent modifierFlags] & NSControlKeyMask) && IsRightClickEmulateEnabled())
636 if ([theEvent clickCount]>1 && SWELL_NeedModernListViewHacks())
638 [super mouseDown:theEvent];
641 m_leftmousemovecnt=0;
644 NSPoint pt=[theEvent locationInWindow];
645 pt=[self convertPoint:pt fromView:nil];
646 m_start_item=(int)[self rowAtPoint:pt];
647 m_start_subitem=(int)[self columnAtPoint:pt];
651 m_start_item_clickmode=0;
652 if (m_start_item >=0 && (m_fastClickMask&(1<<m_start_subitem)))
654 NMLISTVIEW nmlv={{(HWND)self,(UINT_PTR)[self tag], NM_CLICK}, m_start_item, m_start_subitem, 0, 0, 0, {(int)floor(pt.x), (int)floor(pt.y)}, };
655 SWELL_ListView_Row *row=m_items->Get(nmlv.iItem);
657 nmlv.lParam = row->m_param;
658 SendMessage((HWND)[self target],WM_NOTIFY,nmlv.hdr.idFrom,(LPARAM)&nmlv);
659 m_start_item_clickmode=4;
663 if (m_start_item>=0 && m_status_imagelist && LVSIL_STATE == m_status_imagelist_type && pt.x <= [self rowHeight]) // in left area
665 m_start_item_clickmode=1;
671 -(void)mouseDragged:(NSEvent *)theEvent
673 if (++m_leftmousemovecnt==4)
675 if (m_start_item>=0 && !(m_start_item_clickmode&3))
679 // if m_start_item isnt selected, change selection to it now
680 if (!(m_start_item_clickmode&4) && ![self isRowSelected:m_start_item])
682 [self selectRowIndexes:[NSIndexSet indexSetWithIndex:m_start_item] byExtendingSelection:!!(GetAsyncKeyState(VK_CONTROL)&0x8000)];
684 NMLISTVIEW hdr={{(HWND)self,(UINT_PTR)[self tag],LVN_BEGINDRAG},m_start_item,m_start_subitem,0,};
685 SendMessage((HWND)[self target],WM_NOTIFY,hdr.hdr.idFrom, (LPARAM) &hdr);
686 m_start_item_clickmode |= 2;
690 else if (m_leftmousemovecnt > 4 && !(m_start_item_clickmode&1))
692 HWND tgt=(HWND)[self target];
695 ScreenToClient(tgt,&p);
697 SendMessage(tgt,WM_MOUSEMOVE,0,(p.x&0xffff) + (((int)p.y)<<16));
701 -(void)mouseUp:(NSEvent *)theEvent
703 if ((m_fakerightmouse||([theEvent modifierFlags] & NSControlKeyMask)) && IsRightClickEmulateEnabled())
705 [self rightMouseUp:theEvent];
709 if ([theEvent clickCount]>1 && SWELL_NeedModernListViewHacks())
711 [super mouseUp:theEvent];
714 if (!(m_start_item_clickmode&1))
716 if (m_leftmousemovecnt>=0 && m_leftmousemovecnt<4 && !(m_start_item_clickmode&4))
718 const bool msel = [self allowsMultipleSelection];
719 if (m_lbMode && !msel) // listboxes --- allow clicking to reset the selection
721 [self deselectAll:self];
724 if (SWELL_NeedModernListViewHacks())
728 NSMutableIndexSet *m = [[NSMutableIndexSet alloc] init];
729 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
731 [m addIndexes:[self selectedRowIndexes]];
732 if ([m containsIndex:m_start_item]) [m removeIndex:m_start_item];
735 if (!msel) [m removeAllIndexes];
736 [m addIndex:m_start_item];
738 m_last_plainly_clicked_item = m_start_item;
740 else if (msel && (GetAsyncKeyState(VK_SHIFT)&0x8000))
742 [m addIndexes:[self selectedRowIndexes]];
743 const int n = ListView_GetItemCount((HWND)self);
744 if (m_last_plainly_clicked_item<0 || m_last_plainly_clicked_item>=n)
745 m_last_plainly_clicked_item=m_start_item;
747 if (m_last_shift_clicked_item>=0 &&
748 m_last_shift_clicked_item<n &&
749 m_last_plainly_clicked_item != m_last_shift_clicked_item)
751 int a1 = m_last_shift_clicked_item;
752 int a2 = m_last_plainly_clicked_item;
753 if (a2<a1) { int tmp=a1; a1=a2; a2=tmp; }
754 [m removeIndexesInRange:NSMakeRange(a1,a2-a1 + 1)];
757 int a1 = m_start_item;
758 int a2 = m_last_plainly_clicked_item;
759 if (a2<a1) { int tmp=a1; a1=a2; a2=tmp; }
760 [m addIndexesInRange:NSMakeRange(a1,a2-a1 + 1)];
762 m_last_shift_clicked_item = m_start_item;
766 m_last_plainly_clicked_item = m_start_item;
767 [m addIndex:m_start_item];
770 [self selectRowIndexes:m byExtendingSelection:NO];
775 else [self deselectAll:self];
779 [super mouseDown:theEvent];
780 [super mouseUp:theEvent];
783 else if (m_leftmousemovecnt>=4)
785 HWND tgt=(HWND)[self target];
788 ScreenToClient(tgt,&p);
789 SendMessage(tgt,WM_LBUTTONUP,0,(p.x&0xffff) + (((int)p.y)<<16));
794 if (!m_lbMode && !(m_start_item_clickmode&(2|4)))
796 NSPoint pt=[theEvent locationInWindow];
797 pt=[self convertPoint:pt fromView:nil];
798 int col = (int)[self columnAtPoint:pt];
799 NMLISTVIEW nmlv={{(HWND)self,(UINT_PTR)[self tag], NM_CLICK}, (int)[self rowAtPoint:pt], col, 0, 0, 0, {(int)floor(pt.x), (int)floor(pt.y)}, };
800 SWELL_ListView_Row *row=m_items->Get(nmlv.iItem);
801 if (row) nmlv.lParam = row->m_param;
802 SendMessage((HWND)[self target],WM_NOTIFY,nmlv.hdr.idFrom,(LPARAM)&nmlv);
806 - (void)rightMouseUp:(NSEvent *)theEvent
808 bool wantContext=true;
812 NSPoint pt=[theEvent locationInWindow];
813 pt=[self convertPoint:pt fromView:nil];
815 // note, windows selects on right mousedown
816 NSInteger row =[self rowAtPoint:pt];
817 if (row >= 0 && ![self isRowSelected:row])
819 NSIndexSet* rows=[NSIndexSet indexSetWithIndex:row];
820 [self deselectAll:self];
821 [self selectRowIndexes:rows byExtendingSelection:NO];
824 NMLISTVIEW nmlv={{(HWND)self,(UINT_PTR)[self tag], NM_RCLICK}, (int)row, (int)[self columnAtPoint:pt], 0, 0, 0, {(int)floor(pt.x), (int)floor(pt.y)}, };
825 if (SendMessage((HWND)[self target],WM_NOTIFY,nmlv.hdr.idFrom,(LPARAM)&nmlv)) wantContext=false;
831 SendMessage((HWND)[self target],WM_CONTEXTMENU,(WPARAM)self,(p.x&0xffff)|(p.y<<16));
836 -(LRESULT)onSwellMessage:(UINT)msg p1:(WPARAM)wParam p2:(LPARAM)lParam
838 HWND hwnd=(HWND)self;
841 case LB_RESETCONTENT:
845 m_items->Empty(true);
850 case LB_INSERTSTRING:
852 int cnt=ListView_GetItemCount(hwnd);
853 if (msg == LB_ADDSTRING && (style & LBS_SORT))
855 SWELL_ListView *tv=(SWELL_ListView*)hwnd;
856 if (tv->m_lbMode && tv->m_items)
858 cnt=ptrlist_bsearch_mod((char *)lParam,tv->m_items,_listviewrowSearchFunc,NULL);
861 if (msg==LB_ADDSTRING) wParam=cnt;
862 else if (wParam > cnt) wParam=cnt;
863 LVITEM lvi={LVIF_TEXT,(int)wParam,0,0,0,(char *)lParam};
864 ListView_InsertItem(hwnd,&lvi);
867 case LB_GETCOUNT: return ListView_GetItemCount(hwnd);
869 ListView_SetItemState(hwnd, (int)lParam,wParam ? LVIS_SELECTED : 0,LVIS_SELECTED);
874 SWELL_ListView_Row *row=self->m_items ? self->m_items->Get(wParam) : NULL;
876 if (row && row->m_vals.Get(0))
878 strcpy((char *)lParam, row->m_vals.Get(0));
879 return (LRESULT)strlen(row->m_vals.Get(0));
885 SWELL_ListView_Row *row=self->m_items ? self->m_items->Get(wParam) : NULL;
888 const char *p=row->m_vals.Get(0);
889 return p?strlen(p):0;
894 return !!(ListView_GetItemState(hwnd,(int)wParam,LVIS_SELECTED)&LVIS_SELECTED);
896 return [self selectedRow];
899 if (wParam<ListView_GetItemCount(hwnd))
901 [self selectRowIndexes:[NSIndexSet indexSetWithIndex:wParam] byExtendingSelection:NO];
902 [self scrollRowToVisible:wParam];
906 [self deselectAll:self];
914 SWELL_ListView_Row *row=m_items->Get(wParam);
915 if (row) return row->m_param;
923 SWELL_ListView_Row *row=m_items->Get(wParam);
924 if (row) row->m_param=lParam;
929 return [[self selectedRowIndexes] count];
930 case LB_DELETESTRING:
931 ListView_DeleteItem((HWND)self, (int)wParam);
936 if (SWELL_GetOSXVersion() >= 0x1070 && [self respondsToSelector:@selector(endUpdates)])
941 if (SWELL_GetOSXVersion() >= 0x1070 && [self respondsToSelector:@selector(beginUpdates)])
950 -(int)getSwellNotificationMode
954 -(void)setSwellNotificationMode:(int)lbMode
959 -(void)onSwellCommand:(int)cmd
966 @implementation SWELL_ImageButtonCell
967 - (NSRect)drawTitle:(NSAttributedString *)title withFrame:(NSRect)frame inView:(NSView *)controlView
969 return NSMakeRect(0,0,0,0);
973 @implementation SWELL_ODButtonCell
974 - (BOOL)isTransparent
983 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
985 NSView *ctl=[self controlView];
986 if (!ctl) { [super drawWithFrame:cellFrame inView:controlView]; return; }
988 HDC hdc=GetDC((HWND)controlView);
991 HWND notWnd = GetParent((HWND)ctl);
992 RECT r={(int)(cellFrame.origin.x+0.5),(int)(cellFrame.origin.y+0.5)};
993 r.right=r.left+(int)(cellFrame.size.width+0.5);
994 r.bottom=r.top+(int)(cellFrame.size.height+0.5);
995 DRAWITEMSTRUCT dis={ODT_BUTTON,(UINT)[ctl tag],0,0,0,(HWND)ctl,hdc,{0,},0};
997 SendMessage(notWnd,WM_DRAWITEM,dis.CtlID,(LPARAM)&dis);
999 ReleaseDC((HWND)controlView,hdc);
1005 @implementation SWELL_ODListViewCell
1006 -(void)setOwnerControl:(SWELL_ListView *)t { m_ownctl=t; m_lastidx=0; }
1007 -(void)setItemIdx:(int)idx
1011 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
1013 if (!m_ownctl) { [super drawInteriorWithFrame:cellFrame inView:controlView]; return; }
1015 int itemidx=m_lastidx;
1017 SWELL_ListView_Row *row=m_ownctl->m_items->Get(itemidx);
1018 if (row) itemData=row->m_param;
1020 HDC hdc=GetDC((HWND)controlView);
1023 HWND notWnd = GetParent((HWND)m_ownctl);
1024 RECT r={(int)(cellFrame.origin.x+0.5),(int)(cellFrame.origin.y+0.5)};
1025 r.right=r.left+(int)(cellFrame.size.width+0.5);
1026 r.bottom=r.top+(int)(cellFrame.size.height+0.5);
1027 DRAWITEMSTRUCT dis={ODT_LISTBOX,(UINT)[m_ownctl tag],(UINT)itemidx,0,0,(HWND)m_ownctl,hdc,{0,},(DWORD_PTR)itemData};
1029 SendMessage(notWnd,WM_DRAWITEM,dis.CtlID,(LPARAM)&dis);
1031 ReleaseDC((HWND)controlView,hdc);
1042 HWND GetDlgItem(HWND hwnd, int idx)
1044 if (!hwnd) return 0;
1048 if ([pid isKindOfClass:[NSWindow class]]) v=[((NSWindow *)pid) contentView];
1049 else if ([pid isKindOfClass:[NSView class]]) v=(NSView *)pid;
1051 if (!idx || !v) return (HWND)v;
1055 NSArray *ar = [v subviews];
1056 const NSInteger n=[ar count];
1057 for (NSInteger x=0;x<n;x++)
1059 NSView *sv = [ar objectAtIndex:x];
1062 if ([sv respondsToSelector:@selector(tag)] && [sv tag] == idx) return (HWND)sv;
1064 if (sv && [sv isKindOfClass:[NSScrollView class]])
1066 sv=[(NSScrollView *)sv documentView];
1067 if (sv && [sv respondsToSelector:@selector(tag)] && [sv tag] == idx) return (HWND)sv;
1069 if (sv && [sv isKindOfClass:[NSClipView class]])
1071 sv = [(NSClipView *)sv documentView];
1072 if (sv && [sv respondsToSelector:@selector(tag)] && [sv tag] == idx) return (HWND)sv;
1076 // we might want to enable this for max compat with old code, but hopefully not: return [v viewWithTag:idx];
1082 LONG_PTR SetWindowLong(HWND hwnd, int idx, LONG_PTR val)
1084 if (!hwnd) return 0;
1088 if (idx==GWL_EXSTYLE && [pid respondsToSelector:@selector(swellSetExtendedStyle:)])
1090 LONG ret=(LONG) [(SWELL_hwndChild*)pid swellGetExtendedStyle];
1091 [(SWELL_hwndChild*)pid swellSetExtendedStyle:(LONG)val];
1094 if (idx==GWL_USERDATA && [pid respondsToSelector:@selector(setSwellUserData:)])
1096 LONG_PTR ret=(LONG_PTR)[(SWELL_hwndChild*)pid getSwellUserData];
1097 [(SWELL_hwndChild*)pid setSwellUserData:(LONG_PTR)val];
1101 if (idx==GWL_ID && [pid respondsToSelector:@selector(tag)] && [pid respondsToSelector:@selector(setTag:)])
1103 int ret= (int) [pid tag];
1104 [pid setTag:(int)val];
1105 return (LONG_PTR)ret;
1108 if (idx==GWL_WNDPROC && [pid respondsToSelector:@selector(setSwellWindowProc:)])
1110 WNDPROC ov=(WNDPROC)[pid getSwellWindowProc];
1111 [pid setSwellWindowProc:(WNDPROC)val];
1112 return (LONG_PTR)ov;
1114 if (idx==DWL_DLGPROC && [pid respondsToSelector:@selector(setSwellDialogProc:)])
1116 DLGPROC ov=(DLGPROC)[pid getSwellDialogProc];
1117 [pid setSwellDialogProc:(DLGPROC)val];
1118 return (LONG_PTR)ov;
1123 if ([pid respondsToSelector:@selector(setSwellStyle:)])
1125 LONG ov=[pid getSwellStyle];
1126 [pid setSwellStyle:(LONG)val];
1129 else if ([pid isKindOfClass:[NSButton class]])
1131 int ret=(int)GetWindowLong(hwnd,idx);
1133 if ((val&0xf) == BS_AUTO3STATE)
1135 [pid setButtonType:NSSwitchButton];
1136 [pid setAllowsMixedState:YES];
1137 if ([pid isKindOfClass:[SWELL_Button class]]) [pid swellSetRadioFlags:0];
1139 else if ((val & 0xf) == BS_AUTOCHECKBOX)
1141 [pid setButtonType:NSSwitchButton];
1142 [pid setAllowsMixedState:NO];
1143 if ([pid isKindOfClass:[SWELL_Button class]]) [pid swellSetRadioFlags:0];
1145 else if ((val & 0xf) == BS_AUTORADIOBUTTON)
1147 [pid setButtonType:NSRadioButton];
1148 if ([pid isKindOfClass:[SWELL_Button class]]) [pid swellSetRadioFlags:(val&WS_GROUP)?3:1];
1155 if ([[pid window] contentView] == pid)
1157 NSView *tv=(NSView *)pid;
1158 NSWindow *oldw = [tv window];
1159 NSUInteger smask = [oldw styleMask];
1161 if (smask & NSTitledWindowMask)
1164 if (smask & NSResizableWindowMask) mf|=WS_THICKFRAME;
1166 if (mf != (val&(WS_CAPTION|WS_THICKFRAME)))
1168 BOOL dovis = IsWindowVisible((HWND)oldw);
1169 NSWindow *oldpar = [oldw parentWindow];
1170 char oldtitle[2048];
1172 GetWindowText(hwnd,oldtitle,sizeof(oldtitle));
1173 NSRect fr=[oldw frame];
1175 if ([oldw respondsToSelector:@selector(swellGetOwner)]) oldOwner=(HWND)[(SWELL_ModelessWindow*)oldw swellGetOwner];
1176 NSInteger oldlevel = [oldw level];
1180 SWELL_hwndChild *tempview = [[SWELL_hwndChild alloc] initChild:nil Parent:(NSView *)oldw dlgProc:nil Param:0];
1183 unsigned int mask=0;
1185 if (val & WS_CAPTION)
1187 mask|=NSTitledWindowMask;
1188 if (val & WS_THICKFRAME)
1189 mask|=NSMiniaturizableWindowMask|NSClosableWindowMask|NSResizableWindowMask;
1192 HWND SWELL_CreateModelessFrameForWindow(HWND childW, HWND ownerW, unsigned int);
1193 HWND bla=SWELL_CreateModelessFrameForWindow((HWND)tv,(HWND)oldOwner,mask);
1198 // move owned windows over
1199 if ([oldw respondsToSelector:@selector(swellGetOwnerWindowHead)])
1201 void **p=(void **)[(SWELL_ModelessWindow*)oldw swellGetOwnerWindowHead];
1202 if (p && [(id)bla respondsToSelector:@selector(swellGetOwnerWindowHead)])
1204 void **p2=(void **)[(SWELL_ModelessWindow*)bla swellGetOwnerWindowHead];
1209 OwnedWindowListRec *rec = (OwnedWindowListRec *) *p2;
1212 if (rec->hwnd && [rec->hwnd respondsToSelector:@selector(swellSetOwner:)])
1213 [(SWELL_ModelessWindow *)rec->hwnd swellSetOwner:(id)bla];
1219 // move all child and owned windows over to new window
1220 NSArray *ar=[oldw childWindows];
1224 for (x = 0; x < [ar count]; x ++)
1226 NSWindow *cw=[ar objectAtIndex:x];
1230 [oldw removeChildWindow:cw];
1231 [(NSWindow *)bla addChildWindow:cw ordered:NSWindowAbove];
1239 if (oldpar) [oldpar addChildWindow:(NSWindow *)bla ordered:NSWindowAbove];
1240 if (oldtitle[0]) SetWindowText(hwnd,oldtitle);
1242 [(NSWindow *)bla setFrame:fr display:dovis];
1243 [(NSWindow *)bla setLevel:oldlevel];
1244 if (dovis) ShowWindow(bla,SW_SHOW);
1246 DestroyWindow((HWND)oldw);
1250 [oldw setContentView:tv];
1261 if ([pid respondsToSelector:@selector(setSwellExtraData:value:)])
1264 if ([pid respondsToSelector:@selector(getSwellExtraData:)]) ov=(LONG_PTR)[pid getSwellExtraData:idx];
1266 [pid setSwellExtraData:idx value:val];
1275 LONG_PTR GetWindowLong(HWND hwnd, int idx)
1277 if (!hwnd) return 0;
1282 if (idx==GWL_EXSTYLE && [pid respondsToSelector:@selector(swellGetExtendedStyle)])
1284 return (LONG_PTR)[pid swellGetExtendedStyle];
1287 if (idx==GWL_USERDATA && [pid respondsToSelector:@selector(getSwellUserData)])
1289 return (LONG_PTR)[pid getSwellUserData];
1291 if (idx==GWL_USERDATA && [pid isKindOfClass:[NSText class]])
1296 if (idx==GWL_ID && [pid respondsToSelector:@selector(tag)])
1300 if (idx==GWL_WNDPROC && [pid respondsToSelector:@selector(getSwellWindowProc)])
1302 return (LONG_PTR)[pid getSwellWindowProc];
1304 if (idx==DWL_DLGPROC && [pid respondsToSelector:@selector(getSwellDialogProc)])
1306 return (LONG_PTR)[pid getSwellDialogProc];
1311 if ([pid respondsToSelector:@selector(getSwellStyle)])
1313 return (LONG_PTR)[pid getSwellStyle];
1316 if ([pid isKindOfClass:[NSButton class]])
1319 if ([pid allowsMixedState]) ret |= BS_AUTO3STATE;
1320 else if ([pid isKindOfClass:[SWELL_Button class]] && (tmp = (int)[pid swellGetRadioFlags]))
1322 ret |= BS_AUTORADIOBUTTON;
1323 if (tmp&2) ret|=WS_GROUP;
1325 else ret |= BS_AUTOCHECKBOX;
1328 if ([pid isKindOfClass:[NSView class]])
1330 if ([[pid window] contentView] != pid) ret |= WS_CHILDWINDOW;
1333 NSUInteger smask =[[pid window] styleMask];
1334 if (smask & NSTitledWindowMask)
1337 if (smask & NSResizableWindowMask) ret|=WS_THICKFRAME;
1344 if ([pid respondsToSelector:@selector(getSwellExtraData:)])
1346 return (LONG_PTR)[pid getSwellExtraData:idx];
1353 static bool IsWindowImpl(NSView *ch, NSView *par)
1355 if (!par || ![par isKindOfClass:[NSView class]]) return false;
1357 NSArray *ar = [par subviews];
1358 if (!ar) return false;
1360 NSInteger x,n=[ar count];
1362 if ([ar objectAtIndex:x] == ch)
1369 if (IsWindowImpl(ch,[ar objectAtIndex:x]))
1378 bool IsWindow(HWND hwnd)
1380 if (!hwnd) return false;
1381 // this is very costly, but required
1384 NSArray *ch=[NSApp windows];
1386 NSInteger x,n=[ch count];
1390 NSWindow *w = [ch objectAtIndex:x];
1391 if (w == (NSWindow *)hwnd || [w contentView] == (NSView *)hwnd)
1397 @catch (NSException *ex) {
1405 NSWindow *w = [ch objectAtIndex:x];
1407 // only validate children of our windows (maybe an option for this?)
1408 ([w isKindOfClass:[SWELL_ModelessWindow class]] || [w isKindOfClass:[SWELL_ModalDialog class]]) &&
1409 IsWindowImpl((NSView*)hwnd,[w contentView]))
1415 @catch (NSException *ex) {
1426 bool IsWindowVisible(HWND hwnd)
1428 if (!hwnd) return false;
1432 if ([turd isKindOfClass:[NSView class]])
1434 NSWindow *w = [turd window];
1435 if (w && ![w isVisible]) return false;
1437 return ![turd isHiddenOrHasHiddenAncestor];
1439 if ([turd isKindOfClass:[NSWindow class]])
1441 return !![turd isVisible];
1448 bool IsWindowEnabled(HWND hwnd)
1450 if (!hwnd) return false;
1457 if ([view isKindOfClass:[NSWindow class]]) view = [view contentView];
1459 rv = view && [view respondsToSelector:@selector(isEnabled)] && [view isEnabled];
1469 static void *__GetNSImageFromHICON(HICON ico) // local copy to not be link dependent on swell-gdi.mm
1471 HGDIOBJ__ *i = (HGDIOBJ__ *)ico;
1472 if (!i || i->type != TYPE_BITMAP) return 0;
1473 return i->bitmapptr;
1477 @implementation SWELL_Button : NSButton
1479 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
1482 self = [super init];
1490 -(int)swellGetRadioFlags { return m_radioflags; }
1491 -(void)swellSetRadioFlags:(int)f { m_radioflags=f; }
1492 -(LONG_PTR)getSwellUserData { return m_userdata; }
1493 -(void)setSwellUserData:(LONG_PTR)val { m_userdata=val; }
1495 -(void)setSwellGDIImage:(void *)par
1497 m_swellGDIimage=par;
1499 -(void *)getSwellGDIImage
1501 return m_swellGDIimage;
1506 LRESULT SendMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1508 if (!hwnd) return 0;
1512 if ([obj respondsToSelector:@selector(onSwellMessage:p1:p2:)])
1514 return (LRESULT) [obj onSwellMessage:msg p1:wParam p2:lParam];
1518 if (msg == BM_GETCHECK && [obj isKindOfClass:[NSButton class]])
1520 NSInteger a=[(NSButton*)obj state];
1521 if (a==NSMixedState) return BST_INDETERMINATE;
1522 return a!=NSOffState;
1524 if (msg == BM_SETCHECK && [obj isKindOfClass:[NSButton class]])
1526 [(NSButton*)obj setState:(wParam&BST_INDETERMINATE)?NSMixedState:((wParam&BST_CHECKED)?NSOnState:NSOffState)];
1529 if ((msg==BM_GETIMAGE || msg == BM_SETIMAGE) && [obj isKindOfClass:[SWELL_Button class]])
1531 if (wParam != IMAGE_BITMAP && wParam != IMAGE_ICON) return 0; // ignore unknown types
1532 LONG_PTR ret=(LONG_PTR) (void *)[obj getSwellGDIImage];
1533 if (msg==BM_SETIMAGE)
1536 if (lParam) img=(NSImage *)__GetNSImageFromHICON((HICON)lParam);
1538 [obj setSwellGDIImage:(void *)(img?lParam:0)];
1542 else if (msg >= CB_ADDSTRING && msg <= CB_INITSTORAGE && ([obj isKindOfClass:[NSPopUpButton class]] || [obj isKindOfClass:[NSComboBox class]]))
1546 case CB_ADDSTRING: return SWELL_CB_AddString(hwnd,0,(char*)lParam);
1547 case CB_DELETESTRING: SWELL_CB_DeleteString(hwnd,0,(int)wParam); return 1;
1548 case CB_GETCOUNT: return SWELL_CB_GetNumItems(hwnd,0);
1549 case CB_GETCURSEL: return SWELL_CB_GetCurSel(hwnd,0);
1550 case CB_GETLBTEXT: return SWELL_CB_GetItemText(hwnd,0,(int)wParam,(char *)lParam, 1<<20);
1551 case CB_GETLBTEXTLEN: return SWELL_CB_GetItemText(hwnd,0,(int)wParam,NULL,0);
1552 case CB_INSERTSTRING: return SWELL_CB_InsertString(hwnd,0,(int)wParam,(char *)lParam);
1553 case CB_RESETCONTENT: SWELL_CB_Empty(hwnd,0); return 0;
1554 case CB_SETCURSEL: SWELL_CB_SetCurSel(hwnd,0,(int)wParam); return 0;
1555 case CB_GETITEMDATA: return SWELL_CB_GetItemData(hwnd,0,(int)wParam);
1556 case CB_SETITEMDATA: SWELL_CB_SetItemData(hwnd,0,(int)wParam,lParam); return 0;
1558 case CB_FINDSTRINGEXACT:
1559 if (lParam) return SWELL_CB_FindString(hwnd,0,(int)wParam,(const char *)lParam,msg==CB_FINDSTRINGEXACT);
1561 case CB_INITSTORAGE: return 0;
1565 else if (msg >= TBM_GETPOS && msg <= TBM_SETRANGE && ([obj isKindOfClass:[NSSlider class]]))
1569 case TBM_GETPOS: return SWELL_TB_GetPos(hwnd,0);
1570 case TBM_SETTIC: SWELL_TB_SetTic(hwnd,0,(int)lParam); return 1;
1571 case TBM_SETPOS: SWELL_TB_SetPos(hwnd,0,(int)lParam); return 1;
1572 case TBM_SETRANGE: SWELL_TB_SetRange(hwnd,0,LOWORD(lParam),HIWORD(lParam)); return 1;
1576 else if ((msg == EM_SETSEL || msg == EM_GETSEL || msg == EM_SETPASSWORDCHAR) && ([obj isKindOfClass:[NSTextField class]]))
1578 if (msg == EM_GETSEL)
1581 NSResponder *rs = [[obj window] firstResponder];
1582 if ([rs isKindOfClass:[NSView class]] && [(NSView *)rs isDescendantOf:obj])
1584 NSText* text=[[obj window] fieldEditor:YES forObject:(NSTextField*)obj];
1585 if (text) range=[text selectedRange];
1587 if (wParam) *(int*)wParam=(int)range.location;
1588 if (lParam) *(int*)lParam=(int)(range.location+range.length);
1590 else if (msg == EM_SETSEL)
1592 // [(NSTextField*)obj selectText:obj]; // Force the window's text field editor onto this control
1593 // don't force it, just ignore EM_GETSEL/EM_SETSEL if not in focus
1594 NSResponder *rs = [[obj window] firstResponder];
1595 if ([rs isKindOfClass:[NSView class]] && [(NSView *)rs isDescendantOf:obj])
1597 NSText* text = [[obj window] fieldEditor:YES forObject:(NSTextField*)obj]; // then get it from the window
1598 NSUInteger sl = [[text string] length];
1599 if (wParam == -1) lParam = wParam = 0;
1600 else if (lParam == -1) lParam = sl;
1601 if (wParam>sl) wParam=sl;
1602 if (lParam>sl) lParam=sl;
1603 if (text) [text setSelectedRange:NSMakeRange(wParam, wdl_max(lParam-wParam,0))]; // and set the range
1606 else if (msg == EM_SETPASSWORDCHAR)
1608 // not implemented, because it requires replacing obj within its parent window
1609 // instead caller explicitly destroy the edit control and create a new one with ES_PASSWORD
1617 // if content view gets unhandled message send to window
1618 if ([obj isKindOfClass:[NSView class]] && (w=[obj window]) && [w contentView] == obj && [w respondsToSelector:@selector(onSwellMessage:p1:p2:)])
1620 return (LRESULT) [(SWELL_hwndChild *)w onSwellMessage:msg p1:wParam p2:lParam];
1622 // if window gets unhandled message send to content view
1623 else if ([obj isKindOfClass:[NSWindow class]] && (v=[obj contentView]) && [v respondsToSelector:@selector(onSwellMessage:p1:p2:)])
1625 return (LRESULT) [(SWELL_hwndChild *)v onSwellMessage:msg p1:wParam p2:lParam];
1633 void DestroyWindow(HWND hwnd)
1638 if ([pid isKindOfClass:[NSView class]])
1640 KillTimer(hwnd,~(UINT_PTR)0);
1641 sendSwellMessage((id)pid,WM_DESTROY,0,0);
1643 NSWindow *pw = [(NSView *)pid window];
1644 if (pw && [pw contentView] == pid) // destroying contentview should destroy top level window
1646 DestroyWindow((HWND)pw);
1650 if (pw && [NSApp keyWindow] == pw)
1652 id foc=[pw firstResponder];
1653 if (foc && (foc == pid || IsChild((HWND)pid,(HWND)foc)))
1655 HWND h=GetParent((HWND)pid);
1659 [(NSView *)pid removeFromSuperview];
1662 else if ([pid isKindOfClass:[NSWindow class]])
1664 KillTimer(hwnd,~(UINT_PTR)0);
1665 sendSwellMessage([(id)pid contentView],WM_DESTROY,0,0);
1666 sendSwellMessage((id)pid,WM_DESTROY,0,0);
1668 if ([(id)pid respondsToSelector:@selector(swellDoDestroyStuff)])
1669 [(id)pid swellDoDestroyStuff];
1671 NSWindow *par=[(NSWindow*)pid parentWindow];
1674 [par removeChildWindow:(NSWindow*)pid];
1676 [(NSWindow *)pid close]; // this is probably bad, but close takes too long to close!
1681 void EnableWindow(HWND hwnd, int enable)
1686 if ([bla isKindOfClass:[NSWindow class]]) bla = [bla contentView];
1688 if (bla && [bla respondsToSelector:@selector(setEnabled:)])
1690 if (enable == -1000 && [bla respondsToSelector:@selector(setEnabledSwellNoFocus)])
1691 [bla setEnabledSwellNoFocus];
1693 [bla setEnabled:(enable?YES:NO)];
1694 if ([bla isKindOfClass:[SWELL_TextField class]])
1696 NSTextField* txt = (NSTextField*)bla;
1697 if (![txt isEditable] && ![txt isBordered] && ![txt drawsBackground]) // looks like a static text control
1699 NSColor* col = [txt textColor];
1700 float alpha = (enable ? 1.0f : 0.5f);
1701 [txt setTextColor:[col colorWithAlphaComponent:alpha]];
1708 void SetForegroundWindow(HWND hwnd)
1713 void SetFocus(HWND hwnd) // these take NSWindow/NSView, and return NSView *
1719 if ([r isKindOfClass:[NSWindow class]])
1721 [(NSWindow *)r makeFirstResponder:[(NSWindow *)r contentView]];
1722 if ([(NSWindow *)r isVisible]) [(NSWindow *)r makeKeyAndOrderFront:nil];
1724 else if ([r isKindOfClass:[NSView class]])
1726 NSWindow *wnd=[(NSView *)r window];
1729 [wnd makeFirstResponder:r];
1730 if ([wnd isVisible])
1732 [wnd makeKeyAndOrderFront:nil];
1739 void SWELL_GetViewPort(RECT *r, const RECT *sourcerect, bool wantWork)
1743 NSArray *ar=[NSScreen screens];
1745 const NSInteger cnt=[ar count];
1750 cx=(sourcerect->left+sourcerect->right)/2;
1751 cy=(sourcerect->top+sourcerect->bottom)/2;
1753 for (NSInteger x = 0; x < cnt; x ++)
1755 NSScreen *sc=[ar objectAtIndex:x];
1758 NSRect tr=wantWork ? [sc visibleFrame] : [sc frame];
1759 if (!x || (cx >= tr.origin.x && cx < tr.origin.x+tr.size.width &&
1760 cy >= tr.origin.y && cy < tr.origin.y+tr.size.height))
1762 r->left=(int)tr.origin.x;
1763 r->right=(int)(tr.origin.x+tr.size.width+0.5);
1764 r->top=(int)tr.origin.y;
1765 r->bottom=(int)(tr.origin.y+tr.size.height+0.5);
1778 void ScreenToClient(HWND hwnd, POINT *p)
1781 // no need to try/catch, this should never have an issue *wince*
1784 if ([ch isKindOfClass:[NSWindow class]]) ch=[((NSWindow *)ch) contentView];
1785 if (!ch || ![ch isKindOfClass:[NSView class]]) return;
1787 NSWindow *window=[ch window];
1789 NSPoint wndpt = [window convertScreenToBase:NSMakePoint(p->x,p->y)];
1791 // todo : WM_NCCALCSIZE
1792 NSPoint po = [ch convertPoint:wndpt fromView:nil];
1794 p->x=(int)(po.x+0.5);
1795 p->y=(int)(po.y+0.5);
1798 void ClientToScreen(HWND hwnd, POINT *p)
1803 if ([ch isKindOfClass:[NSWindow class]]) ch=[((NSWindow *)ch) contentView];
1804 if (!ch || ![ch isKindOfClass:[NSView class]]) return;
1806 NSWindow *window=[ch window];
1808 NSPoint wndpt = [ch convertPoint:NSMakePoint(p->x,p->y) toView:nil];
1810 NSPoint po = [window convertBaseToScreen:wndpt];
1811 // todo : WM_NCCALCSIZE
1813 p->x=(int)(po.x+0.5);
1814 p->y=(int)(po.y+0.5);
1817 static NSView *NavigateUpScrollClipViews(NSView *ch)
1819 NSView *par=[ch superview];
1820 if (par && [par isKindOfClass:[NSClipView class]])
1822 par=[par superview];
1823 if (par && [par isKindOfClass:[NSScrollView class]])
1831 HWND SWELL_NavigateUpScrollClipViews(HWND h)
1834 if (h && [(id)h isKindOfClass:[NSView class]]) v = (NSView *)h;
1835 else if (h && [(id)h isKindOfClass:[NSWindow class]]) v = [(NSWindow *)h contentView];
1837 return (HWND)NavigateUpScrollClipViews(v);
1841 bool GetWindowRect(HWND hwnd, RECT *r)
1843 r->left=r->top=r->right=r->bottom=0;
1844 if (!hwnd) return false;
1850 if ([ch isKindOfClass:[NSView class]] && (nswnd=[(NSView *)ch window]) && [nswnd contentView]==ch)
1853 if ([ch isKindOfClass:[NSWindow class]])
1855 NSRect b=[ch frame];
1856 r->left=(int)(b.origin.x);
1857 r->top=(int)(b.origin.y);
1858 r->right = (int)(b.origin.x+b.size.width+0.5);
1859 r->bottom= (int)(b.origin.y+b.size.height+0.5);
1862 if (![ch isKindOfClass:[NSView class]]) return false;
1863 ch=NavigateUpScrollClipViews(ch);
1864 NSRect b=[ch bounds];
1865 r->left=(int)(b.origin.x);
1866 r->top=(int)(b.origin.y);
1867 r->right = (int)(b.origin.x+b.size.width+0.5);
1868 r->bottom= (int)(b.origin.y+b.size.height+0.5);
1869 ClientToScreen((HWND)ch,(POINT *)r);
1870 ClientToScreen((HWND)ch,((POINT *)r)+1);
1871 SWELL_END_TRY(return false;)
1876 void GetWindowContentViewRect(HWND hwnd, RECT *r)
1880 if (hwnd && [(id)hwnd isKindOfClass:[NSView class]] && (nswnd=[(NSView *)hwnd window]) && [nswnd contentView]==(id)hwnd)
1883 if (hwnd && [(id)hwnd isKindOfClass:[NSWindow class]])
1885 NSView *ch=[(id)hwnd contentView];
1886 NSRect b=[ch bounds];
1887 r->left=(int)(b.origin.x);
1888 r->top=(int)(b.origin.y);
1889 r->right = (int)(b.origin.x+b.size.width+0.5);
1890 r->bottom= (int)(b.origin.y+b.size.height+0.5);
1891 ClientToScreen(hwnd,(POINT *)r);
1892 ClientToScreen(hwnd,((POINT *)r)+1);
1894 else GetWindowRect(hwnd,r);
1899 void GetClientRect(HWND hwnd, RECT *r)
1901 r->left=r->top=r->right=r->bottom=0;
1906 if ([ch isKindOfClass:[NSWindow class]]) ch=[((NSWindow *)ch) contentView];
1907 if (!ch || ![ch isKindOfClass:[NSView class]]) return;
1908 ch=NavigateUpScrollClipViews(ch);
1910 NSRect b=[ch bounds];
1911 r->left=(int)(b.origin.x);
1912 r->top=(int)(b.origin.y);
1913 r->right = (int)(b.origin.x+b.size.width+0.5);
1914 r->bottom= (int)(b.origin.y+b.size.height+0.5);
1916 // todo this may need more attention
1917 NCCALCSIZE_PARAMS tr={{*r,},};
1918 SendMessage(hwnd,WM_NCCALCSIZE,FALSE,(LPARAM)&tr);
1919 r->right = r->left + (tr.rgrc[0].right-tr.rgrc[0].left);
1920 r->bottom = r->top + (tr.rgrc[0].bottom-tr.rgrc[0].top);
1926 void SetWindowPos(HWND hwnd, HWND hwndAfter, int x, int y, int cx, int cy, int flags)
1931 NSWindow *nswnd; // content views = move window
1932 if (hwnd && [(id)hwnd isKindOfClass:[NSView class]] && (nswnd=[(NSView *)hwnd window]) && [nswnd contentView]==(id)hwnd)
1935 // todo: handle SWP_SHOWWINDOW
1938 if ([ch isKindOfClass:[NSWindow class]] || (isview=[ch isKindOfClass:[NSView class]]))
1942 ch=NavigateUpScrollClipViews(ch);
1943 if (isview && !(flags&SWP_NOZORDER))
1945 NSView *v = (NSView *)ch;
1946 NSView *par = [v superview];
1947 NSArray *subs = [par subviews];
1948 NSInteger idx = [subs indexOfObjectIdenticalTo:v], cnt=[subs count];
1950 NSView *viewafter = NULL;
1951 NSWindowOrderingMode omode = NSWindowAbove;
1953 if (cnt>1 && hwndAfter != (HWND)ch)
1955 if (hwndAfter==HWND_TOPMOST||hwndAfter==HWND_NOTOPMOST)
1958 else if (hwndAfter == HWND_TOP)
1960 if (idx<cnt-1) viewafter = [subs objectAtIndex:cnt-1];
1962 else if (hwndAfter == HWND_BOTTOM)
1964 if (idx>0) viewafter = [subs objectAtIndex:0];
1965 omode = NSWindowBelow;
1969 NSInteger a=[subs indexOfObjectIdenticalTo:(NSView *)hwndAfter];
1970 if (a != NSNotFound && a != (idx-1)) viewafter = (NSView *)hwndAfter;
1976 HWND h = GetCapture();
1977 if (!h || (h!=(HWND)v && !IsChild((HWND)v,h))) // if this window is captured don't reorder!
1979 NSView *oldfoc = (NSView*)[[v window] firstResponder];
1980 if (!oldfoc || ![oldfoc isKindOfClass:[NSView class]] ||
1981 (oldfoc != v && ![oldfoc isDescendantOf:v])) oldfoc=NULL;
1983 // better way to do this? maybe :/
1985 [v removeFromSuperviewWithoutNeedingDisplay];
1986 [par addSubview:v positioned:omode relativeTo:viewafter];
1989 if (oldfoc) [[v window] makeFirstResponder:oldfoc];
1994 NSRect f=[ch frame];
1996 if (!(flags&SWP_NOMOVE))
1998 f.origin.x=(float)x;
1999 f.origin.y=(float)y;
2002 if (!(flags&SWP_NOSIZE))
2004 f.size.width=(float)cx;
2005 f.size.height=(float)cy;
2006 if (f.size.height<0)f.size.height=-f.size.height;
2013 NSSize mins=[ch minSize];
2014 NSSize maxs=[ch maxSize];
2015 if (f.size.width < mins.width) f.size.width=mins.width;
2016 else if (f.size.width > maxs.width) f.size.width=maxs.width;
2017 if (f.size.height < mins.height) f.size.height=mins.height;
2018 else if (f.size.height> maxs.height) f.size.height=maxs.height;
2019 [ch setFrame:f display:NO];
2024 // this doesnt seem to actually be a good idea anymore
2025 // if ([[ch window] contentView] != ch && ![[ch superview] isFlipped])
2026 // f.origin.y -= f.size.height;
2028 if ([ch isKindOfClass:[NSScrollView class]])
2030 NSView *cv=[ch documentView];
2031 if (cv && [cv isKindOfClass:[NSTextView class]])
2033 NSRect fr=[cv frame];
2034 NSSize sz=[ch contentSize];
2036 if (![ch hasHorizontalScroller]) {a ++; fr.size.width=sz.width; }
2037 if (![ch hasVerticalScroller]) { a++; fr.size.height=sz.height; }
2038 if (a) [cv setFrame:fr];
2048 BOOL EnumWindows(BOOL (*proc)(HWND, LPARAM), LPARAM lp)
2050 NSArray *ch=[NSApp windows];
2052 const NSInteger n=[ch count];
2053 for(NSInteger x=0;x<n; x ++)
2055 NSWindow *w = [ch objectAtIndex:x];
2056 if (!proc((HWND)[w contentView],lp))
2067 HWND GetWindow(HWND hwnd, int what)
2069 if (!hwnd) return 0;
2072 if ([(id)hwnd isKindOfClass:[NSWindow class]]) hwnd=(HWND)[(id)hwnd contentView];
2073 if (!hwnd || ![(id)hwnd isKindOfClass:[NSView class]]) return 0;
2075 NSView *v=(NSView *)hwnd;
2076 if (what == GW_CHILD)
2078 NSArray *ar=[v subviews];
2079 if (ar && [ar count]>0)
2081 return (HWND)[ar objectAtIndex:0];
2085 if (what == GW_OWNER)
2087 v=NavigateUpScrollClipViews(v);
2088 if ([[v window] contentView] == v)
2090 if ([[v window] respondsToSelector:@selector(swellGetOwner)])
2092 return (HWND)[(SWELL_ModelessWindow*)[v window] swellGetOwner];
2096 return (HWND)[v superview];
2099 if (what >= GW_HWNDFIRST && what <= GW_HWNDPREV)
2101 v=NavigateUpScrollClipViews(v);
2102 if ([[v window] contentView] == v)
2104 if (what <= GW_HWNDLAST) return (HWND)hwnd; // content view is only window
2106 return 0; // we're the content view so cant do next/prev
2108 NSView *par=[v superview];
2111 NSArray *ar=[par subviews];
2113 if (ar && (cnt=[ar count]) > 0)
2115 if (what == GW_HWNDFIRST)
2116 return (HWND)[ar objectAtIndex:0];
2117 if (what == GW_HWNDLAST)
2118 return (HWND)[ar objectAtIndex:(cnt-1)];
2120 NSInteger idx=[ar indexOfObjectIdenticalTo:v];
2121 if (idx == NSNotFound) return 0;
2123 if (what==GW_HWNDNEXT) idx++;
2124 else if (what==GW_HWNDPREV) idx--;
2126 if (idx<0 || idx>=cnt) return 0;
2128 return (HWND)[ar objectAtIndex:idx];
2138 HWND GetParent(HWND hwnd)
2141 if (hwnd && [(id)hwnd isKindOfClass:[NSView class]])
2143 hwnd=(HWND)NavigateUpScrollClipViews((NSView *)hwnd);
2145 NSView *cv=[[(NSView *)hwnd window] contentView];
2146 if (cv == (NSView *)hwnd) hwnd=(HWND)[(NSView *)hwnd window]; // passthrough to get window parent
2149 HWND h=(HWND)[(NSView *)hwnd superview];
2154 if (hwnd && [(id)hwnd isKindOfClass:[NSWindow class]])
2156 HWND h= (HWND)[(NSWindow *)hwnd parentWindow];
2157 if (h) h=(HWND)[(NSWindow *)h contentView];
2161 if (hwnd && [(id)hwnd respondsToSelector:@selector(swellGetOwner)])
2163 HWND h= (HWND)[(SWELL_ModelessWindow *)hwnd swellGetOwner];
2164 if (h && [(id)h isKindOfClass:[NSWindow class]]) h=(HWND)[(NSWindow *)h contentView];
2172 HWND SetParent(HWND hwnd, HWND newPar)
2175 NSView *v=(NSView *)hwnd;
2176 if (!v || ![(id)v isKindOfClass:[NSView class]]) return 0;
2177 v=NavigateUpScrollClipViews(v);
2179 if ([(id)hwnd isKindOfClass:[NSView class]])
2181 NSView *tv=(NSView *)hwnd;
2182 if ([[tv window] contentView] == tv) // if we're reparenting a contentview (aka top level window)
2184 if (!newPar) return NULL;
2186 NSView *npv = (NSView *)newPar;
2187 if ([npv isKindOfClass:[NSWindow class]]) npv=[(NSWindow *)npv contentView];
2188 if (!npv || ![npv isKindOfClass:[NSView class]])
2191 char oldtitle[2048];
2193 GetWindowText(hwnd,oldtitle,sizeof(oldtitle));
2195 NSWindow *oldwnd = [tv window];
2197 if ([oldwnd respondsToSelector:@selector(swellGetOwner)]) oldown=[(SWELL_ModelessWindow*)oldwnd swellGetOwner];
2199 if ([tv isKindOfClass:[SWELL_hwndChild class]]) ((SWELL_hwndChild*)tv)->m_lastTopLevelOwner = oldown;
2202 SWELL_hwndChild *tmpview = [[SWELL_hwndChild alloc] initChild:nil Parent:(NSView *)oldwnd dlgProc:nil Param:0];
2205 [npv addSubview:tv];
2208 DestroyWindow((HWND)oldwnd); // close old window since its no longer used
2209 if (oldtitle[0]) SetWindowText(hwnd,oldtitle);
2212 else if (!newPar) // not content view, not parent (so making it a top level modeless dialog)
2214 char oldtitle[2048];
2216 GetWindowText(hwnd,oldtitle,sizeof(oldtitle));
2219 [tv removeFromSuperview];
2222 unsigned int wf=(NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask|NSResizableWindowMask);
2223 if ([tv respondsToSelector:@selector(swellCreateWindowFlags)])
2224 wf=(unsigned int)[(SWELL_hwndChild *)tv swellCreateWindowFlags];
2227 if ([tv isKindOfClass:[SWELL_hwndChild class]])
2229 id oldown = ((SWELL_hwndChild*)tv)->m_lastTopLevelOwner;
2232 NSArray *ch=[NSApp windows];
2233 const NSInteger n = [ch count];
2234 for(NSInteger x=0;x<n && !newOwner; x ++)
2236 NSWindow *w = [ch objectAtIndex:x];
2237 if (w == (NSWindow *)oldown || [w contentView] == (NSView *)oldown) newOwner = (HWND)w;
2242 HWND SWELL_CreateModelessFrameForWindow(HWND childW, HWND ownerW, unsigned int);
2243 HWND bla=SWELL_CreateModelessFrameForWindow((HWND)tv,(HWND)newOwner,wf);
2244 // create a new modeless frame
2248 [(NSWindow *)bla display];
2252 if (oldtitle[0]) SetWindowText(hwnd,oldtitle);
2258 HWND ret=(HWND) [v superview];
2262 [v removeFromSuperview];
2264 NSView *np=(NSView *)newPar;
2265 if (np && [np isKindOfClass:[NSWindow class]]) np=[(NSWindow *)np contentView];
2267 if (np && [np isKindOfClass:[NSView class]])
2278 int IsChild(HWND hwndParent, HWND hwndChild)
2280 if (!hwndParent || !hwndChild || hwndParent == hwndChild) return 0;
2282 id par=(id)hwndParent;
2283 id ch=(id)hwndChild;
2284 if (![ch isKindOfClass:[NSView class]]) return 0;
2285 if ([par isKindOfClass:[NSWindow class]])
2287 return [ch window] == par;
2289 else if ([par isKindOfClass:[NSView class]])
2291 return !![ch isDescendantOf:par];
2297 HWND GetForegroundWindow()
2300 NSWindow *window=[NSApp keyWindow];
2301 if (!window) return 0;
2302 id ret=[window firstResponder];
2303 if (ret && [ret isKindOfClass:[NSView class]])
2305 // if (ret == [window contentView]) return (HWND) window;
2308 return (HWND)window;
2316 NSWindow *window=[NSApp keyWindow];
2317 if (!window) return 0;
2318 id ret=[window firstResponder];
2319 if (ret && [ret isKindOfClass:[NSView class]])
2321 // if (ret == [window contentView]) return (HWND) window;
2323 if ([ret isKindOfClass:[NSTextView class]] && [ret superview] && [[ret superview] superview])
2325 NSView* v = [[ret superview] superview];
2326 if ([v isKindOfClass:[NSTextField class]]) return (HWND) v;
2335 bool IsEquivalentTextView(HWND h1, HWND h2)
2337 if (!h1 || !h2) return false;
2338 if (h1 == h2) return true;
2340 NSView* v1 = (NSView*)h1;
2341 NSView* v2 = (NSView*)h2;
2342 if ([v1 isKindOfClass:[NSTextField class]] && [v2 isKindOfClass:[NSTextView class]])
2348 if ([v1 isKindOfClass: [NSTextView class]] && [v2 isKindOfClass:[NSTextField class]])
2350 if ([v1 superview] && [[v1 superview] superview] && [[[v1 superview] superview] superview] == v2) return true;
2358 BOOL SetDlgItemText(HWND hwnd, int idx, const char *text)
2360 NSView *obj=(NSView *)(idx ? GetDlgItem(hwnd,idx) : hwnd);
2361 if (!obj) return false;
2365 if ([(id)obj isKindOfClass:[NSView class]] && (nswnd=[(NSView *)obj window]) && [nswnd contentView]==(id)obj)
2367 SetDlgItemText((HWND)nswnd,0,text); // also set window if setting content view
2370 if ([obj respondsToSelector:@selector(onSwellSetText:)])
2372 [(SWELL_hwndChild*)obj onSwellSetText:text];
2377 NSString *lbl=(NSString *)SWELL_CStringToCFString(text);
2378 if ([obj isKindOfClass:[NSWindow class]] || [obj isKindOfClass:[NSButton class]]) [(NSButton*)obj setTitle:lbl];
2379 else if ([obj isKindOfClass:[NSControl class]])
2381 [(NSControl*)obj setStringValue:lbl];
2382 if ([obj isKindOfClass:[NSTextField class]] && [(NSTextField *)obj isEditable])
2384 SendMessage(GetParent((HWND)obj),WM_COMMAND,[(NSControl *)obj tag]|(EN_CHANGE<<16),(LPARAM)obj);
2387 else if ([obj isKindOfClass:[NSText class]])
2389 // todo if there is a way to find out that the window's NSTextField is already assigned
2390 // to another field, restore the assignment afterwards
2391 [(NSText*)obj setString:lbl];
2392 [obj setNeedsDisplay:YES]; // required on Sierra, it seems -- if the parent is hidden (e.g. DialogBox() + WM_INITDIALOG), the view is not drawn
2394 else if ([obj isKindOfClass:[NSBox class]])
2396 [(NSBox *)obj setTitle:lbl];
2409 BOOL GetDlgItemText(HWND hwnd, int idx, char *text, int textlen)
2412 NSView *pvw=(NSView *)(idx?GetDlgItem(hwnd,idx) : hwnd);
2413 if (!pvw) return false;
2417 if ([(id)pvw isKindOfClass:[NSView class]] && [[(id)pvw window] contentView] == pvw)
2419 pvw=(NSView *)[(id)pvw window];
2422 if ([(id)pvw respondsToSelector:@selector(onSwellGetText)])
2424 const char *p=(const char *)[(SWELL_hwndChild*)pvw onSwellGetText];
2425 lstrcpyn_safe(text,p?p:"",textlen);
2431 if ([pvw isKindOfClass:[NSButton class]]||[pvw isKindOfClass:[NSWindow class]]) s=[((NSButton *)pvw) title];
2432 else if ([pvw isKindOfClass:[NSControl class]]) s=[((NSControl *)pvw) stringValue];
2433 else if ([pvw isKindOfClass:[NSText class]]) s=[(NSText*)pvw string];
2434 else if ([pvw isKindOfClass:[NSBox class]]) s=[(NSBox *)pvw title];
2437 if (s) SWELL_CFStringToCString(s,text,textlen);
2438 // [s getCString:text maxLength:textlen];
2445 void CheckDlgButton(HWND hwnd, int idx, int check)
2447 NSView *pvw=(NSView *)GetDlgItem(hwnd,idx);
2449 if ([pvw isKindOfClass:[NSButton class]])
2450 [(NSButton*)pvw setState:(check&BST_INDETERMINATE)?NSMixedState:((check&BST_CHECKED)?NSOnState:NSOffState)];
2454 int IsDlgButtonChecked(HWND hwnd, int idx)
2456 NSView *pvw=(NSView *)GetDlgItem(hwnd,idx);
2457 if (pvw && [pvw isKindOfClass:[NSButton class]])
2459 NSInteger a=[(NSButton*)pvw state];
2460 if (a==NSMixedState) return BST_INDETERMINATE;
2461 return a!=NSOffState;
2466 void SWELL_TB_SetPos(HWND hwnd, int idx, int pos)
2468 NSSlider *p=(NSSlider *)GetDlgItem(hwnd,idx);
2469 if (p && [p isKindOfClass:[NSSlider class]])
2471 [p setDoubleValue:(double)pos];
2475 sendSwellMessage(p,TBM_SETPOS,1,pos);
2479 void SWELL_TB_SetRange(HWND hwnd, int idx, int low, int hi)
2481 NSSlider *p=(NSSlider *)GetDlgItem(hwnd,idx);
2482 if (p && [p isKindOfClass:[NSSlider class]])
2484 [p setMinValue:low];
2489 sendSwellMessage(p,TBM_SETRANGE,1,((low&0xffff)|(hi<<16)));
2494 int SWELL_TB_GetPos(HWND hwnd, int idx)
2496 NSSlider *p=(NSSlider *)GetDlgItem(hwnd,idx);
2497 if (p && [p isKindOfClass:[NSSlider class]])
2499 return (int) ([p doubleValue]+0.5);
2503 return (int) sendSwellMessage(p,TBM_GETPOS,0,0);
2508 void SWELL_TB_SetTic(HWND hwnd, int idx, int pos)
2510 NSSlider *p=(NSSlider *)GetDlgItem(hwnd,idx);
2511 sendSwellMessage(p,TBM_SETTIC,0,pos);
2514 void SWELL_CB_DeleteString(HWND hwnd, int idx, int wh)
2516 NSComboBox *p=(NSComboBox *)GetDlgItem(hwnd,idx);
2518 if ([p isKindOfClass:[SWELL_ComboBox class]])
2520 if (wh>=0 && wh<[p numberOfItems])
2522 [p removeItemAtIndex:wh];
2523 if (((SWELL_ComboBox*)p)->m_ids) ((SWELL_ComboBox*)p)->m_ids->Delete(wh);
2526 else if ( [p isKindOfClass:[NSPopUpButton class]])
2528 NSMenu *menu = [p menu];
2531 if (wh >= 0 && wh < [menu numberOfItems])
2532 [menu removeItemAtIndex:wh];
2538 int SWELL_CB_FindString(HWND hwnd, int idx, int startAfter, const char *str, bool exact)
2540 NSComboBox *p=(NSComboBox *)GetDlgItem(hwnd,idx);
2543 int pos = startAfter;
2547 const size_t l1len = strlen(str);
2548 const int ni=(int)[p numberOfItems];
2550 if ([p isKindOfClass:[NSComboBox class]])
2554 NSString *s=[p itemObjectValueAtIndex:pos];
2558 SWELL_CFStringToCString(s,buf,sizeof(buf));
2559 if (exact ? !stricmp(str,buf) : !strnicmp(str,buf,l1len))
2568 NSMenuItem *i=[(NSPopUpButton *)p itemAtIndex:pos];
2571 NSString *s=[i title];
2575 SWELL_CFStringToCString(s,buf,sizeof(buf));
2576 if (exact ? !stricmp(str,buf) : !strnicmp(str,buf,l1len))
2585 int SWELL_CB_GetItemText(HWND hwnd, int idx, int item, char *buf, int bufsz)
2587 NSComboBox *p=(NSComboBox *)GetDlgItem(hwnd,idx);
2590 if (!p) return CB_ERR;
2591 const int ni = (int)[p numberOfItems];
2592 if (item < 0 || item >= ni) return CB_ERR;
2594 if ([p isKindOfClass:[NSComboBox class]])
2596 NSString *s=[p itemObjectValueAtIndex:item];
2599 if (!buf) return (int) ([s lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 64);
2601 SWELL_CFStringToCString(s,buf,bufsz);
2607 NSMenuItem *i=[(NSPopUpButton *)p itemAtIndex:item];
2610 NSString *s=[i title];
2613 if (!buf) return (int) ([s lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 64);
2615 SWELL_CFStringToCString(s,buf,bufsz);
2624 int SWELL_CB_InsertString(HWND hwnd, int idx, int pos, const char *str)
2626 NSString *label=(NSString *)SWELL_CStringToCFString(str);
2627 NSComboBox *p=(NSComboBox *)GetDlgItem(hwnd,idx);
2630 bool isAppend=false;
2631 const int ni = (int)[p numberOfItems];
2637 else if (pos < 0) pos=0;
2638 else if (pos > ni) pos=ni;
2641 if ([p isKindOfClass:[SWELL_ComboBox class]])
2643 if (isAppend && (((int)[(SWELL_ComboBox*)p getSwellStyle]) & CBS_SORT))
2645 pos=(int)arr_bsearch_mod(label,[p objectValues],_nsStringSearchProc);
2649 [p addItemWithObjectValue:label];
2651 [p insertItemWithObjectValue:label atIndex:pos];
2653 if (((SWELL_ComboBox*)p)->m_ids) ((SWELL_ComboBox*)p)->m_ids->Insert(pos,(char*)0);
2654 [p setNumberOfVisibleItems:(ni+1)];
2658 NSMenu *menu = [(NSPopUpButton *)p menu];
2661 const bool needclearsel = [p indexOfSelectedItem] < 0;
2662 if (isAppend && [p respondsToSelector:@selector(getSwellStyle)] && (((int)[(SWELL_PopUpButton*)p getSwellStyle]) & CBS_SORT))
2664 pos=(int)arr_bsearch_mod(label,[menu itemArray],_nsMenuSearchProc);
2666 NSMenuItem *item=[menu insertItemWithTitle:label action:NULL keyEquivalent:@"" atIndex:pos];
2667 [item setEnabled:YES];
2668 if (needclearsel) [(NSPopUpButton *)p selectItemAtIndex:-1];
2676 int SWELL_CB_AddString(HWND hwnd, int idx, const char *str)
2678 return SWELL_CB_InsertString(hwnd,idx,-1000,str);
2681 int SWELL_CB_GetCurSel(HWND hwnd, int idx)
2683 NSComboBox *p=(NSComboBox *)GetDlgItem(hwnd,idx);
2685 return (int)[p indexOfSelectedItem];
2688 void SWELL_CB_SetCurSel(HWND hwnd, int idx, int item)
2690 NSComboBox *cb = (NSComboBox *)GetDlgItem(hwnd,idx);
2693 if (item < 0 || item >= [cb numberOfItems])
2695 // combo boxes can be NSComboBox or NSPopupButton, NSComboBox needs
2696 // a different deselect method (selectItemAtIndex:-1 throws an exception)
2697 if ([cb isKindOfClass:[NSComboBox class]])
2699 const NSInteger sel = [cb indexOfSelectedItem];
2700 if (sel>=0) [cb deselectItemAtIndex:sel];
2702 else if ([cb isKindOfClass:[NSPopUpButton class]])
2703 [(NSPopUpButton*)cb selectItemAtIndex:-1];
2706 [cb selectItemAtIndex:item];
2709 int SWELL_CB_GetNumItems(HWND hwnd, int idx)
2711 NSComboBox *p=(NSComboBox *)GetDlgItem(hwnd,idx);
2713 return (int)[p numberOfItems];
2718 void SWELL_CB_SetItemData(HWND hwnd, int idx, int item, LONG_PTR data)
2720 id cb=(id)GetDlgItem(hwnd,idx);
2723 if ([cb isKindOfClass:[NSPopUpButton class]])
2725 if (item < 0 || item >= [cb numberOfItems]) return;
2726 NSMenuItem *it=[(NSPopUpButton*)cb itemAtIndex:item];
2729 SWELL_DataHold *p=[[SWELL_DataHold alloc] initWithVal:(void *)data];
2730 [it setRepresentedObject:p];
2733 else if ([cb isKindOfClass:[SWELL_ComboBox class]])
2735 if (item < 0 || item >= [cb numberOfItems]) return;
2736 if (((SWELL_ComboBox*)cb)->m_ids) ((SWELL_ComboBox*)cb)->m_ids->Set(item,(char*)data);
2740 LONG_PTR SWELL_CB_GetItemData(HWND hwnd, int idx, int item)
2742 id cb=(id)GetDlgItem(hwnd,idx);
2744 if ([cb isKindOfClass:[NSPopUpButton class]])
2746 if (item < 0 || item >= [cb numberOfItems]) return 0;
2747 NSMenuItem *it=[(NSPopUpButton*)cb itemAtIndex:item];
2749 id p= [it representedObject];
2750 if (!p || ![p isKindOfClass:[SWELL_DataHold class]]) return 0;
2751 return (LONG_PTR) (void *)[p getValue];
2753 else if ([cb isKindOfClass:[SWELL_ComboBox class]])
2755 if (item < 0 || item >= [cb numberOfItems]) return 0;
2756 if (((SWELL_ComboBox*)cb)->m_ids) return (LONG_PTR) ((SWELL_ComboBox*)cb)->m_ids->Get(item);
2761 void SWELL_CB_Empty(HWND hwnd, int idx)
2763 id cb=(id)GetDlgItem(hwnd,idx);
2765 if ([cb isKindOfClass:[NSPopUpButton class]] ||
2766 [cb isKindOfClass:[NSComboBox class]]) [cb removeAllItems];
2768 if ([cb isKindOfClass:[SWELL_ComboBox class]])
2770 if (((SWELL_ComboBox*)cb)->m_ids) ((SWELL_ComboBox*)cb)->m_ids->Empty();
2775 BOOL SetDlgItemInt(HWND hwnd, int idx, int val, int issigned)
2778 sprintf(buf,issigned?"%d":"%u",val);
2779 return SetDlgItemText(hwnd,idx,buf);
2782 int GetDlgItemInt(HWND hwnd, int idx, BOOL *translated, int issigned)
2785 if (!GetDlgItemText(hwnd,idx,buf,sizeof(buf)))
2787 if (translated) *translated=0;
2791 while (*p == ' ' || *p == '\t') p++;
2793 if ((a<0 && !issigned) || (!a && p[0] != '0')) { if (translated) *translated=0; return 0; }
2794 if (translated) *translated=1;
2798 void SWELL_HideApp()
2804 BOOL SWELL_GetGestureInfo(LPARAM lParam, GESTUREINFO* gi)
2806 if (!lParam || !gi) return FALSE;
2807 memcpy(gi, (GESTUREINFO*)lParam, sizeof(GESTUREINFO));
2812 void ShowWindow(HWND hwnd, int cmd)
2816 if (pid && [pid isKindOfClass:[NSWindow class]])
2818 if (cmd == SW_SHOWNA && [pid isKindOfClass:[SWELL_ModelessWindow class]])
2820 if (((SWELL_ModelessWindow *)pid)->m_wantInitialKeyWindowOnShow)
2822 ((SWELL_ModelessWindow *)pid)->m_wantInitialKeyWindowOnShow=false;
2828 [pid makeKeyAndOrderFront:pid];
2830 else if (cmd==SW_SHOWNA)
2832 [pid orderFront:pid];
2834 else if (cmd==SW_HIDE)
2838 else if (cmd == SW_SHOWMINIMIZED)
2840 // this ought to work
2841 //if ([NSApp mainWindow] == pid)
2843 // [NSApp hide:pid];
2847 [pid miniaturize:pid];
2852 if (!pid || ![pid isKindOfClass:[NSView class]]) return;
2854 pid=NavigateUpScrollClipViews(pid);
2860 [((NSView *)pid) setHidden:NO];
2864 NSWindow *pw=[pid window];
2865 if (pw && [NSApp keyWindow] == pw)
2867 id foc=[pw firstResponder];
2868 if (foc && (foc == pid || IsChild((HWND)pid,(HWND)foc)))
2870 HWND h=GetParent((HWND)pid);
2874 if (![((NSView *)pid) isHidden])
2876 if ((NSView *)pid != [pw contentView])
2878 HWND par = (HWND) [(NSView *)pid superview];
2882 GetWindowRect((HWND)pid,&r);
2883 ScreenToClient(par,(LPPOINT)&r);
2884 ScreenToClient(par,((LPPOINT)&r)+1);
2885 InvalidateRect(par,&r,FALSE);
2888 [((NSView *)pid) setHidden:YES];
2895 if ((nswnd=[(NSView *)pid window]) && [nswnd contentView]==(id)pid)
2897 ShowWindow((HWND)nswnd,cmd);
2901 void *SWELL_ModalWindowStart(HWND hwnd)
2903 if (hwnd && [(id)hwnd isKindOfClass:[NSView class]]) hwnd=(HWND)[(NSView *)hwnd window];
2904 if (!hwnd) return 0;
2905 return (void *)[NSApp beginModalSessionForWindow:(NSWindow *)hwnd];
2908 bool SWELL_ModalWindowRun(void *ctx, int *ret) // returns false and puts retval in *ret when done
2910 if (!ctx) return false;
2911 NSInteger r=[NSApp runModalSession:(NSModalSession)ctx];
2912 if (r==NSRunContinuesResponse) return true;
2913 if (ret) *ret=(int)r;
2917 void SWELL_ModalWindowEnd(void *ctx)
2921 if ([NSApp runModalSession:(NSModalSession)ctx] == NSRunContinuesResponse)
2924 while ([NSApp runModalSession:(NSModalSession)ctx]==NSRunContinuesResponse) Sleep(10);
2926 [NSApp endModalSession:(NSModalSession)ctx];
2930 void SWELL_CloseWindow(HWND hwnd)
2932 if (hwnd && [(id)hwnd isKindOfClass:[NSWindow class]])
2934 [((NSWindow*)hwnd) close];
2936 else if (hwnd && [(id)hwnd isKindOfClass:[NSView class]])
2938 [[(NSView*)hwnd window] close];
2943 #include "swell-dlggen.h"
2945 static id m_make_owner;
2946 static NSRect m_transform;
2947 static float m_parent_h;
2948 static bool m_doautoright;
2949 static NSRect m_lastdoauto;
2950 static bool m_sizetofits;
2951 static int m_make_radiogroupcnt;
2953 #define ACTIONTARGET (m_make_owner)
2955 void SWELL_MakeSetCurParms(float xscale, float yscale, float xtrans, float ytrans, HWND parent, bool doauto, bool dosizetofit)
2957 m_make_radiogroupcnt=0;
2958 m_sizetofits=dosizetofit;
2959 m_lastdoauto.origin.x = 0;
2960 m_lastdoauto.origin.y = -100;
2961 m_lastdoauto.size.width = 0;
2962 m_doautoright=doauto;
2963 m_transform.origin.x=xtrans;
2964 m_transform.origin.y=ytrans;
2965 m_transform.size.width=xscale;
2966 m_transform.size.height=yscale;
2967 m_make_owner=(id)parent;
2968 if ([m_make_owner isKindOfClass:[NSWindow class]]) m_make_owner=[(NSWindow *)m_make_owner contentView];
2970 if ([(id)m_make_owner isKindOfClass:[NSView class]])
2972 m_parent_h=[(NSView *)m_make_owner bounds].size.height;
2973 if (m_transform.size.height > 0 && [(id)parent isFlipped])
2974 m_transform.size.height*=-1;
2978 static void UpdateAutoCoords(NSRect r)
2980 m_lastdoauto.size.width=r.origin.x + r.size.width - m_lastdoauto.origin.x;
2983 static NSRect MakeCoords(int x, int y, int w, int h, bool wantauto, bool ignorevscaleheight=false)
2987 return NSMakeRect(-x,-y,-w,-h);
2989 float ysc=m_transform.size.height;
2990 float ysc2 = ignorevscaleheight ? 1.0 : ysc;
2991 int newx=(int)((x+m_transform.origin.x)*m_transform.size.width + 0.5);
2992 int newy=(int)((ysc >= 0.0 ? m_parent_h - ((y+m_transform.origin.y) )*ysc + h*ysc2 :
2993 ((y+m_transform.origin.y) )*-ysc) + 0.5);
2995 NSRect ret= NSMakeRect(newx,
2997 (int) (w*m_transform.size.width+0.5),
2998 (int) (h*fabs(ysc2)+0.5));
3001 if (wantauto && m_doautoright)
3003 float dx = ret.origin.x - m_lastdoauto.origin.x;
3004 if (fabs(dx)<32 && m_lastdoauto.origin.y >= ret.origin.y && m_lastdoauto.origin.y < ret.origin.y + ret.size.height)
3006 ret.origin.x += (int) m_lastdoauto.size.width;
3009 m_lastdoauto.origin.x = oret.origin.x + oret.size.width;
3010 m_lastdoauto.origin.y = ret.origin.y + ret.size.height*0.5;
3011 m_lastdoauto.size.width=0;
3016 static const double minwidfontadjust=1.81;
3017 #define TRANSFORMFONTSIZE (m_transform.size.width<1?8:m_transform.size.width<2?10:12)
3018 /// these are for swell-dlggen.h
3019 HWND SWELL_MakeButton(int def, const char *label, int idx, int x, int y, int w, int h, int flags)
3021 UINT_PTR a=(UINT_PTR)label;
3022 if (a < 65536) label = "ICONTEMP";
3023 SWELL_Button *button=[[SWELL_Button alloc] init];
3024 if (flags & BS_BITMAP)
3026 SWELL_ImageButtonCell * cell = [[SWELL_ImageButtonCell alloc] init];
3027 [button setCell:cell];
3031 if (m_transform.size.width < minwidfontadjust)
3033 [button setFont:[NSFont systemFontOfSize:TRANSFORMFONTSIZE]];
3036 [button setTag:idx];
3037 if (g_swell_want_nice_style==1)
3038 [button setBezelStyle:NSShadowlessSquareBezelStyle ];
3040 [button setBezelStyle:NSRoundedBezelStyle ];
3041 NSRect tr=MakeCoords(x,y,w,h,true);
3044 if (g_swell_want_nice_style!=1 && tr.size.height >= 18 && tr.size.height<24)
3049 [button setFrame:tr];
3050 NSString *labelstr=(NSString *)SWELL_CStringToCFString_FilterPrefix(label);
3051 [button setTitle:labelstr];
3052 [button setTarget:ACTIONTARGET];
3053 [button setAction:@selector(onSwellCommand:)];
3054 if (flags & BS_LEFT) [button setAlignment:NSLeftTextAlignment];
3055 if (flags&SWELL_NOT_WS_VISIBLE) [button setHidden:YES];
3056 [m_make_owner addSubview:button];
3057 if (m_doautoright) UpdateAutoCoords([button frame]);
3058 if (def) [[m_make_owner window] setDefaultButtonCell:(NSButtonCell*)button];
3061 return (HWND) button;
3065 @implementation SWELL_TextView
3067 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
3074 -(void) setTag:(NSInteger)tag
3079 -(LRESULT)onSwellMessage:(UINT)msg p1:(WPARAM)wParam p2:(LPARAM)lParam
3084 if (wParam == SB_TOP)
3086 [self scrollRangeToVisible:NSMakeRange(0, 0)];
3088 else if (wParam == SB_BOTTOM)
3090 NSUInteger len = [[self string] length];
3091 [self scrollRangeToVisible:NSMakeRange(len, 0)];
3097 NSUInteger sl = [[self string] length];
3098 if (wParam == -1) lParam = wParam = 0;
3099 else if (lParam == -1) lParam = sl;
3101 if (wParam>sl)wParam=sl;
3102 if (lParam>sl)lParam=sl;
3103 [self setSelectedRange:NSMakeRange(wParam, lParam>wParam ? lParam-wParam : 0)];
3109 NSRange r = [self selectedRange];
3110 if (wParam) *(int*)wParam = (int)r.location;
3111 if (lParam) *(int*)lParam = (int)(r.location+r.length);
3117 HGDIOBJ__* obj = (HGDIOBJ__*)wParam;
3118 if (obj && obj->type == TYPE_FONT)
3120 if (obj->ct_FontRef)
3122 [self setFont:(NSFont *)obj->ct_FontRef];
3124 #ifdef SWELL_ATSUI_TEXT_SUPPORT
3125 else if (obj->atsui_font_style)
3127 ATSUFontID fontid = kATSUInvalidFontID;
3129 Boolean isbold = NO;
3130 Boolean isital = NO;
3131 Boolean isunder = NO;
3132 if (ATSUGetAttribute(obj->atsui_font_style, kATSUFontTag, sizeof(ATSUFontID), &fontid, 0) == noErr &&
3133 ATSUGetAttribute(obj->atsui_font_style, kATSUSizeTag, sizeof(Fixed), &fsize, 0) == noErr && fsize &&
3134 ATSUGetAttribute(obj->atsui_font_style, kATSUQDBoldfaceTag, sizeof(Boolean), &isbold, 0) == noErr &&
3135 ATSUGetAttribute(obj->atsui_font_style, kATSUQDItalicTag, sizeof(Boolean), &isital, 0) == noErr &&
3136 ATSUGetAttribute(obj->atsui_font_style, kATSUQDUnderlineTag, sizeof(Boolean), &isunder, 0) == noErr)
3140 ByteCount namelen=0;
3141 if (ATSUFindFontName(fontid, kFontFullName, (FontPlatformCode)kFontNoPlatform, kFontNoScriptCode, kFontNoLanguageCode, sizeof(name), name, &namelen, 0) == noErr && name[0] && namelen)
3145 for (i = 0; i < namelen; ++i) name[i] = name[2*i];
3148 // todo bold/ital/underline
3149 NSString* str = (NSString*)SWELL_CStringToCFString(name);
3150 CGFloat sz = Fix2Long(fsize);
3151 NSFont* font = [NSFont fontWithName:str size:sz];
3155 [self setFont:font];
3168 - (BOOL)becomeFirstResponder;
3170 BOOL didBecomeFirstResponder = [super becomeFirstResponder];
3171 if (didBecomeFirstResponder) SendMessage(GetParent((HWND)self),WM_COMMAND,[self tag]|(EN_SETFOCUS<<16),(LPARAM)self);
3172 return didBecomeFirstResponder;
3177 @implementation SWELL_TextField
3178 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
3180 - (BOOL)becomeFirstResponder;
3182 BOOL didBecomeFirstResponder = [super becomeFirstResponder];
3183 if (didBecomeFirstResponder) SendMessage(GetParent((HWND)self),WM_COMMAND,[self tag]|(EN_SETFOCUS<<16),(LPARAM)self);
3184 return didBecomeFirstResponder;
3190 HWND SWELL_MakeEditField(int idx, int x, int y, int w, int h, int flags)
3192 if ((flags&WS_VSCROLL) || (flags&WS_HSCROLL)) // || (flags & ES_READONLY))
3194 SWELL_TextView *obj=[[SWELL_TextView alloc] init];
3195 [obj setEditable:(flags & ES_READONLY)?NO:YES];
3196 if (m_transform.size.width < minwidfontadjust)
3197 [obj setFont:[NSFont systemFontOfSize:TRANSFORMFONTSIZE]];
3199 [obj setDelegate:ACTIONTARGET];
3201 [obj setHorizontallyResizable:NO];
3203 if (flags & WS_VSCROLL)
3205 NSRect fr=MakeCoords(x,y,w,h,true);
3207 [obj setVerticallyResizable:YES];
3208 NSScrollView *obj2=[[NSScrollView alloc] init];
3210 if (flags&WS_VSCROLL) [obj2 setHasVerticalScroller:YES];
3211 if (flags&WS_HSCROLL)
3213 [obj2 setHasHorizontalScroller:YES];
3214 [obj setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
3215 [obj setHorizontallyResizable:YES];
3216 [[obj textContainer] setWidthTracksTextView:NO];
3217 [[obj textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
3219 [obj2 setAutohidesScrollers:YES];
3220 [obj2 setDrawsBackground:NO];
3221 [obj2 setDocumentView:obj];
3222 [m_make_owner addSubview:obj2];
3223 if (m_doautoright) UpdateAutoCoords([obj2 frame]);
3224 if (flags&SWELL_NOT_WS_VISIBLE) [obj2 setHidden:YES];
3228 memset(&tr,0,sizeof(tr));
3229 tr.size = [obj2 contentSize];
3237 [obj setFrame:MakeCoords(x,y,w,h,true)];
3238 [obj setVerticallyResizable:NO];
3239 if (flags&SWELL_NOT_WS_VISIBLE) [obj setHidden:YES];
3240 [m_make_owner addSubview:obj];
3241 if (m_doautoright) UpdateAutoCoords([obj frame]);
3249 if (flags & ES_PASSWORD) obj=[[NSSecureTextField alloc] init];
3250 else obj=[[SWELL_TextField alloc] init];
3251 [obj setEditable:(flags & ES_READONLY)?NO:YES];
3252 if (flags & ES_READONLY) [obj setSelectable:YES];
3253 if (m_transform.size.width < minwidfontadjust)
3254 [obj setFont:[NSFont systemFontOfSize:TRANSFORMFONTSIZE]];
3256 NSCell* cell = [obj cell];
3257 if (flags&ES_CENTER) [cell setAlignment:NSCenterTextAlignment];
3258 else if (flags&ES_RIGHT) [cell setAlignment:NSRightTextAlignment];
3262 [cell setScrollable:YES];
3265 [obj setTarget:ACTIONTARGET];
3266 [obj setAction:@selector(onSwellCommand:)];
3267 [obj setDelegate:ACTIONTARGET];
3269 [obj setFrame:MakeCoords(x,y,w,h,true)];
3270 if (flags&SWELL_NOT_WS_VISIBLE) [obj setHidden:YES];
3271 [m_make_owner addSubview:obj];
3272 if (m_doautoright) UpdateAutoCoords([obj frame]);
3278 HWND SWELL_MakeLabel( int align, const char *label, int idx, int x, int y, int w, int h, int flags)
3280 NSTextField *obj=[[SWELL_TextField alloc] init];
3281 [obj setEditable:NO];
3282 [obj setSelectable:NO];
3283 [obj setBordered:NO];
3284 [obj setBezeled:NO];
3285 [obj setDrawsBackground:NO];
3286 if (m_transform.size.width < minwidfontadjust)
3287 [obj setFont:[NSFont systemFontOfSize:TRANSFORMFONTSIZE]];
3289 if (flags & SS_NOTIFY)
3291 [obj setTarget:ACTIONTARGET];
3292 [obj setAction:@selector(onSwellCommand:)];
3295 NSString *labelstr=(NSString *)SWELL_CStringToCFString_FilterPrefix(label);
3296 [obj setStringValue:labelstr];
3297 [obj setAlignment:(align<0?NSLeftTextAlignment:align>0?NSRightTextAlignment:NSCenterTextAlignment)];
3299 [[obj cell] setWraps:(h>12 ? YES : NO)];
3302 [obj setFrame:MakeCoords(x,y,w,h,true)];
3303 if (flags&SWELL_NOT_WS_VISIBLE) [obj setHidden:YES];
3304 [m_make_owner addSubview:obj];
3305 if (m_sizetofits && strlen(label)>1)[obj sizeToFit];
3306 if (m_doautoright) UpdateAutoCoords([obj frame]);
3313 HWND SWELL_MakeCheckBox(const char *name, int idx, int x, int y, int w, int h, int flags=0)
3315 return SWELL_MakeControl(name,idx,"Button",BS_AUTOCHECKBOX|flags,x,y,w,h,0);
3318 HWND SWELL_MakeListBox(int idx, int x, int y, int w, int h, int styles)
3320 HWND hw=SWELL_MakeControl("",idx,"SysListView32_LB",styles,x,y,w,h,0);
3325 GetClientRect(hw,&r);
3326 lvc.cx=300;//yer.right-r.left;
3328 ListView_InsertColumn(hw,0,&lvc);
3335 typedef struct ccprocrec
3337 SWELL_ControlCreatorProc proc;
3339 struct ccprocrec *next;
3342 static ccprocrec *m_ccprocs;
3344 void SWELL_RegisterCustomControlCreator(SWELL_ControlCreatorProc proc)
3348 ccprocrec *p=m_ccprocs;
3349 while (p && p->next)
3351 if (p->proc == proc)
3358 ccprocrec *ent = (ccprocrec*)malloc(sizeof(ccprocrec));
3367 void SWELL_UnregisterCustomControlCreator(SWELL_ControlCreatorProc proc)
3372 ccprocrec *p=m_ccprocs;
3375 if (p->proc == proc)
3379 if (lp) lp->next=p->next;
3380 else m_ccprocs=p->next;
3391 HWND SWELL_MakeControl(const char *cname, int idx, const char *classname, int style, int x, int y, int w, int h, int exstyle)
3395 NSRect wcr=MakeCoords(x,y,w,h,false);
3396 ccprocrec *p=m_ccprocs;
3399 HWND hwnd=p->proc((HWND)m_make_owner,cname,idx,classname,style,
3400 (int)(wcr.origin.x+0.5),(int)(wcr.origin.y+0.5),(int)(wcr.size.width+0.5),(int)(wcr.size.height+0.5));
3403 if (exstyle) SetWindowLong(hwnd,GWL_EXSTYLE,exstyle);
3409 if (!stricmp(classname,"SysTabControl32"))
3411 SWELL_TabView *obj=[[SWELL_TabView alloc] init];
3412 if (1) // todo: only if on 10.4 maybe?
3418 [obj setDelegate:(id)obj];
3419 [obj setAllowsTruncatedLabels:YES];
3420 [obj setNotificationWindow:ACTIONTARGET];
3422 [obj setFrame:MakeCoords(x,y,w,h,false)];
3423 if (style&SWELL_NOT_WS_VISIBLE) [obj setHidden:YES];
3424 [m_make_owner addSubview:obj];
3425 SetAllowNoMiddleManRendering((HWND)m_make_owner,FALSE);
3429 else if (!stricmp(classname, "SysListView32")||!stricmp(classname, "SysListView32_LB"))
3431 SWELL_ListView *obj = [[SWELL_ListView alloc] init];
3432 [obj setColumnAutoresizingStyle:NSTableViewNoColumnAutoresizing];
3433 [obj setFocusRingType:NSFocusRingTypeNone];
3434 [obj setDataSource:(id)obj];
3437 BOOL isLB=!stricmp(classname, "SysListView32_LB");
3438 [obj setSwellNotificationMode:isLB];
3442 [obj setHeaderView:nil];
3443 [obj setAllowsMultipleSelection:!!(style & LBS_EXTENDEDSEL)];
3447 if ((style & LVS_NOCOLUMNHEADER) || !(style & LVS_REPORT)) [obj setHeaderView:nil];
3448 [obj setAllowsMultipleSelection:!(style & LVS_SINGLESEL)];
3450 [obj setAllowsColumnReordering:NO];
3451 [obj setAllowsEmptySelection:YES];
3454 id target=ACTIONTARGET;
3455 [obj setDelegate:target];
3456 [obj setTarget:target];
3457 [obj setAction:@selector(onSwellCommand:)];
3458 if ([target respondsToSelector:@selector(swellOnControlDoubleClick:)])
3460 [obj setDoubleAction:@selector(swellOnControlDoubleClick:)];
3464 [obj setDoubleAction:@selector(onSwellCommand:)];
3466 NSScrollView *obj2=[[NSScrollView alloc] init];
3467 NSRect tr=MakeCoords(x,y,w,h,false);
3469 [obj2 setDocumentView:obj];
3470 [obj2 setHasVerticalScroller:YES];
3471 if (!isLB) [obj2 setHasHorizontalScroller:YES];
3472 [obj2 setAutohidesScrollers:YES];
3473 [obj2 setDrawsBackground:NO];
3475 if (style&SWELL_NOT_WS_VISIBLE) [obj2 setHidden:YES];
3476 [m_make_owner addSubview:obj2];
3479 if (isLB || !(style & LVS_REPORT))
3482 lvc.mask=LVCF_TEXT|LVCF_WIDTH;
3483 lvc.cx=(int)ceil(wdl_max(tr.size.width - 4.0,isLB ? 1200.0 : 300.0));
3484 lvc.pszText=(char*)"";
3485 ListView_InsertColumn((HWND)obj,0,&lvc);
3486 if (isLB && (style & LBS_OWNERDRAWFIXED))
3488 NSArray *ar=[obj tableColumns];
3490 if (ar && [ar count] && (c=[ar objectAtIndex:0]))
3492 SWELL_ODListViewCell *t=[[SWELL_ODListViewCell alloc] init];
3494 [t setOwnerControl:obj];
3502 else if (!stricmp(classname, "SysTreeView32"))
3504 SWELL_TreeView *obj = [[SWELL_TreeView alloc] init];
3505 [obj setFocusRingType:NSFocusRingTypeNone];
3506 [obj setDataSource:(id)obj];
3508 id target=ACTIONTARGET;
3509 [obj setHeaderView:nil];
3510 [obj setDelegate:target];
3511 [obj setAllowsColumnReordering:NO];
3512 [obj setAllowsMultipleSelection:NO];
3513 [obj setAllowsEmptySelection:YES];
3516 [obj setTarget:target];
3517 [obj setAction:@selector(onSwellCommand:)];
3518 if ([target respondsToSelector:@selector(swellOnControlDoubleClick:)])
3519 [obj setDoubleAction:@selector(swellOnControlDoubleClick:)];
3521 [obj setDoubleAction:@selector(onSwellCommand:)];
3522 NSScrollView *obj2=[[NSScrollView alloc] init];
3523 NSRect tr=MakeCoords(x,y,w,h,false);
3525 [obj2 setDocumentView:obj];
3526 [obj2 setHasVerticalScroller:YES];
3527 [obj2 setAutohidesScrollers:YES];
3528 [obj2 setDrawsBackground:NO];
3530 if (style&SWELL_NOT_WS_VISIBLE) [obj2 setHidden:YES];
3531 [m_make_owner addSubview:obj2];
3535 NSTableColumn *col=[[NSTableColumn alloc] init];
3536 SWELL_ListViewCell *cell = [[SWELL_ListViewCell alloc] initTextCell:@""];
3537 [col setDataCell:cell];
3540 [col setWidth:(int)ceil(wdl_max(tr.size.width,300.0))];
3541 [col setEditable:NO];
3542 [[col dataCell] setWraps:NO];
3543 [obj addTableColumn:col];
3544 [obj setOutlineTableColumn:col];
3548 /// [obj setIndentationPerLevel:10.0];
3552 else if (!stricmp(classname, "msctls_progress32"))
3554 SWELL_ProgressView *obj=[[SWELL_ProgressView alloc] init];
3555 [obj setStyle:NSProgressIndicatorBarStyle];
3556 [obj setIndeterminate:NO];
3558 [obj setFrame:MakeCoords(x,y,w,h,false)];
3559 if (style&SWELL_NOT_WS_VISIBLE) [obj setHidden:YES];
3560 [m_make_owner addSubview:obj];
3564 else if (!stricmp(classname,"Edit"))
3566 return SWELL_MakeEditField(idx,x,y,w,h,style);
3568 else if (!stricmp(classname, "static"))
3570 NSTextField *obj=[[SWELL_TextField alloc] init];
3571 [obj setEditable:NO];
3572 [obj setSelectable:NO];
3573 [obj setBordered:NO];
3574 [obj setBezeled:NO];
3575 [obj setDrawsBackground:NO];
3576 if (m_transform.size.width < minwidfontadjust)
3577 [obj setFont:[NSFont systemFontOfSize:TRANSFORMFONTSIZE]];
3579 if (cname && *cname)
3581 NSString *labelstr=(NSString *)SWELL_CStringToCFString_FilterPrefix(cname);
3582 [obj setStringValue:labelstr];
3586 if ((style&SS_TYPEMASK) == SS_LEFTNOWORDWRAP) [[obj cell] setWraps:NO];
3587 else if ((style&SS_TYPEMASK) == SS_CENTER) [[obj cell] setAlignment:NSCenterTextAlignment];
3588 else if ((style&SS_TYPEMASK) == SS_RIGHT) [[obj cell] setAlignment:NSRightTextAlignment];
3591 [obj setFrame:MakeCoords(x,y,w,h,true)];
3592 if (style&SWELL_NOT_WS_VISIBLE) [obj setHidden:YES];
3593 [m_make_owner addSubview:obj];
3594 if ((style & SS_TYPEMASK) == SS_BLACKRECT)
3596 [obj setHidden:YES];
3601 else if (!stricmp(classname,"Button"))
3603 if (style & BS_GROUPBOX)
3605 return SWELL_MakeGroupBox(cname, idx, x, y, w, h, style &~BS_GROUPBOX);
3607 if (style & BS_DEFPUSHBUTTON)
3609 return SWELL_MakeButton(1, cname, idx, x,y,w,h,style &~BS_DEFPUSHBUTTON);
3611 if (style & BS_PUSHBUTTON)
3613 return SWELL_MakeButton(0, cname, idx, x,y,w,h,style &~BS_PUSHBUTTON);
3615 SWELL_Button *button=[[SWELL_Button alloc] init];
3616 [button setTag:idx];
3617 NSRect fr=MakeCoords(x,y,w,h,true);
3618 SEL actionSel = @selector(onSwellCommand:);
3619 if ((style & 0xf) == BS_AUTO3STATE)
3621 [button setButtonType:NSSwitchButton];
3622 [button setAllowsMixedState:YES];
3624 else if ((style & 0xf) == BS_AUTOCHECKBOX)
3626 [button setButtonType:NSSwitchButton];
3627 [button setAllowsMixedState:NO];
3629 else if ((style & 0xf) == BS_AUTORADIOBUTTON)
3631 #ifdef MAC_OS_X_VERSION_10_8
3632 // Compiling with the OSX 10.8+ SDK and running on 10.8+ causes radio buttons with a common action selector to
3633 // be treated as a group. This works around that. if you need more than 8 groups (seriously?!), add the extra
3634 // functions in swell-dlg.mm and in the switch below
3638 if ((style & WS_GROUP) ||
3639 !(sv = [m_make_owner subviews]) ||
3641 !(v = [sv lastObject]) ||
3642 ![v isKindOfClass:[SWELL_Button class]] ||
3643 ([(SWELL_Button *)v swellGetRadioFlags]&2)) m_make_radiogroupcnt++;
3645 switch (m_make_radiogroupcnt & 7)
3647 case 0: actionSel = @selector(onSwellCommand0:); break;
3648 case 1: break; // default
3649 case 2: actionSel = @selector(onSwellCommand2:); break;
3650 case 3: actionSel = @selector(onSwellCommand3:); break;
3651 case 4: actionSel = @selector(onSwellCommand4:); break;
3652 case 5: actionSel = @selector(onSwellCommand5:); break;
3653 case 6: actionSel = @selector(onSwellCommand6:); break;
3654 case 7: actionSel = @selector(onSwellCommand7:); break;
3658 [button setButtonType:NSRadioButton];
3659 [button swellSetRadioFlags:(style & WS_GROUP)?3:1];
3661 else if ((style & 0xf) == BS_OWNERDRAW)
3663 SWELL_ODButtonCell *cell = [[SWELL_ODButtonCell alloc] init];
3664 [button setCell:cell];
3668 else // normal button
3670 if (style & BS_BITMAP)
3672 SWELL_ImageButtonCell * cell = [[SWELL_ImageButtonCell alloc] init];
3673 [button setCell:cell];
3676 if (style & BS_LEFT) [button setAlignment:NSLeftTextAlignment];
3677 // fr.size.width+=8;
3680 if (m_transform.size.width < minwidfontadjust)
3681 [button setFont:[NSFont systemFontOfSize:TRANSFORMFONTSIZE]];
3682 [button setFrame:fr];
3683 NSString *labelstr=(NSString *)SWELL_CStringToCFString_FilterPrefix(cname);
3684 [button setTitle:labelstr];
3685 [button setTarget:ACTIONTARGET];
3686 [button setAction:actionSel];
3687 if (style&BS_LEFTTEXT) [button setImagePosition:NSImageRight];
3688 if (style&SWELL_NOT_WS_VISIBLE) [button setHidden:YES];
3689 [m_make_owner addSubview:button];
3690 if (m_sizetofits && (style & 0xf) != BS_OWNERDRAW) [button sizeToFit];
3691 if (m_doautoright) UpdateAutoCoords([button frame]);
3694 return (HWND)button;
3696 else if (!stricmp(classname,"REAPERhfader")||!stricmp(classname,"msctls_trackbar32"))
3698 NSSlider *obj=[[NSSlider alloc] init];
3700 [obj setMinValue:0.0];
3701 [obj setMaxValue:1000.0];
3702 [obj setFrame:MakeCoords(x,y,w,h,false)];
3703 if (!stricmp(classname, "msctls_trackbar32"))
3705 [[obj cell] setControlSize:NSMiniControlSize];
3707 [obj setTarget:ACTIONTARGET];
3708 [obj setAction:@selector(onSwellCommand:)];
3709 if (style&SWELL_NOT_WS_VISIBLE) [obj setHidden:YES];
3710 [m_make_owner addSubview:obj];
3714 else if (!stricmp(classname,"COMBOBOX"))
3716 return SWELL_MakeCombo(idx, x, y, w, h, style);
3721 HWND SWELL_MakeCombo(int idx, int x, int y, int w, int h, int flags)
3723 if ((flags & 0x3) == CBS_DROPDOWNLIST)
3725 SWELL_PopUpButton *obj=[[SWELL_PopUpButton alloc] init];
3727 [obj setFont:[NSFont systemFontOfSize:10.0f]];
3728 NSRect rc=MakeCoords(x,y,w,18,true,true);
3730 [obj setSwellStyle:flags];
3732 [obj setAutoenablesItems:NO];
3733 [obj setTarget:ACTIONTARGET];
3734 [obj setAction:@selector(onSwellCommand:)];
3736 if (g_swell_want_nice_style==1)
3738 [obj setBezelStyle:NSShadowlessSquareBezelStyle ];
3739 [[obj cell] setArrowPosition:NSPopUpArrowAtBottom];
3741 if (flags&SWELL_NOT_WS_VISIBLE) [obj setHidden:YES];
3742 [m_make_owner addSubview:obj];
3743 if (m_doautoright) UpdateAutoCoords([obj frame]);
3749 SWELL_ComboBox *obj=[[SWELL_ComboBox alloc] init];
3750 [obj setFocusRingType:NSFocusRingTypeNone];
3751 [obj setFont:[NSFont systemFontOfSize:10.0f]];
3752 [obj setEditable:(flags & 0x3) == CBS_DROPDOWNLIST?NO:YES];
3753 [obj setSwellStyle:flags];
3755 [obj setFrame:MakeCoords(x,y-1,w,22,true,true)];
3756 [obj setTarget:ACTIONTARGET];
3757 [obj setAction:@selector(onSwellCommand:)];
3758 [obj setDelegate:ACTIONTARGET];
3759 if (flags&SWELL_NOT_WS_VISIBLE) [obj setHidden:YES];
3760 [m_make_owner addSubview:obj];
3761 if (m_doautoright) UpdateAutoCoords([obj frame]);
3767 @implementation SWELL_BoxView
3769 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
3775 -(void) setTag:(NSInteger)tag
3781 HWND SWELL_MakeGroupBox(const char *name, int idx, int x, int y, int w, int h, int style)
3783 SWELL_BoxView *obj=[[SWELL_BoxView alloc] init];
3785 // this just doesn't work, you can't color the border unless it's NSBoxCustom,
3786 // and I can't get it to show the title text if it's NSBoxCustom
3787 //[obj setBoxType:(NSBoxType)4]; // NSBoxCustom, so we can color the border
3788 //[obj setTitlePosition:(NSTitlePosition)2]; // NSAtTop, default but NSBoxCustom unsets it
3790 // [obj setTag:idx];
3791 if (1) // todo: only if on 10.4 maybe?
3796 NSString *labelstr=(NSString *)SWELL_CStringToCFString_FilterPrefix(name);
3797 [obj setTitle:labelstr];
3800 if (style & BS_CENTER)
3802 [[obj titleCell] setAlignment:NSCenterTextAlignment];
3804 [obj setFrame:MakeCoords(x,y,w,h,false)];
3805 [m_make_owner addSubview:obj positioned:NSWindowBelow relativeTo:nil];
3811 int TabCtrl_GetItemCount(HWND hwnd)
3813 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TabView class]]) return 0;
3814 SWELL_TabView *tv=(SWELL_TabView*)hwnd;
3815 return (int)[tv numberOfTabViewItems];
3818 BOOL TabCtrl_AdjustRect(HWND hwnd, BOOL fLarger, RECT *r)
3820 if (!r || !hwnd || ![(id)hwnd isKindOfClass:[SWELL_TabView class]]) return FALSE;
3822 int sign=fLarger?-1:1;
3823 r->left+=sign*7; // todo: correct this?
3831 BOOL TabCtrl_DeleteItem(HWND hwnd, int idx)
3833 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TabView class]]) return 0;
3834 SWELL_TabView *tv=(SWELL_TabView*)hwnd;
3835 if (idx<0 || idx>= [tv numberOfTabViewItems]) return 0;
3836 [tv removeTabViewItem:[tv tabViewItemAtIndex:idx]];
3840 int TabCtrl_InsertItem(HWND hwnd, int idx, TCITEM *item)
3842 if (!item || !hwnd || ![(id)hwnd isKindOfClass:[SWELL_TabView class]]) return -1;
3843 if (!(item->mask & TCIF_TEXT) || !item->pszText) return -1;
3844 SWELL_TabView *tv=(SWELL_TabView*)hwnd;
3846 const int ni = (int)[tv numberOfTabViewItems];
3848 else if (idx>ni) idx=ni;
3850 NSTabViewItem *tabitem=[[NSTabViewItem alloc] init];
3851 NSString *str=(NSString *)SWELL_CStringToCFString(item->pszText);
3852 [tabitem setLabel:str];
3854 id turd=[tv getNotificationWindow];
3855 [tv setNotificationWindow:nil];
3856 [tv insertTabViewItem:tabitem atIndex:idx];
3857 [tv setNotificationWindow:turd];
3862 int TabCtrl_SetCurSel(HWND hwnd, int idx)
3864 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TabView class]]) return -1;
3865 SWELL_TabView *tv=(SWELL_TabView*)hwnd;
3866 int ret=TabCtrl_GetCurSel(hwnd);
3867 if (idx>=0 && idx < [tv numberOfTabViewItems])
3869 [tv selectTabViewItemAtIndex:idx];
3874 int TabCtrl_GetCurSel(HWND hwnd)
3876 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TabView class]]) return 0;
3877 SWELL_TabView *tv=(SWELL_TabView*)hwnd;
3878 NSTabViewItem *item=[tv selectedTabViewItem];
3879 if (!item) return 0;
3880 return (int)[tv indexOfTabViewItem:item];
3883 void ListView_SetExtendedListViewStyleEx(HWND h, int mask, int style)
3886 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return;
3887 SWELL_ListView *tv=(SWELL_ListView*)h;
3889 if (mask&LVS_EX_GRIDLINES)
3892 if (style&LVS_EX_GRIDLINES)
3894 s=NSTableViewSolidVerticalGridLineMask|NSTableViewSolidHorizontalGridLineMask;
3896 [tv setGridStyleMask:s];
3899 if (mask&LVS_EX_HEADERDRAGDROP)
3901 [tv setAllowsColumnReordering:!!(style&LVS_EX_HEADERDRAGDROP)];
3905 // todo LVS_EX_FULLROWSELECT (enabled by default on OSX)
3908 void SWELL_SetListViewFastClickMask(HWND hList, int mask)
3910 if (!hList || ![(id)hList isKindOfClass:[SWELL_ListView class]]) return;
3911 SWELL_ListView *lv = (SWELL_ListView *)hList;
3912 lv->m_fastClickMask=mask;
3917 void ListView_SetImageList(HWND h, HIMAGELIST imagelist, int which)
3921 SWELL_ListView *v=(SWELL_ListView *)h;
3923 v->m_status_imagelist_type=which;
3924 v->m_status_imagelist=(WDL_PtrList<HGDIOBJ__> *)imagelist;
3925 if (v->m_cols && v->m_cols->GetSize()>0)
3927 NSTableColumn *col=(NSTableColumn*)v->m_cols->Get(0);
3928 if (![col isKindOfClass:[SWELL_StatusCell class]])
3930 SWELL_StatusCell *cell=[[SWELL_StatusCell alloc] initNewCell];
3932 [col setDataCell:cell];
3938 int ListView_GetColumnWidth(HWND h, int pos)
3940 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]]) return 0;
3941 SWELL_ListView *v=(SWELL_ListView *)h;
3942 if (!v->m_cols || pos < 0 || pos >= v->m_cols->GetSize()) return 0;
3944 NSTableColumn *col=v->m_cols->Get(pos);
3947 if ([col respondsToSelector:@selector(isHidden)] && [(SWELL_TableColumnExtensions*)col isHidden]) return 0;
3948 return (int) floor(0.5+[col width]);
3951 void ListView_InsertColumn(HWND h, int pos, const LVCOLUMN *lvc)
3953 if (!h || !lvc) return;
3954 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return;
3958 SWELL_ListView *v=(SWELL_ListView *)h;
3959 NSTableColumn *col=[[NSTableColumn alloc] init];
3960 // note, not looking at lvc->mask at all
3962 [col setEditable:NO];
3963 // [col setResizingMask:2]; // user resizable, this seems to be the default
3965 if (lvc->fmt == LVCFMT_CENTER) [[col headerCell] setAlignment:NSCenterTextAlignment];
3966 else if (lvc->fmt == LVCFMT_RIGHT) [[col headerCell] setAlignment:NSRightTextAlignment];
3968 if (!v->m_lbMode && !(v->style & LVS_NOCOLUMNHEADER))
3970 NSString *lbl=(NSString *)SWELL_CStringToCFString(lvc->pszText);
3971 [[col headerCell] setStringValue:lbl];
3975 if (!pos && v->m_status_imagelist)
3977 SWELL_StatusCell *cell=[[SWELL_StatusCell alloc] initNewCell];
3979 [col setDataCell:cell];
3984 SWELL_ListViewCell *cell = [[SWELL_ListViewCell alloc] initTextCell:@""];
3985 [col setDataCell:cell];
3988 if (lvc->fmt == LVCFMT_CENTER) [cell setAlignment:NSCenterTextAlignment];
3989 else if (lvc->fmt == LVCFMT_RIGHT) [cell setAlignment:NSRightTextAlignment];
3993 [v addTableColumn:col];
3994 v->m_cols->Add(col);
3997 if (lvc->mask&LVCF_WIDTH)
3999 ListView_SetColumnWidth(h,pos,lvc->cx);
4004 void ListView_SetColumn(HWND h, int pos, const LVCOLUMN *lvc)
4006 if (!h || !lvc || ![(id)h isKindOfClass:[SWELL_ListView class]]) return;
4007 SWELL_ListView *v=(SWELL_ListView *)h;
4008 if (!v->m_cols || pos < 0 || pos >= v->m_cols->GetSize()) return;
4010 NSTableColumn *col=v->m_cols->Get(pos);
4013 if (lvc->mask&LVCF_FMT)
4015 if (lvc->fmt == LVCFMT_LEFT) [[col headerCell] setAlignment:NSLeftTextAlignment];
4016 else if (lvc->fmt == LVCFMT_CENTER) [[col headerCell] setAlignment:NSCenterTextAlignment];
4017 else if (lvc->fmt == LVCFMT_RIGHT) [[col headerCell] setAlignment:NSRightTextAlignment];
4019 if (lvc->mask&LVCF_WIDTH)
4023 if ([col respondsToSelector:@selector(setHidden:)]) [(SWELL_TableColumnExtensions*)col setHidden:YES];
4027 if ([col respondsToSelector:@selector(setHidden:)]) [(SWELL_TableColumnExtensions*)col setHidden:NO];
4028 [col setWidth:lvc->cx];
4031 if (lvc->mask&LVCF_TEXT)
4033 if (!v->m_lbMode && !(v->style&LVS_NOCOLUMNHEADER))
4035 NSString *lbl=(NSString *)SWELL_CStringToCFString(lvc->pszText);
4036 [[col headerCell] setStringValue:lbl];
4042 bool ListView_DeleteColumn(HWND h, int pos)
4044 if (!h) return false;
4045 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return false;
4046 SWELL_ListView *v=(SWELL_ListView *)h;
4047 if (!v->m_cols || pos < 0 || pos >= v->m_cols->GetSize()) return false;
4048 [v removeTableColumn:v->m_cols->Get(pos)];
4049 v->m_cols->Delete(pos);
4053 void ListView_GetItemText(HWND hwnd, int item, int subitem, char *text, int textmax)
4055 LVITEM it={LVIF_TEXT,item,subitem,0,0,text,textmax,};
4056 ListView_GetItem(hwnd,&it);
4059 int ListView_InsertItem(HWND h, const LVITEM *item)
4061 if (!h || !item || item->iSubItem) return 0;
4062 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return 0;
4064 SWELL_ListView *tv=(SWELL_ListView*)h;
4065 if (!tv->m_lbMode && (tv->style & LVS_OWNERDATA)) return -1;
4066 if (!tv->m_items) return -1;
4070 else if (a > tv->m_items->GetSize()) a=tv->m_items->GetSize();
4072 if (!tv->m_lbMode && (item->mask & LVIF_TEXT))
4074 if (tv->style & LVS_SORTASCENDING)
4076 a=ptrlist_bsearch_mod((char *)item->pszText,tv->m_items,_listviewrowSearchFunc,NULL);
4078 else if (tv->style & LVS_SORTDESCENDING)
4080 a=ptrlist_bsearch_mod((char *)item->pszText,tv->m_items,_listviewrowSearchFunc2,NULL);
4084 SWELL_ListView_Row *nr=new SWELL_ListView_Row;
4085 nr->m_vals.Add(strdup((item->mask & LVIF_TEXT) ? item->pszText : ""));
4086 if (item->mask & LVIF_PARAM) nr->m_param = item->lParam;
4087 tv->m_items->Insert(a,nr);
4091 if ((item->mask&LVIF_STATE) && (item->stateMask & (0xff<<16)))
4093 nr->m_imageidx=(item->state>>16)&0xff;
4098 if (a < tv->m_items->GetSize()-1)
4100 NSIndexSet *sel=[tv selectedRowIndexes];
4101 if (sel && [sel count])
4103 NSMutableIndexSet *ms = [[NSMutableIndexSet alloc] initWithIndexSet:sel];
4104 [ms shiftIndexesStartingAtIndex:a by:1];
4105 [tv selectRowIndexes:ms byExtendingSelection:NO];
4110 if (item->mask & LVIF_STATE)
4112 if (item->stateMask & LVIS_SELECTED)
4114 if (item->state&LVIS_SELECTED)
4116 bool isSingle = tv->m_lbMode ? !(tv->style & LBS_EXTENDEDSEL) : !!(tv->style&LVS_SINGLESEL);
4117 [tv selectRowIndexes:[NSIndexSet indexSetWithIndex:a] byExtendingSelection:isSingle?NO:YES];
4125 void ListView_SetItemText(HWND h, int ipos, int cpos, const char *txt)
4127 if (!h || cpos < 0 || cpos >= 32) return;
4128 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return;
4130 SWELL_ListView *tv=(SWELL_ListView*)h;
4131 if (!tv->m_lbMode && (tv->style & LVS_OWNERDATA)) return;
4132 if (!tv->m_items) return;
4134 SWELL_ListView_Row *p=tv->m_items->Get(ipos);
4137 for (x = p->m_vals.GetSize(); x < cpos; x ++)
4139 p->m_vals.Add(strdup(""));
4141 if (cpos < p->m_vals.GetSize())
4143 free(p->m_vals.Get(cpos));
4144 p->m_vals.Set(cpos,strdup(txt));
4146 else p->m_vals.Add(strdup(txt));
4151 int ListView_GetNextItem(HWND h, int istart, int flags)
4153 if (flags==LVNI_FOCUSED||flags==LVNI_SELECTED)
4156 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return -1;
4158 SWELL_ListView *tv=(SWELL_ListView*)h;
4160 if (flags==LVNI_SELECTED)
4162 //int orig_start=istart;
4163 if (istart++<0)istart=0;
4164 const int n = (int)[tv numberOfRows];
4167 if ([tv isRowSelected:istart]) return istart;
4173 return (int)[tv selectedRow];
4178 bool ListView_SetItem(HWND h, LVITEM *item)
4180 if (!item) return false;
4181 if (!h) return false;
4182 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return false;
4184 SWELL_ListView *tv=(SWELL_ListView*)h;
4185 if (tv->m_lbMode || !(tv->style & LVS_OWNERDATA))
4187 if (!tv->m_items) return false;
4188 SWELL_ListView_Row *row=tv->m_items->Get(item->iItem);
4189 if (!row) return false;
4191 if (item->mask & LVIF_PARAM)
4193 row->m_param=item->lParam;
4195 if ((item->mask & LVIF_TEXT) && item->pszText)
4197 ListView_SetItemText(h,item->iItem,item->iSubItem,item->pszText);
4199 if ((item->mask&LVIF_IMAGE) && item->iImage >= 0)
4201 row->m_imageidx=item->iImage+1;
4202 ListView_RedrawItems(h, item->iItem, item->iItem);
4205 if ((item->mask & LVIF_STATE) && item->stateMask)
4207 ListView_SetItemState(h,item->iItem,item->state,item->stateMask);
4213 bool ListView_GetItem(HWND h, LVITEM *item)
4215 if (!item) return false;
4216 if ((item->mask&LVIF_TEXT)&&item->pszText && item->cchTextMax > 0) item->pszText[0]=0;
4218 if (!h) return false;
4219 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return false;
4222 SWELL_ListView *tv=(SWELL_ListView*)h;
4223 if (tv->m_lbMode || !(tv->style & LVS_OWNERDATA))
4225 if (!tv->m_items) return false;
4227 SWELL_ListView_Row *row=tv->m_items->Get(item->iItem);
4228 if (!row) return false;
4230 if (item->mask & LVIF_PARAM) item->lParam=row->m_param;
4231 if (item->mask & LVIF_TEXT) if (item->pszText && item->cchTextMax>0)
4233 char *p=row->m_vals.Get(item->iSubItem);
4234 lstrcpyn_safe(item->pszText,p?p:"",item->cchTextMax);
4236 if (item->mask & LVIF_STATE)
4238 if (item->stateMask & (0xff<<16))
4240 item->state|=row->m_imageidx<<16;
4246 if (item->iItem <0 || item->iItem >= tv->ownermode_cnt) return false;
4248 if (item->mask & LVIF_STATE)
4250 if ((item->stateMask&LVIS_SELECTED) && [tv isRowSelected:item->iItem]) item->state|=LVIS_SELECTED;
4251 if ((item->stateMask&LVIS_FOCUSED) && [tv selectedRow] == item->iItem) item->state|=LVIS_FOCUSED;
4256 int ListView_GetItemState(HWND h, int ipos, UINT mask)
4258 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]]) return 0;
4259 SWELL_ListView *tv=(SWELL_ListView*)h;
4261 if (tv->m_lbMode || !(tv->style & LVS_OWNERDATA))
4263 if (!tv->m_items) return 0;
4264 SWELL_ListView_Row *row=tv->m_items->Get(ipos);
4266 if (mask & (0xff<<16))
4268 flag|=row->m_imageidx<<16;
4273 if (ipos<0 || ipos >= tv->ownermode_cnt) return 0;
4276 if ((mask&LVIS_SELECTED) && [tv isRowSelected:ipos]) flag|=LVIS_SELECTED;
4277 if ((mask&LVIS_FOCUSED) && [tv selectedRow]==ipos) flag|=LVIS_FOCUSED;
4281 bool ListView_SetItemState(HWND h, int ipos, UINT state, UINT statemask)
4284 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]]) return false;
4285 SWELL_ListView *tv=(SWELL_ListView*)h;
4286 static int _is_doing_all;
4291 int n=ListView_GetItemCount(h);
4293 for (x = 0; x < n; x ++)
4294 ListView_SetItemState(h,x,state,statemask);
4296 ListView_RedrawItems(h,0,n-1);
4300 if (tv->m_lbMode || !(tv->style & LVS_OWNERDATA))
4302 if (!tv->m_items) return false;
4303 SWELL_ListView_Row *row=tv->m_items->Get(ipos);
4304 if (!row) return false;
4305 if (statemask & (0xff<<16))
4307 if (row->m_imageidx!=((state>>16)&0xff))
4309 row->m_imageidx=(state>>16)&0xff;
4316 if (ipos<0 || ipos >= tv->ownermode_cnt) return 0;
4319 if (statemask & LVIS_SELECTED)
4321 if (state & LVIS_SELECTED)
4323 bool isSingle = tv->m_lbMode ? !(tv->style & LBS_EXTENDEDSEL) : !!(tv->style&LVS_SINGLESEL);
4324 if (![tv isRowSelected:ipos]) { didsel=true; [tv selectRowIndexes:[NSIndexSet indexSetWithIndex:ipos] byExtendingSelection:isSingle?NO:YES]; }
4328 if ([tv isRowSelected:ipos]) { didsel=true; [tv deselectRow:ipos]; }
4331 if (statemask & LVIS_FOCUSED)
4333 if (state&LVIS_FOCUSED)
4350 NMLISTVIEW nm={{(HWND)h,(UINT_PTR)[tv tag],LVN_ITEMCHANGED},ipos,0,state,};
4351 SendMessage(GetParent(h),WM_NOTIFY,nm.hdr.idFrom,(LPARAM)&nm);
4356 ListView_RedrawItems(h,ipos,ipos);
4361 void ListView_RedrawItems(HWND h, int startitem, int enditem)
4363 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]]) return;
4364 SWELL_ListView *tv=(SWELL_ListView*)h;
4365 if (!tv->m_items) return;
4369 void ListView_DeleteItem(HWND h, int ipos)
4372 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return;
4374 SWELL_ListView *tv=(SWELL_ListView*)h;
4375 if (!tv->m_items) return;
4377 if (ipos >=0 && ipos < tv->m_items->GetSize())
4379 if (ipos != tv->m_items->GetSize()-1)
4381 NSIndexSet *sel=[tv selectedRowIndexes];
4382 if (sel && [sel count])
4384 NSMutableIndexSet *ms = [[NSMutableIndexSet alloc] initWithIndexSet:sel];
4385 [ms shiftIndexesStartingAtIndex:ipos+1 by:-1];
4386 [tv selectRowIndexes:ms byExtendingSelection:NO];
4390 tv->m_items->Delete(ipos,true);
4397 void ListView_DeleteAllItems(HWND h)
4400 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return;
4402 SWELL_ListView *tv=(SWELL_ListView*)h;
4403 tv->ownermode_cnt=0;
4404 if (tv->m_items) tv->m_items->Empty(true);
4409 int ListView_GetSelectedCount(HWND h)
4412 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return 0;
4414 SWELL_ListView *tv=(SWELL_ListView*)h;
4415 return (int)[tv numberOfSelectedRows];
4418 int ListView_GetItemCount(HWND h)
4421 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return 0;
4423 SWELL_ListView *tv=(SWELL_ListView*)h;
4424 if (tv->m_lbMode || !(tv->style & LVS_OWNERDATA))
4426 if (!tv->m_items) return 0;
4428 return tv->m_items->GetSize();
4430 return tv->ownermode_cnt;
4433 int ListView_GetSelectionMark(HWND h)
4436 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return 0;
4438 SWELL_ListView *tv=(SWELL_ListView*)h;
4439 return (int)[tv selectedRow];
4442 int SWELL_GetListViewHeaderHeight(HWND h)
4445 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return 0;
4447 SWELL_ListView* tv=(SWELL_ListView*)h;
4448 NSTableHeaderView* hv=[tv headerView];
4449 NSRect r=[hv bounds];
4450 return (int)(r.size.height+0.5);
4453 void ListView_SetColumnWidth(HWND h, int pos, int wid)
4455 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]]) return;
4456 SWELL_ListView *v=(SWELL_ListView *)h;
4457 if (!v->m_cols || pos < 0 || pos >= v->m_cols->GetSize()) return;
4459 NSTableColumn *col=v->m_cols->Get(pos);
4464 if ([col respondsToSelector:@selector(setHidden:)]) [(SWELL_TableColumnExtensions*)col setHidden:YES];
4468 if ([col respondsToSelector:@selector(setHidden:)]) [(SWELL_TableColumnExtensions*)col setHidden:NO];
4473 BOOL ListView_GetColumnOrderArray(HWND h, int cnt, int* arr)
4475 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]]) return FALSE;
4476 SWELL_ListView* lv=(SWELL_ListView*)h;
4477 if (!lv->m_cols || lv->m_cols->GetSize() != cnt) return FALSE;
4480 for (i=0; i < cnt; ++i)
4482 arr[i]=[lv getColumnPos:i];
4488 BOOL ListView_SetColumnOrderArray(HWND h, int cnt, int* arr)
4490 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]]) return FALSE;
4491 SWELL_ListView* lv=(SWELL_ListView*)h;
4492 if (!lv->m_cols || lv->m_cols->GetSize() != cnt) return FALSE;
4495 for (i=0; i < cnt; ++i)
4497 int pos=[lv getColumnPos:i];
4499 if (dest>=0 && dest<cnt) [lv moveColumn:pos toColumn:dest];
4505 HWND ListView_GetHeader(HWND h)
4507 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]]) return 0;
4511 int Header_GetItemCount(HWND h)
4513 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]]) return 0;
4514 SWELL_ListView* lv=(SWELL_ListView*)h;
4515 if (lv->m_cols) return lv->m_cols->GetSize();
4519 BOOL Header_GetItem(HWND h, int col, HDITEM* hi)
4521 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]] || !hi) return FALSE;
4522 SWELL_ListView* lv=(SWELL_ListView*)h;
4523 if (!lv->m_cols || col < 0 || col >= lv->m_cols->GetSize()) return FALSE;
4524 NSTableColumn* hcol=lv->m_cols->Get(col);
4525 if (!hcol) return FALSE;
4527 if (hi->mask&HDI_FORMAT)
4530 NSImage* img=[lv indicatorImageInTableColumn:hcol];
4533 NSString* imgname=[img name];
4536 if ([imgname isEqualToString:@"NSAscendingSortIndicator"]) hi->fmt |= HDF_SORTUP;
4537 else if ([imgname isEqualToString:@"NSDescendingSortIndicator"]) hi->fmt |= HDF_SORTDOWN;
4546 BOOL Header_SetItem(HWND h, int col, HDITEM* hi)
4548 if (!h || ![(id)h isKindOfClass:[SWELL_ListView class]] || !hi) return FALSE;
4549 SWELL_ListView* lv=(SWELL_ListView*)h;
4550 if (!lv->m_cols || col < 0 || col >= lv->m_cols->GetSize()) return FALSE;
4551 NSTableColumn* hcol=lv->m_cols->Get(col);
4552 if (!hcol) return FALSE;
4554 if (hi->mask&HDI_FORMAT)
4557 if (hi->fmt&HDF_SORTUP) img=[NSImage imageNamed:@"NSAscendingSortIndicator"];
4558 else if (hi->fmt&HDF_SORTDOWN) img=[NSImage imageNamed:@"NSDescendingSortIndicator"];
4559 [lv setIndicatorImage:img inTableColumn:hcol];
4566 int ListView_HitTest(HWND h, LVHITTESTINFO *pinf)
4568 if (!h || !pinf) return -1;
4569 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return -1;
4571 SWELL_ListView *tv=(SWELL_ListView*)h;
4576 // rowAtPoint will return a row even if it is scrolled out of the clip view
4577 NSScrollView* sv=(NSScrollView *)NavigateUpScrollClipViews(tv);
4578 if (![sv isKindOfClass:[NSScrollView class]] && ![sv isKindOfClass:[NSClipView class]]) sv=NULL;
4580 NSRect r=[sv documentVisibleRect];
4581 int x=pinf->pt.x-r.origin.x;
4582 int y=pinf->pt.y-r.origin.y;
4584 if (x < 0) pinf->flags |= LVHT_TOLEFT;
4585 if (x >= r.size.width) pinf->flags |= LVHT_TORIGHT;
4586 if (y < 0) pinf->flags |= LVHT_ABOVE;
4587 if (y >= r.size.height) pinf->flags |= LVHT_BELOW;
4591 NSPoint pt = NSMakePoint( pinf->pt.x, pinf->pt.y );
4592 pinf->iItem=(int)[(NSTableView *)h rowAtPoint:pt];
4593 if (pinf->iItem >= 0)
4595 if (tv->m_status_imagelist && pt.x <= [tv rowHeight])
4597 pinf->flags=LVHT_ONITEMSTATEICON;
4601 pinf->flags=LVHT_ONITEMLABEL;
4606 pinf->flags=LVHT_NOWHERE;
4613 int ListView_SubItemHitTest(HWND h, LVHITTESTINFO *pinf)
4615 int row = ListView_HitTest(h, pinf);
4617 NSPoint pt=NSMakePoint(pinf->pt.x,pinf->pt.y);
4618 if (row < 0 && pt.y < 0)
4619 { // Fake the point in the client area of the listview to get the column # (like win32)
4622 pinf->iSubItem=(int)[(NSTableView *)h columnAtPoint:pt];
4626 void ListView_SetItemCount(HWND h, int cnt)
4629 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return;
4631 SWELL_ListView *tv=(SWELL_ListView*)h;
4632 if (!tv->m_lbMode && (tv->style & LVS_OWNERDATA))
4634 tv->ownermode_cnt=cnt;
4635 [tv noteNumberOfRowsChanged];
4639 void ListView_EnsureVisible(HWND h, int i, BOOL pok)
4642 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return;
4644 SWELL_ListView *tv=(SWELL_ListView*)h;
4647 if (!tv->m_lbMode && (tv->style & LVS_OWNERDATA))
4649 if (i >=tv->ownermode_cnt-1) i=tv->ownermode_cnt-1;
4653 if (tv->m_items && i >= tv->m_items->GetSize()) i=tv->m_items->GetSize()-1;
4657 [tv scrollRowToVisible:i];
4661 static bool ListViewGetRectImpl(HWND h, int item, int subitem, RECT* r) // subitem<0 for full item rect
4663 if (!h) return false;
4664 if (![(id)h isKindOfClass:[SWELL_ListView class]]) return false;
4665 if (item < 0 || item > ListView_GetItemCount(h)) return false;
4666 SWELL_ListView *tv=(SWELL_ListView*)h;
4668 if (subitem >= 0 && (!tv->m_cols || subitem >= tv->m_cols->GetSize())) return false;
4669 subitem=[tv getColumnPos:subitem];
4672 if (subitem < 0) ar = [tv rectOfRow:item];
4673 else ar=[tv frameOfCellAtColumn:subitem row:item];
4674 NSSize sp=[tv intercellSpacing];
4676 r->left=(int)ar.origin.x;
4677 r->top=(int)ar.origin.y;
4678 r->right=(int)(ar.origin.x+ar.size.width+sp.width);
4679 r->bottom=(int)(ar.origin.y+ar.size.height+sp.height);
4684 bool ListView_GetSubItemRect(HWND h, int item, int subitem, int code, RECT *r)
4686 return ListViewGetRectImpl(h, item, subitem, r);
4689 bool ListView_GetItemRect(HWND h, int item, RECT *r, int code)
4691 return ListViewGetRectImpl(h, item, -1, r);
4694 int ListView_GetTopIndex(HWND h)
4696 NSTableView* tv = (NSTableView*)h;
4698 NSScrollView* sv = [tv enclosingScrollView];
4701 NSPoint pt = { 0, 0 };
4702 NSView *hdr = [tv headerView];
4703 if (hdr && ![hdr isHidden])
4705 NSRect fr=[hdr frame];
4706 if (fr.size.height > 0.0) pt.y = fr.origin.y + fr.size.height;
4708 pt.y += [sv documentVisibleRect].origin.y;
4709 return (int)[tv rowAtPoint:pt];
4712 int ListView_GetCountPerPage(HWND h)
4714 NSTableView* tv = (NSTableView*)h;
4716 NSScrollView* sv = [tv enclosingScrollView];
4719 NSRect tvr = [sv documentVisibleRect];
4720 int rowh = [tv rowHeight];
4721 return tvr.size.height/rowh;
4724 bool ListView_Scroll(HWND h, int xscroll, int yscroll)
4726 NSTableView* tv = (NSTableView*)h;
4727 NSScrollView* sv = [tv enclosingScrollView];
4728 if (!sv) return false;
4730 NSRect tvr = [sv documentVisibleRect];
4731 NSPoint pt = { tvr.origin.x, tvr.origin.y };
4732 if (xscroll > 0) pt.x += tvr.size.width-1;
4733 if (yscroll > 0) pt.y += tvr.size.height-1;
4735 const NSInteger nr = [tv numberOfRows];
4736 NSInteger rowidx = [tv rowAtPoint:pt];
4737 if (rowidx < 0) rowidx=0;
4738 else if (rowidx >= nr) rowidx=nr-1;
4740 const NSInteger nc = [tv numberOfColumns];
4741 NSInteger colidx = [tv columnAtPoint:pt];
4742 if (colidx < 0) colidx=0;
4743 else if (colidx >= nc) colidx = nc-1;
4745 // colidx is our column index, not the display order, convert
4746 if ([tv isKindOfClass:[SWELL_ListView class]]) colidx = [(SWELL_ListView*)tv getColumnPos:(int)colidx];
4748 NSRect ir = [tv frameOfCellAtColumn:colidx row:rowidx];
4752 if (ir.size.height) rowidx += yscroll / ir.size.height;
4754 if (rowidx < 0) rowidx=0;
4755 else if (rowidx >= nr) rowidx = nr-1;
4756 [tv scrollRowToVisible:rowidx];
4761 if (ir.size.width) colidx += xscroll / ir.size.width;
4763 if (colidx < 0) colidx=0;
4764 else if (colidx >= nc) colidx = nc-1;
4766 // scrollColumnToVisible takes display order, which we have here
4767 [tv scrollColumnToVisible:colidx];
4774 bool ListView_GetScroll(HWND h, POINT* p)
4776 NSTableView* tv = (NSTableView*)h;
4777 NSScrollView* sv = [tv enclosingScrollView];
4780 NSRect cr = [sv documentVisibleRect];
4789 void ListView_SortItems(HWND hwnd, PFNLVCOMPARE compf, LPARAM parm)
4792 if (![(id)hwnd isKindOfClass:[SWELL_ListView class]]) return;
4793 SWELL_ListView *tv=(SWELL_ListView*)hwnd;
4794 if (tv->m_lbMode || (tv->style & LVS_OWNERDATA) || !tv->m_items) return;
4797 tmp.Resize(tv->m_items->GetSize()*sizeof(void *));
4800 for(x=0;x<tv->m_items->GetSize();x++)
4802 SWELL_ListView_Row *r = tv->m_items->Get(x);
4805 r->m_tmp = !![tv isRowSelected:x];
4809 __listview_mergesort_internal(tv->m_items->GetList(),tv->m_items->GetSize(),sizeof(void *),compf,parm,(char*)tmp.Get());
4812 NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];
4814 for(x=0;x<tv->m_items->GetSize();x++)
4816 SWELL_ListView_Row *r = tv->m_items->Get(x);
4817 if (r && (r->m_tmp&1)) [indexSet addIndex:x];
4819 [tv selectRowIndexes:indexSet byExtendingSelection:NO];
4827 HWND WindowFromPoint(POINT p)
4829 NSArray *windows=[NSApp orderedWindows];
4830 const NSInteger cnt=windows ? [windows count] : 0;
4832 NSWindow *kw = [NSApp keyWindow];
4833 if (kw && windows && [windows containsObject:kw]) kw=NULL;
4835 NSWindow *bestwnd=0;
4836 for (NSInteger x = kw ? -1 : 0; x < cnt; x ++)
4839 if (x>=0) wnd=[windows objectAtIndex:x];
4840 if (wnd && [wnd isVisible])
4842 NSRect fr=[wnd frame];
4843 if (p.x >= fr.origin.x && p.x < fr.origin.x + fr.size.width &&
4844 p.y >= fr.origin.y && p.y < fr.origin.y + fr.size.height)
4852 if (!bestwnd) return 0;
4853 NSPoint pt=NSMakePoint(p.x,p.y);
4854 NSPoint lpt=[bestwnd convertScreenToBase:pt];
4855 NSView *v=[[bestwnd contentView] hitTest:lpt];
4856 if (v) return (HWND)v;
4857 return (HWND)[bestwnd contentView];
4860 void UpdateWindow(HWND hwnd)
4862 if (hwnd && [(id)hwnd isKindOfClass:[NSView class]] && [(NSView *)hwnd needsDisplay])
4864 NSWindow *wnd = [(NSView *)hwnd window];
4865 [wnd displayIfNeeded];
4869 void SWELL_FlushWindow(HWND h)
4874 if ([(id)h isKindOfClass:[NSView class]])
4876 if ([(NSView *)h needsDisplay]) return;
4878 w = [(NSView *)h window];
4880 else if ([(id)h isKindOfClass:[NSWindow class]]) w = (NSWindow *)h;
4882 if (w && ![w viewsNeedDisplay])
4889 static void InvalidateSuperViews(NSView *view)
4892 view = [view superview];
4895 if ([view isKindOfClass:[SWELL_hwndChild class]])
4897 if (((SWELL_hwndChild *)view)->m_isdirty&2) break;
4898 ((SWELL_hwndChild *)view)->m_isdirty|=2;
4900 view = [view superview];
4904 BOOL InvalidateRect(HWND hwnd, const RECT *r, int eraseBk)
4906 if (!hwnd) return FALSE;
4908 if ([view isKindOfClass:[NSWindow class]]) view=[view contentView];
4909 if ([view isKindOfClass:[NSView class]])
4914 bool skip_parent_invalidate=false;
4915 if ([view isKindOfClass:[SWELL_hwndChild class]])
4917 if (!(((SWELL_hwndChild *)view)->m_isdirty&1))
4919 ((SWELL_hwndChild *)view)->m_isdirty|=1;
4921 else skip_parent_invalidate=true; // if already dirty, then assume parents are already dirty too
4923 if (!skip_parent_invalidate)
4925 InvalidateSuperViews(view);
4930 if (tr.top>tr.bottom)
4932 int a = tr.top; tr.top=tr.bottom; tr.bottom=a;
4934 [sv setNeedsDisplayInRect:NSMakeRect(tr.left,tr.top,tr.right-tr.left,tr.bottom-tr.top)];
4936 else [sv setNeedsDisplay:YES];
4942 static HWND m_fakeCapture;
4943 static BOOL m_capChangeNotify;
4947 return m_fakeCapture;
4950 HWND SetCapture(HWND hwnd)
4952 HWND oc=m_fakeCapture;
4953 int ocn=m_capChangeNotify;
4955 m_capChangeNotify = hwnd && [(id)hwnd respondsToSelector:@selector(swellCapChangeNotify)] && [(SWELL_hwndChild*)hwnd swellCapChangeNotify];
4957 if (ocn && oc && oc != hwnd) SendMessage(oc,WM_CAPTURECHANGED,0,(LPARAM)hwnd);
4962 void ReleaseCapture()
4964 HWND h=m_fakeCapture;
4966 if (m_capChangeNotify && h)
4968 SendMessage(h,WM_CAPTURECHANGED,0,0);
4973 HDC BeginPaint(HWND hwnd, PAINTSTRUCT *ps)
4976 memset(ps,0,sizeof(PAINTSTRUCT));
4977 if (!hwnd) return 0;
4979 if (![turd respondsToSelector:@selector(getSwellPaintInfo:)]) return 0;
4981 [(SWELL_hwndChild*)turd getSwellPaintInfo:(PAINTSTRUCT *)ps];
4985 BOOL EndPaint(HWND hwnd, PAINTSTRUCT *ps)
4990 LRESULT DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4992 if (msg==WM_RBUTTONUP||msg==WM_NCRBUTTONUP)
4994 POINT p={GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
4996 if (msg==WM_RBUTTONUP)
4998 ClientToScreen(hwnd,&p);
4999 HWND h=WindowFromPoint(p);
5000 if (h && IsChild(hwnd,h)) hwndDest=h;
5002 SendMessage(hwnd,WM_CONTEXTMENU,(WPARAM)hwndDest,(p.x&0xffff)|(p.y<<16));
5005 else if (msg==WM_CONTEXTMENU || msg == WM_MOUSEWHEEL || msg == WM_MOUSEHWHEEL || msg == WM_GESTURE)
5007 if ([(id)hwnd isKindOfClass:[NSView class]])
5009 NSView *h=(NSView *)hwnd;
5010 while (h && [[h window] contentView] != h)
5013 if (h && [h respondsToSelector:@selector(onSwellMessage:p1:p2:)])
5015 return SendMessage((HWND)h,msg,wParam,lParam);
5020 else if (msg==WM_NCHITTEST)
5025 GetWindowRect(hwnd,&r);
5026 POINT pt={GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
5028 if (r.top > r.bottom)
5030 pt.y = r.bottom + (r.top - pt.y); // translate coordinate into flipped-window
5032 int a=r.top; r.top=r.bottom; r.bottom=a;
5034 NCCALCSIZE_PARAMS p={{r,}};
5035 SendMessage(hwnd,WM_NCCALCSIZE,FALSE,(LPARAM)&p);
5036 if (!PtInRect(&p.rgrc[0],pt)) rv=HTNOWHERE;
5040 else if (msg==WM_KEYDOWN || msg==WM_KEYUP) return 69;
5041 else if (msg == WM_DISPLAYCHANGE)
5043 if ([(id)hwnd isKindOfClass:[NSView class]])
5045 NSArray *ch = [(NSView *)hwnd subviews];
5049 for(x=0;x<[ch count]; x ++)
5051 NSView *v = [ch objectAtIndex:x];
5052 sendSwellMessage(v,WM_DISPLAYCHANGE,wParam,lParam);
5056 void SWELL_DoDialogColorUpdates(HWND hwnd, DLGPROC d, bool isUpdate);
5057 DLGPROC d = (DLGPROC)GetWindowLong(hwnd,DWL_DLGPROC);
5058 if (d) SWELL_DoDialogColorUpdates(hwnd,d,true);
5066 void SWELL_BroadcastMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
5069 NSArray *ch=[NSApp orderedWindows];
5070 for(x=0;x<[ch count]; x ++)
5072 NSView *v = [[ch objectAtIndex:x] contentView];
5073 if (v && [v respondsToSelector:@selector(onSwellMessage:p1:p2:)])
5075 [(SWELL_hwndChild *)v onSwellMessage:uMsg p1:wParam p2:lParam];
5077 if (uMsg == WM_DISPLAYCHANGE)
5078 InvalidateRect((HWND)v,NULL,FALSE);
5096 ///////////////// clipboard compatability (NOT THREAD SAFE CURRENTLY)
5099 BOOL DragQueryPoint(HDROP hDrop,LPPOINT pt)
5101 if (!hDrop) return 0;
5102 DROPFILES *df=(DROPFILES*)GlobalLock(hDrop);
5105 GlobalUnlock(hDrop);
5109 void DragFinish(HDROP hDrop)
5111 //do nothing for now (caller will free hdrops)
5114 UINT DragQueryFile(HDROP hDrop, UINT wf, char *buf, UINT bufsz)
5116 if (!hDrop) return 0;
5117 DROPFILES *df=(DROPFILES*)GlobalLock(hDrop);
5120 char *p=(char*)df + df->pFiles;
5121 if (wf == 0xFFFFFFFF)
5137 lstrcpyn_safe(buf,p,bufsz);
5147 GlobalUnlock(hDrop);
5161 static WDL_PtrList<void> m_clip_recs;
5162 static WDL_PtrList<NSString> m_clip_fmts;
5163 static WDL_PtrList<char> m_clip_curfmts;
5164 struct swell_pendingClipboardStates
5168 swell_pendingClipboardStates(UINT _type, HANDLE _h)
5173 ~swell_pendingClipboardStates()
5179 static WDL_PtrList<swell_pendingClipboardStates> m_clipsPending;
5181 bool OpenClipboard(HWND hwndDlg)
5183 m_clipsPending.Empty(true);
5185 CF_TEXT; // ensure this type is registered
5187 NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:@"SWELL_APP"];
5188 m_clip_curfmts.Empty();
5189 NSArray *ar=[pasteboard types];
5192 if (ar && [ar count])
5196 for (x = 0; x < [ar count]; x ++)
5198 NSString *s=[ar objectAtIndex:x];
5201 for (y = 0; y < m_clip_fmts.GetSize(); y ++)
5203 if ([s compare:(NSString *)m_clip_fmts.Get(y)]==NSOrderedSame)
5205 if (m_clip_curfmts.Find((char*)(INT_PTR)(y+1))<0)
5206 m_clip_curfmts.Add((char*)(INT_PTR)(y+1));
5216 void CloseClipboard() // frees any remaining items in clipboard
5218 m_clip_recs.Empty(GlobalFree);
5220 if (m_clipsPending.GetSize())
5223 for (x=0;x<m_clipsPending.GetSize() && m_clipsPending.Get(x)->type != CF_TEXT;x++);
5224 NSPasteboard *pasteboard = x<m_clipsPending.GetSize() ? [NSPasteboard generalPasteboard] : [NSPasteboard pasteboardWithName:@"SWELL_APP"];
5226 NSMutableArray *ar = [[NSMutableArray alloc] initWithCapacity:m_clipsPending.GetSize()];
5228 for (x=0;x<m_clipsPending.GetSize();x++)
5230 swell_pendingClipboardStates *cs=m_clipsPending.Get(x);
5231 NSString *fmt=m_clip_fmts.Get(cs->type-1);
5232 if (fmt) [ar addObject:fmt];
5236 [pasteboard declareTypes:ar owner:nil];
5237 for (x=0;x<m_clipsPending.GetSize();x++)
5239 swell_pendingClipboardStates *cs=m_clipsPending.Get(x);
5240 NSString *fmt=m_clip_fmts.Get(cs->type-1);
5243 void *buf=GlobalLock(cs->h);
5246 int bufsz=GlobalSize(cs->h);
5247 if (cs->type == CF_TEXT)
5249 char *t = (char *)malloc(bufsz+1);
5252 memcpy(t,buf,bufsz);
5254 NSString *s = (NSString*)SWELL_CStringToCFString(t);
5255 [pasteboard setString:s forType:fmt];
5262 NSData *data=[NSData dataWithBytes:buf length:bufsz];
5263 [pasteboard setData:data forType:fmt];
5265 GlobalUnlock(cs->h);
5270 m_clipsPending.Empty(true);
5274 UINT EnumClipboardFormats(UINT lastfmt) // won't enumerate CF_TEXT (since thats a separate pasteboard)
5276 if (!m_clip_curfmts.GetSize()) return 0;
5277 if (lastfmt == 0) return (UINT)(INT_PTR)m_clip_curfmts.Get(0);
5279 for (x = m_clip_curfmts.GetSize()-2; x >= 0; x--) // scan backwards to avoid dupes causing infinite loops
5281 if ((UINT)(INT_PTR)m_clip_curfmts.Get(x) == lastfmt)
5282 return (UINT)(INT_PTR)m_clip_curfmts.Get(x+1);
5287 HANDLE GetClipboardData(UINT type)
5289 NSString *fmt=m_clip_fmts.Get(type-1);
5291 NSPasteboard *pasteboard = type == CF_TEXT ? [NSPasteboard generalPasteboard] : [NSPasteboard pasteboardWithName:@"SWELL_APP"];
5294 if (type == CF_TEXT)
5297 NSString *str = [pasteboard stringForType:fmt];
5300 int l = (int) ([str length]*4 + 32);
5301 char *buf = (char *)malloc(l);
5303 SWELL_CFStringToCString(str,buf,l);
5305 l = (int) (strlen(buf)+1);
5307 memcpy(GlobalLock(h),buf,l);
5315 NSData *data=[pasteboard dataForType:fmt];
5316 if (!data) return 0;
5317 int l = (int)[data length];
5319 if (h) memcpy(GlobalLock(h),[data bytes],l);
5323 if (h) m_clip_recs.Add(h);
5327 void EmptyClipboard()
5329 m_clipsPending.Empty(true);
5333 void SetClipboardData(UINT type, HANDLE h)
5335 m_clipsPending.Add(new swell_pendingClipboardStates(type,h));
5338 UINT RegisterClipboardFormat(const char *desc)
5341 if (!strcmp(desc,"SWELL__CF_TEXT"))
5343 s=NSStringPboardType;
5346 if (!s) s=(NSString*)SWELL_CStringToCFString(desc);
5348 for (x = 0; x < m_clip_fmts.GetSize(); x ++)
5350 NSString *ts=m_clip_fmts.Get(x);
5351 if ([ts compare:s]==NSOrderedSame)
5358 return m_clip_fmts.GetSize();
5361 int EnumPropsEx(HWND hwnd, PROPENUMPROCEX proc, LPARAM lParam)
5363 if (!hwnd || ![(id)hwnd respondsToSelector:@selector(swellEnumProps:lp:)]) return -1;
5364 return (int)[(SWELL_hwndChild *)hwnd swellEnumProps:proc lp:lParam];
5367 HANDLE GetProp(HWND hwnd, const char *name)
5369 if (!hwnd || ![(id)hwnd respondsToSelector:@selector(swellGetProp:wantRemove:)]) return NULL;
5370 return (HANDLE)[(SWELL_hwndChild *)hwnd swellGetProp:name wantRemove:NO];
5373 BOOL SetProp(HWND hwnd, const char *name, HANDLE val)
5375 if (!hwnd || ![(id)hwnd respondsToSelector:@selector(swellSetProp:value:)]) return FALSE;
5376 return (BOOL)!![(SWELL_hwndChild *)hwnd swellSetProp:name value:val];
5379 HANDLE RemoveProp(HWND hwnd, const char *name)
5381 if (!hwnd || ![(id)hwnd respondsToSelector:@selector(swellGetProp:wantRemove:)]) return NULL;
5382 return (HANDLE)[(SWELL_hwndChild *)hwnd swellGetProp:name wantRemove:YES];
5386 int GetSystemMetrics(int p)
5393 NSScreen *s=[NSScreen mainScreen];
5394 if (!s) return 1024;
5395 return p==SM_CXSCREEN ? [s frame].size.width : [s frame].size.height;
5397 case SM_CXHSCROLL: return 16;
5398 case SM_CYHSCROLL: return 16;
5399 case SM_CXVSCROLL: return 16;
5400 case SM_CYVSCROLL: return 16;
5405 BOOL ScrollWindow(HWND hwnd, int xamt, int yamt, const RECT *lpRect, const RECT *lpClipRect)
5407 if (hwnd && [(id)hwnd isKindOfClass:[NSWindow class]]) hwnd=(HWND)[(id)hwnd contentView];
5408 if (!hwnd || ![(id)hwnd isKindOfClass:[NSView class]]) return FALSE;
5410 if (!xamt && !yamt) return FALSE;
5412 // move child windows only
5417 NSArray *ar=[(NSView*)hwnd subviews];
5418 NSInteger i,c=[ar count];
5421 NSView *v=(NSView *)[ar objectAtIndex:i];
5428 [(id)hwnd setNeedsDisplay:YES];
5432 NSRect r=[(NSView*)hwnd bounds];
5435 [(id)hwnd setBoundsOrigin:r.origin];
5436 [(id)hwnd setNeedsDisplay:YES];
5441 HWND FindWindowEx(HWND par, HWND lastw, const char *classname, const char *title)
5443 // note: this currently is far far far from fully functional, bleh
5446 if (!title) return NULL;
5448 // get a list of top level windows, find any that match
5449 // (this does not scan child windows, which is a todo really)
5451 NSArray *ch=[NSApp windows];
5452 NSInteger x=0,n=[ch count];
5457 NSWindow *w = [ch objectAtIndex:x];
5458 if ((HWND)w == lastw || (HWND)[w contentView] == lastw) break;
5463 NSString *srch=(NSString*)SWELL_CStringToCFString(title);
5464 for(;x<n && !rv; x ++)
5466 NSWindow *w = [ch objectAtIndex:x];
5467 if ([[w title] isEqualToString:srch]) rv=(HWND)[w contentView];
5473 HWND h=lastw?GetWindow(lastw,GW_HWNDNEXT):GetWindow(par,GW_CHILD);
5481 GetWindowText(h,buf,sizeof(buf));
5482 if (strcmp(title,buf)) isOk=false;
5486 if (!stricmp(classname,"Static") && ![(id)h isKindOfClass:[NSTextField class]]) isOk=false;
5487 // todo: other classname translations
5491 h=GetWindow(h,GW_HWNDNEXT);
5496 BOOL TreeView_SetIndent(HWND hwnd, int indent)
5498 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return 0;
5499 SWELL_TreeView* tv = (SWELL_TreeView*)hwnd;
5500 [tv setIndentationPerLevel:(float)indent];
5504 HTREEITEM TreeView_InsertItem(HWND hwnd, TV_INSERTSTRUCT *ins)
5506 if (!hwnd || !ins) return 0;
5507 if (![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return 0;
5509 SWELL_TreeView *tv=(SWELL_TreeView*)hwnd;
5511 HTREEITEM__ *par=NULL;
5514 if (ins->hParent && ins->hParent != TVI_ROOT && ins->hParent != TVI_FIRST && ins->hParent != TVI_LAST && ins->hParent != TVI_SORT)
5516 if ([tv findItem:ins->hParent parOut:&par idxOut:&inspos])
5518 par = (HTREEITEM__ *)ins->hParent;
5523 if (ins->hInsertAfter == TVI_FIRST) inspos=0;
5524 else if (ins->hInsertAfter == TVI_LAST || ins->hInsertAfter == TVI_SORT || !ins->hInsertAfter) inspos=par ? par->m_children.GetSize() : tv->m_items ? tv->m_items->GetSize() : 0;
5525 else inspos = par ? par->m_children.Find((HTREEITEM__*)ins->hInsertAfter)+1 : tv->m_items ? tv->m_items->Find((HTREEITEM__*)ins->hInsertAfter)+1 : 0;
5527 HTREEITEM__ *item=new HTREEITEM__;
5528 if (ins->item.mask & TVIF_CHILDREN)
5529 item->m_haschildren = !!ins->item.cChildren;
5530 if (ins->item.mask & TVIF_PARAM) item->m_param = ins->item.lParam;
5531 if (ins->item.mask & TVIF_TEXT) item->m_value = strdup(ins->item.pszText);
5534 if (!tv->m_items) tv->m_items = new WDL_PtrList<HTREEITEM__>;
5535 tv->m_items->Insert(inspos,item);
5537 else par->m_children.Insert(inspos,item);
5540 return (HTREEITEM) item;
5543 BOOL TreeView_Expand(HWND hwnd, HTREEITEM item, UINT flag)
5545 if (!hwnd || !item) return false;
5547 if (![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return false;
5549 SWELL_TreeView *tv=(SWELL_TreeView*)hwnd;
5551 id itemid=((HTREEITEM__*)item)->m_dh;
5552 bool isExp=!![tv isItemExpanded:itemid];
5554 if (flag == TVE_EXPAND && !isExp) [tv expandItem:itemid];
5555 else if (flag == TVE_COLLAPSE && isExp) [tv collapseItem:itemid];
5556 else if (flag==TVE_TOGGLE)
5558 if (isExp) [tv collapseItem:itemid];
5559 else [tv expandItem:itemid];
5567 HTREEITEM TreeView_GetSelection(HWND hwnd)
5569 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return NULL;
5571 SWELL_TreeView *tv=(SWELL_TreeView*)hwnd;
5572 NSInteger idx=[tv selectedRow];
5573 if (idx<0) return NULL;
5575 SWELL_DataHold *t=[tv itemAtRow:idx];
5576 if (t) return (HTREEITEM)[t getValue];
5581 void TreeView_DeleteItem(HWND hwnd, HTREEITEM item)
5583 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return;
5584 SWELL_TreeView *tv=(SWELL_TreeView*)hwnd;
5586 HTREEITEM__ *par=NULL;
5589 if ([tv findItem:item parOut:&par idxOut:&idx])
5593 par->m_children.Delete(idx,true);
5595 else if (tv->m_items)
5597 tv->m_items->Delete(idx,true);
5603 void TreeView_DeleteAllItems(HWND hwnd)
5605 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return;
5606 SWELL_TreeView *tv=(SWELL_TreeView*)hwnd;
5608 if (tv->m_items) tv->m_items->Empty(true);
5612 void TreeView_SelectItem(HWND hwnd, HTREEITEM item)
5614 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return;
5616 NSInteger row=[(SWELL_TreeView*)hwnd rowForItem:((HTREEITEM__*)item)->m_dh];
5618 [(SWELL_TreeView*)hwnd selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
5623 NMTREEVIEW nm={{(HWND)hwnd,(UINT_PTR)[(SWELL_TreeView*)hwnd tag],TVN_SELCHANGED},};
5624 SendMessage(GetParent(hwnd),WM_NOTIFY,nm.hdr.idFrom,(LPARAM)&nm);
5629 BOOL TreeView_GetItem(HWND hwnd, LPTVITEM pitem)
5631 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]] || !pitem || !(pitem->mask & TVIF_HANDLE) || !(pitem->hItem)) return FALSE;
5633 HTREEITEM__ *ti = (HTREEITEM__*)pitem->hItem;
5634 pitem->cChildren = ti->m_haschildren ? 1:0;
5635 pitem->lParam = ti->m_param;
5636 if ((pitem->mask&TVIF_TEXT)&&pitem->pszText&&pitem->cchTextMax>0)
5638 lstrcpyn_safe(pitem->pszText,ti->m_value?ti->m_value:"",pitem->cchTextMax);
5643 NSInteger itemRow = [(SWELL_TreeView*)hwnd rowForItem:ti->m_dh];
5644 if (itemRow >= 0 && [(SWELL_TreeView*)hwnd isRowSelected:itemRow])
5645 pitem->state |= TVIS_SELECTED;
5646 if ([(SWELL_TreeView*)hwnd isItemExpanded:ti->m_dh])
5647 pitem->state |= TVIS_EXPANDED;
5652 BOOL TreeView_SetItem(HWND hwnd, LPTVITEM pitem)
5654 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]] || !pitem || !(pitem->mask & TVIF_HANDLE) || !(pitem->hItem)) return FALSE;
5656 HTREEITEM__ *par=NULL;
5659 if (![(SWELL_TreeView*)hwnd findItem:pitem->hItem parOut:&par idxOut:&idx]) return FALSE;
5661 HTREEITEM__ *ti = (HTREEITEM__*)pitem->hItem;
5663 if (pitem->mask & TVIF_CHILDREN) ti->m_haschildren = pitem->cChildren?1:0;
5664 if (pitem->mask & TVIF_PARAM) ti->m_param = pitem->lParam;
5666 if ((pitem->mask&TVIF_TEXT)&&pitem->pszText)
5669 ti->m_value=strdup(pitem->pszText);
5670 InvalidateRect(hwnd, 0, FALSE);
5673 if (pitem->stateMask & TVIS_SELECTED)
5675 NSInteger itemRow = [(SWELL_TreeView*)hwnd rowForItem:ti->m_dh];
5678 if (pitem->state&TVIS_SELECTED)
5680 [(SWELL_TreeView*)hwnd selectRowIndexes:[NSIndexSet indexSetWithIndex:itemRow] byExtendingSelection:NO];
5686 NMTREEVIEW nm={{(HWND)hwnd,(UINT_PTR)[(SWELL_TreeView*)hwnd tag],TVN_SELCHANGED},};
5687 SendMessage(GetParent(hwnd),WM_NOTIFY,nm.hdr.idFrom,(LPARAM)&nm);
5694 // todo figure out unselect?!
5695 // [(SWELL_TreeView*)hwnd selectRowIndexes:[NSIndexSet indexSetWithIndex:itemRow] byExtendingSelection:NO];
5700 if (pitem->stateMask & TVIS_EXPANDED)
5701 TreeView_Expand(hwnd,pitem->hItem,(pitem->state&TVIS_EXPANDED)?TVE_EXPAND:TVE_COLLAPSE);
5707 HTREEITEM TreeView_HitTest(HWND hwnd, TVHITTESTINFO *hti)
5709 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]] || !hti) return NULL;
5710 SWELL_TreeView* tv = (SWELL_TreeView*)hwnd;
5715 for (i = 0; i < [tv numberOfRows]; ++i)
5717 NSRect r = [tv rectOfRow:i];
5718 if (x >= r.origin.x && x < r.origin.x+r.size.width && y >= r.origin.y && y < r.origin.y+r.size.height)
5720 SWELL_DataHold* t = [tv itemAtRow:i];
5721 if (t) return (HTREEITEM)[t getValue];
5726 return NULL; // not hit
5729 HTREEITEM TreeView_GetRoot(HWND hwnd)
5731 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return NULL;
5732 SWELL_TreeView *tv=(SWELL_TreeView*)hwnd;
5734 if (!tv->m_items) return 0;
5735 return (HTREEITEM) tv->m_items->Get(0);
5738 HTREEITEM TreeView_GetChild(HWND hwnd, HTREEITEM item)
5740 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return NULL;
5742 HTREEITEM__ *titem=(HTREEITEM__ *)item;
5743 if (!titem) return TreeView_GetRoot(hwnd);
5745 return (HTREEITEM) titem->m_children.Get(0);
5747 HTREEITEM TreeView_GetNextSibling(HWND hwnd, HTREEITEM item)
5749 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return NULL;
5750 SWELL_TreeView *tv=(SWELL_TreeView*)hwnd;
5752 if (!item) return TreeView_GetRoot(hwnd);
5754 HTREEITEM__ *par=NULL;
5756 if ([tv findItem:item parOut:&par idxOut:&idx])
5760 return par->m_children.Get(idx+1);
5762 if (tv->m_items) return tv->m_items->Get(idx+1);
5767 void TreeView_SetBkColor(HWND hwnd, int color)
5769 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return;
5770 [(NSOutlineView*)hwnd setBackgroundColor:[NSColor colorWithCalibratedRed:GetRValue(color)/255.0f
5771 green:GetGValue(color)/255.0f
5772 blue:GetBValue(color)/255.0f alpha:1.0f]];
5774 void TreeView_SetTextColor(HWND hwnd, int color)
5776 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_TreeView class]]) return;
5778 SWELL_TreeView *f = (SWELL_TreeView *)hwnd;
5779 [f->m_fgColor release];
5780 f->m_fgColor = [NSColor colorWithCalibratedRed:GetRValue(color)/255.0f
5781 green:GetGValue(color)/255.0f
5782 blue:GetBValue(color)/255.0f alpha:1.0f];
5783 [f->m_fgColor retain];
5785 void ListView_SetBkColor(HWND hwnd, int color)
5787 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_ListView class]]) return;
5788 [(NSTableView*)hwnd setBackgroundColor:[NSColor colorWithCalibratedRed:GetRValue(color)/255.0f
5789 green:GetGValue(color)/255.0f
5790 blue:GetBValue(color)/255.0f alpha:1.0f]];
5793 void ListView_SetSelColors(HWND hwnd, int *colors, int ncolors) // this works for SWELL_ListView as well as SWELL_TreeView
5796 NSMutableArray *ar=[[NSMutableArray alloc] initWithCapacity:ncolors];
5800 const int color = colors ? *colors++ : 0;
5801 [ar addObject:[NSColor colorWithCalibratedRed:GetRValue(color)/255.0f
5802 green:GetGValue(color)/255.0f
5803 blue:GetBValue(color)/255.0f alpha:1.0f]];
5806 if ([(id)hwnd isKindOfClass:[SWELL_ListView class]])
5808 SWELL_ListView *lv = (SWELL_ListView*)hwnd;
5809 [lv->m_selColors release];
5812 else if ([(id)hwnd isKindOfClass:[SWELL_TreeView class]])
5814 SWELL_TreeView *lv = (SWELL_TreeView*)hwnd;
5815 [lv->m_selColors release];
5823 void ListView_SetGridColor(HWND hwnd, int color)
5825 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_ListView class]]) return;
5826 [(NSTableView*)hwnd setGridColor:[NSColor colorWithCalibratedRed:GetRValue(color)/255.0f
5827 green:GetGValue(color)/255.0f
5828 blue:GetBValue(color)/255.0f alpha:1.0f]];
5830 void ListView_SetTextBkColor(HWND hwnd, int color)
5832 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_ListView class]]) return;
5833 // not implemented atm
5835 void ListView_SetTextColor(HWND hwnd, int color)
5837 if (!hwnd || ![(id)hwnd isKindOfClass:[SWELL_ListView class]]) return;
5839 SWELL_ListView *f = (SWELL_ListView *)hwnd;
5840 [f->m_fgColor release];
5841 f->m_fgColor = [NSColor colorWithCalibratedRed:GetRValue(color)/255.0f
5842 green:GetGValue(color)/255.0f
5843 blue:GetBValue(color)/255.0f alpha:1.0f];
5844 [f->m_fgColor retain];
5848 BOOL ShellExecute(HWND hwndDlg, const char *action, const char *content1, const char *content2, const char *content3, int blah)
5850 if (content1 && !strnicmp(content1,"http://",7))
5852 NSWorkspace *wk = [NSWorkspace sharedWorkspace];
5853 if (!wk) return FALSE;
5854 NSString *fnstr=(NSString *)SWELL_CStringToCFString(content1);
5855 BOOL ret=[wk openURL:[NSURL URLWithString:fnstr]];
5860 if (content1 && !stricmp(content1,"explorer.exe")) content1="";
5861 else if (content1 && (!stricmp(content1,"notepad.exe")||!stricmp(content1,"notepad"))) content1="TextEdit.app";
5863 if (content2 && !stricmp(content2,"explorer.exe")) content2="";
5865 if (content1 && content2 && *content1 && *content2)
5867 NSWorkspace *wk = [NSWorkspace sharedWorkspace];
5868 if (!wk) return FALSE;
5869 NSString *appstr=(NSString *)SWELL_CStringToCFString(content1);
5870 NSString *fnstr=(NSString *)SWELL_CStringToCFString(content2);
5871 BOOL ret=[wk openFile:fnstr withApplication:appstr andDeactivate:YES];
5876 else if ((content1&&*content1) || (content2&&*content2))
5878 const char *fn = (content1 && *content1) ? content1 : content2;
5879 NSWorkspace *wk = [NSWorkspace sharedWorkspace];
5880 if (!wk) return FALSE;
5881 NSString *fnstr = nil;
5884 if (fn && !strnicmp(fn, "/select,\"", 9))
5886 char* tmp = strdup(fn+9);
5887 if (*tmp && tmp[strlen(tmp)-1]=='\"') tmp[strlen(tmp)-1]='\0';
5890 if ([wk respondsToSelector:@selector(activateFileViewerSelectingURLs:)]) // 10.6+
5892 fnstr=(NSString *)SWELL_CStringToCFString(tmp);
5893 NSURL *url = [NSURL fileURLWithPath:fnstr isDirectory:false];
5896 [wk activateFileViewerSelectingURLs:[NSArray arrayWithObjects:url, nil]]; // NSArray (and NSURL) autoreleased
5902 if (WDL_remove_filepart(tmp))
5904 fnstr=(NSString *)SWELL_CStringToCFString(tmp);
5905 ret=[wk openFile:fnstr];
5911 else if (strlen(fn)>4 && !stricmp(fn+strlen(fn)-4,".app"))
5913 fnstr=(NSString *)SWELL_CStringToCFString(fn);
5914 ret=[wk launchApplication:fnstr];
5918 fnstr=(NSString *)SWELL_CStringToCFString(fn);
5919 ret=[wk openFile:fnstr];
5930 @implementation SWELL_FocusRectWnd
5932 -(BOOL)isOpaque { return YES; }
5933 -(void) drawRect:(NSRect)rect
5935 NSColor *col=[NSColor colorWithCalibratedRed:0.5 green:0.5 blue:0.5 alpha:1.0];
5938 CGRect r = CGRectMake(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);
5940 CGContextRef ctx = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
5942 CGContextFillRect(ctx,r);
5947 // r=NULL to "free" handle
5948 // otherwise r is in hwndPar coordinates
5949 void SWELL_DrawFocusRect(HWND hwndPar, RECT *rct, void **handle)
5951 if (!handle) return;
5952 NSWindow *wnd = (NSWindow *)*handle;
5958 NSWindow *ow=[wnd parentWindow];
5959 if (ow) [ow removeChildWindow:wnd];
5960 // [wnd setParentWindow:nil];
5970 ClientToScreen(hwndPar,((LPPOINT)&r));
5971 ClientToScreen(hwndPar,((LPPOINT)&r)+1);
5977 if (r.top>r.bottom) { int a=r.top; r.top=r.bottom;r.bottom=a; }
5978 NSRect rr=NSMakeRect(r.left,r.top,r.right-r.left,r.bottom-r.top);
5983 if ([(id)hwndPar isKindOfClass:[NSWindow class]]) par=(NSWindow *)hwndPar;
5984 else if ([(id)hwndPar isKindOfClass:[NSView class]]) par=[(NSView *)hwndPar window];
5988 if (wnd && ([wnd parentWindow] != par))
5990 NSWindow *ow=[wnd parentWindow];
5991 if (ow) [ow removeChildWindow:wnd];
5992 // [wnd setParentWindow:nil];
6000 *handle = wnd = [[NSWindow alloc] initWithContentRect:rr styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
6001 [wnd setOpaque:YES];
6002 [wnd setAlphaValue:0.5];
6003 [wnd setExcludedFromWindowsMenu:YES];
6004 [wnd setIgnoresMouseEvents:YES];
6005 [wnd setContentView:[[SWELL_FocusRectWnd alloc] init]];
6007 if (par) [par addChildWindow:wnd ordered:NSWindowAbove];
6010 [wnd setLevel:NSPopUpMenuWindowLevel];
6011 [wnd orderFront:wnd];
6013 // [wnd setParentWindow:par];
6014 // [wnd orderWindow:NSWindowAbove relativeTo:[par windowNumber]];
6017 [wnd setFrame:rr display:YES];
6022 @implementation SWELL_PopUpButton
6023 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
6025 -(void)setSwellStyle:(LONG)style { m_style=style; }
6026 -(LONG)getSwellStyle { return m_style; }
6029 @implementation SWELL_ComboBox
6030 STANDARD_CONTROL_NEEDSDISPLAY_IMPL
6032 -(void)setSwellStyle:(LONG)style { m_style=style; }
6033 -(LONG)getSwellStyle { return m_style; }
6034 -(id)init { self = [super init]; if (self) { m_ids=new WDL_PtrList<char>; } return self; }
6035 -(void)dealloc { delete m_ids; [super dealloc]; }
6036 - (BOOL)becomeFirstResponder;
6038 BOOL didBecomeFirstResponder = [super becomeFirstResponder];
6039 if (didBecomeFirstResponder) SendMessage(GetParent((HWND)self),WM_COMMAND,[self tag]|(EN_SETFOCUS<<16),(LPARAM)self);
6040 return didBecomeFirstResponder;
6047 bool SWELL_HandleMouseEvent(NSEvent *evt)
6049 NSEventType etype = [evt type];
6050 if (GetCapture()) return false;
6051 if (etype >= NSLeftMouseDown && etype <= NSRightMouseDragged)
6056 NSWindow *w = [evt window];
6059 NSView *cview = [w contentView];
6060 NSView *besthit=NULL;
6063 NSPoint lpt = [evt locationInWindow];
6064 NSView *hitv=[cview hitTest:lpt];
6065 lpt = [w convertBaseToScreen:lpt];
6067 int xpos=(int)floor(lpt.x);
6068 int ypos=(int)floor(lpt.y);
6072 int ht=(int)sendSwellMessage(hitv,WM_NCHITTEST,0,MAKELPARAM(xpos,ypos));
6073 if (ht && ht != HTCLIENT) besthit=hitv;
6075 if (hitv==cview) break;
6076 hitv = [hitv superview];
6081 if (etype == NSLeftMouseDown) [besthit mouseDown:evt];
6082 else if (etype == NSLeftMouseUp) [besthit mouseUp:evt];
6083 else if (etype == NSLeftMouseDragged) [besthit mouseDragged:evt];
6084 else if (etype == NSRightMouseDown) [besthit rightMouseDown:evt];
6085 else if (etype == NSRightMouseUp) [besthit rightMouseUp:evt];
6086 else if (etype == NSRightMouseDragged) [besthit rightMouseDragged:evt];
6087 else if (etype == NSMouseMoved) [besthit mouseMoved:evt];
6096 int SWELL_GetWindowWantRaiseAmt(HWND h)
6098 SWELL_ModelessWindow* mw=0;
6099 if ([(id)h isKindOfClass:[SWELL_ModelessWindow class]])
6101 mw=(SWELL_ModelessWindow*)h;
6103 else if ([(id)h isKindOfClass:[NSView class]])
6105 NSWindow* wnd=[(NSView*)h window];
6106 if (wnd && [wnd isKindOfClass:[SWELL_ModelessWindow class]])
6108 mw=(SWELL_ModelessWindow*)wnd;
6111 if (mw) return mw->m_wantraiseamt;
6115 void SWELL_SetWindowWantRaiseAmt(HWND h, int amt)
6117 SWELL_ModelessWindow *mw=NULL;
6118 if ([(id)h isKindOfClass:[SWELL_ModelessWindow class]]) mw=(SWELL_ModelessWindow *)h;
6119 else if ([(id)h isKindOfClass:[NSView class]])
6121 NSWindow *w = [(NSView *)h window];
6122 if (w && [w isKindOfClass:[SWELL_ModelessWindow class]]) mw = (SWELL_ModelessWindow*)w;
6126 int diff = amt - mw->m_wantraiseamt;
6127 mw->m_wantraiseamt = amt;
6128 if (diff && [NSApp isActive]) [mw setLevel:[mw level]+diff];
6133 int SWELL_SetWindowLevel(HWND hwnd, int newlevel)
6135 NSWindow *w = (NSWindow *)hwnd;
6136 if (w && [w isKindOfClass:[NSView class]]) w= [(NSView *)w window];
6138 if (w && [w isKindOfClass:[NSWindow class]])
6140 int ol = (int)[w level];
6141 [w setLevel:newlevel];
6147 void SetAllowNoMiddleManRendering(HWND h, bool allow)
6149 if (!h || ![(id)h isKindOfClass:[SWELL_hwndChild class]]) return;
6150 SWELL_hwndChild* v = (SWELL_hwndChild*)h;
6151 v->m_allow_nomiddleman = allow;
6154 void SetOpaque(HWND h, bool opaque)
6156 if (!h || ![(id)h isKindOfClass:[SWELL_hwndChild class]]) return;
6157 SWELL_hwndChild* v = (SWELL_hwndChild*)h;
6158 [v setOpaque:opaque];
6161 void SetTransparent(HWND h)
6165 if ([(id)h isKindOfClass:[NSWindow class]]) wnd=(NSWindow*)h;
6166 else if ([(id)h isKindOfClass:[NSView class]]) wnd=[(NSView*)h window];
6169 [wnd setBackgroundColor:[NSColor clearColor]];
6174 int SWELL_GetDefaultButtonID(HWND hwndDlg, bool onlyIfEnabled)
6176 if (![(id)hwndDlg isKindOfClass:[NSView class]]) return 0;
6177 NSWindow *wnd = [(NSView *)hwndDlg window];
6178 NSButtonCell * cell = wnd ? [wnd defaultButtonCell] : nil;
6180 if (!cell || !(view=[cell controlView])) return 0;
6181 int cmdid = (int)[view tag];
6182 if (cmdid && onlyIfEnabled)
6184 if (![cell isEnabled]) return 0;
6190 void SWELL_SetWindowRepre(HWND hwnd, const char *fn, bool isDirty)
6194 if ([(id)hwnd isKindOfClass:[NSWindow class]]) w=(NSWindow *)hwnd;
6195 if ([(id)hwnd isKindOfClass:[NSView class]]) w=[(NSView *)hwnd window];
6199 if (GetProp((HWND)[w contentView],"SWELL_DisableWindowRepre")) return;
6201 [w setDocumentEdited:isDirty];
6203 if (!fn || !*fn) [w setRepresentedFilename:@""];
6206 NSString *str = (NSString *)SWELL_CStringToCFString(fn);
6207 [w setRepresentedFilename:str];
6213 void SWELL_SetWindowShadow(HWND hwnd, bool shadow)
6216 NSWindow *w = (NSWindow *)hwnd;
6217 if ([w isKindOfClass:[NSView class]]) w = [(NSView *)w window];
6218 if (w && [w isKindOfClass:[NSWindow class]]) [w setHasShadow:shadow];
6221 #if 0 // not sure if this will interfere with coolSB
6222 BOOL ShowScrollBar(HWND hwnd, int nBar, BOOL vis)
6225 if (nBar == SB_HORZ || nBar == SB_BOTH) v |= WS_HSCROLL;
6226 if (nBar == SB_VERT || nBar == SB_BOTH) v |= WS_VSCROLL;
6229 int s=GetWindowLong(hwnd, GWL_STYLE);
6232 SetWindowLong(hwnd, GWL_STYLE, s);
6233 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
6241 void SWELL_GenerateDialogFromList(const void *_list, int listsz)
6243 #define SIXFROMLIST list->p1,list->p2,list->p3, list->p4, list->p5, list->p6
6244 SWELL_DlgResourceEntry *list = (SWELL_DlgResourceEntry*)_list;
6247 if (!strcmp(list->str1,"__SWELL_BUTTON"))
6249 SWELL_MakeButton(list->flag1,list->str2, SIXFROMLIST);
6251 else if (!strcmp(list->str1,"__SWELL_EDIT"))
6253 SWELL_MakeEditField(SIXFROMLIST);
6255 else if (!strcmp(list->str1,"__SWELL_COMBO"))
6257 SWELL_MakeCombo(SIXFROMLIST);
6259 else if (!strcmp(list->str1,"__SWELL_LISTBOX"))
6261 SWELL_MakeListBox(SIXFROMLIST);
6263 else if (!strcmp(list->str1,"__SWELL_GROUP"))
6265 SWELL_MakeGroupBox(list->str2,SIXFROMLIST);
6267 else if (!strcmp(list->str1,"__SWELL_CHECKBOX"))
6269 SWELL_MakeCheckBox(list->str2,SIXFROMLIST);
6271 else if (!strcmp(list->str1,"__SWELL_LABEL"))
6273 SWELL_MakeLabel(list->flag1, list->str2, SIXFROMLIST);
6275 else if (*list->str2)
6277 SWELL_MakeControl(list->str1, list->flag1, list->str2, SIXFROMLIST);
6284 BOOL EnumChildWindows(HWND hwnd, BOOL (*cwEnumFunc)(HWND,LPARAM),LPARAM lParam)
6286 if (!hwnd || ![(id)hwnd isKindOfClass:[NSView class]]) return TRUE;
6287 NSArray *ar = [(NSView *)hwnd subviews];
6291 NSInteger x,n=[ar count];
6294 NSView *v = [ar objectAtIndex:x];
6297 if ([v isKindOfClass:[NSScrollView class]])
6299 NSView *sv=[(NSScrollView *)v documentView];
6302 if ([v isKindOfClass:[NSClipView class]])
6304 NSView *sv = [(NSClipView *)v documentView];
6308 if (!cwEnumFunc((HWND)v,lParam) || !EnumChildWindows((HWND)v,cwEnumFunc,lParam))
6320 void SWELL_GetDesiredControlSize(HWND hwnd, RECT *r)
6322 if (hwnd && r && [(id)hwnd isKindOfClass:[NSControl class]])
6324 NSControl *c = (NSControl *)hwnd;
6325 NSRect fr = [c frame];
6327 NSRect frnew=[c frame];
6330 r->right = (int)frnew.size.width;
6331 r->bottom = (int)frnew.size.height;
6335 BOOL SWELL_IsGroupBox(HWND hwnd)
6337 if (hwnd && [(id)hwnd isKindOfClass:[SWELL_BoxView class]]) return TRUE;
6340 BOOL SWELL_IsButton(HWND hwnd)
6342 if (hwnd && [(id)hwnd isKindOfClass:[SWELL_Button class]]) return TRUE;
6345 BOOL SWELL_IsStaticText(HWND hwnd)
6347 if (hwnd && [(id)hwnd isKindOfClass:[NSTextField class]]) return TRUE;
6353 bool SWELL_SetAppAutoHideMenuAndDock(int ah)
6356 static NSUInteger _defpres;
6359 if (SWELL_GetOSXVersion()>=0x1060)
6362 _defpres = [(SWELL_AppExtensions*)[NSApplication sharedApplication] presentationOptions];
6371 const int NSApplicationPresentationAutoHideDock = (1 << 0),
6372 NSApplicationPresentationHideDock = (1<<1),
6373 NSApplicationPresentationAutoHideMenuBar = (1 << 2);
6375 if (ah>0) [(SWELL_AppExtensions*)[NSApplication sharedApplication] setPresentationOptions:((ah>=2?NSApplicationPresentationHideDock:NSApplicationPresentationAutoHideDock)|NSApplicationPresentationAutoHideMenuBar)];
6376 else [(SWELL_AppExtensions*)[NSApplication sharedApplication] setPresentationOptions:_defpres];