2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$XConsortium: WmFeedback.c /main/6 1996/10/23 17:20:55 rswiston $"
36 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
42 #include "WmResNames.h"
44 #define MWM_NEED_TIME16
48 #include <X11/Shell.h>
50 #include <Xm/DialogS.h>
51 #include <Xm/BulletinB.h>
52 #include <Xm/MessageB.h>
54 #define MOVE_OUTLINE_WIDTH 2
55 #define FEEDBACK_BEVEL 2
57 #define DEFAULT_POSITION_STRING "(0000x0000)"
59 #define CB_HIGHLIGHT_THICKNESS 3
62 * include extern functions
64 #include "WmFeedback.h"
65 #include "WmFunction.h"
66 #include "WmGraphics.h"
68 #include "WmPanelP.h" /* for typedef in WmManage.h */
71 #include "WmColormap.h"
78 static Cursor waitCursor = (Cursor)0L;
80 /* see WmGlobal.h for index defines: */
82 #ifndef NO_MESSAGE_CATALOG
83 static char *confirm_mesg[4] = {"Switch to Default Behavior?",
84 "Switch to Custom Behavior?",
96 * catgets returns a pointer to an area that is over written
97 * on each call to catgets.
100 tmpString = ((char *)GETMESSAGE(22, 12, "Switch to Default Behavior?"));
101 if ((confirm_mesg[0] =
102 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
104 Warning (((char *)GETMESSAGE(22, 2, "Insufficient memory for local message string")));
105 confirm_mesg[0] = "Switch to Default Behavior?";
109 strcpy(confirm_mesg[0], tmpString);
112 tmpString = ((char *)GETMESSAGE(22, 13, "Switch to Custom Behavior?"));
113 if ((confirm_mesg[1] =
114 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
116 Warning (((char *)GETMESSAGE(22, 2, "Insufficient memory for local message string")));
117 confirm_mesg[1] = "Switch to Custom Behavior?";
121 strcpy(confirm_mesg[1], tmpString);
126 tmpString = ((char *)GETMESSAGE(22, 3, "Restart Mwm?"));
130 tmpString = ((char *)GETMESSAGE(22, 10, "Restart Workspace Manager?"));
132 if ((confirm_mesg[2] =
133 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
135 Warning (((char *)GETMESSAGE(22, 5, "Insufficient memory for local message string")));
138 confirm_mesg[2] = "Restart Mwm?";
142 confirm_mesg[2] = "Restart Workspace Manager?";
147 strcpy(confirm_mesg[2], tmpString);
154 tmpString = ((char *)GETMESSAGE(22, 6, "QUIT Mwm?"));
161 tmpString = ((char *)GETMESSAGE(22, 9, "Log out?"));
165 tmpString = ((char *)GETMESSAGE(22, 11, "QUIT Workspace Manager?"));
167 #else /* MINIMAL_DT */
168 tmpString = ((char *)GETMESSAGE(22, 11, "QUIT Workspace Manager?"));
169 #endif /* MINIMAL_DT */
172 if ((confirm_mesg[3] =
173 (char *)XtMalloc ((unsigned int) (strlen(tmpString) + 1))) == NULL)
175 Warning (((char *)GETMESSAGE(22, 8, "Insufficient memory for local message string")));
178 confirm_mesg[3] = "QUIT Mwm?";
184 confirm_mesg[3] = "Log out?";
188 confirm_mesg[3] = "QUIT Workspace Manager?";
190 #else /* MINIMAL_DT */
191 tmpString = ((char *)GETMESSAGE(22, 11, "QUIT Workspace Manager?"));
192 #endif /* MINIMAL_DT */
196 strcpy(confirm_mesg[3], tmpString);
202 static char *confirm_mesg[4] = {"Toggle to Default Behavior?",
203 "Toggle to Custom Behavior?",
208 static char *confirm_widget[4] = {"confirmDefaultBehavior",
209 "confirmCustomBehavior",
214 typedef void (*ConfirmFunc)(Boolean);
215 static ConfirmFunc confirm_func[4] = {Do_Set_Behavior,
221 /*************************************<->*************************************
223 * ShowFeedbackWindow(pSD, x, y, width, height, style)
228 * Pop up the window for moving and sizing feedback
233 * pSD - pointer to screen data
234 * x - initial x-value
235 * y - initial y-value
236 * width - initial width value
237 * height - initial height value
238 * style - show size, position, or both
247 *************************************<->***********************************/
248 void ShowFeedbackWindow (WmScreenData *pSD, int x, int y, unsigned int width, unsigned int height, unsigned long style)
250 unsigned long mask = 0;
251 XSetWindowAttributes win_attribs;
252 XWindowChanges win_changes;
253 int direction, ascent, descent;
254 XCharStruct xcsLocation;
258 if ( (pSD->fbStyle = style) == FB_OFF)
263 pSD->fbLastWidth = width;
264 pSD->fbLastHeight = height;
267 * Derive the size and position of the window from the text extents
268 * Set starting position of each string
270 XTextExtents(pSD->feedbackAppearance.font, DEFAULT_POSITION_STRING,
271 strlen(DEFAULT_POSITION_STRING), &direction, &ascent,
272 &descent, &xcsLocation);
274 pSD->fbWinWidth = xcsLocation.width + 4*FEEDBACK_BEVEL;
276 switch (pSD->fbStyle)
279 pSD->fbSizeY = 2*FEEDBACK_BEVEL + ascent;
280 pSD->fbWinHeight = (ascent + descent) + 4*FEEDBACK_BEVEL;
284 pSD->fbLocY = 2*FEEDBACK_BEVEL + ascent;
285 pSD->fbWinHeight = (ascent + descent) + 4*FEEDBACK_BEVEL;
289 case (FB_SIZE | FB_POSITION):
290 pSD->fbLocY = 2*FEEDBACK_BEVEL + ascent;
291 pSD->fbSizeY = pSD->fbLocY + ascent + descent;
292 pSD->fbWinHeight = 2*(ascent + descent) + 4*FEEDBACK_BEVEL;
296 if (pSD->feedbackGeometry) /* set by user */
298 unsigned int junkWidth, junkHeight;
300 mask = XParseGeometry(pSD->feedbackGeometry, &tmpX, &tmpY,
301 &junkWidth, &junkHeight);
304 if (mask & (XValue|YValue))
306 winX = (mask & XNegative) ?
307 DisplayWidth(DISPLAY, pSD->screen) + tmpX - pSD->fbWinWidth : tmpX;
308 winY = (mask & YNegative) ?
309 DisplayHeight(DISPLAY, pSD->screen) + tmpY -pSD->fbWinHeight : tmpY;
313 winX = (DisplayWidth(DISPLAY, pSD->screen) - pSD->fbWinWidth)/2;
314 winY = (DisplayHeight(DISPLAY, pSD->screen) -pSD->fbWinHeight)/2;
318 * Put new text into the feedback strings
320 UpdateFeedbackText (pSD, x, y, width, height);
323 * bevel the window border for a 3-D look
325 if ( (pSD->fbTop && pSD->fbBottom) ||
326 ((pSD->fbTop = AllocateRList((unsigned)2*FEEDBACK_BEVEL)) &&
327 (pSD->fbBottom = AllocateRList((unsigned)2*FEEDBACK_BEVEL))) )
329 pSD->fbTop->used = 0;
330 pSD->fbBottom->used = 0;
331 BevelRectangle (pSD->fbTop,
334 pSD->fbWinWidth, pSD->fbWinHeight,
335 FEEDBACK_BEVEL, FEEDBACK_BEVEL,
336 FEEDBACK_BEVEL, FEEDBACK_BEVEL);
340 * Create window if not yet created, otherwise fix size and position
343 if (!pSD->feedbackWin)
350 mask = CWEventMask | CWOverrideRedirect | CWSaveUnder;
351 win_attribs.event_mask = ExposureMask;
352 win_attribs.override_redirect = TRUE;
353 win_attribs.save_under = TRUE;
356 * Use background pixmap if one is specified, otherwise set the
357 * appropriate background color.
360 if (pSD->feedbackAppearance.backgroundPixmap)
362 mask |= CWBackPixmap;
363 win_attribs.background_pixmap =
364 pSD->feedbackAppearance.backgroundPixmap;
369 win_attribs.background_pixel =
370 pSD->feedbackAppearance.background;
373 pSD->feedbackWin = XCreateWindow (DISPLAY, pSD->rootWindow,
378 InputOutput, CopyFromParent,
383 win_changes.x = winX;
384 win_changes.y = winY;
385 win_changes.width = pSD->fbWinWidth;
386 win_changes.height = pSD->fbWinHeight;
387 win_changes.stack_mode = Above;
389 mask = CWX | CWY | CWWidth | CWHeight | CWStackMode;
391 XConfigureWindow(DISPLAY, pSD->feedbackWin, (unsigned int) mask,
397 * Make the feedback window visible (map it)
400 if (pSD->feedbackWin)
402 /* Make sure the feedback window doesn't get buried */
403 XRaiseWindow(DISPLAY, pSD->feedbackWin);
404 XMapWindow (DISPLAY, pSD->feedbackWin);
405 PaintFeedbackWindow(pSD);
408 } /* END OF FUNCTION ShowFeedbackWindow */
412 /*************************************<->*************************************
414 * PaintFeedbackWindow(pSD)
419 * Repaints the feedback window in response to exposure events
424 * pSD - pointer to screen data
432 *************************************<->***********************************/
433 void PaintFeedbackWindow (WmScreenData *pSD)
435 if (pSD->feedbackWin)
440 if (pSD->fbTop->used > 0)
442 XFillRectangles (DISPLAY, pSD->feedbackWin,
443 pSD->feedbackAppearance.inactiveTopShadowGC,
444 pSD->fbTop->prect, pSD->fbTop->used);
446 if (pSD->fbBottom->used > 0)
448 XFillRectangles (DISPLAY, pSD->feedbackWin,
449 pSD->feedbackAppearance.inactiveBottomShadowGC,
450 pSD->fbBottom->prect,
451 pSD->fbBottom->used);
457 XClearArea (DISPLAY, pSD->feedbackWin,
458 FEEDBACK_BEVEL, FEEDBACK_BEVEL,
459 pSD->fbWinWidth-2*FEEDBACK_BEVEL,
460 pSD->fbWinHeight-2*FEEDBACK_BEVEL,
466 if (pSD->fbStyle & FB_POSITION)
468 WmDrawString (DISPLAY, pSD->feedbackWin,
469 pSD->feedbackAppearance.inactiveGC,
470 pSD->fbLocX, pSD->fbLocY,
471 pSD->fbLocation, strlen(pSD->fbLocation));
473 if (pSD->fbStyle & FB_SIZE)
475 WmDrawString (DISPLAY, pSD->feedbackWin,
476 pSD->feedbackAppearance.inactiveGC,
477 pSD->fbSizeX, pSD->fbSizeY,
478 pSD->fbSize, strlen(pSD->fbSize));
485 /*************************************<->*************************************
487 * HideFeedbackWindow (pSD)
492 * Hide the feedback window
497 * pDS - pointer to screen data
506 *************************************<->***********************************/
507 void HideFeedbackWindow (WmScreenData *pSD)
509 if (pSD->feedbackWin)
511 XUnmapWindow (DISPLAY, pSD->feedbackWin);
513 ForceColormapFocus (ACTIVE_PSD, ACTIVE_PSD->colormapFocus);
516 pSD->fbStyle = FB_OFF;
522 /*************************************<->*************************************
524 * UpdateFeedbackInfo (pSD, x, y, width, height)
529 * Update the information in the feedback window
534 * pSD - pointer to screen info
537 * width - width value
538 * height - height value
548 *************************************<->***********************************/
549 void UpdateFeedbackInfo (WmScreenData *pSD, int x, int y, unsigned int width, unsigned int height)
552 * Currently the feedback window must always be redrawn to (potentially)
553 * repair damage done by moving the configuration outline. The feedback
554 * repainting generally only needs to be done when the information
555 * changes or the feedback window is actually overwritten by the
556 * configuration outline.
560 /* only update if something changed */
561 if (((pSD->fbStyle & FB_POSITION) &&
562 ((pSD->fbLastX != x) || (pSD->fbLastY != y))) ||
563 ((pSD->fbStyle & FB_SIZE) &&
564 ((pSD->fbLastWidth != width) || (pSD->fbLastHeight != height))))
569 pSD->fbLastWidth = width;
570 pSD->fbLastHeight = height;
572 UpdateFeedbackText (pSD, x, y, width, height);
574 PaintFeedbackWindow(pSD);
581 /*************************************<->*************************************
583 * UpdateFeedbackText (pSD, x, y, width, height)
588 * Update the information in the feedback strings
593 * pSD - pointer to screen data
596 * width - width value
597 * height - height value
607 *************************************<->***********************************/
608 void UpdateFeedbackText (WmScreenData *pSD, int x, int y, unsigned int width, unsigned int height)
610 int direction, ascent, descent;
613 if (pSD->fbStyle & FB_POSITION)
615 sprintf (pSD->fbLocation, "(%4d,%-4d)", x, y);
616 XTextExtents(pSD->feedbackAppearance.font, pSD->fbLocation,
617 strlen(pSD->fbLocation), &direction, &ascent,
619 pSD->fbLocX = (pSD->fbWinWidth - xcs.width)/2;
622 if (pSD->fbStyle & FB_SIZE)
624 sprintf (pSD->fbSize, "%4dx%-4d", width, height);
625 XTextExtents(pSD->feedbackAppearance.font, pSD->fbSize,
626 strlen(pSD->fbSize), &direction, &ascent,
628 pSD->fbSizeX = (pSD->fbWinWidth - xcs.width)/2;
634 /*************************************<->*************************************
637 * OkCB (w, client_data, call_data)
642 * QuestionBox Ok callback.
659 *************************************<->***********************************/
661 static void OkCB (w, client_data, call_data)
669 confirm_func[((WmScreenData *)client_data)->actionNbr] (False);
671 wmGD.confirmDialogMapped = False;
673 } /* END OF FUNCTION OkCB */
676 /*************************************<->*************************************
679 * CancelCB (w, client_data, call_data)
684 * QuestionBox Cancel callback.
701 *************************************<->***********************************/
703 static void CancelCB (w, client_data, call_data)
711 wmGD.confirmDialogMapped = False;
713 } /* END OF FUNCTION CancelCB */
717 /*************************************<->*************************************
720 * ConfirmAction (pSD,nbr)
725 * Post a QuestionBox and ask for confirmation. If so, executes the
726 * appropriate action.
731 * nbr = action number
733 * pSD->screenTopLevel
738 * actionNbr = current QuestionBox widget index.
739 * confirmW[actionNbr] = QuestionBox widget.
745 *************************************<->***********************************/
747 void ConfirmAction (WmScreenData *pSD, int nbr)
752 Dimension width, height;
753 Widget dialogShellW = NULL;
754 XmString messageString;
755 static XmString defaultMessageString = NULL;
759 * If there is a system modal window, don't post another
760 * one. We need to think about a way to let a new system
761 * modal window be posted, and when unposted, restore the
762 * modal state of the current system modal window.
765 if(wmGD.systemModalActive)
770 if (pSD->confirmboxW[nbr] == NULL)
771 /* First time for this one */
773 #ifndef NO_MESSAGE_CATALOG
775 * Initialize messages
781 * Create a dialog popup shell with explicit keyboard policy.
785 XtSetArg(args[n], XmNx, (XtArgVal)
786 (DisplayWidth (DISPLAY, pSD->screen)/2)); n++;
787 XtSetArg(args[n], XmNy, (XtArgVal)
788 (DisplayHeight (DISPLAY, pSD->screen)/2)); n++;
789 XtSetArg(args[n], XtNallowShellResize, (XtArgVal) TRUE); n++;
790 XtSetArg(args[n], XtNkeyboardFocusPolicy, (XtArgVal) XmEXPLICIT); n++;
791 XtSetArg(args[n], XtNdepth,
792 (XtArgVal) DefaultDepth(DISPLAY, pSD->screen)); n++;
793 XtSetArg(args[n], XtNscreen,
794 (XtArgVal) ScreenOfDisplay(DISPLAY, pSD->screen)); n++;
797 XtCreatePopupShell ((String) WmNfeedback,
798 transientShellWidgetClass,
799 pSD->screenTopLevelW, args, n);
802 * Create a QuestionBox as a child of the popup shell.
803 * Set traversalOn and add callbacks for the OK and CANCEL buttons.
804 * Unmanage the HELP button.
808 XtSetArg(args[n], XmNdialogType, (XtArgVal) XmDIALOG_QUESTION); n++;
809 XtSetArg(args[n], XmNmessageAlignment, (XtArgVal) XmALIGNMENT_CENTER);
811 XtSetArg(args[n], XmNtraversalOn, (XtArgVal) TRUE); n++;
814 * In 1.2 confirmbox's widget name changed from the generic
815 * WmNconfirmbox (ie. 'confirmbox') to a more descriptive name
816 * so that each confirm dialog can be customized separately (e.g.
817 * "Mwm*confirmRestart*messageString: restart it?").
820 pSD->confirmboxW[nbr] =
821 XtCreateManagedWidget (confirm_widget[nbr], xmMessageBoxWidgetClass,
822 dialogShellW, args, n);
825 XtSetArg(args[n], XmNmessageString, &messageString); n++;
826 XtGetValues(pSD->confirmboxW[nbr], (ArgList) args, n);
828 if (defaultMessageString == NULL)
830 defaultMessageString = XmStringCreateLocalized ("");
836 * If the message string is the default, then put something
837 * 'reasonable' in instead.
840 if (XmStringCompare( messageString, defaultMessageString ))
842 messageString = XmStringCreateLocalized(confirm_mesg[nbr]);
843 XtSetArg(args[n], XmNmessageString, (XtArgVal) messageString); n++;
844 XtSetValues(pSD->confirmboxW[nbr], (ArgList) args, n);
845 XmStringFree(messageString);
849 XtSetArg (args[n], XmNtraversalOn, (XtArgVal) TRUE); n++;
850 XtSetArg (args[n], XmNhighlightThickness,
851 (XtArgVal) CB_HIGHLIGHT_THICKNESS); n++;
852 #ifndef NO_MESSAGE_CATALOG
853 XtSetArg(args[n], XmNlabelString, wmGD.okLabel); n++;
855 XtSetValues ( XmMessageBoxGetChild (pSD->confirmboxW[nbr],
856 XmDIALOG_OK_BUTTON), args, n);
857 #ifndef NO_MESSAGE_CATALOG
859 XtSetArg(args[n], XmNlabelString, wmGD.cancelLabel); n++;
861 XtSetValues ( XmMessageBoxGetChild (pSD->confirmboxW[nbr],
862 XmDIALOG_CANCEL_BUTTON), args, n);
863 XtAddCallback (pSD->confirmboxW[nbr], XmNokCallback,
864 (XtCallbackProc)OkCB, (XtPointer)pSD);
865 XtAddCallback (pSD->confirmboxW[nbr], XmNcancelCallback,
866 (XtCallbackProc)CancelCB, (XtPointer)NULL);
869 (XmMessageBoxGetChild (pSD->confirmboxW[nbr],
870 XmDIALOG_HELP_BUTTON));
872 XtRealizeWidget (dialogShellW);
875 * Center the DialogShell in the display.
879 XtSetArg(args[n], XmNheight, &height); n++;
880 XtSetArg(args[n], XmNwidth, &width); n++;
881 XtGetValues (dialogShellW, (ArgList) args, n);
883 x = (DisplayWidth (DISPLAY, pSD->screen) - ((int) width))/2;
884 y = (DisplayHeight (DISPLAY, pSD->screen) - ((int) height))/2;
886 XtSetArg(args[n], XmNx, (XtArgVal) x); n++;
887 XtSetArg(args[n], XmNy, (XtArgVal) y); n++;
888 XtSetValues (dialogShellW, (ArgList) args, n);
890 ManageWindow (pSD, XtWindow(dialogShellW), MANAGEW_CONFIRM_BOX);
894 ReManageDialog (pSD, pSD->confirmboxW[nbr]);
897 pSD->actionNbr = nbr;
901 wmGD.confirmDialogMapped = True;
903 } /* END OF FUNCTION ConfirmAction */
907 /*************************************<->*************************************
909 * ShowWaitState (flag)
914 * Enter/Leave the wait state.
919 * flag = TRUE for Enter, FALSE for Leave.
931 *************************************<->***********************************/
933 void ShowWaitState (Boolean flag)
939 unsigned int xHotspot;
940 unsigned int yHotspot;
948 if (wmGD.useLargeCursors)
950 width = time32_width;
951 height = time32_height;
952 bits = (char *)time32_bits;
953 maskBits = (char *)time32m_bits;
954 xHotspot = time32_x_hot;
955 yHotspot = time32_y_hot;
958 #endif /* LARGECURSORS */
961 width = time16_width;
962 height = time16_height;
963 bits = (char *)time16_bits;
964 maskBits = (char *)time16m_bits;
965 xHotspot = time16_x_hot;
966 yHotspot = time16_y_hot;
969 pixmap = XCreateBitmapFromData (DISPLAY,
970 DefaultRootWindow(DISPLAY), bits,
973 maskPixmap = XCreateBitmapFromData (DISPLAY,
974 DefaultRootWindow(DISPLAY), maskBits,
976 #ifdef INTEGRATION_TESTING_
977 xcolors[1].pixel = BlackPixelOfScreen(DefaultScreenOfDisplay(DISPLAY));
978 xcolors[0].pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(DISPLAY));
979 #else /* INTEGRATION_TESTING */
981 xcolors[0].pixel = BlackPixelOfScreen(DefaultScreenOfDisplay(DISPLAY));
982 xcolors[1].pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(DISPLAY));
984 #endif /* INTEGRATION_TESTING */
985 XQueryColors (DISPLAY,
986 DefaultColormapOfScreen(DefaultScreenOfDisplay
989 waitCursor = XCreatePixmapCursor (DISPLAY, pixmap, maskPixmap,
990 &(xcolors[0]), &(xcolors[1]),
992 XFreePixmap (DISPLAY, pixmap);
993 XFreePixmap (DISPLAY, maskPixmap);
998 XGrabPointer (DISPLAY, DefaultRootWindow(DISPLAY), FALSE,
999 0, GrabModeAsync, GrabModeAsync, None,
1000 waitCursor, CurrentTime);
1001 XGrabKeyboard (DISPLAY, DefaultRootWindow(DISPLAY), FALSE,
1002 GrabModeAsync, GrabModeAsync, CurrentTime);
1006 XUngrabPointer (DISPLAY, CurrentTime);
1007 XUngrabKeyboard (DISPLAY, CurrentTime);
1010 } /* END OF FUNCTION ShowWaitState */
1014 /*************************************<->*************************************
1021 * This function determines whether a server supports large cursors. It it
1022 * does large feedback cursors are used in some cases (wait state and
1023 * system modal state); otherwise smaller (16x16) standard cursors are used.
1027 * wmGD.useLargeCusors = set to True if larger cursors are supported.
1029 *************************************<->***********************************/
1031 void InitCursorInfo (void)
1033 unsigned int cWidth;
1034 unsigned int cHeight;
1036 wmGD.useLargeCursors = False;
1038 if (XQueryBestCursor (DISPLAY, DefaultRootWindow(DISPLAY),
1039 32, 32, &cWidth, &cHeight))
1041 if ((cWidth >= 32) && (cHeight >= 32))
1043 wmGD.useLargeCursors = True;
1047 } /* END OF FUNCTION InitCursorInfo */