/*****************************************************************************/ /* PlotSpi.c This little (and simple-minded) plotting package was developed to support the HyperSpi application. It allows simple, two-colour (black on white) graphs to be created in memory (as pixmaps). The bit-manipulation routines are long- word aligned (in an attempt to make AXP systems efficient). The function parameter 'PlotOperation' specifies whether the the pixel will be turned on, turned off or changed to the complement of the existing pixel (logical exclusive-OR). BUILD_DETAILS ------------- See BUILD_HYPERSPI.COM VERSION HISTORY --------------- 21-MAY-2011 MGD maintenance 01-AUG-1997 MGD general maintenance in line with hyperspi.c 20-JUN-1995 MGD initial development */ /*****************************************************************************/ /* standard C header files */ #include #include #include #include /***************/ /* definitions */ /***************/ #define boolean int #define true 1 #define false 0 #define VMSok(x) ((x) & STS$M_SUCCESS) #define VMSnok(x) !(((x) & STS$M_SUCCESS)) #ifdef __VMS /* vaxc$errno will be an extern int */ # define ERROR_VALUE vaxc$errno #else # define ERROR_VALUE errno #endif #define PLOT_ON 0 #define PLOT_OFF 1 #define PLOT_XOR 2 const int LongBits = sizeof(unsigned long) * 8; boolean DoPlotDiagnostic; int PlotAreaX, PlotAreaY, PlotScaleX, PlotScaleY; char *GraphPtr; extern boolean Debug; extern int RecordSampleRate, FromHour, SizeOfPlotX, SizeOfPlotY, SizeOfMarginX, SizeOfMarginY, XMag, YMag; extern char Utility[]; /*****************************************************************************/ /* Allocate enough memory to accomodate the X by Y graph, pointed to by global storage 'GraphPtr'. Set global storage 'PlotAreaX' and 'PlotAreaY' to the respective sizes of the graph (note that the actual maximum plot point of each of these is one less). */ PlotAllocate ( int XSize, int YSize ) { int BytesRequired; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "PlotAllocate() %d,%d\n", XSize, YSize); PlotAreaX = XSize; PlotAreaY = YSize; /* bits in plot area, divided by bits/per byte, + rounding error allowance */ BytesRequired = ((PlotAreaX * PlotAreaY) / 8) + 4; if (Debug) fprintf (stdout, "BytesRequired: %d long-words: %d\n", BytesRequired, BytesRequired/4); if ((GraphPtr = (char*)malloc (BytesRequired)) == NULL) FatalError ("MALLOC", "error allocating graph memory", ERROR_VALUE); memset (GraphPtr, 0, BytesRequired); } /*****************************************************************************/ /* Place a box surrounding the area specified by 'XSize' and 'YSize' offset from 0,0 by the 'XOrigin' and 'YOrigin'. Note that this box is actually outside the area specified by 'XSize' and 'YSize'. Place graduation points alongside each axis. */ PlotAxes (int PlotOperation) { int hr, cnt, x, y, XSize, YSize, YGraduation; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "PlotAxes()\n"); XSize = SizeOfPlotX + XMag - 1; YSize = SizeOfPlotY + YMag - 1; PlotLineX (PlotOperation, -1, XSize+1, -1, SizeOfMarginX, SizeOfMarginY); PlotLineX (PlotOperation, -1, XSize+1, YSize+1, SizeOfMarginX, SizeOfMarginY); PlotLineY (PlotOperation, -1, YSize+1, -1, SizeOfMarginX, SizeOfMarginY); PlotLineY (PlotOperation, -1, YSize+1, XSize+1, SizeOfMarginX, SizeOfMarginY); /* place graduation along X axis */ hr = FromHour + 1; x = (cnt = 1) * 60 * XMag / RecordSampleRate; while (x < XSize+1) { for (y = -5; y < -1; y++) PlotPixel (PlotOperation, x, y, SizeOfMarginX, SizeOfMarginY); if (hr > 23) { y = -12; PlotPixel (PlotOperation, x-1, y, SizeOfMarginX, SizeOfMarginY); PlotPixel (PlotOperation, x+1, y, SizeOfMarginX, SizeOfMarginY); for (; y < -1; y++) PlotPixel (PlotOperation, x, y, SizeOfMarginX, SizeOfMarginY); hr = 0; } else if (hr == 12) { for (y = -10; y < -1; y++) PlotPixel (PlotOperation, x, y, SizeOfMarginX, SizeOfMarginY); } else if (!(hr % 6)) { for (y = -8; y < -1; y++) PlotPixel (PlotOperation, x, y, SizeOfMarginX, SizeOfMarginY); } hr++; x = ++cnt * 60 * XMag / RecordSampleRate; } if (PlotScaleY % 2) YGraduation = 20 * YMag; else if (PlotScaleY == 50) YGraduation = 20 * YMag; else if (PlotScaleY == 250) YGraduation = 20 * YMag; else if (PlotScaleY == 500) YGraduation = 20 * YMag; else if (PlotScaleY == 2500) YGraduation = 20 * YMag; else if (PlotScaleY == 5000) YGraduation = 20 * YMag; else YGraduation = 10 * YMag; /* place graduation along Y axis */ for (y = YGraduation; y < YSize+1; y += YGraduation) for (x = -6; x < -1; x++) PlotPixel (PlotOperation, x, y, SizeOfMarginX, SizeOfMarginY); if (PlotScaleY % 2 || PlotScaleY == 250 || PlotScaleY == 2500) return; /* place intermediate graduation along Y axis */ for (y = (YGraduation/2); y < YSize+1; y += YGraduation) for (x = -4; x < -1; x++) PlotPixel (PlotOperation, x, y, SizeOfMarginX, SizeOfMarginY); } /*****************************************************************************/ /* */ PlotPixel ( int PlotOperation, int AtX, int AtY, int XOrigin, int YOrigin ) { int Bit, LongWord; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "PlotPixel() %d,%d %d,%d\n", AtX, AtY, XOrigin, YOrigin); AtX += XOrigin; AtY += YOrigin; if (AtX < 0) { PlotDiagnostic ("PlotPixel() X coordinate less than zero", AtX); AtX = 0; } if (AtX >= PlotAreaX) { PlotDiagnostic ("PlotPixel() X coordinate out of range", AtX); AtX = PlotAreaX-1; } if (AtY < 0) { PlotDiagnostic ("PlotPixel() Y coordinate less than zero", AtY); AtY = 0; } if (AtY >= PlotAreaY || AtY < 0) { PlotDiagnostic ("PlotPixel() Y coordinate out of range", AtY); AtY = PlotAreaY-1; } AtY = PlotAreaY - AtY - 1; LongWord = (Bit = AtX + (AtY * PlotAreaX)) / LongBits; Bit %= LongBits; if (!PlotOperation) ((unsigned long*)GraphPtr)[LongWord] |= 1 << Bit; else if (PlotOperation == PLOT_XOR) ((unsigned long*)GraphPtr)[LongWord] ^= 1 << Bit; else ((unsigned long*)GraphPtr)[LongWord] &= ~(1 << Bit); } /*****************************************************************************/ /* */ PlotLineX ( int PlotOperation, int FromX, int ToX, int AtY, int XOrigin, int YOrigin ) { int AtX, Bit, CurrentLongWord, LongWord; unsigned long Pixels; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "PlotLineX() FromX: %d ToX: %d AtY: %d %d,%d\n", FromX, ToX, AtY, XOrigin, YOrigin); FromX += XOrigin; ToX += XOrigin; AtY += YOrigin; if (FromX < 0) { PlotDiagnostic ("PlotLineX() start X coordinate less than zero", FromX); FromX = 0; } if (FromX >= PlotAreaX) { PlotDiagnostic ("PlotLineX() start X coordinate out of range", FromX); FromX = PlotAreaX-1; } if (ToX < 0) { PlotDiagnostic ("PlotLineX() end X coordinate less than zero", ToX); ToX = 0; } if (ToX >= PlotAreaX) { PlotDiagnostic ("PlotLineX() end X coordinate out of range", ToX); ToX = PlotAreaX-1; } if (AtY < 0) { PlotDiagnostic ("PlotLineX() Y coordinate less than zero", AtY); AtY = 0; } if (AtY >= PlotAreaY) { PlotDiagnostic ("PlotLineX() Y coordinate out of range", AtY); AtY = PlotAreaY-1; } if (FromX > ToX) { int Temp; Temp = FromX; FromX = ToX; ToX = Temp; } CurrentLongWord = -1; AtY = PlotAreaY - AtY - 1; for (AtX = FromX; AtX <= ToX; AtX++) { LongWord = (Bit = AtX + (AtY * PlotAreaX)) / LongBits; Bit %= LongBits; if (CurrentLongWord != LongWord) { if (CurrentLongWord != -1) ((unsigned long*)GraphPtr)[CurrentLongWord] = Pixels; Pixels = ((unsigned long*)GraphPtr)[CurrentLongWord = LongWord]; } if (!PlotOperation) Pixels |= 1 << Bit; else if (PlotOperation == PLOT_XOR) Pixels ^= 1 << Bit; else Pixels &= ~(1 << Bit); } if (CurrentLongWord != -1) { if (Debug) fprintf (stdout, "storing: %d\n", CurrentLongWord); ((unsigned long*)GraphPtr)[CurrentLongWord] = Pixels; } } /*****************************************************************************/ /* */ PlotLineY ( int PlotOperation, int FromY, int ToY, int AtX, int XOrigin, int YOrigin ) { int Bit, AtY, LongWord; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "PlotLineY() FromY: %d ToY: %d AtX: %d %d,%d\n", FromY, ToY, AtX, XOrigin, YOrigin); FromY += YOrigin; ToY += YOrigin; AtX += XOrigin; if (FromY < 0) { PlotDiagnostic ("PlotLineY() start Y coordinate less than zero", FromY); FromY = 0; } if (FromY >= PlotAreaY) { PlotDiagnostic ("PlotLineY() start Y coordinate out of range", FromY); FromY = PlotAreaY-1; } if (ToY < 0) { PlotDiagnostic ("PlotLineY() end Y coordinate less than zero", ToY); ToY = 0; } if (ToY >= PlotAreaY) { PlotDiagnostic ("PlotLineY() end Y coordinate out of range", ToY); ToY = PlotAreaY-1; } if (AtX < 0) { PlotDiagnostic ("PlotLineY() X coordinate less than zero", AtX); AtX = 0; } if (AtX >= PlotAreaX) { PlotDiagnostic ("PlotLineY() X coordinate out of range", AtX); AtX = PlotAreaX-1; } if (FromY > ToY) { int Temp; Temp = FromY; FromY = ToY; ToY = Temp; } FromY = PlotAreaY - FromY - 1; ToY = PlotAreaY - ToY - 1; for (AtY = FromY; AtY >= ToY; AtY--) { LongWord = (Bit = AtX + (AtY * PlotAreaX)) / LongBits; Bit %= LongBits; if (!PlotOperation) ((unsigned long*)GraphPtr)[LongWord] |= 1 << Bit; else if (PlotOperation == PLOT_XOR) ((unsigned long*)GraphPtr)[LongWord] ^= 1 << Bit; else ((unsigned long*)GraphPtr)[LongWord] &= ~(1 << Bit); } } /*****************************************************************************/ /* */ PlotDiagnostic ( char *Description, int Value ) { if (!DoPlotDiagnostic) return; fprintf (stdout, "DIAGNOSTIC; %s: %d\n", Description, Value); } /*****************************************************************************/ /* */ FatalError ( char *Identifier, char *Description, int ErrorValue ) { /*********/ /* begin */ /*********/ #ifdef __VMS fprintf (stdout, "%%%s-E-%s, %s\n", Utility, Identifier, Description); if (ErrorValue) exit (ErrorValue); else exit (2 | 0x10000000); #else if (ErrorValue) fprintf (stdout, "%s: %s: %s\n", Utility, Description, strerror(ErrorValue)); else fprintf (stdout, "%s: %s\n", Utility, Description); exit (1); #endif } /*****************************************************************************/