TweetFollow Us on Twitter

Extend Excel
Volume Number:6
Issue Number:1
Column Tag:Intermediate Mac'ing

Extending Excel

By Vincent Parsons, Austin, TX

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

Vincent Parsons is a junior in the Science Academy at LBJ High School in Austin, Texas. He has experience in MacApp, HyperCard, SuperCard, and C, and when he’s not in school or programming, he runs a Role Playing Game Bulletin Board System. He would appreciate feedback on this article and would like to hear from anyone having success implementing DLLs. He can be reached at AppleLink D1977.

A Little History

In November of 1988, an associate of mine attended the Microsoft Excel Developers Conference. He returned with news that users of Excel for Windows 2.1 (and Excel 2.2 for the Macintosh at its release) have the ability to extend Excel using Dynamic Link Libraries (DLLs). DLLs are dynamically linked external functions that can be called directly from Excel macros.

The introduction of DLLs on the Mac opens up new markets for Macintosh programmers, letting them use the Macintosh’s superior development environments, and then with very little effort bring the same products to the MSDOS environment. For this reason, I am discussing development of DLLs for Windows in conjunction with development of DLLs on the Macintosh.

Microsoft Blues

I began investigating how to implement DLLs using the documentation my associate had received at the conference. Soon I had written several very simple DLLs for Windows. To my surprise very few worked correctly (two even crashed Windows). After much correspondence with Microsoft Technical Support, who informed me that my problems were due to bugs internal to Excel, I concluded that much of Microsoft’s documentation on DLLs was incorrect.

I began using a trial subscription of Microsoft OnLine, Microsoft’s technical support service. While response turn-around was usually fast, all too often the answer was unacceptable. Answers were typically an acknowledgement that the problem was internal to Excel. In fact, I was unable get a definite commitment that the problems would be fixed within a reasonable time period (‘the next release’ is not satisfactory), nor did Microsoft provide any work-arounds for Excel’s problems. When asked about programming DLLs for Macintosh Excel 2.2 (in beta test at that time), they stated that technical support could not support unreleased products. My feeling is that, at least for this project, the $600 fee for one year of support would not have been justified. When compared to Apple’s excellent technical support provided through AppleLink (at a similar yearly rate), Microsoft’s technical support has a long way to go to reach the standards Macintosh programmers expect.

Since I was reporting bugs, sending corrections to their documentation, and getting little true support, I suggested that they send me an Excel T-Shirt as some compensation for my toil. After some ribbing, Technical Support finally responded telling me that since they currently didn’t have a T-Shirt program they would pass the suggestion on to a supervisor.

When Macintosh Excel 2.2 was released, I was appalled to discover that the documentation for it was incorrect also. In fact, the Macintosh version of the Functions and Macros manual refers to those arcane MSDOS far pointers!

Actually, most forms of DLLs do work, but not as documented in the published manuals. In this article, I will document how to implement DLLs in both the Macintosh and Windows environments using as much common source code as possible.

So What Are They Really?

DLLs on the Macintosh are very similar to HyperCard’s XFCNs. They are CODE resources in their own type of file. The main difference between DLLs and XFCNs is that Excel DLLs have no call-back routines -- the only data to which the DLL has access is what was passed to it. DLLs don’t have access to conversion routines such as those in HyperCard.

Nearly anything thing modal can be done using DLLs. Custom functions can be created giving Excel increased functionality. An example of this is complex arithmetic. DLLs also have full access to the Macintosh or Windows toolbox. The possibilities are endless.

The Excel Side

There are three macro functions that Excel uses to access DLLs -- Register, Call, and Unregister. For an example of a macro (SampAAA, discussed later), see figure 1. The Register function for the sample macro is contained in cell A2. The full macro and spread sheets are included on the source disk.

• Register

The Register function loads the DLL’s code into memory. The syntax of Register for Excel for the Macintosh is:

/* 1 */

Register(file_name, resource_name, argument_text)

or for Excel for Windows:

Register(file_name, function_name, argument_text)

The file_name is the name of the file containing the DLL code resources. On the Macintosh, resource_name is the name of the CODE resource of the DLL you wish to execute. Under Windows, however, function_name is the name of the exported function of the DLL. The argument_text specifies the number and data types of the arguments to the function and the data type of the return value. The argument_text is a series of letter codes A-K. The letters A-K specify different data types (see figures 2 and 3). The first letter of the argument_text determines the return value data type of the function. All following letters are argument data types to be passed to the DLL at execution. The Register function returns an ASCII representation of the address of the DLL code with the argument_text appended to the end. For example, the following Register function would open a file named “SampDLLs”, load the CODE resource named “SampAAA” into memory, and, when executed, would be passed two Booleans (type A) and return a Boolean:

`2
=Register(“SampDLLs”,“SampAAA”,“ AAA”)

• Call

The Call function executes the DLL code contained in the memory allocated by the Register function. The syntax of the Call function is:

`3
Call(register_return_value, argument1,  )

The register_return_value is a reference to the return-value of the Register function. Is is possible, though it is not recommended, to put the Register function inside the Call function instead of using a reference. There are several reasons not to use this technique: it makes execution slower if that DLL is to be executed more than once, it makes the Unregister function useless, and it is bad memory management. The arguments are the values to be passed to the DLL. For example, the following Call function calls the DLL defined in the previous Register example (contained in cell A2 of the macro sheet):

`4
=Call(A2, true, false)

or

`5
=Call(Register(“SampDLLs”,“SampAAA”,“AAA”),true,false)

• Unregister

The Unregister function releases the memory allocated by the Register function. The Unregister function is not a part of Excel for Window 2.1, so, if you’re developing DLLs on both platforms, don’t put Unregister in your macro sheets on the Windows version. The reason for using the Unregister function is for memory management. You should unregister any DLLs that you are done with -- it is a good idea to put the Unregister functions in an auto-close autoexecing macro. The syntax of Unregister is:

`6

Unregister(register_return_value)

The register_return_ value is the same as that for the Call function. For example, 
the following Unregister function releases the memory allocated by the previous Register 
example (contained in cell A2 of the macro sheet).

`7

=Unregister(A2) 

• Macro Sheet Tips

Since Excel documents have the same file format for both the Macintosh and Windows, creating multi-platform macro sheets is easy. Since the file formats are the same, if you make your macro sheets have the extension .XLM, your spread sheets the extension .XLS, and your workspace documents the extension of .XLW, conversion becomes as easy as copying your Excel documents to a PC disk. Remember, if your DLLs are to be used under Windows, be sure to omit the Unregister function from the macro sheet.

Programming DLLs

I will discuss developing DLLs using three development environments: MPW C 3.0 and THINK C 4.0 for the Macintosh, and Microsoft C 5.1 for MSDOS. Programming DLLs is done differently for each of these development systems. For the same source code to be used, conditional compiling becomes necessary. To implement the conditional compiles, I used the predefined preprocessor symbols THINK_C (for THINK C 4.0), applec (for MPW C 3.0), and MSDOS (for Microsoft C 5.1). I will discuss the required differences in the following sections.

• THINK C 4.0

THINK C 4.0 has advantages and disadvantages for creating DLLs. The biggest disadvantage is that each DLL requires its own project. One advantage, however, is that THINK C, unlike MPW C, allows the use of global variables (don’t forget to call RememberA0, SetUpA4, and RestoreA4). Unlike MPW and Microsoft C which define a 64-bit float to be a double, THINK C defines it as a short double. For portability reasons, it is necessary to define a double64 (see the header file DLL.h).

Another difference is that since THINK C automatically includes many standard precompiled headers, #include statements usually aren’t necessary. One inconvenience is that entry points must be named main. In MPW C, for example, the entry point can be set to any function. Also, the code resources created by THINK C are 1 1/2 to 2 times larger than those created by MPW C.

After creating your project, select Set Project Type from the Project menu, and THINK C will open a dialog (see figure 4). DLLs are code resources of type ‘CODE’, the file type and creator need to be set to ‘XLLB’ and ‘XCEL’ respectively, and Microsoft suggests that the purgeable attribute be set (20 hex). Finally set the name for the DLL and choose a unique resource ID.

Note to users of THINK C 3.1:

Since THINK C 3.1 doesn’t have the ability to put a newly created code resource into an existing file, combining DLLs into one file requires the use of ResEdit. Also, for compatibility reasons, the THINK C portions of the source code use old style function declarations since THINK C 3.1 does not support new style function declarations.

• MPW C 3.0

If you plan to develop a library of DLLs for the Macintosh, MPW C 3.0 is by far the best development environment for such a task. Although globals are not allowed when building code resources with the MPW linker, MPW has many advantages. First, using one make file, you can automatically build your entire library of DLLs and put them into the same file (or different files) in one step without using ResEdit. Also, due to MPW C’s ability to define the entry point of the CODE resource to be any function, the DLL functions don’t all need to be named main. Since MPW C doesn’t automatically include standard headers, Types.h at minimum must be included.

Certain compile and link options are very important when creating DLLs (see SampDLLs.make). When compiling, be sure to use the -b option if you use any string or floating-point constants. This is because MPW C normally stores string and floating-point constants in the global data area, and when compiling DLLs with MPW C, there isn’t a global data area. Use the -t and -c options to set the file type to ‘XLLB’ and the creator to ‘XCEL’. Though it is not required, it is a good idea to use the -ra option to set the resource’s purgeable attribute. The -sg option lets you name the resource (this name is used in the Register function), and the -rt option lets you set the resource type (CODE) and a unique resource ID. Also, when linking DLLs, the -m option must be used to set the entry point. Since DLLs are declared as pascal-style functions, remember to put the function name after the -m option in all capital letters. Finally, use the -o option to define the object file be used.

• Microsoft C 5.1

Microsoft C 5.1 is the DOS compiler I used to create DLLs. DLLs for Windows are executable files (.exe extension) that contain one or more entry points. In addition to a make file (See SAMPDLLS.MAK), Microsoft C requires a module definition file (See SAMPDLLS.DEF).

In the definition file, several module statements are required. The LIBRARY statement provides the name for the library of DLLs. The DESCRIPTION string is often useful for embedding source-control or copyright information, though any ASCII string is allowed. The STUB statement sets the program to be executed if the DLL is executed outside of Windows. WINSTUB.EXE simply displays the string “This program requires Microsoft Windows,” and then quits. Set the CODE statement to MOVEABLE. This allows Windows to perform memory management better. Set the DATA statement to FIXED SINGLE. Since many of the argument types are passed as pointers, moving the data segment would make the pointers invalid. DLLs require a single data segment. The HEAPSIZE module statement sets the local heap size. The maximum heap size is 65,536 bytes. For most simple DLLs, 4096 bytes is satisfactory. The STACKSIZE module statement sets the size of the local stack. Since DLLs use Excel’s stack, be sure to set this value to 0. After the Exports statement, list all the DLL functions by name.

The make file executes four programs: implib (the library importer), cl (the Microsoft C compiler/linker), lib (library manager), and link4 (the Windows linker). The backslash (\) is the Microsoft’s make file continuation character. Implib converts the definition file into an import library needed for link4.

Several options are used with the Microsoft C compiler/linker. The -c option tells the compiler to create only object files, and not do any linking. This is because link4 must be used to link DLLs. The /D option defines the THINK_C and applec preprocessor symbols to false. The -Gs option removes stack probes, and the -As and -An options tell the compiler to use the small memory model and to use near pointers. The options -Gw and -Aw are required for Windows.

Since MSDOS allows command lines to be only 128 characters, it was necessary to combine the object files into two libraries, and then to link those libraries. If only a few object files are being linked, building the libraries is not required.

It is necessary to use the /a:16 option with link4. This aligns the code on word boundaries. The /NOE option prevents link4 from searching the libraries extended dictionary. The files win87em, swindlibc, and slibw are library files that need to be linked with the DLL. The extra comma is a placeholder for a map file. Finally, in order to do any development of DLLs with Microsoft C, Microsoft C 5.1 and the latest Microsoft Windows Software Development Kit need to be obtained.

Sample DLLs

I have provided several sample DLLs demonstrating all of the argument data types and various techniques. All of the samples will compile under either MPW C 3.0 or THINK C 4.0, and nearly all will also compile under Microsoft C 5.1. Most of the samples’ names end with the argument_text used for the Register function.

