

|
Volume Number: | 3 | |||
Issue Number: | 6 | |||
Column Tag: | Assembly Language Lab |
Icon Reader Utility
By Ms. Jean Thomas, Swarthmore, PA
Getting Application Icons
Whenever I receive a number of new programs, one of the things I most look forward to is seeing the new icons. Normally this would require a trip to the Finder, but even there you can’t see any related document icons until you open the application and create a file (or use ResEdit). If you don’t happen to have 120k free on your disk, you can use this little IconApp utility to view application and document icons.
Even though every application on the Desktop has an icon, applications that haven’t been ‘bundled’ or set up to display a specific icon (along with other information) take on a generic application icon which is stored in the Finder. Applications which have been bundled and have a file reference number, used by the Finder to associate applications with their icons (BNDL and FREF), can have a unique icon on the Desktop. The Finder copies the file’s icons into the destkop file and keeps track of each icon set per each file creator tag. Thus if another applicaton is loaded with the same creator as a previous application, it’s icon will change to the wrong icon on the desktop. This is why creator tags must be unique. Also, the deskto never forgets, so even if you have a unique creator tag, it may be necessary to force the Finder to rebuild the desktop file by holding down the cmd-option keys during a re-boot. This program opens an application’s resource fork and displays the program’s bundled icons in a small dialog box.
An icon is a quickdraw object that is defined as a small 128 byte bitmap four bytes wide living in a small rectangle 32 by 32. In our program we define a bitmap to hold the icon as follows:
iconmap: dc.l ; pointer to bit image base address dc.w ; integer of row bytes (4) dc.w ; rect top 0 dc.w ; rect left 0 dc.w ; rect bottom 32 dc.w ; rect right 32
We read in the icons and store them in our iconmap, then call PlotIcon to display them in our dialog box.
Getting access to the icons of an application requires that we open its resource fork. Given a filename, _OpenResFile returns the file reference number of the selected file. In order to simplify things, I used the standard file reply dialog to get ‘rname+appreply’ or a filename from the dialog reply record. _OpenResFile also returns -1 to the stack if an error occurred in opening the resource file, such as ‘no resource file’,etc. Normally you would call _ResError to check for the specific error code if anything went wrong, but since we are only dealing with applications, I skipped that step. Unless the file has been corrupted, every application will have a resource fork with at least one resource of type ‘CODE’. In the event of corruption, however, IconApp will simply beep and return. One important thing to remember is that _OpenResFile assumes that the resource file to be opened resides on the default volume, so we have to get the volume reference number from the sfreply record before opening any resource first.
SearchIcon clr -(SP) ; room for resource file ref num lea rname+appreply,A1 ; get filename move.l A1,-(SP) _OpenResFile ; open resource file move (SP),D7 ; D7=refnum cmpi #-1,D7 ; error?(no resources) bne ValidName ; no,get filename bra NoRez ; yes,beep and return
Once we know the application has a resource fork, its time to look for any icons. Given a resource type, ‘ICN#’ in this case, _CountResources will return the total number of resources in the chosen file. Applications with unique icons always have at least one ‘ICN#’ resource, but larger applications often have file or document icons as well.
ValidName CheckDItem #3 ; get statictext handle move.l theItem(A5),-(SP) pea rname+appreply ; get our filename _SetIText ; print it in dialog clr -(SP) ; room for # of icons move.L #’ICN#’,-(SP) ; resource type _CountResources move (SP),D5 ; get # of icons in file subq #2,D5 cmpi #1,D5 ; is there at least one icon? blt NoIcon ; no, say so bra DoIcon ; otherwise,prepare to plot it
At the beginning of IconApp, the handle of a generic icon bitmap was stored in A4. If an application doesn’t have an ‘ICN#’ resource, both the filename and the generic icon will be plotted in our dialog box.
Since the total number of icons in the selected application was stored in D5, creating a loop to plot each icon is straight forward. D6 will be an index to the next plotted icon. Any application which has reached this point will contain at least one ‘ICN#’ resource, so D6 is initialized to 1. _GetIndResource can be used to call a number of resources consecutively, so passing D6 and a resource type to _GetIndResource returns a handle to the resource. Each time an icon is plotted, the index to the last icon is compared to the total number of resources in the file. I only included frames for three icons, so if the last plotted icon is not the third one, D6 is incremented and we return to plot the next one. The reference number of the most recently opened resource file was saved in D7 when the file was first opened, so we pass that same refnum to _CloseResFile before dealing dealing with another application.
Fig. 0: Our IconApp reads Icons!
Fig.1: Reply Record Equates
In order to draw both a generic icon and any icon resources in an application, I used _BlockMove (register-based), where A0 points to a source, A1 points to a destination and D0 is the number of bytes to transfer from one rectangle to another. In this case, A0 is a handle to the icon and A1 points to a 128-byte bitmap which will hold the icon. Since we want the entire icon, D0 contains 128. In order to transfer the icon bit map to the screen, we call _Ploticon which will draw the icon in a pre-specified rectangle in the dialog box.
MACRO IconDraw IRect = clr.l -(SP) move.L #’ICN#’,-(SP) move D6,-(SP) _GetIndResource move.l (SP),A0 movea.l (A0),A0 cmpa.l #0,A0 beq CloseRez lea iconmap,A1 movea.l (A1),A1 move.l #128,D0 _BlockMove pea {IRect} lea iconmap,A1 move.l A1,-(SP) _PlotIcon
_BlockMove is a useful way to transfer bitmap images to the screen. It is also a neat way to achieve flicker-free animation without resorting to the dreaded alternate screen buffer.
Fig.2: MacDraw Icons
Fig.3: Generic Icon
User Notes
IconApp is a very simple application, but it demonstrates how to use bitmaps and manipulate resource files effectively. Using the program is easy: just click on the ‘Icons’ button and select a file in the normal way. Both the application and document icons of the selected file, along with the application name, will be printed out in the dialog box. IconApp will search for and draw up to three icons in the frames.
Some corrupted applications which have been bundled and have a unique icon will appear on the Desktop with a generic icon. IconApp will plot the correct icon in the icon frames instead of the one that appears in the Finder. This is because it reads the icon from the application file and not the desktop file, so even if two applications have the same file creator tag, our utility will display the proper icon.
;IconApp IncludeMacTraps.D IncludeSysEqu.D IncludePackMacs.Txt ;------------------------------Macros---------------- ; IconDraw assumes that D5 contains the total number ; of resources of type ‘ICN#’ in the application, and ; D6 is an index to the icon we are going to plot next. ; A0-> the sourcerect,A1-> the destrect and ; D0-> the number of bytes to transfer. MACRO IconDraw IRect = clr.l -(SP) ;handle move.L #’ICN#’,-(SP);res type move D6,-(SP) ;index _GetIndResource move.l (SP),A0 movea.l(A0),A0 ;handle to ptr cmpa.l #0,A0 ;nil? beq CloseRez ;yes, so exit lea iconmap,A1 movea.l(A1),A1 move.l #128,D0 _BlockMove ;copy icon res to iconmap pea {IRect} lea iconmap,A1 ;get icon handle move.l A1,-(SP) _PlotIcon;plot icon in rect | MACRO CheckDItem Item= move.l (A2),-(SP) ; get Dialog pointer move.w {Item},-(SP) ; Dialog item in question pea theType(A5); VAR type pea theItem(A5); VAR item pea theRect(A5); VAR box _GetDItem | XDEF START ; linker requisite ;------------------Equates---------------------- AllEvents equ $0000FFFF DWindLenequ $AA ;------------------Initialize Managers---------- START pea -4(A5); push Quickdraw globals _InitGraf; init Quickdraw _InitFonts ; init Font manager _InitWindows ; init Window manager _InitMenus ; init Menu manager clr.l -(SP) ; no restart procedure _InitDialogs ; init Dialog manager _TEInit; init TextEdit move.l #AllEvents,D0 ; all standard events _FlushEvents ; flushed from event queue _InitCursor; get standard arrow cursor ;--------------------------Miscellaneous------------------ move.l #128,D0 ; 128 bytes for icon _NewPtr; get pointer cmpi #0,D0 ; error? Bne Quit; yes, exit out lea iconmap,A1 ; no, get handle to icon move.l A0,(A1) ; save pointer to icon data move.L #’ICON’,-(SP); res type for icon move #128,-(SP) ; ResID of our generic icon _GetResource ; get generic icon from system move.l (SP),A4 ; save its handle in A4 bra IconInfo ; get IconDialog box Quit _ExitToShell ;------------------------------------------------------------------ IconInfo clr.l -(SP) ; get room for Dialog pointer move.w #160,-(SP) ; resource ID pea IconDialog(A5) ; storage for Dialog record move.l #-1,-(SP); in front of other windows _GetNewDialog lea IconHandle,A2; duplicate handle move.l (SP),(A2); leave handle on stack _DrawDialog; draw dialog box and.. lea IconHandle,A2 move.l (A2),-(SP) ; set port to us _SetPort DialogLoop bsr Outline ; outline the ‘quit’ button bsr GetFrames ; draw our three icon frames clr.l -(SP) ; no filter proc pea ItemHit ; VAR ItemHit _ModalDialog move ItemHit,D0 ; Get Item chosen cmp.b #1,D0 ; quit? beq.s CloseIt cmp.b #2,D0 ; get appl. icon? beq.s GetFile bra DialogLoop ; no,wait for a valid choice CloseIt move.l (A2),-(SP) ; get dialog ptr. _CloseDialog ; close dialog _ExitToShell ; exit... GetFile move.w #100,-(sp) ; upper corner of reply box move.w #100,-(sp) pea scratch ; dummy string clr.l -(sp) ; filter move #1,-(sp) ; only applications pea apptype ; type list clr.l -(sp) ; dialog hook pea appreply ; reply record move #2,-(sp) ; standard file reply dialog _pack3 move rgood+appreply,d0 ; was a file chosen? beq DialogLoop ; no, return lea parmblock(A5),A0 ; A0-> parameter block clr.l ioCompletion(A0) ; no completion routine lea appreply,A1; A1-> reply record move.w 6(A1),ioVRefNum(A0) ; get drive refnum clr.l ioVNPtr(A0); volume name pointer _SetVol SearchIcon clr -(SP) ; room for resource file ref num lea rname+appreply,A1 ; get filename move.l A1,-(SP) _OpenResFile ; open resource file move (SP),D7 ; D7=refnum cmpi #-1,D7; error?(no resources) Bne ValidName ; no,get filename bra NoRez ; yes,beep and return NoRez move #20,-(SP) _SysBeep bra DialogLoop ValidName CheckDItem #3 ; get statictext handle move.l theItem(A5),-(SP) pea rname+appreply ; get our filename _SetIText; print it in dialog clr -(SP) ; room for # of icons move.L #’ICN#’,-(SP); resource type _CountResources move (SP),D5 ; get # of icons in file subq #2,D5 cmpi #1,D5 ; is there at least one icon? blt NoIcon; no, say so bra DoIcon; otherwise,prepare to plot it DoIcon move #1,D6 ; get first icon IconDraw iconrect1; plot it cmp D5,D6 ; is this the only icon? beq CloseRez ; yes,close resource file addq #1,D6 ; no,add one to counter bra DoIcon2 ; get second icon DoIcon2 IconDraw iconrect2; plot second icon cmp D5,D6 ; is there a third icon? beq CloseRez ; no, close resource file addq #1,D6 ; yes, add one to counter bra DoIcon3 ; get third icon DoIcon3 IconDraw iconrect3; plot third icon bra CloseRez ; close resource file NoIcon CheckDItem #3 ; get statictext handle move.l theItem(A5),-(SP) pea rname+appreply ; get our filename _SetIText; print it in dialog move.l A4,A0 ; get handle of generic icon movea.l(A0),A0 ; A0-> sourcerect cmpa.l #0,A0 beq CloseRez lea iconmap,A1 ; A1-> destrect movea.l(A1),A1 move.l #128,D0 ; D0 = number of bytes to move _BlockMove pea iconrect1 lea iconmap,A1 move.l A1,-(SP) _PlotIcon; plot generic icon bra DialogLoop ; return GetFrames:; print icon frames pea iconframe1 _FrameRect pea iconframe2 _FrameRect pea iconframe3 _FrameRect rts OutLine:; outline first item in dialog, or ‘quit’ button CheckDItem #1 move #3,-(SP) move #3,-(SP) _PenSize pea theRect(A5); VAR box move #-4,-(SP) move #-4,-(SP) _InsetRect pea theRect(A5) move #16,-(SP) move #16,-(SP) _FrameRoundRect rts CloseRez move D7,-(SP) ; D7=rsrc.file refnum _CloseResFile ; close resource file bra DialogLoop ; return ;----------------------Local storage------------------ EventRecord What: dc.w0 ;what event number Message: dc.l 0 ;ptr. to msg When: dc.l0 ;Time event was posted Point: dc.l0 ;mouse coordinates Modify:dc.w0 ;state of keys & button WWindow: dc.l 0 ;Find window’s result IconHandledc.l 0 ItemHit dc.w0 ; dialog items scratch dc.b 14 dc.b ‘’ dc.l 0 apptype dc.b‘APPL’ dcb.b 14,$ff appreplydc.w5 dc.b 63 dcb.b 63,0 iconmap dc.w 0,0,4,0,0,$20,$20 iconrect1 dc.w 17,61,49,93 iconrect2 dc.w 17,120,49,152 iconrect3 dc.w 17,174,49,206 iconframe1dc.w 10,57,54,98 iconframe2dc.w 10,115,54,156 iconframe3dc.w 10,169,54,210 ;----------------------Globals---------------- IconDialogds.w DWindLen theType ds.w1 ; VAR for GetDItem theItem ds.l1 ; VAR for GetDItem theRect ds.w4 ; VAR for GetDItem parmblock ds.w 80 ; IconApp_rscs.ASM RESOURCE ‘INAP’ 0 ‘IDENTIFICATION’ DC.B 15, ‘ICON RETRIEVER ‘ .ALIGN 2 RESOURCE ‘BNDL’ 128 ‘BUNDLE’ DC.L ‘INAP’;NAME OF SIGNATURE DC.W 0,1 ;DATA (DOESN’T CHANGE) DC.L ‘ICN#’;ICON MAPPINGS DC.W0 ;NUMBER OF MAPPINGS-1 DC.W 0,128 ;MAP 0 TO ICON 128 DC.L ‘FREF’;FREF MAPPINGS DC.W0 ;NUMBER OF MAPPINGS-1 DC.W0,128 ;MAP 0 TO FREF 128 RESOURCE ‘FREF’ 128 ‘FREF 1’ DC.B ‘APPL’, 0, 0, 0 .ALIGN 2 RESOURCE ‘ICN#’ 128 ‘MY ICON’ ; APPLICATION ICON BIT MAP DC.L $00000000,$00000000,$3FFFFFFC,$35555554 DC.L $2AAAAAAC,$35555554,$2AAAAAAC,$35FFFFD4 DC.L $2B0000AC,$354000D4,$2B4000AC,$355800D4 DC.L $2B5000AC,$355000D4,$2B1380AC,$351A80D4 DC.L $2B0280AC,$3502A0D4,$2B03B2AC,$35002AD4 DC.L $2B0026AC,$350022D4,$2B0000AC,$350000D4 DC.L $2BFFFFAC,$35555554,$2AAAAAAC,$35555554 DC.L $2AAAAAAC,$3FFFFFFC,$00000000,$00000000 * DC.L $00000000,$00000000,$3FFFFFFC,$3FFFFFFC DC.L $3FFFFFFC,$3FFFFFFC,$3FFFFFFC,$3FFFFFFC DC.L $3FFFFFFC,$3FFFFFFC,$3FFFFFFC,$3FFFFFFC DC.L $3FFFFFFC,$3FFFFFFC,$3FFFFFFC,$3FFFFFFC DC.L $3FFFFFFC,$3FFFFFFC,$3FFFFFFC,$3FFFFFFC DC.L $3FFFFFFC,$3FFFFFFC,$3FFFFFFC,$3FFFFFFC DC.L $3FFFFFFC,$3FFFFFFC,$3FFFFFFC,$3FFFFFFC DC.L $3FFFFFFC,$3FFFFFFC,$00000000,$00000000 .ALIGN 2 RESOURCE ‘ICON’ 128 ‘THE ICON’ ; GENERIC APPLICATION ICON BIT MAP DC.L $00010000,$00028000,$00044000,$00082000 DC.L $00101000,$00200800,$00400400,$00800200 DC.L $01000100,$02000080,$04000040,$08000020 DC.L $10000010,$20000008,$40003F04,$80004082 DC.L $40008041,$20013022,$1001C814,$080E7F8F DC.L $04023007,$02010007,$01008007,$00806007 DC.L $00401FE7,$0020021F,$00100407,$00080800 DC.L $00041000,$00022000,$00014000,$00008000 * DC.L $00010000,$00038000,$0007C00,$0000FE000 DC.L $001FF000,$003FF800,$007FFC0,$000FFFE00 DC.L $01FFFF00,$03FFFF80,$07FFFFC,$00FFFFFE0 DC.L $1FFFFFF0,$3FFFFFF8,$7FFFFFF,$CFFFFFFFE DC.L $7FFFFFFF,$3FFFFFFE,$1FFFFFF,$C0FFFFFFF DC.L $07FFFFFF,$03FFFFFF,$01FFFFF,$F00FFFFFF DC.L $007FFFFF,$003FFE1F,$001FFC0,$7000FF800 DC.L $0007F000,$0003E000,$0001C00,$000008000 .ALIGN 2 RESOURCE ‘DLOG’ 160 ‘Icon Dialog’ DC.W 107,122,227,376 ;BoundsRect DC.W 1 ; Dialog box w/ outline DC.B 1,1 ; Visible DC.B 0,0 ; NoGoAway DC.L 0 ; RefCon DC.W 160 ; DITL ResID DC.B ‘Icon..’ ; Title .ALIGN 2 RESOURCE ‘DITL’ 160 ‘Icon..’ STRING_FORMAT 2 DC.W 3 ;3 Items (4-1=3) DC.L 0 ; handle holder DC.W 86,194,115,248 ; BoundsRect DC.B 4 ; Button #1 DC.B ‘Quit’; title DC.L 0 ; handle holder DC.W 86,106,115,185 ; BoundsRect DC.B 4 ; button #2 DC.B ‘Icons..’ ; title DC.L 0 ; handle holder DC.W 60,78,76,241 ; BoundsRect DC.B 8 ; statictext #1 DC.B ‘’ DC.L 0 ; handle holder DC.W 60,3,76,76 ; BoundsRect DC.B 8 ; statictext #2 DC.B ‘File Name:’ STRING_FORMAT 0 ; normal !START [ ) /OUTPUT IconApp IconApp /TYPE ‘APPL’ ‘INAP’ /BUNDLE /RESOURCES IconApp_rscs $

- SPREAD THE WORD:
- Slashdot
- Digg
- Del.icio.us
- Newsvine