TweetFollow Us on Twitter

Calculating Distance
Volume Number:4
Issue Number:3
Column Tag:VIP Views

Calculating Distance for Navigation

By Bill Luckie, Contributing Editor, Simi Valley, CA

V.I.P. 2.2

Mainstay has released version 2.2 which is a significant upgrade and is free to all registered owners. V.I.P. 2.2 includes 25 additional procedures, improved keyboard control, 5 new intrinsic functions to provide added flexibility in handling Point and Rectangle objects, and the ability to create a true “About...” under the Apple menu. If you are a V.I.P. owner and haven’t sent in your registration card, you are missing some neat features.

In the beginning

In a previous article (April 1987), I presented a ‘shell’ program which implemented some of the common user interface actions e.g., Menus, Windows, File handling, and Events. In this program you will see that the same routines are used. In some cases these routines have been expanded to handle the specifics required of our program, and of course additional routines have been added. The only change brought about by changes to V.I.P. itself is the ‘About’ routine, which is now called Gee_Whiz. As mentioned earlier V.I.P. programmers can now create a “About (program name)” entry under the Apple menu and have it display whatever they choose. In this case selecting ‘About GC_Dist...’ displays the same window and information as presented at program startup.

The guts and feathers

The purpose of this program is to illustrate by example some of the most commonly used procedures. In addition to the already explored subjects we will create Dialogs, obtain user input data organized as records and save them to disk, work with some of V.I.P.’s intrinsic functions, and most importantly, have some fun programming. As is the case with most programs there is certainly more than one way to accomplish a particular objective. What I present here is not advocated as the only way, or even the best way, to do the job. In fact I violate a few of the rules set forth in Inside Macintosh, and I’ll tell you about them as we proceed.

Figure 1 Our Dialog Box

How far is it?

This program computes and displays the Great Circle distance between any two cities in the data file. Figure 4 contains the data required, which is input using the dialog as shown in figure 1. The Great Circle distance, in case you didn’t know, is the shortest distance between any two points on a sphere. It is most commonly used to represent the distance in nautical miles between airports for payload/range, performance, and fare calculations. Airports are each identified by a unique three character code. Los Angeles International airport, for example is LAX. The position on the globe of each airport is given as a latitude and longitude usually expressed in degrees and minutes. Latitudes south of the equator, and longitudes west of Greenwich, England are identified as negative angles. To work with these data, degrees and minutes are converted to decimal degrees, and to cope with SANE’s handling of some intrinsic functions, a conversion of decimal degrees to radians and vice is also required.

Learning to love rectangles

Three dialogs are used in this program. Record_Dialog, which is used to input the city code, latitude and longitude data. Edit_Dialog, which allows viewing and editing of the records previously saved to disk, and Input_Dialog for the user to specify the origin and destination city codes as input to routines for calculating the great circle distance.

V.I.P. allows the programmer to create dialogs using built in procedures as I have done in this example, or as resources created with a resource editor such as ResEdit or Dialog Creator. The difficulty in using V.I.P.’s procedures to create dialogs is in the visualization and placement of the various rectangles which bound each dialog item. Dialogs can contain static text, editable text, radio buttons, check boxes, and ordinary buttons, each situated within a rectangle. Creating complicated dialogs using V.I.P.’s procedures is enough to discourage ordinary mortals, but there is an easy solution even if you don’t care about resources.

My approach is to use Dialog Creator. Dialog Creator by Michael Bayer of Apple Canada lets you create dialog templates and dialog item lists interactively. It’s a simple matter to draw the dialog then print the text source file which gives you the coordinates of each rectangle and the assurance that your dialog will look OK.

For each of the three dialogs used in this program the code is essentially the same. A rectangle is specified for the size and location of the dialog window, and the new dialog procedure follows with arguments for rect, title, and dialog name. Entering a text string as the title argument indicates the dialog is to be non modal. Set rect and append dialog item procedures are now repeated for each item in the dialog. When referring to dialog items, their order of appearance in the dialog item list (DITL) is used.

By convention, dialog item #1 is the default action to be performed when the user presses the return or enter key generally signifying OK. (Note; this default action is implemented automatically in V.I.P. for modal dialogs only) When all dialog items have been appended to the list, the open dialog procedure displays the dialog on the screen. If you prefer to create dialogs as resources, then you will need to change all occurrences of kill dialog to close dialog so as to not erase them from memory until Quit is selected.

DoDialogEvent

Now that we have our dialogs created, we need to be able to process the information entered or displayed according to the users action. For example, in the dialog as shown in figure 1, you can see there are three editable text fields and two buttons. Data entered by the user in the text edit fields is saved to disk when the ‘Save it’ button is clicked, or conversely, the dialog is dismissed whenever the ‘Quit’ button is clicked.

