📄 gvwgs.c
字号:
/* Copyright (C) 1996-2001, Ghostgum Software Pty Ltd. All rights reserved.
This file is part of GSview.
This program is distributed with NO WARRANTY OF ANY KIND. No author
or distributor accepts any responsibility for the consequences of using it,
or for whether it serves any particular purpose or works at all, unless he
or she says so in writing. Refer to the GSview Free Public Licence
(the "Licence") for full details.
Every copy of GSview must include a copy of the Licence, normally in a
plain ASCII text file named LICENCE. The Licence grants you the right
to copy, modify and redistribute GSview, but only under certain conditions
described in the Licence. Among other things, the Licence requires that
the copyright notice and this notice be preserved on all copies.
*/
/* gvwgs.c */
/* Ghostscript DLL interface for GSview */
#include "gvwgs.h"
#include "cdll.h"
#ifdef _MSC_VER
#define _export
#endif
HINSTANCE phInstance;
POINT char_size;
LPSTR szAppName = "GSview Print";
HWND hwnd_client, hwnd_text;
int status_height;
#define WINDOWWIDTH (80*char_size.x)
#define WINDOWHEIGHT (24*char_size.y)
HFONT hfont;
#define TWLENGTH 16384
#define TWSCROLL 1024
char twbuf[TWLENGTH];
int twend;
int multithread = FALSE;
BOOL quitnow = FALSE;
char gsarg[2048];
unsigned long gstid;
GSDLL gsdll;
/* command line options */
int debug = 0; /* don't shut down or delete files if debugging */
char *gsdllname;
char *option;
char *filename;
FILE *infile;
unsigned long lsize, ldone;
int pcdone;
char title[64];
/* forward declarations */
void show_about(void);
int init_window(void);
void gs_addmess(const char *str);
int get_args(LPSTR lpszCmdLine, int *pargc, char **pargv[]);
int parse_args(int argc, char *argv[]);
void text_update(void);
LRESULT CALLBACK _export ClientWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int message_box(char *str, int icon);
void saveas(void);
void gs_thread(void *arg);
#define GetNotification(wParam,lParam) (HIWORD(wParam))
#define SendDlgNotification(hwnd, id, notice) \
SendMessage((hwnd), WM_COMMAND, MAKELONG((id),(notice)), (LPARAM)GetDlgItem((hwnd),(id)))
int PASCAL
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)
{
int i, argc;
char **argv;
MSG msg;
phInstance = hInstance;
if (init_window())
return 1;
ShowWindow(hwnd_client, cmdShow);
get_args(lpszCmdLine, &argc, &argv);
if (parse_args(argc, argv)) {
if (multithread)
gstid = _beginthread(gs_thread, 131072, NULL);
else
{
/* process messages for window creation */
while ((PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE)) != 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
gs_thread(0); /* this will call PeekMessage */
}
}
while (!quitnow && GetMessage(&msg, (HWND)NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (!debug) {
if (option)
unlink(option);
if (filename)
unlink(filename);
}
for (i=0; i<argc; i++)
free(argv[i]);
free(argv);
DestroyWindow(hwnd_client);
return 0;
}
int
init_window(void)
{
WNDCLASS wndclass;
HDC hdc;
TEXTMETRIC tm;
LOGFONT lf;
HMENU hmenu;
RECT rect;
/* figure out which version of Windows */
DWORD version = GetVersion();
/* Win32s: bit 15 HIWORD is 1 and bit 14 is 0 */
/* Win95: bit 15 HIWORD is 1 and bit 14 is 1 */
/* WinNT: bit 15 HIWORD is 0 and bit 14 is 0 */
/* WinNT with Win95 shell recognised by WinNT + LOBYTE(LOWORD) >= 4 */
/* check if Windows NT */
if ((HIWORD(version) & 0x8000)==0)
multithread = TRUE;
/* check if Windows 95 (Windows 4.0) */
if ( ((HIWORD(version) & 0x8000)!=0) && ((HIWORD(version) & 0x4000)!=0) )
multithread = TRUE;
/* Win32s */
if ( ((HIWORD(version) & 0x8000)!=0) && ((HIWORD(version) & 0x4000)==0) )
multithread = FALSE;
/* register the window class */
wndclass.style = 0;
wndclass.lpfnWndProc = ClientWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = phInstance;
wndclass.hIcon = LoadIcon(phInstance, MAKEINTRESOURCE(ID_GSVIEW));
wndclass.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
wndclass.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
RegisterClass(&wndclass);
hdc = GetDC(NULL); /* desktop */
memset(&lf, 0, sizeof(lf));
lf.lfHeight = 8;
strcpy(lf.lfFaceName, "Helv");
hfont = CreateFontIndirect(&lf);
SelectObject(hdc, hfont);
GetTextMetrics(hdc, (LPTEXTMETRIC)&tm);
ReleaseDC(NULL, hdc);
char_size.x = tm.tmAveCharWidth;
char_size.y = tm.tmHeight;
status_height = 0 /* 6*char_size.y/4 */;
hwnd_client = CreateWindow(szAppName, (LPSTR)szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
WINDOWWIDTH, WINDOWHEIGHT,
NULL, NULL, phInstance, (void FAR *)NULL);
hmenu = LoadMenu(phInstance, MAKEINTRESOURCE(ID_GSVIEW));
SetMenu(hwnd_client, hmenu);
GetClientRect(hwnd_client, &rect);
hwnd_text = CreateWindow("EDIT", "",
WS_CHILD | /* WS_VISIBLE | */ ES_MULTILINE | ES_READONLY | WS_BORDER | WS_VSCROLL | WS_HSCROLL | DS_3DLOOK,
rect.left, rect.top,
rect.right-rect.left, rect.bottom-rect.left-status_height,
hwnd_client, (HMENU)TEXTWIN_MLE, phInstance, NULL);
SendMessage(hwnd_text, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
ShowWindow(hwnd_text, SW_SHOWNA);
return 0;
}
/* Window Procedure */
LRESULT CALLBACK _export
ClientWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message) {
/* case WM_CLOSE: */
case WM_DESTROY:
PostQuitMessage(0);
quitnow = TRUE;
break;
case WM_SIZE:
if ( (wParam == SIZE_RESTORED) || (wParam == SIZE_MAXIMIZED) ) {
SetWindowPos(hwnd_text, HWND_TOP, 0, 0,
LOWORD(lParam), HIWORD(lParam)-status_height,
SWP_SHOWWINDOW);
}
case WM_TEXTUPDATE:
text_update();
break;
case WM_PCUPDATE:
sprintf(title, "%d%% - %s",
(int)(wParam) > 100 ? 100 : (int)(wParam) , szAppName);
SetWindowText(hwnd, title);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_EXIT:
PostQuitMessage(0);
return 0;
case IDM_SAVEAS:
saveas();
return 0;
case IDM_COPYCLIP:
{HGLOBAL hglobal;
LPSTR p;
DWORD start, end;
SendMessage(hwnd_text, EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
if (start == end) {
start = 0;
end = twend;
}
hglobal = GlobalAlloc(GHND | GMEM_SHARE, end-start+1);
if (hglobal == (HGLOBAL)NULL) {
MessageBeep(-1);
return(FALSE);
}
p = (LPSTR)GlobalLock(hglobal);
if (p == (LPSTR)NULL) {
MessageBeep(-1);
return(FALSE);
}
strncpy(p, twbuf+start, end-start);
GlobalUnlock(hglobal);
OpenClipboard(hwnd_client);
EmptyClipboard();
SetClipboardData(CF_TEXT, hglobal);
CloseClipboard();
}
return 0;
case IDM_ABOUT:
show_about();
return 0;
}
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
/* Text Window for Ghostscript Messages */
/* uses MS-Windows multiline edit field */
void
text_update(void)
{
DWORD linecount;
SendMessage(hwnd_text, WM_SETREDRAW, FALSE, 0);
SetWindowText(hwnd_text, twbuf);
/* EM_SETSEL, followed by EM_SCROLLCARET doesn't work */
linecount = SendMessage(hwnd_text, EM_GETLINECOUNT, (WPARAM)0, (LPARAM)0);
SendMessage(hwnd_text, EM_LINESCROLL, (WPARAM)0, (LPARAM)linecount-17);
SendMessage(hwnd_text, WM_SETREDRAW, TRUE, 0);
InvalidateRect(hwnd_text, (LPRECT)NULL, TRUE);
UpdateWindow(hwnd_text);
}
/* Add string for Ghostscript message window */
void
gs_addmess_count(const char *str, int count)
{
const char *s;
char *p;
int i, lfcount;
/* we need to add \r after each \n, so count the \n's */
lfcount = 0;
s = str;
for (i=0; i<count; i++) {
if (*s == '\n')
lfcount++;
s++;
}
if (count + lfcount >= TWSCROLL)
return; /* too large */
if (count + lfcount + twend >= TWLENGTH-1) {
/* scroll buffer */
twend -= TWSCROLL;
memmove(twbuf, twbuf+TWSCROLL, twend);
}
p = twbuf+twend;
for (i=0; i<count; i++) {
if (*str == '\n') {
*p++ = '\r';
}
*p++ = *str++;
}
twend += (count + lfcount);
*(twbuf+twend) = '\0';
/* tell main thread to update the MLE */
PostMessage(hwnd_client, WM_TEXTUPDATE, 0, 0);
}
void
gs_addmess(const char *str)
{
gs_addmess_count(str, lstrlen(str));
}
void
gs_addmessf(const char *fmt, ...)
{
va_list args;
int count;
char buf[1024];
va_start(args,fmt);
count = vsprintf(buf,fmt,args);
gs_addmess(buf);
va_end(args);
}
#define MAX_ARGC 10
/* Scan command line and produce argc and argv. */
/* Quotes must be used around arguments which have embedded spaces. */
/* We use this because the inbuilt Borland scanner gives incorrect */
/* results for quoted arguments with embedded spaces. */
int
get_args(LPSTR lpszCmdLine, int *pargc, char **pargv[])
{
int argc = 0;
char **argv;
char *start, *end;
int inquote;
int length;
argv = (char **)malloc( (MAX_ARGC+1) * sizeof(char *) );
if (argv == (char **)NULL)
return 0;
memset(argv, 0, (MAX_ARGC+1) * sizeof(char *));
argv[argc] = (char *)malloc(MAXSTR+1);
if (argv[argc] == NULL) {
free(argv);
return 0;
}
GetModuleFileName(phInstance, argv[argc], MAXSTR);
argc++;
start = lpszCmdLine;
/* skip leading spaces */
while (*start && (*start == ' '))
start++;
end = start;
while (*end) {
/* found new argument */
inquote = FALSE;
if (*end == '\042') {
/* skip leading quote */
start++;
end++;
inquote = TRUE;
}
while (*end) {
if (!inquote && (*end==' ')) {
break;
}
else if (inquote && (*end=='\042')) {
break;
}
else
end++;
}
length = (int)(end-start);
argv[argc] = (char *)malloc(length+1);
if (argv[argc] == NULL) {
free(argv);
return 0;
}
strncpy(argv[argc], start, length);
argv[argc][length] = '\0';
if (*end)
end++; /* skip trailing quote or space */
start = end;
/* skip leading spaces */
while (*start && (*start == ' '))
start++;
end = start;
argc++;
if (argc == MAX_ARGC)
break;
}
*pargc = argc;
*pargv = argv;
return argc;
}
/* Parse command line arguments */
/* Return 0 if error */
int
parse_args(int argc, char *argv[])
{
char buf[MAXSTR];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -