TweetFollow Us on Twitter

Scrolling Menubar
Volume Number:5
Issue Number:4
Column Tag:Programmer's Workshop

April Fool's INIT: Scrolling the Menu Bar!?

By Mike Scanlin, San Diego, CA

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

Probably everyone who reads this magazine knows at least one person who owns a Mac that they’d like to play a joke on. This INIT resource might be just the thing you’re looking for. It is a patch to _GetNextEvent that will scroll the menu bar off the right side of the screen (leaving the menu bar blank) when the mouse is clicked in the very top pixel of the menu bar with an odd horizontal position. It does nothing if the mouse is clicked anywhere else on the screen, so it is possible to use the menus when this patch is installed, just so long as you don’t click in the very top pixel at an odd position. The menus will come back eventually (after a few sarcastic messages are displayed in the empty menu bar), so this is a pretty harmless patch (although extremely annoying according to my guinea pig roommate). Command key equivalents for current menus (like COMMAND-Q) will work even though no menus are shown. It is possible to remove the patch once it is installed by typing COMMAND-SHIFT-OPTION-TAB. The patch will beep to let you know it has been removed.

HOW IT WORKS

This patch to _GetNextEvent is an application of the technique I used in the Shift Mod patch (September 1987 issue of MacTutor). It is a tail patch on _GetNextEvent that looks at the event being returned and intercepts it if it is a mouseDown event with a vertical position of zero and an odd horizontal position. When it finds such an event the menu bar is scrolled off the screen and then _DrawMenuBar and _HiliteMenu are patched to do nothing. The reason those two traps are patched is because we don’t want anything drawn in the menu bar while we’re displaying our messages. The menu bar is restored by restoring those two traps and then calling _DrawMenuBar. Note that because we are patching _DrawMenuBar the user will not be able to get the menus back by quitting the current application and/or launching another application (because every application uses _DrawMenuBar to put their menus up).

Once we have scrolled the menus off, the patch to _GetNextEvent will intercept any mouseDown event anywhere in the menu bar area and display a message in the menu bar for 1 second or until the mouse button is let go, which ever is longer. After four such messages, the patches to _DrawMenuBar and _HiliteMenuBar are removed and _DrawMenuBar is called to draw the current menu bar (which may not necessarily be the one that was scrolled off since the user could have changed applications in the mean time).

To do the actual scrolling you would expect me to use _ScrollRect. That’s what I tried at first, but it was too slow (took about 10 seconds for the menu bar to get all the way off the screen). Then I tried scrolling by 3 or 4 pixels at a time, but it wasn’t smooth enough. The version you see here is scrolling by rotating bits in screen memory (via the 68000’s roxr instruction). Although somewhat unorthodox (Apple wouldn’t approve) it now only takes about 2 seconds to smoothly scroll the menu bar all the way off the screen.

PROBLEM

There is a potential problem with this patch. There is a danger in patching and unpatching traps that may be patched by other applications. For applications that patch traps this isn’t normally a problem because they get a chance to restore the traps when they quit (before something else can patch them). But it is possible for our patches to be unpatched at a bad time. A “bad time” to unpatch would be after something else has patched on top of one of our patches. For instance, if we patch _GetNextEvent and then some other program patches it and then we unpatch ours, the second patch will be unpatched along with ours, but the application that made the second patch won’t know about it. To partially correct this from happening, I have the removePatch routine check if something has patched _GetNextEvent after we have patched it (by calling _GetTrapAddress and comparing it to ourself) and if it has, then ignore the request to unpatch ourself. I did not do this for _DrawMenuBar and _HiliteMenu, but it is unlikely that other applications would patch either of those two (besides, this is only a joke -- it’s not something you’re going to leave around in your System Folder forever).

One additional problem is that while this patch should work on any size monochrome monitor, it will not work on a Mac II color monitor. If anyone comes up with a simple fix, please send it in.

