From 9cc0d6d3f8a89f35ddea92e30bdc2822c4164358 Mon Sep 17 00:00:00 2001
From: Marcus Brinkmann <marcus@gnu.org>
Date: Thu, 22 Aug 2002 19:24:19 +0000
Subject: libcons/ 2002-08-22  Marcus Brinkmann  <marcus@gnu.org>

	* demuxer.c, init-init.c, init-loop.c, opts-version.c,
	extra-version.c, dir-changed.c, file-changed.c,
	opts-std-startup.c, cons-lookup.c, cons-switch.c, vcons-remove.c,
	vcons-add.c, vcons-open.c, vcons-close.c, vcons-refresh.c, priv.h,
	mutations.h, cons.h: New files.
---
 libcons/file-changed.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 266 insertions(+)
 create mode 100644 libcons/file-changed.c

(limited to 'libcons/file-changed.c')

diff --git a/libcons/file-changed.c b/libcons/file-changed.c
new file mode 100644
index 00000000..ff51fa29
--- /dev/null
+++ b/libcons/file-changed.c
@@ -0,0 +1,266 @@
+/* file-changed.c - Handling file changed notifications.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   Written by Marcus Brinkmann.
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+#include <mach.h>
+#include <errno.h>
+
+#include "cons.h"
+#include "fs_notify_S.h"
+
+kern_return_t
+cons_S_file_changed (cons_notify_t notify, natural_t tickno,
+		     file_changed_type_t change,
+		     off_t start, off_t end)
+{
+  error_t err = 0;
+  vcons_t vcons;
+
+  if (!notify || !notify->vcons)
+    return EOPNOTSUPP;
+
+  vcons = notify->vcons;
+
+  mutex_lock (&vcons->lock);
+  switch (change)
+    {
+    case FILE_CHANGED_NULL:
+      /* Always sent first for sync.  */
+      cons_vcons_refresh (vcons);
+      break;
+    case FILE_CHANGED_WRITE:
+      /* File data has been written.  */
+      while (vcons->state.changes.written < vcons->display->changes.written)
+	{
+	  cons_change_t change;
+	  
+	  if (vcons->display->changes.written - vcons->state.changes.written
+	      > vcons->cons->slack)
+	    {
+	      cons_vcons_refresh (vcons);
+	      continue;
+	    }
+	  change = vcons->state.changes.buffer[vcons->state.changes.written
+					       % vcons->state.changes.length];
+	  if (vcons->display->changes.written - vcons->state.changes.written
+	      > vcons->state.changes.length - 1)
+	    {
+	      /* While we were reading the entry, the server might
+		 have overwritten it.  */
+	      cons_vcons_refresh (vcons);
+	      continue;
+	    }
+	  vcons->state.changes.written++;
+
+	  if (change.what.not_matrix)
+	    {
+	      if (change.what.cursor_pos)
+		{
+		  vcons->state.cursor.col = vcons->display->cursor.col;
+		  vcons->state.cursor.row = vcons->display->cursor.row;
+		  cons_vcons_set_cursor_pos (vcons, vcons->state.cursor.col,
+					     vcons->state.cursor.row);
+		  cons_vcons_update (vcons);
+		}
+	      if (change.what.cursor_status)
+		{
+		  vcons->state.cursor.status = vcons->display->cursor.status;
+		  cons_vcons_set_cursor_status (vcons,
+						vcons->state.cursor.status);
+		  cons_vcons_update (vcons);
+		}
+	      if (change.what.screen_cur_line)
+		{
+		  off_t size = vcons->state.screen.width
+		    * vcons->state.screen.lines;
+		  off_t vis_start;
+		  uint32_t new_cur_line;
+		  int scrolling;
+		  off_t start;
+		  off_t end;
+		  
+		  new_cur_line = vcons->display->screen.cur_line;
+		  scrolling = new_cur_line - vcons->state.screen.cur_line;
+		  if (scrolling < 0)
+		    scrolling += vcons->state.screen.lines;
+		  cons_vcons_scroll (vcons, scrolling);
+		  vis_start = vcons->state.screen.width * new_cur_line;
+		  start = ((new_cur_line + vcons->state.screen.height
+			    - scrolling) * vcons->state.screen.width) % size;
+		  end = start + scrolling * vcons->state.screen.width - 1;
+		  cons_vcons_write (vcons, vcons->state.screen.matrix + start,
+				    end < size
+				    ? end - start + 1 
+				    : size - start,
+				    (start - vis_start)
+				    % vcons->state.screen.width,
+				    (start - vis_start)
+				    / vcons->state.screen.width);
+		  if (end >= size)
+		    cons_vcons_write (vcons,
+				      vcons->state.screen.matrix,
+				      end - size + 1,
+				      (size - vis_start)
+				      % vcons->state.screen.width,
+				      (size - vis_start)
+				      / vcons->state.screen.width);
+		  cons_vcons_update (vcons);
+		  vcons->state.screen.cur_line = new_cur_line;
+		}
+	      if (change.what.screen_scr_lines)
+		{
+		  vcons->state.screen.scr_lines
+		    = vcons->display->screen.scr_lines;
+		}
+	      if (change.what.bell_audible)
+		{
+		  while (vcons->state.bell.audible
+			 < vcons->display->bell.audible)
+		    {
+		      cons_vcons_beep (vcons);
+		      vcons->state.bell.audible++;
+		    }
+		}
+	      if (change.what.bell_visible)
+		{
+		  while (vcons->state.bell.visible
+			 < vcons->display->bell.visible)
+		    {
+		      cons_vcons_flash (vcons);
+		      vcons->state.bell.visible++;
+		    }
+		}
+	    }
+	  else
+	    {
+	      /* For clipping.  */
+	      off_t size = vcons->state.screen.width*vcons->state.screen.lines;
+	      off_t rotate = vcons->state.screen.width
+		* vcons->state.screen.cur_line;
+	      off_t vis_end = vcons->state.screen.height
+		* vcons->state.screen.width - 1;
+	      off_t end2 = -1;
+	      off_t start_rel = 0;    /* start relative to visible start.  */
+	      off_t start = change.matrix.start;
+	      off_t end = change.matrix.end;
+
+	      /* Rotate the buffer.  */
+	      start -= rotate;
+	      if (start < 0)
+		start += size;
+	      end -= rotate;
+	      if (end < 0)
+		end += size;
+	      
+	      /* Find the intersection.  */
+	      if (start > vis_end)
+		{
+		  if (end < start)
+		    {
+		      start = 0;
+		      if (vis_end < end)
+			end = vis_end;
+		    }
+		  else
+		    start = -1;
+		}
+	      else
+		{
+		  if (end >= start)
+		    {
+		      if (end > vis_end)
+			end = vis_end;
+		    }
+		  else
+		    {
+		      end2 = end;
+		      end = vis_end;
+		    }
+		}
+	      /* We now have three cases: No intersection if start ==
+		 -1, one intersection [start;end] if end2 == -1, and
+		 two intersections [start;end] and [0;end2] if end2 !=
+		 -1.  However, we still have to undo the buffer
+		 rotation.  */
+	      if (start != -1)
+		{
+		  start_rel = start;
+		  start += rotate;
+		  if (start >= size)
+		    start -= size;
+		  end += rotate;
+		  if (end >= size)
+		    end -= size;
+		  if (start > end)
+		    end += size;
+		}
+	      if (end2 != -1)
+		/* The interval should be [vis_start:end2].  */
+		end2 += rotate;
+	      
+	      if (start != -1)
+		{
+		  cons_vcons_write (vcons, vcons->state.screen.matrix + start,
+				    end < size
+				    ? end - start + 1
+				    : size - start,
+				    start_rel % vcons->state.screen.width,
+				    start_rel / vcons->state.screen.width);
+		  if (end >= size)
+		    cons_vcons_write (vcons, vcons->state.screen.matrix,
+				      end - size + 1,
+				      (size - rotate)
+				      % vcons->state.screen.width,
+				      (size - rotate)
+				      / vcons->state.screen.width);
+		  if (end2 != -1)
+		    {
+		      cons_vcons_write (vcons,
+					vcons->state.screen.matrix + rotate,
+					end2 < size
+					? end2 - rotate + 1
+					: size - rotate,
+					0, 0);
+		      if (end2 >= size)
+			cons_vcons_write (vcons, vcons->state.screen.matrix,
+					  end2 - size + 1,
+					  (size - rotate)
+					  % vcons->state.screen.width,
+					  (size - rotate)
+					  / vcons->state.screen.width);
+		    }
+		  cons_vcons_update (vcons);
+		}
+	    }
+	}
+      break;
+    case FILE_CHANGED_EXTEND:
+      /* File has grown.  */
+    case FILE_CHANGED_TRUNCATE:
+      /* File has been truncated.  */
+    case FILE_CHANGED_META:
+      /* Stat information has changed, and none of the previous three
+	 apply.  Not sent for changes in node times.  */
+    default:
+      err = EINVAL;
+    };
+
+  mutex_unlock (&vcons->lock);
+  return err;
+}
-- 
cgit v1.2.3