📄 printing.c
字号:
/* printing.c
Dtelnet printing facility
provides XTERM/VT100 attached printer emulation
- initiated 2001-05-31 Mark Melvin
*/
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include "resource.h"
#include "dialog.h"
#include "term.h"
#include "dtelnet.h"
#include "printing.h"
#include "utils.h"
#define PRINTERNAMELEN 128
#define PRINTBUFFERSIZE 4096
/* These are the print buffering variables */
static char printingBuffer[PRINTBUFFERSIZE];
static int bufflen;
static int currline;
/* preferences */
static int marginTop = 0;
static int marginBottom = 0;
static int marginLeft = 0;
static int marginRight = 0;
static char printerName[PRINTERNAMELEN];
/* These are the dimensions of the paper */
static int numrows;
static int numcols;
static int charWidth;
static int charHeight;
static BOOL pageBreak = FALSE;
/* The controlling variable. Every entry points must be checked against this. */
static BOOL printingActive = FALSE;
/* The printer's resource */
static HDC printDC;
/* .INI file Strings */
static const char printingStr[] = "Printing";
static const char printerStr[] = "Printer";
static const char marginLeftStr[] = "Margin Left";
static const char marginTopStr[] = "Margin Top";
static const char marginRightStr[] = "Margin Rigth";
static const char marginBottomStr[] = "Margin Bottom";
/**************************** UI functions ***************************/
static HWND dlgPrinting = NULL;
static HWND dlgPreferences = NULL;
/* Dialog procedure for the print dialog
*/
BOOL CALLBACK printingDlgProc(HWND dlg,
UINT message, WPARAM wparam, LPARAM lparam)
{
switch (message) {
case WM_INITDIALOG:
dialogRegister(dlg);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wparam)) {
case IDCANCEL:
/* User pressed Cancel, abort printing */
AbortDoc(printDC);
printingActive = FALSE;
EndDialog(dlg, IDCANCEL);
break;
case IDOK:
EndDialog(dlg, IDOK);
dialogUnRegister(dlg);
}
break;
}
return FALSE;
}
void printingShowDialog(void)
{
dlgPrinting = CreateDialog(telnetGetInstance(), MAKEINTRESOURCE(IDD_PRINTING_DIALOG),
telnetGetWnd(), printingDlgProc);
}
void printingCloseDialog(void)
{
if (dlgPrinting) {
SendMessage(dlgPrinting, WM_COMMAND, IDOK, 0L);
}
}
/******************* preferences *********************/
static void prefEnumPrinters(HWND comboWnd)
{
#ifdef WIN32
PRINTER_INFO_1 *pi;
DWORD i, count, needed, flags;
flags = PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS;
EnumPrinters(flags, NULL, 1, NULL, 0, &needed, &count);
pi = (PRINTER_INFO_1*) xmalloc(needed);
EnumPrinters(flags, NULL, 1, (BYTE*) pi, needed, &needed, &count);
for ( i = 0 ; i < count ; i++ ) {
SendMessage(comboWnd, CB_ADDSTRING, 0, (LPARAM) pi[i].pName);
}
free(pi);
#else
char szPrinter[80];
GetProfileString ("windows", "device", ",,,", szPrinter, sizeof(szPrinter));
if (strtok(szPrinter, ",") != NULL) {
SendMessage(comboWnd, CB_ADDSTRING, 0, (LPARAM) szPrinter);
}
#endif
SendMessage(comboWnd, CB_SELECTSTRING, 0, (LPARAM) printerName);
}
static BOOL CALLBACK prefDlgProc(HWND dlg,
UINT message,
WPARAM wparam,
LPARAM lparam)
{
switch (message)
{
case WM_INITDIALOG:
dlgPreferences = dlg;
dialogRegister(dlg);
SetDlgItemInt(dlg, IDC_PRINTPREF_MLEFT, marginLeft, FALSE);
SetDlgItemInt(dlg, IDC_PRINTPREF_MTOP, marginTop, FALSE);
SetDlgItemInt(dlg, IDC_PRINTPREF_MRIGHT, marginRight, FALSE);
SetDlgItemInt(dlg, IDC_PRINTPREF_MBOTTOM, marginBottom, FALSE);
prefEnumPrinters(GetDlgItem(dlg, IDC_PRINTPREF_PRINTERS));
return TRUE;
case WM_COMMAND:
switch (LOWORD(wparam))
{
case IDOK:
marginLeft = GetDlgItemInt(dlg, IDC_PRINTPREF_MLEFT, NULL, FALSE);
marginTop = GetDlgItemInt(dlg, IDC_PRINTPREF_MTOP, NULL, FALSE);
marginRight = GetDlgItemInt(dlg, IDC_PRINTPREF_MRIGHT, NULL, FALSE);
marginBottom = GetDlgItemInt(dlg, IDC_PRINTPREF_MBOTTOM, NULL, FALSE);
/* if any margin is higher than MARGIN_MAX, truncate it silently
*/
#define MARGIN_MAX 1000
marginLeft = min(marginLeft, MARGIN_MAX);
marginTop = min(marginTop, MARGIN_MAX);
marginRight = min(marginRight, MARGIN_MAX);
marginBottom = min(marginBottom, MARGIN_MAX);
GetDlgItemText(dlg, IDC_PRINTPREF_PRINTERS, printerName, sizeof(printerName));
case IDCANCEL:
DestroyWindow(dlg);
dialogUnRegister(dlg);
dlgPreferences = NULL;
return TRUE;
}
break;
}
return FALSE;
}
void printingPrefDialog(void)
{
if (!dlgPreferences) {
CreateDialog(
telnetGetInstance(),
MAKEINTRESOURCE(IDD_PRINTING_PREF),
telnetGetWnd(),
prefDlgProc
);
}
}
/************************* Internal Functions ************************/
/* Starting a new page */
void printingNewPage(void)
{
currline = 0;
bufflen = 0;
StartPage(printDC);
pageBreak = FALSE;
}
/* End of page */
void printingEndPage(void)
{
EndPage(printDC);
}
/*
Starting a print job:
- get the default printer from win.ini
- init the printer DC
- calculate output sizes from the DC
*/
BOOL printingNewJob(void)
{
DOCINFO docInfo;
TEXTMETRIC tm;
#ifdef WIN32
printDC = CreateDC ("WINSPOOL", printerName, NULL, NULL);
#else
static char szPrinter[80];
char *szDevice, *szDriver, *szOutput;
GetProfileString ("windows", "device", ",,,", szPrinter, 80);
if (NULL != (szDevice = strtok(szPrinter, ",")) &&
NULL != (szDriver = strtok(NULL, ",")) &&
NULL != (szOutput = strtok(NULL, ","))) {
printDC = CreateDC (szDriver, szDevice, szOutput, NULL);
}
#endif
if (!printDC) {
MessageBox(telnetGetWnd(), "Printer not found.", telnetAppName(), MB_OK | MB_ICONSTOP);
return FALSE;
}
docInfo.cbSize = sizeof(DOCINFO);
docInfo.lpszDocName = "DTelnet Session";
docInfo.lpszOutput = NULL;
GetTextMetrics(printDC, &tm);
charWidth = tm.tmAveCharWidth;
charHeight = (tm.tmHeight+tm.tmExternalLeading);
numcols = (GetDeviceCaps(printDC, HORZRES)-(marginLeft+marginRight))
/ charWidth;
numrows = (GetDeviceCaps(printDC, VERTRES)-(marginTop+marginBottom))
/ charHeight;
printingShowDialog();
if (StartDoc(printDC, &docInfo) <= 0) {
DeleteDC(printDC);
printingCloseDialog();
MessageBox(telnetGetWnd(), "Printer is inaccesible.", telnetAppName(), MB_OK|MB_ICONSTOP);
return FALSE;
}
printingNewPage();
return TRUE;
}
/* Terminate the printing job */
void printingEndJob(void)
{
printingEndPage();
EndDoc(printDC);
DeleteDC(printDC);
printingCloseDialog();
}
/* Render a line */
void printingRenderLine(char* startpos, int linelength)
{
if (pageBreak){
printingEndPage();
printingNewPage();
}
TextOut(printDC, marginLeft, marginTop+(currline * charHeight), startpos, linelength);
currline++;
if (currline > numrows) {
pageBreak = TRUE;
}
}
/* Split buffer into lines and send to renderer */
void printingFlush(void)
{
char* start;
int length;
start = printingBuffer;
/* Split lines to fit in numcols */
while (bufflen > 0) {
length = ((bufflen <= numcols) ? bufflen : numcols);
printingRenderLine(start, length);
start += length;
bufflen -= length;
}
}
/********************* Exported Functions ***********************/
/* Inject a character into buffer */
void printingAddChar(char c)
{
switch (c) {
case '\n':
printingFlush();
break;
case '\t':
/* change tabs into spaces, 8 is hard-coded tab-size for now */
while (bufflen < numcols && !(bufflen % 8)) {
printingAddChar(' ');
}
break;
case 12:
/* do a page break */
printingFlush();
pageBreak = TRUE;
break;
default:
printingBuffer[bufflen++] = c;
/* force newline if buffer exhausted */
if (bufflen == PRINTBUFFERSIZE) printingFlush();
}
}
/* Start printing on attached printer */
void printingStart()
{
if (!printingActive)
{
printingActive = printingNewJob();
}
}
/* Stop printing */
void printingStop()
{
if (printingActive)
{
printingFlush();
printingEndJob();
printingActive = FALSE;
}
}
BOOL printingIsActive(void)
{
return printingActive;
}
void printingGetProfile(void)
{
marginLeft = GetPrivateProfileInt(
printingStr, marginLeftStr, marginLeft, telnetIniFile());
marginTop = GetPrivateProfileInt(
printingStr, marginTopStr, marginTop, telnetIniFile());
marginRight = GetPrivateProfileInt(
printingStr, marginRightStr, marginRight, telnetIniFile());
marginBottom = GetPrivateProfileInt(
printingStr, marginBottomStr, marginBottom, telnetIniFile());
GetPrivateProfileString(
printingStr, printerStr, "", printerName, sizeof(printerName), telnetIniFile());
}
void printingSaveProfile(void)
{
char str[24];
sprintf(str, "%d", marginLeft);
WritePrivateProfileString(printingStr, marginLeftStr, str, telnetIniFile());
sprintf(str, "%d", marginTop);
WritePrivateProfileString(printingStr, marginTopStr, str, telnetIniFile());
sprintf(str, "%d", marginRight);
WritePrivateProfileString(printingStr, marginRightStr, str, telnetIniFile());
sprintf(str, "%d", marginBottom);
WritePrivateProfileString(printingStr, marginBottomStr, str, telnetIniFile());
WritePrivateProfileString(printingStr, printerStr, printerName, telnetIniFile());
}
/*** functions to support Screen Dump operations ***/
void printingAddLine(Line line)
{
int nchar, cs;
nchar = 0;
cs = DTCHAR_OEM; /* OEM - but why? */
bufflen = line.len;
termGetChars (printingBuffer, line.text, bufflen, &nchar, &cs);
printingFlush();
}
void printingPrintScreen()
{
int row;
int idx=term.topVisibleLine;
if (printingActive) {
MessageBox(telnetGetWnd(), "Printer busy.", telnetAppName(), MB_OK|MB_ICONEXCLAMATION);
return;
}
if (printingNewJob())
{
// Print all visible lines of the terminal window.
for (row = 0 ; row < TERM_MAX_Y && row < term.winSize.cy &&
idx < term.numLinesUsed; row++, idx++)
{
printingAddLine(*term.lineList[idx]);
}
printingEndJob();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -