TweetFollow Us on Twitter

Self Doc Scripts
Volume Number:6
Issue Number:6
Column Tag:HyperChat™

Almost Self Documenting Scripts

By Tom Trinko, Ph.D., Colleen Trino, Fremont, CA

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

Almost Self Documenting HyperTalk™ Scripts

[Tom Trinko, Ph.D., is working on advanced computing systems designs at LMSC. He has worked on machines ranging from PDP-11s to CDC 6600s. Colleen Trinko is currently a full-time mother and a part-time instructional designer at Apple.]

One problem we all have with code is remembering what it does and how it does it. If most of the code we generated were one shot throw-away stuff this wouldn’t be a concern. As the sheer amount of code we have to write increases, however, it becomes more and more difficult to start from scratch. A number of different ways of dealing with the problem have been developed for Mac programmers, such as Prototyper™ or Program Extender™ . The simplest technique is still recycling your own code. After all, you at least know you’ll eventually be able to figure it out!

HyperTalk™ is well structured to support code reuseabilty because of its pseudo object oriented construction. Once you’ve written a handler (on mouseup...end mouseup) to perform a certain function, say make visible all of the hidden objects in a card, there’s no reason you can’t use that same handler in all of your other stacks--or projects if you’re using SuperCard™. The difficulty we encounter is trying to remember which handlers are where and when you find a handler, remembering what it does.

One possible solution to this problem that we’ve developed is to place a description of what each handler does at the beginning of the handler. You could place it at the end of the handler to save a little processing time when the handler is executed but HyperCard really doesn’t take much time to skip over comments. An example handler is shown in Listing 1.

Listing 1:
function linechoosen loc
  --input  x,y location of the mouse click(use the clickloc)
  --output line number clicked on in a scrolling field
  -- This is a generally useful function which takes the clickloc as
  -- input and finds out which line in a scrolling field was clicked 
on
  put second item of loc into pos
  put pos - the top of the target into pos
  put pos + the scroll of the target into pos
  get the textsize of the target
  put it+trunc(it/3) into size
  put trunc(pos/size)+1 into linehit
  return linehit
end linechoosen

Now this is nice but it still doesn’t help you find where in your 5 Megabyte stack the handler you want resides. That’s where the scripts in Listing 2 come in handy. These scripts, when placed in a button, will do the following: (1) search through a stack and find all of the functions (function name...end name) and all of the handlers that reside in the stack, and (2) place the location, name and all comments that lie between the first line of the handler/function and the first executable line in the handler/function into two variables “functionlist” and “handlerlist”. These two variables are structured as shown in Figure 1. You can place the two variables in two scrolling fields for easy access.

Figure 1
STACK:linechoosen <-- address and name of function   line 1 of functionlist
  --input  x,y location of the mouse click(use the clickloc)
2 
  -- This is a generally useful function which takes the clickloc 
3  
  -- input and finds out which line in a scrolling field was clicked
4 
BKGND handler lists:findloc 
5

If you have a really big stack it might still take awhile to wade through all of the information returned so we’ve included two scripts, shown in Listings 3a and 3b, which let you search for keywords in the two fields and automatically scroll the fields to the line where the match was found. Once you’ve found the item of interest you can go directly to the script containing the handler if you put the scripts from listing 6 into the scrolling fields and the scripts from listing 5 into the background or card the scrolling field is in. Just click on the line containing the name of the handler or function you’re interested in and you will be taken to the edit window for that script.

Listing 4 contains some miscellaneous scripts that are required in the stack script. Note that the closestack, checkfreespace, and deletefield handlers are not required but they make life a little nicer. The redolist and popmenu handlers are used by the scripts which search through the stack and make the function and handler lists. The linechoosen function is used by the scripts in listing 6 but it can be used in any scrolling field to see what physical line the user has clicked on.

If you decide to use the scripts in listing 5 and 6, you must make sure that the address line for a function or handler does not occupy more than one physical line in the field you display it in. The distinction between physical and logical lines in a field is fairly simple. As an example suppose that line n of a variable is 80 characters long. If we put that variable into a field which is 60 characters wide then the logical line n of the variable will be shown on physical lines n and n+1. If however you use the fragment

   put line n of field x into temp