The DoDialogEvent routine receives two input arguments, i.e. Dialog and item to direct the action to be taken depending on which dialog is active and which item of the dialog was selected. In this case the first if logic form is true, and program flow is directed to the Get_Record routine when item=1, and to the kill dialog procedure whenever item=2. Actions to be performed by the other dialogs are similarly handled.

The purpose of handling all dialog events in one routine is probably not apparent in this small program. However, this routine like those presented in my previous article, are really generic, in that they don’t do any real work, but merely direct program flow to a routine specifically designed to perform a discrete task. Programs written using a structured approach are usually easier to modify and are certainly easier to debug.

Get_Record

This routine when called by the DoDialogEvent routine simply executes three get dialog item procedures corresponding to the three text edit fields in the Record_Dialog. If you count the items appended to Record_Dialog you will see that items 7, 8, and 9 are the text edit fields receiving user entries for City Code, Latitude, and Longitude respectively. To assure the City Code is stored properly, the object ‘City’ is converted to upper case. When this routine has completed its miniscule tasks, program flow resumes in the DoDialogEvent routine and the Store_Records routine is called.

Figure 2 Editing our distance data base

Store_Records

With the information the user has entered in Record_Dialog extracted by the Get_Record routine as a result of the user clicking the ‘Save It’ button, we are now going to save it to disk as a record. A record, as I’m sure you know, is a group of related data organized in fields. In V.I.P., records themselves are identified by a Record Number, and individual fields are located within a record by specifying the offset (the number of bytes) from the beginning of the record. In preparation for storing the record to disk, the program decides if this is the first time its been asked to store a record, and if so, to display the standard file dialog, otherwise just save the record to disk without further ado. The first procedure sets the value of n according to how many times the routine is accessed, and is used as an argument to the object RecNo[n] which serves to automatically number our records.

The if (flag) logic form checks for true and directs execution flow accordingly. So, let’s say this is the first record to be stored. In that case flag=0 or false, and execution continues with the first else logic form. The get document name procedure displays the standard file dialog with the prompt, “Save file as ‘Cities’”. Here’s my first transgression from the scriptures of Inside Macintosh. Rather than allowing the user to name the file anything he (she) wishes, I tell ‘em name it ‘Cities’. If this offends your sensibilities, please feel free to change the code. Actually, you may name the file anything you choose. The argument name serves equally as the input argument, and its contents appear as the default name in the edit field reserved for the name of the file to be saved. To change the default name, initialize the global object ‘FileName’ to whatever you prefer, and don’t’ forget to set the array size at least equal to the string length plus 1.

The user accepts ‘Cities’ as the name of the file to be saved and clicks OK to dismiss the dialog, and the open file procedure opens the file in the ‘write’ mode. The allocate record procedure allocates a record in memory with a length of 18 bytes, and identifies it with RecNo[n], which is now 1.

City code is always 3 bytes plus 1 byte for end of string marker, the maximum length of Latitude and longitude is 6 bytes plus an additional byte for end of string. All data making up the record is stored as a continuous text string with the record length being the sum of each field plus an additional byte.

Three put field procedures take the global objects, City, Lat, and Long, and position them within the record. Arguments for put field are; record number, byte offset, and field length. Byte offset is expressed in bytes and the first position in a record is byte position zero. Field length is also expressed in bytes and is sized to handle the longest entry anticipated.

Figure 4 Output of our distance program

Procedures write record, free record, and close file complete the task of saving the record to disk. Now, because this is the first time this routine has been called, we set the value of flag to 1 or true. An alert is displayed informing the user that additional records added during this session will be saved without the GetFile dialog. Three set dialog item procedures clear the previously entered data, and position the text edit caret in the first text edit field ready for entry of the next record.

Assuming the user continues by entering data for the next record; when the Save It button is clicked, program flow progresses exactly as before. The difference is, when Store_Records is called this time, the counter n is incremented and the first if logic form now evaluates to true. The open file procedure opens the file ‘FileName’, and the get document length procedure returns the length in bytes of the file in the object ‘Position’. To avoid overwriting previously saved records, the file position procedure sets the file position according to the value of Position. From here on the same procedures are executed as before to save the record to disk.

Review_Records

Let’s say, for purposes of this tutorial, that you have entered all of the data and you wish to see if it is correct. By selecting View or Edit Records... from the Options menu, a non-modal dialog is displayed as shown in figure 2, and the Review_Records routine is called. This short routine opens the file ‘FileName’ in the read only mode. A for logic form provides a loop to be executed 10 times (NoRecs is a constant assigned the value of 10). The allocate record and read record procedures contained within the for loop are thusly executed 10 times to bring the entire file into memory. For safety sake the file is closed, and the value of the object n is set to zero.

