Beispiel #1
0
RexxMethod2(logical_t, dlgctrl_hasKeyPressConnection, OPTIONAL_CSTRING, methodName, CSELF, pCSelf)
{
    if ( ComCtl32Version <  COMCTL32_6_0 )
    {
        return FALSE;
    }

    pCDialogControl pcdc = (pCDialogControl)pCSelf;

    SUBCLASSDATA *pData = NULL;
    if ( ! GetWindowSubclass(pcdc->hCtrl, KeyPressSubclassProc, pcdc->id, (DWORD_PTR *)&pData) )
    {
        return FALSE;
    }
    if ( pData == NULL )
    {
        return FALSE;
    }
    if ( argumentOmitted(1) )
    {
        return TRUE;
    }

    char *tmpName = strdupupr(methodName);
    if ( tmpName == NULL )
    {
        outOfMemoryException(context->threadContext);
        return FALSE;
    }

    BOOL exists = (seekKeyPressMethod((KEYPRESSDATA *)pData->pData, tmpName) > 0);
    free(tmpName);
    return exists;
}
Beispiel #2
0
RexxMethod2(int32_t, dlgctrl_connectFKeyPress, CSTRING, methodName, CSELF, pCSelf)
{
    keyPressErr_t result = connectKeyPressSubclass(context, methodName, "FKEYS", NULL, (pCDialogControl)pCSelf);
    if ( result == memoryErr )
    {
        outOfMemoryException(context->threadContext);
    }
    return -(int32_t)result;
}
Beispiel #3
0
/**
 * Creates the Rexx dialog control object that represents the underlying Windows
 * dialog control.
 *
 * The control object can, almost, be created entirely from within the C / C++
 * environment.  A method context and the Rexx parent dialog are needed.
 *
 * @param c
 * @param hControl
 * @param hDlg
 * @param id
 * @param controlType
 * @param self
 * @param isCategoryDlg
 * @param putInBag
 *
 * @return RexxObjectPtr
 */
RexxObjectPtr createRexxControl(RexxMethodContext *c, HWND hControl, HWND hDlg, uint32_t id, oodControl_t controlType,
                                RexxObjectPtr self, bool isCategoryDlg, bool putInBag)
{
    RexxObjectPtr result = TheNilObj;

    // Check if the Rexx control object has already been instantiated.
    RexxObjectPtr rxControl = (RexxObjectPtr)getWindowPtr(hControl, GWLP_USERDATA);
    if ( rxControl != NULLOBJECT )
    {
        // Okay, this specific control has already had a control object
        // instantiated to represent it.  We return this object.
        result = rxControl;
        goto out;
    }

    // No pointer is stored in the user data area, so no control object has been
    // instantiated for this specific control, yet.  We instantiate one now and
    // then store the object in the user data area of the control window.

    PNEWCONTROLPARAMS pArgs = (PNEWCONTROLPARAMS)malloc(sizeof(NEWCONTROLPARAMS));
    if ( pArgs == NULL )
    {
        outOfMemoryException(c->threadContext);
        goto out;
    }

    RexxClassObject controlCls = oodClass4controlType(c, controlType);
    if ( controlCls == NULLOBJECT )
    {
        goto out;
    }

    pArgs->isCatDlg = isCategoryDlg;
    pArgs->controlType = controlType;
    pArgs->hwnd = hControl;
    pArgs->hwndDlg = hDlg;
    pArgs->id = id;
    pArgs->parentDlg = self;

    rxControl = c->SendMessage1(controlCls, "NEW", c->NewPointer(pArgs));
    free(pArgs);

    if ( rxControl != NULLOBJECT && rxControl != TheNilObj )
    {
        result = rxControl;
        setWindowPtr(hControl, GWLP_USERDATA, (LONG_PTR)result);

        if ( putInBag )
        {
            c->SendMessage1(self, "PUTCONTROL", result);
        }
    }

out:
    return result;
}
Beispiel #4
0
RexxMethod4(int32_t, dlgctrl_connectKeyPress, CSTRING, methodName, CSTRING, keys, OPTIONAL_CSTRING, filter,
            CSELF, pCSelf)
{
    keyPressErr_t result = connectKeyPressSubclass(context, methodName, keys, filter, (pCDialogControl)pCSelf);
    if ( result == memoryErr )
    {
        outOfMemoryException(context->threadContext);
    }
    return -(int32_t)result;
}
Beispiel #5
0
/** MessageDialog()
 *
 *
 *  @param  text
 *  @param  hwnd  Handle of owner window.  If the user specifies 0 we do not use
 *                an owner window.  If the user omits hwnd, then we try the to
 *                find and use the topmost dialog.
 *
 *
 *  @note  Sets the .SystemErrorCode.
 *
 */
RexxRoutine6(int, messageDialog_rtn, CSTRING, text, OPTIONAL_CSTRING, hwnd, OPTIONAL_CSTRING, _title,
             OPTIONAL_CSTRING, button, OPTIONAL_CSTRING, icon, OPTIONAL_CSTRING, miscStyles)
{
    oodResetSysErrCode(context->threadContext);

    int result = -1;

    char *uprButton = NULL;
    char *uprIcon = NULL;
    char *uprMiscStyles = NULL;

    HWND hwndOwner = (HWND)string2pointer(hwnd);
    if ( hwndOwner == NULL )
    {
        if ( argumentOmitted(2) && TopDlg != NULL && TopDlg->onTheTop )
        {
            hwndOwner = TopDlg->hDlg;
        }
    }

    CSTRING title = "ooDialog Application Message";
    if ( argumentExists(3) )
    {
        title = _title;
    }

    // Defaults.  These values are all 0.
    uint32_t flags = MB_OK | MB_DEFBUTTON1 | MB_APPLMODAL;

    uint32_t flag;
    if ( argumentExists(4) )
    {
        uprButton = strdupupr(button);
        if ( uprButton == NULL )
        {
            outOfMemoryException(context->threadContext);
            goto done_out;
        }

        flag = winKeyword2ID(uprButton, context->threadContext, 4, "MessageDialog button keyword");
        if ( flag == (int)-1 )
        {
            goto done_out;
        }
        flags |= flag;
    }

    // There is no default for the icon, if omitted there is no icon.
    if ( argumentExists(5) )
    {
        uprIcon = strdupupr(icon);
        if ( uprIcon == NULL )
        {
            outOfMemoryException(context->threadContext);
            goto done_out;
        }

        flag = winKeyword2ID(uprIcon, context->threadContext, 5, "MessageDialog icon keyword");
        if ( flag == (int)-1 )
        {
            goto done_out;
        }
        flags |= flag;
    }

    if ( argumentExists(6) )
    {
        uprMiscStyles = strdupupr(miscStyles);
        if ( uprMiscStyles == NULL )
        {
            outOfMemoryException(context->threadContext);
            goto done_out;
        }

        flag = getMiscMBStyle(uprMiscStyles, context, 6, "MessageDialog style keyword");
        if ( flag == (int)-1 )
        {
            goto done_out;
        }
        flags |= flag;
    }

    result = MessageBox(hwndOwner, text, title, flags);
    if ( result == 0 )
    {
        oodSetSysErrCode(context->threadContext);
    }

done_out:
    safeFree(uprButton);
    safeFree(uprIcon);
    safeFree(uprMiscStyles);

    return result;
}
Beispiel #6
0
/** fileNameDialog()
 *
 *  Displays either the Open File or Save File dialog to the user and returns
 *  their selection to the Rexx programmer.
 *
 *  This serves as the implementation for both the fileNameDialog() and the
 *  getFileNameWindow() public routines.  getFileNameWindow() was documented
 *  prior to 4.0.0 and therefore must be retained for backward compatibility.
 *
 *  All arguments are optional.
 *
 *  @param preselected
 *  @param _hwndOwner
 *  @param fileFilter
 *  @param loadOrSave
 *  @param _title
 *  @param _defExt
 *  @param multi
 *  @param _sep
 *
 *  @return  The selected file name(s) on success, 0 if the user cancelled or on
 *           error.
 *
 *  @remarks  For the Default file extension.  Previous to 4.2.0, .txt was
 *            always used unless  the user specified something else.  There is
 *            no way for the Rexx programmer to specify no extension.  Now, if
 *            the argument is used, but the empty string the programmer can
 *            specify no extension.
 */
