/*** Main source of the Gotcha! screencapture program. Copyright (C) 1998-2002 Thorsten Thielen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ #define INCL_WINHOOKS #include "gotcha.h" #include "dll/gotchdll.h" #include "settings.h" #include "string.h" #include "io.h" #define INCL_EXCEPTQ_CLASS #define INCL_LOADEXCEPTQ #include "exceptq.h" HAB hab; HWND hwndFrame, hwndSnapshot; PFNWP OldFrameWP, wpOldButton; PSETTINGS pset; BOOL g_fIdle = FALSE, g_fSetPathName = FALSE; HWND g_hwndMenuSSW; HMODULE g_hmod = NULLHANDLE; Helper *g_phelp = NULL; #include "bitmap.cpp" #include "mainwin.cpp" #include "snapshot.cpp" #include "savebmp.cpp" // ** CheckCmdlineArgs **************************************************** /*FOLD00*/ BOOL CheckCmdlineArgs (int argc, char *argv[]) { BOOL fAuto = FALSE; for (USHORT i = 1; i < argc; i++) { // batch mode if ((stricmp (argv[i], "-a") == 0)) { if (pset->QuerySaveStyle () != FSS_FORCEFILE) pset->SetFileSaveStyle (FSS_NUMFILES); fAuto = TRUE; if (i < argc-1) if (argv[i+1][0] != '-') { i++; pset->SetFileSaveStyle (FSS_NUMFILES); pset->SetNumSaveDir (argv[i]); } } // force saving to the given file name else if ((stricmp (argv[i], "-f") == 0) && (i < argc-1)) { if (argv[i+1][0] != '-') { i++; pset->SetFileSaveStyle (FSS_FORCEFILE); pset->SetForceSaveFile (argv[i]); g_fSetPathName = TRUE; } } // set to idle priority else if (stricmp (argv[i], "-i") == 0) { g_fIdle = TRUE; pset->SetFlag (SEI_IDLEPRIORITY, TRUE); } } return fAuto; } // ** main **************************************************************** /*FOLD00*/ int main (int argc, PSZ argv[]) { ScopedExceptqLoader sel; #ifdef _DOLOGDEBUG_ LogDebug( "Gotcha! start" ); #endif #ifdef _DOLOGMEM_ LogMem("main", TRUE); #endif // init system and msg queue hab = WinInitialize (0); HMQ hmq = WinCreateMsgQueue (hab, 0); //DisplayError("DEBUG", "%d", Version()); #ifdef _QUIET_ if ((Version() < 2)) { DisplayError("GOTCHDLL.DLL TOO OLD", "The file gotchdll.dll is to old for this version of " "Gotcha! Quiet As you should have received a sufficiently " "new version with the program, check if an older " "version of gotchdll.dll is still residing somewhere " "in your LIBPATH. And did you actually copy the new " "gotchdll.dll to some directory in your LIBPATH?"); exit (0); } int rc; HMTX hmtx = NULLHANDLE; // running multiple instances orphans all but the first closed hook unloaded rc = DosOpenMutexSem("\\SEM32\\GOTCHA", &hmtx); if (!rc) { DisplayError("GOTCHA QUIET ALREADY RUNNING", "Another instance of Gotcha Quiet is running." " You can open Gotcha Quiet's settings using" " the Alt+Print Screen key combination"); exit (0); } rc = DosCreateMutexSem("\\SEM32\\GOTCHA", &hmtx, 0, FALSE); if (rc) { DisplayError("Semaphore creation failed", "Try restarting Gotcha Quiet"); exit (0); } #endif // register our window classes WinRegisterClass (hab, "thth.wc.gotcha.main", WindowProcedure, 0L, sizeof (ULONG)*2L); WinRegisterClass (hab, "thth.wc.gotcha.snapshot", wpSnapshot, CS_SIZEREDRAW, sizeof (ULONG)*2L); // load the settings pset = new SETTINGS; pset->idleSetInIni = pset->QueryFlag(SEI_IDLEPRIORITY); pset->saveStyle = pset->QuerySaveStyle (); pset->pNumSaveDir = pset->QueryNumSaveDir (); pset->pForceSaveFile = pset->QueryForceSaveFile(); pset->bSerialCapture = pset->SerialCapture (); #ifdef _QUIET_ bool fPrtScr = FALSE; ULONG ulDataSize = 0; rc = PrfQueryProfileSize( HINI_PROFILE, "PM_ControlPanel", "PrintScreen", &ulDataSize ); rc = PrfQueryProfileData(HINI_USERPROFILE, "PM_ControlPanel", "PrintScreen", &fPrtScr, &ulDataSize); bool temp = FALSE;// always turn it off while running PrfWriteProfileData(HINI_USERPROFILE, "PM_ControlPanel", "PrintScreen", &temp, sizeof(bool)); PrfQueryProfileSize(pset->QueryPrfHandle (), "PM", "PrintScreen", &ulDataSize ); int rc1 = PrfQueryProfileData(pset->QueryPrfHandle (), "PM", "PrintScreen", &temp, &ulDataSize); bool temp2 = TRUE; PrfQueryProfileData(pset->QueryPrfHandle (), "PM", "PrintScreen", &temp2, &ulDataSize); if (!rc1 || (temp2 && (temp != fPrtScr))) { // no entry or user has changed PM setting if (!rc) // Print screen is on by default (no ini entry) fPrtScr = TRUE; PrfWriteProfileData(pset->QueryPrfHandle (), "PM", "PrintScreen", &fPrtScr, sizeof(bool)); } temp = FALSE; PrfWriteProfileData(pset->QueryPrfHandle (), "PM", "Exited", &temp, sizeof(bool)); #endif // check cmd line args and if "-a" found take screenshot and exit if (CheckCmdlineArgs (argc, argv)) { CaptureWindow (HWND_DESKTOP, HWND_DESKTOP, NULL, TRUE); pset->SetFileSaveStyle(pset->saveStyle); pset->SetNumSaveDir (pset->pNumSaveDir); delete pset; WinDestroyMsgQueue (hmq); WinTerminate (hab); exit (0); } SetIdlePriority(pset->QueryFlag(SEI_IDLEPRIORITY)); // create the windows hwndFrame = CreateMainWindow (); hwndSnapshot = CreateSnapshotWindow (); SWP swp; USHORT us[7]; // position main window pset->QueryWindowData (&swp, us, FALSE); WinSetWindowPos (hwndFrame, HWND_DESKTOP, swp.x,swp.y, 0,0, SWP_SHOW | SWP_MOVE); #ifdef _QUIET_ InitDLL (hab, hwndFrame); StartInputHook (); #endif // position snapshot window pset->QueryWindowData (&swp, us); // size, activate & show window WinSetWindowPos (hwndSnapshot, HWND_DESKTOP, swp.x,swp.y, swp.cx,swp.cy, SWP_SHOW | SWP_SIZE | SWP_MOVE); if (! pset->SnapshotWindow ()) WinShowWindow (hwndSnapshot, FALSE); else WinShowWindow (hwndSnapshot, TRUE); WinSetWindowPos (hwndFrame, NULLHANDLE, 0,0, 0,0, SWP_SHOW); WinSetWindowPos (WinWindowFromID (hwndFrame, FID_CLIENT), NULLHANDLE, 0,0, 0,0, SWP_SHOW); g_phelp = new Helper(hwndFrame); // do the main msg loop QMSG qmsg; while (WinGetMsg (hab, &qmsg, 0L, 0, 0)) WinDispatchMsg (hab, &qmsg); // Set priorty to unless user set regular since running -q sets it to idle in the ini if (g_fIdle) { pset->SetFlag (SEI_IDLEPRIORITY, pset->idleSetInIni); } // Don't change the ini stored paths if the paths were set from the command line if (g_fSetPathName) { pset->SetFileSaveStyle(pset->saveStyle); pset->SetForceSaveFile (pset->pForceSaveFile); pset->SetNumSaveDir (pset->pNumSaveDir); } // save size, etc. of snapshot window WinQueryWindowPos (hwndSnapshot, &swp); pset->SetWindowData (&swp); // save size, etc. of main window WinQueryWindowPos (hwndFrame, &swp); pset->SetWindowData (&swp, FALSE); // goodbye windows! WinDestroyWindow (hwndSnapshot); WinDestroyWindow (hwndFrame); #ifdef _QUIET_ PrfQueryProfileSize(pset->QueryPrfHandle (), "PM", "PrintScreen", &ulDataSize ); PrfQueryProfileData(pset->QueryPrfHandle (), "PM", "PrintScreen", &fPrtScr, &ulDataSize); PrfWriteProfileData(HINI_USERPROFILE, "PM_ControlPanel", "PrintScreen", &fPrtScr, sizeof(bool)); temp = TRUE; PrfWriteProfileData(pset->QueryPrfHandle (), "PM", "Exited", &temp, sizeof(bool)); StopInputHook (); DosCloseMutexSem(hmtx); #endif delete g_phelp; delete pset; WinDestroyMsgQueue (hmq); WinTerminate (hab); #ifdef _DOLOGMEM_ LogMem("main", FALSE); #endif #ifdef _DOLOGDEBUG_ LogDebug( "Gotcha! end" ); #endif } // ** DisplayError ******************************************************** /*FOLD00*/ VOID DisplayError (PSZ pszTitle, PSZ psz, ...) { CHAR dstring[401]; va_list valst; va_start (valst, psz); vsnprintf (dstring, 401, psz, valst); va_end (valst); WinMessageBox (HWND_DESKTOP, WinQueryActiveWindow (HWND_DESKTOP), dstring, pszTitle, 0, MB_OK | MB_ERROR | MB_APPLMODAL | MB_MOVEABLE); } // saymsg2 was adapted from code in FM/2 APIRET saymsg2(int DefaultButton, HWND hwnd, PCSZ pszTitle, PCSZ pszFmt, ...) { ULONG i; APIRET rc; CHAR szMsg[4096]; va_list va; MB2INFO *pmbInfo; MB2D mb2dBut[3]; ULONG ulInfoSize = (sizeof(MB2INFO) + (sizeof(MB2D) * 2)); va_start(va, pszFmt); szMsg[sizeof(szMsg) - 1] = 0; vsprintf(szMsg, pszFmt, va); va_end(va); if (szMsg[sizeof(szMsg) - 1]) { fprintf(stderr, "Buffer overflow in saymsg2 - need %u bytes\n", strlen(szMsg) + 1); fflush(stderr); } memset(mb2dBut, 0, sizeof(MB2D) * 3); strcpy(mb2dBut[0].achText,"Ok"); strcpy(mb2dBut[1].achText,"Cancel"); strcpy(mb2dBut[2].achText,"Settings"); mb2dBut[0].idButton = 1; mb2dBut[1].idButton = 2; mb2dBut[2].idButton = 3; if (DefaultButton) mb2dBut[DefaultButton - 1].flStyle = BS_DEFAULT; pmbInfo = (MB2INFO *) malloc(ulInfoSize); memset(pmbInfo, 0, ulInfoSize); if (pmbInfo) { pmbInfo->cb = ulInfoSize; pmbInfo->hIcon = 0; pmbInfo->cButtons = 3; pmbInfo->flStyle = MB_MOVEABLE | MB_ICONQUESTION ; pmbInfo->hwndNotify = NULLHANDLE; for (i = 0; i < 3; i++) { memcpy( pmbInfo->mb2d+i , mb2dBut+i , sizeof(MB2D)); } rc = WinMessageBox2(HWND_DESKTOP, hwnd, szMsg, pszTitle, SM2_DIALOG, pmbInfo); WinSetFocus(HWND_DESKTOP, SM2_DIALOG); free(pmbInfo); return rc; } return MBID_ERROR; } // ** AddSysMenuItem ****************************************************** /*FOLD00*/ VOID AddSysMenuItem (HWND hwndFrame, MENUITEM *Item, PSZ Text) { HWND hwndSysMenu = WinWindowFromID (hwndFrame, FID_SYSMENU); USHORT idSysMenu = SHORT1FROMMR (WinSendMsg (hwndSysMenu, MM_ITEMIDFROMPOSITION, NULL, NULL )); MENUITEM miSysMenu; WinSendMsg (hwndSysMenu, MM_QUERYITEM, MPFROM2SHORT (idSysMenu,FALSE), MPFROMP(&miSysMenu)); HWND hwndSysSubMenu = miSysMenu.hwndSubMenu; WinSendMsg (hwndSysSubMenu, MM_INSERTITEM, MPFROMP(Item), MPFROMP(Text)); } // ** DoCountdown ********************************************************* /*fold00*/ VOID DoCountdown (ULONG ul) { if (ul > 10) DosBeep (4000L-3000L, 20); else DosBeep (4000L-ul*300L, 20); } // ** SetIdlePriority **************************************************** /*FOLD00*/ VOID SetIdlePriority (BOOL f) { #if 0 //#ifndef _QUEIT_ if (f) DosSetPriority(PRTYS_PROCESS, PRTYC_IDLETIME, 0, 0); else DosSetPriority(PRTYS_PROCESS, PRTYC_REGULAR, 0, 0); #else DosSetPriority(PRTYS_PROCESS, PRTYC_FOREGROUNDSERVER, 0, 0); #endif } // *********************************************************************** #ifdef _DOLOGMEM_ VOID LogMem (PSZ psz, BOOL f) { FILE *pf = fopen("gotcha.mem","ab"); static ULONG TotalPhysicalMemory, ul = 0; ULONG i; if (!f) ul--; DosQuerySysInfo(QSV_TOTAVAILMEM, QSV_TOTAVAILMEM, &TotalPhysicalMemory, sizeof(TotalPhysicalMemory)); for (i = 0; i < ul; i++) fputs(" ", pf); fprintf(pf,"%10ld (%s)\n", TotalPhysicalMemory, psz); if (f) ul++; fclose(pf); } #endif #ifdef _DOLOGDEBUG_ VOID LogDebug( PSZ psz, ... ) { CHAR dstring[401]; va_list valst; va_start (valst, psz); vsnprintf (dstring, 401, psz, valst); va_end (valst); FILE *pf = fopen( "gotcha.log", "ab" ); fprintf( pf, "%s\n", dstring ); fclose( pf ); } #endif // ***********************************************************************