When the Get Record button is clicked, the DoDialogEvent routine calls the Next_Record routine. As you might have guessed, when the Save Changes button is clicked, DoDialogEvent processes the request by calling the Save_Changes routine. The dialog is ultimately dismissed by clicking the window’s close box.

Next_Record

This routine is simply a series of get field and set dialog item procedures to display the contents of the records saved in the file ‘FileName’. To start at the beginning of the file, the object n is assigned the value of 1. Record Number is displayed by converting the object n to a byte type array named string with the procedure number to string. Note, the minimum dimension for a byte type array to handle number to string conversions is 13.

The Next_Record routine is called each time the user clicks the Get Record button. When the last record has been viewed, the assign procedure within the if logic form is executed to set the value of the object n to zero. This merely allows the continuous viewing of records by starting again at record number 1 when the last record has been displayed.

Figure 5 Our data base for distance calculation

Save_Changes

While viewing the records, changes may be made by entering the appropriate data in one or more of the text edit fields and clicking the Save Changes button. To no one’s surprise, the Save_Changes routine is called by the DoDialogEvent routine whenever the Save Changes button is clicked.

This routine simply opens the file ‘FileName’ in the write mode and sets the file position to overwrite the record to be changed. To do this, the procedure file position uses the argument (n-1)*18. Or in plain English, subtract 1 from the record number because the record pointer is left at the end of the record we wish to change. Now multiply by the record length (18), to set the file pointer to the correct position as calculated from the beginning of the file.

The actual writing of the record uses the same procedures as described previously. Two if logic forms are used to maintain correspondence with the actual record number, and if n=0 as is the case when the last record is the one to be edited, we simply assign the value of 10 to n. To make this a temporary measure, the object ‘flag’ is set to true, which is detected by the next if, and the value of n is once more zero. This only makes sense if you remember ‘n’ will always be something between 0 and 9 whenever this routine is called. So if n is equal to anything from 1 to 9, just write the record, else if n=0 change it to 10 temporarily. There must be an easier way.

Find_City

By selecting Compute Distance... from the Options menu, the dialog as shown in figure 4 is displayed. When the user enters the city codes for the origin and destination cities and clicks the Do It button, the Find_City routine is called by the Get_Input routine, and receives Origin and Destination as input arguments

The first thing this routine does is check to see if you are trying to fool it by entering the same city code for both the origin and destination cities. Normally an input like this should result in a distance of zero, but for some reason Apple’s SANE doesn’t like zero’s as operands for certain intrinsic functions. So, rather than having the Find_City routine complete all of its tasks, and then trap the error in the Calculate routine, I simply chose to display an alert informing the user of the problem.

Find_City opens the file ‘FileName’, reads the records into memory, and then compares the City field in the first record with the input argument Origin. If match=0 (are the same), two get field and string to number procedures extract and convert the data stored as Latitude and Longitude to numbers for the Origin City. When the origin city has been found, flag1 is set to true, and program execution continues looking for a match with the Destination city.

In this manner, the maximum number of times the records are searched for both the Origin and Destination cities is equal to the number of records in the file. If either flag1 or flag2 is not set to true, an alert informs the user that his choice is not in the file, and execution of this routine is terminated with a return procedure.

When both Origin and Destination cities have been found, Latitude and Longitude of the Origin and Destination cities are now passed to the Calculate routine as A,B,C,D respectively, as are the Origin and Destination city codes.

Calculate

If you haven’t fallen asleep by now, I’m sure you recall the data we stored as Latitude and Longitude represented degrees and minutes which were actually stored as byte arrays and later converted to real numbers by the Find_City routine. So, for example, the Latitude of LAX we entered was 3356 with the rightmost two characters representing the minutes portion in every case.

When the object A is received in this routine, and assuming LAX is the Origin city, it would appear as 3356.000 if we were to examine its value. To extract the minutes portion of this number we simply divide by 100 to move the decimal point two places to the left, and use the int & fract procedure to separate the integer and fractional portions so we can convert the fractional portion to decimal degrees. By dividing the fraction by 60 and multiplying by 100, and adding the fractional part now in decimal degrees to the integer we have a number we can almost work with.

This same series of manipulations is completed for objects B,C, and D, and now because SANE utilizes radians when working with sin, cos, and acos, we need to do another conversion. By multiplying each object A,B,C,D by (pi/180) we are finally ready to do the calculation to see how far it is between our Origin and Destination cities, however the answer wont make any sense until we convert the result ‘Dist’ to Nautical Miles. The distance is rounded off to the nearest whole number, converted to a string, and a series of draw string procedures displays the results as shown in figure 3.

Odds & Ends

If all of this seems like the long way around to arrive at the shortest distance between two points, you are probably correct. In this example program with only 10 cities we could have as easily entered Latitudes and Longitudes in a form that would not require conversion. However, when considering there are over 6900 airports in the world, each with its own identifier and Latitude and Longitude, you can perhaps appreciate the simplicity of using whole numbers to represent degrees and minutes rather than complex numbers more easily assimilated by a computer.

