📄 vgadisp.c
字号:
vga_unlockvc();}void graphicsoff(){/* we let zgv.c deal with this now, so this is just a placeholder */}/* tells us if mode is ok to use in current circumstances. */int mode_is_usable_now(int modenum){if(vga_hasmode(modenum) && cfg.mode_allowed[modenum] && ((pixelsize==1 && get_mode_numcols(modenum)<=256) || (pixelsize==3 && get_mode_numcols(modenum)> 256))) return(1);return(0);}int allow_zoom(void){return(zoom && (!cfg.zoom_reduce_only || width>scrnwide || height>scrnhigh));}void swap_black_to_bg(byte *palette){unsigned char *ptr,minidx=0;int mindist=(1<<30),dist;int f,r,g,b;if(pixelsize!=1 || palette[0]+palette[256]+palette[512]==0) return;for(f=1;f<256;f++) { /* we can afford to be fairly approximate about this */ dist=palette[f]+palette[256+f]+palette[512+f]; if(dist<mindist) { mindist=dist; minidx=f; if(dist==0) break; } }if(minidx==0) return; /* sanity check - should be impossible *//* do the swap */ptr=theimage;for(f=0;f<width*height;f++,ptr++) { if(*ptr==minidx) *ptr=0; else { if(*ptr==0) *ptr=minidx; } }r=palette[minidx];g=palette[minidx+256];b=palette[minidx+512];palette[minidx]=palette[0];palette[minidx+256]=palette[256];palette[minidx+512]=palette[512];palette[0]=r;palette[256]=g;palette[512]=b;}/* returns 1 if ESC or 'x' was pressed, 0 if because of timeout when * using cfg.repeat_timer option. * * caller must restore mouse pos this saves, in appropriate mode. */int showgif(char *filename,byte *palette){int opx,opy,px,py,quitshow,key,redraw;int npx=0,npy=0; /* equivalent to px,py in scaling>1 mode */int f;int mode_prefix=0;int rb_menu_mode=0,scrolling_with_mouse=0;int slideshow_pause=0;static int orient_lastpicexit_state=0; /* last picture orientation state */int orient_current_state; /* current picture orientation state */int vkcache_reinit=0;int doing_auto_animate=0;wait_for_foreground();/* make sure we have a decent saved mouse position (initial position, * or (more usually) from selector). */save_mouse_pos();orient_current_state=0; /* picture starts off at normal orientation *//* if image has less than 256 colours, we fill in the 64 greys so that * using the vkludge on, say, a mono file will look much better. */if(numcols<256) { for(f=numcols;f<numcols+64;f++) palette[f]=palette[256+f]=palette[512+f]=((f-numcols)<<2); /* get rid of any junk entries which vkludge etc. might try and use */ for(;f<256;f++) palette[f]=palette[256+f]=palette[512+f]=0; }/* try for black background for 8-bit images if asked to */if(pixelsize==1 && cfg.black_bg) swap_black_to_bg(palette);/* put 5-bit version of palette[] in pal32_no_bc. This is in a different * format, as required by closest() which uses it. */for(f=0;f<256;f++) { pal32_no_bc[f*3 ]=(palette[f]>>3); pal32_no_bc[f*3+1]=(palette[f+256]>>3); pal32_no_bc[f*3+2]=(palette[f+512]>>3); }/* init vkludge cache for this picture. Doesn't need updating for * brightness/contrast changes, and is filled in as needed. */if(pixelsize==1) init_vkludge_cache();pic_incr=0;repeat_sig=0;if(cfg.repeat_timer && !tagview_mode) { if(cfg.repeat_timer==-1) repeat_sig=2; /* make it look (nearly) instant */ else { signal(SIGALRM,repeat_sighandler); alarm(cfg.repeat_timer); } }if(tagview_mode) { signal(SIGALRM,repeat_sighandler); alarm(cfg.tag_timer); }quitshow=0;filterpal(palette);if(!cfg.repeat_timer || (cfg.repeat_timer && first_repeat)) { px=py=0; if(cfg.automodefit) do_auto_mode_fit(); graphicson(); first_repeat=0; if(cfg.revert) { scaling=1; interp=0; } if(!cfg.revert_orient && !orient_override) { orient_change_state(orient_current_state,orient_lastpicexit_state,0); orient_current_state=orient_lastpicexit_state; } }else if(cfg.repeat_timer) { px=saved_px; py=saved_py; }/* an orientation override always happens, even for repeat pics. * (Not least because it seems like the sort of thing which would be * dead useful for them. :-)) */if(orient_override) { orient_change_state(orient_current_state,orient_override_state,0); orient_current_state=orient_override_state; }if(cfg.auto_animate && gif_delaycount>=2 && pixelsize==1) doing_auto_animate=1;else redrawgif(px,py,npx,npy);while(!quitshow && (repeat_sig!=1 || rb_menu_mode || slideshow_pause)) { if(doing_auto_animate) key='e',quitshow=1; /* do animation only, then exit */ else { if(rb_menu_mode) mousecur_on(); key=wait_for_keys_or_mouse(zgv_ttyfd); if(rb_menu_mode) mousecur_off(); } opx=px; opy=py; redraw=0; /* convert xzgv-ish keypresses */ if(cfg.xzgvkeys) { switch(key) { /* omissions/problems: * - ctrl-cursors aren't distinguishable, so we can't support those. * - ^q would break slideshow pausing, which IMHO isn't worth it. * (I've also omitted q for some sort of consistency with that.) * - tab would break selecting some modes, also not worth it. */ case 'b': key=127; break; case ' ': key=RK_ENTER; break; case RK_CTRLSPACE: key=' '; break; case 'W'-0x40: key=RK_ESC; break; case 'N': key=128+'n'; break; } } if(rb_menu_mode) { /* we deal with keys ourselves... */ if(key==RK_ESC || key=='x') { rb_menu_mode=0; undraw_rb_menu(); continue; } /* but mouse dealt with by this. if not clicked an entry, skip * rest of loop. * (no repeat_sig==2 handling required here, as even in incredibly * pathological circumstances we *can't* get here with repeat_sig==2.) */ if(rb_menu_event(&key)) /* returns non-zero if should stay in menu */ continue; /* otherwise restore saved area of screen, and do action in (faked) key */ rb_menu_mode=0; undraw_rb_menu(); goto parsekey; /* skip normal mouse stuff just in case */ } if(has_mouse) { int mbuttons=mouse_getbutton(); int mleft_start=is_start_click_left(); /* important to read both, even if not using both */ int mleft=is_end_click_left(),mright=is_end_click_right(); /* if right button released, get the right-button menu. */ if(mright) { /* only allow it if >=480 pixels high! */ if(scrnhigh>=480) { rb_menu_mode=1; scrolling_with_mouse=0; draw_rb_menu(); /* if left mouse button down, ignore first end-left-click. */ rb_ignore_first_left_click=((mbuttons&MOUSE_LEFTBUTTON)?1:0); /* skip rest of main loop except this - we still might have to * sort this out (hugely unlikely, but all the same...) */ if(repeat_sig==2) repeat_sig--; continue; } } if(scrolling_with_mouse) { /* mouse is in sensible range/location for image scroll, then; * read the mouse position into px/py. */ px=mouse_getx(); py=mouse_gety(); } /* if left mouse button pressed, or currently scrolling w/mouse, * prepare for next event's movement. * (a bit nasty doing this every time, but we have to, really.) */ if((mleft_start || scrolling_with_mouse) && !allow_zoom()) { int max_x,max_y; scrolling_with_mouse=1; max_x=width*scaling-scrnwide-1; max_y=height*scaling-scrnhigh-1; /* make sure we don't give it crazy ranges, esp. not 0..0, * which would probably cause a div by zero or something... */ if(max_x<=0) max_x=1; if(max_y<=0) max_y=1; mouse_setxrange(0,max_x); mouse_setyrange(0,max_y); mouse_setposition(px,py); } /* if left button not down, don't move with mouse any more. * this is after the rest to make sure we don't miss any * scrolling motions if scrolling_with_mouse is currently set. */ if(!(mbuttons&MOUSE_LEFTBUTTON)) scrolling_with_mouse=0; mleft=0; /* kludge to keep gcc -Wall happy */ } parsekey: /* avoid problems with mode or scaling change etc. */ if(key) scrolling_with_mouse=0; /* mode selection - note that F11=shift-F1 and F12=shift-F2 */ if(key=='0' || key=='^' || (key>='5' && key<='8') || (key>=RK_F1 && key<=RK_F10) || (key>=RK_SHIFT_F1 && key<=RK_SHIFT_F10)) { struct modedesc_tag *md_ptr; int mode=0,fallback_mode=0; for(md_ptr=modedesc;md_ptr->mode;md_ptr++) { if(mode_prefix!=md_ptr->is_tab_key) continue; if(key==md_ptr->viewer_key && mode_is_usable_now(md_ptr->mode)) { if(md_ptr->bytespp==4) /* if 32-bit */ fallback_mode=md_ptr->mode; else mode=md_ptr->mode; } } mode_prefix=0; /* if mode is no good, try the fallback (if any) */ if(!mode && fallback_mode) mode=fallback_mode; /* if we've got something valid, use it. */ if(mode) { int oldmode=curvgamode; curvgamode=mode; if(curvgamode==G640x480x16 || oldmode==G640x480x16) { /* when switching to/from 640x480x4, need filterpal() * in case of implicit gamma change (see apply_gamma()). * Note that this is the only graphicson() call that needs * this, as the 640x480x4 mode can't be switched to * in any other way than specifically selecting it. */ filterpal(palette); } graphicson(); redraw=1; } } else /* if not a mode-selecting key... */ { if(key) mode_prefix=0; switch(key) {#ifdef PCD_SUPPORT case 128+'1': case 128+'2': case 128+'3': case 128+'4': case 128+'5': /* Alt1 - Alt5 */ cfg.pcdres=key-128-'0'; quitshow=2; pic_incr=PIC_INCR_RELOAD_KLUDGE; break;#endif case 9: /* tab */ mode_prefix=1; break; case 'F': cfg.fakecols=!cfg.fakecols; if(pixelsize==1) { filterpal(palette),setpalvec(0,256,palrgb); if(curvgamode==G640x480x16) redraw=1; } break; /* the way pause/resume slideshow works is quite simple - * pausing overrides the repeat_sig var set when the timer * times out, and resuming disables that override. */ case 'S'-0x40: /* pause slideshow */ if(tagview_mode) slideshow_pause=1; break; case 'Q'-0x40: /* resume slideshow */ if(tagview_mode) slideshow_pause=0; break; case 's': case 'd': if(allow_zoom()) vga_clear(); /* cls if zoomed, in case x2 is smaller! */ zoom=0; if(scaling<512) { int oldscale=scaling; scaling+=(key=='d')?scaling:1; if(scaling>512) scaling=512; samecentre(&px,&py,scaling,px,py,oldscale); redraw=1; /* no cls reqd. - must be bigger */ } break; case 'S': case 'D': if(scaling>1 || allow_zoom()) { int oldscale=scaling; scaling-=(key=='D')?scaling/2:1; if(scaling<1) scaling=1; samecentre(&px,&py,scaling,px,py,oldscale); redraw=1; if(width*scaling<scrnwide || height*scaling<scrnhigh) vga_clear(); } zoom=0; break; case 'n': if(allow_zoom() || scaling>1) { samecentre(&px,&py,1,px,py,scaling); vga_clear(); } scaling=1; zoom=0; redraw=1; interp=0; inextpix=1; break; case RK_HOME: case 'A'-0x40: px=py=0; break; case RK_END: case 'E'-0x40: px=py=1<<30; break; case RK_PAGE_UP: case 'U'-0x40: py-=scrnhigh*9/10; break; case RK_PAGE_DOWN: case 'V'-0x40: py+=scrnhigh*9/10; break; case '-': px-=scrnwide*9/10; break; case '=': px+=scrnwide*9/10; break; case 'v': vkludge=((vkludge==1)?0:1); redraw=1; graphicson(); break; case ',': case '.': case '<': case '>': case 128+',': case 128+'.': case 'B': case '*': case ';': case '1': case '2': case '3': case '4': switch(key) { case ',': contrast-=0.05; break; case '.': contrast+=0.05; break; case '<': brightness-=10; break; case '>': brightness+=10; break; case 128+',': picgamma/=1.05; break; case 128+'.': picgamma*=1.05; break; case 'B': cfg.bc_order_rev=!cfg.bc_order_rev; break; case '1': picgamma=1.0; break; case '2': picgamma=2.2; break; case '3': picgamma=(1.0/2.2); break; case '4': picgamma=cfg.initial_picgamma; break; default: brightness=0; contrast=1.0; break; } filterpal(palette); /* make palr/g/b/t */ if(scrnpixelsize>1) redraw=1; /* redraw if non-palette-based... */ else setpalvec(0,256,palrgb); /* else change onscreen palette */ /* 640x480 16-colour needs *both*! */ if(curvgamode==G640x480x16) redraw=1; /* any palette change will invalidate the vkludge cache. * Set flag to say we should reinit the cache when we next redraw. */ vkcache_reinit=1; break; case ':': file_details(filename,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -