event handling (min/max);
authorClaus Gittinger <cg@exept.de>
Wed, 05 Dec 2001 15:56:15 +0100
changeset 3570 b48b4f789317
parent 3569 38818408ecae
child 3571 7b97a1b3ff80
event handling (min/max); native MessageBox support
WinWorkstation.st
--- a/WinWorkstation.st	Tue Dec 04 17:45:42 2001 +0100
+++ b/WinWorkstation.st	Wed Dec 05 15:56:15 2001 +0100
@@ -28,30 +28,24 @@
 #define COUNT_RESOURCES       /* */
 #define COUNT_BMP_RESOURCES   /* */
 #define DEBUG_DELETEOBJECT    /* */
-#define DEBUG_DC_REUSE    /* */
+#define DEBUG_DC_REUSE        /* */
 
 #define ADJUSTWINDOW
 #define ALWAYSTRUECOLOR
 #define WIN32THREADS
+
 /* #define DEBUGMASK            /* */
 #define SET_FOCUS_IN_WINTHREAD
 #define SET_CURSOR_IN_WINTHREAD
 #define DELAY_ENTER_LEAVE_WHILE_IN_SIZE_MOVE /* */
-/* #define BEEP_IN_WINTHREAD    /* */
-/* #define KEEP_STD_CURSORS    /* not useful - those are allocated only once, in any case */
-/* #define HANDLE_VIEWGRAVITY  /* not yet working */
+#define xxBEEP_IN_WINTHREAD    /* */
+#define xxKEEP_STD_CURSORS     /* not useful - those are allocated only once, in any case */
+#define xxHANDLE_VIEWGRAVITY   /* not yet working */
+#define xxCOMPRESS_WINDOWPOSCHANGED
 
 #define LATE_WM_PAINT                   /* fill-bg in ST/X thread (instead of in event-thread) */
 					/* seems to be needed to avoid DC conflicts */
 
-#ifdef LATE_WM_PAINT
-# define ONE_IF_LATE_WM_PAINT   1
-# define ZERO_IF_LATE_WM_PAINT  0
-#else
-# define ONE_IF_LATE_WM_PAINT   0
-# define ZERO_IF_LATE_WM_PAINT  1
-#endif
-
 #define CACHE_LAST_DC                   /* remember last DC in gcData */
 #define CACHE_LAST_PEN                  /* remember last pen in gcData */
 #define CACHE_LAST_BRUSH                /* remember last brush in gcData */
@@ -67,6 +61,14 @@
 #define MAX_NUM_PEN_CACHED   32         /* upper limit */
 #define MAX_NUM_BRUSH_CACHED 32         /* upper limit */
 
+#ifdef LATE_WM_PAINT
+# define ONE_IF_LATE_WM_PAINT   1
+# define ZERO_IF_LATE_WM_PAINT  0
+#else
+# define ONE_IF_LATE_WM_PAINT   0
+# define ZERO_IF_LATE_WM_PAINT  1
+#endif
+
 #undef INT
 #define INT WIN_INT
 #undef Array
@@ -787,7 +789,8 @@
  * a need to access the Mutex
  */
 #define NUMQUICKFREE_EV    32
-static struct queuedEvent *quickFreeEvent[NUMQUICKFREE_EV];
+#define NUMQUICKFREE_EV    0
+static struct queuedEvent *quickFreeEvent[NUMQUICKFREE_EV+1];
 static struct queuedEvent *eventQueueHead = (struct queuedEvent *)0;
 static struct queuedEvent *eventQueueTail = (struct queuedEvent *)0;
 static int eventsendcount = 0;
@@ -816,11 +819,13 @@
  static HDC  last_wm_paint_dc = 0;
 #endif
 
-static HWND lastPos_win = 0;
-static int lastPos_w;
-static int lastPos_h;
-static int lastPos_x;
-static int lastPos_y;
+#ifdef COMPRESS_WINDOWPOSCHANGED
+ static HWND lastPos_win = 0;
+ static int lastPos_w;
+ static int lastPos_h;
+ static int lastPos_x;
+ static int lastPos_y;
+#endif
 
 %}
 ! !
@@ -1955,7 +1960,9 @@
 		}
 	    }
 	    if (i == NUMQUICKFREE_EV) {
-		lockEventFreeList();
+		if (! lockEventFreeList()) {
+		    fprintf(stderr, "WinWorkstation [error]: could not lock evFreeList\n");
+		}
 		ev->ev_next = eventFreeList;
 		eventFreeList = ev;
 		unlockEventFreeList();
@@ -2117,7 +2124,7 @@
 	RECT *pRect;
 	union {
 	    RGNDATA rgnData;
-	    char    bytes[256];
+	    char    bytes[512];
 	} data;
 
 	wantExpose = (GetWindow_eventMask(hWnd) & ExposureMask);
@@ -2125,11 +2132,18 @@
 	if (hRgnInOrNull) {
 	    updRgn = hRgnInOrNull;
 	} else {
+	    PAINTSTRUCT ps;
+
 	    /*
 	     * fetch the update region, even if ExposureMask is empty.
 	     */
 	    updRgn = CreateRectRgn(0, 0, 0, 0);
 	    ret = GetUpdateRgn(hWnd, updRgn, FALSE);
+
+	    BeginPaint(hWnd, &ps);
+	    /* store the rectangle required for image bit reversal */
+	    /* updateRect = ps.rcPaint;   */
+	    EndPaint(hWnd, &ps);
         
 	    switch (ret) {
 		case ERROR:
@@ -2157,7 +2171,7 @@
 	    numRects = data.rgnData.rdh.nCount;
 	    pRect = data.rgnData.Buffer;
 	    DPRINTF(("region numRects=%d\n", numRects));
-	} else{
+	} else {
 	    /* a big region ... */
 	    GetRgnBox(updRgn, &updRect);
 	    numRects = 1;
@@ -2172,10 +2186,6 @@
 	    }
 	}
 
-	if (updRgn && (updRgn != hRgnInOrNull)) {
-	    _DeleteObject(updRgn, __LINE__);
-	}
-
 	if (numRects) {
 	    if (doClear) {
 		__clearRectangles(hWnd, numRects, pRect);
@@ -2198,6 +2208,10 @@
 	    }
 	}
 
+	if (updRgn && (updRgn != hRgnInOrNull)) {
+	    _DeleteObject(updRgn, __LINE__);
+	}
+
 	return numRects;
 }
 
@@ -2378,7 +2392,7 @@
 }
 #endif /* HANDLE_VIEWGRAVITY */
 
-static
+static int
 winEventProcessing(hWnd, message, wParam, lParam, pDefault)
     HWND hWnd;                /* window handle                   */
     UINT message;             /* type of message                 */
@@ -2742,7 +2756,8 @@
 		    }
 		    if (!(wp->flags & SWP_NOSIZE) 
 		     || !(wp->flags & SWP_NOMOVE)) {
-			enqEvent(ENQ_AT_END, 0, hWnd, WM_WINDOWPOSCHANGED, wParam, x, y, w, h, EV_NOTIME);
+			enqEvent(ENQ_AT_END, 0, hWnd, WM_WINDOWPOSCHANGED, 0, x, y, w, h, EV_NOTIME);
+#ifdef COMPRESS_WINDOWPOSCHANGED
 			/*
 			 * remember the current
 			 * window and size;
@@ -2755,6 +2770,7 @@
 			lastPos_x = x;
 			lastPos_y = y;
 			lastPos_win = hWnd;
+#endif
 		    }
 		}
 	    }
@@ -2796,8 +2812,12 @@
 
 	    if (((GetWindow_flag(hWnd) & LI_INPUTWIN) == 0)
 	     && (hWnd != __rootWinSpezial)) {
-		switch (__generateExposes(hWnd, NULL, WM_PAINT, ZERO_IF_LATE_WM_PAINT)) 
-		{
+		PAINTSTRUCT dummyPaint;
+		int retVal;
+
+		retVal = __generateExposes(hWnd, NULL, WM_PAINT, ZERO_IF_LATE_WM_PAINT);
+
+		switch (retVal) {
 		    case -1:  /* error */
 			*pDefault = 0;
 			break;
@@ -2805,7 +2825,7 @@
 		    default:  /* generated events */
 			break;
 		}
-# if 0
+# ifdef THIS_IS_BAD
 		*pDefault = 0;
 		return 1;
 # endif
@@ -2818,8 +2838,65 @@
 
 	case WM_SIZE:
 	    EVENT_PRINTF(("WM_SIZE\n"));
-	    *pDefault = 0;
-	    return 0;
+	    /*
+	     * ignore child window messages ...
+	     */
+	    if (GetParent(hWnd) != NULL) {
+		*pDefault = 0;
+		return 0;
+	    }
+
+	    switch (wParam) {
+		case SIZE_MAXIMIZED:     /* default handling */
+		case SIZE_MINIMIZED:     /* default handling */
+		case SIZE_RESTORED:      /* default handling */
+		    {
+			RECT rct;
+			int x, y, w, h;
+
+			GetClientRect(hWnd, &rct);
+
+			x = rct.left;
+			y = rct.top;
+			w = rct.right - rct.left;
+			h = rct.bottom - rct.top;
+
+			if ((w == 0) && (h == 0)) {
+			    /*
+			     * iconified ...
+			     */
+			    if (! GetWindow_iconified(hWnd)) {
+				SetWindow_iconified(hWnd, 1);
+				enqEvent(ENQ_AT_END, 0, hWnd, __WM_ICONIFIED, 1, 0, 0, 0, 0, EV_NOTIME);
+			    }
+			} else {
+			    if (GetWindow_iconified(hWnd)) {
+				SetWindow_iconified(hWnd, 0);
+				enqEvent(ENQ_AT_END, 0, hWnd, __WM_ICONIFIED, 0, 0, 0, 0, 0, EV_NOTIME);
+			    }
+			    enqEvent(ENQ_AT_END, 0, hWnd, WM_WINDOWPOSCHANGED, 0, x, y, w, h, EV_NOTIME);
+#ifdef COMPRESS_WINDOWPOSCHANGED
+			    /*
+			     * remember the current
+			     * window and size;
+			     * This allows the backend to ignore
+			     * intermediate events.
+			     */
+			    lastPos_win = 0;
+			    lastPos_w = w;
+			    lastPos_h = h;
+			    lastPos_x = x;
+			    lastPos_y = y;
+			    lastPos_win = hWnd;
+#endif
+			}
+		   }
+		   break;
+
+		default:                 /* ignore */
+		    *pDefault = 0;
+		    return 0;
+	    }
 	    break;
 
 	case WM_DROPFILES:
@@ -3475,7 +3552,11 @@
 	    EVENT_PRINTF(("WM_SETTEXT\n"));
 	    break;
 
+#ifdef WM_SYNCPAINT
+	case WM_SYNCPAINT:
+#else
 	case 0x88:
+#endif
 	    EVENT_PRINTF(("0x88 (undoc)\n"));
 	    break;
 
@@ -3776,6 +3857,165 @@
 	    enqEvent(ENQ_AT_END, 0, hWnd, message, wParam, 0, 0, 0, 0, EV_NOTIME);
 	    break;
 
+#if 0
+	case WM_NULL:                       
+	    EVENT_PRINTF(("WM_NULL\n"));
+	    break;
+
+	case WM_ENABLE:                       
+	    EVENT_PRINTF(("WM_ENABLE\n"));
+	    break;
+
+	case WM_SETREDRAW:                       
+	    EVENT_PRINTF(("WM_SETREDRAW\n"));
+	    break;
+
+	case WM_DEVMODECHANGE:                
+	    EVENT_PRINTF(("WM_DEVMODECHANGE\n"));
+	    break;
+
+	case WM_TIMECHANGE:                   
+	    EVENT_PRINTF(("WM_TIMECHANGE\n"));
+	    break;
+
+	case WM_CANCELMODE:                   
+	    EVENT_PRINTF(("WM_CANCELMODE\n"));
+	    break;
+
+	case WM_CHILDACTIVATE:                
+	    EVENT_PRINTF(("WM_CHILDACTIVATE\n"));
+	    break;
+
+	case WM_QUEUESYNC:                    
+	    EVENT_PRINTF(("WM_QUEUESYNC\n"));
+	    break;
+
+	case WM_NEXTDLGCTL:                   
+	    EVENT_PRINTF(("WM_NEXTDLGCTL\n"));
+	    break;
+
+	case WM_SPOOLERSTATUS:               
+	    EVENT_PRINTF(("WM_SPOOLERSTATUS\n"));
+	    break;
+
+	case WM_DRAWITEM:                     
+	    EVENT_PRINTF(("WM_DRAWITEM\n"));
+	    break;
+
+	case WM_MEASUREITEM:                  
+	    EVENT_PRINTF(("WM_MEASUREITEM\n"));
+	    break;
+
+	case WM_DELETEITEM:                   
+	    EVENT_PRINTF(("WM_DELETEITEM\n"));
+	    break;
+
+	case WM_VKEYTOITEM:                   
+	    EVENT_PRINTF(("WM_VKEYTOITEM\n"));
+	    break;
+
+	case WM_CHARTOITEM:                   
+	    EVENT_PRINTF(("WM_CHARTOITEM\n"));
+	    break;
+
+	case WM_SETFONT:                      
+	    EVENT_PRINTF(("WM_SETFONT\n"));
+	    break;
+
+	case WM_GETFONT:                      
+	    EVENT_PRINTF(("WM_GETFONT\n"));
+	    break;
+
+	case WM_SETHOTKEY:                    
+	    EVENT_PRINTF(("WM_SETHOTKEY\n"));
+	    break;
+
+	case WM_GETHOTKEY:                    
+	    EVENT_PRINTF(("WM_GETHOTKEY\n"));
+	    break;
+
+	case WM_QUERYDRAGICON:                
+	    EVENT_PRINTF(("WM_QUERYDRAGICON\n"));
+	    break;
+
+	case WM_COMPAREITEM:                  
+	    EVENT_PRINTF(("WM_COMPAREITEM\n"));
+	    break;
+
+	case WM_GETOBJECT:                    
+	    EVENT_PRINTF(("WM_GETOBJECT\n"));
+	    break;
+
+	case WM_COMPACTING:                   
+	    EVENT_PRINTF(("WM_COMPACTING\n"));
+	    break;
+
+	case WM_COMMNOTIFY:                   
+	    EVENT_PRINTF(("WM_COMMNOTIFY\n"));
+	    break;
+
+	case WM_COPYDATA:                     
+	    EVENT_PRINTF(("WM_COPYDATA\n"));
+	    break;
+
+	case WM_CANCELJOURNAL:                
+	    EVENT_PRINTF(("WM_CANCELJOURNAL\n"));
+	    break;
+
+	case WM_NOTIFY:                
+	    EVENT_PRINTF(("WM_NOTIFY\n"));
+	    break;
+
+	case WM_INPUTLANGCHANGEREQUEST:                
+	    EVENT_PRINTF(("WM_INPUTLANGCHANGEREQUEST\n"));
+	    break;
+
+	case WM_INPUTLANGCHANGE:                
+	    EVENT_PRINTF(("WM_INPUTLANGCHANGE\n"));
+	    break;
+
+	case WM_TCARD:                
+	    EVENT_PRINTF(("WM_TCARD\n"));
+	    break;
+
+	case WM_HELP:                
+	    EVENT_PRINTF(("WM_HELP\n"));
+	    break;
+
+	case WM_USERCHANGED:                
+	    EVENT_PRINTF(("WM_USERCHANGED\n"));
+	    break;
+
+	case WM_NOTIFYFORMAT:                
+	    EVENT_PRINTF(("WM_NOTIFYFORMAT\n"));
+	    break;
+
+	case WM_CONTEXTMENU:                
+	    EVENT_PRINTF(("WM_CONTEXTMENU\n"));
+	    break;
+
+	case WM_GETICON:                
+	    EVENT_PRINTF(("WM_GETICON\n"));
+	    break;
+
+	case WM_SETICON:                
+	    EVENT_PRINTF(("WM_SETICON\n"));
+	    break;
+
+	case WM_NCXBUTTONDOWN:                
+	    EVENT_PRINTF(("WM_NCXBUTTONDOWN\n"));
+	    break;
+
+	case WM_NCXBUTTONUP:                
+	    EVENT_PRINTF(("WM_NCXBUTTONUP\n"));
+	    break;
+
+	case WM_NCXBUTTONDBLCLK:                
+	    EVENT_PRINTF(("WM_NCXBUTTONDBLCLK\n"));
+	    break;
+
+#endif
+
 	default:
 	    UNHANDLED_EVENT_PRINTF(("WinWorkstat [info]: unhandled msg = %x\n", message));
 	    break;
