added a new parameter for completion flags to input_new
[midnight-commander.git] / src / cons.handler.c
blobb08c2662dd0a938c832a5a36c84b78857aa79528
1 /* Client interface for General purpose Linux console save/restore server
2 Copyright (C) 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2006, 2007 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 #include <config.h>
21 #include <signal.h>
22 #include <stdio.h>
24 #include <sys/types.h>
25 #ifdef __FreeBSD__
26 # include <sys/consio.h>
27 # include <sys/ioctl.h>
28 #endif
29 #include <unistd.h>
31 #include "global.h"
32 #include "tty.h"
33 #include "cons.saver.h"
35 signed char console_flag = 0;
37 #ifdef __linux__
39 /* The cons saver can't have a pid of 1, used to prevent bunches of
40 * #ifdef linux */
42 int cons_saver_pid = 1;
43 static int pipefd1[2] = { -1, -1 };
44 static int pipefd2[2] = { -1, -1 };
46 static void
47 show_console_contents_linux (int starty, unsigned char begin_line,
48 unsigned char end_line)
50 unsigned char message = 0;
51 unsigned short bytes = 0;
52 int i;
54 /* Is tty console? */
55 if (!console_flag)
56 return;
57 /* Paranoid: Is the cons.saver still running? */
58 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)) {
59 cons_saver_pid = 0;
60 console_flag = 0;
61 return;
64 /* Send command to the console handler */
65 message = CONSOLE_CONTENTS;
66 write (pipefd1[1], &message, 1);
67 /* Check for outdated cons.saver */
68 read (pipefd2[0], &message, 1);
69 if (message != CONSOLE_CONTENTS)
70 return;
72 /* Send the range of lines that we want */
73 write (pipefd1[1], &begin_line, 1);
74 write (pipefd1[1], &end_line, 1);
75 /* Read the corresponding number of bytes */
76 read (pipefd2[0], &bytes, 2);
78 /* Read the bytes and output them */
79 for (i = 0; i < bytes; i++) {
80 if ((i % COLS) == 0)
81 move (starty + (i / COLS), 0);
82 read (pipefd2[0], &message, 1);
83 addch (message);
86 /* Read the value of the console_flag */
87 read (pipefd2[0], &message, 1);
90 static void
91 handle_console_linux (unsigned char action)
93 char *tty_name;
94 char *mc_conssaver;
95 int status;
97 switch (action) {
98 case CONSOLE_INIT:
99 /* Close old pipe ends in case it is the 2nd time we run cons.saver */
100 close (pipefd1[1]);
101 close (pipefd2[0]);
102 /* Create two pipes for communication */
103 pipe (pipefd1);
104 pipe (pipefd2);
105 /* Get the console saver running */
106 cons_saver_pid = fork ();
107 if (cons_saver_pid < 0) {
108 /* Cannot fork */
109 /* Delete pipes */
110 close (pipefd1[1]);
111 close (pipefd1[0]);
112 close (pipefd2[1]);
113 close (pipefd2[0]);
114 console_flag = 0;
115 } else if (cons_saver_pid > 0) {
116 /* Parent */
117 /* Close the extra pipe ends */
118 close (pipefd1[0]);
119 close (pipefd2[1]);
120 /* Was the child successful? */
121 read (pipefd2[0], &console_flag, 1);
122 if (!console_flag) {
123 close (pipefd1[1]);
124 close (pipefd2[0]);
125 waitpid (cons_saver_pid, &status, 0);
127 } else {
128 /* Child */
129 /* Close the extra pipe ends */
130 close (pipefd1[1]);
131 close (pipefd2[0]);
132 tty_name = ttyname (0);
133 /* Bind the pipe 0 to the standard input */
134 close (0);
135 dup (pipefd1[0]);
136 close (pipefd1[0]);
137 /* Bind the pipe 1 to the standard output */
138 close (1);
139 dup (pipefd2[1]);
140 close (pipefd2[1]);
141 /* Bind standard error to /dev/null */
142 close (2);
143 open ("/dev/null", O_WRONLY);
144 if (tty_name) {
145 /* Exec the console save/restore handler */
146 mc_conssaver = concat_dir_and_file (SAVERDIR, "cons.saver");
147 execl (mc_conssaver, "cons.saver", tty_name, (char *) NULL);
149 /* Console is not a tty or execl() failed */
150 console_flag = 0;
151 write (1, &console_flag, 1);
152 _exit (3);
153 } /* if (cons_saver_pid ...) */
154 break;
156 case CONSOLE_DONE:
157 case CONSOLE_SAVE:
158 case CONSOLE_RESTORE:
159 /* Is tty console? */
160 if (!console_flag)
161 return;
162 /* Paranoid: Is the cons.saver still running? */
163 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)) {
164 cons_saver_pid = 0;
165 console_flag = 0;
166 return;
168 /* Send command to the console handler */
169 write (pipefd1[1], &action, 1);
170 if (action != CONSOLE_DONE) {
171 /* Wait the console handler to do its job */
172 read (pipefd2[0], &console_flag, 1);
174 if (action == CONSOLE_DONE || !console_flag) {
175 /* We are done -> Let's clean up */
176 close (pipefd1[1]);
177 close (pipefd2[0]);
178 waitpid (cons_saver_pid, &status, 0);
179 console_flag = 0;
181 break;
185 #elif defined(__FreeBSD__)
188 * FreeBSD support copyright (C) 2003 Alexander Serkov <serkov@ukrpost.net>.
189 * Support for screenmaps by Max Khon <fjoe@FreeBSD.org>
192 #define FD_OUT 1
194 static struct scrshot screen_shot;
195 static struct vid_info screen_info;
197 static void
198 console_init (void)
200 if (console_flag)
201 return;
203 screen_info.size = sizeof (screen_info);
204 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1)
205 return;
207 memset (&screen_shot, 0, sizeof (screen_shot));
208 screen_shot.xsize = screen_info.mv_csz;
209 screen_shot.ysize = screen_info.mv_rsz;
210 if ((screen_shot.buf =
211 g_malloc (screen_info.mv_csz * screen_info.mv_rsz * 2)) == NULL)
212 return;
214 console_flag = 1;
217 static void
218 set_attr (unsigned attr)
221 * Convert color indices returned by SCRSHOT (red=4, green=2, blue=1)
222 * to indices for ANSI sequences (red=1, green=2, blue=4).
224 static const int color_map[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
225 int bc, tc;
227 tc = attr & 0xF;
228 bc = (attr >> 4) & 0xF;
230 printf ("\x1B[%d;%d;3%d;4%dm", (bc & 8) ? 5 : 25, (tc & 8) ? 1 : 22,
231 color_map[tc & 7], color_map[bc & 7]);
234 #define cursor_to(x, y) do { \
235 printf("\x1B[%d;%df", (y) + 1, (x) + 1); \
236 fflush(stdout); \
237 } while (0)
239 static void
240 console_restore (void)
242 int i, last;
244 if (!console_flag)
245 return;
247 cursor_to (0, 0);
249 /* restoring all content up to cursor position */
250 last = screen_info.mv_row * screen_info.mv_csz + screen_info.mv_col;
251 for (i = 0; i < last; ++i) {
252 set_attr ((screen_shot.buf[i] >> 8) & 0xFF);
253 putc (screen_shot.buf[i] & 0xFF, stdout);
256 /* restoring cursor color */
257 set_attr ((screen_shot.buf[last] >> 8) & 0xFF);
259 fflush (stdout);
262 static void
263 console_shutdown (void)
265 if (!console_flag)
266 return;
268 g_free (screen_shot.buf);
270 console_flag = 0;
273 static void
274 console_save (void)
276 int i;
277 scrmap_t map;
278 scrmap_t revmap;
280 if (!console_flag)
281 return;
283 /* screen_info.size is already set in console_init() */
284 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1) {
285 console_shutdown ();
286 return;
289 /* handle console resize */
290 if (screen_info.mv_csz != screen_shot.xsize
291 || screen_info.mv_rsz != screen_shot.ysize) {
292 console_shutdown ();
293 console_init ();
296 if (ioctl (FD_OUT, CONS_SCRSHOT, &screen_shot) == -1) {
297 console_shutdown ();
298 return;
301 if (ioctl (FD_OUT, GIO_SCRNMAP, &map) == -1) {
302 console_shutdown ();
303 return;
306 for (i = 0; i < 256; i++) {
307 char *p = memchr (map.scrmap, i, 256);
308 revmap.scrmap[i] = p ? p - map.scrmap : i;
311 for (i = 0; i < screen_shot.xsize * screen_shot.ysize; i++) {
312 screen_shot.buf[i] =
313 (screen_shot.buf[i] & 0xff00) | (unsigned char) revmap.
314 scrmap[screen_shot.buf[i] & 0xff];
318 static void
319 show_console_contents_freebsd (int starty, unsigned char begin_line,
320 unsigned char end_line)
322 int col, line;
323 char c;
325 if (!console_flag)
326 return;
328 for (line = begin_line; line <= end_line; line++) {
329 move (starty + line - begin_line, 0);
330 for (col = 0; col < min (COLS, screen_info.mv_csz); col++) {
331 c = screen_shot.buf[line * screen_info.mv_csz + col] & 0xFF;
332 addch (c);
337 static void
338 handle_console_freebsd (unsigned char action)
340 switch (action) {
341 case CONSOLE_INIT:
342 console_init ();
343 break;
345 case CONSOLE_DONE:
346 console_shutdown ();
347 break;
349 case CONSOLE_SAVE:
350 console_save ();
351 break;
353 case CONSOLE_RESTORE:
354 console_restore ();
355 break;
358 #endif /* __FreeBSD__ */
360 void
361 show_console_contents (int starty, unsigned char begin_line,
362 unsigned char end_line)
364 standend ();
366 if (look_for_rxvt_extensions ()) {
367 show_rxvt_contents (starty, begin_line, end_line);
368 return;
370 #ifdef __linux__
371 show_console_contents_linux (starty, begin_line, end_line);
372 #elif defined (__FreeBSD__)
373 show_console_contents_freebsd (starty, begin_line, end_line);
374 #else
375 console_flag = 0;
376 #endif
379 void
380 handle_console (unsigned char action)
382 (void) action;
384 if (look_for_rxvt_extensions ())
385 return;
387 #ifdef __linux__
388 handle_console_linux (action);
389 #elif defined (__FreeBSD__)
390 handle_console_freebsd (action);
391 #endif