0,0 → 1,629 |
#include "fitz.h" |
#include "mupdf.h" |
#include "muxps.h" |
#include "pdfapp.h" |
|
#include <menuet/os.h> |
|
// #include <sys/select.h> |
#include <sys/time.h> |
#include <sys/types.h> |
#include <unistd.h> |
#include <signal.h> |
|
|
|
#ifndef timeradd |
#define timeradd(a, b, result) \ |
do { \ |
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ |
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ |
if ((result)->tv_usec >= 1000000) \ |
{ \ |
++(result)->tv_sec; \ |
(result)->tv_usec -= 1000000; \ |
} \ |
} while (0) |
#endif |
|
#ifndef timersub |
#define timersub(a, b, result) \ |
do { \ |
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ |
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ |
if ((result)->tv_usec < 0) { \ |
--(result)->tv_sec; \ |
(result)->tv_usec += 1000000; \ |
} \ |
} while (0) |
#endif |
|
extern int ximage_init(Display *display, int screen, Visual *visual); |
extern int ximage_get_depth(void); |
extern Visual *ximage_get_visual(void); |
extern Colormap ximage_get_colormap(void); |
extern void ximage_blit(Drawable d, GC gc, int dstx, int dsty, |
unsigned char *srcdata, |
int srcx, int srcy, int srcw, int srch, int srcstride); |
|
static Display *xdpy; |
static Atom XA_TARGETS; |
static Atom XA_TIMESTAMP; |
static Atom XA_UTF8_STRING; |
static Atom WM_DELETE_WINDOW; |
static int x11fd; |
static int xscr; |
static Window xwin; |
static Pixmap xicon, xmask; |
static GC xgc; |
static XEvent xevt; |
static int mapped = 0; |
static Cursor xcarrow, xchand, xcwait; |
static int justcopied = 0; |
static int dirty = 0; |
static int dirtysearch = 0; |
static char *password = ""; |
static XColor xbgcolor; |
static XColor xshcolor; |
static int reqw = 0; |
static int reqh = 0; |
static char copylatin1[1024 * 16] = ""; |
static char copyutf8[1024 * 48] = ""; |
static Time copytime; |
static char *filename; |
|
static pdfapp_t gapp; |
static int closing = 0; |
static int reloading = 0; |
|
/* |
* Dialog boxes |
*/ |
|
void winwarn(pdfapp_t *app, char *msg) |
{ |
fprintf(stderr, "mupdf: %s\n", msg); |
} |
|
void winerror(pdfapp_t *app, fz_error error) |
{ |
fz_catch(error, "aborting"); |
exit(1); |
} |
|
char *winpassword(pdfapp_t *app, char *filename) |
{ |
char *r = password; |
password = NULL; |
return r; |
} |
|
/* |
* X11 magic |
*/ |
|
static void winopen(void) |
{ |
|
|
/* |
xwin = XCreateWindow(xdpy, DefaultRootWindow(xdpy), |
10, 10, 200, 100, 1, |
ximage_get_depth(), |
InputOutput, |
ximage_get_visual(), |
0, |
NULL); */ |
|
__menuet__define_window(10,10,200,200, |
0,0,0); |
|
} |
|
void winclose(pdfapp_t *app) |
{ |
closing = 1; |
} |
|
void wincursor(pdfapp_t *app, int curs) |
{ |
|
} |
|
void wintitle(pdfapp_t *app, char *s) |
{ |
|
} |
|
void winhelp(pdfapp_t *app) |
{ |
|
} |
|
void winresize(pdfapp_t *app, int w, int h) |
{ |
|
|
|
|
} |
|
static void fillrect(int x, int y, int w, int h) |
{ |
if (w > 0 && h > 0) |
XFillRectangle(xdpy, xwin, xgc, x, y, w, h); |
} |
|
static void winblitsearch(pdfapp_t *app) |
{ |
if (gapp.isediting) |
{ |
char buf[sizeof(gapp.search) + 50]; |
sprintf(buf, "Search: %s", gapp.search); |
XSetForeground(xdpy, xgc, WhitePixel(xdpy, xscr)); |
fillrect(0, 0, gapp.winw, 30); |
windrawstring(&gapp, 10, 20, buf); |
} |
} |
|
static void winblit(pdfapp_t *app) |
{ |
int x0 = gapp.panx; |
int y0 = gapp.pany; |
int x1 = gapp.panx + gapp.image->w; |
int y1 = gapp.pany + gapp.image->h; |
|
XSetForeground(xdpy, xgc, xbgcolor.pixel); |
fillrect(0, 0, x0, gapp.winh); |
fillrect(x1, 0, gapp.winw - x1, gapp.winh); |
fillrect(0, 0, gapp.winw, y0); |
fillrect(0, y1, gapp.winw, gapp.winh - y1); |
|
XSetForeground(xdpy, xgc, xshcolor.pixel); |
fillrect(x0+2, y1, gapp.image->w, 2); |
fillrect(x1, y0+2, 2, gapp.image->h); |
|
if (gapp.iscopying || justcopied) |
{ |
pdfapp_invert(&gapp, gapp.selr); |
justcopied = 1; |
} |
|
pdfapp_inverthit(&gapp); |
|
if (gapp.image->n == 4) |
ximage_blit(xwin, xgc, |
x0, y0, |
gapp.image->samples, |
0, 0, |
gapp.image->w, |
gapp.image->h, |
gapp.image->w * gapp.image->n); |
else if (gapp.image->n == 2) |
{ |
int i = gapp.image->w*gapp.image->h; |
unsigned char *color = malloc(i*4); |
if (color != NULL) |
{ |
unsigned char *s = gapp.image->samples; |
unsigned char *d = color; |
for (; i > 0 ; i--) |
{ |
d[2] = d[1] = d[0] = *s++; |
d[3] = *s++; |
d += 4; |
} |
ximage_blit(xwin, xgc, |
x0, y0, |
color, |
0, 0, |
gapp.image->w, |
gapp.image->h, |
gapp.image->w * 4); |
free(color); |
} |
} |
|
pdfapp_inverthit(&gapp); |
|
if (gapp.iscopying || justcopied) |
{ |
pdfapp_invert(&gapp, gapp.selr); |
justcopied = 1; |
} |
|
winblitsearch(app); |
} |
|
void winrepaint(pdfapp_t *app) |
{ |
dirty = 1; |
} |
|
void winrepaintsearch(pdfapp_t *app) |
{ |
dirtysearch = 1; |
} |
|
void windrawstringxor(pdfapp_t *app, int x, int y, char *s) |
{ |
int prevfunction; |
XGCValues xgcv; |
|
XGetGCValues(xdpy, xgc, GCFunction, &xgcv); |
prevfunction = xgcv.function; |
xgcv.function = GXxor; |
XChangeGC(xdpy, xgc, GCFunction, &xgcv); |
|
XSetForeground(xdpy, xgc, WhitePixel(xdpy, DefaultScreen(xdpy))); |
|
XDrawString(xdpy, xwin, xgc, x, y, s, strlen(s)); |
XFlush(xdpy); |
|
XGetGCValues(xdpy, xgc, GCFunction, &xgcv); |
xgcv.function = prevfunction; |
XChangeGC(xdpy, xgc, GCFunction, &xgcv); |
|
printf("drawstring '%s'\n", s); |
} |
|
void windrawstring(pdfapp_t *app, int x, int y, char *s) |
{ |
XSetForeground(xdpy, xgc, BlackPixel(xdpy, DefaultScreen(xdpy))); |
XDrawString(xdpy, xwin, xgc, x, y, s, strlen(s)); |
} |
|
void windocopy(pdfapp_t *app) |
{ |
/* unsigned short copyucs2[16 * 1024]; |
char *latin1 = copylatin1; |
char *utf8 = copyutf8; |
unsigned short *ucs2; |
int ucs; |
|
pdfapp_oncopy(&gapp, copyucs2, 16 * 1024); |
|
for (ucs2 = copyucs2; ucs2[0] != 0; ucs2++) |
{ |
ucs = ucs2[0]; |
|
utf8 += runetochar(utf8, &ucs); |
|
if (ucs < 256) |
*latin1++ = ucs; |
else |
*latin1++ = '?'; |
} |
|
*utf8 = 0; |
*latin1 = 0; |
|
XSetSelectionOwner(xdpy, XA_PRIMARY, xwin, copytime); |
|
justcopied = 1;*/ |
} |
|
void onselreq(Window requestor, Atom selection, Atom target, Atom property, Time time) |
{ |
/* XEvent nevt; |
|
if (property == None) |
property = target; |
|
nevt.xselection.type = SelectionNotify; |
nevt.xselection.send_event = True; |
nevt.xselection.display = xdpy; |
nevt.xselection.requestor = requestor; |
nevt.xselection.selection = selection; |
nevt.xselection.target = target; |
nevt.xselection.property = property; |
nevt.xselection.time = time; |
|
if (target == XA_TARGETS) |
{ |
Atom atomlist[4]; |
atomlist[0] = XA_TARGETS; |
atomlist[1] = XA_TIMESTAMP; |
atomlist[2] = XA_STRING; |
atomlist[3] = XA_UTF8_STRING; |
printf(" -> targets\n"); |
XChangeProperty(xdpy, requestor, property, target, |
32, PropModeReplace, |
(unsigned char *)atomlist, sizeof(atomlist)/sizeof(Atom)); |
} |
|
else if (target == XA_STRING) |
{ |
XChangeProperty(xdpy, requestor, property, target, |
8, PropModeReplace, |
(unsigned char *)copylatin1, strlen(copylatin1)); |
} |
|
else if (target == XA_UTF8_STRING) |
{ |
XChangeProperty(xdpy, requestor, property, target, |
8, PropModeReplace, |
(unsigned char *)copyutf8, strlen(copyutf8)); |
} |
|
else |
{ |
nevt.xselection.property = None; |
} |
|
XSendEvent(xdpy, requestor, False, SelectionNotify, &nevt); |
* */ |
} |
|
void winreloadfile(pdfapp_t *app) |
{ |
int fd; |
|
pdfapp_close(app); |
|
fd = open(filename, O_BINARY | O_RDONLY, 0666); |
if (fd < 0) |
winerror(app, fz_throw("cannot reload file '%s'", filename)); |
|
pdfapp_open(app, filename, fd, 1); |
} |
|
void winopenuri(pdfapp_t *app, char *buf) |
{ |
/* |
char *browser = getenv("BROWSER"); |
if (!browser) |
browser = "open"; |
if (fork() == 0) |
execlp(browser, browser, buf, (char*)0); |
* */ |
|
} |
|
static void onkey(int c) |
{ |
/* if (justcopied) |
{ |
justcopied = 0; |
winrepaint(&gapp); |
} |
* */ |
|
pdfapp_onkey(&gapp, c); |
} |
|
static void onmouse(int x, int y, int btn, int modifiers, int state) |
{ |
/* if (state != 0 && justcopied) |
{ |
justcopied = 0; |
winrepaint(&gapp); |
}*/ |
|
pdfapp_onmouse(&gapp, x, y, btn, modifiers, state); |
} |
|
static void signal_handler(int signal) |
{ |
/* |
if (signal == SIGHUP) |
reloading = 1; |
* */ |
|
} |
|
static void usage(void) |
{ |
fprintf(stderr, "usage: mupdf [options] file.pdf [page]\n"); |
fprintf(stderr, "\t-b -\tset anti-aliasing quality in bits (0=off, 8=best)\n"); |
fprintf(stderr, "\t-p -\tpassword\n"); |
fprintf(stderr, "\t-r -\tresolution\n"); |
fprintf(stderr, "\t-A\tdisable accelerated functions\n"); |
exit(1); |
} |
|
int main(int argc, char **argv) |
{ |
int c; |
int len; |
char buf[128]; |
KeySym keysym; |
int oldx = 0; |
int oldy = 0; |
int resolution = 72; |
int pageno = 1; |
int accelerate = 1; |
int fd; |
fd_set fds; |
int width = -1; |
int height = -1; |
|
while ((c = fz_getopt(argc, argv, "p:r:b:A")) != -1) |
{ |
switch (c) |
{ |
case 'p': password = fz_optarg; break; |
case 'r': resolution = atoi(fz_optarg); break; |
case 'A': accelerate = 0; break; |
case 'b': fz_set_aa_level(atoi(fz_optarg)); break; |
default: usage(); |
} |
} |
|
if (resolution < MINRES) |
resolution = MINRES; |
if (resolution > MAXRES) |
resolution = MAXRES; |
|
if (argc - fz_optind == 0) |
usage(); |
|
filename = argv[fz_optind++]; |
|
if (argc - fz_optind == 1) |
pageno = atoi(argv[fz_optind++]); |
|
if (accelerate) |
fz_accelerate(); |
|
winopen(); |
|
pdfapp_init(&gapp); |
gapp.scrw = DisplayWidth(xdpy, xscr); |
gapp.scrh = DisplayHeight(xdpy, xscr); |
gapp.resolution = resolution; |
gapp.pageno = pageno; |
|
fd = open(filename, O_BINARY | O_RDONLY, 0666); |
if (fd < 0) |
winerror(&gapp, fz_throw("cannot open file '%s'", filename)); |
|
pdfapp_open(&gapp, filename, fd, 0); |
|
FD_ZERO(&fds); |
FD_SET(x11fd, &fds); |
|
signal(SIGHUP, signal_handler); |
|
while (!closing) |
{ |
do |
{ |
XNextEvent(xdpy, &xevt); |
|
switch (xevt.type) |
{ |
case Expose: |
dirty = 1; |
break; |
|
case ConfigureNotify: |
if (gapp.image) |
{ |
if (xevt.xconfigure.width != reqw || |
xevt.xconfigure.height != reqh) |
gapp.shrinkwrap = 0; |
} |
width = xevt.xconfigure.width; |
height = xevt.xconfigure.height; |
|
break; |
|
case KeyPress: |
len = XLookupString(&xevt.xkey, buf, sizeof buf, &keysym, NULL); |
|
if (!gapp.isediting) |
switch (keysym) |
{ |
case XK_Escape: |
len = 1; buf[0] = '\033'; |
break; |
|
case XK_Up: |
len = 1; buf[0] = 'k'; |
break; |
case XK_Down: |
len = 1; buf[0] = 'j'; |
break; |
|
case XK_Left: |
len = 1; buf[0] = 'b'; |
break; |
case XK_Right: |
len = 1; buf[0] = ' '; |
break; |
|
case XK_Page_Up: |
len = 1; buf[0] = ','; |
break; |
case XK_Page_Down: |
len = 1; buf[0] = '.'; |
break; |
} |
if (len) |
onkey(buf[0]); |
|
onmouse(oldx, oldy, 0, 0, 0); |
|
break; |
|
case MotionNotify: |
oldx = xevt.xbutton.x; |
oldy = xevt.xbutton.y; |
onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, xevt.xbutton.state, 0); |
break; |
|
case ButtonPress: |
onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, xevt.xbutton.state, 1); |
break; |
|
case ButtonRelease: |
copytime = xevt.xbutton.time; |
onmouse(xevt.xbutton.x, xevt.xbutton.y, xevt.xbutton.button, xevt.xbutton.state, -1); |
break; |
|
case SelectionRequest: |
onselreq(xevt.xselectionrequest.requestor, |
xevt.xselectionrequest.selection, |
xevt.xselectionrequest.target, |
xevt.xselectionrequest.property, |
xevt.xselectionrequest.time); |
break; |
|
case ClientMessage: |
if (xevt.xclient.format == 32 && xevt.xclient.data.l[0] == WM_DELETE_WINDOW) |
closing = 1; |
break; |
} |
} |
while (!closing && XPending(xdpy)); |
|
if (closing) |
continue; |
|
if (width != -1 || height != -1) |
{ |
pdfapp_onresize(&gapp, width, height); |
width = -1; |
height = -1; |
} |
|
if (dirty || dirtysearch) |
{ |
if (dirty) |
winblit(&gapp); |
else if (dirtysearch) |
winblitsearch(&gapp); |
dirty = 0; |
dirtysearch = 0; |
} |
|
if (XPending(xdpy)) |
continue; |
|
if (select(x11fd + 1, &fds, NULL, NULL, NULL) < 0) |
{ |
if (reloading) |
{ |
winreloadfile(&gapp); |
reloading = 0; |
} |
} |
} |
|
pdfapp_close(&gapp); |
|
XDestroyWindow(xdpy, xwin); |
|
XFreePixmap(xdpy, xicon); |
|
XFreeCursor(xdpy, xcwait); |
XFreeCursor(xdpy, xchand); |
XFreeCursor(xdpy, xcarrow); |
|
XFreeGC(xdpy, xgc); |
|
XCloseDisplay(xdpy); |
|
return 0; |
} |