@@ -4029,9 +4269,11 @@
 		EVENT_PRINTF(("*WM_KILLFOCUS\n"));
 		continue;
 #endif
+#if 0
 	    case WM_SIZE:
 		EVENT_PRINTF(("*WM_SIZE\n"));
 		continue;
+#endif
 	}
 
 	/*
@@ -9843,6 +10085,7 @@
 
 	do { /* only to allow continue */
 	    if (deqEvent(ev, wWanted, evMask)) {
+#ifdef COMPRESS_WINDOWPOSCHANGED
 		if ((ev->ev_hWnd == lastPos_win)
 		 && (ev->ev_message == WM_WINDOWPOSCHANGED)
 		 && ((ev->ev_arg1 != lastPos_x)
@@ -9850,11 +10093,13 @@
 		     || (ev->ev_arg3 != lastPos_w)
 		     || (ev->ev_arg4 != lastPos_h))) {
 		    /*
-		     * ignore resize 
-		     * (that event is an intermediate one)
+		     * ignore intermediate resize events
+		     * (that event is an intermediate one, because the peek-values
+		     *  have already been updated for another event)
 		     */
 		    continue;
 		}
+#endif
 		RETURN ( true );
 	    }
 	} while (0);
@@ -12304,6 +12549,161 @@
 	extension:nil
 	blocking:true   
     "
