//=========================================================== // SPad - A better Notepad // Copyright (C) 1995 Douglas Boling // // Revision History: // // 1.0 Initial Release // 1.1 Bug fixes // removed problem OutputDebugString calls // fixed overstrike of non-char keys // added menu del routine // //=========================================================== // Returns no. of elements #define dim(x) (sizeof(x) / sizeof(x[0])) #define MAXFNAMELEN 256 #define NUMBUFFS 4 //----------------------------------------------------------- // Include files //----------------------------------------------------------- #include "windows.h" #include "commdlg.h" #include "shellapi.h" #include "stdlib.h" #include "stdio.h" #include "string.h" #include "SPad.h" #include "statbar.h" //----------------------------------------------------------- // NonPublic procedure declarations //---------------------------------------------------------- // Message handler functions for edit box window proc LONG DoSetTextSText (HWND, UINT, UINT, LONG); LONG DoGetTextSText (HWND, UINT, UINT, LONG); LONG DoPaintSText (HWND, UINT, UINT, LONG); LONG DoSizeSText (HWND, UINT, UINT, LONG); LONG DoDestroySText (HWND, UINT, UINT, LONG); INT ParseCmdLine (PFILEDATA, LPSTR); INT CopyAllToClip (HWND, PFILEDATA); LONG SearchReplace (HWND, LPSTR, LPSTR, BOOL, BOOL, BOOL); INT GetFileData (PFILEDATA, LONG, HWND); INT ChkMaxSize (PFILEDATA, HWND); INT ScrollProc (PFILEDATA, HWND, INT); INT BufftoEBox (PFILEDATA, INT, UINT, HWND); INT GetSegment (PFILEDATA, LPSEGLIST, INT *); HGLOBAL CreateEditWnd (HWND, PFILEDATA, HWND *); void SetTabs (HWND, INT); //----------------------------------------------------------- // Global data //----------------------------------------------------------- // Message dispatch table for MainWindowProc struct decodeUINT MainMessages[] = { WM_CREATE, DoCreateMain, WM_SETFOCUS, DoSetFocusMain, WM_SIZE, DoSizeMain, MYMSG_REFORMAT, DoMyMsgReformatMain, MYMSG_OPEN, DoMyMsgOpenMain, WM_INITMENU, DoInitMenuMain, WM_VSCROLL, DoVScrollMain, WM_COMMAND, DoCommandMain, WM_DROPFILES, DoDropFilesMain, WM_DESTROY, DoDestroyMain, WM_CLOSE, DoCloseMain, }; // Command Message dispatch for MainWindowProc struct decodeCMD MainMenuItems[] = { IDD_EBOX, DoMainCtlEBox, IDM_NEW, DoMainMenuNew, IDM_OPEN, DoMainMenuOpen, IDM_SAVE, DoMainMenuSave, IDM_SAVEAS, DoMainMenuSaveAs, IDM_RONLY, DoMainMenuROnly, IDM_EXIT, DoMainMenuExit, IDM_UNDO, DoMainMenuUndo, IDM_CUT, DoMainMenuCut, IDM_COPY, DoMainMenuCopy, IDM_PASTE, DoMainMenuPaste, IDM_DELETE, DoMainMenuDelete, IDM_SELALL, DoMainMenuSelectAll, IDM_WORDWRAP, DoMainMenuWWrap, IDM_FIND, DoMainMenuFind, IDM_FINDNEXT, DoMainMenuFindNext, IDM_REPLACE, DoMainMenuReplace, IDM_SELFONT, DoMainMenuSelFont, IDM_DEFPORP, DoMainMenuDefPFont, IDM_DEFFIXED, DoMainMenuDefFFont, IDM_SETTABS, DoMainMenuSetTabs, IDM_HELP, DoMainMenuHelp, IDM_ABOUT, DoMainMenuAbout, }; char szAppName[] = "WinSPad"; // Application name char szTitleText[] = "Super Pad"; // Application window title char szMenuName[] = "WinSPadMenu"; // Menu name char szIconName[] = "WinSPadIcon"; // Icon name char szProfileName[144]; // INI file name HANDLE hInst; HWND hMain; WORD fStatFlags = SFLAG_FFIRST; WNDPROC lpfnOldEditProc; WNDPROC lpfnEditSCProc; FILEDATA FileData; char szCmd[128] = ""; LONG lStartLine = 0; INT sStartCol = 0; INT sStartX = 0; INT sStartY = 0; BOOL fPaint = TRUE; HWND hWndVScroll = 0; UINT wFindMsg = 0; // Message num of FINDREPLACE msg HWND hwndFR = 0; // Handle of Find/Rep modless dialog char szFindText[255] = ""; char szRepText[255] = ""; DWORD fFindFlags; FINDREPLACE fr; BOOL fScrolling = FALSE; char szDebug[128]; HGLOBAL hEdit; //============================================================ // WinMain -- entry point for this application from Windows. //============================================================ INT APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) { MSG msg; INT rc; HACCEL hAccel; hInst = hInstance; if(!hPrevInstance) if((rc = InitApp(hInstance)) != 0) return rc; // Initialize this instance if((rc = InitInstance(hInstance, lpCmdLine, nCmdShow)) != 0) return rc; hAccel = LoadAccelerators (hInstance, szAppName); // // Application message loop // while (GetMessage (&msg, NULL, 0, 0)) { if ((hwndFR == 0) || !IsDialogMessage (hwndFR, &msg)) { if (!TranslateAccelerator (hMain, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } } // Instance cleanup return TermInstance(hInstance, msg.wParam); } //----------------------------------------------------------- // InitApp - Global initialization code for this application. //----------------------------------------------------------- INT InitApp(HANDLE hInstance) { WNDCLASS wc; // // Register App Main Window class // wc.style = 0; // Window style wc.lpfnWndProc = MainWndProc; // Callback function wc.cbClsExtra = 0; // Extra class data wc.cbWndExtra = 0; // Extra window data wc.hInstance = hInstance; // Owner handle wc.hIcon = LoadIcon(hInst, szIconName); // Application icon wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Default cursor wc.hbrBackground = COLOR_WINDOW + 1; wc.lpszMenuName = szMenuName; // Menu name wc.lpszClassName = szAppName; // Window class name if (RegisterClass(&wc) == 0) return 1; StatusBarInit (hInstance); return 0; } //----------------------------------------------------------- // InitInstance - Instance initialization code for this app. //----------------------------------------------------------- INT InitInstance(HANDLE hInstance, LPSTR lpCmdLine, INT nCmdShow) { INT i, x, y, cx, cy; INT sField[6]; HFONT hFont; LOGFONT fm; char szText[80]; //Create INI filename GetModuleFileName (hInst, szProfileName, sizeof (szProfileName)); for (x = lstrlen (szProfileName); x && szProfileName[x] != '.'; --x); lstrcpy (&szProfileName[x], ".INI"); //Init file structure memset (&FileData, 0, sizeof (FileData)); for (i = 0; i < NUMBUFFS; i++) FileData.bd[i].hBuff = 0; FileData.sTabs = GetPrivateProfileInt (szAppName, PRO_TABS, 8, szProfileName); FileData.fFlags = GetPrivateProfileInt (szAppName, PRO_FLAGS, FFLAG_PORPFONT | FFLAG_WWRAP, szProfileName); FileData.fFlags &= FFLAG_RONLY | FFLAG_WWRAP | FFLAG_PORPFONT | FFLAG_FIXEDFONT; FileData.sEBoxLines = 1; FileData.wScrollMax = 1; // Alloc and lock segment list FileData.hSegList = GlobalAlloc (GHND, 65536); if (FileData.hSegList == 0) return 0x12; FileData.lpbl = (LPSEGLIST) GlobalLock (FileData.hSegList); // Allocate RAM buffers for (i = 0; i < NUMBUFFS;i++) { FileData.bd[i].hBuff = GlobalAlloc (GHND, BUFFSIZE); } // Init first blk FileData.sActBuff = 0; FileData.lpbl->lLoc = 0; FileData.lpbl->wSize = 0; FileData.lpbl->fFlags = FLAG_LASTSEG | STAT_SEGINEDIT; FileData.bd[0].lpSegListPtr = FileData.lpbl; FileData.bd[0].sLRU = NUMBUFFS; // Create temp file for swapping dirty segments GetTempFileName (0, "SPD", 0, FileData.szSwapName); FileOps (&FileData.hTempFile, FOP_OPEN, (LONG)(LPVOID)FileData.szSwapName, OF_READWRITE | OF_CREATE, &i); if (!i) { FileOps (&FileData.hTempFile, FOP_CLOSE, 0, 0, &i); FileOps (&FileData.hTempFile, FOP_OPEN, (LONG)(LPVOID)FileData.szSwapName, OF_READWRITE | OF_SHARE_EXCLUSIVE, &i); } if (i) return i; //Read INI file info x = GetPrivateProfileInt (szAppName, PRO_XPOS, CW_USEDEFAULT, szProfileName); y = GetPrivateProfileInt (szAppName, PRO_YPOS, CW_USEDEFAULT, szProfileName); cx = GetPrivateProfileInt (szAppName, PRO_XSIZE, CW_USEDEFAULT, szProfileName); cy = GetPrivateProfileInt (szAppName, PRO_YSIZE, CW_USEDEFAULT, szProfileName); // Create main window hMain = CreateWindow (szAppName, szTitleText, WS_OVERLAPPEDWINDOW, x, y, cx, cy, NULL, NULL, hInstance, lpCmdLine); if(!hMain) return 0x10; //Create status bar sField[0] = 0; sField[1] = 40; sField[2] = 40; sField[3] = 40; sField[4] = 40; i = StatusBarCreate (hMain, 5, sField); if (i) return i; if (!(FileData.fFlags & (FFLAG_PORPFONT | FFLAG_FIXEDFONT))) { hFont = GetStockObject (SYSTEM_FONT); GetObject (hFont, sizeof (fm), &fm); fm.lfHeight = GetPrivateProfileInt (szAppName, PRO_FONT1, fm.lfHeight, szProfileName); fm.lfWidth = GetPrivateProfileInt (szAppName, PRO_FONT2, fm.lfWidth, szProfileName); fm.lfEscapement = 0; fm.lfOrientation = 0; // fm.lfEscapement = GetPrivateProfileInt (szAppName, PRO_FONT3, // fm.lfEscapement, szProfileName); // fm.lfOrientation = GetPrivateProfileInt (szAppName, PRO_FONT4, // fm.lfOrientation, szProfileName); fm.lfWeight = GetPrivateProfileInt (szAppName, PRO_FONT5, fm.lfWeight, szProfileName); fm.lfItalic = (BYTE)GetPrivateProfileInt (szAppName, PRO_FONT6, fm.lfItalic, szProfileName); fm.lfUnderline = (BYTE)GetPrivateProfileInt (szAppName, PRO_FONT7, fm.lfUnderline, szProfileName); fm.lfStrikeOut = (BYTE)GetPrivateProfileInt (szAppName, PRO_FONT8, fm.lfStrikeOut, szProfileName); fm.lfCharSet = (BYTE)GetPrivateProfileInt (szAppName, PRO_FONT9, fm.lfCharSet, szProfileName); fm.lfOutPrecision = (BYTE)GetPrivateProfileInt (szAppName, PRO_FONT10, fm.lfOutPrecision, szProfileName); fm.lfClipPrecision = (BYTE)GetPrivateProfileInt (szAppName, PRO_FONT11, fm.lfClipPrecision, szProfileName); fm.lfQuality = (BYTE)GetPrivateProfileInt (szAppName, PRO_FONT12, fm.lfQuality, szProfileName); fm.lfPitchAndFamily = (BYTE)GetPrivateProfileInt (szAppName, PRO_FONT13, fm.lfPitchAndFamily, szProfileName); GetPrivateProfileString (szAppName, PRO_FONT14, fm.lfFaceName, fm.lfFaceName, sizeof (fm.lfFaceName), szProfileName); //Create and set current font for edit box hFont = CreateFontIndirect (&fm); SendDlgItemMessage (hMain, IDD_EBOX, WM_SETFONT, hFont, 0); } if (*lpCmdLine) { i = ParseCmdLine (&FileData, lpCmdLine); if (i == 0) PostMessage (hMain, MYMSG_OPEN, FileData.fFlags, (LPARAM)(LPSTR)szCmd); else { GetErrorString (i, szText, sizeof (szText)); MessageBox (hMain, szText, szAppName, MB_ICONSTOP | MB_OK); } } if (sStartX || sStartY) { if (sStartX == 0) sStartX = x; if (sStartY == 0) sStartY = y; fStatFlags |= SFLAG_SWITCHSTART; SetWindowPos (hMain, NULL, sStartX, sStartY, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } ShowWindow(hMain, nCmdShow | SW_SHOW); UpdateWindow(hMain); // force WM_PAINT message return 0; // return success flag } //------------------------------------------------------------ // TermInstance - Instance termination code for this app. //------------------------------------------------------------ INT TermInstance(HANDLE hinstance, int sDefRC) { INT i; // Free global memory used by edit control. GlobalFree (hEdit); // Free segment list buffer if (FileData.hSegList) { GlobalUnlock (FileData.hSegList); GlobalFree (FileData.hSegList); } // Free RAM buffers for (i = 0; i < NUMBUFFS; i++) { if (FileData.bd[i].hBuff) { GlobalFree (FileData.bd[i].hBuff); } } return sDefRC; } //============================================================ // Message handling procedures for MainWindow //============================================================ //------------------------------------------------------------ // MainWndProc - Callback function for application window //------------------------------------------------------------ LONG CALLBACK MainWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT i; // // Search message list to see if we need to handle this // message. If in list, call procedure. // for(i = 0; i < dim(MainMessages); i++) { if(wMsg == MainMessages[i].Code) return (*MainMessages[i].Fxn)(hWnd, wMsg, wParam, lParam); } // Used to capture register message used by Find and Replace if (wMsg == wFindMsg) DoFindNextMain (hWnd, wMsg, wParam, lParam); return DefWindowProc(hWnd, wMsg, wParam, lParam); } //------------------------------------------------------------ // GetEBoxPos - Compute the size and position of the files // listbox. //------------------------------------------------------------ void GetEBoxPos (HWND hWnd, INT *x, INT *y, INT *Cx, INT *Cy) { RECT rect; GetClientRect (hWnd, &rect); ModifyClientRect (hWnd, &rect); *x = rect.left; *y = rect.top; *Cx = rect.right - rect.left; *Cy = rect.bottom - rect.top; return; } //------------------------------------------------------------ // DoCreateMain - process WM_CREATE message for frame window. //------------------------------------------------------------ LONG DoCreateMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT x, y, cx ,cy; HWND hWndEdit; wFindMsg = RegisterWindowMessage ("commdlg_FindReplace"); GetEBoxPos (hWnd, &x, &y, &cx, &cy); hWndVScroll = CreateWindow ("scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_VERT | SBS_RIGHTALIGN, x, y, cx, cy, hWnd, IDD_VSB, hInst, NULL); hEdit = CreateEditWnd (hWnd, &FileData, &hWndEdit); // Subclass edit box lpfnEditSCProc = (WNDPROC)MakeProcInstance ((FARPROC)EditWndSCProc, hInst); lpfnOldEditProc = MySubClassWindow (hWndEdit, lpfnEditSCProc); DragAcceptFiles (hWnd, TRUE); SetWindowText (hWndEdit, ""); ShowWindow (hWndEdit, SW_SHOW); return 0; } //------------------------------------------------------------ // DoSizeMain - process WM_SIZE message for frame window. //------------------------------------------------------------ LONG DoSizeMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT x,y, cx, cy, cxs; char szText[128], *pszText; RECT rect; if ((wParam == SIZE_MAXHIDE) || (wParam == SIZE_MAXSHOW)) return 0; if (wParam != SIZE_MINIMIZED) { SetWindowText (hWnd, szTitleText); GetWindowRect (GetDlgItem (hWnd, IDD_VSB), &rect); cxs = rect.right - rect.left; GetEBoxPos (hWnd, &x, &y, &cx, &cy); SetWindowPos (GetDlgItem (hWnd, IDD_VSB), NULL, cx - cxs, y, cxs, cy, SWP_NOZORDER); SetWindowPos (GetDlgItem (hWnd, IDD_EBOX), NULL, x, y, cx-cxs, cy, SWP_NOZORDER); SendMessage (hWnd, MYMSG_REFORMAT, 0, 0); SetFocus (GetDlgItem (hWnd, IDD_EBOX)); } else { if (lstrlen (FileData.szFileName)) { lstrcpy (szText, szTitleText); lstrcat (szText, " - "); pszText = FileData.szFileName + lstrlen (FileData.szFileName); while ((pszText > FileData.szFileName) && (*pszText != '\\')) pszText--; if (pszText != FileData.szFileName) pszText++; lstrcat (szText, pszText); SetWindowText (hWnd, szText); } } return 0; } //------------------------------------------------------------ // DoMyMsgOpenMain - process MYMSG_OPEN message //------------------------------------------------------------ LONG DoMyMsgOpenMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT rc = 0; HCURSOR hCursor; FileData.fFlags = wParam & (FFLAG_VIEWONLY | FFLAG_RONLY | FFLAG_WWRAP | FFLAG_PORPFONT | FFLAG_FIXEDFONT); // Set the tab stops. SetTabs (GetDlgItem (hWnd, IDD_EBOX), FileData.sTabs); // Set the read only state SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETREADONLY, FileData.fFlags & FFLAG_RONLY, 0); // Set the fonts if (FileData.fFlags & FFLAG_PORPFONT) SendMessage (hWnd, WM_COMMAND, IDM_DEFPORP, 0); else if (FileData.fFlags & FFLAG_FIXEDFONT) SendMessage (hWnd, WM_COMMAND, IDM_DEFFIXED, 0); hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)); // Load in new file if (*(LPSTR)lParam) rc = InitFile ((LPSTR)lParam, &FileData, hWnd, lStartLine, sStartCol); else rc = InitFile (0, &FileData, hWnd, lStartLine, sStartCol); SetCursor (hCursor); if (rc) { PrintError (hWnd, rc); return 0; } DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoMyMsgReformatMain - process MYMSG_REFORMAT message for // frame window. //------------------------------------------------------------ LONG DoMyMsgReformatMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { HDC hdc; TEXTMETRIC tm; HFONT hFont; RECT rect; //Determine the number of lines in the edit box. GetClientRect (GetDlgItem (hWnd, IDD_EBOX), &rect); hdc = GetDC (NULL); hFont = (HFONT) SendDlgItemMessage (hWnd, IDD_EBOX, WM_GETFONT, 0, 0); if (hFont == 0) hFont = GetStockObject (SYSTEM_FONT); SelectObject (hdc, hFont); GetTextMetrics (hdc, &tm); FileData.sEBoxLines = (rect.bottom - rect.top) / (tm.tmHeight + tm.tmExternalLeading) + 1; ReleaseDC (NULL, hdc); ScrollProc (&FileData, GetDlgItem (hWnd, IDD_EBOX), 0); InvalidateRect (GetDlgItem (hWnd, IDD_EBOX), 0, TRUE); DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoSetFocusMain - process WM_SETFOCUS message for frame window. //------------------------------------------------------------ LONG DoSetFocusMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { SetFocus (GetDlgItem (hWnd, IDD_EBOX)); return 0; } //------------------------------------------------------------ // DoInitMenuMain - process WM_INITMENU message for frame window. //------------------------------------------------------------ LONG DoInitMenuMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { LONG lRet; HMENU hMenu; hMenu = (HMENU) wParam; // See if Save / Save As allowed. Set Read Only menu check if (FileData.fFlags & FFLAG_RONLY) { CheckMenuItem (hMenu, IDM_RONLY, MF_BYCOMMAND | MF_CHECKED); EnableMenuItem (hMenu, IDM_SAVE, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem (hMenu, IDM_SAVEAS, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem (hMenu, IDM_REPLACE, MF_BYCOMMAND | MF_GRAYED); } else { CheckMenuItem (hMenu, IDM_RONLY, MF_BYCOMMAND | MF_UNCHECKED); EnableMenuItem (hMenu, IDM_SAVE, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem (hMenu, IDM_SAVEAS, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem (hMenu, IDM_REPLACE, MF_BYCOMMAND | MF_ENABLED); } if (FileData.fFlags & FFLAG_VIEWONLY) EnableMenuItem (hMenu, IDM_RONLY, MF_BYCOMMAND | MF_GRAYED); else EnableMenuItem (hMenu, IDM_RONLY, MF_BYCOMMAND | MF_ENABLED); // See if Cut, Copy and Delete allowed. EnableMenuItem (hMenu, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem (hMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); lRet = SendDlgItemMessage (hWnd, IDD_EBOX, EM_GETSEL, 0, 0); if (LOWORD (lRet) == HIWORD (lRet)) { EnableMenuItem (hMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); } else { EnableMenuItem (hMenu, IDM_COPY, MF_BYCOMMAND | MF_ENABLED); if (!(FileData.fFlags & FFLAG_RONLY)) { EnableMenuItem (hMenu, IDM_CUT, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem (hMenu, IDM_DELETE, MF_BYCOMMAND | MF_ENABLED); } } // See if Paste allowed lRet = 0; if (!(FileData.fFlags & FFLAG_RONLY) && OpenClipboard (hWnd)) { if (IsClipboardFormatAvailable (CF_TEXT)) lRet = 1; CloseClipboard (); } if (lRet) EnableMenuItem (hMenu, IDM_PASTE, MF_BYCOMMAND | MF_ENABLED); else EnableMenuItem (hMenu, IDM_PASTE, MF_BYCOMMAND | MF_GRAYED); // See if UnDo allowed if (SendDlgItemMessage (hWnd, IDD_EBOX, EM_CANUNDO, 0, 0)) EnableMenuItem (hMenu, IDM_UNDO, MF_BYCOMMAND | MF_ENABLED); else EnableMenuItem (hMenu, IDM_UNDO, MF_BYCOMMAND | MF_GRAYED); // Set Word Wrap menu check if (FileData.fFlags & FFLAG_WWRAP) CheckMenuItem (hMenu, IDM_WORDWRAP, MF_BYCOMMAND | MF_CHECKED); else CheckMenuItem (hMenu, IDM_WORDWRAP, MF_BYCOMMAND | MF_UNCHECKED); // Set Porp/fixed font check if (FileData.fFlags & FFLAG_PORPFONT) CheckMenuItem (hMenu, IDM_DEFPORP, MF_BYCOMMAND | MF_CHECKED); else CheckMenuItem (hMenu, IDM_DEFPORP, MF_BYCOMMAND | MF_UNCHECKED); if (FileData.fFlags & FFLAG_FIXEDFONT) CheckMenuItem (hMenu, IDM_DEFFIXED, MF_BYCOMMAND | MF_CHECKED); else CheckMenuItem (hMenu, IDM_DEFFIXED, MF_BYCOMMAND | MF_UNCHECKED); return 0; } //------------------------------------------------------------ // SetEBoxScroll - Positions the vert scroll bar for the edit // box. //------------------------------------------------------------ void SetEBoxScroll (PFILEDATA pfd, HWND hWnd) { LONG lFilePtr; UINT wPos; LPSEGLIST lpSegList; // Set the proper scroll bar position lpSegList = pfd->lpbl; lFilePtr = 0; while ((lpSegList != pfd->bd[pfd->sActBuff].lpSegListPtr) && !(lpSegList->fFlags & FLAG_LASTSEG)) { lFilePtr += lpSegList->wSize; lpSegList++; } wPos = HIWORD (SendDlgItemMessage (hWnd, IDD_EBOX, EM_GETSEL, 0, 0)); lFilePtr = (lFilePtr + wPos) / pfd->wScrollMax; SetScrollPos (GetDlgItem (hMain, IDD_VSB), SB_CTL, (INT)lFilePtr, TRUE); return; } //------------------------------------------------------------ // DoVScrollMain - process WM_VSCROLL message for frame window // by decoding the menubar item with the menuitems[] array, // then running the corresponding function to process the command. //------------------------------------------------------------ LONG DoVScrollMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT sScrollPos, sScroll, rc = 0; sScrollPos = GetScrollPos (GetDlgItem (hWnd, IDD_VSB), SB_CTL); sScroll = 0; switch (wParam) { case SB_BOTTOM: rc = GetFileData (&FileData, 0x7fffffff, GetDlgItem (hWnd, IDD_EBOX)); break; case SB_TOP: rc = GetFileData (&FileData, 0, GetDlgItem (hWnd, IDD_EBOX)); break; case SB_LINEDOWN: sScroll = 1; break; case SB_LINEUP: sScroll = -1; break; case SB_PAGEDOWN: sScroll = FileData.sEBoxLines - 1; break; case SB_PAGEUP: sScroll = -(FileData.sEBoxLines - 1); break; case SB_THUMBPOSITION: rc = GetFileData (&FileData, (LONG)LOWORD (lParam) * FileData.wScrollMax, GetDlgItem (hWnd, IDD_EBOX)); sScroll = 0; break; } if (rc) { PrintError (hWnd, rc); return 0; } sScrollPos += sScroll; if (sScroll) { if (ScrollProc (&FileData, GetDlgItem (hWnd, IDD_EBOX), sScroll) == 0) { SendDlgItemMessage (hWnd, IDD_EBOX, EM_LINESCROLL, 0, MAKELPARAM (sScroll, 0)); { INT sCol, sLine, sNLL, snl, sStart, sEnd; DWORD dwCur; dwCur = SendDlgItemMessage (hWnd, IDD_EBOX, EM_GETSEL, 0, 0); if (sScroll > 0) { sStart = LOWORD (dwCur); sEnd = HIWORD (dwCur); } else { sStart = HIWORD (dwCur); sEnd = LOWORD (dwCur); } // Get the current line number sLine = (INT)SendDlgItemMessage (hWnd, IDD_EBOX, EM_LINEFROMCHAR, sEnd, 0); // Get the starting char index of curr line sCol = (INT)SendDlgItemMessage (hWnd, IDD_EBOX, EM_LINEINDEX, sLine, 0); // Compute column offset into current line of cursor sCol = sEnd - sCol; // Get length of next line snl = (INT)SendDlgItemMessage (hWnd, IDD_EBOX, EM_LINEINDEX, sLine+sScroll, 0); sNLL = (INT)SendDlgItemMessage (hWnd, IDD_EBOX, EM_LINELENGTH, snl, 0); // If column past end of next line, put cur on end of next line if (sCol > sNLL) sCol = sNLL; // Get starting char index of next line if (GetKeyState (VK_SHIFT) & 0x8000) SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETSEL, 1, MAKELPARAM (sStart, snl + sCol)); else SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETSEL, 1, MAKELPARAM (snl + sCol, snl + sCol)); } } SetEBoxScroll (&FileData, hWnd); } return 0; } //------------------------------------------------------------ // DoCommandMain - process WM_COMMAND message for frame window // by decoding the menubar item with the menuitems[] array, // then running the corresponding function to process the command. //------------------------------------------------------------ LONG DoCommandMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT i; UINT idItem, wNotifyCode; HWND hwndCtl; idItem = (UINT) wParam; // Parse Parameters hwndCtl = (HWND) LOWORD(lParam); wNotifyCode = (UINT) HIWORD(lParam); // // Call routine to handle control message // for(i = 0; i < dim(MainMenuItems); i++) { if(idItem == MainMenuItems[i].Code) return (*MainMenuItems[i].Fxn)(hWnd, idItem, hwndCtl, wNotifyCode); } return DefWindowProc(hWnd, wMsg, wParam, lParam); } //------------------------------------------------------------ // DoDropFilesMain - process WM_DROPFILES message for frame window. //------------------------------------------------------------ LONG DoDropFilesMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { char szFileName[256], *pszPtr; INT i, x, y, sFiles, rc; RECT rect; sFiles = DragQueryFile ((HDROP) wParam, -1, 0, 0); if (sFiles) { DragQueryFile ((HDROP) wParam, 0, szFileName, sizeof (szFileName)); // Save current file rc = TermFile (hWnd, &FileData); if (rc) { DragFinish ((HDROP) wParam); PrintError (hWnd, rc); return 0; } else { if (IsIconic (hWnd)) ShowWindow (hWnd, SW_RESTORE); SendMessage (hWnd, MYMSG_OPEN, FileData.fFlags, (LPARAM)(LPSTR)szFileName); } } // Process additional files by opening new copies of program GetModuleFileName (hInst, szFileName, sizeof (szFileName)); pszPtr = szFileName + lstrlen (szFileName); // Get current pos of window to cascade new wnds. GetWindowRect (hWnd, &rect); for (i = 1; i < sFiles; i++) { x = rect.left + (i * GetSystemMetrics (SM_CYCAPTION)); y = rect.top + (i * GetSystemMetrics (SM_CYCAPTION)); wsprintf (pszPtr, " /X %d /Y %d ", x, y); DragQueryFile ((HDROP) wParam, i, szFileName + lstrlen (szFileName), sizeof (szFileName) - lstrlen (szFileName)); WinExec (szFileName, SW_SHOW); } DragFinish ((HDROP) wParam); return TRUE; } //------------------------------------------------------------ // DoCloseMain - process WM_CLOSE message for frame window. //------------------------------------------------------------ LONG DoCloseMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT rc; // Kill search if occuring fStatFlags &= ~(SFLAG_SEARCHING | SFLAG_PASTING); //Save file if necessary rc = TermFile (hWnd, &FileData); if (rc) PrintError (hWnd, rc); else DestroyWindow (hMain); return 0; } //------------------------------------------------------------ // DoDestroyMain - process WM_DESTROY message for frame window. //------------------------------------------------------------ LONG DoDestroyMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { RECT rect; HFONT hFont; LOGFONT fm; DragAcceptFiles (hWnd, FALSE); //Save Window position if (!IsIconic (hWnd) && !IsZoomed (hWnd)) { GetWindowRect (hWnd, &rect); MyWritePrivateProfileInt (szAppName, PRO_XPOS, rect.left, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_YPOS, rect.top, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_XSIZE, rect.right - rect.left, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_YSIZE, rect.bottom - rect.top, szProfileName); } // If not started with command line switches, save state if (!(fStatFlags & SFLAG_SWITCHSTART)) { // If custom font, save it if (!(FileData.fFlags & (FFLAG_PORPFONT | FFLAG_FIXEDFONT))) { //Get current font from edit box to init Font Dlg box hFont = (HANDLE) SendDlgItemMessage (hWnd, IDD_EBOX, WM_GETFONT, 0, 0); if (hFont) { GetObject (hFont, sizeof (fm), &fm); MyWritePrivateProfileInt (szAppName, PRO_FONT1, fm.lfHeight, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT2, fm.lfWidth, szProfileName); // MyWritePrivateProfileInt (szAppName, PRO_FONT3, fm.lfEscapement, // szProfileName); // MyWritePrivateProfileInt (szAppName, PRO_FONT4, fm.lfOrientation, // szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT5, fm.lfWeight, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT6, fm.lfItalic, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT7, fm.lfUnderline, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT8, fm.lfStrikeOut, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT9, fm.lfCharSet, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT10, fm.lfOutPrecision, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT11, fm.lfClipPrecision, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT12, fm.lfQuality, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_FONT13, fm.lfPitchAndFamily, szProfileName); WritePrivateProfileString (szAppName, PRO_FONT14, fm.lfFaceName, szProfileName); } else FileData.fFlags |= FFLAG_PORPFONT; } MyWritePrivateProfileInt (szAppName, PRO_FLAGS, FileData.fFlags, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_TABS, FileData.sTabs, szProfileName); } // Unsubclass edit window MySubClassWindow (GetDlgItem (hWnd, IDD_EBOX), lpfnOldEditProc); PostQuitMessage (0); return DefWindowProc(hWnd, wMsg, wParam, lParam); } //============================================================ // Control handling procedures for MainWindow //============================================================ //------------------------------------------------------------ // DoMainCtlEBox - Process Editbox control messages //------------------------------------------------------------ LONG DoMainCtlEBox (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT rc; LPSEGLIST lpSegList; switch (wNotifyCode) { case EN_CHANGE: if (!fScrolling) { FileData.fFlags |= FLAG_DIRTY; if (FileData.sActBuff != -1) { lpSegList = FileData.bd[FileData.sActBuff].lpSegListPtr; lpSegList->wSize = GetWindowTextLength (GetDlgItem (hWnd, IDD_EBOX)); if (lpSegList->wSize > MAXBLKSIZE) { rc = ChkMaxSize (&FileData, GetDlgItem (hWnd, IDD_EBOX)); if (rc == 0) rc = ScrollProc (&FileData, GetDlgItem (hWnd, IDD_EBOX), 0); if (rc < 0) PrintError (hWnd, rc); } } } break; case EN_MAXTEXT: rc = ChkMaxSize (&FileData, GetDlgItem (hWnd, IDD_EBOX)); if (rc == 0) rc = ScrollProc (&FileData, GetDlgItem (hWnd, IDD_EBOX), 0); if (rc < 0) PrintError (hWnd, rc); break; } return 0; } //------------------------------------------------------------ // DoMainMenuNew - Process New menu item //------------------------------------------------------------ LONG DoMainMenuNew (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT rc; rc = TermFile (hWnd, &FileData); if (rc == 0) { rc = InitFile (0, &FileData, hWnd, 0, 0); SetWindowText (GetDlgItem (hWnd, IDD_EBOX), ""); } if (rc) PrintError (hWnd, rc); else DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuOpen - Process Open menu item //------------------------------------------------------------ LONG DoMainMenuOpen (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { char szStr[MAXFNAMELEN]; static char *szFilter[] = {"All Files (*.*)", "*.*", "" }; INT rc; DWORD fFlags; // Save current file rc = TermFile (hWnd, &FileData); if (rc == ERR_CANCELED) return 0; if (rc) { PrintError (hWnd, rc); return 0; } if (FileData.fFlags & FFLAG_RONLY) fFlags = OFN_FILEMUSTEXIST | OFN_READONLY; else fFlags = OFN_FILEMUSTEXIST; rc = MyGetFilename (hWnd, szStr, sizeof (szStr), fFlags, *szFilter, 1); if (rc == 0) return 0; if (rc == 2) FileData.fFlags |= FFLAG_RONLY; SendMessage (hWnd, MYMSG_OPEN, FileData.fFlags, (LPARAM)(LPSTR)szStr); return 0; } //------------------------------------------------------------ // DoMainMenuSave - Process Save menu item //------------------------------------------------------------ LONG DoMainMenuSave (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT rc; rc = SaveFile (hWnd, &FileData); if (rc) { PrintError (hWnd, rc); return 0; } else DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuSaveAs - Process Save As menu item //------------------------------------------------------------ LONG DoMainMenuSaveAs (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { char szFileName[MAXFNAMELEN]; static char *szFilter[] = {"All Files (*.*)", "*.*", "" }; INT rc; lstrcpy (szFileName, FileData.szFileName); if (MyGetSavename (hWnd, szFileName, sizeof (szFileName), *szFilter, 1) == 0) return 0; if (lstrcmpi (szFileName, FileData.szFileName) == 0) rc = SaveFile (hWnd, &FileData); else rc = WriteToFile (hWnd, &FileData, szFileName); if (rc == 0) { // Close old source file FileOps (&FileData.hSrcFile, FOP_CLOSE, 0, 0, &rc); // Copy new name into file structure. lstrcpy (FileData.szFileName, szFileName); // Reopen new source file. FileOps (&FileData.hSrcFile, FOP_OPEN, (LONG)(LPVOID)FileData.szFileName, OF_READ | OF_SHARE_DENY_WRITE, &rc); } if (rc) PrintError (hWnd, rc); else DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuROnly - Process Read Only menu item //------------------------------------------------------------ LONG DoMainMenuROnly (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { if (FileData.fFlags & FFLAG_RONLY) { FileData.fFlags &= ~FFLAG_RONLY; SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETREADONLY, FALSE, 0); } else { FileData.fFlags |= FFLAG_RONLY; SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETREADONLY, TRUE, 0); } return 0; } //------------------------------------------------------------ // DoMainMenuExit - Process Exit menu item //------------------------------------------------------------ LONG DoMainMenuExit (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { // Close the app SendMessage (hWnd, WM_CLOSE, 0, 0); return 0; } //------------------------------------------------------------ // DoMainMenuUndo - Process Edit|Undo menu item //------------------------------------------------------------ LONG DoMainMenuUndo (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { SendDlgItemMessage (hWnd, IDD_EBOX, WM_UNDO, 0, 0); DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuCut - Process Edit|Cut menu item //------------------------------------------------------------ LONG DoMainMenuCut (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { SendDlgItemMessage (hWnd, IDD_EBOX, WM_CUT, 0, 0); DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuCopy - Process Edit|Copy menu item //------------------------------------------------------------ LONG DoMainMenuCopy (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { SendDlgItemMessage (hWnd, IDD_EBOX, WM_COPY, 0, 0); DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // EnableMainWindow //------------------------------------------------------------ INT EnableMainWindow (HWND hWnd, BOOL fEnable) { HMENU hMenu; hMenu = GetMenu (hWnd); if (fEnable) { // Un-readonly the ebox if (!(FileData.fFlags & FFLAG_RONLY)) SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETREADONLY, FALSE, 0); EnableMenuItem (hMenu, 0, MF_BYPOSITION | MF_ENABLED); EnableMenuItem (hMenu, 1, MF_BYPOSITION | MF_ENABLED); EnableMenuItem (hMenu, 2, MF_BYPOSITION | MF_ENABLED); EnableMenuItem (hMenu, 3, MF_BYPOSITION | MF_ENABLED); } else { SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETREADONLY, TRUE, 0); EnableMenuItem (hMenu, 0, MF_BYPOSITION | MF_GRAYED); EnableMenuItem (hMenu, 1, MF_BYPOSITION | MF_GRAYED); EnableMenuItem (hMenu, 2, MF_BYPOSITION | MF_GRAYED); EnableMenuItem (hMenu, 3, MF_BYPOSITION | MF_GRAYED); } DrawMenuBar (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuPaste - Process Edit|Paste menu item //------------------------------------------------------------ LONG DoMainMenuPaste (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { HGLOBAL hData, hTemp; LPSTR lpTemp, lpDest; char huge *lpClip; LONG lSize, lEboxSize; HWND hWndEdit; UINT wCur; INT i, rc = 0; if (OpenClipboard (hWnd)) { // See if text in clipboard hData = GetClipboardData (CF_TEXT); if (hData) { // Get edit box handle since it is used often hWndEdit = GetDlgItem (hWnd, IDD_EBOX); // compute size of clip data lSize = GlobalSize (hData); lEboxSize = GetWindowTextLength (hWndEdit); // If data will overflow ebox, stuff it in smaller chunks if (lSize + lEboxSize > 0xc000) { // Need temp buff since clip data in huge seg hTemp = GlobalAlloc (GHND, STDREADLEN+15); if (hTemp == 0) { PrintError (hWnd, ERR_OUT_OF_MEMORY); return 0; } lpClip = GlobalLock (hData); lpTemp = GlobalLock (hTemp); // Set flag for possible cancel. fStatFlags |= SFLAG_PASTING; EnableMainWindow (hWnd, FALSE); while ((lSize > 0) && (rc == 0)) { // Break data into small chunks. Since we // are dealing with a huge segment, we can't // use the std lib stuff. if (lSize > STDREADLEN) { for (i = 0, lpDest = lpTemp; i < STDREADLEN; i++) *lpDest++ = *lpClip++; lSize -= lpDest - lpTemp; } else { // If at end of data, scan to term zero. lpDest = lpTemp; while (--lSize && (*lpDest++ = *lpClip++)) ; } *lpDest = '\0'; // Insert the data SendMessage (hWndEdit, EM_REPLACESEL, 0, (LPARAM)lpTemp); if (!MyYield()) rc = ERR_CANCELED; // Set no sel wCur = HIWORD (SendDlgItemMessage (hWnd, IDD_EBOX, EM_GETSEL, 0, 0)); SendMessage (hWndEdit, EM_SETSEL, 0, MAKELPARAM (wCur, wCur)); if (!(fStatFlags & SFLAG_PASTING)) rc = ERR_CANCELED; } if (rc == 0) rc = 1; GlobalUnlock (hData); GlobalUnlock (hTemp); GlobalFree (hTemp); EnableMainWindow (hWnd, TRUE); } } CloseClipboard(); } if (rc == 0) SendDlgItemMessage (hWnd, IDD_EBOX, WM_PASTE, 0, 0); ScrollProc (&FileData, hWndEdit, 0); if (rc >= 0) DisplayCurrStatus (hWnd); else PrintError (hWnd, rc); return 0; } //------------------------------------------------------------ // DoMainMenuDelete - Process Edit|Delete menu item //------------------------------------------------------------ LONG DoMainMenuDelete (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { SendDlgItemMessage (hWnd, IDD_EBOX, EM_REPLACESEL, 0, (LPARAM)(LPSTR)""); ScrollProc (&FileData, GetDlgItem (hWnd, IDD_EBOX), 0); DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuSelectAll - Process Edit|Select All menu item //------------------------------------------------------------ LONG DoMainMenuSelectAll (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { FileData.fFlags |= FFLAG_SELALL; SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETSEL, 1, MAKELPARAM (0, -1)); return 0; } //------------------------------------------------------------ // DoMainMenuWWrap - Process Edit|Word Wrap menu item //------------------------------------------------------------ LONG DoMainMenuWWrap (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT sTop, sTopChar, sMod; HGLOBAL hTemp, hBuff; HWND hWndE1, hWndE2; LPSTR lpBuff; DWORD dwCur; HFONT hFont; hWndE1 = GetDlgItem (hWnd, IDD_EBOX); // Modify the wrap flag if (FileData.fFlags & FFLAG_WWRAP) { FileData.fFlags &= ~FFLAG_WWRAP; } else { FileData.fFlags |= FFLAG_WWRAP; } // Allocate transfer buffer. hBuff = GlobalAlloc (GHND, 0x10000); if (hBuff) { lpBuff = GlobalLock (hBuff); // Unsubclass current ebox buffer. MySubClassWindow (hWndE1, lpfnOldEditProc); hFont = (HFONT)SendMessage (hWndE1, WM_GETFONT, 0, 0); // Create new ebox window and subclass hTemp = CreateEditWnd (hWnd, &FileData, &hWndE2); lpfnOldEditProc = MySubClassWindow (hWndE2, lpfnEditSCProc); if (hFont) SendMessage (hWndE2, WM_SETFONT, hFont, 0); // Get current scroll position dwCur = SendMessage (hWndE1, EM_GETSEL, 0, 0); sTop = (INT)SendMessage (hWndE1, EM_GETFIRSTVISIBLELINE, 0, 0); sTopChar = (INT)SendMessage (hWndE1, EM_LINEINDEX, sTop, 0); sMod = (INT)SendMessage (hWndE1, EM_GETMODIFY, 0, 0); // Move the data GetWindowText (hWndE1, lpBuff, 0xFFFF); SetWindowText (hWndE2, lpBuff); // Set current scroll postition sTop = (INT)SendMessage (hWndE2, EM_LINEFROMCHAR, sTopChar, 0); SendMessage (hWndE2, EM_LINESCROLL, 0, MAKELPARAM (sTop, 0)); SendMessage (hWndE2, EM_SETSEL, 1, dwCur); SendMessage (hWndE2, EM_SETMODIFY, sMod, 0); ShowWindow (hWndE2, SW_SHOW); SetFocus (hWndE2); // Free transfer buffer GlobalUnlock (hBuff); GlobalFree (hBuff); // Destroy old edit window DestroyWindow (hWndE1); GlobalUnlock (hEdit); GlobalFree (hEdit); // Save new edit box 'local' buffer. hEdit = hTemp; } SendMessage (hWnd, MYMSG_REFORMAT, 0, 0); return 0; } //------------------------------------------------------------ // DoMainMenuFind - Process Find menu item. //------------------------------------------------------------ LONG DoMainMenuFind (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { hwndFR = MyDispFindtextBox (hWnd, szFindText, sizeof (szFindText), FR_DOWN | FR_HIDEWHOLEWORD); DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuFindNext - Process Find Next menu item. //------------------------------------------------------------ LONG DoMainMenuFindNext (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { if (fStatFlags & SFLAG_FFIRST) { PostMessage (hWnd, WM_COMMAND, IDM_FIND, 0); return 0; } fr.lStructSize = sizeof (fr); fr.Flags = fFindFlags | FR_FINDNEXT; fr.Flags &= ~FR_REPLACE; fr.lpstrFindWhat = (LPSTR)&szFindText; PostMessage (hWnd, wFindMsg, 0, (LPARAM) (LPFINDREPLACE)&fr); return 0; } //------------------------------------------------------------ // DoMainMenuReplace - Process Find, Find Next and Find Prev menu // items. //------------------------------------------------------------ LONG DoMainMenuReplace (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { hwndFR = MyDispReptextBox (hWnd, szFindText, sizeof (szFindText), szRepText, sizeof (szRepText), FR_HIDEWHOLEWORD); DisplayCurrStatus (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuFindNext - Process Find Next message. //------------------------------------------------------------ LONG DoFindNextMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { FINDREPLACE far *lpfr; INT sRepCnt, sLine; DWORD dwData; LONG lFindPtr; char szStatText[80]; lpfr = (FINDREPLACE far *)lParam; if (lpfr->Flags & FR_DIALOGTERM) { fStatFlags &= ~SFLAG_SEARCHING; hwndFR = 0; SetFocus (hWnd); return 0; } fStatFlags &= ~SFLAG_FFIRST; fFindFlags = lpfr->Flags; SetStatusBarText (hWnd, "Searching...", 0); fStatFlags |= SFLAG_SEARCHING; EnableMainWindow (hWnd, FALSE); lFindPtr = SearchReplace (hWnd, lpfr->lpstrFindWhat, lpfr->lpstrReplaceWith, (lpfr->Flags & FR_DOWN) ? TRUE : FALSE, (lpfr->Flags & FR_MATCHCASE) ? TRUE : FALSE, (lpfr->Flags & FR_FINDNEXT) ? TRUE : FALSE); EnableMainWindow (hWnd, TRUE); if (lFindPtr != -1) { GetFileData (&FileData, lFindPtr, GetDlgItem (hWnd, IDD_EBOX)); sLine = (INT)SendDlgItemMessage (hWnd, IDD_EBOX, EM_LINEFROMCHAR, -1, 0); if (sLine == (INT)SendDlgItemMessage (hWnd, IDD_EBOX, EM_GETFIRSTVISIBLELINE, 0, 0)) ScrollProc (&FileData, GetDlgItem (hWnd, IDD_EBOX), -1); dwData = SendDlgItemMessage (hWnd, IDD_EBOX, EM_GETSEL, 0, 0); SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETSEL, 0, MAKELONG (LOWORD (dwData), LOWORD (dwData)+lstrlen (lpfr->lpstrFindWhat))); SetStatusBarText (hWnd, "Found", 0); if (lpfr->Flags & FR_REPLACE) { SendDlgItemMessage (hWnd, IDD_EBOX, EM_REPLACESEL, 0, (LPARAM)lpfr->lpstrReplaceWith); } else if (lpfr->Flags & FR_REPLACEALL) { sRepCnt = 0; fStatFlags |= SFLAG_SEARCHING; EnableMainWindow (hWnd, FALSE); fPaint = FALSE; while ((lFindPtr != -1) && (fStatFlags & SFLAG_SEARCHING)) { sRepCnt++; GetFileData (&FileData, lFindPtr, GetDlgItem (hWnd, IDD_EBOX)); dwData = SendDlgItemMessage (hWnd, IDD_EBOX, EM_GETSEL, 0, 0); SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETSEL, 0, MAKELONG (LOWORD (dwData), LOWORD (dwData)+lstrlen (lpfr->lpstrFindWhat))); SendDlgItemMessage (hWnd, IDD_EBOX, EM_REPLACESEL, 0, (LPARAM)lpfr->lpstrReplaceWith); lFindPtr = SearchReplace (hWnd, lpfr->lpstrFindWhat, lpfr->lpstrReplaceWith, (lpfr->Flags & FR_DOWN) ? TRUE : FALSE, (lpfr->Flags & FR_MATCHCASE) ? TRUE : FALSE, TRUE); } fPaint = TRUE; EnableMainWindow (hWnd, TRUE); wsprintf (szStatText, "%d occurrences changed.", sRepCnt); SetStatusBarText (hWnd, szStatText, 0); } } else SetStatusBarText (hWnd, "Text not found", 0); return 0; } //------------------------------------------------------------ // DoMainMenuSelFont - Process Select Font menu item //------------------------------------------------------------ LONG DoMainMenuSelFont (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT sSize; HFONT hFont, hFontOld; COLORREF rgbColor; LOGFONT fm; //Get current font from edit box to init Font Dlg box hFontOld = (HANDLE) SendDlgItemMessage (hWnd, IDD_EBOX, WM_GETFONT, 0, 0); if (hFontOld == 0) GetObject (GetStockObject (SYSTEM_FONT), sizeof (fm), &fm); else GetObject (hFontOld, sizeof (fm), &fm); rgbColor = RGB (0, 0, 0); if (MyGetFont (hWnd, &fm, &sSize, &rgbColor, CF_INITTOLOGFONTSTRUCT)) { // If user selects font, create it and tell edit box // to use it. if (hFont = CreateFontIndirect (&fm)) SendDlgItemMessage (hWnd, IDD_EBOX, WM_SETFONT, (WPARAM) hFont, 0); FileData.fFlags &= ~(FFLAG_PORPFONT | FFLAG_FIXEDFONT); SendMessage (hWnd, MYMSG_REFORMAT, 0, 0); } return 0; } //------------------------------------------------------------ // DoMainMenuDefPFont - Process Select Sys Prop Font menu item //------------------------------------------------------------ LONG DoMainMenuDefPFont (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { HFONT hFont, hFontOld; //Get current font from edit box hFontOld = (HANDLE) SendDlgItemMessage (hWnd, IDD_EBOX, WM_GETFONT, 0, 0); hFont = GetStockObject (SYSTEM_FONT); SendDlgItemMessage (hWnd, IDD_EBOX, WM_SETFONT, (WPARAM) hFont, 0); if (hFontOld) DeleteObject (hFontOld); FileData.fFlags &= ~FFLAG_FIXEDFONT; FileData.fFlags |= FFLAG_PORPFONT; SendMessage (hWnd, MYMSG_REFORMAT, 0, 0); return 0; } //------------------------------------------------------------ // DoMainMenuDefFFont - Process Select Sys Fixed Font menu item //------------------------------------------------------------ LONG DoMainMenuDefFFont (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { HFONT hFont, hFontOld; //Get current font from edit box hFontOld = (HANDLE) SendDlgItemMessage (hWnd, IDD_EBOX, WM_GETFONT, 0, 0); hFont = GetStockObject (ANSI_FIXED_FONT); SendDlgItemMessage (hWnd, IDD_EBOX, WM_SETFONT, (WPARAM) hFont, 0); if (hFontOld) DeleteObject (hFontOld); FileData.fFlags |= FFLAG_FIXEDFONT; FileData.fFlags &= ~FFLAG_PORPFONT; SendMessage (hWnd, MYMSG_REFORMAT, 0, 0); return 0; } //------------------------------------------------------------ // DoMainMenuSetTabs - Process Set Tabs menu item //------------------------------------------------------------ LONG DoMainMenuSetTabs (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT i; i = MyDisplayDialog(hInst, "TabsBox", hWnd, (WNDPROC) SetTabsDlgProc, FileData.sTabs); if (i) { FileData.sTabs = i; SetTabs (GetDlgItem (hWnd, IDD_EBOX), i); } return 0; } //------------------------------------------------------------ // DoMainMenuHelp - Process Help menu item //------------------------------------------------------------ LONG DoMainMenuHelp (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { char szText [1024], *pszText; INT i; szText[0] = '\0'; for (i = 1000; i < 1004; i++) { pszText = szText + lstrlen (szText); LoadString (hInst, i, pszText, sizeof (szText)); } MessageBox (hWnd, szText, szTitleText, MB_OK); return 0; } //------------------------------------------------------------ // DoMainMenuAbout - Process About menu item //------------------------------------------------------------ LONG DoMainMenuAbout (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { MyDisplayDialog(hInst, "AboutBox", hWnd, (WNDPROC) AboutDlgProc, 0); DisplayCurrStatus (hWnd); return 0; } //============================================================ // // EditWndSCProc - Edit box subclass procedure // //============================================================ LONG CALLBACK EditWndSCProc (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { LONG lRet; UINT wLIndex; INT sScroll, rc; INT sLen; PAINTSTRUCT ps; RECT rect; switch (wMsg) { case WM_PAINT: if (fPaint) break; if (GetUpdateRect (hWnd, &rect, FALSE) == 0) return 0; BeginPaint (hWnd, &ps); ValidateRect (hWnd, NULL); EndPaint (hWnd, &ps); return 0; case WM_CHAR: if (!(FileData.fFlags & FFLAG_RONLY)) { lRet = SendMessage (hWnd, EM_GETSEL, 0, 0); // If no selection, and a real character, check overstrike if (LOWORD (lRet) == HIWORD (lRet)) { if ((wParam < ' ') && (wParam != VK_TAB) && (wParam != VK_RETURN)) break; // If overstrike mode, sel next char so it is replaced by // key just hit. if (!(GetKeyState (VK_INSERT) & 1)) { wLIndex = (UINT)SendMessage (hWnd, EM_LINEINDEX, -1, 0); sLen = (INT)SendMessage (hWnd, EM_LINELENGTH, LOWORD (lRet), 0); // If enter, move cursor to start of next line. if (wParam == VK_RETURN) { if (wLIndex < GetWindowTextLength (hWnd)) { wLIndex = wLIndex + sLen + 2; SendMessage (hWnd, EM_SETSEL, 0, MAKELPARAM (wLIndex, wLIndex)); // If at end of file, allow enter to insert new line if (wLIndex < GetWindowTextLength (hWnd)) return 0; } // If cursor at end of line or beyond, don't overstrike } else if (sLen > (INT)(LOWORD (lRet) - wLIndex)) { lRet += 0x10000; SendMessage (hWnd, EM_SETSEL, 1, lRet); } } } // Check here for too much data in edit box lRet = CallWindowProc (lpfnOldEditProc, hWnd, wMsg, wParam, lParam); ScrollProc (&FileData, hWnd, 0); SetEBoxScroll (&FileData, GetParent (hWnd)); return lRet; } break; case WM_LBUTTONDOWN: // Clear select all flag FileData.fFlags &= ~FFLAG_SELALL; break; case WM_KEYDOWN: rc = 0; // Clear select all flag FileData.fFlags &= ~FFLAG_SELALL; // Check for scrolling keys and perform necessary segment // stuff. sScroll = 0; switch (wParam) { case VK_SHIFT: return CallWindowProc (lpfnOldEditProc, hWnd, wMsg, wParam, lParam); case VK_UP: sScroll = -1; break; case VK_DOWN: sScroll = 1; break; case VK_PRIOR: if (GetKeyState (VK_CONTROL) & 0x1000) { rc = GetFileData (&FileData, 0, hWnd); if (rc) PrintError (GetParent (hWnd), rc); else DisplayCurrStatus (GetParent (hWnd)); return 0; } sScroll = -(FileData.sEBoxLines - 1); break; case VK_NEXT: if (GetKeyState (VK_CONTROL) & 0x1000) { rc = GetFileData (&FileData, 0x7fffffff, hWnd); if (rc) PrintError (GetParent (hWnd), rc); else DisplayCurrStatus (GetParent (hWnd)); return 0; } sScroll = FileData.sEBoxLines - 1; break; case VK_HOME: if (GetKeyState (VK_CONTROL) & 0x1000) { rc = GetFileData (&FileData, 0, hWnd); if (rc) PrintError (GetParent (hWnd), rc); else DisplayCurrStatus (GetParent (hWnd)); return 0; } break; case VK_END: if (GetKeyState (VK_CONTROL) & 0x1000) { rc = GetFileData (&FileData, 0x7fffffff, hWnd); if (rc) PrintError (GetParent (hWnd), rc); else DisplayCurrStatus (GetParent (hWnd)); return 0; } break; case VK_DELETE: rc = ScrollProc (&FileData, hWnd, 0); SetEBoxScroll (&FileData, GetParent (hWnd)); if (rc < 0) PrintError (GetParent (hWnd), rc); return CallWindowProc (lpfnOldEditProc, hWnd, wMsg, wParam, lParam); } if (sScroll) { // Process scroll char rc = ScrollProc (&FileData, hWnd, sScroll); SetEBoxScroll (&FileData, GetParent (hWnd)); } if (rc >= 0) lRet = CallWindowProc (lpfnOldEditProc, hWnd, wMsg, wParam, lParam); if (rc < 0) { PrintError (GetParent (hWnd), rc); return 0; } else DisplayCurrStatus (GetParent (hWnd)); return lRet; } return CallWindowProc (lpfnOldEditProc, hWnd, wMsg, wParam, lParam); } //============================================================ // SetTabsDlgProc - SetTabs dialog box dialog procedure //============================================================ BOOL CALLBACK SetTabsDlgProc (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT i; switch (wMsg) { case WM_INITDIALOG: SetDlgItemInt (hWnd, IDD_TABVAL, (INT)lParam, FALSE); return TRUE; case WM_COMMAND: switch (wParam) { case IDOK: i = (INT)GetDlgItemInt (hWnd, IDD_TABVAL, NULL, FALSE); EndDialog (hWnd, i); return TRUE; case IDCANCEL: EndDialog (hWnd, 0); return TRUE; } break; } return FALSE; } //============================================================ // AboutDlgProc - About dialog box dialog procedure //============================================================ BOOL CALLBACK AboutDlgProc (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { HWND hwndText; RECT rect; HDC hdc; PAINTSTRUCT ps; HPEN hDPen, hLPen, hOldPen; switch (wMsg) { case WM_INITDIALOG: return TRUE; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); hwndText = GetDlgItem (hWnd, IDD_COPYDATE); if (IsWindow (hwndText)) { GetClientRect (hwndText, &rect); ClientToScreen (hwndText, (LPPOINT)&rect); ScreenToClient (hWnd, (LPPOINT)&rect); rect.left -= 2; rect.top -= 2; rect.right += rect.left + 4; rect.bottom += rect.top + 4; hDPen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNSHADOW)); hLPen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNHIGHLIGHT)); hOldPen = SelectObject (hdc, hDPen); MoveTo (hdc, rect.left, rect.bottom); LineTo (hdc, rect.left, rect.top); LineTo (hdc, rect.right+1, rect.top); //Start at bottom left, draw light pen over and up. SelectObject (hdc, hLPen); MoveTo (hdc, rect.left+1, rect.bottom); LineTo (hdc, rect.right, rect.bottom); LineTo (hdc, rect.right, rect.top); SelectObject (hdc, hOldPen); DeleteObject (hDPen); DeleteObject (hLPen); } EndPaint(hWnd, &ps); return TRUE; case WM_COMMAND: if ((wParam == IDOK) || (wParam == IDCANCEL)) { EndDialog(hWnd, 0); return TRUE; } } return FALSE; } //------------------------------------------------------------ // SetTabs - Sets the tab stops for the edit window //------------------------------------------------------------ void SetTabs (HWND hWndEBox, INT sTabs) { sTabs *= 4; SendMessage (hWndEBox, EM_SETTABSTOPS, 1, (LPARAM)(INT far *)&sTabs); InvalidateRect (hWndEBox, NULL, FALSE); return; } //------------------------------------------------------------ // CreateEditWnd - Creates a multiline edit box with proper // setup. //------------------------------------------------------------ HGLOBAL CreateEditWnd (HWND hWnd, PFILEDATA pfd, HWND *hWndEdit) { INT x,y, cx, cy; HWND hWndTemp; RECT rect; LONG lStyle; HGLOBAL hEdit; LPBYTE lpBuff; if (hWndEdit == 0) hWndEdit = &hWndTemp; // Allocate memory for edit box local store hEdit = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE, 0x10000); lpBuff = GlobalLock (hEdit); LocalInit (HIWORD (lpBuff), 0, (WORD)GlobalSize (hEdit) - 16); GlobalUnlock (hEdit); GetEBoxPos (hWnd, &x, &y, &cx, &cy); GetClientRect (hWndVScroll, &rect); cx -= (rect.right - rect.left); if (pfd->fFlags & FFLAG_WWRAP) lStyle = WS_CHILD | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | ES_NOHIDESEL; else lStyle = WS_CHILD | ES_MULTILINE | ES_AUTOVSCROLL | WS_HSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | ES_NOHIDESEL; // Note we are using a seperate global memory block for the edit // control. This will allow it to contain a full 64K of data and // at the same time dramatically increase performance of the box. *hWndEdit = CreateWindow ("edit", NULL, lStyle, x, y, cx, cy, hWnd, IDD_EBOX, hEdit, NULL); SendMessage (*hWndEdit, EM_FMTLINES, FALSE, 0); SendMessage (*hWndEdit, EM_LIMITTEXT, 0, 0); return hEdit; } //------------------------------------------------------------ // DisplayCurrStatus - Creates a text string describing the // current status, then displays it in the status bar. //------------------------------------------------------------ void DisplayCurrStatus (HWND hWnd) { if (lstrlen (FileData.szFileName)) SetStatusBarText (hWnd, FileData.szFileName, 0); else SetStatusBarText (hWnd, "Super Notepad", 0); if (FileData.fFlags & FLAG_DIRTY) SetStatusBarText (hWnd, "Mod", 1); else SetStatusBarText (hWnd, "", 1); if (GetKeyState (VK_CAPITAL) & 1) SetStatusBarText (hWnd, "Cap", 2); else SetStatusBarText (hWnd, "", 2); if (GetKeyState (VK_INSERT) & 1) SetStatusBarText (hWnd, "Ins", 3); else SetStatusBarText (hWnd, "Ovr", 3); if (GetKeyState (VK_NUMLOCK) & 1) SetStatusBarText (hWnd, "Num", 4); else SetStatusBarText (hWnd, "", 4); return; } //============================================================ // Text and buffer management routines //============================================================ //------------------------------------------------------------ // CopyAllToClip - Copy file text to clipboard //------------------------------------------------------------ INT CopyAllToClip (HWND hWnd, PFILEDATA pfd) { LPSEGLIST lpSegList; HGLOBAL hData; char huge *lpData; LPSTR lpBuff; LONG lSize = 0; INT i, sBuff, rc = 0; if (OpenClipboard (hWnd) == 0) return ERR_CANTOPENCLIP; // Update size of currently edited blk lpSegList = pfd->bd[pfd->sActBuff].lpSegListPtr; lpSegList->wSize = GetWindowTextLength (GetDlgItem (hWnd, IDD_EBOX)); // Get the size of the file lpSegList = pfd->lpbl; for (i = 1; i < SEGLISTSIZE; i++) { lSize += (LONG)lpSegList->wSize; if (lpSegList->fFlags & FLAG_LASTSEG) break; lpSegList++; } // Alloc memory for clipboard data hData = GlobalAlloc (GHND | GMEM_DDESHARE, lSize+1); if (hData == 0) return ERR_FILEDATATOOBIG; lpData = GlobalLock (hData); // Get data from file, write it to the data block lpSegList = pfd->lpbl; while (rc == 0) { sBuff = GetSegment (pfd, lpSegList, &rc); if (rc == 0) { lpBuff = GlobalLock (pfd->bd[sBuff].hBuff); _fmemmove (lpData, lpBuff, lpSegList->wSize); GlobalUnlock (pfd->bd[sBuff].hBuff); lpData += lpSegList->wSize; } if (lpSegList->fFlags & FLAG_LASTSEG) break; lpSegList++; } *lpData = '\0'; // Set the clipboard data rc = 0; GlobalUnlock (hData); if (SetClipboardData (CF_TEXT, hData) == 0) { rc = ERR_CANTSETCLIP; GlobalFree (hData); } CloseClipboard (); return rc; } //------------------------------------------------------------ // SearchReplace - Handles the search and replace functions. //------------------------------------------------------------ LONG SearchReplace (HWND hWnd, LPSTR pszFind, LPSTR pszRep, BOOL fDown, BOOL fChkCase, BOOL fNext) { INT sBuff, rc, sFindCnt, sFindLen; UINT wOffset, wFindOffset; LPSEGLIST lpSegList, lpFindSeg; LPSTR lpbBuff, lpbSrch, lpbEnd; LONG lTemp; char ch1; char szFindText[256]; wOffset = (UINT) HIWORD (SendDlgItemMessage (hWnd, IDD_EBOX, EM_GETSEL, 0, 0)); SendDlgItemMessage (hWnd, IDD_EBOX, EM_SETSEL, 0, MAKELONG (wOffset, wOffset)); lpSegList = FileData.bd[FileData.sActBuff].lpSegListPtr; sFindLen = lstrlen (pszFind); if (!fChkCase) { lstrcpy (szFindText, pszFind); pszFind = szFindText; AnsiUpper (pszFind); } sFindCnt = sFindLen; while ((fStatFlags & SFLAG_SEARCHING) && (sFindCnt)) { if (!MyYield()) { fStatFlags &= ~SFLAG_SEARCHING; break; } sBuff = GetSegment (&FileData, lpSegList, &rc); if (rc) break; if (!MyYield()) { fStatFlags &= ~SFLAG_SEARCHING; break; } lpbBuff = GlobalLock (FileData.bd[sBuff].hBuff); lpbSrch = lpbBuff + wOffset; if (fDown) { lpbEnd = lpbBuff + lpSegList->wSize; while ((sFindCnt) && (lpbSrch < lpbEnd)) { if (fChkCase) ch1 = *lpbSrch++; else ch1 = (char)(DWORD)AnsiUpper (MAKELP (0, *lpbSrch++)); if (ch1 == *(pszFind+sFindLen-sFindCnt)) { // Mark ptr to start of found word. Ugly because // word could stradle segments. if (sFindCnt == sFindLen) { lpFindSeg = lpSegList; wFindOffset = lpbSrch - lpbBuff - 1; } sFindCnt--; } else sFindCnt = sFindLen; } if (sFindCnt) { if (lpSegList->fFlags & FLAG_LASTSEG) break; lpSegList++; wOffset = 0; } } else { while ((sFindCnt) && (lpbSrch > lpbBuff)) { if (fChkCase) ch1 = *--lpbSrch; else ch1 = (char)(DWORD) AnsiUpper (MAKELP (0, *--lpbSrch)); if (ch1 == *(pszFind+sFindCnt-1)) { sFindCnt--; // Mark ptr to start of found word. Ugly because // word could stradle segments. if (sFindCnt == 0) { lpFindSeg = lpSegList; wFindOffset = lpbSrch - lpbBuff; } } else sFindCnt = sFindLen; } if (sFindCnt) { if (lpSegList == FileData.lpbl) break; lpSegList--; wOffset = lpSegList->wSize; } } GlobalUnlock (FileData.bd[sBuff].hBuff); } if (sFindCnt) return -1; // convert buffer/offset to offset into file lpSegList = FileData.lpbl; lTemp = 0; while (lpSegList != lpFindSeg) { lTemp += lpSegList->wSize; lpSegList++; } lTemp += wFindOffset; return lTemp; } //------------------------------------------------------------ // DeleteEntry - Removes an entry from the segment list //------------------------------------------------------------ INT DeleteEntry (LPFILEDATA pfd, INT sBuff) { LPSEGLIST lpPtr, lpNext; INT i, sBuffs = 0; lpPtr = pfd->bd[sBuff].lpSegListPtr; // Remove deleted seg from buffer list pfd->bd[sBuff].lpSegListPtr = 0; pfd->bd[sBuff].sLRU = 0; // Count number of active buffers. for (i = 0; i < NUMBUFFS; i++) if (pfd->bd[i].lpSegListPtr) sBuffs++; lpNext = lpPtr+1; if (lpPtr->fFlags & FLAG_LASTSEG) { if (lpPtr != pfd->lpbl) lpPtr--; lpPtr->fFlags |= FLAG_LASTSEG; } else { while (!(lpPtr->fFlags & FLAG_LASTSEG)) { // If segment in buffer list, adjust ptr in list. if (sBuffs) { for (i = 0; i < NUMBUFFS; i++) { if (lpNext == pfd->bd[i].lpSegListPtr) { pfd->bd[i].lpSegListPtr--; sBuffs--; break; } } } // Move data from next seg to this seg. lpPtr->lLoc = lpNext->lLoc; lpPtr->fFlags = lpNext->fFlags; lpPtr->wSize = lpNext->wSize; lpPtr++; lpNext++; } } return 0; } //------------------------------------------------------------ // SplitEntry - Splits a block in the segment list //------------------------------------------------------------ INT SplitEntry (LPFILEDATA pfd, INT sBuff, INT sNewBuff) { LPSEGLIST lpPtr, lpNext, lpSplit; LONG lSize = 0; INT i, sBuffs = 0; lpSplit = pfd->bd[sBuff].lpSegListPtr; pfd->bd[sNewBuff].lpSegListPtr = 0; pfd->bd[sNewBuff].sLRU = 0; // Count number of segments to get last segment ptr lpPtr = pfd->lpbl; for (i = 0; i < SEGLISTSIZE; i++) { lSize += lpPtr->wSize; if (lpPtr->fFlags & FLAG_LASTSEG) break; lpPtr++; } // While we're here, update the scroll bar modifier. pfd->wScrollMax = (UINT)((lSize / 32767) + 1); // If list full, exit if (i == SEGLISTSIZE) return ERR_FILE_TOO_BIG; // Count number of active buffers. for (i = 0; i < NUMBUFFS; i++) if (pfd->bd[i].lpSegListPtr) sBuffs++; lpNext = lpPtr+1; while (lpPtr > lpSplit) { // If segment in buffer list, adjust ptr in list. if (sBuffs) { for (i = 0; i < NUMBUFFS; i++) { if (lpPtr == pfd->bd[i].lpSegListPtr) { pfd->bd[i].lpSegListPtr++; sBuffs--; break; } } } // Move data from next seg to this seg. lpNext->lLoc = lpPtr->lLoc; lpNext->fFlags = lpPtr->fFlags; lpNext->wSize = lpPtr->wSize; // Don't dup last seg flag lpPtr->fFlags &= ~FLAG_LASTSEG; lpPtr--; lpNext--; } // Move data from next seg to this seg. lpNext->lLoc = lpPtr->lLoc; lpNext->fFlags = lpPtr->fFlags; lpNext->wSize = lpPtr->wSize; // Don't dup last seg flag lpPtr->fFlags &= ~FLAG_LASTSEG; pfd->bd[sNewBuff].lpSegListPtr = lpNext; lpNext->fFlags |= sNewBuff; pfd->bd[sNewBuff].sLRU = pfd->bd[sBuff].sLRU; return 0; } //------------------------------------------------------------ // ChkMaxSize - Monitors and fixes ebox when it contains too // much data. //------------------------------------------------------------ INT ChkMaxSize (PFILEDATA pfd, HWND hWndEdit) { UINT wCaret, wSplit, wEnd; LPSEGLIST lpSegList, lpSegListNew; INT sTop, sBuff, sNewBuff, rc = 0; LPSTR lpBuff, lpBuff1; INT sSide = -1; DWORD dwData; lpSegList = pfd->bd[pfd->sActBuff].lpSegListPtr; if (lpSegList == 0) return 0; dwData = SendMessage (hWndEdit, EM_GETSEL, 0, 0); wEnd = GetWindowTextLength (hWndEdit); // Check for too much data in edit box if ((wEnd > MAXBLKSIZE) && (LOWORD (dwData) == HIWORD (dwData))) { wCaret = LOWORD (dwData); sTop = (INT) SendMessage (hWndEdit, EM_GETFIRSTVISIBLELINE, 0, 0); wSplit = (UINT) SendMessage (hWndEdit, EM_LINEINDEX, sTop, 0); if (wSplit < STDREADLEN) { wSplit = (UINT) SendMessage (hWndEdit, EM_LINEINDEX, sTop + pfd->sEBoxLines, 0); if (wEnd - wSplit < STDREADLEN) sSide = 0; else { sSide = 1; wSplit = wEnd - STDREADLEN; } } else wSplit = STDREADLEN; if (sSide) { // Get old segment data sBuff = GetSegment (pfd, lpSegList, &rc); if (rc == 0) sNewBuff = GetFreeBuffer (pfd, &rc); if (rc == 0) { // Make dup entry in seglist table rc = SplitEntry (pfd, sBuff, sNewBuff); if (rc == 0) { // Copy data from end of blk to next blk lpBuff1 = GlobalLock (pfd->bd[sNewBuff].hBuff); lpBuff = GlobalLock (pfd->bd[sBuff].hBuff); _fmemmove (lpBuff1, lpBuff+ wSplit, wEnd - wSplit); // Get ptrs to blk data lpSegListNew = pfd->bd[sNewBuff].lpSegListPtr; lpSegList = pfd->bd[sBuff].lpSegListPtr; // Adjust size of blks lpSegListNew->wSize = wEnd - wSplit; lpSegList->wSize -= wEnd - wSplit; // Update blk flags to indicate both in buffs not ebox lpSegList->fFlags &= ~FLAG_STATEMASK; lpSegList->fFlags |= STAT_SEGINBUFF | FLAG_DIRTY; lpSegListNew->fFlags &= ~FLAG_STATEMASK; lpSegListNew->fFlags |= STAT_SEGINBUFF | FLAG_DIRTY; // Make no buff active pfd->sActBuff = -1; // If removing data from before cursor, xchg blk order if (sSide < 0) { wCaret -= STDREADLEN; sBuff = sNewBuff; } // Reload proper blk into ebox pfd->bd[sBuff].sLRU = 1; rc = BufftoEBox (pfd, sBuff, wCaret, hWndEdit); } } } } return rc; } //------------------------------------------------------------ // ScrollProc - Handles edit box scrolling //------------------------------------------------------------ INT ScrollProc (PFILEDATA pfd, HWND hWndEdit, INT sScroll) { UINT wBlkEnd, wBlkStart, wCaret, wSplit, wEnd, wLLine; LPSEGLIST lpSegList, lpSegListNew; INT i, sTop, sBuff, sDelBuff = -2, rc = 0; LPSTR lpBuff; BOOL fDirty; DWORD dwData; HCURSOR hCursor; lpSegList = pfd->bd[pfd->sActBuff].lpSegListPtr; if (lpSegList == 0) return 0; dwData = SendMessage (hWndEdit, EM_GETSEL, 0, 0); wEnd = GetWindowTextLength (hWndEdit); sTop = (INT) SendMessage (hWndEdit, EM_GETFIRSTVISIBLELINE, 0, 0); wLLine = (INT) SendMessage (hWndEdit, EM_LINEFROMCHAR, wEnd, 0); // Check for scrolling outside current edit box text. if (sScroll >= 0) { // Check for scroll past end of file if (((UINT)(sTop + 1 + sScroll + pfd->sEBoxLines) < wLLine) || (lpSegList->fFlags & FLAG_LASTSEG)) return 0; wBlkStart = LOWORD (dwData); wBlkEnd = HIWORD (dwData); wCaret = wBlkEnd; // Split data at top of screen. wSplit = (UINT) SendMessage (hWndEdit, EM_LINEINDEX, max (sTop - 1,0), 0); // Protect wSplit from illegal line val if (wSplit == 0xffff) wSplit = wEnd; if (wBlkStart < wSplit) wSplit = wBlkStart; // Compute ptr to new segment lpSegListNew = lpSegList + 1; // Check for too large mark if ((wEnd - wSplit) + lpSegListNew->wSize >= 0xc000) { MessageBeep(0); return ERR_TOOBIGMARK; } } else { // Check for scroll before top of file if ((sTop - 1 + sScroll > 0) || (lpSegList == pfd->lpbl)) return 0; wBlkStart = HIWORD (dwData); wBlkEnd = LOWORD (dwData); wCaret = wBlkEnd; // Split data at bottom of screen. wSplit = (UINT) SendMessage (hWndEdit, EM_LINEINDEX, sTop + pfd->sEBoxLines + 1, 0); // Protect wSplit from illegal line val if (wSplit == 0xffff) wSplit = wEnd; if (wBlkStart > wSplit) wSplit = wBlkStart; // Compute ptr to new segment lpSegListNew = lpSegList - 1; // Check for too large mark if (wSplit + lpSegListNew->wSize >= 0xc000) { MessageBeep(0); return ERR_TOOBIGMARK; } } fScrolling = TRUE; // See if old edit box data has changed. fDirty = (BOOL) SendMessage (hWndEdit, EM_GETMODIFY, 0, 0); // If the size of the segment being split from the edit box // is less than the minimum, combine it with the next segment // and delete the entry from the list. Don't do this if only // one entry in list. if (!(pfd->lpbl->fFlags & FLAG_LASTSEG)) { if ((sScroll >= 0) && (wSplit < MINBLKSIZE)) { wSplit = 0; sDelBuff = pfd->sActBuff; lpSegListNew->fFlags |= FLAG_DIRTY; } else if ((sScroll < 0) && (lpSegList->wSize - wSplit < MINBLKSIZE)) { wSplit = wEnd; sDelBuff = pfd->sActBuff; lpSegListNew->fFlags |= FLAG_DIRTY; } } // Get old segment data lpBuff = GlobalLock (pfd->bd[pfd->sActBuff].hBuff); GetWindowText (hWndEdit, lpBuff, 0xFFFF); // Get new segment data sBuff = GetSegment (&FileData, lpSegListNew, &rc); if (rc) { PrintError (GetParent (hWndEdit), rc); return 0; } hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)); fPaint = FALSE; if (sScroll >= 0) { // Scroll down // Adjust size of old segment lpSegList->wSize = wSplit; // Adjust location ptr if still using the org file as source if (!(lpSegListNew->fFlags & FLAG_EVERDIRTY)) lpSegListNew->lLoc -= (wEnd - wSplit); // Select text up to split and delete SendMessage (hWndEdit, EM_SETSEL, 1, MAKELPARAM (0, wSplit)); SendMessage (hWndEdit, EM_REPLACESEL, 0, (LPARAM)(LPSTR)""); wEnd = GetWindowTextLength (hWndEdit); // Adjust selection marks wCaret -= wSplit; wBlkStart -= wSplit; wBlkEnd -= wSplit; } else { // Scroll up // Move start of blk over the data left in ebox _fmemmove (lpBuff, lpBuff+wSplit, wEnd-wSplit); // Adjust size of old segment lpSegList->wSize = wEnd-wSplit; // Adjust location ptr if still using the org file as source if (!(lpSegList->fFlags & FLAG_EVERDIRTY)) lpSegList->lLoc += wSplit; // Select text beyond split and delete SendMessage (hWndEdit, EM_SETSEL, 1, MAKELPARAM (wSplit, wEnd)); SendMessage (hWndEdit, EM_REPLACESEL, 0, (LPARAM)(LPSTR)""); wEnd = 0; // Adjust selection marks wCaret += lpSegListNew->wSize; wBlkStart += lpSegListNew->wSize; wBlkEnd += lpSegListNew->wSize; } // Set terminating zero for old segment *(lpBuff+lpSegList->wSize) = '\0'; // Move ebox insert pointer SendMessage (hWndEdit, EM_SETSEL, 1, MAKELPARAM (wEnd, wEnd)); // Insert text from new segment lpBuff = GlobalLock (pfd->bd[sBuff].hBuff); *(lpBuff+lpSegListNew->wSize) = '\0'; SendMessage (hWndEdit, EM_REPLACESEL, 0, (LPARAM)lpBuff); // Unlock segments GlobalUnlock (pfd->bd[pfd->sActBuff].hBuff); GlobalUnlock (pfd->bd[sBuff].hBuff); // If scrolling back, scroll past new lines of text if (sScroll < 0) { wLLine = (INT) SendMessage (hWndEdit, EM_LINEFROMCHAR, lpSegListNew->wSize, 0); SendMessage (hWndEdit, EM_LINESCROLL, 0, MAKELPARAM (wLLine, 0)); } SetCursor (hCursor); // Set selection SendMessage (hWndEdit, EM_SETSEL, 0, MAKELPARAM (wCaret, wCaret)); SendMessage (hWndEdit, EM_SETSEL, 1, MAKELPARAM (wBlkStart, wBlkEnd)); fPaint = TRUE; InvalidateRect (hWndEdit, NULL, FALSE); // Set active buffer and revise LRU values. pfd->sActBuff = sBuff; for (i = 0; i < NUMBUFFS; i++) if ((pfd->bd[i].sLRU > pfd->bd[sBuff].sLRU) && (pfd->bd[i].sLRU)) pfd->bd[i].sLRU--; pfd->bd[sBuff].sLRU = NUMBUFFS; // Update buffer flags lpSegList->fFlags &= ~FLAG_STATEMASK; lpSegList->fFlags |= STAT_SEGINBUFF; if (fDirty) { pfd->fFlags |= FLAG_DIRTY; lpSegList->fFlags |= FLAG_DIRTY; // If old dirty, dirty part may have been within split text lpSegListNew->fFlags |= FLAG_DIRTY; } lpSegListNew->fFlags &= ~FLAG_STATEMASK; lpSegListNew->fFlags |= STAT_SEGINEDIT; lpSegListNew->wSize = GetWindowTextLength (hWndEdit); // Clear ebox dirty flag SendMessage (hWndEdit, EM_SETMODIFY, FALSE, 0); // If a segment was deleted, remove segment entry from list if (sDelBuff != -2) DeleteEntry (pfd, sDelBuff); fScrolling = FALSE; return 0; } //------------------------------------------------------------ // GetSegList - Returns a pointer to the entry in the segment // list containing the data. //------------------------------------------------------------ LPSEGLIST GetSegListEntry (PFILEDATA pfd, LONG lFilePtr, UINT *wOffset) { INT i; LPSEGLIST lpSegList; // Look in buffer list for data location lpSegList = pfd->lpbl; for (i = 1; i < SEGLISTSIZE; i++) { if (((LONG)lpSegList->wSize > lFilePtr) || (lpSegList->fFlags & FLAG_LASTSEG)) break; lFilePtr -= (LONG)lpSegList->wSize; lpSegList++; } if (lFilePtr > (LONG)lpSegList->wSize) { *wOffset = lpSegList->wSize; if (*wOffset) (*wOffset)--; } else *wOffset = (UINT)lFilePtr; return lpSegList; } //------------------------------------------------------------ // BufftoEBox - Moves data from a buffer to the edit box. //------------------------------------------------------------ INT BufftoEBox (PFILEDATA pfd, INT sNewBuff, UINT wOffset, HWND hWndEBox) { INT i, sLen; UINT wLIndex; DWORD dwCur; LPBYTE lpbBuff; LPSEGLIST lpSegList, lpSegListOld; if (sNewBuff != pfd->sActBuff) { // If current buffer, get and save data if (pfd->sActBuff != -1) { lpSegListOld = pfd->bd[pfd->sActBuff].lpSegListPtr; lpSegListOld->fFlags &= ~FLAG_STATEMASK; lpSegListOld->fFlags |= STAT_SEGINBUFF; lpbBuff = GlobalLock (pfd->bd[pfd->sActBuff].hBuff); lpSegListOld->wSize = GetWindowTextLength (hWndEBox); GetWindowText (hWndEBox, lpbBuff, 0xffff); GlobalUnlock (pfd->bd[pfd->sActBuff].hBuff); // If dirty, set the proper flags if (SendMessage (hWndEBox, EM_GETMODIFY, 0, 0)) { lpSegListOld->fFlags |= FLAG_DIRTY; pfd->fFlags |= FLAG_DIRTY; } } lpSegList = pfd->bd[sNewBuff].lpSegListPtr; // Set the ebox text lpbBuff = GlobalLock (pfd->bd[sNewBuff].hBuff); *(lpbBuff+lpSegList->wSize) = '\0'; SetWindowText (hWndEBox, lpbBuff); GlobalUnlock (pfd->bd[sNewBuff].hBuff); // Set status flags lpSegList->fFlags &= ~FLAG_STATEMASK; lpSegList->fFlags |= STAT_SEGINEDIT; // Set active buffer and revise LRU values. pfd->sActBuff = sNewBuff; for (i = 0; i < NUMBUFFS; i++) if ((pfd->bd[i].sLRU > pfd->bd[sNewBuff].sLRU) && (pfd->bd[i].sLRU)) pfd->bd[i].sLRU--; pfd->bd[sNewBuff].sLRU = NUMBUFFS; } // Set cursor position within edit box. if (GetKeyState (VK_SHIFT) & 0x8000) { dwCur = SendMessage (hWndEBox, EM_GETSEL, 0, 0); SendMessage (hWndEBox, EM_SETSEL, 0, MAKELONG (LOWORD (dwCur), wOffset)); } else SendMessage (hWndEBox, EM_SETSEL, 0, MAKELONG (wOffset, wOffset)); // Make sure cursur does not split a CR/LF combo dwCur = SendMessage (hWndEBox, EM_GETSEL, 0, 0); wLIndex = (UINT)SendMessage (hWndEBox, EM_LINEINDEX, -1, 0); sLen = (INT)SendMessage (hWndEBox, EM_LINELENGTH, HIWORD (dwCur), 0); // If cursor pos past end of line, must be between CR & LF if ((INT)HIWORD (dwCur) - wLIndex > sLen) if (GetKeyState (VK_SHIFT) & 0x8000) SendMessage (hWndEBox, EM_SETSEL, 1, MAKELONG (LOWORD (dwCur), HIWORD (dwCur)+1)); else SendMessage (hWndEBox, EM_SETSEL, 1, MAKELONG (LOWORD (dwCur)+1, HIWORD (dwCur)+1)); return 0; } //------------------------------------------------------------ // GetFreeBuffer - Frees a buffer by saving or discarding // data in Least Recently used buffer. //------------------------------------------------------------ INT GetFreeBuffer (PFILEDATA pfd, INT *rc) { INT sBuff; UINT wBytes; LPBYTE lpbBuff; LPSEGLIST lpSegListOld; // Find Least recently used buffer. for (sBuff = 0; sBuff < NUMBUFFS; sBuff++) if (pfd->bd[sBuff].sLRU < 2) break; if (sBuff == NUMBUFFS) { // OutputDebugString ("Cannot find LRU buffer\n"); MessageBeep(0); if (pfd->sActBuff) sBuff = 0; else sBuff = 1; } rc = 0; //If buffer contains data, save to swap file lpSegListOld = pfd->bd[sBuff].lpSegListPtr; if (lpSegListOld) { lpSegListOld->fFlags &= ~FLAG_STATEMASK; lpSegListOld->fFlags |= FLAG_BUFFNUMMASK; if (lpSegListOld->fFlags & FLAG_DIRTY) { // Seek to the end of the swap file. lpSegListOld->lLoc = FileOps (&pfd->hTempFile, FOP_SEEK, 0, 2, rc); lpbBuff = GlobalLock (pfd->bd[sBuff].hBuff); wBytes = (UINT) FileOps (&pfd->hTempFile, FOP_WRITE, (LONG)lpbBuff, lpSegListOld->wSize, rc); GlobalUnlock (pfd->bd[sBuff].hBuff); // Need disk full check here. if ((*rc == 0) && (wBytes != lpSegListOld->wSize)) *rc = ERR_TEMPDIRFULL; if (*rc) { // OutputDebugString ("Swap file write error. Disk full\n"); MessageBeep(0); MessageBox (hMain, "The temporary directory is full. Please"\ " save your file to continue editing.", szTitleText, MB_OK | MB_ICONSTOP); PrintError (hMain, *rc); } else lpSegListOld->fFlags |= STAT_SEGINSWAP | FLAG_EVERDIRTY; } else { if (lpSegListOld->fFlags & FLAG_EVERDIRTY) { lpSegListOld->fFlags |= STAT_SEGINSWAP; } else { lpSegListOld->fFlags |= STAT_SEGINFILE; } } } return sBuff; } //------------------------------------------------------------ // GetSegment - Loads the specified file segment into a RAM // buffer. //------------------------------------------------------------ INT GetSegment (PFILEDATA pfd, LPSEGLIST lpSegList, INT *rc) { INT sBuff; HFILE hFile; LPBYTE lpbBuff; *rc = 0; // If in editbox, return active buffer switch (lpSegList->fFlags & FLAG_STATEMASK) { case STAT_SEGINEDIT: lpbBuff = GlobalLock (pfd->bd[pfd->sActBuff].hBuff); lpSegList->wSize = GetWindowTextLength (GetDlgItem (hMain, IDD_EBOX)); GetWindowText (GetDlgItem (hMain, IDD_EBOX), lpbBuff, (UINT)(BUFFSIZE-1)); GlobalUnlock (pfd->bd[pfd->sActBuff].hBuff); return pfd->sActBuff; // If in a buffer, return buffer number case STAT_SEGINBUFF: sBuff = lpSegList->fFlags & FLAG_BUFFNUMMASK; if (sBuff >= NUMBUFFS) *rc = -1000; return lpSegList->fFlags & FLAG_BUFFNUMMASK; case STAT_SEGINSWAP: // Free a buffer to use. sBuff = GetFreeBuffer (pfd, rc); if (*rc) return pfd->sActBuff; hFile = pfd->hTempFile; break; case STAT_SEGINFILE: // Free a buffer to use. sBuff = GetFreeBuffer (pfd, rc); if (*rc) return pfd->sActBuff; hFile = pfd->hSrcFile; break; } pfd->bd[sBuff].lpSegListPtr = lpSegList; // Read file data into buffer lpbBuff = GlobalLock (pfd->bd[sBuff].hBuff); if (hFile) { FileOps (&hFile, FOP_SEEK, lpSegList->lLoc, 0, rc); lpSegList->wSize = (UINT)FileOps (&hFile, FOP_READ, (LONG)lpbBuff, lpSegList->wSize, rc); } else lpSegList->wSize = 0; //Terminate data with zero *(lpbBuff + lpSegList->wSize) = '\0'; GlobalUnlock (pfd->bd[sBuff].hBuff); // Set segment list flags lpSegList->fFlags &= ~FLAG_BUFFNUMMASK; lpSegList->fFlags |= (FLAG_BUFFNUMMASK & sBuff); lpSegList->fFlags &= ~FLAG_STATEMASK; lpSegList->fFlags |= STAT_SEGINBUFF; lpSegList->fFlags &= ~FLAG_DIRTY; return sBuff; } //------------------------------------------------------------ // GetFileData - Loads the specified file data into the edit // window. //------------------------------------------------------------ INT GetFileData (PFILEDATA pfd, LONG lFilePtr, HWND hWndEBox) { INT sBuff, rc; UINT wOffset; LPSEGLIST lpSegList; // Look in buffer list for data location lpSegList = GetSegListEntry (pfd, lFilePtr, &wOffset); if (GetKeyState (VK_SHIFT) & 0x8000) { if (lpSegList != pfd->bd[pfd->sActBuff].lpSegListPtr) return ERR_TOOBIGMARK; } sBuff = GetSegment (pfd, lpSegList, &rc); if (rc == 0) rc = BufftoEBox (pfd, sBuff, wOffset, hWndEBox); // Set the scroll bar position SetEBoxScroll (pfd, GetParent (hWndEBox)); return rc; } //------------------------------------------------------------ // GotoLine - Sets cursor at the line and column specified. //------------------------------------------------------------ INT GotoLine (PFILEDATA pfd, HWND hWndEBox, LONG lLine, INT sCol) { INT i, rc = 0, sBuff; char ch; LPSEGLIST lpSegList; LPBYTE lpbBuff; LONG lFilePtr; // Scroll to starting line and column lFilePtr = 0; lpSegList = pfd->lpbl; do { // Load data into Ebox to have box compute number of lines. // Necessary because wordwrap will change the number of lines // depending on the size of the edit box. sBuff = GetSegment (pfd, lpSegList, &rc); if (rc) return rc; rc = BufftoEBox (pfd, sBuff, 0, hWndEBox); i = (INT) SendMessage (hWndEBox, EM_GETLINECOUNT, 0, 0); if (lLine < (LONG)i) break; // Keep track of the number of bytes processed lFilePtr += lpSegList->wSize; if (lpSegList->fFlags & FLAG_LASTSEG) { lLine = (LONG)i; break; } lLine -= (i - 1); // See if the block ends with a line number lpbBuff = GlobalLock (pfd->bd[sBuff].hBuff); ch = *(lpbBuff + lpSegList->wSize); GlobalUnlock (pfd->bd[sBuff].hBuff); if ((ch == 0x0a) || (ch == 0x0d)) lLine--; lpSegList++; } while (TRUE); i = (INT)SendMessage (hWndEBox, EM_LINEINDEX, (INT)lLine - 1, 0); lFilePtr += i + sCol; GetFileData (pfd, lFilePtr, hWndEBox); return 0; } //------------------------------------------------------------ // InitFile - Initializes buffers and reads in first part of // a file. //------------------------------------------------------------ INT InitFile (LPSTR szFileName, PFILEDATA pfd, HWND hWnd, LONG lLine, INT sCol) { INT i, rc = 0, sSegs = 0; LPSEGLIST lpSegList; LONG lTemp; HWND hWndEBox; hWndEBox = GetDlgItem (hWnd, IDD_EBOX); // Init structure if (szFileName) { FileOps (&pfd->hSrcFile, FOP_FIND, (LONG)(LPSTR)szFileName, (LONG)(LPSTR)&pfd->szFileName, &rc); if (rc) return rc; FileOps (&pfd->hSrcFile, FOP_OPEN, (LONG)(LPVOID)pfd->szFileName, OF_READ | OF_SHARE_DENY_WRITE, &rc); if (rc) pfd->hSrcFile = 0; } else pfd->szFileName[0] = '\0'; // Compute size of file if (pfd->hSrcFile) { pfd->lFileSize = FileOps (&pfd->hSrcFile, FOP_SEEK, 0, 2, &rc); FileOps (&pfd->hSrcFile, FOP_SEEK, 0, 0, &rc); } else pfd->lFileSize = 0; // Init buffer list lpSegList = pfd->lpbl; lTemp = pfd->lFileSize; for (i = 0; i < SEGLISTSIZE; i++) { if (lTemp) { lpSegList->lLoc = (LONG) i * STDREADLEN; sSegs++; } else lpSegList->lLoc = 0; lpSegList->fFlags = STAT_SEGINFILE; if (lTemp > STDREADLEN) lpSegList->wSize = STDREADLEN; else { lpSegList->wSize = (UINT) lTemp; lpSegList->fFlags |= FLAG_LASTSEG; } if (lTemp) lTemp -= lpSegList->wSize; lpSegList++; } pfd->sActBuff = -1; // Allocate RAM buffers for (i = 0; i < NUMBUFFS;i++) { FileData.bd[i].sLRU = 0; FileData.bd[i].lpSegListPtr = 0; } if (pfd->hSrcFile == 0) { FileData.sActBuff = 0; FileData.lpbl->lLoc = 0; FileData.lpbl->wSize = 0; FileData.lpbl->fFlags = FLAG_LASTSEG | STAT_SEGINEDIT; FileData.bd[0].sLRU = NUMBUFFS; FileData.bd[0].lpSegListPtr = FileData.lpbl; } // Compute multiply factor to extend scroll bar range to cover // file size. if (pfd->lFileSize < 32767) pfd->wScrollMax = 1; else pfd->wScrollMax = (UINT)((pfd->lFileSize / 32767) + 1); SetScrollRange (GetDlgItem (hWnd, IDD_VSB), SB_CTL, 0, (INT)(pfd->lFileSize / pfd->wScrollMax), TRUE); GotoLine (pfd, hWndEBox, lLine, sCol); return rc; } //------------------------------------------------------------ // WriteToFile - Writes the data to a file //------------------------------------------------------------ INT WriteToFile (HWND hWnd, PFILEDATA pfd, char *pszOutName) { INT rc = 0, sBuff; LPSEGLIST lpSegList; HFILE hOutFile; LPBYTE lpbBuff; UINT wWritten; LONG lData; SetStatusBarText (hWnd, "Saving file...", 0); FileOps (&hOutFile, FOP_OPEN, (LONG)(LPVOID)pszOutName, OF_READWRITE | OF_CREATE, &rc); if (rc) return rc; // Write file to disk lpSegList = pfd->lpbl; while (TRUE) { sBuff = GetSegment (pfd, lpSegList, &rc); if (rc == 0) { lpbBuff = GlobalLock (pfd->bd[sBuff].hBuff); wWritten = (UINT)FileOps (&hOutFile, FOP_WRITE, (LONG)lpbBuff, lpSegList->wSize, &rc); GlobalUnlock (pfd->bd[sBuff].hBuff); } if (wWritten != lpSegList->wSize) { MessageBeep(0); MessageBox (hMain, "Unable to save file to disk", szTitleText, MB_OK); FileOps (&hOutFile, FOP_CLOSE, 0, 0, &rc); remove (pszOutName); return ERR_NODISKSPACE; } if (lpSegList->fFlags & FLAG_LASTSEG) break; lpSegList++; } // Close edited file FileOps (&hOutFile, FOP_CLOSE, 0, 0, &rc); if (rc == 0) { // Clear dirty flags lpSegList = pfd->lpbl; lData = 0; while (TRUE) { lpSegList->lLoc = lData; lpSegList->fFlags &= ~(FLAG_EVERDIRTY | FLAG_DIRTY); if ((lpSegList->fFlags & FLAG_STATEMASK) == STAT_SEGINSWAP) { lpSegList->fFlags &= ~FLAG_STATEMASK; lpSegList->fFlags |= STAT_SEGINFILE; } if (lpSegList->fFlags & FLAG_LASTSEG) break; lData += lpSegList->wSize; lpSegList++; } pfd->fFlags &= ~FLAG_DIRTY; SendDlgItemMessage (hMain, IDD_EBOX, EM_SETMODIFY, 0, 0); if (rc == 0) { // Close, delete and reopen swap file FileOps (&pfd->hTempFile, FOP_CLOSE, 0, 0, &rc); remove (pfd->szSwapName); FileOps (&pfd->hTempFile, FOP_OPEN, (LONG)(LPVOID)pfd->szSwapName, OF_READWRITE | OF_CREATE | OF_SHARE_EXCLUSIVE, &rc); FileOps (&pfd->hTempFile, FOP_CLOSE, 0, 0, &rc); FileOps (&pfd->hTempFile, FOP_OPEN, (LONG)(LPVOID)pfd->szSwapName, OF_READWRITE | OF_SHARE_EXCLUSIVE, &rc); } SetStatusBarText (hWnd, "Save Complete.", 0); } return rc; } //------------------------------------------------------------ // SaveFile - Saves the file being edited //------------------------------------------------------------ INT SaveFile (HWND hWnd, PFILEDATA pfd) { static char *szFilter[] = {"All Files (*.*)", "*.*", "" }; char szTmpOutFile[144]; INT i, rc = 0; if (lstrlen (FileData.szFileName) == 0) { if (MyGetSavename (hWnd, FileData.szFileName, sizeof (FileData.szFileName), *szFilter, 1) == 0) return ERR_CANCELED; pfd->hSrcFile = 0; } // Make sure we have write access to the file if (pfd->hSrcFile) { FileOps (&pfd->hSrcFile, FOP_CLOSE, 0, 0, &rc); if (rc) return rc; FileOps (&pfd->hSrcFile, FOP_OPEN, (LONG)(LPVOID)pfd->szFileName, OF_READWRITE | OF_SHARE_EXCLUSIVE, &rc); } else { FileOps (&pfd->hSrcFile, FOP_OPEN, (LONG)(LPVOID)pfd->szFileName, OF_CREATE | OF_READWRITE | OF_SHARE_EXCLUSIVE, &rc); } if (rc) return rc; // Copy original filename and append a differnt extension lstrcpy (szTmpOutFile, pfd->szFileName); for (i = lstrlen (szTmpOutFile); i && szTmpOutFile[i] != '.' && szTmpOutFile[i] != '\\'; --i); if (szTmpOutFile[i] != '\\') lstrcpy (&szTmpOutFile[i], ".O~~"); else lstrcat (szTmpOutFile, ".O~~"); // Write to new file rc = WriteToFile (hWnd, pfd, szTmpOutFile); if (rc) return rc; // Remove original file FileOps (&pfd->hSrcFile, FOP_CLOSE, 0, 0, &rc); remove (pfd->szFileName); // Rename new file to original file name rc = rename (szTmpOutFile, pfd->szFileName); if (rc == 0) { // Del temp outfile remove (szTmpOutFile); // Reopen source file. FileOps (&pfd->hSrcFile, FOP_OPEN, (LONG)(LPVOID)pfd->szFileName, OF_READ | OF_SHARE_DENY_WRITE, &rc); } else rc = ERR_LOSTSOURCEFILE; return rc; } //------------------------------------------------------------ // TermFile - Terminates file editing //------------------------------------------------------------ INT TermFile (HWND hWnd, PFILEDATA pfd) { INT rc = 0; // If dirty query user for save. if ((pfd->fFlags & FLAG_DIRTY) || SendDlgItemMessage (hWnd, IDD_EBOX, EM_GETMODIFY, 0, 0)) { rc = MessageBox (hWnd, "The current file has been changed.\n"\ "Would you like to save the changes?", szTitleText, MB_YESNOCANCEL | MB_ICONEXCLAMATION); if (rc == IDCANCEL) return ERR_CANCELED; if (rc == IDYES) { rc = SaveFile (hWnd, pfd); } else rc = 0; } // Close source file if ((pfd->hSrcFile) && !rc) { FileOps (&pfd->hSrcFile, FOP_CLOSE, 0, 0, &rc); pfd->hSrcFile = 0; } // Close temp file if ((pfd->hTempFile) && !rc) { FileOps (&pfd->hTempFile, FOP_CLOSE, 0, 0, &rc); remove (pfd->szSwapName); pfd->hTempFile = 0; } return rc; } //------------------------------------------------------------ // CnvCmd2Num - converts a command parameter to a number //------------------------------------------------------------ LONG CnvCmd2Num (LPSTR *plpszCmd, LONG lMax, INT *rc) { LONG i = 0; LPSTR lpCmdLine; lpCmdLine = *plpszCmd; *rc = 0; // Remove any leading spaces while (*lpCmdLine && (*lpCmdLine <= ' ')) lpCmdLine++; // Convert to decimal number i = 0; while ((*rc == 0) && (*lpCmdLine > ' ')) { if ((*lpCmdLine >= '0') && (*lpCmdLine <= '9')) { i *= 10; i += *lpCmdLine++ - '0'; } else *rc = ERR_SYNTAX; if (i > lMax) *rc = ERR_NUMTOOBIG; } *plpszCmd = lpCmdLine; return i; } //------------------------------------------------------------ // ParseCmdline - Parses the command line. // SuperPad [file name] [/Ln] [/Cn] [/R+|-] [V] [/F] [/P] [/Tn] [/W+|-] //------------------------------------------------------------ INT ParseCmdLine (PFILEDATA pfd, LPSTR lpCmdLine) { INT i, rc = 0; BOOL fName = FALSE; while ((rc == 0) && (*lpCmdLine)) { if (*lpCmdLine == '/') { fStatFlags |= SFLAG_SWITCHSTART; lpCmdLine++; switch ((char)(LONG)AnsiUpper ((LPSTR)MAKELONG (*lpCmdLine++, 0))) { case 'C': i = (INT) CnvCmd2Num (&lpCmdLine, 1023, &rc); if (rc == 0) sStartCol = i; break; case 'F': pfd->fFlags |= FFLAG_FIXEDFONT; pfd->fFlags &= ~FFLAG_PORPFONT; break; case 'L': lStartLine = CnvCmd2Num (&lpCmdLine, 1000000, &rc); if (rc) lStartLine = 0; break; case 'P': pfd->fFlags |= FFLAG_PORPFONT; pfd->fFlags &= ~FFLAG_FIXEDFONT; break; case 'R': if (*lpCmdLine == '+') { pfd->fFlags |= FFLAG_RONLY; lpCmdLine++; } else if ((*lpCmdLine == '-') && !(pfd->fFlags & FFLAG_VIEWONLY)) { pfd->fFlags &= ~FFLAG_RONLY; lpCmdLine++; } else pfd->fFlags |= FFLAG_RONLY; break; case 'T': i = (INT) CnvCmd2Num (&lpCmdLine, 64, &rc); if (i == 0) i = 1; if (rc == 0) pfd->sTabs = i; break; case 'V': pfd->fFlags |= FFLAG_VIEWONLY; pfd->fFlags |= FFLAG_RONLY; break; case 'W': if (*lpCmdLine == '+') { pfd->fFlags |= FFLAG_WWRAP; lpCmdLine++; } else if (*lpCmdLine == '-') { pfd->fFlags &= ~FFLAG_WWRAP; lpCmdLine++; } else pfd->fFlags |= FFLAG_WWRAP; break; case 'X': i = (INT) CnvCmd2Num (&lpCmdLine, GetSystemMetrics (SM_CXSCREEN)-20, &rc); if (rc == 0) sStartX = i; break; case 'Y': i = (INT) CnvCmd2Num (&lpCmdLine, GetSystemMetrics (SM_CYSCREEN)-20, &rc); if (rc == 0) sStartY = i; break; default: rc = ERR_SYNTAX; break; } } else if (*lpCmdLine > ' ') { if (!fName) { i = 0; while (*lpCmdLine > ' ') szCmd[i++] = *lpCmdLine++; szCmd[i] = '\0'; fName = TRUE; } else rc = ERR_SYNTAX; } else lpCmdLine++; } return rc; } //============================================================ // General Helper Routines //============================================================ //------------------------------------------------------------ // MyDisplayDialog - Display a dialog box //------------------------------------------------------------ INT MyDisplayDialog (HINSTANCE hInstance, LPCSTR szDlgName, HWND hWnd, WNDPROC lpDialogProc, LPARAM lParam) { WNDPROC lpDlgProcInst; INT rc; lpDlgProcInst = MakeProcInstance(lpDialogProc, hInst); rc = DialogBoxParam (hInstance, szDlgName, hWnd, lpDlgProcInst, lParam); FreeProcInstance(lpDlgProcInst); return rc; } //------------------------------------------------------------ // MyWritePrivateProfileInt - Writes an integer to the profile //------------------------------------------------------------ BOOL MyWritePrivateProfileInt (char *szSec, char *szEntry, int Num, char *szProfile) { char szStr[33]; wsprintf (szStr, "%d", Num); return WritePrivateProfileString (szSec, szEntry, szStr, szProfile); } //------------------------------------------------------------ // MySubClassWindow - Subclasses a window //------------------------------------------------------------ WNDPROC MySubClassWindow (HWND hWnd, WNDPROC lpfnNewProc) { WNDPROC lpfnOldProc; lpfnOldProc = (WNDPROC) GetWindowLong (hWnd, GWL_WNDPROC); SetWindowLong (hWnd, GWL_WNDPROC, (LONG) lpfnNewProc); return lpfnOldProc; } //------------------------------------------------------------ // MyYield - Yields control to other programs, but returns // if Windows is idle. //------------------------------------------------------------ BOOL MyYield (void) { MSG msg; BOOL bCont; bCont = TRUE; while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) bCont = FALSE; TranslateMessage(&msg); DispatchMessage(&msg); } return bCont; } //------------------------------------------------------------ // MyGetFilename - Uses the common File Open dialog box to // query the user for a filename //------------------------------------------------------------ BOOL MyGetFilename (HWND hWnd, char *szFilename, INT sMaxLen, DWORD fFlags, char *szFilter, INT sFilterIndex) { OPENFILENAME ofn; INT rc; memset (&ofn, 0, sizeof (ofn)); *szFilename = '\0'; ofn.lStructSize = sizeof (ofn); ofn.hwndOwner = hWnd; ofn.hInstance = hInst; ofn.lpstrFilter = szFilter; ofn.nFilterIndex = sFilterIndex; ofn.lpstrFile = szFilename; ofn.nMaxFile = sMaxLen; ofn.Flags = fFlags; rc = 0; if (GetOpenFileName (&ofn)) rc++; if (ofn.Flags & OFN_READONLY) rc++; return rc; } //------------------------------------------------------------ // MyGetSavename - Uses the common Save dialog box to // query the user for a filename //------------------------------------------------------------ BOOL MyGetSavename (HWND hWnd, char *szFilename, INT sMaxLen, char *szFilter, INT sFilterIndex) { OPENFILENAME ofn; memset (&ofn, 0, sizeof (ofn)); ofn.lStructSize = sizeof (ofn); ofn.hwndOwner = hWnd; ofn.hInstance = hInst; ofn.lpstrFilter = szFilter; ofn.nFilterIndex = sFilterIndex; ofn.lpstrFile = szFilename; ofn.nMaxFile = sMaxLen; ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; return (GetSaveFileName (&ofn)); } //------------------------------------------------------------ // MyDispFindtext - Uses the common Find dialog box to // query the user for search text //------------------------------------------------------------ HWND MyDispFindtextBox (HWND hWnd, char far *lpszFindText, INT sMaxLen, DWORD fFlags) { static FINDREPLACE fr; HWND hWndDlg; DWORD dw; memset (&fr, 0, sizeof (fr)); fr.lStructSize = sizeof (fr); fr.hwndOwner = hWnd; fr.hInstance = hInst; fr.Flags = fFlags; fr.lpstrFindWhat = lpszFindText; fr.wFindWhatLen = sMaxLen; hWndDlg = FindText (&fr); dw = CommDlgExtendedError(); return hWndDlg; } //------------------------------------------------------------ // MyDispReptext - Uses the common Find dialog box to // find and replace text. //------------------------------------------------------------ HWND MyDispReptextBox (HWND hWnd, char far *lpszFindText, INT sMaxFind, char far *lpszRepText, INT sMaxRep, DWORD fFlags) { static FINDREPLACE fr; memset (&fr, 0, sizeof (fr)); fr.lStructSize = sizeof (fr); fr.hwndOwner = hWnd; fr.hInstance = hInst; fr.Flags = fFlags; fr.lpstrFindWhat = lpszFindText; fr.lpstrReplaceWith = lpszRepText; fr.wFindWhatLen = sMaxFind; fr.wReplaceWithLen = sMaxRep; return (ReplaceText (&fr)); } //------------------------------------------------------------ // MyGetFont - Uses the common Choose Font dialog box to // query the user for a font. //------------------------------------------------------------ BOOL MyGetFont (HWND hWnd, LPLOGFONT lpFont, INT *sSize, COLORREF *rgbColor, DWORD dwFlags) { CHOOSEFONT cf; BOOL rc; memset (&cf, 0, sizeof (CHOOSEFONT)); cf.lStructSize = sizeof (CHOOSEFONT); cf.hwndOwner = hWnd; cf.hDC = 0; cf.lpLogFont = lpFont; cf.iPointSize = *sSize; cf.Flags = dwFlags | CF_SCREENFONTS; cf.rgbColors = *rgbColor; cf.lCustData = 0; cf.lpfnHook = 0; cf.lpTemplateName = 0; cf.hInstance = hInst; cf.lpszStyle = 0; cf.nFontType = SCREEN_FONTTYPE; cf.nSizeMin = 0; cf.nSizeMax = 0; rc = ChooseFont (&cf); if (rc) { *rgbColor = cf.rgbColors; *sSize = cf.iPointSize; } return rc; } //------------------------------------------------------------ // FileOps - All File operations // lParam1 lParam2 // OPEN Ptr to filename File access flags // READ Ptr to buffer Number of bytes to read // WRITE Ptr to buffer Number of bytes to write // SEEK Offset in file Base of offset // CLOSE Not used Not used // FIND Ptr to filename Buffer for qualified filename //------------------------------------------------------------ LONG FileOps (HFILE *hFile, INT sOp, LONG lParam1, LONG lParam2, INT *rc) { OFSTRUCT ofFile; LONG lReturn; *rc = 0; lReturn = 0; switch (sOp) { case FOP_OPEN: *hFile = OpenFile ((LPSTR) lParam1, &ofFile, (UINT)lParam2); if (*hFile == HFILE_ERROR) *rc = ERR_FOPEN_ERR - ofFile.nErrCode; break; case FOP_READ: lReturn = _hread (*hFile, (LPBYTE)lParam1, lParam2); if ((INT)lReturn == HFILE_ERROR) { *rc = ERR_FILEREAD; lReturn = 0; } break; case FOP_WRITE: lReturn = _lwrite (*hFile, (LPBYTE)lParam1, (UINT)lParam2); if ((INT)lReturn == HFILE_ERROR) { *rc = ERR_FILEWRITE; lReturn = 0; } break; case FOP_SEEK: lReturn = _llseek (*hFile, lParam1, (WORD)lParam2); if ((INT)lReturn == HFILE_ERROR) { *rc = ERR_FILESEEK; lReturn = 0; } break; case FOP_CLOSE: _lclose (*hFile); break; case FOP_FIND: *hFile = OpenFile ((LPSTR) lParam1, &ofFile, OF_EXIST); if (*hFile == HFILE_ERROR) *rc = ERR_FOPEN_ERR - ofFile.nErrCode; else lstrcpy ((LPSTR)lParam2, ofFile.szPathName); break; } return lReturn; } //------------------------------------------------------------ // GetErrorString - Returns an error string //------------------------------------------------------------ BOOL GetErrorString (INT sErrorCode, char *pszOut, INT sMax) { lstrcpy (pszOut, "Error - "); sErrorCode = abs (sErrorCode); if (LoadString (hInst, sErrorCode, pszOut + lstrlen(pszOut), sMax - lstrlen (pszOut)) == 0) wsprintf (pszOut, "Error number: %d", sErrorCode); return TRUE; } //------------------------------------------------------------ // PrintError - Displays a message box with an error code //------------------------------------------------------------ void PrintError (HWND hWnd, INT rc) { char szErrStr[80]; GetErrorString (rc, szErrStr, sizeof (szErrStr)); SetStatusBarText (hWnd, szErrStr, 0); return; }