RexxRoutine8(RexxObjectPtr, fileNameDlg_rtn,
            OPTIONAL_CSTRING, preselected, OPTIONAL_CSTRING, _hwndOwner, OPTIONAL_RexxStringObject, fileFilter,
            OPTIONAL_CSTRING, loadOrSave,  OPTIONAL_CSTRING, _title,     OPTIONAL_CSTRING, _defExt,
            OPTIONAL_CSTRING, multi,       OPTIONAL_CSTRING, _sep)
{
    // The bulk of the work here is setting up the open file name struct based
    // on the arguements passed by the user.

    OPENFILENAME OpenFileName = {0};
    OpenFileName.lStructSize  = sizeof(OPENFILENAME);
    OpenFileName.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLEHOOK |
                         OFN_EXPLORER | OFN_ENABLESIZING;

    // Allocate a large buffer for the returned file name(s).
    char * pszFiles = (char *)LocalAlloc(GPTR, FILENAME_BUFFER_LEN);
    if ( pszFiles == NULL )
    {
        outOfMemoryException(context->threadContext);
        return NULLOBJECT;
    }
    OpenFileName.lpstrFile = pszFiles;
    OpenFileName.nMaxFile = FILENAME_BUFFER_LEN;

    // Preselected file name and / or the directory to start in.
    if ( argumentExists(1) && *preselected != '\0' )
    {
        if ( preselected[strlen(preselected) - 1] == '\\' )
        {
            OpenFileName.lpstrInitialDir = preselected;
        }
        else
        {
          StrNCpy(pszFiles, preselected, _MAX_PATH);
        }
    }

    // Possible owner window.
    if ( argumentExists(2) && *_hwndOwner != '\0' )
    {
        OpenFileName.hwndOwner = (HWND)string2pointer(_hwndOwner);
    }

    // File filter string.  Note that the string needs to end with a double
    // null, which has never been documented well to the Rexx user.  This makes
    // it a little tricky if the user sends a string.  There is little chance
    // the user added the extra null.  The need for embedded nulls to separate
    // strings has been documented, so we can expect embedded nulls in the
    // string.  Therefore we have to get the real length of the string data.

    char *filterBuf = NULL;
    OpenFileName.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
    OpenFileName.nFilterIndex = 1L;

    if ( argumentExists(3) )
    {
        size_t len = context->StringLength(fileFilter);
        if ( len > 0 )
        {
            filterBuf = (char *)LocalAlloc(GMEM_FIXED, len + 2);
            if ( filterBuf == NULL )
            {
                outOfMemoryException(context->threadContext);
                LocalFree(pszFiles);
                return NULLOBJECT;
            }

            memcpy(filterBuf, context->StringData(fileFilter), len);
            filterBuf[len] = '\0';
            filterBuf[len + 1] = '\0';

            OpenFileName.lpstrFilter = filterBuf;
        }
        else
        {
            OpenFileName.lpstrFilter = NULL;
            OpenFileName.nFilterIndex = 0;
        }
    }

    // Open or save file dialog.  Allow mutiple file selection on open, or not.
    bool open = true;
    bool multiSelect = false;
    if ( argumentExists(4) && *loadOrSave != '\0' )
    {
        char f = toupper(*loadOrSave);
        if ( f == 'S' || f == '0' )
        {
            open = false;
        }
    }
    if ( open && argumentExists(7) && *multi != '\0' )
    {
        char f = toupper(*multi);
        if ( f == 'M' || f == '1' )
        {
            multiSelect = true;
        }
    }

    // Dialog title.
    if ( argumentExists(5) && *_title != '\0' )
    {
        OpenFileName.lpstrTitle = _title;
    }
    else
    {
        OpenFileName.lpstrTitle = (open ? "Open a File" : "Save File As");
    }

    // Default file extension.
    if ( argumentExists(6) )
    {
        OpenFileName.lpstrDefExt = *_defExt != '\0' ? _defExt : NULL;
    }
    else
    {
        OpenFileName.lpstrDefExt = "txt";
    }

    // Hook procedure to bring dialog to the foreground.
    OpenFileName.lpfnHook = OFNSetForegroundHookProc;

    // Default separator character, can be changed by the user to handle file
    // names with spaces.
    char sepChar = ' ';
    if ( argumentExists(8) && *_sep != '\0' )
    {
        sepChar = *_sep;
    }

    // Okay, show the dialog.
    BOOL success;
    if ( open )
    {
        OpenFileName.Flags |= OFN_FILEMUSTEXIST;
        if ( multiSelect )
        {
            OpenFileName.Flags |= OFN_ALLOWMULTISELECT;
        }

        success = GetOpenFileName(&OpenFileName);

        if ( success && multiSelect )
        {
            // If more than one name selected, names are separated with ASCII 0
            // instead of spaces.
            char *p = pszFiles;

            while ( (*p != '\0') || (*(p+1) != '\0') )
            {
                if ( *p == 0 )
                {
                    *p = sepChar;
                }
                p++;
            }
        }
    }
    else
    {
        OpenFileName.Flags |= OFN_OVERWRITEPROMPT;
        success = GetSaveFileName(&OpenFileName);
    }

    // Return 0 if the user cancelled, or on error.  Otherwise, the return is in
    // the allocated file buffer.
    RexxObjectPtr result = TheZeroObj;
    if ( success )
    {
        result = context->String(pszFiles);
    }

    LocalFree(pszFiles);
    safeLocalFree(filterBuf);

    if ( ! success )
    {
        // Raise an exception if this was a Windows API failure.  Prior to
        // 4.0.0, this was a generic 'routine failed' exception.  We'll try to
        // give the user a little more information.
        DWORD rc = CommDlgExtendedError();
        if ( rc != 0 )
        {
            systemServiceExceptionCode(context->threadContext, API_FAILED_MSG,
                                       open ? "GetOpenFileName" : "GetSaveFileName", rc);
        }
    }

    return result;
}
Beispiel #7
0
static char *searchSoundPath(CSTRING file, RexxCallContext *c)
{
    oodResetSysErrCode(c->threadContext);

    // We need a buffer for the path to search, a buffer for the returned full
    // file name, (if found,) and a pointer to char (an unused arg to
    // SearchPath().)
    char *fullFileName = NULL;
    char *pFileName;

    // Calculate how much room we need for the search path buffer.
    uint32_t cchCWD = GetCurrentDirectory(0, NULL);

    // Many modern systems no longer have the SOUNDPATH set.
    SetLastError(0);
    uint32_t cchSoundPath = GetEnvironmentVariable("SOUNDPATH", NULL, 0);
    uint32_t rc = GetLastError();
    if ( cchSoundPath == 0 && rc != ERROR_ENVVAR_NOT_FOUND )
    {
        oodSetSysErrCode(c->threadContext, rc);
        return NULL;
    }

    // Allocate our needed buffers.
    AutoFree buf = (char *)malloc(cchCWD + cchSoundPath + 3);
    fullFileName = (char *)malloc(_MAX_PATH);
    if (buf == NULL || fullFileName == NULL)
    {
        safeFree(fullFileName);
        outOfMemoryException(c->threadContext);
    }

    // Now get the current directory and the sound path.
    cchCWD = GetCurrentDirectory(cchCWD + 1, buf);
    if (cchCWD == 0)
    {
        safeFree(fullFileName);
        oodSetSysErrCode(c->threadContext);
        return NULL;
    }

    if (cchSoundPath != 0)
    {
        buf[cchCWD++] = ';';
        cchSoundPath = GetEnvironmentVariable("SOUNDPATH", buf + cchCWD, cchSoundPath + 1);
        if (cchSoundPath == 0)
        {
            safeFree(fullFileName);
            oodSetSysErrCode(c->threadContext);
            return NULL;
        }
    }

    AutoErrorMode errorMode(SEM_FAILCRITICALERRORS);
    cchSoundPath = SearchPath(buf, file, NULL, _MAX_PATH, fullFileName, &pFileName);

    if (cchSoundPath == 0 || cchSoundPath >= _MAX_PATH)
    {
        safeFree(fullFileName);
        oodSetSysErrCode(c->threadContext);
        return NULL;
    }

    return fullFileName;
}
Beispiel #8
0
/** DialogControl::connectKeyEvent()
 *
 *  Experimental!  Connects a key event to a method in the Rexx dialog.
 *
 *
 *  @return True for success, false for error
 *
 *
 */
