Annotation of OpenXM_contrib/gnuplot/os2/gclient.c, Revision 1.1.1.1
1.1 maekawa 1: #ifdef INCRCSDATA
2: static char RCSid[]="$Id: gclient.c,v 1.15 1998/03/22 22:34:21 drd Exp $" ;
3: #endif
4:
5: /****************************************************************************
6:
7: PROGRAM: Gnupmdrv
8:
9: MODULE: gclient.c
10:
11: This file contains the client window procedures for Gnupmdrv
12:
13: ****************************************************************************/
14:
15: /* PM driver for GNUPLOT */
16:
17: /*[
18: * Copyright 1992, 1993, 1998 Roger Fearick
19: *
20: * Permission to use, copy, and distribute this software and its
21: * documentation for any purpose with or without fee is hereby granted,
22: * provided that the above copyright notice appear in all copies and
23: * that both that copyright notice and this permission notice appear
24: * in supporting documentation.
25: *
26: * Permission to modify the software is granted, but not the right to
27: * distribute the complete modified source code. Modifications are to
28: * be distributed as patches to the released version. Permission to
29: * distribute binaries produced by compiling modified sources is granted,
30: * provided you
31: * 1. distribute the corresponding source modifications from the
32: * released version in the form of a patch file along with the binaries,
33: * 2. add special version identification to distinguish your version
34: * in addition to the base release version number,
35: * 3. provide your name and address as the primary contact for the
36: * support of your modified version, and
37: * 4. retain our contact information in regard to use of the base
38: * software.
39: * Permission to distribute the released version of the source code along
40: * with corresponding source modifications in the form of a patch file is
41: * granted with same provisions 2 through 4 for binary distributions.
42: *
43: * This software is provided "as is" without express or implied warranty
44: * to the extent permitted by applicable law.
45: ]*/
46:
47: /*
48: * AUTHOR
49: *
50: * Gnuplot driver for OS/2: Roger Fearick
51: *
52: * Send your comments or suggestions to
53: * info-gnuplot@dartmouth.edu.
54: * This is a mailing list; to join it send a note to
55: * majordomo@dartmouth.edu.
56: * Send bug reports to
57: * bug-gnuplot@dartmouth.edu.
58: **/
59:
60: #define INCL_PM
61: #define INCL_WIN
62: #define INCL_SPL
63: #define INCL_SPLDOSPRINT
64: #define INCL_WINSTDFONT
65: #define INCL_DOSMEMMGR
66: #define INCL_DOSPROCESS
67: #define INCL_DOSERRORS
68: #define INCL_DOSFILEMGR
69: #define INCL_DOSNMPIPES
70: #define INCL_DOSSESMGR
71: #define INCL_DOSSEMAPHORES
72: #define INCL_DOSMISC
73: #define INCL_DOSQUEUES
74: #define INCL_WINSWITCHLIST
75: #include <os2.h>
76: #include <string.h>
77: #include <stdio.h>
78: #include <io.h>
79: #include <fcntl.h>
80: #include <math.h>
81: #include <stdlib.h>
82: #include <unistd.h>
83: #include <process.h>
84: #include <signal.h>
85: #include "gnupmdrv.h"
86:
87: /*==== g l o b a l d a t a ================================================*/
88:
89: extern char szIPCName[] ; /* name used in IPC with gnuplot */
90: extern char szIniFile[256] ; /* full path of ini file */
91: extern int bServer ;
92: extern int bPersist ;
93: extern int bEnhanced ;
94:
95: /*==== l o c a l d a t a ==================================================*/
96:
97: static long lLineTypes[7] = { LINETYPE_SOLID,
98: LINETYPE_SHORTDASH,
99: LINETYPE_DOT,
100: LINETYPE_DASHDOT,
101: LINETYPE_LONGDASH,
102: LINETYPE_DOUBLEDOT,
103: LINETYPE_DASHDOUBLEDOT } ;
104: static long lCols[16] = { CLR_BLACK,
105: CLR_DARKGRAY,
106: CLR_BLUE,
107: CLR_RED,
108: CLR_GREEN,
109: CLR_CYAN,
110: CLR_PINK,
111: CLR_YELLOW,
112: CLR_DARKBLUE,
113: CLR_DARKRED,
114: CLR_DARKGREEN,
115: CLR_DARKCYAN,
116: CLR_DARKPINK,
117: CLR_BROWN,
118: CLR_PALEGRAY,
119: CLR_WHITE } ;
120:
121: static LONG alColourTable[ 16 ] ;
122:
123: #define GNUBUF 1024 /* buffer for gnuplot commands */
124: #define PIPEBUF 4096 /* size of pipe buffers */
125: #define CMDALLOC 4096 /* command buffer allocation increment (ints) */
126: #define ENVSIZE 2048 /* size of environment */
127:
128: #define PAUSE_DLG 1 /* pause handled in dialog box */
129: #define PAUSE_BTN 2 /* pause handled by menu item */
130: #define PAUSE_GNU 3 /* pause handled by Gnuplot */
131:
132: #define DEFLW 50
133:
134: static ULONG ppidGnu=0L ; /* gnuplot pid */
135: static HPS hpsScreen ; /* screen pres. space */
136: static int iSeg = 1 ;
137:
138: static HSWITCH hSwitch = 0 ; /* switching between windows */
139: static SWCNTRL swGnu ;
140:
141: static BOOL bLineTypes = FALSE ; // true if use dashed linetypes
142: BOOL bWideLines ;
143: static BOOL bColours = TRUE ;
144: static BOOL bShellPos = FALSE ;
145: static BOOL bPlotPos = FALSE ;
146: static BOOL bPopFront = TRUE ;
147: static BOOL bNewFont = FALSE ;
148: static BOOL bHorz = TRUE ;
149:
150: static ULONG ulPlotPos[4] ;
151: static ULONG ulShellPos[4] ;
152: static PAUSEDATA pausedata = {sizeof(PAUSEDATA), NULL, NULL} ;
153: static char szFontNameSize[FONTBUF] ;
154: static PRQINFO3 infPrinter = { "" } ;
155: static QPRINT qPrintData = { sizeof(QPRINT), 0.0, 0.0, 1.0, 1.0, 0,
156: "", "", &infPrinter, 0, NULL } ;
157: //static HEV semStartSeq ; /* semaphore to start things in right sequence */
158: static HEV semPause ;
159: static HMTX semHpsAccess ;
160: static ULONG ulPauseReply = 1 ;
161: static ULONG ulPauseMode = PAUSE_DLG ;
162:
163: static HWND hSysMenu ;
164: /* stuff for screen-draw thread control */
165:
166: static BOOL bExist ;
167: //static HEV semDrawDone ;
168:
169: /* thread control */
170:
171: static TID tidDraw, tidSpawn ;
172:
173: /* font data */
174:
175: static int lSupOffset = 0 ;
176: static int lSubOffset = 0 ;
177: static int lBaseSupOffset = 0 ;
178: static int lBaseSubOffset = 0 ;
179: static int lCharWidth = 217 ;
180: static int lCharHeight = 465 ;
181:
182:
183: /*==== f u n c t i o n s =====================================================*/
184:
185: int DoPrint( HWND ) ;
186: HBITMAP CopyToBitmap( HPS ) ;
187: HMF CopyToMetaFile( HPS ) ;
188: MRESULT WmClientCmdProc( HWND , ULONG, MPARAM, MPARAM ) ;
189: void ChangeCheck( HWND, USHORT, USHORT ) ;
190: BOOL QueryIni( HAB ) ;
191: static void SaveIni( HWND ) ;
192: static void ThreadDraw( void* ) ;
193: static void DoPaint( HWND, HPS ) ;
194: static void Display( HPS ) ;
195: void SelectFont( HPS, char * );
196: void SwapFont( HPS, char * );
197: static void CopyToClipBrd( HWND ) ;
198: static void ReadGnu( void* ) ;
199: static void EditLineTypes( HWND, HPS, BOOL ) ;
200: static void EditCharCell( HPS, SIZEF* ) ;
201: static HPS InitScreenPS( void ) ;
202: static int BufRead( HFILE, void*, int, PULONG ) ;
203: int GetNewFont( HWND, HPS ) ;
204: void SigHandler( int ) ;
205: void FontExpand( char * ) ;
206: static char *ParseText(HPS, char *, BOOL, char *,
207: int, int, BOOL, BOOL ) ;
208: static void CharStringAt(HPS, int, int, int, char *) ;
209: static int QueryTextBox( HPS, int, char * ) ;
210: static void LMove( HPS hps, POINTL *p ) ;
211: static void LLine( HPS hps, POINTL *p ) ;
212: static void LType( int iType ) ;
213:
214: /*==== c o d e ===============================================================*/
215:
216: MRESULT EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
217: /*
218: ** Window proc for main window
219: ** -- passes most stuff to active child window via WmClientCmdProc
220: ** -- passes DDE messages to DDEProc
221: */
222: {
223: static BOOL bSw = FALSE ;
224: static BOOL bFirst = TRUE ;
225: static RECTL rectlPaint = { 0, 0, 0, 0 } ;
226: static int iPaintCount = 0 ;
227: static int firstcall = 1 ;
228:
229: switch (message) {
230:
231: case WM_CREATE:
232: {
233: HDC hdcScreen ;
234: SIZEL sizlPage ;
235: // set initial values
236: ChangeCheck( hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0 ) ;
237: ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
238: ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
239: ChangeCheck( hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0 ) ;
240: // disable close from system menu (close only from gnuplot)
241: hApp = WinQueryWindow( hWnd, QW_PARENT ) ; /* temporary assignment.. */
242: hSysMenu = WinWindowFromID( hApp, FID_SYSMENU ) ;
243: // setup semaphores
244: // DosCreateEventSem( NULL, &semDrawDone, 0L, 0L ) ;
245: // DosCreateEventSem( NULL, &semStartSeq, 0L, 0L ) ;
246: DosCreateEventSem( NULL, &semPause, 0L, 0L ) ;
247: DosCreateMutexSem( NULL, &semHpsAccess, 0L, 1L ) ;
248: bExist = TRUE ;
249: // create a dc and hps to draw on the screen
250: hdcScreen = WinOpenWindowDC( hWnd ) ;
251: sizlPage.cx = 0 ; sizlPage.cy = 0 ;
252: sizlPage.cx = 19500 ; sizlPage.cy = 12500 ;
253: hpsScreen = GpiCreatePS( hab, hdcScreen, &sizlPage,
254: PU_HIMETRIC|GPIT_NORMAL|GPIA_ASSOC) ;
255: // spawn server for GNUPLOT ...
256: tidSpawn = _beginthread( ReadGnu, NULL, 32768, NULL ) ;
257: }
258: break ;
259:
260: case WM_GPSTART:
261:
262: // get details of command-line window
263: hSwitch = WinQuerySwitchHandle( 0, ppidGnu ) ;
264: WinQuerySwitchEntry( hSwitch, &swGnu ) ;
265: if( firstcall ) {
266: // set size of this window
267: WinSetWindowPos( WinQueryWindow( hWnd, QW_PARENT ),
268: bPopFront?HWND_TOP:swGnu.hwnd,
269: ulShellPos[0],
270: ulShellPos[1],
271: ulShellPos[2],
272: ulShellPos[3],
273: bShellPos?(bPopFront?SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ACTIVATE
274: :SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ZORDER)
275: :(bPopFront?SWP_SHOW|SWP_ACTIVATE:SWP_SHOW|SWP_ZORDER) ) ;
276: signal( SIGTERM, SigHandler ) ;
277: firstcall = 0 ;
278: }
279: if( !bPopFront ) WinSwitchToProgram( hSwitch ) ;
280: // DosPostEventSem( semDrawDone ) ;
281: DosReleaseMutexSem( semHpsAccess ) ;
282: return 0 ;
283:
284: case WM_COMMAND:
285:
286: return WmClientCmdProc( hWnd , message , mp1 , mp2 ) ;
287:
288: case WM_CHAR:
289: /* If the user types a command in the driver window,
290: we route it to the gnuplot window and switch that
291: to the front. Doesn't work for full-screen
292: sessions, though (but does switch). */
293: {
294: USHORT usFlag ;
295: usFlag = SHORT1FROMMP( mp1 ) ;
296: if( !(usFlag & (KC_KEYUP|KC_ALT|KC_CTRL)) ) {
297: USHORT uc = SHORT1FROMMP( mp2 ) ;
298: HWND hw = WinQueryWindow( swGnu.hwnd, QW_BOTTOM ) ;
299: WinSetFocus( HWND_DESKTOP, hw ) ;
300: WinSendMsg( hw, message,
301: MPFROM2SHORT((USHORT)(KC_SCANCODE), 1),
302: MPFROMSHORT(uc) ) ;
303: WinSwitchToProgram( hSwitch ) ;
304: }
305: }
306: break ;
307:
308: case WM_DESTROY:
309:
310: if( WinSendMsg( hWnd, WM_USER_PRINT_QBUSY, 0L, 0L ) != 0L ) {
311: WinMessageBox( HWND_DESKTOP,
312: hWnd,
313: "Still printing - not closed",
314: APP_NAME,
315: 0,
316: MB_OK | MB_ICONEXCLAMATION ) ;
317: return 0L ;
318: }
319: return (WinDefWindowProc(hWnd, message, mp1, mp2));
320:
321: case WM_PAINT:
322: {
323: ULONG ulCount ;
324: PID pid; TID tid;
325: HPS hps_tmp;
326: RECTL rectl_tmp;
327: DosQueryMutexSem( semHpsAccess, &pid, &tid, &ulCount ) ;
328: if (( ulCount > 0 ) && (tid != tidDraw)) {
329: /* simple repaint while building plot or metafile */
330: /* use temporary PS */
331: hps_tmp = WinBeginPaint(hWnd,0,&rectl_tmp );
332: WinFillRect(hps_tmp,&rectl_tmp,CLR_BACKGROUND);
333: WinEndPaint(hps_tmp);
334: /* add dirty rectangle to saved rectangle */
335: /* to be repainted when PS is available again */
336: WinUnionRect(hab,&rectlPaint,&rectl_tmp,&rectlPaint);
337: iPaintCount ++ ;
338: break ;
339: }
340: WinInvalidateRect( hWnd, &rectlPaint, TRUE ) ;
341: DoPaint( hWnd, hpsScreen ) ;
342: WinSetRectEmpty( hab, &rectlPaint ) ;
343: }
344: break ;
345:
346: case WM_SIZE :
347:
348: {
349: WinInvalidateRect( hWnd, NULL, TRUE ) ;
350: }
351: break ;
352:
353: case WM_PRESPARAMCHANGED:
354: {
355: char *pp ;
356: ULONG ulID ;
357: pp = malloc(FONTBUF) ;
358: if( WinQueryPresParam( hWnd,
359: PP_FONTNAMESIZE,
360: 0,
361: &ulID,
362: FONTBUF,
363: pp,
364: QPF_NOINHERIT ) != 0L ) {
365: strcpy( szFontNameSize, pp ) ;
366: bNewFont = TRUE ;
367: WinInvalidateRect( hWnd, NULL, TRUE ) ;
368: }
369: free(pp) ;
370: }
371: break ;
372:
373: case WM_USER_PRINT_BEGIN:
374: case WM_USER_PRINT_OK :
375: case WM_USER_DEV_ERROR :
376: case WM_USER_PRINT_ERROR :
377: case WM_USER_PRINT_QBUSY :
378:
379: return( PrintCmdProc( hWnd, message, mp1, mp2 ) ) ;
380:
381: case WM_GNUPLOT:
382: // display the plot
383: if( bPopFront )
384: WinSetWindowPos( hwndFrame, HWND_TOP, 0,0,0,0, SWP_ACTIVATE|SWP_ZORDER ) ;
385: if( iPaintCount > 0 ) { /* if outstanding paint messages, repaint */
386: WinInvalidateRect( hWnd, &rectlPaint, TRUE ) ;
387: iPaintCount = 0 ;
388: }
389: return 0L ;
390:
391: case WM_PAUSEPLOT:
392: /* put pause message on screen, or enable 'continue' button */
393: if( ulPauseMode == PAUSE_DLG ) {
394: pausedata.pszMessage = (char*)mp1 ;
395: WinLoadDlg( HWND_DESKTOP,
396: hWnd,
397: (PFNWP)PauseMsgDlgProc,
398: 0L,
399: IDD_PAUSEBOX,
400: &pausedata ) ;
401: }
402: else {
403: WinEnableMenuItem( WinWindowFromID(
404: WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
405: IDM_CONTINUE,
406: TRUE ) ;
407: }
408: return 0L ;
409:
410: case WM_PAUSEEND:
411: /* resume plotting */
412: ulPauseReply = (ULONG) mp1 ;
413: DosPostEventSem( semPause ) ;
414: return 0L ;
415:
416: default: /* Passes it on if unproccessed */
417: return (WinDefWindowProc(hWnd, message, mp1, mp2));
418: }
419: return (NULL);
420: }
421:
422: MRESULT WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
423: /*
424: ** Handle client window command (menu) messages
425: */
426: {
427: extern HWND hApp ;
428: static ulPauseItem = IDM_PAUSEDLG ;
429:
430: switch( (USHORT) SHORT1FROMMP( mp1 ) ) {
431:
432: case IDM_ABOUT : /* show the 'About' box */
433:
434: WinDlgBox( HWND_DESKTOP,
435: hWnd ,
436: (PFNWP)About ,
437: 0L,
438: ID_ABOUT,
439: NULL ) ;
440: break ;
441:
442:
443: case IDM_GPLOTINF: /* view gnuplot.inf */
444: {
445: char path[256] ;
446: char *p ;
447: strcpy( path, "start view " ) ;
448: if( (p=getenv("GNUPLOT")) != NULL ) {
449: strcat( path, p ) ;
450: strcat( path, "/" ) ;
451: }
452: strcat( path, "gnuplot" ) ;
453: system( path ) ;
454: }
455: break ;
456:
457: case IDM_PRINT : /* print plot */
458:
459: if( SetupPrinter( hWnd, &qPrintData ) ) {
460: WinPostMsg( hWnd,
461: WM_USER_PRINT_BEGIN,
462: (MPARAM) &qPrintData,
463: (MPARAM) hpsScreen ) ;
464: }
465: break ;
466:
467: case IDM_PRINTSETUP : /* select printer */
468:
469: WinDlgBox( HWND_DESKTOP,
470: hWnd ,
471: (PFNWP)QPrintersDlgProc,
472: 0L,
473: IDD_QUERYPRINT,
474: qPrintData.szPrinterName ) ;
475: break ;
476:
477: case IDM_LINES_THICK:
478: // change line setting
479: bWideLines = !bWideLines ;
480: ChangeCheck( hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0 ) ;
481: WinInvalidateRect( hWnd, NULL, TRUE ) ;
482: break ;
483:
484: case IDM_LINES_SOLID:
485: // change line setting
486: bLineTypes = !bLineTypes ;
487: ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
488: EditLineTypes( hWnd, hpsScreen, bLineTypes ) ;
489: WinInvalidateRect( hWnd, NULL, TRUE ) ;
490: break ;
491:
492: case IDM_COLOURS:
493: // change colour setting
494: bColours = !bColours ;
495: ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
496: WinInvalidateRect( hWnd, NULL, TRUE ) ;
497: break ;
498:
499: case IDM_FRONT:
500: /* toggle z-order forcing */
501: bPopFront = !bPopFront ;
502: ChangeCheck( hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0 ) ;
503: break ;
504:
505: case IDM_FONTS:
506:
507: if( GetNewFont( hWnd, hpsScreen ) ) {
508: bNewFont = TRUE ;
509: WinInvalidateRect( hWnd, NULL, TRUE ) ;
510: }
511: break ;
512:
513: case IDM_SAVE :
514: SaveIni( hWnd ) ;
515: break ;
516:
517: case IDM_COPY : /* copy to clipboard */
518: if( WinOpenClipbrd( hab ) ) {
519: CopyToClipBrd( hWnd ) ;
520: }
521: else {
522: WinMessageBox( HWND_DESKTOP,
523: hWnd,
524: "Can't open clipboard",
525: APP_NAME,
526: 0,
527: MB_OK | MB_ICONEXCLAMATION ) ;
528: }
529: break ;
530:
531: case IDM_CLEARCLIP : /* clear clipboard */
532: if( WinOpenClipbrd( hab ) ) {
533: WinEmptyClipbrd( hab ) ;
534: WinCloseClipbrd( hab ) ;
535: }
536: else {
537: WinMessageBox( HWND_DESKTOP,
538: hWnd,
539: "Can't open clipboard",
540: APP_NAME,
541: 0,
542: MB_OK | MB_ICONEXCLAMATION ) ;
543: }
544: break ;
545:
546: case IDM_COMMAND: /* go back to GNUPLOT command window */
547: WinSwitchToProgram( hSwitch ) ;
548: break ;
549:
550: case IDM_CONTINUE:
551: WinPostMsg( hWnd, WM_PAUSEEND, (MPARAM)1L, (MPARAM)0L ) ;
552: WinEnableMenuItem( WinWindowFromID(
553: WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
554: IDM_CONTINUE,
555: FALSE ) ;
556: break ;
557:
558: case IDM_PAUSEGNU: /* gnuplot handles pause */
559: ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEGNU ) ;
560: ulPauseItem = IDM_PAUSEGNU ;
561: ulPauseMode = PAUSE_GNU ;
562: break ;
563:
564: case IDM_PAUSEDLG: /* pause message in dlg box */
565: ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEDLG ) ;
566: ulPauseItem = IDM_PAUSEDLG ;
567: ulPauseMode = PAUSE_DLG ;
568: break ;
569:
570: case IDM_PAUSEBTN: /* pause uses menu button, no message */
571: ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEBTN ) ;
572: ulPauseItem = IDM_PAUSEBTN ;
573: ulPauseMode = PAUSE_BTN ;
574: break ;
575:
576: case IDM_HELPFORHELP:
577: WinSendMsg(WinQueryHelpInstance(hWnd),
578: HM_DISPLAY_HELP, 0L, 0L ) ;
579: return 0L ;
580:
581: case IDM_EXTENDEDHELP:
582: WinSendMsg(WinQueryHelpInstance(hWnd),
583: HM_EXT_HELP, 0L, 0L);
584: return 0L ;
585:
586: case IDM_KEYSHELP:
587: WinSendMsg(WinQueryHelpInstance(hWnd),
588: HM_KEYS_HELP, 0L, 0L);
589: return 0L ;
590:
591: case IDM_HELPINDEX:
592: WinSendMsg(WinQueryHelpInstance(hWnd),
593: HM_HELP_INDEX, 0L, 0L);
594: return 0L ;
595:
596: default :
597:
598: return WinDefWindowProc( hWnd, message, mp1, mp2 ) ;
599:
600: }
601: return( NULL ) ;
602: }
603:
604: void ChangeCheck( HWND hWnd , USHORT wItem1 , USHORT wItem2 )
605: /*
606: ** Utility function:
607: **
608: ** move check mark from menu item 1 to item 2
609: */
610: {
611: HWND hMenu ;
612:
613: hMenu = WinWindowFromID( WinQueryWindow( hWnd, QW_PARENT ),
614: FID_MENU ) ;
615: if( wItem1 != 0 )
616: WinSendMsg( hMenu,
617: MM_SETITEMATTR,
618: MPFROM2SHORT( wItem1, TRUE ),
619: MPFROM2SHORT( MIA_CHECKED, 0 ) ) ;
620: if( wItem2 != 0 )
621: WinSendMsg( hMenu,
622: MM_SETITEMATTR,
623: MPFROM2SHORT( wItem2, TRUE ),
624: MPFROM2SHORT( MIA_CHECKED, MIA_CHECKED ) ) ;
625: }
626:
627: static void CopyToClipBrd( HWND hWnd )
628: /*
629: ** Copy window to clipboard as bitmap.
630: */
631: {
632: HAB hab ;
633: HBITMAP hbm ;
634: HMF hmf ;
635:
636: hab = WinQueryAnchorBlock( hWnd ) ;
637: WinEmptyClipbrd( hab ) ;
638: hbm = CopyToBitmap( hpsScreen ) ;
639: WinSetClipbrdData( hab, (ULONG) hbm, CF_BITMAP, CFI_HANDLE) ;
640: hmf = CopyToMetaFile( hpsScreen ) ;
641: WinSetClipbrdData( hab, (ULONG) hmf, CF_METAFILE, CFI_HANDLE) ;
642: WinCloseClipbrd( hab ) ;
643: }
644:
645: HBITMAP CopyToBitmap( HPS hps )
646: /*
647: ** Copy ps to a bitmap.
648: */
649: {
650: HPS hpsMem ;
651: HWND hwnd ;
652: HAB hab ;
653: PSZ psz[4] = {NULL,"Display",NULL,NULL} ;
654: HDC hdcMem, hdcScr ;
655: SIZEL sizel ;
656: BITMAPINFOHEADER2 bmp ;
657: PBITMAPINFO2 pbmi ;
658: HBITMAP hbm ;
659: BYTE abBmp[80] ;
660: LONG alData[2] ;
661: RECTL rectl ;
662: POINTL aptl[6] ;
663: HMF hmf ;
664:
665: hdcScr = GpiQueryDevice( hps ) ;
666: hwnd = WinWindowFromDC( hdcScr ) ;
667: hab = WinQueryAnchorBlock( hwnd ) ;
668: hdcMem = DevOpenDC( hab,
669: OD_MEMORY,
670: "*",
671: 4L,
672: (PDEVOPENDATA) psz,
673: hdcScr ) ;
674: sizel.cx = 0/*GNUPAGE*/ ; sizel.cy = 0/*GNUPAGE*/ ;
675: hpsMem = GpiCreatePS( hab, hdcMem, &sizel, PU_PELS|GPIA_ASSOC|GPIT_MICRO ) ;
676: GpiQueryDeviceBitmapFormats( hpsMem, 2L, alData ) ;
677: WinQueryWindowRect( hwnd, &rectl ) ;
678: memset( &bmp, 0, sizeof(bmp) ) ;
679: bmp.cbFix = (ULONG) sizeof( bmp ) ;
680: bmp.cx = (SHORT) (rectl.xRight-rectl.xLeft) ;
681: bmp.cy = (SHORT) (rectl.yTop-rectl.yBottom) ;
682: bmp.cPlanes = alData[0] ;
683: bmp.cBitCount = alData[1] ;
684: hbm = GpiCreateBitmap( hpsMem, &bmp, 0, NULL, NULL ) ;
685: GpiSetBitmap( hpsMem, hbm ) ;
686: aptl[0].x = 0 ; aptl[0].y = 0 ;
687: aptl[1].x = (LONG)bmp.cx ; aptl[1].y = (LONG)bmp.cy ;
688: aptl[2].x = 0 ; aptl[2].y = 0 ;
689: GpiBitBlt( hpsMem, hps, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE ) ;
690: GpiDestroyPS( hpsMem ) ;
691: DevCloseDC( hdcMem ) ;
692: return hbm ;
693: }
694:
695: HMF CopyToMetaFile( HPS hps )
696: /*
697: ** Copy ps to a mteafile.
698: */
699: {
700: HDC hdcMF, hdcOld ;
701: HAB hab ;
702: HWND hwnd ;
703: PSZ psz[4] = {NULL,"Display",NULL,NULL} ;
704: HMF hmf ;
705: hdcOld = GpiQueryDevice( hps ) ;
706: hwnd = WinWindowFromDC( hdcOld ) ;
707: hab = WinQueryAnchorBlock( hwnd ) ;
708: hdcMF = DevOpenDC( hab, OD_METAFILE, "*", 4L, psz, hdcOld ) ;
709: DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
710: GpiSetDrawingMode( hps, DM_DRAW ) ;
711: GpiAssociate( hps, 0 ) ;
712: GpiAssociate( hps, hdcMF ) ;
713: ScalePS( hps ) ;
714: GpiDrawChain( hps ) ;
715: GpiAssociate( hps, 0 ) ;
716: GpiAssociate( hps, hdcOld ) ;
717: DosReleaseMutexSem( semHpsAccess ) ;
718: hmf = DevCloseDC( hdcMF ) ;
719: return hmf ;
720: }
721:
722: BOOL QueryIni( HAB hab )
723: /*
724: ** Query INI file
725: */
726: {
727: BOOL bPos, bData, bSwp ;
728: ULONG ulOpts[5] ;
729: HINI hini ;
730: ULONG ulCB ;
731: char *p ;
732: static SWP pauseswp ;
733:
734: // read gnuplot ini file
735:
736: hini = PrfOpenProfile( hab, szIniFile ) ;
737: ulCB = sizeof( ulShellPos ) ;
738: bPos = PrfQueryProfileData( hini, APP_NAME, INISHELLPOS, &ulShellPos, &ulCB ) ;
739: ulCB = sizeof( SWP ) ;
740: bSwp = PrfQueryProfileData( hini, APP_NAME, INIPAUSEPOS, &pauseswp, &ulCB ) ;
741: if( bSwp ) pausedata.pswp = &pauseswp ;
742: ulCB = sizeof( ulOpts ) ;
743: bData = PrfQueryProfileData( hini, APP_NAME, INIOPTS, &ulOpts, &ulCB ) ;
744: if( bData ) {
745: bLineTypes = (BOOL)ulOpts[0] ;
746: bWideLines = (BOOL)ulOpts[1] ;
747: bColours = (BOOL)ulOpts[2] ;
748: ulPauseMode = ulOpts[3] ;
749: bPopFront = (BOOL)ulOpts[4] ;
750: }
751: else {
752: bLineTypes = FALSE ; /* default values */
753: /* bWideLines = FALSE ; */
754: bColours = TRUE ;
755: bPopFront = TRUE ;
756: ulPauseMode = 1 ;
757: }
758: ulCB = 4*sizeof(float) ;
759: PrfQueryProfileData( hini, APP_NAME, INIFRAC, &qPrintData.xsize, &ulCB ) ;
760: if( PrfQueryProfileSize( hini, APP_NAME, INIPRDRIV, &ulCB ) ) {
761: PDRIVDATA pdriv = (PDRIVDATA) malloc( ulCB ) ;
762: if( pdriv != NULL ) {
763: PrfQueryProfileData( hini, APP_NAME, INIPRDRIV, pdriv, &ulCB ) ;
764: qPrintData.pdriv = pdriv ;
765: qPrintData.cbpdriv = ulCB ;
766: }
767: }
768: PrfQueryProfileString( hini, APP_NAME, INIPRPR, "",
769: qPrintData.szPrinterName,
770: (long) sizeof qPrintData.szPrinterName ) ;
771: PrfQueryProfileString( hini, APP_NAME, INIFONT, INITIAL_FONT,
772: szFontNameSize, FONTBUF ) ;
773: ulCB = sizeof( ulOpts ) ;
774: bData = PrfQueryProfileData( hini, APP_NAME, INICHAR, &ulOpts, &ulCB ) ;
775: if( bData ) {
776: lCharWidth = ulOpts[0] ;
777: lCharHeight = ulOpts[1] ;
778: }
779: else {
780: lCharWidth = 217 ;
781: lCharHeight = 465 ;
782: }
783: PrfCloseProfile( hini ) ;
784:
785: if( qPrintData.szPrinterName[0] == '\0' ) {
786: // get default printer name
787: PrfQueryProfileString( HINI_PROFILE,
788: "PM_SPOOLER",
789: "PRINTER",
790: ";",
791: qPrintData.szPrinterName,
792: (long) sizeof qPrintData.szPrinterName ) ;
793: if( (p=strchr( qPrintData.szPrinterName, ';' )) != NULL ) *p = '\0' ;
794: }
795: bShellPos = bPos ;
796: return bPos ;
797: }
798:
799: static void SaveIni( HWND hWnd )
800: /*
801: ** save data in ini file
802: */
803: {
804: SWP swp ;
805: HINI hini ;
806: ULONG ulOpts[5] ;
807: HFILE hfile ;
808: ULONG ulAct ;
809: ERRORID errid ;
810: char achErr[64] ;
811: HAB hab ;
812:
813: hab = WinQueryAnchorBlock( hWnd ) ;
814: hini = PrfOpenProfile( hab, szIniFile ) ;
815: if( hini != NULLHANDLE ) {
816: WinQueryWindowPos( hwndFrame, &swp ) ;
817: ulPlotPos[0] = swp.x ;
818: ulPlotPos[1] = swp.y ;
819: ulPlotPos[2] = swp.cx ;
820: ulPlotPos[3] = swp.cy ;
821: PrfWriteProfileData( hini, APP_NAME, INISHELLPOS, &ulPlotPos, sizeof(ulPlotPos) ) ;
822: if( pausedata.pswp != NULL )
823: PrfWriteProfileData( hini, APP_NAME, INIPAUSEPOS,
824: pausedata.pswp, sizeof(SWP) ) ;
825: ulOpts[0] = (ULONG)bLineTypes ;
826: ulOpts[1] = (ULONG)bWideLines ;
827: ulOpts[2] = (ULONG)bColours ;
828: ulOpts[3] = ulPauseMode ;
829: ulOpts[4] = (ULONG)bPopFront ;
830: PrfWriteProfileData( hini, APP_NAME, INIOPTS, &ulOpts, sizeof(ulOpts) ) ;
831: PrfWriteProfileData( hini, APP_NAME, INIFRAC, &qPrintData.xsize, 4*sizeof(float) ) ;
832: if( qPrintData.pdriv != NULL )
833: PrfWriteProfileData( hini, APP_NAME, INIPRDRIV, qPrintData.pdriv,
834: qPrintData.cbpdriv ) ;
835: PrfWriteProfileString( hini, APP_NAME, INIPRPR,
836: qPrintData.szPrinterName[0] == '\0'? NULL:
837: qPrintData.szPrinterName ) ;
838: PrfWriteProfileString( hini, APP_NAME, INIFONT, szFontNameSize ) ;
839: ulOpts[0] = (ULONG)lCharWidth ;
840: ulOpts[1] = (ULONG)lCharHeight ;
841: PrfWriteProfileData( hini, APP_NAME, INICHAR, &ulOpts, sizeof(ulOpts) ) ;
842: PrfCloseProfile( hini ) ;
843: }
844: else {
845: WinMessageBox( HWND_DESKTOP,
846: HWND_DESKTOP,
847: "Can't write ini file",
848: APP_NAME,
849: 0,
850: MB_OK | MB_ICONEXCLAMATION ) ;
851: }
852: }
853:
854: static void DoPaint( HWND hWnd, HPS hps )
855: /*
856: ** Paint the screen with current data
857: */
858: {
859: ULONG ulCount ;
860:
861: static RECTL rectl ;
862: if( tidDraw != 0 ) {
863: /* already drawing - stop it; include the rectl now
864: being drawn in, in the update region; and return
865: without calling beginpaint so that the paint
866: message is resent */
867: GpiSetStopDraw( hpsScreen, SDW_ON ) ;
868: DosSleep(1) ;
869: WinInvalidateRect( hWnd, &rectl, TRUE ) ;
870: return ;
871: }
872: /* winbeginpaint here, so paint message is
873: not resent when we return, then spawn a
874: thread to do the drawing */
875: WinBeginPaint( hWnd, hps, &rectl ) ; //rl
876: tidDraw = _beginthread( ThreadDraw, NULL, 32768, NULL ) ;
877: }
878:
879: static void ThreadDraw( void* arg )
880: /*
881: ** Thread to draw plot on screen
882: */
883: {
884: HAB hab ;
885:
886: hab = WinInitialize( 0 ) ;
887:
888: InitScreenPS() ;
889:
890: DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
891: ScalePS( hpsScreen ) ;
892: GpiSetStopDraw( hpsScreen, SDW_OFF ) ;
893: GpiSetDrawingMode( hpsScreen, DM_DRAW ) ;
894: GpiDrawChain( hpsScreen ) ;
895: WinEndPaint( hpsScreen ) ;
896: DosReleaseMutexSem( semHpsAccess ) ;
897: WinTerminate( hab ) ;
898: tidDraw = 0 ;
899: }
900:
901: HPS InitScreenPS()
902: /*
903: ** Initialise the screen ps for drawing
904: */
905: {
906: RECTL rectClient ;
907: int nColour = 0 ;
908:
909: GpiResetPS( hpsScreen, GRES_ATTRS ) ;
910: GpiErase(hpsScreen);
911:
912: WinQueryWindowRect( hApp, (PRECTL)&rectClient ) ;
913: {
914: double ratio = 1.560 ;
915: double xs = rectClient.xRight - rectClient.xLeft ;
916: double ys = rectClient.yTop - rectClient.yBottom ;
917: if( ys > xs/ratio ) { /* reduce ys to fit */
918: rectClient.yTop = rectClient.yBottom + (int)(xs/ratio) ;
919: }
920: else if( ys < xs/ratio ) { /* reduce xs to fit */
921: rectClient.xRight = rectClient.xLeft + (int)(ys*ratio) ;
922: }
923: }
924:
925: GpiSetPageViewport( hpsScreen, &rectClient ) ;
926: if( !bColours ) {
927: int i ;
928: for( i=0; i<8; i++ ) alColourTable[i] = 0 ;
929: for( i=8; i<16; i++ ) alColourTable[i] = 0 ;
930: alColourTable[0] = 0xFFFFFF ;
931: nColour = 16 ;
932: }
933: GpiCreateLogColorTable( hpsScreen,
934: LCOL_RESET,
935: LCOLF_CONSECRGB,
936: 0, nColour, alColourTable ) ;
937: return hpsScreen ;
938: }
939:
940: enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode;
941:
942:
943: short ScalePS( HPS hps )
944: /*
945: ** Get a font to use
946: ** Scale the plot area to world coords for subsequent plotting
947: */
948: {
949: RECTL rectView ;
950:
951: SelectFont( hps, szFontNameSize ) ;
952: return 0 ;
953: }
954:
955: static SIZEF sizBaseSubSup ;
956: static SIZEF sizCurSubSup ;
957: static SIZEF sizCurFont ;
958: static long lVOffset = 0 ;
959: static SIZEF sizBaseFont ;
960: static struct _ft {
961: char *name ;
962: LONG lcid ;
963: } tabFont[256] = {{NULL,0L}, {NULL}};
964:
965: void SelectFont( HPS hps, char *szFontNameSize )
966: /*
967: ** Select a named and sized outline (adobe) font
968: */
969: {
970: HDC hdc ;
971: FATTRS fat ;
972: LONG xDeviceRes, yDeviceRes ;
973: POINTL ptlFont ;
974: SIZEF sizfx ;
975: static LONG lcid = 0L ;
976: static char *szFontName ;
977: static short shPointSize ;
978:
979: sscanf( szFontNameSize, "%hd", &shPointSize ) ;
980: szFontName = strchr( szFontNameSize, '.' ) + 1 ;
981:
982: fat.usRecordLength = sizeof fat ;
983: fat.fsSelection = 0 ;
984: fat.lMatch = 0 ;
985: fat.idRegistry = 0 ;
986: fat.usCodePage = 0 ; //GpiQueryCp (hps) ;
987: fat.lMaxBaselineExt = 0 ;
988: fat.lAveCharWidth = 0 ;
989: fat.fsType = 0 ;
990: fat.fsFontUse = FATTR_FONTUSE_OUTLINE |
991: FATTR_FONTUSE_TRANSFORMABLE ;
992:
993: strcpy (fat.szFacename, szFontName) ;
994:
995: if(tabFont[0].name !=NULL) free( tabFont[0].name ) ;
996: tabFont[0].name = strdup( szFontName ) ;
997: tabFont[0].lcid = 10L ;
998:
999: lcid = GpiQueryCharSet( hps ) ;
1000: if( lcid != 10L ) lcid = 10L ;
1001: else {
1002: GpiSetCharSet( hps, 0L) ;
1003: GpiDeleteSetId( hps, lcid ) ;
1004: }
1005: GpiCreateLogFont (hps, NULL, lcid, &fat) ;
1006: GpiSetCharSet( hps, lcid ) ;
1007:
1008: hdc = GpiQueryDevice (hps) ;
1009:
1010: DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ;
1011: DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION, 1L, &yDeviceRes) ;
1012:
1013: // Find desired font size in pixels
1014:
1015: ptlFont.x = 2540L * (long)shPointSize / 72L ;
1016: ptlFont.y = 2540L * (long)shPointSize / 72L ;
1017:
1018: // Set the character box
1019:
1020: sizfx.cx = MAKEFIXED (ptlFont.x, 0) ;
1021: sizfx.cy = MAKEFIXED (ptlFont.y, 0) ;
1022: lVOffset = ptlFont.y ;
1023:
1024: sizBaseFont = sizfx ;
1025: GpiSetCharBox (hps, &sizfx) ;
1026:
1027: // set up some useful globals
1028: {
1029: FONTMETRICS fm ;
1030: GpiQueryFontMetrics( hps, sizeof(FONTMETRICS), &fm ) ;
1031: lBaseSubOffset = -fm.lSubscriptYOffset ;
1032: lBaseSupOffset = fm.lSuperscriptYOffset ;
1033: lSubOffset = lBaseSubOffset ;
1034: lSupOffset = lBaseSupOffset ;
1035: lCharHeight = fm.lMaxAscender*1.2 ;
1036: lCharWidth = fm.lAveCharWidth ;
1037: sizBaseSubSup.cx = MAKEFIXED( ptlFont.x*0.7, 0 ) ;
1038: sizBaseSubSup.cy = MAKEFIXED( ptlFont.y*0.7, 0 ) ;
1039: }
1040: sizCurFont = sizBaseFont ;
1041: sizCurSubSup = sizBaseSubSup ;
1042: if( bNewFont ) {
1043: // EditCharCell( hps, &sizfx ) ;
1044: bNewFont = FALSE ;
1045: }
1046: }
1047:
1048: void SwapFont( HPS hps, char *szFNS )
1049: /*
1050: ** Select a named and sized outline (adobe) font
1051: */
1052: {
1053: HDC hdc ;
1054: FATTRS fat ;
1055: LONG xDeviceRes, yDeviceRes ;
1056: POINTL ptlFont ;
1057: SIZEF sizfx ;
1058: static LONG lcid = 0L ;
1059: static int itab = 1 ;
1060: static char *szFontName ;
1061: static short shPointSize ;
1062:
1063: if( szFNS == NULL ) { /* restore base font */
1064: sizCurFont = sizBaseFont ;
1065: sizCurSubSup = sizBaseSubSup ;
1066: lSubOffset = lBaseSubOffset ;
1067: lSupOffset = lBaseSupOffset ;
1068: GpiSetCharSet( hps, 10 ) ;
1069: GpiSetCharBox (hps, &sizBaseFont) ;
1070: }
1071: else {
1072: sscanf( szFNS, "%hd", &shPointSize ) ;
1073: szFontName = strchr( szFNS, '.' ) + 1 ;
1074:
1075: {
1076: int i ;
1077: lcid = 0 ;
1078: for(i=0;i<itab;i++) {
1079: if( strcmp( szFontName, tabFont[i].name ) == 0 ) {
1080: lcid = tabFont[i].lcid ;
1081: break ;
1082: }
1083: }
1084: }
1085: if( lcid == 0 ) {
1086:
1087: fat.usRecordLength = sizeof fat ;
1088: fat.fsSelection = 0 ;
1089: fat.lMatch = 0 ;
1090: fat.idRegistry = 0 ;
1091: fat.usCodePage = 0 ; //GpiQueryCp (hps) ;
1092: fat.lMaxBaselineExt = 0 ;
1093: fat.lAveCharWidth = 0 ;
1094: fat.fsType = 0 ;
1095: fat.fsFontUse = FATTR_FONTUSE_OUTLINE |
1096: FATTR_FONTUSE_TRANSFORMABLE ;
1097:
1098: strcpy (fat.szFacename, szFontName) ;
1099:
1100:
1101: tabFont[itab].name = strdup( szFontName ) ;
1102: lcid = itab+10 ;
1103: tabFont[itab].lcid = lcid ;
1104: ++itab ;
1105:
1106: // lcid = 11L ;
1107: GpiSetCharSet( hps, 0L) ;
1108: GpiDeleteSetId( hps, lcid ) ;
1109: GpiCreateLogFont (hps, NULL, lcid, &fat) ;
1110: }
1111: GpiSetCharSet( hps, lcid ) ;
1112: hdc = GpiQueryDevice (hps) ;
1113:
1114: DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ;
1115: DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION, 1L, &yDeviceRes) ;
1116:
1117: // Find desired font size in pixels
1118:
1119: ptlFont.x = 2540L * (long)shPointSize / 72L ;
1120: ptlFont.y = 2540L * (long)shPointSize / 72L ;
1121:
1122: // Set the character box
1123:
1124: sizCurFont.cx = MAKEFIXED (ptlFont.x, 0) ;
1125: sizCurFont.cy = MAKEFIXED (ptlFont.y, 0) ;
1126: // lVOffset = ptlFont.y ;
1127:
1128: GpiSetCharBox (hps, &sizCurFont) ;
1129: sizCurSubSup.cx = MAKEFIXED( ptlFont.x*0.7, 0 ) ;
1130: sizCurSubSup.cy = MAKEFIXED( ptlFont.y*0.7, 0 ) ;
1131:
1132: // set up some useful globals
1133: {
1134: FONTMETRICS fm ;
1135: GpiQueryFontMetrics( hps, sizeof(FONTMETRICS), &fm ) ;
1136: lSubOffset = -fm.lSubscriptYOffset ;
1137: lSupOffset = fm.lSuperscriptYOffset ;
1138: }
1139: }
1140:
1141: }
1142:
1143: static void ReadGnu( void* arg )
1144: /*
1145: ** Thread to read plot commands from GNUPLOT pm driver.
1146: ** Opens named pipe, then clears semaphore to allow GNUPLOT driver to proceed.
1147: ** Reads commands and builds a command list.
1148: */
1149: {
1150: HPIPE hRead = 0L ;
1151: POINTL ptl ;
1152: POINTL aptl[4] ;
1153: long lCurCol ;
1154: long lOldLine = 0 ;
1155: BOOL bBW = FALSE ; /* passed frpm print.c ?? */
1156: BOOL bPath = FALSE ;
1157: BOOL bDots = FALSE ;
1158: char *szEnv ;
1159: char *szFileBuf ;
1160: ULONG rc;
1161: USHORT usErr ;
1162: ULONG cbR ;
1163: USHORT i ;
1164: PID ppid ;
1165: unsigned char buff[2] ;
1166: HEV hev ;
1167: static char *szPauseText = NULL ;
1168: ULONG ulPause ;
1169: char *pszPipeName, *pszSemName ;
1170: LONG commands[4] ;
1171: HPS hps ;
1172: HAB hab ;
1173: int linewidth = DEFLW ;
1174:
1175: hab = WinInitialize( 0 ) ;
1176: DosEnterCritSec() ;
1177: pszPipeName = malloc( 256 ) ;
1178: pszSemName = malloc( 256 ) ;
1179: DosExitCritSec() ;
1180: strcpy( pszPipeName, "\\pipe\\" ) ;
1181: strcpy( pszSemName, "\\sem32\\" ) ;
1182: strcat( pszPipeName, szIPCName ) ;
1183: strcat( pszSemName, szIPCName ) ;
1184:
1185: /* open a named pipe for communication with gnuplot */
1186:
1187: rc = DosCreateNPipe( pszPipeName,
1188: &hRead,
1189: NP_ACCESS_DUPLEX|NP_NOINHERIT|NP_NOWRITEBEHIND ,
1190: 1|NP_WAIT|NP_READMODE_MESSAGE|NP_TYPE_MESSAGE,
1191: PIPEBUF,
1192: PIPEBUF,
1193: 0xFFFFFFFF) ;
1194: hev = 0 ; /* OK, gnuplot can try to open npipe ... */
1195: DosOpenEventSem( pszSemName, &hev ) ;
1196: DosPostEventSem( hev ) ;
1197:
1198:
1199:
1200: /* attach to gnuplot */
1201:
1202: server:
1203:
1204: if( DosConnectNPipe( hRead ) == 0L ) {
1205:
1206: WinPostMsg( hSysMenu,
1207: MM_SETITEMATTR,
1208: MPFROM2SHORT(SC_CLOSE, TRUE ),
1209: MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED) ) ;
1210:
1211: /* store graphics commands */
1212: /* use semaphore to prevent problems with drawing while reallocating
1213: the command buffers */
1214:
1215: DosRead( hRead, &ppidGnu, 4, &cbR ) ;
1216: // DosPostEventSem( semStartSeq ) ; /* once we've got pidGnu */
1217: WinPostMsg( hApp, WM_GPSTART, 0, 0 ) ;
1218:
1219:
1220: hps = hpsScreen ;
1221: InitScreenPS() ;
1222: while (1) {
1223:
1224: usErr=BufRead(hRead,buff, 1, &cbR) ;
1225: if( usErr != 0 ) break ;
1226:
1227: switch( *buff ) {
1228: case 'G' : /* enter graphics mode */
1229: {
1230: ULONG ulCount ;
1231:
1232: if( tidDraw != 0 ) {
1233: /* already drawing - stop it */
1234: GpiSetStopDraw( hpsScreen, SDW_ON ) ;
1235: while(tidDraw != 0) DosSleep(1) ;
1236: }
1237: /* wait for access to command list and lock it */
1238: // DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;
1239: // DosEnterCritSec() ;
1240: DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
1241: InitScreenPS() ;
1242: ScalePS( hps ) ;
1243: // DosResetEventSem( semDrawDone, &ulCount ) ;
1244: GpiSetDrawingMode( hps, DM_DRAWANDRETAIN ) ;
1245: for(i=1;i<=iSeg;i++)
1246: GpiDeleteSegment( hps, i ) ;
1247: iSeg = 1 ;
1248: GpiOpenSegment( hps, iSeg ) ;
1249: // DosExitCritSec() ;
1250: GpiSetLineEnd( hps, LINEEND_ROUND ) ;
1251: GpiSetLineWidthGeom( hps, linewidth ) ;
1252: GpiSetCharBox (hps, &sizBaseFont) ;
1253: }
1254: break ;
1255:
1256: case 'Q' : /* query terminal info */
1257: DosWrite( hRead, &lCharWidth, sizeof(int), &cbR ) ;
1258: DosWrite( hRead, &lCharHeight, sizeof(int), &cbR ) ;
1259: break ;
1260:
1261: case 'E' : /* leave graphics mode (graph completed) */
1262: if( bPath ) {
1263: GpiEndPath( hps ) ;
1264: GpiStrokePath( hps, 1, 0 ) ;
1265: bPath = FALSE ;
1266: }
1267: GpiCloseSegment( hps ) ;
1268: // DosPostEventSem( semDrawDone ) ;
1269: DosReleaseMutexSem( semHpsAccess ) ;
1270: WinPostMsg( hApp, WM_GNUPLOT, 0L, 0L ) ;
1271: break ;
1272:
1273: case 'R' :
1274: /* gnuplot has reset drivers, allow user to kill this */
1275: WinPostMsg( hSysMenu,
1276: MM_SETITEMATTR,
1277: MPFROM2SHORT(SC_CLOSE, TRUE ),
1278: MPFROM2SHORT(MIA_DISABLED, (USHORT)0 ) ) ;
1279: /* if we are keeping us on the screen, wait for new connection */
1280: if( bServer||bPersist ) {
1281: DosDisConnectNPipe( hRead ) ;
1282: goto server ;
1283: }
1284: break ;
1285:
1286: case 'r' :
1287: /* resume after multiplot */
1288: {
1289: ULONG ulCount ;
1290: DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
1291: // DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;
1292: iSeg++ ;
1293: // DosResetEventSem( semDrawDone, &ulCount ) ;
1294: GpiSetDrawingMode( hps, DM_DRAWANDRETAIN ) ;
1295: GpiOpenSegment( hps, iSeg ) ;
1296: }
1297: break ;
1298:
1299: case 's' :
1300: /* suspend after multiplot */
1301: break ;
1302:
1303: case 'M' : /* move */
1304: case 'V' : /* draw vector */
1305: if( *buff=='M' ) {
1306: if( bPath ) {
1307: GpiEndPath( hps ) ;
1308: GpiStrokePath( hps, 1, 0 ) ;
1309: bPath = FALSE ;
1310: }
1311: }
1312: else {
1313: if( bWideLines/*bWideLines*/ && !bPath ) {
1314: GpiBeginPath( hps, 1 ) ;
1315: bPath = TRUE ;
1316: }
1317: }
1318: BufRead(hRead,&ptl.x, 2*sizeof(int), &cbR) ;
1319: if( (*buff=='V') && bDots ) ptl.x += 5 ;
1320: else if( (*buff=='M') && bDots ) ptl.x -= 5 ;
1321: if( *buff == 'M' ) LMove( hps, &ptl ) ;
1322: else LLine( hps, &ptl ) ;
1323: break ;
1324:
1325: case 'P' : /* pause */
1326: {
1327: int len ;
1328: BufRead(hRead,&len, sizeof(int), &cbR) ;
1329: len = (len+sizeof(int)-1)/sizeof(int) ;
1330: if( len > 0 ){ /* get pause text */
1331: DosEnterCritSec() ;
1332: szPauseText = malloc( len*sizeof(int) ) ;
1333: DosExitCritSec() ;
1334: BufRead(hRead,szPauseText, len*sizeof(int), &cbR) ;
1335: }
1336: if( ulPauseMode != PAUSE_GNU ) {
1337: /* pause and wait for semaphore to be cleared */
1338: DosResetEventSem( semPause, &ulPause ) ;
1339: WinPostMsg( hApp, WM_PAUSEPLOT, (MPARAM) szPauseText, 0L ) ;
1340: DosWaitEventSem( semPause, SEM_INDEFINITE_WAIT ) ;
1341: }
1342: else { /* gnuplot handles pause */
1343: ulPauseReply = 2 ;
1344: }
1345: DosEnterCritSec() ;
1346: if( szPauseText != NULL ) free( szPauseText ) ;
1347: szPauseText = NULL ;
1348: DosExitCritSec() ;
1349: /* reply to gnuplot so it can continue */
1350: DosWrite( hRead, &ulPauseReply, sizeof(int), &cbR ) ;
1351: }
1352: break ;
1353:
1354: case 'T' : /* write text */
1355: /* read x, y, len */
1356: if( bPath ) {
1357: GpiEndPath( hps ) ;
1358: GpiStrokePath( hps, 1, 0 ) ;
1359: bPath = FALSE ;
1360: }
1361: {
1362: int x, y, len, sw ;
1363: char *str ;
1364: BufRead(hRead,&x, sizeof(int), &cbR) ;
1365: BufRead(hRead,&y, sizeof(int), &cbR) ;
1366: BufRead(hRead,&len, sizeof(int), &cbR) ;
1367:
1368: DosEnterCritSec() ;
1369: len = (len+sizeof(int)-1)/sizeof(int) ;
1370: if( len == 0 ) len = 1 ; //?? how about read
1371: str = malloc( len*sizeof(int) ) ;
1372: *str = '\0' ;
1373: DosExitCritSec() ;
1374: BufRead(hRead, str, len*sizeof(int), &cbR) ;
1375: lCurCol = GpiQueryColor( hps ) ;
1376: GpiSetColor( hps, CLR_BLACK ) ;
1377: sw = QueryTextBox( hps, strlen(str), str ) ;
1378: switch(jmode) {
1379: case LEFT: sw = 0; break;
1380: case CENTRE: sw = -sw/2; break;
1381: case RIGHT: sw = -sw; break;
1382: }
1383: if( bHorz ) {
1384: ptl.x = (LONG)(x+sw) ; ptl.y = (LONG)(y-lVOffset/4) ;
1385: }
1386: else {
1387: ptl.x = (LONG)x ; ptl.y = (LONG)(y+sw) ;
1388: }
1389: if(bEnhanced)
1390: CharStringAt( hps, ptl.x, ptl.y, strlen( str ) , str ) ;
1391: else
1392: GpiCharStringAt( hps, &ptl, strlen( str ), str ) ;
1393: GpiSetColor( hps, lCurCol ) ;
1394: DosEnterCritSec() ;
1395: free(str) ;
1396: DosExitCritSec() ;
1397: }
1398: break ;
1399:
1400: case 'J' : /* justify */
1401: BufRead(hRead,&jmode, sizeof(int), &cbR) ;
1402: break ;
1403:
1404: case 'A' : /* text angle */
1405: {
1406: int ta ;
1407: GRADIENTL grdl ;
1408: SIZEF sizHor, sizVer ;
1409: if( bPath ) {
1410: GpiEndPath( hps ) ;
1411: GpiStrokePath( hps, 1, 0 ) ;
1412: bPath = FALSE ;
1413: }
1414: BufRead(hRead,&ta, sizeof(int), &cbR) ;
1415: if( ta == 0 ) {
1416: grdl.x = 0L ; grdl.y = 0L ;
1417: GpiSetCharAngle( hps, &grdl ) ;
1418: if( !bHorz ) {
1419: bHorz = TRUE ;
1420: }
1421: }
1422: else if( ta == 1 ) {
1423: grdl.x = 0L ; grdl.y = 1L ;
1424: GpiSetCharAngle( hps, &grdl ) ;
1425: if( bHorz ) {
1426: bHorz = FALSE ;
1427: }
1428: }
1429: }
1430: break ;
1431:
1432: case 'L' : /* line type */
1433: {
1434: int lt, col ;
1435: if( bPath ) {
1436: GpiEndPath( hps ) ;
1437: GpiStrokePath( hps, 1, 0 ) ;
1438: bPath = FALSE ;
1439: }
1440: BufRead(hRead,<, sizeof(int), &cbR) ;
1441: /* linetype = -2 axes, -1 border, 0 arrows, all to 0 */
1442: col = lt ;
1443: if( lt == -2 ) GpiSetLineWidthGeom( hps, DEFLW*0.85 ) ;
1444: else if( lt == -1 ) GpiSetLineWidthGeom( hps, DEFLW*0.6 ) ;
1445: else GpiSetLineWidthGeom( hps, linewidth ) ;
1446: if( lt < 0 ) lt = 0 ;
1447: lt = (lt%8);
1448: col = (col+2)%16 ;
1449: GpiLabel( hps, lLineTypes[lt] ) ;
1450: lOldLine=lt ;
1451: LType( (bLineTypes||bBW)?lt:0 ) ;
1452: // GpiSetLineType( hps, (bLineTypes||bBW)?lLineTypes[lt]:lLineTypes[0] ) ;
1453: if( !bBW ) { /* maintain some flexibility here in case we don't want
1454: the model T option */
1455: if( bColours ) GpiSetColor( hps, lCols[col] ) ;
1456: else GpiSetColor( hps, CLR_BLACK ) ;
1457: }
1458: }
1459: break ;
1460:
1461: case 'W' : /* line width */
1462: {
1463: int lw ;
1464: if( bPath ) {
1465: GpiEndPath( hps ) ;
1466: GpiStrokePath( hps, 1, 0 ) ;
1467: bPath = FALSE ;
1468: }
1469: BufRead(hRead,&lw, sizeof(int), &cbR) ;
1470: GpiSetLineWidthGeom( hps, DEFLW*lw/100 ) ;
1471: linewidth = DEFLW*lw/100 ;
1472: }
1473: break ;
1474:
1475: case 'D' : /* points mode */
1476: {
1477: int lt ;
1478: BufRead(hRead,<, sizeof(int), &cbR) ;
1479: /* 1: enter point mode, 0: exit */
1480: if( bLineTypes || bBW ) {
1481: if( lt==1) LType(0) ;
1482: else LType( lOldLine ) ;
1483: // if( lt == 1 ) lOldLine = GpiSetLineType( hps, lLineTypes[0] ) ;
1484: // else GpiSetLineType( hps, lOldLine ) ;
1485: }
1486: // if( lt == 1 ) GpiSetLineWidthGeom( hps, 20 ) ;
1487: // else GpiSetLineWidthGeom( hps, 50 ) ;
1488: bDots = lt ;
1489: }
1490: break ;
1491:
1492: case 'F' : /* set font */
1493:
1494: {
1495: int len ;
1496: char *str ;
1497: char font[FONTBUF] ;
1498: BufRead(hRead,&len, sizeof(int), &cbR) ;
1499: len = (len+sizeof(int)-1)/sizeof(int) ;
1500: if( len == 0 ) {
1501: SwapFont( hps, NULL ) ;
1502: }
1503: else {
1504: char *p ;
1505: str = malloc( len*sizeof(int) ) ;
1506: BufRead(hRead, str, len*sizeof(int), &cbR) ;
1507: p = strchr(str, ',') ;
1508: if( p==NULL ) strcpy( font, "14" ) ;
1509: else {
1510: *p = '\0' ;
1511: strcpy( font, p+1 ) ;
1512: }
1513: strcat( font,"." ) ;
1514: strcat( font, str ) ;
1515: free( str ) ;
1516: SwapFont( hps, font ) ;
1517: }
1518: }
1519: break ;
1520:
1521: case 'O' : /* set options */
1522:
1523: {
1524: int len ;
1525: char *str ;
1526: BufRead(hRead,&len, sizeof(int), &cbR) ;
1527: len = (len+sizeof(int)-1)/sizeof(int) ;
1528: bWideLines = FALSE ; /* reset options */
1529: bEnhanced = FALSE ;
1530:
1531: if( len > 0 ) {
1532: char *p ;
1533: p = str = malloc( len*sizeof(int) ) ;
1534: BufRead(hRead, str, len*sizeof(int), &cbR) ;
1535: while( (p=strchr(p,'-')) != NULL ) {
1536: ++p ;
1537: if( *p == 'w' ) bWideLines = TRUE ;
1538: if( *p == 'e' ) bEnhanced = TRUE ;
1539: ++p ;
1540: }
1541: free( str ) ;
1542: }
1543: }
1544: break ;
1545:
1546:
1547: default : /* should handle error */
1548: break ;
1549: }
1550: }
1551: }
1552: exitserver:
1553: DosDisConnectNPipe( hRead ) ;
1554: WinPostMsg( hApp, WM_CLOSE, 0L, 0L ) ;
1555: }
1556:
1557: static void EditLineTypes( HWND hwnd, HPS hps, BOOL bDashed )
1558: /*
1559: */
1560: {
1561: int i, rc ;
1562: char buf[64] ;
1563: GpiSetDrawingMode( hps, DM_RETAIN ) ;
1564: GpiOpenSegment( hps, iSeg ) ;
1565: GpiSetEditMode( hps, SEGEM_REPLACE ) ;
1566: for( i=0; i<7; i++ ) {
1567: while( GpiSetElementPointerAtLabel( hps, lLineTypes[i] ) ) {
1568: GpiOffsetElementPointer( hps, 1 ) ;
1569: GpiSetLineType( hps, bDashed?lLineTypes[i]:lLineTypes[0] ) ;
1570: }
1571: GpiSetElementPointer( hps, 0 ) ;
1572: }
1573: GpiSetEditMode( hps, SEGEM_INSERT ) ;
1574: GpiCloseSegment( hps ) ;
1575: }
1576:
1577: static void EditCharCell( HPS hps, SIZEF *psize )
1578: /*
1579: ** Edit segment to change char cell (font size)
1580: */
1581: {
1582: int i ;
1583: LONG rl, rc ;
1584: SIZEF sizH, sizV ;
1585: char buf[64] ;
1586: int iVert = 0 ;
1587:
1588: sizH = *psize ;
1589: sizV.cx = sizH.cy ;
1590: sizV.cy = sizH.cx ;
1591: GpiSetDrawingMode( hps, DM_RETAIN ) ;
1592: GpiOpenSegment( hps, iSeg ) ;
1593: GpiSetEditMode( hps, SEGEM_REPLACE ) ;
1594: i=0 ;
1595: while( GpiSetElementPointer( hps, i ) ) {
1596: rc = GpiQueryElementPointer( hps) ;
1597: if( rc != i ) break ;
1598: rl = GpiQueryElementType( hps, &rc, 0, NULL ) ;
1599: if( rc == 0x34 || rc == 0x74 ) {
1600: LONG gdata ;
1601: GpiQueryElement( hps, 5, 4, (PBYTE)&gdata ) ;
1602: if( gdata == 0 ) iVert = 0 ;
1603: else iVert = 1 ;
1604: }
1605: else if( rc==0x33 || rc==0x03 ) GpiSetCharBox(hps, iVert?&sizV:&sizH ) ;
1606: ++i ;
1607: }
1608: GpiSetEditMode( hps, SEGEM_INSERT ) ;
1609: GpiCloseSegment( hps ) ;
1610: }
1611:
1612: static int BufRead( HFILE hfile, void *buf, int nBytes, ULONG *pcbR )
1613: /*
1614: ** pull next plot command out of buffer read from GNUPLOT
1615: */
1616: {
1617: ULONG ulR, ulRR ;
1618: int rc ;
1619: static char buffer[GNUBUF] ;
1620: static char *pbuffer = buffer+GNUBUF, *ebuffer = buffer+GNUBUF ;
1621:
1622: for( ; nBytes > 0 ; nBytes-- ) {
1623: if( pbuffer >= ebuffer ) {
1624: ulR = GNUBUF ;
1625: rc = DosRead( hfile, buffer, ulR, &ulRR ) ;
1626: if( rc != 0 ) return rc ;
1627: if( ulRR == 0 ) return 1 ;
1628: pbuffer = buffer ;
1629: ebuffer = pbuffer+ulRR ;
1630: }
1631: *(char*)buf++ = *pbuffer++ ;
1632: }
1633: return 0L ;
1634: }
1635:
1636:
1637: int GetNewFont( HWND hwnd, HPS hps )
1638: /*
1639: ** Get a new font using standard font dialog
1640: */
1641: {
1642: static FONTDLG pfdFontdlg; /* Font dialog info structure */
1643: static int i1 =1 ;
1644: static int iSize ;
1645: char szPtList[64] ;
1646: HWND hwndFontDlg; /* Font dialog window handle */
1647: char *p ;
1648: char szFamilyname[FACESIZE];
1649:
1650: if( i1 ) {
1651: strcpy( pfdFontdlg.fAttrs.szFacename, strchr( szFontNameSize, '.' ) + 1 ) ;
1652: strcpy( szFamilyname, strchr( szFontNameSize, '.' ) + 1 ) ;
1653: sscanf( szFontNameSize, "%d", &iSize ) ;
1654: memset(&pfdFontdlg, 0, sizeof(FONTDLG));
1655:
1656: pfdFontdlg.cbSize = sizeof(FONTDLG);
1657: pfdFontdlg.hpsScreen = hps;
1658: /* szFamilyname[0] = 0;*/
1659: pfdFontdlg.pszFamilyname = szFamilyname;
1660: pfdFontdlg.usFamilyBufLen = FACESIZE;
1661: pfdFontdlg.fl = FNTS_HELPBUTTON |
1662: FNTS_CENTER | FNTS_VECTORONLY |
1663: FNTS_OWNERDRAWPREVIEW ;
1664: pfdFontdlg.clrFore = CLR_BLACK;
1665: pfdFontdlg.clrBack = CLR_WHITE;
1666: pfdFontdlg.usWeight = FWEIGHT_NORMAL ; //5 ;
1667: pfdFontdlg.fAttrs.usCodePage = 0;
1668: pfdFontdlg.fAttrs.usRecordLength = sizeof(FATTRS) ;
1669: }
1670: sprintf( szPtList, "%d 8 10 12 14 18 24", iSize ) ;
1671: pfdFontdlg.pszPtSizeList = szPtList ;
1672: pfdFontdlg.fxPointSize = MAKEFIXED(iSize,0);
1673: hwndFontDlg = WinFontDlg(HWND_DESKTOP, hwnd, &pfdFontdlg);
1674: if( i1 ) {
1675: pfdFontdlg.fl = FNTS_HELPBUTTON |
1676: FNTS_CENTER | FNTS_VECTORONLY |
1677: FNTS_INITFROMFATTRS ;
1678: i1=0;
1679: }
1680: if (hwndFontDlg && (pfdFontdlg.lReturn == DID_OK)) {
1681: iSize = FIXEDINT( pfdFontdlg.fxPointSize ) ;
1682: sprintf( szFontNameSize, "%d.%s", iSize, pfdFontdlg.fAttrs.szFacename ) ;
1683: return 1 ;
1684: }
1685: else return 0 ;
1686: }
1687:
1688: void SigHandler( int sig )
1689: /*
1690: ** Handle termination signal to free up resources before
1691: ** termination.
1692: */
1693: {
1694: if( sig == SIGTERM ) {
1695: if( bPersist ) {
1696: DosKillThread( tidSpawn ) ;
1697: signal( SIGTERM, SIG_ACK ) ;
1698: return ;
1699: }
1700: DosEnterCritSec() ;
1701: DosKillThread( tidSpawn ) ;
1702: DosKillThread( tidDraw ) ;
1703: DosExitCritSec() ;
1704: exit(0) ;
1705: }
1706: }
1707:
1708: /* disable debugging info */
1709: #define TEXT_DEBUG(x) /* fprintf x; */
1710:
1711: /* used in determining height of processed text */
1712:
1713: //static float max_height, min_height;
1714:
1715: /* process a bit of string, and return the last character used.
1716: * p is start of string
1717: * brace is TRUE to keep processing to }, FALSE for do one character
1718: * fontname & fontsize are obvious
1719: * base is the current baseline
1720: * widthflag is TRUE if the width of this should count,
1721: * FALSE for zero width boxes
1722: * showflag is TRUE if this should be shown,
1723: * FALSE if it should not be shown (like TeX \phantom)
1724: */
1725:
1726: static char *starttext = NULL ;
1727: static int textlen = 0 ;
1728: static BOOL bText = FALSE ;
1729: static int textwidth = 0 ;
1730: static POINTL ptlText ;
1731: static FILE *ff ;
1732: static char *ParseText(HPS hps, char *p, BOOL brace, char *fontname,
1733: int fontsize, int base, BOOL widthflag, BOOL showflag)
1734: {
1735: POINTL aptl[TXTBOX_COUNT] ;
1736: BOOL bChangeFont = FALSE ;
1737: TEXT_DEBUG((ff,"RECURSE WITH [%p] %s, %d %s %.1f %.1f %d %d\n", p, p, brace, fontname, fontsize, base, widthflag, showflag))
1738:
1739: /* Start each recursion with a clean string */
1740:
1741: //{FILE *ff;int i=textlen;ff=fopen("deb","a");
1742: //for(i=0;i<textlen;i++)fputc(starttext[i], ff);fputc('\n',ff) ; fclose(ff);}
1743: if( textlen > 0 ) {
1744: GpiQueryTextBox( hps, textlen, starttext, TXTBOX_COUNT, aptl ) ;
1745: if( bHorz ) textwidth += aptl[TXTBOX_BOTTOMRIGHT].x ;
1746: else textwidth += aptl[TXTBOX_BOTTOMRIGHT].y ;
1747: }
1748: if( bText ) {
1749: if(textlen > 0 ) {
1750: GpiCharStringAt( hps, &ptlText, textlen, starttext ) ;
1751: ptlText.x += aptl[TXTBOX_CONCAT].x + (bHorz?0:(-base)) ;
1752: ptlText.y += aptl[TXTBOX_CONCAT].y + (bHorz?base:0) ;
1753: }
1754: else {
1755: ptlText.x += (bHorz?0:(-base)) ;
1756: ptlText.y += (bHorz?base:0) ;
1757: }
1758: }
1759: textlen = 0 ;
1760: starttext = p ;
1761: if( fontname != NULL ) {
1762: char szFont[FONTBUF] ;
1763: sprintf(szFont, "%d.%s", fontsize, fontname ) ;
1764: SwapFont( hps, szFont ) ;
1765: bChangeFont = TRUE ;
1766: }
1767: if( base != 0 ) GpiSetCharBox( hps, &sizCurSubSup ) ;
1768:
1769: for ( ; *p; ++p)
1770: { int shift;
1771:
1772: switch (*p)
1773: {
1774: case '}' :
1775: /*{{{ deal with it*/
1776: if (brace) {
1777: brace = 0 ;
1778: break ;
1779: }
1780:
1781: break;
1782: /*}}}*/
1783:
1784: case '_' :
1785: case '^' :
1786: /*{{{ deal with super/sub script*/
1787:
1788: shift = (*p == '^') ? lSupOffset : lSubOffset;
1789: p = ParseText(hps, p+1, FALSE, NULL/*fontname*/, fontsize*0.7, base+shift, widthflag, showflag);
1790: break;
1791: /*}}}*/
1792:
1793: case '{' :
1794: {
1795: char *savepos=NULL, save=0;
1796: char *localfontname=fontname, ch;
1797: char localfontbuf[FONTBUF] ;
1798: int recode=1;
1799: int f=fontsize;
1800: BOOL bChangeFont = FALSE ;
1801: char *q=localfontbuf ;
1802:
1803: /*{{{ recurse (possibly with a new font) */
1804:
1805: TEXT_DEBUG((ff,"Dealing with {\n"))
1806:
1807: if (*++p == '/')
1808: { /* then parse a fontname, optional fontsize */
1809: while (*++p == ' ');
1810: if (*p=='-')
1811: {
1812: recode=0;
1813: while (*++p == ' ');
1814: }
1815: localfontname = p;
1816: while ((ch = *p) > ' ' && ch != '=') {
1817: localfontname=localfontbuf ;
1818: if(*p=='_') *q=' ' ;
1819: else *q=*p ;
1820: ++p;++q;
1821: }
1822: *q = '\0' ;
1823: FontExpand( localfontbuf ) ;
1824: save = *(savepos=p);
1825: if (ch == '=')
1826: {
1827: *p++ = '\0';
1828: /*{{{ get optional font size*/
1829: TEXT_DEBUG((ff,"Calling strtod(%s) ...", p))
1830: f = strtod(p, &p);
1831: TEXT_DEBUG((ff,"Retured %.1f and %s\n", f, p))
1832:
1833: if (!f) f = fontsize;
1834:
1835: TEXT_DEBUG((ff,"Font size %.1f\n", f))
1836: /*}}}*/
1837: }
1838: else
1839: {
1840: *p++ = '\0';
1841: f = fontsize;
1842: }
1843:
1844: while (*p == ' ')
1845: ++p;
1846: if (! (*localfontname)) {
1847: localfontname = fontname;
1848: if( f != fontsize )
1849: localfontname = strchr( szFontNameSize, '.' ) + 1 ;
1850: }
1851: }
1852: /*}}}*/
1853:
1854: TEXT_DEBUG((ff,"Before recursing, we are at [%p] %s\n", p, p))
1855:
1856: p = ParseText(hps,p, TRUE, localfontname, f, base, widthflag, showflag);
1857:
1858: TEXT_DEBUG((ff,"BACK WITH %s\n", p));
1859: if (savepos)
1860: /* restore overwritten character */
1861: *savepos = save;
1862:
1863: break;
1864: }
1865:
1866: case '@' :
1867: /*{{{ phantom box - prints next 'char', then restores currentpoint */
1868:
1869: p = ParseText(hps,++p, FALSE, NULL/*fontname*/, fontsize, base, FALSE, showflag);
1870:
1871: break;
1872: /*}}}*/
1873:
1874: case '&' :
1875: /*{{{ character skip - skips space equal to length of character(s) */
1876:
1877: p = ParseText(hps,++p, FALSE, NULL/*fontname*/, fontsize, base, widthflag, FALSE);
1878:
1879: break;
1880: /*}}}*/
1881:
1882: case '\\' :
1883: {
1884: char buffer[4] ; /* should need only one char.. */
1885: char *q = buffer ;
1886: *q = '\0' ;
1887: ParseText(hps,q, FALSE, NULL, fontsize, base, widthflag, showflag);
1888: /*{{{ is it an escape */
1889: /* special cases */
1890:
1891: if (p[1]=='\\' || p[1]=='{' || p[1]=='}')
1892: {
1893: *q++=p[1] ;
1894: ++p ;
1895: }
1896: #if 0
1897: else if (p[1] >= '0' && p[1] <= '7')
1898: {
1899: /* up to 3 octal digits */
1900: int c = 0 ;
1901: c+=p[1];
1902: ++p;
1903: if (p[1] >= '0' && p[1] <= '7')
1904: {
1905: c*=8; c+=p[1];
1906: ++p;
1907: if (p[1] >= '0' && p[1] <= '7')
1908: {
1909: c*=8; c+=p[1];
1910: ++p;
1911: }
1912: }
1913: *q++ = c ;
1914: break;
1915: }
1916: #endif
1917: *q = '\0' ;
1918: textlen = 1 ;
1919: starttext=buffer ;
1920: ParseText(hps,q, FALSE, NULL/*fontname*/, fontsize, base, widthflag, showflag);
1921: starttext=p+1 ;
1922: textlen = 0 ;
1923: /*}}}*/
1924: }
1925: break ;
1926:
1927: default:
1928: ++textlen ;
1929:
1930: /*}}}*/
1931:
1932: }
1933:
1934: /* like TeX, we only do one character in a recursion, unless it's
1935: * in braces
1936: */
1937:
1938: if (!brace) break ;
1939: }
1940: if( textlen > 0 ) {
1941: GpiQueryTextBox( hps, textlen, starttext, TXTBOX_COUNT, aptl ) ;
1942: if( widthflag ) {
1943: if( bHorz ) textwidth += aptl[TXTBOX_BOTTOMRIGHT].x ;
1944: else textwidth += aptl[TXTBOX_BOTTOMRIGHT].y ;
1945: }
1946: }
1947: if( bText ) {
1948: if( textlen > 0 ) {
1949: if( showflag)
1950: GpiCharStringAt( hps, &ptlText, textlen, starttext ) ;
1951: if( widthflag ) {
1952: ptlText.x += aptl[TXTBOX_CONCAT].x ;
1953: ptlText.y += aptl[TXTBOX_CONCAT].y ;
1954: }
1955: }
1956: if( base != 0 ) {
1957: ptlText.x -= (bHorz?0:(-base)) ;
1958: ptlText.y -= (bHorz?base:0) ;
1959: }
1960: }
1961: if( bChangeFont ) {
1962: SwapFont( hps, NULL ) ;
1963: bChangeFont = FALSE ;
1964: }
1965: if( base != 0 ) GpiSetCharBox( hps, &sizBaseFont ) ;
1966:
1967:
1968: textlen = 0 ;
1969: starttext = p+1 ;
1970: return p;
1971: }
1972:
1973: static void CharStringAt(HPS hps, int x, int y, int len, char *str)
1974: {
1975: /* flush any pending graphics (all the XShow routines do this...) */
1976:
1977: char *fontname ;
1978: int fontsize ;
1979:
1980: if (!strlen(str))
1981: return;
1982:
1983: /* set up the globals */
1984:
1985: ptlText.x = x ;
1986: ptlText.y = y ;
1987: bText = TRUE ;
1988: starttext = NULL ;
1989: textlen = 0 ;
1990: textwidth = 0 ;
1991: sscanf( szFontNameSize, "%d", &fontsize ) ;
1992: fontname = strchr( szFontNameSize, '.' ) + 1 ;
1993:
1994: while (*(str = ParseText(hps, str, TRUE, NULL,
1995: fontsize,
1996: 0.0, TRUE, TRUE)));
1997:
1998: }
1999:
2000: static int QueryTextBox( HPS hps, int len, char *str )
2001: {
2002: char *fontname ;
2003: int fontsize ;
2004: if (!strlen(str))
2005: return 0 ;
2006:
2007:
2008: /* set up the globals */
2009:
2010: bText = FALSE ;
2011: starttext = NULL ;
2012: textlen = 0 ;
2013: textwidth = 0 ;
2014: sscanf( szFontNameSize, "%d", &fontsize ) ;
2015: fontname = strchr( szFontNameSize, '.' ) + 1 ;
2016:
2017: while (*(str = ParseText(hps, str, TRUE, NULL,
2018: fontsize,
2019: 0.0, TRUE, TRUE)));
2020:
2021: return textwidth ;
2022: }
2023:
2024: void FontExpand( char *name )
2025: {
2026: if ( strcmp(name,"S")==0 ) strcpy( name, "Symbol Set" ) ;
2027: else if( strcmp(name,"H")==0 ) strcpy( name, "Helvetica" ) ;
2028: else if( strcmp(name,"T")==0 ) strcpy( name, "Times New Roman" ) ;
2029: else if( strcmp(name,"C")==0 ) strcpy( name, "Courier" ) ;
2030: }
2031:
2032: /*=======================================*/
2033: static POINTL pCur ;
2034: static int iLinebegin = 1 ;
2035: static int iLtype = 0 ;
2036: static int iState = 0 ;
2037: static double togo = 0.0 ;
2038: static int iPatt[8][9]
2039: = {
2040: { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2041: { 300, 200, -1, 0, 0, 0, 0, 0, 0 },
2042: { 150, 150, -1, 0, 0, 0, 0, 0, 0 },
2043: { 300, 200, 150, 200, -1, 0, 0, 0, 0 },
2044: { 500, 200, -1, 0, 0, 0, 0, 0, 0 },
2045: { 300, 200, 150, 200, 150, 200, -1, 0, 0 },
2046: { 300, 200, 150, 200, 150, 200, 150, 200, -1 },
2047: { 500, 200, 150, 200, -1, 0, 0, 0, 0 }
2048: } ;
2049:
2050: void LMove( HPS hps, POINTL *p )
2051: {
2052: double ds, dx, dy ;
2053: if( iLinebegin ) {
2054: pCur = *p ;
2055: GpiMove( hps, p ) ;
2056: }
2057: else if( iLtype == 0 ) GpiMove( hps, p ) ;
2058: else {
2059: dx = p->x - pCur.x ;
2060: dy = p->y - pCur.y ;
2061: ds = sqrt( dx*dx + dy*dy ) ;
2062: dx /= ds ; dy /= ds ;
2063: while( ds > 0.0 ) {
2064: if( ds < togo ) {
2065: togo -= ds ;
2066: ds = 0.0 ;
2067: GpiMove( hps, p ) ;
2068: pCur = *p ;
2069: }
2070: else {
2071: POINTL pn ;
2072: pn.x = pCur.x + togo * dx ;
2073: pn.y = pCur.y + togo * dy ;
2074: GpiMove( hps, &pn ) ;
2075: pCur = pn ;
2076: ds -= togo ;
2077: iState++ ;
2078: if( iPatt[iLtype][iState] < 0 ) {
2079: togo = iPatt[iLtype][0] ;
2080: iState = 0 ;
2081: }
2082: else togo = iPatt[iLtype][iState] ;
2083: }
2084: }
2085: }
2086: }
2087:
2088: void LLine( HPS hps, POINTL *p )
2089: {
2090: double ds, dx, dy ;
2091: if( iLinebegin ) iLinebegin = 0 ;
2092:
2093: if( iLtype == 0 ) GpiLine( hps, p ) ;
2094: else {
2095: dx = p->x - pCur.x ;
2096: dy = p->y - pCur.y ;
2097: ds = sqrt( dx*dx + dy*dy ) ;
2098: dx /= ds ; dy /= ds ;
2099: while( ds > 0.0 ) {
2100: if( ds < togo ) {
2101: togo -= ds ;
2102: ds = 0.0 ;
2103: if( iState&1 ) GpiMove( hps, p ) ;
2104: else GpiLine( hps, p ) ;
2105: pCur = *p ;
2106: }
2107: else {
2108: POINTL pn ;
2109: pn.x = pCur.x + togo * dx ;
2110: pn.y = pCur.y + togo * dy ;
2111: if( iState&1 ) GpiMove( hps, &pn ) ;
2112: else GpiLine( hps, &pn ) ;
2113: pCur = pn ;
2114: ds -= togo ;
2115: iState++ ;
2116: if( iPatt[iLtype][iState] < 0 ) {
2117: togo = iPatt[iLtype][0] ;
2118: iState = 0 ;
2119: }
2120: else togo = iPatt[iLtype][iState] ;
2121: }
2122: }
2123: }
2124: }
2125:
2126: void LType( int iType )
2127: {
2128: iLinebegin = 1 ;
2129: if( iType > 7 ) iType = 0 ;
2130: iLtype = iType ;
2131: iState = 0 ;
2132: togo = iPatt[iLtype][0] ;
2133: }
2134:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>