From 450203f8a237f7f6a71fbc36c5c80bba2914e55a Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Thu, 9 Apr 1998 02:21:49 +0000 Subject: [PATCH] regex_comand() calls corrected in the XView edition Generic PC port added. It is not yet added into the main makefile. PC port should replace os2 and nt ports. --- pc/BUGS | 15 + pc/Makefile | 0 pc/Makefile.BC2 | 57 ++++ pc/Makefile.BC5 | 56 ++++ pc/Makefile.EMX | 56 ++++ pc/Makefile.IBM | 62 ++++ pc/Makefile.PC | 170 ++++++++++ pc/Makefile.VC4 | 56 ++++ pc/README | 42 +++ pc/TODO | 12 + pc/chmod.c | 494 ++++++++++++++++++++++++++++ pc/config.h | 227 +++++++++++++ pc/cons_nt.c | 110 +++++++ pc/cons_os2.c | 110 +++++++ pc/dirent.h | 70 ++++ pc/dirent_nt.c | 92 ++++++ pc/dirent_os2.c | 131 ++++++++ pc/drive.c | 218 ++++++++++++ pc/drive.h | 4 + pc/key_nt.c | 305 +++++++++++++++++ pc/key_os2.c | 408 +++++++++++++++++++++++ pc/mc.def | 4 + pc/mc.rc | 57 ++++ pc/mc_nt.ico | Bin 0 -> 1078 bytes pc/mc_os2.ico | Bin 0 -> 3344 bytes pc/slint_pc.c | 220 +++++++++++++ pc/sys/param.h | 7 + pc/sys/time.h | 16 + pc/trace_nt.c | 186 +++++++++++ pc/trace_nt.h | 72 ++++ pc/util_nt.c | 664 +++++++++++++++++++++++++++++++++++++ pc/util_os2.c | 854 ++++++++++++++++++++++++++++++++++++++++++++++++ pc/util_win32.c | 182 +++++++++++ pc/util_win32.h | 42 +++ pc/util_winnt.c | 85 +++++ xv/xvicon.c | 6 +- xv/xvscreen.c | 5 +- 37 files changed, 5093 insertions(+), 2 deletions(-) create mode 100644 pc/BUGS create mode 100644 pc/Makefile create mode 100644 pc/Makefile.BC2 create mode 100644 pc/Makefile.BC5 create mode 100644 pc/Makefile.EMX create mode 100644 pc/Makefile.IBM create mode 100644 pc/Makefile.PC create mode 100644 pc/Makefile.VC4 create mode 100644 pc/README create mode 100644 pc/TODO create mode 100644 pc/chmod.c create mode 100644 pc/config.h create mode 100644 pc/cons_nt.c create mode 100644 pc/cons_os2.c create mode 100644 pc/dirent.h create mode 100644 pc/dirent_nt.c create mode 100644 pc/dirent_os2.c create mode 100644 pc/drive.c create mode 100644 pc/drive.h create mode 100644 pc/key_nt.c create mode 100644 pc/key_os2.c create mode 100644 pc/mc.def create mode 100644 pc/mc.rc create mode 100644 pc/mc_nt.ico create mode 100644 pc/mc_os2.ico create mode 100644 pc/slint_pc.c create mode 100644 pc/sys/param.h create mode 100644 pc/sys/time.h create mode 100644 pc/trace_nt.c create mode 100644 pc/trace_nt.h create mode 100644 pc/util_nt.c create mode 100644 pc/util_os2.c create mode 100644 pc/util_win32.c create mode 100644 pc/util_win32.h create mode 100644 pc/util_winnt.c diff --git a/pc/BUGS b/pc/BUGS new file mode 100644 index 000000000..940445e47 --- /dev/null +++ b/pc/BUGS @@ -0,0 +1,15 @@ +BUGS OF PC port + +- Troubles with keys (Ctrl-Tab, Gray +,-,*, Alt-Shift-A etc) +- Filtered view hangs in close_pipe() because error is set, but nothing +is available on stderr +- Windows '95 will not delete directory if not empty. (as it does + not return ENOTEMPTY but ENOACCESS)! Already fixed? +- Windows '95 will not allow "''" in root drives +- OS/2 port uses always screen size 80x25. Do we need newer SLang? +- IBM C++ has some problems with O_TEXT -> troubles with editor +- OS/2 port causes access violation while copying files. +- getcwd from EMX returns a UNIX-like path -> drive change fails. + +-please report! + diff --git a/pc/Makefile b/pc/Makefile new file mode 100644 index 000000000..e69de29bb diff --git a/pc/Makefile.BC2 b/pc/Makefile.BC2 new file mode 100644 index 000000000..d20900501 --- /dev/null +++ b/pc/Makefile.BC2 @@ -0,0 +1,57 @@ +# Makefile.BC5 +# +# Midnight Commander for OS/2 makefile +# for Borland C++ 2 +# +# Hacked by Dan Nicolaescu from Visual IDE mak +# Hacked by Pavel Roskin to make it work with cmd.exe from Windows NT4 +# 980206 hacked by Pavel Roskin to make it work with GNU make +# 980316 hacked by Pavel Roskin to make it work with Borland C++ +# -------------------------------------------------------------------------- + +TARGET_OS=OS2 + +CC=bcc.exe +LINK=bcc.exe +OBJ_SUFFIX=obj +OBJ_PLACE=-o +EXE_PLACE=-e +# Just comment RSC out if you have problems with resources +# RSC=rc.exe +# RES_PLACE=-fo + +# ---- Compiler-specific optional stuff +MC_MISC_CFLAGS=-D__MT__ + +ifndef RELEASE +# ---- Debug build +OBJS_DIR=debug +EXTRA_MC_SRCS= +SPECIFIC_DEFINES= +SPECIFIC_MC_CFLAGS=-v -y $(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA=-lv +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) -I../edit -I../src +RC_DEFINES=-D_DEBUG +else +# ---- Release build +OBJS_DIR=release +EXTRA_MC_SRCS= +SPECIFIC_DEFINES= +SPECIFIC_MC_CFLAGS=-O2 $(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA= +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) -I../edit -I../src +RC_DEFINES=-DRELEASE=$(RELEASE) +endif + +# ---- Compiler independent defines +include Makefile.PC + +# ---- Linkers are usualy compiler-specific + +MC_LIBS=c2mt.lib +SPECIFIC_MC_LFLAGS=$(SPECIFIC_MC_LFLAGS_EXTRA) + +$(MC_EXE): $(MC_RES) $(OBJS) $(MCEDIT_OBJS) $(SLANG_OBJS) + $(LINK) $(EXE_PLACE)$(MC_EXE) $(SPECIFIC_MC_LFLAGS) $+ $(MC_LIBS) diff --git a/pc/Makefile.BC5 b/pc/Makefile.BC5 new file mode 100644 index 000000000..50a75f704 --- /dev/null +++ b/pc/Makefile.BC5 @@ -0,0 +1,56 @@ +# Makefile.BC5 +# +# Midnight Commander for Win32 makefile +# for Borland C++ 5.01 +# +# Hacked by Dan Nicolaescu from Visual IDE mak +# Hacked by Pavel Roskin to make it work with cmd.exe from Windows NT4 +# 980206 hacked by Pavel Roskin to make it work with GNU make +# 980316 hacked by Pavel Roskin to make it work with Borland C++ +# -------------------------------------------------------------------------- + +TARGET_OS=NT + +CC=bcc32.exe +LINK=bcc32.exe +OBJ_SUFFIX=obj +OBJ_PLACE=-o +EXE_PLACE=-e +# Just comment RSC out if you have problems with resources +# RSC=rc.exe +# RES_PLACE=-fo + +# ---- Compiler-specific optional stuff +MC_MISC_CFLAGS= + +ifndef RELEASE +# ---- Debug build +OBJS_DIR=debug +EXTRA_MC_SRCS=trace_nt.c +SPECIFIC_DEFINES=-DHAVE_TRACE +SPECIFIC_MC_CFLAGS=-v -y $(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA=-lv +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) -I../edit -I../src +RC_DEFINES=-D_DEBUG +else +# ---- Release build +OBJS_DIR=release +EXTRA_MC_SRCS= +SPECIFIC_DEFINES= +SPECIFIC_MC_CFLAGS=$(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA= +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) -I../edit -I../src +RC_DEFINES=-DRELEASE=$(RELEASE) +endif + +# ---- Compiler independent defines +include Makefile.PC + +# ---- Linkers are usualy compiler-specific +SPECIFIC_MC_LFLAGS=$(SPECIFIC_MC_LFLAGS_EXTRA) +MC_LIBS= + +$(MC_EXE): $(MC_RES) $(OBJS) $(MCEDIT_OBJS) $(SLANG_OBJS) + $(LINK) $(EXE_PLACE)$(MC_EXE) $(SPECIFIC_MC_LFLAGS) $+ $(MC_LIBS) diff --git a/pc/Makefile.EMX b/pc/Makefile.EMX new file mode 100644 index 000000000..5dd70c311 --- /dev/null +++ b/pc/Makefile.EMX @@ -0,0 +1,56 @@ +# Makefile.vc4 +# +# Midnight Commander for Win32 makefile +# for Microsoft Visual C++ 4.x +# +# Hacked by Dan Nicolaescu from Visual IDE mak +# Hacked by Pavel Roskin to make it work with cmd.exe from Windows NT4 +# 980206 hacked by Pavel Roskin to make it work with GNU make +# -------------------------------------------------------------------------- + +TARGET_OS=OS2 + +CC=gcc.exe +LINK=gcc.exe +OBJ_SUFFIX=o +OBJ_PLACE=-o +EXE_PLACE=-o +# Just comment RSC out if you have problems with resources +# RSC=rc.exe +# RES_PLACE=-fo + +# ---- Compiler-specific optional stuff +MC_MISC_CFLAGS=-Zmt + +ifndef RELEASE +# ---- Debug build +OBJS_DIR=debug +EXTRA_MC_SRCS= +SPECIFIC_DEFINES= +SPECIFIC_MC_CFLAGS=-g -O0 $(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA= +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) +RC_DEFINES=-D_DEBUG +else +# ---- Release build +OBJS_DIR=release +EXTRA_MC_SRCS= +SPECIFIC_DEFINES= +SPECIFIC_MC_CFLAGS=-O2 $(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA= +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) +RC_DEFINES=-DRELEASE=$(RELEASE) +endif + +# ---- Compiler independent defines +include Makefile.PC + +# ---- Linkers are very compiler-specific + +SPECIFIC_MC_LFLAGS= -Zmt $(SPECIFIC_MC_LFLAGS_EXTRA) +MC_LIBS= + +$(MC_EXE): $(MC_RES) $(OBJS) $(MCEDIT_OBJS) $(SLANG_OBJS) + $(LINK) $(EXE_PLACE) $(MC_EXE) $(MC_LIBS) $(SPECIFIC_MC_LFLAGS) $+ diff --git a/pc/Makefile.IBM b/pc/Makefile.IBM new file mode 100644 index 000000000..71ed5f29e --- /dev/null +++ b/pc/Makefile.IBM @@ -0,0 +1,62 @@ +# Makefile.vc4 +# +# Midnight Commander for Win32 makefile +# for Microsoft Visual C++ 4.x +# +# Hacked by Dan Nicolaescu from Visual IDE mak +# Hacked by Pavel Roskin to make it work with cmd.exe from Windows NT4 +# 980206 hacked by Pavel Roskin to make it work with GNU make +# 980327 hacked by Pavel Roskin to make it work with Visual Age C++ +# -------------------------------------------------------------------------- + +TARGET_OS=OS2 + +CC=icc.exe +LINK=icc.exe +OBJ_SUFFIX=obj +OBJ_PLACE=-Fo +EXE_PLACE=-Fe +# Just comment RSC out if you have problems with resources +# RSC=rc.exe +# RES_PLACE=-fo + +# ---- Compiler-specific optional stuff +MC_MISC_CFLAGS=-Q -Gm + +ifndef RELEASE +# ---- Debug build +OBJS_DIR=debug +EXTRA_MC_SRCS= +SPECIFIC_DEFINES= +SPECIFIC_MC_CFLAGS=-Ti $(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA=-Ti +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) -I../src +RC_DEFINES=-D_DEBUG +else +# ---- Release build +OBJS_DIR=release +EXTRA_MC_SRCS= +SPECIFIC_DEFINES= +SPECIFIC_MC_CFLAGS=-O $(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA= +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) -I../src +RC_DEFINES=-DRELEASE=$(RELEASE) +endif + +# ---- Compiler independent defines +include Makefile.PC + +# ---- Linkers are very compiler-specific + +SPECIFIC_MC_LFLAGS= -Q -Gm $(SPECIFIC_MC_LFLAGS_EXTRA) +MC_LIBS= +MC_DEF=$(MC_PC_DIR)/mc.def + +LINK_CMD=$(LINK) $(EXE_PLACE)$(MC_EXE) $(SPECIFIC_MC_LFLAGS) $(MC_RES) \ + $(OBJS) $(MCEDIT_OBJS) $(SLANG_OBJS) $(MC_LIBS) $(MC_DEF) +_LINK_CMD=$(subst /,\\,$(LINK_CMD)) + +$(MC_EXE): $(MC_RES) $(OBJS) $(MCEDIT_OBJS) $(SLANG_OBJS) + $(_LINK_CMD) diff --git a/pc/Makefile.PC b/pc/Makefile.PC new file mode 100644 index 000000000..95222feab --- /dev/null +++ b/pc/Makefile.PC @@ -0,0 +1,170 @@ +# Makefile +# Written by Dan Nicolaescu +# 970423 hacked by Juan f. Grigera +# 970525 hacked again by jfg to add internal editor +# 971127 hacked by Pavel Roskin to make it work with mc-4.1.11 +# 980206 hacked by Pavel Roskin to make it work with GNU make +# 980329 changed by Pavel Roskin to make it common for OS/2 and NT +# +# This is the Makefile for Midnight Commander under OS/2 and Windows NT +# +# Supported Compilers: +# +# For Windows NT: +# Makefile.VC4: Microsoft Visual C++ 4.0 and above +# Makefile.BC5: Borland C++ 5.x +# For OS/2: +# Makefile.EMX: EMX/GCC +# Makefile.BC2: Borland C++ 2.x +# Makefile.IBM: IBM CSet or Visual Age C++ +# ... + +# ---- Directories +MC_PC_DIR=. +MC_SRC_DIR=../src +VFS_DIR=../vfs +MCEDIT_SRC_DIR=../edit +MCEDIT_OBJS_DIR=$(OBJS_DIR)/edit +SLANG_SRC_DIR=../slang +SLANG_OBJS_DIR=$(OBJS_DIR)/slang +MC_EXE=$(OBJS_DIR)/mc.exe + +# --- Midnight Defines +COMMON_DEFINES=-DMC_$(TARGET_OS) $(SPECIFIC_DEFINES) +MC_DEFINES=$(COMMON_DEFINES) -DHAVE_CONFIG_H +MC_INCLUDES=-I$(MC_SRC_DIR) -I$(MC_PC_DIR) -I$(SLANG_SRC_DIR) +SLANG_DEFINES=$(COMMON_DEFINES) +SLANG_INCLUDES=-I$(MC_PC_DIR) -I$(SLANG_SRC_DIR) +MCEDIT_DEFINES=$(COMMON_DEFINES) -DHAVE_CONFIG_H +MCEDIT_INCLUDES=-I$(MC_PC_DIR) -I$(MC_SRC_DIR)/.. -I$(SLANG_SRC_DIR) + +CFLAGS=$(SPECIFIC_MC_CFLAGS) $(MC_INCLUDES) $(MC_DEFINES) -c +SLANG_CFLAGS=$(SPECIFIC_SLANG_CFLAGS) $(SLANG_INCLUDES) $(SLANG_DEFINES) -c +MCEDIT_CFLAGS=$(SPECIFIC_MCEDIT_CFLAGS) $(MCEDIT_INCLUDES) $(MCEDIT_DEFINES) -c +RSC_FLAGS=$(RES_PLACE)$(OBJS_DIR)/mc.res $(RC_DEFINES) + + + +all: object-dirs mc +object-dirs: $(OBJS_DIR) $(SLANG_OBJS_DIR) $(MCEDIT_OBJS_DIR) + +mc: $(MC_EXE) + +clean: + deltree -y "$(SLANG_OBJS_DIR)" + deltree -y "$(MCEDIT_OBJS_DIR)" + deltree -y "$(OBJS_DIR)" + +$(OBJS_DIR): + mkdir "$@" + +$(SLANG_OBJS_DIR): + mkdir "$@" + +$(MCEDIT_OBJS_DIR): + mkdir "$@" + +$(OBJS_DIR)/%.$(OBJ_SUFFIX): $(MC_PC_DIR)/%.c + $(CC) $(CFLAGS) $(OBJ_PLACE)$@ $< + +$(OBJS_DIR)/%.$(OBJ_SUFFIX): $(MC_SRC_DIR)/%.c + $(CC) $(CFLAGS) $(OBJ_PLACE)$@ $< + +$(SLANG_OBJS_DIR)/%.$(OBJ_SUFFIX): $(SLANG_SRC_DIR)/%.c + $(CC) $(SLANG_CFLAGS) $(OBJ_PLACE)$@ $< + +$(MCEDIT_OBJS_DIR)/%.$(OBJ_SUFFIX): $(MCEDIT_SRC_DIR)/%.c + $(CC) $(MCEDIT_CFLAGS) $(OBJ_PLACE)$@ $< + +MC_SRCS= \ + terms.c \ + user.c \ + file.c \ + listmode.c \ + cmd.c \ + command.c \ + help.c \ + menu.c \ + view.c \ + dir.c \ + info.c \ + widget.c \ + option.c \ + dlg.c \ + panelize.c \ + profile.c \ + util.c \ + dialog.c \ + ext.c \ + color.c \ + layout.c \ + setup.c \ + regex.c \ + hotlist.c \ + tree.c \ + win.c \ + complete.c \ + find.c \ + wtools.c \ + boxes.c \ + background.c \ + main.c \ + popt.c \ + text.c \ + screen.c + +PC_SRCS= \ + slint_pc.c \ + chmod.c \ + drive.c + +NT_SRCS= \ + cons_nt.c \ + dirent_nt.c \ + key_nt.c \ + util_win32.c \ + util_winnt.c \ + util_nt.c + +OS2_SRCS= \ + cons_os2.c \ + dirent_os2.c \ + key_os2.c \ + util_os2.c + +SLANG_NT=slw32tty.c +SLANG_OS2=slos2tty.c + +SLANG_SRCS= \ + slerr.c \ + slgetkey.c \ + slsmg.c \ + slvideo.c \ + $(SLANG_$(TARGET_OS)) + +MCEDIT_SRCS= \ + edit.c \ + editcmd.c \ + editdraw.c \ + editmenu.c \ + editoptions.c \ + editwidget.c \ + wordproc.c + +SRCS=$(MC_SRCS) $(PC_SRCS) $($(TARGET_OS)_SRCS) $(EXTRA_MC_SRCS) + +OBJS=$(addprefix $(OBJS_DIR)/, \ + $(patsubst %.c,%.$(OBJ_SUFFIX),$(SRCS))) +SLANG_OBJS=$(addprefix $(SLANG_OBJS_DIR)/, \ + $(patsubst %.c,%.$(OBJ_SUFFIX),$(SLANG_SRCS))) +MCEDIT_OBJS=$(addprefix $(MCEDIT_OBJS_DIR)/, \ + $(patsubst %.c,%.$(OBJ_SUFFIX),$(MCEDIT_SRCS))) + +ifdef RSC +MC_RES=$(OBJS_DIR)/mc.res +else +MC_RES= +endif + +$(OBJS_DIR)/mc.res: $(MC_PC_DIR)/mc.rc $(MC_PC_DIR)/mc_nt.ico $(MC_PC_DIR)/config.h ../VERSION + $(RSC) $(RSC_FLAGS) $(MC_PC_DIR)/mc.rc diff --git a/pc/Makefile.VC4 b/pc/Makefile.VC4 new file mode 100644 index 000000000..482f357af --- /dev/null +++ b/pc/Makefile.VC4 @@ -0,0 +1,56 @@ +# Makefile.vc4 +# +# Midnight Commander for Win32 makefile +# for Microsoft Visual C++ 4.x +# +# Hacked by Dan Nicolaescu from Visual IDE mak +# Hacked by Pavel Roskin to make it work with cmd.exe from Windows NT4 +# 980206 hacked by Pavel Roskin to make it work with GNU make +# -------------------------------------------------------------------------- + +TARGET_OS=NT + +CC=cl.exe +LINK=link.exe +OBJ_SUFFIX=obj +OBJ_PLACE=-Fo +EXE_PLACE=-out: +# Just comment RSC out if you have problems with resources +RSC=rc.exe +RES_PLACE=-fo + +# ---- Compiler-specific optional stuff +MC_MISC_CFLAGS=-nologo -YX -Fp$(OBJS_DIR)/mc.pch + +ifndef RELEASE +# ---- Debug build +OBJS_DIR=debug +EXTRA_MC_SRCS=trace_nt.c +SPECIFIC_DEFINES=-DHAVE_TRACE +SPECIFIC_MC_CFLAGS=-MLd -W3 -Gm -Zi -Od -Fd$(OBJS_DIR)/mc.pdb $(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA=-debug -incremental:yes +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) +RC_DEFINES=-D_DEBUG +else +# ---- Release build +OBJS_DIR=release +EXTRA_MC_SRCS= +SPECIFIC_DEFINES= +SPECIFIC_MC_CFLAGS=-ML -W3 -O2 $(MC_MISC_CFLAGS) +SPECIFIC_MC_LFLAGS_EXTRA=-incremental:no +SPECIFIC_SLANG_CFLAGS=$(SPECIFIC_MC_CFLAGS) +SPECIFIC_MCEDIT_CFLAGS=$(SPECIFIC_MC_CFLAGS) +RC_DEFINES=-DRELEASE=$(RELEASE) +endif + +# ---- Compiler independent defines +include Makefile.PC + +# ---- Linkers are usualy compiler-specific +SPECIFIC_MC_LFLAGS=-nologo -subsystem:console -pdb:$(OBJS_DIR)/mc.pdb \ + -machine:I386 $(SPECIFIC_MC_LFLAGS_EXTRA) +MC_LIBS=advapi32.lib + +$(MC_EXE): $(MC_RES) $(OBJS) $(MCEDIT_OBJS) $(SLANG_OBJS) + $(LINK) $(EXE_PLACE)$(MC_EXE) $(MC_LIBS) $(SPECIFIC_MC_LFLAGS) $+ diff --git a/pc/README b/pc/README new file mode 100644 index 000000000..0341f9950 --- /dev/null +++ b/pc/README @@ -0,0 +1,42 @@ + This is the port of Midnight Commander for OS/2, Windows 95 and Windows NT. + + This port is based on the port for Windows NT by + Juan Grigera +and the port for OS/2 by + Alexander Dong +and is currently maintained by + Pavel Roskin +(e-mail address will change in the next future). + + This port of the Midnight Commander is released under the GNU General +Public License version 2.0 or any later version. See file COPYING for +details. + + Following compilers are supported: + For Windows NT: + Makefile.VC4: Microsoft Visual C++ 4.0 and above + Makefile.BC5: Borland C++ 5.x + For OS/2: + Makefile.EMX: EMX/GCC + Makefile.BC2: Borland C++ 2.x + Makefile.IBM: IBM CSet or Visual Age C++ + + You need GNU make in order to compile mc. Other implementation of +make will not work! Run + +gmake -f Makefile.xxx [RELEASE=1] + +where gmake is name of GNU make and Makefile.xxx is the makefile for +your compiler. You may want to add RELEASE=1 if you want to compile an +optimized version without debug information. + Please note, that not all compilers are equal. You may need to create +dummy include files or change something in order to be able to compile +mc. BUT PLEASE DON'T TRY TO INCORPORATE SUCH QUICK HACKS INTO THE +MC DISTRIBUTION! Try to make your changes work with all other compilers. + If you add a file, don't forget to add it into FILES statement of +Makefile in this directory. Otherwise this file will not be copied to +the distribution. + This port is not very stable now. See files BUGS and TODO in this +directory. + +Pavel Roskin diff --git a/pc/TODO b/pc/TODO new file mode 100644 index 000000000..5e8d1feb7 --- /dev/null +++ b/pc/TODO @@ -0,0 +1,12 @@ +TODO + +- Make most files common for OS/2 and NT +- Move settings from mc.ini to the registry for Windows NT/95 (optionally?) +- Fix opendir/readdir d_date and d_time packing (they return 10). +- Fix gettimeofday() +- Write a better stat function than the one RTL gives us. We can provide +user ID (on NT) and rwx permissions. +- Optionally use vfsapi.lib for ext2 filesystems on OS/2 +- Write the VFS +- Write a better documentation +- Write a better canonify_pathname() diff --git a/pc/chmod.c b/pc/chmod.c new file mode 100644 index 000000000..32cdb3652 --- /dev/null +++ b/pc/chmod.c @@ -0,0 +1,494 @@ +/* Chmod command for Windows NT and OS/2 + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include + +#ifdef __os2__ +#define INCL_DOSFILEMGR +#include +#endif + +#ifdef _OS_NT +#include +#endif + +#include +#include +/* for chmod and stat */ +#include +#include +#include +#include "tty.h" +#include "mad.h" +#include "util.h" +#include "win.h" +#include "color.h" +#include "dlg.h" +#include "widget.h" +#include "dialog.h" /* For do_refresh() */ + +#include "dir.h" +#include "panel.h" /* Needed for the externs */ +#include "file.h" +#include "main.h" +#include "chmod.h" +#include "achown.h" +#include "chown.h" + +#ifdef _OS_NT +#define FILE_ARCHIVED FILE_ATTRIBUTE_ARCHIVE +#define FILE_DIRECTORY FILE_ATTRIBUTE_DIRECTORY +#define FILE_HIDDEN FILE_ATTRIBUTE_HIDDEN +#define FILE_READONLY FILE_ATTRIBUTE_READONLY +#define FILE_SYSTEM FILE_ATTRIBUTE_SYSTEM +#define mk_chmod(fname,st) SetFileAttributes(fname,st) +#endif + +static int single_set; +struct Dlg_head *ch_dlg; + +#define PX 5 +#define PY 2 + +#define FX 40 +#define FY 2 + +#define BX 6 +#define BY 17 + +#define TX 40 +#define TY 12 + +#define PERMISSIONS 4 +#define BUTTONS 6 + +#define B_MARKED B_USER +#define B_ALL B_USER+1 +#define B_SETMRK B_USER+2 +#define B_CLRMRK B_USER+3 + +int mode_change, need_update; +int c_file, end_chmod; + +umode_t and_mask, or_mask, c_stat; +char *c_fname, *c_fown, *c_fgrp, *c_fperm; +int c_fsize; + +static WLabel *statl; +static int normal_color; +static int title_color; +static int selection_color; + +/* bsedos.h */ +struct { + mode_t mode; + char *text; + int selected; + WCheck *check; +} check_perm[PERMISSIONS] = { + + { + FILE_ARCHIVED, "Archive", 0, 0, + }, + { + FILE_READONLY, "Read Only", 0, 0, + }, + { + FILE_HIDDEN, "Hidden", 0, 0, + }, + { + FILE_SYSTEM, "System", 0, 0, + }, +}; + +struct { + int ret_cmd, flags, y, x; + char *text; +} chmod_but[BUTTONS] = { + + { + B_CANCEL, NORMAL_BUTTON, 2, 33, "&Cancel", + }, + { + B_ENTER, DEFPUSH_BUTTON, 2, 17, "&Set", + }, + { + B_CLRMRK, NORMAL_BUTTON, 0, 42, "C&lear marked", + }, + { + B_SETMRK, NORMAL_BUTTON, 0, 27, "S&et marked", + }, + { + B_MARKED, NORMAL_BUTTON, 0, 12, "&Marked all", + }, + { + B_ALL, NORMAL_BUTTON, 0, 0, "Set &all", + }, +}; + +static void chmod_toggle_select (void) +{ + int Id = ch_dlg->current->dlg_id - BUTTONS + single_set * 2; + + attrset (normal_color); + check_perm[Id].selected ^= 1; + + dlg_move (ch_dlg, PY + PERMISSIONS - Id, PX + 1); + addch ((check_perm[Id].selected) ? '*' : ' '); + dlg_move (ch_dlg, PY + PERMISSIONS - Id, PX + 3); +} + +static void chmod_refresh (void) +{ + attrset (normal_color); + dlg_erase (ch_dlg); + + draw_box (ch_dlg, 1, 2, 20 - single_set, 66); + draw_box (ch_dlg, PY, PX, PERMISSIONS + 2, 33); + draw_box (ch_dlg, FY, FX, 10, 25); + + dlg_move (ch_dlg, FY + 1, FX + 2); + addstr ("Name"); + dlg_move (ch_dlg, FY + 3, FX + 2); + addstr ("Permissions (Octal)"); + dlg_move (ch_dlg, FY + 5, FX + 2); + addstr ("Owner name"); + dlg_move (ch_dlg, FY + 7, FX + 2); + addstr ("Group name"); + + attrset (title_color); + dlg_move (ch_dlg, 1, 28); + addstr (" Chmod command "); + dlg_move (ch_dlg, PY, PX + 1); + addstr (" Permission "); + dlg_move (ch_dlg, FY, FX + 1); + addstr (" File "); + + attrset (selection_color); + + dlg_move (ch_dlg, TY, TX); + addstr ("Use SPACE to change"); + dlg_move (ch_dlg, TY + 1, TX); + addstr ("an option, ARROW KEYS"); + dlg_move (ch_dlg, TY + 2, TX); + addstr ("to move between options"); + dlg_move (ch_dlg, TY + 3, TX); + addstr ("and T or INS to mark"); +} + +static int chmod_callback (Dlg_head *h, int Par, int Msg) +{ + char buffer [10]; + + switch (Msg) { + case DLG_ACTION: + if (Par >= BUTTONS - single_set * 2){ + c_stat ^= check_perm[Par - BUTTONS + single_set * 2].mode; + sprintf (buffer, "%o", c_stat); + label_set_text (statl, buffer); + chmod_toggle_select (); + mode_change = 1; + } + break; + + case DLG_KEY: + if ((Par == 'T' || Par == 't' || Par == KEY_IC) && + ch_dlg->current->dlg_id >= BUTTONS - single_set * 2) { + chmod_toggle_select (); + if (Par == KEY_IC) + dlg_one_down (ch_dlg); + return 1; + } + break; +#ifndef HAVE_X + case DLG_DRAW: + chmod_refresh (); + break; +#endif + } + return 0; +} + +static void init_chmod (void) +{ + int i; + + do_refresh (); + end_chmod = c_file = need_update = 0; + single_set = (cpanel->marked < 2) ? 2 : 0; + + if (use_colors){ + normal_color = COLOR_NORMAL; + title_color = COLOR_HOT_NORMAL; + selection_color = COLOR_NORMAL; + } else { + normal_color = NORMAL_COLOR; + title_color = SELECTED_COLOR; + selection_color = SELECTED_COLOR; + } + + ch_dlg = create_dlg (0, 0, 22 - single_set, 70, dialog_colors, + chmod_callback, "[Chmod]", "chmod", DLG_CENTER); + + x_set_dialog_title (ch_dlg, "Chmod command"); + +#define XTRACT(i) BY+chmod_but[i].y-single_set, BX+chmod_but[i].x, \ + chmod_but[i].ret_cmd, chmod_but[i].flags, chmod_but[i].text, 0, 0, NULL + + tk_new_frame (ch_dlg, "b."); + for (i = 0; i < BUTTONS; i++) { + if (i == 2 && single_set) + break; + else + add_widgetl (ch_dlg, button_new (XTRACT (i)), XV_WLAY_RIGHTOF); + } + + +#define XTRACT2(i) 0, check_perm [i].text, NULL + tk_new_frame (ch_dlg, "c."); + for (i = 0; i < PERMISSIONS; i++) { + check_perm[i].check = check_new (PY + (PERMISSIONS - i), PX + 2, + XTRACT2 (i)); + add_widget (ch_dlg, check_perm[i].check); + } +} + +int pc_stat_file (char *filename) +{ + mode_t st; + +#ifdef _OS_NT + st = GetFileAttributes (filename); +#endif /* _OS_NT */ + +#ifdef __os2__ + HFILE fHandle = 0L; + ULONG fInfoLevel = 1; /* 1st Level Info: Standard attributs */ + FILESTATUS3 fInfoBuf; + ULONG fInfoBufSize; + ULONG fAction = 0; + APIRET rc; + + fInfoBufSize = sizeof(FILESTATUS3); + rc = DosOpen((PSZ) filename, + &fHandle, + &fAction, + (ULONG) 0, + FILE_NORMAL, + OPEN_ACTION_OPEN_IF_EXISTS, + (OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE), + (PEAOP2) NULL); + if (rc != 0) { + return -1; + } + + rc = DosQueryFileInfo(fHandle, fInfoLevel, &fInfoBuf, fInfoBufSize); + DosClose(fHandle); + if (rc != 0) { + return -1; /* error ! */ + } else { + st = fInfoBuf.attrFile; + } +#endif /* __os2__ */ + + if (st & FILE_DIRECTORY) + st = -1; + return st; +} + +static void chmod_done (void) +{ + if (need_update) + update_panels (UP_OPTIMIZE, UP_KEEPSEL, UP_KEEPSEL); + repaint_screen (); +} + +char *next_file (void) +{ + while (!cpanel->dir.list[c_file].f.marked) + c_file++; + + return cpanel->dir.list[c_file].fname; +} + +#ifdef __os2__ +static int mk_chmod (char *filename, ULONG st) +{ + HFILE fHandle = 0L; + ULONG fInfoLevel = 1; /* 1st Level Info: Standard attributs */ + FILESTATUS3 fInfoBuf; + ULONG fInfoBufSize; + ULONG fAction = 0L; + APIRET rc; + + if (!(st & FILE_READONLY)) + chmod(filename, (S_IWRITE | S_IREAD)); + fInfoBufSize = sizeof(FILESTATUS3); + rc = DosOpen((PSZ) filename, + &fHandle, + &fAction, + (ULONG) 0, + FILE_NORMAL, + OPEN_ACTION_OPEN_IF_EXISTS, + (OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE), + 0L); + if (rc != 0) { + return rc; + } + + rc = DosQueryFileInfo(fHandle, fInfoLevel, &fInfoBuf, fInfoBufSize); + if (rc!=0) { + DosClose(fHandle); + return rc; + } + fInfoBuf.attrFile = st; + rc = DosSetFileInfo(fHandle, fInfoLevel, &fInfoBuf, fInfoBufSize); + rc = DosClose(fHandle); + return rc; +} +#endif /* __os2__ */ + +static void do_chmod (mode_t sf) +{ + sf &= and_mask; + sf |= or_mask; + + mk_chmod(cpanel->dir.list[c_file].fname, sf); + + do_file_mark (cpanel, c_file, 0); +} + +static void apply_mask (mode_t sf) +{ + char *fname; + mode_t sf_stat; + + need_update = end_chmod = 1; + do_chmod (sf); + + do { + fname = next_file (); + if ((sf_stat = pc_stat_file (fname)) < 0) + break; + + c_stat = sf_stat; + do_chmod (c_stat); + } while (cpanel->marked); +} + +void chmod_cmd (void) +{ + char buffer [10]; + char *fname; + int i; + mode_t sf_stat; + + do { /* do while any files remaining */ + init_chmod (); + if (cpanel->marked) + fname = next_file (); /* next marked file */ + else + fname = selection (cpanel)->fname; /* single file */ + + if ((sf_stat = pc_stat_file (fname)) < 0) /* get status of file */ + break; + + c_stat = sf_stat; + mode_change = 0; /* clear changes flag */ + + /* set check buttons */ + for (i = 0; i < PERMISSIONS; i++){ + check_perm[i].check->state = (c_stat & check_perm[i].mode) ? 1 : 0; + check_perm[i].selected = 0; + } + + tk_new_frame (ch_dlg, "l."); + /* Set the labels */ + c_fname = name_trunc (fname, 21); + add_widget (ch_dlg, label_new (FY+2, FX+2, c_fname, NULL)); + c_fown = "unknown"; + add_widget (ch_dlg, label_new (FY+6, FX+2, c_fown, NULL)); + c_fgrp = "unknown"; + add_widget (ch_dlg, label_new (FY+8, FX+2, c_fgrp, NULL)); + sprintf (buffer, "%o", c_stat); + statl = label_new (FY+4, FX+2, buffer, NULL); + add_widget (ch_dlg, statl); + tk_end_frame (); + + run_dlg (ch_dlg); /* retrieve an action */ + + /* do action */ + switch (ch_dlg->ret_value){ + case B_ENTER: + if (mode_change) + mk_chmod (fname, c_stat); /*.ado */ + need_update = 1; + break; + + case B_CANCEL: + end_chmod = 1; + break; + + case B_ALL: + case B_MARKED: + and_mask = or_mask = 0; + and_mask = ~and_mask; + + for (i = 0; i < PERMISSIONS; i++) { + if (check_perm[i].selected || ch_dlg->ret_value == B_ALL) + if (check_perm[i].check->state & C_BOOL) + or_mask |= check_perm[i].mode; + else + and_mask &= ~check_perm[i].mode; + } + + apply_mask (sf_stat); + break; + + case B_SETMRK: + and_mask = or_mask = 0; + and_mask = ~and_mask; + + for (i = 0; i < PERMISSIONS; i++) { + if (check_perm[i].selected) + or_mask |= check_perm[i].mode; + } + + apply_mask (sf_stat); + break; + case B_CLRMRK: + and_mask = or_mask = 0; + and_mask = ~and_mask; + + for (i = 0; i < PERMISSIONS; i++) { + if (check_perm[i].selected) + and_mask &= ~check_perm[i].mode; + } + + apply_mask (sf_stat); + break; + } + + if (cpanel->marked && ch_dlg->ret_value!=B_CANCEL) { + do_file_mark (cpanel, c_file, 0); + need_update = 1; + } + destroy_dlg (ch_dlg); + } while (cpanel->marked && !end_chmod); + chmod_done (); +} diff --git a/pc/config.h b/pc/config.h new file mode 100644 index 000000000..7f8b5c857 --- /dev/null +++ b/pc/config.h @@ -0,0 +1,227 @@ +/**************************************************************************** + CONFIG.H - Midnight Commander Configuration for Win32 and OS/2 + + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + ---------------------------------------------------------------------------- + Changes: + - Created 951204/jfg + - Changed from Alexander Dong (ado) for OS/2 + - Changed 980329 by Pavel Roskin for both OS/2 and NT + + ---------------------------------------------------------------------------- + Contents: + - Headers flags + - Library flags + - Typedefs + - etc. + ****************************************************************************/ +#ifndef __CONFIG_H +#define __CONFIG_H + +#define OS2_NT + +#ifdef MC_NT +# ifndef WIN32 +# define WIN32 +# endif +# ifndef __WIN32__ +# define __WIN32__ +# endif +# ifndef MSWINDOWS +# define MSWINDOWS +# endif +# ifndef _OS_NT +# define _OS_NT +# endif +#endif /* MC_NT */ + +#ifdef MC_OS2 +# ifndef OS2 +# define OS2 +# endif +# ifndef __os2__ +# define __os2__ +# endif +#endif /* MC_OS2 */ + +#include "..\VERSION" + +#ifndef pc_system +# define pc_system +#endif + +#ifndef HAVE_SLANG +# define HAVE_SLANG +#endif + +#ifndef _CONSOLE +# define _CONSOLE +#endif + +#define FLOAT_TYPE +#define MIDNIGHT +#define USE_INTERNAL_EDIT + +#define STDC_HEADERS +#define HAVE_STDLIB_H +#define HAVE_STRING_H +#define HAVE_DIRENT_H +#define HAVE_LIMITS_H +#define HAVE_FCNTL_H +#define HAVE_UTIME_H + +#define HAVE_MEMSET +#define HAVE_MEMCHR +#define HAVE_MEMCPY +#define HAVE_MEMCMP +#define HAVE_MEMMOVE +#define HAVE_STRDUP +#define HAVE_STRERROR +#define HAVE_TRUNCATE + +#define REGEX_MALLOC +#define NO_INFOMOUNT + +typedef unsigned int umode_t; +#define S_IFLNK 0 +#define S_ISLNK(x) 0 + +#ifdef __EMX__ + +#define S_IFBLK 0 +#define S_ISBLK(x) 0 + +#endif /* __EMX__ */ + +#ifdef _MSC_VER + +#pragma include_alias(, ) + +#define INLINE +#define inline + +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) + +#define S_ISFIFO(m) 0 +#define S_ISBLK(x) 0 + +#define S_IRWXU 0000700 +#define S_IRUSR 0000400 +#define S_IWUSR 0000200 +#define S_IXUSR 0000100 + +#define S_IRWXG 0000070 +#define S_IRGRP 0000040 +#define S_IWGRP 0000020 +#define S_IXGRP 0000010 +#define S_IRWXO 0000007 +#define S_IROTH 0000004 +#define S_IWOTH 0000002 +#define S_IXOTH 0000001 + +/* FIXME: is this definition correct? */ +#define R_OK 4 + +#define pipe(p) _pipe(p, 4096, 0x8000 /* O_BINARY */) +#define popen _popen +#define pclose _pclose + +typedef int mode_t; +typedef unsigned int nlink_t; +typedef int gid_t; +typedef int uid_t; +typedef int pid_t; + +#endif /* _MSC_VER */ + +#ifdef __BORLANDC__ + +#define INLINE +#define inline + +#define S_IRWXG 0000070 +#define S_IRGRP 0000040 +#define S_IWGRP 0000020 +#define S_IXGRP 0000010 +#define S_IRWXO 0000007 +#define S_IROTH 0000004 +#define S_IWOTH 0000002 +#define S_IXOTH 0000001 + +/* FIXME: is this definition correct? */ +#define R_OK 4 + +#define pipe(p) _pipe(p, 4096, 0x8000 /* O_BINARY */) +#define popen _popen +#define pclose _pclose +#define sleep _sleep + +typedef int pid_t; + +#endif /* __BORLANDC__ */ + +#ifdef __IBMC__ + +#define INLINE +#define inline + +#define S_ISFIFO(m) 0 +#define S_ISBLK(x) 0 + +#define S_ISCHR(m) (((m) & S_IFCHR) != 0) +#define S_ISDIR(m) (((m) & S_IFDIR) != 0) +#define S_ISREG(m) (((m) & S_IFREG) != 0) + +#define S_IRWXU 0000700 +#define S_IRUSR 0000400 +#define S_IWUSR 0000200 +#define S_IXUSR 0000100 + +#define S_IRWXG 0000070 +#define S_IRGRP 0000040 +#define S_IWGRP 0000020 +#define S_IXGRP 0000010 +#define S_IRWXO 0000007 +#define S_IROTH 0000004 +#define S_IWOTH 0000002 +#define S_IXOTH 0000001 + +#define ENOTDIR ENOENT + +/* FIXME: is this definition correct? */ +#define R_OK 4 + +#pragma map( chdir , "_chdir" ) +#pragma map( getcwd, "_getcwd" ) +#pragma map( mkdir , "_mkdir" ) +#pragma map( rmdir , "_rmdir" ) + +#define popen DosCreatePipe +#define pclose DosClose +#define sleep DosSleep + +typedef unsigned int nlink_t; +typedef int mode_t; +typedef int gid_t; +typedef int uid_t; +typedef int pid_t; + +#endif /* __IBMC__ */ + +#endif /* __CONFIG_H */ diff --git a/pc/cons_nt.c b/pc/cons_nt.c new file mode 100644 index 000000000..4b5d9b93f --- /dev/null +++ b/pc/cons_nt.c @@ -0,0 +1,110 @@ +/* Client interface for General purpose Win32 console save/restore server + Having the same interface as its Linux counterpart: + Copyright (C) 1994 Janne Kukonlehto + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Note: + show_console_contents doesn't know how to write to its window + the rest works fine. +*/ +#include + +#include +#include "trace_nt.h" + +int cons_saver_pid = 1; + +#include "tty.h" +#include "util.h" +#include "win.h" +#include "cons.saver.h" + +signed char console_flag = 1; +static HANDLE hSaved, hNew; + +void show_console_contents (int starty, unsigned char begin_line, + unsigned char end_line) +{ + COORD c0 = { 0, 0 }; + COORD csize; + SMALL_RECT rect; + CHAR_INFO *pchar; + + csize.X = COLS; + csize.Y = end_line-begin_line; + rect.Left = 0; + rect.Top = begin_line; + rect.Right = COLS; + rect.Bottom = end_line; + +/* -- This code reads characters and attributes */ + pchar = malloc (sizeof(CHAR_INFO) * (end_line-begin_line) * COLS); + /* Copy from one console to the curses virtual screen */ + win32APICALL(ReadConsoleOutput (hSaved, pchar, csize, c0, &rect)); + + /* FIXME: this should've work, + but refresh() is called after this write :-( */ + win32APICALL(WriteConsoleOutput (hNew, pchar, csize, c0, &rect)); + + free (pchar); +} + +void handle_console (unsigned char action) +{ + static SECURITY_ATTRIBUTES sa; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + switch (action){ + case CONSOLE_INIT: + /* Save Standard handle */ + hSaved = GetStdHandle (STD_OUTPUT_HANDLE); + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + /* Create a new console buffer */ + sa.bInheritHandle = TRUE; + win32APICALL_HANDLE(hNew, + CreateConsoleScreenBuffer (GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, + CONSOLE_TEXTMODE_BUFFER, NULL)); + win32APICALL(GetConsoleScreenBufferInfo(hSaved, &csbi)); + win32APICALL(SetConsoleScreenBufferSize(hNew, csbi.dwSize)); + + /* that becomes standard handle */ + win32APICALL(SetConsoleActiveScreenBuffer(hNew)); + win32APICALL(SetConsoleMode(hNew, ENABLE_PROCESSED_INPUT)); + win32APICALL(SetStdHandle(STD_OUTPUT_HANDLE, hNew)); + break; + + case CONSOLE_DONE: + win32APICALL(CloseHandle (hNew)); + break; + + case CONSOLE_SAVE: + /* Current = our standard handle */ + win32APICALL(SetConsoleActiveScreenBuffer (hNew)); + win32APICALL(SetStdHandle (STD_OUTPUT_HANDLE, hNew)); + break; + + case CONSOLE_RESTORE: + /* Put saved (shell) screen buffer */ + win32APICALL(SetConsoleActiveScreenBuffer (hSaved)); + win32APICALL(SetStdHandle (STD_OUTPUT_HANDLE, hSaved)); + break; + default: + win32Trace(("Invalid action code %d sent to handle_console", action)); + } +} diff --git a/pc/cons_os2.c b/pc/cons_os2.c new file mode 100644 index 000000000..5b6184820 --- /dev/null +++ b/pc/cons_os2.c @@ -0,0 +1,110 @@ +/* Client interface for General purpose OS/2 console save/restore server. + 1997 Alexander Dong + Having the same interface as its Linux counterpart: + Copyright (C) 1994 Janne Kukonlehto + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include + +#ifdef __os2__ +#define INCL_BASE +#define INCL_NOPM +#define INCL_VIO +#define INCL_KBD +#define INCL_DOS +#define INCL_SUB +#define INCL_DOSERRORS +#include +#endif + +#include "tty.h" +#include "util.h" +#include "win.h" +#include "cons.saver.h" + +signed char console_flag = 1; +static unsigned char *scr_buffer; +static unsigned char *pointer; + +static int GetScrRows(); +static int GetScrCols(); + +static int GetScrRows() +{ + VIOMODEINFO pvMode = {80}; + unsigned int hVio = 0; + VioGetMode(&pvMode, hVio); + return (pvMode.row ? pvMode.row: 25); +} + +static int GetScrCols() +{ + VIOMODEINFO pvMode = {80}; + unsigned int hVio = 0; + VioGetMode(&pvMode, hVio); + return (pvMode.col ? pvMode.col: 80); +} + +void show_console_contents (int starty, unsigned char begin_line, unsigned char end_line) +{ + int col = GetScrCols(); + int row = GetScrRows(); + int n; + register int z; + + pointer = scr_buffer; + for (z=0; z<(begin_line * col); z++) { + pointer++; pointer++; + } + n = (end_line - begin_line + 1) * col; + VioWrtCellStr((PCH) pointer, (USHORT) n, begin_line, 0, 0); + return; +} + +void handle_console (unsigned char action) +{ + static int col; + static int row; + int n; + + switch (action) { + case CONSOLE_INIT: /* Initialize */ + col = GetScrCols(); + row = GetScrRows(); + scr_buffer = (unsigned char *) malloc(col * row * 2); /* short values */ + n = col * row * 2; + VioReadCellStr((PCH) scr_buffer, (USHORT *) &n, 0, 0, 0); /* Just save it */ + break; + case CONSOLE_DONE: + free(scr_buffer); + break; + case CONSOLE_SAVE: /* Save the screen */ + n = col * row * 2; + VioReadCellStr((PCH) scr_buffer, (USHORT *) &n, 0, 0, 0); + break; + case CONSOLE_RESTORE: + n = col * row * 2; + VioWrtCellStr ((PCH) scr_buffer, (USHORT) n, 0, 0, 0); /* Write it back */ + break; + default: + /* This is not possible, but if we are here, just save the screen */ + handle_console(CONSOLE_SAVE); + break; + } + return; +} diff --git a/pc/dirent.h b/pc/dirent.h new file mode 100644 index 000000000..5c8024d32 --- /dev/null +++ b/pc/dirent.h @@ -0,0 +1,70 @@ +/* + * direct.h Defines the types and structures used by the directory routines + * + */ +#ifndef _DIRENT_H_incl +#define _DIRENT_H_incl + +#ifdef __WATCOMC__ +#include + +#else + +#ifdef __cplupplus +extern "C" { +#endif + +#include + +#ifdef __os2__ +#ifndef __OS2_H__ +#define INCL_DOSFILEMGR +#define INCL_DOSERRORS +#include +#endif +#endif /* __os2__ */ + +#define NAME_MAX 255 /* maximum filename for HPFS or NTFS */ + +typedef struct dirent { + unsigned long* d_handle; + unsigned d_attr; /* file's attribute */ + unsigned short int d_time; /* file's time */ + unsigned short int d_date; /* file's date */ + long d_size; /* file's size */ + char d_name[ NAME_MAX + 1 ]; /* file's name */ + unsigned short d_ino; /* serial number (not used) */ + char d_first; /* flag for 1st time */ +} DIR; + +#ifndef _A_NORMAL +#define _A_NORMAL 0x00 /* Normal file - read/write permitted */ +#define _A_RDONLY 0x01 /* Read-only file */ +#define _A_HIDDEN 0x02 /* Hidden file */ +#define _A_SYSTEM 0x04 /* System file */ +#define _A_VOLID 0x08 /* Volume-ID entry */ +#define _A_SUBDIR 0x10 /* Subdirectory */ +#define _A_ARCH 0x20 /* Archive file */ +#endif /* _A_NORMAL_ */ + +extern int closedir( DIR * ); +/* +extern char *getcwd( char *__buf, unsigned __size ); +extern unsigned _getdrive( void ); +extern unsigned _getdiskfree( unsigned __drive, struct _diskfree_t *__diskspace); +*/ +extern DIR *opendir( const char * ); +extern struct dirent *readdir( DIR * ); +#if !defined(__os2__) +extern int chdir( const char *__path ); +extern int mkdir( const char *__path ); +extern int rmdir( const char *__path ); +#endif + +#ifdef __cplusplus +}; +#endif + +#endif /* __WATCOMC__ */ + +#endif /* _DIRENT_H_incl */ diff --git a/pc/dirent_nt.c b/pc/dirent_nt.c new file mode 100644 index 000000000..029912a75 --- /dev/null +++ b/pc/dirent_nt.c @@ -0,0 +1,92 @@ + +#include +#include +#include +#include +#include +#include + +DIR *opendir (const char * a_dir) +{ + int err; + WIN32_FIND_DATA wfd; + DIR* dd_dir = (DIR*) malloc (sizeof(DIR)); + + char *c_dir = malloc (strlen(a_dir) + 4); + strcpy (c_dir, a_dir); + strcat (c_dir, "\\*"); + + dd_dir->d_handle = FindFirstFile (c_dir, &wfd); + if (dd_dir->d_handle == INVALID_HANDLE_VALUE) { + err = GetLastError(); + switch (err) { + case ERROR_NO_MORE_FILES: + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + errno = ENOENT; + break; + case ERROR_NOT_ENOUGH_MEMORY: + errno = ENOMEM; + break; + default: + errno = EINVAL; + break; + } + free(dd_dir); + return NULL; + } + dd_dir->d_attr = (wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) + ? 0 : wfd.dwFileAttributes; + + dd_dir->d_time = dd_dir->d_date = 10; + dd_dir->d_size = wfd.nFileSizeLow; + strcpy (dd_dir->d_name, wfd.cFileName); + dd_dir->d_first = 1; + + free (c_dir); + return dd_dir; +} + +DIR *readdir( DIR * dd_dir) +{ + int err; + WIN32_FIND_DATA wfd; + + if (dd_dir->d_first) { + dd_dir->d_first = 0; + return dd_dir; + } + + if(!FindNextFile (dd_dir->d_handle, &wfd)) { + err = GetLastError(); + switch (err) { + case ERROR_NO_MORE_FILES: + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + errno = ENOENT; + break; + case ERROR_NOT_ENOUGH_MEMORY: + errno = ENOMEM; + break; + default: + errno = EINVAL; + break; + } + return NULL; + } + dd_dir->d_attr = (wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) + ? 0 : wfd.dwFileAttributes; + + dd_dir->d_time = dd_dir->d_date = 10; + dd_dir->d_size = wfd.nFileSizeLow; + strcpy (dd_dir->d_name, wfd.cFileName); + return dd_dir; +} + +int closedir (DIR *dd_dir) +{ + FindClose(dd_dir->d_handle); + free (dd_dir); + return 1; +} + diff --git a/pc/dirent_os2.c b/pc/dirent_os2.c new file mode 100644 index 000000000..63e8a3d63 --- /dev/null +++ b/pc/dirent_os2.c @@ -0,0 +1,131 @@ +#define INCL_DOSFILEMGR +#define INCL_DOSERRORS + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include "dirent.h" +#include + +DIR *opendir (const char * a_dir) +{ + APIRET rc; + FILEFINDBUF3 FindBuffer = {0}; + ULONG FileCount = 1; + DIR *dd_dir = (DIR*) malloc (sizeof(DIR)); + char *c_dir = (char*) malloc (strlen(a_dir) + 5); + + strcpy (c_dir, a_dir); + strcat (c_dir, "\\*.*"); + dd_dir->d_handle = HDIR_CREATE; + + rc = DosFindFirst(c_dir, + (PHDIR) &dd_dir->d_handle, + /* FILE_NORMAL || FILE_DIRECTORY, */ + FILE_DIRECTORY, + (PVOID) &FindBuffer, + sizeof(FILEFINDBUF3), + &FileCount, + FIL_STANDARD); + + switch (rc) { + case ERROR_NO_MORE_FILES: + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + errno = ENOENT; + free(dd_dir); + return NULL; + break; + case ERROR_BUFFER_OVERFLOW: + errno = ENOMEM; + free(dd_dir); + return NULL; + break; + case NO_ERROR: /* go through */ + break; + default: + errno = EINVAL; + free(dd_dir); + return NULL; + break; + } + dd_dir->d_attr = FindBuffer.attrFile; + /* dd_dir->d_attr = (wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) + ? 0 : wfd.dwFileAttributes; */ + + dd_dir->d_time = dd_dir->d_date = 10; + dd_dir->d_size = FindBuffer.cbFile; + strcpy (dd_dir->d_name, FindBuffer.achName); + dd_dir->d_first = 1; + + free (c_dir); + return dd_dir; +} + +DIR *readdir( DIR * dd_dir) +{ + APIRET rc; + FILEFINDBUF3 FindBuffer = {0}; + ULONG FileCount = 1; + DIR *ret_dir = (DIR*) malloc (sizeof(DIR)); + + if (dd_dir->d_first) { + dd_dir->d_first = 0; + return dd_dir; + } + + rc = DosFindNext((HDIR) dd_dir->d_handle, + (PVOID) &FindBuffer, + sizeof(FILEFINDBUF3), + &FileCount); + + switch (rc) { + case ERROR_NO_MORE_FILES: + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + errno = ENOENT; + return NULL; + break; + case ERROR_BUFFER_OVERFLOW: + errno = ENOMEM; + return NULL; + break; + case NO_ERROR: /* go through */ + break; + default: + errno = EINVAL; + return NULL; + break; + } + /* dd_dir->d_attr = (wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) + ? 0 : wfd.dwFileAttributes; */ + /* #define FILE_NORMAL 0x0000 + #define FILE_READONLY 0x0001 + #define FILE_HIDDEN 0x0002 + #define FILE_SYSTEM 0x0004 + #define FILE_DIRECTORY 0x0010 + #define FILE_ARCHIVED 0x0020 + */ + + ret_dir->d_attr = FindBuffer.attrFile; + + ret_dir->d_time = ret_dir->d_date = 10; + ret_dir->d_size = FindBuffer.cbFile; + strcpy (ret_dir->d_name, FindBuffer.achName); + return ret_dir; +} + +int closedir (DIR *dd_dir) +{ + if (dd_dir->d_handle != HDIR_CREATE) { + DosFindClose((HDIR) dd_dir->d_handle); + } + free (dd_dir); + return 1; +} + + diff --git a/pc/drive.c b/pc/drive.c new file mode 100644 index 000000000..db0ab9ba3 --- /dev/null +++ b/pc/drive.c @@ -0,0 +1,218 @@ +/* Ch-Drive command for Windows NT and OS/2 + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Bug: + the code will not work if you have more drives than those that + can fit in a panel. + */ + +#include +#ifdef _OS_NT +#include +#include "util_win32.h" +#endif +#include +#include +#include +#include +#include "tty.h" +#include "mad.h" +#include "util.h" +#include "win.h" +#include "color.h" +#include "dlg.h" +#include "widget.h" +#include "dialog.h" +#include "dir.h" +#include "panel.h" +#include "main.h" +#include "cmd.h" + +struct Dlg_head *drive_dlg; +WPanel *this_panel; + +static int drive_dlg_callback (Dlg_head *h, int Par, int Msg); +static void drive_dlg_refresh (void); +static void drive_cmd(void); + +#define B_DRIVE_BASE 100 +#define MAX_LGH 13 /* Length for drives */ + +static void drive_cmd() +{ + int i, nNewDrive, nDrivesAvail; + char szTempBuf[7], szDrivesAvail[27*4], *p; + + /* Dialogbox position */ + int x_pos; + int y_pos = (LINES-6)/2-3; + int y_height; + int x_width; + + int m_drv; + + /* Get drives name and count */ +#ifdef _OS_NT + GetLogicalDriveStrings (255, szDrivesAvail); + for (nDrivesAvail = 0, p = szDrivesAvail; *p; nDrivesAvail++) + p+=4; +#else + unsigned long uDriveNum, uDriveMap; + nDrivesAvail = 0; + p = szDrivesAvail; + DosQueryCurrentDisk(&uDriveNum, &uDriveMap); + for (i = 0; i < 26; i++) { + if ( uDriveMap & (1 << i) ) { + *p = 'A' + i; + p += 4; + nDrivesAvail++; + } + } + *p = 0; +#endif + + /* Create Dialog */ + do_refresh (); + + m_drv = ((nDrivesAvail > MAX_LGH) ? MAX_LGH: nDrivesAvail); + /* Center on x, relative to panel */ + x_pos = this_panel->widget.x + (this_panel->widget.cols - m_drv*3)/2 + 2; + + if (nDrivesAvail > MAX_LGH) { + y_height = 8; + x_width = 33; + } else { + y_height = 6; + x_width = (nDrivesAvail - 1) * 2 + 9; + } + + drive_dlg = create_dlg (y_pos, x_pos, y_height, x_width, dialog_colors, + drive_dlg_callback, "[ChDrive]", "drive", DLG_NONE); + + x_set_dialog_title (drive_dlg, "Change Drive"); + + if (nDrivesAvail>MAX_LGH) { + for (i = 0; i < nDrivesAvail - MAX_LGH; i++) { + p -= 4; + sprintf(szTempBuf, "&%c", *p); + add_widgetl(drive_dlg, + button_new (5, + (m_drv-i-1)*2+4 - (MAX_LGH*2 - nDrivesAvail) * 2, + B_DRIVE_BASE + nDrivesAvail - i - 1, + HIDDEN_BUTTON, + szTempBuf, 0, NULL, NULL), + XV_WLAY_RIGHTOF); + } + } + + /* Add a button for each drive */ + for (i = 0; i < m_drv; i++) { + p -= 4; + sprintf (szTempBuf, "&%c", *p); + add_widgetl(drive_dlg, + button_new (3, (m_drv-i-1)*2+4, B_DRIVE_BASE+m_drv-i-1, + HIDDEN_BUTTON, szTempBuf, 0, NULL, NULL), + XV_WLAY_RIGHTOF); + } + + run_dlg(drive_dlg); + + /* do action */ + if (drive_dlg->ret_value != B_CANCEL) { + int errocc = 0; /* no error */ + int rtn; + char drvLetter; + + nNewDrive = drive_dlg->ret_value - B_DRIVE_BASE; + drvLetter = (char) *(szDrivesAvail + (nNewDrive*4)); +#ifdef _OS_NT + if (win32_GetPlatform() == OS_WinNT) { /* Windows NT */ + rtn = _chdrive(drvLetter - 'A' + 1); + } else { /* Windows 95 */ + rtn = 1; + SetCurrentDirectory(szDrivesAvail+(nNewDrive*4)); + } +#else + rtn = DosSetDefaultDisk(nNewDrive + 1); +#endif + if (rtn == -1) + errocc = 1; + else { + getcwd (this_panel->cwd, sizeof (this_panel->cwd)-2); + if (toupper(drvLetter) == toupper(*(this_panel->cwd))) { + clean_dir (&this_panel->dir, this_panel->count); + this_panel->count = do_load_dir(&this_panel->dir, + this_panel->sort_type, + this_panel->reverse, + this_panel->case_sensitive, + this_panel->filter); + this_panel->top_file = 0; + this_panel->selected = 0; + this_panel->marked = 0; + this_panel->total = 0; + show_dir(this_panel); + reread_cmd(); + } else + errocc = 1; + } + if (errocc) + message (1, " Error ", " Can't access drive %c: ", + *(szDrivesAvail+(nNewDrive*4)) ); + } + destroy_dlg (drive_dlg); + repaint_screen (); +} + +void drive_cmd_a() +{ + this_panel = left_panel; + drive_cmd(); +} + +void drive_cmd_b() +{ + this_panel = right_panel; + drive_cmd(); +} + +void drive_chg(WPanel *panel) +{ + this_panel = panel; + drive_cmd(); +} + +static int drive_dlg_callback (Dlg_head *h, int Par, int Msg) +{ + switch (Msg) { +#ifndef HAVE_X + case DLG_DRAW: + drive_dlg_refresh (); + break; +#endif + } + return 0; +} + +static void drive_dlg_refresh (void) +{ + attrset (dialog_colors[0]); + dlg_erase (drive_dlg); + draw_box (drive_dlg, 1, 1, drive_dlg->lines-2, drive_dlg->cols-2); + + attrset (dialog_colors[2]); + dlg_move (drive_dlg, 1, drive_dlg->cols/2 - 7); + addstr (" Change Drive "); +} diff --git a/pc/drive.h b/pc/drive.h new file mode 100644 index 000000000..7b7c01f2d --- /dev/null +++ b/pc/drive.h @@ -0,0 +1,4 @@ +void drive_cmd_a(WPanel *); +void drive_cmd_b(WPanel *); +void drive_chg(WPanel *panel); + diff --git a/pc/key_nt.c b/pc/key_nt.c new file mode 100644 index 000000000..b39d3dd5e --- /dev/null +++ b/pc/key_nt.c @@ -0,0 +1,305 @@ +/* Keyboard support routines. + for Windows NT system. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Bugs: + Have trouble with non-US keyboards, "Alt-gr"+keys (API tells CTRL-ALT is pressed) + */ +#include +#ifndef _OS_NT +#error This file is for Win32 systems. +#else + +#include +#include +#include "mouse.h" +#include "global.h" +#include "main.h" +#include "key.h" +#include "../vfs/vfs.h" +#include "tty.h" +#include "trace_nt.h" + +/* Global variables */ +int old_esc_mode = 0; +HANDLE hConsoleInput; +DWORD dwSaved_ControlState; +Gpm_Event evSaved_Event; + +/* Unused variables */ +int double_click_speed; /* they are here to keep linker happy */ +int mou_auto_repeat; +int use_8th_bit_as_meta = 0; + +/* Static Tables */ +struct { + int key_code; + int vkcode; +} key_table [] = { + { KEY_F(1), VK_F1 }, + { KEY_F(2), VK_F2 }, + { KEY_F(3), VK_F3 }, + { KEY_F(4), VK_F4 }, + { KEY_F(5), VK_F5 }, + { KEY_F(6), VK_F6 }, + { KEY_F(7), VK_F7 }, + { KEY_F(8), VK_F8 }, + { KEY_F(9), VK_F9 }, + { KEY_F(10), VK_F10 }, + { KEY_F(11), VK_F11 }, + { KEY_F(12), VK_F12 }, + { KEY_F(13), VK_F13 }, + { KEY_F(14), VK_F14 }, + { KEY_F(15), VK_F15 }, + { KEY_F(16), VK_F16 }, + { KEY_F(17), VK_F17 }, + { KEY_F(18), VK_F18 }, + { KEY_F(19), VK_F19 }, + { KEY_F(20), VK_F20 }, + { KEY_IC, VK_INSERT }, + { KEY_DC, VK_DELETE }, + { KEY_BACKSPACE, VK_BACK }, + + { KEY_PPAGE, VK_PRIOR }, + { KEY_NPAGE, VK_NEXT }, + { KEY_LEFT, VK_LEFT }, + { KEY_RIGHT, VK_RIGHT }, + { KEY_UP, VK_UP }, + { KEY_DOWN, VK_DOWN }, + { KEY_HOME, VK_HOME }, + { KEY_END, VK_END }, + + { ALT('*'), VK_MULTIPLY }, + { ALT('+'), VK_ADD }, + { ALT('-'), VK_SUBTRACT }, + + { ESC_CHAR, VK_ESCAPE }, + + { 0, 0} +}; + +/* init_key - Called in main.c to initialize ourselves + Get handle to console input +*/ +void init_key (void) +{ + win32APICALL_HANDLE (hConsoleInput, GetStdHandle (STD_INPUT_HANDLE)); +} + +int ctrl_pressed () +{ + return dwSaved_ControlState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED); +} + +int shift_pressed () +{ + return dwSaved_ControlState & SHIFT_PRESSED; +} + +int alt_pressed () +{ + return dwSaved_ControlState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED); +} + +static int VKtoCurses (int a_vkc) +{ + int i; + + for (i = 0; key_table[i].vkcode != 0; i++) + if (a_vkc == key_table[i].vkcode) { + return key_table[i].key_code; + } + return 0; +} + +static int translate_key_code(int asc, int scan) +{ + int c; + c = VKtoCurses (scan); + if (!asc && !c) + return 0; + if (asc && c) + return c; + if (!asc) + { + if (shift_pressed() && (c >= KEY_F(1)) && (c <= KEY_F(10))) + c += 10; + if (alt_pressed() && (c >= KEY_F(1)) && (c <= KEY_F(2))) + c += 10; + if (alt_pressed() && (c == KEY_F(7))) + c = ALT('?'); + if (ctrl_pressed() && c == '\t') + c = ALT('\t'); + return c; + } + if (ctrl_pressed()) + return XCTRL(asc); + if (alt_pressed()) + return ALT(asc); + if (asc == 13) + return 10; + return asc; +} + +int get_key_code (int no_delay) +{ + INPUT_RECORD ir; /* Input record */ + DWORD dw; /* number of records actually read */ + int ch, vkcode, j; + + if (no_delay) { + /* Check if any input pending, otherwise return */ + nodelay (stdscr, TRUE); + win32APICALL(PeekConsoleInput(hConsoleInput, &ir, 1, &dw)); + if (!dw) + return 0; + } + + do { + win32APICALL(ReadConsoleInput(hConsoleInput, &ir, 1, &dw)); + switch (ir.EventType) { + case KEY_EVENT: + if (!ir.Event.KeyEvent.bKeyDown) /* Process key just once: when pressed */ + break; + + vkcode = ir.Event.KeyEvent.wVirtualKeyCode; + ch = ir.Event.KeyEvent.uChar.AsciiChar; + dwSaved_ControlState = ir.Event.KeyEvent.dwControlKeyState; + j = translate_key_code (ch, vkcode); + if (j) + return j; + break; + + case MOUSE_EVENT: + /* Save event as a GPM-like event */ + evSaved_Event.x = ir.Event.MouseEvent.dwMousePosition.X; + evSaved_Event.y = ir.Event.MouseEvent.dwMousePosition.Y+1; + evSaved_Event.buttons = ir.Event.MouseEvent.dwButtonState; + switch (ir.Event.MouseEvent.dwEventFlags) { + case 0: + evSaved_Event.type = GPM_DOWN | GPM_SINGLE; + break; + case MOUSE_MOVED: + evSaved_Event.type = GPM_MOVE; + break; + case DOUBLE_CLICK: + evSaved_Event.type = GPM_DOWN | GPM_DOUBLE; + break; + }; + return 0; + } + } while (!no_delay); + return 0; +} + +static int getch_with_delay (void) +{ + int c; + + while (1) { + /* Try to get a character */ + c = get_key_code (0); + if (c != ERR) + break; + } + /* Success -> return the character */ + return c; +} + +/* Returns a character read from stdin with appropriate interpretation */ +int get_event (Gpm_Event *event, int redo_event, int block) +{ + int c; + static int flag; /* Return value from select */ + static int dirty = 3; + + if ((dirty == 1) || is_idle ()){ + refresh (); + doupdate (); + dirty = 1; + } else + dirty++; + + vfs_timeout_handler (); + + c = block ? getch_with_delay () : get_key_code (1); + + if (!c) { + /* Code is 0, so this is a Control key or mouse event */ + return EV_NONE; /* FIXME: mouse not supported */ + } + + return c; +} + +/* Returns a key press, mouse events are discarded */ +int mi_getch () +{ + Gpm_Event ev; + int key; + + while ((key = get_event (&ev, 0, 1)) == 0) + ; + return key; +} + +/* + is_idle - A function to check if we're idle. + It checks for any waiting event (that can be a Key, Mouse event, + and other internal events like focus or menu) +*/ +int is_idle (void) +{ + DWORD dw; + if (GetNumberOfConsoleInputEvents (hConsoleInput, &dw)) + if (dw > 15) + return 0; + return 1; +} + +/* get_modifier */ +int get_modifier() +{ + int retval = 0; + + if (dwSaved_ControlState & LEFT_ALT_PRESSED) /* code is not clean, because we return Linux-like bitcodes*/ + retval |= ALTL_PRESSED; + if (dwSaved_ControlState & RIGHT_ALT_PRESSED) + retval |= ALTR_PRESSED; + + if (dwSaved_ControlState & RIGHT_CTRL_PRESSED || + dwSaved_ControlState & LEFT_CTRL_PRESSED) + retval |= CONTROL_PRESSED; + + if (dwSaved_ControlState & SHIFT_PRESSED) + retval |= SHIFT_PRESSED; + + return retval; +} + +/* void functions for UNIX compatibility */ +void define_sequence (int code, char* vkcode, int action) {} +void channels_up() {} +void channels_down() {} +void init_key_input_fd (void) {} +void numeric_keypad_mode (void) {} +void application_keypad_mode (void) {} + +/* mouse is not yet supported, sorry */ +void init_mouse (void) {} +void shut_mouse (void) {} + +#endif /* _OS_NT */ diff --git a/pc/key_os2.c b/pc/key_os2.c new file mode 100644 index 000000000..f1998711d --- /dev/null +++ b/pc/key_os2.c @@ -0,0 +1,408 @@ +/* Keyboard support routines. + for OS/2 system. + + 20. April 97: Alexander Dong (ado) + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#ifndef __os2__ +#error This file is for OS/2 systems. +#else + +#define INCL_BASE +#define INCL_NOPM +#define INCL_VIO +#define INCL_KBD +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_WININPUT +#include +#include +#include "mouse.h" +#include "global.h" +#include "main.h" +#include "key.h" +#include "../vfs/vfs.h" +#include "tty.h" + +/* Code to read keystrokes in a separate thread */ + +typedef struct kbdcodes { + UCHAR ascii; + UCHAR scan; + USHORT shift; /* .ado: change for mc */ +} KBDCODES; + +/* Global variables */ +int old_esc_mode = 0; +/* HANDLE hConsoleInput; +DWORD dwSaved_ControlState; */ +Gpm_Event evSaved_Event; + +/* Unused variables */ +int double_click_speed; /* they are here to keep linker happy */ +int mou_auto_repeat; +int use_8th_bit_as_meta = 0; + +static int VKtoCurses (int vkcode); + +/* -------------------------------------------------------------- */ +/* DEFINITIONS: + Return from SLANG: KeyCode: 0xaaaabbcc + + where: aaaa = Flags + bb = Scan code + cc = ASCII-code (if available) + + if no flags (CTRL and ALT) is set, cc will be returned. + If CTRL is pressed, cc is already the XCTRL(code). + case cc is: + 0xE0: The scan code will be used for the following keys: + Insert: 0x52, DEL: 0x53, + Page_Up: 0x49, Page_Down: 0x51, + Pos1: 0x47, Ende: 0x4F, + Up: 0x48, Down: 0x50, + Left: 0x4B, Right: 0x4D, + + 0x00: The function keys are defined as: + F1: 3b00, F2: 3c00 ... F10: 4400, F11: 8500, F12: 8600. + With ALT-bit set: + ALT(F1): 6800, 6900,... ALT(F10): 7100, ALT(F11): 8b00 + ALT(F12): 8c00 + + Mapping for ALT(key_code): + For Mapping with normal keys, only the scan code can be + used. (see struct ALT_table) + + Special keys: + ENTER (number block): 0xaaaaE00D + + (number block): 0xaaaa4E2B Normal: 1B2B + - (number block): 0xaaaa4A2D Normal: 352D + * (number block): 0xaaaa372A Normal: 1B2A + / (number block): 0xaaaaE02F +*/ +/* -------------------------------------------------------------- */ +#define RIGHT_SHIFT_PRESSED 1 +#define LEFT_SHIFT_PRESSED 2 +#define CTRL_PRESSED 4 +#define ALT_PRESSED 8 +#define SCROLL_LOCK_MODE 16 +#define NUM_LOCK_MODE 32 +#define CAPS_LOCK_MODE 64 +#define INSERT_MODE 128 +#define LEFT_CTRL_PRESSED 256 +#define LEFT_ALT_PRESSED 512 +#define RIGHT_CTRL_PRESSED 1024 +#define RIGHT_ALT_PRESSED 2048 +#define SCROLL_LOCK_PRESSED 4096 +#define NUM_LOCK_PRESSED 8192 +#define CAPS_LOCK_PRESSED 16384 +#define SYSREQ 32768 +/* -------------------------------------------------------------- */ + +/* Static Tables */ +struct { + int key_code; + int vkcode; +} fkt_table [] = { + { KEY_F(1), 0x3B }, + { KEY_F(2), 0x3C }, + { KEY_F(3), 0x3D }, + { KEY_F(4), 0x3E }, + { KEY_F(5), 0x3F }, + { KEY_F(6), 0x40 }, + { KEY_F(7), 0x41 }, + { KEY_F(8), 0x42 }, + { KEY_F(9), 0x43 }, + { KEY_F(10), 0x44 }, + { KEY_F(11), 0x85 }, + { KEY_F(12), 0x86 }, + { 0, 0} +}; + + +struct { + int key_code; + int vkcode; +} ALT_table [] = { + { ALT('a'), 0x1E }, + { ALT('b'), 0x30 }, + { ALT('c'), 0x2E }, + { ALT('d'), 0x20 }, + { ALT('e'), 0x12 }, + { ALT('f'), 0x21 }, + { ALT('g'), 0x22 }, + { ALT('h'), 0x23 }, + { ALT('i'), 0x17 }, + { ALT('j'), 0x24 }, + { ALT('k'), 0x25 }, + { ALT('l'), 0x26 }, + { ALT('m'), 0x32 }, + { ALT('n'), 0x31 }, + { ALT('o'), 0x18 }, + { ALT('p'), 0x19 }, + { ALT('q'), 0x10 }, + { ALT('r'), 0x13 }, + { ALT('s'), 0x1F }, + { ALT('t'), 0x14 }, + { ALT('u'), 0x16 }, + { ALT('v'), 0x2F }, + { ALT('w'), 0x11 }, + { ALT('x'), 0x2D }, + { ALT('y'), 0x15 }, + { ALT('z'), 0x2C }, + { ALT('\n'), 0x1c }, + { ALT('\n'), 0xA6 }, + { ALT(KEY_F(1)), 0x68 }, + { ALT(KEY_F(2)), 0x69 }, + { ALT(KEY_F(3)), 0x6A }, + { ALT(KEY_F(4)), 0x6B }, + { ALT(KEY_F(5)), 0x6C }, + { ALT(KEY_F(6)), 0x6D }, + { ALT(KEY_F(7)), 0x6E }, + { ALT(KEY_F(8)), 0x6F }, + { ALT(KEY_F(9)), 0x70 }, + { ALT(KEY_F(10)), 0x71 }, + { ALT(KEY_F(11)), 0x8B }, + { ALT(KEY_F(12)), 0x8C }, + { 0, 0} +}; + + +struct { + int key_code; + int vkcode; +} movement [] = { + { KEY_IC, 0x52 }, + { KEY_DC, 0x53 }, + { KEY_PPAGE, 0x49 }, + { KEY_NPAGE, 0x51 }, + { KEY_LEFT, 0x4B }, + { KEY_RIGHT, 0x4D }, + { KEY_UP, 0x48 }, + { KEY_DOWN, 0x50 }, + { KEY_HOME, 0x47 }, + { KEY_END, 0x4F }, + { 0, 0} +}; + + +/* init_key -- to make linker happy */ +void init_key (void) +{ + return; +} + + +/* The maximum sequence length (32 + null terminator) */ +static int seq_buffer[33]; +static int *seq_append = 0; + +static int push_char (int c) +{ + if (!seq_append) + seq_append = seq_buffer; + + if (seq_append == &(seq_buffer [sizeof (seq_buffer)-2])) + return 0; + *(seq_append++) = c; + *seq_append = 0; + return 1; +} + +int get_key_code (int no_delay) +{ + unsigned int inp_ch; + + if (no_delay) { + /* Check if any input pending, otherwise return */ + nodelay (stdscr, TRUE); + inp_ch = SLang_input_pending(0); + if (inp_ch == 0) { + return 0; + } + } + + if (no_delay) { + return (VKtoCurses(inp_ch)); + } + + do { + inp_ch = SLang_getkey(); + if (!inp_ch) + inp_ch = (SLang_getkey() << 8); + if (inp_ch) return (VKtoCurses(inp_ch)); + } while (!no_delay); + return 0; +} + +static int VKtoCurses (int a_vkc) +{ + int ctrlState = 0; + int altState = 0; + + int fsState; + char scanCode; + char asciiCode; + register int i; + int rtnCode = 0; + + fsState = (a_vkc & 0xFFFF0000) >> 16; + fsState &= (~INSERT_MODE); /* Ignore Insertion mode */ + + scanCode = (char) ((a_vkc & 0x0000FFFF) >> 8); + asciiCode = (char) (a_vkc & 0x000000FF); + + ctrlState = (fsState & CTRL_PRESSED); + altState = (fsState & ALT_PRESSED); + + rtnCode = asciiCode; + + if (ctrlState) { + /* CTRL pressed */ + rtnCode = XCTRL(asciiCode); + } + + if (altState) { + /* ALT pressed + * rtnCode = ALT(asciiCode); + * + * With German keyboards, the Values between 7B -> 7D + * and 5b, 5d, 40, fd, fc and e6 are only reachable with the AltGr + * key. If such a combination is used, asciiCode will not be zero. + * With the normal ALT key, the asciiCode will always be zero. + */ + if (asciiCode) { + return asciiCode; + } + } + + /* Scan Movement codes */ + if (asciiCode == 0) { + /* Replace key code with that in table */ + for (i=0; movement[i].vkcode != 0 || movement[i].key_code != 0; i++) + if (scanCode == movement[i].vkcode) + return (movement[i].key_code); + } + + if (asciiCode == 0) { + /* Function-key detected */ + for (i=0; fkt_table[i].vkcode != 0 || fkt_table[i].key_code != 0; i++) + if (scanCode == fkt_table[i].vkcode) + return (fkt_table[i].key_code); + /* ALT - KEY */ + /* if (altState) */ { + for (i=0; ALT_table[i].vkcode != 0 || ALT_table[i].key_code != 0; i++) + if (scanCode == ALT_table[i].vkcode) + return (ALT_table[i].key_code); + } + } + + if (asciiCode == 0x0d) { + return '\n'; + } + + return rtnCode; +} + + +static int getch_with_delay (void) +{ + int c; + + while (1) { + /* Try to get a character */ + c = get_key_code (0); + if (c != ERR) + break; + } + /* Success -> return the character */ + return c; +} + +int get_event (Gpm_Event *event, int redo_event, int block) +{ + int c; + static int dirty = 3; + + if ((dirty == 1) || is_idle ()){ + refresh (); + doupdate (); + dirty = 1; + } else + dirty++; + + vfs_timeout_handler (); + + c = block ? getch_with_delay () : get_key_code (1); + if (!c) { + /* Code is 0, so this is a Control key or mouse event */ + *event = evSaved_Event; + return EV_NONE; /* FIXME: when should we return EV_MOUSE ? */ + } + + return c; +} + +/* Returns a key press, mouse events are discarded */ +int mi_getch () +{ + Gpm_Event ev; + int key; + + while ((key = get_event (&ev, 0, 1)) == 0) + ; + return key; +} + + +/* + is_idle - A function to check if we're idle. + It checks for any waiting event (that can be a Key, Mouse event, + and other internal events like focus or menu) +*/ +int is_idle (void) +{ + return 1; +} + +/* get_modifier */ +int get_modifier() +{ + return 0; +} + +int ctrl_pressed () +{ + return 0; +} + + +/* void functions for UNIX copatibility */ +void define_sequence (int code, char* vkcode, int action) {} +void channels_up() {} +void channels_down() {} +void init_key_input_fd (void) {} +void numeric_keypad_mode (void) {} +void application_keypad_mode (void) {} + +/* mouse is not yet supported, sorry */ +void init_mouse (void) {} +void shut_mouse (void) {} + +#endif /* __os2__ */ diff --git a/pc/mc.def b/pc/mc.def new file mode 100644 index 000000000..1715d59e3 --- /dev/null +++ b/pc/mc.def @@ -0,0 +1,4 @@ +NAME MC WINDOWCOMPAT +DESCRIPTION 'Midnight Commander' +EXETYPE OS2 +PROTMODE diff --git a/pc/mc.rc b/pc/mc.rc new file mode 100644 index 000000000..912bfcb46 --- /dev/null +++ b/pc/mc.rc @@ -0,0 +1,57 @@ + +#include "windows.h" +#include "winver.h" +#include "config.h" + + +/* English (U.S.) resources */ + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) + +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif /* _WIN32 */ + +/* Version */ + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 3,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40000L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "Free Software Foundation" + VALUE "FileDescription", "GNU Midnight Commander" + VALUE "FileVersion", VERSION + VALUE "InternalName", "MC" + VALUE "LegalCopyright", "(c) Free Software Foundation" + VALUE "LegalTrademarks", "see GNU General Public License" + VALUE "OriginalFilename", "MC.EXE" + VALUE "ProductName", "GNU Midnight Commander" + VALUE "ProductVersion", VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +/* Icon */ +0 ICON DISCARDABLE "mc_nt.ico" + +#endif /* English (U.S.) resources */ + diff --git a/pc/mc_nt.ico b/pc/mc_nt.ico new file mode 100644 index 0000000000000000000000000000000000000000..6cae3a94bc4eddf134befb8f10c636760680047a GIT binary patch literal 1078 zcmdT?F%E+;3_K_jof@8ysp1(7Jcuo;N1m1Ebj%OZv(pMuAw(;d8tn7gP87)pRH)&7 z2en5H+=*RRcwYgx3(&LX=>xq&!w3jxw@uh&N2CBFQ^XjF+Q{}JXU*vRw4~u|b3lTH za`P@vD5EyS=dAdF^Bmc||BQZ4IXexn_k79QFoj^Dod4vQ&E%>eoH05td^8&xg@Jve zSLgc@gunl@l$`jgIG$}VxOYov0megIXiJl}>8Chk<%$DN6; LiMtv2%2VwLa_O|^ literal 0 HcmV?d00001 diff --git a/pc/mc_os2.ico b/pc/mc_os2.ico new file mode 100644 index 0000000000000000000000000000000000000000..295bbea4a05b00737a988300a21bedb68f319880 GIT binary patch literal 3344 zcmeHJ!BWC75Pj7;GU!a(8BU%!@)?L+y!i2H@lB)l1(R%BLHvwiJqPx*yeoJ32@K;5Mv~KNZ$LF{VLjrw5GBHjt`tuV{Exx zn&jclosFXCH!<8wUZfDWhaT2xh?^667gzS#O|<6`*D-+b#K_r@R;v{;4Npw}fT$7o zRTD~a9dHL2U|q)@;pGFa?6Y3L9bt3^E>T;!ee~h(LfnDH-OjV@LoR~WLI0u7v!ke4 zijlJ+9hxr(b#%!LWIzRLLex)X?(fFV-M1y5;LjnA{|}A#mG_yNI{p{s+j3r()&&1u z84DxV6LTD6;-ZnKM&nd$OuLEGMyBfTQQRQ0z-?xbq2db{_@d@oX44<$mCsZ~Gwvc* zvP$V>DjmwQ1app}D3BES2B_MTOrS6>o}+18zjVeY>@9t%%+ zS%%_#FRf!y3olDt#Mr01W#tpiRRT#Gd#WyBwG`zln?~Wwpyu4#(*o(@~k; literal 0 HcmV?d00001 diff --git a/pc/slint_pc.c b/pc/slint_pc.c new file mode 100644 index 000000000..abe177a48 --- /dev/null +++ b/pc/slint_pc.c @@ -0,0 +1,220 @@ +/* Slang interface to the Midnight Commander for Windows NT and OS/2 + This emulates some features of ncurses on top of slang + S-lang is not fully consistent between its Unix and non-Unix versions. + + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include "tty.h" +#include "mad.h" +#include "color.h" +#include "util.h" +#include "mouse.h" /* Gpm_Event is required in key.h */ +#include "key.h" /* define_sequence */ +#include "main.h" /* extern: force_colors */ +#include "win.h" /* do_exit_ca_mode */ + +#ifdef HAVE_SLANG + +static void slang_sigterm () +{ + SLsmg_reset_smg (); +} + +static int slinterrupt; + +void enable_interrupt_key(void) +{ + SLang_set_abort_signal(NULL); + slinterrupt = 1; +} +void disable_interrupt_key(void) +{ + slinterrupt = 0; +} +int got_interrupt () +{ + int t; + int SLKeyboard_Quit=0; /* FIXME!! */ + t = slinterrupt ? SLKeyboard_Quit : 0; + /* SLKeyboard_Quit = 0; */ + return t; +} + +/* Only done the first time */ +void slang_init (void) +{ + SLtt_get_terminfo (); + SLang_init_tty (XCTRL('c'), 1, 0); + slang_prog_mode (); + load_terminfo_keys (); +} + +/* Done each time we come back from done mode */ +void slang_prog_mode (void) +{ + SLsmg_init_smg (); + SLsmg_touch_lines (0, LINES); +} + +/* Called each time we want to shutdown slang screen manager */ +void slang_shell_mode (void) +{ + +} + +void slang_shutdown () +{ + slang_shell_mode (); + do_exit_ca_mode (); + SLang_reset_tty (); + + /* reset the colors to those that were + * active when the program was started up + (not written) + */ +} + +/* keypad routines */ +void slang_keypad (int set) +{ + /* enable keypad strings */ +} + +static int no_slang_delay; + +void set_slang_delay (int v) +{ + no_slang_delay = v; +} + +void hline (int ch, int len) +{ + int last_x, last_y; + + last_x = SLsmg_get_column (); + last_y = SLsmg_get_row (); + + if (ch == 0) + ch = ACS_HLINE; + + if (ch == ACS_HLINE){ + SLsmg_draw_hline (len); + } else { + while (len--) + addch (ch); + } + move (last_y, last_x); +} + +void vline (int character, int len) +{ + if (!slow_terminal){ + SLsmg_draw_vline (len); + } else { + int last_x, last_y, pos = 0; + + last_x = SLsmg_get_column (); + last_y = SLsmg_get_row (); + + while (len--){ + move (last_y + pos++, last_x); + addch (' '); + } + move (last_x, last_y); + } +} + +void init_pair (int index, char *foreground, char *background) +{ + SLtt_set_color (index, "", foreground, background); +} + + +int has_colors () +{ + /* No terminals on NT, make default color */ + if (!disable_colors) + SLtt_Use_Ansi_Colors = 1; + + /* Setup emulated colors */ + if (SLtt_Use_Ansi_Colors){ + init_pair (A_REVERSE, "black", "white"); + } else { +/* SLtt_set_mono (A_BOLD, NULL, SLTT_BOLD_MASK); + SLtt_set_mono (A_REVERSE, NULL, SLTT_REV_MASK); + SLtt_set_mono (A_BOLD|A_REVERSE, NULL, SLTT_BOLD_MASK | SLTT_REV_MASK); + */ } + return SLtt_Use_Ansi_Colors; +} + +void attrset (int color) +{ + if (!SLtt_Use_Ansi_Colors){ + SLsmg_set_color (color); + return; + } + + if (color & A_BOLD){ + if (color == A_BOLD) + SLsmg_set_color (A_BOLD); + else + SLsmg_set_color ((color & (~A_BOLD)) + 8); + return; + } + + if (color == A_REVERSE) + SLsmg_set_color (A_REVERSE); + else + SLsmg_set_color (color); +} + +void load_terminfo_keys () +{ +} + +int getch () +{ + if (no_slang_delay) + if (SLang_input_pending (0) == 0) + return -1; + + return SLang_getkey (); +} + +extern int slow_terminal; + +#else + +/* Non slang builds do not understand got_interrupt */ +int got_interrupt () +{ + return 0; +} +#endif /* HAVE_SLANG */ + +void mc_refresh (void) +{ +/* if (!we_are_background) (no background mode yet) */ + refresh (); +} + +void slang_set_raw_mode (void) +{ + return; +} + diff --git a/pc/sys/param.h b/pc/sys/param.h new file mode 100644 index 000000000..5e2a01c23 --- /dev/null +++ b/pc/sys/param.h @@ -0,0 +1,7 @@ +/* Systems having sys/param.h should not include this file */ + +#ifdef HAVE_PARAM_H +#error Remove this file if you have real sys/param.h +#else +/* FIXME: We should warn, that this file should not be included */ +#endif diff --git a/pc/sys/time.h b/pc/sys/time.h new file mode 100644 index 000000000..c410cca95 --- /dev/null +++ b/pc/sys/time.h @@ -0,0 +1,16 @@ + +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +#ifndef _WINSOCKAPI_ /* winsock.h defines struct timeval */ + +struct timeval { + long tv_sec; + long tv_usec; +}; + +#endif + +int gettimeofday (struct timeval*, void *); + +#endif diff --git a/pc/trace_nt.c b/pc/trace_nt.c new file mode 100644 index 000000000..61aea9f56 --- /dev/null +++ b/pc/trace_nt.c @@ -0,0 +1,186 @@ +/* trace_nt.c - Debugging routines + for Midnight Commander, under Win32 + + Written 951215 by Juan Grigera + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#ifdef HAVE_TRACE + +#include +#ifdef _OS_NT +#include +#endif +#include +#include "trace_nt.h" + +/* Global variables */ +int __win32_tracing_enabled = 1; + +static int _win32_tracing_started = 0; +static FILE *__win32_trace_f = NULL; + +/* Definitions */ +#define TRACE_FILE "mcTrace.out" + +/* Prototypes - static funcs */ +static void _win32InitTrace (void); +static void _win32EndTrace (void); +static const char* GetLastErrorText(void); +static char *visbuf(const char *buf); + + +/* + void _win32InitTrace() + This func will open file TRACE_FILE for output and add _win32EndTrace to onexit + list of funcs. + */ +static void _win32InitTrace() +{ + if (!_win32_tracing_started) { + _win32_tracing_started = 1; + + __win32_trace_f = fopen(TRACE_FILE, "wt"); + if (__win32_trace_f == NULL) { + printf("Midnight Commander[DEBUG]: Can't open trace file '" TRACE_FILE "': %s \n", strerror(errno)); + } + atexit (&_win32EndTrace); + } +} + +/* + void _win32EndTrace() + This func closes file TRACE_FILE if opened. + */ +static void _win32EndTrace() +{ + if (_win32_tracing_started) { + _win32_tracing_started = 0; + if (__win32_trace_f) + fclose (__win32_trace_f); + } + +} + +/* + void _win32Trace (char *fmt, ...) + Format and output debug strings. They are written to TRACE_FILE. + Debug Output is controlled by SetTrace (see below). + Win32: Output is sent to Debug Output also. + */ +void _win32Trace (const char *fmt, ...) +{ + va_list ap; + char buffer[256]; + char *vp; + + + if (!_win32_tracing_started) + _win32InitTrace(); + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + vp = buffer; + +#ifdef _OS_NT /* Write Output to Debug monitor also */ + OutputDebugString (vp); + #if (_MSC_VER > 800) /* Don't write newline in MSVC++ 1.0, has a dammed bug in Debug Output screen */ + OutputDebugString ("\n"); + #endif +#endif + + if(__win32_trace_f) + fprintf (__win32_trace_f, "%s\n", vp); +} + +/* + void SetTrace (int trace) + Control debug output. Turn it of or on. + trace: 0 = off, 1 = on. + */ +void _win32SetTrace (int trace) +{ + /* Prototypes - interlan funcs */ + __win32_tracing_enabled = trace; +} +void _win32TraceOn () +{ + __win32_tracing_enabled = 1; +} +void _win32TraceOff() +{ + __win32_tracing_enabled = 0; +} + + +#ifdef _OS_NT +/* + void DebugFailedWin32APICall (const char* name, int line, const char* file) + Report a System call failure. + name - text containing the source code that called the offending API func + line, file - place of "name" in code + + See Also: definition of win32APICALL macro. + */ +void _win32DebugFailedWin32APICall (const char* name, int line, const char* file) +{ + _win32Trace ("%s(%d): Call to Win32 API Failed. \"%s\".", file, line, name); + _win32Trace (" System Error (%d): %s. ", GetLastError(), GetLastErrorText()); +} +#endif + +/* + void DebugAssertionFailed (const char* name, int line, const char* file) + Report a logical condition failure. (e.g. a bad argument to a func) + name - text containing the logical condition + line, file - place of "name" in code + + See Also: definition of ASSERT macro. + */ +void _win32DebugAssertionFailed (const char* name, int line, const char* file) +{ + _win32Trace ("%s(%d): Assertion failed! \"%s\".", file, line, name); +} + + +/* const char* GetLastErrorText() + Retrieves the text associated with the last system error. + + Returns pointer to static buffer. Contents valid till next call +*/ +static const char* GetLastErrorText() +{ +#define MAX_MSG_SIZE 256 + static char szMsgBuf[MAX_MSG_SIZE]; + DWORD dwError, dwRes; + + dwError = GetLastError (); + + dwRes = FormatMessage ( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError, + MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), + szMsgBuf, + MAX_MSG_SIZE, + NULL); + if (0 == dwRes) { + sprintf (szMsgBuf, "FormatMessage failed with %d", GetLastError()); + } + return szMsgBuf; +} + +#endif /*HAVE_TRACE*/ diff --git a/pc/trace_nt.h b/pc/trace_nt.h new file mode 100644 index 000000000..1eda3963f --- /dev/null +++ b/pc/trace_nt.h @@ -0,0 +1,72 @@ +/* trace_nt.h - Debugging routines + + Written by Juan Grigera + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ------------------------------------------------------------------------------------------ * + TRACER FUNCTIONS + * ------------------------------------------------------------------------------------------ */ + +#ifdef HAVE_TRACE +/************************/ +/* Debug version */ +/************************/ + +/* Macros + ------ + win32Trace(x) - Trace macro. Use double in parenthesis for x. Same args as printf. + win32ASSERT(x) - assert macro, but will not abort program and output sent to trace routine. + win32APICALL(x) - Use to enclose a Win32 system call that should return TRUE. + win32APICALL_HANDLE(h,api) - Use to enclose a Win32 system call that should return a handle. +*/ +#define win32Trace(x) if (__win32_tracing_enabled) _win32Trace x +#define win32ASSERT(x) if (!(x)) _win32DebugAssertionFailed (#x, __LINE__, __FILE__) +#define win32APICALL(x) if (!(x)) _win32DebugFailedWin32APICall (#x, __LINE__, __FILE__) +#define win32APICALL_HANDLE(h,api) h=api; if (h==INVALID_HANDLE_VALUE) _win32DebugFailedWin32APICall (#h" = "#api, __LINE__, __FILE__) + +/* Prototypes */ +void _win32Trace (const char *, ...); +void _win32DebugFailedWin32APICall (const char *name, int line, const char *file); +void _win32DebugAssertionFailed (const char *name, int line, const char *file); + +void _win32SetTrace (int trace); +void _win32TraceOn (void); +void _win32TraceOff (void); + +#define SetTrace _win32SetTrace +#define TraceOn _win32TraceOn +#define TraceOff _win32TraceOff + +/* Global variables */ +extern int __win32_tracing_enabled; + +#else +/************************/ +/* Non-debug version */ +/************************/ + +/* Wipe-out these macros */ +#define win32Trace(x) +#define win32ASSERT(x) +#define win32APICALL(x) x +#define win32APICALL_HANDLE(h,api) h=api; + +/* Wipe-out these funcs */ +#define SetTrace(x) +#define TraceOn() +#define TraceOff() +#endif diff --git a/pc/util_nt.c b/pc/util_nt.c new file mode 100644 index 000000000..84d85256c --- /dev/null +++ b/pc/util_nt.c @@ -0,0 +1,664 @@ +/* Various utilities - NT versions + Copyright (C) 1994, 1995, 1996 the Free Software Foundation. + + Written 1994, 1995, 1996 by: + Juan Grigera, Miguel de Icaza, Janne Kukonlehto, Dugan Porter, + Jakub Jelinek, Mauricio Plaza. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include /* my_system */ +#include /* INT_MAX */ +#include +#include /* select: timeout */ +#include +#include +#include +#include +#include +#include "util.h" +#include "util_win32.h" + +#ifdef __BORLANDC__ +#define ENOTEMPTY ERROR_DIR_NOT_EMPTY +#endif + +char *get_owner (int uid) +{ + return "none"; +} + +char *get_group (int gid) +{ + return "none"; +} + +/* Pipes are guaranteed to be able to hold at least 4096 bytes */ +/* More than that would be unportable */ +#define MAX_PIPE_SIZE 4096 + +static int error_pipe[2]; /* File descriptors of error pipe */ +static int old_error; /* File descriptor of old standard error */ + +/* Creates a pipe to hold standard error for a later analysis. */ +/* The pipe can hold 4096 bytes. Make sure no more is written */ +/* or a deadlock might occur. */ +void open_error_pipe (void) +{ + if (pipe (error_pipe) < 0){ + message (0, " Warning ", " Pipe failed "); + } + old_error = dup (2); + if(old_error < 0 || close(2) || dup (error_pipe[1]) != 2){ + message (0, " Warning ", " Dup failed "); + close (error_pipe[0]); + close (error_pipe[1]); + } + close (error_pipe[1]); +} + +void close_error_pipe (int error, char *text) +{ + char *title; + char msg[MAX_PIPE_SIZE]; + int len = 0; + + if (error) + title = " Error "; + else + title = " Warning "; + if (old_error >= 0){ + close (2); + dup (old_error); + close (old_error); + len = read (error_pipe[0], msg, MAX_PIPE_SIZE); + + if (len >= 0) + msg[len] = 0; + close (error_pipe[0]); + } + if (error < 0) + return; /* Just ignore error message */ + if (text == NULL){ + if (len == 0) return; /* Nothing to show */ + + /* Show message from pipe */ + message (error, title, msg); + } else { + /* Show given text and possible message from pipe */ + message (error, title, " %s \n %s ", text, msg); + } +} + +void check_error_pipe (void) +{ + char error[MAX_PIPE_SIZE]; + int len = 0; + if (old_error >= 0){ + while (len < MAX_PIPE_SIZE) + { + int rvalue; + + rvalue = read (error_pipe[0], error + len, 1); + len ++; + if (rvalue <= 0) + break; + } + error[len] = 0; + close (error_pipe[0]); + } + if (len > 0) + message (0, " Warning ", error); +} + +int my_system (int as_shell_command, const char *shell, const char *command) +{ + int status = 0; + +#if 0 +/* .ado: temp. turn out */ + if (as_shell_command) { + /* It is only the shell, /c will not work */ + if (command) + spawnlp (P_WAIT, shell, shell, "/c", command, (char *) 0); + else + spawnlp (P_WAIT, shell, (char *) 0); + } else + spawnl (P_WAIT, shell, shell, command, (char *) 0); + + if (win32_GetPlatform() == OS_Win95) { + SetConsoleTitle ("GNU Midnight Commander"); /* title is gone after spawn... */ + } +#endif + if (as_shell_command) { + if (!access(command, 0)) { + switch(win32_GetEXEType (shell)) { + case EXE_win16: /* Windows 3.x archive or OS/2 */ + case EXE_win32GUI: /* NT or Chicago GUI API */ + spawnlp (P_NOWAIT, shell, shell, "/c", command, (char *) 0); /* don't wait for GUI programs to end */ + break; + case EXE_otherCUI: /* DOS COM, MZ, ZM, Phar Lap */ + case EXE_win32CUI: /* NT or Chicago Console API, also OS/2 */ + case EXE_Unknown: + default: + spawnlp (P_WAIT, shell, shell, "/c", command, (char *) 0); + break; + } + } + else + spawnlp (P_WAIT, shell, shell, "/c", command, (char *) 0); + } + else + spawnl (P_WAIT, shell, shell, command, (char *) 0); + + if (win32_GetPlatform() == OS_Win95) { + SetConsoleTitle ("GNU Midnight Commander"); /* title is gone after spawn... */ + } + + return status; +} + +/* get_default_shell + Get the default shell for the current hardware platform +*/ +char* get_default_shell() +{ + if (win32_GetPlatform() == OS_WinNT) + return "cmd.exe"; + else + return "command.com"; +} + +char *tilde_expand (char *directory) +{ + return strdup (directory); +} + +/* sleep: Call Windows API. + Can't do simple define. That would need in every source +*/ +void sleep(unsigned long dwMiliSecs) +{ + Sleep(dwMiliSecs); +} + +/* Canonicalize path, and return a new path. Do everything in situ. + The new path differs from path in: + Multiple `/'s are collapsed to a single `/'. + Leading `./'s and trailing `/.'s are removed. + Trailing `/'s are removed. + Non-leading `../'s and trailing `..'s are handled by removing + portions of the path. */ +char *canonicalize_pathname (char *path) +{ + int i, start; + char stub_char; + + stub_char = (*path == PATH_SEP) ? PATH_SEP : '.'; + + /* Walk along path looking for things to compact. */ + i = 0; + for (;;) { + if (!path[i]) + break; + + while (path[i] && path[i] != PATH_SEP) + i++; + + start = i++; + + /* If we didn't find any slashes, then there is nothing left to do. */ + if (!path[start]) + break; + + /* Handle multiple `/'s in a row. */ + while (path[i] == PATH_SEP) + i++; + + if ((start + 1) != i) { + strcpy (path + start + 1, path + i); + i = start + 1; + } + + /* Handle backquoted `/'. */ + if (start > 0 && path[start - 1] == '\\') + continue; + + /* Check for trailing `/'. */ + if (start && !path[i]) { + zero_last: + path[--i] = '\0'; + break; + } + + /* Check for `../', `./' or trailing `.' by itself. */ + if (path[i] == '.') { + /* Handle trailing `.' by itself. */ + if (!path[i + 1]) + goto zero_last; + + /* Handle `./'. */ + if (path[i + 1] == PATH_SEP) { + strcpy (path + i, path + i + 1); + i = start; + continue; + } + + /* Handle `../' or trailing `..' by itself. + Remove the previous ?/ part with the exception of + ../, which we should leave intact. */ + if (path[i + 1] == '.' && (path[i + 2] == PATH_SEP || !path[i + 2])) { + while (--start > -1 && path[start] != PATH_SEP); + if (!strncmp (path + start + 1, "../", 3)) + continue; + strcpy (path + start + 1, path + i + 2); + i = start; + continue; + } + } + } + + if (!*path) { + *path = stub_char; + path[1] = '\0'; + } + return path; +} + +#ifndef USE_VFS +/* + int mc_rmdir (char *path); + Fix for Win95 UGLY BUG in rmdir: it will return ENOACCESS instead + of ENOTEMPTY. + */ +int mc_rmdir (char *path) +{ + if (win32_GetPlatform() == OS_Win95) { + if (rmdir(path)) { + SetLastError (ERROR_DIR_NOT_EMPTY); + _doserrno = ERROR_DIR_NOT_EMPTY; /* FIXME: We are always saying the same thing! */ + errno = ENOTEMPTY; + return -1; + } else + return 0; + } + else + return rmdir(path); /* No trouble in Windows NT */ +} + +static int conv_nt_unx_rc(int rc) +{ + int errCode; + switch (rc) { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_TOO_MANY_OPEN_FILES: + errCode = ENOENT; + break; + case ERROR_INVALID_HANDLE: + case ERROR_ARENA_TRASHED: + case ERROR_ACCESS_DENIED: + case ERROR_INVALID_ACCESS: + case ERROR_WRITE_PROTECT: + case ERROR_WRITE_FAULT: + case ERROR_READ_FAULT: + case ERROR_SHARING_VIOLATION: + errCode = EACCES; + break; + case ERROR_NOT_ENOUGH_MEMORY: + errCode = ENOMEM; + break; + case ERROR_INVALID_BLOCK: + case ERROR_INVALID_FUNCTION: + case ERROR_INVALID_DRIVE: + errCode = ENODEV; + break; + case ERROR_CURRENT_DIRECTORY: + errCode = ENOTDIR; + break; + case ERROR_NOT_READY: + errCode = EINVAL; + break; + default: + errCode = EINVAL; + break; + } /* endswitch */ + return errCode; +} + +/* + int mc_unlink (char *pathName) + For Windows 95 and NT, files should be able to be deleted even + if they don't have write-protection. We should build a question box + like: Delete anyway? Yes All +*/ +int mc_unlink (char *pathName) +{ + char *fileName; + char *trunced_name; + static int erase_all = 0; + BOOL rc; + DWORD returnError; + + rc = DeleteFile(pathName); + returnError = GetLastError(); + if ((rc == FALSE) && (returnError == ERROR_ACCESS_DENIED)) { + int result; + if (!erase_all) { + errno = conv_nt_unx_rc(returnError); + trunced_name = name_trunc(pathName, 30); + fileName = (char *) malloc(strlen(trunced_name) + 16); + strcpy(fileName, "File "); + strcat(fileName, trunced_name); + strcat(fileName, " protected"); + result = query_dialog(fileName, "Delete anyway?", 3, 3, " No ", " Yes ", " All in the future!"); + free(fileName); + + switch (result) { + case 0: + do_refresh (); + return -1; + case 1: + do_refresh (); + break; + case 2: + do_refresh (); + erase_all = 1; + break; + default: + do_refresh (); + return -1; + break; + } + } + + chmod(pathName, S_IWRITE); /* make it writable */ + rc = DeleteFile(pathName); + returnError = GetLastError(); + if (rc == FALSE) { + errno = conv_nt_unx_rc(returnError); + return -1; + } + } + if (rc == TRUE) return 0; + else + return -1; +} +#endif /*USE_VFS*/ + +void my_statfs (struct my_statfs *myfs_stats, char *path) +{ + int len = 0; + DWORD lpSectorsPerCluster, lpBytesPerSector, lpFreeClusters, lpClusters; + DWORD lpMaximumComponentLength, lpFileSystemFlags; + static char lpVolumeNameBuffer[256], lpFileSystemNameBuffer[30]; + + GetDiskFreeSpace(NULL, &lpSectorsPerCluster, &lpBytesPerSector, + &lpFreeClusters, &lpClusters); + + /* KBytes available */ + myfs_stats->avail = lpSectorsPerCluster * lpBytesPerSector * lpFreeClusters / 1024; + + /* KBytes total */ + myfs_stats->total = lpSectorsPerCluster * lpBytesPerSector * lpClusters / 1024; + myfs_stats->nfree = lpFreeClusters; + myfs_stats->nodes = lpClusters; + + GetVolumeInformation(NULL, lpVolumeNameBuffer, 255, NULL, + &lpMaximumComponentLength, &lpFileSystemFlags, + lpFileSystemNameBuffer, 30); + + myfs_stats->mpoint = lpFileSystemNameBuffer; + myfs_stats->device = lpVolumeNameBuffer; + + + myfs_stats->type = GetDriveType(NULL); + switch (myfs_stats->type) { + /* + * mmm. DeviceIoControl may fail if you are not root case + * F5_1Pt2_512, 5.25", 1.2MB, 512 bytes/sector + * myfs_stats->typename = "5.25\" 1.2MB"; break; case + * F3_1Pt44_512, 3.5", 1.44MB, 512 bytes/sector + * myfs_stats->typename = "3.5\" 1.44MB"; break; case + * F3_2Pt88_512, 3.5", 2.88MB, 512 bytes/sector + * myfs_stats->typename = "3.5\" 2.88MB"; break; case + * F3_20Pt8_512, 3.5", 20.8MB, 512 bytes/sector + * myfs_stats->typename = "3.5\" 20.8MB"; break; case + * F3_720_512, 3.5", 720KB, 512 bytes/sector + * myfs_stats->typename = "3.5\" 720MB"; break; case + * F5_360_512, 5.25", 360KB, 512 bytes/sector + * myfs_stats->typename = "5.25\" 360KB"; break; case + * F5_320_512, 5.25", 320KB, 512 bytes/sector + * case F5_320_1024, 5.25", 320KB, 1024 + * bytes/sector myfs_stats->typename = "5.25\" 320KB"; break; + * case F5_180_512, 5.25", 180KB, 512 + * bytes/sector myfs_stats->typename = "5.25\" 180KB"; break; + * case F5_160_512, 5.25", 160KB, 512 + * bytes/sector myfs_stats->typename = "5.25\" 160KB"; break; + * case RemovableMedia, Removable media other than + * floppy myfs_stats->typename = "Removable"; break; case + * FixedMedia Fixed hard disk media + * myfs_stats->typename = "Hard Disk"; break; case Unknown: + * Format is unknown + */ + case DRIVE_REMOVABLE: + myfs_stats->typename = "Removable"; + break; + case DRIVE_FIXED: + myfs_stats->typename = "Hard Disk"; + break; + case DRIVE_REMOTE: + myfs_stats->typename = "Networked"; + break; + case DRIVE_CDROM: + myfs_stats->typename = "CD-ROM"; + break; + case DRIVE_RAMDISK: + myfs_stats->typename = "RAM disk"; + break; + default: + myfs_stats->typename = "unknown"; + break; + }; +} + +int gettimeofday (struct timeval* tvp, void *p) +{ + if (p != NULL) + return 0; + + /* Since MC only calls this func from get_random_hint we return + some value, not exactly the "correct" one */ + tvp->tv_sec = GetTickCount()/1000; /* Number of milliseconds since Windows started*/ + tvp->tv_usec = GetTickCount(); +} + +/* FAKE functions */ + +int +look_for_exe(const char* pathname) +{ + int j; + char *p; + int lgh = strlen(pathname); + + if (lgh < 4) { + return 0; + } else { + p = (char *) pathname; + for (j=0; jst_mode & S_IFDIR)) { + if (!look_for_exe(pathname)) { + buffer->st_mode &= !S_IXUSR & !S_IXGRP & !S_IXOTH; + } + } + } +#endif + return rc; +} + +int getuid () +{ +/* SID sid; + LookupAccountName (NULL, &sid... + return 0; +*/ + return 0; +} + +int getgid () +{ + return 0; +} + +int readlink (char* path, char* buf, int size) +{ + return -1; +} +int symlink (char *n1, char *n2) +{ + return -1; +} +int link (char *p1, char *p2) +{ + return -1; +} +int chown (char *path, int owner, int group) +{ + return -1; +} +int mknod (char *path, int mode, int dev) +{ + return -1; +} + +void init_uid_gid_cache (void) +{ + return; +} + +int mc_doublepopen (int inhandle, int inlen, pid_t *the_pid, char *command, ...) +{ + return 0; +} + +int mc_doublepclose (int pipe, pid_t pid) +{ +/* win32Trace(("mc_doublepclose called")); */ + return 0; +} + +/*hacks to get it compile, remove these after vfs works */ +#ifndef USE_VFS +char *vfs_get_current_dir (void) +{ + return NULL; +} + +int vfs_current_is_extfs (void) +{ + return 0; +} + +int vfs_file_is_ftp (char *filename) +{ + return 0; +} + +int mc_utime (char *path, struct utimbuf *times) +{ + return 0; +} + + +void extfs_run (char *file) +{ + return; +} +#endif + +char * +get_default_editor (void) +{ + return "notepad.exe"; +} + +int +errno_dir_not_empty (int err) +{ + if (err == ENOTEMPTY || err == EEXIST || err == EACCES) + return 1; + return 0; +} + +/* The MC library directory is by default the directory where mc.exe + is situated. It is possible to specify this directory via MCHOME + environment variable */ +char * +get_mc_lib_dir () +{ + char *cur; + char *mchome = getenv("MCHOME"); + + if (mchome && *mchome) + return mchome; + mchome = malloc(MC_MAXPATHLEN); + GetModuleFileName(NULL, mchome, MC_MAXPATHLEN); + for (cur = mchome + strlen(mchome); \ + (cur > mchome) && (*cur != PATH_SEP); cur--); + *cur = 0; + cur = strdup(mchome); + free(mchome); + if (!cur || !*cur) { + free(cur); + return "C:\\MC"; + } + return cur; +} +int get_user_rights (struct stat *buf) +{ + return 2; +} +void init_groups (void) +{ +} +void delete_groups (void) +{ +} diff --git a/pc/util_os2.c b/pc/util_os2.c new file mode 100644 index 000000000..0082e3987 --- /dev/null +++ b/pc/util_os2.c @@ -0,0 +1,854 @@ +/* Various utilities - OS/2 versions + Copyright (C) 1994, 1995, 1996 the Free Software Foundation. + + Written 1994, 1995, 1996 by: + Juan Grigera, Miguel de Icaza, Janne Kukonlehto, Dugan Porter, + Jakub Jelinek, Mauricio Plaza. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#define INCL_DOS +#define INCL_PM +#define INCL_DOSPROCESS +#define INCL_DOSFILEMGR +#define INCL_DOSDEVICES /* Device values */ +#define INCL_DOSDATETIME +#define INCL_DOSERRORS +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* my_system */ +#include /* INT_MAX */ +#include /* select: timeout */ +#include +#include +#include +#include +#include +#include "util.h" +#include "dialog.h" + +#ifndef ENOTEMPTY +#define ENOTEMPTY ERROR_DIR_NOT_EMPTY +#endif + +char * +get_owner (int uid) +{ + return "none"; +} + +char * +get_group (int gid) +{ + return "none"; +} + +/* Pipes are guaranteed to be able to hold at least 4096 bytes */ +/* More than that would be unportable */ +#define MAX_PIPE_SIZE 4096 + +static int error_pipe[2]; /* File descriptors of error pipe */ +static int old_error; /* File descriptor of old standard error */ + +/* Creates a pipe to hold standard error for a later analysis. */ +/* The pipe can hold 4096 bytes. Make sure no more is written */ +/* or a deadlock might occur. */ +void +open_error_pipe (void) +{ + return; +} + +void +close_error_pipe (int error, char *text) +{ + return; +} + +void +check_error_pipe (void) +{ + char error[MAX_PIPE_SIZE]; + int len = 0; + if (old_error >= 0){ + while (len < MAX_PIPE_SIZE) + { + int rvalue; + + rvalue = read (error_pipe[0], error + len, 1); + len ++; + if (rvalue <= 0) + break; + } + error[len] = 0; + close (error_pipe[0]); + } + if (len > 0) + message (0, " Warning ", error); +} + + +static int +StartWindowsProg (char *name, SHORT type) +{ +#if 0 /* FIXME: PM DDL's should be loaded (or not loaded) at run time */ + PROGDETAILS pDetails; + + memset(&pDetails, 0, sizeof(PROGDETAILS)) ; + pDetails.Length = sizeof(pDetails); + pDetails.pszExecutable = name; /* program name */ + pDetails.pszStartupDir = NULL; /* default directory for new app. */ + pDetails.pszParameters = NULL; /* command line */ + pDetails.progt.fbVisible = SHE_VISIBLE ; + pDetails.pszEnvironment = NULL; + + switch (type) { + case 0: + /* Win Standard */ + pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ; + break; + case 1: + /* Win 3.1 Protect */ + pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ; + break; + case 2: + /* Win 3.1 Enh. Protect */ + pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ; + break; + default: + pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ; + break; + } + WinStartApp(NULLHANDLE, + &pDetails, + NULL, + NULL, + SAF_INSTALLEDCMDLINE|SAF_STARTCHILDAPP) ; +#endif + return 0; +} + + +static int +os2_system (int as_shell_command, const char *shell, const char *command, char *parm); + +/* + as_shell_command = 1: If a program is started during input line, CTRL-O + or RETURN + = 0: F3, F4 +*/ +int +my_system (int as_shell_command, const char *shell, const char *command) +{ + char *sh; /* This is the shell -- always! */ + char *cmd; /* This is the command (only the command) */ + char *parm; /* This is the parameter (can be more than one) */ + register int length, i; + char temp[4096]; /* That's enough! */ + + sh = get_default_shell(); + if (strcmp(sh, shell)) { + /* + Not equal -- That means: shell is the program and command is the + parameter + */ + cmd = (char *) shell; + parm = (char *) command; + } else { + /* look into the command and take out the program */ + if (command) { + strcpy(temp, command); + length = strlen(command); + for (i=length-1; i>=0; i--) { + if (command[i] == ' ') { + temp[i] = (char) 0; + length--; + } else + break; + } + if (i==-1) { + /* only blanks */ + return -1; + } + if (parm = strchr(temp, (char) ' ')) { + *parm = (char) 0; + parm++; + } + cmd = (char *) temp; + } else { + /* command is NULL */ + cmd = parm = NULL; + } + } + return os2_system (as_shell_command, sh, cmd, parm); +} + +static int +ux_startp (const char *shell, const char *command, const char *parm) +{ + if (parm) { + spawnlp (P_WAIT, + (char *) shell, + (char *) shell, + "/c", + (char *) command, + (char *) parm, + (char *) 0); + } else { + spawnlp (P_WAIT, + (char *) shell, + (char *) shell, + "/c", + (char *) command, + (char *) 0); + } + return 0; +} + + +static int +os2_system (int as_shell_command, const char *shell, const char *command, char *parm) +{ + register int i, j; + ULONG AppType = 0; /* Application type flags (returned) */ + APIRET rc = NO_ERROR; /* Return Code */ + char pathValue[5] = "PATH"; /* For DosSearchPath */ + UCHAR searchResult[MC_MAXPATHLEN * 2 + 1]; /* For DosSearchPath */ + + char *cmdString; + char *postFix[3]; + char *line; + /* ------------------------------------------------------- */ + STARTDATA StartData; + CHAR ObjBuf[100]; + ULONG SessionID; + PID pid; + + if (command == NULL) { + /* .ado: just start a shell, we don't need the parameter */ + spawnl (P_WAIT, + (char *) shell, + (char *) shell, + (char *) command, (char *) 0); + return 0; + } + + memset(&StartData, 0, sizeof(StartData)) ; + StartData.Length = sizeof(StartData); + StartData.Related = SSF_RELATED_CHILD; + StartData.FgBg = SSF_FGBG_BACK; + StartData.TraceOpt = SSF_TRACEOPT_NONE; + StartData.PgmTitle = NULL; + StartData.TermQ = NULL; + StartData.InheritOpt = SSF_INHERTOPT_PARENT; + StartData.IconFile = 0; + StartData.PgmHandle = 0; + StartData.PgmControl = SSF_CONTROL_VISIBLE ; + StartData.ObjectBuffer = ObjBuf; + StartData.ObjectBuffLen = 100; + StartData.PgmInputs = parm; + + postFix[0] = ".exe"; + postFix[1] = ".cmd"; + postFix[2] = ".bat"; + + i = strlen(command); + if (command[i-1] == ' ') { + /* The user has used ALT-RETURN */ + i--; + } + cmdString = (char *) malloc(i+1); + for (j=0; j 4) && (cmdString[i-4]) != '.')) { + /* without Extension */ + line = (char *) malloc(i+5); + rc = 1; + for (i=0; (i<3 && rc); i++) { + /* Search for the file */ + strcpy(line, cmdString); + strcat(line, postFix[i]); + rc = DosSearchPath((SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY), + (PSZ) pathValue, + line, + searchResult, + sizeof(searchResult)); + } + free (line); + } else { + /* Just search */ + rc = DosSearchPath((SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY), + (PSZ) pathValue, + cmdString, + searchResult, + sizeof(searchResult)); + } + free(cmdString); + if (rc != 0) { + /* Internal command or the program was written with absolut path */ + return ux_startp(shell, command, parm); + } + + /* Application to be started */ + StartData.PgmName = searchResult; + StartData.Environment = NULL; + rc = DosQueryAppType(searchResult, &AppType); + if (rc == NO_ERROR) { + StartData.SessionType = PROG_WINDOWABLEVIO; + if ((AppType & 0x00000007) == FAPPTYP_WINDOWAPI) { + /* Window API */ + StartData.SessionType = PROG_PM; + return DosStartSession(&StartData, &SessionID, &pid); + } + if ((AppType & 0x00000007) == FAPPTYP_WINDOWCOMPAT) { + /* Window compat */ + return ux_startp(shell, command, parm); + } + if (AppType & 0x0000ffff & FAPPTYP_DOS) { + /* PC/DOS Format */ + StartData.SessionType = PROG_WINDOWEDVDM; + return DosStartSession(&StartData, &SessionID, &pid); + } + if (AppType & 0x0000ffff & FAPPTYP_WINDOWSREAL) { + /* Windows real mode app */ + return StartWindowsProg(searchResult, 0); + } + if (AppType & 0x0000ffff & FAPPTYP_WINDOWSPROT) { + /* Windows Protect mode app*/ + return StartWindowsProg(searchResult, 1); + } + if (AppType & 0x0000ffff & FAPPTYP_WINDOWSPROT31) { + /* Windows 3.1 Protect mode app*/ + return StartWindowsProg(searchResult, 2); + } + rc = DosStartSession(&StartData, &SessionID, &pid) ; + } else { + /* It's not a known exe type or it's a CMD/BAT file */ + i = strlen(searchResult); + if ((toupper(searchResult[--i]) == 'T') && + (toupper(searchResult[--i]) == 'A') && + (toupper(searchResult[--i]) == 'B') && + (searchResult[--i] == '.') ) { + StartData.SessionType = PROG_WINDOWEDVDM; + rc = DosStartSession(&StartData, &SessionID, &pid) ; + } else { + rc = ux_startp (shell, command, parm); + } + } + return rc; +} + +char *tilde_expand (char *directory) +{ + return strdup (directory); +} + + +/* Canonicalize path, and return a new path. Do everything in situ. + The new path differs from path in: + Multiple BACKSLASHs are collapsed to a single BACKSLASH. + Leading `./'s and trailing `/.'s are removed. + Trailing BACKSLASHs are removed. + Non-leading `../'s and trailing `..'s are handled by removing + portions of the path. */ +char * +canonicalize_pathname (char *path) +{ + int i, start; + char stub_char; + + stub_char = (*path == PATH_SEP) ? PATH_SEP : '.'; + + /* Walk along path looking for things to compact. */ + i = 0; + for (;;) { + if (!path[i]) + break; + + while (path[i] && path[i] != PATH_SEP) + i++; + + start = i++; + + /* If we didn't find any slashes, then there is nothing left to do. */ + if (!path[start]) + break; + + /* Handle multiple BACKSLASHs in a row. */ + while (path[i] == PATH_SEP) + i++; + + if ((start + 1) != i) { + strcpy (path + start + 1, path + i); + i = start + 1; + } + + /* Handle backquoted BACKSLASH. */ +/* if (start > 0 && path[start - 1] == '\\') + continue; */ + + /* Check for trailing BACKSLASH. */ + if (start && !path[i]) { + zero_last: + path[--i] = '\0'; + break; + } + + /* Check for `../', `./' or trailing `.' by itself. */ + if (path[i] == '.') { + /* Handle trailing `.' by itself. */ + if (!path[i + 1]) + goto zero_last; + + /* Handle `./'. */ + if (path[i + 1] == PATH_SEP) { + strcpy (path + i, path + i + 1); + i = start; + continue; + } + + /* Handle `../' or trailing `..' by itself. + Remove the previous ?/ part with the exception of + ../, which we should leave intact. */ + if (path[i + 1] == '.' && (path[i + 2] == PATH_SEP || !path[i + 2])) { + while (--start > -1 && path[start] != PATH_SEP); + if (!strncmp (path + start + 1, "..\\", 3)) + continue; + strcpy (path + start + 1, path + i + 2); + i = start; + continue; + } + } + } + + if (!*path) { + *path = stub_char; + path[1] = '\0'; + } + return path; +} + + +void +my_statfs (struct my_statfs *myfs_stats, char *path) +{ + PFSALLOCATE pBuf; + PFSINFO pFsInfo; + ULONG lghBuf; + + ULONG diskNum = 0; + ULONG logical = 0; + + UCHAR szDeviceName[3] = "A:"; + PBYTE pszFSDName = NULL; /* pointer to FS name */ + APIRET rc = NO_ERROR; /* Return code */ + BYTE fsqBuffer[sizeof(FSQBUFFER2) + (3 * CCHMAXPATH)] = {0}; + ULONG cbBuffer = sizeof(fsqBuffer); /* Buffer length) */ + PFSQBUFFER2 pfsqBuffer = (PFSQBUFFER2) fsqBuffer; + + int i, len = 0; + + /* ------------------------------------------------------------------ */ + + lghBuf = sizeof(FSALLOCATE); + pBuf = (PFSALLOCATE) malloc(lghBuf); + + /* Get the free number of Bytes */ + rc = DosQueryFSInfo(0L, FSIL_ALLOC, (PVOID) pBuf, lghBuf); + /* KBytes available */ + myfs_stats->avail = pBuf->cSectorUnit * pBuf->cUnitAvail * pBuf->cbSector / 1024; + /* KBytes total */ + myfs_stats->total = pBuf->cSectorUnit * pBuf->cUnit * pBuf->cbSector / 1024; + myfs_stats->nfree = pBuf->cUnitAvail; + myfs_stats->nodes = pBuf->cbSector; + + lghBuf = sizeof(FSINFO); + pFsInfo = (PFSINFO) malloc(lghBuf); + rc = DosQueryFSInfo(0L, + FSIL_VOLSER, + (PVOID) pFsInfo, + lghBuf); + /* Get name */ + myfs_stats->device = strdup(pFsInfo->vol.szVolLabel); /* Label of the Disk */ + + /* Get the current disk for DosQueryFSAttach */ + rc = DosQueryCurrentDisk(&diskNum, &logical); + + szDeviceName[0] = (UCHAR) (diskNum + (ULONG) 'A' - 1); + /* Now get the type of the disk */ + rc = DosQueryFSAttach(szDeviceName, + 0L, + FSAIL_QUERYNAME, + pfsqBuffer, + &cbBuffer); + + pszFSDName = pfsqBuffer->szName + pfsqBuffer->cbName + 1; + myfs_stats->mpoint = strdup(pszFSDName); /* FAT, HPFS ... */ + + myfs_stats->type = pBuf->idFileSystem; + /* What is about 3 ?*/ + if (myfs_stats->type == 0) { + myfs_stats->typename = (char *) malloc(11); + strcpy(myfs_stats->typename, "Local Disk"); + } else { + myfs_stats->typename = (char *) malloc(13); + strcpy(myfs_stats->typename, "Other Device"); + } + + free(pBuf); + free(pFsInfo); +} + +int +gettimeofday (struct timeval* tvp, void *p) +{ + DATETIME pdt = {0}; + if (p != NULL) /* what is "p"? */ + return 0; + + /* Since MC only calls this func from get_random_hint we return + * some value, not exactly the "correct" one + */ + DosGetDateTime(&pdt); + tvp->tv_usec = (pdt.hours * 60 + pdt.minutes) * 60 + pdt.seconds; + /* Number of milliseconds since Windows started */ + tvp->tv_sec = tvp->tv_usec * 1000 + pdt.hundredths * 10; + return 0; +} + +/* FAKE functions */ + +int +look_for_exe(const char* pathname) +{ + int j; + char *p; + int lgh = strlen(pathname); + + if (lgh < 4) { + return 0; + } else { + p = (char *) pathname; + for (j=0; jst_mode & S_IFDIR)) { + if (!look_for_exe(pathname)) { + buffer->st_mode &= !S_IXUSR & !S_IXGRP & !S_IXOTH; + } + } + } +#endif + return rc; +} + +int +getuid () +{ + return 0; +} + +int +getgid () +{ + return 0; +} + +int +readlink (char* path, char* buf, int size) +{ + return -1; +} + +int +symlink (char *n1, char *n2) +{ + return -1; +} + +int +link (char *p1, char *p2) +{ + return -1; +} + +int +chown (char *path, int owner, int group) +{ + return -1; +} + +int +mknod (char *path, int mode, int dev) +{ + return -1; +} + +void +init_uid_gid_cache (void) +{ + return; +} + +int +mc_doublepopen (int inhandle, int inlen, pid_t *the_pid, char *command, ...) +{ + return 0; +} + +int +mc_doublepclose (int pipe, pid_t pid) +{ + return 0; +} + +/*hacks to get it compile, remove these after vfs works */ +char * +vfs_get_current_dir (void) +{ + return NULL; +} + +int +vfs_current_is_extfs (void) +{ + return 0; +} + +int +vfs_file_is_ftp (char *filename) +{ + return 0; +} + +int +mc_utime (char *path, void *times) +{ + return 0; +} + + +void +extfs_run (char *file) +{ + return; +} + +int +geteuid(void) +{ + return 0; +} + + +int +mc_chdir(char *pathname) +{ + APIRET ret; + register int lgh = strlen(pathname); + + /* Set the current drive */ + if (lgh == 0) { + return -1; + } else { + /* First set the default drive */ + if (lgh > 1) { + if (pathname[1] == ':') { + ret = DosSetDefaultDisk(toupper(pathname[0]) - 'A' + 1); + } + } + /* After that, set the current dir! */ + ret = DosSetCurrentDir(pathname); + } + return ret; +} + +int +mc_chmod(char *pathName, int unxmode) +{ + /* OS/2 does not need S_REG */ + int os2Mode = unxmode & 0x0FFF; + return chmod(pathName, os2Mode); +} + +static int +conv_os2_unx_rc(int os2rc) +{ + int errCode; + switch (os2rc) { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_FILENAME_EXCED_RANGE: + errCode = ENOENT; + break; + case ERROR_NOT_DOS_DISK: + case ERROR_SHARING_VIOLATION: + case ERROR_SHARING_BUFFER_EXCEEDED: + case ERROR_ACCESS_DENIED: + errCode = EACCES; + break; + case ERROR_INVALID_PARAMETER: + errCode = EINVAL; + break; + default: + errCode = EINVAL; + break; + } + return errCode; +} + +int +mc_open (char *file, int flags, int pmode) +{ + return open(file, (flags | O_BINARY), pmode); +} + +int +mc_unlink(char *pathName) +{ + /* Use OS/2 API to delete a file, if the file is set as read-only, + the file will be deleted without asking the user! */ + APIRET rc; + rc = DosDelete(pathName); + if (!rc) { + return 0; + } + if (rc == ERROR_ACCESS_DENIED) { + chmod(pathName, (S_IREAD|S_IWRITE)); + rc = DosDelete(pathName); + if (rc) { + errno = conv_os2_unx_rc(rc) ; + return -1; + } else { + return 0; + } + } else { + errno = conv_os2_unx_rc(rc) ; + return -1; + } +} + +char * +get_default_editor (void) +{ + char *tmp; + APIRET rc; + char pathValue[5] = "PATH"; + UCHAR searchResult[MC_MAXPATHLEN + 1]; + + /* EPM is not always be installed */ + rc = DosSearchPath((SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY), + (PSZ) pathValue, + "EPM.EXE", + searchResult, + sizeof(searchResult)); + if (rc != 0) { + /* The system editor is always there */ + return strdup("e.exe"); + } else { + /* Let it be searched from my_system */ + return strdup("epm.exe"); + } +} + +/* get_default_shell + Get the default shell for the current hardware platform + TODO: Get the value of %OS2_SHELL% or %SHELL%: which one? +*/ +char * +get_default_shell() +{ + return getenv ("COMSPEC"); +} + +int +errno_dir_not_empty (int err) +{ + if (err == ENOTEMPTY) + return 1; + return 0; +} + +/* The MC library directory is by default the directory where mc.exe + is situated. It is recommended to specify this directory via MCHOME + environment variable, otherwise you will be unable to rename mc.exe */ +char * +get_mc_lib_dir () +{ + HMODULE mc_hm; + int rc; + char *cur = NULL; + char *mchome = getenv("MCHOME"); + + if (mchome && *mchome) + return mchome; + mchome = malloc(MC_MAXPATHLEN); + rc = DosQueryModuleHandle ("MC.EXE", &mc_hm); + if (!rc) + rc = DosQueryModuleName (mc_hm, MC_MAXPATHLEN, mchome); + if (!rc) + { + for (cur = mchome + strlen(mchome); \ + (cur > mchome) && (*cur != PATH_SEP); cur--); + *cur = 0; + cur = strdup(mchome); + free(mchome); + } + if (!cur || !*cur) { + free(cur); + return "C:\\MC"; + } + return cur; +} + +int get_user_rights (struct stat *buf) +{ + return 2; +} +void init_groups (void) +{ +} +void delete_groups (void) +{ +} diff --git a/pc/util_win32.c b/pc/util_win32.c new file mode 100644 index 000000000..aecab175e --- /dev/null +++ b/pc/util_win32.c @@ -0,0 +1,182 @@ +/* Utilities - Win32 utilities (Windows NT and Windows '95) + Copyright (C) 1994, 1995, 1996 the Free Software Foundation. + + Written 1996 by Juan Grigera + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include "util_win32.h" +#include "trace_nt.h" + +/* int win32_GetPlatform () + Checks in which OS Midnight Commander is running. + + Returns: + OS_WinNT - Windows NT 3.x + OS_Win95 - Windows 4.x + + Note: GetVersionEx (Win32API) is called only once. +*/ +int win32_GetPlatform () +{ + static int platform = 0; + + return (platform ? platform : (platform = win32_GetVersionEx()) ); +} + +/* int win32_GetVersionEx () + intended for use by win32_GetPlatform only +*/ +int win32_GetVersionEx () +{ + OSVERSIONINFO ovi; + + ovi.dwOSVersionInfoSize = sizeof(ovi); + win32APICALL( GetVersionEx(&ovi) ); + + return ovi.dwPlatformId; +} + +/* int win32_GetEXEType (const char* filename) + Determines whether filename (an Executable) is + a Console application (CUI) or a Graphical application(GUI). + + filename - Name of executable file to check + + Returns: EXE_win16 - Windows 3.x archive or OS/2 + EXE_win32CUI - NT or Chicago Console API, also OS/2 + EXE_win32GUI - NT or Chicago GUI API + EXE_otherCUI - DOS COM, MZ, ZM, Phar Lap + EXE_Unknown - Unknown + EXE_Error - Couldn't read file/EXE image + + TODO: better management of OS/2 images + EXE_CompressedArchive can be easily implemented + Notes: This function parses the executable header (the only ugly way + to do it). If header is not found or not understood, + 0 is returned. + + Information on NE, LE, LX and MZ taken from Ralf Brown's interrupt + list, under INT 21-function 4B ("EXEC" - LOAD AND/OR EXECUTE PROGRAM), + Tables 0806 - 836. + + Parsing of PE header (Win32 signature, "Portable Executable") + taken from MSKBase article Number: Q90493. +*/ + +/* ---- Executable Signatures ---- */ + +/* Alternative DOS signagure */ +#define IMAGE_DOS_SIGNATURE_ALTERNATIVE 0x4D5A /* ZM */ + +/* Phar Lap .EXP files */ +#define IMAGE_OLDPHARLAP_SIGNATURE 0x504D /* MP */ +#define IMAGE_NEWPHARLAP_286_SIGNATURE 0x3250 /* P2 */ +#define IMAGE_NEWPHARLAP_386_SIGNATURE 0x3350 /* P3 */ + +/* New Executables */ +#define IMAGE_LX_SIGNATURE 0x584C /* LX */ +#define IMAGE_PE_SIGNATURE 0x4550 /* PE */ + + +int win32_GetEXEType (const char* a_szFileName) +{ + HANDLE hImage; + DWORD dwDumm; + DWORD SectionOffset; + DWORD CoffHeaderOffset; + WORD wSignature; +/* DWORD MoreDosHeader[16]; */ + + IMAGE_DOS_HEADER image_dos_header; + IMAGE_FILE_HEADER image_file_header; + IMAGE_OPTIONAL_HEADER image_optional_header; +/* IMAGE_SECTION_HEADER image_section_header; */ + + /* Open the EXE file - Use Native API for SHARE compatibility */ + hImage = CreateFile(a_szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hImage == INVALID_HANDLE_VALUE) { + win32Trace (("win32_GetEXEType: Could not open file %s. API Error %d.", a_szFileName, GetLastError())); + return EXE_Error; + } + + /* Read the MZ (DOS) image header. */ + win32APICALL( ReadFile (hImage, (LPVOID)&image_dos_header, sizeof(IMAGE_DOS_HEADER), &dwDumm, NULL) ); + + switch (image_dos_header.e_magic) { + case IMAGE_DOS_SIGNATURE: /* MZ or ZM */ + case IMAGE_DOS_SIGNATURE_ALTERNATIVE: + break; + + case IMAGE_OLDPHARLAP_SIGNATURE: /* MP, P2, P3: Phar Lap executables */ + case IMAGE_NEWPHARLAP_286_SIGNATURE: + case IMAGE_NEWPHARLAP_386_SIGNATURE: + return EXE_otherCUI; + + default: + return EXE_otherCUI; /* Probably .COM? */ + } + + /* Read more MS-DOS header. */ +/* win32APICALL( ReadFile (hImage, MoreDosHeader, sizeof(MoreDosHeader)); */ + + /* Get new executable header */ + CoffHeaderOffset = SetFilePointer(hImage, image_dos_header.e_lfanew, NULL, FILE_BEGIN); +/* + sizeof(ULONG); */ + win32APICALL( ReadFile (hImage, (LPVOID) &wSignature, sizeof(WORD), &dwDumm, NULL) ); + + switch (wSignature) { + case IMAGE_PE_SIGNATURE: /* PE - Portable Executable */ + break; + case IMAGE_OS2_SIGNATURE: /* NE - New Executable OS/2 and Windows 3.x */ + case IMAGE_OS2_SIGNATURE_LE: /* LE - Linear Execuable (Windows 3.x) */ + case IMAGE_LX_SIGNATURE: /* LX - Linear Execuable (OS/2) */ + return EXE_win16; + default: + return EXE_Unknown; /* unknown New Executable or bad pointer */ + + } + + /* Continue parsing PE (COFF-like) */ + SectionOffset = CoffHeaderOffset + IMAGE_SIZEOF_FILE_HEADER + IMAGE_SIZEOF_NT_OPTIONAL_HEADER; + + win32APICALL( ReadFile(hImage, (LPVOID) &image_file_header, IMAGE_SIZEOF_FILE_HEADER, &dwDumm, NULL) ); + + /* Read optional header. */ + win32APICALL( ReadFile(hImage, (LPVOID) &image_optional_header, IMAGE_SIZEOF_NT_OPTIONAL_HEADER, &dwDumm, NULL) ); + + switch (image_optional_header.Subsystem) { + case IMAGE_SUBSYSTEM_WINDOWS_GUI: + return EXE_win32GUI; + + case IMAGE_SUBSYSTEM_WINDOWS_CUI: + case IMAGE_SUBSYSTEM_OS2_CUI: + case IMAGE_SUBSYSTEM_POSIX_CUI: + return EXE_win32CUI; + + case IMAGE_SUBSYSTEM_UNKNOWN: + case IMAGE_SUBSYSTEM_NATIVE: + return EXE_Unknown; /* FIXME: what is "NATIVE??" */ + default: + win32Trace(("Unknown type %u.\n", image_optional_header.Subsystem)); + return EXE_Unknown; + } +} + + diff --git a/pc/util_win32.h b/pc/util_win32.h new file mode 100644 index 000000000..2ed74c7fe --- /dev/null +++ b/pc/util_win32.h @@ -0,0 +1,42 @@ +/* util.Win32.h - Header + Utilities - Win32 utilities (Windows NT and Windows '95) + Copyright (C) 1994, 1995, 1996 the Free Software Foundation. + + Written 1996 by Juan Grigera + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Prototypes */ +int win32_GetPlatform (); +int win32_GetEXEType (const char* a_szFileName); +int win32_GetVersionEx (); + + +/* Constants */ +enum { + OS_WinNT = VER_PLATFORM_WIN32_NT, /* windows.h values */ + OS_Win95 = VER_PLATFORM_WIN32_WINDOWS, +}; + +enum { + EXE_Unknown, + EXE_win16, + EXE_win32CUI, + EXE_win32GUI, + EXE_otherCUI, + EXE_Error +}; + diff --git a/pc/util_winnt.c b/pc/util_winnt.c new file mode 100644 index 000000000..cddf6eff8 --- /dev/null +++ b/pc/util_winnt.c @@ -0,0 +1,85 @@ +/* Utilities - Windows NT specific utilities (not in Win95) + Copyright (C) 1994, 1995, 1996 the Free Software Foundation. + + Written 1996 by Juan Grigera + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include +#include +#include "util_win32.h" +#include "trace_nt.h" + + +/* int winnt_IsAdministrator() - Determines whether user has Administrator (root) + priviledges. + Return: 1 if administrator + 0 if not + + Note: Code taken from MSKbase Number: Q118626. + + To determine whether or not a user is an administrator, you need to examine + the user's access token with GetTokenInformation(). The access token + represents the user's privileges and the groups to which the user belongs. +*/ + +int winnt_IsAdministrator() +{ + HANDLE hAccessToken; + UCHAR InfoBuffer[1024]; + PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS)InfoBuffer; + DWORD dwInfoBufferSize; + PSID psidAdministrators; + SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; + UINT x; + BOOL bSuccess; + + if(!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&hAccessToken)) + return 0; + + bSuccess = GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer, + 1024, &dwInfoBufferSize); + + CloseHandle(hAccessToken); + + if( !bSuccess ) + return 0; + + if(!AllocateAndInitializeSid(&siaNtAuthority, 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &psidAdministrators)) + return 0; + + bSuccess = 0; + for(x=0;xGroupCount;x++) { + if( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) ) { + bSuccess = 1; + break; + } + } + FreeSid(psidAdministrators); + return bSuccess; +} + + +int geteuid () +{ + if (winnt_IsAdministrator()) + return 0; + return 1; +} + diff --git a/xv/xvicon.c b/xv/xvicon.c index 3315336da..d0b0221b0 100644 --- a/xv/xvicon.c +++ b/xv/xvicon.c @@ -118,7 +118,11 @@ struct xviconruncommand { void xvIconRunCommand (struct xviconruncommand *xirc) { - regex_command (x_basename (xirc->filename), xirc->action, xirc->drops, NULL); + char *droplist [2]; + droplist [0] = xirc->drops; + droplist [1] = NULL; + + regex_command (x_basename (xirc->filename), xirc->action, droplist, NULL); free (xirc->filename); free (xirc->action); if (xirc->drops != NULL) diff --git a/xv/xvscreen.c b/xv/xvscreen.c index d135fb8c8..3bfa3b7d2 100644 --- a/xv/xvscreen.c +++ b/xv/xvscreen.c @@ -269,9 +269,12 @@ struct user_drop { static void user_drop (struct user_drop *usdr) { WPanel *panel = current_panel; + char *droplist[2]; + droplist [0] = usdr->drops; + droplist [1] = NULL; xv_set_current_panel (usdr->panel); - regex_command (usdr->filename, "Drop", usdr->drops, NULL); + regex_command (usdr->filename, "Drop", droplist, NULL); free (usdr->drops); free (usdr); xv_set_current_panel (panel);