📄 gvxprn.c
字号:
* on gs_print_stdin_pipe.
*/
void print_write_fn(gpointer data, gint fd, GdkInputCondition condition)
{
if (fd != gs_print_pipe_stdin[1]) {
gs_addmess("print_write_fn: called with wrong source\n");
return;
}
if (gs_print_file <=0) {
gs_addmess("print_write_fn: gs_print_file is closed\n");
return;
}
if (gs_print_pipe_stdin[1] == -1) {
gs_addmess("print_write_fn: gs_print_pipe_stdin[1] is closed\n");
return;
}
if (condition == GDK_INPUT_EXCEPTION) {
/* complain */
gs_addmess("print_write_fn: exception\n");
close(gs_print_pipe_stdin[1]);
gs_print_pipe_stdin[1] = -1;
return;
}
else if (condition == GDK_INPUT_WRITE) {
int pcdone;
int bytes_written = 0;
do {
if (gs_print_buffer_count == 0) {
gs_print_buffer_count = read(gs_print_file,
gs_print_buffer, gs_print_buffer_length);
}
if (gs_print_buffer_count == 0) {
print_stop_stdin();
close(gs_print_file);
gs_print_file = -1;
if (gs_print_pipe_stdin[1] != -1) {
close(gs_print_pipe_stdin[1]);
gs_print_pipe_stdin[1] = -1;
}
break;
}
bytes_written = write(gs_print_pipe_stdin[1],
gs_print_buffer+gs_print_buffer_index, gs_print_buffer_count);
if (bytes_written == -1) {
break; /* come back later */
}
else if (bytes_written == 0) {
/* pipe probably closed */
gs_addmess("print_write_fn: wrote 0 bytes to GS\n");
print_check_zombie();
}
else {
gs_print_buffer_count -= bytes_written;
if (gs_print_buffer_count == 0)
gs_print_buffer_index = 0;
else
gs_print_buffer_index += bytes_written;
gs_print_bytes_done += bytes_written;
pcdone = (int)(gs_print_bytes_done * 100 / gs_print_bytes_size);
if (pcdone != gs_print_percent) {
gs_print_percent = pcdone;
percent_print_message(gs_print_percent);
}
}
} while (bytes_written > 0);
}
else {
gs_addmessf("print_write_fn: unknown condition %d\n", condition);
}
}
/* Asynchronous read of GS print stdout/stderr.
* This is called from event loop when a read is possible
* on gs_print_stdout_pipe or gs_print_stderr_pipe.
*/
void print_read_stdout_fn(gpointer data, gint fd, GdkInputCondition condition)
{
int is_stdout = (fd == gs_print_pipe_stdout[0]);
int is_stderr = (fd == gs_print_pipe_stderr[0]);
if (!is_stdout && !is_stderr) {
gs_addmess("print_read_stdout_fn: called with wrong source\n");
return;
}
if (condition == GDK_INPUT_EXCEPTION) {
/* complain */
gs_addmess("print_read_stdout_fn: exception\n");
if (is_stdout)
print_stop_stdout();
else
print_stop_stderr();
return;
}
else if (condition == GDK_INPUT_READ) {
char buf[256];
int bytes_read = 0;
do {
bytes_read = read(fd, buf, sizeof(buf));
if (bytes_read == -1) {
if (errno == EAGAIN) {
break; /* come back later */
}
else {
gs_addmessf("print_read_stdout_fn: read from GS failed, errno=%d\n", errno);
}
}
else if (bytes_read == 0) {
gs_addmessf("print_read_stdout_fn: read 0 bytes from GS %s\n",
is_stdout ? "stdout" : "stderr");
print_check_zombie();
}
else {
add_print_message(buf, bytes_read);
}
} while (bytes_read > 0);
}
else {
gs_addmessf("print_read_stdout_fn: unknown condition %d\n", condition);
}
}
void print_stop_stdin(void)
{
if (gs_print_pipe_stdin_tag >=0) {
gdk_input_remove(gs_print_pipe_stdin_tag);
gs_print_pipe_stdin_tag = -1;
if (debug & DEBUG_GENERAL)
gs_addmess("print_stop_stdin:\n");
}
}
void print_start_stdin(void)
{
if (gs_print_pipe_stdin_tag >=0)
return;
gs_print_pipe_stdin_tag = gdk_input_add(gs_print_pipe_stdin[1],
(GdkInputCondition)(GDK_INPUT_WRITE | GDK_INPUT_EXCEPTION),
print_write_fn, 0);
if (debug & DEBUG_GENERAL)
gs_addmess("print_start_stdin:\n");
}
void print_stop_stdout(void)
{
if (gs_print_pipe_stdout_tag >=0) {
gdk_input_remove(gs_print_pipe_stdout_tag);
gs_print_pipe_stdout_tag = -1;
if (debug & DEBUG_GENERAL)
gs_addmess("print_stop_stdout:\n");
}
}
void print_start_stdout(void)
{
if (gs_print_pipe_stdout_tag >=0)
return;
gs_print_pipe_stdout_tag = gdk_input_add(gs_print_pipe_stdout[0],
(GdkInputCondition)(GDK_INPUT_READ | GDK_INPUT_EXCEPTION),
print_read_stdout_fn, 0);
if (debug & DEBUG_GENERAL)
gs_addmess("print_start_stdout:\n");
}
void print_stop_stderr(void)
{
if (gs_print_pipe_stderr_tag >=0) {
gdk_input_remove(gs_print_pipe_stderr_tag);
gs_print_pipe_stderr_tag = -1;
if (debug & DEBUG_GENERAL)
gs_addmess("print_stop_stderr:\n");
}
}
void print_start_stderr(void)
{
if (gs_print_pipe_stderr_tag >=0)
return;
gs_print_pipe_stderr_tag = gdk_input_add(gs_print_pipe_stderr[0],
(GdkInputCondition)(GDK_INPUT_READ | GDK_INPUT_EXCEPTION),
print_read_stdout_fn, 0);
if (debug & DEBUG_GENERAL)
gs_addmess("print_start_stderr:\n");
}
/* print will fork another process to run Ghostscript.
* stdin will be obtained from main process
* stdout/err will be written to a window owned by the main process.
*/
void print_start_gs(void)
{
char *nargv[10];
char dash_string[] = "-";
char dashc_string[] = "-c";
char quit_string[] = "quit";
gs_print_file = open(printer.psname, O_RDONLY);
if (gs_print_file == -1) {
print_stop_gs();
return;
}
gs_print_bytes_size = lseek(gs_print_file, 0, SEEK_END);
lseek(gs_print_file, 0, SEEK_SET);
gs_print_bytes_done = 0;
gs_print_percent = 0;
gs_print_buffer_count = 0;
gs_print_buffer_index = 0;
gs_print_buffer_length = 4096;
gs_print_buffer = (char *)malloc(gs_print_buffer_length);
if (gs_print_buffer == NULL) {
print_stop_gs();
return;
}
/* redirect stdio of Ghostscript */
if (pipe(gs_print_pipe_stdin)) {
gs_addmessf("Could not open pipe for stdin, errno=%d\n", errno);
print_stop_gs();
return;
}
if (pipe(gs_print_pipe_stdout)) {
gs_addmessf("Could not open pipe for stdout, errno=%d\n", errno);
print_stop_gs();
return;
}
if (pipe(gs_print_pipe_stderr)) {
gs_addmessf("Could not open pipe for stderr, errno=%d\n", errno);
print_stop_gs();
return;
}
show_print_message();
printer.pid = fork();
if (printer.pid == 0) {
char atopt[MAXSTR];
strcpy(atopt, "@");
strcat(atopt, printer.optname);
/* child */
close(gs_print_pipe_stdin[1]); /* close write handle */
dup2(gs_print_pipe_stdin[0], 0);/* duplicate and make it stdin */
close(gs_print_pipe_stdin[0]); /* close original read handle */
close(gs_print_pipe_stdout[0]);
dup2(gs_print_pipe_stdout[1], 1);/* duplicate and make it stdout */
close(gs_print_pipe_stdout[1]);
close(gs_print_pipe_stderr[0]);
dup2(gs_print_pipe_stderr[1], 2);/* duplicate and make it stderr */
close(gs_print_pipe_stderr[1]);
/* replace with Ghostscript */
/* start Ghostscript */
{
char buf[MAXSTR];
FILE *f = fopen(printer.optname, "r");
while (fgets(buf, sizeof(buf), f))
fprintf(stdout, "option: %s", buf);
fclose(f);
}
nargv[0] = option.gsexe;
nargv[1] = atopt;
nargv[2] = dash_string; /* read stdin */
nargv[3] = dashc_string;
nargv[4] = quit_string;
nargv[5] = NULL;
if (debug & DEBUG_GENERAL)
fprintf(stdout, "child: starting gs for printing\n");
if (execvp(nargv[0], nargv) == -1) {
int j;
int err = errno;
/* write to stdout, which will be captured by GSview */
fprintf(stdout, "Failed to start Ghostscript process\n");
for (j=0; nargv[j]; j++)
fprintf(stdout, " %s", nargv[j]);
fputc('\n', stdout);
fprintf(stdout, " errno=%d\n", err);
fflush(stdout);
/* If we used exit(), it would call the atexit function
* registered by gtk, and kill all the parent's windows.
* Instead we use _exit() which does not call atexit functions.
*/
_exit(1);
}
}
else {
/* parent */
int flags;
close(gs_print_pipe_stdin[0]); /* close read handle */
gs_print_pipe_stdin[0] = -1;
/* make pipe non blocking */
flags = fcntl(gs_print_pipe_stdin[1], F_GETFL, 0);
if (fcntl(gs_print_pipe_stdin[1], F_SETFL, flags | O_NONBLOCK)) {
gs_addmessf("Could not set stdin pipe to non-blocking, errno=%d\n", errno);
print_stop_gs();
return;
}
close(gs_print_pipe_stdout[1]); /* close write handle */
gs_print_pipe_stdout[1] = -1;
/* make pipe non blocking */
flags = fcntl(gs_print_pipe_stdout[0], F_GETFL, 0);
if (fcntl(gs_print_pipe_stdout[0], F_SETFL, flags | O_NONBLOCK)) {
gs_addmessf("Could not set stdout pipe to non-blocking, errno=%d\n", errno);
print_stop_gs();
return;
}
print_start_stdout();
close(gs_print_pipe_stderr[1]); /* close write handle */
gs_print_pipe_stdout[1] = -1;
/* make pipe non blocking */
flags = fcntl(gs_print_pipe_stderr[0], F_GETFL, 0);
if (fcntl(gs_print_pipe_stderr[0], F_SETFL, flags | O_NONBLOCK)) {
gs_addmessf("Could not set stderr pipe to non-blocking, errno=%d\n", errno);
print_stop_gs();
return;
}
print_start_stderr();
/* Trigger async write */
print_start_stdin();
if (debug & DEBUG_GENERAL)
gs_addmess("print_start_gs: parent\n");
}
}
/* print a range of pages using a Ghostscript device */
void
gsview_print(BOOL convert)
{
if (psfile.name[0] == '\0') {
gserror(IDS_NOTOPEN, NULL, MB_ICONEXCLAMATION, SOUND_NOTOPEN);
return;
}
if (option.print_method == PRINT_GDI)
option.print_method = PRINT_GS;
nHelpTopic = convert ? IDS_TOPICCONVERT : IDS_TOPICPRINT;
if (print_dialog_box(convert) != IDOK)
return;
if (!convert)
option.print_reverse = psfile.page_list.reverse;
if (!gsview_cprint(printer.psname, printer.optname, convert)) {
gs_addmess("gsview_print: gsview_cprint failed\n");
return;
}
if (debug & DEBUG_GENERAL)
gs_addmessf("gsview_print: optname=%s psname=%s\n", printer.optname, printer.psname);
/* start GS print */
print_start_gs();
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -