// wsmooth.c RHS 9/1/90 #include"windows.h" #include"wsmooth.h" #include"wsmooth2.h" #include #include #include #include #include #include #include"filebuf.h" #define textrowsperpage() ((PixRowsPerPage/CharLineHeight)+3) #define SB_PIXLINEUP (SB_LINEUP+0x0100) #define SB_PIXLINEDOWN (SB_LINEDOWN+0x0100) long numlines; HWND WinSmooth = 0; char filename[128]; char classname[11] = "WinSmooth"; char windowname[128] = "WinSmooth"; BOOL direction = DOWN; HANDLE hOrgBrush; HCURSOR hNormalCursor, hHourGlassCursor; BOOL sb_init = FALSE; SETTINGS settings = { DEFAULTMSECS, DEFAULTPIXELROWS, DEFAULTBACK, DEFAULTFORE, FALSE }; HANDLE hinstance; void ResetPixRows(void); void ResetBackGround(HDC hDC); void RetrieveSettings(void); void PaintMainWindow(HWND hwnd); // beginning of WinSmooth int PASCAL WinMain(HANDLE hInstance,HANDLE hPrevInstance, LPSTR lpszCmdLine, int cmdShow) { MSG msg; RetrieveSettings(); // retrieve settings from WIN.INI lstrcpy((LPSTR)filename,lpszCmdLine); process_cmdline(filename); // get (and override with) command-line settings hOrgBrush = CreateSolidBrush(settings.back); if(!hPrevInstance) { WNDCLASS cl; cl.lpszClassName = (LPSTR) classname; cl.hInstance = hInstance; cl.lpfnWndProc = MainWindowProc; cl.hCursor = LoadCursor(NULL, IDC_ARROW); cl.hIcon = LoadIcon(hInstance,(LPSTR)"WSMOOTH"); cl.lpszMenuName = (LPSTR)"FILEMENU"; cl.hbrBackground = hOrgBrush; cl.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; cl.cbClsExtra = 0; cl.cbWndExtra = 0; if(!RegisterClass(&cl)) return FALSE; hNormalCursor = cl.hCursor; } hHourGlassCursor = LoadCursor(NULL, IDC_WAIT); WinSmooth = CreateWindow((LPSTR)classname, (LPSTR)windowname, WS_OVERLAPPEDWINDOW | WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, (LPSTR)NULL); if(!WinSmooth) return FALSE; ShowWindow(WinSmooth, cmdShow); UpdateWindow(WinSmooth); hinstance = hInstance; ChangeTitleBar(filename); // in case it wasn't done when file was opened while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } exit(msg.wParam); } // WinSmooth termination and cleanup BOOL FAR PASCAL CloseApplication(void) { filebuf_destruct(); return TRUE; } struct _keytable { WORD virkey; int msg; WORD sbcode; } keyscroll[] = { VK_PRIOR, WM_VSCROLL, SB_PAGEUP, VK_NEXT, WM_VSCROLL, SB_PAGEDOWN, VK_HOME, WM_VSCROLL, SB_TOP, VK_END, WM_VSCROLL, SB_BOTTOM, VK_UP, WM_VSCROLL, SB_LINEUP, VK_DOWN, WM_VSCROLL, SB_LINEDOWN }; #define MAXKEYS (sizeof(keyscroll) / sizeof(keyscroll[0])) #define MYTIMER 1 #define RBUTTONDCLICK 2 // main window procedure for WinSmooth long FAR PASCAL MainWindowProc(HWND hwnd, unsigned message, WORD wParam, LONG lParam) { static BOOL paused = TRUE, rbdclk = FALSE, app_activated = TRUE; static BOOL restart = TRUE; FARPROC lpProcAbout, lpOpenDialog, lpSettingsDialog; switch(message) { //////////// Windows Messages case WM_CREATE: { if(!WSopenfile(filename)) PostMessage(hwnd,WM_COMMAND,IDM_OPEN,0L); else PostMessage(hwnd,WM_WSM_STARTTIMER,0,0L); } break; case WM_PAINT: PaintMainWindow(hwnd); break; case WM_TIMER: // timer message switch(wParam) { case MYTIMER: if(settings.PixelRows > 0) PostMessage(hwnd,WM_VSCROLL, (direction == DOWN) ? SB_PIXLINEDOWN : SB_PIXLINEUP,0L); break; case RBUTTONDCLICK: KillTimer(hwnd,RBUTTONDCLICK); if(!rbdclk) PostMessage(hwnd,WM_RBUTTONDOWN,MY_RBUTTON,0L); else rbdclk = FALSE; break; } break; case WM_VSCROLL: // vertical scrollbar message ProcessVscroll(hwnd, wParam, lParam); break; case WM_CLOSE: // close application DestroyWindow(hwnd); break; case WM_DESTROY: // destroy application CloseApplication(); KillTimer(hwnd,MYTIMER); DeleteObject(hOrgBrush); PostQuitMessage(0); break; case WM_INITMENU: // stop timer when User uses menu restart = (paused ? FALSE : TRUE); SendMessage(hwnd,WM_WSM_STOPTIMER,0,0L); break; case WM_ACTIVATE: // if activation message sent if(wParam == 0) app_activated = FALSE; break; case WM_COMMAND: // menu messages { switch(wParam) { case IDM_OPEN: // open a new file { int newfile,fileisopen = filebuf_fileisopen(); lpOpenDialog = MakeProcInstance(OpenDlg, hinstance); // Open the file and get its handle newfile = DialogBox(hinstance, "OPEN", hwnd, lpOpenDialog); FreeProcInstance(lpOpenDialog); if(newfile) { sb_init = FALSE; SendMessage(hwnd,WM_VSCROLL,SB_TOP,0L); InvalidateRect(hwnd, NULL, TRUE); SendMessage(hwnd,WM_PAINT,0,0L); } else if(!fileisopen) { int i; if((i = MessageBox(hwnd,"Terminate WinSmooth?","WinSmooth", MB_OKCANCEL | MB_ICONQUESTION)) == IDOK) PostMessage(hwnd,WM_CLOSE,0,0L); else PostMessage(hwnd,WM_COMMAND,IDM_OPEN,0L); } } break; case IDM_ABOUT: // display About box lpProcAbout = MakeProcInstance(About, hinstance); DialogBox(hinstance, "ABOUTBOX", hwnd, lpProcAbout); FreeProcInstance(lpProcAbout); break; case IDM_SETTINGS: lpSettingsDialog = MakeProcInstance(Settings, hinstance); DialogBox(hinstance, "SETTINGS", hwnd, lpSettingsDialog); FreeProcInstance(lpSettingsDialog); break; case IDM_EXIT: // terminate program PostMessage(hwnd,WM_CLOSE,0,0L); break; default: break; } if(restart) SendMessage(hwnd,WM_WSM_STARTTIMER,0,0L); } break; //////////////////// Mouse Message Handling case WM_LBUTTONDOWN: // left mouse button == SPACE if(app_activated) PostMessage(hwnd,WM_CHAR,SPACE,0L); app_activated = TRUE; break; case WM_RBUTTONDOWN: // right mouse button == '-' if(wParam == MY_RBUTTON) PostMessage(hwnd,WM_CHAR,'-',0L); else { rbdclk = FALSE; SetTimer(hwnd,RBUTTONDCLICK,GetDoubleClickTime(),NULL); } break; case WM_RBUTTONDBLCLK: // right button Double click == '+' rbdclk = TRUE; PostMessage(hwnd,WM_WSM_INCPIXROWS,0,0L); break; //////////////////// Keyboard Message handling case WM_KEYDOWN: { int i; PostMessage(hwnd,WM_WSM_STARTTIMER,0,0L); for(i = 0; i < MAXKEYS; i++) if(wParam == keyscroll[i].virkey) { SendMessage(hwnd,keyscroll[i].msg,keyscroll[i].sbcode,0L); break; } } break; case WM_CHAR: PostMessage(hwnd,WM_WSM_STARTTIMER,0,0L); switch(wParam) { case ESC: // quit the application PostMessage(hwnd,WM_CLOSE,0,0L); break; case SPACE: // stop the timer if(!paused) PostMessage(hwnd,WM_WSM_STOPTIMER,0,0L); break; case '+': // increase # of rows scrolled PostMessage(hwnd,WM_WSM_INCPIXROWS,0,0L); break; case '-': // decrease # of rows scrolled PostMessage(hwnd,WM_WSM_DECPIXROWS,0,0L); break; default: // if 0-9, set # of rows scrolled if(wParam >= '0' && wParam <= '9') settings.PixelRows = (wParam-'0'); break; } break; //////////////////// Application Messages case WM_WSM_STARTTIMER: if(paused && settings.PixelRows > MINPIXELROWS) SetTimer(hwnd,MYTIMER,settings.Msecs,NULL); paused = FALSE; break; case WM_WSM_STOPTIMER: if(!paused) KillTimer(hwnd,MYTIMER); paused = TRUE; break; case WM_WSM_DECPIXROWS: if(settings.PixelRows > MINPIXELROWS) settings.PixelRows--; break; case WM_WSM_INCPIXROWS: if(settings.PixelRows < MAXPIXELROWS) settings.PixelRows++; break; case WM_WSM_HOURGLASS_CURSOR: SetCursor(hHourGlassCursor); break; case WM_WSM_NORMAL_CURSOR: SetCursor(hNormalCursor); break; case WM_SIZE: ResetPixRows(); // fall thru in case icon'd default: return (DefWindowProc(hwnd, message, wParam, lParam)); break; } return (0L); } long NewPixTopRow = 0L, CurPixTopRow = 0L, BottPixRow = 0L; unsigned PixRowsPerPage = 0, CharLineHeight = 0, TextRowsPerPage; // vertical scroll processing for WinSmooth void ProcessVscroll(HWND hwnd, WORD wParam, LONG lParam) { BOOL bscroll = FALSE; switch(wParam) { case SB_PIXLINEUP: // move up a pixel row NewPixTopRow = CurPixTopRow - settings.PixelRows; direction = UP; break; case SB_PIXLINEDOWN: // move down a pixel row NewPixTopRow = CurPixTopRow + settings.PixelRows; direction = DOWN; break; case SB_LINEUP: // move up a character row NewPixTopRow = CurPixTopRow - CharLineHeight; direction = UP; break; case SB_LINEDOWN: // move down a character row NewPixTopRow = CurPixTopRow + CharLineHeight; direction = DOWN; break; case SB_PAGEUP: // move up a 'page' of rows NewPixTopRow = CurPixTopRow - (PixRowsPerPage - 1); break; case SB_PAGEDOWN: // move down a 'page' of rows NewPixTopRow = CurPixTopRow + PixRowsPerPage - 1; break; case SB_TOP: // go to top row NewPixTopRow = 0L; break; case SB_BOTTOM: // go to bottom row if((NewPixTopRow = (BottPixRow-textrowsperpage())) < 0L) NewPixTopRow = 0L; break; case SB_THUMBPOSITION: // reset to new position case SB_THUMBTRACK: // reset to new position NewPixTopRow = (long)LOWORD(lParam); NewPixTopRow *= CharLineHeight; break; } switch(wParam) { case SB_PIXLINEUP: case SB_LINEUP: case SB_PIXLINEDOWN: case SB_LINEDOWN: case SB_PAGEUP: case SB_PAGEDOWN: case SB_TOP: case SB_BOTTOM: case SB_THUMBPOSITION: bscroll = TRUE; break; } NewPixTopRow = max(NewPixTopRow, 0L); NewPixTopRow = min(NewPixTopRow,BottPixRow); if(bscroll) { if((labs(NewPixTopRow - CurPixTopRow) < (long)PixRowsPerPage)) { int temp1; long temp2; temp2 = CurPixTopRow - NewPixTopRow; temp1 = (int)temp2; ScrollWindow(hwnd, 0,temp1,NULL,NULL); } else InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); } } int Y, lineno; // WinSmooth paint procedure void PaintMainWindow(HWND hwnd) { PAINTSTRUCT ps; HDC hdc; int TextTopRow, recttop, rectbott; static int X, CharHeight; int bottchar; BeginPaint(hwnd, &ps); recttop = ps.rcPaint.top; rectbott = ps.rcPaint.bottom; hdc = ps.hdc; if(!sb_init) { TEXTMETRIC tmFontInfo; numlines = (long)filebuf_numlines(); GetTextMetrics(hdc, (LPTEXTMETRIC) &tmFontInfo); CharLineHeight = tmFontInfo.tmExternalLeading + tmFontInfo.tmHeight; CharHeight = tmFontInfo.tmHeight; X = tmFontInfo.tmAveCharWidth; BottPixRow = (numlines*CharLineHeight); SetScrollRange(hwnd,SB_VERT,0,(unsigned)numlines,TRUE); ResetBackGround(hdc); ResetPixRows(); } // for writing the text... SetBkMode(hdc,TRANSPARENT); // has to be for back ground dithering SetTextColor(hdc,settings.fore); SetBkColor(hdc,settings.back); Y = (int)(NewPixTopRow%CharLineHeight)*-1; if(sb_init) Y--; else sb_init = TRUE; UnrealizeObject(hOrgBrush); SetBrushOrg(hdc,0, (Y%8) ? (Y%8)+8 : 0); SelectObject(hdc,hOrgBrush); if(Rectangle(hdc,ps.rcPaint.left,recttop,ps.rcPaint.right,ps.rcPaint.bottom)) FillRect(hdc,&ps.rcPaint,hOrgBrush); SelectObject(hdc,hOrgBrush); TextTopRow = max(0u,(unsigned)(NewPixTopRow/CharLineHeight)); for( lineno = TextTopRow; lineno < min((int)numlines, TextTopRow+TextRowsPerPage-1); lineno++) { bottchar = Y+CharHeight; if( ((rectbott-recttop+1 < (int)CharLineHeight) && ((recttop >= Y && recttop <= bottchar) || (rectbott >= Y && rectbott <= bottchar))) || (Y >= recttop && Y <= rectbott) || (bottchar >= recttop && bottchar <= rectbott)) { LPSTR p; unsigned len; filebuf_seekline(lineno); p = filebuf_nextline(&len); TextOut(hdc, X, Y, p, len); } Y += CharLineHeight; } CurPixTopRow = NewPixTopRow; SetScrollPos(hwnd,SB_VERT,(unsigned)(NewPixTopRow/CharLineHeight),TRUE); ValidateRect(hwnd, (LPRECT)NULL); EndPaint(hwnd, (LPPAINTSTRUCT) &ps); if((direction == DOWN) && (CurPixTopRow > (BottPixRow-textrowsperpage()))) direction = UP; else if(CurPixTopRow == 0L && direction == UP) direction = DOWN; } // sets up background color for main window void ResetBackGround(HDC hDC) { HANDLE hOldBrush; hOrgBrush = CreateSolidBrush(settings.back); hOldBrush = SelectObject(hDC,hOrgBrush); DeleteObject(hOldBrush); SetClassWord(WinSmooth,GCW_HBRBACKGROUND,hOrgBrush); } // sets pixel row variable based on window size void ResetPixRows(void) { RECT rect; if(WinSmooth) { GetClientRect(WinSmooth, &rect); PixRowsPerPage = rect.bottom; if(CharLineHeight) TextRowsPerPage = textrowsperpage(); } } #define INIBUFSIZE 20 // retrieves WIN.INI settings for WinSmooth void RetrieveSettings(void) { char buf[INIBUFSIZE+1],defbuf[INIBUFSIZE+1]; settings.Msecs = GetProfileInt((LPSTR)"WinSmooth",(LPSTR)"Msecs",settings.Msecs); settings.PixelRows = GetProfileInt((LPSTR)"WinSmooth",(LPSTR)"PixelRows",settings.PixelRows); sprintf(defbuf,"%lu",settings.back); GetProfileString((LPSTR)"WinSmooth",(LPSTR)"BackGround",(LPSTR)defbuf,(LPSTR)buf,INIBUFSIZE); sscanf(buf,"%lu",&settings.back); sprintf(defbuf,"%lu",settings.fore); GetProfileString((LPSTR)"WinSmooth",(LPSTR)"ForeGround",(LPSTR)defbuf,(LPSTR)buf,INIBUFSIZE); sscanf(buf,"%lu",&settings.fore); settings.stripbits = GetProfileInt((LPSTR)"WinSmooth",(LPSTR)"StripBits",settings.stripbits); } // end of wsmooth.c