/*{{{ send_sync -- start a session by sending current bitmap state*/ void send_sync(void) { BITMAP *map; int i; for (i = 1; i < next_id; i++) { if ((map = bit_maps[i]) && IS_SCREEN(map) && IS_PRIMARY(map)) { SEND_screen(i, BIT_WIDE(map), BIT_HIGH(map), 0); if (log_noinitial) log_noinitial = 0; else { map->primary->type |= _DIRTY; #ifdef DEBUG fprintf(stderr, "Setting %d (%d x %d) to dirty SCREEN \n", i, BIT_WIDE(map), BIT_HIGH(map)); #endif } } else if (map && IS_PRIMARY(map) && map->primary->id == i) map->primary->type |= _DIRTY; else if (map) fprintf(stderr, "Bitmap %d is corrupted\n", i); #ifdef DEBUG else fprintf(stderr, "Bitmap %d is not there!!!\n", i); #endif } }
/*{{{ bit_save -- convert bitmap data to external format*/ void *bit_save(BITMAP *bp) { int portable_size = B_SIZE8(BIT_WIDE(bp), 1, BIT_DEPTH(bp)); int bitmap_size = bit_linesize(BIT_WIDE(bp), BIT_DEPTH(bp)); int i; char *r, *map; char *s = (char *)BIT_DATA(bp); if ((r = map = malloc(BIT_HIGH(bp) * portable_size)) == NULL) return NULL; for (i = 0; i < BIT_HIGH(bp); i++, r += portable_size, s += bitmap_size) memcpy(r, s, portable_size); return (void *)map; }
void stretch_window(void) { int dx, dy; int x0, x1, y0, y1; SETMOUSEICON(&mouse_box); move_mouse(screen, mouse, &mousex, &mousey, 0); SETMOUSEICON(DEFAULT_MOUSE_CURSOR); x0 = ACTIVE(x0); y0 = ACTIVE(y0); x1 = x0 + BIT_WIDE(ACTIVE(border)); y1 = y0 + BIT_HIGH(ACTIVE(border)); if (2 * (mousex - x0) < x1 - x0) x0 = x1; dx = mousex - x0; if (2 * (mousey - y0) < y1 - y0) y0 = y1; dy = mousey - y0; /* x0,y0 is corner farthest from mouse. x0+dx,y0+dx is mouse position */ get_rect(screen, mouse, x0, y0, &dx, &dy, 0); do_button(0); /* look for shape event here */ do_event(EVENT_SHAPE, active, E_MAIN); (void)shape(x0, y0, dx, dy); }
/* Write a bitmap. Given an open FILE pointer to an file and a pointer to a bitmap, write the header and the bitmap. Return 0 on failure, positive on success. */ int bitmapwrite(FILE *fp, BITMAP *bp) { char *datap; int w, h; unsigned char d; struct b_header head; int sizefile1; /* the size of 1 line of the bitmap as stored in a file, in bytes */ int sizemem1; /* the size of 1 line of the bitmap as stored in memory, in bytes */ w = BIT_WIDE(bp); h = BIT_HIGH(bp); d = BIT_DEPTH(bp); B_PUTHDR8(&head, w, h, d); sizefile1 = B_SIZE8(w, 1, d); if (fwrite((char *)&head, sizeof head, 1, fp) != 1) return 0; sizemem1 = bit_linesize(w, d); datap = (char *)BIT_DATA(bp); while (h-- > 0) { if (fwrite(datap, sizefile1, 1, fp) != 1) return 0; datap += sizemem1; } return (1); }
/*{{{ in_win -- see if rectangle in window*/ static int in_win(WINDOW *win, int x0, int y0, int x1, int y1) { return ( W(x0) + BIT_WIDE(W(border)) <= x0 || x1 <= W(x0) || W(y0) + BIT_HIGH(W(border)) <= y0 || y1 <= W(y0) ? 0 : 1); }
int main(int argc, char *argv[]) { BITMAP *bp; int i; #ifdef MOVIE log_start(fopen("lines.log","w")); #endif bp=bit_open(SCREEN_DEV); bit_blit(bp,0,0,BIT_WIDE(bp),BIT_HIGH(bp),BIT_CLR,(BITMAP*)0,0,0); srand(getpid()*time((time_t*)0)); for (i=0; i<1000; i++) bit_line(bp,rand()%BIT_WIDE(bp),rand()%BIT_HIGH(bp),rand()%BIT_WIDE(bp),rand()%BIT_HIGH(bp),BIT_SET); bit_destroy(bp); #ifdef MOVIE log_end(); #endif exit(0); }
/*{{{ log_alloc -- log bit_alloc*/ void log_alloc(BITMAP *bp) { int id; id = get_mid(); bp->id = id; reg_map(bp); if (do_save) SEND_data(id, BIT_WIDE(bp), BIT_HIGH(bp), BIT_DATA(bp)); }
void border(WINDOW *win, int be_fat) { int both = win->borderwid; int out = (be_fat == BORDER_FAT) ? both - 1 : win->outborderwid; int inr = both - out; int clr = PUTOP(BIT_CLR, W(style)); int set = PUTOP(BIT_SET, W(style)); BITMAP *bdr = (W(flags) & W_ACTIVE) ? W(border) : W(save); int w = BIT_WIDE(bdr); int h = BIT_HIGH(bdr); if (both <= 0) return; ONE_BOX(bdr, 0, 0, w, h, out, set); ONE_BOX(bdr, out, out, w - out - out, h - out - out, inr, clr); }
/*{{{ main*/ int main(int argc, char *argv[]) { /*{{{ variables*/ enum { NOTHING, LOCAL, REMOTE } in=NOTHING; int c; int x,y; int mouse_x,mouse_y; int image_width,image_height; int image_xoffset=0,image_yoffset=0; int my_width,my_height; int err=0,usage=0; BITMAP *bp; FILE *input; static struct menu_entry menu[] = { { "quit","q" } }; char file[_POSIX_PATH_MAX]; /*}}} */ /*{{{ parse arguments*/ while ((c=getopt(argc,argv,"l:r:"))!=EOF) { switch (c) { /*{{{ l file*/ case 'l': { if ((input=fopen(optarg,"r"))==(FILE*)0) { fprintf(stderr,"%s: Can't open %s\r\n",argv[0],optarg); err=1; } else in=LOCAL; break; } /*}}} */ /*{{{ r file*/ case 'r': { char *cwd; in=REMOTE; if (*optarg!='/' && *optarg!='.') { if ((cwd=getcwd((char*)0,(size_t)0))!=(char*)0) { strcpy(file,cwd); strcat(file,"/"); strcat(file,optarg); } else { fprintf(stderr,"%s: Can't get current directory\r\n",argv[0]); err=1; } } else strcpy(file,optarg); break; } /*}}} */ /*{{{ default*/ default: { usage=1; break; } /*}}} */ } } if (err) exit(err); if (usage || optind!=argc) { fprintf(stderr,"Usage: mgrview [-l file | -r file]\n"); exit(1); } if (in==NOTHING) { in=LOCAL; input=stdin; } /*}}} */ /*{{{ setup*/ ckmgrterm(argv[0]); m_setup(M_MODEOK); signal(SIGINT,clean); signal(SIGTERM,clean); signal(SIGPIPE,clean); m_ttyset(); m_push(P_MENU|P_EVENT|P_FLAGS); m_setmode(M_ABS); m_setcursor(CS_INVIS); menu_load(1,1,menu); m_setevent(REDRAW, "R"); m_setevent(RESHAPE, "R"); m_setevent(BUTTON_1,"[%p]"); m_setevent(BUTTON_2,"m"); m_flush(); /*}}} */ if (in==LOCAL) { /*{{{ load bitmap to client space*/ if ((bp=bitmapread(input))==(BITMAP*)0) { fprintf(stderr,"%s: No MGR bitmap.\r\n",argv[0]); clean(1); } image_width=BIT_WIDE(bp); image_height=BIT_HIGH(bp); /*}}} */ /*{{{ transfer bitmap to server space*/ m_func(BIT_SRC); m_bitcreate(IMAGE_BITMAP,image_width,image_height); m_bitldto(image_width,image_height,0,0,IMAGE_BITMAP,bit_size(image_width,image_height,BIT_DEPTH(bp))); fwrite(BIT_DATA(bp),bit_size(image_width,image_height,BIT_DEPTH(bp)),1,m_termout); m_flush(); bit_destroy(bp); /*}}} */ } else if (in==REMOTE) { /*{{{ transfer bitmap from server fs to server space*/ m_bitfromfile(IMAGE_BITMAP,file); m_get(); if (sscanf(m_linebuf,"%d %d",&image_width,&image_height)<2) { fprintf(stderr,"%s: No MGR bitmap.\r\n",argv[0]); clean(1); } /*}}} */ } /*{{{ user interaction*/ get_size((int*)0,(int*)0,&my_width,&my_height); display(image_xoffset,image_yoffset,my_width,my_height,image_width,image_height); m_flush(); while ((c=getc(m_termin))!='q') switch (c) { /*{{{ m -- left button displays menu*/ case 'm': { m_selectmenu(1); m_flush(); break; } /*}}} */ /*{{{ [%d %d] -- right button*/ case '[': { fscanf(m_termin,"%d %d]",&mouse_x,&mouse_y); /*{{{ compute new x start*/ if (my_width>image_width) image_xoffset=0; else if (mouse_x<=0) image_xoffset=0; else if (mouse_x>=my_width) image_xoffset=my_width-image_width; else { /*{{{ move x start by difference from mouse and middle*/ image_xoffset=image_xoffset-(mouse_x-my_width/2); /*}}} */ /*{{{ check and corrent range of x start*/ if (image_xoffset<my_width-image_width) image_xoffset=my_width-image_width; else if (image_xoffset>0) image_xoffset=0; /*}}} */ } /*}}} */ /*{{{ compute new y start*/ if (my_height>image_height) image_yoffset=0; else if (mouse_y<=0) image_yoffset=0; else if (mouse_y>=my_height) image_yoffset=my_height-image_height; else { /*{{{ move y start by difference from mouse and middle*/ image_yoffset=image_yoffset-(mouse_y-my_height/2); /*}}} */ /*{{{ check and corrent range of y start*/ if (image_yoffset<my_height-image_height) image_yoffset=my_height-image_height; else if (image_yoffset>0) image_yoffset=0; /*}}} */ } /*}}} */ display(image_xoffset,image_yoffset,my_width,my_height,image_width,image_height); m_flush(); break; } /*}}} */ /*{{{ R -- redraw*/ case 'R': { get_size((int*)0,(int*)0,&my_width,&my_height); /*{{{ compute new x offset*/ if (my_width<image_width) { if (image_xoffset<my_width-image_width) image_xoffset=my_width-image_width; } else image_xoffset=0; /*}}} */ /*{{{ compute new y offset*/ if (my_height<image_height) { if (image_yoffset<my_height-image_height) image_yoffset=my_height-image_height; } else image_yoffset=0; /*}}} */ m_func(BIT_CLR); m_bitwrite(0,0,my_width,my_height); m_func(BIT_SRC); m_bitcopyto(image_xoffset,image_yoffset,image_width,image_height,0,0,WINDOW_BITMAP,IMAGE_BITMAP); m_flush(); break; } /*}}} */ } /*}}} */ /*{{{ exit*/ m_bitdestroy(IMAGE_BITMAP); get_colrow(&x,&y); m_move(0,y-1); clean(0); /* NOTREACHED */ return 255; /*}}} */ }
/*{{{ shape -- reshape a window to specified dimensions*/ int shape(int x, int y, int dx, int dy) { int sx, sy, w, h; WINDOW *win; if (dx > 0) { sx = x; w = dx; } else { sx = x + dx; w = -dx; } if (dy > 0) { sy = y; h = dy; } else { sy = y + dy; h = -dy; } if (sx < 0) sx = 0; if (sx + w >= BIT_WIDE(screen)) w = BIT_WIDE(screen) - sx; if (sy + h >= BIT_HIGH(screen)) h = BIT_HIGH(screen) - sy; if (w < 2 * ACTIVE(borderwid) + ACTIVE(font)->head.wide * MIN_X || h < 2 * ACTIVE(borderwid) + ACTIVE(font)->head.high * MIN_Y) return (-1); #ifdef MGR_ALIGN alignwin(screen, &sx, &w, ACTIVE(borderwid)); #endif /* remove current window position */ save_win(active); erase_win(ACTIVE(border)); clip_bad(active); /* invalidate clip lists */ /* redraw remaining windows */ repair(active); /* adjust window state */ ACTIVE(x0) = sx; ACTIVE(y0) = sy; bit_destroy(ACTIVE(window)); bit_destroy(ACTIVE(border)); ACTIVE(border) = bit_create(screen, sx, sy, w, h); ACTIVE(window) = bit_create(ACTIVE(border), ACTIVE(borderwid), ACTIVE(borderwid), w - ACTIVE(borderwid) * 2, h - ACTIVE(borderwid) * 2); for (win = ACTIVE(next); win != (WINDOW *)0; win = W(next)) { if (W(flags) & W_ACTIVE && intersect(active, win)) save_win(win); } CLEAR(ACTIVE(window), PUTOP(BIT_CLR, ACTIVE(style))); border(active, BORDER_THIN); bit_blit(ACTIVE(border), 0, 0, BIT_WIDE(ACTIVE(save)) - ACTIVE(borderwid), BIT_HIGH(ACTIVE(save)) - ACTIVE(borderwid), BIT_SRC, ACTIVE(save), 0, 0); /* make sure character cursor is in a good spot */ if (ACTIVE(x) > BIT_WIDE(ACTIVE(window))) { ACTIVE(x) = 0; ACTIVE(y) += ((int)(ACTIVE(font)->head.high)); } if (ACTIVE(y) > BIT_HIGH(ACTIVE(window))) { #ifdef WIERD ACTIVE(y) = BIT_HIGH(ACTIVE(window)); scroll(ACTIVE(window), 0, BIT_HIGH(ACTIVE(window)), ((int)(ACTIVE(font)->head.high)), SWAPCOLOR(ACTIVE(style))); bit_blit(ACTIVE(window), 0, BIT_HIGH(ACTIVE(window)) - ((int)(ACTIVE(font)->head.high)), BIT_WIDE(ACTIVE(save)), ((int)(ACTIVE(font)->head.high)), BIT_SRC, ACTIVE(save), ACTIVE(borderwid), BIT_HIGH(ACTIVE(save)) - ((int)(ACTIVE(font)->head.high)) - ACTIVE(borderwid)); #else ACTIVE(y) = BIT_HIGH(ACTIVE(window)) - ((int)(ACTIVE(font)->head.high)); #endif } bit_destroy(ACTIVE(save)); ACTIVE(save) = (BITMAP *)0; /* invalidate clip lists */ clip_bad(active); un_covered(); set_size(active); return (0); }
/*{{{ gen_list -- generate a clip list*/ static int gen_list(WINDOW *window) { WINDOW *win = window; struct rect_list *list = NULL, *prev = (struct rect_list *)0; int x_cnt = 2, y_cnt = 2; int i, j; int count = 0; int skip; /* covered by another window - skip patch */ int hold; /* hold for coalescing */ /* build arrays of window coordinates: intersecting win's above win */ x[0] = W(borderwid) + W(x0); y[0] = W(borderwid) + W(y0); x[1] = W(borderwid) + W(x0) + BIT_WIDE(W(window)); y[1] = W(borderwid) + W(y0) + BIT_HIGH(W(window)); for (win = active; win != window; win = W(next)) { if (!(in_win(win, x[0], y[0], x[1], y[1]))) continue; if (W(x0) >= x[0] && W(x0) <= x[1]) x[x_cnt++] = W(x0); if (W(y0) >= y[0] && W(y0) <= y[1]) y[y_cnt++] = W(y0); if (W(x0) + BIT_WIDE(W(border)) >= x[0] && W(x0) + BIT_WIDE(W(border)) <= x[1]) x[x_cnt++] = W(x0) + BIT_WIDE(W(border)); if (W(y0) + BIT_HIGH(W(border)) >= y[0] && W(y0) + BIT_HIGH(W(border)) <= y[1]) y[y_cnt++] = W(y0) + BIT_HIGH(W(border)); if (y_cnt >= MAX_COORDS || x_cnt >= MAX_COORDS) break; } /* sort window coordinate lists */ qsort(x, x_cnt, sizeof(int), cmp); qsort(y, y_cnt, sizeof(int), cmp); x_cnt--; y_cnt--; /* build list of covering rectangles */ for (j = 0; j < y_cnt; j++) { if (y[j] == y[j + 1]) /* avoid zero-height patches */ continue; for (hold = x_cnt, i = 0; i < x_cnt; i++) { if (x[i] == x[i + 1]) /* avoid zero-width patches */ continue; /* see if patch is visible */ for (skip = 0, win = active; win != window; win = W(next)) if (in_win(win, x[i], y[j], x[i + 1], y[j + 1])) { skip++; break; } /* visible, add patch to list, or append to previous patch */ if (!skip) { if (i == hold) { /* coalescing across */ list->rect.wide += x[i + 1] - x[i]; hold++; } else { /* flush held rect */ count++; /* only for debugging */ list = malloc(sizeof(struct rect_list)); list->rect.x = x[i] - W(x0); list->rect.y = y[j] - W(y0); list->rect.wide = x[i + 1] - x[i]; list->rect.high = y[j + 1] - y[j]; list->next = NULL; if (prev) prev->next = list; if (!W(clip_list)) /* set initial rectangle */ W(clip_list) = (char *)list; prev = list; hold = i + 1; /* next 'i' to check for coalescing */ } } } } /* look at rect list DEBUG code, commented out! for(list=(struct rect_list *) W(clip_list);list;list = list->next) { int x = list->rect.x, y = list->rect.y, wide = list->rect.wide, high = list->rect.high; in_mouseoff( x, y, wide, high ); bit_blit(W(border), x, y, wide, high, BIT_NOT(BIT_DST),0L,0,0); dbgprintf('U',(stderr," Rect %d,%d %dx%d\n", x, y, wide, high )); getchar(); bit_blit(W(border), x, y, wide, high, BIT_NOT(BIT_DST),0L,0,0); MOUSE_ON(screen,mousex,mousey); } DEBUG code, commented out! */ dbgprintf('U', (stderr, "%s: Built clip list (%d)\r\n", W(tty), count)); return (0); /* I'll think of something */ }