• SampAAA

The SampAAA DLL demonstrates the use of Boolean arguments. Booleans in DLLs are unsigned shorts -- zero if false, any other number if true. The function of this DLL is to return the logical AND of the two Boolean values passed in.

• SampBBB

The SampBBB DLL demonstrates the use of type B (double64) arguments. On the Macintosh, type B is passed as a pointer to a double64, and returns a pointer to a double64. Under Windows, type B is passed as a double64 value, and returns a far pointer to a double64. The reason for the difference is that the pascal convention on the Macintosh is to pass a pointer for anything larger than four bytes. The function of this DLL is to return the double64 product of the two double64s passed in.

Under Windows, a static double64 variable (answer) is allocated on the stack and is available to Excel after the completion of the DLL. Since statics are not allowed on the Macintosh, the answer is put into the area pointed to by one of the input parameters. When the parameter is returned, the pointer is still valid, giving Excel access to the return value. For this reason, type B return values are only possible on the Macintosh if you have a type B input parameter.

• SampCC and SampDD

The SampCC and SampDD DLLs demonstrate the use of type C (zero-terminated string) and type D (byte-count string) arguments. On the Macintosh, type C and D are passed in and out as a char *. Under Windows, type C and D are passed in and out as a char far *. The function of these two DLLs is to switch the case of each character of the input string and return the modified string to Excel.

• SampEIIE

The SampEIIE DLL demonstrates the use of type E (64-bit floating-point number buffer) arguments. The type E data type is only useful for return values. For a return value of type E, it is required to have a input value of type E. The input type E is also used to allocate Excel memory to hold the output value -- whatever is passed in the Call function is ignored. On the Macintosh, type E is passed as a pointer to a double64, and returns a pointer to a double64. Under Windows, type E is passed as a pointer to a double64 value, and returns a double64. The function of the DLL is to return the quotient of the two shorts (type I, see below) passed in.

• SampFHF and SampGHG

The SampFHF and SampGHG DLLs demonstrate the use of type F (zero-terminated string) and type G (byte-count string) argument types. The type F and G data types are only useful for return values. For a return value of type F or G, it is required to have a input value of type F or G. The input types F and G are used to allocate Excel memory to hold the output value -- whatever is passed in the Call function is ignored. On the Macintosh, types F and G are passed to and from the DLL as a char *. Under Windows, types F and G are passed as a char far *. The function of the DLL is to return a hex representation of the unsigned short (type H, see below) passed in.

• SampHHH

The SampHHH DLL demonstrates the use of type H (unsigned short -- a 16-bit integer) argument type. Type H is passed to and returned on both the Macintosh and under Windows as an unsigned short. The function of the DLL is to return the product of the two unsigned shorts passed in.

• SampIII

The SampIII DLL demonstrates the use of type I (short -- a 16-bit integer) argument type. Type I is passed to and returned on both the Macintosh and under Windows as a short. The function of the DLL is to return the product of the two shorts passed in.

• SampJJ

The SampJJ DLL demonstrates the use of the type J (unsigned long -- a 32-bit integer) argument type. Type J is passed to and returned from the DLL on both the Macintosh and under Windows as an unsigned long. The function of the DLL is to return the lower 16 bits of the unsigned long passed in.

• SampKKK

The SampKKK DLL demonstrates the use of the type K (floating-point array) argument type. On the Macintosh, type K is passed to and from the DLL as a pointer to the following structure:

/* 8 */

typedef struct fp {
 unsigned short rows;
 unsigned short columns;
 double64 array[n];
} FP;

/* The first short contains number of rows,     */
/* the second short contains number of columns. */
/* These are followed by rows times columns of  */
/* IEEE double64s.                              */

Under Windows, type K is passed to and from the DLL as a far pointer to a structure (see above). The function of this DLL is to input two complex numbers (1x2 arrays) and return their product.

• Flash

My final sample that works both in the Macintosh and under Windows is a DLL version of our favorite sample XCMD, Flash. Flash demonstrates the use of using toolbox functions in both the Macintosh and Windows environments (Yes, Flash even works under Windows!!!). Since Flash doesn’t really require a return value, I chose to return a simple Boolean. Flash is passed a short (type I), and flashes the current GrafPort that many times.

• SampMem

SampMem is to be used only on a Macintosh. SampMem demonstrates a technique used by many HyperCard XCMDs. This technique allows the creation of a handle that can be used by any DLL simply by passing an unsigned long representation of that handle to each DLL that needs to use it. SampMem is passed two arguments: an opcode (short) and an unsigned long. If the opcode is 0, SampMem creates a handle, casts that handle to an unsigned long, and then returns the unsigned long. It initializes the handle to the unsigned long parameter. If the opcode is 1, SampMem casts the incoming unsigned long to a handle, increments an unsigned long stored in the handle, and returns the current value of the unsigned long in the handle. If the opcode is 3, SampMem casts the incoming unsigned long to a handle and disposes the handle. To prevent unwanted execution of this DLL, in the sample spreadsheet, a space has been put in front of the macro function call. To execute it, remove the space and click the check box. I would suggest that you put a call with opcode 0 in an auto-open macro, and a call with opcode 2 in an auto-close macro. This will make sure that the handle is created and disposed of at the correct time.

Closing Thoughts

DLLs have desperately needed correct documentation with useful examples for a long time. I hope that I have provided for that need in this article. I would like to thank Andrew Donoho for introducing me to DLLs and my father, Ron Parsons, for his help and support. One thing still bugs me though -- I still don’t have an Excel T-Shirt.

/************************************************/
/*                  Sample DLL’s                */
/*       Copyright © Vincent Parsons 1989.      */
/************************************************/
/*    DLL code for MPW C 3.0 or THINK C 4.0     */
/*       with Excel for the Macintosh 2.2       */
/*             and Microsoft C 5.1              */
/*          with Excel for Windows 2.1          */
/************************************************/

/*  File DLL.h  */

#ifndef _DLLDEF_

#define _DLLDEF_

#if THINK_C
#define double64 short double
#elif applec|MSDOS
#define double64 double
#endif

#endif

