/*
 * @(#)xwin.h
 *
 * Copyright 2005 - 2017  David A. Bagley, bagleyd AT verizon.net
 *
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of the author not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 *
 * This program is distributed in the hope that it will be "useful",
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

/* Header file for xwin */

#ifndef _xwin_h
#define _xwin_h

#define NUM_DEGREES 360
#define FILE_NAME_LENGTH 1024
#define TITLE_FILE_LENGTH (FILE_NAME_LENGTH+8)
#define TITLE_LENGTH 2048

#ifdef WINVER
#define STRICT

#include <windows.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#if ((WINVER > 0x030a) && !defined(GCL_HBRBACKGROUND) && !defined(GCLP_HBRBACKGROUND))
#undef WINVER
#define WINVER 0x030a
#endif
#if (WINVER <= 0x030a)		/* if WINDOWS 3.1 or less */
#define Position int
#define SETBACK(h,b) (void)SetClassWord(h,GCW_HBRBACKGROUND,(WORD)b)
#define MoveTO(h,x,y,lp) MoveTo(h,x,y)
#else
#define Position long
#ifdef GCLP_HBRBACKGROUND
#define SETBACK(h,b) (void)SetClassLongA(h,GCLP_HBRBACKGROUND,(LONG)(intptr_t)b)
#else
#define SETBACK(h,b) (void)SetClassLong(h,GCL_HBRBACKGROUND,(LONG)b)
#endif
#define MoveTO(h,x,y,lp) MoveToEx(h,x,y,lp)
#endif
#ifndef Point
#define Point POINT
#endif
#ifndef Boolean
#define Boolean BOOL
#endif
#ifndef True
#define True TRUE
#endif
#ifndef False
#define False FALSE
#endif
#ifndef None
#define None NULL
#endif
#ifndef XtPointer
#define XtPointer void *
#endif
#define GC COLORREF  /* Equate apples to oranges */
#define Pixmap HBITMAP
#define FULL_CIRCLE NUM_DEGREES

#undef RGB
#define RGB(r,g,b) ((COLORREF)(((DWORD)(r)|((DWORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
#define FLUSH(w) ;
#define DC(w,dr) ((dr==0)?w->core.hDC:w->core.memDC)
#define LINE(w,x1,y1,x2,y2) (void)MoveTO(w,x1,y1,NULL); \
  (void)LineTo(w,x2,y2)
#define DRAWLINE(w,dr,c,x1,y1,x2,y2) \
  if (dr) w->core.hOldBitmap = \
  (HBITMAP) SelectObject(w->core.memDC,dr); \
  w->core.hPen = CreatePen(PS_SOLID, 1, c); \
  w->core.hOldPen = (HPEN) SelectObject(DC(w,dr), w->core.hPen); \
  SetPixel(DC(w,dr),x2,y2,c); \
  LINE(DC(w,dr),x1,y1,x2,y2); \
  (void) SelectObject(DC(w,dr), w->core.hOldPen); \
  (void) DeleteObject(w->core.hPen); \
  if (dr) (void) SelectObject(w->core.memDC,w->core.hOldBitmap)
#define RECTANGLE(w,x,y,l,h) (void)Rectangle(w,x,y,x+l,y+h)
#define DRAWRECTANGLE(w,dr,c,x,y,l,h) \
  if (dr) w->core.hOldBitmap = (HBITMAP) SelectObject(w->core.memDC,dr); \
  w->core.hPen = CreatePen(PS_SOLID,1,c); \
  w->core.hOldPen = (HPEN) SelectObject(DC(w,dr),w->core.hPen); \
  RECTANGLE(DC(w,dr),x,y,(l)+1,(h)+1); \
  (void) SelectObject(DC(w,dr),w->core.hOldPen); \
  (void) DeleteObject(w->core.hPen); \
  if (dr) (void) SelectObject(w->core.memDC,w->core.hOldBitmap)
