ui_carbon.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 02 Feb 2006 07:07:03 +0000
changeset 104 339482f858af
parent 99 7163ff6f2789
child 108 0b8bcaef83e7
permissions -rw-r--r--
Argh, really fix byte order serialization.
icculus@81
     1
icculus@81
     2
#if !PLATFORM_MACOSX
icculus@81
     3
int ui_init_carbon(void) { return(0); } /* not implemented if not MacOS. */
icculus@81
     4
#else
icculus@81
     5
icculus@0
     6
#include <Carbon/Carbon.h>
icculus@0
     7
icculus@0
     8
#include "platform.h"
icculus@0
     9
#include "ui.h"
icculus@0
    10
icculus@0
    11
#define MOJOPATCH_SIG         'mjpt'
icculus@0
    12
#define MOJOPATCH_STATUS_ID   0
icculus@0
    13
#define MOJOPATCH_PROGRESS_ID 1
icculus@0
    14
icculus@68
    15
static WindowRef window;
icculus@0
    16
static ControlRef progress;
icculus@0
    17
static ControlRef status;
icculus@0
    18
icculus@81
    19
static void ui_pump_carbon(void)
icculus@0
    20
{
icculus@0
    21
    EventRef theEvent;
icculus@11
    22
    EventTargetRef theTarget;
icculus@11
    23
icculus@11
    24
    theTarget = GetEventDispatcherTarget();
icculus@0
    25
    if (ReceiveNextEvent(0, NULL, 0, true, &theEvent) == noErr)
icculus@0
    26
    {
icculus@0
    27
        SendEventToEventTarget(theEvent, theTarget);
icculus@0
    28
        ReleaseEvent(theEvent);
icculus@0
    29
    } /* if */
icculus@81
    30
} /* ui_pump_carbon */
icculus@0
    31
icculus@0
    32
icculus@81
    33
static void ui_title_carbon(const char *str)
icculus@81
    34
{
icculus@99
    35
    CFStringRef cfstr = CFStringCreateWithBytes(NULL,
icculus@99
    36
                                                (const unsigned char *) str,
icculus@99
    37
                                                strlen(str),
icculus@81
    38
                                                kCFStringEncodingISOLatin1, 0);
icculus@81
    39
    SetWindowTitleWithCFString(window, cfstr);
icculus@81
    40
    CFRelease(cfstr);
icculus@81
    41
    ui_pump_carbon();
icculus@81
    42
} /* ui_title_carbon */
icculus@81
    43
icculus@81
    44
icculus@81
    45
static void ui_real_deinit_carbon(void)
icculus@0
    46
{
icculus@45
    47
    /* !!! FIXME */
icculus@81
    48
} /* ui_real_deinit_carbon */
icculus@81
    49
icculus@81
    50
icculus@81
    51
static void ui_add_to_log_carbon(const char *str, int debugging)
icculus@81
    52
{
icculus@81
    53
    /*
icculus@81
    54
     * stdout in a Mac GUI app shows up in the system console, which can be
icculus@81
    55
     *  viewed via /Applications/Utilities/Console.app ...
icculus@81
    56
     */
icculus@81
    57
icculus@81
    58
    /* !!! FIXME */
icculus@0
    59
    printf("MojoPatch%s: %s\n", debugging ? " [debug]" : "", str);
icculus@81
    60
} /* ui_add_to_log_carbon */
icculus@0
    61
icculus@0
    62
icculus@8
    63
static int do_msgbox(const char *str, AlertType alert_type,
icculus@8
    64
                     AlertStdCFStringAlertParamRec *param,
icculus@8
    65
                     DialogItemIndex *idx)
icculus@0
    66
{
icculus@0
    67
    const char *_title = "MojoPatch";
icculus@8
    68
    int retval = 0;
icculus@8
    69
    DialogItemIndex val = 0;
icculus@99
    70
    CFStringRef title = CFStringCreateWithBytes(NULL,
icculus@99
    71
                                                (const unsigned char *) _title,
icculus@99
    72
                                                strlen(_title),
icculus@0
    73
                                                kCFStringEncodingISOLatin1, 0);
icculus@99
    74
    CFStringRef msg = CFStringCreateWithBytes(NULL,
icculus@99
    75
                                              (const unsigned char *) str,
icculus@99
    76
                                              strlen(str),
icculus@99
    77
                                              kCFStringEncodingISOLatin1, 0);
icculus@0
    78
    if ((msg != NULL) && (title != NULL))
icculus@0
    79
    {
icculus@0
    80
        DialogRef dlg = NULL;
icculus@0
    81
icculus@8
    82
        if (CreateStandardAlert(alert_type, title, msg, param, &dlg) == noErr)
icculus@8
    83
        {
icculus@8
    84
            RunStandardAlert(dlg, NULL, (idx) ? idx : &val);
icculus@8
    85
            retval = 1;
icculus@8
    86
        } /* if */
icculus@0
    87
    } /* if */
icculus@0
    88
icculus@0
    89
    if (msg != NULL)
icculus@0
    90
        CFRelease(msg);
icculus@0
    91
icculus@0
    92
    if (title != NULL)
icculus@0
    93
        CFRelease(title);
icculus@8
    94
icculus@8
    95
    return(retval);
icculus@0
    96
} /* do_msgbox */
icculus@0
    97
icculus@0
    98
icculus@8
    99
static int ui_prompt_yes_or_no(const char *question, int yes)
icculus@8
   100
{
icculus@8
   101
    OSStatus err;
icculus@8
   102
    DialogItemIndex item;
icculus@8
   103
    AlertStdCFStringAlertParamRec params;
icculus@8
   104
    err = GetStandardAlertDefaultParams(&params, kStdCFStringAlertVersionOne);
icculus@8
   105
    if (err != noErr)
icculus@8
   106
        return(0);
icculus@8
   107
icculus@8
   108
    params.movable = TRUE;
icculus@8
   109
    params.helpButton = FALSE;
icculus@8
   110
    params.defaultText = CFSTR("Yes");
icculus@8
   111
    params.cancelText = CFSTR("No");
icculus@8
   112
    params.defaultButton = (yes) ? kAlertStdAlertOKButton :
icculus@8
   113
                                   kAlertStdAlertCancelButton;
icculus@8
   114
    params.cancelButton = kAlertStdAlertCancelButton;
icculus@8
   115
    if (!do_msgbox(question, kAlertCautionAlert, &params, &item))
icculus@8
   116
        return(0); /* oh well. */
icculus@8
   117
icculus@8
   118
    return(item == kAlertStdAlertOKButton);
icculus@8
   119
} /* ui_prompt_yes_or_no */
icculus@8
   120
icculus@81
   121
icculus@81
   122
static int ui_prompt_yn_carbon(const char *question)
icculus@8
   123
{
icculus@8
   124
    return(ui_prompt_yes_or_no(question, 1));
icculus@81
   125
} /* ui_prompt_yn_carbon */
icculus@8
   126
icculus@81
   127
icculus@81
   128
static int ui_prompt_ny_carbon(const char *question)
icculus@8
   129
{
icculus@8
   130
    return(ui_prompt_yes_or_no(question, 1));  /* !!! FIXME! should be zero. */
icculus@81
   131
} /* ui_prompt_ny_carbon */
icculus@8
   132
icculus@8
   133
icculus@81
   134
