+/* This is a screen print program for MMURTL. It runs\r
+ like any other application on the system except it\r
+ looks for a Global Hot key (CTRL-ALT-PrintScreen)\r
+ and prints the REAL screen to LPT1 or a file.\r
+\r
+ The screen print is straight text with CR/LF at the\r
+ end of each line. Nulls and non-printable characters\r
+ are converted to spaces.\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include "\OSSource\MKernel.h"\r
+#include "\OSSource\MJob.h"\r
+#include "\OSSource\MVid.h"\r
+#include "\OSSource\MData.h"\r
+#include "\OSSource\MTimer.h"\r
+#include "\OSSource\MDevDrv.h"\r
+#include "\OSSource\Parallel.h"\r
+\r
+#define ErcOK 0\r
+\r
+struct RqBlkType *pRqBlk; /* A pointer to a Reqeust Block */\r
+unsigned long AnExch; /* Where we wait for Requests */\r
+unsigned long Message[2]; /* The Message with the Request */\r
+long rqHndlG; /* Used for global print request */\r
+long rqHndlK; /* Used for keyboard request */\r
+long cbFilename;\r
+char Filename[80];\r
+char fToFile = 0;\r
+long ourJob, printJob;\r
+\r
+FILE *fh;\r
+\r
+long keycode, keycodeG;\r
+\r
+unsigned char buf[4160]; /* for a snapshot of the screen */\r
+\r
+/***************************************************\r
+ Copies active screen memory to a working buffer.\r
+ and beeps to let user know it's been done.\r
+***************************************************/\r
+void CaptureScreen(void)\r
+{\r
+ CopyData(0xB8000, buf, 4000);\r
+ Tone(1000,15); /* 1000 Hz for 100ms */\r
+ Tone(300,15); /* 300 Hz for 100ms */\r
+}\r
+\r
+\r
+/***************************************************\r
+ This filles all nulls and NON ASCII chars in\r
+ the capture buffer with spaces.\r
+****************************************************/\r
+\r
+ProcessScreen(void)\r
+{\r
+long i;\r
+ for (i=0; i<4000; i+=2)\r
+ {\r
+ if ((buf[i] < 0x20) || (buf[i] > 0x7E))\r
+ buf[i] = ' ';\r
+ }\r
+}\r
+\r
+/***************************************************\r
+ Sends the contents of the processed screen buffer\r
+ to the file the user specified. LF is added to\r
+ each line.\r
+****************************************************/\r
+\r
+void ScreenToFile(FILE *fh)\r
+{\r
+long i, j;\r
+ for (i=0; i<25; i++)\r
+ {\r
+ for (j=0; j<160; j+=2)\r
+ {\r
+ fputc(buf[(i*160)+j], fh);\r
+ }\r
+ fputc(0x0A, fh);\r
+ }\r
+}\r
+\r
+\r
+/***************************************************\r
+ Sends the contents of the processed screen buffer\r
+ to the LPT1 device. CR/LF is added to each line.\r
+****************************************************/\r
+\r
+void ScreenToLPT(void)\r
+{\r
+long erc;\r
+long i, j;\r
+\r
+\r
+ /* If device status went OK, we open the printer port */\r
+\r
+ /* device, dOpNum, dLBA, dnBlocks, pData */\r
+ erc = DeviceOp(3, CmdOpenL, 0, 0, &i);\r
+\r
+ if (erc)\r
+ {\r
+ printf("OpenLPT ERROR: %d \r\n", erc);\r
+ return;\r
+ }\r
+\r
+ for (i=0; i<25; i++)\r
+ {\r
+ for (j=0; j<160; j+=2)\r
+ {\r
+ erc = DeviceOp(3, CmdWriteB, 0, 1, &buf[(i*160)+j]);\r
+ if (erc)\r
+ break;\r
+ }\r
+ erc = DeviceOp(3, CmdWriteB, 0, 1, "\r");\r
+ erc = DeviceOp(3, CmdWriteB, 0, 1, "\n");\r
+ if (erc)\r
+ break;\r
+ }\r
+ erc = DeviceOp(3, CmdWriteB, 0, 1, "\f");\r
+\r
+ if (erc)\r
+ printf("Can't write to LPT. Error: %d\r\n", erc);\r
+\r
+ /* device, dOpNum, dLBA, dnBlocks, pData */\r
+ erc = DeviceOp(3, CmdCloseL, 0, 0, &i);\r
+ if (erc)\r
+ printf("Can't close LPT. Error: %d\r\n", erc);\r
+\r
+}\r
+\r
+\r
+/***************************************************\r
+ Displays the menu after a user does something\r
+****************************************************/\r
+\r
+void menu(void)\r
+{\r
+ printf("CTRL-ALT-PrintScrn will print the screen from any job you're viewing.\r\n");\r
+ printf("Press:\r\n");\r
+ printf(" 1) To direct screen prints to LPT1/Printer (default).\r\n");\r
+ printf(" 2) To direct screen prints to a file.\r\n");\r
+ printf(" 3) To terminte the screen print utility.\r\n\n");\r
+}\r
+\r
+/***************************************************\r
+ Main entry point for SPU.\r
+****************************************************/\r
+\r
+void main(long argc, char *argv[])\r
+{\r
+unsigned long OSError, x, y;\r
+unsigned char c, ExitChar;\r
+\r
+ GetJobNum(&ourJob);\r
+ SetJobName("ScreenPrint", 11);\r
+\r
+ FillData(Filename, 80, ' ');\r
+ cbFilename = 0;\r
+ fToFile = 0;\r
+\r
+ OSError = AllocExch(&AnExch); /* get an exchange */\r
+\r
+ if (OSError) /* look for a kernel error */\r
+ ExitJob(OSError);\r
+\r
+ SetNormVid(WHITE|BGBLACK);\r
+ ClrScr();\r
+\r
+ printf("Screen Print Utility installed as job number: %d.\r\n\n", ourJob);\r
+\r
+ /* Leave a global request for a key with the keyboard service */\r
+\r
+ OSError = Request("KEYBOARD", 2, AnExch, &rqHndlG, 0, &keycodeG,\r
+ 4, 0, 0, 0, 0, 0);\r
+ if (OSError)\r
+ printf("Error %d on Global Keyboard Request\r\n", OSError);\r
+\r
+ OSError = Request("KEYBOARD", 1, AnExch, &rqHndlK, 0, &keycode,\r
+ 4, 0, 0, 1, 0, 0); /* 1 in dData0 = Wait for key */\r
+\r
+ if (OSError)\r
+ printf("Error %d on ReadKey Request\r\n", OSError);\r
+\r
+ menu();\r
+\r
+ while(1)\r
+ {\r
+ /* We now have two requests waiting at the keyboard service.\r
+ One is for the global key, the other is for a ReadKbd.\r
+ When we Wait(), we will get one or the other back. We find\r
+ out which one by checking the handle to see which it matches.\r
+ Eaither someone wants the screen printed or the user\r
+ has selcted a menu item.\r
+ */\r
+\r
+ OSError = WaitMsg(AnExch, Message); /* Exch & pointer */\r
+\r
+ if (!OSError)\r
+ {\r
+\r
+ if (Message[0] == rqHndlK) /* it was a menu item */\r
+ {\r
+\r
+ c = keycode & 0x7f; /* lop off upper stuff in keycode */\r
+ switch (c)\r
+ {\r
+ case '1':\r
+ fToFile = 0;\r
+ printf("Screen print directed to printer (LPT1)\r\n");\r
+ strcpy(Filename, "LPT");\r
+ cbFilename = 3;\r
+ break;\r
+ case '2':\r
+ printf("\r\nEnter filename to print to: ");\r
+ GetXY(&x, &y);\r
+ EditLine(Filename, cbFilename, 50, &cbFilename,\r
+ &ExitChar, BLACK|BGWHITE);\r
+ if ((ExitChar == 0x0d) && (cbFilename))\r
+ {\r
+ Filename[cbFilename] = 0; /* null terminte */\r
+ fToFile = 1;\r
+ }\r
+ else\r
+ fToFile = 0;\r
+ printf("\r\n");\r
+ break;\r
+ case '3':\r
+ /* cancel the global key request */\r
+ OSError = Request("KEYBOARD", 3, AnExch, &rqHndlG, 0, 0,\r
+ 0, 0, 0, ourJob, 0, 0);\r
+ OSError = WaitMsg(AnExch, Message);\r
+ DeAllocExch(AnExch);\r
+ exit(0);\r
+ break;\r
+ }\r
+ /* leave another keyboard request */\r
+ OSError = Request("KEYBOARD", 1, AnExch, &rqHndlK, 0, &keycode,\r
+ 4, 0, 0, 1, 0, 0); /* 1 in dData0 = Wait for key */\r
+ menu();\r
+\r
+ }\r
+ else if (Message[0] == rqHndlG) /* It's a screen print!! */\r
+ {\r
+ if ((keycodeG & 0xff) == 0x1C) /* it's us! */\r
+ {\r
+ CaptureScreen();\r
+ ProcessScreen();\r
+ if (fToFile)\r
+ {\r
+ fh = fopen(Filename, "a");\r
+ if (fh)\r
+ {\r
+ ScreenToFile(fh);\r
+ fclose(fh);\r
+ }\r
+ else\r
+ printf("Can't open file: %s\r\n", Filename);\r
+ }\r
+ else\r
+ ScreenToLPT();\r
+\r
+ GetVidOwner(&printJob);\r
+ if (fToFile)\r
+ printf("Screen print sent to %s for job %d\r\n\n",\r
+ Filename, printJob);\r
+ else\r
+ printf("Screen print sent to LPT1 for job %d\r\n\n",\r
+ printJob);\r
+ menu();\r
+ }\r
+\r
+ /* Leave another global request with the keyboard service */\r
+\r
+ OSError = Request("KEYBOARD", 2, AnExch, &rqHndlG, 0, &keycodeG,\r
+ 4, 0, 0, 0, 0, 0);\r
+\r
+ }\r
+ }\r
+ else\r
+ printf("Error %d on WaitMsg from kernel\r\n", OSError);\r
+ } /* Loop while(1) */\r
+}\r