The R Project SVN R

Rev

Rev 88361 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 88361 Rev 88464
Line 35... Line 35...
35
   Add waitevent() function
35
   Add waitevent() function
36
   Caret handling improvements (see comments in controls.c)
36
   Caret handling improvements (see comments in controls.c)
37
   Allow to leave a dropfield (combo box) with TAB key
37
   Allow to leave a dropfield (combo box) with TAB key
38
   Allow navigating to previous controls with Shift+TAB key
38
   Allow navigating to previous controls with Shift+TAB key
39
   Path length limitations
39
   Path length limitations
-
 
40
   Propagation of R errors from window procedures
40
 */
41
 */
41
 
42
 
42
#include "internal.h"
43
#include "internal.h"
43
 
44
 
44
/*
45
/*
Line 238... Line 239...
238
 
239
 
239
static int showMDIToolbar = 1;
240
static int showMDIToolbar = 1;
240
void toolbar_show(void)
241
void toolbar_show(void)
241
{
242
{
242
    showMDIToolbar = 1;
243
    showMDIToolbar = 1;
243
    SendMessage(hwndFrame,WM_PAINT, (WPARAM) 0, (LPARAM) 0);
244
    sendmessage(hwndFrame,WM_PAINT, (WPARAM) 0, (LPARAM) 0);
244
}
245
}
245
void toolbar_hide(void)
246
void toolbar_hide(void)
246
{
247
{
247
    showMDIToolbar = 0;
248
    showMDIToolbar = 0;
248
    SendMessage(hwndFrame,WM_PAINT, (WPARAM) 0, (LPARAM) 0);
249
    sendmessage(hwndFrame,WM_PAINT, (WPARAM) 0, (LPARAM) 0);
249
}
250
}
250
 
251
 
251
static void handle_mdiframesize(void)
252
static void handle_mdiframesize(void)
252
{
253
{
253
    HWND tool=NULL ,status=NULL;
254
    HWND tool=NULL ,status=NULL;
Line 272... Line 273...
272
	show(MDIToolbar);
273
	show(MDIToolbar);
273
    }
274
    }
274
    if (status) {
275
    if (status) {
275
	MoveWindow(status,1,fh-sh,fw-2,sh,TRUE);
276
	MoveWindow(status,1,fh-sh,fw-2,sh,TRUE);
276
    }
277
    }
277
    SetFocus((HWND)SendMessage(hwndClient,
278
    SetFocus((HWND)sendmessage(hwndClient,
278
			       WM_MDIGETACTIVE,(WPARAM)0,(LPARAM) 0));
279
			       WM_MDIGETACTIVE,(WPARAM)0,(LPARAM) 0));
279
}
280
}
280
 
281
 
281
/*
282
/*
282
 *  The window is being resized for some reason.
283
 *  The window is being resized for some reason.
Line 841... Line 842...
841
 *  If we were to use only one window procedure, we would have to
842
 *  If we were to use only one window procedure, we would have to
842
 *  have a way of determining which is the default window proc
843
 *  have a way of determining which is the default window proc
843
 *  for a window from just knowing the hwnd (which may or may not
844
 *  for a window from just knowing the hwnd (which may or may not
844
 *  belong to us).
845
 *  belong to us).
845
 */
846
 */
-
 
847
 
-
 
848
/* R modification: propagation of R errors from window procedures.
-
 
849
   R errors are implemented using long jumps, but Windows API and
-
 
850
   specifically window procedures don't work with them (e.g. causing
-
 
851
   a crash). This uses R_UnwindProtect to catch errors still inside
-
 
852
   a window procedure and propagate it via global variables to the
-
 
853
   call sites of Windows API calls that may end up calling a window
-
 
854
   procedure. */
-
 
855
 
-
 
856
#include <setjmp.h>
-
 
857
 
-
 
858
typedef void *SEXP;
-
 
859
typedef bool Rboolean;
-
 
860
 
-
 
861
SEXP R_UnwindProtect(SEXP (*fun)(void *data), void *data,
-
 
862
                     void (*clean)(void *data, Rboolean jump), void *cdata,
-
 
863
                     SEXP cont);
-
 
864
SEXP R_MakeUnwindCont(void);
-
 
865
SEXP Rf_protect(SEXP);
-
 
866
void Rf_unprotect(int);
-
 
867
void R_ContinueUnwind(SEXP cont);
-
 
868
extern LibImport SEXP R_NilValue;
-
 
869
 
-
 
870
static SEXP wndproc_cont_token;
-
 
871
 
-
 
872
static void wndproc_rethrow_error(void)
-
 