RexxMethod2(RexxObjectPtr, dlgctrl_connectKeyEvent, CSTRING, methodName, CSELF, pCSelf)
{
    oodResetSysErrCode(context->threadContext);

    RexxObjectPtr result = TheFalseObj;
    if ( ! requiredComCtl32Version(context, "connectKeyEvent", COMCTL32_6_0) )
    {
        goto done_out;
    }
    if ( *methodName == '\0' )
    {
        context->RaiseException1(Rexx_Error_Invalid_argument_null, TheOneObj);
        goto done_out;
    }

    pCDialogControl pcdc = (pCDialogControl)pCSelf;

    SUBCLASSDATA *pData = NULL;
    BOOL success = GetWindowSubclass(pcdc->hCtrl, KeyEventProc, pcdc->id, (DWORD_PTR *)&pData);

    // Nothing fancy yet, we could allow removing the subclass.

    if ( pData != NULL )
    {
        // The subclass is already installed, we call this an error.
        oodSetSysErrCode(context->threadContext, ERROR_NOT_SUPPORTED);
        goto done_out;
    }

    pData = (SUBCLASSDATA *)LocalAlloc(LPTR, sizeof(SUBCLASSDATA));
    if ( pData == NULL )
    {
        outOfMemoryException(context->threadContext);
        goto done_out;
    }

    KEYEVENTDATA *pKeyEventData = (KEYEVENTDATA *)LocalAlloc(LPTR, sizeof(KEYEVENTDATA));
    if ( pKeyEventData == NULL )
    {
        LocalFree(pData);
        outOfMemoryException(context->threadContext);
        goto done_out;
    }

    pKeyEventData->method = (char *)malloc(strlen(methodName) + 1);
    if ( pKeyEventData->method == NULL )
    {
        freeKeyEventData(pData);
        outOfMemoryException(context->threadContext);
        goto done_out;
    }
    strcpy(pKeyEventData->method, methodName);

    pData->hCtrl = pcdc->hCtrl;
    pData->uID = pcdc->id;
    pData->pData = pKeyEventData;

    if ( SendMessage(pcdc->hDlg, WM_USER_SUBCLASS, (WPARAM)KeyEventProc, (LPARAM)pData) == 0 )
    {
        // The subclass was not installed, free memeory, set error code.
        freeKeyEventData(pData);
        oodSetSysErrCode(context->threadContext, ERROR_SIGNAL_REFUSED);
        goto done_out;
    }

    result = TheTrueObj;

done_out:
    return result;
}