One routine we didn’t talk about this time is DoCloseBox. This routine is fairly straightforward, and performs the chores of disposing of the various windows and non modal dialogs used by the program. The only thing worth mentioning is my solution to avoid the possibility of opening the same window twice. In the DoOptions routine you will see that I have inserted a disable menu item procedure which globally disables the Options menu whenever a routine using a window is called. While this isn’t the most elegant way of avoiding the embarrassment of not being able to close a window, it works. An enable menu item procedure in the DoCloseBox routine is executed to restore the Options menu after the current window is closed.

That about does it for this time. I hope what you have read here is helpful in learning Visual Interactive Programming. If you would like to see other V.I.P. stuff, write to MacTutor! In the meantime have fun, after all that’s what it’s all about.

byte
 AboutFlag
 AboutWindow
 City[4]
 EditDialog
 EditWindow
 FileName[7]={‘C’,’i’,’t’,’i’,’e’,’s’,’\0'}
 InputDialog
 InputWindow
 Lat[7]
 Long[7]
 Menu[3]
 Quit
 RecordDialog
 RecordWindow
 WhichWindow
 Window
 flag
 go
 n

integer
 RecNo[10]

rectangle
 r

constants
 NoRecs = 10
 pi = 3.14159265

main
GC_Dist program for MacTutor™
by Bill Luckie  © 1987

Visual Interactive Programming
V.I.P. by Dominique Lienart, published by Mainstay.
===================================
DoSetup
while (! Quit)
 DoSelect
exit
===================================


Calculate (A,B,C,D,Origin,Destination)

--> real A
--> real B
--> real C
--> real D
--> byte Origin[4]
--> byte Destination[4]

byte
 S2[13]

integer
 Distance

real
 Dist
 fraction
 integer

rectangle
 r

assign (A / 100,A)
int & fract (A,integer,fraction)
assign (fraction / 60 * 100,fraction)
assign (integer + fraction,A)
assign (B / 100,B)
int & fract (B,integer,fraction)
assign (fraction / 60 * 100,fraction)
assign (integer + fraction,B)
assign (C / 100,C)
int & fract (C,integer,fraction)
assign (fraction / 60 * 100,fraction)
assign (integer + fraction,C)
assign (D / 100,D)
int & fract (D,integer,fraction)
assign (fraction / 60 * 100,fraction)
assign (integer + fraction,D)
assign (A * (pi/180),A)
assign (B * (pi/180),B)
assign (C * (pi/180),C)
assign (D * (pi/180),D)
assign (60*acos(sin(A)*sin(C)+cos(A)*cos(C)*cos(D-B)),Dist)
assign (Dist * (1/pi * 180),Dist)
int & fract (Dist,integer,fraction)
if (fraction   .5)
 assign (integer + 1,Distance)
else 
 assign (integer,Distance)
number to string (“@i”,Distance,S2)
activate window (Window)
set text font (0)
move to (50,18)
draw string (“The distance from “,0)
draw string (Origin,0)
draw string (“ to “,0)
draw string (Destination,0)
draw string (“ is “,0)
draw string (S2,0)
draw string (“ Nautical miles.”,0)
===================================
DoAbout

byte
 ID
 go
 message
 type

point
 location

rectangle
 Portrect
 Windowrect

assign (0,go)
set rect (60,60,120,450,Windowrect)
set rect (0,0,120,450,Portrect)
new window (4,0,1,Windowrect,Portrect,””,Window)
set text font (0)
move to (15,85)
draw string (“GC_Dist program for MacTutor™”,0)
move to (30,145)
draw string (“ by Bill Luckie.”,0)
move to (45,168)
draw string (“© 1987”,0)
if (AboutFlag)
 while (! go)
 get next event (type,location,message,ID)
 if (type = 3)
 assign (1,go)
 else 
 
else 
 wait (90)
kill window (Window)
assign (1,AboutFlag)
assign (0,Window)
===================================
DoCloseBox

get window (WhichWindow)
if (WhichWindow = AboutWindow)
 kill window (AboutWindow)
 assign (0,AboutWindow)
else 
 if (WhichWindow = InputWindow)
 kill window (Window)
 assign (0,Window)
 kill dialog (InputDialog)
 assign (0,InputWindow)
 assign (0,InputDialog)
 else 
 if (WhichWindow = EditWindow)
 kill dialog (EditDialog)
 assign (0,EditWindow)
 assign (0,EditDialog)
 else 
 
enable menu item (Menu[3],0)
===================================
DoDialogEvent (Dialog,item)

--> byte Dialog
--> byte item

if (Dialog = RecordDialog)
 switch (item,1,2)
 case 1
 Get_Record
 Store_Records
 case 2
 kill dialog (RecordDialog)
 assign (0,RecordDialog)
 default 
 
else 
 if (Dialog = InputDialog & item = 1)
 Get_Input
 else 
 if (Dialog = EditDialog)
 switch (item,1,2)
 case 1
 Next_Record
 case 2
 Save_Changes
 default 
 
 else 
===================================
DoEdit (item)

--> byte item

switch (item,3,4,5,6)
case 1
 cut text
case 2
 copy text
case 3
 paste text
case 4
 clear text
default 
===================================
DoFile (item)

--> byte item

byte
 result

switch (item,1,2,4)
case 1
 set up page
case 2
 if (AboutWindow)
 print text (AboutWindow)
 else 
 alert (1,”There is no window to print from.”,result)
case 3
 assign (1,Quit)
default 
===================================
DoMenuSelect (menu,item)

--> byte menu
--> byte item

switch (menu,Menu[1],Menu[2],Menu[3])
case 1
 DoFile (item)
case 2
 DoEdit (item)
case 3
 DoOptions (item)
default 
===================================
DoOptions (item)

--> byte item

switch (item,1,2,3,5)
case 1
 Record_Dialog
case 2
 disable menu item (Menu[3],0)
 Edit_Dialog
case 3
 disable menu item (Menu[3],0)
 Input_Dialog
case 4
 disable menu item (Menu[3],0)
 Gee_Whiz
default 
===================================
DoSelect

byte
 EventID
 EventMessage
 EventType

point
 MouseLocation

get next event (EventType,MouseLocation,EventMessage,EventID)
switch (EventType,1,4,5)
case 1
 if (EventMessage=0 & EventID=1)
 DoAbout
 else 
 DoMenuSelect (EventMessage,EventID)
case 2
 DoCloseBox
case 3
 DoDialogEvent (EventMessage,EventID)
default 
===================================
DoSetup

new menu (“File”,Menu[1])
append menu item (Menu[1],”Page Setup...;Print...;(-;Quit/Q”)
new menu (“Edit”,Menu[2])
append menu item (Menu[2],”(Undo/Z;(-;Cut/X;Copy/C;Paste/V;Clear”)
new menu (“Options”,Menu[3])
append menu item (Menu[3],”Create new Records...;View or Edit Records...;Compute 
Distance...;(-;Gee Whiz Stuff...”)
DoAbout
===================================
Edit_Dialog

rectangle
 r

set rect (100,106,250,406,r)
new dialog (r,”Edit Records”,EditDialog)
set rect (111,23,144,116,r)
append dialog item (EditDialog,1,r,”Get Record”)
set rect (111,179,144,280,r)
append dialog item (EditDialog,1,r,”Save Changes”)
set rect (3,72,19,228,r)
append dialog item (EditDialog,4,r,”Review & Edit Records.”)
set rect (27,50,43,150,r)
append dialog item (EditDialog,4,r,”City Code:”)
set rect (47,50,63,150,r)
append dialog item (EditDialog,4,r,”Latitude:”)
set rect (67,50,83,150,r)
append dialog item (EditDialog,4,r,”Longitude:”)
set rect (87,50,103,156,r)
append dialog item (EditDialog,4,r,”Record No.:”)
set rect (29,190,45,217,r)
append dialog item (EditDialog,5,r,””)
set rect (50,190,66,240,r)
append dialog item (EditDialog,5,r,””)
set rect (71,190,87,240,r)
append dialog item (EditDialog,5,r,””)
set rect (88,138,104,158,r)
append dialog item (EditDialog,5,r,””)
open dialog (EditDialog,EditWindow)
Review_Records
===================================
Find_City (Origin,Destination)

--> byte Origin[4]
--> byte Destination[4]

byte
 f
 flag1
 flag2
 match
 n
 result

integer
 RecNo[10]

real
 A
 B
 C
 D

compare string (Origin,Destination,match)
if (match = 0)
 alert (1,”The Origin and Destination cities are the same.”,result)
 return
else 
 
assign (0,flag1)
assign (0,flag2)
open file (FileName,1,”TEXT”,f)
for (n,1,NoRecs,1)
 allocate record (18,RecNo[n])
 read record (f,RecNo[n])
close file (f)
for (n,1,NoRecs,1)
 get field (n,0,4,City)
 upper case (City)
 compare string (City,Origin ,match)
 if (match = 0)
 get field (n,4,7,Lat)
 string to number (3,Lat,A)
 get field (n,11,7,Long)
 string to number (3,Long,B)
 assign (1,flag1)
 else 
 
 compare string (City,Destination,match)
 if (match = 0)
 get field (n,4,7,Lat)
 string to number (3,Lat,C)
 get field (n,11,7,Long)
 string to number (3,Long,D)
 assign (1,flag2)
 else 
 
if (! flag1)
 alert (1,”Sorry, Origin city code not in file.”,result)
 return
else 
 if (! flag2)
 alert (1,”Sorry, Destination city code not in file.”,result)
 return
 else 

Calculate (A,B,C,D,Origin,Destination)
===================================
Gee_Whiz

byte
 AboutFile

rectangle
 PortRect
 WindowRect

set rect (50,40,312,472,WindowRect)
set rect (0,0,1000,432,PortRect)
new window (7,1,1,WindowRect,PortRect,”Gee Whiz Stuff”,AboutWindow)
open file (“Gee_Whiz”,1,”TEXT”,AboutFile)
load text (AboutFile,AboutWindow)
close file (AboutFile)
===================================
Get_Input

byte
 Destination[4]
 Origin[4]
 state

clear window (Window)
get dialog item (InputDialog,4,state,Origin)
upper case (Origin)
get dialog item (InputDialog,5,state,Destination)
upper case (Destination)
Find_City (Origin,Destination)
===================================
Get_Record

byte
 state

get dialog item (RecordDialog,7,state,City)
upper case (City)
get dialog item (RecordDialog,8,state,Lat)
get dialog item (RecordDialog,9,state,Long)
===================================
Input_Dialog

rectangle
 r
 r1

set rect (182,61,326,451,r)
new dialog (r,”Select cities”,InputDialog)
set rect (106,164,137,227,r)
append dialog item (InputDialog,1,r,”Do it”)
set rect (31,104,47,204,r)
append dialog item (InputDialog,4,r,”Origin:”)
set rect (62,104,78,204,r)
append dialog item (InputDialog,4,r,”Destination:”)
set rect (34,220,50,245,r)
append dialog item (InputDialog,5,r,””)
set rect (60,220,76,245,r)
append dialog item (InputDialog,5,r,””)
set rect (3,49,26,342,r)
append dialog item (InputDialog,4,r,”Enter city codes for Origin & Destination.”)
set rect (52,68,152,444,r)
set rect (0,0,155,447,r1)
new window (4,0,1,r,r1,””,Window)
open dialog (InputDialog,InputWindow)
===================================
Next_Record

byte
 result
 string[13]

assign (n + 1,n)
get field (RecNo[n],0,4,City)
set dialog item (EditDialog,8,9,City)
get field (RecNo[n],4,7,Lat)
set dialog item (EditDialog,9,9,Lat)
get field (RecNo[n],11,7,Long)
set dialog item (EditDialog,10,9,Long)
number to string (“@b”,n,string)
set dialog item (EditDialog,11,9,string)
if (n = NoRecs)
 assign (0,n)
else 
===================================
Record_Dialog

rectangle
 r

set rect (100,154,251,359,r)
new dialog (r,””,RecordDialog)
set rect (115,5,147,85,r)
append dialog item (RecordDialog,1,r,”Save It”)
set rect (115,119,147,199,r)
append dialog item (RecordDialog,1,r,”Quit”)
set rect (4,38,22,176,r)
append dialog item (RecordDialog,4,r,”Enter new records”)
set rect (30,6,46,106,r)
append dialog item (RecordDialog,4,r,”City Code:”)
set rect (60,6,76,106,r)
append dialog item (RecordDialog,4,r,”Latitude:”)
set rect (90,6,105,106,r)
append dialog item (RecordDialog,4,r,”Longitude:”)
set rect (30,105,46,140,r)
append dialog item (RecordDialog,5,r,””)
set rect (60,105,76,162,r)
append dialog item (RecordDialog,5,r,””)
set rect (90,105,106,162,r)
append dialog item (RecordDialog,5,r,””)
open dialog (RecordDialog,RecordWindow)
===================================
Review_Records

byte
 f

integer
 result
open file (FileName,1,”TEXT”,f)
for (n,1,NoRecs,1)
 allocate record (18,RecNo[n])
 read record (f,RecNo[n])
close file (f)
assign (0,n)
===================================
Save_Changes
byte
 f
 state

integer
 result

assign (0,flag)
open file (FileName,2,”TEXT”,f)
if (n = 0)
 assign (10,n)
 assign (1,flag)
else 
 
file position (f,(n-1) * 18,0,result)
get dialog item (EditDialog,8,state,City)
get dialog item (EditDialog,9,state,Lat)
get dialog item (EditDialog,10,state,Long)
allocate record (18,RecNo[n])
put field (RecNo[n],0,4,City)
put field (RecNo[n],4,7,Lat)
put field (RecNo[n],11,7,Long)
write record (f,RecNo[n])
close file (f)
if (flag)
 assign (0,n)
else 
===================================
Store_Records
byte
 f
 ok
 result

integer
 Position
 RecNo[10]
 status

assign (n + 1,n)
if (flag)
 open file (FileName,2,”TEXT”,f)
 get document length (FileName,Position)
 file position (f,Position,0,status)
 allocate record (18,RecNo[n])
 put field (RecNo[n],0,4,City)
 put field (RecNo[n],4,7,Lat)
 put field (RecNo[n],11,7,Long)
 write record (f,RecNo[n])
 free record (RecNo[n])
 close file (f)
else 
 get document name (1,”Save file as ‘Cities’”,”TEXT”,ok,FileName)
 if (ok)
 open file (FileName,2,”TEXT”,f)
 allocate record (18,RecNo[n])
 put field (RecNo[n],0,4,City)
 put field (RecNo[n],4,7,Lat)
 put field (RecNo[n],11,7,Long)
 write record (f,RecNo[n])
 free record (RecNo[n])
 close file (f)
 assign (1,flag)
 alert (1,”Additional records added during this session will be saved 
without the GetFile dialog.” ,result)
 else 
 
set dialog item (RecordDialog,7,1,””)
set dialog item (RecordDialog,8,9,””)
set dialog item (RecordDialog,9,9,””)
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

iExplorer 4.1.9 - View and transfer file...
iExplorer is an iPhone browser for Mac lets you view the files on your iOS device. By using a drag and drop interface, you can quickly copy files and folders between your Mac and your iPhone or... Read more
PCalc 4.5.3 - Full-featured scientific c...
PCalc is a full-featured, scriptable scientific calculator with support for hexadecimal, octal, and binary calculations, as well as an RPN mode, programmable functions, and an extensive set of unit... Read more
Slack 2.9.0 - Collaborative communicatio...
Slack is a collaborative communication app that simplifies real-time messaging, archiving, and search for modern working teams. Version 2.9.0: Slack now officially, and fully, supports Japanese.... Read more
Microsoft Office 2016 15.40 - Popular pr...
Microsoft Office 2016 - Unmistakably Office, designed for Mac. The new versions of Word, Excel, PowerPoint, Outlook and OneNote provide the best of both worlds for Mac users - the familiar Office... Read more
Apple iOS 11.1.2 - The latest version of...
iOS 11 sets a new standard for what is already the world’s most advanced mobile operating system. It makes iPhone better than before. It makes iPad more capable than ever. And now it opens up both to... Read more
Adobe InCopy CC 2018 13.0.1.207 - Create...
InCopy CC 2018 is available as part of Adobe Creative Cloud for as little as $19.99/month (or $9.99/month if you're a previous InCopy customer). Adobe InCopy CC 2018, ideal for large team projects... Read more
Adobe InDesign CC 2018 13.0.1.207 - Prof...
InDesign CC 2018 is available as part of Adobe Creative Cloud for as little as $19.99/month (or $9.99/month if you're a previous InDesign customer). Adobe InDesign CC 2018 is part of Creative Cloud.... Read more
Tor Browser Bundle 7.0.10 - Anonymize We...
The Tor Browser Bundle is an easy-to-use portable package of Tor, Vidalia, Torbutton, and a Firefox fork preconfigured to work together out of the box. It contains a modified copy of Firefox that... Read more
OmniOutliner Pro 5.2 - Pro version of th...
OmniOutliner Pro is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
iShowU Instant 1.2.3 - Full-featured scr...
iShowU Instant gives you real-time screen recording like you've never seen before! It is the fastest, most feature-filled real-time screen capture tool from shinywhitebox yet. All of the features you... Read more

Latest Forum Discussions

See All

A Boy and His Blob (Games)
A Boy and His Blob 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: | Read more »
Fight terrible monsters and collect epic...
Released on Western markets early last month, Dragon Project, created by Japanese developer COLOPL, brings epic monster hunting action to mobile for the very first time. Collect a huge array of weapons and armor, and join up with friends to fight... | Read more »
I Am The Hero (Games)
I Am The Hero 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: I Am The Hero is a pixel art, beat 'em up, fighting game that tells the story of a "Hero" with a glorious but mysterious past.... | Read more »
Kauldron (Music)
Kauldron 1.0 Device: iOS Universal Category: Music Price: $3.99, Version: 1.0 (iTunes) Description: Kauldron is our warmest sounding, punchiest synth yet! A completely new modeling technology, combined with carefully designed... | Read more »
Lineage II: Revolution is mobile’s bigge...
NCSoft’s hit fantasy MMORPG series has just made the leap to mobile with the help of Netmarble in Lineage II: Revolution. With over 1.5 million players having already pre-registered ahead of the game’s launch, Revolution hit the app stores... | Read more »
Swing skilfully in new physics-based pla...
Sometimes it’s the most difficult of obstacles that can be the most rewarding. One game hoping to prove this is OCMO, the new tough but fair platformer from developers Team Ocmo. Primed to set every speedrunner’s pulse racing, as an otherworldly... | Read more »
RPGolf (Games)
RPGolf 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Once upon a time, the kingdom was a land of peace, harmony, and an all-consuming passion for the greatest sport - GOLF. Everyone in the... | Read more »
Everything you need to know about Fire E...
Fire Emblem Heroes is getting its biggest update yet as Nintendo unveiled Book II last night, featuring a whole new set of story missions and yes, collectible heroes. The update's not out just yet, but here's what you can expect when the new... | Read more »
The biggest updates out this week - Nove...
A big game update is always a treat. Multiply that by four and you're having a really good week. Those weeks don't come around very often, but you're in luck. This chilly mid-November is chock full updates for some of your favorite titles, and they... | Read more »
Ocmo (Games)
Ocmo 1.0.13 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.13 (iTunes) Description: Ocmo is an award winning ninja rope platformer that challenges even hardcore gamers. Fluid movement, physics based gameplay and... | Read more »

Price Scanner via MacPrices.net

Early Black Friday sale: Apple iMacs for up t...
B&H Photo has 27-inch iMacs in stock and on sale for up $130-$150 off MSRP including free shipping. B&H charges sales tax in NY & NJ only: – 27″ 3.8GHz iMac (MNED2LL/A): $2149 $150 off... Read more
Apple restocks refurbished Mac minis starting...
Apple has restocked Certified Refurbished Mac minis starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: – 1.4GHz Mac mini: $419 $80 off MSRP – 2.6GHz Mac... Read more
Save on 12″ MacBooks, Apple refurbished model...
Apple has Certified Refurbished 2017 12″ Retina MacBooks available for $200-$240 off the cost of new models. Apple will include a standard one-year warranty with each MacBook, and shipping is free.... Read more
Early Holiday sale: 12″ iPad Pros for up to $...
B&H Photo has 12″ iPad Pros on sale today for up to $130 off MSRP. Shipping is free, and B&H collects no sales tax outside NY & NJ: – 12″ 64GB WiFi iPad Pro: $749, save $50 – 12″ 256GB... Read more
Holiday sale prices on Apple 13″ MacBook Pros...
B&H Photo has 2017 13″ MacBook Pros in stock today and on sale for $100-$150 off MSRP, each including free shipping plus NY & NJ sales tax only: – 13-inch 2.3GHz/128GB Space Gray MacBook Pro... Read more
Sale: 13″ MacBook Airs starting at $899, $100...
B&H Photo has 2017 13″ MacBook Airs on sale today for $100 off MSRP including free shipping. B&H charges NY & NJ sales tax only: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $899, $100 off... Read more
Week’s Best Deal on 13″ MacBook Pros: Apple r...
Apple has a full line of Apple Certified Refurbished 2017 13″ MacBook Pros available for $200-$300 off MSRP. A standard Apple one-year warranty is included with each MacBook, and shipping is free.... Read more
Deal: 15″ 2.6GHz MacBook Pro for $1799 w/free...
B&H Photo has clearance 2016 15″ 2.6GHz Touch Bar MacBook Pros in stock today and available for $600 off original MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: – 15″ 2.... Read more
Black Friday pricing on the 1.4GHz Mac mini....
MacMall has the 1.4GHz Mac mini on sale for $399 including free shipping. Their price is $100 off MSRP (20% off), and it’s the lowest price for available for this model from any reseller. MacMall’s... Read more
Early Black Friday deal: 15″ Apple MacBook Pr...
B&H Photo has 15″ MacBook Pros on sale for up to $200 off MSRP. Shipping is free, and B&H charges sales tax in NY & NJ only: – 15″ 2.8GHz MacBook Pro Space Gray (MPTR2LL/A): $2199, $200... Read more

Jobs Board

*Apple* Solution Consultant - Apple (United...
# Apple Solution Consultant - Rochester, MN Job Number: 113037950 Rochester, MN, Minnesota, United States Posted: 19-Sep-2017 Weekly Hours: 40.00 **Job Summary** Are Read more
Sr. Experience Producer, Today at *Apple* -...
# Sr. Experience Producer, Today at Apple Job Number: 56495251 Santa Clara Valley, California, United States Posted: 23-Jun-2017 Weekly Hours: 40.00 **Job Summary** Read more
AppleCare Support Engineer for *Apple* Medi...
…Summary AppleCare Engineering, Software & Services, is a group that works to represent Apple 's World Wide contact centers and Apple 's customers to groups within Read more
Site Reliability Engineer, *Apple* Pay - Ap...
Job Summary The Apple Pay Site Reliability Engineering Team is hiring for multiple roles focused on the front line customer experience and the back end integration Read more
*Apple* Solutions Consultant - Apple (United...
# Apple Solutions Consultant Job Number: 86078534 Fairless Hills, Pennsylvania, United States Posted: 07-Jul-2017 Weekly Hours: 40.00 **Job Summary** As an Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.