+!
+
+nativeMessageBoxFor:ownerId text:textOrNil title:titleOrNil flags:flagArray blocking:blocking
+    "start a native message box dialog.
+
+     EXPERIMENTAL & non-portable: use with caution"
+
+    |errorCode answer|
+
+%{  /* STACK: 32000*/
+
+#ifndef NO_NATIVE_DIALOGS
+    HWND hWndOwner = NULL;
+    int boxFlags = 0;
+    char *__title;
+    char *__text;
+    int __answer;
+
+    if (__isExternalAddress(ownerId)) {
+	hWndOwner = _HWNDVal(ownerId);
+    }
+    if (__isString(titleOrNil)) {
+	__title = __stringVal(titleOrNil);
+    } else {
+	__title = "";
+    }
+    if (__isString(textOrNil)) {
+	__text = __stringVal(textOrNil);
+    } else {
+	__text = "";
+    }
+
+    if (__isNonNilObject(flagArray) && __isArray(flagArray)) {
+	int i;
+
+	for (i=0; i<__arraySize(flagArray); i++) {
+	    OBJ flag = __ArrayInstPtr(flagArray)->a_element[i];
+	    int flagVal = 0;
+
+	    if (__isSmallInteger(flag)) {
+		flagVal = __intVal(flag);
+	    } else if (flag == @symbol(ABORTRETRYIGNORE)) {
+		flagVal = MB_ABORTRETRYIGNORE;
+	    } else if (flag == @symbol(APPLMODAL)) {
+		flagVal = MB_APPLMODAL;
+	    } else if (flag == @symbol(DEFAULT_DESKTOP_ONLY)) {
+		flagVal = MB_DEFAULT_DESKTOP_ONLY;
+	    } else if (flag == @symbol(DEFBUTTON1)) {
+		flagVal = MB_DEFBUTTON1;
+	    } else if (flag == @symbol(DEFBUTTON2)) {
+		flagVal = MB_DEFBUTTON2;
+	    } else if (flag == @symbol(DEFBUTTON3)) {
+		flagVal = MB_DEFBUTTON3;
+	    } else if (flag == @symbol(ICONASTERISK)) {
+		flagVal = MB_ICONASTERISK;
+	    } else if (flag == @symbol(ICONHAND)) {
+		flagVal = MB_ICONHAND;
+	    } else if (flag == @symbol(ICONINFORMATION)) {
+		flagVal = MB_ICONINFORMATION;
+	    } else if (flag == @symbol(ICONQUESTION)) {
+		flagVal = MB_ICONQUESTION;
+	    } else if (flag == @symbol(ICONSTOP)) {
+		flagVal = MB_ICONSTOP;
+	    } else if (flag == @symbol(OK)) {
+		flagVal = MB_OK;
+	    } else if (flag == @symbol(OKCANCEL)) {
+		flagVal = MB_OKCANCEL;
+	    } else if (flag == @symbol(RETRYCANCEL)) {
+		flagVal = MB_RETRYCANCEL;
+	    } else if (flag == @symbol(SETFOREGROUND)) {
+		flagVal = MB_SETFOREGROUND;
+	    } else if (flag == @symbol(SYSTEMMODAL)) {
+		flagVal = MB_SYSTEMMODAL;
+	    } else if (flag == @symbol(TASKMODAL)) {
+		flagVal = MB_TASKMODAL;
+	    } else if (flag == @symbol(YESNO)) {
+		flagVal = MB_YESNO;
+	    } else if (flag == @symbol(YESNOCANCEL)) {
+		flagVal = MB_YESNOCANCEL;
+	    }
+	    boxFlags |= flagVal;
+	}
+    }
+
+    if (blocking == true) {
+	__answer = MessageBox(hWndOwner, 
+		   __text,
+		   __title,
+		   boxFlags);
+    } else {
+	__answer = __STX_API_CALL4( (void *)MessageBox,
+				    (void *)hWndOwner, 
+				    (void *)__text,
+				    (void *)__title,
+				    (void *)boxFlags);
+    }
+
+    switch (__answer) {
+	case IDABORT:
+	    answer = @symbol(IDABORT);
+	    break;
+	case IDCANCEL:
+	    answer = @symbol(IDCANCEL);
+	    break;
+	case IDIGNORE:
+	    answer = @symbol(IDIGNORE);
+	    break;
+	case IDNO:
+	    answer = @symbol(IDNO);
+	    break;
+	case IDOK:
+	    answer = @symbol(IDOK);
+	    break;
+	case IDRETRY:
+	    answer = @symbol(IDRETRY);
+	    break;
+	case IDYES:
+	    answer = @symbol(IDYES);
+	    break;
+	default:
+	    answer = __MKSMALLINT(__answer);
+	    break;
+    }
+#else
+    errorCode = __MKSMALLINT(-1);
+#endif /* NO_NATIVE_DIALOGS */
+%}.
+    (errorCode notNil) ifTrue:[
+	self primitiveFailed.
+    ].
+
+    ^ answer
+
+    "
+     Display 
+	nativeMessageBoxFor:nil 
+	text:'Hello world' 
+	title:'Message'
+	flags:#( OK APPLMODAL ICONSTOP )
+	blocking:true
+
+     Display 
+	nativeMessageBoxFor:nil 
+	text:'Hello world' 
+	title:'Message'
+	flags:#( OK APPLMODAL ICONSTOP )
+	blocking:false
+
+     Display 
+	nativeMessageBoxFor:nil 
+	text:'Hello world' 
+	title:'Message'
+	flags:#( ABORTRETRYIGNORE ICONSTOP )
+	blocking:false
+    "
 ! !
 
 !WinWorkstation methodsFor:'pointer queries '!
@@ -14220,6 +14620,6 @@
 !WinWorkstation class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/WinWorkstation.st,v 1.211 2001-11-28 15:17:53 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/WinWorkstation.st,v 1.212 2001-12-05 14:56:15 cg Exp $'
 ! !
 WinWorkstation initialize!