aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c289
1 files changed, 185 insertions, 104 deletions
diff --git a/src/main.c b/src/main.c
index e79af03..a8d043b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,4 +1,6 @@
+#include <unistd.h>
+
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
@@ -11,6 +13,11 @@
#include "meh.h"
+#define MODE_NORM 0
+#define MODE_LIST 1
+#define MODE_CTL 2
+static int mode;
+
extern Display *display;
/* Supported Formats */
@@ -46,125 +53,195 @@ struct image *imgopen(FILE *f){
return NULL;
}
-int imageslen;
-int imageidx;
-char **images;
+static int imageslen;
+static int imageidx;
+static char **images;
+
+static char *filename = NULL;
+static int width = 0, height = 0;
+static struct image *img = NULL;
+static XImage *ximg = NULL;
+static int redraw = 0;
-const char *nextimage(){
+void nextimage(){
if(++imageidx == imageslen)
imageidx = 0;
- return images[imageidx];
+ filename = images[imageidx];
}
-const char *previmage(){
+void previmage(){
if(--imageidx < 0)
imageidx = imageslen - 1;
- return images[imageidx];
+ filename = images[imageidx];
}
-void run(){
- const char *(*direction)() = nextimage;
- const char *filename = direction();
- int width = 0, height = 0;
- struct image *img = NULL;
- XImage *ximg = NULL;
- int redraw = 0;
+static void (*direction)() = nextimage;
- for(;;){
- XEvent event;
- for(;;){
- if(redraw && !XPending(display))
- break;
- XNextEvent(display, &event);
- switch(event.type){
- case ConfigureNotify:
- if(width != event.xconfigure.width || height != event.xconfigure.height){
- width = event.xconfigure.width;
- height = event.xconfigure.height;
- redraw = 1;
- if(ximg)
- XDestroyImage(ximg);
- ximg = NULL;
-
- /* Some window managers need reminding */
- if(img)
- setaspect(img->width, img->height);
- }
- break;
- case Expose:
- redraw = 1;
- break;
- case KeyPress:
- switch(XLookupKeysym(&event.xkey, 0)){
- case XK_Escape:
- exit(0);
- break;
- case XK_q:
- exit(0);
- break;
- case XK_t:
- case XK_n:
- if(XLookupKeysym(&event.xkey, 0) == XK_t){
- direction = nextimage;
- }else{
- direction = previmage;
- }
- filename = direction();
- /* Pass through */
- case XK_r:
- if(img){
- if(img->buf)
- free(img->buf);
- free(img);
- }
- if(ximg)
- XDestroyImage(ximg);
- ximg = NULL;
- img = NULL;
- redraw = 1;
- break;
- case XK_Return:
- puts(filename);
- fflush(stdout);
- break;
- }
+void handlekeypress(XEvent *event){
+ KeySym key = XLookupKeysym(&event->xkey, 0);
+ switch(key){
+ case XK_Escape:
+ case XK_q:
+ exit(0);
+ break;
+ case XK_Return:
+ puts(filename);
+ fflush(stdout);
+ break;
+ case XK_t:
+ case XK_n:
+ if(mode == MODE_CTL)
+ return;
+ direction = key == XK_t ? nextimage : previmage;
+ direction();
+ /* Pass through */
+ case XK_r:
+ if(img){
+ if(img->buf)
+ free(img->buf);
+ free(img);
+ }
+ if(ximg)
+ XDestroyImage(ximg);
+ ximg = NULL;
+ img = NULL;
+ redraw = 1;
+ break;
+ }
+}
+
+void handleevent(XEvent *event){
+ switch(event->type){
+ case ConfigureNotify:
+ if(width != event->xconfigure.width || height != event->xconfigure.height){
+ width = event->xconfigure.width;
+ height = event->xconfigure.height;
+ redraw = 1;
+ if(ximg)
+ XDestroyImage(ximg);
+ ximg = NULL;
+
+ /* Some window managers need reminding */
+ if(img)
+ setaspect(img->width, img->height);
+ }
+ break;
+ case Expose:
+ redraw = 1;
+ break;
+ case KeyPress:
+ handlekeypress(event);
+ break;
+ }
+}
+
+void doredraw(){
+ if(!img){
+ if(!filename)
+ return;
+ const char *firstimg = filename;
+ while(!img){
+ FILE *f;
+ if((f = fopen(filename, "rb"))){
+ if((img = imgopen(f)))
break;
+ else
+ fprintf(stderr, "Invalid format '%s'\n", filename);
+ }else{
+ fprintf(stderr, "Cannot open '%s'\n", filename);
+ }
+ if(mode == MODE_CTL)
+ return;
+ direction();
+ if(filename == firstimg){
+ fprintf(stderr, "No valid images to view\n");
+ exit(EXIT_FAILURE);
}
}
- if(redraw){
- if(!img){
- const char *firstimg = filename;
- while(!img){
- FILE *f;
- if((f = fopen(filename, "rb"))){
- if((img = imgopen(f)))
- break;
- else
- fprintf(stderr, "Invalid format '%s'\n", filename);
- }else{
- fprintf(stderr, "Cannot open '%s'\n", filename);
- }
- filename = direction();
- if(filename == firstimg){
- fprintf(stderr, "No valid images to view\n");
- exit(EXIT_FAILURE);
- }
- }
+ setaspect(img->width, img->height);
- setaspect(img->width, img->height);
+ img->buf = malloc(3 * img->width * img->height);
+ if(img->fmt->read(img)){
+ fprintf(stderr, "read error!\n");
+ }
+ img->fmt->close(img);
+
+ /* Allow for some events to be read, read is slow */
+ /*while(XPending(display)){
+ XEvent event;
+ XNextEvent(display, &event);
+ handleevent(&event);
+ }*/
+ }
+ if(!ximg)
+ ximg = getimage(img, width, height);
+ drawimage(ximg, width, height);
+}
+
+
+void run(){
+ int xfd;
+ xfd = ConnectionNumber(display);
+ fd_set fds;
+ struct timeval tv0 = {0, 0};
+ struct timeval *tv = &tv0;
- img->buf = malloc(3 * img->width * img->height);
- if(img->fmt->read(img)){
- fprintf(stderr, "read error!\n");
+ char buf[512];
+ int bufidx = 0;
+ for(;;){
+ FD_ZERO(&fds);
+ FD_SET(xfd, &fds);
+ if(mode == MODE_CTL)
+ FD_SET(0, &fds); /* STDIN */
+ int ret = select(xfd+1, &fds, NULL, NULL, tv);
+ if(ret == -1){
+ perror("select failed\n");
+ }
+ if(FD_ISSET(0, &fds)){
+ assert(mode == MODE_CTL);
+ int n = read(0, buf, 512 - bufidx);
+ if(n == -1){
+ perror("read failed");
+ }else if(n == 0){
+ fprintf(stderr, "done reading\n");
+ exit(0);
+ }
+ char *p;
+ p = &buf[bufidx];
+ bufidx+=n;
+ for(; n > 0; p++, n--){
+ if(*p == '\n' || *p == '\0'){
+ n--;
+ *p = '\0';
+ strcpy(filename, buf);
+ for(;n && (*p == '\0' || *p == '\n'); p++, n--);
+ bufidx = n;
+ if(n)
+ memmove(buf, p, n);
+ if(img){
+ if(img->buf)
+ free(img->buf);
+ free(img);
+ }
+ if(ximg)
+ XDestroyImage(ximg);
+ ximg = NULL;
+ img = NULL;
+ redraw = 1;
+ tv = &tv0;
}
- img->fmt->close(img);
- continue; /* Allow for some events to be read, read is slow */
}
- if(!ximg)
- ximg = getimage(img, width, height);
- drawimage(ximg, width, height);
- redraw = 0;
+ }
+ if(!XPending(display) && ret == 0 && redraw){
+ doredraw();
+ tv = NULL;
+ }
+ while(XPending(display)){
+ tv = &tv0;
+ XEvent event;
+ XNextEvent(display, &event);
+ handleevent(&event);
}
}
}
@@ -176,17 +253,21 @@ int main(int argc, char *argv[]){
if(!strcmp(argv[1], "-ctl")){
if(argc != 2)
usage();
- printf("not implemented\n");
- exit(EXIT_FAILURE);
+ mode = MODE_CTL;
+ filename = malloc(512);
+ filename[0] = '\0';
}else if(!strcmp(argv[1], "-list")){
if(argc != 2)
usage();
+ mode = MODE_LIST;
printf("not implemented\n");
exit(EXIT_FAILURE);
}else{
+ mode = MODE_NORM;
images = &argv[1];
imageslen = argc-1;
- imageidx = -1;
+ imageidx = 0;
+ filename = argv[1];
}
xinit();
run();