// lbinstdj.cc - implements main application class, lbinstdj_app. // Copyright (C) 2000 Laurynas Biveinis // // 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. // // 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. // // 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 // #include "global.h" #include "aexecupd.h" #include "lbinstdj.h" #ifdef HAVE_TV_H # define Uses_MsgBox # define Uses_TButton # define Uses_TCommandSet # define Uses_TDialog # define Uses_TEventQueue # define Uses_TInputLine # define Uses_TLabel # define Uses_TRadioButtons # define Uses_TRect # define Uses_TSItem # define Uses_TStaticText # define Uses_TWindow # include #endif #include #include #include #include #include #include #include #include #include #include #include static bool is_win9x_dos_box(void) __attribute__((const)); lbinstdj_app::lbinstdj_app(void) : TProgInit(&lbinstdj_app::initStatusLine, &lbinstdj_app::initMenuBar, &lbinstdj_app::initDeskTop ) { message(this, evCommand, cmStartInstallation, NULL); } //----------------------------------------------------------------------------- bool lbinstdj_app::check_for_reg_key(const char * key, const char * value) { char fname[L_tmpnam]; char * buf; bool found = false; char command[500] = "regedit /e "; struct stat finfo; ifstream f; tmpnam(fname); strcat(command, fname); strcat(command, " "); strcat(command, key); if (exec_command(command, "Checking registry...") == -1) errno_box("Registry check (launching regedit) failed: %s"); stat(fname, &finfo); buf = new char[finfo.st_size]; f.open(fname); f.read(buf, finfo.st_size); f.close(); ::remove(fname); found = (strstr(buf, value)) ? true : false; delete [] buf; return found; } //----------------------------------------------------------------------------- void lbinstdj_app::do_installation(void) { greetings(); if ((_osmajor == 7) && num_tails_enabled()) update_registry(); char djdir[PATH_MAX + 1]; get_dir(new djgpp_dir_dialog, djdir); if (mkdir(djdir, S_IWUSR) && (errno != EEXIST)) errno_box("DJGPP directory creation failed: %s\n"); init_zippo(djdir); char zip_dir[PATH_MAX + 1]; get_dir(new zip_path_dialog, zip_dir); int zip_dir_len = strlen(zip_dir); if ((zip_dir[zip_dir_len] != '\\') || (zip_dir[zip_dir_len] != '/')) strcat(zip_dir, "/"); /* ... */ old_installation(djdir, zip_dir); if (!num_tails_enabled()) restore_num_tails(); update_autoexec_bat(djdir); destroy(this); exit(0); } //----------------------------------------------------------------------------- void lbinstdj_app::errno_box(const char * message) { char error_buf[300]; sprintf(error_buf, message, strerror(errno)); messageBox(error_buf, mfError | mfOKButton); destroy(this); exit(3); return; } //----------------------------------------------------------------------------- int lbinstdj_app::exec_command(const char * command, const char * message) { TRect bounds = deskTop->getExtent(); int mes_len = strlen(message); TDialog * exec_dialog = new TDialog(TRect((bounds.b.x - mes_len - 4) / 2, 8, (bounds.b.x + mes_len + 4) / 2, 13), "Please Wait"); exec_dialog->insert(new TStaticText(TRect(2, 2, 2 + mes_len, 3), message)); deskTop->lock(); deskTop->insert(exec_dialog); deskTop->unlock(); TEventQueue::suspend(); __djgpp_exception_toggle(); int exit_code = system(command); __djgpp_exception_toggle(); TEventQueue::resume(); deskTop->remove(exec_dialog); destroy(exec_dialog); return exit_code; } //----------------------------------------------------------------------------- void lbinstdj_app::exit_request(const int message) { if (message == cmCancel) { destroy(this); exit(2); } } //----------------------------------------------------------------------------- void lbinstdj_app::get_dir(path_dialog * dialog, char * dir) { bool ok = dialog->get_path(dir); destroy(dialog); if (!ok) exit_request(cmCancel); } //----------------------------------------------------------------------------- void lbinstdj_app::greetings(void) { int return_code; TDialog * dialog = new TDialog(TRect(0, 0, 57, 14), "Welcome to DJGPP"); dialog->options |= ofCentered; dialog->insert(new TStaticText(TRect(5, 1, 55, 2), "Welcome to the LBInstDJ, the DJGPP installer!")); dialog->insert(new TStaticText(TRect(2, 3, 55, 5), "This program will help you to install DJGPP, the \n" "complete C, C++, etc. development system for DOS.")); dialog->insert(new TStaticText(TRect(2, 5, 48, 6), "Now press \"Next\" button below to continue.")); dialog->insert(new TStaticText(TRect(2, 6, 55, 9), "You can press \"Exit\" button at any time to abort \n" "installation process.")); dialog->insert(new TStaticText(TRect(2, 9, 55, 10), "Copyright (C) Laurynas Biveinis ")); dialog->insert(new TButton(TRect(15, 11, 27, 13), "~N~ext", cmOK, bfDefault)); dialog->insert(new TButton(TRect(30, 11, 42, 13), "~E~xit", cmCancel, bfNormal)); dialog->selectNext(False); return_code = TProgram::deskTop->execView(dialog); destroy(dialog); exit_request(return_code); } //----------------------------------------------------------------------------- void lbinstdj_app::handleEvent(TEvent& event) { TApplication::handleEvent(event); if ((event.what == evCommand) && (event.message.command == cmStartInstallation)) do_installation(); } //----------------------------------------------------------------------------- // We have to redefine this because we don't have status line and want to // cover its area. TDeskTop *lbinstdj_app::initDeskTop(TRect r) { return new TDeskTop(r); } //----------------------------------------------------------------------------- TMenuBar *lbinstdj_app::initMenuBar(TRect r) { (void)r; // Imagine that we do use this variable return NULL; } //----------------------------------------------------------------------------- TStatusLine *lbinstdj_app::initStatusLine(TRect r) { (void)r; return NULL; } //----------------------------------------------------------------------------- void lbinstdj_app::init_zippo(const char * dir) { (void)dir; } //----------------------------------------------------------------------------- void lbinstdj_app::merge_registry_file(const char * file) { char command[300] = "regedit "; strcat(command, file); if (exec_command(command, "Updating registry...") == -1) errno_box("Registry update (launching regedit) failed: %s"); } //----------------------------------------------------------------------------- bool lbinstdj_app::num_tails_enabled(void) { return check_for_reg_key( "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\control\\FileSystem", "\"NameNumericTail\"=hex:01"); } //----------------------------------------------------------------------------- void lbinstdj_app::old_installation(const char * djdir, const char * zipdir) { char command_line[600] = "unzip -o "; // 256 + 256 + little extra strcat(command_line, zipdir); strcat(command_line, "*.zip -d "); strcat(command_line, djdir); strcat(command_line, " > /dev/null"); exec_command(command_line, "Extracting DJGPP packages..."); } //----------------------------------------------------------------------------- void lbinstdj_app::restore_num_tails(void) { TDialog * dialog = new TDialog(TRect(0, 0, 60, 11), "Enable Numeric Tails"); dialog->options |= ofCentered; dialog->insert(new TStaticText(TRect(4, 2, 58, 8), "You have disabled numeric tails in short file names.\n" "That was OK for DJGPP installation but due to Windows\n" "problems it can lead to data loss in the future.\n \n" " Do you want to re-enable numeric tails now?")); dialog->insert(new TButton(TRect(10, 8, 20, 10), "~Y~es", cmYes, bfDefault)); dialog->insert(new TButton(TRect(25, 8, 35, 10), "~N~o", cmNo, bfNormal)); dialog->insert(new TButton(TRect(40, 8, 50, 10), "~E~xit", cmCancel, bfNormal)); dialog->selectNext(False); int exit_code = deskTop->execView(dialog); destroy(dialog); exit_request(exit_code); if (exit_code == cmYes) merge_registry_file("onnumtl.reg"); } //----------------------------------------------------------------------------- void lbinstdj_app::update_registry(void) { int dlg_exit; TDialog * dialog = new TDialog(TRect(0, 0, 60, 12), "Question"); dialog->options |= ofCentered; dialog->insert(new TStaticText(TRect(2, 1, 58, 6), "If you are going to use DJGPP in both DOS box under\n" "Windows and in plain DOS mode, this program will have\n" "to update Windows registry to disable numeric tails in\n" "short file names (See the DJGPP FAQ 22.19 for details).\n" "However, this will require additional reboot.")); dialog->insert(new TStaticText(TRect(2, 7, 58, 8), " So, are you going to use DJGPP in both ways?")); dialog->insert(new TButton(TRect(2, 9, 18, 11), "~Y~es", cmYes, bfNormal)); dialog->insert(new TButton(TRect(22, 9, 38, 11), "~N~o", cmNo, bfDefault)); dialog->insert(new TButton(TRect(42, 9, 58, 11), "~E~xit", cmCancel, bfNormal)); dialog->selectNext(False); dlg_exit = TProgram::deskTop->execView(dialog); destroy(dialog); exit_request(dlg_exit); if (dlg_exit == cmYes) { merge_registry_file("nonumtl.reg"); if (is_win9x_dos_box()) messageBox("Now please restart your computer and rerun LBInstDJ.", mfInformation | mfOKButton); else messageBox("Now please start Windows and run LBInstDJ from there.", mfInformation | mfOKButton); destroy(this); exit(1); } } //----------------------------------------------------------------------------- void lbinstdj_app::update_autoexec_bat(const char * dir) { int exit_code; autoexec_update * update_dialog = new autoexec_update; exit_code = update_dialog->update(dir); destroy(update_dialog); exit_request(exit_code); } // Helper functions bool is_win9x_dos_box(void) { __dpmi_regs registers; registers.x.ax = 0x7147; registers.h.dl = 0x00; registers.x.ds = __tb >> 4; registers.x.si = __tb & 0x0F; __dpmi_int(0x21, ®isters); return (_osmajor == 7) && (registers.x.ax != 0x7100); }