term.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       term.c (6724B)
       ---
            1 /*
            2  * Draw and manage a text terminal on the screen,
            3  * before the window manager has taken over.
            4  */
            5 #include        "u.h"
            6 #include        "lib.h"
            7 #include        "mem.h"
            8 #include        "dat.h"
            9 #include        "fns.h"
           10 #include        "error.h"
           11 
           12 #define Image IMAGE
           13 #include        <draw.h>
           14 #include        <memdraw.h>
           15 #include        <cursor.h>
           16 #include        "screen.h"
           17 
           18 enum
           19 {
           20         Border = 4
           21 };
           22 
           23 static struct {
           24         Lock        lk;
           25         int printing;
           26         Memsubfont *font;
           27         int tabx;        /* width of tab */
           28         int spacex;        /* width of space */
           29         int xpos;
           30         Memimage *fg;        /* text color */
           31         Memimage *bg;        /* background color */
           32         Memimage *screen;        /* screen image - can change! */
           33         Memimage *grey;
           34         Rectangle flushr;        /* rectangle needs flushing */
           35         Rectangle text;        /* rectangle holding text */
           36         Rectangle maxtext;        /* total space for text */
           37         Rectangle line;        /* remainder of current output line */
           38 } term;
           39 
           40 static void termputs(char*, int);
           41 static void showkmesg(void);
           42 static void kickscreen(void);
           43 
           44 void
           45 terminit(int printing)
           46 {
           47         Memimage *grey;
           48 
           49         lock(&term.lk);
           50         _memimageinit();
           51         term.printing = printing;
           52         term.font = getmemdefont();
           53         term.fg = memblack;
           54         term.bg = memwhite;
           55         
           56         term.spacex = memsubfontwidth(term.font, " ").x;
           57         term.tabx = term.spacex * 8;
           58 
           59         /* a lot of work to get a grey color */
           60         grey = allocmemimage(Rect(0,0,1,1), CMAP8);
           61         grey->flags |= Frepl;
           62         grey->clipr = Rect(-100000, -100000, 100000, 100000);
           63         memfillcolor(grey, 0x770000FF);
           64         term.grey = grey;
           65 
           66         term.flushr = Rect(0, 0, 0, 0);
           67         /* x11 will call termreplacescreenimage when it is ready */
           68         unlock(&term.lk);
           69         
           70         /* maybe it already has */
           71         if(term.screen)
           72                 termreplacescreenimage(term.screen);
           73 
           74         /* If we're the output mechanism, set it up and kick off the screen. */
           75         if(printing)
           76                 screenputs = termputs;
           77         if(conf.monitor)
           78                 kickscreen();        /* make x11 ready */
           79 }
           80 
           81 static void
           82 addflush(Rectangle r)
           83 {
           84         if(term.flushr.min.x >= term.flushr.max.x)
           85                 term.flushr = r;
           86         else
           87                 combinerect(&term.flushr, r);
           88 }
           89 
           90 static void
           91 termcursor(int on)
           92 {
           93         Rectangle r;
           94 
           95         if(!term.printing)
           96                 return;
           97         r = term.line;
           98         r.max.x = r.min.x+2;
           99         if(on)
          100                 memimagedraw(term.screen, r, term.grey, ZP, memopaque, ZP, S);
          101         else
          102                 memimagedraw(term.screen, r, term.bg, ZP, memopaque, ZP, S);
          103         addflush(r);
          104 }
          105 
          106 static void
          107 _termreplacescreenimage(Memimage *m)
          108 {
          109         int h;
          110         Rectangle r, r0;
          111 
          112         if(term.bg == nil){
          113                 /* not yet init */
          114                 term.screen = m;
          115                 return;
          116         }
          117 
          118         /* white background */
          119         if(!mouse.open)
          120                 memimagedraw(m, m->r, term.bg, ZP, memopaque, ZP, S);
          121         
          122         /* grey heading: Plan 9 VX */
          123         r = m->r;
          124         h = term.font->height;
          125         r.max.y = r.min.y + Border + h + Border;
          126         if(!mouse.open){
          127                 memimagedraw(m, r, term.grey, ZP, memopaque, ZP, S);
          128                 memimagestring(m, addpt(r.min, Pt(Border, Border)),
          129                         memwhite, ZP, term.font, "Plan 9 VX");
          130         }
          131         r.min.y = r.max.y;
          132         r.max.y += 2;
          133         if(!mouse.open){
          134                 memimagedraw(m, r, memblack, ZP, memopaque, ZP, S);
          135         }
          136 
          137         /* text area */
          138         r.min.x += Border;
          139         r.max.x -= Border;
          140         r.min.y = r.max.y;
          141         r.max.y = m->r.max.y;
          142         r.max.y = r.min.y + Dy(r)/h*h;
          143         term.maxtext = r;
          144 
          145         /* occupied text area - just one blank line */
          146         r0 = r;
          147         r0.max.y = r0.min.y + h;
          148         term.text = r0;
          149         term.line = r0;
          150 
          151         /* ready to commit */
          152         term.screen = m;
          153         if(!mouse.open){
          154                 showkmesg();
          155                 termcursor(1);
          156                 flushmemscreen(m->r);
          157         }
          158 }
          159 
          160 void
          161 termreplacescreenimage(Memimage *m)
          162 {
          163         if(up){
          164                 drawqlock();
          165                 lock(&term.lk);
          166                 _termreplacescreenimage(m);
          167                 unlock(&term.lk);
          168                 drawqunlock();
          169                 return;
          170         }
          171         lock(&term.lk);
          172         _termreplacescreenimage(m);
          173         unlock(&term.lk);
          174 }
          175 
          176 void
          177 termredraw(void)
          178 {
          179         Memimage *m;
          180 
          181         if(!term.screen)
          182                 return;
          183 
          184         drawqlock();
          185         lock(&term.lk);
          186         m = term.screen;
          187         term.screen = nil;
          188         if(m)
          189                 _termreplacescreenimage(m);
          190         unlock(&term.lk);
          191         drawqunlock();
          192 }
          193 
          194 static void
          195 termscroll(void)
          196 {
          197         Rectangle r0, r1;
          198         int dy, h;
          199         
          200         dy = Dy(term.maxtext) / 2;
          201         h = term.font->height;
          202         dy = dy/h*h;
          203         if(dy < term.font->height)
          204                 dy = term.font->height;
          205         r0 = term.text;
          206         r1 = term.text;
          207         r0.max.y -= dy;
          208         r1.min.y += dy;
          209         memimagedraw(term.screen, r0, term.screen, r1.min,
          210                 memopaque, ZP, S);
          211         r1.min.y = r0.max.y;
          212         memimagedraw(term.screen, r1, term.bg, ZP, memopaque, ZP, S);
          213         addflush(r0);
          214         addflush(r1);
          215         term.text = r0;
          216 }
          217 
          218 static void
          219 termputc(Rune r)
          220 {
          221         int dx, n;
          222         Rectangle rect;
          223         char buf[UTFmax+1];
          224         Memsubfont *font;
          225         
          226         font = term.font;
          227 
          228         switch(r){
          229         case '\n':
          230                 if(term.text.max.y >= term.maxtext.max.y)
          231                         termscroll();
          232                 term.text.max.y += font->height;
          233                 /* fall through */
          234         case '\r':
          235                 term.line = term.text;
          236                 term.line.min.y = term.line.max.y - font->height;
          237                 break;
          238         case '\t':
          239                 dx = term.tabx - (term.line.min.x - term.text.min.x) % term.tabx;
          240                 if(term.line.min.x+dx >= term.line.max.x)
          241                         termputc('\n');
          242                 else{
          243                         /* white out the space, just because */
          244                         rect = term.line;
          245                         rect.max.x = rect.min.x + dx;
          246                         memimagedraw(term.screen, rect, term.bg, ZP, memopaque, ZP, S);
          247                         term.line.min.x += dx;
          248                         addflush(rect);
          249                 }
          250                 break;
          251         case '\b':
          252                 if(term.line.min.x <= term.text.min.x)
          253                         break;
          254                 /* white out the backspaced letter */
          255                 term.line.min.x -= term.spacex;
          256                 rect = term.line;
          257                 rect.max.x = rect.min.x + term.spacex;
          258                 memimagedraw(term.screen, rect, term.bg, ZP, memopaque, ZP, S);
          259                 addflush(rect);
          260                 break;
          261         default:
          262                 n = runetochar(buf, &r);
          263                 buf[n] = 0;
          264                 dx = memsubfontwidth(term.font, buf).x;
          265                 if(term.line.min.x+dx > term.line.max.x)
          266                         termputc('\n');
          267                 rect = term.line;
          268                 term.line.min.x += dx;
          269                 rect.max.x = term.line.min.x;
          270                 memimagedraw(term.screen, rect, term.bg, ZP, memopaque, ZP, S);
          271                 memimagestring(term.screen, rect.min, term.fg, ZP, term.font, buf);
          272                 addflush(rect);
          273                 break;
          274         }
          275 }
          276 
          277 static void
          278 _termputs(char *s, int n)
          279 {
          280         int i, locked;
          281         Rune r;
          282         int nb;
          283         char *p, *ep;
          284 
          285         if(term.screen == nil || !term.printing)
          286                 return;
          287         locked = 0;
          288         for(i=0; i<100; i++){
          289                 locked = drawcanqlock();
          290                 if(locked)
          291                         break;
          292                 microdelay(100);
          293         }
          294         if(!mouse.open)
          295                 termcursor(0);
          296         for(p=s, ep=s+n; p<ep; p+=nb){
          297                 nb = chartorune(&r, p);
          298                 if(nb <= 0){
          299                         nb = 1;
          300                         continue;
          301                 }
          302                 termputc(r);
          303         }
          304         if(!mouse.open)
          305                 termcursor(1);
          306         flushmemscreen(term.flushr);
          307         term.flushr = Rect(10000, 10000, -10000, -10000);
          308         if(locked)
          309                 drawqunlock();
          310 }
          311 
          312 static void
          313 termputs(char *s, int n)
          314 {
          315         lock(&term.lk);
          316         _termputs(s, n);
          317         unlock(&term.lk);
          318 }        
          319 
          320 static void
          321 showkmesg(void)
          322 {
          323         int n, nb;
          324         char buf[512], *p, *ep;
          325         Rune r;
          326 
          327         n = tailkmesg(buf, sizeof buf);
          328         if(n > 0){
          329                 if(n < sizeof buf || (p = memchr(buf, '\n', n)) == nil)
          330                         p = buf;
          331                 /* can't call termputs - drawqlock is held */
          332                 for(ep=p+n; p<ep; p+=nb){
          333                         nb = chartorune(&r, p);
          334                         if(nb <= 0){
          335                                 nb = 1;
          336                                 continue;
          337                         }
          338                         termputc(r);
          339                 }
          340         }
          341 }
          342 
          343 static void
          344 kickscreen(void)
          345 {
          346         Rectangle r;
          347         ulong chan;
          348         int depth;
          349         int width;
          350         int softscreen;
          351         void *x;
          352         
          353         attachscreen(&r, &chan, &depth, &width, &softscreen, &x);
          354 }
          355 
          356