static int ui_file_picker_carbon(char *buf, size_t bufsize)
icculus@8
   135
{
icculus@8
   136
    NavDialogCreationOptions dlgopt;
icculus@8
   137
    NavDialogRef dlg;
icculus@8
   138
    NavReplyRecord reply;
icculus@8
   139
    NavUserAction action;
icculus@8
   140
    AEKeyword keyword;
icculus@8
   141
    AEDesc desc;
icculus@8
   142
    FSRef fsref;
icculus@8
   143
    OSStatus rc;
icculus@8
   144
    int retval = 0;
icculus@8
   145
icculus@8
   146
    NavGetDefaultDialogCreationOptions(&dlgopt);
icculus@8
   147
    dlgopt.optionFlags |= kNavSupportPackages;
icculus@8
   148
    dlgopt.optionFlags |= kNavAllowOpenPackages;
icculus@8
   149
    dlgopt.optionFlags &= ~kNavAllowMultipleFiles;
icculus@81
   150
    dlgopt.windowTitle = CFSTR("Please select the product's icon and click 'OK'.");  /* !!! FIXME! */
icculus@8
   151
    dlgopt.actionButtonLabel = CFSTR("OK");
icculus@8
   152
    NavCreateChooseFolderDialog(&dlgopt, NULL, NULL, NULL, &dlg);
icculus@8
   153
    NavDialogRun(dlg);
icculus@8
   154
    action = NavDialogGetUserAction(dlg);
icculus@8
   155
    if (action == kNavUserActionCancel)
icculus@8
   156
        _log("User cancelled file selector!");
icculus@8
   157
    else
icculus@8
   158
    {
icculus@8
   159
        NavDialogGetReply(dlg, &reply);
icculus@8
   160
        rc = AEGetNthDesc(&reply.selection, 1, typeFSRef, &keyword, &desc);
icculus@8
   161
        if (rc != noErr)
icculus@81
   162
            _fatal("Unexpected error in AEGetNthDesc: %d", (int) rc);
icculus@8
   163
        else
icculus@8
   164
        {
icculus@8
   165
            /* !!! FIXME: Check return values here! */
icculus@8
   166
            BlockMoveData(*desc.dataHandle, &fsref, sizeof (fsref));
icculus@99
   167
            FSRefMakePath(&fsref, (unsigned char *) buf, bufsize - 1);
icculus@8
   168
            buf[bufsize - 1] = '\0';
icculus@8
   169
            AEDisposeDesc(&desc);
icculus@8
   170
            retval = 1;
icculus@8
   171
        } /* if */
icculus@8
   172
icculus@8
   173
        NavDisposeReply(&reply);
icculus@8
   174
    } /* else */
icculus@8
   175
icculus@8
   176
    NavDialogDispose(dlg);
icculus@8
   177
icculus@8
   178
    _log("File selector complete. User %s path.",
icculus@8
   179
            retval ? "selected" : "did NOT select");
icculus@8
   180
icculus@8
   181
    return(retval);
icculus@81
   182
} /* ui_file_picker_carbon */
icculus@8
   183
icculus@8
   184
icculus@81
   185
static void ui_fatal_carbon(const char *str)
icculus@0
   186
{
icculus@81
   187
    do_msgbox(str, kAlertStopAlert, NULL, NULL);
icculus@0
   188
} /* ui_fatal */
icculus@0
   189
icculus@0
   190
icculus@81
   191
static void ui_success_carbon(const char *str)
icculus@0
   192
{
icculus@8
   193
    do_msgbox(str, kAlertNoteAlert, NULL, NULL);
icculus@81
   194
} /* ui_success_carbon */
icculus@0
   195
icculus@0
   196
icculus@81
   197
static void ui_msgbox_carbon(const char *str)
icculus@50
   198
{
icculus@50
   199
    do_msgbox(str, kAlertNoteAlert, NULL, NULL);
icculus@81
   200
} /* ui_msgbox_carbon */
icculus@50
   201
icculus@50
   202
icculus@81
   203
static void ui_total_progress_carbon(int percent)
icculus@0
   204
{
icculus@0
   205
    static int lastpercent = -1;
icculus@0
   206
    if (percent != lastpercent)
icculus@0
   207
    {
icculus@0
   208
        Boolean indeterminate = (percent < 0) ? TRUE : FALSE;
icculus@0
   209
        SetControlData(progress, kControlEntireControl,
icculus@0
   210
                        kControlProgressBarIndeterminateTag,
icculus@0
   211
                        sizeof (indeterminate), &indeterminate);
icculus@0
   212
        SetControl32BitValue(progress, percent);
icculus@0
   213
        lastpercent = percent;
icculus@0
   214
    } /* if */
icculus@81
   215
} /* ui_total_progress_carbon */
icculus@0
   216
icculus@0
   217
icculus@81
   218
static void ui_status_carbon(const char *str)
icculus@0
   219
{
icculus@0
   220
    SetControlData(status, kControlEditTextPart, kControlStaticTextTextTag,
icculus@0
   221
                    strlen(str), str);
icculus@0
   222
    Draw1Control(status);
icculus@81
   223
} /* ui_status_carbon */
icculus@81
   224
