File: mac_icon.C

package info (click to toggle)
boinc 5.4.11-4%2Betch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 21,440 kB
  • ctags: 16,986
  • sloc: cpp: 70,682; ansic: 45,747; php: 35,513; xml: 10,487; sh: 9,324; python: 4,291; makefile: 1,958; asm: 1,258; perl: 914; sql: 395; csh: 126; pascal: 124
file content (195 lines) | stat: -rw-r--r-- 7,334 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2005 University of California
//
// This is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/* Mac-specific code to display custom icon for science application (optional)
   adapted from code written by Bernd Machenschalk.  Used with permission of the 
   Einstein@home project.
   
    To use this code:
    1. Create a *.icns file using "/Developer/Applications/utilities/Icon Composer.app"
    2. Convert the *.icns file to an app_icon.h file as follows: in Terminal, run 
      "MakeAppIcon_h <source_file> <dest_file>".  (The MakeAppIcon_h command-line utility 
      is built by the Mac boinc XCode project.)
    3. In the science application's main(), #include "app_icon.h" and call:
        setMacIcon(argv[0], MacAppIconData, sizeof(MacAppIconData));
    4. Science application must link with Carbon.framework.
*/

#include <Carbon/Carbon.h>
#include "boinc_api.h"

#define RESIDICON -16455

char MacPListData[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
"<plist version=\"1.0\">\n<dict>\n"
"\t<key>NSUIElement</key>\n\t<string>1</string>\n</dict>\n</plist>\n";


/* checks for an OS error, reports the line number and returns */
#define CHECK_OSERR(e) {\
  if (e) {\
    fprintf(stderr,"MacOS Error %d occured in %s line %d\n",e,__FILE__,__LINE__);\
    return(e); } }

// Adds ther specified resource to the file given as an argument.
int setMacRsrcForFile(char *filename, char *rsrcData, long rsrcSize, 
                            OSType rsrcType, int rsrcID, StringPtr rsrcName) {
    OSErr oserr;        /* stores an OS error code */
    FSSpec fsspec;      /* FileSpec */
    FSRef fsref;        /* File Reference */
    FInfo finfo;        /* File Info */
    short rref;         /* Resource Reference */
    Handle hand;
    int retry;

    /* get finder spec for this file */
    CHECK_OSERR((int)FSPathMakeRef((StringPtr)filename, &fsref, NULL));
    CHECK_OSERR(FSGetCatalogInfo(&fsref, nil, NULL, NULL, &fsspec, NULL));

    /* Open the resource fork for writing, create it if it does not exist.
        On a dual-processor system, the other cpu may have the resource fork 
        open for writing, so if we fail we wait and retry.
    */
    for (retry=0;retry<5;retry++) {
        rref = FSpOpenResFile(&fsspec, fsRdWrPerm);
        oserr = ResError();
        if (oserr == eofErr) { /* EOF, resource fork/file not found */
            // If we set file type and signature to non-NULL, it makes OS mistakenly
            // identify file as a classic application instead of a UNIX executable.
            FSpCreateResFile(&fsspec, 0, 0, smRoman);
            oserr = ResError();
            if (oserr == noErr) {
                rref = FSpOpenResFile(&fsspec, fsRdWrPerm);
                oserr = ResError();
            }
        }
        if (oserr == noErr)
            break;
        sleep (1);
    };

    if (oserr)
        return oserr; // give up after 5 seconds
        
    /* add the resource if not already present */
    if (!GetResource(rsrcType, rsrcID)) { /* if resource not found */
        oserr = PtrToHand(rsrcData, &hand, rsrcSize);
        if (!oserr)
            AddResource(hand, rsrcType, rsrcID, rsrcName);
    }

    /* add this to the file on disk */
    CloseResFile(rref);
    CHECK_OSERR(ResError());

    if (rsrcType == 'icns') {
        /* set custom icon flag */
        CHECK_OSERR(FSpGetFInfo(&fsspec, &finfo));
        finfo.fdFlags |= kHasCustomIcon;
        CHECK_OSERR( FSpSetFInfo(&fsspec, &finfo));
    }
    return(0);
}


static char * PersistentFGets(char *buf, size_t buflen, FILE *f) {
    char *p = buf;
    size_t len = buflen;
    size_t datalen = 0;

    *buf = '\0';
    while (datalen < (buflen - 1)) {
        fgets(p, len, f);
        if (feof(f)) break;
        if (ferror(f) && (errno != EINTR)) break;
        if (strchr(buf, '\n')) break;
        datalen = strlen(buf);
        p = buf + datalen;
        len -= datalen;
    }
    return (buf[0] ? buf : NULL);
}


void getPathToThisApp(char* pathBuf, size_t bufSize) {
    FILE *f;
    char buf[64], *c;
    pid_t myPID = getpid();
    int i;
    
    *pathBuf = 0;    // in case of failure
    
    // Before launching this project application, the BOINC client set the 
    // current directory to the slot directory which contains this application 
    // (or the soft-link to it.)  So all we need for the path to this 
    // application is the file name.  We use the -c option so ps strips off 
    // any command-line arguments for us.
    sprintf(buf, "ps -cp %d -o command=", myPID);
    f = popen(buf,  "r");
    if (!f)
        return;
    PersistentFGets(pathBuf, bufSize, f);  // Skip over line of column headings
    PersistentFGets(pathBuf, bufSize, f);  // Get the UNIX command which ran us
    fclose(f);

    c = strstr(pathBuf, " -"); 
    if (c)
        *c = 0;     // Strip off any command-line arguments
        
    for (i=strlen(pathBuf)-1; i>=0; --i) {
        if (pathBuf[i] <= ' ')
            pathBuf[i] = 0;  // Strip off trailing spaces, newlines, etc.
        else
            break;
    }
}


// Adds plst resource 0 to the file given as an argument.  This 
// identifies the applciation to the OS as an NSUIElement, so 
// that the application does not show in the Dock and it has no 
// menu bar.
int setMacPList() {
    char path[1024], resolvedPath[1024];;
    StringPtr rsrcName = (StringPtr)"\pApplication PList";

    getPathToThisApp(path, sizeof(path));
    if (path[0] == 0)
        return -1; // Should never happen
    
    setMacRsrcForFile(path, MacPListData, sizeof(MacPListData), 'plst', 0, rsrcName);
    boinc_resolve_filename(path, resolvedPath, sizeof(resolvedPath));
    return(setMacRsrcForFile(resolvedPath, MacPListData, sizeof(MacPListData), 'plst', 0, rsrcName));
}


// Adds icns resource to the file given as an argument.
// If the file is a soft link, also adds icns resource to the resolved flle. 
// Typically called from a main() with argv[0] to attach resources to itself */
int setMacIcon(char *filename, char *iconData, long iconSize) {
    char path[1024];
    StringPtr rsrcName = (StringPtr)"\pApplication icons";

    setMacRsrcForFile(filename, iconData, iconSize, 'icns', RESIDICON, rsrcName);
    boinc_resolve_filename(filename, path, sizeof(path));
    return(setMacRsrcForFile(path, iconData, iconSize, 'icns', RESIDICON, rsrcName));
}
const char *BOINC_RCSID_112a101526="$Id: mac_icon.C,v 1.9 2006/02/28 09:53:10 charlief Exp $";