#define FILLRECTANGLE(w,dr,c,x,y,l,h) \
  if (dr) w->core.hOldBitmap = (HBITMAP) SelectObject(w->core.memDC,dr); \
  w->core.hPen = CreatePen(PS_SOLID,1,c); \
  w->core.hOldPen = (HPEN) SelectObject(DC(w,dr),w->core.hPen); \
  w->core.hBrush = CreateSolidBrush(c); \
  w->core.hOldBrush = (HBRUSH) SelectObject(DC(w,dr),w->core.hBrush); \
  if (l==1&&h==1) SetPixel(DC(w,dr),x,y,c); \
  RECTANGLE(DC(w,dr),x,y,l,h); \
  (void) SelectObject(DC(w,dr),w->core.hOldBrush); \
  (void) DeleteObject(w->core.hBrush); \
  (void) SelectObject(DC(w,dr),w->core.hOldPen); \
  (void) DeleteObject(w->core.hPen); \
  if (dr) (void) SelectObject(w->core.memDC,w->core.hOldBitmap)
#define FILLRECTANGLE2(w,dr,c,cl,x,y,l,h) \
  if (dr) w->core.hOldBitmap = (HBITMAP) SelectObject(w->core.memDC,dr); \
  w->core.hPen = CreatePen(PS_SOLID,1,cl); \
  w->core.hOldPen = (HPEN) SelectObject(w->core.hDC, w->core.hPen); \
  w->core.hBrush = CreateSolidBrush(c); \
  w->core.hOldBrush = (HBRUSH) SelectObject(w->core.hDC, w->core.hBrush); \
  RECTANGLE(DC(w,dr),x,y,(l)+1,(h)+1); \
  (void) SelectObject(w->core.hDC, w->core.hOldBrush); \
  (void) DeleteObject(w->core.hBrush); \
  (void) SelectObject(w->core.hDC, w->core.hOldPen); \
  (void) DeleteObject(w->core.hPen); \
  if (dr) (void) SelectObject(w->core.memDC,w->core.hOldBitmap)
#define CIRCLE(w,r,x,y) if(r>0) \
 (void)Ellipse(w,x-r+1,y-r+1,x+r,y+r)
#define DRAWCIRCLE(w,dr,c,d,x,y) \
  if (dr) w->core.hOldBitmap = (HBITMAP) SelectObject(w->core.memDC,dr); \
  w->core.hPen = CreatePen(PS_SOLID,1,c); \
  w->core.hOldPen = (HPEN) SelectObject(DC(w,dr),w->core.hPen); \
  w->core.hBrush = CreateSolidBrush(c); \
  w->core.hOldBrush = (HBRUSH) SelectObject(DC(w,dr),w->core.hBrush); \
  CIRCLE(DC(w,dr),(((d+(d+1)%2)>>1)+1),(x),(y)); \
  (void) SelectObject(DC(w,dr),w->core.hOldBrush); \
  (void) DeleteObject(w->core.hBrush); \
  (void) SelectObject(DC(w,dr),w->core.hOldPen); \
  (void) DeleteObject(w->core.hPen); \
  if (dr) (void) SelectObject(w->core.memDC,w->core.hOldBitmap)
#define FILLCIRCLE(w,dr,c,d,x,y) \
  w->core.hOldBitmap = (HBITMAP) SelectObject(w->core.memDC,dr); \
  w->core.hPen = CreatePen(PS_SOLID,1,c); \
  w->core.hOldPen = (HPEN) SelectObject(DC(w,dr),w->core.hPen); \
  w->core.hBrush = CreateSolidBrush(c); \
  w->core.hOldBrush = (HBRUSH) SelectObject(DC(w,dr),w->core.hBrush); \
  CIRCLE(DC(w,dr),(((d+(d+1)%2)>>1)+1),(x),(y)); \
  (void) SelectObject(DC(w,dr),w->core.hOldBrush); \
  (void) DeleteObject(w->core.hBrush); \
  (void) SelectObject(DC(w,dr),w->core.hOldPen); \
  (void) DeleteObject(w->core.hPen); \
  if (dr) (void) SelectObject(w->core.memDC,w->core.hOldBitmap)