/************************************************/
/* SampAAA is an example of two data type A     */
/* inputs and one data type A output.  The      */
/* output is the logical AND of the two inputs. */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampAAA”,”AAA”)      */
/*   for both the Mac and the PC.               */
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal unsigned short main(unsigned short b1,
 unsigned short b2); /* prototype */

pascal unsigned short main(b1, b2)
unsigned short b1;
unsigned short b2;

#elif applec
pascal unsigned short SampAAA(unsigned short b1,
unsigned short b2)

#elif MSDOS
unsigned short far pascal SampAAA(
 unsigned short b1, unsigned short b2)
#endif
{
 /* Returned parameter is the logical AND of
 the two inputs */
 return (b1 & b2);
}
/************************************************/
/* SampBBB is an example of two data type B     */
/* inputs and one data type B output.  The      */
/* output is the product of the two inputs.     */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampBBB”,”BBB”)      */
/*   for both the Mac and the PC.               */
/************************************************/
/* 
   Note that the floating point numbers 
   are passed as double64 * on the Mac and 
   double64 on the PC.
   
   The function type is pascal double64 * on the 
   Mac and double64 far * far pascal on the PC.
   
   On the Mac the returned value is d1 (a pointer 
   to the double64 result) and the answer has been 
   stored in the Excel buffer used by the input 
   variable.
   
   On the PC the answer is stored in a static 
   variable and the returned value is a pointer 
   to that static value.
   
   This was done so the REGISTER command is the 
   same in the PC and the Mac.
*/
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal double64 * main(double64 * d1, double64 * d2);
 /* prototype */

pascal double64 * main(d1, d2)
double64 * d1;
double64 * d2;

#elif applec
pascal double64 * SampBBB(double64 * d1, double64 * d2)

#elif MSDOS
double64 far * far pascal SampBBB(double64 d1,
 double64 d2)
#endif
{
#if applec | THINK_C
 double64 answer;
 
 /* Returned parameter is the product of the two inputs */
 answer = *d1 * *d2;
 *d1 = answer; /* Store value in Excel data
 buffer since static */
 return ( d1 );  /* variables are not
 permitted in Mac code resources */

#elif MSDOS
 static double64 answer;
 
 /* Returned parameter is the product of the two inputs */
 answer = d1 * d2;
 return ( (double64 far *)&answer );

#endif
}

/************************************************/
/* SampCC is an example of one data type C      */
/* input and one data type C output.  The       */
/* output has all upper case letters converted  */
/* to lower case and vice versa.  The answer    */
/* has been stored in the Excel buffer used by  */
/* the input variable.                          */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampCC”,”CC”)        */
/*   for both the Mac and the PC.               */
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal char * main(char * c1);/* prototype */

pascal char * main(c1)
char * c1;

#elif applec
pascal char * SampCC(char * c1)

#elif MSDOS
char far * far pascal SampCC(char far * c1)
#endif
{
 short i = 0;
 
 while ( c1[i] != ‘\0’ ) {/* C String */
 if ((c1[i] >= ‘A’) && (c1[i] <= ‘Z’))
 c1[i] += 32;
 else if ((c1[i] >= ‘a’) && (c1[i] <= ‘z’))
 c1[i] -= 32;
 i++;
 }
 
 return (c1);
}

/************************************************/
/* SampDD is an example of one data type D      */
/* input and one data type D output.  The       */
/* output has all upper case letters converted  */
/* to lower case and vice versa.  The answer    */
/* has been stored in the Excel buffer used by  */
/* the input variable.                          */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampDD”,”DD”)        */
/*   for both the Mac and the PC.               */
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal char * main(char * c1);/* prototype */

pascal char * main(c1)
char * c1;

#elif applec
pascal char * SampDD(char * c1)

#elif MSDOS
char far * far pascal SampDD(char far * c1)
#endif
{
 short i = 1;
 
 while ( i <= c1[0] ) { /* P String */
 if ((c1[i] >= ‘A’) && (c1[i] <= ‘Z’))
 c1[i] += 32;
 else if ((c1[i] >= ‘a’) && (c1[i] <= ‘z’))
 c1[i] -= 32;
 i++;
 }
 
 return (c1);
}

/************************************************/
/* SampEIIE is an example of two data type I    */
/* inputs and one data type E output.  The      */
/* output is the quotient of the two inputs.    */
/* A type E parameter is used to reserve space  */
/* for the returned value.                      */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampEIIE”,”EIIE”)    */
/*   for both the Mac and the PC.               */
/************************************************/
/* 
   A type E parameter is used to reserve storage
   space in an Excel data buffer for use by the
   DLL.  No data is actually passed as type E.
   
   The function type is pascal double64 * on the 
   Mac and double64 far * far pascal on the PC.
   
   On the Mac the returned value is d1 (a pointer 
   to the double64 result) and the answer has 
   been stored in the Excel buffer reserved by 
   the input variable.
   
   On the PC the returned value is d1 (a double64
   result) and the answer has been stored in the 
   Excel buffer reserved by the input variable.
   
   This was done so the REGISTER command is the 
   same in the PC and the Mac.
*/
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal double64 * main(short i1, short i2, double64 * d1);
 /* prototype */

pascal double64 * main(i1, i2, d1)
short i1;
short i2;
double64 * d1;

#elif applec
pascal double64 * SampEIIE(short i1, short i2,
 double64 * d1)

#elif MSDOS
double64 far pascal SampEIIE(short i1, short i2,
 double64 * d1)
#endif
{
 double64 answer;
 
 /* Returned parameter is the quotient of the
 two inputs */
 answer = (double64)i1/(double64)i2;
 *d1 = answer; /* Store value in Excel data buffer */
 
#if applec | THINK_C
 return ( d1 );
#elif MSDOS
 return ( (double64) *d1 );
#endif
}

/************************************************/
/* SampFHF is an example of one data type H     */
/* input and one data type F output.  The       */
/* output is the ASCII hex representation of    */
/* the type H input.  The answer has been       */
/* stored in the Excel buffer reserved by the   */
/* type F input variable.                       */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampFHF”,”FHF”)      */
/*   for both the Mac and the PC.               */
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal char * main(unsigned short u1, char * c1);
 /* prototype */

pascal char * main(u1, c1)
unsigned short u1;
char * c1;

#elif applec
pascal char * SampFHF(unsigned short u1, char * c1)