873
{
-
 
874
    if (wndproc_cont_token) {
-
 
875
	SEXP token = wndproc_cont_token;
-
 
876
	wndproc_cont_token = NULL;
-
 
877
	R_ContinueUnwind(token);
-
 
878
    }
-
 
879
}
-
 
880
 
-
 
881
typedef struct {
-
 
882
    WNDPROC proc_real;
-
 
883
    HWND hwnd;
-
 
884
    UINT message;
-
 
885
    WPARAM wParam;
-
 
886
    LPARAM lParam;
-
 
887
    LRESULT res;
-
 
888
} wndproc_call;
-
 
889
 
-
 
890
SEXP wndproc_unwind_fun(void *data)
-
 
891
{
-
 
892
    wndproc_call *w = data;
-
 
893
    w->res = w->proc_real(w->hwnd, w->message, w->wParam, w->lParam);
-
 
894
    return NULL;
-
 
895
}
-
 
896
 
-
 
897
void wndproc_unwind_clean(void *data, Rboolean jump)
-
 
898
{
-
 
899
    if (jump) 
-
 
900
	longjmp(*(jmp_buf *)data, 1);
-
 
901
}
-
 
902
 
-
 
903
LRESULT WINAPI wndproc_unwind (WNDPROC proc_real, HWND hwnd, UINT message,
-
 
904
                               WPARAM wParam, LPARAM lParam)
-
 
905
{
-
 
906
    jmp_buf jmpbuf;
-
 
907
    wndproc_call w;
-
 
908
    volatile SEXP token;
-
 
909
 
-
 
910
    if (R_NilValue == NULL) {
-
 
911
	/* when R heap hasn't been initialized yet */
-
 
912
	wndproc_cont_token = NULL;
-
 
913
	return proc_real(hwnd, message, wParam, lParam);
-
 
914
    }
-
 
915
    if (setjmp(jmpbuf) == 1) {
-
 
916
	/* long jump */
-
 
917
	wndproc_cont_token = token;
-
 
918
	return 0;
-
 
919
    }
-
 
920
    w.hwnd = hwnd;
-
 
921
    w.message = message;
-
 
922
    w.wParam = wParam;
-
 
923
    w.lParam = lParam;
-
 
924
    w.proc_real = proc_real;
-
 
925
    SEXP saved_token = wndproc_cont_token;
-
 
926
    token = Rf_protect(R_MakeUnwindCont());
-
 
927
    R_UnwindProtect(wndproc_unwind_fun, &w, wndproc_unwind_clean, jmpbuf, token);
-
 
928
    Rf_unprotect(1);
-
 
929
    wndproc_cont_token = saved_token;
-
 
930
    return w.res;
-
 
931
}
-
 
932
 
-
 
933
/* end of R modification */
-
 
934
 
846
LRESULT WINAPI
935
LRESULT WINAPI
847
app_win_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
936
app_win_proc_real (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
848
{
937
{
849
    long result;
938
    long result;
850
    int pass = 0;
939
    int pass = 0;
851
 
940
 
852
    result = handle_message(hwnd, message, wParam, lParam, &pass);
941
    result = handle_message(hwnd, message, wParam, lParam, &pass);
853
    if (pass)
942
    if (pass) {
854
	result = DefWindowProc(hwnd, message, wParam, lParam);
943
	result = DefWindowProc(hwnd, message, wParam, lParam);
-
 
944
	wndproc_rethrow_error();
-
 
945
    }
855
    return result;
946
    return result;
856
}
947
}
857
 
948
 
-
 
949
/* R modification: propagation of R errors from window procedures. */
-
 
950
 
858
LRESULT WINAPI
951
LRESULT WINAPI
859
app_doc_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
952
app_win_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-
 
953
{
-
 
954
    return wndproc_unwind(app_win_proc_real, hwnd, message, wParam, lParam);
-
 
955
}
-
 
956
 
-
 
957
/* end of R modification */
-
 
958
 
-
 
959
 
-
 
960
LRESULT WINAPI
-
 
961
app_doc_proc_real (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
860
{
962
{
861
    long result;
963
    long result;
862
    int pass = 0;
964
    int pass = 0;
863
    object obj;
965
    object obj;
864
    if ((message==WM_MDIACTIVATE) && ((HWND)lParam==hwnd)) {
966
    if ((message==WM_MDIACTIVATE) && ((HWND)lParam==hwnd)) {
Line 866... Line 968...
866
	obj = find_by_handle(hwnd);
968
	obj = find_by_handle(hwnd);
867
	MDIToolbar = (obj) ? obj->toolbar : NULL;
969
	MDIToolbar = (obj) ? obj->toolbar : NULL;
868
	handle_mdiframesize();
970
	handle_mdiframesize();
869
	if (obj && obj->menubar) {
971
	if (obj && obj->menubar) {
870
	    menu mdi = (obj->menubar)->menubar;
972
	    menu mdi = (obj->menubar)->menubar;
871
	    SendMessage(hwndClient, WM_MDISETMENU,
973
	    sendmessage(hwndClient, WM_MDISETMENU,
872
			(WPARAM)obj->menubar->handle,
974
			(WPARAM)obj->menubar->handle,
873
			(LPARAM)(mdi?(mdi->handle):0));
975
			(LPARAM)(mdi?(mdi->handle):0));
874
	    DrawMenuBar(hwndFrame);
976
	    DrawMenuBar(hwndFrame);
875
	}
977
	}
876
	if (obj) updatestatus(obj->status);
978
	if (obj) updatestatus(obj->status);
Line 878... Line 980...
878
		     RDW_UPDATENOW|RDW_ALLCHILDREN);
980
		     RDW_UPDATENOW|RDW_ALLCHILDREN);
879
	SetFocus(hwnd);
981
	SetFocus(hwnd);
880
	return 1;
982
	return 1;
881
    }
983
    }
882
    result = handle_message(hwnd, message, wParam, lParam, &pass);
984
    result = handle_message(hwnd, message, wParam, lParam, &pass);
883
    if (pass)
985
    if (pass) {
884
	result = DefMDIChildProc(hwnd, message, wParam, lParam);
986
	result = DefMDIChildProc(hwnd, message, wParam, lParam);
-
 
987
	wndproc_rethrow_error();
-
 
988
    }
885
    return result;
989
    return result;
886
}
990
}
887
 
991
 
-
 
992
/* R modification: propagation of R errors from window procedures. */
-
 
993
 
888
LRESULT WINAPI
994
LRESULT WINAPI
889
app_work_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
995
app_doc_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-
 
996
{
-
 
997
    return wndproc_unwind(app_doc_proc_real, hwnd, message, wParam, lParam);
-
 
998
}
-
 
999
 
-
 
1000
/* end of R modification */
-
 
1001
 
-
 
1002
LRESULT WINAPI
-
 
1003
app_work_proc_real (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
890
{
1004
{
891
    long result;
1005
    long result;
892
    int pass = 0;
1006
    int pass = 0;
893
    result = handle_message(hwnd, message, wParam, lParam, &pass);
1007
    result = handle_message(hwnd, message, wParam, lParam, &pass);
894
    if (pass)
1008
    if (pass)
895
	result = DefFrameProc(hwnd, hwndClient, message, wParam, lParam);
1009
	result = DefFrameProc(hwnd, hwndClient, message, wParam, lParam);
896
    return result;
1010
    return result;
897
}
1011
}
898
 
1012
 
-
 
1013
/* R modification: propagation of R errors from window procedures. */
-
 
1014
 
-
 
1015
LRESULT WINAPI
-
 
1016
app_work_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-
 
1017
{
-
 
1018
    return wndproc_unwind(app_work_proc_real, hwnd, message, wParam, lParam);
-
 
1019
}
-
 
1020
 
-
 
1021
/* end of R modification */
-
 
1022
 
-
 
1023
 
899
/*
1024
/*
900
 *  To handle controls correctly, we replace each control's event
1025
 *  To handle controls correctly, we replace each control's event
901
 *  handling procedure with our own when we create it. We handle
1026
 *  handling procedure with our own when we create it. We handle
902
 *  certain events ourselves, and pass the rest to the default
1027
 *  certain events ourselves, and pass the rest to the default
903
 *  routines.
1028
 *  routines.
Line 921... Line 1046...
921
    drawto(obj);
1046
    drawto(obj);
922
    obj->call->keydown(obj, ch);
1047
    obj->call->keydown(obj, ch);
923
    keystate = 0;
1048
    keystate = 0;
924
}
1049
}
925
 
1050
 
926
long WINAPI
1051
LRESULT WINAPI
927
app_control_procedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1052
app_control_procedure_real (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
928
{
1053
{
929
    int prevent_activation = 0;
1054
    int prevent_activation = 0;
930
    int key;
1055
    int key;
931
    long result;
1056
    long result;
932
    object obj, next, prev;
1057
    object obj, next, prev;
Line 1032... Line 1157...
1032
	handle_findreplace(hwnd, (LPFINDREPLACE) lParam);
1157
	handle_findreplace(hwnd, (LPFINDREPLACE) lParam);
1033
	return 0;
1158
	return 0;
1034
    }
1159
    }
1035
 
1160
 
1036
    result = CallWindowProc((obj->winproc), hwnd, message, wParam, lParam);
1161
    result = CallWindowProc((obj->winproc), hwnd, message, wParam, lParam);
-
 
1162
    wndproc_rethrow_error();
1037
 
1163
 
1038
    /* Re-activate the control if necessary. */
1164
    /* Re-activate the control if necessary. */
1039
    if (prevent_activation)
1165
    if (prevent_activation)
1040
	obj->state |= GA_Enabled;
1166
	obj->state |= GA_Enabled;
1041
    return result;
1167
    return result;
1042
}
1168
}
1043
 