/* scrollMenuBarPatch.c     18 Nov 1987
 *
 * by Mike Scanlin and Andy Voelker
 *
 * This will install a patch to
 * _GetNextEvent that intercepts
 * mouseDown events if they occur in the
 * very top pixel-row of the screen. If
 * an event is intercepted, the menu bar
 * is scrolled off the right side of the
 * screen before the user can react.
 * After 4 more clicks in the menuBar
 * (with appropriately sarcastic messages 
 * displayed after each one) the origina
 * l menuBar is restored. The patch can
 * be removed by typing
 * COMMAND-OPTION-SHIFT-TAB.
 */

#include “EventMgr.h”
#include “QuickDraw.h”
#include “asm.h”

/* low memory globals */
extern Handle    MenuList : 0x0A1C;
extern PtrScrnBase : 0x0824;
extern GrafPtr WMgrPort   : 0x09DE;

/* the traps we patch */
#define GetNextEventTrap  0xA970
#define DrawMenuBarTrap   0xA937
#define HiliteMenuTrap    0xA938

#define CLICKS_TO_MENU    4
#define MESSAGE_DELAY60
#define MENU_BAR_HEIGHT   20
#define TAB_KEY  0x09
#define JMP_INSTRUCTION   0x4EF9

#define memFullErr -108
#define screenBits_bounds_right  -110
#define screenBits_bounds_left-114

void  main(void);

