diff --git a/C.Samples/Benchmarks/FIB.cc b/C.Samples/Benchmarks/FIB.cc new file mode 100644 index 0000000..92263f3 --- /dev/null +++ b/C.Samples/Benchmarks/FIB.cc @@ -0,0 +1,46 @@ +/*************************************************************** +* +* Fibonacci +* +* Recursively computes Fibonacci numbers to test the speed of +* function calls. +* +* To get the best performance from the desktop development +* environment, be sure and turn debugging off from the +* Compile Dialog. Use the Compile command from the Run menu +* to get the compile dialog. +* +****************************************************************/ + +#pragma keep "FIB" +#pragma optimize -1 +#pragma lint -1 + +#include + +#define NTIMES 10 /* # iterations */ +#define NUMBER 23 /* largest Fib # smaller than 32767 */ + + +int Fibonacci(int x) + +{ +if (x > 2) + return Fibonacci(x-1)+Fibonacci(x-2); +else + return 1; +} + + +int main (void) + +{ +int value; +unsigned i; + +printf("%d iterations:\n", NTIMES); +for (i = 0; i < NTIMES; ++i) + value = Fibonacci(NUMBER); +printf("Fibonacci(%d) = %d\n", NUMBER, value); +return 0; +} diff --git a/C.Samples/Benchmarks/Float.cc b/C.Samples/Benchmarks/Float.cc new file mode 100644 index 0000000..cfcbc6d --- /dev/null +++ b/C.Samples/Benchmarks/Float.cc @@ -0,0 +1,51 @@ +/*************************************************************** +* +* Float +* +* Test simple floating point operations. +* +* To get the best performance from the desktop development +* environment, be sure and turn debugging off from the +* Compile Dialog. Use the Compile command from the Run menu +* to get the compile dialog. +* +***************************************************************/ + +#pragma keep "Float" +#pragma optimize -1 +#pragma lint -1 + +#include + +#define const1 3.141597 +#define const2 1.7839032e4 +#define count 1000 + +int main(void) + +{ +double a,b,c; +int i; + +a = const1; +b = const2; +printf("%d iterations.\n", count); +for (i = 0; i < count; ++i) { + c = a*b; + c = c/a; + c = a*b; + c = c/a; + c = a*b; + c = c/a; + c = a*b; + c = c/a; + c = a*b; + c = c/a; + c = a*b; + c = c/a; + c = a*b; + c = c/a; + } +printf("Done. C is %e.\n", c); +return 0; +} diff --git a/C.Samples/Benchmarks/Gamm.cc b/C.Samples/Benchmarks/Gamm.cc new file mode 100644 index 0000000..2db6089 --- /dev/null +++ b/C.Samples/Benchmarks/Gamm.cc @@ -0,0 +1,114 @@ +/*************************************************************** +* +* Gamm +* +* Test the speed of floating point operations in a mix tha +* is typical of scientific and engineering applications. +* +* To get the best performance from the desktop development +* environment, be sure and turn debugging off from the +* Compile Dialog. Use the Compile command from the Run menu +* to get the compile dialog. +* +***************************************************************/ + +#pragma keep "Gamm" +#pragma optimize -1 +#pragma lint -1 + +#include + + +int main (void) + +{ +int five,i,j,n,rep,ten,thirty; +float acc,acc1,divn,rn,root,x,y; +float a[30], b[30], c[30]; + +printf("Start timing 15000 Gamm units\n"); +n = 50; +five = 5; +ten = 10; +thirty = 30; +rn = n; +divn = 1.0/rn; +x = 0.1; +acc = 0.0; + +/* initialize a and b */ +y = 1.0; +for (i = 0; i < thirty; ++i) { + a[i] = i+1; + b[i] = -y; + y = -y; + }; + +/* one pass thru this loop corresponds to 300 gamm units */ +for (rep = 0; rep < n; ++rep) { + /* first addition/subtraction loop */ + i = 29; + for (j = 0; j < 30; ++j) { + c[i] = a[i]+b[i]; + --i; + }; + /* first polynomial loop */ + y = 1.0; + for (i = 0; i < 10; ++i) + y = (y+c[i])*x; + acc1 = y*divn; + /* first maximum element loop */ + y = c[10]; + for (i = 10; i < 20; ++i) + if (c[i] > y) + y = c[i]; + /* first square root loop */ + root = 1.0; + for (i = 0; i < 5; ++i) + root = 0.5*(root+y/root); + acc1 = acc1+root*divn; + /* second addition/subtraction loop */ + for (i = 0; i < 30; ++i) + a[i] = c[i]-b[i]; + /* second polynomial loop */ + y = 0.0; + for (i = 0; i < 10; ++i) + y = (y+a[i])*x; + /* second square root loop */ + root = 1.0; + for (i = 1; i < 5; ++i) + root = 0.5*(root+y/root); + acc1 = acc1+root*divn; + /* first multiplication loop */ + for (i = 0; i < thirty; ++i) + c[i] = c[i]*b[i]; + /* second maximum element loop */ + y = c[19]; + for (i = 20; i < thirty; ++i) + if (c[i] > y) + y = c[i]; + /* third square root loop */ + root = 1.0; + for (i = 0; i < 5; ++i) + root = 0.5*(root+y/root); + acc1 = acc1+root*divn; + /* third polynomial loop */ + y = 0.0; + for (i = 0; i < 10; ++i) + y = (y+c[i])*x; + acc1 = acc1+y*divn; + /* third maximum element loop */ + y = c[0]; + for (i = 1; i < 10; ++i); + if (c[i] > y) + y = c[i]; + /* fourth square root loop */ + root = 1.0; + for (i = 0; i < 5; ++i) + root = 0.5*(root+y/root); + acc1 = acc1+root*divn; + acc = acc+acc1; + } +printf("%12d %12.7e %12.7e\n", n, acc, acc1); +return 0; +} diff --git a/C.Samples/Benchmarks/IMath.cc b/C.Samples/Benchmarks/IMath.cc new file mode 100644 index 0000000..f6102ef --- /dev/null +++ b/C.Samples/Benchmarks/IMath.cc @@ -0,0 +1,56 @@ +/*************************************************************** +* +* Integer Math +* +* Test the speed of the four basic integer math operations. +* +* To get the best performance from the desktop development +* environment, be sure and turn debugging off from the +* Compile Dialog. Use the Compile command from the Run menu +* to get the compile dialog. +* +****************************************************************/ + +#pragma keep "IMath" +#pragma optimize -1 +#pragma lint -1 + +#include + +#define ITER 10000 + + +int main (void) + +{ +int a,b,c,d,e,f; +unsigned i; + +printf("Start timing...\n"); +b = 1000; +c = 10; +d = 100; +e = 5; +f = 10; +for (i = 0; i < ITER; ++i) { + a = b+c-d*e/f; + a = b+c-d*e/f; + a = b+c-d*e/f; + a = b+c-d*e/f; + a = b+c-d*e/f; + a = b+c-d*e/f; + a = b+c-d*e/f; + a = b+c-d*e/f; + a = b+c-d*e/f; + a = b+c-d*e/f; + a = b+c-d*e/f; + } +if (a == 960) { + printf("Stop timing - correct result.\n"); + return 0; + } +else { + printf("INCORRECT RESULT.\n"); + return -1; + } +} diff --git a/C.Samples/Benchmarks/Prime.cc b/C.Samples/Benchmarks/Prime.cc new file mode 100644 index 0000000..3ca1fdd --- /dev/null +++ b/C.Samples/Benchmarks/Prime.cc @@ -0,0 +1,50 @@ +/*************************************************************** +* +* This is probably the most famous benchmark in use today. +* It tests the speed that a compiler can do logic and looping +* operations. While there are things that you can do to make +* this benchmark run faster under ORCA/C, we have not +* doctored it in any way - this is the original benchmark +* in its original form. +* +* To get the best performance from the desktop development +* environment, be sure and turn debugging off from the +* Compile Dialog. Use the Compile command from the Run menu +* to get the compile dialog. +* +***************************************************************/ + +#pragma keep "Prime" +#pragma optimize -1 +#pragma lint -1 + +#include + +#define true 1 +#define false 0 +#define size 8190 + +char flags[size+1]; + +void main (void) + +{ +int i,prime,k,count,iter; + +printf("10 iterations\n"); +for (iter = 1; iter <= 10; iter++) { + count = 0; + for (i = 0; i <= size; i++) + flags[i] = true; + for (i = 0; i <= size; i++) { + if (flags[i]) { + prime = i+i+3; + /* printf("\n%d", prime); */ + for (k = i+prime; k <= size; k += prime) + flags[k] = false; + count++; + } + } + } + printf("\n%d primes.", count); +} diff --git a/C.Samples/Benchmarks/Quick.cc b/C.Samples/Benchmarks/Quick.cc new file mode 100644 index 0000000..6929016 --- /dev/null +++ b/C.Samples/Benchmarks/Quick.cc @@ -0,0 +1,96 @@ +/*************************************************************** +* +* QuickSort +* +* Creates an array of long integers, then sorts the array. +* +* To get the best performance from the desktop development +* environment, be sure and turn debugging off from the +* Compile Dialog. Use the Compile command from the Run menu +* to get the compile dialog. +* +***************************************************************/ + +#pragma keep "Quick" +#pragma optimize -1 +#pragma lint -1 + +#include +#include + +#define maxNum 999 /* size of array to sort - 1 */ +#define count 10 /* # of iterations */ +#define modulus 0x00020000 /* for random number generator */ +#define c 13849 +#define a 25173 + +typedef long arrayType[maxNum]; + +arrayType buffer; /* array to sort */ +long seed; /* seed for random number generator */ + + +void Quick (int lo, int hi, arrayType base) + +{ +int i,j; +long pivot,temp; + +if (hi > lo) { + pivot = base[hi]; + i = lo-1; + j = hi; + do { + do ++i; while ((base[i] < pivot) && (j > i)); + if (j > i) + do --j; while ((base[j] > pivot) && (j > i)); + temp = base[i]; + base[i] = base[j]; + base[j] = temp; + } + while (j > i); + base[j] = base[i]; + base[i] = base[hi]; + base[hi] = temp; + Quick(lo, i-1, base); + Quick(i+1, hi, base); + } +} + + +long Random (long size) + +{ +seed = seed*a+c; +return seed % size; +} + + +int main (void) + +{ +int i,j; /* loop variables */ +int pass; /* for checking the array */ + +seed = 7; +printf("Filling array and sorting %d times.\n", count); +for (i = 0; i < count; ++i) { + for (j = 0; j < maxNum; ++j) + buffer[j] = labs(Random(modulus)); + Quick(0, maxNum-1, buffer); + } +printf("Done.\n"); + +pass = 1; +for (i = 0; i < maxNum-1; ++i) + if (buffer[i] > buffer[i+1]) + pass = 0; +if (pass) { + printf("The last array is sorted properly.\n"); + return 0; + } +else { + printf("The last array is NOT sorted properly!\n"); + return -1; + } +} diff --git a/C.Samples/Benchmarks/Savage.cc b/C.Samples/Benchmarks/Savage.cc new file mode 100644 index 0000000..ec456db --- /dev/null +++ b/C.Samples/Benchmarks/Savage.cc @@ -0,0 +1,35 @@ +/*************************************************************** +* +* Savage +* +* Test the speed (and stability) of floating point functions. +* +* To get the best performance from the desktop development +* environment, be sure and turn debugging off from the +* Compile Dialog. Use the Compile command from the Run menu +* to get the compile dialog. +* +****************************************************************/ + +#pragma keep "Savage" +#pragma optimize -1 +#pragma lint -1 + +#define loop 250 + +#include +#include + +int main (void) + +{ +int i; +double sum; + +printf("Start...\n"); +sum = 1.0; +for (i = 1; i < loop; ++i) + sum = tan(atan(exp(log(sqrt(sum*sum)))))+1.0; +printf("sum = %e", sum); +return 0; +} diff --git a/C.Samples/CDA.Samples/Calendar.cc b/C.Samples/CDA.Samples/Calendar.cc new file mode 100644 index 0000000..411c54c --- /dev/null +++ b/C.Samples/CDA.Samples/Calendar.cc @@ -0,0 +1,288 @@ +/*************************************************************** +* +* Calendar +* +* This classic desk accessory shows the calendar for the +* current date. The arrow keys can be used to see calendars +* for previous or future months. +* +* Commands (each is a single keystroke) +* +* up-arrow Look at the same month in the previous +* year. +* down-arrow Look at the same month in the next +* year. +* left-arrow Look at the previous month. +* right-arrow Look at the next month. +* ? or / Display help screen. +* ESC Return to CDA main menu. +* +* Mike Westerfield +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +***************************************************************/ + +#pragma keep "Calendar" +#pragma cda "Calendar" Start ShutDown +#pragma lint -1 + +#include +#include +#include +#include + +#define LEFT_ARROW 0x08 /* key codes for legal commands */ +#define DOWN_ARROW 0x0A +#define UP_ARROW 0x0B +#define RIGHT_ARROW 0x15 +#define ESC 0x1B +#define SLASH '/' +#define QUESTION '?' + +int ch; /* ord of last character read */ +int month, year; /* current month and year */ + +/**************************************************************** +* +* Factor: Computes the 'factor' for the first day of the +* month. The factor is the number of days since +* 31 Dec 0000. +* +****************************************************************/ + +long Factor (long year, long month) + +{ +if (month < 2) + return 365 * year + 1 + 31 * month + (year - 1) / 4 - + ((year - 1) / 100 + 1) * 3 / 4; +return 365 * year + 1 + 31 * month - ((month + 1) * 4 + 23) / 10 + + year / 4 - (year / 100 + 1) * 3 / 4; +} + +/**************************************************************** +* +* GetKey: Returns the ordinal value of the next key typed +* by the user. +* +****************************************************************/ + +int GetKey (void) + +{ +char ch, *cp; + +cp = (char *) 0x00C000; /* wait for keypress */ +while ((*cp & 0x80) == 0) ; +ch = *cp; /* save the key */ +cp = (char *) 0x00C010; /* clear the strobe */ +*cp = 0; +return ch & 0x7F; /* return the key read */ +} + +/**************************************************************** +* +* GetThisMonth: Reads the clock to obtain today's month +* +****************************************************************/ + +void GetThisMonth (void) + +{ +time_t lt; /* encoded time */ +struct tm *ct; /* current time */ + +lt = time(NULL); /* get the coded time */ +ct = gmtime(<); /* convert to a decoded time */ +year = ct->tm_year + 1900; /* set the month/year */ +month = ct->tm_mon; +} + +/**************************************************************** +* +* GotoXY: Positions the cursor +* +****************************************************************/ + +void GotoXY (int x, int y) + +{ +putchar(0x1E); +putchar(0x20 + x); +putchar(0x20 + y); +} + +/**************************************************************** +* +* PrintCalendar: Prints the calendar for the current +* and year. +* +****************************************************************/ + +void PrintCalendar (void) + +{ +#define TAB 26 /* disp of calendar from left edge */ +#define VTAB 5 /* disp of calendar from top */ + +int startDay, /* day of week for 1st day in month */ + numDays, /* # days in the month */ + nextMonth, nextYear, /* work variables */ + i, /* loop variable */ + vt, /* line # for next line of days */ + pos; /* day position for next date */ + +/* Compute day of week for 1st day in month */ +startDay = (int) ((Factor (year, month) - 1) % 7); +nextMonth = month+1; /* compute # days in month */ +if (nextMonth == 12) { + nextMonth = 0; + nextYear = year+1; + } +else + nextYear = year; +numDays = (int) (Factor (nextYear, nextMonth) - Factor (year, month)); + +putchar(12); /* clear the screen */ +GotoXY(TAB+7, VTAB); /* position cursor */ +switch (month) { /* write the month */ + case 0: printf(" January "); break; + case 1: printf("February "); break; + case 2: printf(" March "); break; + case 3: printf(" April "); break; + case 4: printf(" May "); break; + case 5: printf(" June "); break; + case 6: printf(" July "); break; + case 7: printf(" August "); break; + case 8: printf("September "); break; + case 9: printf(" October "); break; + case 10: printf("November "); break; + case 11: printf("December "); + } +printf("%d", year); /* write the year */ +GotoXY(TAB, VTAB+2); /* write the day header line */ +printf("Sun Mon Tue Wed Thu Fri Sat"); +vt = VTAB+4; /* set current date line */ +pos = 0; /* set day position */ +GotoXY(TAB-1, vt); /* position cursor for 1st line */ +for (i = 1; i <= startDay; i++) { /* skip over blank days */ + pos++; + printf(" "); + } + +/* Write the dates */ +for (i = 1; i <= numDays; i++) { + printf("%4d", i); + pos++; + if (pos == 7) { + pos = 0; + vt += 2; + GotoXY(TAB-1, vt); + } + } +GotoXY(25, 23); /* write instructions */ +printf("Hit ? for help, or ESC to quit"); +} + +/**************************************************************** +* +* PrintHelp: Print the help screen. +* +****************************************************************/ + +void PrintHelp (void) + +{ +int ch; /* dummy variable for reading keyboard */ + +putchar(0x0C); /* clear screen */ +printf( "This program recognizes the following single-keystroke commands:" + "\n\n" + " key action\n" + " --- ------\n" + " up-arrow Show the current month in the previous year.\n" + " down-arrow Show the current month in the next year.\n" + " left-arrow Show the previous month.\n" + " right-arrow Show the next month.\n" + " ESC exit the program."); + +GotoXY(0, 23); +printf("Hit any key to return to the program."); +ch = GetKey(); +} + +/************************************************************** +* +* Start: Body of calendar program +* +**************************************************************/ + +void Start(void) + +{ +putchar('\006'); /* turn the cursor off */ +GetThisMonth(); /* find out what month it is */ +PrintCalendar(); /* print the calendar for this month */ +do { + ch = GetKey(); /* get a command */ + switch (ch) { + case LEFT_ARROW: { + month--; + if (month < 0) { + month = 11; + year--; + } + PrintCalendar(); + break; + } + + case RIGHT_ARROW: { + month++; + if (month > 11) { + month = 0; + year++; + } + PrintCalendar(); + break; + } + + case UP_ARROW: { + year--; + PrintCalendar(); + break; + } + + case DOWN_ARROW: { + year++; + PrintCalendar(); + break; + } + + case QUESTION: + case SLASH: { + PrintHelp(); + PrintCalendar(); + break; + } + + case ESC: return; + + default: + SysBeep(); + } + } +while (1); +} + +/************************************************************* +* +* ShutDown: Does nothing +* +*************************************************************/ + +void ShutDown(void) + +{ +} diff --git a/C.Samples/CDA.Samples/Echo.cc b/C.Samples/CDA.Samples/Echo.cc new file mode 100644 index 0000000..f37c960 --- /dev/null +++ b/C.Samples/CDA.Samples/Echo.cc @@ -0,0 +1,44 @@ +/**************************************************************** +* +* Echo +* +* This is about the simplest a classic desk accessory can be, +* providing a quick framework for developing your own. It +* simply reads strings typed from the keyboard and echos +* them back to the screen. +* +* Mike Westerfield +* +* Copyright 1989 +* Byte Works, Inc. +* +****************************************************************/ + +#pragma keep "Echo" +#pragma cda "Echo from C" Start ShutDown +#pragma lint -1 + +#include +#include + +char str[256]; + + +void Start(void) + +{ +printf("This program echoes the strings you type from the keyboard. To\n"); +printf("quit, hit the RETURN key at the beginning of a line.\n\n"); + +do { + fgets(str, 256, stdin); /* read a string */ + printf("%s\n", str); /* write the same string */ + } +while (strlen(str) > 1); /* quit if the string is empty */ +} + + +void ShutDown(void) + +{ +} diff --git a/C.Samples/CDev.Samples/WorldCDev.cc b/C.Samples/CDev.Samples/WorldCDev.cc new file mode 100644 index 0000000..3b97fb9 --- /dev/null +++ b/C.Samples/CDev.Samples/WorldCDev.cc @@ -0,0 +1,71 @@ +/****************************************************************/ +/* */ +/* Hello World CDev */ +/* */ +/* Mike Westerfield */ +/* October 1991 */ +/* */ +/* Copyright 1991 */ +/* Byte Works, Inc. */ +/* All Rights Reserved. */ +/* */ +/****************************************************************/ +/* */ +/* This CDev displays a text message. It can be used as a */ +/* framework for developing your own CDevs. */ +/* */ +/* For detailed information about CDevs, see Apple II File */ +/* Type Notes for file type $D8. Apple II File Type Notes */ +/* are available from major online services, large users */ +/* groups, or from APDA. */ +/* */ +/****************************************************************/ + +#pragma keep "worldobj" +#pragma cdev Driver +#pragma lint -1 + +#include +#include +#include + + +GrafPortPtr wPtr; /* our window pointer */ + + +/* DoAbout - Show the help info */ + +void DoAbout (void) + +{ +NewControl2(wPtr, 0x0009, 257L); /* draw the text (it's a stattext control) */ +} + + +/* DoCreate - Create the controls */ + +void DoCreate (void) + +{ +NewControl2(wPtr, 0x0009, 256L); /* create the controls */ +} + + + +/* Driver - main entry point */ + +long Driver (long data2, long data1, int message) + +#define createCDev 7 /* message numbers */ +#define aboutCDev 8 + +{ +wPtr = (void *) data1; /* get our window pointer (most calls) */ +switch (message) { + case createCDev: DoCreate(); + break; + case aboutCDev: DoAbout(); + break; + } +return 1; +} diff --git a/C.Samples/CDev.Samples/WorldCDev.make b/C.Samples/CDev.Samples/WorldCDev.make new file mode 100644 index 0000000..7f68f3d --- /dev/null +++ b/C.Samples/CDev.Samples/WorldCDev.make @@ -0,0 +1,3 @@ +cmpl +t +e -x worldcdev.cc +compile +t +e worldcdev.rez keep=WorldCDev +filetype WorldCDev $C7 diff --git a/C.Samples/CDev.Samples/WorldCDev.rez b/C.Samples/CDev.Samples/WorldCDev.rez new file mode 100644 index 0000000..604cad3 --- /dev/null +++ b/C.Samples/CDev.Samples/WorldCDev.rez @@ -0,0 +1,110 @@ +#include "types.rez" + +/* This is the required resource to tell the control panel about the CDev */ +resource rCDEVFlags (0x1) { + 0x00C0, + 1, + 1, + 1, + 0, + {0, 0, 110, 200}, + "Hello World", + "Mike Westerfield", + "1.0" + }; + +/* Code resource; the executable part of the CDev */ +read rCDevCode (0x1,convert) "worldobj"; + +/* This is the icon displayed by the control panel */ +resource rIcon (0x1) { + 0x8000, /* color icon */ + 20, /* height in pixels */ + 28, /* width in pixels */ + $"FFFFFFFFFFF1111111FFFFFFFFFF" + $"FFFFFFFF111111111111FFFFFFFF" + $"FFFFFF1111118881111881FFFFFF" + $"FFFFF111888888888818811FFFFF" + $"FFFF11118888888888118111FFFF" + $"FFF1111111888888811111111FFF" + $"FFF1111111888888111111111FFF" + $"FF111111111881181111111111FF" + $"FF111111111181111111111111FF" + $"FF111111111181111111111111FF" + $"FF111111118888881111111111FF" + $"FF111111118888888111111111FF" + $"FFF1111111888888811111111FFF" + $"FFF1111111188888111111111FFF" + $"FFFF11111111888811111111FFFF" + $"FFFFF111111118811111111FFFFF" + $"FFFFFF1111111181111111FFFFFF" + $"FFFFFFFF111111111111FFFFFFFF" + $"FFFFFFFFFF11111111FFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFF", + + $"00000000000FFFFFFF0000000000" + $"00000000FFFFFFFFFFFF00000000" + $"000000FFFFFFFFFFFFFFFF000000" + $"00000FFFFFFFFFFFFFFFFFF00000" + $"0000FFFFFFFFFFFFFFFFFFFF0000" + $"000FFFFFFFFFFFFFFFFFFFFFF000" + $"000FFFFFFFFFFFFFFFFFFFFFF000" + $"00FFFFFFFFFFFFFFFFFFFFFFFF00" + $"00FFFFFFFFFFFFFFFFFFFFFFFF00" + $"00FFFFFFFFFFFFFFFFFFFFFFFF00" + $"00FFFFFFFFFFFFFFFFFFFFFFFF00" + $"00FFFFFFFFFFFFFFFFFFFFFFFF00" + $"000FFFFFFFFFFFFFFFFFFFFFF000" + $"000FFFFFFFFFFFFFFFFFFFFFF000" + $"0000FFFFFFFFFFFFFFFFFFFF0000" + $"00000FFFFFFFFFFFFFFFFFF00000" + $"000000FFFFFFFFFFFFFFFF000000" + $"00000000FFFFFFFFFFFF00000000" + $"0000000000FFFFFFFF0000000000" + $"0000000000000000000000000000" + }; + +/* The following resources define the various controls in the main display */ +resource rControlList (256) { + { + 256, + }; + }; + +resource rControlTemplate (256) { + 0x00000001, /* control id */ + {38,5,49,205}, /* control rectangle */ + statTextControl {{ /* control type */ + 0x0000, /* flags */ + 0x1002, /* more flags */ + 0, /* ref con */ + 256, /* text reference */ + 13 /* text length */ + }}; + }; +resource rTextForLETextBox2 (256) { + "Hello, world." + }; + +/* The following resources define the controls for the help screen */ +resource rControlList (257) { + { + 257, + }; + }; + +resource rControlTemplate (257) { + 0x00000002, /* control id */ + {38,5,49,205}, /* control rectangle */ + statTextControl {{ /* control type */ + 0x0000, /* flags */ + 0x1002, /* more flags */ + 0, /* ref con */ + 257, /* text reference */ + 19 /* text length */ + }}; + }; +resource rTextForLETextBox2 (257) { + "Put help info here." + }; + diff --git a/C.Samples/Desktop.Samples/Clock.cc b/C.Samples/Desktop.Samples/Clock.cc new file mode 100644 index 0000000..f410179 --- /dev/null +++ b/C.Samples/Desktop.Samples/Clock.cc @@ -0,0 +1,163 @@ +/************************************************************** +* +* This desk accessory brings up a simple clock. It can be +* used as an outline when creating more complex desk accessories. +* +* Original Pascal version by Phil Montoya +* C Translation by Mike Westerfield +* +* Copyright 1987,1989 +* Byte Works, Inc. +* +**************************************************************/ + +#pragma keep "Clock" +#pragma nda Open Close Action Init 60 0xFFFF "--Clock\\H**" +#pragma lint -1 + +#include + +#include +#include +#include +#include +#include + +#define TRUE 1 /* boolean constants */ +#define FALSE 0 + +int clockActive = 0; /* are we already active flag */ +GrafPortPtr clockWinPtr; /* window pointer */ + +char title[] = "\pClock"; /* window title */ +ParamList clockWin = { /* new window record */ + 78, /* paramLength */ + 0xC0A0, /* wFrameBits */ + title, /* wTitle */ + 0L, /* wRefCon */ + {0,0,0,0}, /* wZoom */ + NULL, /* wColor */ + 0,0, /* wYOrigin,wXOrigin */ + 0,0, /* wDataH,wDataW */ + 0,0, /* wMaxH,wMaxW */ + 0,0, /* wScrollVer,wScrollHor */ + 0,0, /* wPageVer,wPageHor */ + 0, /* wInfoRefCon */ + 0, /* wInfoHeight */ + NULL, /* wFrameDefProc */ + NULL, /* wInfoDefProc */ + NULL, /* wContDefProc */ + {50,50,62,200}, /* wPosition */ + (void *) -1L, /* wPlane */ + NULL /* wStorage */ + }; + +/*************************************************************** +* +* DrawTime - Reads the time and draws it in the window +* +***************************************************************/ + +void DrawTime (void) + +{ +int i; /* index variable */ +char timeString[21]; /* string to hold time */ + +ReadAsciiTime(timeString); +timeString[20] = 0; +for (i = 0; i < 20; i++) + timeString[i] &= 0x7F; +MoveTo(7, 10); +DrawCString(timeString); +} + +/*************************************************************** +* +* Open - opens the desk accessory if it is not already active +* +* Outputs: +* GrafPortPtr - pointer to desk accessory window +* +***************************************************************/ + +GrafPortPtr Open (void) + +{ +if (!clockActive) { + clockWinPtr = NewWindow(&clockWin); /* open a window */ + SetSysWindow(clockWinPtr); /* set it to the system window */ + clockActive = TRUE; /* we are now active */ + return clockWinPtr; /* return our window pointer */ + } +} + +/*************************************************************** +* +* Close - closes the desk accessory if it is active +* +***************************************************************/ + +void Close(void) + +{ +if (clockActive) { + CloseWindow(clockWinPtr); + clockActive = FALSE; + } +} + +/*************************************************************** +* +* Action - Handle an action call +* +***************************************************************/ + +void Action (long param, int code) + +{ +EventRecordPtr evPtr; +GrafPortPtr currPort; + +switch (code) { + + case eventAction: { + evPtr = (EventRecordPtr) param; + if (evPtr->what == updateEvt) { + BeginUpdate(clockWinPtr); + DrawTime(); + EndUpdate(clockWinPtr); + } + return; + } + + case runAction: { + currPort = GetPort(); + SetPort(clockWinPtr); + DrawTime(); + SetPort(currPort); + return; + } + + default: + return; + + } +} + +/*************************************************************** +* +* Initialization +* +***************************************************************/ + +void Init(int code) + +{ +if (code == 0) { + if (clockActive) + Close(); + } +else + clockActive = FALSE; +} diff --git a/C.Samples/Desktop.Samples/Frame.cc b/C.Samples/Desktop.Samples/Frame.cc new file mode 100644 index 0000000..a7ce65c --- /dev/null +++ b/C.Samples/Desktop.Samples/Frame.cc @@ -0,0 +1,199 @@ +/**************************************************************** +* +* Frame +* +* This desktop program is about as simple as they get. It +* brings up the Apple menu, a file menu with Quit and Close, +* and an edit menu with Undo, Cut, Copy, Paste and Clear. +* This is the minimum configuration for supporting desk +* accessories. (All of these menus have pre-assigned numbers, +* assigned by Apple.) +* +* The purpose of this rather simple program is to show how +* easy a desktop program can be to write, and to give you a +* framework to use in developing your own programs. +* +* Mike Westerfield +* +* Copyright 1989 +* Byte Works, Inc. +* +****************************************************************/ + +#pragma keep "Frame" +#pragma lint -1 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define apple_About 257 /* Menu ID numbers */ +#define file_Quit 256 + +enum alertKind {norml, stop, note, caution}; /* kinds of alerts */ + +typedef int BOOL; /* simulate boolean types */ +BOOL done; /* tells if the program should stop */ +WmTaskRec lastEvent; /* last event returned in event loop */ + + +/**************************************************************** +* +* DoAlert - Create an alert box +* +* Input: +* kind - kind of alert +* msg - alert message +* +****************************************************************/ + +void DoAlert (enum alertKind kind, char *msg) + +{ +static ItemTemplate button = /* button item */ + { 1, 36, 15, 0, 0, buttonItem, "\pOK", 0, 0, NULL }; + +static ItemTemplate message = /* message item */ + { 100, 5, 100, 90, 280, itemDisable+statText, NULL, 0, 0, NULL }; + +static AlertTemplate alertRec = /* alert box */ + { 50, 180, 107, 460, 2, 0x80, 0x80, 0x80, 0x80, NULL, NULL, NULL }; + + +SetForeColor (0); /* set text colors */ +SetBackColor (15); + +message.itemDescr = msg; /* init. non-constant */ +alertRec.atItemList [0] = (ItemTempPtr) &button; /* template fields */ +alertRec.atItemList [1] = (ItemTempPtr) &message; + +switch (kind) { + case norml: Alert (&alertRec, NULL); + break; + + case stop: StopAlert (&alertRec, NULL); + break; + + case note: NoteAlert (&alertRec, NULL); + break; + + case caution: CautionAlert (&alertRec, NULL); + break; + + default: printf ("Error in DoAlert\n"); + exit (-1); + break; + } +} + + +/**************************************************************** +* +* MenuAbout - Create the About menu +* +****************************************************************/ + +void MenuAbout (void) + +{ +DoAlert (note, "\pFrame 1.0\r" + "Copyright 1989\r" + "Byte Works, Inc.\r\r" + "By Mike Westerfield"); +} + + +/**************************************************************** +* +* HandleMenu - Handle a menu selection +* +****************************************************************/ + +void HandleMenu (int menuNum) + +{ +switch (menuNum) { + case apple_About: MenuAbout (); + break; + + case file_Quit: done = TRUE; + break; + + default: break; + } +HiliteMenu (FALSE, (int) (lastEvent.wmTaskData >> 16)); +} + + +/**************************************************************** +* +* InitMenus - Initialize the menu bar +* +****************************************************************/ + +void InitMenus (void) + +{ +InsertMenu (NewMenu (">> Edit \\N3\r" /* create the edit menu */ + "--Undo\\N250V*Zz\r" + "--Cut\\N251*Xx\r" + "--Copy\\N252*Cc\r" + "--Paste\\N253*Vv\r" + "--Clear\\N254\r" + ".\r"), 0); + +InsertMenu (NewMenu (">> File \\N2\r" /* create the file menu */ + "--Close\\N255V\r" + "--Quit\\N256*Qq\r" + ".\r"), 0); + +InsertMenu (NewMenu (">>@\\XN1\r" /* create the Apple menu */ + "--About Frame\\N257V\r" + ".\r"), 0); + +FixAppleMenu (1); /* add desk accessories */ +FixMenuBar (); /* draw the completed menu bar */ +DrawMenuBar (); +} + + +/**************************************************************** +* +* Main Program +* +****************************************************************/ + +int main (void) + +{ +int event; /* event # returned by TaskMaster */ + +startdesk (640); +InitMenus (); /* set up the menu bar */ +lastEvent.wmTaskMask = 0x1FFFL; /* let Task Master do most stuff */ +ShowCursor (); /* show the cursor */ + +done = FALSE; /* main event loop */ +do { + event = TaskMaster (0x076E, &lastEvent); + switch (event) { /* handle the events we need to */ + case wInSpecial: + case wInMenuBar: HandleMenu ((int) lastEvent.wmTaskData); + default: break; + } + } +while (!done); +enddesk (); +} diff --git a/C.Samples/Desktop.Samples/MiniCAD.cc b/C.Samples/Desktop.Samples/MiniCAD.cc new file mode 100644 index 0000000..32d56be --- /dev/null +++ b/C.Samples/Desktop.Samples/MiniCAD.cc @@ -0,0 +1,374 @@ +/**************************************************************** +* +* MiniCAD +* +* MiniCAD is a (very) simple CAD program based on the Frame +* program. With MiniCAD, you can open new windows, close +* windows that are on the desktop, and draw lines using the +* mouse. Multiple windows are supported. +* +* Mike Westerfield +* +* Copyright 1989 +* Byte Works, Inc. +* +****************************************************************/ + +#pragma keep "MiniCAD" +#pragma lint -1 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define apple_About 257 /* Menu ID #s */ +#define file_Quit 256 +#define file_New 258 +#define file_Close 255 + +#define maxWindows 4 /* max # of drawing windows */ +#define maxLines 50 /* max # of lines in a window */ + +typedef int BOOL; /* simulate boolean types */ +typedef struct { Point p1, p2; } lineRecord; /* line defined by its endpts */ + + /* holds info about 1 window */ +struct windowRecord { GrafPortPtr wPtr; /* ptr to the window's port */ + char *name; /* name of the window */ + int numLines; /* # lines in this window */ + lineRecord lines [maxLines]; /* lines in drawing */ + }; + +enum alertKind {norml, stop, note, caution}; /* kinds of alerts */ + +BOOL done; /* tells if the program should stop */ +WmTaskRec lastEvent; /* last event returned in event loop */ + +static struct windowRecord windows [maxWindows] = /* drawing windows */ + { { NULL, "\pPaint 1" }, { NULL, "\pPaint 2" }, + { NULL, "\pPaint 3" }, { NULL, "\pPaint 4" } }; + +static ParamList wParms = /* parameters for NewWindow */ + { 78, 0xDDA7, NULL, 0, 0, 615, 25, 188, NULL, 0, 0, 0, 0, 0, 0, 10, 10, + 0, 0, 0, 0, NULL, NULL, NULL, 25, 0, 188, 615, NULL, NULL }; + +static ItemTemplate button = /* button item */ + { 1, 36, 15, 0, 0, buttonItem, "\pOK", 0, 0, NULL }; + +static ItemTemplate message = /* message item */ + { 100, 5, 100, 90, 280, itemDisable+statText, NULL, 0, 0, NULL }; + +static AlertTemplate alertRec = /* alert box */ + { 50, 180, 107, 460, 2, 0x80, 0x80, 0x80, 0x80, NULL, NULL, NULL }; + + +/**************************************************************** +* +* DoAlert - Create an alert box +* +* Input: +* kind - kind of alert +* msg - alert message +* +****************************************************************/ + +void DoAlert (enum alertKind kind, char *msg) + +{ +SetForeColor (0); /* set text colors */ +SetBackColor (15); + +message.itemDescr = msg; /* init. non-constant */ +alertRec.atItemList [0] = (ItemTempPtr) &button; /* template fields */ +alertRec.atItemList [1] = (ItemTempPtr) &message; + +switch (kind) { + case norml: Alert (&alertRec, NULL); + break; + + case stop: StopAlert (&alertRec, NULL); + break; + + case note: NoteAlert (&alertRec, NULL); + break; + + case caution: CautionAlert (&alertRec, NULL); + break; + + default: printf ("Error in DoAlert\n"); + exit (-1); + break; + } +} + + +#pragma databank 1 +/**************************************************************** +* +* DrawWindow - Draw the contents of the current window +* +****************************************************************/ + +void DrawWindow (void) + +{ +int i; /* window's index */ +int j; /* loop variable */ + +struct windowRecord *wp; /* work pointers */ +lineRecord *lp; + +i = GetWRefCon (GetPort()); +if (windows [i].numLines) { /* skip the work if there */ + /* aren't any lines */ + SetPenMode (modeCopy); /* set up to draw */ + SetSolidPenPat (0); + SetPenSize (2, 1); + wp = &windows [i]; /* draw each of the lines */ + for (j = 0; j < wp->numLines; ++j) { + lp = &(wp->lines [j]); + MoveTo (lp->p1.h, lp->p1.v); + LineTo (lp->p2.h, lp->p2.v); + } + } +} +#pragma databank 0 + + +/**************************************************************** +* +* DoClose - Close the front drawing window, if there is one +* +****************************************************************/ + +void DoClose (void) + +{ +int i; + +if (FrontWindow () != NULL) { + i = GetWRefCon (FrontWindow ()); + CloseWindow (windows [i].wPtr); + windows [i].wPtr = NULL; + EnableMItem (file_New); + } +} + + +/**************************************************************** +* +* MenuAbout - Create the About alert box +* +****************************************************************/ + +void MenuAbout (void) + +{ +DoAlert (note, "\pMini-CAD 1.0\r" + "Copyright 1989\r" + "Byte Works, Inc.\r\r" + "By Mike Westerfield"); +} + + +/**************************************************************** +* +* DoNew - Open a new drawing window +* +****************************************************************/ + +void DoNew (void) + +{ +int i; /* index variable */ + +i = 0; /* find an empty record */ +while (windows[i].wPtr != NULL) + ++i; +windows[i].numLines = 0; /* no lines drawn yet */ + +wParms.wTitle = (Pointer) windows[i].name; /* init. non-constant */ +wParms.wRefCon = i; /* wParms fields */ +wParms.wContDefProc = (VoidProcPtr) DrawWindow; +wParms.wPlane = (GrafPortPtr) topMost; + +windows[i].wPtr = NewWindow (&wParms); /* open the window */ +if (toolerror()) { + DoAlert (stop, "\pError opening the window."); + windows [i].wPtr = NULL; + } +else if (i == 3) /* don't allow more than 4 open windows */ + DisableMItem (file_New); +} + + +/**************************************************************** +* +* HandleMenu - Handle a menu selection +* +****************************************************************/ + +void HandleMenu (int menuNum) + +{ +switch (menuNum) { + case apple_About: MenuAbout(); + break; + + case file_Quit: done = TRUE; + break; + + case file_New: DoNew (); + break; + + case file_Close: DoClose (); + } +HiliteMenu (FALSE, (int) (lastEvent.wmTaskData >> 16)); +} + + +/**************************************************************** +* +* InitMenus - Initialize the menu bar +* +****************************************************************/ + +void InitMenus (void) + +{ +InsertMenu (NewMenu (">> Edit \\N3\r" /* create the edit menu */ + "--Undo\\N250V*Zz\r" + "--Cut\\N251*Xx\r" + "--Copy\\N252*Cc\r" + "--Paste\\N253*Vv\r" + "--Clear\\N254\r" + ".\r"), 0); + +InsertMenu (NewMenu (">> File \\N2\r" /* create the file menu */ + "--New\\N258*Nn\r" + "--Close\\N255V\r" + "--Quit\\N256*Qq\r" + ".\r"), 0); + +InsertMenu (NewMenu (">>@\\XN1\r" /* create the Apple menu */ + "--About...\\N257V\r" + ".\r"), 0); + +FixAppleMenu (1); /* add desk accessories */ +FixMenuBar (); /* draw the completed menu bar */ +DrawMenuBar (); +} + + +/**************************************************************** +* +* Sketch - Track the mouse, drawing lines to connect the points +* +****************************************************************/ + +void Sketch (void) + +{ +Point endPoint; /* the end point of the line */ +Point firstPoint; /* the initial point */ +int i; /* window index */ +int numLines; /* copy of windows [i].numLines */ +EventRecord sEvent; /* last event returned in event loop */ + +/* get the window's index */ +i = GetWRefCon (FrontWindow()); + +/* check for too many lines */ +if (windows [i].numLines == maxLines) + DoAlert (stop, "\pThe window is full -\rmore lines cannot be\radded."); +else { + /* initialize the pen */ + StartDrawing (FrontWindow()); + SetSolidPenPat (15); + SetPenSize (2, 1); + SetPenMode (modeXOR); + + /* record the initial pen location */ + firstPoint = lastEvent.where; + GlobalToLocal (&firstPoint); + MoveTo (firstPoint.h, firstPoint.v); + LineTo (firstPoint.h, firstPoint.v); + endPoint = firstPoint; + + /* follow the pen, rubber-banding the line */ + while (!GetNextEvent (mUpMask, &sEvent)) { + GlobalToLocal (&sEvent.where); + if ((endPoint.h != sEvent.where.h) || (endPoint.v != sEvent.where.v)) { + MoveTo (firstPoint.h, firstPoint.v); + LineTo (endPoint.h, endPoint.v); + MoveTo (firstPoint.h, firstPoint.v); + LineTo (sEvent.where.h, sEvent.where.v); + endPoint.h = sEvent.where.h; + endPoint.v = sEvent.where.v; + } + } + + /* erase the last XORed line */ + MoveTo (firstPoint.h, firstPoint.v); + LineTo (endPoint.h, endPoint.v); + + /* if we have a line (not a point), record it in window's line list */ + if ((firstPoint.h != endPoint.h) || (firstPoint.v != endPoint.v)) { + numLines = windows[i].numLines++; + windows [i].lines [numLines].p1 = firstPoint; + windows [i].lines [numLines].p2 = endPoint; + SetPenMode (modeCopy); + SetSolidPenPat (0); + MoveTo (firstPoint.h, firstPoint.v); + LineTo (endPoint.h, endPoint.v); + } + } +} + + +/**************************************************************** +* +* Program begins here +* +****************************************************************/ + +int main (void) + +{ +int event; /* event #; returned by TaskMaster */ + +startdesk (640); +InitMenus (); /* set up the menu bar */ +lastEvent.wmTaskMask = 0x1FFFL; /* let task master do most stuff */ +ShowCursor (); /* show the cursor */ + +done = FALSE; /* main event loop */ +do { + event = TaskMaster (0x076E, &lastEvent); + switch (event) { /* handle the events we need to */ + case wInSpecial: + case wInMenuBar: HandleMenu ((int) lastEvent.wmTaskData); + break; + + case wInGoAway : DoClose (); + break; + + case wInContent: Sketch (); + } + } +while (!done); +enddesk (); +return 0; +} diff --git a/C.Samples/Desktop.Samples/Reversi.cc b/C.Samples/Desktop.Samples/Reversi.cc new file mode 100644 index 0000000..bd6b334 --- /dev/null +++ b/C.Samples/Desktop.Samples/Reversi.cc @@ -0,0 +1,1627 @@ +/****************************************************************** +* +* Reversi +* +* A desktop program for the Apple IIGS. +* +* Reversi is a board game played between two players. This +* program will play against an opponent (probably you, but you +* could play it against another program), or it will play +* itself (useful when you are learning). +* +* To play the game, the black piece goes first; the human +* plays black by default (the game allows this to be changed). +* The object of the game is to try to trap enemy pieces +* between one of your existing pieces and the new piece to +* be played. +* +* The game is so popular and well known that there are several +* commercial versions available, and all come with rules and +* basic strategy hints. Many fine books are also available +* from your local book store. When looking, you should note +* that the game is also sold under the name Othello. +* +* The program itself is provided as a real-world example of +* using the desktop. Unlike the other samples on this disk, +* this program was designed as a working game, not as a +* sample. For that reason, some problems that can be avoided +* by careful choice of a sample are handled here - like +* scrolling without the help of TaskMaster (to avoid scrolling +* a small part of the Moves window). +* +* To learn how the program works, start with the main event +* loop at the end of the program, and examine how it handles +* each event. The move selection procedure, FindMove, is the +* only place where an event loop is not used. That function +* uses a technique called an alpha-beta search to find the best +* move. To understand that search, you may refer to text books +* on artificial intelligence, or to any one of several fine +* articles, mostly dealing with chess, that appeared in Byte +* Magazine in the early 1980's. +* +* Note that the program is contained in two files: the first +* part of the source program is in the file named +* REVERSI1.CC, while the second part of the source is in the +* file named REVERSI2.CC. The ORCA/C append command is used +* at the end of the first file to automatically begin +* compilation of the second source file. +* +* Original Pascal version by Mike Westerfield +* +* C translation by Barbara Allred +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +*******************************************************************/ + +#pragma keep "Reversi" +#pragma lint -1 + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define squareWidth 52 /* width of one square */ +#define squareHeight 20 /* height of one square */ + +#define blank 0 /* square colors */ +#define blackPiece 1 +#define whitePiece 2 +#define border 3 + +#define apple_AboutReversi 257 /* menu names/numbers */ + +#define file_NewGame 258 +#define file_Quit 259 + +#define edit_UndoLastMove 270 +#define edit_Cut 271 +#define edit_Copy 272 +#define edit_Paste 273 +#define edit_Clear 274 + +#define level_1Ply 262 +#define level_2Ply 263 +#define level_3Ply 264 +#define level_4Ply 265 +#define level_5Ply 266 +#define level_6Ply 267 +#define level_7Ply 268 +#define level_8Ply 269 + +#define options_SelfPlay 280 +#define options_ComputerPlaysWhite 281 +#define options_Pass 282 +#define options_ShowScoreWindow 283 +#define options_ShowMovesWindow 284 + + +typedef int BOOL; /* simulate boolean types */ + +enum alertKind { norml, stop, note, caution }; /* kinds of alerts */ + /* move list: */ +struct moveListType { int num; /* #legal moves */ + char moves [60]; }; /* list of moves */ + + +/* Global variables */ + +static int ply = 1; /* set initial playing level to 1 */ +static int color = whitePiece; /* color the computer plays */ +static int currentColor; /* color to move next */ +static int movesMade; /* # moves, by playing level, made */ +static int topMove; /* 1st visible move in moves list */ +static int event; /* event #; returned by TaskMaster */ +static int moveHeight; /* current height of move window */ +static int charHeight; /* size of a character */ +static int moves [61]; /* list of moves made */ + +static int disp [8] = /* move displacements */ +{ 9, 10, 11, -1, 1, -9, -10, -11 }; + +static int bSc [300] = /* square scores for 3 portions of game */ +{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 500, -20, + 100, 50, 50, 100, -20, 500, 0, 0, -20, -250, -2, -2, -2, + -2, -250, -20, 0, 0, 100, -2, 30, 10, 10, 30, -2, 100, + 0, 0, 50, -2, 10, 2, 2, 10, -2, 50, 0, 0, 50, + -2, 10, 2, 2, 10, -2, 50, 0, 0, 100, -2, 30, 10, + 10, 30, -2, 100, 0, 0, -20, -250, -2, -2, -2, -2, -250, + -20, 0, 0, 500, -20, 100, 50, 50, 100, -20, 500, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 500, -20, 200, 50, 50, 200, + -20, 500, 0, 0, -20, -250, 15, 10, 10, 15, -250, -20, 0, + 0, 200, 15, 35, 20, 20, 35, 15, 200, 0, 0, 50, 10, + 20, 15, 15, 20, 10, 50, 0, 0, 50, 10, 20, 15, 15, + 20, 10, 50, 0, 0, 200, 15, 35, 20, 20, 35, 15, 200, + 0, 0, -20, -250, 15, 10, 10, 15, -250, -20, 0, 0, 500, + -20, 200, 50, 50, 200, -20, 500, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 400, -20, 100, 75, 75, 100, -20, 400, 0, 0, + -20, -300, 60, 10, 10, 60, -300, -20, 0, 0, 100, 60, 50, + 5, 5, 50, 60, 100, 0, 0, 75, 10, 5, 30, 30, 5, + 10, 75, 0, 0, 75, 10, 5, 30, 30, 5, 10, 75, 0, + 0, 100, 60, 50, 5, 5, 50, 60, 100, 0, 0, -20, -300, + 60, 10, 10, 60, -300, -20, 0, 0, 400, -20, 100, 75, 75, + 100, -20, 400 }; + +static BOOL done; /* are we done yet? */ +static BOOL selfPlay; /* computer-human or computer-computer */ +static BOOL movesLeft; /* are there legal moves left? */ +static BOOL updateMoves; /* does entire list need updating? */ +static BOOL showScoreWindow; /* is scoreWindow visible? */ +static BOOL showMovesWindow; /* is movesWindow visible? */ +static BOOL movesNotFront; /* is Moves window the front window? */ + +static char board [100]; /* main game board */ +static char msg [256]; /* for builing alert strings */ + + /* strings for SetItem calls */ +static char selfPlayStr [] = "--Self Play"; +static char computerPlayStr [] = "--Play Computer"; +static char computerPlaysBlack [] = "--Computer Plays Black"; +static char computerPlaysWhite [] = "--Computer Plays White"; + +static WmTaskRec lastEvent; /* last event returned in event loop */ + +static ParamList wParms = /* parameters for NewWindow */ + { 78, 0x80E4, NULL, 0, 0, 0, 0, 0, NULL, 0, 0, squareHeight * 8, + squareWidth * 8, squareHeight * 8, squareWidth * 8, 0, 0, 0, 0, 0, 0, + NULL, NULL, NULL, 32, 32, 32 + squareHeight * 8, 32 + squareWidth * 8, + (GrafPortPtr) topMost, NULL }; +static ParamList boardParms, scoreParms, movesParms; /* window parameter */ + /* records */ + +static GrafPortPtr boardWindow; /* pointer to the game board window */ +static GrafPortPtr scoreWindow; /* pointer to the score window */ +static GrafPortPtr movesWindow; /* pointer to the Moves window */ + +static CtlRecHndl growHandle; /* Moves window's grow box */ +static CtlRecHndl vScrollHandle; /* Moves window's vertical scroll bar */ + + +/* Utility routines */ + +/**************************************************************** +* +* DoAlert - Create an alert box +* +* Input: +* kind - kind of alert +* msg - alert message +* +****************************************************************/ +void DoAlert (enum alertKind kind, char *msg) +{ +static ItemTemplate button = /* button item */ + { 1, 36, 15, 0, 0, buttonItem, "\pOK", 0, 0, NULL }; + +static ItemTemplate message = /* message item */ + { 100, 5, 100, 90, 280, itemDisable+statText, NULL, 0, 0, NULL }; + +static AlertTemplate alertRec = /* alert box */ + { 50, 180, 107, 460, 2, 0x80, 0x80, 0x80, 0x80, NULL, NULL, NULL }; + + +SetForeColor (0); /* set text colors */ +SetBackColor (15); + +message.itemDescr = msg; /* init. non-constant */ +alertRec.atItemList [0] = (ItemTempPtr) &button; /* template fields */ +alertRec.atItemList [1] = (ItemTempPtr) &message; + +switch (kind) { + case norml: Alert (&alertRec, NULL); + break; + + case stop: StopAlert (&alertRec, NULL); + break; + + case note: NoteAlert (&alertRec, NULL); + break; + + case caution: CautionAlert (&alertRec, NULL); + break; + + default: printf ("Error in DoAlert\n"); + exit (-1); + break; + } +} /* DoAlert */ + + +/**************************************************************** +* +* Even - Returns an even number by incrementing odd parameters; +* for move list calculations +* +* Input: +* i - integer tested for being even +* +* Output: +* i if i is even; i+1 if i is odd +* +****************************************************************/ +int Even (int i) +{ +if (i & 0x0001) + return i+1; +else + return i; +} /* Even */ + + +/* Routines involved in playing the game */ + +/**************************************************************** +* +* Plot - Plot a point +* +* Input: +* h - horizontal pixel of point +* v - vertical pixel of point +* +****************************************************************/ +void Plot (int h, int v) +{ +MoveTo (h, v); +LineTo (h, v); +} /* Plot */ + + +/**************************************************************** +* +* DrawSquare - Draw a square on the game board +* +* Input: +* square - number of square to draw +* col - color of square to draw +* +****************************************************************/ +void DrawSquare (int square, int col) +{ +#define penBlack 0 /* pen colors */ +#define penGreen 2 +#define penWhite 3 + +Rect r; /* square's rectangle */ + +StartDrawing (boardWindow); /* draw to our window */ +r.h2 = (square % 10) * squareWidth - 1; /* set up square's rectangle */ +r.v2 = (square / 10) * squareHeight - 1; +r.h1 = r.h2 - squareWidth + 1; +r.v1 = r.v2 - squareHeight + 1; + +SetSolidPenPat (penGreen); /* draw background of square */ +PaintRect (&r); +SetSolidPenPat (penBlack); /* draw edge of square */ +MoveTo (r.h1, r.v2); +LineTo (r.h2, r.v2); +LineTo (r.h2, r.v1); + +switch (square) { /* draw "corner" dots, if required */ + + case 22: case 26: case 62: case 66: + Plot (r.h2-1, r.v2-1); + break; + + case 23: case 27: case 63: case 67: + Plot (r.h1, r.v2-1); + break; + + case 32: case 36: case 72: case 76: + Plot (r.h2-1, r.v1); + break; + + case 33: case 37: case 73: case 77: + Plot (r.h1, r.v1); + break; + + default: + break; + } + +if (col != blank) { /* draw the piece, if any */ + if (col == whitePiece) + SetSolidPenPat (penWhite); + PaintOval (&r); + } +} /* DrawSquare */ + + +/**************************************************************** +* +* DrawBoard - Draw (or redraw) the entire game board +* +****************************************************************/ + +void DrawBoard (void) +{ +int i; /* loop variable */ +int col; /* column # */ + +for (i = 11; i <= 88; i++) { + col = i % 10; + if ((col != 0) && (col != 9)) + DrawSquare (i, board[i]); + } +} /* DrawBoard */ + + +/**************************************************************** +* +* GetMoves - Create a list of legal moves +* +* Input: +* board - game board to search for moves +* color - color of piece for which conducting search +* moveList - record of moves to make +* +****************************************************************/ +void GetMoves (char board[], int color, struct moveListType *moveList) +{ +int index; /* square being checked */ +int tindex; /* work index */ +int enemyColor = color ^ 3; /* temp variable for enemy color */ +int dir; /* direction being checked */ +struct moveListType lMoveList; /* local move list - for efficiency */ + +lMoveList.num = 0; /* no moves so far */ +for (index = 11; index < 90; index++) { /* loop over all squares */ + + if (board[index] == blank) /* check only empty squares */ + + for (dir = 0; dir < 8; dir++) { /* loop in all 8 directions */ + tindex = index + disp[dir]; /* see if there's a capture */ + if (board[tindex] == enemyColor) { /* in this direction */ + while (board[tindex] == enemyColor) /* skip enemy pieces */ + tindex += disp[dir]; + if (board[tindex] == color) { /* if last piece is ours, */ + /* move is legal */ + lMoveList.moves [lMoveList.num] = index; + lMoveList.num++; + goto Out; + } + } + } +Out: ; + } +*moveList = lMoveList; /* return move list */ +} /* GetMoves */ + + +/**************************************************************** +* +* CheckForDone - Check if game is over +* +****************************************************************/ +void CheckForDone (void) +{ +struct moveListType moveList; /* for checking # of moves */ +char string [10]; /* for converting scores to strings*/ +int wcnt, bcnt; /* # pieces for each side */ +int i; /* loop variable */ + +GetMoves (board, whitePiece, &moveList); +if (! moveList.num) { + GetMoves (board, blackPiece, &moveList); + if (! moveList.num) { + for (i = 11, wcnt = 0, bcnt = 0; i < 90; i++) { + if (board[i] == whitePiece) + wcnt++; + else if (board[i] == blackPiece) + bcnt++; + } + if (wcnt == bcnt) + strcpy (msg, "The game is overs. It\ris a draw."); + + else { + if (wcnt > bcnt) + strcpy (msg, "White"); + else + strcpy (msg, "Black"); + strcat (msg, " wins by a score\rof "); + sprintf (string, "%d", bcnt); /* convert scores to strings */ + strcat (msg, string); + strcat (msg, " to "); + sprintf (string, "%d", wcnt); + strcat (msg, string); + } + DoAlert (note, c2pstr (msg)); + movesLeft = false; + } + } +} /* CheckForDone */ + + +/**************************************************************** +* +* ScoreEdge - Score an edge of the game board by these rules: +* +* 1. An edge must have at least one empty square to be scored. +* 2. If there is a single space between friendly pieces, score -100. +* 3. If there are two spaces between friendly pieces, score 30. +* 4. If there are three spaces between friendly pieces, score -50. +* 5. If there is a solid line of enemy pieces between friendly +* pieces, score -150; +* +* Input: +* edge - array of edge squares to score +* +* Output: +* score of edges +* +****************************************************************/ +int ScoreEdge (int edge[]) +{ +BOOL atLeastOneBlank; /* for checking rule #1 */ +int s = 0, rs; /* for computing scores */ +int enemyColor; /* temp variable for enemy color */ +int i, j; /* loop variables */ + +atLeastOneBlank = false; /* check rule 1 */ +for (i = 1; i < 9; i++) + atLeastOneBlank = atLeastOneBlank || (edge[i] == blank); + +if (atLeastOneBlank) /* check all edge */ + for (i = 1; i < 8; i++) /* positions */ + if ((edge[i] == blackPiece) || (edge[i] == whitePiece)) { + enemyColor = edge[i] ^ 3; + j = i + 1; + if (edge[j] == enemyColor) { /* check rule 5 */ + while (edge[j] == enemyColor) + j++; + if (edge[j] == edge[i]) + if (enemyColor == whitePiece) + s -= 150; + else + s += 150; + } + else if (edge[j] == blank) { /* check rules 2..4 */ + while (edge[j] == blank) + j++; + if (edge[j] == edge[i]) { + switch (j - i) { + case 2: rs = -100; /* score rule 2 */ + break; + + case 3: rs = 30; /* score rule 3 */ + break; + + case 4: rs = -50; /* score rule 4 */ + break; + + default: break; + } + + if (edge[i] == whitePiece) + s -= rs; + else + s += rs; + } /* if */ + } /* else if */ + } /* if */ + return s; +} /* ScoreEdge */ + + +/**************************************************************** +* +* Score - Score the game board passed +* +* Input: +* board - game board to score +* +* Output: +* score of game board +* +****************************************************************/ +int Score (char board[]) +{ +int s = 0, rs; /* temp variables for scoring */ +int pi; /* game portion index */ +int numPieces = 0; /* # pieces on board */ +int edge [10]; /* for scoring edges */ +int i; /* loop variable */ + +for (i = 11; i < 90; i++) /* loop over all squares */ + if (board[i] == whitePiece) { /* add 4 for black, decrement */ + s -= 4; /* 4 for white */ + numPieces++; + } + else if (board[i] == blackPiece) { + s += 4; + numPieces++; + } + +if (numPieces < 24) /* set index into board scores */ + pi = 0; /* by part of game this is */ +else if (numPieces < 44) + pi = 100; +else + pi = 200; + +for (i = 11; i < 90; i++) /* loop over all squares, */ + /* summing square values */ + if ((board[i] == blackPiece) || (board[i] == whitePiece)) { + + if ((i == 12) || (i == 21) || (i == 22)) /* squares adjacent to corners */ + { /* get special treatment */ + if ((board[11] == blackPiece) || (board[11] == whitePiece)) + rs = 10; + else + rs = bSc[pi+i]; + } + + else if ((i == 17) || (i == 27) || (i == 28)) { + if ((board[18] == blackPiece) || (board[18] == whitePiece)) + rs = 10; + else + rs = bSc[pi+i]; + } + + else if ((i == 71) || (i == 72) || (i == 82)) { + if ((board[81] == blackPiece) || (board[81] == whitePiece)) + rs = 10; + else + rs = bSc[pi+i]; + } + + else if ((i == 77) || (i == 78) || (i == 87)) { + if ((board[88] == blackPiece) || (board[88] == whitePiece)) + rs = 10; + else + rs = bSc[pi+i]; + } + + else + rs = bSc[pi+i]; + + if (board[i] == whitePiece) + s -= rs; + else + s += rs; + } + +for (i = 0; i < 10; i++) /* score top edge */ + edge[i] = board[10+i]; +s += ScoreEdge (edge); + +for (i = 0; i < 10; i++) /* score bottom edge */ + edge[i] = board[i+80]; +s += ScoreEdge (edge); + +for (i = 0; i < 10; i++) /* score left edge */ + edge[i] = board[1+i*10]; +s += ScoreEdge (edge); + +for (i = 0; i < 10; i++) /* score right edge */ + edge[i] = board[8+i*10]; +s += ScoreEdge (edge); + +return s; /* return the score */ +} /* Score */ + + +/**************************************************************** +* +* MakeAMove - Make a move on the main playing board +* +* Input: +* index - board index of move to make +* col - color of player making move +* +****************************************************************/ +void MakeAMove (int index, int col) +{ +#define pause 100 /* index for pause */ + +int dir; /* loop variable for directions */ +int tindex; /* temp index; for captures */ +int enemyColor; /* temp variable for enemy color */ +int i; /* loop variable */ + +moves[++movesMade] = index; /* record the move */ +DrawSquare (index, col); /* flash the piece played */ +for (i = 0; i < pause; i++) + ; +DrawSquare (index, blank); +for (i = 0; i < pause; i++) + ; +DrawSquare (index, col); + +board[index] = col; /* make the move on the board */ +enemyColor = col ^ 3; /* set enemy color */ +for (dir = 0; dir < 8; dir++) { /* loop in all 8 directions */ + tindex = index + disp[dir]; /* see if there's a capture */ + if (board[tindex] == enemyColor) { /* in this direction */ + + while (board[tindex] == enemyColor) /* skip enemy pieces */ + tindex += disp[dir]; + + if (board[tindex] == col) { /* if last piece is ours, capture */ + tindex = index + disp[dir]; + + while (board[tindex] != col) { + DrawSquare (tindex, col); + board[tindex] = col; + tindex += disp[dir]; + } /* while */ + } /* if */ + } /* if */ + } /* for */ +} /* MakeAMove */ + + +/**************************************************************** +* +* EndScore - Compute an end-game score (no more moves) for passed board +* +* Input: +* board - game board to score +* +* Output: +* score of game board passed +* +****************************************************************/ +int EndScore (char board[]) +{ +int s = 0; /* work copy of score */ +int i; /* loop variable */ + +for (i = 11; i < 90; i++) /* count difference in pieces */ + if (board[i] == whitePiece) + s--; + else if (board[i] == blackPiece) + s++; + +if (s < 0) /* set the return value */ + return INT_MIN + 65 + s; +else if (s > 0) + return INT_MAX - 65 + s; +else + return 0; +} /* EndScore */ + + +static char boardName [] = "\pReversi"; /* names of Reversi's windows */ +static char scoreName [] = "\pScores"; +static char movesName [] = "\pMoves"; + + +/**************************************************************** +* +* ScoreMove - Find the score for a particular move +* +* Input: +* board - game board to make move on +* index - move to make +* s - best score at previous level +* col - color computer is playing +* level - current playing level +* +* Output: +* score for chosen move +* +****************************************************************/ +int ScoreMove (char board[], int index, int s, int col, int level) +{ +int bscore; /* best score from this level */ +int bmove; /* best move from this level */ +int enemyColor; /* color of the enemy peices */ +int dir; /* direction loop variable */ +int tindex; /* temp board index; for captures */ +int i; /* loop variable */ +struct moveListType moveList; /* list of legal moves */ +char lBoard [100]; /* local copy of game board */ + +/* Make the move passed */ + +memcpy (lBoard, board, 100); /* make local copy of passed board */ + +enemyColor = col ^ 3; /* set enemy color */ +if (index) { /* if there was a move, make it */ + lBoard[index] = col; /* make the move on the board */ + for (dir = 0; dir < 8; dir++) { /* loop in all 8 directions */ + tindex = index + disp[dir]; /* see if there's a capture in */ + if (lBoard[tindex] == enemyColor) { /* this direction */ + while (lBoard[tindex] == enemyColor) /* skip enemy pieces */ + tindex += disp[dir]; + if (lBoard[tindex] == col) { /* if last piece is ours, capture */ + tindex = index + disp[dir]; + while (lBoard[tindex] != col) { + lBoard[tindex] = col; + tindex += disp[dir]; + } + } /* if */ + } /* if */ + } /* for */ + } /* if */ + + +/* Part 2: Score the board */ + +if (level == ply) /* if at max depth, score is static */ + return Score (lBoard); + +else { /* else pick from available moves */ + GetMoves (lBoard, enemyColor, &moveList); /* get a list of legal moves */ + if (enemyColor == whitePiece) /* init. score is worst possible, so */ + bscore = INT_MAX; /* that any alternative is selected */ + else + bscore = INT_MIN; + if (! moveList.num) { /* if no moves, check for end of game */ + GetMoves (lBoard, col, &moveList); + if (! moveList.num) + bscore = EndScore (lBoard); + else + bscore = ScoreMove (lBoard, 0, bscore, enemyColor, level+1); + } + + else { + for (i = 0; i < moveList.num; i++) { /* scan/score available moves */ + s = ScoreMove (lBoard, moveList.moves[i], bscore, enemyColor, + level+1); + if (enemyColor == whitePiece) { /* if this is the best so far, */ + /* remember the move */ + if (s < bscore) { + bscore = s; + bmove = moveList.moves[i]; + } + } + else { + if (s > bscore) { + bscore = s; + bmove = moveList.moves[i]; + } + } /* else */ + } /* for */ + } /* else */ + return bscore; + } /* else */ +} /* ScoreMove */ + + +/**************************************************************** +* +* FindMove - Make a computer-generated move +* +* Input: +* col - color computer is playing +* +****************************************************************/ +void FindMove (int col) +{ +struct moveListType moveList; /* list of legal moves */ +int bmove; /* best move from this level */ +int bscore; /* best score from this level */ +int s; /* work copy of score */ +int i; /* loop variable */ + +WaitCursor (); /* change to the watch cursor */ +GetMoves (board, col, &moveList); /* get a list of legal moves */ +if (moveList.num == 1) /* if there's only 1 move, make it */ + MakeAMove (moveList.moves[0], col); +else if (moveList.num > 1) { /* if there's more than 1, initial */ + if (col == whitePiece) /* score is worst possible, so */ + bscore = INT_MAX; /* any alternative is selected */ + else + bscore = INT_MIN; + + for (i = 0; i < moveList.num; i++) { /* scan/score available moves */ + s = ScoreMove (board, moveList.moves[i], bscore, col, 1); + if (col == whitePiece) { + if (s < bscore) { /* if this is best so far, */ + bscore = s; /* remember the move */ + bmove = moveList.moves[i]; + } + } + else { /* if color is black then */ + if (s > bscore) { + bscore = s; + bmove = moveList.moves[i]; + } + } + } + MakeAMove (bmove, col); /* make the best move found */ + } + +else { /* no legal moves */ + strcpy (msg, "\pI cannot move, so I\rmust pass.\r"); + InitCursor (); + DoAlert (note, msg); + WaitCursor (); + } + +InitCursor (); /* back to the arrow cursor */ +CheckForDone (); +} /* FindMove */ + + +/**************************************************************** +* +* NewGame - Set up the board for a new game +* +****************************************************************/ +void NewGame (void) +{ +Rect r; /* rectangle for clearing Moves window */ +GrafPortPtr port; /* graph port pointer */ +int i; /* loop variable */ +int col, row; /* row, column numbers */ + +static void DrawMoves (void); /* subroutines called by NewGame */ +static void DrawScore (void); + +/* Write the contents of the Scores window */ + +for (i = 0; i < 100; i++) { /* initialize the game board */ + col = i % 10; + row = i / 10; + if ((!row) || (!col) || (row == 9) || (col == 9)) + board[i] = border; + else + board[i] = blank; + } +board[44] = whitePiece; board[55] = whitePiece; +board[45] = blackPiece; board[54] = blackPiece; + +currentColor = blackPiece; /* black moves first */ +movesLeft = true; /* the game is not over yet... */ +movesMade = 0; /* empty the moves list */ +topMove = 1; /* first visible move in moves list */ +updateMoves = true; /* draw entire list */ + +if (showMovesWindow) { /* if move list is visible, clear it */ + port = GetPort (); /* save the graph port */ + StartDrawing (movesWindow); /* draw to the Moves window */ + GetPortRect (&r); /* get the rectangle */ + EraseRect (&r); /* erase the window's contents */ + DrawControls (movesWindow); /* draw the controls */ + SetPort (port); /* restore the old graph port */ + DrawMoves (); /* draw the pieces */ + } +if (showScoreWindow) + DrawScore (); /* redraw the Scores window */ +} /* NewGame */ + + +/* Initialization routines */ + + +/**************************************************************** +* +* InitMenus - Create and draw the initial menu bar +* +****************************************************************/ +void InitMenus (void) +{ +InsertMenu (NewMenu (">> Options \\N5\r" /* create the Options menu */ + "--Self Play\\N280\r" + "--Computer Plays Black\\N281\r" + "---\\N514D\r" + "--Pass\\N282\r" + "--Show Score Window\\N283\r" + "--Show Moves Window\\N284\r" + ".\r"), 0); + +InsertMenu (NewMenu (">> Level \\N4\r" /* create the Level menu */ + "--1 Ply\\N262\r" + "--2 Ply\\N263\r" + "--3 Ply\\N264\r" + "--4 Ply\\N265\r" + "--5 Ply\\N266\r" + "--6 Ply\\N267\r" + "--7 Ply\\N268\r" + "--8 Ply\\N269\r" + ".\r"), 0); + +InsertMenu (NewMenu (">> Edit \\N3\r" /* create the Edit menu */ + "--Undo Last Move\\N270D*Zz\r" + "---\\N512D\r" + "--Cut\\N271D*Xx\r" + "--Copy\\N272D*Cc\r" + "--Paste\\N273D*Vv\r" + "--Clear\\N274D\r" + ".\r"), 0); + +InsertMenu (NewMenu (">> File \\N2\r" /* create the File menu */ + "--New Game\\N258*Nn\r" + "---\\N513D\r" + "--Quit\\N259*Qq\r" + ".\r"), 0); + +InsertMenu (NewMenu (">>@\\XN1\r" /* create the Apple menu */ + "--About Reversi\\N257\r" + "---\\N513D\r" + ".\r"), 0); + +FixAppleMenu (1); /* add desk accessories */ +FixMenuBar (); /* draw the completed menu bar */ +DrawMenuBar (); +CheckMItem (true, level_1Ply); /* check ply 1 */ +} /* InitMenus */ + + +/**************************************************************** +* +* InitVariables - Initialize global variables +* +****************************************************************/ +void InitVariables (void) +{ +Rect r; /* rectangle for finding height of chars */ + +CharBounds ('A', &r); /* find the height of a character */ +charHeight = r.h2 - r.h1; +NewGame (); /* set up the board for a new game */ +} + + +/**************************************************************** +* +* InitWindow - Draw the game board's window +* +****************************************************************/ +void InitWindow (void) +{ +#define scoreWidth 96 /* width of Score, Moves windows */ + +Rect r; /* for setting sizes of controls */ + +boardParms = wParms; /* create the board window */ +boardParms.wTitle = boardName; +boardWindow = NewWindow (&boardParms); + +scoreParms = wParms; /* create the Scores window */ +scoreParms.wTitle = scoreName; +scoreParms.wFrameBits = 0xC0C4; +scoreParms.wDataH = 29; +scoreParms.wDataW = scoreWidth; +scoreParms.wMaxH = 29; +scoreParms.wMaxW = scoreWidth; +scoreParms.wPosition.v1 = 32; +scoreParms.wPosition.h1 = 640 - 32 - scoreWidth; +scoreParms.wPosition.v2 = 61; +scoreParms.wPosition.h2 = 640 - 32; +scoreWindow = NewWindow (&scoreParms); + +movesParms = scoreParms; /* create the Moves window */ +movesParms.wTitle = movesName; +movesParms.wDataH = 112; +movesParms.wPosition.v1 = 80; +movesParms.wPosition.v2 = 192; +movesWindow = NewWindow (&movesParms); + +r.h1 = scoreWidth - 23; /* create a grow box */ +r.h2 = scoreWidth + 1; +r.v1 = 100; r.v2 = 113; +growHandle = NewControl (movesWindow, &r, NULL, 0, 0, 0, 0, (void *) 0x08000000, + 0L, NULL); + +r.v1 = 0; r.v2 = 101; /* create scroll bar */ +vScrollHandle = NewControl (movesWindow, &r, NULL, 3, 0, 112, 25, + (void *) 0x06000000, 0L, NULL); + +moveHeight = 112; /* set height of window */ +SelectWindow (boardWindow); /* make game board the front window */ +} /* InitWindow */ + + +/* Action Routines */ + + +/**************************************************************** +* +* WriteMove - Write a move on the screen +* +* Input: +* move - move to write +* +****************************************************************/ +void WriteMove (int move) +{ +printf ("%c%d ", (char) (move % 10 - 1 + 'A'), 9 - move / 10); +} /* WriteMove */ + + +/**************************************************************** +* +* DrawMoves - Write the contents of the Moves window +* +****************************************************************/ +void DrawMoves (void) +{ +GrafPortPtr port, p2; /* graphics ports */ +CtlRecHndl ctl; /* for finding scroll bar */ +Rect r; /* rectangle for drawing colors */ +int i, n; /* index variables */ + +if (showMovesWindow) { + port = GetPort (); /* save the current graph port */ + StartDrawing (movesWindow); /* draw to the Score window */ + SetForeColor (0); /* black pen on white background */ + SetBackColor (15); + + if (updateMoves) { + SetSolidPenPat (0); /* draw black column header */ + r.v1 = 5; r.h1 = 26; + r.v2 = 13; r.h2 = 40; + PaintOval (&r); + r.v1 = 5; r.h1 = 47; /* draw white column header */ + r.v2 = 13; r.h2 = 61; + PaintOval (&r); + SetSolidPenPat (15); + r.v1 = 6; r.h1 = 48; + r.v2 = 12; r.h2 = 60; + PaintOval (&r); + } + + if (movesMade > 0) { /* draw the moves */ + MoveTo (2, 25); + i = topMove; + n = (i + 1) / 2; + + while (i <= movesMade) { + if ((updateMoves) || (i > movesMade - 2)) { + if (n < 10) + printf (" "); + printf ("%2d: ", n); + WriteMove (moves[i]); + if (i + 1 <= movesMade) + WriteMove (moves[i+1]); + else + printf (" "); + } + + printf ("\r"); + n++; + i += 2; + } + printf (" \r"); /* blank the last line (for scrolls) */ + SetCtlParams (Even (movesMade) / 2 * charHeight, moveHeight - 25, + vScrollHandle); /* update the thumb size */ + SetPort (port); /* restore the old graph port */ + } + updateMoves = false; /* complete update is no longer needed */ + } +} /* DrawMoves */ + + +/**************************************************************** +* +* DrawScore - Write the contents of the Score window +* +****************************************************************/ +void DrawScore (void) +{ +int i; /* loop variable */ +int wcnt, bcnt; /* for counting pieces */ +GrafPortPtr port; /* current graphics port */ + +if (showScoreWindow) { + port = GetPort (); /* save the graph port */ + StartDrawing (scoreWindow); /* draw to the score window */ + SetForeColor (0); /* black pen on white background */ + SetBackColor (15); + MoveTo (2, 10); /* start at upper left corner */ + + for (i = 11, wcnt = 0, bcnt = 0; i < 90; i++) /* count the pieces on board */ + if (board[i] == whitePiece) + wcnt++; + else if (board[i] == blackPiece) + bcnt++; + printf ("White: %d \rBlack: %d \r", wcnt, bcnt); /* write the scores */ + printf ("Score: %d \r", Score (board)); + SetPort (port); /* restore the old graph port */ + } +} /* DrawScore */ + + +/**************************************************************** +* +* MenuShowMovesWindow - Hide or show the Moves window +* +****************************************************************/ +void MenuShowMovesWindow (void) +{ +GrafPortPtr port; /* current graphics port */ + +showMovesWindow = ! showMovesWindow; /* reverse window's status */ +CheckMItem (showMovesWindow, options_ShowMovesWindow); +ShowHide (showMovesWindow, movesWindow); +if (showMovesWindow) { /* if visible, draw it... */ + updateMoves = true; /* draw the moves list */ + DrawMoves (); + port = GetPort (); /* save the graph port */ + StartDrawing (movesWindow); /* redraw the controls */ + SetPort (port); + } +SelectWindow (boardWindow); +} /* MenuShowMovesWindow */ + + +/**************************************************************** +* +* MenuShowScoreWindow - Hide or show the Score window +* +****************************************************************/ +void MenuShowScoreWindow (void) +{ +showScoreWindow = ! showScoreWindow; +CheckMItem (showScoreWindow, options_ShowScoreWindow); +ShowHide (showScoreWindow, scoreWindow); +SelectWindow (boardWindow); +DrawScore (); +} /* MenuShowScoreWindow */ + + +/**************************************************************** +* +* MenuAbout - Show the About dialog +* +****************************************************************/ +void MenuAbout (void) +{ +strcpy (msg, "\pReversi 1.0\rCopyright 1989\rByte Works, Inc.\r" + "\rBy Mike Westerfield"); +DoAlert (note, msg); +} /* MenuAbout */ + + +/**************************************************************** +* +* MenuColor - Change the color the computer plays +* +****************************************************************/ +void MenuColor (void) +{ +if (color == whitePiece) { + SetMItem (computerPlaysWhite, options_ComputerPlaysWhite); + color = blackPiece; + } +else { + SetMItem (computerPlaysBlack, options_ComputerPlaysWhite); + color = whitePiece; + } +} /* MenuColor */ + + +/**************************************************************** +* +* MenuPass - Player wants to pass +* +****************************************************************/ +void MenuPass (void) +{ +struct moveListType moveList; /* for seeing if there are legal moves */ + +GetMoves (board, currentColor, &moveList); /* get a list of legal moves */ +if (! moveList.num) /* OK to pass if there are no moves */ + currentColor ^= 3; +else { /* error to pass if there are moves */ + strcpy (msg, "\pYou have legal moves\rso you cannot pass.\r"); + DoAlert (stop, msg); + } +} /* MenuPass */ + + +/**************************************************************** +* +* MenuSelfPlay - Change the current playing mode +* +****************************************************************/ +void MenuSelfPlay (void) +{ +selfPlay = ! selfPlay; +if (selfPlay) + SetMItem (computerPlayStr, options_SelfPlay); +else + SetMItem (selfPlayStr, options_SelfPlay); +} /* MenuSelfPlay */ + + +/**************************************************************** +* +* MenuSetPly - Change the current playing level +* +* Input: +* newPly - menu number of playing level selected +* +****************************************************************/ +void MenuSetPly (int newPly) +{ +CheckMItem (false, ply + level_1Ply - 1); /* uncheck old ply */ +CheckMItem (true, newPly); /* check new ply */ +ply = newPly - level_1Ply + 1; /* set the ply level */ +} /* MenuSetPly */ + + +/**************************************************************** +* +* HandleMenu - Handle a menu event +* +* Input: +* menuNum - menu number of menu to handle +* +****************************************************************/ +void HandleMenu (int menuNum) +{ +switch (menuNum) { /* handle the menu */ + case apple_AboutReversi: + MenuAbout (); + break; + + case file_NewGame: + NewGame (); + DrawBoard (); + break; + + case file_Quit: + done = true; + break; + + case level_1Ply: case level_2Ply: case level_3Ply: case level_4Ply: + case level_5Ply: case level_6Ply: case level_7Ply: case level_8Ply: + MenuSetPly (menuNum); + break; + + case options_SelfPlay: + MenuSelfPlay (); + break; + + case options_ComputerPlaysWhite: + MenuColor (); + break; + + case options_Pass: + MenuPass (); + break; + + case options_ShowScoreWindow: + MenuShowScoreWindow (); + break; + + case options_ShowMovesWindow: + MenuShowMovesWindow (); + break; + + default: + break; + } /* switch */ + +HiliteMenu (false, (int) (lastEvent.wmTaskData >> 16)); +} /* HandleMenu */ + + +/**************************************************************** +* +* HideAWindow - Hide the front window +* +****************************************************************/ +void HideAWindow (void) +{ +if (FrontWindow () == scoreWindow) + MenuShowScoreWindow (); +else /* if FrontWindow == movesWindow */ + MenuShowMovesWindow (); +} /* HideAWindow */ + + +/**************************************************************** +* +* LegalMove - Check if a move is legal +* +* Input: +* index - move to make +* color - color of player making the move +* +****************************************************************/ +BOOL LegalMove (int index, int color) +{ +struct moveListType moveList; /* for list of legal moves */ +int i; /* loop variable */ + +GetMoves (board, color, &moveList); +for (i = 0; i < moveList.num; i++) + if (index == moveList.moves[i]) + return true; +return false; +} /* LegalMove */ + + +/**************************************************************** +* +* GrowMoves - Grow the Moves window (the only window that can grow) +* +****************************************************************/ +void GrowMoves (void) +{ +Rect rt; /* for creating scroll bar */ +int movesInWindow; /* # moves the Moves window can display */ +union longShort { long isLong; /* for converting between int and long */ + int lsw, msw; } r, s; + +s.isLong = GetMaxGrow (movesWindow); /* get max size */ + /* track the growing of the window */ +r.isLong = GrowWindow (s.msw, 64, lastEvent.where.h, lastEvent.where.v, + movesWindow); +if (r.isLong) { /* if the size changed then... */ + SizeWindow (s.msw, r.lsw, movesWindow); /* change the window's size */ + MoveControl (73, r.lsw - 12, growHandle); /* move the grow box */ + DisposeControl (vScrollHandle); /* resize the scroll bar */ + rt.h1 = 73; rt.h2 = 89; + rt.v1 = 0; rt.v2 = r.lsw - 11; + + vScrollHandle = /* update the thumb size */ + NewControl (movesWindow, &rt, NULL, 3, 0, 112, 25, (void *) 0x06000000, + 0L, NULL); + /* position thumb of the scroll bar */ + SetCtlParams (Even (movesMade) / 2 * charHeight, r.lsw - 25, vScrollHandle); + SetCtlValue (topMove / 2 * charHeight, vScrollHandle); + + if (r.lsw > moveHeight) { /* if the window grew then... */ + /* dispose of trailing blanks */ + movesInWindow = (r.lsw - 25) / charHeight * 2 + 2; + if ((Even(topMove) + movesInWindow + 1) / 2 > (Even (movesMade) + 1) / 2) + { + topMove = Even (movesMade) - movesInWindow; + if (!(topMove & 0x0001)) + topMove++; + if (topMove < 1) + topMove = 1; + } + + updateMoves = true; /* redraw moves list */ + moveHeight = r.lsw; + DrawMoves (); + } + + moveHeight = r.lsw; /* update the window size */ + } +} /* GrowMoves */ + + +/**************************************************************** +* +* Scroll - Handle vertical scrolls in the Moves window +* +****************************************************************/ +void Scroll (void) +{ +int part; /* part # from TrackControl */ +int movesInWindow; /* # moves the Moves window can display */ + +part = TrackControl (lastEvent.where.h, lastEvent.where.v, (void *) -1, + vScrollHandle); +movesInWindow = (moveHeight - 25) / charHeight * 2 + 2; + +if ((part > 4) && (part < 9)) { /* if the part is not the slide switch... */ + switch (part) { + case 5: /* handle up arrow */ + if (topMove > 1) + topMove -= 2; + break; + + case 6: /* handle down arrow */ + if (Even (topMove) + movesInWindow < Even (movesMade) + 1) + topMove += 2; + break; + + case 7: /* handle up page */ + if (topMove > 1) { + topMove -= movesInWindow; + if (topMove < 1) + topMove = 1; + } + break; + + case 8: /* handle down page */ + if (Even(topMove) + movesInWindow < Even(movesMade) + 1) { + topMove += movesInWindow; + if ( ((Even(topMove) + movesInWindow + 1) / 2) > + (Even(movesMade) + 1) / 2 ) { + topMove = Even (movesMade) - movesInWindow; + if (! (topMove >> 16) & 0x0001) + topMove++; + } + } + } /* switch */ + + updateMoves = true; /* redraw the window */ + DrawMoves (); + /* position thumb of the scroll bar */ + SetCtlValue (topMove / 2 * charHeight, vScrollHandle); + } + +else if (part == 129) { /* reposition based on new thumb loc. */ + topMove = GetCtlValue (vScrollHandle) * 2 / charHeight +1; + if (! (topMove >> 16) & 0x0001) + topMove++; + updateMoves = true; + DrawMoves (); + } +} /* Scroll */ + + +/**************************************************************** +* +* TryMove - If there is a legal move at the indicated coordinates, +* make it +* +****************************************************************/ +void TryMove (void) +{ +Point p; /* location of mouse */ +int row, col; /* position on board */ +int index; /* index into board array */ + +if (movesLeft) { /* make sure game is not over */ + StartDrawing (boardWindow); /* easy way to set port */ + p.h = lastEvent.where.h; /* find out where the mouse is */ + p.v = lastEvent.where.v; + GlobalToLocal (&p); + col = p.h / squareWidth + 1; /* convert to board index */ + row = p.v / squareHeight + 1; + index = row * 10 + col; + + if (LegalMove( index, currentColor)) { /* if move is legal, make it */ + MakeAMove (index, currentColor); + currentColor ^= 3; /* switch color to move */ + } + + else { /* flag a bad move */ + strcpy (msg, "\pIllegal move -\rtry again."); + DoAlert (stop, msg); + } + CheckForDone (); + DrawScore (); /* update the score */ + DrawMoves (); /* update the move list */ + } +} /* TryMove */ + + +/**************************************************************** +* +* DoContent - Handle a mouse-down event in the content region +* +****************************************************************/ +void DoContent (void) +{ +int part; /* part # returned by FindControl */ +CtlRecHndl ctl; /* control handle */ + +if (FrontWindow () == (GrafPortPtr) lastEvent.wmTaskData) { + if ((GrafPortPtr) lastEvent.wmTaskData == boardWindow) + TryMove (); /* try making a move */ + + else if ((GrafPortPtr) lastEvent.wmTaskData == movesWindow) { + part = FindControl (&ctl, lastEvent.where.h, lastEvent.where.v, + movesWindow); + if (part == 10) + GrowMoves (); /* handle grow box */ + else if (part) + Scroll (); /* handle scroll bar */ + } + } +} /* DoContent */ + + +/**************************************************************** +* +* Update - Handle an update event +* +****************************************************************/ +void Update (void) +{ +if (lastEvent.message == (long) boardWindow) { + BeginUpdate (boardWindow); /* update the board window */ + DrawBoard (); /* redraw the board */ + EndUpdate (boardWindow); /* complete the update */ + } + +else if (lastEvent.message == (long) scoreWindow) { + BeginUpdate (scoreWindow); /* update the score window */ + DrawScore (); /* redraw the score window */ + EndUpdate (scoreWindow); /* complete the update */ + } + +else if (lastEvent.message == (long) movesWindow) { + BeginUpdate (movesWindow); /* update the Moves window */ + updateMoves = true; /* redraw the Moves window */ + DrawMoves (); + EndUpdate (movesWindow); /* complete the update */ + DrawControls (movesWindow); /* redraw the controls */ + } +} /* Update */ + + +/**************************************************************** +* +* Main program starts here +* +****************************************************************/ + +int main (void) + +{ +startdesk (640); /* initialize the dekstop environment */ +QDAuxStartUp (); +SetPenMode (0); /* set pen mode to copy */ +InitMenus (); /* set up the menu bar */ +InitWindow (); /* draw the board's window */ +InitVariables (); /* initialize global variables */ +lastEvent.wmTaskMask = 0x13FFL; /* let Task Master do most stuff */ +ShowCursor (); /* show the cursor */ + +done = false; /* main event loop */ +do { + event = TaskMaster (0x074E, &lastEvent); + switch (event) { /* handle the events we need to */ + case wInMenuBar: HandleMenu ((int) lastEvent.wmTaskData); + break; + + case inUpdate: Update (); + break; + + case wInContent: DoContent (); + break; + + case wInGoAway : HideAWindow (); + break; + + default: break; + } + + + /* If the Moves window has been brought to front, draw its controls. */ + + if (FrontWindow () == movesWindow) { + if (movesNotFront) { + movesNotFront = false; + HiliteControl (0, vScrollHandle); + HiliteControl (0, growHandle); + DrawControls (movesWindow); + } + } + else if (! movesNotFront) { + movesNotFront = true; + HiliteControl (255, vScrollHandle); + HiliteControl (255, growHandle); + } + + if (movesLeft) { /* let the computer move */ + if (selfPlay) { + FindMove (currentColor); + currentColor ^= 3; + DrawScore (); + DrawMoves (); + } + else if (color == currentColor) { + FindMove (color); + currentColor ^= 3; + DrawScore (); + DrawMoves (); + } + } /* if */ + } +while (!done); + +QDAuxShutDown (); /* shut down the desktop environment */ +enddesk (); +} /* Reversi */ diff --git a/C.Samples/Graphic.Samples/Bounce.cc b/C.Samples/Graphic.Samples/Bounce.cc new file mode 100644 index 0000000..af9ec9e --- /dev/null +++ b/C.Samples/Graphic.Samples/Bounce.cc @@ -0,0 +1,167 @@ +/**************************************************************** +* +* A simple graphics demo. +* +* By Phil Montoya and Barbara Allred +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +****************************************************************/ + +#pragma keep "Bounce" +#pragma lint -1 + +#include +#include + +#define screenMode 640 /* 640x200 graphics Super HiRes display mode */ +#define copyMode 0 /* pen copy mode */ +#define size 6 /* number of points */ + +/* Global variables */ + +static int curColor = white; /* pen color */ +static int curSize = 1; /* no. points-1 */ +static int x[size]; /* initial points */ +static int y[size]; +static int xv[size], yv[size]; /* move and velocity arrays */ +static int maxX, maxY; /* max X, Y coordinates */ +static int minX, minY; /* min X, Y coordinates */ +static Rect r; /* drawing rectangle */ + + +/**************************************************************** +* +* UpDate - Updates x and y by velocity factors and changes +* direction if necessary +* +* Inputs: +* px - X location +* pxv - X velocity +* py - Y location +* pyv - Y velocity +* +****************************************************************/ + +void UpDate (int *px, int *pxv, int *py, int *pyv) + +{ +*px += *pxv; /* move x by velocity factor */ +if ((*px < minX) || (*px > maxX)) { /* if x is beyond border... */ + *px -= *pxv; /* ...move back */ + *pxv = -(*pxv); /* ...change directions */ + } +*py += *pyv; /* move y by velocity factor */ +if ((*py < minY) || (*py > maxY)) { /* if y is beyond border... */ + *py -= *pyv; /* ...move back */ + *pyv = -(*pyv); /* ...change directions */ + } +} + + +/**************************************************************** +* +* NextPenColor - Changes the pen color +* +****************************************************************/ + +void NextPenColor (void) + +{ +curColor++; /* get next color */ +if (curColor > white) /* if out of colors then start over */ + curColor = black; +SetSolidPenPat(curColor); /* set the pen to this color */ +} + + +/**************************************************************** +* +* Initialize - initialization for program +* +****************************************************************/ + +void Initialize (void) + +{ +int i, j; + +SetPenSize(4, 2); /* use a fatter pen */ +SetPenMode(copyMode); /* use the copy pen mode */ +GetPortRect(&r); +maxX = r.h2; maxY = r.v2; /* don't go beyond screen edges */ +minX = r.h1; minY = r.v1; + +i = maxX - minX; /* set initial points */ +j = maxX >> 1; +x[0] = minX + j + 20; x[1] = minX + j - 20; +x[2] = x[3] = x[4] = x[5] = minX + j; + +i = maxY - minY; +j = maxY >> 1; +y[3] = minY + j + 10; y[4] = minY + j - 10; +y[0] = y[1] = y[2] = y[5] = minY + j; + +for (i = 0, j = 6; i < size; i++) { /* set velocity factors */ + if (i & 0x0001) /* if i is odd... */ + j = -j; + yv [i] = j; + xv [i] = -j; + j -= 2; + } +} + + +/**************************************************************** +* +* DrawShapes - This is the engine of the demo. +* +****************************************************************/ + +void DrawShapes (void) + +{ +int i, j, k; + +for (k = white; k >= black; k--) { /* cycle thru 16 screens */ + SetSolidPenPat(k); /* set the background color */ + PaintRect(&r); + + /* The number of shapes per screen depends on the size of the shape. */ + /* The more points a shape has the less times it will be drawn and */ + /* vice-versa. This keeps the time and density per screen approximately */ + /* the same. */ + + for (i = 0; i < (((size-curSize) * 38) + 75); i++) { + /* draw this series of shapes */ + NextPenColor (); /* change pen colors */ + MoveTo (x[curSize], y[curSize]); /* initial from position */ + UpDate (x+curSize, xv+curSize, y+curSize, yv+curSize); + for (j = 0; j < curSize; j++) { /* draw this shape */ + LineTo (x[j], y[j]); + UpDate (x+j, xv+j, y+j, yv+j); + } + } + curSize++; /* next shape size */ + if (curSize == size) + curSize = 1; + } +} + + +/**************************************************************** +* +* Program Begins Here +* +****************************************************************/ + +int main (void) + +{ +startgraph(screenMode); /* set up graphics screen */ +Initialize(); /* initialize global data */ +DrawShapes(); /* draw the shapes */ +endgraph(); /* shut down the graphics screen */ +return 0; +} diff --git a/C.Samples/Graphic.Samples/CallGSOS.cc b/C.Samples/Graphic.Samples/CallGSOS.cc new file mode 100644 index 0000000..118ef19 --- /dev/null +++ b/C.Samples/Graphic.Samples/CallGSOS.cc @@ -0,0 +1,94 @@ +/***************************************************************** +* +* Call GS/OS +* +* This program shows how to call GS/OS directly. You should +* compare it with callp16.cc, which shows how to call ProDOS 16 +* (an older operating system that is now a subset of GS/OS). +* +* This program dumps the contents of a screen image file to the +* graphics screen. It is assumed that the program callp16 was +* executed prior to running this program, and that you have +* made a note of the filename containing the screen dump that +* was created by callp16. +* +* DO NOT EXECUTE THIS PROGRAM FROM THE DESKTOP. It uses non- +* standard mechanisms for accessing the graphics screen. +* +* By Barbara Allred and Mike Westerfield +* +* Copyright 1989 +* Byte Works, Inc. +* +*******************************************************************/ + +#pragma keep "CallGSOS" +#pragma debug 1 /* check stack overflows */ +#pragma lint -1 + +#include +#include +#include +#include +#include +#include +#include + +#define SCREENWIDTH 320 /* screen width in pixels */ + +static GSString255 filename; /* name of file having screen contents */ + + /* Data Control Blocks for GS/OS calls */ +OpenRecGS openDCB = { 15, 0, NULL, 1, 0}; +IORecGS readDCB = { 5, 0, (void *) 0x00E12000, 32768L, 0L, 0 }; +RefNumRecGS closeDCB = { 1, 0 }; + +int main (void) + +{ +char *str; +int i; + +/* Prompt user for the name of the file to load. */ +printf ("Please enter the name of the file containing the screen image:\n"); +scanf ("%s", filename.text); +filename.length = strlen(filename.text); + +/* Initialize the pen and graphics screen. */ +startgraph(SCREENWIDTH); /* start QuickDraw II */ +SetPenSize(4, 2); /* use fatter pen */ + +/* Open the file and then write its contents to the graphics screen. */ +openDCB.pathname = &filename; /* open the file */ +OpenGS(&openDCB); +if (i = toolerror()) { + MoveTo(50, 100); + SetSolidPenPat(black); + sprintf(str, "Unable to open file for screen dump: err = %d\n", i); + DrawCString(str); + goto Fail; + } + +readDCB.refNum = openDCB.refNum; /* read the file, sending */ +ReadGS(&readDCB); /* contents to screen */ +if (i = toolerror()) { + MoveTo(50, 100); + SetSolidPenPat(black); + sprintf(str, "Unable to read file for screen dump: err = %d\n", i); + DrawCString(str); + goto Fail; + } + +closeDCB.refNum = openDCB.refNum; /* close the file */ +CloseGS (&closeDCB); + +/* Wrap up: Wait for user to signal end, then shut down tools started. */ +Fail: +SetSolidPenPat(black); /* wait for user to signal end */ +str = "Press RETURN when ready to quit program"; +MoveTo(SCREENWIDTH-CStringWidth(str), 40); +DrawCString(str); +getchar(); getchar(); +endgraph(); +return 0; +} diff --git a/C.Samples/Graphic.Samples/CallP16.cc b/C.Samples/Graphic.Samples/CallP16.cc new file mode 100644 index 0000000..9f4fed2 --- /dev/null +++ b/C.Samples/Graphic.Samples/CallP16.cc @@ -0,0 +1,121 @@ +/***************************************************************** +* +* Call ProDOS 16 +* +* This program draws ovals on the 16 color screen. It then +* dumps the contents of the graphics screen to a file. If the +* file is loaded and then stored to the graphics screen, the +* image dumped is displayed. +* +* DO NOT EXECUTE THIS PROGRAM FROM THE DESKTOP. It uses non- +* standard mechanisms for accessing the graphics screen. +* +* By Barbara Allred and Mike Westerfield +* +* Copyright 1989 +* Byte Works, Inc. +* +*******************************************************************/ + +#pragma keep "CallP16" +#pragma debug 1 /* check stack overflows */ + +#include + +#pragma lint -1 + +#include +#include +#include +#include + +Rect ovalRect, *ovalPtr = &ovalRect; /* bounds rectangle for ovals */ + + /* Data Control Blocks for ProDOS 16 calls */ +FileRec createDCB = { NULL, 0x00E3, 0x06, 0, 0x01, 0, 0 }; +OpenRec openDCB; +FileIORec writeDCB; + + +int main (void) + +{ +#define SCREENWIDTH 320 /* screen width in pixels */ + +int x = 40; /* horizontal location in global coords */ +int y = 20; /* vertical location in global coords */ +int color; /* initial pen color */ +char *str; /* work pointer */ + +char filename [L_tmpnam+1] = ""; /* name of file receiving screen dump */ +char *fn; + +/* Start Quick Draw II */ +startgraph(SCREENWIDTH); +SetPenSize(4, 2); /* use fatter pen */ + +/* Draw ovals in different colors on the screen. */ +for (color = 0; color < 15; color++) { + ovalRect.v1 = x; ovalRect.h1 = y; + ovalRect.v2 = x + 15; ovalRect.h2 = y + 15; + SetSolidPenPat(color+1); + MoveTo(y, x); + PaintOval(ovalPtr); + SetSolidPenPat(color); + MoveTo(y, x); + FrameOval(ovalPtr); + if (toolerror()) { + DrawCString("Failure in drawing routine\n"); + goto Fail; + } + y += 10; x += 10; + } + +/* Dump contents of screen to a file. */ +fn = tmpnam(&filename[1]); /* get unique filename for dump */ +if (fn == NULL) { + MoveTo (100, 50); + SetSolidPenPat(black); + DrawCString("Unable to obtain unique filename for screen dump"); + goto Fail; + } +filename[0] = strlen(&filename[1]); /* convert C-string to P-string */ + +createDCB.pathname = filename; /* create screen dump file */ +CREATE(&createDCB); +if (toolerror()) { + MoveTo(50, 100); + SetSolidPenPat(black); + DrawCString("Unable to create file for screen dump"); + goto Fail; + } +openDCB.openPathname = filename; /* open the screen dump file */ +OPEN(&openDCB); +if (toolerror()) { + MoveTo(50, 100); + SetSolidPenPat(black); + DrawCString("Unable to open file for screen dump"); + goto Fail; + } +writeDCB.fileRefNum = openDCB.openRefNum; /* write screen contents to file */ +writeDCB.dataBuffer = (void *) 0x00E12000; +writeDCB.requestCount = 32768L; +WRITE(&writeDCB); +if (toolerror()) { + MoveTo(50, 100); + SetSolidPenPat(black); + DrawCString("Unable to write screen contents to file"); + goto Fail; + } +CLOSE(&openDCB); /* close the screen dump file */ + +/* Wrap up: Wait for key press and then shut down QuickDraw II. */ +Fail: +SetSolidPenPat(black); /* wait for user to signal end */ +str = "Press return when ready to quit program"; +MoveTo(SCREENWIDTH-CStringWidth(str), 40); +DrawCString(str); +getchar(); +endgraph(); +printf("The name of the file containing the screen dump is:\n%b", filename); +} diff --git a/C.Samples/Graphic.Samples/Pipe.cc b/C.Samples/Graphic.Samples/Pipe.cc new file mode 100644 index 0000000..5534085 --- /dev/null +++ b/C.Samples/Graphic.Samples/Pipe.cc @@ -0,0 +1,73 @@ +/**************************************************************** +* +* Pipe +* +* A simple graphics demo. +* +* by Mike Westerfield +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +****************************************************************/ + +#pragma keep "Pipe" +#pragma lint -1 + +#include + +#define xWidth 20 +#define yWidth 10 + +int main (void) + +{ +Rect r; /* drawing rectangle */ +int x = xWidth; /* horizontal width of pipe */ +int y = yWidth; /* vertical width of pipe */ +int color = 1; /* pen color */ +int maxX; /* maximum horizontal pixel */ +int maxY; /* maximum vertical pixel */ +int minX; /* minimum horizontal pixel */ +int minY; /* minimum vertical pixel */ +int deltaX = 6; /* pipe width increment */ +int deltaY = 3; /* pipe depth increment */ +int i; + +GetPortRect(&r); /* initialize drawing rectangle */ +maxX = r.h2 - xWidth; /* don't go beyond rect edges */ +maxY = r.v2 - yWidth; +minX = r.v1; +minY = r.h1; + +for (i = 0; i < 150; ++i) { /* main loop: draw pipe, a series of ovals */ + r.h1 = x - xWidth; + r.h2 = x + xWidth; + r.v1 = y - yWidth; + r.v2 = y + yWidth; + color ^= 3; + SetSolidPenPat(color); + PaintOval(&r); + SetSolidPenPat(0); + FrameOval(&r); + + x += deltaX; /* bend pipe as needed to fit within rectangle */ + if (x < xWidth) { + x = xWidth; + deltaX = -deltaX; + } + else if (x > maxX) { + x = maxX; + deltaX = -deltaX; + } + y += deltaY; + if (y < yWidth) { + y = yWidth; + deltaY = -deltaY; + } + else if (y > maxY) { + y = maxY; + deltaY = -deltaY; + } + } +} diff --git a/C.Samples/Graphic.Samples/Spiral.cc b/C.Samples/Graphic.Samples/Spiral.cc new file mode 100644 index 0000000..02dbab7 --- /dev/null +++ b/C.Samples/Graphic.Samples/Spiral.cc @@ -0,0 +1,46 @@ +/**************************************************************** +* +* Spiral +* +* A simple graphics demo. Uses the shell STOP command from the +* debug menu to stop the program early. +* +* by Mike Westerfield +* +* Copyright 1989 +* Byte Works, Inc. +* +****************************************************************/ + +#pragma keep "Spiral" +#pragma lint -1 + +#include +#include + +int main (void) + +{ +float r, theta, rot; +int color = 1; +int stopFlag; +Rect rect; + +GetPortRect(&rect); +SetPenSize(3, 1); +for (rot = 0.0002; rot < 0.0005; rot += 0.0001) { + theta = 0.0; + r = 40.0; + MoveTo ((int) (cos (theta) * r * 3) + 160, + (int) (sin (theta) * r) + 40); + while (r > 0.0) { + SetSolidPenPat (color); + color ^= 3; + theta += 3.1415926535 / 21.0 + rot; + LineTo ((int) (cos (theta) * r * 3) + 160, + (int) (sin (theta) * r) + 40); + r -= 0.02; + } + } +Out: ; +} diff --git a/C.Samples/HyperCard/xcmd.cc b/C.Samples/HyperCard/xcmd.cc new file mode 100644 index 0000000..9738de9 --- /dev/null +++ b/C.Samples/HyperCard/xcmd.cc @@ -0,0 +1,34 @@ +/***************************************************************** +* +* HyperCard XCMD +* +* This sample is a framework program, showing the essential parts +* of a HyperCard XCMD. +* +* For complete details on the requirements for HyperCard XCMDs, +* see the HyperCard technical documentation on the System 6.0 +* CD ROM. +* +* Build this program using the script xcmd.make. This script has +* quite a few comments about the build process, so it's worth +* loading the scrept and reading the comments. +* +* By Mike Westerfield +* +* Copyright 1993 +* Byte Works, Inc. +* +*****************************************************************/ + +#pragma keep "xcmd" +#pragma lint -1 +#pragma xcmd main + +#include +#include + +void main (XCMDPtr parm) + +{ +SysBeep(); +} diff --git a/C.Samples/HyperCard/xcmd.make b/C.Samples/HyperCard/xcmd.make new file mode 100644 index 0000000..032d5f1 --- /dev/null +++ b/C.Samples/HyperCard/xcmd.make @@ -0,0 +1,26 @@ +* +* This file builds the sample xcmd.cc. +* + +* +* There's nothing special about the compile -- just be sure the program +* itself uses the xcmd pragma, the small memory model, and does not use the +* segment directive. +* + +compile xcmd.cc + +* +* The -x flag is crutial! XCMDs must consist of a single segment, and +* without the -x flag on the link, the linker creates an expressload +* segment. +* + +link -x xcmd keep=xcmd + +* +* The Rez compiler packs the executable code and a name into a file for +* HyperCard. +* + +compile xcmd.rez keep=Beep diff --git a/C.Samples/HyperCard/xcmd.rez b/C.Samples/HyperCard/xcmd.rez new file mode 100644 index 0000000..ea0f893 --- /dev/null +++ b/C.Samples/HyperCard/xcmd.rez @@ -0,0 +1,23 @@ +/***************************************************************** +* +* HyperCard XCMD +* +* This is the resource file for xcmd.cc. +* +* By Mike Westerfield +* +* Copyright 1993 +* Byte Works, Inc. +* +*****************************************************************/ + +#include "types.rez" + +read $801E(1, convert) "xcmd"; + +resource rResName ($0001801E) { + 1, + { + 1, "Beep"; + } + }; diff --git a/C.Samples/HyperStudio/nba.cc b/C.Samples/HyperStudio/nba.cc new file mode 100644 index 0000000..6b4371f --- /dev/null +++ b/C.Samples/HyperStudio/nba.cc @@ -0,0 +1,35 @@ +/***************************************************************** +* +* HyperStudio New Button Action (NBA) +* +* This sample is a framework program, showing the essential parts +* of a HyperStudio NBA. +* +* For complete details on the requirements for HyperStudio NBAs, +* contact Roger Wagner Publishing. When this sample was written, +* details for writing HyperStudio NDAs were available in disk form +* for $10. +* +* Build this program using the script xcmd.make. This script has +* quite a few comments about the build process, so it's worth +* loading the scrept and reading the comments. +* +* By Mike Westerfield +* +* Copyright 1993 +* Byte Works, Inc. +* +*****************************************************************/ + +#pragma keep "nba" +#pragma lint -1 +#pragma nba main + +#include "HyperStudio.h" +#include + +void main (HSParamPtr parm) + +{ +SysBeep(); +} diff --git a/C.Samples/HyperStudio/nba.make b/C.Samples/HyperStudio/nba.make new file mode 100644 index 0000000..345b40f --- /dev/null +++ b/C.Samples/HyperStudio/nba.make @@ -0,0 +1,27 @@ +* +* This file builds the sample nba.cc. +* + +* +* There's nothing special about the compile -- just be sure the program +* itself uses the nba pragma, the small memory model, and does not use the +* segment directive. +* + +compile nba.cc + +* +* The -x flag is crutial! NBAs must consist of a single segment, and +* without the -x flag on the link, the linker creates an expressload +* segment. +* + +link -x nba keep=nba + +* +* The Rez compiler packs the executable code and a name into a file for +* HyperStudio. +* + +compile nba.rez keep=Beep +filetype Beep $BC $4007 diff --git a/C.Samples/HyperStudio/nba.rez b/C.Samples/HyperStudio/nba.rez new file mode 100644 index 0000000..8a15429 --- /dev/null +++ b/C.Samples/HyperStudio/nba.rez @@ -0,0 +1,23 @@ +/***************************************************************** +* +* HyperStudio NBA +* +* This is the resource file for nba.cc. +* +* By Mike Westerfield +* +* Copyright 1993 +* Byte Works, Inc. +* +*****************************************************************/ + +#include "types.rez" + +read $8017($7FF0, convert) "nba"; + +resource rResName ($00018017) { + 1, + { + $7FF0, "Beep"; + } + }; diff --git a/C.Samples/Text.Samples/Ackermann.cc b/C.Samples/Text.Samples/Ackermann.cc new file mode 100644 index 0000000..fbd31c9 --- /dev/null +++ b/C.Samples/Text.Samples/Ackermann.cc @@ -0,0 +1,64 @@ +/***************************************************************** +* +* Ackermann +* +* This program implements a famous mathematical function that +* is often used to examine recursion. It is deceptively +* simple, but can take enormous amounts of time and stack +* space for relatively small arguments. For that reason, +* rangechecking has been enabled to ensure the integrity of the +* stack. +* +* By Mike Westerfield +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +*****************************************************************/ + +#pragma keep "Ackermann" +#pragma debug 0x0001 +#pragma lint -1 + +#include + +/* Constants */ +#define maxm 2 /* max value of 1st argument */ +#define maxn 3 /* max value of 2nd argument */ + +/* Global variables */ +int a, m, n, depth, maxdepth; + +/**************************************************************** +* +* Ackermann - Demonstrates recursion in ORCA/C +* +****************************************************************/ + +int Ackermann (int m, int n) + +{ +depth++; +if (depth > maxdepth) + maxdepth = depth; +if (m == 0) + return (n + 1); +if (n == 0) + return (Ackermann (m-1, 1)); +return (Ackermann (m-1, Ackermann (m, n-1))); +depth--; +} + + +int main (void) + +{ +for (m = 0; m <= maxm; m++) + for (n = 0; n <= maxn; n++) { + depth = 0; + maxdepth = 0; + a = Ackermann (m, n); + printf ("Ackermann(%d, %d) = %-4d ", m, n, a); + printf ("Max recursion depth was %d\n", maxdepth); + } +} diff --git a/C.Samples/Text.Samples/Artillery.cc b/C.Samples/Text.Samples/Artillery.cc new file mode 100644 index 0000000..f8dd293 --- /dev/null +++ b/C.Samples/Text.Samples/Artillery.cc @@ -0,0 +1,101 @@ +/************************************************ +* +* Artillery +* +* This classic interactive text game lets you +* pick the angle of your artillery gun in +* an attempt to knock out the enemy position. +* The computer picks a secret distance. When +* you fire, you will be told how much you +* missed by, and must fire again. The object +* is to hit the target with the fewest shells. +* +************************************************/ + +#pragma keep "Artillery" +#pragma lint -1 + +#include +#include +#include +#include +#include + +#define FALSE 0 /* boolean constants */ +#define TRUE 1 + +#define BLASTRADIUS 50.0 /* max distance from target for a hit */ +#define DTR 0.01745329 /* convert from degrees to radians */ +#define VELOCITY 434.6 /* muzzle velocity */ + +int main(void) + +{ +float angle, /* angle */ + distance, /* distance to the target */ + flightTime, /* time of flight */ + x, /* distance to impact */ + vx,vy; /* x, y velocities */ +int done, /* is there a hit, yet? */ + tries, /* number of shots */ + i; /* loop variable */ + +/* choose a distance to the target */ +srand((int) time(NULL)); +for (i = 0; i < 100; ++i) + rand(); +distance = rand()/5.55373; + +/* not done yet... */ +done = FALSE; +tries = 1; + +/* shoot 'til we hit it */ +do { + /* get the firing angle */ + printf("Firing angle: "); + scanf("%f", &angle); + + /* compute the muzzle velocity in x, y */ + angle *= DTR; + vx = cos(angle)*VELOCITY; + vy = sin(angle)*VELOCITY; + + /* find the time of flight */ + /* (velocity = acceleration*flightTime, two trips) */ + flightTime = 2.0*vy/32.0; + + /* find the distance */ + /* (distance = velocity*flightTime) */ + x = vx*flightTime; + + /* see what happened... */ + if (fabs(distance-x) < BLASTRADIUS) { + done = TRUE; + printf("A hit, after %d", tries); + if (tries == 1) + printf(" try!\n"); + else + printf(" tries!\n"); + switch (tries) { + case 1: + printf("(A lucky shot...)\n"); + break; + case 2: + printf("Phenomenal shooting!\n"); + break; + case 3: + printf("Good shooting.\n"); + break; + otherwise: + printf("Practice makes perfect - try again.\n"); + } + } + else if (distance > x) + printf("You were short by %d feet.\n", (int)(distance-x)); + else + printf("You were over by %d feet.\n", (int)(x-distance)); + ++tries; + } +while (!done); +} diff --git a/C.Samples/Text.Samples/CLine.cc b/C.Samples/Text.Samples/CLine.cc new file mode 100644 index 0000000..812d30a --- /dev/null +++ b/C.Samples/Text.Samples/CLine.cc @@ -0,0 +1,45 @@ +/*************************************************************** +* +* Command Line +* +* On the Apple IIgs, all EXE programs can expect three things +* to be passed to them by the shell: a user ID number for use +* with tool kits, an eight character shell ID which +* identifies the shell that executed the program, and the +* text from the command line itself. This program shows how +* to access these values from C, printing them to the +* screen. Be sure and execute the program with some text +* after the name - for example, +* +* CLINE Hello, world. +* +* When any EXE program returns to the shell, it passes an +* error code in the A register. You can set this value from +* C by returning an integer value as the result of main, as +* shown in this program. +* +* If you compile this program from the desktop, turn debug +* code off before executing the program from the shell window. +* +***************************************************************/ + +#pragma keep "CLine" +#pragma lint -1 + +#include +#include + +int main(void) + +{ +char *shellName, *line; +int userNumber; + +userNumber = userid(); +shellName = shellid(); +line = commandline(); +printf("User ID: %d\n", userNumber); +printf("Shell ID: %s\n", shellName); +printf("Command line: %s\n", line); +return 0; +} diff --git a/C.Samples/Text.Samples/ErrorExit.cc b/C.Samples/Text.Samples/ErrorExit.cc new file mode 100644 index 0000000..8d1e81b --- /dev/null +++ b/C.Samples/Text.Samples/ErrorExit.cc @@ -0,0 +1,52 @@ +/******************************************************************* +* +* Error Exit +* +* You can call the library routines that handle run-time errors +* from your own program. One of these, called strerror, will +* print a text run-time error message to standard output. You +* pass a single integer parameter, which is the run-time error +* number. This procedure is generally called from an error trap +* subroutine - see the sample program ERRORTRAP.CC for an example +* of how to trap errors. In this program strerror is used to +* list the current run-time error messages. +* +* The two built-in macros __FILE__ and __LINE__ are used to print +* the current line number and the name of the current source file. +* +* The library subroutine SystemErrorLocation provides trace-back +* information; it is further covered in the text sample program +* ERRORTRAP.CC. +* +* By Mike Westerfield and Barbara Allred +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +*********************************************************************/ + +#pragma keep "ErrorExit" +#pragma debug 8 /* enable trace-back of code */ +#pragma lint -1 + +#include +#include +#include + +extern pascal void SystemErrorLocation (void); +/* A library procedure that prints the current location and a traceback. */ + +int main (void) + +{ +int i; + +printf ("Run-time error messages are:\n\n"); +for (i = 1; i <= sys_nerr; i++) + printf ("%3d: %s\n", i, strerror (i)); + +printf ("\nCurrent line: %d\nCurrent file: %s\n", __LINE__, __FILE__); + +printf ("Exiting with a traceback.\n"); +SystemErrorLocation (); +} diff --git a/C.Samples/Text.Samples/ErrorTrap.cc b/C.Samples/Text.Samples/ErrorTrap.cc new file mode 100644 index 0000000..8cf4185 --- /dev/null +++ b/C.Samples/Text.Samples/ErrorTrap.cc @@ -0,0 +1,95 @@ +/****************************************************************** +* +* Error Trap +* +* You can trap run-time errors with ORCA/C. There are several +* reasons to do this, including: +* +* 1. Error messages take up space. By replacing the +* system error handler with your own, you can cut +* out the space needed to store the run-time error +* messages. +* 2. You may want to trap some kinds of run-time +* errors, like file not found or out of memory, +* and handle them yourself. If you do not, the +* error will cause the program to stop executing, +* which may not be the desired result. +* +* This program shows how to intercept and handle run-time +* errors. This is done by placing a function in your program +* called SYSTEMERROR. The function has a single parameter, +* which is an integer error number. SYSTEMERROR replaces a +* function by the same name that is normally linked in from +* the libraries. Another library function, SystemErrorLocation, +* provides the name of the function and the line number where +* the run-time error occurred. +* +* Note that if you do not want to handle a particular error, +* you can call the system error handlers from your program. +* See the sample program ERROREXIT.CC for an example. +* +* By Mike Westerfield and Barbara Allred +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +*******************************************************************/ + +#pragma keep "ErrorTrap" +#pragma debug 9 /* enable range checking + trace-back */ +#pragma lint -1 + +#include + +extern pascal void SystemErrorLocation (void); +/* A library procedure that prints the current location and a traceback. */ + +/**************************************************************** +* +* BadFunction - Subroutine that will generate a run-time error +* +****************************************************************/ + +static void BadFunction (void) + +{ +char ch [8000]; /* this array is too large for */ +} /* the default run-time stack */ + + +/**************************************************************** +* +* DoIt - Calls function that will generate a run-time error +* +****************************************************************/ + +static void DoIt (void) +{ +BadFunction(); /* call function with large array */ +} + + +/**************************************************************** +* +* SystemError - Replaces SYSTEMERROR function in the ORCA library +* +****************************************************************/ + +static void SYSTEMERROR (int errorNumber) + +{ +printf ("Run-time error detected. error number = %d\n", errorNumber); +} + + +/**************************************************************** +* +* Main program starts here +* +****************************************************************/ + +int main(void) +{ +DoIt(); +SystemErrorLocation(); +} diff --git a/C.Samples/Text.Samples/Finance.cc b/C.Samples/Text.Samples/Finance.cc new file mode 100644 index 0000000..d9095d0 --- /dev/null +++ b/C.Samples/Text.Samples/Finance.cc @@ -0,0 +1,61 @@ +/************************************************ +* +* Finance +* +* This program prints the balance on an +* account for monthly payments, along with the +* total amount paid so far. +* +*************************************************/ + +#pragma keep "Finance" +#pragma lint -1 + +#include + +#define LOANAMOUNT 10000.0 /* amount of the loan */ +#define PAYMENT 600.0 /* monthly payment */ +#define INTEREST 15 /* yearly interest (as %) */ + +int main(void) + +{ +float balance, /* amount left to pay */ + monthlyInterest, /* multiplier for interest */ + paid ; /* total amount paid */ +int month; /* month number */ + +/* set up the initial values */ +balance = LOANAMOUNT; +paid = month = 0; +monthlyInterest = 1.0 + INTEREST/1200.0; + +/* write out the conditions */ +printf("Payment schedule for a loan of %10.2f\n", LOANAMOUNT); +printf("with monthly payments of %5.2f at an\n", PAYMENT); +printf("interest rate of %d%%.\n\n", INTEREST); +printf(" month balance amount paid\n"); +printf(" ----- ------- -----------\n"); + +/* check for payments that are too small */ +if (balance*monthlyInterest - balance >= PAYMENT) + printf("The payment is too small!"); +else + while (balance > 0) { + /* add in the interest */ + balance *= monthlyInterest; + /* make a payment */ + if (balance > PAYMENT) { + balance -= PAYMENT; + paid += PAYMENT; + } + else { + paid += balance; + balance = 0; + } + /* update the month number */ + ++month; + /* write the new statistics */ + printf("%15d %14.2f %14.2f\n", month, balance, paid); + } +} diff --git a/C.Samples/Text.Samples/Key.cc b/C.Samples/Text.Samples/Key.cc new file mode 100644 index 0000000..add966a --- /dev/null +++ b/C.Samples/Text.Samples/Key.cc @@ -0,0 +1,107 @@ +/***************************************************************** +* +* Keyboard Handling +* +* This program shows one way to access the keyboard directly +* from ORCA/C. Keep in mind that the standard file input +* collects an entire line of characters before reporting the +* first character. This is necessary to allow editing of the +* input line. When using the desktop environment, you can get +* keypress events from the event manager. This program shows +* how to detect a keypress as soon as it is hit. It echoes +* keys until you type CONTROL-@ (ASCII 0). +* +* The program works by reading the keyboard (at $C000) until +* the value is negative, indicating that a key has been +* pressed. It then stores a value (any value will do) in +* $C010 to indicate that the key has been read. This makes +* the value at $C010 positive (bit 7 is clear). The value of +* the key is then ANDed with $7F to clear the high bit. +* +* THIS METHOD OF READING THE KEYBOARD ONLY WORKS IN THE TEXT +* ENVIRONMENT. When the event manager is active, as it always +* is in a desktop program, you should call the event manager +* to read keystrokes. +* +* Checking to see when a key has been pressed is bundled into +* the function KeyPress. Returning the key and clearing the +* strobe is done in ReadChar. +* +* See key2 for a version that splits the keyboard routines off +* into a separately compilable module. +* +* See key3 for a version that uses assembly language to do the +* same thing. +* +* By Mike Westerfield and Barbara Allred +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +*******************************************************************/ + +#pragma keep "Key" +#pragma lint -1 + +#include + +static char ch; /* character read from keyboard */ + +/**************************************************************** +* +* KeyPress - Check if a key has been pressed +* +****************************************************************/ + +int KeyPress(void) + +{ +char *keyboard; + +keyboard = (char *) 0x00C000; +return ((*keyboard) & 0x80) != 0; +} + + +/**************************************************************** +* +* ReadChar - Return the last character typed on the keyboard. +* Note: Returns a character whether or not one has +* been typed! +* +****************************************************************/ + +char ReadChar (void) + +{ +char *keyboard, *strobe; + +keyboard = (char *) 0x00C000; +strobe = (char *) 0x00C010; +*strobe = 0; +return *keyboard & 0x7F; +} + + +/**************************************************************** +* +* Main program starts here +* +****************************************************************/ + +int main(void) + +{ +printf ("Press any key(s) and then RETURN. Enter CTRL-@ to quit.\n"); +do { + while (! KeyPress()) /* wait for a keypress */ + ; + ch = ReadChar(); /* get character typed from keybrd */ + if (ch == 0x0D) /* write character to the screen */ + printf ("\n"); + else + printf ("%c", ch); + } +while (ch != 0); +return 0; +} diff --git a/C.Samples/Text.Samples/Key2.Build b/C.Samples/Text.Samples/Key2.Build new file mode 100644 index 0000000..65fc04b --- /dev/null +++ b/C.Samples/Text.Samples/Key2.Build @@ -0,0 +1,20 @@ +unset exit +echo compile key2.cc +compile key2.cc +if {status} == 0 + echo compile key2.funcs + compile key2.funcs + if {status} == 0 + echo link key2.cc key2.funcs + link key2 funcs keep=Key2 + if {status} == 0 + key2 + else + echo Unable to link key2.cc key2.funcs + end + else + echo Unable to compile key2.funcs + end +else + echo Unable to compile key2.cc +end diff --git a/C.Samples/Text.Samples/Key2.Funcs b/C.Samples/Text.Samples/Key2.Funcs new file mode 100644 index 0000000..12c0660 --- /dev/null +++ b/C.Samples/Text.Samples/Key2.Funcs @@ -0,0 +1,43 @@ +/***************************************************************** +* +* This file contains the functions for KEY2.CC. See that file +* for detailed comments. +* +*******************************************************************/ + +#pragma keep "Funcs" + +/**************************************************************** +* +* KeyPress - Check if a key has been pressed +* +****************************************************************/ + +int KeyPress(void) + +{ +char *keyboard; + +keyboard = (char *) 0x00C000; +return ((*keyboard) & 0x80) != 0; +} + + +/**************************************************************** +* +* ReadChar - Returns the last character typed on the keyboard. +* Note: Returns a character whether or not one has +* been typed! +* +****************************************************************/ + +char ReadChar(void) + +{ +char *keyboard, *strobe; + +keyboard = (char *) 0x00C000; +strobe = (char *) 0x00C010; +*strobe = 0; +return *keyboard & 0x7F; +} diff --git a/C.Samples/Text.Samples/Key2.cc b/C.Samples/Text.Samples/Key2.cc new file mode 100644 index 0000000..7090299 --- /dev/null +++ b/C.Samples/Text.Samples/Key2.cc @@ -0,0 +1,61 @@ +/***************************************************************** +* +* Keyboard Handling +* +* This program demonstrates separate compilation by splitting +* the program KEY into two parts: the main program, and a +* separately compiled file with the keyboard subroutines that +* can then be called from many different programs without the +* need for recompiling. See KEY.CC for a full description of +* what this program does. +* +* The program now consists of four files: +* +* Key2.Build - EXEC file which separately compiles the two +* source files, then links their object +* modules to create the final program. To +* use the EXEC file, simply type KEY2.BUILD +* from the command line. +* +* Key2.cc - File containing main program. +* +* Key2.h - Header file accessed by the main program; +* Contains declarations of external functions. +* +* Key2.Funcs - File containing keyboard functions called +* by main program. +* +* See Key3 for a version that uses assembly language to read +* the keyboard. +* +* By Mike Westerfield and Barbara Allred +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +*******************************************************************/ + +#pragma keep "Key2" +#pragma lint -1 + +#include "Key2.h" +#include + +int main(void) + +{ +char ch; + +printf ("Press any key(s) and then RETURN. Enter CTRL-@ to quit.\n"); +do { + while (! KeyPress()) /* wait for a keypress */ + ; + ch = ReadChar(); /* get character typed from keybrd */ + if (ch == 0x0D) /* write character to the screen */ + printf ("\n"); + else + printf ("%c", ch); + } +while (ch != 0); +return 0; +} diff --git a/C.Samples/Text.Samples/Key2.h b/C.Samples/Text.Samples/Key2.h new file mode 100644 index 0000000..fa9af5a --- /dev/null +++ b/C.Samples/Text.Samples/Key2.h @@ -0,0 +1,4 @@ +/* Header file for program Key2.CC */ + +extern int KeyPress(void); +extern char ReadChar(void); diff --git a/C.Samples/Text.Samples/Key3.asm b/C.Samples/Text.Samples/Key3.asm new file mode 100644 index 0000000..07a689d --- /dev/null +++ b/C.Samples/Text.Samples/Key3.asm @@ -0,0 +1,41 @@ +**************************************************************** +* +* KeyPress - Check to see if a key has been pressed +* +* Outputs: +* A - 1 (true) if pressed, else 0 +* +**************************************************************** +* +KeyPress start +keyBoard equ $C000 keyboard location + + sep #$30 use short regs for load + lda >keyBoard load keyboard value + asl A shift sign bit into bit 0 + rol A + rep #$30 back to long regs + and #1 and out all but the bit we want + rtl + end + +**************************************************************** +* +* ReadChar - return the last character typed on the keyboard +* +* Outputs: +* A - character typed +* +**************************************************************** +* +ReadChar start +keyBoard equ $C000 keyboard location +strobe equ $C010 strobe location + + sep #$30 use short regs + sta >strobe clear strobe + lda >keyBoard load character + rep #$30 back to long regs + and #$007F and out high bits + rtl + end diff --git a/C.Samples/Text.Samples/Key3.cc b/C.Samples/Text.Samples/Key3.cc new file mode 100644 index 0000000..8445cb1 --- /dev/null +++ b/C.Samples/Text.Samples/Key3.cc @@ -0,0 +1,64 @@ +/***************************************************************** +* +* Keyboard Handling +* +* This is the final incarnation of the keyboard polling sample. +* See KEY.CC for complete comments on what the program does and +* how it works. +* +* In this version, we will write the two subroutines in +* assembly language. While you could use separate compilation +* to compile and assemble the two pieces separately, then +* link them, as in the last example, we will use chaining +* to avoid all of that. Chaining is a feature of all +* languages fully installed in ORCA or APW that allows a +* single program to be written in more than one language +* without resorting to separate compilation. Which method +* you prefer - chaining or separate compilation - depends +* on your own taste. +* +* To chain the two files together, we just place an append +* command after the end of the program. The rest is automatic +* To compile, assemble, link, and execute, we can now use the +* familiar RUN command: +* +* run key3.cc +* +* Note: both the assembler and compiler must be properly +* installed for this to work. The assembler is sold +* separately as ORCA/M 2.0 for the Apple IIGS. +* +* By Mike Westerfield and Barbara Allred +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +*******************************************************************/ + +#pragma keep "Key3" +#pragma lint -1 + +#include + +int main (void) + +{ +extern int KEYPRESS (void); /* declare assembly-language */ +extern int READCHAR (void); /* routines to be called */ +char ch; /* character read from keyboard */ + +printf("Press any key(s) and then RETURN. Enter CTRL-@ to quit.\n"); +do { + while (! KEYPRESS()) /* wait for a keypress */ + ; + ch = READCHAR(); /* get character typed from keybrd */ + if (ch == 0x0D) /* write character to the screen */ + printf ("\n"); + else + printf ("%c", ch); + } +while (ch != 0); +return 0; +} + +#append "Key3.asm" diff --git a/C.Samples/Text.Samples/Print.cc b/C.Samples/Text.Samples/Print.cc new file mode 100644 index 0000000..4ec510d --- /dev/null +++ b/C.Samples/Text.Samples/Print.cc @@ -0,0 +1,34 @@ +/***************************************************************** +* +* Text Printer Demo +* +* This example shows how to access the .PRINTER text printer +* driver from a C program. The .PRINTER driver must be installed +* before this sample is executed. +* +* There really isn't much to this sample, which may seem bad at +* first, but it's really good: accessing the text printer driver +* really is as simple as opening the printer and writing to it! +* +* By Mike Westerfield +* +* Copyright 1993 +* Byte Works, Inc. +* +*****************************************************************/ + +#pragma keep "Print" +#pragma lint -1 + +#include + +void main (void) + +{ +FILE *f; + +f = fopen(".printer", "w+"); +fprintf(f, "Hello, printer!\n"); +fputc('\f', f); /* on most printers, this will eject a page */ +fclose(f); +} diff --git a/C.Samples/Text.Samples/Trace.cc b/C.Samples/Text.Samples/Trace.cc new file mode 100644 index 0000000..cd04fb4 --- /dev/null +++ b/C.Samples/Text.Samples/Trace.cc @@ -0,0 +1,62 @@ +/**************************************************************** +* +* Trace +* +* ORCA/C can give you a traceback when a run-time error occurs. +* A traceback shows the function and line number where the +* error occurred, then gives a list of functions and line +* numbers that show what subroutine calls were made to get to +* the point where the error occurred. This program illustrates +* this by deliberately failing in the function named Fail. +* +* By Mike Westerfield and Barbara Allred +* +* Copyright 1987-1989 +* Byte Works, Inc. +* +******************************************************************/ + +#pragma keep "Trace" +#pragma debug 9 +#pragma lint -1 + +#include + + +/**************************************************************** +* +* Fail - Subroutine that will generate a run-time error +* +****************************************************************/ + +static void Fail (void) +{ +char ch [8000]; /* this array is too large for */ +} /* the default run-time stack */ + + +/**************************************************************** +* +* DoIt - Calls subroutine that will generate a run-time error +* +****************************************************************/ + +static void DoIt (void) + +{ +Fail(); +} + + +/**************************************************************** +* +* Main program starts here +* +****************************************************************/ + +int main (void) + +{ +printf ("This program fails. Generating a traceback:\n"); +DoIt(); +}