icculus@81
   225
icculus@81
   226
static int ui_show_readme_carbon(const char *fname, const char *text)
icculus@81
   227
{
icculus@81
   228
    /*
icculus@81
   229
     * Just let the Finder pick the right program to view the file...
icculus@81
   230
     *  this lets you ship with a .txt, .html, .rtf, or whatever, for a
icculus@81
   231
     *  readme on this platform.
icculus@81
   232
     */
icculus@81
   233
icculus@81
   234
    size_t allocsize = strlen(fname) + 32;
icculus@81
   235
    char *cmd = (char *) alloca(allocsize);
icculus@81
   236
    if (!cmd)
icculus@81
   237
    {
icculus@81
   238
        _fatal("Out of memory.");
icculus@81
   239
        return(0);
icculus@81
   240
    } /* if */
icculus@81
   241
icculus@81
   242
    snprintf(cmd, allocsize, "open %s", fname);
icculus@81
   243
    system(cmd);  /* !!! FIXME: error check? */
icculus@81
   244
    return(1);
icculus@81
   245
} /* ui_show_readme_carbon */
icculus@81
   246
icculus@81
   247
icculus@81
   248
/* user interface stuff you implement. */
icculus@81
   249
int ui_init_carbon(void)
icculus@81
   250
{
icculus@81
   251
    ControlID statusID = { MOJOPATCH_SIG, MOJOPATCH_STATUS_ID };
icculus@81
   252
    ControlID progressID = { MOJOPATCH_SIG, MOJOPATCH_PROGRESS_ID };
icculus@81
   253
    IBNibRef nibRef = NULL;
icculus@81
   254
    OSStatus err;
icculus@81
   255
    Boolean b = TRUE;
icculus@81
   256
icculus@81
   257
    /* !!! FIXME: This is corrupting the "basedir" variable in platform_unix.c ! */
icculus@81
   258
    if (CreateNibReference(CFSTR("mojopatch"), &nibRef) != noErr)
icculus@81
   259
    {
icculus@81
   260
        fprintf(stderr, "MOJOPATCH: Carbon UI failed to initialize!\n");
icculus@81
   261
        fprintf(stderr, "MOJOPATCH: You probably don't have a .nib file!\n");
icculus@81
   262
        return(0);  /* usually .nib isn't found. */
icculus@81
   263
    } /* if */
icculus@81
   264
icculus@81
   265
    err = SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
icculus@81
   266
    if (err == noErr)
icculus@81
   267
        err = CreateWindowFromNib(nibRef, CFSTR("MainWindow"), &window);
icculus@81
   268
    DisposeNibReference( nibRef );
icculus@81
   269
icculus@81
   270
    if (err == noErr)
icculus@81
   271
        err = GetControlByID(window, &statusID, &status);
icculus@81
   272
icculus@81
   273
    if (err == noErr)
icculus@81
   274
        err = GetControlByID(window, &progressID, &progress);
icculus@81
   275
icculus@81
   276
    if (err == noErr)
icculus@81
   277
    {
icculus@81
   278
        ShowWindow(window);
icculus@81
   279
        err = ActivateWindow(window, TRUE);
icculus@81
   280
    } /* if */
icculus@81
   281
icculus@81
   282
    if (err == noErr)
icculus@81
   283
    {
icculus@81
   284
        err = SetControlData(progress, kControlEntireControl,
icculus@81
   285
                              kControlProgressBarAnimatingTag,
icculus@81
   286
                              sizeof (b), &b);
icculus@81
   287
    } /* if */
icculus@81
   288
icculus@81
   289
    if (err == noErr);
icculus@81
   290
        UI_SET_FUNC_POINTERS(carbon);
icculus@81
   291
icculus@81
   292
    return(err == noErr);
icculus@81
   293
} /* ui_init_carbon */
icculus@81
   294
icculus@81
   295
#endif
icculus@0
   296
icculus@0
   297
/* end of ui_carbon.c ... */
icculus@0
   298