void main()
{
 asm {
 
/* This first section is the only part
 * that gets run initially. It gets some
 * space in the system heap and sets up a 
 * patch to _GetNextEvent. The patch
 * won’t do anything until the user
 * clicks in the very top pixel of the
 * menu bar (in which case it will scroll 
 * the menu bar off the screen to the
 * right). */
 
   move.l D3,-(SP)

/* get the old trap address */
 move   #GetNextEventTrap,D0
 _GetTrapAddress

/* set the address for the JMP
 * instruction that calls the original
 * trap */
 lea    @origTrap,A1
 move.l A0,(A1)

/* get some space in the system heap for
 * our patch */
 lea    @last,A0
 lea    @first,A1
 suba.l A1,A0
/* D0 = length of patch */
 move.l A0,D0  
/* save length for _BlockMove */
 move.l D0,D3    
 _NewPtrSYS
 cmpi   #memFullErr,D0
 beq.s  @noPatch
 lea    @saveLoc,A1
/* save for removePatch */
 move.l A0,(A1)
/* save for _BlockMove */ 
 move.l A0,-(SP) 

/* set the trap address to the space we
 * just got in the system heap. */
 move   #GetNextEventTrap,D0
 _SetTrapAddress

/* now move our patch into place */
 lea    @first,A0
/* (SP)+ is the result from _NewPtr */
 move.l (SP)+,A1 
 move.l D3,D0
 _BlockMove

@noPatch
 move.l (SP)+,D3

/* this is the end of the installation
 * part, but we can’t do an RTS here
 * because LSC needs to clean up. So we
 * fall through to the end. */
 bra    @last

/***************************************
 * Here’s the new _GetNextEvent. It calls 
 * the existing _GetNextEvent and then
 * checks if a mouseDown or keyDown event 
 * is being reported. If not, the event
 * is passed to the application
 * unmodified. If we end up using the
 * event ourselves, a null event is
 * returned to the application.
 ***************************************/

@first
/* pop the original return address and
 * save it */
 lea    @exitAddress,A0
 move.l (SP)+,(A0)
/* save ptr to event record so we can get 
 * at it later */
 lea    @eventRecPtr,A0
 move.l (SP),(A0)
/* set the return address to our patch */
 pea    @tailPatch

/* the nops get filled with the address
 * of the original _GetNextEvent */
 dcJMP_INSTRUCTION
@origTrap 
 nop
 nop

/* this is where it comes after the
 * normal _GetNextEvent processing */
@tailPatch
 movem.lA1/D0-D3,-(SP)
 
 lea    @eventRecPtr,A0
 move.l (A0),A0

/* check if it’s a keydown event that
 * says to remove ourself. This is the
 * only keyDown that we intercept. */
 move 
 OFFSET(EventRecord,what)(A0),D0
 cmpi   #keyDown,D0
 bne.s  @noKeyDown
/* the key to remove the patch is
 * COMMAND-SHIFT-OPTION-Tab */
 move.l 
 OFFSET(EventRecord,message)(A0),D0
 cmpi.b #TAB_KEY,D0
 bne.s  @noKeyDown
 move 
 OFFSET(EventRecord,modifiers)(A0),D0
 andi   
 #optionKey+cmdKey+shiftKey,D0
 eori   
 #optionKey+cmdKey+shiftKey,D0
 beq.s  @removePatch
 
@noKeyDown
/* if it’s not a mousedown event, then
 * ignore it */
 cmpi   #mouseDown,D0
 bne.s  @patchExit

/* if we’ve already scrolled the menu
 * list, then don’t scroll it again */
 lea    @menus,A1
 tst    (A1)
 bne.s  @alreadyGone
 
/* if no menus exist, then leave */
 move.l MenuList,A1
 move.l (A1),A1
 tst    (A1)
 beq.s  @patchExit

/* if the mouse is not at an odd
 * location, then leave */
 move.l 
 OFFSET(EventRecord,where)(A0),D0
 andi   #1,D0
 beq.s  @patchExit
/* if the mouse is not at the very top
 * pixel of the menu bar, then leave */
 move.l 
 OFFSET(EventRecord,where)(A0),D0
/* put vertical coordinate in low word */
 swap   D0
 cmpi   #1,D0
 bge.s  @patchExit
 
/* now we’re set to scroll that puppy. */
 bsr    @scrollMenuBar

/* save the fact that the menu bar that
 * was just scrolled */
 lea    @menus,A0
 move   #1,(A0)
 
/* patch _DrawMenuBar and _HiliteMenu to
 * do nothing if and when they’re
 * called */
 bsr    @disableTraps

 lea    @clicks,A1
 move   #CLICKS_TO_MENU,(A1)
 
 bra.s  @returnNullEvent

@alreadyGone
/* if mouse is not in menu bar, then
 * leave */
 move.l 
 OFFSET(EventRecord,where)(A0),D0
/* put vertical coordinate in low word */
 swap   D0
 cmpi   #MENU_BAR_HEIGHT,D0
 bge.s  @patchExit

/* print a message in the menu bar */
 bsr    @drawAMessage

 lea    @clicks,A0
 subi   #1,(A0)
 bne.s  @returnNullEvent

/* now that we’re finished playing,
 * restore _DrawMenuBar and 
 * _HiliteMenu */
 bsr    @restoreMenus
 
@returnNullEvent
/* set the event to null */
 lea    @eventRecPtr,A0
 move.l (A0),A0
 clr    
 OFFSET(EventRecord,what)(A0)
/* change _GetNextEvent’s return value to 
 * false. The 20 is for the 5 regs that
 * are saved on the stack at this point
 */
 clr    20(SP)

@patchExit
 movem.l(SP)+,A1/D0-D3
/* JMP to the place that called
 * _GetNextEvent */
 dcJMP_INSTRUCTION
@exitAddress
 nop
 nop

/* this is where it comes to remove the
 * _GetNextEvent patch */
@removePatch
/* if the menus aren’t shown, then
 * restore them before leaving */
 bsr    @restoreMenus
/* check if we are the most recent patch
 * to _GetNextEvent. If we’re not, then
 * don’t unpatch. */
   move #GetNextEventTrap,D0
 _GetTrapAddress
 lea    @first,A1
 cmpa.l A1,A0
 bne.s  @returnNullEvent
/* set the trap address back to the
 * original trap. */
 lea    @origTrap,A0
 move.l (A0),A0
 move   #GetNextEventTrap,D0
 _SetTrapAddress
/* beep to let them know it has been 
 * removed */
 move   #1,-(SP)
 _SysBeep
/* free up mem occupied by this patch */
 lea    @saveLoc,A0
 move.l A0),A0
 _DisposPtr
 bra.s  @returnNullEvent

/* This routine will disable _DrawMenuBar 
 * and _HiliteMenu */
@disableTraps
 move   #DrawMenuBarTrap,D0
 _GetTrapAddress
 lea    @drawMenuBarAddr,A1
 move.l A0,(A1)
 lea    @doNothing,A0
 move   #DrawMenuBarTrap,D0
 _SetTrapAddress
 move   #HiliteMenuTrap,D0
 _GetTrapAddress
 lea    @hiliteMenuAddr,A1
 move.l A0,(A1)
 lea    @doNothingWithParam,A0
 move   #HiliteMenuTrap,D0
 _SetTrapAddress
 rts
 
/* This routine will restore _DrawMenuBar 
 * and _HiliteMenu and then draw the 
 * current menu bar */
@restoreMenus
 lea    @menus,A0
 tst    (A0)
 beq.s  @doNothing
/* unpatch DrawMenuBar and then draw the
 * old menu bar */
 lea    @drawMenuBarAddr,A0
 move.l (A0),A0
 move   #DrawMenuBarTrap,D0
 _SetTrapAddress
 lea    @hiliteMenuAddr,A0
 move.l (A0),A0
 move   #HiliteMenuTrap,D0
 _SetTrapAddress
 lea    @menus,A0
 clr    (A0)
 _DrawMenuBar
@doNothing
 rts

/* This is the _HiliteMenu routine that
 * does nothing. It gets rid of the
 * parameter passed to _HiliteMenu and
 * then returns. */
@doNothingWithParam
 move.l (SP)+,A0
 addq.l #2,SP
 jmp    (A0)

/* This is the routine that actually does 
 * the scrolling */
@scrollMenuBar
/* hide the cursor so we don’t get part
 * of the cursor scrolled with the
 * menuBar */
 _HideCursor

/* get the current screen width from the
 * Quickdraw global screenBits */
 move.l (A5),A0
/* D3 = # of columns (width) - 1 in the
 * current screen */
 move 
 screenBits_bounds_right(A0),D3
 sub    
 screenBits_bounds_left(A0),D3
 move   D3,D2
 subq   #1,D3
/* D2 = # of bytes - 1 in one screen
 * row */ 
 asr    #3,D2
 subq   #1,D2

/* here’s the loop that actually scrolls
 * the menu bar all the way across the
 * screen */
@wayOut
 move   #MENU_BAR_HEIGHT - 2,D1

/* this outside loop will scroll all rows 
 * of the menu bar one pixel to the right 
 */
@outside
 move   D2,D0
 addq   #1,D0
/* calc # of bytes from base addr to
 * start of current row */
 mulu   D1,D0    
 move.l ScrnBase,A0
 adda.l D0,A0
/* white-out the left edge of this row */
 clr.b  (A0)
/* D0 = number of words in one row */
 move   D2,D0    
 asr    #1,D0
/* set the X flag */
 andi.b #0xEF,CCR
/* this inner loop will scroll one row of 
 * the screen one pixel to the right */
@inside
 roxr   (A0)+
 dbra   D0,@inside

/* go and do the next row */
 dbra   D1,@outside

/* make the corners look like they used
 * to (i.e. rounded and black) */
 move   D2,D0
 move.l ScrnBase,A1
 ori.b  #0xF8,(A1)
 adda   D0,A1
 ori.b  #0x1F,(A1)+
 ori.b  #0xE0,(A1)
 adda   D0,A1
 ori.b  #0x07,(A1)+
 ori.b  #0xC0,(A1)
 adda   D0,A1
 ori.b  #0x03,(A1)+
 ori.b  #0x80,(A1)
 adda   D0,A1
 ori.b  #0x01,(A1)+
 ori.b  #0x80,(A1)
 adda   D0,A1
 ori.b  #0x01,(A1)
 
 dbra   D3,@wayOut

 _ShowCursor
 rts

/* this routine will print a string in
 * the menu bar, wait a bit and then
 * erase it */
@drawAMessage
/* set the current port to the window
 * manager’s */
 move.l (A5),A0
 lea    @savePort,A1
 move.l (A0),(A1)
 move.l WMgrPort,(A0)

/* save the old clipRgn */
 lea    @saveClip,A0
 move.l WMgrPort,A1
 move.l 
 OFFSET(GrafPort,clipRgn)(A1),(A0)
/* set the clipRgn to be big enough for
 * the string we want to print */
 subq   #4,SP
 _NewRgn
 move.l WMgrPort,A1
 move.l 
 (SP)+,OFFSET(GrafPort,clipRgn)(A1)
 pea    @stringRect
 _ClipRect

/* the string we print depends on the
 * value of the clicks variable */
 lea    @clicks,A0
 move   (A0),D0
 cmpi   #4,D0
 bne.s  @1
 pea    @string1
 bra.s  @5
@1 cmpi #3,D0
 bne.s  @2
 pea    @string2
 bra.s  @5
@2 cmpi #2,D0
 bne.s  @3
 pea    @string3
 bra.s  @5
@3 cmpi #1,D0
 bne.s  @delay
 pea    @string4
@5 move #10,-(SP)
 move   #14,-(SP)
 _MoveTo
 _DrawString
@delay  
 lea    @downTime,A0
 move.l Ticks,(A0)

/* wait until the mouse is released or 60 
 * ticks, which ever is longer */
@waitTilMouseUp
 subq.l #2,SP
 _StillDown
 tst    (SP)+
 bne.s  @waitTilMouseUp
 lea    @downTime,A0
 move.l (A0),D0
 addi.l #MESSAGE_DELAY,D0
 cmp.l  Ticks,D0
 bgt.s  @waitTilMouseUp

/* erase the string */
 pea    @stringRect
 _EraseRect

/* dispose of the clipRgn we created */
 move.l WMgrPort,A1
 move.l 
 OFFSET(GrafPort,clipRgn)(A1),-(SP)
 _DisposeRgn
/* restore the old clip rgn */
 lea    @saveClip,A0
 move.l WMgrPort,A1
 move.l 
 (A0),OFFSET(GrafPort,clipRgn)(A1)
 
/* restore the old port */
 move.l (A5),A0
 lea    @savePort,A1
 move.l (A1),(A0)
 rts
 
@eventRecPtrdc.l 0
/* @menus is TRUE while menus that exist
 * are not being shown */
@menus  dc0 
@downTime dc.l   0
/* @clicks is the number of menus clicks
 * until menus return */
@clicks dc0 
/* @words is the number of 16 bit words
 * in one row of screen */
@words  dc0
/* @saveLoc is the address of our patch
 * in the system heap */  
@saveLocdc.l0  
@savePort dc.l   0
@saveClip dc.l   0
@drawMenuBarAddr dc.l0
@hiliteMenuAddr  dc.l0

/* this rect should be big enough to
 * enclose the longest of the strings. */
@stringRect dc
 0,8,MENU_BAR_HEIGHT-1,300

/* define the pascal strings. Does LSC
 * provide a better way than this? */
@string1dc.b13,’N’,’o’,
 ‘ ‘,’M’,’e’,’n’,’u’,’s’,’ ‘,’H’,’e’,
 ‘r’,’e’
@string2dc.b14,’S’,’t’,’i’,
 ‘l’,’l’,’ ‘,’N’,’o’,’ ‘,’M’,’e’,’n’,
 ‘u’,’s’
@string3dc.b7,’N’,’o’,’t’,
 ‘ ‘,’Y’,’e’,’t’
@string4dc.b25,’W’,’h’,’e’,
 ‘r’,’e’,’ ‘,’D’,’i’,’d’,’ ‘,’T’,’h’,
 ‘o’,’s’,’e’, ‘,’M’,’e’,’n’,’u’,’s’,
 ‘ ‘,’G’,’o’,’?’
@last
 }
}

 
AAPL
$112.94
Apple Inc.
+1.16
MSFT
$47.98
Microsoft Corpora
+0.32
GOOG
$524.87
Google Inc.
+8.52