1169
 
-
 
1170
/* R modification: propagation of R errors from window procedures. */
-
 
1171
 
1044
long WINAPI
1172
LRESULT WINAPI
1045
edit_control_procedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1173
app_control_procedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-
 
1174
{
-
 
1175
    return wndproc_unwind(app_control_procedure_real, hwnd, message, wParam, lParam);
-
 
1176
}
-
 
1177
 
-
 
1178
/* end of R modification */
-
 
1179
 
-
 
1180
LRESULT WINAPI
-
 
1181
edit_control_procedure_real (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1046
{
1182
{
1047
    int key;
1183
    int key;
1048
    object obj, next, prev;
1184
    object obj, next, prev;
1049
    HANDLE hwndCombo;
1185
    HANDLE hwndCombo;
-
 
1186
    long result;
1050
 
1187
 
1051
    /* Find the library (dropfield/combo box) object associated
1188
    /* Find the library (dropfield/combo box) object associated
1052
       with the hwnd. */
1189
       with the hwnd. */
1053
    hwndCombo = GetParent(hwnd);
1190
    hwndCombo = GetParent(hwnd);
1054
    if (! hwndCombo)
1191
    if (! hwndCombo)
Line 1086... Line 1223...
1086
	if (key == VK_TAB) 
1223
	if (key == VK_TAB) 
1087
	    return 0;
1224
	    return 0;
1088
	break;
1225
	break;
1089
    }
1226
    }
1090
 
1227
 
1091
    return CallWindowProc((obj->edit_winproc), hwnd, message, wParam, lParam);
1228
    result = CallWindowProc((obj->edit_winproc), hwnd, message, wParam, lParam);
-
 
1229
    wndproc_rethrow_error();
-
 
1230
    return result;
-
 
1231
}
-
 
1232
 
-
 
1233
/* R modification: propagation of R errors from window procedures. */
-
 
1234
 
-
 
1235
LRESULT WINAPI
-
 
1236
edit_control_procedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-
 
1237
{
-
 
1238
    return wndproc_unwind(edit_control_procedure_real, hwnd, message, wParam, lParam);
1092
}
1239
}
1093
 
1240
 
-
 
1241
/* end of R modification */
-
 
1242
 
-
 
1243
 
1094
/*
1244
/*
1095
 *  Timer functions use a timer procedure not associated with a window.
1245
 *  Timer functions use a timer procedure not associated with a window.
1096
 *  We use this one procedure to handle both timer events and mouse-down
1246
 *  We use this one procedure to handle both timer events and mouse-down
1097
 *  timer events. The mouse-down timer happens when the user has held
1247
 *  timer events. The mouse-down timer happens when the user has held
1098
 *  a mouse button down for longer than mouse_msec milliseconds, and
1248
 *  a mouse button down for longer than mouse_msec milliseconds, and
Line 1275... Line 1425...
1275
	    return result;
1425
	    return result;
1276
	if ((modeless) && IsDialogMessage(modeless, &msg))
1426
	if ((modeless) && IsDialogMessage(modeless, &msg))
1277
	    return result;
1427
	    return result;
1278
	TranslateMessage(&msg);
1428
	TranslateMessage(&msg);
1279
	DispatchMessage(&msg);
1429
	DispatchMessage(&msg);
-
 
1430
	wndproc_rethrow_error();
1280
    }
1431
    }
1281
    deletion_traversal();
1432
    deletion_traversal();
1282
    if ((active_windows <= 0) || (msg.message == WM_QUIT))
1433
    if ((active_windows <= 0) || (msg.message == WM_QUIT))
1283
	return 0;
1434
	return 0;
1284
    else
1435
    else
Line 1329... Line 1480...
1329
void finish_events(void)
1480
void finish_events(void)
1330
{
1481
{
1331
    settimer(0);
1482
    settimer(0);
1332
    setmousetimer(0);
1483
    setmousetimer(0);
1333
}
1484
}
-
 
1485
 
-
 
1486
/* R modification: propagation of R errors from window procedures. */
-
 
1487
 
-
 
1488
PROTECTED LRESULT
-
 
1489
sendmessage_unwind(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
-
 
1490
{
-
 
1491
    LRESULT result = SendMessage(hWnd, Msg, wParam, lParam);
-
 
1492
    wndproc_rethrow_error();
-
 
1493
    return result;
-
 
1494
}
-
 
1495
 
-
 
1496
/* end of R modification */