Temp will contain the full 80 characters. The reason this is important is that the scripts in listing 4 determine which physical line the mouse has been clicked in and then get that logical line to parse to find the identity of the object containing the script. So if logical line 8 occupies two physical lines then when the user clicks on physical line 24 he will get the wrong answer because logical line 23, not 24, actually contains what is displayed in line 24. This problem is avoided by clipping the length of the logical lines to be less than the physical field width. In the listings the field is assumed to be 75 characters wide. When you set up your card, check that your field is at least this wide. Note that you will not be able to access scripts whose address lines have been truncated because they will not have complete address information. On the other hand you will still be able to access the scripts of handlers displayed after those with names greater than 75 characters in length.

To give you a feel for what a card using these scripts could look like we’ve included a picture of the version we use in Figure 2.

Figure 2

We’ve used a popup menu XFCN as an interface in these scripts because it works well and is an unobtrusive interface. If you don’t have access to any of the several popup menu XFCN’s presently available you have a couple of simple options. You could add a few checkbox buttons to your card which correspond to the popup menu options, or implement a completely HyperTalk-based popup menu using the techniques described in the MacTutor article “Pop-up Menus in HyperTalk” by Joseph Bergin(Vol 4 #5 May 1988 pp85). Notice since the popup menu is always accessed through the function popmenu(in listing 4) you only have to change the call to the XFCN there in order to eliminate the need for the XFCN in the stack.

Please send any comments, bug reports, insults, etc. to

GEnie                                      T.Trinko
AppleLink                                  Trinko
MouseHole                                  TomT
Delphi                                     TTrinko
AppleLink Personal Edition     Trinko2
Listing 2:  This goes into a button labeled “Update”

on mousedown
  --This a mousedown handler so that the popupmenu can be used to let
  -- the user pick whether or not the listing should contain the
  -- comment lines immediately following the start of handlers and/or
  -- functions.
  global linesofcode   --contains the number of lines of HyperTalk
  global temphandlerlist,tempfunctionlist
  put 0 into linesofcode
  --set up the popupmenu
  put “With comments,Without comments” into list
  put the clickloc into loc
  --here we let the user decide whether or not comments will be displayed
  put popmenu(list,loc) into commentflag
  -- if the user cancels then exit
  if commentflag < 1 then exit mousedown
  --let the user know something is happening
  set the cursor to watch
  --clear the variables which will contain the lists
  put empty into handlerlist
  put empty into functionlist
  --start by looking throught the stack script
  put the script of this stack into temp
  add the number of lines in temp to linesofcode
  --get a list of the handlers & functions in the stack script
  findhandler temp,”STACK”,commentflag
  put temphandlerlist into handlerlist
  put tempfunctionlist into functionlist
  --here go through all of the background scripts
  repeat with i=1 to the number of backgrounds
    put the script of bkgnd i into temp
    --check to see if there is a script present in the bkgnd
    if temp is not empty then
      add the number of lines in temp to linesofcode
      --here set up the address
      put “BKGND “ & the short name of bkgnd i into name
      findhandler temp,name,commentflag
      put appendlist(temphandlerlist,handlerlist) into handlerlist
      put appendlist(tempfunctionlist,functionlist) into functionlist
    end if
  end repeat
  --here go through all of the card scripts
  repeat with i=1 to the number of cards
    put the script of card i into temp
    if temp is not empty then
      add the number of lines in temp to linesofcode
      put “CARD “ & the short name of card i into name
      findhandler temp,name,commentflag
      put appendlist(temphandlerlist,handlerlist) into handlerlist
      put appendlist(tempfunctionlist,functionlist) into functionlist
    end if
  end repeat
  --Now we have to actually go to the bkgnds and cards in order to
  -- access the object scripts.  By locking the screen we cut the
  -- processing time.
  set the lockscreen to true
  --Since we know we want to come back to this card pushing the
  --  card will save us a little time.
  push card
  repeat with j=1 to the number of backgrounds
    go to bkgnd j
    if the number of bkgnd fields > 0 then
      repeat with i=1 to the number of bkgnd fields
        put the script of bkgnd field i into temp
        if temp is not empty then
          add the number of lines in temp to linesofcode
          put “BKGND “ into name
          put the short name of bkgnd j  after name
          put “:FIELD “ after name
          put the short name of bkgnd field i after name
          findhandler temp,name,commentflag
          put appendlist(temphandlerlist,handlerlist) into handlerlist
          put appendlist(tempfunctionlist,functionlist) into functionlist
        end if
      end repeat
    end if
    if the number of bkgnd buttons > 0 then
      repeat with i=1 to the number of bkgnd buttons
        put the script of bkgnd button i into temp
        if temp is not empty then
          add the number of lines in temp to linesofcode
          put “BKGND “ into name
          put the short name of bkgnd j  after name
          put “:BUTTON “ after name
          put the short name of bkgnd button i after name
          findhandler temp,name,commentflag
          put appendlist(temphandlerlist,handlerlist) into handlerlist
          put appendlist(tempfunctionlist,functionlist) into functionlist
        end if
      end repeat
    end if
  end repeat
  repeat with j=1 to the number of cards
    go to card j
    if (commentflag < 3) or ((the short name of this bkgnd) is not “model 
space”) then
      if the number of card fields > 0 then
        repeat with i=1 to the number of card fields
          put the script of card field i into temp
          if temp is not empty then
            add the number of lines in temp to linesofcode
            put “CARD “ into name
            put the short name of card j  after name
            put “:FIELD “ after name
            put the short name of card field i after name
            findhandler temp,name,commentflag
            put appendlist(temphandlerlist,handlerlist) into handlerlist
            put appendlist(tempfunctionlist,functionlist) into functionlist
          end if
        end repeat
      end if
    end if
    if the number of card buttons > 0 then
      repeat with i=1 to the number of card buttons
        put the script of card button i into temp
        if temp is not empty then
          add the number of lines in temp to linesofcode
          put “CARD “ into name
          put the short name of card j  after name
          put “:BUTTON “ after name
          put the short name of card button i after name
          findhandler temp,name,commentflag
          put appendlist(temphandlerlist,handlerlist) into handlerlist
          put appendlist(tempfunctionlist,functionlist) into functionlist
        end if
      end repeat
    end if
  end repeat
  --here we return to the original card
  pop card
  set the scroll of bkgnd field “handler” to 0
  put handlerlist into bkgnd field “handler”
  set the scroll of bkgnd  field “functions” to 0
  put functionlist into bkgnd field “functions”
  put “This stack contains “ & linesofcode & “ lines of code(including 
comments)” into message
end mousedown
on findhandler temp,source,commentflag
  --inputs  a script,an address,< 2 --> list comments
  --output  a list containing the first line of each handler and if
  --        commentflag <2 the comment lines imediately following the
  --        first line in the handler in global variable temphandlerlist
  --        a list of the functions in global variable tempfunctionlist
  global temphandlerlist,tempfunctionlist
  put 0 into numhandlers
  put 0 into numfunctions
  put empty into temphandlerlist
  put empty into tempfunctionlist
  repeat with i=1 to the number of lines in temp
    --check to see if the lines starts a handler
    if word 1 of line i of temp is “on” then
      add 1 to numhandlers
      put source & “:” &word 2 of line i of temp into temp1
      --make sure the line fits in the field.  NOTE: if you change
      -- the field width and/or font you should change the 75 to the
      -- appropriate value.  This is necessary because if the address 
of a function or
      -- handler takes up more than one line in the field it will cause 
problems.
      put char 1 to 75 of temp1 into line numhandlers of temphandlerlist
      --if the user wants the comments listed
      if commentflag < 2 then
        --a repeat forever might be faster but you could get an error 
if
        -- a script ended with an unfinished handler
        repeat with k=1 to the number of lines in temp
          if char 3 of line i+k of temp is “-” then
            add 1 to numhandlers
            put char 1 to 75 of line i+k of temp into line numhandlers 
of temphandlerlist
          else
            exit repeat
          end if
        end repeat
      end if
      -- here we deal with the functions
    else if word 1 of line i of temp is “function” then
      add 1 to numfunctions
      put source & “:” & word 2 of line i of temp into temp1
      --if you change the width of the field or the font size you
      -- should change the number 75 as well
      put char 1 to 75 of temp1 into line numfunctions of tempfunctionlist
      if commentflag < 2 then
        repeat with k=1 to 100
          if char 3 of line i+k of temp is “-” then
            add 1 to numfunctions
            put char 1 to 75 of line i+k of temp into line numfunctions 
of tempfunctionlist
          else
            exit repeat
          end if
        end repeat
      end if
    end if
  end repeat
end findhandler

function appendlist newlist,oldlist
  -- input list 1,list 2(both lists are line ordered)
  -- output list 2 with list 1 appended afterwards
  put the number of lines in newlist into nlines
  put the number of lines in oldlist into start
  repeat with i=start+1 to (start+nlines)
    put line i-start of newlist into line i of oldlist
  end repeat
  return oldlist
end appendlist
Listing 3a:  This belongs in a button labeled “Find String”
on mousedown
  --This is a mousedown handler to allow the use of the popup menu
  global lastfoundline,lastfoundchar,findstring,commentflag,fieldname
  put “Handlers,Functions,Both,Cancel” into list
  put the clickloc into loc
  put popmenu(list,loc) into commentflag
  --exit if the user didn’t make a selection or he selected “Cancel”
  if commentflag < 1 or commentflag = the number of items in list¬
  then exit mousedown
  put empty into lastfoundline
  put empty into lastfoundchar
  put empty into findstring
  ask “Enter the string to find”
  --Continue only if the user didn’t cancel or not enter a string
  if it is not empty then
    put it into findstring
    -- let the user know something is going on
    set the cursor to watch
    if commentflag = 1 or commentflag =3 then
      put bkgnd field “handler” into temp1
      put  findloc(temp1,findstring) into temp2
      --if a match was found
      if temp2 is not empty then
        put item 1 of temp2 into lastfoundline
        put item 2 of temp2 into lastfoundchar
        --scroll the field to show the match
        put getscrollline(lastfoundline,”bkgnd field handler”) into scroll
        set the scroll of bkgnd field “handler” to scroll
        --select the line with the match so it appears in inverse
        select line lastfoundline of bkgnd field “handler”
        put “handler” into fieldname
        exit mousedown
      end if
    end if
    --if the user wanted only functions or both searched
    if commentflag > 1 then
      put bkgnd field “functions” into temp1
      put  findloc(temp1,findstring) into temp2
      if temp2 is not empty then
        put item 1 of temp2 into lastfoundline
        put item 2 of temp2 into lastfoundchar
        put getscrollline(lastfoundline,”bkgnd field functions”) into 
scroll
        set the scroll of bkgnd field “functions” to scroll
        select line lastfoundline of bkgnd field “functions”
        put “functions” into fieldname
        exit mousedown
      end if
    end if
  end if
  put “Sorry the string was not found” into message
end mousedown
Listing 3b:  This goes in a button labeled “Find Next”

on mouseUp
  global lastfoundline,lastfoundchar,findstring,commentflag,fieldname
  --let the user know something is going on
  set the cursor to watch
  if (commentflag = 1 or commentflag =3) and fieldname = “handler” then
    --search the rest of the field after the last match for the next
    --match
    put line lastfoundline + 1 to (the number of lines in bkgnd field¬
    “handler”) of bkgnd field “handler” into temp1
    put  findloc(temp1,findstring) into temp2
    if temp2 is not empty then
      add item 1 of temp2 to lastfoundline
      put getscrollline(lastfoundline,”bkgnd field handler”) into scroll
      set the scroll of bkgnd field “handler” to scroll
      select line lastfoundline of bkgnd field “handler”
      exit mouseup
    end if
  end if
  if commentflag > 1 then
    put line lastfoundline + 1 to (the number of lines in bkgnd field¬
    “functions”) of bkgnd field “functions” into temp1
    put  findloc(temp1,findstring) into temp2
    if temp2 is not empty then
      add item 1 of temp2 to lastfoundline
      put item 2 of temp2 into lastfoundchar
      put getscrollline(lastfoundline,”bkgnd field functions”) into scroll
      set the scroll of bkgnd field “functions” to scroll
      select line lastfoundline of bkgnd field “functions”
      exit mouseup
    end if
  end if
  beep
  put “Sorry.  No other match found.”
end mouseUp
Listing 4:  These handlers go into the stack script

on closestack
  -- when leaving check to see if you should do garbage collection
  -- if there is more than 15k free then compact the stack
  checkfreespace
end closestack
function popmenu list,loc
  -- input: list of options,location of menu
  -- output: number of menu item picked 0 if none or cancel
  -- this takes a list of options,and a menu location and displays
  -- a menu.  It also checks to see if the user picks the cancel option
  if the number of items in list < 1 then
    put “Cancel” into list
  end if
  put ((the number of items in list) + 10) into nlist
  put redolist (list) into list
  put item 1 of  loc+50 into h
  put item 2 of  loc+50 into v
  -- This is Andrew Gilmartins Popup Menu XFCN
  get PopUpMenu(list,nlist, v, h)
  if it is 0 then
    put “You must hold the mouse button down on this button to see the 
menu”
  end if
  return it
end popmenu
function redolist list
  --input list in format “a,b,c,d”
  --output list in format “a;b;c;d”
  -- this just reformats the list for popupmenu to use “;” as the
  -- item seperator not “,”
  put empty into newlist
  repeat with x=1 to the number of items in list
    put item x of list & “;” after newlist
  end repeat
  return newlist
end redolist
on deleteField
  -- this protects you against accidentilly deleting a field
  answer “Do you really want to delete this Field?” with “ok” or “No 
Way!”
  if it is not “ok” then
    click at “999,999”
    exit deletefield
  else
    checkfreespace
    pass deletefield
  end if
end deletefield
function linechoosen loc
  --input  x,y location of the mouse click(use the clickloc)
  -- This is a generally useful function which takes the clickloc as
  -- input and finds out which line in a scrolling field was clicked 
on
  put second item of loc into pos
  put pos - the top of the target into pos
  put pos + the scroll of the target into pos
  get the textsize of the target
  put it+trunc(it/3) into size
  put trunc(pos/size)+1 into linehit
  return linehit
end linechoosen
on checkfreespace
  -- This checks on the amount of garbage needing collecting
  get the freesize of this stack
  if it > 15000 then
    put “Please wait,I’m doing some garbage collection” into message
    domenu “compact stack”
    hide message
  end if
end checkfreespace

Listing 5:  These go into the bkgnd and are used by the scripts in the 
two 
     scrolling fields to get the identity of the script that should be
     edited

function finditemname temp
  --input  a string
  --output the address of the handler/function defined in that line
  --        if the line doesn’t contain such an address empty is returned
  put empty into address
  put offset(“:”,temp) into colon1
  -- if the line doesn’t contain a : it is not a valid line
  if colon1 < 1 then
    return address
    exit finditemname
  else
    --here get rid of everything prior to the address
    put findsegment(temp) into temp1
    put item 2 of temp1 into temp
    --here loop over the address segments
    -- the first segment will be the actual object and the second will
    -- be the card or bkgnd that its in.
    repeat with i=1 to 2
      put findsegment(temp) into temp1
      put item 1 of temp1 into tempaddress
      -- if the item is in the stack card or bkgnd script go right to 
it
      if tempaddress is “stack” and i=1 then
        put “this stack” into address
        return address
        exit finditemname
      else if word 1 of tempaddress is “bkgnd” and i=1 then
        put insertquotes(tempaddress) into address
        return address
        exit finditemname
      else if word 1 of tempaddress is “card” and i=1 then
        put insertquotes(tempaddress) into address
        return address
        exit finditemname
      else
        if i=1 then
          put insertquotes(tempaddress) into item 1 of address
        else
          put insertquotes(tempaddress) into item 2 of address
          if word 1 of tempaddress is “bkgnd” then
            put “bkgnd “  before item 1 of address
          end if
        end if
      end if
      put item 2 of temp1 into temp
    end repeat
    return address
  end if
end finditemname
function insertquotes tempaddress
  --input  string
  --output string with quotes around all but first word
  put the number of words in tempaddress into temp
  put 1 into start
  if word 1 of tempaddress is word 2 of tempaddress then
    put 2 into start
  end if
  put word start of tempaddress  into tempadd
  repeat with k=start+1 to temp
    put “ “ after tempadd
    if start is 1 and k is (start+1) then
      put quote after tempadd
    end if
    put  word k of tempaddress after tempadd
  end repeat
  if start = 1 then
    put quote after tempadd
  end if
  return tempadd
end insertquotes
function findsegment temp
  --input a string
  --output segment after last colon,segment before last colon
  put the number of chars in temp into len
  repeat with i=len down to 1
    if char i of temp is “:” then
      put char (i+1) to len of temp into segment
      put char 1 to i-1 of temp into item 2 of segment
      return segment
      exit findsegment
    end if
  end repeat
  return temp
end findsegment
Listing 6:  This goes into the script for the two scrolling fields
on mouseup
  global hit,temp,address
  put the clickloc into loc
  put linechoosen(loc) into hit
  put line hit of bkgnd field “handler” into temp
  --get the address of the object(card button “test” of card “huh?”)
  put finditemname(temp) into address
  if address is empty then
    put “Sorry. This line doesn’t contain the name of an object.”
    exit mouseup
  end if
  --addresses are of two types those that work from anywhere
  --”edit the script of this stack” for example or those that only
  --work in a bkgnd or card such as “edit the script of button “test””
  if item 2 of address is  empty then
    edit the script of address
  else
    go to (item 2 of address)
    edit the script of item 1 of address
  end if
end mouseup

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Tor Browser 12.5.5 - Anonymize Web brows...
Using Tor Browser you can protect yourself against tracking, surveillance, and censorship. Tor was originally designed, implemented, and deployed as a third-generation onion-routing project of the U.... Read more
Malwarebytes 4.21.9.5141 - Adware remova...
Malwarebytes (was AdwareMedic) helps you get your Mac experience back. Malwarebytes scans for and removes code that degrades system performance or attacks your system. Making your Mac once again your... Read more
TinkerTool 9.5 - Expanded preference set...
TinkerTool is an application that gives you access to additional preference settings Apple has built into Mac OS X. This allows to activate hidden features in the operating system and in some of the... Read more
Paragon NTFS 15.11.839 - Provides full r...
Paragon NTFS breaks down the barriers between Windows and macOS. Paragon NTFS effectively solves the communication problems between the Mac system and NTFS. Write, edit, copy, move, delete files on... Read more
Apple Safari 17 - Apple's Web brows...
Apple Safari is Apple's web browser that comes bundled with the most recent macOS. Safari is faster and more energy efficient than other browsers, so sites are more responsive and your notebook... Read more
Firefox 118.0 - Fast, safe Web browser.
Firefox offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and casual... Read more
ClamXAV 3.6.1 - Virus checker based on C...
ClamXAV is a popular virus checker for OS X. Time to take control ClamXAV keeps threats at bay and puts you firmly in charge of your Mac’s security. Scan a specific file or your entire hard drive.... Read more
SuperDuper! 3.8 - Advanced disk cloning/...
SuperDuper! is an advanced, yet easy to use disk copying program. It can, of course, make a straight copy, or "clone" - useful when you want to move all your data from one machine to another, or do a... Read more
Alfred 5.1.3 - Quick launcher for apps a...
Alfred is an award-winning productivity application for OS X. Alfred saves you time when you search for files online or on your Mac. Be more productive with hotkeys, keywords, and file actions at... Read more
Sketch 98.3 - Design app for UX/UI for i...
Sketch is an innovative and fresh look at vector drawing. Its intentionally minimalist design is based upon a drawing space of unlimited size and layers, free of palettes, panels, menus, windows, and... Read more

Latest Forum Discussions

See All

Listener Emails and the iPhone 15! – The...
In this week’s episode of The TouchArcade Show we finally get to a backlog of emails that have been hanging out in our inbox for, oh, about a month or so. We love getting emails as they always lead to interesting discussion about a variety of topics... | Read more »
TouchArcade Game of the Week: ‘Cypher 00...
This doesn’t happen too often, but occasionally there will be an Apple Arcade game that I adore so much I just have to pick it as the Game of the Week. Well, here we are, and Cypher 007 is one of those games. The big key point here is that Cypher... | Read more »
SwitchArcade Round-Up: ‘EA Sports FC 24’...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for September 29th, 2023. In today’s article, we’ve got a ton of news to go over. Just a lot going on today, I suppose. After that, there are quite a few new releases to look at... | Read more »
‘Storyteller’ Mobile Review – Perfect fo...
I first played Daniel Benmergui’s Storyteller (Free) through its Nintendo Switch and Steam releases. Read my original review of it here. Since then, a lot of friends who played the game enjoyed it, but thought it was overpriced given the short... | Read more »
An Interview with the Legendary Yu Suzuk...
One of the cool things about my job is that every once in a while, I get to talk to the people behind the games. It’s always a pleasure. Well, today we have a really special one for you, dear friends. Mr. Yu Suzuki of Ys Net, the force behind such... | Read more »
New ‘Marvel Snap’ Update Has Balance Adj...
As we wait for the information on the new season to drop, we shall have to content ourselves with looking at the latest update to Marvel Snap (Free). It’s just a balance update, but it makes some very big changes that combined with the arrival of... | Read more »
‘Honkai Star Rail’ Version 1.4 Update Re...
At Sony’s recently-aired presentation, HoYoverse announced the Honkai Star Rail (Free) PS5 release date. Most people speculated that the next major update would arrive alongside the PS5 release. | Read more »
‘Omniheroes’ Major Update “Tide’s Cadenc...
What secrets do the depths of the sea hold? Omniheroes is revealing the mysteries of the deep with its latest “Tide’s Cadence" update, where you can look forward to scoring a free Valkyrie and limited skin among other login rewards like the 2nd... | Read more »
Recruit yourself some run-and-gun royalt...
It is always nice to see the return of a series that has lost a bit of its global staying power, and thanks to Lilith Games' latest collaboration, Warpath will be playing host the the run-and-gun legend that is Metal Slug 3. [Read more] | Read more »
‘The Elder Scrolls: Castles’ Is Availabl...
Back when Fallout Shelter (Free) released on mobile, and eventually hit consoles and PC, I didn’t think it would lead to something similar for The Elder Scrolls, but here we are. The Elder Scrolls: Castles is a new simulation game from Bethesda... | Read more »

Price Scanner via MacPrices.net

Clearance M1 Max Mac Studio available today a...
Apple has clearance M1 Max Mac Studios available in their Certified Refurbished store for $270 off original MSRP. Each Mac Studio comes with Apple’s one-year warranty, and shipping is free: – Mac... Read more
Apple continues to offer 24-inch iMacs for up...
Apple has a full range of 24-inch M1 iMacs available today in their Certified Refurbished store. Models are available starting at only $1099 and range up to $260 off original MSRP. Each iMac is in... Read more
Final weekend for Apple’s 2023 Back to School...
This is the final weekend for Apple’s Back to School Promotion 2023. It remains active until Monday, October 2nd. Education customers receive a free $150 Apple Gift Card with the purchase of a new... Read more
Apple drops prices on refurbished 13-inch M2...
Apple has dropped prices on standard-configuration 13″ M2 MacBook Pros, Certified Refurbished, to as low as $1099 and ranging up to $230 off MSRP. These are the cheapest 13″ M2 MacBook Pros for sale... Read more
14-inch M2 Max MacBook Pro on sale for $300 o...
B&H Photo has the Space Gray 14″ 30-Core GPU M2 Max MacBook Pro in stock and on sale today for $2799 including free 1-2 day shipping. Their price is $300 off Apple’s MSRP, and it’s the lowest... Read more
Apple is now selling Certified Refurbished M2...
Apple has added a full line of standard-configuration M2 Max and M2 Ultra Mac Studios available in their Certified Refurbished section starting at only $1699 and ranging up to $600 off MSRP. Each Mac... Read more
New sale: 13-inch M2 MacBook Airs starting at...
B&H Photo has 13″ MacBook Airs with M2 CPUs in stock today and on sale for $200 off Apple’s MSRP with prices available starting at only $899. Free 1-2 day delivery is available to most US... Read more
Apple has all 15-inch M2 MacBook Airs in stoc...
Apple has Certified Refurbished 15″ M2 MacBook Airs in stock today starting at only $1099 and ranging up to $230 off MSRP. These are the cheapest M2-powered 15″ MacBook Airs for sale today at Apple.... Read more
In stock: Clearance M1 Ultra Mac Studios for...
Apple has clearance M1 Ultra Mac Studios available in their Certified Refurbished store for $540 off original MSRP. Each Mac Studio comes with Apple’s one-year warranty, and shipping is free: – Mac... Read more
Back on sale: Apple’s M2 Mac minis for $100 o...
B&H Photo has Apple’s M2-powered Mac minis back in stock and on sale today for $100 off MSRP. Free 1-2 day shipping is available for most US addresses: – Mac mini M2/256GB SSD: $499, save $100 –... Read more

Jobs Board

Licensed Dental Hygienist - *Apple* River -...
Park Dental Apple River in Somerset, WI is seeking a compassionate, professional Dental Hygienist to join our team-oriented practice. COMPETITIVE PAY AND SIGN-ON Read more
Sublease Associate Optometrist- *Apple* Val...
Sublease Associate Optometrist- Apple Valley, CA- Target Optical Date: Sep 30, 2023 Brand: Target Optical Location: Apple Valley, CA, US, 92307 **Requisition Read more
*Apple* / Mac Administrator - JAMF - Amentum...
Amentum is seeking an ** Apple / Mac Administrator - JAMF** to provide support with the Apple Ecosystem to include hardware and software to join our team and Read more
Child Care Teacher - Glenda Drive/ *Apple* V...
Child Care Teacher - Glenda Drive/ Apple ValleyTeacher Share by Email Share on LinkedIn Share on Twitter Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.