#elif MSDOS
char far * far pascal SampFHF(unsigned short u1,
 char far * c1)
#endif
{
 short i;
 
 for (i = 3; i >= 0; i--) {/* C String */
 c1[i] = u1 & 0xF; /* Get nibble */
 if (c1[i] <= 9) c1[i] += ‘0’;
 else c1[i] += 55; /* Make ASCII hex */
 u1 = u1 >> 4;   /* Get next nibble */
 }
 c1[4] = 0;
 
 return (c1);
}

/************************************************/
/* SampGHG is an example of one data type H     */
/* input and one data type F output.  The       */
/* output is the ASCII hex representation of    */
/* the type H input.  The answer has been       */
/* stored in the Excel buffer reserved by the   */
/* type F input variable.                       */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampGHG”,”GHG”)      */
/*   for both the Mac and the PC.               */
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal char * main(unsigned short u1, char * c1);
 /* prototype */

pascal char * main(u1, c1)
unsigned short u1;
char * c1;

#elif applec
pascal char * SampGHG(unsigned short u1,
 char * c1)

#elif MSDOS
char far * far pascal SampGHG(unsigned short u1,
 char far * c1)
#endif
{
 short i;
 
 for (i = 4; i > 0; i--) {/* P String */
 c1[i] = u1 & 0xF; /* Get nibble */
 if (c1[i] <= 9) c1[i] += ‘0’;
 else c1[i] += 55; /* Make ASCII hex */
 u1 = u1 >> 4;   /* Get next nibble */
 }
 c1[0] = 4;
 
 return (c1);
}

/************************************************/
/* SampHHH is an example of two data type H     */
/* inputs and one data type H output.  The      */
/* output is the product of the two type H      */
/* inputs.                                      */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampHHH”,”HHH”)      */
/*   for both the Mac and the PC.               */
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal unsigned short main(unsigned short u1,
 unsigned short u2);
 /* prototype */

pascal unsigned short main(u1, u2)
unsigned short u1;
unsigned short u2;

#elif applec
pascal unsigned short SampHHH(unsigned short u1,
 unsigned short u2)

#elif MSDOS
unsigned short far pascal SampHHH(
 unsigned short u1, unsigned short u2)
#endif
{
 return ( u1 * u2 );
}

/************************************************/
/* SampIII is an example of two data type I     */
/* inputs and one data type I output.  The      */
/* output is the product of the two type I      */
/* inputs.                                      */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampIII”,”III”)      */
/*   for both the Mac and the PC.               */
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>
#endif

#if THINK_C
pascal short main(short u1, short u2);
 /* prototype */

pascal short main(u1, u2)
short u1;
short u2;

#elif applec
pascal short SampIII(short u1, short u2)

#elif MSDOS
short far pascal SampIII(short u1, short u2)
#endif
{
 return ( u1 * u2 );
}

/************************************************/
/* SampJJ is an example of one data type J      */
/* input and one data type J output.  The       */
/* output is the lower 16 bits of the type J    */
/* input.                                       */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampJJ”,”JJ”)        */
/*   for both the Mac and the PC.               */
/************************************************/

#include “DLL.h”

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal unsigned long main(unsigned long u1);
 /* prototype */

pascal unsigned long main(u1)
unsigned long u1;

#elif applec
pascal unsigned long SampJJ(unsigned long u1)

#elif MSDOS
unsigned long far pascal SampJJ(unsigned long u1)
#endif
{
 return ( u1 & 0x0000FFFF );
}

/************************************************/
/* SampKKK is an example of two data type K     */
/* inputs and one data type K output.  The      */
/* output is the complex product of the         */
/* two type K inputs intrepreted as complex     */
/* numbers.                                     */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampKKK”,”KKK”)      */
/*   for both the Mac and the PC.               */
/************************************************/
/*
   Note that the complex number is passed
   as FP * c1 on the Mac and on the PC.

   The function type is pascal FP * on the Mac
   and FP far * far pascal on the PC.

   On the Mac the returned value is c1 (the
   pointer to the FP result) and the answer
   has been stored in the Excel buffer used
   by the input variable.

   On the PC the answer is stored in a static
   variable and the returned value is a pointer
   to that static value.

   This was done so the REGISTER command was
   the same in the PC and the Mac.
*/
/************************************************/

#include “DLL.h”

typedef struct fp {
 unsigned short rows;
 unsigned short columns;
 double64 array[2];
} FP;

#if applec
#include <Types.h>

#elif MSDOS
#include <windows.h>

#endif

#if THINK_C
pascal FP * main(FP * k1, FP * k2);
 /* prototype */

pascal FP * main(k1, k2)
FP * k1;
FP * k2;

#elif applec
pascal FP * SampKKK(FP * k1, FP * k2)

#elif MSDOS
FP far * far pascal SampKKK(FP far * k1, FP far * k2)
#endif
{
#if applec | THINK_C
 FP answer; /* Automatic variable */
#elif MSDOS
 static FP answer;
#endif

 answer.array[0] =
 (k1->array[0] * k2->array[0]) -
 (k1->array[1] * k2->array[1]);
 answer.array[1] =
 (k1->array[0] * k2->array[1]) +
 (k1->array[1] * k2->array[0]);
 answer.rows = k1->rows;
 answer.columns = k1->columns;

#if applec | THINK_C
 * k1 = answer;
/*Store value in Excel data buffer since static*/
/*variables not permitted in MPW code resources*/
 return ( k1 );
#elif MSDOS
 return( (FP far *)&answer );
#endif
}

/************************************************/
/* Flash is an example of direct manipulation   */
/* of the screen from a DLL. The DLL inverts    */
/* the window rectangle twice the input         */
/* parameter times.                             */
/************************************************/
/*   =REGISTER(“SampDLLs”,”Flash”,”AI”)         */
/*   for both the Mac and the PC.               */
/************************************************/

#ifdef applec

#include <Types.h>
#include <Memory.h>
#include <OSUtils.h>
#include <QuickDraw.h>

#elif MSDOS
#include <windows.h>

#endif

#ifdef THINK_C
pascal unsigned short main(short flashCount);
 /* prototype */

pascal unsigned short main(flashCount)
short flashCount;

#elif applec
pascal unsigned short Flash(short flashCount)

#elif MSDOS
unsigned short far pascal Flash(short flashCount)
#endif
{
 short  again;
#if THINK_C | applec
 GrafPtrport;
 
 GetPort(&port);
 for (again = 1; again <= flashCount; again++)
 {
 InvertRect(&port->portRect);
 InvertRect(&port->portRect);
 }
#elif MSDOS 
 HWND myWindowHandle;
 HDC  myDisplayContext;
 RECT myRect;
 
 myWindowHandle = GetActiveWindow();
 myDisplayContext =
 GetWindowDC(myWindowHandle);
 GetWindowRect(myWindowHandle, (LPRECT)&myRect);
 for (again = 1; again <= flashCount; again++)
 {
 InvertRect(myDisplayContext, (LPRECT)&myRect);
 InvertRect(myDisplayContext, (LPRECT)&myRect);
 }
 ReleaseDC(myWindowHandle,myDisplayContext);
#endif  
 return(again);
}

/************************************************/
/* SampMem is an example of using memory        */
/* management to save a value from one          */
/* execution of a DLL to the next               */
/************************************************/
/*   =REGISTER(“SampDLLs”,”SampMem”,”JIJ”)      */
/*   Macintosh only.                            */
/************************************************/

#include “DLL.h”

typedef long * LongPtr;

#if applec
#include <Types.h>
#include <Memory.h>

#endif

#if THINK_C
pascal unsigned long main(short opcode, unsigned long u1);
 /* prototype */

pascal unsigned long main(opcode, u1)
short opcode;
unsigned long u1;

#elif applec
pascal unsigned long SampMem(short opcode, unsigned long u1)

#endif
{
 unsigned long tempLong;
 unsigned long result;

 switch (opcode) {
 case 0:
 result = (unsigned long)NewHandle(4);
 *((LongPtr)(*((Handle)result))) = u1;
 break;
 case 1:
 tempLong = *((LongPtr)(*((Handle)u1)));
 tempLong++;
 *((LongPtr)(*((Handle)u1))) = tempLong;
 result = tempLong;
 break;
 case 2:
 DisposHandle((Handle)u1);
 result = 0;
 break;
 default: 
 result = 0;
 break;
 }
 return ( result );
}

/************************************************/
#************************************************/
#*        MPW C 3.0 Sample DLL Makefile         */
#************************************************/

SampAAA.c.o ƒ SampAAA.c SampDLLs.make DLL.h
 C -b SampAAA.c

SampAAA ƒ SampAAA.c.o
 Link -c “XCEL” -t “XLLB” -sg SampAAA -rt CODE=1 
  -ra SampAAA=resPurgeable -m SAMPAAA 
  SampAAA.c.o -o SampDLLs

SampBBB.c.o ƒ SampBBB.c SampDLLs.make DLL.h
 C -b SampBBB.c

SampBBB ƒ SampBBB.c.o
 Link -c “XCEL” -t “XLLB” -sg SampBBB -rt CODE=2 
  -ra SampBBB=resPurgeable -m SAMPBBB 
  SampBBB.c.o -o SampDLLs

SampCC.c.o ƒ SampCC.c SampDLLs.make DLL.h
 C -b SampCC.c

SampCC ƒ SampCC.c.o
 Link -c “XCEL” -t “XLLB” -sg SampCC -rt CODE=3 
  -ra SampCC=resPurgeable -m SAMPCC 
  SampCC.c.o -o SampDLLs

SampDD.c.o ƒ SampDD.c SampDLLs.make DLL.h
 C -b SampDD.c

SampDD ƒ SampDD.c.o
 Link -c “XCEL” -t “XLLB” -sg SampDD -rt CODE=4 
  -ra SampDD=resPurgeable -m SAMPDD 
  SampDD.c.o -o SampDLLs

SampEIIE.c.o ƒ SampEIIE.c SampDLLs.make DLL.h
 C -b SampEIIE.c

SampEIIE ƒ SampEIIE.c.o
 Link -c “XCEL” -t “XLLB” -sg SampEIIE -rt CODE=5
  -ra SampEIIE=resPurgeable -m SAMPEIIE 
  SampEIIE.c.o -o SampDLLs

SampFHF.c.o ƒ SampFHF.c SampDLLs.make DLL.h
 C -b SampFHF.c

SampFHF ƒ SampFHF.c.o
 Link -c “XCEL” -t “XLLB” -sg SampFHF -rt CODE=6 
  -ra SampFHF=resPurgeable -m SAMPFHF 
  SampFHF.c.o -o SampDLLs

SampGHG.c.o ƒ SampGHG.c SampDLLs.make DLL.h
 C -b SampGHG.c

SampGHG ƒ SampGHG.c.o
 Link -c “XCEL” -t “XLLB” -sg SampGHG -rt CODE=7 
  -ra SampGHG=resPurgeable -m SAMPGHG 
  SampGHG.c.o -o SampDLLs

SampHHH.c.o ƒ SampHHH.c SampDLLs.make DLL.h
 C -b SampHHH.c

SampHHH ƒ SampHHH.c.o
 Link -c “XCEL” -t “XLLB” -sg SampHHH -rt CODE=8 
  -ra SampHHH=resPurgeable -m SAMPHHH 
  SampHHH.c.o -o SampDLLs

SampIII.c.o ƒ SampIII.c SampDLLs.make DLL.h
 C -b SampIII.c

SampIII ƒ SampIII.c.o
 Link -c “XCEL” -t “XLLB” -sg SampIII -rt CODE=9 
  -ra SampIII=resPurgeable -m SAMPIII 
  SampIII.c.o -o SampDLLs

SampJJ.c.o ƒ SampJJ.c SampDLLs.make DLL.h
 C -b SampJJ.c

SampJJ ƒ SampJJ.c.o
 Link -c “XCEL” -t “XLLB” -sg SampJJ -rt CODE=10 
  -ra SampJJ=resPurgeable -m SAMPJJ 
  SampJJ.c.o -o SampDLLs

SampKKK.c.o ƒ SampKKK.c SampDLLs.make DLL.h
 C -b SampKKK.c

