mc/src/screen.c

2441 lines
58 KiB
C
Raw Normal View History

1998-02-27 07:54:42 +03:00
/* Panel managing.
Copyright (C) 1994, 1995 Miguel de Icaza.
1998-02-27 07:54:42 +03:00
This program 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 of the License, or
(at your option) any later version.
1998-02-27 07:54:42 +03:00
This program 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.
Written by: 1995 Miguel de Icaza
1997, 1999 Timur Bakeyev
1998-02-27 07:54:42 +03:00
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-1307, USA. */
1998-02-27 07:54:42 +03:00
#include <config.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h> /* For chdir(), readlink() and getwd()/getcwd() */
#endif
1998-02-27 07:54:42 +03:00
#include "global.h"
#include "tty.h"
1998-02-27 07:54:42 +03:00
#include "dir.h"
#include "panel.h"
#include "color.h"
#include "tree.h"
#include "win.h"
#include "ext.h" /* regexp_command */
#include "mouse.h" /* For Gpm_Event */
#include "layout.h" /* Most layout variables are here */
#include "wtools.h" /* for message (...) */
1998-02-27 07:54:42 +03:00
#include "cmd.h"
#include "key.h" /* XCTRL and ALT macros */
#include "setup.h" /* For loading/saving panel options */
#include "user.h"
#include "profile.h"
#include "execute.h"
1998-02-27 07:54:42 +03:00
#include "widget.h"
#include "menu.h" /* menubar_visible */
#define WANT_WIDGETS
#include "main.h" /* the_menubar */
1998-02-27 07:54:42 +03:00
#define ELEMENTS(arr) ( sizeof(arr) / sizeof((arr)[0]) )
#define J_LEFT 1
#define J_RIGHT 2
#define J_CENTER 3
#define IS_FIT(x) ((x) & 0x0004)
#define MAKE_FIT(x) ((x) | 0x0004)
#define HIDE_FIT(x) ((x) & 0x0003)
#define J_LEFT_FIT 5
#define J_RIGHT_FIT 6
#define J_CENTER_FIT 7
#define NORMAL 0
#define SELECTED 1
#define MARKED 2
#define MARKED_SELECTED 3
#define STATUS 5
/*
* This describes a format item. The parse_display_format routine parses
* the user specified format and creates a linked list of format_e structures.
*/
typedef struct format_e {
struct format_e *next;
int requested_field_len;
int field_len;
int just_mode;
int expand;
const char *(*string_fn)(file_entry *, int len);
const char *title;
const char *id;
} format_e;
1998-02-27 07:54:42 +03:00
/* If true, show the mini-info on the panel */
int show_mini_info = 1;
/* If true, then use stat() on the cwd to determine directory changes */
int fast_reload = 0;
/* If true, use some usability hacks by Torben */
int torben_fj_mode = 0;
/* If true, up/down keys scroll the pane listing by pages */
int panel_scroll_pages = 1;
/* If 1, we use permission hilighting */
int permission_mode = 0;
/* If 1 - then add per file type hilighting */
int filetype_mode = 1;
/* The hook list for the select file function */
Hook *select_file_hook = 0;
static cb_ret_t panel_callback (WPanel *p, widget_msg_t msg, int parm);
static int panel_event (Gpm_Event *event, WPanel *panel);
static void paint_frame (WPanel *panel);
static const char *panel_format (WPanel *panel);
static const char *mini_status_format (WPanel *panel);
1998-02-27 07:54:42 +03:00
/* This macro extracts the number of available lines in a panel */
#define llines(p) (p->widget.lines-3 - (show_mini_info ? 2 : 0))
static void
1998-02-27 07:54:42 +03:00
set_colors (WPanel *panel)
{
standend ();
attrset (NORMAL_COLOR);
1998-02-27 07:54:42 +03:00
}
/* Delete format string, it is a linked list */
1998-12-03 00:27:27 +03:00
static void
1998-02-27 07:54:42 +03:00
delete_format (format_e *format)
{
format_e *next;
1998-02-27 07:54:42 +03:00
while (format){
next = format->next;
g_free (format);
1998-02-27 07:54:42 +03:00
format = next;
}
}
/* This code relies on the default justification!!! */
1998-12-03 00:27:27 +03:00
static void
1998-02-27 07:54:42 +03:00
add_permission_string (char *dest, int width, file_entry *fe, int attr, int color, int is_octal)
{
int i, r, l;
l = get_user_permissions (&fe->st);
1998-02-27 07:54:42 +03:00
if (is_octal){
/* Place of the access bit in octal mode */
l = width + l - 3;
r = l + 1;
} else {
/* The same to the triplet in string mode */
l = l * 3 + 1;
r = l + 3;
}
1998-02-27 07:54:42 +03:00
for(i = 0; i < width; i++){
if (i >= l && i < r){
if (attr == SELECTED || attr == MARKED_SELECTED)
attrset (MARKED_SELECTED_COLOR);
else
attrset (MARKED_COLOR);
} else
attrset (color);
1998-02-27 07:54:42 +03:00
addch (dest[i]);
}
}
/* String representations of various file attributes */
/* name */
static const char *
string_file_name (file_entry *fe, int len)
{
static char buffer [BUF_SMALL];
size_t i;
for (i = 0; i < sizeof(buffer) - 1; i++) {
char c;
c = fe->fname[i];
if (!c)
break;
if (!is_printable(c))
c = '?';
buffer[i] = c;
}
buffer[i] = 0;
return buffer;
}
/* size */
static const char *
string_file_size (file_entry *fe, int len)
{
static char buffer [BUF_TINY];
/* Don't ever show size of ".." since we don't calculate it */
if (!strcmp (fe->fname, "..")) {
return _("UP--DIR");
}
#ifdef HAVE_STRUCT_STAT_ST_RDEV
if (S_ISBLK (fe->st.st_mode) || S_ISCHR (fe->st.st_mode))
g_snprintf (buffer, sizeof (buffer), "%3d,%3d",
(int) ((fe->st.st_rdev >> 8) & 0xff),
(int) (fe->st.st_rdev & 0xff));
else
#endif
{
size_trunc_len (buffer, len, fe->st.st_size, 0);
}
return buffer;
}
/* bsize */
static const char *
string_file_size_brief (file_entry *fe, int len)
{
if (S_ISLNK (fe->st.st_mode) && !fe->f.link_to_dir) {
return _("SYMLINK");
}
if ((S_ISDIR (fe->st.st_mode) || fe->f.link_to_dir) && strcmp (fe->fname, "..")) {
return _("SUB-DIR");
}
return string_file_size (fe, len);
}
1998-02-27 07:54:42 +03:00
/* This functions return a string representation of a file entry */
/* type */
static const char *
1998-02-27 07:54:42 +03:00
string_file_type (file_entry *fe, int len)
{
static char buffer[2];
1998-02-27 07:54:42 +03:00
if (S_ISDIR (fe->st.st_mode))
buffer[0] = PATH_SEP;
else if (S_ISLNK (fe->st.st_mode)) {
if (fe->f.link_to_dir)
buffer[0] = '~';
else if (fe->f.stale_link)
buffer[0] = '!';
else
buffer[0] = '@';
} else if (S_ISCHR (fe->st.st_mode))
buffer[0] = '-';
else if (S_ISSOCK (fe->st.st_mode))
buffer[0] = '=';
else if (S_ISDOOR (fe->st.st_mode))
buffer[0] = '>';
else if (S_ISBLK (fe->st.st_mode))
buffer[0] = '+';
else if (S_ISFIFO (fe->st.st_mode))
buffer[0] = '|';
else if (S_ISNAM (fe->st.st_mode))
buffer[0] = '#';
else if (!S_ISREG (fe->st.st_mode))
buffer[0] = '?'; /* non-regular of unknown kind */
else if (is_exe (fe->st.st_mode))
buffer[0] = '*';
1998-02-27 07:54:42 +03:00
else
buffer[0] = ' ';
buffer[1] = '\0';
1998-02-27 07:54:42 +03:00
return buffer;
}
/* mtime */
static const char *
string_file_mtime (file_entry *fe, int len)
1998-02-27 07:54:42 +03:00
{
if (!strcmp (fe->fname, "..")) {
return "";
}
return file_date (fe->st.st_mtime);
}
1998-02-27 07:54:42 +03:00
/* atime */
static const char *
string_file_atime (file_entry *fe, int len)
{
if (!strcmp (fe->fname, "..")) {
return "";
}
return file_date (fe->st.st_atime);
}
1998-02-27 07:54:42 +03:00
/* ctime */
static const char *
string_file_ctime (file_entry *fe, int len)
{
if (!strcmp (fe->fname, "..")) {
return "";
}
return file_date (fe->st.st_ctime);
1998-02-27 07:54:42 +03:00
}
/* perm */
static const char *
1998-02-27 07:54:42 +03:00
string_file_permission (file_entry *fe, int len)
{
return string_perm (fe->st.st_mode);
1998-02-27 07:54:42 +03:00
}
/* mode */
static const char *
string_file_perm_octal (file_entry *fe, int len)
1998-02-27 07:54:42 +03:00
{
static char buffer [10];
1998-02-27 07:54:42 +03:00
g_snprintf (buffer, sizeof (buffer), "0%06lo", (unsigned long) fe->st.st_mode);
1998-02-27 07:54:42 +03:00
return buffer;
}
/* nlink */
static const char *
string_file_nlinks (file_entry *fe, int len)
1998-02-27 07:54:42 +03:00
{
static char buffer[BUF_TINY];
1998-02-27 07:54:42 +03:00
g_snprintf (buffer, sizeof (buffer), "%16d", (int) fe->st.st_nlink);
1998-02-27 07:54:42 +03:00
return buffer;
}
/* inode */
static const char *
string_inode (file_entry *fe, int len)
1998-02-27 07:54:42 +03:00
{
static char buffer [10];
1998-02-27 07:54:42 +03:00
g_snprintf (buffer, sizeof (buffer), "%lu",
(unsigned long) fe->st.st_ino);
return buffer;
1998-02-27 07:54:42 +03:00
}
/* nuid */
static const char *
string_file_nuid (file_entry *fe, int len)
1998-02-27 07:54:42 +03:00
{
static char buffer [10];
1998-02-27 07:54:42 +03:00
g_snprintf (buffer, sizeof (buffer), "%lu",
(unsigned long) fe->st.st_uid);
return buffer;
}
/* ngid */
static const char *
string_file_ngid (file_entry *fe, int len)
{
static char buffer [10];
g_snprintf (buffer, sizeof (buffer), "%lu",
(unsigned long) fe->st.st_gid);
return buffer;
1998-03-07 03:05:06 +03:00
}
/* owner */
static const char *
string_file_owner (file_entry *fe, int len)
{
return get_owner (fe->st.st_uid);
}
/* group */
static const char *
string_file_group (file_entry *fe, int len)
{
return get_group (fe->st.st_gid);
}
/* mark */
static const char *
string_marked (file_entry *fe, int len)
1998-02-27 07:54:42 +03:00
{
return fe->f.marked ? "*" : " ";
1998-02-27 07:54:42 +03:00
}
/* space */
static const char *
1998-02-27 07:54:42 +03:00
string_space (file_entry *fe, int len)
{
return " ";
}
/* dot */
static const char *
1998-02-27 07:54:42 +03:00
string_dot (file_entry *fe, int len)
{
return ".";
}
#define GT 1
Ok, most of the "Elliot Lee confidential bug report" has been dealt with with this commit. This also addresses a bunch of the comments from the status.shtml from DrMike. Miguel. 1998-04-15 Miguel de Icaza <miguel@nuclecu.unam.mx> * screen.c (GT): Assign two spaces for the minimum size of the "type" field for the GNOME edition. This gives some extra space for the icon that gets displayed. * dlg.c (remove_widget): New function: used to remove a widget from an existing Dlg_head; (destroy_widget): Destroy a specific Widget. (add_widgetl): Extended to deal with the fact that a running Dlg_head can become empty. * panelize.c (l_call): Update the input line every time the user selects the entry with the mouse (pretty common in the gnome edition). * hotlist.c (add_new_group_input): Removed an extra field that was causing problems. * find.c (find_parameters): Tree button is gone for gnome until we get the tree function working on gnome. * cmd.c (save_setup_cmd): Per Elliot's suggestion, do not pop up a dialog box to inform the user about the saved setup. 1998-04-15 Miguel de Icaza <miguel@nuclecu.unam.mx> * gcmd.c (gnome_close_panel): Implement the close-the-panel functionality. * gscreen.c (x_panel_destroy): Implement the gnome mode way of destroying the panel. * gview.c (view_status): Add cacheing of the information status, to avoid excessive flicker. It would be better if GtkLabel did not flicker though. (scrollbar_moved): Scroll correctly. We now use view_move_backward and view_move_forward to adjust the scrollbar contents. This displays the scrollbar correctly. * gwidget.c (x_listbox_select_nth): This may be invoked before the widget has been created, work around this problem. * gscreen.c (show_dir): Set the title bar for the window to the current directoy. Reported by both Mike and Elliot. * layout: Updated to the new hotlist dialog box.
1998-04-16 06:45:53 +04:00
1998-02-27 07:54:42 +03:00
static struct {
const char *id;
1998-02-27 07:54:42 +03:00
int min_size;
int expands;
int default_just;
const char *title;
1998-02-27 07:54:42 +03:00
int use_in_gui;
const char *(*string_fn)(file_entry *, int);
1998-02-27 07:54:42 +03:00
sortfn *sort_routine;
} formats [] = {
{ "name", 12, 1, J_LEFT_FIT, N_("Name"), 1, string_file_name, (sortfn *) sort_name },
{ "size", 7, 0, J_RIGHT, N_("Size"), 1, string_file_size, (sortfn *) sort_size },
{ "bsize", 7, 0, J_RIGHT, N_("Size"), 1, string_file_size_brief, (sortfn *) sort_size },
{ "type", GT, 0, J_LEFT, "", 2, string_file_type, (sortfn *) sort_type },
{ "mtime", 12, 0, J_RIGHT, N_("MTime"), 1, string_file_mtime, (sortfn *) sort_time },
{ "atime", 12, 0, J_RIGHT, N_("ATime"), 1, string_file_atime, (sortfn *) sort_atime },
{ "ctime", 12, 0, J_RIGHT, N_("CTime"), 1, string_file_ctime, (sortfn *) sort_ctime },
{ "perm", 10, 0, J_LEFT, N_("Permission"),1,string_file_permission, NULL },
{ "mode", 6, 0, J_RIGHT, N_("Perm"), 1, string_file_perm_octal, NULL },
{ "nlink", 2, 0, J_RIGHT, N_("Nl"), 1, string_file_nlinks, (sortfn *) sort_links },
{ "inode", 5, 0, J_RIGHT, N_("Inode"), 1, string_inode, (sortfn *) sort_inode },
{ "nuid", 5, 0, J_RIGHT, N_("UID"), 1, string_file_nuid, (sortfn *) sort_nuid },
{ "ngid", 5, 0, J_RIGHT, N_("GID"), 1, string_file_ngid, (sortfn *) sort_ngid },
{ "owner", 8, 0, J_LEFT_FIT, N_("Owner"), 1, string_file_owner, (sortfn *) sort_owner },
{ "group", 8, 0, J_LEFT_FIT, N_("Group"), 1, string_file_group, (sortfn *) sort_group },
{ "mark", 1, 0, J_RIGHT, " ", 1, string_marked, NULL },
{ "|", 1, 0, J_RIGHT, " ", 0, NULL, NULL },
{ "space", 1, 0, J_RIGHT, " ", 0, string_space, NULL },
{ "dot", 1, 0, J_RIGHT, " ", 0, string_dot, NULL },
1998-02-27 07:54:42 +03:00
};
static char *
to_buffer (char *dest, int just_mode, int len, const char *txt)
1998-02-27 07:54:42 +03:00
{
int txtlen = strlen (txt);
int still, over;
1998-02-27 07:54:42 +03:00
/* Fill buffer with spaces */
memset (dest, ' ', len);
still = (over=(txtlen > len)) ? (txtlen - len) : (len - txtlen);
switch (HIDE_FIT(just_mode)){
case J_LEFT:
still = 0;
break;
case J_CENTER:
still /= 2;
break;
case J_RIGHT:
default:
break;
}
if (over){
if (IS_FIT(just_mode))
strcpy (dest, name_trunc(txt, len));
else
strncpy (dest, txt+still, len);
} else
strncpy (dest+still, txt, txtlen);
1999-02-01 03:08:16 +03:00
dest[len] = '\0';
return (dest + len);
1998-02-27 07:54:42 +03:00
}
static int
1998-02-27 07:54:42 +03:00
file_compute_color (int attr, file_entry *fe)
{
switch (attr) {
1998-02-27 07:54:42 +03:00
case SELECTED:
return (SELECTED_COLOR);
1998-02-27 07:54:42 +03:00
case MARKED:
return (MARKED_COLOR);
1998-02-27 07:54:42 +03:00
case MARKED_SELECTED:
return (MARKED_SELECTED_COLOR);
1998-02-27 07:54:42 +03:00
case STATUS:
return (NORMAL_COLOR);
1998-02-27 07:54:42 +03:00
case NORMAL:
default:
if (!filetype_mode)
return (NORMAL_COLOR);
1998-02-27 07:54:42 +03:00
}
/* if filetype_mode == true */
if (S_ISDIR (fe->st.st_mode))
return (DIRECTORY_COLOR);
else if (S_ISLNK (fe->st.st_mode)) {
if (fe->f.link_to_dir)
return (DIRECTORY_COLOR);
else if (fe->f.stale_link)
return (STALE_LINK_COLOR);
else
return (LINK_COLOR);
} else if (S_ISSOCK (fe->st.st_mode))
return (SPECIAL_COLOR);
else if (S_ISCHR (fe->st.st_mode))
return (DEVICE_COLOR);
else if (S_ISBLK (fe->st.st_mode))
return (DEVICE_COLOR);
else if (S_ISNAM (fe->st.st_mode))
return (DEVICE_COLOR);
else if (S_ISFIFO (fe->st.st_mode))
return (SPECIAL_COLOR);
else if (S_ISDOOR (fe->st.st_mode))
return (SPECIAL_COLOR);
else if (!S_ISREG (fe->st.st_mode))
return (STALE_LINK_COLOR); /* non-regular file of unknown kind */
else if (is_exe (fe->st.st_mode))
return (EXECUTABLE_COLOR);
else if (fe->fname && (!strcmp (fe->fname, "core")
|| !strcmp (extension (fe->fname), "core")))
return (CORE_COLOR);
return (NORMAL_COLOR);
1998-02-27 07:54:42 +03:00
}
/* Formats the file number file_index of panel in the buffer dest */
static void
format_file (char *dest, int limit, WPanel *panel, int file_index, int width, int attr, int isstatus)
1998-02-27 07:54:42 +03:00
{
int color, length, empty_line;
const char *txt;
1998-02-27 07:54:42 +03:00
char *old_pos;
char *cdest = dest;
format_e *format, *home;
file_entry *fe;
1998-02-27 07:54:42 +03:00
length = 0;
empty_line = (file_index >= panel->count);
home = (isstatus) ? panel->status_format : panel->format;
1998-02-27 07:54:42 +03:00
fe = &panel->dir.list [file_index];
if (!empty_line)
color = file_compute_color (attr, fe);
else
color = NORMAL_COLOR;
1998-02-27 07:54:42 +03:00
for (format = home; format; format = format->next){
if (length == width)
break;
1998-02-27 07:54:42 +03:00
if (format->string_fn){
int len;
1998-02-27 07:54:42 +03:00
if (empty_line)
txt = " ";
else
txt = (*format->string_fn)(fe, format->field_len);
old_pos = cdest;
len = format->field_len;
if (len + length > width)
len = width - length;
if (len + (cdest - dest) > limit)
len = limit - (cdest - dest);
if (len <= 0)
break;
cdest = to_buffer (cdest, format->just_mode, len, txt);
length += len;
1998-02-27 07:54:42 +03:00
attrset (color);
1998-02-27 07:54:42 +03:00
if (permission_mode && !strcmp(format->id, "perm"))
add_permission_string (old_pos, format->field_len, fe, attr, color, 0);
else if (permission_mode && !strcmp(format->id, "mode"))
add_permission_string (old_pos, format->field_len, fe, attr, color, 1);
else
addstr (old_pos);
1998-02-27 07:54:42 +03:00
} else {
if (attr == SELECTED || attr == MARKED_SELECTED)
attrset (SELECTED_COLOR);
else
attrset (NORMAL_COLOR);
one_vline ();
length++;
}
}
1998-02-27 07:54:42 +03:00
if (length < width){
int still = width - length;
while (still--)
addch (' ');
}
}
static void
1998-02-27 07:54:42 +03:00
repaint_file (WPanel *panel, int file_index, int mv, int attr, int isstatus)
{
int second_column = 0;
int width, offset;
char buffer [BUF_MEDIUM];
1998-02-27 07:54:42 +03:00
offset = 0;
if (!isstatus && panel->split){
1998-02-27 07:54:42 +03:00
second_column = (file_index - panel->top_file) / llines (panel);
width = (panel->widget.cols - 2)/2 - 1;
1998-02-27 07:54:42 +03:00
if (second_column){
offset = 1 + width;
1998-02-27 07:54:42 +03:00
width = (panel->widget.cols-2) - (panel->widget.cols-2)/2 - 1;
}
1998-02-27 07:54:42 +03:00
} else
width = (panel->widget.cols - 2);
/* Nothing to paint */
if (width <= 0)
return;
1998-02-27 07:54:42 +03:00
if (mv){
if (!isstatus && panel->split){
widget_move (&panel->widget,
(file_index - panel->top_file) %
llines (panel) + 2,
(offset + 1));
} else
widget_move (&panel->widget, file_index - panel->top_file + 2, 1);
}
format_file (buffer, sizeof(buffer), panel, file_index, width, attr, isstatus);
1998-02-27 07:54:42 +03:00
if (!isstatus && panel->split){
if (second_column)
addch (' ');
else {
attrset (NORMAL_COLOR);
one_vline ();
}
}
}
static void
1998-02-27 07:54:42 +03:00
display_mini_info (WPanel *panel)
{
if (!show_mini_info)
return;
1998-02-27 07:54:42 +03:00
widget_move (&panel->widget, llines (panel)+3, 1);
1998-02-27 07:54:42 +03:00
if (panel->searching){
attrset (INPUT_COLOR);
printw ("/%-*s", panel->widget.cols-3, panel->search_buffer);
attrset (NORMAL_COLOR);
return;
}
/* Status displays total marked size */
if (panel->marked){
char buffer [BUF_SMALL];
const char *p = " %-*s";
int cols = panel->widget.cols-2;
1998-02-27 07:54:42 +03:00
attrset (MARKED_COLOR);
printw ("%*s", cols, " ");
1998-02-27 07:54:42 +03:00
widget_move (&panel->widget, llines (panel)+3, 1);
/* FIXME: use ngettext() here when gettext-0.10.35 becomes history */
g_snprintf (buffer, sizeof (buffer), (panel->marked == 1) ?
_("%s bytes in %d file") : _("%s bytes in %d files"),
size_trunc_sep (panel->total), panel->marked);
if ((int) strlen (buffer) > cols-2){
buffer [cols] = 0;
1998-02-27 07:54:42 +03:00
p += 2;
} else
cols -= 2;
printw ((char *) p, cols, buffer);
1998-02-27 07:54:42 +03:00
return;
}
/* Status resolves links and show them */
set_colors (panel);
if (S_ISLNK (panel->dir.list [panel->selected].st.st_mode)){
1998-02-27 07:54:42 +03:00
char *link, link_target [MC_MAXPATHLEN];
int len;
link = concat_dir_and_file (panel->cwd, panel->dir.list [panel->selected].fname);
len = mc_readlink (link, link_target, MC_MAXPATHLEN - 1);
g_free (link);
1998-02-27 07:54:42 +03:00
if (len > 0){
link_target[len] = 0;
printw ("-> %-*s", panel->widget.cols - 5,
name_trunc (link_target, panel->widget.cols - 5));
} else
printw ("%-*s", panel->widget.cols - 2, _("<readlink failed>"));
1998-02-27 07:54:42 +03:00
return;
}
2003-06-02 22:13:42 +04:00
/* Default behavior */
1998-02-27 07:54:42 +03:00
repaint_file (panel, panel->selected, 0, STATUS, 1);
return;
}
static void
1998-02-27 07:54:42 +03:00
paint_dir (WPanel *panel)
{
int i;
int color; /* Color value of the line */
int items; /* Number of items */
items = llines (panel) * (panel->split ? 2 : 1);
1998-02-27 07:54:42 +03:00
for (i = 0; i < items; i++){
if (i+panel->top_file >= panel->count)
color = 0;
else {
color = 2 * (panel->dir.list [i+panel->top_file].f.marked);
color += (panel->selected==i+panel->top_file && panel->active);
}
repaint_file (panel, i+panel->top_file, 1, color, 0);
1998-02-27 07:54:42 +03:00
}
standend ();
}
static void
mini_info_separator (WPanel *panel)
{
if (!show_mini_info)
return;
1998-02-27 07:54:42 +03:00
standend ();
widget_move (&panel->widget, llines (panel) + 2, 1);
1998-02-27 07:54:42 +03:00
#ifdef HAVE_SLANG
attrset (NORMAL_COLOR);
hline (ACS_HLINE, panel->widget.cols - 2);
1998-02-27 07:54:42 +03:00
#else
hline ((slow_terminal ? '-' : ACS_HLINE) | NORMAL_COLOR,
panel->widget.cols - 2);
#endif /* !HAVE_SLANG */
1998-02-27 07:54:42 +03:00
}
static void
1998-02-27 07:54:42 +03:00
show_dir (WPanel *panel)
{
char *tmp;
1998-02-27 07:54:42 +03:00
set_colors (panel);
draw_double_box (panel->widget.parent,
panel->widget.y, panel->widget.x,
panel->widget.lines, panel->widget.cols);
1998-02-27 07:54:42 +03:00
#ifdef HAVE_SLANG
1998-02-27 07:54:42 +03:00
if (show_mini_info) {
SLsmg_draw_object (panel->widget.y + llines (panel) + 2,
panel->widget.x, SLSMG_LTEE_CHAR);
SLsmg_draw_object (panel->widget.y + llines (panel) + 2,
panel->widget.x + panel->widget.cols - 1,
SLSMG_RTEE_CHAR);
1998-02-27 07:54:42 +03:00
}
#endif /* HAVE_SLANG */
1998-02-27 07:54:42 +03:00
if (panel->active)
attrset (REVERSE_COLOR);
widget_move (&panel->widget, 0, 3);
1998-02-27 07:54:42 +03:00
tmp = g_malloc (panel->widget.cols + 1);
tmp[panel->widget.cols] = '\0';
trim (strip_home_and_password (panel->cwd), tmp,
min (max (panel->widget.cols - 7, 0), panel->widget.cols) );
1998-02-27 07:54:42 +03:00
addstr (tmp);
g_free (tmp);
widget_move (&panel->widget, 0, 1);
addstr ("<");
widget_move (&panel->widget, 0, panel->widget.cols - 2);
addstr (">");
widget_move (&panel->widget, 0, panel->widget.cols - 3);
addstr ("v");
1998-02-27 07:54:42 +03:00
if (panel->active)
standend ();
}
/* To be used only by long_frame and full_frame to adjust top_file */
static void
adjust_top_file (WPanel *panel)
{
int old_top = panel->top_file;
1998-02-27 07:54:42 +03:00
if (panel->selected - old_top > llines (panel))
panel->top_file = panel->selected;
if (old_top - panel->count > llines (panel))
panel->top_file = panel->count - llines (panel);
}
/*
* Repaint everything that can change on the panel - title, entries and
* mini status. The rest of the frame and the mini status separator are
* not repainted.
*/
static void
1998-02-27 07:54:42 +03:00
panel_update_contents (WPanel *panel)
{
show_dir (panel);
paint_dir (panel);
display_mini_info (panel);
panel->dirty = 0;
1998-02-27 07:54:42 +03:00
}
/* Repaint everything, including frame and separator */
static void
1998-02-27 07:54:42 +03:00
paint_panel (WPanel *panel)
{
paint_frame (panel);
panel_update_contents (panel);
mini_info_separator (panel);
}
/*
* Repaint the contents of the panels without frames. To schedule panel
* for repainting, set panel->dirty to 1. There are many reasons why
* the panels need to be repainted, and this is a costly operation, so
* it's done once per event.
*/
void
update_dirty_panels (void)
{
if (current_panel->dirty)
panel_update_contents (current_panel);
if ((get_other_type () == view_listing) && other_panel->dirty)
panel_update_contents (other_panel);
}
static void
do_select (WPanel *panel, int i)
{
if (i != panel->selected) {
panel->dirty = 1;
panel->selected = i;
panel->top_file = panel->selected - (panel->widget.lines - 2) / 2;
if (panel->top_file < 0)
panel->top_file = 0;
}
}
static inline void
do_try_to_select (WPanel *panel, const char *name)
1998-02-27 07:54:42 +03:00
{
int i;
1998-02-27 07:54:42 +03:00
char *subdir;
if (!name) {
do_select(panel, 0);
1998-02-27 07:54:42 +03:00
return;
}
/* We only want the last component of the directory,
* and from this only the name without suffix. */
subdir = vfs_strip_suffix_from_filename (x_basename(name));
1998-02-27 07:54:42 +03:00
/* Search that subdirectory, if found select it */
for (i = 0; i < panel->count; i++){
if (strcmp (subdir, panel->dir.list [i].fname) == 0) {
do_select (panel, i);
g_free (subdir);
return;
}
1998-02-27 07:54:42 +03:00
}
/* Try to select a file near the file that is missing */
if (panel->selected >= panel->count)
do_select (panel, panel->count-1);
g_free (subdir);
1998-02-27 07:54:42 +03:00
}
void
try_to_select (WPanel *panel, const char *name)
{
do_try_to_select (panel, name);
select_item (panel);
display_mini_info (panel);
}
1998-02-27 07:54:42 +03:00
void
panel_update_cols (Widget *widget, int frame_size)
{
int cols, origin;
1998-02-27 07:54:42 +03:00
if (horizontal_split){
widget->cols = COLS;
return;
}
if (frame_size == frame_full){
cols = COLS;
origin = 0;
} else {
if (widget == get_panel_widget (0)){
cols = first_panel_size;
origin = 0;
} else {
cols = COLS-first_panel_size;
origin = first_panel_size;
}
}
1998-02-27 07:54:42 +03:00
widget->cols = cols;
widget->x = origin;
}
static char *
panel_save_name (WPanel *panel)
{
extern int saving_setup;
1998-02-27 07:54:42 +03:00
/* If the program is shuting down */
if ((midnight_shutdown && auto_save_setup) || saving_setup)
return g_strdup (panel->panel_name);
1998-02-27 07:54:42 +03:00
else
return g_strconcat ("Temporal:", panel->panel_name, (char *) NULL);
1998-02-27 07:54:42 +03:00
}
static void
panel_destroy (WPanel *p)
{
int i;
1998-02-27 07:54:42 +03:00
char *name = panel_save_name (p);
panel_save_setup (p, name);
panel_clean_dir (p);
/* save and clean history */
if (p->dir_history) {
history_put (p->hist_name, p->dir_history);
p->dir_history = g_list_first (p->dir_history);
g_list_foreach (p->dir_history, (GFunc) g_free, NULL);
g_list_free (p->dir_history);
}
g_free (p->hist_name);
1998-02-27 07:54:42 +03:00
delete_format (p->format);
delete_format (p->status_format);
g_free (p->user_format);
1998-02-27 07:54:42 +03:00
for (i = 0; i < LIST_TYPES; i++)
g_free (p->user_status_format[i]);
g_free (p->dir.list);
g_free (p->panel_name);
g_free (name);
1998-02-27 07:54:42 +03:00
}
static void
panel_format_modified (WPanel *panel)
{
panel->format_modified = 1;
}
/* Panel creation */
/* The parameter specifies the name of the panel for setup retieving */
WPanel *
panel_new (const char *panel_name)
1998-02-27 07:54:42 +03:00
{
WPanel *panel;
char *section;
int i, err;
panel = g_new0 (WPanel, 1);
These are a bunch of changes to fix CORBA and session management. They are almost complete (i.e. to handle all nitty gritty cases), but they seem to be working OK right now. SM should be much more stable now. Please tell me if you find any weird behavior - Federico 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdesktop-icon.c (desktop_icon_realize): Remove the WM_CLIENT_LEADER property from icon windows so that window managers will not store SM information for them. * gnome-open-dialog.c: Added missing #includes. * gdesktop-init.c (desktop_init_at): Removed an unused variable. * gdesktop.h: Added some missing prototypes. * gmain.h: Added some missing prototypes. * Makefile.in: Added gsession.[ch] to the list of sources. * gmain.c (create_panels): Consider whether we have a CORBA server and session management. * gdesktop.c: #include "gdesktop-init.h" * gdesktop.c: Added a missing cast to GNOME_DIALOG. * gmain.c (create_panels): Removed the run_desktop global variable. * glayout.c (create_container): Set the wmclass of the panel to include its unique ID. * gsession.[ch]: New file with the functions that deal with session management. * glayout.c (gnome_exit): Use session_set_restart(). * gcorba.c (corba_init): Now returns an int with an error value. (corba_init_server): Initialize the server properly. Fixed all the object implementation code. (corba_create_window): New function used to create a window with the CORBA server. * gmain.c (gnome_check_super_user): Now the check for running as root is done here. There should be no GUI code in src/. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * dlg.c (dlg_run_done): Do not call the callback of a NULL current widget. * setup.h: Added missing prototype for setup_init(). * filegui.c (check_progress_buttons): Added a missing return value. * dlg.c (remove_widget): Added a missing return value. * main.c: Removed the global directory_list variable. Removed the main_corba_register_server() function. * main.h: Removed the global run_desktop variable. * panel.h: Now the panel structure has a unique numerical ID used for session management. * screen.c (panel_new): Maintain a unique ID for each panel. * main.c (maybe_display_linksdir): Handle display of the desktop init dir here. (main): Call gnome_check_super_user(). (init_corba_with_args): Call corba_init_server(). * main.c (init_corba_with_args): Do CORBA initialization here. Also removed the global force_activation option. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * vfs.c (vfs_add_current_stamps): Only do stamping of the panels if they exist. * mcserv.c: #include <sys/wait.h> (get_client): Put `#ifdef __EMX__' around an otherwise-unused variable. * utilvfs.c (vfs_split_url): Fix NULL <-> 0 confusion when comparing characters. * ftpfs.c (retrieve_dir): Removed unused variable dot_dot_found. * extfs.c (extfs_init): Assign `key' to c, not `&key'.
1999-03-30 10:09:56 +04:00
1998-02-27 07:54:42 +03:00
/* No know sizes of the panel at startup */
init_widget (&panel->widget, 0, 0, 0, 0, (callback_fn)
panel_callback, (mouse_h) panel_event);
1998-02-27 07:54:42 +03:00
/* We do not want the cursor */
widget_want_cursor (panel->widget, 0);
These are a bunch of changes to fix CORBA and session management. They are almost complete (i.e. to handle all nitty gritty cases), but they seem to be working OK right now. SM should be much more stable now. Please tell me if you find any weird behavior - Federico 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdesktop-icon.c (desktop_icon_realize): Remove the WM_CLIENT_LEADER property from icon windows so that window managers will not store SM information for them. * gnome-open-dialog.c: Added missing #includes. * gdesktop-init.c (desktop_init_at): Removed an unused variable. * gdesktop.h: Added some missing prototypes. * gmain.h: Added some missing prototypes. * Makefile.in: Added gsession.[ch] to the list of sources. * gmain.c (create_panels): Consider whether we have a CORBA server and session management. * gdesktop.c: #include "gdesktop-init.h" * gdesktop.c: Added a missing cast to GNOME_DIALOG. * gmain.c (create_panels): Removed the run_desktop global variable. * glayout.c (create_container): Set the wmclass of the panel to include its unique ID. * gsession.[ch]: New file with the functions that deal with session management. * glayout.c (gnome_exit): Use session_set_restart(). * gcorba.c (corba_init): Now returns an int with an error value. (corba_init_server): Initialize the server properly. Fixed all the object implementation code. (corba_create_window): New function used to create a window with the CORBA server. * gmain.c (gnome_check_super_user): Now the check for running as root is done here. There should be no GUI code in src/. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * dlg.c (dlg_run_done): Do not call the callback of a NULL current widget. * setup.h: Added missing prototype for setup_init(). * filegui.c (check_progress_buttons): Added a missing return value. * dlg.c (remove_widget): Added a missing return value. * main.c: Removed the global directory_list variable. Removed the main_corba_register_server() function. * main.h: Removed the global run_desktop variable. * panel.h: Now the panel structure has a unique numerical ID used for session management. * screen.c (panel_new): Maintain a unique ID for each panel. * main.c (maybe_display_linksdir): Handle display of the desktop init dir here. (main): Call gnome_check_super_user(). (init_corba_with_args): Call corba_init_server(). * main.c (init_corba_with_args): Do CORBA initialization here. Also removed the global force_activation option. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * vfs.c (vfs_add_current_stamps): Only do stamping of the panels if they exist. * mcserv.c: #include <sys/wait.h> (get_client): Put `#ifdef __EMX__' around an otherwise-unused variable. * utilvfs.c (vfs_split_url): Fix NULL <-> 0 confusion when comparing characters. * ftpfs.c (retrieve_dir): Removed unused variable dot_dot_found. * extfs.c (extfs_init): Assign `key' to c, not `&key'.
1999-03-30 10:09:56 +04:00
mc_get_current_wd (panel->cwd, sizeof (panel->cwd) - 2);
1998-02-27 07:54:42 +03:00
strcpy (panel->lwd, ".");
panel->hist_name = g_strconcat ("Dir Hist ", panel_name, (char *) NULL);
panel->dir_history = history_get (panel->hist_name);
directory_history_add (panel, panel->cwd);
panel->dir.list = g_new (file_entry, MIN_FILES);
panel->dir.size = MIN_FILES;
panel->active = 0;
panel->filter = 0;
panel->split = 0;
panel->top_file = 0;
panel->selected = 0;
panel->marked = 0;
panel->total = 0;
panel->reverse = 0;
panel->dirty = 1;
panel->searching = 0;
panel->dirs_marked = 0;
panel->is_panelized = 0;
panel->format = 0;
panel->status_format = 0;
panel->format_modified = 1;
These are a bunch of changes to fix CORBA and session management. They are almost complete (i.e. to handle all nitty gritty cases), but they seem to be working OK right now. SM should be much more stable now. Please tell me if you find any weird behavior - Federico 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdesktop-icon.c (desktop_icon_realize): Remove the WM_CLIENT_LEADER property from icon windows so that window managers will not store SM information for them. * gnome-open-dialog.c: Added missing #includes. * gdesktop-init.c (desktop_init_at): Removed an unused variable. * gdesktop.h: Added some missing prototypes. * gmain.h: Added some missing prototypes. * Makefile.in: Added gsession.[ch] to the list of sources. * gmain.c (create_panels): Consider whether we have a CORBA server and session management. * gdesktop.c: #include "gdesktop-init.h" * gdesktop.c: Added a missing cast to GNOME_DIALOG. * gmain.c (create_panels): Removed the run_desktop global variable. * glayout.c (create_container): Set the wmclass of the panel to include its unique ID. * gsession.[ch]: New file with the functions that deal with session management. * glayout.c (gnome_exit): Use session_set_restart(). * gcorba.c (corba_init): Now returns an int with an error value. (corba_init_server): Initialize the server properly. Fixed all the object implementation code. (corba_create_window): New function used to create a window with the CORBA server. * gmain.c (gnome_check_super_user): Now the check for running as root is done here. There should be no GUI code in src/. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * dlg.c (dlg_run_done): Do not call the callback of a NULL current widget. * setup.h: Added missing prototype for setup_init(). * filegui.c (check_progress_buttons): Added a missing return value. * dlg.c (remove_widget): Added a missing return value. * main.c: Removed the global directory_list variable. Removed the main_corba_register_server() function. * main.h: Removed the global run_desktop variable. * panel.h: Now the panel structure has a unique numerical ID used for session management. * screen.c (panel_new): Maintain a unique ID for each panel. * main.c (maybe_display_linksdir): Handle display of the desktop init dir here. (main): Call gnome_check_super_user(). (init_corba_with_args): Call corba_init_server(). * main.c (init_corba_with_args): Do CORBA initialization here. Also removed the global force_activation option. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * vfs.c (vfs_add_current_stamps): Only do stamping of the panels if they exist. * mcserv.c: #include <sys/wait.h> (get_client): Put `#ifdef __EMX__' around an otherwise-unused variable. * utilvfs.c (vfs_split_url): Fix NULL <-> 0 confusion when comparing characters. * ftpfs.c (retrieve_dir): Removed unused variable dot_dot_found. * extfs.c (extfs_init): Assign `key' to c, not `&key'.
1999-03-30 10:09:56 +04:00
panel->panel_name = g_strdup (panel_name);
panel->user_format = g_strdup (DEFAULT_USER_FORMAT);
These are a bunch of changes to fix CORBA and session management. They are almost complete (i.e. to handle all nitty gritty cases), but they seem to be working OK right now. SM should be much more stable now. Please tell me if you find any weird behavior - Federico 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdesktop-icon.c (desktop_icon_realize): Remove the WM_CLIENT_LEADER property from icon windows so that window managers will not store SM information for them. * gnome-open-dialog.c: Added missing #includes. * gdesktop-init.c (desktop_init_at): Removed an unused variable. * gdesktop.h: Added some missing prototypes. * gmain.h: Added some missing prototypes. * Makefile.in: Added gsession.[ch] to the list of sources. * gmain.c (create_panels): Consider whether we have a CORBA server and session management. * gdesktop.c: #include "gdesktop-init.h" * gdesktop.c: Added a missing cast to GNOME_DIALOG. * gmain.c (create_panels): Removed the run_desktop global variable. * glayout.c (create_container): Set the wmclass of the panel to include its unique ID. * gsession.[ch]: New file with the functions that deal with session management. * glayout.c (gnome_exit): Use session_set_restart(). * gcorba.c (corba_init): Now returns an int with an error value. (corba_init_server): Initialize the server properly. Fixed all the object implementation code. (corba_create_window): New function used to create a window with the CORBA server. * gmain.c (gnome_check_super_user): Now the check for running as root is done here. There should be no GUI code in src/. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * dlg.c (dlg_run_done): Do not call the callback of a NULL current widget. * setup.h: Added missing prototype for setup_init(). * filegui.c (check_progress_buttons): Added a missing return value. * dlg.c (remove_widget): Added a missing return value. * main.c: Removed the global directory_list variable. Removed the main_corba_register_server() function. * main.h: Removed the global run_desktop variable. * panel.h: Now the panel structure has a unique numerical ID used for session management. * screen.c (panel_new): Maintain a unique ID for each panel. * main.c (maybe_display_linksdir): Handle display of the desktop init dir here. (main): Call gnome_check_super_user(). (init_corba_with_args): Call corba_init_server(). * main.c (init_corba_with_args): Do CORBA initialization here. Also removed the global force_activation option. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * vfs.c (vfs_add_current_stamps): Only do stamping of the panels if they exist. * mcserv.c: #include <sys/wait.h> (get_client): Put `#ifdef __EMX__' around an otherwise-unused variable. * utilvfs.c (vfs_split_url): Fix NULL <-> 0 confusion when comparing characters. * ftpfs.c (retrieve_dir): Removed unused variable dot_dot_found. * extfs.c (extfs_init): Assign `key' to c, not `&key'.
1999-03-30 10:09:56 +04:00
for (i = 0; i < LIST_TYPES; i++)
panel->user_status_format[i] = g_strdup (DEFAULT_USER_FORMAT);
These are a bunch of changes to fix CORBA and session management. They are almost complete (i.e. to handle all nitty gritty cases), but they seem to be working OK right now. SM should be much more stable now. Please tell me if you find any weird behavior - Federico 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdesktop-icon.c (desktop_icon_realize): Remove the WM_CLIENT_LEADER property from icon windows so that window managers will not store SM information for them. * gnome-open-dialog.c: Added missing #includes. * gdesktop-init.c (desktop_init_at): Removed an unused variable. * gdesktop.h: Added some missing prototypes. * gmain.h: Added some missing prototypes. * Makefile.in: Added gsession.[ch] to the list of sources. * gmain.c (create_panels): Consider whether we have a CORBA server and session management. * gdesktop.c: #include "gdesktop-init.h" * gdesktop.c: Added a missing cast to GNOME_DIALOG. * gmain.c (create_panels): Removed the run_desktop global variable. * glayout.c (create_container): Set the wmclass of the panel to include its unique ID. * gsession.[ch]: New file with the functions that deal with session management. * glayout.c (gnome_exit): Use session_set_restart(). * gcorba.c (corba_init): Now returns an int with an error value. (corba_init_server): Initialize the server properly. Fixed all the object implementation code. (corba_create_window): New function used to create a window with the CORBA server. * gmain.c (gnome_check_super_user): Now the check for running as root is done here. There should be no GUI code in src/. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * dlg.c (dlg_run_done): Do not call the callback of a NULL current widget. * setup.h: Added missing prototype for setup_init(). * filegui.c (check_progress_buttons): Added a missing return value. * dlg.c (remove_widget): Added a missing return value. * main.c: Removed the global directory_list variable. Removed the main_corba_register_server() function. * main.h: Removed the global run_desktop variable. * panel.h: Now the panel structure has a unique numerical ID used for session management. * screen.c (panel_new): Maintain a unique ID for each panel. * main.c (maybe_display_linksdir): Handle display of the desktop init dir here. (main): Call gnome_check_super_user(). (init_corba_with_args): Call corba_init_server(). * main.c (init_corba_with_args): Do CORBA initialization here. Also removed the global force_activation option. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * vfs.c (vfs_add_current_stamps): Only do stamping of the panels if they exist. * mcserv.c: #include <sys/wait.h> (get_client): Put `#ifdef __EMX__' around an otherwise-unused variable. * utilvfs.c (vfs_split_url): Fix NULL <-> 0 confusion when comparing characters. * ftpfs.c (retrieve_dir): Removed unused variable dot_dot_found. * extfs.c (extfs_init): Assign `key' to c, not `&key'.
1999-03-30 10:09:56 +04:00
panel->search_buffer[0] = 0;
1998-02-27 07:54:42 +03:00
panel->frame_size = frame_half;
section = g_strconcat ("Temporal:", panel->panel_name, (char *) NULL);
if (!profile_has_section (section, profile_name)) {
g_free (section);
section = g_strdup (panel->panel_name);
1998-02-27 07:54:42 +03:00
}
panel_load_setup (panel, section);
g_free (section);
1998-02-27 07:54:42 +03:00
/* Load format strings */
err = set_panel_formats (panel);
if (err) {
1998-02-27 07:54:42 +03:00
set_panel_formats (panel);
}
These are a bunch of changes to fix CORBA and session management. They are almost complete (i.e. to handle all nitty gritty cases), but they seem to be working OK right now. SM should be much more stable now. Please tell me if you find any weird behavior - Federico 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdesktop-icon.c (desktop_icon_realize): Remove the WM_CLIENT_LEADER property from icon windows so that window managers will not store SM information for them. * gnome-open-dialog.c: Added missing #includes. * gdesktop-init.c (desktop_init_at): Removed an unused variable. * gdesktop.h: Added some missing prototypes. * gmain.h: Added some missing prototypes. * Makefile.in: Added gsession.[ch] to the list of sources. * gmain.c (create_panels): Consider whether we have a CORBA server and session management. * gdesktop.c: #include "gdesktop-init.h" * gdesktop.c: Added a missing cast to GNOME_DIALOG. * gmain.c (create_panels): Removed the run_desktop global variable. * glayout.c (create_container): Set the wmclass of the panel to include its unique ID. * gsession.[ch]: New file with the functions that deal with session management. * glayout.c (gnome_exit): Use session_set_restart(). * gcorba.c (corba_init): Now returns an int with an error value. (corba_init_server): Initialize the server properly. Fixed all the object implementation code. (corba_create_window): New function used to create a window with the CORBA server. * gmain.c (gnome_check_super_user): Now the check for running as root is done here. There should be no GUI code in src/. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * dlg.c (dlg_run_done): Do not call the callback of a NULL current widget. * setup.h: Added missing prototype for setup_init(). * filegui.c (check_progress_buttons): Added a missing return value. * dlg.c (remove_widget): Added a missing return value. * main.c: Removed the global directory_list variable. Removed the main_corba_register_server() function. * main.h: Removed the global run_desktop variable. * panel.h: Now the panel structure has a unique numerical ID used for session management. * screen.c (panel_new): Maintain a unique ID for each panel. * main.c (maybe_display_linksdir): Handle display of the desktop init dir here. (main): Call gnome_check_super_user(). (init_corba_with_args): Call corba_init_server(). * main.c (init_corba_with_args): Do CORBA initialization here. Also removed the global force_activation option. 1999-03-30 Federico Mena Quintero <federico@nuclecu.unam.mx> * vfs.c (vfs_add_current_stamps): Only do stamping of the panels if they exist. * mcserv.c: #include <sys/wait.h> (get_client): Put `#ifdef __EMX__' around an otherwise-unused variable. * utilvfs.c (vfs_split_url): Fix NULL <-> 0 confusion when comparing characters. * ftpfs.c (retrieve_dir): Removed unused variable dot_dot_found. * extfs.c (extfs_init): Assign `key' to c, not `&key'.
1999-03-30 10:09:56 +04:00
1998-02-27 07:54:42 +03:00
/* Load the default format */
panel->count =
do_load_dir (panel->cwd, &panel->dir, panel->sort_type,
panel->reverse, panel->case_sensitive, panel->filter);
1998-02-27 07:54:42 +03:00
return panel;
}
void
panel_reload (WPanel *panel)
{
struct stat current_stat;
if (fast_reload && !stat (panel->cwd, &current_stat)
1998-02-27 07:54:42 +03:00
&& current_stat.st_ctime == panel->dir_stat.st_ctime
&& current_stat.st_mtime == panel->dir_stat.st_mtime)
return;
while (mc_chdir (panel->cwd) == -1) {
1998-02-27 07:54:42 +03:00
char *last_slash;
if (panel->cwd[0] == PATH_SEP && panel->cwd[1] == 0) {
panel_clean_dir (panel);
1998-02-27 07:54:42 +03:00
panel->count = set_zero_dir (&panel->dir);
return;
}
last_slash = strrchr (panel->cwd, PATH_SEP);
if (!last_slash || last_slash == panel->cwd)
strcpy (panel->cwd, PATH_SEP_STR);
else
*last_slash = 0;
memset (&(panel->dir_stat), 0, sizeof (panel->dir_stat));
1998-02-27 07:54:42 +03:00
show_dir (panel);
}
panel->count =
do_reload_dir (panel->cwd, &panel->dir, panel->sort_type,
panel->count, panel->reverse, panel->case_sensitive,
panel->filter);
panel->dirty = 1;
if (panel->selected >= panel->count)
do_select (panel, panel->count - 1);
recalculate_panel_summary (panel);
1998-02-27 07:54:42 +03:00
}
static void
1998-02-27 07:54:42 +03:00
paint_frame (WPanel *panel)
{
int header_len;
int spaces, extra;
int side, width;
const char *txt;
1998-02-27 07:54:42 +03:00
if (!panel->split)
adjust_top_file (panel);
1998-02-27 07:54:42 +03:00
widget_erase (&panel->widget);
show_dir (panel);
widget_move (&panel->widget, 1, 1);
for (side = 0; side <= panel->split; side++){
format_e *format;
1998-02-27 07:54:42 +03:00
if (side){
attrset (NORMAL_COLOR);
one_vline ();
width = panel->widget.cols - panel->widget.cols/2 - 1;
} else if (panel->split)
width = panel->widget.cols/2 - 3;
else
width = panel->widget.cols - 2;
1998-02-27 07:54:42 +03:00
for (format = panel->format; format; format = format->next){
if (format->string_fn){
txt = format->title;
1998-02-27 07:54:42 +03:00
header_len = strlen (txt);
if (header_len > format->field_len)
header_len = format->field_len;
1998-02-27 07:54:42 +03:00
attrset (MARKED_COLOR);
spaces = (format->field_len - header_len) / 2;
extra = (format->field_len - header_len) % 2;
printw ("%*s%.*s%*s", spaces, "",
header_len, txt, spaces+extra, "");
1998-02-27 07:54:42 +03:00
width -= 2 * spaces + extra + header_len;
} else {
attrset (NORMAL_COLOR);
one_vline ();
width --;
continue;
}
}
1998-02-27 07:54:42 +03:00
if (width > 0)
printw ("%*s", width, "");
}
}
static const char *
parse_panel_size (WPanel *panel, const char *format, int isstatus)
1998-02-27 07:54:42 +03:00
{
int frame = frame_half;
format = skip_separators (format);
if (!strncmp (format, "full", 4)){
frame = frame_full;
format += 4;
} else if (!strncmp (format, "half", 4)){
frame = frame_half;
format += 4;
}
if (!isstatus){
panel->frame_size = frame;
panel->split = 0;
}
1998-02-27 07:54:42 +03:00
/* Now, the optional column specifier */
format = skip_separators (format);
1998-02-27 07:54:42 +03:00
if (*format == '1' || *format == '2'){
if (!isstatus)
panel->split = *format == '2';
format++;
}
if (!isstatus)
panel_update_cols (&(panel->widget), panel->frame_size);
1998-02-27 07:54:42 +03:00
return skip_separators (format);
}
/* Format is:
all := panel_format? format
panel_format := [full|half] [1|2]
format := one_format_e
| format , one_format_e
one_format_e := just format.id [opt_size]
just := [<=>]
1998-02-27 07:54:42 +03:00
opt_size := : size [opt_expand]
size := [0-9]+
opt_expand := +
1998-02-27 07:54:42 +03:00
*/
1998-12-03 00:27:27 +03:00
static format_e *
parse_display_format (WPanel *panel, const char *format, char **error, int isstatus, int *res_total_cols)
1998-02-27 07:54:42 +03:00
{
format_e *darr, *old = 0, *home = 0; /* The formats we return */
1998-02-27 07:54:42 +03:00
int total_cols = 0; /* Used columns by the format */
int set_justify; /* flag: set justification mode? */
int justify = 0; /* Which mode. */
int items = 0; /* Number of items in the format */
size_t i;
1998-02-27 07:54:42 +03:00
1999-04-30 16:41:41 +04:00
static size_t i18n_timelength = 0; /* flag: check ?Time length at startup */
1998-02-27 07:54:42 +03:00
*error = 0;
1999-04-30 16:41:41 +04:00
if (i18n_timelength == 0) {
i18n_timelength = i18n_checktimelength (); /* Musn't be 0 */
1999-04-30 16:41:41 +04:00
for (i = 0; i < ELEMENTS(formats); i++)
if (strcmp ("time", formats [i].id+1) == 0)
formats [i].min_size = i18n_timelength;
}
1998-02-27 07:54:42 +03:00
/*
* This makes sure that the panel and mini status full/half mode
* setting is equal
*/
format = parse_panel_size (panel, format, isstatus);
while (*format){ /* format can be an empty string */
1998-02-27 07:54:42 +03:00
int found = 0;
darr = g_new (format_e, 1);
1998-02-27 07:54:42 +03:00
/* I'm so ugly, don't look at me :-) */
if (!home)
home = old = darr;
1998-02-27 07:54:42 +03:00
old->next = darr;
darr->next = 0;
old = darr;
1998-02-27 07:54:42 +03:00
format = skip_separators (format);
if (strchr ("<=>", *format)){
1998-02-27 07:54:42 +03:00
set_justify = 1;
switch (*format)
{
case '<':
justify = J_LEFT;
break;
case '=':
justify = J_CENTER;
break;
case '>':
default:
justify = J_RIGHT;
break;
}
1998-02-27 07:54:42 +03:00
format = skip_separators (format+1);
} else
set_justify = 0;
1998-02-27 07:54:42 +03:00
for (i = 0; i < ELEMENTS(formats); i++){
int klen = strlen (formats [i].id);
if (strncmp (format, formats [i].id, klen) != 0)
continue;
format += klen;
if (formats [i].use_in_gui)
items++;
darr->requested_field_len = formats [i].min_size;
darr->string_fn = formats [i].string_fn;
if (formats [i].title [0])
darr->title = _(formats [i].title);
else
darr->title = "";
1998-02-27 07:54:42 +03:00
darr->id = formats [i].id;
darr->expand = formats [i].expands;
darr->just_mode = formats [i].default_just;
if (set_justify) {
if (IS_FIT(darr->just_mode))
darr->just_mode = MAKE_FIT(justify);
else
darr->just_mode = justify;
}
1998-02-27 07:54:42 +03:00
found = 1;
format = skip_separators (format);
/* If we have a size specifier */
if (*format == ':'){
int req_length;
/* If the size was specified, we don't want
* auto-expansion by default
*/
darr->expand = 0;
format++;
req_length = atoi (format);
darr->requested_field_len = req_length;
format = skip_numbers (format);
/* Now, if they insist on expansion */
if (*format == '+'){
darr->expand = 1;
format++;
}
}
break;
}
if (!found){
char *tmp_format = g_strdup (format);
1998-02-27 07:54:42 +03:00
int pos = min (8, strlen (format));
delete_format (home);
tmp_format [pos] = 0;
*error = g_strconcat (_("Unknown tag on display format: "), tmp_format, (char *) NULL);
g_free (tmp_format);
1998-02-27 07:54:42 +03:00
return 0;
}
total_cols += darr->requested_field_len;
}
1998-02-27 07:54:42 +03:00
*res_total_cols = total_cols;
return home;
}
static format_e *
use_display_format (WPanel *panel, const char *format, char **error, int isstatus)
1998-02-27 07:54:42 +03:00
{
#define MAX_EXPAND 4
int expand_top = 0; /* Max used element in expand */
int usable_columns; /* Usable columns in the panel */
int total_cols;
const char *expand_list [MAX_EXPAND]; /* Expand at most 4 fields. */
1998-02-27 07:54:42 +03:00
int i;
format_e *darr, *home;
1998-02-27 07:54:42 +03:00
if (!format)
format = DEFAULT_USER_FORMAT;
1998-02-27 07:54:42 +03:00
home = parse_display_format (panel, format, error, isstatus, &total_cols);
if (*error)
return 0;
panel->dirty = 1;
1998-02-27 07:54:42 +03:00
/* Status needn't to be split */
usable_columns = ((panel->widget.cols-2)/((isstatus)
? 1
: (panel->split+1))) - (!isstatus && panel->split);
1998-02-27 07:54:42 +03:00
/* Clean expand list */
for (i = 0; i < MAX_EXPAND; i++)
expand_list [i] = '\0';
1998-02-27 07:54:42 +03:00
/* Look for the expandable fields and set field_len based on the requested field len */
for (darr = home; darr && expand_top < MAX_EXPAND; darr = darr->next){
darr->field_len = darr->requested_field_len;
if (darr->expand)
expand_list [expand_top++] = darr->id;
}
1998-02-27 07:54:42 +03:00
/* If we used more columns than the available columns, adjust that */
if (total_cols > usable_columns){
int pdif, dif = total_cols - usable_columns;
1998-02-27 07:54:42 +03:00
while (dif){
pdif = dif;
for (darr = home; darr; darr = darr->next){
if (dif && darr->field_len - 1){
darr->field_len--;
dif--;
}
}
/* avoid endless loop if num fields > 40 */
if (pdif == dif)
break;
1998-02-27 07:54:42 +03:00
}
total_cols = usable_columns; /* give up, the rest should be truncated */
}
/* Expand the available space */
if ((usable_columns > total_cols) && expand_top){
int spaces = (usable_columns - total_cols) / expand_top;
int extra = (usable_columns - total_cols) % expand_top;
for (i = 0, darr = home; darr && (i < expand_top); darr = darr->next)
if (darr->expand){
darr->field_len += (spaces + ((i == 0) ? extra : 0));
i++;
}
}
return home;
}
/* Switches the panel to the mode specified in the format */
/* Seting up both format and status string. Return: 0 - on success; */
/* 1 - format error; 2 - status error; 3 - errors in both formats. */
int
set_panel_formats (WPanel *p)
{
format_e *form;
char *err;
1998-02-27 07:54:42 +03:00
int retcode = 0;
1998-02-27 07:54:42 +03:00
form = use_display_format (p, panel_format (p), &err, 0);
1998-02-27 07:54:42 +03:00
if (err){
g_free (err);
1998-02-27 07:54:42 +03:00
retcode = 1;
}
else {
if (p->format)
delete_format (p->format);
1998-02-27 07:54:42 +03:00
p->format = form;
}
1998-02-27 07:54:42 +03:00
if (show_mini_info){
1998-02-27 07:54:42 +03:00
form = use_display_format (p, mini_status_format (p), &err, 1);
1998-02-27 07:54:42 +03:00
if (err){
g_free (err);
1998-02-27 07:54:42 +03:00
retcode += 2;
}
else {
if (p->status_format)
delete_format (p->status_format);
1998-02-27 07:54:42 +03:00
p->status_format = form;
}
}
1998-02-27 07:54:42 +03:00
panel_format_modified (p);
panel_update_cols (&(p->widget), p->frame_size);
if (retcode)
message( 1, _("Warning" ), _( "User supplied format looks invalid, reverting to default." ) );
if (retcode & 0x01){
g_free (p->user_format);
p->user_format = g_strdup (DEFAULT_USER_FORMAT);
}
if (retcode & 0x02){
g_free (p->user_status_format [p->list_type]);
p->user_status_format [p->list_type] = g_strdup (DEFAULT_USER_FORMAT);
}
1998-02-27 07:54:42 +03:00
return retcode;
}
/* Given the panel->view_type returns the format string to be parsed */
static const char *
1998-02-27 07:54:42 +03:00
panel_format (WPanel *panel)
{
switch (panel->list_type){
case list_long:
return "full perm space nlink space owner space group space size space mtime space name";
1998-02-27 07:54:42 +03:00
case list_brief:
return "half 2 type name";
1998-02-27 07:54:42 +03:00
case list_user:
return panel->user_format;
default:
case list_full:
return "half type name | size | mtime";
1998-02-27 07:54:42 +03:00
}
}
static const char *
1998-02-27 07:54:42 +03:00
mini_status_format (WPanel *panel)
{
if (panel->user_mini_status)
return panel->user_status_format [panel->list_type];
switch (panel->list_type){
case list_long:
return "full perm space nlink space owner space group space size space mtime space name";
1998-02-27 07:54:42 +03:00
case list_brief:
return "half type name space bsize space perm space";
1998-02-27 07:54:42 +03:00
case list_full:
return "half type name";
1998-02-27 07:54:42 +03:00
default:
case list_user:
return panel->user_format;
}
}
/* */
/* Panel operation commands */
/* */
/* Returns the number of items in the given panel */
static int
1998-02-27 07:54:42 +03:00
ITEMS (WPanel *p)
{
if (p->split)
return llines (p) * 2;
else
return llines (p);
}
/* Select current item and readjust the panel */
1998-02-27 07:54:42 +03:00
void
select_item (WPanel *panel)
{
int items = ITEMS (panel);
1998-02-27 07:54:42 +03:00
/* Although currently all over the code we set the selection and
top file to decent values before calling select_item, I could
forget it someday, so it's better to do the actual fitting here */
if (panel->top_file < 0)
1998-02-27 07:54:42 +03:00
panel->top_file = 0;
if (panel->selected < 0)
panel->selected = 0;
if (panel->selected > panel->count - 1)
1998-02-27 07:54:42 +03:00
panel->selected = panel->count - 1;
if (panel->top_file > panel->count - 1)
panel->top_file = panel->count - 1;
if ((panel->count - panel->top_file) < items) {
1998-02-27 07:54:42 +03:00
panel->top_file = panel->count - items;
if (panel->top_file < 0)
panel->top_file = 0;
}
if (panel->selected < panel->top_file)
1998-02-27 07:54:42 +03:00
panel->top_file = panel->selected;
if ((panel->selected - panel->top_file) >= items)
1998-02-27 07:54:42 +03:00
panel->top_file = panel->selected - items + 1;
panel->dirty = 1;
1998-02-27 07:54:42 +03:00
execute_hooks (select_file_hook);
}
/* Clears all files in the panel, used only when one file was marked */
void
unmark_files (WPanel *panel)
{
int i;
if (!panel->marked)
return;
for (i = 0; i < panel->count; i++)
file_mark (panel, i, 0);
panel->dirs_marked = 0;
panel->marked = 0;
panel->total = 0;
}
static void
1998-02-27 07:54:42 +03:00
unselect_item (WPanel *panel)
{
repaint_file (panel, panel->selected, 1, 2*selection (panel)->f.marked, 0);
}
static void
move_down (WPanel *panel)
1998-02-27 07:54:42 +03:00
{
if (panel->selected+1 == panel->count)
return;
1998-02-27 07:54:42 +03:00
unselect_item (panel);
panel->selected++;
if (panel->selected - panel->top_file == ITEMS (panel) &&
panel_scroll_pages){
/* Scroll window half screen */
panel->top_file += ITEMS (panel)/2;
if (panel->top_file > panel->count - ITEMS (panel))
panel->top_file = panel->count - ITEMS (panel);
paint_dir (panel);
select_item (panel);
}
select_item (panel);
}
static void
move_up (WPanel *panel)
1998-02-27 07:54:42 +03:00
{
if (panel->selected == 0)
return;
unselect_item (panel);
panel->selected--;
if (panel->selected < panel->top_file && panel_scroll_pages){
/* Scroll window half screen */
panel->top_file -= ITEMS (panel)/2;
if (panel->top_file < 0) panel->top_file = 0;
paint_dir (panel);
}
select_item (panel);
}
/* Changes the selection by lines (may be negative) */
static void
move_selection (WPanel *panel, int lines)
{
int new_pos;
int adjust = 0;
new_pos = panel->selected + lines;
if (new_pos >= panel->count)
new_pos = panel->count-1;
if (new_pos < 0)
new_pos = 0;
unselect_item (panel);
panel->selected = new_pos;
if (panel->selected - panel->top_file >= ITEMS (panel)){
panel->top_file += lines;
adjust = 1;
}
1998-02-27 07:54:42 +03:00
if (panel->selected - panel->top_file < 0){
panel->top_file += lines;
adjust = 1;
}
1998-02-27 07:54:42 +03:00
if (adjust){
if (panel->top_file > panel->selected)
panel->top_file = panel->selected;
if (panel->top_file < 0)
panel->top_file = 0;
paint_dir (panel);
}
select_item (panel);
}
static cb_ret_t
1998-02-27 07:54:42 +03:00
move_left (WPanel *panel, int c_code)
{
if (panel->split) {
move_selection (panel, -llines (panel));
return MSG_HANDLED;
} else
return maybe_cd (c_code, 0);
1998-02-27 07:54:42 +03:00
}
static int
move_right (WPanel *panel, int c_code)
{
if (panel->split) {
move_selection (panel, llines (panel));
return MSG_HANDLED;
} else
return maybe_cd (c_code, 1);
1998-02-27 07:54:42 +03:00
}
static void
prev_page (WPanel *panel)
{
int items;
if (!panel->selected && !panel->top_file)
return;
unselect_item (panel);
items = ITEMS (panel);
if (panel->top_file < items)
items = panel->top_file;
if (!items)
panel->selected = 0;
else
panel->selected -= items;
panel->top_file -= items;
/* This keeps the selection in a reasonable place */
if (panel->selected < 0)
panel->selected = 0;
if (panel->top_file < 0)
panel->top_file = 0;
select_item (panel);
paint_dir (panel);
}
static void
ctrl_prev_page (WPanel *panel)
1998-02-27 07:54:42 +03:00
{
do_cd ("..", cd_exact);
1998-02-27 07:54:42 +03:00
}
static void
next_page (WPanel *panel)
{
int items;
if (panel->selected == panel->count - 1)
return;
1998-02-27 07:54:42 +03:00
unselect_item (panel);
items = ITEMS (panel);
if (panel->top_file > panel->count - 2 * items)
items = panel->count - items - panel->top_file;
1998-02-27 07:54:42 +03:00
if (panel->top_file + items < 0)
items = -panel->top_file;
1998-02-27 07:54:42 +03:00
if (!items)
panel->selected = panel->count - 1;
1998-02-27 07:54:42 +03:00
else
panel->selected += items;
1998-02-27 07:54:42 +03:00
panel->top_file += items;
/* This keeps the selection in it's relative position */
if (panel->selected >= panel->count)
panel->selected = panel->count - 1;
if (panel->top_file >= panel->count)
panel->top_file = panel->count - 1;
select_item (panel);
paint_dir (panel);
}
static void
ctrl_next_page (WPanel *panel)
1998-02-27 07:54:42 +03:00
{
if ((S_ISDIR (selection (panel)->st.st_mode)
|| link_isdir (selection (panel)))) {
do_cd (selection (panel)->fname, cd_exact);
}
1998-02-27 07:54:42 +03:00
}
static void
goto_top_file (WPanel *panel)
{
unselect_item (panel);
panel->selected = panel->top_file;
select_item (panel);
}
static void
goto_middle_file (WPanel *panel)
{
unselect_item (panel);
panel->selected = panel->top_file + (ITEMS (panel)/2);
if (panel->selected >= panel->count)
panel->selected = panel->count - 1;
select_item (panel);
}
static void
goto_bottom_file (WPanel *panel)
{
unselect_item (panel);
panel->selected = panel->top_file + ITEMS (panel)-1;
if (panel->selected >= panel->count)
panel->selected = panel->count - 1;
select_item (panel);
}
static void
move_home (WPanel *panel)
{
if (panel->selected == 0)
return;
unselect_item (panel);
1998-02-27 07:54:42 +03:00
if (torben_fj_mode){
int middle_pos = panel->top_file + (ITEMS (panel)/2);
if (panel->selected > middle_pos){
goto_middle_file (panel);
return;
}
if (panel->selected != panel->top_file){
goto_top_file (panel);
return;
}
}
1998-02-27 07:54:42 +03:00
panel->top_file = 0;
panel->selected = 0;
paint_dir (panel);
select_item (panel);
}
static void
move_end (WPanel *panel)
{
if (panel->selected == panel->count-1)
return;
unselect_item (panel);
if (torben_fj_mode){
int middle_pos = panel->top_file + (ITEMS (panel)/2);
if (panel->selected < middle_pos){
goto_middle_file (panel);
return;
}
if (panel->selected != (panel->top_file + ITEMS(panel)-1)){
goto_bottom_file (panel);
return;
}
}
1998-02-27 07:54:42 +03:00
panel->selected = panel->count-1;
paint_dir (panel);
select_item (panel);
}
/* Recalculate the panels summary information, used e.g. when marked
files might have been removed by an external command */
void
recalculate_panel_summary (WPanel *panel)
{
int i;
panel->marked = 0;
panel->dirs_marked = 0;
panel->total = 0;
for (i = 0; i < panel->count; i++)
if (panel->dir.list [i].f.marked){
/* do_file_mark will return immediately if newmark == oldmark.
So we have to first unmark it to get panel's summary information
updated. (Norbert) */
panel->dir.list [i].f.marked = 0;
do_file_mark (panel, i, 1);
}
}
1998-02-27 07:54:42 +03:00
/* This routine marks a file or a directory */
void
do_file_mark (WPanel *panel, int idx, int mark)
{
if (panel->dir.list[idx].f.marked == mark)
return;
/* Only '..' can't be marked, '.' isn't visible */
if (!strcmp (panel->dir.list[idx].fname, ".."))
return;
file_mark (panel, idx, mark);
if (panel->dir.list[idx].f.marked) {
panel->marked++;
if (S_ISDIR (panel->dir.list[idx].st.st_mode)) {
if (panel->dir.list[idx].f.dir_size_computed)
panel->total += panel->dir.list[idx].st.st_size;
panel->dirs_marked++;
} else
panel->total += panel->dir.list[idx].st.st_size;
set_colors (panel);
} else {
if (S_ISDIR (panel->dir.list[idx].st.st_mode)) {
if (panel->dir.list[idx].f.dir_size_computed)
panel->total -= panel->dir.list[idx].st.st_size;
panel->dirs_marked--;
} else
panel->total -= panel->dir.list[idx].st.st_size;
panel->marked--;
1998-02-27 07:54:42 +03:00
}
}
static void
do_mark_file (WPanel *panel, int do_move)
{
do_file_mark (panel, panel->selected,
selection (panel)->f.marked ? 0 : 1);
1998-02-27 07:54:42 +03:00
if (mark_moves_down && do_move)
move_down (panel);
}
static void
mark_file (WPanel *panel)
{
do_mark_file (panel, 1);
}
/* Incremental search of a file name in the panel */
static void
do_search (WPanel *panel, int c_code)
{
size_t l;
int i;
1998-02-27 07:54:42 +03:00
int wrapped = 0;
int found;
l = strlen (panel->search_buffer);
if (c_code == KEY_BACKSPACE) {
if (l)
panel->search_buffer[--l] = '\0';
} else {
if (c_code && l < sizeof (panel->search_buffer)) {
panel->search_buffer[l] = c_code;
panel->search_buffer[l + 1] = 0;
1998-02-27 07:54:42 +03:00
l++;
}
}
found = 0;
for (i = panel->selected; !wrapped || i != panel->selected; i++) {
if (i >= panel->count) {
1998-02-27 07:54:42 +03:00
i = 0;
if (wrapped)
break;
wrapped = 1;
}
if (panel->
case_sensitive
? (strncmp (panel->dir.list[i].fname, panel->search_buffer, l)
== 0) : (g_strncasecmp (panel->dir.list[i].fname,
panel->search_buffer, l) == 0)) {
1998-02-27 07:54:42 +03:00
unselect_item (panel);
panel->selected = i;
select_item (panel);
found = 1;
break;
}
}
if (!found)
panel->search_buffer[--l] = 0;
1998-02-27 07:54:42 +03:00
paint_panel (panel);
}
static void
1998-02-27 07:54:42 +03:00
start_search (WPanel *panel)
{
if (panel->searching){
if (panel->selected+1 == panel->count)
panel->selected = 0;
else
move_down (panel);
1998-02-27 07:54:42 +03:00
do_search (panel, 0);
} else {
panel->searching = 1;
panel->search_buffer [0] = 0;
display_mini_info (panel);
mc_refresh ();
}
}
/* Return 1 if the Enter key has been processed, 0 otherwise */
static int
do_enter_on_file_entry (file_entry *fe)
1998-02-27 07:54:42 +03:00
{
char *full_name;
/*
* Directory or link to directory - change directory.
* Try the same for the entries on which mc_lstat() has failed.
*/
if (S_ISDIR (fe->st.st_mode) || link_isdir (fe)
|| (fe->st.st_mode == 0)) {
if (!do_cd (fe->fname, cd_exact))
message (1, MSG_ERROR, _("Cannot change directory"));
return 1;
}
/* Try associated command */
if (regex_command (fe->fname, "Open", 0) != 0)
return 1;
/* Check if the file is executable */
full_name = concat_dir_and_file (current_panel->cwd, fe->fname);
if (!is_exe (fe->st.st_mode) || !if_link_is_exe (full_name, fe)) {
g_free (full_name);
return 0;
}
g_free (full_name);
if (confirm_execute) {
if (query_dialog
(_(" The Midnight Commander "),
_(" Do you really want to execute? "), 0, 2, _("&Yes"),
_("&No")) != 0)
return 1;
}
#ifdef USE_VFS
if (!vfs_current_is_local ()) {
char *tmp;
int ret;
tmp = concat_dir_and_file (vfs_get_current_dir (), fe->fname);
ret = mc_setctl (tmp, VFS_SETCTL_RUN, NULL);
g_free (tmp);
/* We took action only if the dialog was shown or the execution
* was successful */
return confirm_execute || (ret == 0);
}
#endif
{
char *tmp = name_quote (fe->fname, 0);
char *cmd = g_strconcat (".", PATH_SEP_STR, tmp, (char *) NULL);
g_free (tmp);
shell_execute (cmd, 0);
g_free (cmd);
}
return 1;
}
static int
do_enter (WPanel *panel)
{
return do_enter_on_file_entry (selection (panel));
1998-02-27 07:54:42 +03:00
}
/*
* Make the current directory of the current panel also the current
* directory of the other panel. Put the other panel to the listing
* mode if needed. If the current panel is panelized, the other panel
* doesn't become panelized.
*/
1998-02-27 07:54:42 +03:00
static void
chdir_other_panel (WPanel *panel)
{
if (get_other_type () != view_listing) {
set_display_type (get_other_index (), view_listing);
}
1998-02-27 07:54:42 +03:00
do_panel_cd (other_panel, current_panel->cwd, cd_exact);
/* try to select current filename on the other panel */
if (!panel->is_panelized) {
try_to_select (other_panel, selection (panel)->fname);
}
1998-02-27 07:54:42 +03:00
}
static void
chdir_to_readlink (WPanel *panel)
{
char *new_dir;
if (get_other_type () != view_listing)
return;
if (S_ISLNK (panel->dir.list [panel->selected].st.st_mode)) {
1998-02-27 07:54:42 +03:00
char buffer [MC_MAXPATHLEN], *p;
int i;
struct stat st;
i = readlink (selection (panel)->fname, buffer, MC_MAXPATHLEN - 1);
1998-02-27 07:54:42 +03:00
if (i < 0)
return;
if (mc_stat (selection (panel)->fname, &st) < 0)
1998-02-27 07:54:42 +03:00
return;
buffer [i] = 0;
if (!S_ISDIR (st.st_mode)) {
1998-02-27 07:54:42 +03:00
p = strrchr (buffer, PATH_SEP);
if (p && !p[1]) {
*p = 0;
p = strrchr (buffer, PATH_SEP);
}
if (!p)
return;
p[1] = 0;
}
if (*buffer == PATH_SEP)
new_dir = g_strdup (buffer);
1998-02-27 07:54:42 +03:00
else
new_dir = concat_dir_and_file (panel->cwd, buffer);
1998-02-27 07:54:42 +03:00
change_panel ();
do_cd (new_dir, cd_exact);
change_panel ();
1998-02-27 07:54:42 +03:00
move_down (panel);
g_free (new_dir);
1998-02-27 07:54:42 +03:00
}
}
typedef void (*panel_key_callback) (WPanel *);
typedef struct {
int key_code;
panel_key_callback fn;
} panel_key_map;
static void cmd_do_enter(WPanel *wp) { (void) do_enter(wp); }
static void cmd_view_simple(WPanel *wp) { view_simple_cmd(); }
static void cmd_edit_new(WPanel *wp) { edit_cmd_new(); }
static void cmd_copy_local(WPanel *wp) { copy_cmd_local(); }
static void cmd_rename_local(WPanel *wp) { ren_cmd_local(); }
static void cmd_delete_local(WPanel *wp) { delete_cmd_local(); }
static void cmd_select(WPanel *wp) { select_cmd(); }
static void cmd_unselect(WPanel *wp) { unselect_cmd(); }
static void cmd_reverse_selection(WPanel *wp) { reverse_selection_cmd(); }
static const panel_key_map panel_keymap [] = {
1998-02-27 07:54:42 +03:00
{ KEY_DOWN, move_down },
{ KEY_UP, move_up },
/* The action button :-) */
{ '\n', cmd_do_enter },
{ KEY_ENTER, cmd_do_enter },
1998-02-27 07:54:42 +03:00
{ KEY_IC, mark_file },
{ KEY_HOME, move_home },
{ KEY_A1, move_home },
{ ALT ('<'), move_home },
1998-02-27 07:54:42 +03:00
{ KEY_C1, move_end },
{ KEY_END, move_end },
{ ALT ('>'), move_end },
{ KEY_NPAGE, next_page },
{ KEY_PPAGE, prev_page },
{ KEY_NPAGE | KEY_M_CTRL, ctrl_next_page },
{ KEY_PPAGE | KEY_M_CTRL, ctrl_prev_page },
1998-02-27 07:54:42 +03:00
/* To quickly move in the panel */
{ ALT('g'), goto_top_file },
{ ALT('r'), goto_middle_file }, /* M-r like emacs */
{ ALT('j'), goto_bottom_file },
/* Emacs-like bindings */
{ XCTRL('v'), next_page }, /* C-v like emacs */
{ ALT('v'), prev_page }, /* M-v like emacs */
{ XCTRL('p'), move_up }, /* C-p like emacs */
{ XCTRL('n'), move_down }, /* C-n like emacs */
{ XCTRL('s'), start_search }, /* C-s like emacs */
{ ALT('s'), start_search }, /* M-s not like emacs */
{ XCTRL('t'), mark_file },
{ ALT('o'), chdir_other_panel },
{ ALT('l'), chdir_to_readlink },
{ ALT('H'), directory_history_list },
{ KEY_F(13), cmd_view_simple },
{ KEY_F(14), cmd_edit_new },
{ KEY_F(15), cmd_copy_local },
{ KEY_F(16), cmd_rename_local },
{ KEY_F(18), cmd_delete_local },
{ ALT('y'), directory_history_prev },
{ ALT('u'), directory_history_next },
{ ALT('+'), cmd_select },
{ KEY_KP_ADD, cmd_select },
{ ALT('\\'), cmd_unselect },
{ ALT('-'), cmd_unselect },
{ KEY_KP_SUBTRACT, cmd_unselect },
{ ALT('*'), cmd_reverse_selection },
{ KEY_KP_MULTIPLY, cmd_reverse_selection },
1998-02-27 07:54:42 +03:00
{ 0, 0 }
};
static inline cb_ret_t
1998-02-27 07:54:42 +03:00
panel_key (WPanel *panel, int key)
{
int i;
for (i = 0; panel_keymap[i].key_code; i++) {
if (key == panel_keymap[i].key_code) {
int old_searching = panel->searching;
if (panel_keymap[i].fn != start_search)
panel->searching = 0;
(*panel_keymap[i].fn) (panel);
if (panel->searching != old_searching)
display_mini_info (panel);
return MSG_HANDLED;
1998-02-27 07:54:42 +03:00
}
}
if (torben_fj_mode && key == ALT ('h')) {
1998-02-27 07:54:42 +03:00
goto_middle_file (panel);
return MSG_HANDLED;
}
1998-02-27 07:54:42 +03:00
/* We do not want to take a key press if nothing can be done with it */
2003-06-02 23:26:55 +04:00
/* The command line widget may do something more useful */
1998-02-27 07:54:42 +03:00
if (key == KEY_LEFT)
return move_left (panel, key);
if (key == KEY_RIGHT)
return move_right (panel, key);
1998-02-27 07:54:42 +03:00
if (is_abort_char (key)) {
panel->searching = 0;
display_mini_info (panel);
return MSG_HANDLED;
1998-02-27 07:54:42 +03:00
}
/* Do not eat characters not meant for the panel below ' ' (e.g. C-l). */
if ((key >= ' ' && key <= 255) || key == KEY_BACKSPACE) {
if (panel->searching) {
do_search (panel, key);
return MSG_HANDLED;
}
if (!command_prompt) {
start_search (panel);
do_search (panel, key);
return MSG_HANDLED;
1998-02-27 07:54:42 +03:00
}
}
return MSG_NOT_HANDLED;
1998-02-27 07:54:42 +03:00
}
static cb_ret_t
panel_callback (WPanel *panel, widget_msg_t msg, int parm)
1998-02-27 07:54:42 +03:00
{
Dlg_head *h = panel->widget.parent;
switch (msg) {
1998-02-27 07:54:42 +03:00
case WIDGET_DRAW:
paint_panel (panel);
return MSG_HANDLED;
1998-02-27 07:54:42 +03:00
case WIDGET_FOCUS:
current_panel = panel;
1998-02-27 07:54:42 +03:00
panel->active = 1;
if (mc_chdir (panel->cwd) != 0) {
char *cwd = strip_password (g_strdup (panel->cwd), 1);
message (1, MSG_ERROR, _(" Cannot chdir to \"%s\" \n %s "),
cwd, unix_error_string (errno));
g_free(cwd);
} else
subshell_chdir (panel->cwd);
update_xterm_title_path ();
select_item (panel);
show_dir (panel);
paint_dir (panel);
define_label (h, 1, _("Help"), help_cmd);
define_label (h, 2, _("Menu"), user_file_menu_cmd);
define_label (h, 3, _("View"), view_cmd);
define_label (h, 4, _("Edit"), edit_cmd);
define_label (h, 5, _("Copy"), copy_cmd);
define_label (h, 6, _("RenMov"), ren_cmd);
define_label (h, 7, _("Mkdir"), mkdir_cmd);
define_label (h, 8, _("Delete"), delete_cmd);
redraw_labels (h);
return MSG_HANDLED;
1998-02-27 07:54:42 +03:00
case WIDGET_UNFOCUS:
/* Janne: look at this for the multiple panel options */
if (panel->searching){
panel->searching = 0;
display_mini_info (panel);
}
panel->active = 0;
show_dir (panel);
unselect_item (panel);
return MSG_HANDLED;
1998-02-27 07:54:42 +03:00
case WIDGET_KEY:
return panel_key (panel, parm);
case WIDGET_DESTROY:
panel_destroy (panel);
return MSG_HANDLED;
default:
return default_proc (msg, parm);
1998-02-27 07:54:42 +03:00
}
}
void
file_mark (WPanel *panel, int index, int val)
{
if (panel->dir.list[index].f.marked != val) {
panel->dir.list[index].f.marked = val;
panel->dirty = 1;
}
}
1998-02-27 07:54:42 +03:00
/* */
/* Panel mouse events support routines */
/* */
static int mouse_marking = 0;
static void
mouse_toggle_mark (WPanel *panel)
{
do_mark_file (panel, 0);
mouse_marking = selection (panel)->f.marked;
}
static void
mouse_set_mark (WPanel *panel)
{
if (mouse_marking && !(selection (panel)->f.marked))
do_mark_file (panel, 0);
else if (!mouse_marking && (selection (panel)->f.marked))
do_mark_file (panel, 0);
}
static inline int
mark_if_marking (WPanel *panel, Gpm_Event *event)
{
if (event->buttons & GPM_B_RIGHT){
if (event->type & GPM_DOWN)
mouse_toggle_mark (panel);
else
mouse_set_mark (panel);
return 1;
}
return 0;
}
/*
* Mouse callback of the panel minus repainting.
* If the event is redirected to the menu, *redir is set to 1.
*/
static int
do_panel_event (Gpm_Event *event, WPanel *panel, int *redir)
1998-02-27 07:54:42 +03:00
{
const int lines = llines (panel);
1998-02-27 07:54:42 +03:00
int my_index;
/* Mouse wheel events */
if ((event->buttons & GPM_B_UP) && (event->type & GPM_DOWN)) {
prev_page (panel);
return MOU_NORMAL;
}
if ((event->buttons & GPM_B_DOWN) && (event->type & GPM_DOWN)) {
next_page (panel);
return MOU_NORMAL;
}
/* "<" button */
if (event->type & GPM_DOWN && event->x == 2 && event->y == 1) {
directory_history_prev (panel);
return MOU_NORMAL;
}
/* ">" button */
if (event->type & GPM_DOWN && event->x == panel->widget.cols - 1
&& event->y == 1) {
directory_history_next (panel);
return MOU_NORMAL;
}
/* "v" button */
if (event->type & GPM_DOWN && event->x == panel->widget.cols - 2
&& event->y == 1) {
directory_history_list (panel);
return MOU_NORMAL;
}
/* rest of the upper frame, the menu is invisible - call menu */
if (event->type & GPM_DOWN && event->y == 1 && !menubar_visible) {
*redir = 1;
event->x += panel->widget.x;
return (*(the_menubar->widget.mouse)) (event, the_menubar);
}
1998-02-27 07:54:42 +03:00
event->y -= 2;
if ((event->type & (GPM_DOWN | GPM_DRAG))) {
1998-02-27 07:54:42 +03:00
if (!dlg_widget_active (panel))
1998-02-27 07:54:42 +03:00
change_panel ();
if (event->y <= 0) {
1998-02-27 07:54:42 +03:00
mark_if_marking (panel, event);
if (mouse_move_pages)
prev_page (panel);
else
move_up (panel);
return MOU_REPEAT;
}
if (!((panel->top_file + event->y <= panel->count)
&& event->y <= lines)) {
1998-02-27 07:54:42 +03:00
mark_if_marking (panel, event);
if (mouse_move_pages)
next_page (panel);
else
move_down (panel);
return MOU_REPEAT;
}
my_index = panel->top_file + event->y - 1;
if (panel->split) {
if (event->x > ((panel->widget.cols - 2) / 2))
1998-02-27 07:54:42 +03:00
my_index += llines (panel);
}
if (my_index >= panel->count)
my_index = panel->count - 1;
if (my_index != panel->selected) {
1998-02-27 07:54:42 +03:00
unselect_item (panel);
panel->selected = my_index;
select_item (panel);
}
/* This one is new */
mark_if_marking (panel, event);
} else if ((event->type & (GPM_UP | GPM_DOUBLE)) ==
(GPM_UP | GPM_DOUBLE)) {
if (event->y > 0 && event->y <= lines)
do_enter (panel);
1998-02-27 07:54:42 +03:00
}
return MOU_NORMAL;
}
/* Mouse callback of the panel */
static int
panel_event (Gpm_Event *event, WPanel *panel)
{
int ret;
int redir = 0;
ret = do_panel_event (event, panel, &redir);
if (!redir)
panel_update_contents (panel);
return ret;
}
void
panel_re_sort (WPanel *panel)
{
char *filename;
int i;
if (panel == NULL)
return;
filename = g_strdup (selection (panel)->fname);
unselect_item (panel);
do_sort (&panel->dir, panel->sort_type, panel->count-1, panel->reverse, panel->case_sensitive);
panel->selected = -1;
for (i = panel->count; i; i--){
if (!strcmp (panel->dir.list [i-1].fname, filename)){
panel->selected = i-1;
break;
}
}
g_free (filename);
panel->top_file = panel->selected - ITEMS (panel)/2;
if (panel->top_file < 0)
panel->top_file = 0;
select_item (panel);
panel->dirty = 1;
}
void
panel_set_sort_order (WPanel *panel, sortfn *sort_order)
{
if (sort_order == 0)
return;
panel->sort_type = sort_order;
/* The directory is already sorted, we have to load the unsorted stuff */
if (sort_order == (sortfn *) unsorted){
char *current_file;
current_file = g_strdup (panel->dir.list [panel->selected].fname);
panel_reload (panel);
try_to_select (panel, current_file);
g_free (current_file);
}
panel_re_sort (panel);
}