Ignore:
Timestamp:
11/05/07 10:05:50 (16 years ago)
Author:
Nicholas Riley
Message:

VERSION: Updated for 1.1d2.

CPS.h: Remove unused definitions. typedef ProcessSerialNumber CPSProcessSerNum to eliminate warnings.

main.c: Updated for 1.1d2. Remove getInfoCString because it depends on undocumented C behavior that broke in Leopard; replace with ugly CFString code because CFStringCreateWithFormat is stupid. Add Radar references.

README: Updated for 1.1d2 and new compiler. Add Radar references.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/appswitch/appswitch/main.c

    r306 r345  
    33 Nicholas Riley <appswitch@sabi.net>
    44
    5  Copyright (c) 2003-06, Nicholas Riley
     5 Copyright (c) 2003-07, Nicholas Riley
    66 All rights reserved.
    77
     
    2626const char *APP_NAME;
    2727
    28 #define VERSION "1.1d1"
     28#define VERSION "1.1d2"
    2929
    3030struct {
     
    6464    // CoreGraphics errors
    6565    { kCGErrorIllegalArgument, "window server error.\nAre you logged in?" },
     66    { kCGErrorInvalidContext, "application context unavailable" },
    6667    { fnfErr, "file not found" },
    6768    // (abused) errors
     
    295296}
    296297
    297 char *getInfoCString(CFDictionaryRef info, CFStringRef key) {
    298     CFStringRef str = CFDictionaryGetValue(info, key);
     298CFStringRef stringTrimmedToWidth(CFStringRef str, CFIndex width) {
    299299    if (str == NULL)
    300         return "";
    301     static char *cStr = NULL;
    302     static bool wasDynamic = false;
    303     if (wasDynamic)
    304         free(cStr);
    305     cStr = (char *)CFStringGetCStringPtr(str, CFStringGetSystemEncoding());
    306     if (cStr != NULL) {
    307         wasDynamic = false;
    308     } else {
    309         CFIndex cStrLength = CFStringGetMaximumSizeOfFileSystemRepresentation(str);
    310         cStr = (char *)malloc(cStrLength * sizeof(char));
    311         if (!CFStringGetFileSystemRepresentation(str, cStr, cStrLength)) {
    312             CFShow(cStr);
    313             errexit("internal error: string encoding conversion failed");
    314         }
    315         wasDynamic = true;
    316     }
    317     return cStr;
     300        str = CFSTR("");
     301    CFIndex length = CFStringGetLength(str);
     302    if (length == width)
     303        return CFRetain(str);
     304   
     305    CFMutableStringRef padStr = CFStringCreateMutableCopy(NULL, width, str);
     306    CFStringPad(padStr, CFSTR(" "), width, 0);
     307    return padStr;
    318308}
    319309
     
    326316    };
    327317    pid_t pid;
    328     char *format = NULL;
     318    CFStringRef format = NULL;
     319    CFIndex nameWidth = 19;
     320    CFIndex pathWidth = 0;
    329321    if (OPTS.appAction == APP_LIST) {
    330322        int termwidth = 80;
     
    336328             ioctl(STDIN_FILENO,  TIOCGWINSZ, (char *)&ws) != -1) ||
    337329            ws.ws_col != 0) termwidth = ws.ws_col;
    338         char *formatButPath = "%9ld.%ld %5ld %4s %4s %-19.19s";
    339         int pathlen = termwidth - strlen(banner) - 1;
    340         // XXX don't ever free 'format', should fix if we get called repeatedly
     330        char *formatButPath = "%9ld.%ld %5ld %@ %@ %@";
     331        // XXX don't ever release 'format', should fix if we get called repeatedly
    341332        if (OPTS.longList) {
     333            pathWidth = 1;
    342334            printf("%s PATH (bundle identifier)\n", banner);
    343             asprintf(&format, "%s %%s", formatButPath);
    344         } else if (pathlen >= 4) {
    345             printf("%s PATH\n", banner);
    346             asprintf(&format, "%s %%-%d.%ds", formatButPath, pathlen, pathlen);
     335            format = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s %%@"), formatButPath);
    347336        } else {
    348             format = formatButPath;
     337            pathWidth = termwidth - strlen(banner) - 1;
     338            if (pathWidth >= 4) {
     339                printf("%s PATH\n", banner);
     340                format = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s %%@"), formatButPath);
     341            } else {
     342                pathWidth = 0;
     343                format = CFStringCreateWithCString(NULL, formatButPath, kCFStringEncodingUTF8);
     344            }
    349345        }
    350346    }
     
    366362            case MATCH_PID: err = GetProcessPID(&psn, &pid); if (err != noErr || OPTS.pid != pid) continue;
    367363                break;
    368             case MATCH_PATH: if (!infoStringMatches(info, CFSTR("BundlePath"), OPTS.path)) continue;
     364            case MATCH_PATH: if (!infoStringMatches(info, CFSTR("BundlePath"), OPTS.path) &&
     365                !infoStringMatches(info, CFSTR("CFBundleExecutable"), OPTS.path)) continue;
    369366                break;
    370367            case MATCH_BUNDLE_ID: if (!infoStringMatches(info, CFSTR("CFBundleIdentifier"), OPTS.bundleID)) continue;
     
    376373            if (GetProcessPID(&psn, &pid) != noErr)
    377374                pid = -1;
    378             printf(format, psn.lowLongOfPSN, psn.highLongOfPSN, pid,
    379                    getInfoCString(info, CFSTR("FileType")), getInfoCString(info, CFSTR("FileCreator")),
    380                    getInfoCString(info, CFSTR("CFBundleName")), getInfoCString(info, CFSTR("BundlePath")));
    381             if (OPTS.longList) {
    382                 char *bundleID = getInfoCString(info, CFSTR("CFBundleIdentifier"));
    383                 if (bundleID[0] != '\0')
    384                     printf(" (%s)", bundleID);
     375            CFStringRef path = NULL;
     376            // XXX padding/truncation probably breaks with double-width characters
     377            if (pathWidth) {
     378                path = CFDictionaryGetValue(info, CFSTR("BundlePath"));
     379                if (path == NULL)
     380                    path = CFDictionaryGetValue(info, CFSTR("CFBundleExecutable"));
     381                if (!OPTS.longList)
     382                    path = stringTrimmedToWidth(path, pathWidth);
    385383            }
    386             putchar('\n');
     384            CFStringRef name = stringTrimmedToWidth(CFDictionaryGetValue(info, CFSTR("CFBundleName")), nameWidth);
     385            CFStringRef type = stringTrimmedToWidth(CFDictionaryGetValue(info, CFSTR("FileType")), 4);
     386            CFStringRef creator = stringTrimmedToWidth(CFDictionaryGetValue(info, CFSTR("FileCreator")), 4);
     387            CFStringRef line = CFStringCreateWithFormat(NULL, NULL, format,
     388                psn.lowLongOfPSN, psn.highLongOfPSN, pid, type, creator, name, path);
     389            CFRelease(name);
     390            CFRelease(type);
     391            CFRelease(creator);
     392            if (!OPTS.longList)
     393                CFRelease(path);
     394            else {
     395                CFStringRef bundleID = CFDictionaryGetValue(info, CFSTR("CFBundleIdentifier"));
     396                if (bundleID != NULL && CFStringGetLength(bundleID) != 0) {
     397                    CFStringRef origLine = line;
     398                    line = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%@)"), line, bundleID);
     399                    CFRelease(origLine);
     400                }
     401            }
     402            char *cStr = (char *)CFStringGetCStringPtr(line, CFStringGetSystemEncoding());
     403            if (cStr != NULL) {
     404                puts(cStr);
     405            } else {
     406                CFIndex cStrLength = CFStringGetMaximumSizeOfFileSystemRepresentation(line);
     407                cStr = (char *)malloc(cStrLength * sizeof(char));
     408                if (!CFStringGetFileSystemRepresentation(line, cStr, cStrLength)) {
     409                    CFShow(cStr);
     410                    errexit("internal error: string encoding conversion failed");
     411                }
     412                puts(cStr);
     413                free(cStr);
     414            }
    387415            continue;
    388416        }
     
    394422
    395423    errexit("can't find matching process");
    396     return psn;
     424    return psn; // not reached
    397425}
    398426
     
    410438        case APP_LIST: break; // already handled in matchApplication
    411439        case APP_SWITCH: err = SetFrontProcess(&psn); verb = "set front"; break;
     440        // XXX show/hide return paramErr - rdar://problem/5579375 - ask on carbon-dev later
    412441        case APP_SHOW: err = ShowHideProcess(&psn, true); verb = "show"; break;
    413442        case APP_HIDE: err = ShowHideProcess(&psn, false); verb = "hide"; break;
     
    416445        case APP_KILL_HARD:
    417446        {
     447            // no Process Manager equivalent - rdar://problem/4808400
    418448            if (kill(getPID(&psn), SIGKILL) == -1)
    419449                err = (errno == ESRCH) ? procNotFound : (errno == EPERM ? permErr : paramErr);
     
    431461    switch (OPTS.action) {
    432462        case ACTION_NONE: break;
     463        // no Process Manager equivalents - rdar://problem/4808397
    433464        case ACTION_SHOW_ALL: err = CPSPostShowAllReq(&psn); verb = "show all"; break;
    434465        case ACTION_HIDE_OTHERS: err = CPSPostHideMostReq(&psn); verb = "hide other"; break;
Note: See TracChangeset for help on using the changeset viewer.