Mercurial > hg > xemacs-beta
view netinstall/install.cc @ 4477:e34711681f30
Don't determine whether to call general device-type code at startup,
rather decide in the device-specific code itself.
lisp/ChangeLog addition:
2008-07-07 Aidan Kehoe <kehoea@parhasard.net>
Patch to make it up to the device-specific code whether
various Lisp functions should be called during device creation,
not relying on the startup code to decide this. Also, rename
initial-window-system to initial-device-type (which makes more
sense in this scheme), always set it.
* startup.el (command-line):
Use initial-device-type, not initial-window-system; just call
#'make-device, leave the special behaviour to be done the first
time a console type is initialised to be decided on by the
respective console code.
* x-init.el (x-app-defaults-directory): Declare that it should be
bound.
(x-define-dead-key): Have the macro take a DEVICE argument.
(x-initialize-compose): Have the function take a DEVICE argument,
and use it when checking if various keysyms are available on the
keyboard.
(x-initialize-keyboard): Have the function take a DEVICE argument,
allowing device-specific keyboard initialisation.
(make-device-early-x-entry-point-called-p): New.
(make-device-late-x-entry-point-called-p): New. Rename
pre-x-win-initted, x-win-initted.
(make-device-early-x-entry-point): Rename init-pre-x-win, take the
call to make-x-device out (it should be called from the
device-creation code, not vice-versa).
(make-device-late-x-entry-point): Rename init-post-x-win, have it
take a DEVICE argument, use that DEVICE argument when working out
what device-specific things need doing. Don't use
create-console-hook in core code.
* x-win-xfree86.el (x-win-init-xfree86): Take a DEVICE argument;
use it.
* x-win-sun.el (x-win-init-sun): Take a DEVICE argument; use it.
* mule/mule-x-init.el: Remove #'init-mule-x-win, an empty
function.
* tty-init.el (make-device-early-tty-entry-point-called-p): New.
Rename pre-tty-win-initted.
(make-device-early-tty-entry-point): New.
Rename init-pre-tty-win.
(make-frame-after-init-entry-point): New.
Rename init-post-tty-win to better reflect when it's called.
* gtk-init.el (gtk-early-lisp-options-file): New.
Move this path to a documented variable.
(gtk-command-switch-alist): Wrap the docstring to fewer than 79
columns.
(make-device-early-gtk-entry-point-called-p): New.
(make-device-late-gtk-entry-point-called-p): New.
Renamed gtk-pre-win-initted, gtk-post-win-initted to these.
(make-device-early-gtk-entry-point): New.
(make-device-late-gtk-entry-point): New.
Renamed init-pre-gtk-win, init-post-gtk-win to these.
Have make-device-late-gtk-entry-point take a device argument, and use
it; have make-device-early-gtk-entry-point load the GTK-specific
startup code, instead of doing that in C.
(init-gtk-win): Deleted, functionality moved to the GTK device
creation code.
(gtk-define-dead-key): Have it take a DEVICE argument; use this
argument.
(gtk-initialize-compose): Ditto.
* coding.el (set-terminal-coding-system):
Correct the docstring; the function isn't broken.
src/ChangeLog addition:
2008-07-07 Aidan Kehoe <kehoea@parhasard.net>
Patch to make it up to the device-specific code whether
various Lisp functions should be called during device creation,
not relying on the startup code to decide this. Also, rename
initial-window-system to initial-device-type (which makes more
sense in this scheme), always set it.
* redisplay.c (Vinitial_device_type): New.
(Vinitial_window_system): Removed.
Rename initial-window-system to initial-device type, making it
a stream if we're noninteractive. Update its docstring.
* device-x.c (Qmake_device_early_x_entry_point,
Qmake_device_late_x_entry_point): New.
Rename Qinit_pre_x_win, Qinit_post_x_win.
(x_init_device): Call #'make-device-early-x-entry-point earlier,
now we rely on it to find the application class and the
app-defaults directory.
(x_finish_init_device): Call #'make-device-late-x-entry-point with
the created device.
(Vx_app_defaults_directory): Always make this available, to
simplify code in x-init.el.
* device-tty.c (Qmake_device_early_tty_entry_point): New.
Rename Qinit_pre_tty_win, rename Qinit_post_tty_win and move to
frame-tty.c as Qmake_frame_after_init_entry_point.
(tty_init_device): Call #'make-device-early-tty-entry-point before
doing anything.
* frame-tty.c (Qmake_frame_after_init_entry_point): New.
* frame-tty.c (tty_after_init_frame): Have it call the
better-named #'make-frame-after-init-entry-point function
instead of #'init-post-tty-win (since it's called after frame, not
device, creation).
* device-msw.c (Qmake_device_early_mswindows_entry_point,
Qmake_device_late_mswindows_entry_point): New.
Rename Qinit_pre_mswindows_win, Qinit_post_mswindows_win.
(mswindows_init_device): Call
#'make-device-early-mswindows-entry-point here, instead of having
its predecessor call us.
(mswindows_finish_init_device): Call
#'make-device-early-mswindows-entry-point, for symmetry with the
other device types (though it's an empty function).
* device-gtk.c (Qmake_device_early_gtk_entry_point,
Qmake_device_late_gtk_entry_point): New.
Rename Qinit_pre_gtk_win, Qinit_post_gtk_win.
(gtk_init_device): Call #'make-device-early-gtk-entry-point; don't
load ~/.xemacs/gtk-options.el ourselves, leave that to lisp.
(gtk_finish_init_device): Call #'make-device-late-gtk-entry-point
with the created device as an argument.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Wed, 09 Jul 2008 20:46:22 +0200 |
parents | 6504113e7c2d |
children |
line wrap: on
line source
/* * Copyright (c) 2000, Red Hat, Inc. * * 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. * * A copy of the GNU General Public License can be found at * http://www.gnu.org/ * * Written by DJ Delorie <dj@cygnus.com> * */ /* The purpose of this file is to intall all the packages selected in the install list (in ini.h). Note that we use a separate thread to maintain the progress dialog, so we avoid the complexity of handling two tasks in one thread. We also create or update all the files in /etc/setup and create the mount points. */ #include <io.h> #include <stdio.h> #include <stdlib.h> #ifndef WIN32_NATIVE #include <unistd.h> #endif #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <zlib.h> #include "win32.h" #include "commctrl.h" #include "resource.h" #include "ini.h" #include "dialog.h" #include "concat.h" #include "geturl.h" #include "mkdir.h" #include "state.h" #include "tar.h" #include "diskfull.h" #include "msg.h" #include "regedit.h" #include "reginfo.h" #include "log.h" #include "hash.h" #include "desktop.h" #include "port.h" static HWND ins_dialog = 0; static HWND ins_action = 0; static HWND ins_pkgname = 0; static HWND ins_filename = 0; static HWND ins_pprogress = 0; static HWND ins_iprogress = 0; static HWND ins_diskfull = 0; static HANDLE init_event; static int total_bytes = 0; static int total_bytes_sofar = 0; static int package_bytes = 0; static BOOL dialog_cmd (HWND h, int id, HWND hwndctl, UINT code) { switch (id) { case IDCANCEL: exit_setup (1); } return FALSE; } static BOOL CALLBACK dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: ins_dialog = h; ins_action = GetDlgItem (h, IDC_INS_ACTION); ins_pkgname = GetDlgItem (h, IDC_INS_PKG); ins_filename = GetDlgItem (h, IDC_INS_FILE); ins_pprogress = GetDlgItem (h, IDC_INS_PPROGRESS); ins_iprogress = GetDlgItem (h, IDC_INS_IPROGRESS); ins_diskfull = GetDlgItem (h, IDC_INS_DISKFULL); SetEvent (init_event); return FALSE; case WM_COMMAND: return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd); } return FALSE; } static DWORD WINAPI dialog (void *) { MSG m; HWND new_dialog = CreateDialog (hinstance, MAKEINTRESOURCE (IDD_INSTATUS), 0, dialog_proc); if (new_dialog == 0) fatal ("create dialog"); ShowWindow (new_dialog, SW_SHOWNORMAL); UpdateWindow (new_dialog); while (GetMessage (&m, 0, 0, 0) > 0) { TranslateMessage (&m); DispatchMessage (&m); } return FALSE; } static void init_dialog () { if (ins_dialog == 0) { DWORD tid; HANDLE thread; init_event = CreateEvent (0, 0, 0, 0); thread = CreateThread (0, 0, dialog, 0, 0, &tid); WaitForSingleObject (init_event, 10000); CloseHandle (init_event); SendMessage (ins_pprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100)); SendMessage (ins_iprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100)); SendMessage (ins_diskfull, PBM_SETRANGE, 0, MAKELPARAM (0, 100)); } SetWindowText (ins_pkgname, ""); SetWindowText (ins_filename, ""); SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) 0, 0); SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) 0, 0); SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) 0, 0); ShowWindow (ins_dialog, SW_SHOWNORMAL); SetForegroundWindow (ins_dialog); } static void progress (int bytes) { int perc; if (package_bytes > 100) { perc = bytes / (package_bytes / 100); SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) perc, 0); } if (total_bytes > 100) { perc = (total_bytes_sofar + bytes) / (total_bytes / 100); SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) perc, 0); } } static void badrename (char *o, char *n) { char *err = strerror (errno); if (!err) err = "(unknown error)"; note (IDS_ERR_RENAME, o, n, err); } static char *standard_dirs[] = { 0 }; void hash::add_subdirs (char *path) { char *nonp, *pp; for (nonp = path; *nonp == '\\' || *nonp == '/'; nonp++); for (pp = path + strlen(path) - 1; pp>nonp; pp--) if (*pp == '/' || *pp == '\\') { int i, s=0; char c = *pp; *pp = 0; for (i=0; standard_dirs[i]; i++) if (strcmp (standard_dirs[i]+1, path) == 0) { s = 1; break; } if (s == 0) add (path); *pp = c; } } char * map_filename (char *fn, int type) { char *dest_file; while (*fn == '/' || *fn == '\\') fn++; if (type == TY_GENERIC) dest_file = concat (root_dir, XEMACS_PACKAGE_DIR, fn, 0); else // TY_CYGWIN | TY_NATIVE dest_file = concat (root_dir, "/", fn, 0); return dest_file; } static int exists (char *file) { if (_access (file, 0) == 0) return 1; return 0; } static int num_installs, num_uninstalls; static void uninstall_one (char *name, int action, int type) { hash dirs; char line[_MAX_PATH]; char* fname = (type == TY_GENERIC ? concat (root_dir, XEMACS_PACKAGE_DIR, "pkginfo/MANIFEST.", name, 0) : concat (root_dir, XEMACS_SETUP_DIR, "MANIFEST.", name, 0)); FILE* lst = fopen (fname, "rb"); if (lst) { SetWindowText (ins_pkgname, name); SetWindowText (ins_action, "Uninstalling..."); // remove shortcuts and registry entries if (type != TY_GENERIC) remove_xemacs_setup(); if (action == ACTION_UPGRADE) log (0, "Uninstalling old %s", name); else log (0, "Uninstalling %s", name); while (fgets (line, sizeof (line), lst)) { if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0; dirs.add_subdirs (line); char *d = map_filename (line, type); DWORD dw = GetFileAttributes (d); if (dw != 0xffffffff && !(dw & FILE_ATTRIBUTE_DIRECTORY)) { log (LOG_BABBLE, "unlink %s", d); DeleteFile (d); } } fclose (lst); remove (fname); dirs.reverse_sort (); char *subdir = 0; while ((subdir = dirs.enumerate (subdir)) != 0) { char *d = map_filename (subdir, type); if (RemoveDirectory (d)) log (LOG_BABBLE, "rmdir %s", d); } num_uninstalls ++; } } static int install_one (char *name, char *file, int file_size, int action, int type) { int errors = 0; char *local = file, *cp, *fn, *base; base = local; for (cp=local; *cp; cp++) if (*cp == '/' || *cp == '\\' || *cp == ':') base = cp+1; SetWindowText (ins_pkgname, base); if (!exists (local) && exists (base)) local = base; if (!exists (local)) { note (IDS_ERR_OPEN_READ, local, "No such file"); return 1; } char* fname = (type == TY_GENERIC ? concat (root_dir, XEMACS_PACKAGE_DIR, "pkginfo/MANIFEST.", name, 0) : concat (root_dir, XEMACS_SETUP_DIR, "MANIFEST.", name, 0)); FILE* lst = fopen (fname, "wb"); package_bytes = file_size; switch (action) { case ACTION_NEW: SetWindowText (ins_action, "Installing..."); break; case ACTION_UPGRADE: SetWindowText (ins_action, "Upgrading..."); break; } log (0, "Installing %s", local); tar_open (local); while ((fn = tar_next_file ())) { char *dest_file, *disp_file; int len; if (lst) fprintf (lst, "%s\n", fn); dest_file = map_filename (fn, type); // The installer uses a variable width font. Assume roughly 32 chars // will fit and munge the file accordingly. #define MAX_DISP_SIZE 50 disp_file = strdup(dest_file); if ((len = strlen(dest_file)) > MAX_DISP_SIZE) { disp_file += (len - MAX_DISP_SIZE); disp_file[0] = '.'; disp_file[1] = '.'; disp_file[2] = '.'; } #undef MAX_DISP_SIZE SetWindowText (ins_filename, disp_file); log (LOG_BABBLE, "Installing file %s", dest_file); if (tar_read_file (dest_file) != 0) { log (0, "Unable to install file %s", dest_file); errors ++; } progress (tar_ftell ()); num_installs ++; } tar_close (); total_bytes_sofar += file_size; progress (0); int df = diskfull (root_dir); SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0); if (lst) fclose (lst); return errors; } void do_install (HINSTANCE h) { int i; int errors = 0; num_installs = 0, num_uninstalls = 0; next_dialog = IDD_DESKTOP; mkdir_p (1, root_dir); for (i=0; standard_dirs[i]; i++) { char *p = concat (root_dir, standard_dirs[i], 0); mkdir_p (1, p); free (p); } dismiss_url_status_dialog (); init_dialog (); total_bytes = 0; total_bytes_sofar = 0; int df = diskfull (root_dir); SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0); LOOP_PACKAGES { total_bytes += pi.install_size; } for (i=0; i<npackages; i++) { if (package[i].action == ACTION_UNINSTALL || (package[i].action == ACTION_UPGRADE && pi.install)) { uninstall_one (package[i].name, package[i].action, package[i].type); uninstall_one (concat (package[i].name, "-src", 0), package[i].action, package[i].type); } if ((package[i].action == ACTION_NEW || package[i].action == ACTION_UPGRADE) && pi.install) { int e = install_one (package[i].name, pi.install, pi.install_size, package[i].action, package[i].type); if (package[i].srcaction == SRCACTION_YES && pi.source) e += install_one (concat (package[i].name, "-src", 0), pi.source, pi.source_size, package[i].action, package[i].type); if (e) { package[i].action = ACTION_ERROR; errors++; } } } // end of big package loop ShowWindow (ins_dialog, SW_HIDE); char *odbn = concat (root_dir, XEMACS_SETUP_DIR, "installed.db", 0); char *ndbn = concat (root_dir, XEMACS_SETUP_DIR, "installed.db.new", 0); char *sdbn = concat (root_dir, XEMACS_SETUP_DIR, "installed.db.old", 0); mkdir_p (0, ndbn); FILE *odb = fopen (odbn, "rt"); FILE *ndb = fopen (ndbn, "wb"); if (!ndb) { char *err = strerror (errno); if (!err) err = "(unknown error)"; fatal (IDS_ERR_OPEN_WRITE, ndb, err); } if (odb) { char line[1000], pkg[1000]; int printit; while (fgets (line, 1000, odb)) { printit = 1; sscanf (line, "%s", pkg); for (i=0; i<npackages; i++) { if (strcmp (pkg, package[i].name) == 0) switch (package[i].action) { case ACTION_NEW: case ACTION_UPGRADE: case ACTION_UNINSTALL: printit = 0; break; } } if (printit) fputs (line, ndb); } } LOOP_PACKAGES { if (package[i].srcaction == SRCACTION_YES) fprintf (ndb, "%s %s %d %s %d\n", package[i].name, pi.install, pi.install_size, pi.source, pi.source_size); else fprintf (ndb, "%s %s %d\n", package[i].name, pi.install, pi.install_size); } if (odb) fclose (odb); fclose (ndb); remove (sdbn); if (odb && rename (odbn, sdbn)) badrename (odbn, sdbn); remove (odbn); if (rename (ndbn, odbn)) badrename (ndbn, odbn); if (num_installs == 0 && num_uninstalls == 0) { exit_msg = IDS_NOTHING_INSTALLED; return; } if (num_installs == 0) { exit_msg = IDS_UNINSTALL_COMPLETE; return; } if (errors) exit_msg = IDS_INSTALL_INCOMPLETE; else exit_msg = IDS_INSTALL_COMPLETE; }