Updated italian translation
[midnight-commander.git] / src / cons.handler.c
blob39c88b545c2547d99590305e4e22a27b23b07c0d
1 /* Client interface for General purpose Linux console save/restore server
2 Copyright (C) 1994 Janne Kukonlehto <jtklehto@stekt.oulu.fi>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 #include <config.h>
20 #ifdef HAVE_UNISTD_H
21 # include <unistd.h>
22 #endif
23 #include <sys/types.h>
24 #include <signal.h>
25 #include <stdio.h>
27 #ifdef __FreeBSD__
28 #include <sys/consio.h>
29 #include <sys/ioctl.h>
30 #endif /* __FreeBSD__ */
32 #include "global.h"
33 #include "tty.h"
34 #include "cons.saver.h"
36 signed char console_flag = 0;
38 #ifdef __linux__
40 /* The cons saver can't have a pid of 1, used to prevent bunches of
41 * #ifdef linux */
43 int cons_saver_pid = 1;
44 static int pipefd1[2] = { -1, -1 };
45 static int pipefd2[2] = { -1, -1 };
47 static void
48 show_console_contents_linux (int starty, unsigned char begin_line,
49 unsigned char end_line)
51 unsigned char message = 0;
52 unsigned short bytes = 0;
53 int i;
55 /* Is tty console? */
56 if (!console_flag)
57 return;
58 /* Paranoid: Is the cons.saver still running? */
59 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)) {
60 cons_saver_pid = 0;
61 console_flag = 0;
62 return;
65 /* Send command to the console handler */
66 message = CONSOLE_CONTENTS;
67 write (pipefd1[1], &message, 1);
68 /* Check for outdated cons.saver */
69 read (pipefd2[0], &message, 1);
70 if (message != CONSOLE_CONTENTS)
71 return;
73 /* Send the range of lines that we want */
74 write (pipefd1[1], &begin_line, 1);
75 write (pipefd1[1], &end_line, 1);
76 /* Read the corresponding number of bytes */
77 read (pipefd2[0], &bytes, 2);
79 /* Read the bytes and output them */
80 for (i = 0; i < bytes; i++) {
81 if ((i % COLS) == 0)
82 move (starty + (i / COLS), 0);
83 read (pipefd2[0], &message, 1);
84 addch (message);
87 /* Read the value of the console_flag */
88 read (pipefd2[0], &message, 1);
91 static void
92 handle_console_linux (unsigned char action)
94 char *tty_name;
95 char *mc_conssaver;
96 int status;
98 switch (action) {
99 case CONSOLE_INIT:
100 /* Close old pipe ends in case it is the 2nd time we run cons.saver */
101 close (pipefd1[1]);
102 close (pipefd2[0]);
103 /* Create two pipes for communication */
104 pipe (pipefd1);
105 pipe (pipefd2);
106 /* Get the console saver running */
107 cons_saver_pid = fork ();
108 if (cons_saver_pid < 0) {
109 /* Cannot fork */
110 /* Delete pipes */
111 close (pipefd1[1]);
112 close (pipefd1[0]);
113 close (pipefd2[1]);
114 close (pipefd2[0]);
115 console_flag = 0;
116 } else if (cons_saver_pid > 0) {
117 /* Parent */
118 /* Close the extra pipe ends */
119 close (pipefd1[0]);
120 close (pipefd2[1]);
121 /* Was the child successful? */
122 read (pipefd2[0], &console_flag, 1);
123 if (!console_flag) {
124 close (pipefd1[1]);
125 close (pipefd2[0]);
126 waitpid (cons_saver_pid, &status, 0);
128 } else {
129 /* Child */
130 /* Close the extra pipe ends */
131 close (pipefd1[1]);
132 close (pipefd2[0]);
133 tty_name = ttyname (0);
134 /* Bind the pipe 0 to the standard input */
135 close (0);
136 dup (pipefd1[0]);
137 close (pipefd1[0]);
138 /* Bind the pipe 1 to the standard output */
139 close (1);
140 dup (pipefd2[1]);
141 close (pipefd2[1]);
142 /* Bind standard error to /dev/null */
143 close (2);
144 open ("/dev/null", O_WRONLY);
145 if (tty_name) {
146 /* Exec the console save/restore handler */
147 mc_conssaver = concat_dir_and_file (LIBDIR, "cons.saver");
148 execl (mc_conssaver, "cons.saver", tty_name, NULL);
150 /* Console is not a tty or execl() failed */
151 console_flag = 0;
152 write (1, &console_flag, 1);
153 close (1);
154 close (0);
155 _exit (3);
156 } /* if (cons_saver_pid ...) */
157 break;
159 case CONSOLE_DONE:
160 case CONSOLE_SAVE:
161 case CONSOLE_RESTORE:
162 /* Is tty console? */
163 if (!console_flag)
164 return;
165 /* Paranoid: Is the cons.saver still running? */
166 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)) {
167 cons_saver_pid = 0;
168 console_flag = 0;
169 return;
171 /* Send command to the console handler */
172 write (pipefd1[1], &action, 1);
173 if (action != CONSOLE_DONE) {
174 /* Wait the console handler to do its job */
175 read (pipefd2[0], &console_flag, 1);
177 if (action == CONSOLE_DONE || !console_flag) {
178 /* We are done -> Let's clean up */
179 close (pipefd1[1]);
180 close (pipefd2[0]);
181 waitpid (cons_saver_pid, &status, 0);
182 console_flag = 0;
184 break;
188 #elif defined(__FreeBSD__)
191 * FreeBSD support copyright (C) 2003 Alexander Serkov <serkov@ukrpost.net>.
192 * Support for screenmaps by Max Khon <fjoe@FreeBSD.org>
195 #define FD_OUT 1
197 static struct scrshot screen_shot;
198 static struct vid_info screen_info;
200 static void
201 console_init (void)
203 if (console_flag)
204 return;
206 screen_info.size = sizeof (screen_info);
207 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1)
208 return;
210 memset (&screen_shot, 0, sizeof (screen_shot));
211 screen_shot.xsize = screen_info.mv_csz;
212 screen_shot.ysize = screen_info.mv_rsz;
213 if ((screen_shot.buf =
214 g_malloc (screen_info.mv_csz * screen_info.mv_rsz * 2)) == NULL)
215 return;
217 console_flag = 1;
220 static void
221 set_attr (unsigned attr)
224 * Convert color indices returned by SCRSHOT (red=4, green=2, blue=1)
225 * to indices for ANSI sequences (red=1, green=2, blue=4).
227 static const int color_map[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
228 int bc, tc;
230 tc = attr & 0xF;
231 bc = (attr >> 4) & 0xF;
233 printf ("\x1B[%d;%d;3%d;4%dm", (bc & 8) ? 5 : 25, (tc & 8) ? 1 : 22,
234 color_map[tc & 7], color_map[bc & 7]);
237 #define cursor_to(x, y) do { \
238 printf("\x1B[%d;%df", (y) + 1, (x) + 1); \
239 fflush(stdout); \
240 } while (0)
242 static void
243 console_restore (void)
245 int i, last;
247 if (!console_flag)
248 return;
250 cursor_to (0, 0);
252 /* restoring all content up to cursor position */
253 last = screen_info.mv_row * screen_info.mv_csz + screen_info.mv_col;
254 for (i = 0; i < last; ++i) {
255 set_attr ((screen_shot.buf[i] >> 8) & 0xFF);
256 putc (screen_shot.buf[i] & 0xFF, stdout);
259 /* restoring cursor color */
260 set_attr ((screen_shot.buf[last] >> 8) & 0xFF);
262 fflush (stdout);
265 static void
266 console_shutdown (void)
268 if (!console_flag)
269 return;
271 g_free (screen_shot.buf);
273 console_flag = 0;
276 static void
277 console_save (void)
279 int i;
280 scrmap_t map;
281 scrmap_t revmap;
283 if (!console_flag)
284 return;
286 /* screen_info.size is already set in console_init() */
287 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1) {
288 console_shutdown ();
289 return;
292 /* handle console resize */
293 if (screen_info.mv_csz != screen_shot.xsize
294 || screen_info.mv_rsz != screen_shot.ysize) {
295 console_shutdown ();
296 console_init ();
299 if (ioctl (FD_OUT, CONS_SCRSHOT, &screen_shot) == -1) {
300 console_shutdown ();
301 return;
304 if (ioctl (FD_OUT, GIO_SCRNMAP, &map) == -1) {
305 console_shutdown ();
306 return;
309 for (i = 0; i < 256; i++) {
310 char *p = memchr (map.scrmap, i, 256);
311 revmap.scrmap[i] = p ? p - map.scrmap : i;
314 for (i = 0; i < screen_shot.xsize * screen_shot.ysize; i++) {
315 screen_shot.buf[i] =
316 (screen_shot.buf[i] & 0xff00) | (unsigned char) revmap.
317 scrmap[screen_shot.buf[i] & 0xff];
321 static void
322 show_console_contents_freebsd (int starty, unsigned char begin_line,
323 unsigned char end_line)
325 int col, line;
326 char c;
328 if (!console_flag)
329 return;
331 for (line = begin_line; line <= end_line; line++) {
332 move (starty + line - begin_line, 0);
333 for (col = 0; col < min (COLS, screen_info.mv_csz); col++) {
334 c = screen_shot.buf[line * screen_info.mv_csz + col] & 0xFF;
335 addch (c);
340 static void
341 handle_console_freebsd (unsigned char action)
343 switch (action) {
344 case CONSOLE_INIT:
345 console_init ();
346 break;
348 case CONSOLE_DONE:
349 console_shutdown ();
350 break;
352 case CONSOLE_SAVE:
353 console_save ();
354 break;
356 case CONSOLE_RESTORE:
357 console_restore ();
358 break;
361 #endif /* __FreeBSD__ */
363 void
364 show_console_contents (int starty, unsigned char begin_line,
365 unsigned char end_line)
367 standend ();
369 if (look_for_rxvt_extensions ()) {
370 show_rxvt_contents (starty, begin_line, end_line);
371 return;
373 #ifdef __linux__
374 show_console_contents_linux (starty, begin_line, end_line);
375 #elif defined (__FreeBSD__)
376 show_console_contents_freebsd (starty, begin_line, end_line);
377 #else
378 console_flag = 0;
379 #endif
382 void
383 handle_console (unsigned char action)
385 if (look_for_rxvt_extensions ())
386 return;
388 #ifdef __linux__
389 handle_console_linux (action);
390 #elif defined (__FreeBSD__)
391 handle_console_freebsd (action);
392 #endif