SampKKK ƒ SampKKK.c.o
 Link -c “XCEL” -t “XLLB” -sg SampKKK -rt CODE=11
  -ra SampKKK=resPurgeable -m SAMPKKK 
  SampKKK.c.o -o SampDLLs

SampMem.c.o ƒ SampMem.c SampDLLs.make DLL.h
 C -b SampMem.c

SampMem ƒ SampMem.c.o
 Link -c “XCEL” -t “XLLB” -sg SampMem -rt CODE=12
  -ra SampMem=resPurgeable -m SAMPMEM 
  SampMem.c.o 
  {Libraries}Interface.o 
  -o SampDLLs

Flash.c.o ƒ Flash.c SampDLLs.make DLL.h
 C -b Flash.c

Flash ƒ Flash.c.o
 Link -c “XCEL” -t “XLLB” -sg Flash -rt CODE=13 
  -ra Flash=resPurgeable -m FLASH 
  Flash.c.o -o SampDLLs

SampDLLs ƒ 
  SampAAA SampBBB SampCC 
  SampDD SampEIIE SampFHF SampGHG 
  SampHHH SampIII SampJJ SampKKK 
  SampMem Flash 
  SampDLLs.make DLL.h

#************************************************#
#* Microsoft C 5.1 Definition file SAMPDLLS.DEF *#
#************************************************#

LIBRARY SampDLLs

DESCRIPTION ‘Sample DLLs, Copyright 1989 Vincent Parsons’

STUB    ‘WINSTUB.EXE’

CODE    MOVEABLE
DATA    FIXED SINGLE

HEAPSIZE  4096
STACKSIZE 0

EXPORTS

        SampAAA
        SampBBB
        SampCC
        SampDD
        SampEIIE
        SampFHF
        SampGHG
        SampHHH
        SampIII
        SampJJ
        SampKKK
        Flash

#************************************************#
#*    Microsoft C 5.1 Makefile  SAMPDLLS.MAK    *#
#************************************************#

SampDLLs.lib : SampDLLs.def SampDLLs.mak
 implib SampDLLs.lib SampDLLs.def

SampAAA.obj : SampAAA.c SampDLLs.mak
 cl -c /D THINK_C=0 /D applec=0 \
    -Gsw -Asnw SampAAA.c

SampBBB.obj : SampBBB.c SampDLLs.mak
 cl -c -Gsw -Asnw SampBBB.c

SampCC.obj : SampCC.c SampDLLs.mak
 cl -c -Gsw -Asnw SampCC.c

SampDD.obj : SampDD.c SampDLLs.mak
 cl -c -Gsw -Asnw SampDD.c

SampEIIE.obj : SampEIIE.c SampDLLs.mak
 cl -c -Gsw -Asnw SampEIIE.c

SampFHF.obj : SampFHF.c SampDLLs.mak
 cl -c -Gsw -Asnw SampFHF.c

SampGHG.obj : SampGHG.c SampDLLs.mak
 cl -c -Gsw -Asnw SampGHG.c

SampHHH.obj : SampHHH.c SampDLLs.mak
 cl -c -Gsw -Asnw SampHHH.c

SampIII.obj : SampIII.c SampDLLs.mak
 cl -c -Gsw -Asnw SampIII.c

SampJJ.obj : SampJJ.c SampDLLs.mak
 cl -c -Gsw -Asnw SampJJ.c

SampKKK.obj : SampKKK.c SampDLLs.mak
 cl -c -Gsw -Asnw SampKKK.c

Flash.obj : Flash.c SampDLLs.mak
 cl -c -Gsw -Asnw Flash.c

SampDLLs.exe : SampAAA.obj SampBBB.obj \
               SampCC.obj SampDD.obj \
               SampEIIE.obj SampFHF.obj \
               SampGHG.obj SampHHH.obj \
               SampIII.obj SampJJ.obj \
               SampKKK.obj Flash.obj \
               SampDLLs.lib
 lib Samp1.lib -+SampAAA.obj -+SampBBB.obj \
    -+SampCC.obj -+SampDD.obj -+SampEIIE.obj \
    -+SampFHF.obj -+SampGHG.obj;
 lib Samp2.lib -+SampHHH.obj -+SampIII.obj \
    -+SampJJ.obj -+SampKKK.obj;
 link4 /al:16 /NOE  Flash.obj, SampDLLs.exe,,\
    Samp1.lib Samp2.lib win87em swinlibc slibw,\
    SampDLLs.def

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