#define ARC(w,x,y,l,h,a1,a2) if (a2 > 0) Arc(w,x,y,x+l,y+h, \
  (int) (cos(M_PI * (a1) / 180) * (l) + x + ((l)>>1)), \
  (int) (-sin(M_PI * (a1) / 180) * (h) + y + ((h)>>1)), \
  (int) (cos(M_PI * (a1+a2) / 180) * (l) + x + ((l)>>1)), \
  (int) (-sin(M_PI * (a1+a2) / 180) * (h) + y + ((h)>>1))); \
  else Arc(w,x,y,x+l,y+h, \
  (int) (cos(M_PI * (a1+a2) / 180) * (l) + x + ((l)>>1)), \
  (int) (-sin(M_PI * (a1+a2) / 180) * (h) + y + ((h)>>1)), \
  (int) (cos(M_PI * (a1) / 180) * (l) + x + ((l)>>1)), \
  (int) (-sin(M_PI * (a1) / 180) * (h) + y + ((h)>>1)))
#define DRAWARC(w,dr,c,t,x,y,l,h,a1,a2) \
  if (dr) w->core.hOldBitmap = (HBITMAP) SelectObject(w->core.memDC,dr); \
  w->core.hPen = CreatePen(PS_SOLID,t,c); \
  w->core.hOldPen = (HPEN) SelectObject(DC(w,dr),w->core.hPen); \
  ARC(DC(w,dr),x,y,l,h,a1,a2); \
  (void) SelectObject(DC(w,dr),w->core.hOldPen); \
  (void) DeleteObject(w->core.hPen); \
  if (dr) (void) SelectObject(w->core.memDC,w->core.hOldBitmap)
/* PS_ENDCAP_FLAT not seem to work in wine */
#define DRAWARC2(w,dr,c,t,x,y,l,h,a1,a2) \
  if (dr) w->core.hOldBitmap = (HBITMAP) SelectObject(w->core.memDC,dr); \
  {LOGBRUSH lb; lb.lbStyle = BS_SOLID; lb.lbColor = c; lb.lbHatch = 0; \
  w->core.hPen = \
  ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT, (unsigned int) t, \
  &lb, 0, NULL); \
  w->core.hOldPen = (HPEN) SelectObject(w->core.hDC, w->core.hPen); \
  ARC(DC(w,dr),x,y,l,h,a1,a2); \
  (void) SelectObject(w->core.hDC, w->core.hOldPen); \
  (void) DeleteObject(w->core.hPen); } \
  if (dr) (void) SelectObject(w->core.memDC,w->core.hOldBitmap)
#define PIE(w,x,y,l,h,a1,a2) if (a2 > 0) Pie(w->core.hDC,x,y,x+l,y+h, \
  (int) (cos(M_PI * (a1) / 180) * (l) + x + ((l)>>1)), \
  (int) (-sin(M_PI * (a1) / 180) * (h) + y + ((h)>>1)), \
  (int) (cos(M_PI * (a1+a2) / 180) * (l) + x + ((l)>>1)), \
  (int) (-sin(M_PI * (a1+a2) / 180) * (h) + y + ((h)>>1))); \
  else Pie(w->core.hDC,x,y,x+l,y+h, \
  (int) (cos(M_PI * (a1+a2) / 180) * (l) + x + ((l)>>1)), \
  (int) (-sin(M_PI * (a1+a2) / 180) * (h) + y + ((h)>>1)), \
  (int) (cos(M_PI * (a1) / 180) * (l) + x + ((l)>>1)), \
  (int) (-sin(M_PI * (a1) / 180) * (h) + y + ((h)>>1)))
#define DRAWPIE(w,c,x,y,l,h,a1,a2) w->core.hPen = CreatePen(PS_SOLID, 1, c); \
  w->core.hOldPen = (HPEN) SelectObject(w->core.hDC, w->core.hPen); \
  w->core.hBrush = CreateSolidBrush(c); \
  w->core.hOldBrush = (HBRUSH) SelectObject(w->core.hDC, w->core.hBrush); \
  PIE(w,x,y,l,h,a1,a2); \
  (void) SelectObject(w->core.hDC, w->core.hOldBrush); \
  (void) DeleteObject(w->core.hBrush); \
  (void) SelectObject(w->core.hDC, w->core.hOldPen); \
  (void) DeleteObject(w->core.hPen)
#define DRAWTEXT(w,dr,c,x,y,s,l) \
  if (dr) w->core.hOldBitmap = (HBITMAP) SelectObject(w->core.memDC,dr); \
  (void) SetTextColor(DC(w,dr), c); \
  (void) SetBkMode(DC(w,dr), TRANSPARENT); \
  (void) TextOut(DC(w,dr), (x)-3, (y)-11, (LPCSTR) s, l); \
  if (dr) (void) SelectObject(w->core.memDC,w->core.hOldBitmap)
#define POLYGON(w,dr,c,lc,l,n,v,o) \
  if (dr) (w)->core.hOldBitmap = (HBITMAP) SelectObject((w)->core.memDC,dr); \
  FILLPOLYGON(DC((w),dr),&((w)->core.hPen),&((w)->core.hOldPen), \
  &((w)->core.hBrush),&((w)->core.hOldBrush),c,lc, \
  l,n,o); \
  if (dr) (void) SelectObject((w)->core.memDC,(w)->core.hOldBitmap)
#define POLYGON2 POLYGON
#define POLYLINE(w,dr,c,l,n,o) \
  if (dr) (w)->core.hOldBitmap = (HBITMAP) SelectObject((w)->core.memDC,dr); \
  DRAWPOLYLINE(DC((w),dr),&((w)->core.hPen),&((w)->core.hOldPen), \
  c,l,n,o); \
  if (dr) (void) SelectObject((w)->core.memDC,(w)->core.hOldBitmap)

extern void FILLPOLYGON(HDC hDC, HPEN *hPen, HPEN *hOldPen,
	HBRUSH *hBrush, HBRUSH *hOldBrush,
	GC color, GC lineColor, const POINT *poly, int n,
	Boolean origin);
extern void DRAWPOLYLINE(HDC hDC, HPEN *hPen, HPEN *hOldPen,
	GC color, const POINT *poly, int n,
	Boolean origin);

#define DISPLAY_INFO(s) (void) MessageBox(w->core.hWnd, s, "Info", MB_OK)
#if 0
#define DISPLAY_WARNING(s) (void) fprintf(stderr, s)
#else
#define DISPLAY_WARNING(s) (void) MessageBox(w->core.hWnd, (LPCSTR) s, \
  "Warning", MB_OK)
#endif
#define DISPLAY_ERROR(s) (void) fprintf(stderr, "%s\n", s); exit(1)

typedef struct _CorePart {
	HWND        hWnd;
	HDC         hDC;
	HINSTANCE   hInstance;
	Position    width, height;
	HDC         memDC;
	HPEN        hOldPen, hPen;
	HBRUSH      hOldBrush, hBrush;
	HBITMAP     hOldBitmap;
	HMENU       hMenu;
} CorePart;

#else

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <math.h>
#ifdef VMS
#include <unixlib.h>
#else
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
#if HAVE_FCNTL_H
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#include <X11/IntrinsicP.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/CoreP.h>
#include <X11/Xos.h>

