Guest User

Untitled

a guest
Apr 22nd, 2019
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 136.07 KB | None | 0 0
  1. /*
  2. ** GP142.c by Neil McKenzie
  3. **
  4. ** RCS $Id: gp142.c,v 1.17 2000/07/17 22:33:50 boren Exp $
  5. **
  6. ** Copyright (C) 1994 Neil McKenzie. All rights reserved.
  7. **
  8. ** Copyright (c) 1994 Corey Anderson.
  9. **
  10. ** Copyright (c) 1995 Casey Anderson.
  11. ** Revised version 1.5 of October, 1994
  12. ** Revised version 1.61 of December, 1994
  13. ** Revised version 2.00 of January, 1995
  14. ** conversion from callback fns to await_event
  15. ** Revised version 2.01 of July, 1995
  16. ** fixed hotkeys in windows
  17. ** Revised version 2.1 of October, 1995
  18. ** transparent text in windows; float pragma; casts;
  19. ** animation based on wall time elapsed
  20. ** "Fixed" PC window size problem, see FUDGE, below -- brd
  21. ** Includes changes made for port to WIN32 by Shuichi Koga
  22. ** All additions ifdefed by WIN32 -- brd
  23. **
  24. ** Revised version 2.2 on July, 1997
  25. ** X11R6 Melissa Johnson mjhnsn@u.washington.edu
  26. ** Assembly timer code for Mac replaced with C-based code. (Corey)
  27. ** Removed stack of objects. Replaced with offscreen buffer.
  28. ** Dramatically improves animation quality. (Josh, Melissa, Corey)
  29. ** Set GP142_DATE to indicate when GP142 was last _updated_, not
  30. ** merely last compiled. (Corey)
  31. **
  32. ** Revised version 2.2.1 of February, 1998
  33. ** Fixed autoKey/GP142_PERIODIC conflict for Mac,
  34. ** and did some cleanup in Mac event handling code (Daniel)
  35. **
  36. ** Revised February 4, 2000, Dan Boren boren@cs.washington.edu
  37. ** Fixed Windows version of the text window. Implemented double
  38. ** buffering to fix severe redraw bugs.
  39. **
  40. ** Revised February 4, 2000, Dan Boren boren@cs.washington.edu
  41. ** Minor change to Windows version of GP142_open() -- removed
  42. ** extraneous comma
  43. **
  44. ** Revised February, 2000, Dan Boren boren@cs.washington.edu
  45. ** Changed Windows message handling in YeildToSystem(). Changed
  46. ** PeekMessage() to GetMessage() in order to reduce CPU usage
  47. ** that was at 100% with PeekMessage().
  48. **
  49. ** Revised May, 2000, R. Dunn & L. Ruzzo
  50. ** added getDimensions functions to get height/width of text strings.
  51. **
  52. ** Revised May, 2000 Dan Boren boren@cs.washington.edu
  53. ** Used Shuichi's handling of WinMain/main().
  54. ** Fixed memory leak in DrawTextWnd().
  55. **
  56. */
  57.  
  58. #include "gp142lib.h" /* Library specific header */
  59. #define GP142_RCSREV "$Revision: 1.17 $"
  60. #define GP142_RCSDATE "$Date"
  61. #define GP142_VERSION "2.2xx"
  62. #define GP142_DATE "April 2000"
  63.  
  64. #define TIME_PER_STEP 50
  65. #define MAXSTRLEN 200 /* max string length for text fns */
  66. #define UNUSED(parameter) (parameter = parameter)
  67.  
  68. #if defined(WINDOWS)
  69. #define GP142_FUNC FAR EXPORT
  70. #define FUDGE 40 /* On the PC, the window is off by 40 pixels in the */
  71. /* Y dimension. Until we find a general fix, we're */
  72. /* stuck with this hack. -- brd */
  73. #elif defined(MACINTOSH)
  74. #define GP142_FUNC
  75. #elif defined(X11R6)
  76. #define GP142_FUNC
  77. #endif
  78.  
  79. /* Don't use assembly instructions if we can avoid it. */
  80. #define USE_ASM_FOR_TIMER 0
  81.  
  82.  
  83. /************************************************************* global variables ****/
  84. /* for double buffering. Redraw if true - josh */
  85. static int need_redraw = 1;
  86.  
  87. #ifdef MACINTOSH
  88.  
  89. #if USE_ASM_FOR_TIMER
  90. typedef struct {
  91. TMTask atmTask;
  92. long tmWakeUp;
  93. long tmReserved;
  94. long tmRefCon;
  95. } TMInfo, *TMInfoPtr;
  96.  
  97. TMInfo gMyTMInfo;
  98. #endif
  99.  
  100. Rect dragRect = { 0, 0, 1024, 1024 };
  101. Rect winrect = { 50, 20, 50+2*GP142_YMAX+1, 20+2*GP142_XMAX+1 };
  102.  
  103. RGBColor gRGBColors[MAX_COLORS] = {
  104. /* Black used to be 0x1000, 0x1000, 0x1000. Why??? */
  105. { 0x0000, 0x0000, 0x0000 }, /* black */
  106. { 0xFFFF, 0xFFFF, 0xFFFF }, /* white */
  107. { 0xFFFF, 0x0000, 0x0000 }, /* red */
  108. { 0x0000, 0xFFFF, 0x0000 }, /* green */
  109. { 0x0000, 0x0000, 0xFFFF }, /* blue */
  110. { 0xFFFF, 0xFFFF, 0x0000 }, /* yellow */
  111. { 0xFFFF, 0x0000, 0xFFFF }, /* magenta */
  112. { 0x0000, 0xFFFF, 0xFFFF }, /* cyan */
  113. { 0x9999, 0x0000, 0xCCCC }, /* purple */
  114. { 0x0000, 0x3333, 0x9999 }, /* navy blue */
  115. { 0x9999, 0x6666, 0x9999 }, /* dusty plum */
  116. { 0x9999, 0xFFFF, 0xFFFF }, /* ice blue */
  117. { 0x9999, 0xFFFF, 0xCCCC }, /* turquoise */
  118. { 0xFFFF, 0x6666, 0x0000 }, /* orange */
  119. { 0x9999, 0x6666, 0x3333 }, /* brown */
  120. { 0xFFFF, 0x9999, 0xCCCC }, /* pink */
  121. { 0xFFFF, 0xFFFF, 0x9999 }, /* chalk */
  122. { 0xCCCC, 0x9999, 0x3333 }, /* gold */
  123. { 0xFFFF, 0x9999, 0x6666 }, /* peach */
  124. { 0x0000, 0x6666, 0x3333 }, /* forest green */
  125. { 0x3333, 0xCCCC, 0x9999 }, /* sea green */
  126. { 0x9999, 0x9999, 0x3333 }, /* olive */
  127. { 0x8000, 0x8000, 0x8000 }, /* 50% gray */
  128. { 0xCCCC, 0xCCCC, 0xCCCC } /* 20% gray -- 80% white */
  129. };
  130.  
  131. enum {
  132. mAniRun = 1,
  133. mAniHalt,
  134. mAniSingle,
  135. mLog = 5,
  136. mScriptRecord = 7,
  137. mScriptPlay,
  138. mScriptOne,
  139. mQuit = 11};
  140.  
  141. char Menu_String[] = "\p"
  142. "Animate/A;"
  143. "Halt animation/H;"
  144. "Advance one frame/F;"
  145. "(-;"
  146. "Logging/L;"
  147. "(-;"
  148. "Record " kScriptName "/R;"
  149. "Playback " kScriptName "/P;"
  150. "Playback one event/O;"
  151. "(-;"
  152. "Quit/Q;"
  153. "(-;"
  154. "(GP142 v" GP142_VERSION " " GP142_DATE ";"
  155. "(mckenzie@cs.washington.edu;"
  156. "(corin@cs.washington.edu;"
  157. "(casey@cs.washington.edu"
  158. ;
  159.  
  160. MenuHandle RunMenu, DeskMenu;
  161. CWindowPtr gpWin = (CWindowPtr) 0;
  162.  
  163. /* The offscreen GWorld where the GP142 graphics are rendered. */
  164. GWorldPtr gGP142World = NULL;
  165.  
  166. char gColorFlag = 1; /* true if the target Mac runs color Quickdraw */
  167. PixPatHandle color_pp[MAX_COLORS];
  168.  
  169.  
  170. int nrows = 32;
  171. int ncols = 50;
  172.  
  173. #elif defined(WINDOWS)
  174.  
  175.  
  176. /* Structure used to keep around variables we need for initialization,
  177. * but the user shouldn't have to see.
  178. */
  179. typedef struct {
  180. HINSTANCE hInstance, hPrevInstance;
  181. LPSTR lpCmdLine;
  182. int nShowCmd;
  183. } GP142Globals;
  184.  
  185. /* Only one item of type Global needs to exist. */
  186. static GP142Globals global;
  187.  
  188. /* We need to state that there exists a main() apriori. */
  189. void main();
  190.  
  191.  
  192. HWND hDrawWnd = (HWND)NULL; /* handles to 2 windows in application */
  193. HWND hTextWnd = (HWND)NULL;
  194. HMENU hRunMenu; /* handle to menu */
  195. HINSTANCE hInst; /* Instance handle to this library */
  196.  
  197. /* need some stuff for double buffering - josh */
  198. HBITMAP offscreen_bitmap;
  199. HDC offscreen_DC, the_hdc;
  200.  
  201. /* Display context for text window */
  202. HDC text_hdc;
  203.  
  204. /* Handle to ring buffer for debug statements. We save the last
  205. MAX_CONOLE_LINES lines from the debuf window, so we can redraw them when
  206. the text window receives a WM_PAINT message */
  207. HANDLE gConsoleLines[MAX_CONSOLE_LINES];
  208. int gRingFirst = -1; /* -1 indicates that the ring buffer is empty */
  209. int gRingLast = 0; /* last is the next available position */
  210. #define RING_INC(i) (i = (i==MAX_CONSOLE_LINES-1)?0:i+1)
  211.  
  212. COLORREF gRGBColors[MAX_COLORS] = {
  213. RGB(0x00, 0x00, 0x00), /* black */
  214. RGB(0xFF, 0xFF, 0xFF), /* white */
  215. RGB(0xFF, 0x00, 0x00), /* red */
  216. RGB(0x00, 0xFF, 0x00), /* green */
  217. RGB(0x00, 0x00, 0xFF), /* blue */
  218. RGB(0xFF, 0xFF, 0x00), /* yellow */
  219. RGB(0xFF, 0x00, 0xFF), /* magenta */
  220. RGB(0x00, 0xFF, 0xFF), /* cyan */
  221. RGB(0x99, 0x00, 0xCC), /* purple */
  222. RGB(0x00, 0x33, 0x99), /* navy blue */
  223. RGB(0x99, 0x66, 0x99), /* dusty plum */
  224. RGB(0x99, 0xFF, 0xFF), /* ice blue */
  225. RGB(0x99, 0xFF, 0xCC), /* turquoise */
  226. RGB(0xFF, 0x66, 0x00), /* orange */
  227. RGB(0x99, 0x66, 0x33), /* brown */
  228. RGB(0xFF, 0x99, 0xCC), /* pink */
  229. RGB(0xFF, 0xFF, 0x99), /* chalk */
  230. RGB(0xCC, 0x99, 0x33), /* gold */
  231. RGB(0xFF, 0x99, 0x66), /* peach */
  232. RGB(0x00, 0x66, 0x33), /* forest green */
  233. RGB(0x33, 0xCC, 0x99), /* sea green */
  234. RGB(0x99, 0x99, 0x33), /* olive */
  235. RGB(0x80, 0x80, 0x80), /* 50% gray */
  236. RGB(0xCC, 0xCC, 0xCC) /* 20% gray -- 80% white */
  237. };
  238.  
  239. #elif defined(X11R6)
  240.  
  241. #define MAX_FONTS 7
  242.  
  243. Display *display;
  244. int screen;
  245. char *prog_name;
  246. Window window;
  247. Window wincomm;
  248. Window winc[8];
  249. GC gc;
  250. GC gccon;
  251. FontDB* font_info;
  252. FontDB* current_font;
  253. XColor color_ids[MAX_COLORS];
  254. int current_color_id;
  255.  
  256. /* for double-buffering - josh */
  257. Pixmap offscreen_buffer;
  258.  
  259. RGBColor gRGBColors[MAX_COLORS] = {
  260. { 0x1000, 0x1000, 0x1000 }, /* black */
  261. { 0xFFFF, 0xFFFF, 0xFFFF }, /* white */
  262. { 0xFFFF, 0x0000, 0x0000 }, /* red */
  263. { 0x0000, 0xFFFF, 0x0000 }, /* green */
  264. { 0x0000, 0x0000, 0xFFFF }, /* blue */
  265. { 0xFFFF, 0xFFFF, 0x0000 }, /* yellow */
  266. { 0xFFFF, 0x0000, 0xFFFF }, /* magenta */
  267. { 0x0000, 0xFFFF, 0xFFFF }, /* cyan */
  268. { 0x9999, 0x0000, 0xCCCC }, /* purple */
  269. { 0x0000, 0x3333, 0x9999 }, /* navy blue */
  270. { 0x9999, 0x6666, 0x9999 }, /* dusty plum */
  271. { 0x9999, 0xFFFF, 0xFFFF }, /* ice blue */
  272. { 0x9999, 0xFFFF, 0xCCCC }, /* turquoise */
  273. { 0xFFFF, 0x6666, 0x0000 }, /* orange */
  274. { 0x9999, 0x6666, 0x3333 }, /* brown */
  275. { 0xFFFF, 0x9999, 0xCCCC }, /* pink */
  276. { 0xFFFF, 0xFFFF, 0x9999 }, /* chalk */
  277. { 0xCCCC, 0x9999, 0x3333 }, /* gold */
  278. { 0xFFFF, 0x9999, 0x6666 }, /* peach */
  279. { 0x0000, 0x6666, 0x3333 }, /* forest green */
  280. { 0x3333, 0xCCCC, 0x9999 }, /* sea green */
  281. { 0x9999, 0x9999, 0x3333 }, /* olive */
  282. { 0x8000, 0x8000, 0x8000 }, /* 50% gray */
  283. { 0xCCCC, 0xCCCC, 0xCCCC } /* 20% gray -- 80% white */
  284. };
  285.  
  286. #endif
  287.  
  288. static char *gColorName[MAX_COLORS] = {
  289. "black",
  290. "white",
  291. "red",
  292. "green",
  293. "blue",
  294. "yellow",
  295. "magenta",
  296. "cyan",
  297. "purple",
  298. "navy blue",
  299. "dusty plum",
  300. "ice blue",
  301. "turquoise",
  302. "orange",
  303. "brown",
  304. "pink",
  305. "chalk",
  306. "gold",
  307. "peach",
  308. "forest green",
  309. "sea green",
  310. "olive",
  311. "50% gray",
  312. "20% gray"
  313. };
  314.  
  315.  
  316. static int gEventAction;
  317. static GP142_event_t gEventRecord;
  318.  
  319. /* control flags */
  320. static char gRunFlag; /* Running animation? */
  321. static char gSingleStepFlag; /* Single stepping animation? */
  322. static char gDoneFlag; /* Program concluded? */
  323. static char gLogging = LOG_ON; /* Log actions to console? */
  324. static char gRecordingFlag = FALSE; /* Recording user actions for later playback? */
  325. static char gScriptStepFlag = FALSE; /* Playback one action? */
  326. static char gScriptPlayFlag = FALSE; /* Continuously playback actions? */
  327. static int gAnimExpired = FALSE;
  328.  
  329. /* scripting */
  330. static FILE *gScriptFP = NULL; /* file pointer to script file (in or out); NULL if not open */
  331. static int gTaskCount = 0; /* number of consecutive calls to GP142_user_task */
  332.  
  333. static int gXCenter, gYCenter;
  334.  
  335.  
  336. /********************************************************* Library Initialization ***/
  337. #ifdef MACINTOSH
  338.  
  339. #if USE_ASM_FOR_TIMER
  340.  
  341. #ifndef __MWERKS__
  342.  
  343. void timerFlagProc(void)
  344. {
  345. long oldA5;
  346. TMInfoPtr recPtr;
  347.  
  348. asm { /* The time manager puts the address */
  349. move.l a1, recPtr /* of the expired timer in register a1*/
  350. }
  351.  
  352. oldA5 = SetA5(recPtr->tmRefCon); /* This is so we can touch the global */
  353. /* variables of GP142 app*/
  354.  
  355. gAnimExpired = TRUE;
  356.  
  357. oldA5 = SetA5(oldA5); /* Change global variable start address */
  358. /* back to what it was*/
  359.  
  360. PrimeTime((QElemPtr)recPtr, TIME_PER_STEP); /* Reprime the timer for another */
  361. /* .1 seconds */
  362. }
  363.  
  364. #else /* __MWERKS__ */
  365.  
  366. /*
  367. ** Metrowerks supports asm only for entire functions.
  368. ** This func is equiv to the preceding one:
  369. ** Save A5; restore GP142's A5 from timer record;
  370. ** set global flag; restore A5; requeue timer record.
  371. ** WLR 2/96. Thanks to MAC.
  372. */
  373. static asm void timerFlagProc(void)
  374. {
  375. move.l A5, A0
  376. move.l struct(TMInfo_s.tmRefCon)(A1), A5
  377. move.w #1, gAnimExpired
  378. move.l A0, A5
  379. move.l A1, A0
  380. move.l #TIME_PER_STEP, D0
  381. _PrimeTime
  382. rts
  383. }
  384. #endif
  385.  
  386. #endif /* USE_ASM_FOR_TIMER */
  387.  
  388. extern int GP142_open(void) /* was GP142_main() in GP142 v1.x */
  389. {
  390. int console_flag = /* 0 for either defers opening */
  391. nrows!=0 && ncols!=0 ; /* console, but leaves default size. */
  392.  
  393. ToolboxInit(); /* Initialize the Mac toolbox */
  394. #ifdef __MWERKS__
  395. if (nrows) SIOUXSettings.rows = nrows;
  396. if (ncols) SIOUXSettings.columns= ncols;
  397. SIOUXSettings.initializeTB = 0; /* Do we initialize the ToolBox ... */
  398. SIOUXSettings.setupmenus = 0; /* Do we draw the SIOUX menus ... */
  399. SIOUXSettings.autocloseonquit = 1; /* Do we close the SIOUX window on program termination ... */
  400. SIOUXSettings.asktosaveonclose = 0; /* Do we offer to save on a close ... */
  401. SIOUXSettings.toppixel = 40; /* The topleft window position (in pixels) */
  402. SIOUXSettings.leftpixel = 2; /* (0,0 centers on main screen) ... */
  403. #else
  404. if (nrows) console_options.nrows = nrows;
  405. if (ncols) console_options.ncols = ncols;
  406. #endif
  407. if ( console_flag ) { /* don't open console unnecessarily */
  408. printf("GP142 graphics package version " GP142_VERSION " (" GP142_DATE ")\n");
  409. printf("This is the console window\n");
  410. if (!gColorFlag) {
  411. printf("This Macintosh does not have Color Quickdraw.\n");
  412. printf("All objects will be drawn using black.\n");
  413. }
  414. }
  415.  
  416.  
  417. /*Here we initialize a timer, add it to the queue, and prime it*/
  418. #if USE_ASM_FOR_TIMER
  419. gMyTMInfo.atmTask.tmAddr = (TimerUPP)timerFlagProc;
  420. gMyTMInfo.tmRefCon = SetCurrentA5(); /* This is so we can access */
  421. /* the Global variables later */
  422. gMyTMInfo.tmWakeUp = 0;
  423. gMyTMInfo.tmReserved = 0;
  424. InsTime((QElemPtr)&gMyTMInfo);
  425. PrimeTime((QElemPtr)&gMyTMInfo, TIME_PER_STEP);
  426. #endif
  427.  
  428. SelectWindow((void *)gpWin); /* Better to do it once here than every time */
  429. /* through the event loop -dia */
  430. return GP142_SUCCESS;
  431. }
  432.  
  433. /* Initialize Mac stuff */
  434. static void ToolboxInit(void)
  435. {
  436. int i;
  437. long myFeature;
  438. Rect r;
  439.  
  440. #if USES_NEW_HEADERS
  441. InitGraf(&qd.thePort);
  442. #else
  443. InitGraf(&thePort);
  444. #endif
  445. InitFonts();
  446. InitWindows();
  447. InitCursor();
  448. InitDialogs(0);
  449. TEInit();
  450. InitMenus();
  451. FlushEvents( everyEvent, 0 );
  452.  
  453. /* Desk Accessory menu */
  454. DeskMenu = NewMenu(Desk_ID,"\p\024");
  455. #if USES_NEW_HEADERS
  456. AppendResMenu(DeskMenu, 'DRVR');
  457. #else
  458. AddResMenu(DeskMenu, 'DRVR');
  459. #endif
  460. InsertMenu(DeskMenu, 0);
  461.  
  462. /* Run menu */
  463. RunMenu = NewMenu(Run_ID, "\pRun");
  464. AppendMenu(RunMenu, (ConstStr255Param)Menu_String);
  465. InsertMenu(RunMenu, 0);
  466. CheckItem(RunMenu, 4, (int)gLogging);
  467.  
  468. /* Let's see if we can use COLOR */
  469. Gestalt(gestaltQuickdrawVersion, &myFeature);
  470. if (myFeature < gestalt8BitQD) {
  471. gColorFlag = 0;
  472. }
  473.  
  474. /* Create the window */
  475. DrawMenuBar();
  476. if (gColorFlag)
  477. gpWin = (CWindowPtr) NewCWindow(0,&winrect,"\pGP142 Graphics Window",
  478. 1,0,(void *)(-1),1,0);
  479. else
  480. gpWin = (CWindowPtr) NewWindow(0,&winrect,"\pGP142 Graphics Window",
  481. 1,0,(void *)(-1),1,0);
  482.  
  483. gRunFlag = 0;
  484. gDoneFlag = 0;
  485. gSingleStepFlag = 0;
  486.  
  487. /* Make some colors */
  488. if (gColorFlag) {
  489. for (i=0; i<MAX_COLORS; i++) {
  490. color_pp[i] = NewPixPat();
  491. MakeRGBPat(color_pp[i], &gRGBColors[i]);
  492. }
  493. }
  494.  
  495. /* Find the offset to the center of the window */
  496. gXCenter = (winrect.right - winrect.left) >> 1;
  497. gYCenter = (winrect.bottom - winrect.top) >> 1;
  498.  
  499. /* Create the offscreen GWorld into which we will render out GP142
  500. objects */
  501. SetRect(&r, 0, 0, 2*GP142_XMAX+1, 2*GP142_YMAX+1);
  502. if (noErr != NewGWorld(&gGP142World, /* The returned offscreen world */
  503. 8, /* bits per pixel */
  504. &r, /* size of buffer */
  505. nil, /* Color table. Use the default. */
  506. nil, /* I forget why this is nil... */
  507. 0)) { /* Don't need any flags */
  508. SysBeep(10);
  509. ExitToShell();
  510. return;
  511. }
  512. }
  513.  
  514. #elif defined(WINDOWS)
  515.  
  516. /*
  517. * Hide the four global variables from the user, permitting them to simply
  518. * define a main() function. (idea by Shuichi Koga, implemented by Dan Boren).
  519. */
  520. PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  521. {
  522. global.hInstance = hInstance;
  523. global.hPrevInstance = hPrevInstance;
  524. global.lpCmdLine = lpCmdLine;
  525. global.nShowCmd = nShowCmd;
  526.  
  527. main();
  528. }
  529.  
  530.  
  531. void _GP142_pseudocall(void)
  532. {
  533. int a,x,y;
  534. char c='a';
  535. GP142_point p = {0,0};
  536. GP142_event_t t = {0, 0, 0};
  537. x = y =a = 0;
  538. if (a*a) /* we won't actually call these functions
  539. a trick to get rid of compiler warnings */
  540. {
  541. GP142_clear();
  542. GP142_undo();
  543. GP142_logging(LOG_OFF);
  544. GP142_animate(ANI_HALT);
  545. GP142_gets(NULL,NULL);
  546. GP142_pixelXY(0,0,0);
  547. GP142_lineXY(0,0,0,0,0,0);
  548. GP142_rectangleXY(0,0,0,0,0,0);
  549. GP142_triangleXY(0,0,0,0,0,0,0,0);
  550. GP142_ovalXY(0,0,0,0,0,0);
  551. GP142_circleXY(0,0,0,0);
  552. GP142_printfXY(0,0,0,0,NULL);
  553. GP142_textXY(0,0,0,0,NULL);
  554. GP142_await_eventP((GP142_event_t*)NULL);
  555. GP142_pixelP(0,p);
  556. GP142_lineP(0,p,p,0);
  557. GP142_rectangleP(0,p,p,0);
  558. GP142_triangleP(0,p,p,p,0);
  559. GP142_ovalP(0,p,p,0);
  560. GP142_circleP(0,p,0);
  561. GP142_printfP(0,p,0,NULL);
  562. GP142_textP(0,p,0,NULL);
  563. GP142_close();
  564. GP142_await_event(&x,&y,&c);
  565. PlayFromScript();
  566. CloseScript();
  567. SaveToScript(0,t);
  568. }
  569. }
  570.  
  571. extern int GP142_FUNC GP142_open()
  572. /*GP142_open(HANDLE hInstance, HANDLE hPrevInstance,
  573. LPSTR lpszCmdLine, int nCmdShow)*/
  574.  
  575.  
  576. {
  577. WNDCLASS wc;
  578. int x, y;
  579. /* BOOL done = FALSE; */
  580.  
  581. _GP142_pseudocall(); /* let the compiler think all
  582. GP142 functions have been
  583. called */
  584. UNUSED(global.lpCmdLine);
  585.  
  586. /************ register window classes ****************/
  587. if (!global.hPrevInstance) /* initialize window classes when first run */
  588. {
  589. /* first, register the graphics window class */
  590. wc.hInstance = global.hInstance;
  591. wc.hIcon = LoadIcon((HINSTANCE)NULL, IDI_APPLICATION);
  592. wc.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
  593. wc.lpszMenuName = "generic";
  594. wc.style = CS_HREDRAW | CS_VREDRAW;
  595. wc.cbClsExtra = 0;
  596. wc.cbWndExtra = 0;
  597. wc.lpfnWndProc = (WNDPROC) DrawWndProc;
  598. wc.hbrBackground = CreateSolidBrush(gRGBColors[BKGND_COLOR]),
  599. wc.lpszClassName = "DrawWndClass";
  600. RegisterClass(&wc);
  601.  
  602. /* now, register the text window, child of draw */
  603. wc.style = CS_HREDRAW | CS_VREDRAW;
  604. wc.lpfnWndProc = (WNDPROC)TextWndProc;
  605. wc.lpszClassName = "TextWndClass";
  606. RegisterClass(&wc);
  607. }
  608.  
  609.  
  610. /************* Initialize global variables *******************/
  611. x = GetSystemMetrics(SM_CXSCREEN);
  612. y = GetSystemMetrics(SM_CYSCREEN);
  613. gRunFlag = FALSE;
  614. gSingleStepFlag = FALSE;
  615.  
  616. /************ Create windows ***************/
  617. /* Create our two windows: first graphics, then text */
  618. hDrawWnd = CreateWindow("DrawWndClass",
  619. "ABC", /* Title of window */
  620. WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_BORDER, /* window style */
  621. 0, /* position in upper left */
  622. 0,
  623. 2*GP142_XMAX+1, /* pixels horz.*/
  624. 2*GP142_YMAX+FUDGE, /* pixels vert.*/
  625. (HWND)NULL, /* draw has no parent */
  626. (HMENU)NULL, /* use class menu */
  627. global.hInstance, /* instance of program */
  628. NULL); /* NULL window data */
  629. hTextWnd = CreateWindow(
  630. "TextWndClass", /* window class name */
  631. "GP142 Text", /* Title of window */
  632. WS_OVERLAPPEDWINDOW,
  633. 0, /* all the way to the left */
  634. 2*GP142_YMAX+FUDGE+10, /* make it abut draw window */
  635. 2*GP142_XMAX+1,/* x,*/ /* same width as draw window */
  636. y/4, /* 1/4 maximum height */
  637. (HWND)NULL, /* Text has no parent */
  638. (HMENU)NULL, /* no menu */
  639. global.hInstance, /* instance of program */
  640. NULL); /* NULL window data */
  641. SetWindowText(hDrawWnd, TEXT("Paint Brush"));
  642. hInst = global.hInstance;
  643.  
  644.  
  645. /* init the double-buffer windows - josh */
  646. the_hdc = GetDC(hDrawWnd);
  647. offscreen_bitmap = CreateCompatibleBitmap(the_hdc, 2*GP142_XMAX+1, 2*GP142_YMAX+FUDGE);
  648. offscreen_DC = CreateCompatibleDC(the_hdc);
  649. SelectObject (offscreen_DC, offscreen_bitmap);
  650.  
  651. ShowWindow(hTextWnd, global.nShowCmd);
  652. ShowWindow(hDrawWnd, global.nShowCmd);
  653.  
  654. SetTimer(hDrawWnd, 2, TIME_PER_STEP, NULL);
  655.  
  656. return GP142_SUCCESS;
  657. }
  658.  
  659. #elif defined(X11R6)
  660.  
  661. void create_GC(Window window, GC *gc, int fid) {
  662.  
  663. XGCValues gc_val;
  664.  
  665. *gc = XCreateGC(display, window, 0, &gc_val);
  666. XSetFont(display, *gc, fid);
  667.  
  668. XSetForeground(display, *gc, color_ids[2].pixel);
  669. XSetLineAttributes(display, *gc, 3, LineSolid, CapRound, JoinRound);
  670. return;
  671. }
  672.  
  673. extern int GP142_open(void) {
  674.  
  675. char *win_name = "GP142 Graphics Window";
  676. char *win_name_comm = "GP142 Control Window";
  677. char *icon_name = "GP142";
  678. char *icon_name_comm = "GP142 Controls";
  679. char *display_name = NULL;
  680. int i;
  681. unsigned int border_width = 2;
  682. XSizeHints *size_hint;
  683. XWMHints *wm_hint;
  684. XClassHint *class_hint;
  685. XTextProperty WinNameComm, WinName, IconNameComm, IconName;
  686. Window dummy_win;
  687. int dummy_x, dummy_y;
  688. unsigned int dummy_width, dummy_height, dummy_border, depth;
  689. prog_name = "GP142";
  690.  
  691. if (!(size_hint = XAllocSizeHints()) || !(wm_hint = XAllocWMHints())
  692. || !(class_hint = XAllocClassHint())
  693. || (display = XOpenDisplay (display_name)) == NULL) {
  694. fprintf(stderr, "%s: Unable to open X display %s.\n", prog_name,
  695. XDisplayName(display_name));
  696. exit(0);
  697. }
  698.  
  699. screen = DefaultScreen(display);
  700.  
  701. window = XCreateSimpleWindow(display, RootWindow(display, screen), 10,
  702. 10, GP142_XMAX*2, GP142_YMAX*2, border_width,
  703. BlackPixel(display, screen), WhitePixel(display, screen));
  704. wincomm = XCreateSimpleWindow(display, RootWindow(display, screen), 50,
  705. 50, 200, 105, border_width, BlackPixel(display, screen),
  706. WhitePixel(display, screen));
  707. /* double buffering - josh */
  708. XGetGeometry(display, window, &dummy_win, &dummy_x, &dummy_y, &dummy_width, &dummy_height,
  709. &dummy_border, &depth);
  710. offscreen_buffer = XCreatePixmap(display, window, GP142_XMAX*2, GP142_YMAX*2, depth);
  711.  
  712. gXCenter = GP142_XMAX;
  713. gYCenter = GP142_YMAX;
  714.  
  715. /***TODO***/
  716. if (XStringListToTextProperty(&win_name, 1, &WinName) == 0) {
  717. fprintf(stderr, "\n%s: Ow.\n\n", prog_name);
  718. exit(0);
  719. }
  720.  
  721. if (XStringListToTextProperty(&icon_name, 1, &IconName) == 0) {
  722. fprintf(stderr, "\n%s: Ow.\n\n", prog_name);
  723. exit(0);
  724. }
  725.  
  726. if (XStringListToTextProperty(&win_name_comm, 1, &WinNameComm) == 0) {
  727. fprintf(stderr, "\n%s: Ow.\n\n", prog_name);
  728. exit(0);
  729. }
  730.  
  731. if (XStringListToTextProperty(&icon_name_comm, 1, &IconNameComm) == 0) {
  732. fprintf(stderr, "\n%s: Ow.\n\n", prog_name);
  733. exit(0);
  734. }
  735.  
  736. gRunFlag = 0;
  737. gDoneFlag = 0;
  738. gSingleStepFlag = 0;
  739.  
  740. /* size hints to keep windows size from changing */
  741.  
  742. size_hint -> flags = PSize | PPosition | PMinSize | PMaxSize;
  743. size_hint -> min_width = 600;
  744. size_hint -> min_height = 500;
  745. size_hint -> max_width = 600;
  746. size_hint -> max_height = 500;
  747. wm_hint -> flags = StateHint | InputHint;
  748. wm_hint -> input = True;
  749. wm_hint -> initial_state = NormalState;
  750. class_hint -> res_name = prog_name;
  751. class_hint -> res_class = prog_name;
  752. XSetWMProperties(display, window, &WinName, &IconName, 0, 0,
  753. size_hint, wm_hint, class_hint);
  754.  
  755. size_hint -> min_width = 200;
  756. size_hint -> min_height = 105;
  757. size_hint -> max_width = 200;
  758. size_hint -> max_height = 105;
  759. XSetWMProperties(display, wincomm, &WinNameComm, &IconNameComm, 0, 0,
  760. size_hint, wm_hint, class_hint);
  761.  
  762. XSelectInput(display, window, StructureNotifyMask | ExposureMask |
  763. KeyPressMask | ButtonPressMask | EnterWindowMask | LeaveWindowMask);
  764. XSelectInput(display, wincomm, StructureNotifyMask | ExposureMask |
  765. KeyPressMask | ButtonPressMask | EnterWindowMask | LeaveWindowMask);
  766.  
  767. font_info = (FontDB*) malloc (sizeof(FontDB));
  768. if ((font_info == NULL) ||
  769. (font_info->thefont = XLoadQueryFont(display,
  770. "-adobe-times-medium-r-normal--0-150-75-75-p-0-iso8859-1"))
  771. == NULL) {
  772. fprintf(stderr, "Cannot open adobe-times scalable font.\n\n");
  773. exit(0);
  774. }
  775. font_info -> point_size = 15;
  776. font_info -> next = NULL;
  777. current_font = font_info;
  778.  
  779. for (i = 0; i < MAX_COLORS; i++) {
  780. color_ids[i].red = gRGBColors[i].red;
  781. color_ids[i].green = gRGBColors[i].green;
  782. color_ids[i].blue = gRGBColors[i].blue;
  783. color_ids[i].flags = DoRed | DoGreen | DoBlue;
  784. XAllocColor(display, DefaultColormap(display, screen), &color_ids[i]);
  785. }
  786.  
  787. current_color_id = 2;
  788.  
  789. create_GC(window, &gc, font_info->thefont->fid);
  790. create_GC(window, &gccon, font_info->thefont->fid);
  791. XSetForeground(display, gccon, BlackPixel(display, screen));
  792.  
  793. XMapWindow(display, window);
  794. XMapWindow(display, wincomm);
  795.  
  796. for (i = 0; i < 8; i++) {
  797. winc[i] = XCreateSimpleWindow(display, wincomm, (i / 4) * 100,
  798. ((i % 4) * 25) + 5, 95, 20, 2, BlackPixel(display,
  799. screen), WhitePixel(display, screen));
  800. XSelectInput(display, winc[i], StructureNotifyMask | ExposureMask |
  801. KeyPressMask | ButtonPressMask | EnterWindowMask | LeaveWindowMask);
  802. XMapWindow(display,winc[i]);
  803. }
  804.  
  805. /* We must be open and waiting for drawing commands at this
  806. * point. However, X does not guarantee this until we receive the first
  807. * XExpose event
  808. */
  809.  
  810. while(1)
  811. {
  812. XEvent event;
  813. XNextEvent(display, &event);
  814. if(event.type == Expose)
  815. if (event.xany.window == window)
  816. break;
  817. else
  818. Process_event(event);
  819. }
  820.  
  821. return GP142_SUCCESS;
  822. }
  823. #endif
  824.  
  825.  
  826. /************************************************************** Library Closure ***/
  827. #ifdef MACINTOSH
  828. extern int GP142_close(void)
  829. {
  830. #if USE_ASM_FOR_TIMER
  831. /* Remove the timer entry from the queue*/
  832. RmvTime((QElemPtr)&gMyTMInfo);
  833. #endif
  834.  
  835. /* Is there anything we should do here? */
  836. CloseScript();
  837.  
  838. return GP142_SUCCESS;
  839. }
  840.  
  841. #elif defined (WINDOWS)
  842. /* Windows Exit Procedure */
  843. int FAR PASCAL EXPORT WEP (int nParameter)
  844. {
  845. UNUSED(nParameter);
  846. return (1);
  847. }
  848.  
  849. extern int GP142_FUNC
  850. GP142_close(void)
  851. {
  852. /* Free the memory used by our offscreen graphics world */
  853. ReleaseDC(hDrawWnd, the_hdc);
  854. CloseScript();
  855.  
  856. return GP142_SUCCESS;
  857. }
  858.  
  859. #elif defined(X11R6)
  860.  
  861. extern int GP142_close(void) {
  862.  
  863. CloseScript();
  864. while (font_info) {
  865. FontDB* temp;
  866. XUnloadFont(display, font_info -> thefont -> fid);
  867. temp = font_info;
  868. font_info = font_info -> next;
  869. free(temp); /* no need to free memory at the end of the program
  870. * but do it anyway */
  871. }
  872.  
  873. XFreeGC(display, gc);
  874. XCloseDisplay(display);
  875.  
  876. return GP142_SUCCESS;
  877.  
  878. }
  879.  
  880. #endif
  881.  
  882.  
  883.  
  884. /******************************************************* Event Handling ***/
  885. /* Concept: Students will call GP142_await_event() in their own event loop,
  886. and handle the returned value accordingly. Possible return values are
  887. GP142_MOUSE, GP142_KBD, GP142_SK, and GP142_QUIT */
  888.  
  889. /*********************************************************** GP142_await_event()
  890. */
  891. extern int GP142_FUNC
  892. GP142_await_event(int *x, int *y, char *c)
  893. {
  894. GP142_event_t e;
  895. int a;
  896.  
  897. a = GP142_await_eventP(&e);
  898.  
  899. *x = e.x;
  900. *y = e.y;
  901. *c = e.c;
  902.  
  903. return a;
  904. }
  905.  
  906. extern int GP142_FUNC
  907. GP142_await_eventP(GP142_event_t *e)
  908. {
  909. int eventCounter;
  910. #ifdef WINDOWS
  911. BOOL done = FALSE;
  912. #endif
  913.  
  914. /* GP142_await_event() should return only with a message that student
  915. might want to handle. That is, only with mouse, keyboard,
  916. idle, or quit messages. If we're in animiate mode, we'll pass
  917. an idle event after handleing MAX_EVENTS events (or if some
  918. user interaction occurs). Otherwise, we won't return until the
  919. user does some action. */
  920.  
  921. gEventAction = GP142_NONE;
  922. gEventRecord.x = gEventRecord.y = gEventRecord.c = 0;
  923.  
  924. eventCounter = 0;
  925. while ( gEventAction == GP142_NONE ||
  926. (gEventAction == GP142_PERIODIC && gAnimExpired == FALSE))
  927. {
  928. eventCounter = 1;
  929. YieldToSystem();
  930.  
  931. /* If we're reading from a script file, don't honor user's actions;
  932. obey the script instead */
  933. if (gScriptStepFlag || gScriptPlayFlag)
  934. {
  935. gScriptStepFlag = FALSE;
  936. /* This will fill in global data */
  937. if (PlayFromScript() == GP142_SUCCESS)
  938. break;
  939. else
  940. {
  941. gScriptStepFlag = FALSE;
  942. gScriptPlayFlag = FALSE;
  943. }
  944. }
  945.  
  946. /* Only pass back a GP142_PERIODIC if we're animating, or
  947. single stepping */
  948. if ((gSingleStepFlag || gRunFlag) && gEventAction == GP142_NONE)
  949. {
  950. gEventAction = GP142_PERIODIC;
  951. gAnimExpired = FALSE;
  952. gSingleStepFlag = FALSE;
  953. gScriptStepFlag = FALSE;
  954. }
  955.  
  956. }
  957.  
  958. /* Also, if we're recording to a script, we'll want to save the information */
  959. if (gRecordingFlag)
  960. {
  961. if (gEventAction == GP142_PERIODIC)
  962. gTaskCount++;
  963. else
  964. {
  965. if (gTaskCount > 0)
  966. {
  967. SaveToScript(GP142_PERIODIC, gEventRecord);
  968. gTaskCount = 0;
  969. }
  970. SaveToScript(gEventAction, gEventRecord);
  971. }
  972. }
  973.  
  974. *e = gEventRecord;
  975. /* UNUSED(done); // there should be a reason we declared
  976. // done and eventCounter, just leave them here. */
  977. UNUSED(eventCounter);
  978. return gDoneFlag?GP142_QUIT:gEventAction;
  979. }
  980.  
  981. static void YieldToSystem(void)
  982. {
  983. #ifdef MACINTOSH
  984. EventRecord event;
  985. #elif defined(WINDOWS)
  986. MSG msg;
  987. BOOL done = FALSE;
  988. #elif defined(X11R6)
  989. XEvent event;
  990. #endif
  991.  
  992. /* UNUSED(done); */
  993. #ifdef MACINTOSH
  994. #if !USE_ASM_FOR_TIMER /* This stuff was moved out of HandleMessage to fix bug */
  995. UnsignedWide now; /* concerning autoKey event stopping animation -dia */
  996. static UnsignedWide lastExpired = {0,0};
  997. unsigned long delta_microseconds;
  998.  
  999. /* Has it been long enough since the last animation step? */
  1000. Microseconds(&now);
  1001.  
  1002. /* Calculate how many microseconds have elapsed since the last time
  1003. we set the gAnimExpired flag. */
  1004. if (lastExpired.hi == 0 && lastExpired.lo == 0) {
  1005. lastExpired = now;
  1006. gAnimExpired = TRUE;
  1007. } else if (now.hi == lastExpired.hi) {
  1008. delta_microseconds = now.lo - lastExpired.lo;
  1009. } else if (now.hi == lastExpired.hi + 1) {
  1010. delta_microseconds = now.hi + ((unsigned long)(-1) - lastExpired.lo);
  1011. } else {
  1012. /* It's been a _really_ long time since the last timer overflow. */
  1013. delta_microseconds = (unsigned long)(-1);
  1014. }
  1015.  
  1016. /* !!! The 840 number here is kinda a kludge. TIME_PER_STEP represents
  1017. the number of milliseconds between animation steps. Thus, we should
  1018. multiply TIME_PER_STEP by 1000 to determine the number of microseconds
  1019. between steps. However, I found that doing so didn't give the same time
  1020. delay between animation steps as did the original Mac code. So
  1021. 840 is used, which is pretty close. */
  1022. if (delta_microseconds > TIME_PER_STEP * 840) {
  1023. gAnimExpired = TRUE;
  1024. lastExpired = now;
  1025. }
  1026. #endif
  1027. /* SelectWindow((void *)gpWin);
  1028. GetNextEvent(everyEvent, &event);
  1029. SystemTask();*/
  1030. if ((!gSingleStepFlag && !gRunFlag) || !gAnimExpired)
  1031. {
  1032. WaitNextEvent(everyEvent, &event, 1, 0); /* Use WaitNextEvent -dia */
  1033. HandleMessage(&event);
  1034. }
  1035. #elif defined(WINDOWS)
  1036. /*found_message = PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE);*/
  1037. /* GetMessage() returns 0 if a WM_QUIT message was received */
  1038. if (!GetMessage(&msg, (HWND)NULL, 0, 0))
  1039. {
  1040. gEventAction = GP142_QUIT;
  1041. return;
  1042. } else {
  1043. TranslateMessage(&msg);
  1044. DispatchMessage(&msg);
  1045. }
  1046. if (need_redraw) {
  1047. BitBlt (the_hdc,0,0,2*GP142_XMAX+1, 2*GP142_YMAX+FUDGE,
  1048. offscreen_DC,0,0,SRCCOPY);
  1049. need_redraw = 0;
  1050. }
  1051. #elif defined(X11R6)
  1052.  
  1053. if (XPending(display)) {
  1054. XNextEvent(display, &event);
  1055. Process_event(event);
  1056. }
  1057. if (need_redraw) {
  1058. XCopyArea(display, offscreen_buffer, window, gc, 0, 0, GP142_XMAX*2, GP142_YMAX*2, 0, 0);
  1059. XFlush(display);
  1060. need_redraw = 0;
  1061. }
  1062. else {
  1063. usleep(30000);
  1064. gAnimExpired = TRUE;
  1065. }
  1066.  
  1067. #endif
  1068.  
  1069. }
  1070.  
  1071. #ifdef MACINTOSH
  1072. static void HandleMessage(EventRecord *event)
  1073. {
  1074. short windowcode;
  1075. CWindowPtr mouseWindow;
  1076. int c;
  1077. int console_flag = /* 0 for either defers opening */
  1078. nrows!=0 && ncols!=0 ; /* console, but leaves default size. */
  1079.  
  1080. #ifdef __MWERKS__
  1081. /* If we're using the SIOUX console, let it potentially handle an event */
  1082. if (SIOUXHandleOneEvent(event))
  1083. return;
  1084. #endif
  1085.  
  1086. switch ( event->what )
  1087. {
  1088. case keyDown:
  1089. if ((event->modifiers & cmdKey))
  1090. {
  1091. DoMenu(MenuKey(event->message));
  1092. break;
  1093. }
  1094. case autoKey:
  1095. c = event->message & 0x7f;
  1096. if (FrontWindow() == (GrafPtr)gpWin) {
  1097. gEventAction = GP142_KBD;
  1098. gEventRecord.c = c;
  1099. }
  1100. break;
  1101.  
  1102. case mouseDown:
  1103. windowcode = FindWindow(event->where, (void *)&mouseWindow);
  1104. switch ( windowcode )
  1105. {
  1106. case inMenuBar:
  1107. DoMenu(MenuSelect(event->where));
  1108. break;
  1109.  
  1110. case inSysWindow:
  1111. SystemClick(event, (void *)mouseWindow);
  1112. break;
  1113.  
  1114. case inGoAway:
  1115. if (TrackGoAway((void *)mouseWindow, event->where))
  1116. gEventAction = GP142_QUIT;
  1117. break;
  1118.  
  1119. case inDrag:
  1120. DragWindow( (void *)mouseWindow,
  1121. event->where, &dragRect);
  1122. break;
  1123.  
  1124. case inGrow:
  1125. case inContent:
  1126. if (mouseWindow != (CWindowPtr) FrontWindow())
  1127. {
  1128. SelectWindow((void *)mouseWindow);
  1129. WaitMouseUp();
  1130. }
  1131. else
  1132. {
  1133. DoMouseClick(event, mouseWindow);
  1134. }
  1135. break;
  1136. }
  1137. break;
  1138.  
  1139. case activateEvt:
  1140. break;
  1141.  
  1142. case updateEvt:
  1143. BeginUpdate((void *)gpWin);
  1144. refresh(gpWin);
  1145. EndUpdate((void *)gpWin);
  1146. break;
  1147.  
  1148. default:
  1149.  
  1150. if (need_redraw)
  1151. refresh(gpWin);
  1152. break;
  1153. }
  1154. }
  1155.  
  1156.  
  1157. static void refresh(CWindowPtr w)
  1158. {
  1159. CGrafPtr saveport;
  1160. PixMapHandle pixmap;
  1161.  
  1162.  
  1163. GetPort((void *) &saveport);
  1164. SetPort((void *) w);
  1165.  
  1166. pixmap = GetGWorldPixMap(gGP142World);
  1167. LockPixels(pixmap);
  1168. CopyBits((BitMap *)*pixmap, &((WindowPtr)w)->portBits,
  1169. &(*pixmap)->bounds, &w->portRect, srcCopy, nil);
  1170. UnlockPixels(pixmap);
  1171.  
  1172. SetPort((void *)saveport);
  1173.  
  1174. need_redraw = 0;
  1175. }
  1176.  
  1177. /* react to user input */
  1178. static void DoMenu(long menuresult)
  1179. {
  1180. short menuID, itemNumber;
  1181. Str255 AccessoryName;
  1182.  
  1183. menuID = HiWord(menuresult);
  1184. itemNumber = menuresult;
  1185.  
  1186. switch ( menuID ) {
  1187. case Desk_ID:
  1188. #if USES_NEW_HEADERS
  1189. GetMenuItemText(DeskMenu, itemNumber, (void *)&AccessoryName);
  1190. #else
  1191. GetItem(DeskMenu, itemNumber, (void *)&AccessoryName);
  1192. #endif
  1193. OpenDeskAcc((void *)&AccessoryName);
  1194. EnableItem(RunMenu, 0);
  1195. DrawMenuBar();
  1196. break;
  1197.  
  1198. case Run_ID:
  1199. switch ( itemNumber ) {
  1200. case mAniRun: /* run */
  1201. gRunFlag = TRUE;
  1202. break;
  1203.  
  1204. case mAniHalt: /* halt */
  1205. gSingleStepFlag = FALSE;
  1206. gRunFlag = FALSE;
  1207. break;
  1208.  
  1209. case mAniSingle: /* single step */
  1210. gSingleStepFlag = TRUE;
  1211. break;
  1212.  
  1213. case mLog: /* logging */
  1214. gLogging = !gLogging;
  1215. CheckItem(RunMenu, mLog, (int)gLogging);
  1216. break;
  1217.  
  1218. case mScriptRecord: /* record actions */
  1219. gRecordingFlag = !gRecordingFlag;
  1220. CheckItem(RunMenu, mScriptRecord, (int)gRecordingFlag);
  1221. if (!gRecordingFlag)
  1222. {
  1223. if (gTaskCount > 0)
  1224. SaveToScript(GP142_PERIODIC, gEventRecord);
  1225. CloseScript();
  1226. }
  1227. break;
  1228.  
  1229. case mScriptPlay: /* playback actions */
  1230. gScriptPlayFlag = !gScriptPlayFlag;
  1231. CheckItem(RunMenu, mScriptPlay, (int)gScriptPlayFlag);
  1232. gRunFlag = FALSE;
  1233. gSingleStepFlag = FALSE;
  1234. break;
  1235.  
  1236. case mScriptOne: /* playback one action */
  1237. gRunFlag = FALSE;
  1238. gSingleStepFlag = FALSE;
  1239. gScriptStepFlag = TRUE;
  1240. break;
  1241.  
  1242. case mQuit: /* quit */
  1243. gEventAction = GP142_QUIT;
  1244. break;
  1245.  
  1246. default:
  1247. SysBeep(1);
  1248. break;
  1249.  
  1250. } /* end switch (itemNumber) */
  1251. break;
  1252. } /* end switch (menuID) */
  1253. HiliteMenu(0);
  1254. }
  1255.  
  1256.  
  1257. static void DoMouseClick(EventRecord *the_event, CWindowPtr theWin)
  1258. {
  1259. Point newPt;
  1260. CGrafPtr saveport;
  1261.  
  1262. UNUSED(the_event);
  1263.  
  1264. /* If the user clicked in the console window, just ignore it */
  1265. if (theWin != gpWin)
  1266. return;
  1267.  
  1268. GetPort((void *)&saveport);
  1269. SetPort((void *)theWin);
  1270. GetMouse(&newPt);
  1271.  
  1272. gEventAction = GP142_MOUSE;
  1273. gEventRecord.x = newPt.h - gXCenter;
  1274. gEventRecord.y = gYCenter - newPt.v;
  1275.  
  1276. SetPort((void *)saveport);
  1277. }
  1278.  
  1279. #elif defined(WINDOWS)
  1280.  
  1281. #ifdef WIN32
  1282. long FAR PASCAL DrawWndProc(HWND hWnd, UINT message,
  1283. WPARAM wParam, LPARAM lParam)
  1284. #else
  1285. long FAR PASCAL DrawWndProc(HWND hWnd, WORD message,
  1286. WORD wParam, LONG lParam)
  1287. #endif
  1288. {
  1289. #ifndef WIN32
  1290. HANDLE hInstance;
  1291. #endif
  1292. RECT rClient;
  1293. PAINTSTRUCT ps;
  1294. HMENU hMenu;
  1295. static BOOL bCtrlDown = FALSE;
  1296.  
  1297. int click_x, click_y;
  1298.  
  1299. switch(message)
  1300. {
  1301. case WM_CREATE:
  1302. /* Shuichi: Why do this? Not used anywhere */
  1303. #ifndef WIN32
  1304. /* get a handle to the instance handle of the window */
  1305. hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
  1306. #endif
  1307. /* Slap the menu on to the window */
  1308. /* In windows, the menu bar is considered to be a 'menu'
  1309. and all pull-down things are popup menus. */
  1310. hMenu = CreateMenu();
  1311. hRunMenu = CreatePopupMenu();
  1312. AppendMenu(hRunMenu,
  1313. MF_ENABLED | MF_STRING | MF_UNCHECKED, /* menu format */
  1314. IDM_ANIMATE, "&Animate\tCtrl+A");
  1315. AppendMenu(hRunMenu,
  1316. MF_ENABLED | MF_STRING | MF_UNCHECKED,
  1317. IDM_HALT, "&Halt animation\tCtrl+H");
  1318. AppendMenu(hRunMenu,
  1319. MF_ENABLED | MF_STRING | MF_UNCHECKED,
  1320. IDM_ADVANCE_ONE, "Advance one &frame\tCtrl+F");
  1321.  
  1322. AppendMenu(hRunMenu, MF_SEPARATOR, 0, NULL);
  1323.  
  1324. /* Logging is initially TRUE */
  1325. AppendMenu(hRunMenu,
  1326. MF_ENABLED | MF_STRING | MF_CHECKED,
  1327. IDM_LOGGING, "&Logging\tCtrl+L");
  1328.  
  1329. AppendMenu(hRunMenu, MF_SEPARATOR, 0, NULL);
  1330.  
  1331. AppendMenu(hRunMenu,
  1332. MF_ENABLED | MF_STRING | MF_UNCHECKED,
  1333. IDM_RECORD_SCRIPT, "&Record Script\tCtrl+R");
  1334. AppendMenu(hRunMenu,
  1335. MF_ENABLED | MF_STRING | MF_UNCHECKED,
  1336. IDM_PLAY_SCRIPT, "&Playback Script\tCtrl+P");
  1337. AppendMenu(hRunMenu,
  1338. MF_ENABLED | MF_STRING | MF_UNCHECKED,
  1339. IDM_STEP_SCRIPT, "Play &One Script\tCtrl+O");
  1340.  
  1341. AppendMenu(hRunMenu, MF_SEPARATOR, 0, NULL);
  1342.  
  1343. AppendMenu(hRunMenu,
  1344. MF_ENABLED | MF_STRING | MF_UNCHECKED,
  1345. IDM_QUIT, "&Quit\tCtrl+Q");
  1346.  
  1347. AppendMenu(hRunMenu, MF_SEPARATOR, 0, NULL);
  1348.  
  1349. AppendMenu(hRunMenu,
  1350. MF_STRING | MF_UNCHECKED | MF_GRAYED,
  1351. IDM_ABOUT, "GP142 v" GP142_VERSION " " GP142_DATE);
  1352. AppendMenu(hRunMenu,
  1353. MF_STRING | MF_UNCHECKED | MF_GRAYED,
  1354. IDM_ABOUT, "MAC: mckenzie@cs.washington.edu");
  1355. AppendMenu(hRunMenu,
  1356. MF_STRING | MF_UNCHECKED | MF_GRAYED,
  1357. IDM_ABOUT, "WINDOWS: corin@cs.washington.edu");
  1358. AppendMenu(hRunMenu,
  1359. MF_STRING | MF_UNCHECKED | MF_GRAYED,
  1360. IDM_ABOUT, "UPDATES: casey@cs.washington.edu");
  1361.  
  1362. AppendMenu(hMenu,
  1363. MF_ENABLED | MF_POPUP | MF_UNCHECKED,
  1364. (UINT)hRunMenu, "&Run");
  1365. SetMenu(hWnd, hMenu);
  1366. DrawMenuBar(hWnd);
  1367. return 0;
  1368.  
  1369.  
  1370. case WM_LBUTTONDOWN:
  1371. /* the user has clicked the left button on the window */
  1372. click_x = LOWORD(lParam) - gXCenter;
  1373. click_y = gYCenter - HIWORD(lParam);
  1374.  
  1375. /* For the program to link, the user must have this
  1376. function defined in their module, even if it is an
  1377. empty definition */
  1378. gEventAction = GP142_MOUSE;
  1379. gEventRecord.x = click_x;
  1380. gEventRecord.y = click_y;
  1381. return 0;
  1382.  
  1383. case WM_PAINT:
  1384. BeginPaint(hWnd, &ps);
  1385. /* we'll need to do an offscreen blit here.
  1386. - josh */
  1387. BitBlt (the_hdc,0,0,2*GP142_XMAX+1, 2*GP142_YMAX+FUDGE,
  1388. offscreen_DC,0,0,SRCCOPY);
  1389. EndPaint(hWnd, &ps);
  1390. need_redraw = 0;
  1391. return 0;
  1392.  
  1393.  
  1394. case WM_KEYDOWN: /* do things like CTRL-xx shortcuts */
  1395. switch(wParam)
  1396. {
  1397. case VK_CONTROL:
  1398. bCtrlDown = TRUE;
  1399. break;
  1400.  
  1401. case 'H':
  1402. case 'h':
  1403. if (bCtrlDown == TRUE)
  1404. gRunFlag = FALSE;
  1405. break;
  1406.  
  1407. case 'A':
  1408. case 'a':
  1409. if (bCtrlDown == TRUE)
  1410. gRunFlag = TRUE;
  1411. break;
  1412.  
  1413. case 'F':
  1414. case 'f':
  1415. if (bCtrlDown == TRUE)
  1416. {
  1417. gRunFlag = FALSE;
  1418. gSingleStepFlag = TRUE;
  1419. }
  1420. break;
  1421.  
  1422. case 'L':
  1423. case 'l':
  1424. if (bCtrlDown && gLogging)
  1425. {
  1426. gLogging = LOG_OFF;
  1427. CheckMenuItem(hRunMenu,
  1428. IDM_LOGGING,
  1429. MF_BYCOMMAND | MF_UNCHECKED);
  1430. }
  1431. else if (bCtrlDown && !gLogging)
  1432. {
  1433. gLogging = LOG_ON;
  1434. CheckMenuItem(hRunMenu,
  1435. IDM_LOGGING,
  1436. MF_BYCOMMAND | MF_CHECKED);
  1437. }
  1438. break;
  1439.  
  1440.  
  1441. case 'R':
  1442. case 'r':
  1443. if (bCtrlDown && gRecordingFlag)
  1444. {
  1445. gRecordingFlag = FALSE;
  1446. CheckMenuItem(hRunMenu,
  1447. IDM_RECORD_SCRIPT,
  1448. MF_BYCOMMAND | MF_UNCHECKED);
  1449. if (gTaskCount > 0)
  1450. SaveToScript(GP142_PERIODIC, gEventRecord);
  1451. CloseScript();
  1452. }
  1453. else if (bCtrlDown && !gRecordingFlag)
  1454. {
  1455. gRecordingFlag = TRUE;
  1456. CheckMenuItem(hRunMenu,
  1457. IDM_RECORD_SCRIPT,
  1458. MF_BYCOMMAND | MF_CHECKED);
  1459. }
  1460. break;
  1461.  
  1462. case 'P':
  1463. case 'p':
  1464. if (bCtrlDown && gScriptPlayFlag)
  1465. {
  1466. gScriptPlayFlag = FALSE;
  1467. CheckMenuItem(hRunMenu,
  1468. IDM_PLAY_SCRIPT,
  1469. MF_BYCOMMAND | MF_UNCHECKED);
  1470. CloseScript();
  1471. }
  1472. else if (bCtrlDown && !gScriptPlayFlag)
  1473. {
  1474. gRunFlag = FALSE;
  1475. gSingleStepFlag = FALSE;
  1476. gScriptPlayFlag = TRUE;
  1477. CheckMenuItem(hRunMenu,
  1478. IDM_PLAY_SCRIPT,
  1479. MF_BYCOMMAND | MF_CHECKED);
  1480. }
  1481. break;
  1482.  
  1483. case 'O':
  1484. case 'o':
  1485. if (bCtrlDown)
  1486. {
  1487. gScriptStepFlag = TRUE;
  1488. gRunFlag = FALSE;
  1489. gSingleStepFlag = FALSE;
  1490. }
  1491. break;
  1492.  
  1493. case 'Q':
  1494. case 'q':
  1495. if (bCtrlDown == TRUE)
  1496. PostQuitMessage(0);
  1497. break;
  1498. }
  1499. break;
  1500.  
  1501. case WM_CHAR:
  1502. /* call the user's keyboard handler */
  1503. if (bCtrlDown == TRUE)
  1504. break;
  1505.  
  1506. gEventAction = GP142_KBD;
  1507. gEventRecord.c = (char)wParam;
  1508. break;
  1509.  
  1510.  
  1511. case WM_KEYUP:
  1512. switch (wParam)
  1513. {
  1514. case VK_CONTROL:
  1515. bCtrlDown = FALSE;
  1516. break;
  1517. }
  1518. break;
  1519.  
  1520.  
  1521.  
  1522. case WM_COMMAND: /* menu item selected */
  1523. switch (wParam)
  1524. {
  1525. case IDM_ANIMATE:
  1526. gRunFlag = TRUE;
  1527. break;
  1528.  
  1529. case IDM_HALT:
  1530. gRunFlag = FALSE;
  1531. break;
  1532.  
  1533. case IDM_ADVANCE_ONE:
  1534. gRunFlag = FALSE;
  1535. gSingleStepFlag = TRUE;
  1536. break;
  1537.  
  1538. case IDM_LOGGING:
  1539. /* Changed TRUE/FALSE to LOG_ON/LOG_OFF */
  1540. if (gLogging == LOG_ON)
  1541. {
  1542. gLogging = LOG_OFF;
  1543. CheckMenuItem(hRunMenu,
  1544. IDM_LOGGING,
  1545. MF_BYCOMMAND | MF_UNCHECKED);
  1546. }
  1547. else
  1548. {
  1549. gLogging = LOG_ON;
  1550. CheckMenuItem(hRunMenu,
  1551. IDM_LOGGING,
  1552. MF_BYCOMMAND | MF_CHECKED);
  1553. }
  1554. break;
  1555.  
  1556. case IDM_RECORD_SCRIPT:
  1557. if (gRecordingFlag)
  1558. {
  1559. gRecordingFlag = FALSE;
  1560. CheckMenuItem(hRunMenu,
  1561. IDM_RECORD_SCRIPT,
  1562. MF_BYCOMMAND | MF_UNCHECKED);
  1563. if (gTaskCount > 0)
  1564. SaveToScript(GP142_PERIODIC, gEventRecord);
  1565. CloseScript();
  1566. }
  1567. else
  1568. {
  1569. gRecordingFlag = TRUE;
  1570. CheckMenuItem(hRunMenu,
  1571. IDM_RECORD_SCRIPT,
  1572. MF_BYCOMMAND | MF_CHECKED);
  1573. }
  1574. break;
  1575.  
  1576. case IDM_PLAY_SCRIPT:
  1577. if (gScriptPlayFlag)
  1578. {
  1579. gScriptPlayFlag = FALSE;
  1580. CheckMenuItem(hRunMenu,
  1581. IDM_PLAY_SCRIPT,
  1582. MF_BYCOMMAND | MF_UNCHECKED);
  1583. CloseScript();
  1584. }
  1585. else
  1586. {
  1587. gRunFlag = FALSE;
  1588. gSingleStepFlag = FALSE;
  1589. gScriptPlayFlag = TRUE;
  1590. CheckMenuItem(hRunMenu,
  1591. IDM_PLAY_SCRIPT,
  1592. MF_BYCOMMAND | MF_CHECKED);
  1593. }
  1594. break;
  1595.  
  1596. case IDM_STEP_SCRIPT:
  1597. gScriptStepFlag = TRUE;
  1598. gRunFlag = FALSE;
  1599. gSingleStepFlag = FALSE;
  1600. break;
  1601.  
  1602. case IDM_QUIT:
  1603. PostQuitMessage(0);
  1604. break;
  1605. }
  1606. break;
  1607.  
  1608. case WM_SIZE: /* Graphics window's size has changed */
  1609. /*
  1610. ** Hmmm.. As of version 2.1, window size on both PC
  1611. ** and Mac should be immutable, so this code is
  1612. ** probably unnecessary, but I don't think it's
  1613. ** harmful, so I'll leave it in case we ever change
  1614. ** back to resizable windows. --- WLR 10/95
  1615. */
  1616. GetClientRect(hWnd, &rClient);
  1617. gXCenter = (rClient.right - rClient.left)/2 +
  1618. rClient.left;
  1619. gYCenter = (rClient.bottom - rClient.top)/2 +
  1620. rClient.top;
  1621. break;
  1622.  
  1623. case WM_TIMER:
  1624. gAnimExpired = TRUE;
  1625. break;
  1626.  
  1627. case WM_DESTROY:
  1628. case WM_QUIT:
  1629. KillTimer(hWnd, wParam);
  1630. PostQuitMessage(0);
  1631. return 0;
  1632.  
  1633. default:
  1634. return (DefWindowProc(hWnd, message, wParam, lParam));
  1635. }
  1636. #ifndef WIN32
  1637. UNUSED(hInstance);
  1638. #endif
  1639. return 0;
  1640. }
  1641.  
  1642.  
  1643. /****** TextWndProc() *******************************************/
  1644.  
  1645. #ifdef WIN32
  1646. long FAR PASCAL TextWndProc(HWND hWnd, UINT message,
  1647. WPARAM wParam, LPARAM lParam)
  1648. #else
  1649. long FAR PASCAL TextWndProc(HWND hWnd, WORD message,
  1650. WORD wParam, LONG lParam)
  1651. #endif
  1652. {
  1653.  
  1654. /* Begin addition of Clear Window */
  1655. switch (message)
  1656. {
  1657. /* if user selects a keyboard shortcut while the text window
  1658. is active, send the keystroke to the graphics window */
  1659. case WM_KEYDOWN:
  1660. PostMessage(hDrawWnd, /* send to graphics window */
  1661. WM_KEYDOWN, /* message to send */
  1662. wParam, /* send same paramaters */
  1663. lParam);
  1664. break;
  1665.  
  1666. case WM_KEYUP:
  1667. PostMessage(hDrawWnd, WM_KEYUP, wParam, lParam);
  1668. break;
  1669.  
  1670. case WM_PAINT:
  1671. RedrawTextWnd(hWnd);
  1672. return 0;
  1673.  
  1674. default:
  1675. return DefWindowProc(hWnd, message, wParam, lParam);
  1676. }
  1677.  
  1678. return 0;
  1679. }
  1680.  
  1681.  
  1682. #elif defined(X11R6)
  1683.  
  1684. void Process_event(XEvent event) {
  1685. if (event.xany.window == window) {
  1686. switch(event.type) {
  1687. int i;
  1688. char keybuff[11];
  1689. KeySym thekeysym;
  1690. XComposeStatus compstat;
  1691. case Expose:
  1692. XCopyArea(display, offscreen_buffer, window, gc, 0, 0, GP142_XMAX*2, GP142_YMAX*2, 0, 0);
  1693. XFlush(display);
  1694. need_redraw = 0;
  1695. break;
  1696. case ButtonPress:
  1697. gEventRecord.x = event.xbutton.x - GP142_XMAX;
  1698. gEventRecord.y = GP142_YMAX - event.xbutton.y;
  1699. gEventAction = GP142_MOUSE;
  1700. break;
  1701. case KeyPress:
  1702. if (XLookupString((XKeyEvent*) &event, keybuff, 10,
  1703. &thekeysym, &compstat) == 1) {
  1704. if (thekeysym > 31 && thekeysym < 127) {
  1705. gEventRecord.c = thekeysym;
  1706. gEventAction = GP142_KBD;
  1707. }
  1708. }
  1709. break;
  1710. }
  1711. }
  1712. if (event.xany.window == winc[0]) {
  1713. switch (event.type) {
  1714. case Expose:
  1715. XDrawString(display, winc[0], gccon, 5, 15, "Animate", 7);
  1716. break;
  1717. case ButtonPress:
  1718. gRunFlag=TRUE;
  1719. }
  1720. }
  1721. if (event.xany.window == winc[1]) {
  1722. switch (event.type) {
  1723. case Expose:
  1724. XDrawString(display, winc[1], gccon, 5, 15, "Stop", 4);
  1725. break;
  1726. case ButtonPress:
  1727. gRunFlag=FALSE;
  1728. gSingleStepFlag=FALSE;
  1729. }
  1730. }
  1731. if (event.xany.window == winc[2]) {
  1732. switch (event.type) {
  1733. case Expose:
  1734. XDrawString(display, winc[2], gccon, 5, 15, "SingleStep", 10);
  1735. break;
  1736. case ButtonPress:
  1737. gSingleStepFlag=TRUE;
  1738. }
  1739. }
  1740. if (event.xany.window == winc[3]) {
  1741. switch (event.type) {
  1742. case ButtonPress:
  1743. gLogging=!gLogging;
  1744. XClearWindow(display,winc[3]);
  1745. /* drop through to redraw strings */
  1746. case Expose:
  1747. if (gLogging)
  1748. XDrawString(display, winc[3], gccon, 5, 15, "Logging on", 10);
  1749. else
  1750. XDrawString(display, winc[3], gccon, 5, 15, "Logging off", 11);
  1751. break;
  1752. }
  1753. }
  1754. if (event.xany.window == winc[4]) {
  1755. switch (event.type) {
  1756. case ButtonPress:
  1757. gRecordingFlag=!gRecordingFlag;
  1758. XClearWindow(display,winc[4]);
  1759. /* drop through to redraw strings */
  1760. case Expose:
  1761. if (gRecordingFlag)
  1762. XDrawString(display, winc[4], gccon, 5, 15, "Recording on", 12);
  1763. else
  1764. XDrawString(display, winc[4], gccon, 5, 15, "Recording off", 13);
  1765. break;
  1766. }
  1767. }
  1768. if (event.xany.window == winc[5]) {
  1769. switch (event.type) {
  1770. case ButtonPress:
  1771. gScriptPlayFlag=!gScriptPlayFlag;
  1772. gRunFlag=FALSE;
  1773. gSingleStepFlag=FALSE;
  1774. XClearWindow(display,winc[5]);
  1775. /* drop through to redraw strings */
  1776. case Expose:
  1777. if (gScriptPlayFlag)
  1778. XDrawString(display, winc[5], gccon, 5, 15, "Playback on", 11);
  1779. else
  1780. XDrawString(display, winc[5], gccon, 5, 15, "Playback off", 12);
  1781. break;
  1782. }
  1783. }
  1784. if (event.xany.window == winc[6]) {
  1785. switch (event.type) {
  1786. case ButtonPress:
  1787. gRunFlag = FALSE;
  1788. gSingleStepFlag = FALSE;
  1789. gScriptStepFlag = TRUE;
  1790. break;
  1791. case Expose:
  1792. XDrawString(display, winc[6], gccon, 5, 15, "SingleScript", 12);
  1793. break;
  1794. }
  1795. }
  1796. if (event.xany.window == winc[7]) {
  1797. switch (event.type) {
  1798. case Expose:
  1799. XDrawString(display, winc[7], gccon, 5, 15, "Quit", 4);
  1800. break;
  1801. case ButtonPress:
  1802. gEventAction = GP142_QUIT;
  1803. }
  1804. }
  1805. }
  1806. #endif
  1807.  
  1808.  
  1809.  
  1810. /*********************************************************** Scripting Functions ***/
  1811. /* ClearPlayFlag()
  1812. */
  1813. static void ClearPlayFlag(void)
  1814. {
  1815. gScriptPlayFlag = FALSE;
  1816. gScriptStepFlag = FALSE;
  1817.  
  1818. #ifdef MACINTOSH
  1819. CheckItem(RunMenu, mScriptPlay, FALSE);
  1820. #elif defined(WINDOWS)
  1821. CheckMenuItem(hRunMenu,
  1822. IDM_PLAY_SCRIPT,
  1823. MF_BYCOMMAND | MF_UNCHECKED);
  1824. #elif defined(X11R6)
  1825. XClearWindow(display,winc[5]);
  1826. XDrawString(display, winc[5], gccon, 5, 15, "Playback off", 12);
  1827. #endif
  1828. }
  1829.  
  1830.  
  1831. /* SaveToScript()
  1832. */
  1833. static void
  1834. SaveToScript(int a, GP142_event_t e)
  1835. {
  1836. if (gScriptFP == NULL)
  1837. if ((gScriptFP = fopen(kScriptName, "wt")) == NULL)
  1838. {
  1839. printf("Cannot open script file %s for writing\n", kScriptName);
  1840. return;
  1841. }
  1842.  
  1843. switch (a)
  1844. {
  1845. case GP142_MOUSE:
  1846. fprintf(gScriptFP, "GP142_MOUSE(%d, %d);\n", e.x, e.y);
  1847. break;
  1848.  
  1849. case GP142_KBD:
  1850. fprintf(gScriptFP, "GP142_KBD(%d);\n", e.c);
  1851. break;
  1852.  
  1853. case GP142_PERIODIC:
  1854. fprintf(gScriptFP, "GP142_PERIODIC(%d);\n", gTaskCount);
  1855. break;
  1856.  
  1857. default:
  1858. break;
  1859. }
  1860. }
  1861.  
  1862. /* PlayFromScript()
  1863. */
  1864. static int
  1865. PlayFromScript(void)
  1866. {
  1867. char buf[512];
  1868. char s[12];
  1869. int c, i, k;
  1870.  
  1871. /* The only way PlayFromScript will be called is if GP142_await_event() is
  1872. processing a message. So we can simply fill in the global data structures
  1873. gEventAction and gEventRecord. */
  1874.  
  1875. if (gScriptFP == NULL)
  1876. if ((gScriptFP = fopen(kScriptName, "rt")) == NULL)
  1877. {
  1878. printf("Cannot open script file %s for reading\n", kScriptName);
  1879. ClearPlayFlag();
  1880. return GP142_FAILURE;
  1881. }
  1882.  
  1883. /* See if we're working on a block of user tasks right now */
  1884. if (gTaskCount > 0)
  1885. {
  1886. gEventAction = GP142_PERIODIC;
  1887. gTaskCount--;
  1888. return GP142_SUCCESS;
  1889. }
  1890.  
  1891. /* We want to remember to skip over blank lines */
  1892. fgets(buf, 512, gScriptFP);
  1893. while (!feof(gScriptFP) && buf[0] == '\n')
  1894. fgets(buf, 512, gScriptFP);
  1895.  
  1896. if (feof(gScriptFP))
  1897. {
  1898. printf("EOF encountered in script file %s\n", kScriptName);
  1899. ClearPlayFlag();
  1900. return GP142_FAILURE;
  1901. }
  1902.  
  1903. /* We don't get fscanf() or sscanf() services with Windows DLLs, so
  1904. we'll have to be more sneaky about how we parse the script file */
  1905.  
  1906. c = buf[6]; /* buf[] = GP142_%c */
  1907. switch (c)
  1908. {
  1909. case 'M': /* GP142_MOUSE(x, y); */
  1910. gEventAction = GP142_MOUSE;
  1911.  
  1912. k = 6;
  1913. while (!(isdigit(buf[k]) || buf[k] == '-'))
  1914. k++;
  1915.  
  1916. i = 0;
  1917. while (isdigit(s[i] = buf[k+i]) || buf[k+i] == '-')
  1918. i++;
  1919. s[i] = '\0';
  1920. gEventRecord.x = atoi(s);
  1921.  
  1922. k += i;
  1923. while (!(isdigit(buf[k]) || buf[k] == '-'))
  1924. k++;
  1925.  
  1926. i = 0;
  1927. while (isdigit(s[i] = buf[k+i]) || buf[k+i] == '-')
  1928. i++;
  1929. s[i] = '\0';
  1930. gEventRecord.y = atoi(s);
  1931. break;
  1932.  
  1933. case 'K': /* GP142_KBD(c); */
  1934. gEventAction = GP142_KBD;
  1935.  
  1936. k = 6; /* skip over the 'GP142_' */
  1937. while (!isdigit(buf[k]))
  1938. k++;
  1939.  
  1940. i = 0;
  1941. while (isdigit(s[i] = buf[k+i]))
  1942. i++;
  1943. s[i] = '\0';
  1944. gEventRecord.c = atoi(s);
  1945. break;
  1946.  
  1947. case 'P': /* GP142_PERIODIC(i); */
  1948. gEventAction = GP142_PERIODIC;
  1949.  
  1950. k = 6;
  1951. while (!isdigit(buf[k]))
  1952. k++;
  1953.  
  1954. i = 0;
  1955. while (isdigit(s[i] = buf[k+i]))
  1956. i++;
  1957. s[i] = '\0';
  1958.  
  1959. /* we substract 1 because we've already counted
  1960. this task */
  1961. gTaskCount = atoi(s) - 1;
  1962. break;
  1963.  
  1964. default:
  1965. return GP142_FAILURE;
  1966.  
  1967. }
  1968. return GP142_SUCCESS;
  1969. }
  1970.  
  1971.  
  1972. /* CloseScript()
  1973. */
  1974. static void
  1975. CloseScript(void)
  1976. {
  1977. if (gScriptFP != NULL)
  1978. fclose(gScriptFP);
  1979. }
  1980.  
  1981.  
  1982.  
  1983. /********************************************************** API Helper functions ***/
  1984. #ifdef WINDOWS
  1985. static void RedrawTextWnd(HWND hWnd)
  1986. {
  1987. PAINTSTRUCT ps;
  1988. HBRUSH hBrush, hOldBrush;
  1989. HDC our_DC, offscreen_DC;
  1990. HBITMAP offscreen_bitmap;
  1991. RECT windowRect, lastLineRect;
  1992. TEXTMETRIC tm;
  1993. int nScrollHeight;
  1994. int len,i,j;
  1995. char far *pStr;
  1996.  
  1997. BeginPaint(hWnd, &ps);
  1998.  
  1999. GetClientRect(hWnd, &windowRect);
  2000.  
  2001. /* We'll do all the drawing to an off-screen DC and then BitBlt it to the screen */
  2002. our_DC = GetDC(hTextWnd);
  2003. offscreen_DC = CreateCompatibleDC(our_DC);
  2004. offscreen_bitmap = CreateCompatibleBitmap(offscreen_DC, windowRect.right, windowRect.bottom);
  2005. SelectObject (offscreen_DC, offscreen_bitmap);
  2006.  
  2007. /* First, clear window. Just draw a white rectangle */
  2008. hBrush = CreateSolidBrush(GetBkColor(offscreen_DC));
  2009. hOldBrush = SelectObject(offscreen_DC, hBrush);
  2010. FillRect(offscreen_DC, &windowRect, hBrush);
  2011.  
  2012. /* Get ready to draw strings */
  2013.  
  2014. /* set the device context's font */
  2015. SelectObject(offscreen_DC, GetStockObject(ANSI_FIXED_FONT));
  2016.  
  2017. /* we'll need to figure out the height of the font. We'll do this
  2018. by asking Windows to fill in a structure telling all about the
  2019. default font, which we have just set */
  2020. GetTextMetrics(offscreen_DC, &tm);
  2021. nScrollHeight = tm.tmHeight + tm.tmExternalLeading;
  2022.  
  2023. /* This is the rectangle we'll use to erase the last line of text
  2024. that was scrolled up. We now know how big to make it. */
  2025. lastLineRect.top = windowRect.bottom-nScrollHeight;
  2026. lastLineRect.bottom = windowRect.bottom + 1;
  2027. lastLineRect.left = windowRect.left;
  2028. lastLineRect.right = windowRect.right;
  2029.  
  2030. /* Walk through message ring, printing messages */
  2031. for (i=gRingFirst, j=0;
  2032. (i!=gRingLast || j==0) && i >= 0;
  2033. RING_INC(i), j++)
  2034. {
  2035. pStr = GlobalLock(gConsoleLines[i]);
  2036.  
  2037. /* Move everything that was written so far up one line */
  2038. ScrollDC(offscreen_DC,
  2039. 0, /* no horizontal scrolling */
  2040. -nScrollHeight, /* just vertical scrolling; negative means up */
  2041. NULL, /* scroll entire client area */
  2042. NULL, /* and leave clipping rectangle alone */
  2043. (HRGN)NULL, /* Windows needn't compute update region */
  2044. NULL); /* or update rectangle */
  2045.  
  2046. /* Erase the place where the last line was */
  2047. FillRect(offscreen_DC, &lastLineRect, hBrush);
  2048.  
  2049. /* omit trailing newlines */
  2050. len = far_strlen(pStr);
  2051. if (len > 0 && pStr[len-1] == '\n')
  2052. {
  2053. pStr[len-1] = '\0';
  2054. len--;
  2055. }
  2056.  
  2057. TextOut(offscreen_DC,
  2058. windowRect.left + 5, /* leave ~5 pixel left margin */
  2059. windowRect.bottom - nScrollHeight, /* new line appears at bottom */
  2060. pStr, /* the string to display (far pointer) */
  2061. len); /* and the string's length */
  2062.  
  2063. GlobalUnlock(gConsoleLines[i]);
  2064. }
  2065.  
  2066.  
  2067. /* SelectObject(offscreen_DC, hOldBrush); */
  2068.  
  2069. BitBlt (our_DC,0,0,windowRect.right, windowRect.bottom,
  2070. offscreen_DC,0,0,SRCCOPY);
  2071. EndPaint(hWnd, &ps);
  2072.  
  2073. DeleteObject(hBrush);
  2074. DeleteObject(offscreen_bitmap);
  2075.  
  2076. ReleaseDC(hTextWnd, our_DC);
  2077. ReleaseDC(hTextWnd, offscreen_DC);
  2078. DeleteDC(our_DC);
  2079. DeleteDC(offscreen_DC);
  2080. }
  2081.  
  2082.  
  2083. /* little function used just inside DLL; no reason to export it */
  2084. static int far_strlen(char far *s)
  2085. {
  2086. int i=0;
  2087.  
  2088. while (*(s+i) != '\0')
  2089. i++;
  2090. return i;
  2091. }
  2092.  
  2093. /*
  2094. * The following function, thanks to Chris Anderson, provides
  2095. * printint to the text window, essentially just like printf;
  2096. * the only main difference is that newlines ("\n") are ignored.
  2097. */
  2098. extern int GP142_FUNC
  2099. WINprintf(
  2100. const char fmt[], /* the printf format string */
  2101. ... ) /* list of variables to print */
  2102. {
  2103. va_list vlist; /* Argument list pointer */
  2104. char str[1024]; /* Buffer to build string into */
  2105. int cnt; /* Result of SPRINTF for return */
  2106. char far *pStr;
  2107. int i;
  2108. RECT rClient;
  2109.  
  2110. va_start( vlist, fmt ); /* Initialize va_ functions */
  2111.  
  2112. /* prints string to buffer */
  2113. cnt = vsprintf(str, fmt, vlist);
  2114. va_end( vlist ); /* Close va_ functions */
  2115. /* Send string to graphics wind */
  2116.  
  2117. /* Save this string to the text window's ring buffer */
  2118.  
  2119. /* Determine length of string, and store in i */
  2120. i = 0;
  2121. while (str[i] != '\0')
  2122. i++;
  2123.  
  2124. if (gRingFirst == gRingLast) /* ring is full, so overwrite the first */
  2125. {
  2126. GlobalFree(gConsoleLines[gRingFirst]);
  2127. RING_INC(gRingFirst);
  2128. }
  2129.  
  2130.  
  2131. gConsoleLines[gRingLast] = GlobalAlloc(GMEM_MOVEABLE,
  2132. (long unsigned)i+1L);
  2133. pStr = GlobalLock(gConsoleLines[gRingLast]);
  2134.  
  2135. /* Copy string into globally allocated memory */
  2136. i = 0;
  2137. while (str[i] != '\0')
  2138. {
  2139. pStr[i] = str[i];
  2140. i++;
  2141. }
  2142. pStr[i] = '\0';
  2143.  
  2144. GlobalUnlock(gConsoleLines[gRingLast]);
  2145.  
  2146. /* if this was the first string in the buffer, treat it special */
  2147. if (gRingFirst < 0)
  2148. gRingFirst = gRingLast;
  2149.  
  2150. RING_INC(gRingLast);
  2151.  
  2152. /* Display the string */
  2153. /* DrawString(str); Commented out by Dan 2/3/00 */
  2154.  
  2155. /* Try force the whole text window to be redrawn */
  2156. GetClientRect(hTextWnd, &rClient);
  2157. InvalidateRect(hTextWnd, &rClient, 1);
  2158.  
  2159. return( cnt ); /* Return the conversion count */
  2160. }
  2161. #endif
  2162.  
  2163.  
  2164. /***************************************************************** API functions ***/
  2165. /* There are two types of API calls: GP142_gggXY() and GP142_gggP, where
  2166. ggg is the graphics symbol being drawn. The XY indicates that the function
  2167. uses seperate integer values for the x and y components of the coordinates.
  2168. The P means that coordinates are specified in a Point structure. In many
  2169. of the functions, an offset of width/2 has been subtracted from the coords;
  2170. this is meant to split the width of the object's outline across the logical
  2171. outline of the object. This seems to make more intuitive sense to new Mac
  2172. programmers, and increases cross platform (Windows) portability. */
  2173.  
  2174.  
  2175. /**************************************************************** GP142_gets()
  2176. ** It is assumed that the string s is large enough for whatever string the user
  2177. ** enters.
  2178. */
  2179. /***********TODO*************/
  2180. #ifdef MACINTOSH
  2181. extern int
  2182. GP142_gets(const char prompt[], char result[])
  2183. {
  2184. Str255 pasStr;
  2185. DialogPtr dialog;
  2186. Handle itemHandle;
  2187. char *itemPtr;
  2188. Rect itemBox, dialogBounds = {154, 168, 279, 488};
  2189. int i;
  2190. short itemHit = 0;
  2191. short itemType;
  2192.  
  2193. for (i=1; i<255 && prompt[i-1] != '\0'; i++)
  2194. pasStr[i] = prompt[i-1];
  2195. pasStr[0] = i-1;
  2196.  
  2197. itemHandle = (Handle)NewHandle(50);
  2198. HLock(itemHandle);
  2199. itemPtr = *itemHandle;
  2200.  
  2201. itemPtr[0] = 0; /* There are 2 + 1 = 3 items in the list */
  2202. itemPtr[1] = 2;
  2203.  
  2204. /* The Okay button */
  2205. itemPtr[2] = 0; /* Parent window pointer */
  2206. itemPtr[3] = 0;
  2207. itemPtr[4] = 0;
  2208. itemPtr[5] = 0;
  2209. itemPtr[6] = 0; /* Top of button */
  2210. itemPtr[7] = 94;
  2211. itemPtr[8] = 0; /* 64 - right of button */
  2212. itemPtr[9] = -125;
  2213. itemPtr[10] = 0; /* bottom of button */
  2214. itemPtr[11] = 114;
  2215. itemPtr[12] = 0; /* 64 - left of button */
  2216. itemPtr[13] = -67;
  2217. itemPtr[14] = btnCtrl + ctrlItem;
  2218. itemPtr[15] = 4; /* 4 bytes in variable-length field */
  2219. itemPtr[16] = 'O'; /* Variable-length field */
  2220. itemPtr[17] = 'k';
  2221. itemPtr[18] = 'a';
  2222. itemPtr[19] = 'y';
  2223.  
  2224. /* The static text region */
  2225. itemPtr[20] = 0; /* Parent window pointer */
  2226. itemPtr[21] = 0;
  2227. itemPtr[22] = 0;
  2228. itemPtr[23] = 0;
  2229. itemPtr[24] = 0; /* Top of control */
  2230. itemPtr[25] = 10;
  2231. itemPtr[26] = 0; /* left of control */
  2232. itemPtr[27] = 25;
  2233. itemPtr[28] = 0; /* bottom of control */
  2234. itemPtr[29] = 40;
  2235. itemPtr[30] = 1; /* right of control (1*256 + 40)*/
  2236. itemPtr[31] = 40;
  2237. itemPtr[32] = statText;
  2238. itemPtr[33] = 2; /* 2 bytes of additional data */
  2239. itemPtr[34] = '^'; /* Additional data */
  2240. itemPtr[35] = '0';
  2241.  
  2242. /* The edit text region */
  2243. itemPtr[36] = 0; /* Parent window pointer */
  2244. itemPtr[37] = 0;
  2245. itemPtr[38] = 0;
  2246. itemPtr[39] = 0;
  2247. itemPtr[40] = 0; /* Top of control */
  2248. itemPtr[41] = 41;
  2249. itemPtr[42] = 0; /* left of control */
  2250. itemPtr[43] = 25;
  2251. itemPtr[44] = 0; /* bottom of control */
  2252. itemPtr[45] = 82;
  2253. itemPtr[46] = 1; /* right of control */
  2254. itemPtr[47] = 40;
  2255. itemPtr[48] = editText;
  2256. itemPtr[49] = 0;
  2257.  
  2258. HUnlock(itemHandle);
  2259.  
  2260. dialog = NewDialog(nil, /* Let the OS allocate memory */
  2261. &dialogBounds, /* Bounding box of dialog */
  2262. "\pGP142_gets()", /* Title string, pascal style */
  2263. FALSE, /* Don't show the dialog, yet */
  2264. dBoxProc, /* Dialog Box procedure ID */
  2265. (WindowPtr)-1L, /* Dialog will be in front of all windows */
  2266. FALSE, /* Don't have a GoAway close box */
  2267. 0, /* Nothing in the RefCon field */
  2268. itemHandle); /* Handle to item list */
  2269.  
  2270.  
  2271.  
  2272. ParamText(pasStr, "\p", "\p", "\p");
  2273. ShowWindow(dialog);
  2274.  
  2275. while (itemHit != ok)
  2276. ModalDialog(nil, &itemHit);
  2277.  
  2278. /* Get a handle to the edit text of the dialog box */
  2279. #if USES_NEW_HEADERS
  2280. GetDialogItem(dialog, kGetsEditTextID, &itemType, &itemHandle, &itemBox);
  2281. #else
  2282. GetDItem(dialog, kGetsEditTextID, &itemType, &itemHandle, &itemBox);
  2283. #endif
  2284. /* Convert the handle to a pascal string */
  2285. #if USES_NEW_HEADERS
  2286. GetDialogItemText(itemHandle, pasStr);
  2287. #else
  2288. GetIText(itemHandle, pasStr);
  2289. #endif
  2290.  
  2291. #if USES_NEW_HEADERS
  2292. DisposeDialog(dialog);
  2293. #else
  2294. DisposDialog(dialog);
  2295. #endif
  2296.  
  2297. for (i=0; i<pasStr[0]; i++)
  2298. result[i] = pasStr[i+1];
  2299. result[i] = '\0';
  2300.  
  2301. return GP142_SUCCESS;
  2302. }
  2303.  
  2304. #elif defined(WINDOWS)
  2305. #ifdef WIN32
  2306. // Win32 version by Zack Ives, 6/19/98
  2307. //
  2308. // tested on WinNT 4.0
  2309. #pragma pack(push,before)
  2310. #pragma pack(4)
  2311. #define MAX_PROMPT 79
  2312. typedef struct {
  2313. DLGTEMPLATE dt;
  2314. unsigned short
  2315. menuarray,
  2316. classarray;
  2317. WCHAR title[11];
  2318.  
  2319. DLGITEMTEMPLATE edit;
  2320. unsigned short
  2321. editClassArray[2];
  2322. WCHAR editTitleArray[1];
  2323. unsigned short editCreationArray[2];
  2324.  
  2325. DLGITEMTEMPLATE button;
  2326. unsigned short
  2327. buttonClassArray[2];
  2328. WCHAR buttonTitleArray[5];
  2329. unsigned short buttonCreationArray[2];
  2330.  
  2331. DLGITEMTEMPLATE text;
  2332. unsigned short
  2333. textClassArray[2];
  2334. WCHAR textTitleArray[MAX_PROMPT];
  2335. unsigned short textCreationArray[2];
  2336.  
  2337. } dialogInfo;
  2338. #pragma pack(pop, before)
  2339.  
  2340.  
  2341. extern int GP142_FUNC
  2342. GP142_gets(const char prompt[], char result[])
  2343. {
  2344. unsigned long size;
  2345. int promptLen;
  2346. dialogInfo d;
  2347. dialogInfo far *di;
  2348. char title[] = "GP142_gets";
  2349.  
  2350. int temp;
  2351. long unsigned
  2352. dialogStyle = WS_CAPTION | WS_SYSMENU | WS_POPUP | WS_VISIBLE |
  2353. DS_MODALFRAME,
  2354. okayStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,
  2355. editStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_MULTILINE |
  2356. ES_AUTOVSCROLL | WS_BORDER,
  2357. staticStyle = WS_CHILD | WS_VISIBLE | SS_LEFT | WS_GROUP;
  2358.  
  2359. for (promptLen=0; prompt[promptLen] != '\0'; promptLen++);
  2360. promptLen++; /* Add room for NULL terminator */
  2361.  
  2362. size = sizeof(dialogInfo);
  2363.  
  2364. ZeroMemory(&d, sizeof(dialogInfo));
  2365. di = &d;
  2366.  
  2367. di->dt.style = dialogStyle;
  2368. di->dt.dwExtendedStyle = 0;
  2369. di->dt.cdit = 3;
  2370. di->dt.x = 50;
  2371. di->dt.y = 50;
  2372. di->dt.cx = 185;
  2373. di->dt.cy = 92;
  2374. di->menuarray = 0;
  2375. di->classarray = 0;
  2376.  
  2377. for (temp = 0; (unsigned)temp < strlen(title); temp++)
  2378. di->title[temp] = title[temp];
  2379. di->title[temp] = 0;
  2380.  
  2381. /* Okay button */
  2382. di->button.style = okayStyle;
  2383. di->button.x = 67;
  2384. di->button.y = 74;
  2385. di->button.cx = 50;
  2386. di->button.cy = 14;
  2387. di->button.id = kOkayID;
  2388. di->buttonClassArray[0] = 0xFFFF;
  2389. di->buttonClassArray[1] = 0x0080;
  2390. di->buttonTitleArray[0] = 'O';
  2391. di->buttonTitleArray[1] = 'k';
  2392. di->buttonTitleArray[2] = 'a';
  2393. di->buttonTitleArray[3] = 'y';
  2394. di->buttonTitleArray[4] = 0;
  2395. di->buttonCreationArray[0] = 0;
  2396.  
  2397. /* Edit text */
  2398. di->edit.style = editStyle;
  2399. di->edit.x = 8;
  2400. di->edit.y = 30;
  2401. di->edit.cx = 167;
  2402. di->edit.cy = 37;
  2403. di->edit.id = kEditID;
  2404. di->editClassArray[0] = 0xFFFF;
  2405. di->editClassArray[1] = 0x0081;
  2406. di->editTitleArray[0] = 0;
  2407. di->editCreationArray[0] = 0;
  2408.  
  2409. /* Static text */
  2410. di->text.style = staticStyle;
  2411. di->text.x = 8;
  2412. di->text.y = 3;
  2413. di->text.cx = 167;
  2414. di->text.cy = 24;
  2415. di->text.id = kStaticID;
  2416. di->textClassArray[0] = 0xFFFF;
  2417. di->textClassArray[1] = 0x0082;
  2418.  
  2419. for (temp = 0; temp < MAX_PROMPT; temp++)
  2420. if ((unsigned)temp < strlen(prompt))
  2421. di->textTitleArray[temp] = prompt[temp];
  2422. else
  2423. di->textTitleArray[temp] = ' ';
  2424. di->textTitleArray[temp] = 0;
  2425. di->textCreationArray[0] = 0;
  2426.  
  2427. /* Display the dialog box */
  2428. temp = DialogBoxIndirectParam(hInst, (DLGTEMPLATE *)di,
  2429. hDrawWnd, getsDialogProc, (DWORD)result);
  2430.  
  2431. return (temp == -1)?GP142_FAILURE:GP142_SUCCESS;
  2432. }
  2433.  
  2434. #else
  2435. GP142_gets(const char prompt[], char result[])
  2436. {
  2437. unsigned long size;
  2438. int promptLen;
  2439. FARPROC lpDlgProc;
  2440. HANDLE hDialogTemplate;
  2441. unsigned char far *dialogPtr;
  2442. int i, temp;
  2443. long unsigned
  2444. dialogStyle = WS_CAPTION | WS_SYSMENU | WS_POPUP | WS_VISIBLE |
  2445. DS_MODALFRAME,
  2446. okayStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,
  2447. editStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_MULTILINE |
  2448. ES_AUTOVSCROLL | WS_BORDER,
  2449. staticStyle = WS_CHILD | WS_VISIBLE | SS_LEFT | WS_GROUP;
  2450.  
  2451.  
  2452. for (promptLen=0; prompt[promptLen] != '\0'; promptLen++);
  2453. promptLen++; /* Add room for NULL terminator */
  2454.  
  2455. size = 82 + promptLen;
  2456.  
  2457. hDialogTemplate = GlobalAlloc(GMEM_MOVEABLE, (long unsigned)size);
  2458. dialogPtr = (unsigned char far *)GlobalLock(hDialogTemplate);
  2459.  
  2460. dialogPtr[0] = (unsigned char)((dialogStyle & 0x000000FFL) >> 0);
  2461. dialogPtr[1] = (unsigned char)((dialogStyle & 0x0000FF00L) >> 8);
  2462. dialogPtr[2] = (unsigned char)((dialogStyle & 0x00FF0000L) >> 16);
  2463. dialogPtr[3] = (unsigned char)((dialogStyle & 0xFF000000L) >> 24);
  2464. dialogPtr[4] = (unsigned char)3; /* number of controls */
  2465. dialogPtr[5] = (unsigned char)(((50) & 0x00FF)) >> 0; /* left edge pos, LSB */
  2466. dialogPtr[6] = (unsigned char)(((50) & 0xFF00)) >> 8;
  2467. dialogPtr[7] = (unsigned char)(((50) & 0x00FF)) >> 0; /* top edge pos, LSB */
  2468. dialogPtr[8] = (unsigned char)(((50) & 0xFF00)) >> 8;
  2469. dialogPtr[9] = (unsigned char)185; /* width, LSB */
  2470. dialogPtr[10] = (unsigned char)0;
  2471. dialogPtr[11] = (unsigned char)92; /* height, LSB */
  2472. dialogPtr[12] = (unsigned char)0;
  2473. dialogPtr[13] = (unsigned char)0; /* menu */
  2474. dialogPtr[14] = (unsigned char)0; /* class */
  2475. dialogPtr[15] = (unsigned char)'G'; /* caption */
  2476. dialogPtr[16] = (unsigned char)'P';
  2477. dialogPtr[17] = (unsigned char)'1';
  2478. dialogPtr[18] = (unsigned char)'4';
  2479. dialogPtr[19] = (unsigned char)'2';
  2480. dialogPtr[20] = (unsigned char)'_';
  2481. dialogPtr[21] = (unsigned char)'g';
  2482. dialogPtr[22] = (unsigned char)'e';
  2483. dialogPtr[23] = (unsigned char)'t';
  2484. dialogPtr[24] = (unsigned char)'s';
  2485. dialogPtr[25] = (unsigned char)'(';
  2486. dialogPtr[26] = (unsigned char)')';
  2487. dialogPtr[27] = (unsigned char)'\0';
  2488.  
  2489. /* Okay button */
  2490.  
  2491. dialogPtr[28] = (unsigned char)67; /* left edge of button */
  2492. dialogPtr[29] = (unsigned char)0;
  2493. dialogPtr[30] = (unsigned char)74; /* top edge of button */
  2494. dialogPtr[31] = (unsigned char)0;
  2495. dialogPtr[32] = (unsigned char)50; /* width of button */
  2496. dialogPtr[33] = (unsigned char)0;
  2497. dialogPtr[34] = (unsigned char)14; /* height of button */
  2498. dialogPtr[35] = (unsigned char)0;
  2499. dialogPtr[36] = (unsigned char)((kOkayID & 0x00FF) >> 0); /* button ID */
  2500. dialogPtr[37] = (unsigned char)((kOkayID & 0xFF00) >> 8);
  2501. dialogPtr[38] = (unsigned char)((okayStyle & 0x000000FFL) >> 0);/* Button style */
  2502. dialogPtr[39] = (unsigned char)((okayStyle & 0x0000FF00L) >> 8);
  2503. dialogPtr[40] = (unsigned char)((okayStyle & 0x00FF0000L) >> 16);
  2504. dialogPtr[41] = (unsigned char)((okayStyle & 0xFF000000L) >> 24);
  2505. dialogPtr[42] = (unsigned char)0x80; /* Button class */
  2506. dialogPtr[43] = (unsigned char)'O'; /* Button text */
  2507. dialogPtr[44] = (unsigned char)'k';
  2508. dialogPtr[45] = (unsigned char)'a';
  2509. dialogPtr[46] = (unsigned char)'y';
  2510. dialogPtr[47] = (unsigned char)'\0';
  2511. dialogPtr[48] = (unsigned char)0; /* size of variable length field */
  2512.  
  2513.  
  2514. /* Edit text */
  2515. dialogPtr[49] = (unsigned char)8; /* left edge of control */
  2516. dialogPtr[50] = (unsigned char)0;
  2517. dialogPtr[51] = (unsigned char)30; /* top edge of control */
  2518. dialogPtr[52] = (unsigned char)0;
  2519. dialogPtr[53] = (unsigned char)167;/* width of control */
  2520. dialogPtr[54] = (unsigned char)0;
  2521. dialogPtr[55] = (unsigned char)37; /* height of control */
  2522. dialogPtr[56] = (unsigned char)0;
  2523. dialogPtr[57] = (unsigned char)((kEditID & 0x00FF) >> 0);/* control ID */
  2524. dialogPtr[58] = (unsigned char)((kEditID & 0xFF00) >> 8);
  2525. dialogPtr[59] = (unsigned char)((editStyle & 0x000000FFL) >> 0);/* control style */
  2526. dialogPtr[60] = (unsigned char)((editStyle & 0x0000FF00L) >> 8);
  2527. dialogPtr[61] = (unsigned char)((editStyle & 0x00FF0000L) >> 16);
  2528. dialogPtr[62] = (unsigned char)((editStyle & 0xFF000000L) >> 24);
  2529. dialogPtr[63] = (unsigned char)0x81; /* control class */
  2530. dialogPtr[64] = (unsigned char)'\0'; /* control text */
  2531. dialogPtr[65] = (unsigned char)0; /* size of variable length field */
  2532.  
  2533.  
  2534. /* Static text */
  2535. dialogPtr[66] = (unsigned char)8; /* left edge of control */
  2536. dialogPtr[67] = (unsigned char)0;
  2537. dialogPtr[68] = (unsigned char)3; /* top edge of control */
  2538. dialogPtr[69] = (unsigned char)0;
  2539. dialogPtr[70] = (unsigned char)167;/* width of control */
  2540. dialogPtr[71] = (unsigned char)0;
  2541. dialogPtr[72] = (unsigned char)24; /* height of control */
  2542. dialogPtr[73] = (unsigned char)0;
  2543. dialogPtr[74] = (unsigned char)((kStaticID & 0x00FF) >> 0);/* control ID */
  2544. dialogPtr[75] = (unsigned char)((kStaticID & 0xFF00) >> 8);
  2545. dialogPtr[76] = (unsigned char)((staticStyle & 0x000000FFL) >> 0);/* control style */
  2546. dialogPtr[77] = (unsigned char)((staticStyle & 0x0000FF00L) >> 8);
  2547. dialogPtr[78] = (unsigned char)((staticStyle & 0x00FF0000L) >> 16);
  2548. dialogPtr[79] = (unsigned char)((staticStyle & 0xFF000000L) >> 24);
  2549. dialogPtr[80] = (unsigned char)0x82; /* control class */
  2550. for (i=0; i<promptLen; i++)
  2551. dialogPtr[81 + i] = (unsigned char)prompt[i];
  2552. dialogPtr[81 + promptLen] = (unsigned char)0;
  2553.  
  2554. GlobalUnlock(hDialogTemplate);
  2555.  
  2556. /* Display the dialog box */
  2557. lpDlgProc = MakeProcInstance(getsDialogProc, hInst);
  2558. temp = DialogBoxIndirectParam(hInst, hDialogTemplate,
  2559. hDrawWnd, lpDlgProc, (DWORD)result);
  2560. FreeProcInstance(lpDlgProc);
  2561.  
  2562. /* Free the memory */
  2563. GlobalFree(hDialogTemplate);
  2564.  
  2565. return temp==-1?GP142_FAILURE:GP142_SUCCESS;
  2566. }
  2567. #endif
  2568.  
  2569. #ifdef WIN32
  2570. BOOL CALLBACK getsDialogProc(HWND hDlg, UINT wMessage, WPARAM wParam, LONG lParam)
  2571. #else
  2572. BOOL FAR PASCAL EXPORT getsDialogProc(HWND hDlg, WORD wMessage,
  2573. WORD wParam, LONG lParam)
  2574. #endif
  2575. {
  2576. static char *result;
  2577.  
  2578. switch (wMessage)
  2579. {
  2580. case WM_INITDIALOG:
  2581. result = (char *)lParam;
  2582. return TRUE;
  2583.  
  2584. case WM_COMMAND:
  2585. switch (wParam)
  2586. {
  2587. case kOkayID:
  2588. /* Copy the edit text into the result */
  2589. GetDlgItemText(hDlg, kEditID, result, 256);
  2590. EndDialog(hDlg, TRUE);
  2591. return TRUE;
  2592. }
  2593. break;
  2594. }
  2595.  
  2596. return FALSE;
  2597. }
  2598. #endif /* Windows version of GP142_gets() */
  2599.  
  2600.  
  2601.  
  2602. /********************************************************* GP142_animate()
  2603. **
  2604. ** let the user control animation:
  2605. ** f == 0 => halt
  2606. ** f == 1 => single step
  2607. ** f == 2 => run
  2608. ** f == 5 => quit
  2609. **
  2610. */
  2611. extern int GP142_FUNC
  2612. GP142_animate(int f)
  2613. {
  2614. #ifdef MACINTOSH
  2615. if (!gpWin)
  2616. #elif defined(WINDOWS)
  2617. if (!hDrawWnd)
  2618. #elif defined(X11R6)
  2619. if (!display)
  2620. #endif
  2621. return GP142_FAILURE;
  2622.  
  2623. switch ( f )
  2624. {
  2625. case ANI_RUN: /* run */
  2626. gRunFlag = TRUE;
  2627. break;
  2628. case ANI_HALT: /* halt */
  2629. gSingleStepFlag = FALSE;
  2630. gRunFlag = FALSE;
  2631. break;
  2632. case ANI_SINGLE_STEP: /* single step */
  2633. gSingleStepFlag = TRUE;
  2634. break;
  2635. case ANI_QUIT: /* quit */
  2636. gDoneFlag = TRUE;
  2637. break;
  2638. default:
  2639. #ifdef MACINTOSH
  2640. SysBeep(1);
  2641. #endif
  2642. break;
  2643. }
  2644.  
  2645. return GP142_SUCCESS;
  2646. }
  2647.  
  2648.  
  2649.  
  2650. /******************************************************** GP142_logging() **
  2651. ** let the user set the logging flag
  2652. **
  2653. */
  2654. extern int GP142_FUNC
  2655. GP142_logging(int f)
  2656. {
  2657. #ifdef MACINTOSH
  2658. if (!gpWin)
  2659. #elif defined(WINDOWS)
  2660. if (!hDrawWnd)
  2661. #elif defined(X11R6)
  2662. if (!display)
  2663. #endif
  2664. return GP142_FAILURE; /* GP142_open hasn't been called yet; do nothing */
  2665. gLogging = !!f; /* !! forces value to be either 0 or 1 */
  2666. #ifdef MACINTOSH
  2667. CheckItem(RunMenu, mLog, (int)gLogging);
  2668. #elif defined(WINDOWS)
  2669. if (gLogging)
  2670. CheckMenuItem(hRunMenu, IDM_LOGGING, MF_BYCOMMAND | MF_CHECKED);
  2671. else
  2672. CheckMenuItem(hRunMenu, IDM_LOGGING, MF_BYCOMMAND | MF_UNCHECKED);
  2673. #elif defined(X11R6)
  2674. XClearWindow(display,winc[3]);
  2675. if (gLogging)
  2676. XDrawString(display, winc[3], gccon, 5, 15, "Logging on", 10);
  2677. else
  2678. XDrawString(display, winc[3], gccon, 5, 15, "Logging off", 11);
  2679. #endif
  2680. if (gLogging)
  2681. GP142_show_text(TRUE);
  2682.  
  2683. return GP142_SUCCESS ;
  2684. }
  2685.  
  2686. /*
  2687. ** Verify that color is legal; print error and reset if not.
  2688. ** In all cases, return a legal color.
  2689. */
  2690. static int Legalize_Color(int color)
  2691. {
  2692. if ( ! ( 0 <= color && color <= MAX_COLORS ) )
  2693. {
  2694. printf("Illegal color %d; using RED.\n", color);
  2695. color = RED;
  2696. }
  2697. return (color);
  2698. }
  2699.  
  2700.  
  2701. /******************************************************** GP142_pixel() ***/
  2702. extern int GP142_FUNC
  2703. GP142_pixelXY (int color, int x, int y)
  2704. {
  2705. GP142_point p;
  2706. p.x = x;
  2707. p.y = y;
  2708.  
  2709. return GP142_pixelP(color, p);
  2710. }
  2711.  
  2712. extern int GP142_FUNC
  2713. GP142_pixelP (int color, GP142_point p)
  2714. {
  2715. Graphics new_item;
  2716.  
  2717. color = Legalize_Color(color);
  2718. if (gLogging) {
  2719. printf("%s pixel at (%d,%d)\n",
  2720. gColorName[color], p.x, p.y);
  2721. }
  2722.  
  2723. new_item.obj_type = obj_pixel;
  2724. new_item.g.pixel.p = p;
  2725. new_item.color = color;
  2726.  
  2727. Draw_Graphic_Item(&new_item);
  2728.  
  2729. return GP142_SUCCESS;
  2730. }
  2731.  
  2732.  
  2733. /******************************************************* GP142_circle() ***/
  2734. extern int GP142_FUNC
  2735. GP142_circleXY (int color, int x, int y, int radius)
  2736. {
  2737. GP142_point p;
  2738.  
  2739. p.x = x;
  2740. p.y = y;
  2741.  
  2742. return GP142_circleP(color, p, radius);
  2743. }
  2744.  
  2745. extern int GP142_FUNC
  2746. GP142_circleP (int color, GP142_point center, int radius)
  2747. {
  2748. Graphics new_item;
  2749.  
  2750. color = Legalize_Color(color);
  2751. if (radius < 0)
  2752. {
  2753. printf("Radius of %d not possible, using radius %d\n", radius, -radius);
  2754. radius = -radius;
  2755. }
  2756.  
  2757. if (gLogging) {
  2758. printf("%s circle at (%d,%d), radius %d\n",
  2759. gColorName[color], center.x, center.y, radius);
  2760. }
  2761.  
  2762. new_item.obj_type = obj_oval;
  2763. new_item.g.oval.upper_left.x = center.x - radius;
  2764. new_item.g.oval.upper_left.y = center.y + radius;
  2765. new_item.g.oval.lower_right.x = center.x + radius;
  2766. new_item.g.oval.lower_right.y =center.y - radius;
  2767. new_item.color = color;
  2768. new_item.width = 1;
  2769.  
  2770. Draw_Graphic_Item(&new_item);
  2771.  
  2772. return GP142_SUCCESS;
  2773. }
  2774.  
  2775.  
  2776. /***************************************************** GP142_triangle() ***/
  2777. extern int GP142_FUNC
  2778. GP142_triangleXY (
  2779. int color,
  2780. int x1, int y1,
  2781. int x2, int y2,
  2782. int x3, int y3,
  2783. int width)
  2784. {
  2785. GP142_point p1, p2, p3;
  2786.  
  2787. p1.x = x1;
  2788. p1.y = y1;
  2789. p2.x = x2;
  2790. p2.y = y2;
  2791. p3.x = x3;
  2792. p3.y = y3;
  2793.  
  2794. return GP142_triangleP(color, p1, p2, p3, width);
  2795. }
  2796.  
  2797. extern int GP142_FUNC
  2798. GP142_triangleP (int color, GP142_point p1,
  2799. GP142_point p2, GP142_point p3, int width)
  2800. {
  2801. Graphics new_item;
  2802.  
  2803. color = Legalize_Color(color);
  2804. if (width < 0)
  2805. {
  2806. printf("Width of %d not possible, using width %d\n", width, -width);
  2807. width = -width;
  2808. }
  2809.  
  2810. if (gLogging) {
  2811. printf("%s triangle at (%d,%d), (%d,%d), (%d,%d)\n",
  2812. gColorName[color], p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
  2813. }
  2814. new_item.obj_type = obj_triangle;
  2815. new_item.g.triangle.p1.x = p1.x;
  2816. new_item.g.triangle.p1.y = p1.y;
  2817. new_item.g.triangle.p2.x = p2.x;
  2818. new_item.g.triangle.p2.y = p2.y;
  2819. new_item.g.triangle.p3.x = p3.x;
  2820. new_item.g.triangle.p3.y = p3.y;
  2821. new_item.color = color;
  2822. new_item.width = width;
  2823.  
  2824. Draw_Graphic_Item(&new_item);
  2825.  
  2826. return GP142_SUCCESS;
  2827. }
  2828.  
  2829. /************************************************** GP142_rectangle() ****/
  2830. extern int GP142_FUNC
  2831. GP142_rectangleXY (
  2832. int color,
  2833. int x1, int y1,
  2834. int x2, int y2,
  2835. int width)
  2836. {
  2837. GP142_point p1, p2;
  2838.  
  2839. p1.x = x1;
  2840. p1.y = y1;
  2841. p2.x = x2;
  2842. p2.y = y2;
  2843.  
  2844. return GP142_rectangleP(color, p1, p2, width);
  2845. }
  2846.  
  2847. extern int GP142_FUNC
  2848. GP142_rectangleP (
  2849. int color, GP142_point p_upper_left, GP142_point p_lower_right,
  2850. int width)
  2851. {
  2852. Graphics new_item;
  2853. int temp;
  2854.  
  2855. /* Determine proper ordering of points */
  2856. if (p_upper_left.x > p_lower_right.x)
  2857. {
  2858. temp = p_upper_left.x;
  2859. p_upper_left.x = p_lower_right.x;
  2860. p_lower_right.x = temp;
  2861. }
  2862. if (p_upper_left.y < p_lower_right.y)
  2863. {
  2864. temp = p_upper_left.y;
  2865. p_upper_left.y = p_lower_right.y;
  2866. p_lower_right.y = temp;
  2867. }
  2868.  
  2869. color = Legalize_Color(color);
  2870. if (width < 0)
  2871. {
  2872. printf("Width of %d not possible, using width %d\n", width, -width);
  2873. width = -width;
  2874. }
  2875.  
  2876. if (gLogging) {
  2877. if (width == 0)
  2878. printf("%s rectangle with bounding box (%d,%d) to (%d,%d)"
  2879. ", filled\n",
  2880. gColorName[color],
  2881. p_upper_left.x, p_upper_left.y,
  2882. p_lower_right.x, p_lower_right.y);
  2883. else
  2884. printf("%s rectangle with bounding box (%d,%d) to (%d,%d)"
  2885. " with line width %d\n",
  2886. gColorName[color],
  2887. p_upper_left.x, p_upper_left.y,
  2888. p_lower_right.x, p_lower_right.y, width);
  2889. }
  2890.  
  2891.  
  2892.  
  2893. new_item.obj_type = obj_rectangle;
  2894. new_item.g.rectangle.upper_left.x = p_upper_left.x;
  2895. new_item.g.rectangle.upper_left.y = p_upper_left.y;
  2896. new_item.g.rectangle.lower_right.x = p_lower_right.x;
  2897. new_item.g.rectangle.lower_right.y = p_lower_right.y;
  2898. new_item.color = color;
  2899. new_item.width = width;
  2900.  
  2901. Draw_Graphic_Item(&new_item);
  2902.  
  2903. return GP142_SUCCESS;
  2904. }
  2905.  
  2906.  
  2907. /********************************************************* GP142_oval() ***/
  2908. extern int GP142_FUNC
  2909. GP142_ovalXY (
  2910. int color,
  2911. int x1, int y1,
  2912. int x2, int y2,
  2913. int width)
  2914. {
  2915. GP142_point p1, p2;
  2916.  
  2917. p1.x = x1;
  2918. p1.y = y1;
  2919. p2.x = x2;
  2920. p2.y = y2;
  2921.  
  2922. return GP142_ovalP(color, p1, p2, width);
  2923. }
  2924.  
  2925.  
  2926. extern int GP142_FUNC
  2927. GP142_ovalP (
  2928. int color,
  2929. GP142_point p_upper_left, GP142_point p_lower_right,
  2930. int width)
  2931. {
  2932. Graphics new_item;
  2933. int temp;
  2934.  
  2935. /* Determine proper ordering of points */
  2936. if (p_upper_left.x > p_lower_right.x)
  2937. {
  2938. temp = p_upper_left.x;
  2939. p_upper_left.x = p_lower_right.x;
  2940. p_lower_right.x = temp;
  2941. }
  2942. if (p_upper_left.y < p_lower_right.y)
  2943. {
  2944. temp = p_upper_left.y;
  2945. p_upper_left.y = p_lower_right.y;
  2946. p_lower_right.y = temp;
  2947. }
  2948.  
  2949. if (width < 0)
  2950. {
  2951. printf("Width of %d not possible, using width %d\n", width, -width);
  2952. width = -width;
  2953. }
  2954.  
  2955. color = Legalize_Color(color);
  2956. if (gLogging) {
  2957. if (width == 0)
  2958. printf("%s oval with bounding box (%d,%d) to (%d,%d), "
  2959. "filled\n",
  2960. gColorName[color],
  2961. p_upper_left.x, p_upper_left.y,
  2962. p_lower_right.x, p_lower_right.y);
  2963. else
  2964. printf("%s oval with bounding box (%d,%d) to (%d,%d), "
  2965. "line width %d\n",
  2966. gColorName[color],
  2967. p_upper_left.x, p_upper_left.y,
  2968. p_lower_right.x, p_lower_right.y, width);
  2969. }
  2970.  
  2971. new_item.obj_type = obj_oval;
  2972. new_item.g.oval.upper_left.x = p_upper_left.x;
  2973. new_item.g.oval.upper_left.y = p_upper_left.y;
  2974. new_item.g.oval.lower_right.x = p_lower_right.x;
  2975. new_item.g.oval.lower_right.y = p_lower_right.y;
  2976. new_item.color = color;
  2977. new_item.width = width;
  2978.  
  2979. Draw_Graphic_Item(&new_item);
  2980.  
  2981. return GP142_SUCCESS;
  2982. }
  2983.  
  2984.  
  2985. /********************************************************* GP142_line() ***/
  2986. extern int GP142_FUNC
  2987. GP142_lineXY (int color, int x1, int y1, int x2, int y2, int width)
  2988. {
  2989. GP142_point p1, p2;
  2990.  
  2991. p1.x = x1;
  2992. p1.y = y1;
  2993. p2.x = x2;
  2994. p2.y = y2;
  2995.  
  2996. return GP142_lineP(color, p1, p2, width);
  2997. }
  2998.  
  2999.  
  3000. extern int GP142_FUNC
  3001. GP142_lineP (int color, GP142_point pUL, GP142_point pLR, int width)
  3002. {
  3003. Graphics new_item;
  3004.  
  3005. if (width < 0)
  3006. {
  3007. printf("Width of %d not possible, using width %d\n", width, -width);
  3008. width = -width;
  3009. }
  3010.  
  3011. color = Legalize_Color(color);
  3012. if (gLogging) {
  3013. printf("%s line from (%d,%d) to (%d,%d), width %d\n",
  3014. gColorName[color], pUL.x, pUL.y, pLR.x, pLR.y, width);
  3015. }
  3016. new_item.obj_type = obj_line;
  3017. new_item.g.line.upper_left.x = pUL.x;
  3018. new_item.g.line.upper_left.y = pUL.y;
  3019. new_item.g.line.lower_right.x = pLR.x;
  3020. new_item.g.line.lower_right.y = pLR.y;
  3021. new_item.color = color;
  3022. if (width < 1) width = 1;
  3023. new_item.width = width;
  3024.  
  3025. Draw_Graphic_Item(&new_item);
  3026.  
  3027. return GP142_SUCCESS;
  3028. }
  3029.  
  3030.  
  3031. /********************************************************* GP142_text() ***/
  3032. extern int GP142_FUNC
  3033. GP142_textXY(int color, int x, int y, int ptsize, const char *string)
  3034. {
  3035. GP142_point p;
  3036.  
  3037. p.x = x;
  3038. p.y = y;
  3039.  
  3040. return GP142_textP(color, p, ptsize, string);
  3041. }
  3042.  
  3043.  
  3044. extern int GP142_FUNC
  3045. GP142_textP (int color, GP142_point p, int ptsize, const char string[])
  3046. {
  3047. Graphics new_item;
  3048. #ifdef MACINTOSH
  3049. int len;
  3050. #elif defined(WINDOWS)
  3051. char far *pStr;
  3052. int i;
  3053. #elif defined(X11R6)
  3054. int len;
  3055. #endif
  3056.  
  3057. if (ptsize < 0)
  3058. {
  3059. printf("ptsize of %d not possible, using ptsize %d\n", ptsize, -ptsize);
  3060. ptsize = -ptsize;
  3061. }
  3062. if (ptsize > 127)
  3063. {
  3064. printf("ptsize of %d not possible, using ptsize %d\n", ptsize, 127);
  3065. ptsize = 127;
  3066. }
  3067.  
  3068. color = Legalize_Color(color);
  3069. if (gLogging) {
  3070. printf("%s text at (%d,%d), \"%s\"\n",
  3071. gColorName[color], p.x, p.y, string);
  3072. }
  3073. new_item.obj_type = obj_text;
  3074. new_item.g.text.p.x = p.x;
  3075. new_item.g.text.p.y = p.y;
  3076. new_item.color = color;
  3077. new_item.g.text.ptsize = ptsize;
  3078.  
  3079. #ifdef MACINTOSH
  3080. len = strlen(string) + 1;
  3081. if (len > MAXSTRLEN) len = MAXSTRLEN;
  3082. if ((new_item.g.text.the_text = malloc(len)) == NULL) {
  3083. printf("GP142 library error: out of memory\n");
  3084. return GP142_FAILURE;
  3085. }
  3086. strncpy(new_item.g.text.the_text, string, len);
  3087. new_item.g.text.the_text[len - 1] = 0; /* to be for sure, for sure */
  3088. CtoPstr(new_item.g.text.the_text);
  3089. Draw_Graphic_Item(&new_item);
  3090. free(new_item.g.text.the_text);
  3091.  
  3092. #elif defined(WINDOWS)
  3093.  
  3094. i = 0;
  3095. while (string[i] != '\0')
  3096. i++;
  3097. new_item.g.text.hText =
  3098. GlobalAlloc(GMEM_MOVEABLE, (long unsigned)i+1L);
  3099. pStr = GlobalLock(new_item.g.text.hText);
  3100.  
  3101. i = 0;
  3102. while (string[i] != '\0')
  3103. {
  3104. pStr[i] = string[i];
  3105. i++;
  3106. }
  3107. pStr[i] = '\0';
  3108.  
  3109. GlobalUnlock(new_item.g.text.hText);
  3110.  
  3111. Draw_Graphic_Item(&new_item);
  3112. GlobalFree(new_item.g.text.hText);
  3113.  
  3114. #elif defined(X11R6)
  3115.  
  3116. len = strlen(string) + 1;
  3117.  
  3118. if (len > MAXSTRLEN) len = MAXSTRLEN;
  3119.  
  3120. if ((new_item.g.text.the_text = (char *) malloc(len)) == NULL) {
  3121. printf("GP142 library error: out of memory\n");
  3122. return GP142_FAILURE;
  3123. }
  3124.  
  3125. strncpy(new_item.g.text.the_text, string, len);
  3126. new_item.g.text.the_text[len - 1] = 0;
  3127. Draw_Graphic_Item(&new_item);
  3128. free(new_item.g.text.the_text);
  3129.  
  3130. #endif
  3131.  
  3132. return GP142_SUCCESS;
  3133. }
  3134.  
  3135.  
  3136. /****************************************************** GP142_getDimensions() ***/
  3137. /*
  3138. * functions to get the on-screen dimensions of text
  3139. */
  3140.  
  3141. extern int GP142_FUNC
  3142. GP142_getDimensions2 (int ptsize, int *height, int *width, const char string[])
  3143. {
  3144. #ifdef MACINTOSH
  3145. int len;
  3146. FontInfo fontInfo;
  3147. char *theString;
  3148. #elif defined(WINDOWS)
  3149. char far *pStr;
  3150. int i;
  3151. HFONT hFont, hOldFont;
  3152. HANDLE hText;
  3153. SIZE textSize;
  3154. #elif defined(X11R6)
  3155. int len;
  3156. #endif
  3157.  
  3158. if (ptsize < 0)
  3159. {
  3160. printf("ptsize of %d not possible, using ptsize %d\n", ptsize, -ptsize);
  3161. ptsize = -ptsize;
  3162. }
  3163. if (ptsize > 127)
  3164. {
  3165. printf("ptsize of %d not possible, using ptsize %d\n", ptsize, 127);
  3166. ptsize = 127;
  3167. }
  3168.  
  3169. #ifdef MACINTOSH
  3170. len = strlen(string) + 1;
  3171. if (len > MAXSTRLEN) len = MAXSTRLEN;
  3172. if ((theString = malloc(len)) == NULL) {
  3173. printf("GP142 library error: out of memory\n");
  3174. return GP142_FAILURE;
  3175. }
  3176. strncpy(theString, string, len);
  3177. theString[len - 1] = 0; /* to be for sure, for sure */
  3178. CtoPstr(theString);
  3179. TextSize(ptsize);
  3180. GetFontInfo(&fontInfo);
  3181. *width = TextWidth(theString, 1, strlen(string));
  3182. *height = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
  3183. free(theString);
  3184.  
  3185. #elif defined(WINDOWS)
  3186.  
  3187. i = 0;
  3188. while (string[i] != '\0')
  3189. i++;
  3190. hText =
  3191. GlobalAlloc(GMEM_MOVEABLE, (long unsigned)i+1L);
  3192. pStr = GlobalLock(hText);
  3193.  
  3194. i = 0;
  3195. while (string[i] != '\0')
  3196. {
  3197. pStr[i] = string[i];
  3198. i++;
  3199. }
  3200. pStr[i] = '\0';
  3201.  
  3202. GlobalUnlock(hText);
  3203.  
  3204. hFont = CreateFont(-ptsize,
  3205. 0, /* let Windows choose width */
  3206. 0, /* escapement, in 10ths of degrees */
  3207. 0, /* orientation, in 10ths of degrees */
  3208. FW_NORMAL, /* normal weight */
  3209. FALSE, /* no italic */
  3210. FALSE, /* no underline */
  3211. FALSE, /* no strikeout */
  3212. ANSI_CHARSET, /* use ANSI character set */
  3213. OUT_DEFAULT_PRECIS, /* output precision */
  3214. CLIP_DEFAULT_PRECIS, /* clip precision */
  3215. DEFAULT_QUALITY, /* quality */
  3216. DEFAULT_PITCH | FF_DONTCARE, /* pitch and family */
  3217. "GP142-font"); /* way-cool name of font */
  3218.  
  3219. hOldFont = SelectObject(offscreen_DC, hFont);
  3220.  
  3221. pStr = GlobalLock(hText);
  3222.  
  3223. /* To be compatible with the Mac, we want to bump the
  3224. text string 'up' by the height of the string */
  3225. GetTextExtentPoint(offscreen_DC,
  3226. pStr,
  3227. far_strlen(pStr),
  3228. &textSize);
  3229. *width = textSize.cx;
  3230. *height = textSize.cy;
  3231.  
  3232. GlobalUnlock(hText);
  3233.  
  3234. SelectObject(offscreen_DC, hOldFont);
  3235. DeleteObject(hFont);
  3236.  
  3237. #elif defined(X11R6)
  3238.  
  3239. if (ptsize != current_font->point_size) {
  3240.  
  3241. FontDB *temp = font_info;
  3242.  
  3243. while (temp) {
  3244. if (ptsize == temp->point_size)
  3245. break;
  3246. temp = temp->next;
  3247. }
  3248.  
  3249. /* Or else add it to the list and load it. */
  3250.  
  3251. if (!temp) {
  3252. char fontname[100];
  3253. temp = (FontDB*) malloc(sizeof(FontDB));
  3254. sprintf(fontname, "-adobe-helvetica-medium-r-normal--0-%d-75-75-p-0-iso8859-1", ptsize * 10);
  3255. if ((temp == NULL) ||
  3256. (temp->thefont = XLoadQueryFont(display,
  3257. fontname)) == NULL) {
  3258. fprintf(stderr, "Cannot open Adobe scalable font.\n");
  3259. exit(0);
  3260. }
  3261.  
  3262. /* Set font to requested point size and put node at
  3263. * the head of the list. */
  3264.  
  3265. temp->point_size = ptsize;
  3266. temp->next = font_info;
  3267. font_info = temp;
  3268. }
  3269.  
  3270. /* Set gc to new point size */
  3271. XSetFont(display, gc, temp->thefont->fid);
  3272. current_font = temp;
  3273. }
  3274.  
  3275. *height = current_font->thefont->ascent + current_font->thefont->descent;
  3276. *width = XTextWidth(current_font->thefont, string, strlen(string));
  3277.  
  3278. #endif
  3279.  
  3280. return GP142_SUCCESS;
  3281. }
  3282.  
  3283.  
  3284. /****************************************************** GP142_printf() ***/
  3285. /*
  3286. * The following function, thanks to Chris Anderson, subsumes
  3287. * GP142_int and GP142_text (from v1.9 and previous), from users
  3288. * perspective. It provides formated printout to the graphics window,
  3289. * essentially just like printf; newlines ("\n") do advance text to the
  3290. * next line.
  3291. */
  3292. extern int GP142_FUNC
  3293. GP142_printfXY(
  3294. int color, /* text color */
  3295. int x, int y, /* x, y coords of left end of text */
  3296. int point_size, /* text size */
  3297. const char fmt[], /* the printf format string */
  3298. ... ) /* list of variables to print */
  3299. {
  3300. va_list vlist; /* Argument list pointer */
  3301. char str[1024]; /* Buffer to build string into */
  3302. int cnt; /* Result of SPRINTF for return */
  3303.  
  3304. va_start( vlist, fmt ); /* Initialize va_ functions */
  3305.  
  3306. /* prints string to buffer */
  3307. cnt = vsprintf( str, fmt, vlist );
  3308. va_end( vlist ); /* Close va_ functions */
  3309. /* Send string to graphics wind */
  3310. GP142_textXY( color,x,y,point_size,str );
  3311. return( cnt ); /* Return the conversion count */
  3312. }
  3313.  
  3314. extern int GP142_FUNC
  3315. GP142_printfP(
  3316. int color, /* text color */
  3317. GP142_point p, /* x, y coords of left end of text */
  3318. int point_size, /* text size */
  3319. const char fmt[], /* the printf format string */
  3320. ... ) /* list of variables to print */
  3321. {
  3322. va_list vlist; /* Argument list pointer */
  3323. char str[1024]; /* Buffer to build string into */
  3324. int cnt; /* Result of SPRINTF for return */
  3325.  
  3326. va_start( vlist, fmt ); /* Initialize va_ functions */
  3327.  
  3328. /* prints string to buffer */
  3329. cnt = vsprintf( str, fmt, vlist );
  3330. va_end( vlist ); /* Close va_ functions */
  3331. /* Send string to graphics wind */
  3332. GP142_textP( color,p,point_size,str );
  3333. return( cnt ); /* Return the conversion count */
  3334. }
  3335.  
  3336. extern int GP142_FUNC
  3337. GP142_getDimensions(
  3338. int point_size, /* text size */
  3339. int *height,
  3340. int *width,
  3341. const char fmt[], /* the printf format string */
  3342. ... ) /* list of variables to print */
  3343. {
  3344. va_list vlist; /* Argument list pointer */
  3345. char str[1024]; /* Buffer to build string into */
  3346. int cnt; /* Result of SPRINTF for return */
  3347.  
  3348. va_start( vlist, fmt ); /* Initialize va_ functions */
  3349.  
  3350. /* prints string to buffer */
  3351. cnt = vsprintf( str, fmt, vlist );
  3352. va_end( vlist ); /* Close va_ functions */
  3353. /* get dimensions of string */
  3354. GP142_getDimensions2( point_size,height,width,str );
  3355. return ( cnt ); /* Return the conversion count */
  3356. }
  3357.  
  3358.  
  3359. /******************************************************** GP142_undo() ***/
  3360. extern int GP142_FUNC
  3361. GP142_undo(void)
  3362. {
  3363. printf("GP142_undo is no longer supported.\n");
  3364. return GP142_SUCCESS;
  3365. }
  3366.  
  3367. /******************************************************* GP142_flush() ***/
  3368. extern int GP142_FUNC
  3369. GP142_flush(void)
  3370. {
  3371. if (gLogging) {
  3372. printf("Flushing the graphics window\n");
  3373. }
  3374. #ifdef MACINTOSH
  3375. refresh(gpWin);
  3376.  
  3377. #elif defined(WINDOWS)
  3378. if (need_redraw) {
  3379. BitBlt (the_hdc,0,0,2*GP142_XMAX+1, 2*GP142_YMAX+FUDGE,
  3380. offscreen_DC,0,0,SRCCOPY);
  3381. need_redraw = 0;
  3382. }
  3383. #elif defined(X11R6)
  3384. if (need_redraw) {
  3385. XCopyArea(display, offscreen_buffer, window, gc, 0, 0, GP142_XMAX*2, GP142_YMAX*2, 0, 0);
  3386. XFlush(display);
  3387. need_redraw = 0;
  3388. }
  3389. #endif
  3390.  
  3391. return GP142_SUCCESS;
  3392. }
  3393.  
  3394.  
  3395. /******************************************************* GP142_clear() ***/
  3396. extern int GP142_FUNC
  3397. GP142_clear(void)
  3398. {
  3399. if (gLogging) {
  3400. printf("Clearing the graphics window\n");
  3401. }
  3402.  
  3403. /* Clear the offscreen buffer */
  3404. GP_clear();
  3405.  
  3406. return GP142_SUCCESS;
  3407. }
  3408.  
  3409.  
  3410. static void GP_clear(void)
  3411. {
  3412. #ifdef MACINTOSH
  3413. GDHandle oldGD;
  3414. GWorldPtr oldGWorld;
  3415.  
  3416. GetGWorld(&oldGWorld, &oldGD);
  3417. LockPixels(gGP142World->portPixMap);
  3418. SetGWorld(gGP142World, nil);
  3419.  
  3420. EraseRect(&(*gGP142World->portPixMap)->bounds);
  3421.  
  3422. SetGWorld(oldGWorld, oldGD);
  3423. UnlockPixels(gGP142World->portPixMap);
  3424. #elif defined(WINDOWS)
  3425. /* Just draw a white rectangle */
  3426. HBRUSH hBrush, hOldBrush;
  3427. hBrush = CreateSolidBrush(gRGBColors[1]);
  3428. hOldBrush = SelectObject(offscreen_DC, hBrush);
  3429.  
  3430. /* Windows draws lines in a very odd fashion. Windows
  3431. will include the first endpoint when drawing a line, but
  3432. _exclude_ the next endpoint. I gather that this allows
  3433. for poly-lines, but very strange things happen when you
  3434. draw single lines this way. That is why we add 1 to the
  3435. ending x and y coords in the rectangle, oval, etc. */
  3436. Rectangle(offscreen_DC,
  3437. 0, 0, GP142_XMAX*2+1, GP142_YMAX*2+FUDGE);
  3438. SelectObject(offscreen_DC, hOldBrush);
  3439. DeleteObject(hBrush);
  3440. #elif defined(X11R6)
  3441. XGCValues gc_val;
  3442. GC gc_clear;
  3443.  
  3444. gc_clear = XCreateGC(display, window, 0, &gc_val);
  3445. XSetForeground(display, gc_clear, WhitePixel(display, screen));
  3446. XFillRectangle(display, offscreen_buffer, gc_clear, 0, 0,
  3447. GP142_XMAX*2, GP142_YMAX*2);
  3448. #endif
  3449.  
  3450. need_redraw = 1;
  3451. }
  3452.  
  3453.  
  3454. /******************************************** Graphics Output function ***/
  3455. #ifdef MACINTOSH
  3456. static void
  3457. Draw_Graphic_Item(Graphics *item)
  3458. {
  3459. GDHandle oldGD;
  3460. GWorldPtr oldGWorld;
  3461. PolyHandle poly;
  3462. Rect r;
  3463. int color;
  3464. RGBColor savecolor;
  3465. int width;
  3466. int done, j, line, total, length;
  3467. char *s;
  3468. FontInfo fontInfo;
  3469.  
  3470. /* Save the old graphics world */
  3471. GetGWorld(&oldGWorld, &oldGD);
  3472.  
  3473. /* Grab the offscreen graphics world buffer, and set it as the current world */
  3474. LockPixels(gGP142World->portPixMap);
  3475. SetGWorld(gGP142World, nil);
  3476.  
  3477. color = Legalize_Color(item->color); /* just in case...*/
  3478. if (color == 0 || gColorFlag == 0)
  3479. PenPat(&qd.black);
  3480. else
  3481. PenPixPat(color_pp[color]);
  3482. width = item->width;
  3483. PenSize(width, width);
  3484. switch (item->obj_type) {
  3485. case obj_triangle:
  3486. /* triangles are very strange beasts. That is, they are polygons, so they don't
  3487. behave _exactly_ like rectangles or ovals, which are bound by rects. The problem
  3488. has been that filled triangles aren't including their edges. The easiest thing
  3489. to fix this is to explicitly draw the frame of the triangle whenever the width
  3490. is 0. To do this, we simply change the pen size to 1x1 if the the width is 0,
  3491. and _always_ draw the frame. This seems to be working, though I haven't done
  3492. much testing yet... */
  3493. poly = OpenPoly();
  3494. MoveTo(gXCenter+item->g.triangle.p1.x-width/2,
  3495. gYCenter-item->g.triangle.p1.y-width/2);
  3496. LineTo(gXCenter+item->g.triangle.p2.x-width/2,
  3497. gYCenter-item->g.triangle.p2.y-width/2);
  3498. LineTo(gXCenter+item->g.triangle.p3.x-width/2,
  3499. gYCenter-item->g.triangle.p3.y-width/2);
  3500. LineTo(gXCenter+item->g.triangle.p1.x-width/2,
  3501. gYCenter-item->g.triangle.p1.y-width/2);
  3502. ClosePoly();
  3503.  
  3504. if (width == 0)
  3505. {
  3506. if (gColorFlag)
  3507. FillCPoly(poly, color_pp[color]);
  3508. else
  3509. PaintPoly(poly);
  3510. PenSize(1,1); /* force a thin outline */
  3511. }
  3512. FramePoly(poly);
  3513. KillPoly(poly);
  3514. break;
  3515.  
  3516. case obj_rectangle:
  3517. /* As of v1.4 to v1.5, I (Corey) have realized that we have a major inconsistency.
  3518. That is, all the GP142 functions which require a bounding box expect the coords
  3519. for those boxes in Upper-Left, Lower-Right order. The GP142.h file describes these
  3520. functions as taking first the Lower-Left, then Upper-right coords. Luckily, every-
  3521. thing is symmetric about the X and Y midpoint lines. But it is just terribly
  3522. confusing for maintaing the code. This problem also persists to the WIndows
  3523. version. Oh, how I wish that I had found this error when going from v1.3 to v1.4.
  3524. Then, I could have corrected everything, and no one would have needed to change
  3525. any of their GP142 application code. Ah, well. */
  3526.  
  3527. /* left top right bottom! */
  3528. SetRect(&r,
  3529. gXCenter+item->g.rectangle.upper_left.x-width/2,
  3530. gYCenter-item->g.rectangle.upper_left.y-width/2,
  3531. gXCenter+item->g.rectangle.lower_right.x+width/2 +1,
  3532. gYCenter-item->g.rectangle.lower_right.y+width/2 +1);
  3533. if (width == 0)
  3534. if (gColorFlag)
  3535. FillCRect(&r, color_pp[color]);
  3536. else
  3537. PaintRect(&r);
  3538. else
  3539. FrameRect(&r);
  3540. break;
  3541.  
  3542. case obj_oval:
  3543. SetRect(&r,
  3544. gXCenter+item->g.oval.upper_left.x-width/2,
  3545. gYCenter-item->g.oval.upper_left.y-width/2,
  3546. gXCenter+item->g.oval.lower_right.x+width/2 +1,
  3547. gYCenter-item->g.oval.lower_right.y+width/2 +1);
  3548. if (width == 0)
  3549. if (gColorFlag)
  3550. FillCOval(&r, color_pp[color]);
  3551. else
  3552. PaintOval(&r);
  3553. else
  3554. FrameOval(&r);
  3555. break;
  3556.  
  3557. case obj_line:
  3558. MoveTo( gXCenter+item->g.line.upper_left.x-width/2,
  3559. gYCenter-item->g.line.upper_left.y-width/2);
  3560. LineTo( gXCenter+item->g.line.lower_right.x-width/2,
  3561. gYCenter-item->g.line.lower_right.y-width/2);
  3562. break;
  3563.  
  3564. case obj_pixel:
  3565. PenSize(1,1);
  3566. MoveTo( gXCenter+item->g.pixel.p.x,
  3567. gYCenter-item->g.pixel.p.y );
  3568. LineTo( gXCenter+item->g.pixel.p.x,
  3569. gYCenter-item->g.pixel.p.y );
  3570. break;
  3571.  
  3572. case obj_text:
  3573. if (gColorFlag) {
  3574. GetForeColor(&savecolor);
  3575. if (color != 0)
  3576. RGBForeColor(&gRGBColors[color]);
  3577. }
  3578.  
  3579. TextSize(item->g.text.ptsize);
  3580.  
  3581. GetFontInfo(&fontInfo);
  3582.  
  3583. /* We want to honor newline characters in the string by
  3584. advancing the current line some height */
  3585.  
  3586. done = FALSE;
  3587. s = item->g.text.the_text;
  3588. total = 1; /* skip over the pascal length byte */
  3589. length = s[0];
  3590. line = 0;
  3591. while (done != TRUE)
  3592. {
  3593. for (j=0; s[total+j] != '\n' && s[total+j] != '\0'
  3594. && total+j <= length; j++)
  3595. ;
  3596. if (total+j >= length || s[total+j] == '\0')
  3597. done = TRUE;
  3598.  
  3599. MoveTo( gXCenter+item->g.text.p.x,
  3600. gYCenter-item->g.text.p.y +
  3601. line*(fontInfo.ascent +
  3602. fontInfo.descent +
  3603. fontInfo.leading));
  3604. DrawText(s, total, j);
  3605.  
  3606. line++;
  3607. total += j+1;
  3608. }
  3609.  
  3610. if (gColorFlag)
  3611. RGBForeColor(&savecolor);
  3612. break;
  3613. }
  3614.  
  3615.  
  3616. SetGWorld(oldGWorld, oldGD);
  3617. UnlockPixels(gGP142World->portPixMap);
  3618.  
  3619. need_redraw = 1;
  3620. }
  3621.  
  3622.  
  3623.  
  3624. #elif defined(WINDOWS)
  3625.  
  3626. /* The idea here is to actually to the drawing of the object. In fact,
  3627. when the DrawWndProc() recieves a WM_PAINT message, it will simply loop
  3628. through the graphics database, calling Draw_Graphic_Item(). For that
  3629. reason, we don't want to make any Windows API calls that may generate
  3630. a WM_PAINT message in the graphics window! */
  3631. static void FAR Draw_Graphic_Item(Graphics *item)
  3632. {
  3633. HBRUSH hBrush, hOldBrush;
  3634. HPEN hPen, hOldPen;
  3635. HFONT hFont, hOldFont;
  3636. POINT pTriPoints[3];
  3637. LPSTR pStr;
  3638. SIZE textSize;
  3639. int done, j, line, total, length, iPrevBackMode;
  3640.  
  3641. switch (item->obj_type)
  3642. {
  3643. case obj_pixel:
  3644. SetPixel(offscreen_DC,
  3645. gXCenter + item->g.pixel.p.x,
  3646. gYCenter - item->g.pixel.p.y,
  3647. gRGBColors[item->color]);
  3648. break;
  3649.  
  3650. case obj_line:
  3651. /* If we were using Windows NT, we could call ExtCreatePen,
  3652. which would allow for square endcaps of lines. Alas, we're
  3653. stuck with Windows 3.1, with round endcaps. Ah, well. */
  3654. hPen = CreatePen(PS_SOLID,
  3655. item->width,
  3656. gRGBColors[item->color]);
  3657. /* we want to hold on to the old pen to reset it
  3658. after we're done here */
  3659. hOldPen = SelectObject(offscreen_DC, hPen);
  3660.  
  3661.  
  3662. #ifdef WIN32
  3663. MoveToEx(offscreen_DC,
  3664. gXCenter + item->g.line.upper_left.x,
  3665. gYCenter - item->g.line.upper_left.y,
  3666. NULL);
  3667. #else
  3668. MoveTo(offscreen_DC,
  3669. gXCenter + item->g.line.upper_left.x,
  3670. gYCenter - item->g.line.upper_left.y);
  3671. #endif
  3672. LineTo(offscreen_DC,
  3673. gXCenter + item->g.line.lower_right.x,
  3674. gYCenter - item->g.line.lower_right.y);
  3675.  
  3676. SelectObject(offscreen_DC, hOldPen);
  3677. DeleteObject(hPen);
  3678. break;
  3679.  
  3680. case obj_triangle:
  3681. hPen = CreatePen(PS_SOLID,
  3682. item->width,
  3683. gRGBColors[item->color]);
  3684. hOldPen = SelectObject(offscreen_DC, hPen);
  3685.  
  3686. /* copy the triangle points into a different array */
  3687. pTriPoints[0].x = gXCenter + item->g.triangle.p1.x;
  3688. pTriPoints[0].y = gYCenter - item->g.triangle.p1.y;
  3689. pTriPoints[1].x = gXCenter + item->g.triangle.p2.x;
  3690. pTriPoints[1].y = gYCenter - item->g.triangle.p2.y;
  3691. pTriPoints[2].x = gXCenter + item->g.triangle.p3.x;
  3692. pTriPoints[2].y = gYCenter - item->g.triangle.p3.y;
  3693.  
  3694. if (item->width == 0)
  3695. hBrush = CreateSolidBrush(gRGBColors[item->color]);
  3696. else
  3697. hBrush = GetStockObject(HOLLOW_BRUSH);
  3698. hOldBrush = SelectObject(offscreen_DC, hBrush);
  3699.  
  3700. Polygon(offscreen_DC, pTriPoints, 3);
  3701.  
  3702. SelectObject(offscreen_DC, hOldPen);
  3703. SelectObject(offscreen_DC, hOldBrush);
  3704. DeleteObject(hPen);
  3705. DeleteObject(hBrush);
  3706. break;
  3707.  
  3708. case obj_rectangle:
  3709. hPen = CreatePen(PS_SOLID,
  3710. item->width,
  3711. gRGBColors[item->color]);
  3712. /* if width == 0, fill in rectangle */
  3713. if (item->width == 0)
  3714. hBrush = CreateSolidBrush(gRGBColors[item->color]);
  3715. else /* leave rectangle hollow */
  3716. hBrush = GetStockObject(HOLLOW_BRUSH);
  3717.  
  3718. hOldPen = SelectObject(offscreen_DC, hPen);
  3719. hOldBrush = SelectObject(offscreen_DC, hBrush);
  3720.  
  3721. /* Windows draws lines in a very odd fashion. Windows
  3722. will include the first endpoint when drawing a line, but
  3723. _exclude_ the next endpoint. I gather that this allows
  3724. for poly-lines, but very strange things happen when you
  3725. draw single lines this way. That is why we add 1 to the
  3726. ending x and y coords in the rectangle, oval, etc. */
  3727. Rectangle(offscreen_DC,
  3728. gXCenter + item->g.rectangle.upper_left.x,
  3729. gYCenter - item->g.rectangle.upper_left.y,
  3730. gXCenter + item->g.rectangle.lower_right.x+1,
  3731. gYCenter - item->g.rectangle.lower_right.y+1);
  3732.  
  3733. SelectObject(offscreen_DC, hOldPen);
  3734. SelectObject(offscreen_DC, hOldBrush);
  3735. DeleteObject(hPen);
  3736. DeleteObject(hBrush);
  3737. break;
  3738.  
  3739. case obj_oval:
  3740. hPen = CreatePen(PS_SOLID,
  3741. item->width,
  3742. gRGBColors[item->color]);
  3743. /* if width == 0, fill in rectangle */
  3744. if (item->width == 0)
  3745. hBrush = CreateSolidBrush(gRGBColors[item->color]);
  3746. else /* leave rectangle hollow */
  3747. hBrush = GetStockObject(HOLLOW_BRUSH);
  3748.  
  3749. hOldPen = SelectObject(offscreen_DC, hPen);
  3750. hOldBrush = SelectObject(offscreen_DC, hBrush);
  3751.  
  3752. Ellipse(offscreen_DC,
  3753. gXCenter + item->g.oval.upper_left.x,
  3754. gYCenter - item->g.oval.upper_left.y,
  3755. gXCenter + item->g.oval.lower_right.x+1,
  3756. gYCenter - item->g.oval.lower_right.y+1);
  3757.  
  3758. SelectObject(offscreen_DC, hOldPen);
  3759. SelectObject(offscreen_DC, hOldBrush);
  3760. DeleteObject(hPen);
  3761. DeleteObject(hBrush);
  3762. break;
  3763.  
  3764. case obj_text:
  3765. /* Text will be drawn on multiple lines, according to
  3766. where newline characters appear. */
  3767. /* Text is special in Windows. Text color is set with
  3768. a special function, as opposed to the current pen
  3769. color. Go figure! */
  3770. SetTextColor(offscreen_DC, gRGBColors[item->color]);
  3771. /* added by P. Schimpf, v 2.02*/
  3772. iPrevBackMode = GetBkMode(offscreen_DC) ;
  3773. SetBkMode(offscreen_DC, TRANSPARENT) ;
  3774.  
  3775. /* Windows gives us a default font, but the only way
  3776. to specify a particular point size is to create a
  3777. new font. */
  3778. /* the negative number indicates point size as opposed
  3779. to pixel size */
  3780. hFont = CreateFont(-item->g.text.ptsize,
  3781. 0, /* let Windows choose width */
  3782. 0, /* escapement, in 10ths of degrees */
  3783. 0, /* orientation, in 10ths of degrees */
  3784. FW_NORMAL, /* normal weight */
  3785. FALSE, /* no italic */
  3786. FALSE, /* no underline */
  3787. FALSE, /* no strikeout */
  3788. ANSI_CHARSET, /* use ANSI character set */
  3789. OUT_DEFAULT_PRECIS, /* output precision */
  3790. CLIP_DEFAULT_PRECIS, /* clip precision */
  3791. DEFAULT_QUALITY, /* quality */
  3792. DEFAULT_PITCH | FF_DONTCARE, /* pitch and family */
  3793. "GP142-font"); /* way-cool name of font */
  3794.  
  3795. hOldFont = SelectObject(offscreen_DC, hFont);
  3796.  
  3797. pStr = GlobalLock(item->g.text.hText);
  3798.  
  3799. /* To be compatible with the Mac, we want to bump the
  3800. text string 'up' by the height of the string */
  3801. GetTextExtentPoint(offscreen_DC,
  3802. pStr,
  3803. far_strlen(pStr),
  3804. &textSize);
  3805.  
  3806. #if 1
  3807. /* We want to honor newline characters in the string by
  3808. advancing the current line some height */
  3809.  
  3810. done = FALSE;
  3811. total = 0;
  3812. length = far_strlen(pStr);
  3813. line = 0;
  3814. while (done != TRUE)
  3815. {
  3816. for (j=0; pStr[total+j] != '\n' &&
  3817. pStr[total+j] != '\0' &&
  3818. total+j <= length; j++);
  3819. if (total+j >= length || pStr[total+j] == '\0')
  3820. done = TRUE;
  3821.  
  3822. TextOut(offscreen_DC,
  3823. gXCenter + item->g.text.p.x,
  3824. gYCenter - item->g.text.p.y +
  3825. (line-1)*textSize.cy,
  3826. pStr + total, j);
  3827.  
  3828. line++;
  3829. total += j+1;
  3830. }
  3831. #else
  3832. TextOut(offscreen_DC,
  3833. gXCenter + item->g.text.p.x,
  3834. gYCenter - item->g.text.p.y - textSize.cy,
  3835. pStr,
  3836. far_strlen(pStr));
  3837. #endif
  3838. GlobalUnlock(item->g.text.hText);
  3839.  
  3840. SetBkMode(offscreen_DC, iPrevBackMode) ;
  3841. SelectObject(offscreen_DC, hOldFont);
  3842. DeleteObject(hFont);
  3843. break;
  3844. }
  3845. need_redraw = 1;
  3846. }
  3847.  
  3848. #elif defined(X11R6)
  3849.  
  3850. static void Draw_Graphic_Item(Graphics *item) {
  3851.  
  3852. int j, total, line, length, done;
  3853. char *s;
  3854.  
  3855. if (current_color_id != item->color) {
  3856. XSetForeground(display, gc, color_ids[item->color].pixel);
  3857. current_color_id = item->color;
  3858. }
  3859.  
  3860. switch (item->obj_type)
  3861. {
  3862. case obj_pixel:
  3863. XDrawPoint(display, offscreen_buffer, gc,
  3864. gXCenter + item->g.pixel.p.x,
  3865. gYCenter - item->g.pixel.p.y);
  3866. break;
  3867.  
  3868. case obj_triangle:
  3869. XSetLineAttributes(display, gc, item->width, LineSolid,
  3870. CapRound, JoinRound);
  3871. if (item->width==0) {
  3872. XPoint points[3];
  3873. points[0].x = gXCenter+item->g.triangle.p1.x;
  3874. points[0].y = gYCenter-item->g.triangle.p1.y;
  3875. points[1].x = gXCenter+item->g.triangle.p2.x;
  3876. points[1].y = gYCenter-item->g.triangle.p2.y;
  3877. points[2].x = gXCenter+item->g.triangle.p3.x;
  3878. points[2].y = gYCenter-item->g.triangle.p3.y;
  3879. XFillPolygon(display, offscreen_buffer, gc, points, 3,
  3880. Convex, CoordModeOrigin);
  3881. }
  3882.  
  3883. else
  3884. XDrawLine(display, offscreen_buffer, gc,
  3885. gXCenter+item->g.triangle.p1.x,
  3886. gYCenter-item->g.triangle.p1.y,
  3887. gXCenter+item->g.triangle.p2.x,
  3888. gYCenter-item->g.triangle.p2.y);
  3889. XDrawLine(display, offscreen_buffer, gc,
  3890. gXCenter+item->g.triangle.p2.x,
  3891. gYCenter-item->g.triangle.p2.y,
  3892. gXCenter+item->g.triangle.p3.x,
  3893. gYCenter-item->g.triangle.p3.y);
  3894. XDrawLine(display, offscreen_buffer, gc,
  3895. gXCenter+item->g.triangle.p3.x,
  3896. gYCenter-item->g.triangle.p3.y,
  3897. gXCenter+item->g.triangle.p1.x,
  3898. gYCenter-item->g.triangle.p1.y);
  3899. break;
  3900.  
  3901.  
  3902. /* It's a conspiracy. The same problem with excluding the second
  3903. * (lower right) endpoint happens in X too for _filled rectangles_.
  3904. * Similar solution used, adding 1 to the height and width of the
  3905. * filled rectangle drawn. */
  3906.  
  3907. case obj_rectangle:
  3908. XSetLineAttributes(display, gc, item->width,
  3909. LineSolid, CapRound, JoinRound);
  3910. if (item->width==0)
  3911. XFillRectangle(display, offscreen_buffer, gc,
  3912. gXCenter+item->g.rectangle.upper_left.x,
  3913. gYCenter-item->g.rectangle.upper_left.y,
  3914. item->g.rectangle.lower_right.x
  3915. -item->g.rectangle.upper_left.x+1,
  3916. item->g.rectangle.upper_left.y
  3917. -item->g.rectangle.lower_right.y+1);
  3918. else
  3919. XDrawRectangle(display, offscreen_buffer, gc,
  3920. gXCenter+item->g.rectangle.upper_left.x,
  3921. gYCenter-item->g.rectangle.upper_left.y,
  3922. item->g.rectangle.lower_right.x
  3923. -item->g.rectangle.upper_left.x,
  3924. item->g.rectangle.upper_left.y
  3925. -item->g.rectangle.lower_right.y);
  3926. break;
  3927.  
  3928. case obj_line:
  3929. XSetLineAttributes(display, gc, item->width,
  3930. LineSolid, CapRound, JoinRound);
  3931. XDrawLine(display, offscreen_buffer, gc,
  3932. gXCenter+item->g.line.upper_left.x,
  3933. gYCenter-item->g.line.upper_left.y,
  3934. gXCenter+item->g.line.lower_right.x,
  3935. gYCenter-item->g.line.lower_right.y);
  3936. break;
  3937.  
  3938. case obj_oval:
  3939. XSetLineAttributes(display, gc, item->width, LineSolid,
  3940. CapRound, JoinRound);
  3941. if (item->width==0)
  3942. XFillArc(display, offscreen_buffer, gc,
  3943. gXCenter+item->g.oval.upper_left.x,
  3944. gYCenter-item->g.oval.upper_left.y,
  3945. item->g.oval.lower_right.x
  3946. -item->g.oval.upper_left.x,
  3947. item->g.oval.upper_left.y
  3948. -item->g.oval.lower_right.y,
  3949. 0, 23360);
  3950. else
  3951.  
  3952. /* The 23360 is 365 (degrees) * 64; the angles are signed ints
  3953. * in 64ths of a degree. I put 365 degrees for good measure -- it
  3954. * automatically truncates anything past 360. */
  3955.  
  3956. XDrawArc(display, offscreen_buffer, gc,
  3957. gXCenter+item->g.oval.upper_left.x,
  3958. gYCenter-item->g.oval.upper_left.y,
  3959. item->g.oval.lower_right.x
  3960. -item->g.oval.upper_left.x,
  3961. item->g.oval.upper_left.y
  3962. -item->g.oval.lower_right.y,
  3963. 0, 23360);
  3964. break;
  3965.  
  3966. case obj_text:
  3967.  
  3968. /* Check to see if the requested font is currently loaded;
  3969. * if not, search the list and point temp at it if it's there.
  3970. */
  3971.  
  3972. if (item->g.text.ptsize != current_font->point_size) {
  3973.  
  3974. FontDB *temp = font_info;
  3975.  
  3976. while (temp) {
  3977. if (item->g.text.ptsize == temp->point_size)
  3978. break;
  3979. temp = temp->next;
  3980. }
  3981.  
  3982. /* Or else add it to the list and load it. */
  3983.  
  3984. if (!temp) {
  3985. char fontname[100];
  3986. temp = (FontDB*) malloc(sizeof(FontDB));
  3987. sprintf(fontname, "-adobe-helvetica-medium-r-normal--0-%d-75-75-p-0-iso8859-1", item->g.text.ptsize * 10);
  3988. if ((temp == NULL) ||
  3989. (temp->thefont = XLoadQueryFont(display,
  3990. fontname)) == NULL) {
  3991. fprintf(stderr, "Cannot open Adobe scalable font.\n");
  3992. exit(0);
  3993. }
  3994.  
  3995. /* Set font to requested point size and put node at
  3996. * the head of the list. */
  3997.  
  3998. temp->point_size = item->g.text.ptsize;
  3999. temp->next = font_info;
  4000. font_info = temp;
  4001. }
  4002.  
  4003. /* Set gc to new point size */
  4004.  
  4005. XSetFont(display, gc, temp->thefont->fid);
  4006. current_font = temp;
  4007. }
  4008.  
  4009. /* We want to honor newline characters in the string by
  4010. advancing the current line some height */
  4011.  
  4012. line = 0, total = 0;
  4013. done = FALSE;
  4014. s = item->g.text.the_text;
  4015. length = strlen(s);
  4016. while (done != TRUE) {
  4017.  
  4018. for (j = 0; s[total + j] != '\n' && s[total + j] != '\0'
  4019. && total + j <= length; j++);
  4020.  
  4021. if (total + j >= length || s[total + j] == '\0')
  4022. done = TRUE;
  4023.  
  4024. XDrawString(display, offscreen_buffer, gc,
  4025. gXCenter+item->g.text.p.x,
  4026. gYCenter-item->g.text.p.y +
  4027. line*(current_font->thefont->ascent+
  4028. current_font->thefont->descent),
  4029. s+total ,j);
  4030. line++;
  4031. total += j + 1;
  4032. }
  4033. break;
  4034. }
  4035. need_redraw = 1;
  4036. }
  4037.  
  4038. #endif
  4039.  
  4040. /* Show or hide the GP142 text window - zives 6/19/98 */
  4041. void GP142_show_text(int showit)
  4042. {
  4043. #ifdef WINDOWS
  4044. ShowWindow(hTextWnd, (showit) ? SW_SHOW : SW_HIDE);
  4045. #else
  4046. showit = 0; /* HACK: kill compiler warnings */
  4047. #endif
  4048. }
Add Comment
Please, Sign In to add comment