📄 3deffects.c
字号:
/* zgv 5.5 - GIF, JPEG and PBM/PGM/PPM viewer, for VGA PCs running Linux. * Copyright (C) 1993-2001 Russell Marks. See README for license details. * * 3deffects.c - provides the `3d' style boxes, text etc. * used by zgv.c (for file selector) and vgadisp.c * (for help screen) */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <vga.h>#include <vgagl.h>#include <vgamouse.h>#include "3deffects.h"#include "font.h"#include "readnbkey.h"#include "zgv.h"#include "rc_config.h"#include "rcfile.h"#include "mousecur.h"#include "rbmenu.h" /* for rbm_find_and_fix_ui_cols() */int msgbox_draw_ok=0; /* 1 if ok to draw msgbox in current mode */static unsigned char *save_mem=NULL;static int save_x,save_y,save_width,save_height;/* records whether last msgbox() call restored the screen successfully; * if so, the caller can avoid a redraw by checking this via * msgbox_did_restore(). */static int last_msgbox_did_restore=1;/* in 15/16/24-bit, can't use vga_setcolor(), so we have a routine * to take care of that. * (in theory this might be better off as a macro, but we assume * it's inlined by gcc.) */static inline void setcolour(int col){if(vga_getcolors()<=256) vga_setcolor(col);else vga_setrgbcolor((col>>16)&255,(col>>8)&255,col&255);}/* produce tacky 3d text */void drawtext3d(int x,int y,int s,char *str, int isout,int light,int dark,int txt){setcolour(isout?light:dark);vgadrawtext(x-1,y-1,s,str);setcolour(isout?dark:light);vgadrawtext(x+1,y+1,s,str);setcolour(txt);vgadrawtext(x,y,s,str);}/* restore sanity */void undrawtext3d(int x,int y,int s,char *str){setcolour(idx_medium);vgadrawtext(x-1,y-1,s,str);vgadrawtext(x+1,y+1,s,str);vgadrawtext(x,y,s,str);}/* render each bock in 3d */void draw3dbox(int x1,int y1,int x2,int y2,int depth, int isout,int light,int dark){int f;for(f=0;f<depth;f++) { setcolour(isout?light:dark); vga_drawline(x1+f,y2-f,x1+f,y1+f); vga_drawline(x1+f,y1+f,x2-f,y1+f); setcolour(isout?dark:light); vga_drawline(x2-f,y1+f,x2-f,y2-f); vga_drawline(x2-f,y2-f,x1+f,y2-f); }}/* Undraw each relevant bock */void undraw3dbox(int x1,int y1,int x2,int y2,int depth){int f;setcolour(idx_medium);for(f=0;f<depth;f++) { vga_drawline(x1+f,y2-f,x1+f,y1+f); vga_drawline(x1+f,y1+f,x2-f,y1+f); vga_drawline(x2-f,y1+f,x2-f,y2-f); vga_drawline(x2-f,y2-f,x1+f,y2-f); }}void drawbutton(int x1,int y1,int x2,int y2,char *str,int centred, int light,int dark,int realblack,int txt){setcolour(light);vga_drawline(x1,y2-1,x1,y1);vga_drawline(x1,y1,x2-1,y1);setcolour(realblack);vga_drawline(x2,y1,x2,y2);vga_drawline(x2,y2,x1,y2);setcolour(dark);vga_drawline(x1+2,y2-1,x2-1,y2-1);vga_drawline(x2-1,y2-1,x2-1,y1+2);if(str && str[0]) { setcolour(txt); if(centred) vgadrawtext(x1+((x2-x1+1)-vgatextsize(3,str))/2,y1+6,3,str); else vgadrawtext(x1+5,y1+4,3,str); /* mainly for rbmenu.c */ }}/* save old contents of area to put right-button menu on, and draw it. * we know it's either a 4-bit or 8/15/16/24/32=bit mode. */static void save_area(int x1,int y1,int x2,int y2){save_x=x1;save_y=y1;save_width=x2-x1+1;save_height=y2-y1+1;/* max of 4 bytes per pixel */if((save_mem=malloc(save_width*save_height*4))==NULL) return;if(vga_getcurrentmode()!=G640x480x16) { /* use vgagl. mouse cursor does this too, but since we're doing the * same thing it won't hurt. :-) * (besides which, mouse might not be enabled...) */ gl_setcontextvga(vga_getcurrentmode()); gl_getbox(save_x,save_y,save_width,save_height,save_mem); }else { /* 16-colour, use vga_getscansegment */ unsigned char *ptr=save_mem; int y; for(y=0;y<save_height;y++,ptr+=save_width) vga_getscansegment(ptr,save_x,save_y+y,save_width); }}/* restore old contents of area */static void restore_area(){if(save_mem==NULL) return; /* ran out of memory, can't do much! */if(vga_getcurrentmode()!=G640x480x16) { /* use vgagl again */ gl_putbox(save_x,save_y,save_width,save_height,save_mem); }else { /* 16-colour */ unsigned char *ptr=save_mem; int y; for(y=0;y<save_height;y++,ptr+=save_width) vga_drawscansegment(ptr,save_x,save_y+y,save_width); }free(save_mem);}static void blank_area(int x1,int y1,int x2,int y2,int col){int scrncol;if(vga_getcurrentmode()==G640x480x16) { static unsigned char scanbit[640]; int f; memset(scanbit,col,sizeof(scanbit)); for(f=y1;f<y2;f++) vga_drawscansegment(scanbit,x1,f,x2-x1+1); return; }switch(vga_getcolors()) { case 32768: scrncol=GET15BITCOLOUR(col>>16,(col>>8)&255,col&255); break; case 65536: scrncol=GET16BITCOLOUR(col>>16,(col>>8)&255,col&255); break; default: scrncol=col; }gl_setcontextvga(vga_getcurrentmode());gl_fillbox(x1,y1,x2-x1+1,y2-y1+1,scrncol);}/* see def of last_msgbox_did_restore above for details */int msgbox_did_restore(void){return(last_msgbox_did_restore);}/* if msgbox_draw_ok is zero, it changes to file-selector mode before * drawing the box, and obviously this blasts the screen. :-) * Otherwise, it saves/restores the area used as needed. This only * works for 16 and 256-col modes, but we know we must be on file selector * if msgbox_draw_ok is non-zero, so that's ok. * * NB: for type MSGBOXTYPE_FILEDETAILS, `message' is corrupted by the * routine (`\n's overwritten with NULs). */int msgbox(int ttyfd,char *message,int replytype,int light,int dark,int txt){static char *fdlabels[7]= {"Filename:","Size:","Last modified:","Permissions:", "Owner:","Group:","Dimensions:"};static int palsav[256*3];int savedpal=0;int x1,y1,x2,y2,wide,high,key;struct { int x1,y1,x2,y2; } but1,but2;char *ptr;int retval=0;int save_and_restore=1;int mouseblack=idx_blacknz;char *fdetailstr[7];int fdlabelwidth=130; /* width of (left-hand) label bit for file details */last_msgbox_did_restore=0;if(!msgbox_draw_ok) { mouseblack=1; /* mustn't be zero */ if(vga_getxdim()<640 || vga_getydim()<480) { vga_setmode(fs_vgamode); save_and_restore=0; } switch(vga_getcolors()) { case 256: vga_getpalvec(0,256,palsav); savedpal=1; rbm_find_and_fix_ui_cols(&light,&idx_medium,&dark,&txt,&mouseblack, NULL,NULL,NULL); break; case 16: if(save_and_restore) /* then we haven't changed mode, so... */ vga_clear(); save_and_restore=0; vga_setpalette(0,0,0,0); vga_setpalette(idx_medium=1,cfg.medium.r,cfg.medium.g,cfg.medium.b); vga_setpalette(dark=2,cfg.dark.r,cfg.dark.g,cfg.dark.b); vga_setpalette(light=3,cfg.light.r,cfg.light.g,cfg.light.b); vga_setpalette(txt =4,cfg.black.r,cfg.black.g,cfg.black.b); vga_setpalette(mouseblack=5,0,0,0); /* a non-zero-index black */ break; default: /* 15/16/24/32-bit */ idx_medium=4*((cfg.medium.r<<16)|(cfg.medium.g<<8)|cfg.medium.b); dark =4*((cfg.dark.r<<16)|(cfg.dark.g<<8)|cfg.dark.b); light =4*((cfg.light.r<<16)|(cfg.light.g<<8)|cfg.light.b); txt =4*((cfg.black.r<<16)|(cfg.black.g<<8)|cfg.black.b); } if(has_mouse) { int scrncol=light; switch(vga_getcolors()) { case 32768: scrncol=GET15BITCOLOUR(4*cfg.light.r,4*cfg.light.g,4*cfg.light.b); break; case 65536: scrncol=GET16BITCOLOUR(4*cfg.light.r,4*cfg.light.g,4*cfg.light.b); break; } mousecur_init(mouseblack,scrncol); restore_mouse_pos(); } }set_max_text_width(vga_getxdim()-70- fdlabelwidth*(replytype==MSGBOXTYPE_FILEDETAILS));high=70;if(replytype!=MSGBOXTYPE_FILEDETAILS) wide=vgatextsize(3,message);else { int f,num,len,maxlen; /* make the box a bit taller */ high+=210; for(f=0;f<7;f++) fdetailstr[f]=" "; /* split the message string into seven lines, and set width * to widest of them. String length doesn't mean anything; * it's the onscreen width we care about here. */ num=0; while((ptr=strrchr(message,'\n'))!=NULL) *ptr=0,num++; ptr=message;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -