home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * QUOTE.C *
- * *
- * - Quote randomly chooses a quote from a quote file chosen at random. *
- * The quote chosen is displayed in a window under Presentation Manger. *
- * The quote window may be closed by pressing the right mouse button or *
- * by pressing any key when Quote has the input focus. Optionally, the *
- * quote window may be set to expire after a specified number of minutes. *
- * *
- * "Quote" is copyright (c) 1990 by Todd B. Crowe. There is no warranty *
- * implied or otherwise. You may copy the program freely but it must be *
- * accompanied by this notice. The program may not be sold or distributed *
- * commercially or otherwise for profit. I reserve all rights and *
- * privileges to this program. *
- * *
- ****************************************************************************/
-
- #define INCL_DOS
- #define INCL_GPI
- #define INCL_WIN
-
- #include <os2.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- // Constants
- #define ERR_OK 0 // No errors occured on run
- #define ERR_BADARGS -1 // Bad/missing arguments
- #define ERR_REGCLASS -2 // WinRegisterClass failed
- #define ERR_WININIT -3 // Failure to obtain HAB (is this possible?)
- #define ERR_MSGQUEUE -4 // Failure to obtain HMQ (usually DETACH'd)
- #define ID_TIMER 1 // Timer resource ID
- #define MAXQUOTE 16 // Maximum number of quote files/lines
- #define BUFFERSIZE 2048 // Buffer for quote file name and quote text
-
- // Function prototyping
- MRESULT EXPENTRY ClientWndProc(HWND, USHORT, MPARAM, MPARAM);
- int ProcessArguments(int, char **);
- int ParseTime(CHAR *, SHORT *);
- SHORT ReadQuote(CHAR **,SHORT *);
- VOID SeedRandom(VOID);
-
- // Profile record structure
- typedef struct _PROFILEREC {
- USHORT usSEED;
- } PROFILEREC;
-
- // Pause & display counters
- static SHORT sLength = 0L,sDisplay = 0L;
- static BOOL bDisplay = FALSE;
-
- // Private class name (also used to index profile record)
- static HAB hab;
- static CHAR szClientClass[] = "Quote";
- static CHAR szUsage[] = { "Quote - (c)1990 by Todd Crowe\n"
- "USAGE: QUOTE [-{?|Ln|Ttime|Dn}]\n" };
-
- int main(int argc, char **argv)
- {
- static ULONG flFrameFlags = FCF_DLGBORDER | FCF_TASKLIST;
-
- HMQ hmq;
- QMSG qmsg;
- HWND hwndFrame,hwndClient;
- int err;
-
- // Process command line arguments
- err = ProcessArguments(argc,argv);
-
- // Initialize PM interface
- if ((hab = WinInitialize(0)) == NULL) return(ERR_WININIT);
- if ((hmq = WinCreateMsgQueue(hab, 0)) == NULL) return(ERR_MSGQUEUE);
-
- // Check to see if the arguments were bad or '-?' was used
- // if so, put up a message box explaning the proper usage
- if (err == ERR_BADARGS) {
- WinMessageBox(HWND_DESKTOP,NULL,szUsage,szClientClass,0,
- MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
- return(ERR_BADARGS);
- }
-
- // Create a private window class for client window, process messages,
- // and when complete destroy the client window
- else {
- WinRegisterClass(hab, szClientClass, ClientWndProc, CS_SYNCPAINT, 0);
-
- hwndFrame = WinCreateStdWindow(HWND_DESKTOP, 0L, &flFrameFlags,
- szClientClass, NULL, 0L, 0, 0, &hwndClient);
-
- // Start timer ticking once every minute
- WinStartTimer(hab,hwndClient,ID_TIMER,(USHORT)60000);
-
- while (WinGetMsg(hab, &qmsg, NULL, 0, 0))
- WinDispatchMsg(hab, &qmsg);
-
- // Stop the timer
- WinStopTimer(hab,hwndClient,ID_TIMER);
-
- WinDestroyWindow(hwndClient);
- }
-
- // Cleanup
- WinDestroyMsgQueue(hmq);
- WinTerminate(hab);
- return(ERR_OK);
- }
-
- /****************************************************************************
- * ClientWndProc *
- * *
- * Standard PM procedure to handle client window messages. Sizes window *
- * to fit text, draws text in the window, waits for input to terminate. *
- ****************************************************************************/
- MRESULT EXPENTRY ClientWndProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
- {
- SHORT i;
-
- POINTL ptl;
- HPS hps;
- SWP swp;
-
- static SHORT cLines, // Count of quote lines to print
- cLen; // Maximum quote line length
- static CHAR *szLines[MAXQUOTE]; // Pointers to quote lines
- static FONTMETRICS fm;
-
- switch (msg) {
- case WM_CREATE:
- // Read one quote, terminate in case of an error
- if ((cLines = ReadQuote(szLines,&cLen)) == 0) {
- WinPostMsg(hwnd, WM_QUIT, (MPARAM) 0L, (MPARAM) 0L);
- return 0;
- }
-
- if (sLength != 0)
- return 0;
-
- case WM_TIMER:
- // If the window is visible and display time has expired, quit
- if (bDisplay) {
- if (--sDisplay <= 0)
- WinPostMsg(hwnd, WM_QUIT, (MPARAM) 0L, (MPARAM) 0L);
- return 0;
- }
- // Else, if the pause time has expired then display the quote
- else if (--sLength > 0)
- return 0;
-
- // Was display length was set
- if (sDisplay > 0)
- bDisplay = TRUE;
-
- hps = WinGetPS(hwnd);
-
- // Find the DESKTOP Dimensions
- WinQueryWindowPos(HWND_DESKTOP, &swp);
-
- // Get the dimensions of the current font
- GpiQueryFontMetrics(hps, (LONG) sizeof fm, &fm);
-
- // Calculate a window width based on the average width of the
- // current character set.
- i = ((SHORT) fm.lAveCharWidth * cLen) +
- ((SHORT) fm.lAveCharWidth * cLen) / 6;
-
- // Size & Center the window to fit the quote
- WinSetWindowPos(
- WinQueryWindow(hwnd, QW_PARENT, FALSE), HWND_TOP,
- max((swp.cx-i)/2,4),
- max((swp.cy-(cLines * (SHORT) fm.lMaxBaselineExt))/2,4),
- min(i, swp.cx-8),
- min(cLines * (SHORT) fm.lMaxBaselineExt +
- 2 * (SHORT) fm.lMaxDescender + 1, swp.cy-8),
- SWP_ACTIVATE | SWP_SHOW | SWP_SIZE | SWP_MOVE);
-
- WinReleasePS(hps);
-
- return 0;
-
- case WM_PAINT:
- hps = WinBeginPaint(hwnd, NULL, NULL);
- GpiErase(hps);
-
- // Draw each line of the quote
- ptl.x = 4L;
- ptl.y = fm.lMaxDescender + 1;
- for (i=cLines-1;i>=0;i--) {
- GpiCharStringAt(hps, &ptl, strlen(szLines[i]), szLines[i]);
- ptl.y += fm.lMaxBaselineExt;// + fm.lMaxDescender;
- }
-
- WinEndPaint(hps);
- return 0;
-
- case WM_BUTTON2DOWN: case WM_CHAR:
- // Terminate on any button or key press
- WinPostMsg(hwnd, WM_QUIT, (MPARAM) 0L, (MPARAM) 0L);
-
- // Make sure the timer is stopped
- WinStopTimer(hab,hwnd,ID_TIMER);
- return 0;
- }
- return WinDefWindowProc(hwnd, msg, mp1, mp2);
- }
-
-
- /****************************************************************************
- * ProcessArguments *
- * argc: count of command line arguments *
- * argv: pointer to list of command line arguments *
- * RETURN: ERR_OK, ERR_BADARGS *
- * *
- * Processes command line arguments. Pauses program if requested by user *
- * and Quote was START'ed. *
- ****************************************************************************/
- int ProcessArguments(int argc, char **argv)
- {
- int i;
-
- // Ignore the argv[0] and process the rest
- for (i=1;i<argc;i++) {
- // Make sure each argument is preceded by a switch character
- if (((argv[i][0] != '-') && (argv[i][0] != '/')) ||
- (argv[i][1] == '?'))
- return(ERR_BADARGS);
-
- switch (argv[i][1]) {
- case 'd': case 'D':
- sscanf(&argv[i][2],"%d",&sDisplay);
- if (sDisplay < 0)
- return(ERR_BADARGS);
- break;
- // Set pause length
- case 'l': case 'L':
- sscanf(&argv[i][2],"%d",&sLength);
- if (sLength < 0)
- return(ERR_BADARGS);
- break;
- // Calculate pause length based on current and requested times
- case 't': case 'T':
- if (ParseTime(&argv[i][2],&sLength) != ERR_OK)
- return(ERR_BADARGS);
- break;
- }
- }
-
- return(ERR_OK);
- }
-
- /****************************************************************************
- * ParseTime *
- * cbTime: pointer to string containing request time (in HH:MM) *
- * ulEndTime: pointer to variable which will contain pause time (in msec) *
- * RETURN: ERR_OK, ERR_BADARGS *
- * *
- * Processes command line arguments. Pauses program if requested by user *
- * and Quote was START'ed. *
- ****************************************************************************/
- int ParseTime(CHAR *cbTime,SHORT *sEndTime)
- {
- UCHAR ucHours = 0,ucMinutes = 0;
- DATETIME dtDate;
-
- // Make sure colons are in the proper position
- if ((strlen(cbTime) != 5) || (cbTime[2] != ':'))
- return (ERR_BADARGS);
-
- // Calculate request time
- sscanf(cbTime,"%d:%d",&ucHours,&ucMinutes);
- *sEndTime = (SHORT)ucHours*60 + (SHORT)ucMinutes;
-
- // Subtract current time
- DosGetDateTime(&dtDate);
- *sEndTime -= (SHORT)dtDate.hours*60 + (SHORT)dtDate.minutes;
-
- // Make sure pause time is valid (within 24 hours)
- if (*sEndTime < 0)
- *sEndTime += 1440;
-
- return(ERR_OK);
- }
-
- /****************************************************************************
- * ReadQuote *
- * QuoteArray: array of pointers to character strings *
- * cLen: contains length of longest line of quote on return *
- * RETURN: number of lines in the quote read, or zero if error *
- * *
- * Randomly selects a quote file to open, determines the last quote in *
- * the file, and randomly chooses a quote. *
- ****************************************************************************/
- SHORT ReadQuote(CHAR **QuoteArray,SHORT *cLen)
- {
- USHORT usLine, // Current quote on read
- usQuote = 0; // # Quote files, quote #
- SHORT cFiles = 1,
- cLines = 0, // Count of lines in quote
- cLineLen = 0,
- idxData = 0; // Index into buffer
- FILE *fInput;
- HDIR hdir = HDIR_CREATE;
- FILEFINDBUF findbuf;
-
- static CHAR szData[BUFFERSIZE]; // Quote file/text buffer
-
- // Seed the random number generator
- SeedRandom();
-
- // Form a list of all the quote files available (up to MAXQUOTE)
- // - Uses QuoteArray as a list of pointers to quote file names
- // - Uses szData as a buffer to contain the quote file names
- DosFindFirst("*.QUO", &hdir, FILE_NORMAL | FILE_READONLY,
- &findbuf, sizeof(findbuf), &cFiles, 0L);
- while ((cFiles > 0) && (usQuote < MAXQUOTE) &&
- (idxData + CCHMAXPATHCOMP <= BUFFERSIZE)) {
- strcpy(&szData[idxData],findbuf.achName);
- QuoteArray[usQuote++] = &szData[idxData];
- idxData += findbuf.cchName + 1;
- DosFindNext(hdir, &findbuf, sizeof(findbuf), &cFiles);
- }
-
- // If no quote files where found or there is a problem opening the file
- // selected (randomly), return that fact
- if ((usQuote < 1) ||
- ((fInput = fopen(QuoteArray[rand() % (int) usQuote],"r")) == NULL))
- return 0;
-
- // Find the number of the last quote in the file
- fseek(fInput,-128L,SEEK_END);
- fgets(&szData[0],96,fInput);
- do {
- fscanf(fInput,"%5d%%",&usQuote);
- fgets(&szData[0],96,fInput);
- } while (!feof(fInput));
- fseek(fInput,0L,SEEK_SET);
-
- // Initialize the quote buffer & max quote line length
- idxData = 0;
- *cLen = 0;
-
- // Choose a quote at random
- usQuote = (usQuote > 0) ? (USHORT) rand() % usQuote+1 : 0;
-
- // Form a list of the lines of the selected quote (up to BUFFERSIZE)
- // - Uses QuoteArray as a list of pointers to quote lines
- // - Uses szData as a buffer to contain the quote lines
- do {
- fscanf(fInput,"%5d%%",&usLine);
- fgets(&szData[idxData],96,fInput);
- if ((usQuote == usLine) &&
- ((cLineLen = strlen(&szData[idxData])) > 0)) {
- *cLen = max(*cLen,cLineLen-1);
- szData[idxData+cLineLen-1] = 0;
- QuoteArray[cLines++] = &szData[idxData];
- idxData += cLineLen;
- }
- } while ((usQuote >= usLine) && (idxData < BUFFERSIZE-97) &&
- !feof(fInput));
-
- // Return a count of the lines read
- return cLines;
- }
-
- /****************************************************************************
- * SeedRandom *
- * Reads seed from profile record, seeds the random number generator, and *
- * puts a new seed in the profile record. *
- ****************************************************************************/
- VOID SeedRandom(VOID)
- {
- ULONG cb;
- PROFILEREC prfProfile;
-
- // Read in the profile data if it exists
- PrfQueryProfileSize(HINI_USERPROFILE,szClientClass,"Data",&cb);
- if (cb == sizeof(PROFILEREC))
- PrfQueryProfileData(HINI_USERPROFILE,szClientClass,"Data",&prfProfile,&cb);
-
- // Seed the random number generator from seed in profile
- srand((unsigned int) prfProfile.usSEED);
- prfProfile.usSEED = (USHORT) rand();
-
- // Write profile information
- PrfWriteProfileData(HINI_USERPROFILE,szClientClass,"Data",
- &prfProfile,sizeof(PROFILEREC));
- }
-