MacTech Search:
Community Search:

Software Updates via MacUpdate

NeoOffice 2014.6 - Mac-tailored, OpenOff...
NeoOffice is a complete office suite for OS X. With NeoOffice, users can view, edit, and save OpenOffice documents, PDF files, and most Microsoft Word, Excel, and PowerPoint documents. NeoOffice 3.x... Read more
LibreOffice 4.3.5.2 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
CleanApp 5.0.0 Beta 5 - Application dein...
CleanApp is an application deinstaller and archiver.... Your hard drive gets fuller day by day, but do you know why? CleanApp 5 provides you with insights how to reclaim disk space. There are... Read more
Monolingual 1.6.2 - Remove unwanted OS X...
Monolingual is a program for removing unnecesary language resources from OS X, in order to reclaim several hundred megabytes of disk space. It requires a 64-bit capable Intel-based Mac and at least... Read more
NetShade 6.1 - Browse privately using an...
NetShade is an Internet security tool that conceals your IP address on the web. NetShade routes your Web connection through either a public anonymous proxy server, or one of NetShade's own dedicated... Read more
calibre 2.13 - Complete e-library manage...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Mellel 3.3.7 - Powerful word processor w...
Mellel is the leading word processor for OS X and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
ScreenFlow 5.0.1 - Create screen recordi...
Save 10% with the exclusive MacUpdate coupon code: AFMacUpdate10 Buy now! ScreenFlow is powerful, easy-to-use screencasting software for the Mac. With ScreenFlow you can record the contents of your... Read more
Simon 4.0 - Monitor changes and crashes...
Simon monitors websites and alerts you of crashes and changes. Select pages to monitor, choose your alert options, and customize your settings. Simon does the rest. Keep a watchful eye on your... Read more
BBEdit 11.0.2 - Powerful text and HTML e...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more

Latest Forum Discussions

See All

This Week at 148Apps: December 15-19, 20...
Happy Holidays from 148Apps!   How do you know what apps are worth your time and money? Just look to the review team at 148Apps. We sort through the chaos and find the apps you’re looking for. The ones we love become Editor’s Choice, standing out... | Read more »
New Version of Tempo Smart Calendar Help...
New Version of Tempo Smart Calendar Helps You Plan Your Day Without Opening the App Posted by Jessica Fisher on December 22nd, 2014 [ permalink ] | Read more »
Sparkle - Advanced Cross-Synthesis (Mus...
Sparkle - Advanced Cross-Synthesis 1.0 Device: iOS Universal Category: Music Price: $6.99, Version: 1.0 (iTunes) Description: Sparkle is a tool for advanced spectral hybridizations made of several algorithms that operate on frequency... | Read more »
DICETINY is coming to iOS in 2015
DICETINY is coming to iOS in 2015 Posted by Jessica Fisher on December 22nd, 2014 [ permalink ] Fakedice has announced that they’re bringing their digital board game DICETINY to iOS. | Read more »
It Came From Canada: The Witcher Battle...
The Witcher 3: Wild Hunt may still be a few months away, but very soon players will be able to get a new taste of the acclaimed Polish RPG on their mobile devices with The Witcher Battle Arena. While it trades open-world exploration for compact... | Read more »
The Babies Get Lost Again in the New Azt...
The Babies Get Lost Again in the New Aztec Ruins Update for Light in the Dark Posted by Jessica Fisher on December 22nd, 2014 [ permalink ] | Read more »
Living Room 3D for IKEA Makes All In-App...
Living Room 3D for IKEA Makes All In-App Purchases Free Until 2015 Posted by Jessica Fisher on December 22nd, 2014 [ permalink ] | Read more »
Crossbow Warrior – The Legend of William...
Crossbow Warrior – The Legend of William Tell Review By Lee Hamlet on December 22nd, 2014 Our Rating: :: MISSES THE MARKUniversal App - Designed for iPhone and iPad Crossbow Warrior details the entertaining adventures of legendary... | Read more »
A New Update Races onto Asphalt 8: Airbo...
A New Update Races onto Asphalt 8: Airborne Posted by Jessica Fisher on December 22nd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Workflow: Powerful Automation Made Simpl...
Workflow: Powerful Automation Made Simple Review By Campbell Bird on December 22nd, 2014 Our Rating: :: GO WITH THE FLOWUniversal App - Designed for iPhone and iPad This powerful app lets users accomplish multiple tasks at touch of... | Read more »

Price Scanner via MacPrices.net

13-inch 2.4GHz Retina MacBook Pro (Apple refu...
The Apple Store has previous-generation Apple Certified Refurbished 13″ 2.4GHz/128GB Retina MacBook Pros available for $999. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.4GHz/... Read more
Apple resellers offer free overnight shipping
The Apple Store is now offering free next-day shipping on all in stock items if ordered before 12/23/14 at 10:00am PT. Local store pickup is also available within an hour of ordering for any in stock... Read more
Holiday sales continue: MacBook Airs for up t...
 B&H Photo has 2014 MacBook Airs on sale for up to $120 off MSRP, for a limited time, for the Thanksgiving/Christmas Holiday shopping season. Shipping is free, and B&H charges NY sales tax... Read more
Holiday sale continues: 13-inch Retina MacBoo...
 B&H Photo has new 13″ MacBook Pros on sale for up to $150 off MSRP as part of their Holiday pricing. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.5GHz MacBook Pro: $979 save... Read more
Holiday sale continues: 15-inch Retina MacBoo...
 B&H Photo has the new 2014 15″ Retina MacBook Pros on sale for up to $300 off MSRP for a limited time. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.2GHz Retina MacBook Pro: $... Read more
Holiday sale: 13-inch 128GB MacBook Air for $...
 Best Buy has the 2014 13-inch 1.4GHz 128GB MacBook Air on sale for $849.99, or $150 off MSRP, on their online store. Choose free home shipping or free local store pickup (if available). Price valid... Read more
13-inch 2.6GHz Retina MacBook Pro on sale for...
Best Buy has lowered their price on the 2014 13″ 2.6GHz/128GB Retina MacBook Pro to $1149.99 on their online store for a limited time. That’s $150 off MSRP and the lowest price available for this... Read more
Kodak Returns to CES With New Consumer Produ...
Former photography colossus Kodak is returning to CES for the first time in three years where the Kodak booth (#21818 South Hall 1) will showcase a wide range of innovative, imaging-related products... Read more
Invaluable Launches New Eponymously -Named A...
Invaluable, the world’s largest online live auction marketplace, hhas announced the official launch of the Invaluable app for iPad, now available for download in the iTunes App Store. Invaluable... Read more
IDC Reveals Worldwide Mobile Enterprise Appli...
International Data Corporation (IDC) last week hosted the IDC FutureScape: Worldwide Mobile Enterprise Applications and Solutions 2015 Predictions Web conference. The session provided organizations... Read more

Jobs Board

*Apple* Store Leader Program (US) - Apple, I...
…Summary Learn and grow as you explore the art of leadership at the Apple Store. You'll master our retail business inside and out through training, hands-on experience, Read more
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.