/[hurd]/hurd/console/display.c
ViewVC logotype

Diff of /hurd/console/display.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by marcus, Sat Jun 8 23:33:04 2002 UTC revision 1.4 by marcus, Wed Jun 12 14:38:39 2002 UTC
# Line 25  Line 25 
25  #include <iconv.h>  #include <iconv.h>
26  #include <argp.h>  #include <argp.h>
27  #include <string.h>  #include <string.h>
28    #include <assert.h>
29    #include <error.h>
30    
31  #include <sys/io.h>  #include <sys/io.h>
 #include <sys/mman.h>  
32  #include <sys/fcntl.h>  #include <sys/fcntl.h>
33    #include <sys/mman.h>
34  #include <cthreads.h>  #include <cthreads.h>
35    
36    #include <hurd.h>
37    #include <hurd/pager.h>
38    
39  #ifndef __STDC_ISO_10646__  #ifndef __STDC_ISO_10646__
40  #error It is required that wchar_t is UCS-4.  #error It is required that wchar_t is UCS-4.
41  #endif  #endif
42    
43    #include "console.h"
44  #include "display.h"  #include "display.h"
45    
46    
 struct screen  
 {  
   /* A screen matrix, including the scroll back buffer.  */  
   wchar_t *matrix;  
   
   /* The size of the screen, in lines.  */  
   int lines;  
   
   /* The top most line of the screen in the video buffer.  */  
   int current_line;  
   
   /* Maximum number of lines scrolled back.  */  
   int scrolling_max;  
   
   int width;  
   int height;  
 };  
 typedef struct screen *screen_t;  
   