FotoMagico 5.6.12 - Powerful slideshow c...
FotoMagico lets you create professional slideshows from your photos and music with just a few, simple mouse clicks. It sports a very clean and intuitive yet powerful user interface. High image... Read more
OmniGraffle Pro 7.12.1 - Create diagrams...
OmniGraffle Pro helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use... Read more
beaTunes 5.2.1 - Organize your music col...
beaTunes is a full-featured music player and organizational tool for music collections. How well organized is your music library? Are your artists always spelled the same way? Any R.E.M. vs REM?... Read more
HandBrake 1.3.0 - Versatile video encode...
HandBrake is a tool for converting video from nearly any format to a selection of modern, widely supported codecs. Features Supported Sources VIDEO_TS folder, DVD image or real DVD (unencrypted... Read more
Macs Fan Control 1.5.1.6 - Monitor and c...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
TunnelBear 3.9.3 - Subscription-based pr...
TunnelBear is a subscription-based virtual private network (VPN) service and companion app, enabling you to browse the internet privately and securely. Features Browse privately - Secure your data... Read more
calibre 4.3.0 - Complete e-book library...
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
Lyn 1.13 - Lightweight image browser and...
Lyn is a fast, lightweight image browser and viewer designed for photographers, graphic artists, and Web designers. Featuring an extremely versatile and aesthetically pleasing interface, it delivers... Read more
Visual Studio Code 1.40.0 - Cross-platfo...
Visual Studio Code provides developers with a new choice of developer tool that combines the simplicity and streamlined experience of a code editor with the best of what developers need for their... Read more
OmniGraffle 7.12.1 - Create diagrams, fl...
OmniGraffle helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use Graffle to... Read more

Latest Forum Discussions

See All

The House of Da Vinci 2 gets a new gamep...
The House of Da Vinci launched all the way back in 2017. Now, developer Blue Brain Games is gearing up to deliver a second dose of The Room-inspired puzzling. Some fresh details have now emerged, alongside the game's first official trailer. [Read... | Read more »
Shoot 'em up action awaits in Battl...
BattleBrew Productions has just introduced another entry into its award winning, barrelpunk inspired, BattleSky Brigade series. Whilst its previous title BattleSky Brigade TapTap provided fans with idle town building gameplay, this time the... | Read more »
Arcade classic R-Type Dimensions EX blas...
If you're a long time fan of shmups and have been looking for something to play lately, Tozai Games may have just released an ideal game for you on iOS. R-Type Dimensions EX brings the first R-Type and its sequel to iOS devices. [Read more] | Read more »
Intense VR first-person shooter Colonicl...
Our latest VR obsession is Colonicle, an intense VR FPS, recently released on Oculus and Google Play, courtesy of From Fake Eyes and Goboogie Games. It's a pulse-pounding multiplayer shooter which should appeal to genre fanatics and newcomers alike... | Read more »
PUBG Mobile's incoming update bring...
PUGB Mobile's newest Royale Pass season they're calling Fury of the Wasteland arrives tomorrow and with it comes a fair chunk of new content to the game. We'll be seeing a new map, weapon and even a companion system. [Read more] | Read more »
PSA: Download Bastion for free, but wait...
There hasn’t been much news from Supergiant Games on mobile lately regarding new games, but there’s something going on with their first game. Bastion released on the App Store in 2012, and back then it was published by Warner Bros. This Warner... | Read more »
Apple Arcade: Ranked - 51+ [Updated 11.5...
This is Part 2 of our Apple Arcade Ranking list. To see part 1, go here. 51. Patterned [Read more] | Read more »
NABOKI is a blissful puzzler from acclai...
Acclaimed developer Rainbow Train's latest game, NABOKI, is set to launch for iOS, Android, and Steam on November 13th. It's a blissful puzzler all about taking levels apart in interesting, inventive ways. [Read more] | Read more »
A Case of Distrust is a narrative-driven...
A Case of Distrust a narrative-focused mystery game that's set in the roaring 20s. In it, you play as a detective with one of the most private eye sounding names ever – Phyllis Cadence Malone. You'll follow her journey in San Francisco as she... | Read more »
Brown Dust’s October update offers playe...
October is turning out to be a productive month for the Neowiz team, and a fantastic month to be a Brown Dust player. First, there was a crossover event with the popular manga That Time I Got Reincarnated as a Slime. Then, there was the addition of... | Read more »

Price Scanner via MacPrices.net

Score a 37% discount on Apple Smart Keyboards...
Amazon has Apple Smart Keyboards for current-generation 10″ iPad Airs and previous-generation 10″ iPad Pros on sale today for $99.99 shipped. That’s a 37% discount over Apple’s regular MSRP of $159... Read more
Apple has refurbished 2019 13″ 1.4GHz MacBook...
Apple has a full line of Certified Refurbished 2019 13″ 1.4GHz 4-Core Touch Bar MacBook Pros available starting at $1099 and up to $230 off MSRP. Apple’s one-year warranty is included, shipping is... Read more
2019 13″ 1.4GHz 4-Core MacBook Pros on sale f...
Amazon has new 2019 13″ 1.4GHz 4-Core Touch Bar MacBook Pros on sale for $150-$200 off Apple’s MSRP. These are the same MacBook Pros sold by Apple in its retail and online stores: – 2019 13″ 1.4GHz/... Read more
11″ 64GB Gray WiFi iPad Pro on sale for $674,...
Amazon has the 11″ 64GB Gray WiFi iPad Pro on sale today for $674 shipped. Their price is $125 off MSRP for this iPad, and it’s the lowest price available for the 64GB model from any Apple reseller. Read more
2019 15″ MacBook Pros available for up to $42...
Apple has a full line of 2019 15″ 6-Core and 8-Core Touch Bar MacBook Pros, Certified Refurbished, available for up to $420 off the cost of new models. Each model features a new outer case, shipping... Read more
2019 15″ MacBook Pros on sale this week for $...
Apple resellers B&H Photo and Amazon are offering the new 2019 15″ MacBook Pros for up to $300 off Apple’s MSRP including free shipping. These are the same MacBook Pros sold by Apple in its... Read more
Sunday Sale: AirPods with Wireless Charging C...
B&H Photo has Apple AirPods with Wireless Charging Case on sale for $159.99 through 11:59pm ET on November 11th. Their price is $40 off Apple’s MSRP, and it’s the lowest price available for these... Read more
Details of Sams Club November 9th one day App...
Through midnight Saturday night (November 9th), Sams Club online has several Apple products on sale as part of their One Day sales event. Choose free shipping or free local store pickup (if available... Read more
Sprint is offering the 64GB Apple iPhone 11 f...
Sprint has the new 64GB iPhone 11 available for $15 per month for new lines. That’s about 50% off their standard monthly lease of $29.17. Over is valid until November 24, 2019. The fine print: “Lease... Read more
New Sprint November iPhone deal: Lease one iP...
Switch to Sprint and purchase an Apple iPhone 11, 11 Pro, or 11 Pro Max, and get a second 64GB iPhone 11 for free. Requires 2 new lines or 1 upgrade-eligible line and 1 new line. Offer is valid from... Read more

Jobs Board

*Apple* Mobility Pro - Best Buy (United Stat...
**746087BR** **Job Title:** Apple Mobility Pro **Job Category:** Store Associates **Store NUmber or Department:** 000319-Harlem & Irving-Store **Job Description:** Read more
Best Buy *Apple* Computing Master - Best Bu...
**743392BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Store NUmber or Department:** 001171-Southglenn-Store **Job Read more
Best Buy *Apple* Computing Master - Best Bu...
**746015BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Store NUmber or Department:** 000372-Federal Way-Store **Job Description:** Read more
*Apple* Mobility Pro - Best Buy (United Stat...
**744658BR** **Job Title:** Apple Mobility Pro **Job Category:** Store Associates **Store NUmber or Department:** 000586-South Hills-Store **Job Description:** At Read more
Best Buy *Apple* Computing Master - Best Bu...
**741552BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Store NUmber or Department:** 000277-Metcalf-Store **Job Description:** **What Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.