#if 1
#define VOID
#else
#define VOID (void)
#endif
#ifndef Point
#define Point XPoint
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define MULT 64
#define FULL_CIRCLE (NUM_DEGREES*MULT)
#define FLUSH(w) VOID XFlush(XtDisplay(w))
#define DR(w,dr) ((dr==0)?XtWindow(w):dr)
#define DRAWLINE(w,dr,c,x1,y1,x2,y2) VOID XDrawLine(XtDisplay(w),DR(w,dr),\
  c,x1,y1,x2,y2)
#define DRAWRECTANGLE(w,dr,c,i,j,l,h) VOID XDrawRectangle(XtDisplay(w),\
  DR(w,dr),c,i,j,l,h)
#define FILLRECTANGLE(w,dr,c,i,j,l,h) VOID XFillRectangle(XtDisplay(w),\
  DR(w,dr),c,i,j,l,h)
#define FILLRECTANGLE2(w,dr,c,cl,i,j,l,h) VOID XFillRectangle(XtDisplay(w),\
  DR(w,dr),c,i,j,l,h);\
  VOID XDrawRectangle(XtDisplay(w),DR(w,dr),cl,i,j,l,h)
#define DRAWCIRCLE(w,dr,c,d,x,y) if(d>0) VOID XDrawArc(XtDisplay(w),\
  DR(w,dr),c,x-((d)>>1),y-((d)>>1),d,d,0,FULL_CIRCLE)
#define FILLCIRCLE(w,dr,c,d,x,y) if(d>0) VOID XFillArc(XtDisplay(w),\
  DR(w,dr),c,x-((d)>>1),y-((d)>>1),d,d,0,FULL_CIRCLE)
#define DRAWARC(w,dr,c,t,x,y,l,h,a1,a2) \
  if(t>1)XSetLineAttributes(XtDisplay(w),c,t,LineSolid,CapNotLast,JoinRound);\
  VOID XDrawArc(XtDisplay(w),DR(w,dr),c,x,y,l,h,(a1)*MULT,(a2)*MULT);\
  if(t>1)XSetLineAttributes(XtDisplay(w),c,1,LineSolid,CapNotLast,JoinRound)
#define DRAWTEXT(w,dr,c,x,y,s,l) VOID XDrawString(XtDisplay(w),DR(w,dr),\
  c,x,y,s,l)
#define POLYGON(w,dr,c,lc,l,n,v,o) VOID XFillPolygon(XtDisplay(w),DR(w,dr),\
  c,l,n,(v)?Convex:Complex,(o)?CoordModeOrigin:CoordModePrevious); \
  VOID XDrawLines(XtDisplay(w),DR(w,dr),lc,\
  l,(n)+1,(o)?CoordModeOrigin:CoordModePrevious)
#define POLYGON2(w,dr,c,lc,l,n,v,o) VOID XFillPolygon(XtDisplay(w),\
  DR(w,dr),c,l,n,\
  (v) ? Convex:Complex, (o)?CoordModeOrigin:CoordModePrevious);\
  VOID XDrawLines(XtDisplay(w),DR(w,dr),lc,\
  l,n,(o)?CoordModeOrigin:CoordModePrevious)
#define POLYLINE(w,dr,c,l,n,o) VOID XDrawLines(XtDisplay(w),DR(w,dr),c,\
  l,n,(o)?CoordModeOrigin:CoordModePrevious)

#define DISPLAY_INFO(s) XtWarning(s)
#define DISPLAY_WARNING(s) XtWarning(s)
#define DISPLAY_ERROR(s) XtError(s)

#endif

extern void intCat(char **string, const char *var1, const int var2);
extern void stringCat(char **string, const char *var1, const char *var2);
extern void intCpy(char *string, const int var);

#define ABS(a) (((a)<0)?(-(a)):(a))
#define SIGN(a) (((a)<0)?(-1):1)
#define MIN(a,b) (((int)(a)<(int)(b))?(int)(a):(int)(b))
#define MAX(a,b) (((int)(a)>(int)(b))?(int)(a):(int)(b))

#endif /* _xwin_h */