47  struct cursor  struct cursor
48  {  {
   /* The visibility of the cursor.  */  
   u_int32_t status;  
 #define CURSOR_INVISIBLE 1  
 #define CURSOR_STANDOUT 2  
   
   u_int32_t x;  
   u_int32_t y;  
49    u_int32_t saved_x;    u_int32_t saved_x;
50    u_int32_t saved_y;    u_int32_t saved_y;
51  };  };
# Line 128  struct attr Line 108  struct attr
108  };  };
109  typedef struct attr *attr_t;  typedef struct attr *attr_t;
110    
111    struct user_pager_info
112    {
113      display_t display;
114      struct pager *p;
115    };
116    
117  struct display  struct display
118  {  {
119    /* The lock for the virtual console display structure.  */    /* The lock for the virtual console display structure.  */
120    struct mutex lock;    struct mutex lock;
121    
   struct screen screen;  
   struct cursor cursor;  
   struct output output;  
   struct attr attr;  
   
122    /* Indicates if OWNER_ID is initialized.  */    /* Indicates if OWNER_ID is initialized.  */
123    int has_owner;    int has_owner;
124    /* Specifies the ID of the process that should receive the WINCH    /* Specifies the ID of the process that should receive the WINCH
125       signal for this virtual console.  */       signal for this virtual console.  */
126    int owner_id;    int owner_id;
127    
128      struct cursor cursor;
129      struct output output;
130      struct attr attr;
131      struct cons_display *user;
132    
133      struct user_pager_info *upi;  
134      memory_object_t memobj;
135      size_t memobj_size;
136  };  };
137    
138    
139    /* We need a separate bucket for the pager ports.  */
140    struct port_bucket *pager_bucket;
141    
142    mach_port_t
143    display_get_filemap (display_t display, vm_prot_t prot)
144    {
145      error_t err;
146    
147      /* Add a reference for each call, the caller will deallocate it.  */
148      err = mach_port_mod_refs (mach_task_self (), display->memobj,
149                                MACH_PORT_RIGHT_SEND, +1);
150      assert_perror (err);
151    
152      return display->memobj;
153    }
154    
155    /* Implement the pager_clear_user_data callback from the pager library. */
156    void
157    pager_clear_user_data (struct user_pager_info *upi)
158    {
159      free (upi);
160    }
161    
162    /* XXX This is not good enough.  We actually need to provide a backing
163       store.  */
164    error_t
165    pager_read_page (struct user_pager_info *pager, vm_offset_t page,
166                     vm_address_t *buf, int *writelock)
167    {
168      /* This is a read-only medium */
169      *writelock = 1;
170    
171      *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE,
172                                  MAP_ANON, 0, 0);
173      return 0;
174    }
175    
176    error_t
177    pager_write_page (struct user_pager_info *pager,
178                      vm_offset_t page,
179                      vm_address_t buf)
180    {
181      /* XXX Implement me.  */
182      assert (0);
183    }
184    
185    error_t
186    pager_unlock_page (struct user_pager_info *pager,
187                       vm_offset_t address)
188    {
189      return 0;
190    }
191    
192    /* Tell how big the file is. */
193    error_t
194    pager_report_extent (struct user_pager_info *upi,
195                         vm_address_t *offset,
196                         vm_size_t *size)
197    {
198      display_t display = upi->display;
199      *offset = 0;
200      *size = display->memobj_size;
201      return 0;
202    }
203    
204    void
205    pager_dropweak (struct user_pager_info *upi)
206    {
207    }
208    
209    /* A top-level function for the paging thread that just services paging
210       requests.  */
211    static void
212    service_paging_requests (any_t arg)
213    {
214      struct port_bucket *pager_bucket = arg;
215      for (;;)
216        ports_manage_port_operations_multithread (pager_bucket,
217                                                  pager_demuxer,
218                                                  1000 * 60 * 2,
219                                                  1000 * 60 * 10, 0);
220    }    
221    
222    
223  static error_t  static error_t
224  screen_init (screen_t screen)  user_create (display_t display, u_int32_t width, u_int32_t height,
225                 u_int32_t lines)
226  {  {
227    screen->width = 80;    error_t err;
228    screen->height = 25;    struct cons_display *user;
229    screen->lines = 25;   /* XXX For now.  */    display->memobj_size = round_page (sizeof (struct cons_display) +
230    screen->current_line = 0;                                     sizeof (u_int32_t) * width * lines);
231    screen->matrix = calloc (screen->lines * screen->width, sizeof (wchar_t));  
232    if (!screen->matrix)    display->upi = malloc (sizeof (struct user_pager_info));
233      return ENOMEM;    if (!display->upi)
234        return MACH_PORT_NULL;
235      display->upi->display = display;
236      /* 1 & MOCD correct? */
237      display->upi->p = pager_create (display->upi, pager_bucket,
238                                      1, MEMORY_OBJECT_COPY_DELAY);
239      if (display->upi->p == 0)
240        {
241          free (display->upi);
242          return errno;
243        }
244      display->memobj = pager_get_port (display->upi->p);
245      ports_port_deref (display->upi->p);
246    
247      mach_port_insert_right (mach_task_self (), display->memobj, display->memobj,
248                              MACH_MSG_TYPE_MAKE_SEND);
249    
250      err = vm_map (mach_task_self (),
251                    (vm_address_t *) &user, (vm_size_t) display->memobj_size,
252                    (vm_address_t) 0,
253                    1 /* ! (flags & MAP_FIXED) */,
254                    display->memobj, 0 /* (vm_offset_t) offset */,
255                    0 /* ! (flags & MAP_SHARED) */,
256                    VM_PROT_READ | VM_PROT_WRITE,
257                    VM_PROT_READ | VM_PROT_WRITE,
258                    VM_INHERIT_NONE);
259      if (err)
260        {
261          /* UPI will be cleaned up by libpager.  */
262          mach_port_deallocate (mach_task_self (), display->memobj);
263          return err;
264        }
265        
266      user->magic = CONS_MAGIC;
267      user->version = CONS_VERSION_MAJ << 16 | CONS_VERSION_AGE;
268      user->screen.width = width;
269      user->screen.height = height;
270      user->screen.lines = lines;
271      user->screen.cur_line = 0;
272      user->screen.scr_lines = 0;
273      user->screen.matrix = sizeof (struct cons_display) / sizeof (u_int32_t);
274      user->cursor.col = 0;
275      user->cursor.row = 0;
276      user->cursor.status = CONS_CURSOR_NORMAL;
277      wmemset (user->_matrix, L' ', user->screen.width * user->screen.lines);
278    
   wmemset (screen->matrix, L' ', screen->height * screen->width);  
279    /* XXX Set attribute flags.  */    /* XXX Set attribute flags.  */
280      display->user = user;
281    return 0;    return 0;
282  }  }
283    
284  static void  static void
285  screen_deinit (screen_t screen)  user_destroy (display_t display)
286  {  {
287    free (screen->matrix);    /* The pager will be deallocated by libpager.  */
288      mach_port_deallocate (mach_task_self (), display->memobj);
289  }  }
290    
291    
292    #define MATRIX_POS(user,x,y) ((user)->_matrix \
293        + (((user)->screen.cur_line + (y)) % (user)->screen.height) \
294        * (user)->screen.width + (x))
295    
296  static void  static void
297  screen_fill (screen_t screen, size_t x, size_t y, size_t w, size_t h,  screen_fill (display_t display, size_t x, size_t y, size_t w, size_t h,
298               wchar_t chr, char attr)               wchar_t chr, char attr)
299  {  {
300    wchar_t *matrixp = screen->matrix    struct cons_display *user = display->user;
301      + ((screen->current_line + y) % screen->height) * screen->width + x;    wchar_t *matrixp = MATRIX_POS (user, x, y);
302    
303    while (h--)    while (h--)
304      {      {
305        /* XXX Set attribute flags.  */        /* XXX Set attribute flags.  */
306        wmemset (matrixp, L' ', w);        wmemset (matrixp, L' ', w);
307        matrixp += screen->width;        matrixp += user->screen.width;
308      }      }
309    
310    /* XXX Flag screen change, but here?  */    /* XXX Flag screen change, but here or where else?  */
311  }  }
312    
313  static void  static void
314  screen_scroll_up (screen_t screen, size_t x, size_t y, size_t w, size_t h,  screen_scroll_up (display_t display, size_t x, size_t y, size_t w, size_t h,
315                    int amt, wchar_t chr, char attr)                    int amt, wchar_t chr, char attr)
316  {  {
317    wchar_t *matrixp = screen->matrix    struct cons_display *user = display->user;
318      + ((screen->current_line + y) % screen->height) * screen->width + x;    wchar_t *matrixp = MATRIX_POS (user, x, y);
319    
320    if (amt < 0)    if (amt < 0)
321      return;      return;
322    
323    while (h-- > amt)    while (h-- > amt)
324      {      {
325        wmemcpy (matrixp, matrixp + amt * screen->width, w);        wmemcpy (matrixp, matrixp + amt * user->screen.width, w);
326        matrixp += screen->width;        matrixp += user->screen.width;
327      }      }
328    screen_fill (screen, x, y, w, h, chr, attr);    screen_fill (display, x, y, w, h, chr, attr);
329  }  }
330    
331  static void  static void
332  screen_scroll_down (screen_t screen, size_t x, size_t y, size_t w, size_t h,  screen_scroll_down (display_t display, size_t x, size_t y, size_t w, size_t h,
333                      int amt, wchar_t chr, char attr)                      int amt, wchar_t chr, char attr)
334  {  {
335    wchar_t *matrixp = screen->matrix    struct cons_display *user = display->user;
336      + ((screen->current_line + y + h - 1) % screen->height)    wchar_t *matrixp = MATRIX_POS (user, x, y + h - 1);
     * screen->width + x;  
337    
338    if (amt < 0)    if (amt < 0)
339      return;      return;
340    
341    while (h-- > amt)    while (h-- > amt)
342      {      {
343        wmemcpy (matrixp, matrixp - amt * screen->width, w);        wmemcpy (matrixp, matrixp - amt * user->screen.width, w);
344        matrixp -= screen->width;        matrixp -= user->screen.width;
345      }      }
346    screen_fill (screen, x, y, w, h, chr, attr);    screen_fill (display, x, y, w, h, chr, attr);
347  }  }
348    
349  static void  static void
350  screen_scroll_left (screen_t screen, size_t x, size_t y, size_t w, size_t h,  screen_scroll_left (display_t display, size_t x, size_t y, size_t w, size_t h,
351                      int amt, wchar_t chr, char attr)                      int amt, wchar_t chr, char attr)
352  {  {
353      struct cons_display *user = display->user;
354      wchar_t *matrixp = MATRIX_POS (user, x, y);
355    int i;    int i;
   wchar_t *matrixp = screen->matrix  
     + ((screen->current_line + y) % screen->height) * screen->width + x;  
356    
357    if (amt < 0)    if (amt < 0)
358      return;      return;
# Line 238  screen_scroll_left (screen_t screen, siz Line 362  screen_scroll_left (screen_t screen, siz
362    for (i = 0; i < y + h; i++)    for (i = 0; i < y + h; i++)
363      {      {
364        wmemmove (matrixp, matrixp + amt, w - amt);        wmemmove (matrixp, matrixp + amt, w - amt);
365        matrixp += screen->width;        matrixp += user->screen.width;
366      }      }
367    screen_fill (screen, x + w - amt, y, amt, h, chr, attr);    screen_fill (display, x + w - amt, y, amt, h, chr, attr);
368  }  }
369    
370  static void  static void
371  screen_scroll_right (screen_t screen, size_t x, size_t y, size_t w, size_t h,  screen_scroll_right (display_t display, size_t x, size_t y, size_t w, size_t h,
372                       int amt, wchar_t chr, char attr)                       int amt, wchar_t chr, char attr)
373  {  {
374      struct cons_display *user = display->user;
375      wchar_t *matrixp = MATRIX_POS (user, x, y);
376    int i;    int i;
   wchar_t *matrixp = screen->matrix  
     + ((screen->current_line + y) % screen->height) * screen->width + x;  
377    
378    if (amt < 0)    if (amt < 0)
379      return;      return;
# Line 259  screen_scroll_right (screen_t screen, si Line 383  screen_scroll_right (screen_t screen, si
383    for (i = 0; i < y + h; i++)    for (i = 0; i < y + h; i++)
384      {      {
385        wmemmove (matrixp + amt, matrixp, w - amt);        wmemmove (matrixp + amt, matrixp, w - amt);
386        matrixp += screen->width;        matrixp += user->screen.width;
387      }      }
388    screen_fill (screen, x, y, amt, h, chr, attr);    screen_fill (display, x, y, amt, h, chr, attr);
389  }  }
390    
391    
# Line 289  output_deinit (output_t output) Line 413  output_deinit (output_t output)
413    
414    
415  static void  static void
416  handle_esc_bracket_hl (cursor_t cursor, int code, int flag)  handle_esc_bracket_hl (display_t display, int code, int flag)
417  {  {
418    switch (code)    switch (code)
419      {      {
420      case 34:      case 34:
421        /* Cursor standout: <cnorm>, <cvvis>.  */        /* Cursor standout: <cnorm>, <cvvis>.  */
422        if (flag)        if (flag)
423          cursor->status |= CURSOR_STANDOUT;          display->user->cursor.status = CONS_CURSOR_VERY_VISIBLE;
424        else        else
425          cursor->status &= ~CURSOR_STANDOUT;          display->user->cursor.status = CONS_CURSOR_NORMAL;
426        /* XXX Flag cursor status change.  */        /* XXX Flag cursor status change.  */
427        break;        break;
428      }      }
# Line 390  handle_esc_bracket_m (attr_t attr, int c Line 514  handle_esc_bracket_m (attr_t attr, int c
514  static void  static void
515  handle_esc_bracket (display_t display, char op)  handle_esc_bracket (display_t display, char op)
516  {  {
517      struct cons_display *user = display->user;
518    parse_t parse = &display->output.parse;    parse_t parse = &display->output.parse;
519    int i;    int i;
520    
521    static void limit_cursor (void)    static void limit_cursor (void)
522      {      {
523        if (display->cursor.x >= display->screen.width)        if (user->cursor.col >= user->screen.width)
524          display->cursor.x = display->screen.width - 1;          user->cursor.col = user->screen.width - 1;
525        else if (display->cursor.x < 0)        else if (user->cursor.col < 0)
526          display->cursor.x = 0;          user->cursor.col = 0;
527                
528        if (display->cursor.y >= display->screen.height)        if (user->cursor.row >= user->screen.height)
529          display->cursor.y = display->screen.height - 1;          user->cursor.row = user->screen.height - 1;
530        else if (display->cursor.y < 0)        else if (user->cursor.row < 0)
531          display->cursor.y = 0;          user->cursor.row = 0;
532    
533        /* XXX Flag cursor change.  */        /* XXX Flag cursor change.  */
534      }      }
# Line 413  handle_esc_bracket (display_t display, c Line 538  handle_esc_bracket (display_t display, c
538      case 'H':      case 'H':
539      case 'f':      case 'f':
540        /* Cursor position: <cup>.  */        /* Cursor position: <cup>.  */
541        display->cursor.x = parse->params[1] - 1;        user->cursor.col = parse->params[1] - 1;
542        display->cursor.y = parse->params[0] - 1;        user->cursor.row = parse->params[0] - 1;
543        limit_cursor ();        limit_cursor ();
544        break;        break;
545      case 'G':      case 'G':
546        /* Horizontal position: <hpa>.  */        /* Horizontal position: <hpa>.  */
547        display->cursor.x = parse->params[0] - 1;        user->cursor.col = parse->params[0] - 1;
548        limit_cursor ();        limit_cursor ();
549        break;        break;
550      case 'F':      case 'F':
551        /* Beginning of previous line.  */        /* Beginning of previous line.  */
552        display->cursor.x = 0;        user->cursor.col = 0;
553        /* fall through */        /* fall through */
554      case 'A':      case 'A':
555        /* Cursor up: <cuu>, <cuu1>.  */        /* Cursor up: <cuu>, <cuu1>.  */
556        display->cursor.y -= (parse->params[0] ?: 1);        user->cursor.row -= (parse->params[0] ?: 1);
557        limit_cursor ();        limit_cursor ();
558        break;        break;
559      case 'E':      case 'E':
560        /* Beginning of next line.  */        /* Beginning of next line.  */
561        display->cursor.x = 0;        user->cursor.col = 0;
562        /* Fall through.  */        /* Fall through.  */
563      case 'B':      case 'B':
564        /* Cursor down: <cud1>, <cud>.  */        /* Cursor down: <cud1>, <cud>.  */
565        display->cursor.y += (parse->params[0] ?: 1);        user->cursor.row += (parse->params[0] ?: 1);
566        limit_cursor ();        limit_cursor ();
567        break;        break;
568      case 'C':      case 'C':
569        /* Cursor right: <cuf1>, <cuf>.  */        /* Cursor right: <cuf1>, <cuf>.  */
570        display->cursor.x += (parse->params[0] ?: 1);        user->cursor.col += (parse->params[0] ?: 1);
571        limit_cursor ();        limit_cursor ();
572        break;        break;
573      case 'D':      case 'D':
574        /* Cursor left: <cub>, <cub1>.  */        /* Cursor left: <cub>, <cub1>.  */
575        display->cursor.x -= (parse->params[0] ?: 1);        user->cursor.col -= (parse->params[0] ?: 1);
576        limit_cursor ();        limit_cursor ();
577        break;        break;
578      case 's':      case 's':
579        /* Save cursor position: <sc>.  */        /* Save cursor position: <sc>.  */
580        display->cursor.saved_x = display->cursor.x;        display->cursor.saved_x = user->cursor.col;
581        display->cursor.saved_y = display->cursor.y;        display->cursor.saved_y = user->cursor.row;
582        break;        break;
583      case 'u':      case 'u':
584        /* Restore cursor position: <rc>.  */        /* Restore cursor position: <rc>.  */
585        display->cursor.x = display->cursor.saved_x;        user->cursor.col = display->cursor.saved_x;
586        display->cursor.y = display->cursor.saved_y;        user->cursor.row = display->cursor.saved_y;
587        /* In case the screen was larger before:  */        /* In case the screen was larger before:  */
588        limit_cursor ();        limit_cursor ();
589        break;        break;
590      case 'h':      case 'h':
591        /* Reset mode.  */        /* Reset mode.  */
592        for (i = 0; i < parse->nparams; i++)        for (i = 0; i < parse->nparams; i++)
593          handle_esc_bracket_hl (&display->cursor, parse->params[i], 0);          handle_esc_bracket_hl (display, parse->params[i], 0);
594        break;        break;
595      case 'l':      case 'l':
596        /* Set mode.  */        /* Set mode.  */
597        for (i = 0; i < parse->nparams; i++)        for (i = 0; i < parse->nparams; i++)
598          handle_esc_bracket_hl (&display->cursor, parse->params[i], 1);          handle_esc_bracket_hl (display, parse->params[i], 1);
599        break;        break;
600      case 'm':      case 'm':
601        for (i = 0; i < parse->nparams; i++)        for (i = 0; i < parse->nparams; i++)
# Line 481  handle_esc_bracket (display_t display, c Line 606  handle_esc_bracket (display_t display, c
606          {          {
607          case 0:          case 0:
608            /* Clear to end of screen: <ed>.  */            /* Clear to end of screen: <ed>.  */
609            screen_fill (&display->screen, display->cursor.x, display->cursor.y,            screen_fill (display, user->cursor.col, user->cursor.row,
610                         display->screen.width - display->cursor.x, 1, L' ',                         user->screen.width - user->cursor.col, 1, L' ',
611                         display->attr.current);                         display->attr.current);
612            screen_fill (&display->screen, 0, display->cursor.y + 1,            screen_fill (display, 0, user->cursor.row + 1,
613                         display->screen.width,                         user->screen.width,
614                         display->screen.height - display->cursor.y,                         user->screen.height - user->cursor.row,
615                          L' ', display->attr.current);                          L' ', display->attr.current);
616            break;            break;
617          case 1:          case 1:
618            /* Clear to beginning of screen.  */            /* Clear to beginning of screen.  */
619            screen_fill (&display->screen, 0, 0,            screen_fill (display, 0, 0,
620                         display->screen.width, display->cursor.y,                         user->screen.width, user->cursor.row,
621                         L' ', display->attr.current);                         L' ', display->attr.current);
622            screen_fill (&display->screen, 0, display->cursor.y,            screen_fill (display, 0, user->cursor.row,
623                         display->cursor.x + 1, 1,                         user->cursor.col + 1, 1,
624                         L' ', display->attr.current);                         L' ', display->attr.current);
625            break;            break;
626          case 2:          case 2:
627            /* Clear entire screen.  */            /* Clear entire screen.  */
628            screen_fill (&display->screen, 0, 0,            screen_fill (display, 0, 0,
629                         display->screen.width, display->screen.height,                         user->screen.width, user->screen.height,
630                         L' ', display->attr.current);                         L' ', display->attr.current);
631            break;            break;
632          }          }
# Line 511  handle_esc_bracket (display_t display, c Line 636  handle_esc_bracket (display_t display, c
636          {          {
637          case 0:          case 0:
638            /* Clear to end of line: <el>.  */            /* Clear to end of line: <el>.  */
639            screen_fill (&display->screen, display->cursor.x, display->cursor.y,            screen_fill (display, user->cursor.col, user->cursor.row,
640                         display->screen.width - display->cursor.x, 1,                         user->screen.width - user->cursor.col, 1,
641                         L' ', display->attr.current);                         L' ', display->attr.current);
642            break;            break;
643          case 1:          case 1:
644            /* Clear to beginning of line: <el1>.  */            /* Clear to beginning of line: <el1>.  */
645            screen_fill (&display->screen, 0, display->cursor.y,            screen_fill (display, 0, user->cursor.row,
646                         display->cursor.x + 1, 1,                         user->cursor.col + 1, 1,
647                         L' ', display->attr.current);                         L' ', display->attr.current);
648            break;            break;
649          case 2:          case 2:
650            /* Clear entire line.  */            /* Clear entire line.  */
651            screen_fill (&display->screen, 0, display->cursor.y,            screen_fill (display, 0, user->cursor.row,
652                         display->screen.width, 1,                         user->screen.width, 1,
653                         L' ', display->attr.current);                         L' ', display->attr.current);
654            break;            break;
655          }          }
656        break;        break;
657      case 'L':      case 'L':
658        /* Insert line(s): <il1>, <il>.  */        /* Insert line(s): <il1>, <il>.  */
659        screen_scroll_down (&display->screen, 0, display->cursor.y,        screen_scroll_down (display, 0, user->cursor.row,
660                            display->screen.width,                            user->screen.width,
661                            display->screen.height - display->cursor.y,                            user->screen.height - user->cursor.row,
662                            parse->params[0] ?: 1,                            parse->params[0] ?: 1,
663                            L' ', display->attr.current);                            L' ', display->attr.current);
664        break;        break;
665      case 'M':      case 'M':
666        /* Delete line(s): <dl1>, <dl>.  */        /* Delete line(s): <dl1>, <dl>.  */
667        screen_scroll_up (&display->screen, 0, display->cursor.y,        screen_scroll_up (display, 0, user->cursor.row,
668                          display->screen.width,                          user->screen.width,
669                          display->screen.height - display->cursor.y,                          user->screen.height - user->cursor.row,
670                          parse->params[0] ?: 1,                          parse->params[0] ?: 1,
671                          L' ', display->attr.current);                          L' ', display->attr.current);
672        break;        break;
673      case '@':      case '@':
674        /* Insert character(s): <ich1>, <ich>.  */        /* Insert character(s): <ich1>, <ich>.  */
675        screen_scroll_right (&display->screen, display->cursor.x,        screen_scroll_right (display, user->cursor.col,
676                             display->cursor.y,                             user->cursor.row,
677                             display->screen.width - display->cursor.x, 1,                             user->screen.width - user->cursor.col, 1,
678                             parse->params[0] ?: 1,                             parse->params[0] ?: 1,
679                             L' ', display->attr.current);                             L' ', display->attr.current);
680        break;        break;
681      case 'P':      case 'P':
682        /* Delete character(s): <dch1>, <dch>.  */        /* Delete character(s): <dch1>, <dch>.  */
683        screen_scroll_left (&display->screen, display->cursor.x,        screen_scroll_left (display, user->cursor.col,
684                            display->cursor.y,                            user->cursor.row,
685                            display->screen.width - display->cursor.x, 1,                            user->screen.width - user->cursor.col, 1,
686                            parse->params[0] ?: 1,                            parse->params[0] ?: 1,
687                            L' ', display->attr.current);                            L' ', display->attr.current);
688        break;        break;
689      case 'S':      case 'S':
690        /* Scroll up: <ind>, <indn>.  */        /* Scroll up: <ind>, <indn>.  */
691        screen_scroll_up (&display->screen, 0, 0,        screen_scroll_up (display, 0, 0,
692                          display->screen.width, display->screen.height,                          user->screen.width, user->screen.height,
693                          parse->params[0] ?: 1,                          parse->params[0] ?: 1,
694                          L' ', display->attr.current);                          L' ', display->attr.current);
695        break;        break;
696      case 'T':      case 'T':
697        /* Scroll down: <ri>, <rin>.  */        /* Scroll down: <ri>, <rin>.  */
698        screen_scroll_down (&display->screen, 0, 0,        screen_scroll_down (display, 0, 0,
699                            display->screen.width, display->screen.height,                            user->screen.width, user->screen.height,
700                            parse->params[0] ?: 1,                            parse->params[0] ?: 1,
701                            L' ', display->attr.current);                            L' ', display->attr.current);
702        break;        break;
703      case 'X':      case 'X':
704        /* Erase character(s): <ech>.  */        /* Erase character(s): <ech>.  */
705        screen_fill (&display->screen, display->cursor.x, display->cursor.y,        screen_fill (display, user->cursor.col, user->cursor.row,
706                     parse->params[0] ?: 1, 1,                     parse->params[0] ?: 1, 1,
707                     L' ', display->attr.current);                     L' ', display->attr.current);
708        break;        break;
# Line 592  handle_esc_bracket_question_hl (display_ Line 717  handle_esc_bracket_question_hl (display_
717      case 25:      case 25:
718        /* Cursor invisibility: <civis>, <cnorm>.  */        /* Cursor invisibility: <civis>, <cnorm>.  */
719        if (flag)        if (flag)
720          display->cursor.status |= CURSOR_INVISIBLE;          display->user->cursor.status = CONS_CURSOR_INVISIBLE;
721        else        else
722          display->cursor.status &= ~CURSOR_INVISIBLE;          display->user->cursor.status = CONS_CURSOR_NORMAL;
723        /* XXX Flag cursor status change.  */        /* XXX Flag cursor status change.  */
724        break;        break;
725      }      }
# Line 626  handle_esc_bracket_question (display_t d Line 751  handle_esc_bracket_question (display_t d
751  static void  static void
752  display_output_one (display_t display, wchar_t chr)  display_output_one (display_t display, wchar_t chr)
753  {  {
754      struct cons_display *user = display->user;
755    parse_t parse = &display->output.parse;    parse_t parse = &display->output.parse;
756    
757    void newline (void)    void newline (void)
758      {      {
759        if (display->cursor.y < display->screen.height - 1)        if (user->cursor.row < user->screen.height - 1)
760          {          {
761            display->cursor.y++;            user->cursor.row++;
762            /* XXX Flag cursor update.  */            /* XXX Flag cursor update.  */
763          }          }
764        else        else
765          {          {
766            display->screen.current_line++;            user->screen.cur_line++;
767            display->screen.current_line %= display->screen.lines;            user->screen.cur_line %= user->screen.lines;
768    
769            /* XXX Set attribute flags.  */            /* XXX Set attribute flags.  */
770            screen_fill (&display->screen, 0, display->screen.height - 1,            screen_fill (display, 0, user->screen.height - 1,
771                         display->screen.width, 1, L' ', display->screen.width);                         user->screen.width, 1, L' ', user->screen.width);
772            if (display->screen.scrolling_max <            if (user->screen.scr_lines <
773                display->screen.lines - display->screen.height)                user->screen.lines - user->screen.height)
774              display->screen.scrolling_max++;              user->screen.scr_lines++;
775            /* XXX Flag current line change.  */            /* XXX Flag current line change.  */
776            /* XXX Flag change of last line.  */            /* XXX Flag change of last line.  */
777            /* XXX Possibly flag change of length of scroll back buffer.  */            /* XXX Possibly flag change of length of scroll back buffer.  */
# Line 659  display_output_one (display_t display, w Line 785  display_output_one (display_t display, w
785          {          {
786          case L'\r':          case L'\r':
787            /* Carriage return: <cr>.  */            /* Carriage return: <cr>.  */
788            if (display->cursor.x)            if (user->cursor.col)
789              {              {
790                display->cursor.x = 0;                user->cursor.col = 0;
791                /* XXX Flag cursor update.  */                /* XXX Flag cursor update.  */
792              }              }
793            break;            break;
# Line 671  display_output_one (display_t display, w Line 797  display_output_one (display_t display, w
797            break;            break;
798          case L'\b':          case L'\b':
799            /* Cursor backward: <cub1>.  */            /* Cursor backward: <cub1>.  */
800            if (display->cursor.x > 0 || display->cursor.y > 0)            if (user->cursor.col > 0 || user->cursor.row > 0)
801              {              {
802                if (display->cursor.x > 0)                if (user->cursor.col > 0)
803                  display->cursor.x--;                  user->cursor.col--;
804                else                else
805                  {                  {
806                    /* XXX This implements the <bw> functionality.                    /* XXX This implements the <bw> functionality.
807                       The alternative is to cut off and set x to 0.  */                       The alternative is to cut off and set x to 0.  */
808                    display->cursor.x = display->screen.width - 1;                    user->cursor.col = user->screen.width - 1;
809                    display->cursor.y--;                    user->cursor.row--;
810                  }                  }
811                /* XXX Flag cursor update.  */                /* XXX Flag cursor update.  */
812              }              }
813            break;            break;
814          case L'\t':          case L'\t':
815            /* Horizontal tab: <ht> */            /* Horizontal tab: <ht> */
816            display->cursor.x = (display->cursor.x | 7) + 1;            user->cursor.col = (user->cursor.col | 7) + 1;
817            if (display->cursor.x >= display->screen.width)            if (user->cursor.col >= user->screen.width)
818              {              {
819                display->cursor.x = 0;                user->cursor.col = 0;
820                newline ();                newline ();
821              }              }
822            /* XXX Flag cursor update.  */            /* XXX Flag cursor update.  */
# Line 703  display_output_one (display_t display, w Line 829  display_output_one (display_t display, w
829            break;            break;
830          default:          default:
831            {            {
832              int line = (display->screen.current_line + display->cursor.y)              int line = (user->screen.cur_line + user->cursor.row)
833                % display->screen.lines;                % user->screen.lines;
834    
835              /* XXX Set attribute flags.  */              /* XXX Set attribute flags.  */
836              display->screen.matrix[line * display->screen.width              user->_matrix[line * user->screen.width
837                                     + display->cursor.x] = chr;                            + user->cursor.col] = chr;
838    
839              display->cursor.x++;              user->cursor.col++;
840              if (display->cursor.x == display->screen.width)              if (user->cursor.col == user->screen.width)
841                {                {
842                  display->cursor.x = 0;                  user->cursor.col = 0;
843                  newline ();                  newline ();
844                }                }
845            }            }
# Line 729  display_output_one (display_t display, w Line 855  display_output_one (display_t display, w
855            break;            break;
856          case L'c':          case L'c':
857            /* Clear screen and home cursor: <clear>.  */            /* Clear screen and home cursor: <clear>.  */
858            screen_fill (&display->screen, 0, 0,            screen_fill (display, 0, 0,
859                         display->screen.width, display->screen.height,                         user->screen.width, user->screen.height,
860                         L' ', display->attr.current);                         L' ', display->attr.current);
861            display->cursor.x = display->cursor.y = 0;            user->cursor.col = user->cursor.row = 0;
862            /* XXX Flag cursor change.  */            /* XXX Flag cursor change.  */
863            parse->state = STATE_NORMAL;            parse->state = STATE_NORMAL;
864            break;            break;
# Line 818  display_output_some (display_t display, Line 944  display_output_some (display_t display,
944    return err;    return err;
945  }  }
946    
947    void
948    display_init (void)
949    {
950      /* Create the pager bucket, and start to serve paging requests.  */
951      pager_bucket = ports_create_bucket ();
952      if (! pager_bucket)
953        error (5, errno, "Cannot create pager bucket");
954    
955      /* Make a thread to service paging requests.  */
956      cthread_detach (cthread_fork ((cthread_fn_t) service_paging_requests,
957                                    (any_t)pager_bucket));
958    }
959    
960  /* Create a new virtual console display, with the system encoding  /* Create a new virtual console display, with the system encoding
961     being ENCODING.  */     being ENCODING.  */
962  error_t  error_t
# Line 825  display_create (display_t *r_display, co Line 964  display_create (display_t *r_display, co
964  {  {
965    error_t err = 0;    error_t err = 0;
966    display_t display;    display_t display;
967      int width = 80;
968      int height = 25;
969      int lines = 25;       /* XXX For now.  */
970    
971    *r_display = NULL;    *r_display = NULL;
972    display = calloc (1, sizeof *display);    display = calloc (1, sizeof *display);
# Line 832  display_create (display_t *r_display, co Line 974  display_create (display_t *r_display, co
974      return ENOMEM;      return ENOMEM;
975    
976    mutex_init (&display->lock);    mutex_init (&display->lock);
977    err = screen_init (&display->screen);    err = user_create (display, width, height, lines);
978    if (err)    if (err)
979      {      {
980        free (display);        free (display);
# Line 842  display_create (display_t *r_display, co Line 984  display_create (display_t *r_display, co
984    err = output_init (&display->output, encoding);    err = output_init (&display->output, encoding);
985    if (err)    if (err)
986      {      {
987        screen_deinit (&display->screen);        user_destroy (display);
988        free (display);        free (display);
989      }      }
990    *r_display = display;    *r_display = display;
# Line 855  void Line 997  void
997  display_destroy (display_t display)  display_destroy (display_t display)
998  {  {
999    output_deinit (&display->output);    output_deinit (&display->output);
1000    screen_deinit (&display->screen);    user_destroy (display);
1001    free (display);    free (display);
1002  }  }
1003    
# Line 865  void Line 1007  void
1007  display_getsize (display_t display, struct winsize *winsize)  display_getsize (display_t display, struct winsize *winsize)
1008  {  {
1009    mutex_lock (&display->lock);    mutex_lock (&display->lock);
1010    winsize->ws_row = display->screen.height;    winsize->ws_row = display->user->screen.height;
1011    winsize->ws_col = display->screen.width;    winsize->ws_col = display->user->screen.width;
1012    winsize->ws_xpixel = 0;    winsize->ws_xpixel = 0;
1013    winsize->ws_ypixel = 0;    winsize->ws_ypixel = 0;
1014    mutex_unlock (&display->lock);    mutex_unlock (&display->lock);
# Line 1003  display_output (display_t display, int n Line 1145  display_output (display_t display, int n
1145    return amount;    return amount;
1146  }  }
1147    
1148  ssize_t display_read (display_t display, int nonblock, off_t off,  ssize_t
1149                        char *data, size_t len)  display_read (display_t display, int nonblock, off_t off,
1150                  char *data, size_t len)
1151  {  {
   u_int32_t metadata[8];  
   size_t metadatalen = sizeof (metadata);  
   ssize_t written = 0;  
   
1152    mutex_lock (&display->lock);    mutex_lock (&display->lock);
1153    metadata[0] = display->screen.width;    memcpy (data, ((char *) display->user) + off, len);
   metadata[1] = display->screen.height;  
   metadata[2] = display->screen.lines;  
   metadata[3] = display->screen.current_line;  
   metadata[4] = display->screen.scrolling_max;  
   metadata[5] = display->cursor.x;  
   metadata[6] = display->cursor.y;  
   metadata[7] = display->cursor.status;  
     
   if (off >= 0 && off < metadatalen)  
     {  
       int part_len = len;  
   
       if (part_len > metadatalen)  
         part_len = metadatalen;  
       memcpy (data, (char *) metadata + off, part_len);  
       data += part_len;  
       len -= part_len;  
       written += part_len;  
     }  
   off -= metadatalen;  
   if (off < 0)  
     off = 0;  
     
   if (off + len > 2000 * sizeof(wchar_t))  
     len = 2000 * sizeof(wchar_t) - off;  
   memcpy (data, (char *) display->screen.matrix + off, len);  
1154    mutex_unlock (&display->lock);    mutex_unlock (&display->lock);
1155    return written + len;    return len;
1156  }  }
1157    
1158  /* Resume the output on the display DISPLAY.  */  /* Resume the output on the display DISPLAY.  */

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26