From: Ziliang Guo Date: Sun, 28 Apr 2013 16:25:41 +0000 (+0000) Subject: Incorporate rosapps. 0.3.15 was branched somewhat incorrectly so rosapps is not synce... X-Git-Tag: ReactOS-0.3.15~2 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=8ae8c64ccec18cf672c0cb1cc191f2eb2510c825 Incorporate rosapps. 0.3.15 was branched somewhat incorrectly so rosapps is not synced with the original branch. As all of the changes since then have been spelling/comments, it's not really a problem. Rosapps pulled from r58746. svn path=/branches/ReactOS-0.3.15/; revision=58886 --- diff --git a/modules/rosapps/CMakeLists.txt b/modules/rosapps/CMakeLists.txt new file mode 100644 index 00000000000..ea063efff4c --- /dev/null +++ b/modules/rosapps/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(applications) +add_subdirectory(demos) +add_subdirectory(drivers) \ No newline at end of file diff --git a/modules/rosapps/Doxyfile b/modules/rosapps/Doxyfile new file mode 100644 index 00000000000..4f5c9967ae2 --- /dev/null +++ b/modules/rosapps/Doxyfile @@ -0,0 +1,206 @@ +# Doxyfile 1.3.5 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "ROSApps" +PROJECT_NUMBER = +OUTPUT_DIRECTORY = doxy-doc +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = YES +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = D:\osexperts\ +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = NO +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +HAVE_DOT = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = . +FILE_PATTERNS = *.c \ + *.h +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = YES +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = YES +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 200 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = YES +RTF_HYPERLINKS = YES +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = NO +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = ../reactos/include +INCLUDE_FILE_PATTERNS = *.h +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = YES diff --git a/modules/rosapps/applications/CMakeLists.txt b/modules/rosapps/applications/CMakeLists.txt new file mode 100644 index 00000000000..07ce693d155 --- /dev/null +++ b/modules/rosapps/applications/CMakeLists.txt @@ -0,0 +1,9 @@ +add_subdirectory(cmdutils) +add_subdirectory(devutils) +#add_subdirectory(fraginator) +add_subdirectory(imagesoft) +#add_subdirectory(net) +add_subdirectory(notevil) +add_subdirectory(screensavers) +add_subdirectory(sysutils) +#add_subdirectory(winfile) diff --git a/modules/rosapps/applications/applications.rbuild b/modules/rosapps/applications/applications.rbuild new file mode 100644 index 00000000000..b4c9161d1d9 --- /dev/null +++ b/modules/rosapps/applications/applications.rbuild @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/rosapps/applications/cmdutils/CMakeLists.txt b/modules/rosapps/applications/cmdutils/CMakeLists.txt new file mode 100644 index 00000000000..414ae3e69d2 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/CMakeLists.txt @@ -0,0 +1,8 @@ +add_subdirectory(appwiz) +add_subdirectory(comp) +add_subdirectory(mode) +add_subdirectory(sort) +add_subdirectory(tee) +add_subdirectory(touch) +add_subdirectory(uptime) +add_subdirectory(y) diff --git a/modules/rosapps/applications/cmdutils/appwiz/CMakeLists.txt b/modules/rosapps/applications/cmdutils/appwiz/CMakeLists.txt new file mode 100644 index 00000000000..0f3aac816d8 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/appwiz/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_executable(appwiz.exe appwiz.c appwiz.rc) +set_module_type(appwiz.exe win32cui) +set_target_properties(appwiz.exe PROPERTIES SUFFIX "") +add_importlibs(appwiz.exe advapi32 user32 shell32 msvcrt kernel32) +add_cd_file(TARGET appwiz.exe DESTINATION reactos/system32 FOR all) diff --git a/modules/rosapps/applications/cmdutils/appwiz/appwiz.c b/modules/rosapps/applications/cmdutils/appwiz/appwiz.c new file mode 100644 index 00000000000..58ba20a4a88 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/appwiz/appwiz.c @@ -0,0 +1,261 @@ +/* + * + * PROJECT: Add or Remove Programs (Console Version) + * FILE: rosapps/applications/cmdutils/appwiz/appwiz.c + * PURPOSE: ReactOS Software Control Panel + * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org) + * UPDATE HISTORY: + * 07-28-2008 Created + */ + +#define SHOW_ALL 1 +#define APP_ONLY 2 +#define UPD_ONLY 3 + +#include +#include +#include +#include + + +void PrintHelp() +{ + printf(_T("Add or Remove Programs\n\ +APPWIZ [/? /l] [/all /app /upd]\n\ + /?\t Help\n\ + /l\t Show list\n\ + /all\t Show programs and updates\n\ + /app\t Show programs only\n\ + /upd\t Show updates only\n")); + _getch(); +} + + +void RunGUIAppWiz() +{ + SHELLEXECUTEINFO shInputDll; + + memset(&shInputDll, 0x0, sizeof(SHELLEXECUTEINFO)); + shInputDll.cbSize = sizeof(shInputDll); + shInputDll.hwnd = NULL; + shInputDll.lpVerb = _T("open"); + shInputDll.lpFile = _T("RunDll32.exe"); + shInputDll.lpParameters = _T("shell32.dll,Control_RunDLL appwiz.cpl"); + + if (ShellExecuteEx(&shInputDll) == 0) + { + MessageBox(NULL, _T("Can not start appwiz.cpl"), NULL, MB_OK | MB_ICONERROR); + } +} + +void CallUninstall(LPTSTR szUninstallString) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD dwRet; + MSG msg; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.wShowWindow = SW_SHOW; + + if (CreateProcess(NULL, szUninstallString, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + CloseHandle(pi.hThread); + + for (;;) + { + dwRet = MsgWaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE, QS_ALLEVENTS); + if (dwRet == WAIT_OBJECT_0 + 1) + { + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_FAILED) + break; + } + CloseHandle(pi.hProcess); + } +} + + +/* + dwMode: + SHOW_ALL - Applications & Updates + APP_ONLY - Applications only + UPD_ONLY - Updates only +*/ +int ShowAppList(DWORD dwMode, INT iItem) +{ + HKEY hKey, hSubKey; + DWORD dwSize, dwType, dwValue; + TCHAR szName[MAX_PATH]; + TCHAR szParentKeyName[MAX_PATH]; + TCHAR szDisplayName[MAX_PATH]; + TCHAR szOutBuf[MAX_PATH]; + FILETIME FileTime; + BOOL bIsUpdate = FALSE; + BOOL bIsSystemComponent = FALSE; + INT iIndex = 0, iColor = 0, iCount = 1; + HANDLE hOutput; + + if (RegOpenKey(HKEY_LOCAL_MACHINE, + _T("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"), + &hKey) != ERROR_SUCCESS) + { + printf(_T("ERROR: Can not open Uninstall key. Press any key for continue...\n")); + _getch(); + return 0; + } + + hOutput = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hOutput, FOREGROUND_GREEN | FOREGROUND_INTENSITY); + + dwSize = MAX_PATH; + while (RegEnumKeyEx(hKey, iIndex, szName, &dwSize, NULL, NULL, NULL, &FileTime) == ERROR_SUCCESS) + { + if (RegOpenKey(hKey, szName, &hSubKey) == ERROR_SUCCESS) + { + dwType = REG_DWORD; + dwSize = sizeof(DWORD); + + if (RegQueryValueEx(hSubKey, _T("SystemComponent"), + NULL, &dwType, + (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS) + { + bIsSystemComponent = (dwValue == 0x1); + } + else + { + bIsSystemComponent = FALSE; + } + + dwType = REG_SZ; + dwSize = MAX_PATH; + + bIsUpdate = (RegQueryValueEx(hSubKey, _T("ParentKeyName"), + NULL, &dwType, + (LPBYTE) szParentKeyName, + &dwSize) == ERROR_SUCCESS); + dwSize = MAX_PATH; + if (RegQueryValueEx(hSubKey, _T("DisplayName"), + NULL, &dwType, + (LPBYTE) szDisplayName, + &dwSize) == ERROR_SUCCESS) + { + if (!bIsSystemComponent) + { + if ((dwMode == SHOW_ALL) || ((dwMode == APP_ONLY) && (!bIsUpdate)) || ((dwMode == UPD_ONLY) && (bIsUpdate))) + { + if (iItem == -1) + { + wsprintf(szOutBuf, _T(" %d \t %s\n"), iCount, szDisplayName); + CharToOem(szOutBuf, szOutBuf); + printf("%s", szOutBuf); + } + else + { + dwType = REG_SZ; + dwSize = MAX_PATH; + + if ((RegQueryValueEx(hSubKey, _T("UninstallString"), NULL, &dwType, + (LPBYTE) szOutBuf, &dwSize) == ERROR_SUCCESS) && (iItem == iCount)) + { + CallUninstall(szOutBuf); + } + } + iCount++; + iColor++; + } + } + } + } + + if (iColor <= 5) + { + SetConsoleTextAttribute(hOutput, FOREGROUND_GREEN | FOREGROUND_INTENSITY); + } + else + { + SetConsoleTextAttribute(hOutput, FOREGROUND_GREEN | FOREGROUND_INTENSITY | FOREGROUND_RED); + if (iColor >= 10) iColor = 0; + } + + dwSize = MAX_PATH; + iIndex++; + } + + RegCloseKey(hSubKey); + RegCloseKey(hKey); + + SetConsoleTextAttribute(hOutput, FOREGROUND_GREEN | FOREGROUND_INTENSITY); + printf("\n\nPlease enter application/update number and press ENTER for uninstall\nor press any key for Exit...\n"); + + return 1; +} + + +int _tmain(int argc, _TCHAR* argv[]) +{ + INT iNumber; + TCHAR Char[4 + 1]; + + SetConsoleTitle(_T("Application Wizard")); + + if (argc < 2) + { + RunGUIAppWiz(); + return 0; + } + + if (_tcsncmp(argv[1], _T("/?"), 2) == 0) + { + PrintHelp(); + return 0; + } + + if (_tcsncmp(argv[1], _T("/l"), 2) == 0) + { + if (argc < 3) goto ShowAll; + if (_tcsncmp(argv[2], _T("/all"), 4) == 0) + { +ShowAll: + if (ShowAppList(SHOW_ALL, -1) == 0) return 0; + scanf(_T("%s"), Char); + + iNumber = atoi(Char); + + if (iNumber == 0) return 0; + ShowAppList(SHOW_ALL, iNumber); + } + else if (_tcsncmp(argv[2], _T("/app"), 4) == 0) + { + if (ShowAppList(APP_ONLY, -1) == 0) return 0; + + scanf(_T("%s"), Char); + + iNumber = atoi(Char); + + if (iNumber == 0) return 0; + ShowAppList(APP_ONLY, iNumber); + } + else if (_tcsncmp(argv[2], _T("/upd"), 4) == 0) + { + if (ShowAppList(UPD_ONLY, -1) == 0) return 0; + + scanf(_T("%s"), Char); + + iNumber = atoi(Char); + + if (iNumber == 0) return 0; + ShowAppList(UPD_ONLY, iNumber); + } + + return 0; + } + + return 0; +} diff --git a/modules/rosapps/applications/cmdutils/appwiz/appwiz.rbuild b/modules/rosapps/applications/cmdutils/appwiz/appwiz.rbuild new file mode 100644 index 00000000000..1c84412cf6e --- /dev/null +++ b/modules/rosapps/applications/cmdutils/appwiz/appwiz.rbuild @@ -0,0 +1,7 @@ + + advapi32 + user32 + shell32 + appwiz.c + appwiz.rc + diff --git a/modules/rosapps/applications/cmdutils/appwiz/appwiz.rc b/modules/rosapps/applications/cmdutils/appwiz/appwiz.rc new file mode 100644 index 00000000000..6f0156c7a83 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/appwiz/appwiz.rc @@ -0,0 +1,4 @@ +#define REACTOS_STR_FILE_DESCRIPTION "Add or Remove Programs (Console Version)\0" +#define REACTOS_STR_INTERNAL_NAME "appwiz\0" +#define REACTOS_STR_ORIGINAL_FILENAME "appwiz.exe\0" +#include diff --git a/modules/rosapps/applications/cmdutils/cmdutils.rbuild b/modules/rosapps/applications/cmdutils/cmdutils.rbuild new file mode 100644 index 00000000000..0d977f7ac18 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/cmdutils.rbuild @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/rosapps/applications/cmdutils/comp/CMakeLists.txt b/modules/rosapps/applications/cmdutils/comp/CMakeLists.txt new file mode 100644 index 00000000000..4401ba8ef58 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/comp/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_executable(comp comp.c comp.rc) +set_module_type(comp win32cui) +add_importlibs(comp msvcrt kernel32) +add_cd_file(TARGET comp DESTINATION reactos/system32 FOR all) diff --git a/modules/rosapps/applications/cmdutils/comp/comp.c b/modules/rosapps/applications/cmdutils/comp/comp.c new file mode 100644 index 00000000000..ca2f98b55ba --- /dev/null +++ b/modules/rosapps/applications/cmdutils/comp/comp.c @@ -0,0 +1,182 @@ +/* + * ReactOS Win32 Applications + * Copyright (C) 2005 ReactOS Team + * + * 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. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS comp utility + * FILE: comp.c + * PURPOSE: Compares the contents of two files + * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) + * REVISIONS: + * GM 25/09/05 Created + * + */ + + +#include +#include +#include +#include +#include + +#define STRBUF 1024 + +/* getline: read a line, return length */ +INT GetLine(char *line, FILE *in) +{ + if (fgets(line, STRBUF, in) == NULL) + return 0; + else + return strlen(line); +} + +/* print program usage */ +VOID Usage(VOID) +{ + _tprintf(_T("\nCompares the contents of two files or sets of files.\n\n" + "COMP [data1] [data2]\n\n" + " data1 Specifies location and name of first file to compare.\n" + " data2 Specifies location and name of second file to compare.\n")); +} + + +int _tmain (int argc, TCHAR *argv[]) +{ + INT i; + INT LineLen1, LineLen2; + FILE *fp1, *fp2; // file pointers + PTCHAR Line1 = (TCHAR *)malloc(STRBUF * sizeof(TCHAR)); + PTCHAR Line2 = (TCHAR *)malloc(STRBUF * sizeof(TCHAR)); + TCHAR File1[_MAX_PATH], // file paths + File2[_MAX_PATH]; + BOOL bMatch = TRUE, // files match + bAscii = FALSE, // /A switch + bLineNos = FALSE; // /L switch + + /* parse command line for options */ + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '/') + { + --argc; + switch (argv[i][1]) { + case 'A': bAscii = TRUE; + _tprintf(_T("/a not Supported\n")); /*FIXME: needs adding */ + break; + case 'L': bLineNos = TRUE; + _tprintf(_T("/l not supported\n")); /*FIXME: needs adding */ + break; + case '?': Usage(); + return EXIT_SUCCESS; + default: + _tprintf(_T("Invalid switch - /%c\n"), argv[i][1]); + Usage(); + return EXIT_FAILURE; + } + } + } + + switch (argc) + { + case 1 : + _tprintf(_T("Name of first file to compare: ")); + fgets(File1, _MAX_PATH, stdin); + for (i=0; i<_MAX_PATH; i++) + { + if (File1[i] == '\n') + { + File1[i] = '\0'; + break; + } + } + + _tprintf(_T("Name of second file to compare: ")); + fgets(File2, _MAX_PATH, stdin); + for (i=0; i<_MAX_PATH; i++) + { + if (File2[i] == '\n') + { + File2[i] = '\0'; + break; + } + } + break; + case 2 : + _tcsncpy(File1, argv[1], _MAX_PATH); + _tprintf(_T("Name of second file to compare: ")); + fgets(File2, _MAX_PATH, stdin); + for (i=0; i<_MAX_PATH; i++) + { + if (File2[i] == '\n') + { + File2[i] = '\0'; + break; + } + } + break; + case 3 : + _tcsncpy(File1, argv[1], _MAX_PATH); + _tcsncpy(File2, argv[2], _MAX_PATH); + break; + default : + _tprintf(_T("Bad command line syntax\n")); + return EXIT_FAILURE; + break; + } + + + + if ((fp1 = fopen(File1, "r")) == NULL) + { + _tprintf(_T("Can't find/open file: %s\n"), File1); + return EXIT_FAILURE; + } + if ((fp2 = fopen(File2, "r")) == NULL) + { + _tprintf(_T("Can't find/open file: %s\n"), File2); + fclose(fp1); + return EXIT_FAILURE; + } + + + _tprintf(_T("Comparing %s and %s...\n"), File1, File2); + + while ((LineLen1 = GetLine(Line1, fp1) != 0) && + (LineLen2 = GetLine(Line2, fp2) != 0)) + { + // LineCount++; + while ((*Line1 != '\0') && (*Line2 != '\0')) + { + if (*Line1 != *Line2) + { + bMatch = FALSE; + break; + } + Line1++, Line2++; + } + } + + bMatch ? _tprintf(_T("Files compare OK\n")) : _tprintf(_T("Files are different sizes.\n")); + + fclose(fp1); + fclose(fp2); + + + return EXIT_SUCCESS; +} +/* EOF */ diff --git a/modules/rosapps/applications/cmdutils/comp/comp.rbuild b/modules/rosapps/applications/cmdutils/comp/comp.rbuild new file mode 100644 index 00000000000..36c86620d15 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/comp/comp.rbuild @@ -0,0 +1,4 @@ + + comp.c + comp.rc + diff --git a/modules/rosapps/applications/cmdutils/comp/comp.rc b/modules/rosapps/applications/cmdutils/comp/comp.rc new file mode 100644 index 00000000000..9a00c52a8ca --- /dev/null +++ b/modules/rosapps/applications/cmdutils/comp/comp.rc @@ -0,0 +1,4 @@ +#define REACTOS_STR_FILE_DESCRIPTION "File Compare Utility\0" +#define REACTOS_STR_INTERNAL_NAME "comp\0" +#define REACTOS_STR_ORIGINAL_FILENAME "comp.exe\0" +#include diff --git a/modules/rosapps/applications/cmdutils/mode/CMakeLists.txt b/modules/rosapps/applications/cmdutils/mode/CMakeLists.txt new file mode 100644 index 00000000000..578fc4b345c --- /dev/null +++ b/modules/rosapps/applications/cmdutils/mode/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_executable(mode mode.c mode.rc) +set_module_type(mode win32cui) +add_importlibs(mode shell32 user32 msvcrt kernel32) +add_cd_file(TARGET mode DESTINATION reactos/system32 FOR all) diff --git a/modules/rosapps/applications/cmdutils/mode/mode.c b/modules/rosapps/applications/cmdutils/mode/mode.c new file mode 100644 index 00000000000..bdd73414b30 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/mode/mode.c @@ -0,0 +1,458 @@ +/* + * ReactOS mode console command + * + * mode.c + * + * Copyright (C) 2002 Robert Dickenson + * + * 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 + +#define MAX_PORTNAME_LEN 20 +#define MAX_COMPORT_NUM 10 +#define MAX_COMPARAM_LEN 20 + +#define NUM_ELEMENTS(a) (sizeof(a)/sizeof(a[0])) +#define ASSERT(a) + +const TCHAR* const usage_strings[] = { + _T("Device Status: MODE [device] [/STATUS]"), + _T("Select code page: MODE CON[:] CP SELECT=yyy"), + _T("Code page status: MODE CON[:] CP [/STATUS]"), + _T("Display mode: MODE CON[:] [COLS=c] [LINES=n]"), + _T("Typematic rate: MODE CON[:] [RATE=r DELAY=d]"), + _T("Redirect printing: MODE LPTn[:]=COMm[:]"), + _T("Serial port: MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s]\n") \ + _T(" [to=on|off] [xon=on|off] [odsr=on|off]\n") \ + _T(" [octs=on|off] [dtr=on|off|hs]\n") \ + _T(" [rts=on|off|hs|tg] [idsr=on|off]"), +}; + +const TCHAR* const parity_strings[] = { + _T("None"), // default + _T("Odd"), // only symbol in this set to have a 'd' in it + _T("Even"), // ... 'v' in it + _T("Mark"), // ... 'm' in it + _T("Space") // ... 's' and/or a 'c' in it +}; + +const TCHAR* const control_strings[] = { _T("OFF"), _T("ON"), _T("HANDSHAKE"), _T("TOGGLE") }; + +const TCHAR* const stopbit_strings[] = { _T("1"), _T("1.5"), _T("2") }; + + +int Usage() +{ + int i; + + _tprintf(_T("\nConfigures system devices.\n\n")); + for (i = 0; i < NUM_ELEMENTS(usage_strings); i++) { + _tprintf(_T("%s\n"), usage_strings[i]); + } + _tprintf(_T("\n")); + return 0; +} + +int QueryDevices() +{ + TCHAR buffer[20240]; + int len; + TCHAR* ptr = buffer; + + *ptr = '\0'; + if (QueryDosDevice(NULL, buffer, NUM_ELEMENTS(buffer))) { + while (*ptr != '\0') { + len = _tcslen(ptr); + if (_tcsstr(ptr, _T("COM"))) { + _tprintf(_T(" Found serial device - %s\n"), ptr); + } else if (_tcsstr(ptr, _T("PRN"))) { + _tprintf(_T(" Found printer device - %s\n"), ptr); + } else if (_tcsstr(ptr, _T("LPT"))) { + _tprintf(_T(" Found parallel device - %s\n"), ptr); + } else { + //_tprintf(_T(" Found other device - %s\n"), ptr); + } + ptr += (len+1); + } + } else { + _tprintf(_T(" ERROR: QueryDosDevice(...) failed.%ld\n"), GetLastError()); + } + return 1; +} + +int ShowParallelStatus(int nPortNum) +{ + TCHAR buffer[250]; + TCHAR szPortName[MAX_PORTNAME_LEN]; + + _stprintf(szPortName, _T("LPT%d"), nPortNum); + _tprintf(_T("\nStatus for device LPT%d:\n"), nPortNum); + _tprintf(_T("-----------------------\n")); + if (QueryDosDevice(szPortName, buffer, NUM_ELEMENTS(buffer))) { + TCHAR* ptr = _tcsrchr(buffer, '\\'); + if (ptr != NULL) { + if (0 == _tcscmp(szPortName, ++ptr)) { + _tprintf(_T(" Printer output is not being rerouted.\n")); + } else { + _tprintf(_T(" Printer output is being rerouted to serial port %s\n"), ptr); + } + return 0; + } else { + _tprintf(_T(" QueryDosDevice(%s) returned unrecogised form %s.\n"), szPortName, buffer); + } + } else { + _tprintf(_T(" ERROR: QueryDosDevice(%s) failed.\n"), szPortName); + } + return 1; +} + +int ShowConsoleStatus() +{ + DWORD dwKbdDelay; + DWORD dwKbdSpeed; + CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo; + HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); + + _tprintf(_T("\nStatus for device CON:\n")); + _tprintf(_T("-----------------------\n")); + if (GetConsoleScreenBufferInfo(hConsoleOutput, &ConsoleScreenBufferInfo)) { + _tprintf(_T(" Lines: %d\n"), ConsoleScreenBufferInfo.dwSize.Y); + _tprintf(_T(" Columns: %d\n"), ConsoleScreenBufferInfo.dwSize.X); + } + if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &dwKbdDelay, 0)) { + _tprintf(_T(" Keyboard delay: %ld\n"), dwKbdDelay); + } + if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &dwKbdSpeed, 0)) { + _tprintf(_T(" Keyboard rate: %ld\n"), dwKbdSpeed); + } + _tprintf(_T(" Code page: %d\n"), GetConsoleOutputCP()); + return 0; +} + +static +BOOL SerialPortQuery(int nPortNum, LPDCB pDCB, LPCOMMTIMEOUTS pCommTimeouts, BOOL bWrite) +{ + BOOL result; + HANDLE hPort; + TCHAR szPortName[MAX_PORTNAME_LEN]; + + ASSERT(pDCB); + ASSERT(pCommTimeouts); + + _stprintf(szPortName, _T("COM%d"), nPortNum); + hPort = CreateFile(szPortName, + GENERIC_READ|GENERIC_WRITE, + 0, // exclusive + NULL, // sec attr + OPEN_EXISTING, + 0, // no attributes + NULL); // no template + + if (hPort == INVALID_HANDLE_VALUE) { + _tprintf(_T("Illegal device name - %s\n"), szPortName); + _tprintf(_T("Last error = 0x%lx\n"), GetLastError()); + return FALSE; + } + if (bWrite) { + result = SetCommState(hPort, pDCB); + } else { + result = GetCommState(hPort, pDCB); + } + if (!result) { + _tprintf(_T("Failed to %s the status for device COM%d:\n"), bWrite ? _T("set") : _T("get"), nPortNum); + CloseHandle(hPort); + return FALSE; + } + if (bWrite) { + result = SetCommTimeouts(hPort, pCommTimeouts); + } else { + result = GetCommTimeouts(hPort, pCommTimeouts); + } + if (!result) { + _tprintf(_T("Failed to %s Timeout status for device COM%d:\n"), bWrite ? _T("set") : _T("get"), nPortNum); + CloseHandle(hPort); + return FALSE; + + } + CloseHandle(hPort); + return TRUE; +} + +int ShowSerialStatus(int nPortNum) +{ + DCB dcb; + COMMTIMEOUTS CommTimeouts; + + if (!SerialPortQuery(nPortNum, &dcb, &CommTimeouts, FALSE)) { + return 1; + } + if (dcb.Parity > NUM_ELEMENTS(parity_strings)) { + _tprintf(_T("ERROR: Invalid value for Parity Bits %d:\n"), dcb.Parity); + dcb.Parity = 0; + } + if (dcb.StopBits > NUM_ELEMENTS(stopbit_strings)) { + _tprintf(_T("ERROR: Invalid value for Stop Bits %d:\n"), dcb.StopBits); + dcb.StopBits = 0; + } + _tprintf(_T("\nStatus for device COM%d:\n"), nPortNum); + _tprintf(_T("-----------------------\n")); + _tprintf(_T(" Baud: %ld\n"), dcb.BaudRate); + _tprintf(_T(" Parity: %s\n"), parity_strings[dcb.Parity]); + _tprintf(_T(" Data Bits: %d\n"), dcb.ByteSize); + _tprintf(_T(" Stop Bits: %s\n"), stopbit_strings[dcb.StopBits]); + _tprintf(_T(" Timeout: %s\n"), CommTimeouts.ReadIntervalTimeout ? _T("ON") : _T("OFF")); + _tprintf(_T(" XON/XOFF: %s\n"), dcb.fOutX ? _T("ON") : _T("OFF")); + _tprintf(_T(" CTS handshaking: %s\n"), dcb.fOutxCtsFlow ? _T("ON") : _T("OFF")); + _tprintf(_T(" DSR handshaking: %s\n"), dcb.fOutxDsrFlow ? _T("ON") : _T("OFF")); + _tprintf(_T(" DSR sensitivity: %s\n"), dcb.fDsrSensitivity ? _T("ON") : _T("OFF")); + _tprintf(_T(" DTR circuit: %s\n"), control_strings[dcb.fDtrControl]); + _tprintf(_T(" RTS circuit: %s\n"), control_strings[dcb.fRtsControl]); + return 0; +} + +int SetParallelState(int nPortNum) +{ + TCHAR szPortName[MAX_PORTNAME_LEN]; + TCHAR szTargetPath[MAX_PORTNAME_LEN]; + + _stprintf(szPortName, _T("LPT%d"), nPortNum); + _stprintf(szTargetPath, _T("COM%d"), nPortNum); + if (!DefineDosDevice(DDD_REMOVE_DEFINITION, szPortName, szTargetPath)) { + DWORD error = GetLastError(); + + _tprintf(_T("SetParallelState(%d) - DefineDosDevice(%s) failed: 0x%lx\n"), nPortNum, szPortName, error); + } + return 0; +} + +/* + \??\COM1 + \Device\NamedPipe\Spooler\LPT1 +BOOL DefineDosDevice( + DWORD dwFlags, // options + LPCTSTR lpDeviceName, // device name + LPCTSTR lpTargetPath // path string +); +DWORD QueryDosDevice( + LPCTSTR lpDeviceName, // MS-DOS device name string + LPTSTR lpTargetPath, // query results buffer + DWORD ucchMax // maximum size of buffer +); + */ + +int SetConsoleState() +{ +/* + "Select code page: MODE CON[:] CP SELECT=yyy", + "Code page status: MODE CON[:] CP [/STATUS]", + "Display mode: MODE CON[:] [COLS=c] [LINES=n]", + "Typematic rate: MODE CON[:] [RATE=r DELAY=d]", + */ + return 0; +} + +static +int ExtractModeSerialParams(const TCHAR* param) +{ + if ( _tcsstr(param, _T("OFF"))) { + return 0; + } else if (_tcsstr(param, _T("ON"))) { + return 1; + } else if (_tcsstr(param, _T("HS"))) { + return 2; + } else if (_tcsstr(param, _T("TG"))) { + return 3; + } + return -1; +} + +int SetSerialState(int nPortNum, int args, TCHAR *argv[]) +{ + int arg; + int value; + DCB dcb; + COMMTIMEOUTS CommTimeouts; + TCHAR buf[MAX_COMPARAM_LEN+1]; + + if (SerialPortQuery(nPortNum, &dcb, &CommTimeouts, FALSE)) { + for (arg = 2; arg < args; arg++) { + if (_tcslen(argv[arg]) > MAX_COMPARAM_LEN) { + _tprintf(_T("Invalid parameter (too long) - %s\n"), argv[arg]); + return 1; + } + _tcscpy(buf, argv[arg]); + _tcslwr(buf); + if (_tcsstr(buf, _T("baud="))) { + _tscanf(buf+5, "%lu", &dcb.BaudRate); + } else if (_tcsstr(buf, _T("parity="))) { + if (_tcschr(buf, 'D')) { + dcb.Parity = 1; + } else if (_tcschr(buf, 'V')) { + dcb.Parity = 2; + } else if (_tcschr(buf, 'M')) { + dcb.Parity = 3; + } else if (_tcschr(buf, 'S')) { + dcb.Parity = 4; + } else { + dcb.Parity = 0; + } + } else if (_tcsstr(buf, _T("data="))) { + _tscanf(buf+5, "%lu", &dcb.ByteSize); + } else if (_tcsstr(buf, _T("stop="))) { + if (_tcschr(buf, '5')) { + dcb.StopBits = 1; + } else if (_tcschr(buf, '2')) { + dcb.StopBits = 2; + } else { + dcb.StopBits = 0; + } + } else if (_tcsstr(buf, _T("to="))) { // to=on|off + value = ExtractModeSerialParams(buf); + if (value != -1) { + } else { + goto invalid_serial_parameter; + } + } else if (_tcsstr(buf, _T("xon="))) { // xon=on|off + value = ExtractModeSerialParams(buf); + if (value != -1) { + dcb.fOutX = value; + dcb.fInX = value; + } else { + goto invalid_serial_parameter; + } + } else if (_tcsstr(buf, _T("odsr="))) { // odsr=on|off + value = ExtractModeSerialParams(buf); + if (value != -1) { + dcb.fOutxDsrFlow = value; + } else { + goto invalid_serial_parameter; + } + } else if (_tcsstr(buf, _T("octs="))) { // octs=on|off + value = ExtractModeSerialParams(buf); + if (value != -1) { + dcb.fOutxCtsFlow = value; + } else { + goto invalid_serial_parameter; + } + } else if (_tcsstr(buf, _T("dtr="))) { // dtr=on|off|hs + value = ExtractModeSerialParams(buf); + if (value != -1) { + dcb.fDtrControl = value; + } else { + goto invalid_serial_parameter; + } + } else if (_tcsstr(buf, _T("rts="))) { // rts=on|off|hs|tg + value = ExtractModeSerialParams(buf); + if (value != -1) { + dcb.fRtsControl = value; + } else { + goto invalid_serial_parameter; + } + } else if (_tcsstr(buf, _T("idsr="))) { // idsr=on|off + value = ExtractModeSerialParams(buf); + if (value != -1) { + dcb.fDsrSensitivity = value; + } else { + goto invalid_serial_parameter; + } + } else { +invalid_serial_parameter:; + _tprintf(_T("Invalid parameter - %s\n"), buf); + return 1; + } + } + SerialPortQuery(nPortNum, &dcb, &CommTimeouts, TRUE); + } + return 0; +} + +int find_portnum(const TCHAR* cmdverb) +{ + int portnum = -1; + + if (cmdverb[3] >= '0' && cmdverb[3] <= '9') { + portnum = cmdverb[3] - '0'; + if (cmdverb[4] >= '0' && cmdverb[4] <= '9') { + portnum *= 10; + portnum += cmdverb[4] - '0'; + } + } + return portnum; +} + +int main(int argc, TCHAR *argv[]) +{ + int nPortNum; + TCHAR param1[MAX_COMPARAM_LEN+1]; + TCHAR param2[MAX_COMPARAM_LEN+1]; + + if (argc > 1) { + if (_tcslen(argv[1]) > MAX_COMPARAM_LEN) { + _tprintf(_T("Invalid parameter (too long) - %s\n"), argv[1]); + return 1; + } + _tcscpy(param1, argv[1]); + _tcslwr(param1); + if (argc > 2) { + if (_tcslen(argv[2]) > MAX_COMPARAM_LEN) { + _tprintf(_T("Invalid parameter (too long) - %s\n"), argv[2]); + return 1; + } + _tcscpy(param2, argv[2]); + _tcslwr(param2); + } else { + param2[0] = '\0'; + } + if (_tcsstr(param1, _T("/?")) || _tcsstr(param1, _T("-?"))) { + return Usage(); + } else if (_tcsstr(param1, _T("/status"))) { + goto show_status; + } else if (_tcsstr(param1, _T("lpt"))) { + nPortNum = find_portnum(param1); + if (nPortNum != -1) + return ShowParallelStatus(nPortNum); + } else if (_tcsstr(param1, _T("con"))) { + return ShowConsoleStatus(); + } else if (_tcsstr(param1, _T("com"))) { + nPortNum = find_portnum(param1); + if (nPortNum != -1) { + if (param2[0] == '\0' || _tcsstr(param2, _T("/status"))) { + return ShowSerialStatus(nPortNum); + } else { + return SetSerialState(nPortNum, argc, argv); + } + } + } + _tprintf(_T("Invalid parameter - %s\n"), param1); + return 1; + } else { +show_status:; + + QueryDevices(); +/* + ShowParallelStatus(1); + for (nPortNum = 0; nPortNum < MAX_COMPORT_NUM; nPortNum++) { + ShowSerialStatus(nPortNum + 1); + } + ShowConsoleStatus(); + */ + } + return 0; +} diff --git a/modules/rosapps/applications/cmdutils/mode/mode.rbuild b/modules/rosapps/applications/cmdutils/mode/mode.rbuild new file mode 100644 index 00000000000..11eb3065335 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/mode/mode.rbuild @@ -0,0 +1,6 @@ + + . + shell32 + user32 + mode.c + mode.rc diff --git a/modules/rosapps/applications/cmdutils/mode/mode.rc b/modules/rosapps/applications/cmdutils/mode/mode.rc new file mode 100644 index 00000000000..44ca8c4d32c --- /dev/null +++ b/modules/rosapps/applications/cmdutils/mode/mode.rc @@ -0,0 +1,5 @@ + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS mode utility\0" +#define REACTOS_STR_INTERNAL_NAME "mode\0" +#define REACTOS_STR_ORIGINAL_FILENAME "mode.exe\0" +#include diff --git a/modules/rosapps/applications/cmdutils/sort/CMakeLists.txt b/modules/rosapps/applications/cmdutils/sort/CMakeLists.txt new file mode 100644 index 00000000000..1429da4fed9 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/sort/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_executable(sort sort.c sort.rc) +set_module_type(sort win32cui) +add_importlibs(sort msvcrt kernel32) +add_cd_file(TARGET sort DESTINATION reactos/system32 FOR all) \ No newline at end of file diff --git a/modules/rosapps/applications/cmdutils/sort/sort.c b/modules/rosapps/applications/cmdutils/sort/sort.c new file mode 100644 index 00000000000..0d6cc56cb4e --- /dev/null +++ b/modules/rosapps/applications/cmdutils/sort/sort.c @@ -0,0 +1,141 @@ +/* +* SORT - reads line of a file and sorts them in order +* Copyright 1995 Jim Lynch +* +* Adapted for ReactOS +* +* 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 + +#define MAXRECORDS 65536 /* maximum number of records that can be + * sorted */ +#define MAXLEN 4095 /* maximum record length */ + +int rev; /* reverse flag */ +int help; /* help flag */ +int sortcol; /* sort column */ +int err = 0; /* error counter */ + +int +cmpr(const void *a, const void *b) +{ + char *A, *B; + + A = *(char **) a; + B = *(char **) b; + + if (sortcol > 0) { + if (strlen(A) > sortcol) + A += sortcol; + else + A = ""; + if (strlen(B) > sortcol) + B += sortcol; + else + B = ""; + } + if (!rev) + return strcmp(A, B); + else + return strcmp(B, A); +} + +void +usage(void) +{ + fputs("SORT\n", stderr); + fputs("Sorts input and writes output to a file, console or a device.\n", stderr); + if (err) + fputs("Invalid parameter\n", stderr); + fputs(" SORT [options] < [drive:1][path1]file1 > [drive2:][path2]file2\n", stderr); + fputs(" Command | SORT [options] > [drive:][path]file\n", stderr); + fputs(" Options:\n", stderr); + fputs(" /R Reverse order\n", stderr); + fputs(" /+n Start sorting with column n\n", stderr); + fputs(" /? Help\n", stderr); +} + +int main(int argc, char **argv) +{ + char temp[MAXLEN + 1]; + char **list; + char *cp; /* option character pointer */ + int nr; + int i; + + + sortcol = 0; + rev = 0; + while (--argc) { + if (*(cp = *++argv) == '/') { + switch (cp[1]) { + case 'R': + case 'r': + rev = 1; + break; + case '?': + case 'h': + case 'H': + help = 1; + break; + case '+': + sortcol = atoi(cp + 1); + if (sortcol) + sortcol--; + break; + default: + err++; + } + } + } + if (err || help) { + usage(); + exit(1); + } + list = (char **) malloc(MAXRECORDS * sizeof(char *)); + if (list == NULL) { + fputs("SORT: Insufficient memory\n", stderr); + exit(3); + } + for (nr = 0; nr < MAXRECORDS; nr++) { + if (fgets(temp, MAXLEN, stdin) == NULL) + break; + if(strlen(temp)) + temp[strlen(temp)-1]='\0'; + list[nr] = (char *) malloc(strlen(temp) + 1); + if (list[nr] == NULL) { + fputs("SORT: Insufficient memory\n", stderr); + exit(3); + } + strcpy(list[nr], temp); + } + if (nr == MAXRECORDS) { + fputs("SORT: number of records exceeds maximum\n", stderr); + exit(4); + } + qsort((void *) list, nr, sizeof(char *), cmpr); + for (i = 0; i < nr; i++) { + fputs(list[i], stdout); + fputs("\n",stdout); + } + return 0; +} + +/* EOF */ diff --git a/modules/rosapps/applications/cmdutils/sort/sort.rbuild b/modules/rosapps/applications/cmdutils/sort/sort.rbuild new file mode 100644 index 00000000000..188fd1eb282 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/sort/sort.rbuild @@ -0,0 +1,4 @@ + + sort.c + sort.rc + diff --git a/modules/rosapps/applications/cmdutils/sort/sort.rc b/modules/rosapps/applications/cmdutils/sort/sort.rc new file mode 100644 index 00000000000..e3418a39524 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/sort/sort.rc @@ -0,0 +1,5 @@ + +#define REACTOS_STR_FILE_DESCRIPTION "W32 sort command\0" +#define REACTOS_STR_INTERNAL_NAME "sort\0" +#define REACTOS_STR_ORIGINAL_FILENAME "sort.exe\0" +#include diff --git a/modules/rosapps/applications/cmdutils/tee/CMakeLists.txt b/modules/rosapps/applications/cmdutils/tee/CMakeLists.txt new file mode 100644 index 00000000000..189648ef5e7 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/tee/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_executable(tee tee.c tee.rc) +set_module_type(tee win32cui) +add_importlibs(tee msvcrt kernel32) +add_cd_file(TARGET tee DESTINATION reactos/system32 FOR all) \ No newline at end of file diff --git a/modules/rosapps/applications/cmdutils/tee/tee.c b/modules/rosapps/applications/cmdutils/tee/tee.c new file mode 100644 index 00000000000..149f8486d0c --- /dev/null +++ b/modules/rosapps/applications/cmdutils/tee/tee.c @@ -0,0 +1,220 @@ +/* + * TEE.C - external command. + * + * clone from 4nt tee command + * + * 01 Sep 1999 - Paolo Pantaleo + * started + * + * + */ + + +#include +#include +#include +#include + + + +#define TEE_BUFFER_SIZE 8192 + +/*these are function that emulate the ones used in cmd*/ + +/*many of them are just copied in this file from their +original location*/ + +VOID ConOutPuts (LPTSTR szText) +{ + DWORD dwWritten; + + WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szText, _tcslen(szText), &dwWritten, NULL); + WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), _T("\n"), 1, &dwWritten, NULL); +} + + +VOID ConErrPrintf (LPTSTR szFormat, ...) +{ + DWORD dwWritten; + TCHAR szOut[4096]; + va_list arg_ptr; + + va_start (arg_ptr, szFormat); + _vstprintf (szOut, szFormat, arg_ptr); + va_end (arg_ptr); + + WriteFile (GetStdHandle (STD_ERROR_HANDLE), szOut, _tcslen(szOut), &dwWritten, NULL); +} + + + +VOID error_sfile_not_found (LPTSTR f) +{ + ConErrPrintf (_T("Error opening file") _T(" - %s\n"), f); +} + + + + +VOID ConErrPuts (LPTSTR szText) +{ + ConErrPrintf(_T("%s\n"),szText ); +} + + +INT main (int argc,char **p) +{ + /*reading/writing buffer*/ + TCHAR buff[TEE_BUFFER_SIZE]; + + /*handle for file and console*/ + HANDLE hConsoleIn,hConsoleOut; + + /*bytes written by WriteFile and ReadFile*/ + DWORD dwRead,dwWritten; + + + BOOL bRet,bAppend=FALSE; + + + /*command line parsing stuff*/ + LPTSTR tmp; + INT i; + BOOL bQuote; + + /*file list implementation*/ + LPTSTR *files; + INT iFileCounter=0; + HANDLE *hFile; + + /*used to remove '"' (if any)*/ + INT add; + + DWORD dw; + + + if (argc < 2) + return 1; + + if (_tcsncmp (p[1], _T("/?"), 2) == 0) + { + ConOutPuts (_T("Copy standard input to both standard output and a file.\n" + "\n" + "TEE [/A] file...\n" + "\n" + " file One or more files that will receive output.\n" + " /A Append output to files.\n")); + return 0; + } + + files = malloc(sizeof(LPTSTR)*argc); + hFile = malloc(sizeof(HANDLE)*argc); + + hConsoleIn=GetStdHandle(STD_INPUT_HANDLE); + hConsoleOut=GetStdHandle(STD_OUTPUT_HANDLE); + + /*parse command line for /a and file name(s)*/ + for(i=1;i = sizeof(files) / sizeof(*files) ) + { + ConErrPrintf("too many files, maximum is %d\n",sizeof(files) / sizeof(*files)); + return 1; + } + */ + + files[iFileCounter++]= p[i]+add; + } + + /*open file(s)*/ + for(i=0;i0 && bRet) + { + for(i=0;i0 && bRet); + + for(i=0;i + tee.c + tee.rc + diff --git a/modules/rosapps/applications/cmdutils/tee/tee.rc b/modules/rosapps/applications/cmdutils/tee/tee.rc new file mode 100644 index 00000000000..2ed9b99f99c --- /dev/null +++ b/modules/rosapps/applications/cmdutils/tee/tee.rc @@ -0,0 +1,5 @@ + +#define REACTOS_STR_FILE_DESCRIPTION "W32 tee command\0" +#define REACTOS_STR_INTERNAL_NAME "tee\0" +#define REACTOS_STR_ORIGINAL_FILENAME "tee.exe\0" +#include diff --git a/modules/rosapps/applications/cmdutils/touch/CMakeLists.txt b/modules/rosapps/applications/cmdutils/touch/CMakeLists.txt new file mode 100644 index 00000000000..fd5cd2ae231 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/touch/CMakeLists.txt @@ -0,0 +1,10 @@ + +add_executable(touch err.c touch.c touch.rc) +target_link_libraries(touch getopt) +set_module_type(touch win32cui) +add_importlibs(touch msvcrt kernel32) +if(MSVC) + target_link_libraries(touch oldnames) +endif() + +add_cd_file(TARGET touch DESTINATION reactos/system32 FOR all) \ No newline at end of file diff --git a/modules/rosapps/applications/cmdutils/touch/err.c b/modules/rosapps/applications/cmdutils/touch/err.c new file mode 100644 index 00000000000..5f966687eca --- /dev/null +++ b/modules/rosapps/applications/cmdutils/touch/err.c @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "err.h" +#include +#include +#include +#include + +#ifdef __STDC__ +#include +#else +#include +#endif + +extern char *__progname; /* Program name, from crt0. */ + +void +#ifdef __STDC__ +err(int eval, const char *fmt, ...) +#else +err(eval, fmt, va_alist) + int eval; + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + verr(eval, fmt, ap); + va_end(ap); +} + +void +verr(int eval, const char *fmt, va_list ap) +{ + int sverrno; + + sverrno = errno; + (void)fprintf(stderr, "%s: ", __progname); + if (fmt != NULL) { + (void)vfprintf(stderr, fmt, ap); + (void)fprintf(stderr, ": "); + } + (void)fprintf(stderr, "%s\n", strerror(sverrno)); + exit(eval); +} + +void +#if __STDC__ +errx(int eval, const char *fmt, ...) +#else +errx(eval, fmt, va_alist) + int eval; + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + verrx(eval, fmt, ap); + va_end(ap); +} + +void +verrx(int eval, const char *fmt, va_list ap) +{ + (void)fprintf(stderr, "%s: ", __progname); + if (fmt != NULL) + (void)vfprintf(stderr, fmt, ap); + (void)fprintf(stderr, "\n"); + exit(eval); +} + +void +#if __STDC__ +warn(const char *fmt, ...) +#else +warn(fmt, va_alist) + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + vwarn(fmt, ap); + va_end(ap); +} + +void +vwarn(fmt, ap) + const char *fmt; + va_list ap; +{ + int sverrno; + + sverrno = errno; + (void)fprintf(stderr, "%s: ", __progname); + if (fmt != NULL) { + (void)vfprintf(stderr, fmt, ap); + (void)fprintf(stderr, ": "); + } + (void)fprintf(stderr, "%s\n", strerror(sverrno)); +} + +void +#ifdef __STDC__ +warnx(const char *fmt, ...) +#else +warnx(fmt, va_alist) + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + vwarnx(fmt, ap); + va_end(ap); +} + +void +vwarnx(fmt, ap) + const char *fmt; + va_list ap; +{ + (void)fprintf(stderr, "%s: ", __progname); + if (fmt != NULL) + (void)vfprintf(stderr, fmt, ap); + (void)fprintf(stderr, "\n"); +} diff --git a/modules/rosapps/applications/cmdutils/touch/err.h b/modules/rosapps/applications/cmdutils/touch/err.h new file mode 100644 index 00000000000..bbc7397f852 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/touch/err.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _ERR_H_ +#define _ERR_H_ + +/* + * Don't use va_list in the err/warn prototypes. Va_list is typedef'd in two + * places ( and ), so if we include one + * of them here we may collide with the utility's includes. It's unreasonable + * for utilities to have to include one of them to include err.h, so we get + * _BSD_VA_LIST_ from and use it. + */ +/*#include */ +/*#include */ +#include "various.h" +#include + +void err __P((int, const char *, ...)); +void verr __P((int, const char *, va_list)); +void errx __P((int, const char *, ...)); +void verrx __P((int, const char *, va_list)); +void warn __P((const char *, ...)); +void vwarn __P((const char *, va_list)); +void warnx __P((const char *, ...)); +void vwarnx __P((const char *, va_list)); + +#endif /* !_ERR_H_ */ diff --git a/modules/rosapps/applications/cmdutils/touch/touch.c b/modules/rosapps/applications/cmdutils/touch/touch.c new file mode 100644 index 00000000000..257eaeac176 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/touch/touch.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 1993 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * 7/20/97 - Ted Felix + * Ported to Win32 from bsd4.3-reno at wuarchive. + * Biggest problems were err() routines, utines, and + * gettimeofday(). All easily fixed. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1993 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#include +#include +#include + +//#ifdef __STDC__ +//#error "__STDC__ defined" +//#endif + +#include +#include +#include +#include +#include +#define DEFFILEMODE S_IWRITE + +#include +#include +#include +#include +#include +#include +#include + +char *__progname; /* Program name, from crt0. */ + +/* Prototypes */ +int rw __P((char *, struct stat *, int)); +void stime_arg1 __P((char *, time_t *)); +void stime_arg2 __P((char *, int, time_t *)); +void stime_file __P((char *, time_t *)); +void usage __P((void)); + +int +main(int argc, char *argv[]) +{ + struct stat sb; + time_t tv[2]; + int aflag, cflag, fflag, mflag, ch, fd, len, rval, timeset; + char *p; + struct utimbuf utb; + + __progname = argv[0]; + + aflag = cflag = fflag = mflag = timeset = 0; + time(&tv[0]); + + while ((ch = getopt(argc, argv, "acfmr:t:")) != EOF) + switch(ch) { + case 'a': + aflag = 1; + break; + case 'c': + cflag = 1; + break; + case 'f': + fflag = 1; + break; + case 'm': + mflag = 1; + break; + case 'r': + timeset = 1; + stime_file(optarg, tv); + break; + case 't': + timeset = 1; + stime_arg1(optarg, tv); + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + /* Default is both -a and -m. */ + if (aflag == 0 && mflag == 0) + aflag = mflag = 1; + + /* + * If no -r or -t flag, at least two operands, the first of which + * is an 8 or 10 digit number, use the obsolete time specification. + */ + if (!timeset && argc > 1) { + (void)strtol(argv[0], &p, 10); + len = p - argv[0]; + if (*p == '\0' && (len == 8 || len == 10)) { + timeset = 1; + stime_arg2(argv[0], len == 10, tv); + } + } + + /* Otherwise use the current time of day. */ + if (!timeset) + tv[1] = tv[0]; + + if (*argv == NULL) + usage(); + + for (rval = 0; *argv; ++argv) { + /* See if the file exists. */ + if (stat(*argv, &sb)) { + if (!cflag) { + /* Create the file. */ + fd = _open(*argv, + O_WRONLY | O_CREAT, DEFFILEMODE); + if (fd == -1 || fstat(fd, &sb) || _close(fd)) { + rval = 1; + warn("%s", *argv); + continue; + } + + /* If using the current time, we're done. */ + if (!timeset) + continue; + } else + continue; + } + + if (!aflag) + tv[0] = sb.st_atime; + if (!mflag) + tv[1] = sb.st_mtime; + + /* Try utime. */ + utb.actime = tv[0]; + utb.modtime = tv[1]; + if (!utime(*argv, &utb)) + continue; + + /* If the user specified a time, nothing else we can do. */ + if (timeset) { + rval = 1; + warn("%s", *argv); + } + + /* + * System V and POSIX 1003.1 require that a NULL argument + * set the access/modification times to the current time. + * The permission checks are different, too, in that the + * ability to write the file is sufficient. Take a shot. + */ + if (!utime(*argv, NULL)) + continue; + + /* Try reading/writing. */ + if (rw(*argv, &sb, fflag)) + rval = 1; + } + return rval; +} + +#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2; + +void +stime_arg1(char *arg, time_t *tvp) +{ + struct tm *t; + int yearset; + char *p; + /* Start with the current time. */ + if ((t = localtime(&tvp[0])) == NULL) + err(1, "localtime"); + /* [[CC]YY]MMDDhhmm[.SS] */ + if ((p = strchr(arg, '.')) == NULL) + t->tm_sec = 0; /* Seconds defaults to 0. */ + else { + if (strlen(p + 1) != 2) + goto terr; + *p++ = '\0'; + t->tm_sec = ATOI2(p); + } + + yearset = 0; + switch(strlen(arg)) { + case 12: /* CCYYMMDDhhmm */ + t->tm_year = ATOI2(arg); + t->tm_year *= 1000; + yearset = 1; + /* FALLTHOUGH */ + case 10: /* YYMMDDhhmm */ + if (yearset) { + yearset = ATOI2(arg); + t->tm_year += yearset; + } else { + yearset = ATOI2(arg); + if (yearset < 69) + t->tm_year = yearset + 2000; + else + t->tm_year = yearset + 1900; + } + t->tm_year -= 1900; /* Convert to UNIX time. */ + /* FALLTHROUGH */ + case 8: /* MMDDhhmm */ + t->tm_mon = ATOI2(arg); + --t->tm_mon; /* Convert from 01-12 to 00-11 */ + t->tm_mday = ATOI2(arg); + t->tm_hour = ATOI2(arg); + t->tm_min = ATOI2(arg); + break; + default: + goto terr; + } + + t->tm_isdst = -1; /* Figure out DST. */ + tvp[0] = tvp[1] = mktime(t); + if (tvp[0] == -1) +terr: errx(1, + "out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]"); +} + +void +stime_arg2(char *arg, int year, time_t *tvp) +{ + struct tm *t; + /* Start with the current time. */ + if ((t = localtime(&tvp[0])) == NULL) + err(1, "localtime"); + + t->tm_mon = ATOI2(arg); /* MMDDhhmm[yy] */ + --t->tm_mon; /* Convert from 01-12 to 00-11 */ + t->tm_mday = ATOI2(arg); + t->tm_hour = ATOI2(arg); + t->tm_min = ATOI2(arg); + if (year) + t->tm_year = ATOI2(arg); + + t->tm_isdst = -1; /* Figure out DST. */ + tvp[0] = tvp[1] = mktime(t); + if (tvp[0] == -1) + errx(1, + "out of range or illegal time specification: MMDDhhmm[yy]"); +} + +void +stime_file(char *fname, time_t *tvp) +{ + struct stat sb; + + if (stat(fname, &sb)) + err(1, "%s", fname); + tvp[0] = sb.st_atime; + tvp[1] = sb.st_mtime; +} + +int +rw(char *fname, struct stat *sbp, int force) +{ + int fd, needed_chmod, rval; + u_char byte; + + /* Try regular files and directories. */ + if (!S_ISREG(sbp->st_mode) && !S_ISDIR(sbp->st_mode)) { + warnx("%s: %s", fname, strerror(0)); + return (1); + } + + needed_chmod = rval = 0; + if ((fd = _open(fname, O_RDWR, 0)) == -1) { + if (!force || _chmod(fname, DEFFILEMODE)) + goto err; + if ((fd = _open(fname, O_RDWR, 0)) == -1) + goto err; + needed_chmod = 1; + } + + if (sbp->st_size != 0) { + if (_read(fd, &byte, sizeof(byte)) != sizeof(byte)) + goto err; + if (_lseek(fd, (off_t)0, SEEK_SET) == -1) + goto err; + if (_write(fd, &byte, sizeof(byte)) != sizeof(byte)) + goto err; + } else { + if (_write(fd, &byte, sizeof(byte)) != sizeof(byte)) { +err: rval = 1; + warn("%s", fname); +/* } else if (ftruncate(fd, (off_t)0)) {*/ + } else if (_chsize(fd, (off_t)0)) { + rval = 1; + warn("%s: file modified", fname); + } + } + + if (_close(fd) && rval != 1) { + rval = 1; + warn("%s", fname); + } + if (needed_chmod && _chmod(fname, sbp->st_mode) && rval != 1) { + rval = 1; + warn("%s: permissions modified", fname); + } + return (rval); +} + +/*__dead void*/ +void +usage() +{ + (void)fprintf(stderr, + "usage: touch [-acfm] [-r file] [-t time] file ...\n"); + exit(1); +} diff --git a/modules/rosapps/applications/cmdutils/touch/touch.rbuild b/modules/rosapps/applications/cmdutils/touch/touch.rbuild new file mode 100644 index 00000000000..954acbff9fd --- /dev/null +++ b/modules/rosapps/applications/cmdutils/touch/touch.rbuild @@ -0,0 +1,6 @@ + + . + getopt + err.c + touch.c + touch.rc diff --git a/modules/rosapps/applications/cmdutils/touch/touch.rc b/modules/rosapps/applications/cmdutils/touch/touch.rc new file mode 100644 index 00000000000..d4e19216cd0 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/touch/touch.rc @@ -0,0 +1,5 @@ + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Touch utility\0" +#define REACTOS_STR_INTERNAL_NAME "touch\0" +#define REACTOS_STR_ORIGINAL_FILENAME "touch.exe\0" +#include diff --git a/modules/rosapps/applications/cmdutils/touch/various.h b/modules/rosapps/applications/cmdutils/touch/various.h new file mode 100644 index 00000000000..8ad37bd84a1 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/touch/various.h @@ -0,0 +1,55 @@ +// Various things you need when porting BSD and GNU utilities to +// Win32. + +#ifndef VARIOUS_H +#define VARIOUS_H + +/* types.h */ +typedef unsigned char u_char; +typedef unsigned int u_int; +typedef float f4byte_t; +typedef double f8byte_t; +//typedef __int16 s2byte_t; +//typedef __int32 s4byte_t; +//typedef __int64 s8byte_t; +//typedef unsigned __int16 u2byte_t; +//typedef unsigned __int32 u4byte_t; +//typedef unsigned __int64 u8byte_t; +//typedef __int32 quad_t; +//typedef unsigned __int32 u_quad_t; +//typedef unsigned __int16 u_int16_t; +//typedef unsigned __int32 u_int32_t; + +typedef long uid_t; // SunOS 5.5 + +#define __P(x) x +//#define __STDC__ 1 + +/* utmp.h */ +#define UT_LINESIZE 8 +#define UT_HOSTSIZE 16 + +/* stat.h */ +//#define S_ISREG(mode) (((mode)&0xF000) == 0x8000) +//#define S_ISDIR(mode) (((mode)&0xF000) == 0x4000) + +#undef MIN //take care of windows default +#undef MAX //take care of windows default +#define MIN(a, b) ((a) <= (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#define bcopy(s1, s2, n) memmove(s2, s1, n) +#define bcmp(s1, s2, n) (memcmp(s1, s2, n) != 0) +#define bzero(s, n) memset(s, 0, n) + +#define index(s, c) strchr(s, c) +#define rindex(s, c) strrchr(s, c) + +//#ifndef _WINSOCKAPI_ +//struct timeval { +// long tv_sec; /* seconds */ +// long tv_usec; /* and microseconds */ +//}; +//#endif + +#endif diff --git a/modules/rosapps/applications/cmdutils/uptime/CMakeLists.txt b/modules/rosapps/applications/cmdutils/uptime/CMakeLists.txt new file mode 100644 index 00000000000..b8e5f831a87 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/uptime/CMakeLists.txt @@ -0,0 +1,9 @@ +#add_definitions(-DLINUX_OUTPUT) + +add_executable(uptime uptime.c uptime.rc) +set_module_type(uptime win32cui) +add_importlibs(uptime msvcrt kernel32) +if(MSVC) + add_importlibs(uptime ntdll) +endif() +add_cd_file(TARGET uptime DESTINATION reactos/system32 FOR all) \ No newline at end of file diff --git a/modules/rosapps/applications/cmdutils/uptime/uptime.c b/modules/rosapps/applications/cmdutils/uptime/uptime.c new file mode 100644 index 00000000000..bedecb19bfc --- /dev/null +++ b/modules/rosapps/applications/cmdutils/uptime/uptime.c @@ -0,0 +1,34 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +int main(int argc, char* argv[]) +{ + SYSTEMTIME SystemTime; + LARGE_INTEGER liCount, liFreq; + + GetLocalTime(&SystemTime); + + if (QueryPerformanceCounter(&liCount) && + QueryPerformanceFrequency(&liFreq)) + { + LONGLONG TotalSecs = liCount.QuadPart / liFreq.QuadPart; + LONGLONG Days = (TotalSecs / 86400); + LONGLONG Hours = ((TotalSecs % 86400) / 3600); + LONGLONG Mins = ((TotalSecs % 86400) % 3600) / 60; + LONGLONG Secs = ((TotalSecs % 86400) % 3600) % 60; + +#ifdef LINUX_OUTPUT + UNREFERENCED_PARAMETER(Secs); + _tprintf(_T(" %.2u:%.2u "), SystemTime.wHour, SystemTime.wMinute); + _tprintf(_T("up %I64u days, %I64u:%I64u\n"), Days, Hours, Mins); /*%.2I64u secs*/ +#else + _tprintf(_T("System Up Time:\t\t%I64u days, %I64u Hours, %I64u Minutes, %.2I64u Seconds\n"), + Days, Hours, Mins, Secs); +#endif + return 0; + } + + return -1; +} diff --git a/modules/rosapps/applications/cmdutils/uptime/uptime.rbuild b/modules/rosapps/applications/cmdutils/uptime/uptime.rbuild new file mode 100644 index 00000000000..27ded5d4623 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/uptime/uptime.rbuild @@ -0,0 +1,5 @@ + + + uptime.c + uptime.rc + diff --git a/modules/rosapps/applications/cmdutils/uptime/uptime.rc b/modules/rosapps/applications/cmdutils/uptime/uptime.rc new file mode 100644 index 00000000000..203bdb234b5 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/uptime/uptime.rc @@ -0,0 +1,4 @@ +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS uptime\0" +#define REACTOS_STR_INTERNAL_NAME "uptime\0" +#define REACTOS_STR_ORIGINAL_FILENAME "uptime.exe\0" +#include diff --git a/modules/rosapps/applications/cmdutils/y/CMakeLists.txt b/modules/rosapps/applications/cmdutils/y/CMakeLists.txt new file mode 100644 index 00000000000..926bd055ec0 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/y/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_executable(y y.c y.rc) +set_module_type(y win32cui) +add_importlibs(y msvcrt kernel32) +add_cd_file(TARGET y DESTINATION reactos/system32 FOR all) \ No newline at end of file diff --git a/modules/rosapps/applications/cmdutils/y/y.c b/modules/rosapps/applications/cmdutils/y/y.c new file mode 100644 index 00000000000..1e052bdbb51 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/y/y.c @@ -0,0 +1,122 @@ +/* + * Y.C - Y external command. + * + * clone from 4nt y command + * + * 02 Oct 1999 (Paolo Pantaleo) + * started + * + * + */ + +#define BUFF_SIZE 4096 + +#include +#include +#include + +static +VOID ConErrPrintf (LPTSTR szFormat, ...) +{ + DWORD dwWritten; + TCHAR szOut[BUFF_SIZE]; + va_list arg_ptr; + + va_start (arg_ptr, szFormat); + _vstprintf (szOut, szFormat, arg_ptr); + va_end (arg_ptr); + + WriteFile (GetStdHandle (STD_ERROR_HANDLE), szOut, _tcslen(szOut), &dwWritten, NULL); +} + + +static +VOID ConOutPuts (LPTSTR szText) +{ + DWORD dwWritten; + + WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szText, _tcslen(szText), &dwWritten, NULL); + WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), "\n", 1, &dwWritten, NULL); +} + + +int main (int argc, char **argv) +{ + INT i; + HANDLE hFind; + HANDLE hConsoleIn, hConsoleOut, hFile; + char buff[BUFF_SIZE]; + DWORD dwRead,dwWritten; + BOOL bRet; + WIN32_FIND_DATA FindData; + + hConsoleIn = GetStdHandle(STD_INPUT_HANDLE); + hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE); + + if (argc == 2 && _tcsncmp (argv[1], _T("/?"), 2) == 0) + { + ConOutPuts(_T("copy stdin to stdout and then files to stdout\n" + "\n" + "Y [files]\n" + "\n" + "files files to copy to stdout")); + return 0; + } + + /*stdin to stdout*/ + do + { + bRet = ReadFile(hConsoleIn,buff,sizeof(buff),&dwRead,NULL); + + if (dwRead>0 && bRet) + WriteFile(hConsoleOut,buff,dwRead,&dwWritten,NULL); + + } while(dwRead>0 && bRet); + + + /*files to stdout*/ + Sleep(0); + + for (i = 1; i < argc; i++) + { + hFind=FindFirstFile(argv[i],&FindData); + + if (hFind==INVALID_HANDLE_VALUE) + { + ConErrPrintf("File not found - %s\n",argv[i]); + continue; + } + + do + { + hFile = CreateFile(FindData.cFileName, + GENERIC_READ, + FILE_SHARE_READ,NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL,NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + ConErrPrintf("File not found - %s\n",FindData.cFileName); + continue; + } + + do + { + bRet = ReadFile(hFile,buff,sizeof(buff),&dwRead,NULL); + + if (dwRead>0 && bRet) + WriteFile(hConsoleOut,buff,dwRead,&dwWritten,NULL); + + } while(dwRead>0 && bRet); + + CloseHandle(hFile); + + } + while(FindNextFile(hFind,&FindData)); + + FindClose(hFind); + } + + return 0; +} diff --git a/modules/rosapps/applications/cmdutils/y/y.rbuild b/modules/rosapps/applications/cmdutils/y/y.rbuild new file mode 100644 index 00000000000..8c2fae60107 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/y/y.rbuild @@ -0,0 +1,4 @@ + + y.c + y.rc + diff --git a/modules/rosapps/applications/cmdutils/y/y.rc b/modules/rosapps/applications/cmdutils/y/y.rc new file mode 100644 index 00000000000..d6d2c456e0c --- /dev/null +++ b/modules/rosapps/applications/cmdutils/y/y.rc @@ -0,0 +1,5 @@ + +#define REACTOS_STR_FILE_DESCRIPTION "W32 y command\0" +#define REACTOS_STR_INTERNAL_NAME "y\0" +#define REACTOS_STR_ORIGINAL_FILENAME "y.exe\0" +#include diff --git a/modules/rosapps/applications/devutils/CMakeLists.txt b/modules/rosapps/applications/devutils/CMakeLists.txt new file mode 100644 index 00000000000..a782d525147 --- /dev/null +++ b/modules/rosapps/applications/devutils/CMakeLists.txt @@ -0,0 +1,6 @@ +#add_subdirectory(gdb2) +#add_subdirectory(gdihv) +#add_subdirectory(genguid) +#add_subdirectory(symdump) +#add_subdirectory(syscalldump) +add_subdirectory(vgafontedit) diff --git a/modules/rosapps/applications/devutils/directory.rbuild b/modules/rosapps/applications/devutils/directory.rbuild new file mode 100644 index 00000000000..4d2722309da --- /dev/null +++ b/modules/rosapps/applications/devutils/directory.rbuild @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/rosapps/applications/devutils/gdb2/README b/modules/rosapps/applications/devutils/gdb2/README new file mode 100644 index 00000000000..f5df7714beb --- /dev/null +++ b/modules/rosapps/applications/devutils/gdb2/README @@ -0,0 +1 @@ +dbg2 is a tool that splits the console output of gdb and the debugged program. it runs gdb into new console and redirects its output to the original, so the debugged program outputs to the second console. \ No newline at end of file diff --git a/modules/rosapps/applications/devutils/gdb2/gdb2.cpp b/modules/rosapps/applications/devutils/gdb2/gdb2.cpp new file mode 100644 index 00000000000..e6cee05358f --- /dev/null +++ b/modules/rosapps/applications/devutils/gdb2/gdb2.cpp @@ -0,0 +1,298 @@ +/* + * gdb2 - gdb output splitter + * + * Copyright (C) 2000,2001 Nedko Arnaoudov + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ph.h" + +#define GDB_INITIAL_COMMAND "gdb.exe" +#define PARAMS_SEPARATOR " " +#define PARAMS_SEPARATOR_LEN strlen(PARAMS_SEPARATOR); + +void DisplayError(const char *pszAPI); +void ReadAndHandleOutput(HANDLE hPipeRead); +void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut, + HANDLE hChildStdIn, + HANDLE hChildStdErr, + char *pchCommandLine); + +DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam); +HANDLE hChildProcess = NULL; +HANDLE hStdIn = NULL; // Handle to parents std input. +BOOL bRunThread = TRUE; + +int main(int argc, char* argv[]) +{ + HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; + HANDLE hInputWriteTmp,hInputRead,hInputWrite; + HANDLE hErrorWrite; + HANDLE hThread; + DWORD ThreadId; + SECURITY_ATTRIBUTES sa; + + // Set up the security attributes struct. + sa.nLength= sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + + + // Create the child output pipe. + if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) + DisplayError("CreatePipe"); + + + // Create a duplicate of the output write handle for the std error + // write handle. This is necessary in case the child application + // closes one of its std output handles. + if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, + GetCurrentProcess(),&hErrorWrite,0, + TRUE,DUPLICATE_SAME_ACCESS)) + DisplayError("DuplicateHandle"); + + + // Create the child input pipe. + if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0)) + DisplayError("CreatePipe"); + + + // Create new output read handle and the input write handles. Set + // the Properties to FALSE. Otherwise, the child inherits the + // properties and, as a result, non-closeable handles to the pipes + // are created. + if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, + GetCurrentProcess(), + &hOutputRead, // Address of new handle. + 0,FALSE, // Make it uninheritable. + DUPLICATE_SAME_ACCESS)) + DisplayError("DupliateHandle"); + + if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp, + GetCurrentProcess(), + &hInputWrite, // Address of new handle. + 0,FALSE, // Make it uninheritable. + DUPLICATE_SAME_ACCESS)) + DisplayError("DupliateHandle"); + + + // Close inheritable copies of the handles you do not want to be + // inherited. + if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); + if (!CloseHandle(hInputWriteTmp)) DisplayError("CloseHandle"); + + + // Get std input handle so you can close it and force the ReadFile to + // fail when you want the input thread to exit. + if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == + INVALID_HANDLE_VALUE ) + DisplayError("GetStdHandle"); + + SetConsoleTitle("gdb control console"); + + size_t size = strlen(GDB_INITIAL_COMMAND)+PARAMS_SEPARATOR_LEN; + + // get parameters length + for (int i = 1 ; i < argc ; i++) + size += strlen(argv[i])+PARAMS_SEPARATOR_LEN; + + size++; // terminating null + + char *pszCommandLine = new char [size]; + if (!pszCommandLine) + { + printf("out of memory.\n"); + return -1; + } + + strcpy(pszCommandLine,GDB_INITIAL_COMMAND); + for (int i = 1 ; i < argc ; i++) + { + strcat(pszCommandLine,PARAMS_SEPARATOR); + strcat(pszCommandLine,argv[i]); + } + + PrepAndLaunchRedirectedChild(hOutputWrite,hInputRead,hErrorWrite,pszCommandLine); + + + // Close pipe handles (do not continue to modify the parent). + // You need to make sure that no handles to the write end of the + // output pipe are maintained in this process or else the pipe will + // not close when the child process exits and the ReadFile will hang. + if (!CloseHandle(hOutputWrite)) DisplayError("CloseHandle"); + if (!CloseHandle(hInputRead )) DisplayError("CloseHandle"); + if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle"); + + + // Launch the thread that gets the input and sends it to the child. + hThread = CreateThread(NULL,0,GetAndSendInputThread, + (LPVOID)hInputWrite,0,&ThreadId); + if (hThread == NULL) DisplayError("CreateThread"); + + + // Read the child's output. + ReadAndHandleOutput(hOutputRead); + // Redirection is complete + + + // Force the read on the input to return by closing the stdin handle. + if (!CloseHandle(hStdIn)) DisplayError("CloseHandle"); + + + // Tell the thread to exit and wait for thread to die. + bRunThread = FALSE; + + if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED) + DisplayError("WaitForSingleObject"); + + if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle"); + if (!CloseHandle(hInputWrite)) DisplayError("CloseHandle"); + + return 0; +} + +/////////////////////////////////////////////////////////////////////// +// PrepAndLaunchRedirectedChild +// Sets up STARTUPINFO structure, and launches redirected child. +/////////////////////////////////////////////////////////////////////// +void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut, + HANDLE hChildStdIn, + HANDLE hChildStdErr, + char *pchCommandLine) +{ + PROCESS_INFORMATION pi; + STARTUPINFO si; + static CHAR Title[] = "debugged program console"; + + // Set up the start up info struct. + ZeroMemory(&si,sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdOutput = hChildStdOut; + si.hStdInput = hChildStdIn; + si.hStdError = hChildStdErr; + si.lpTitle = Title; + // Use this if you want to hide the child: + // si.wShowWindow = SW_HIDE; + // Note that dwFlags must include STARTF_USESHOWWINDOW if you want to + // use the wShowWindow flags. + + + // Launch the process that you want to redirect (in this case, + // Child.exe). Make sure Child.exe is in the same directory as + // redirect.c launch redirect from a command line to prevent location + // confusion. + if (!CreateProcess(NULL,pchCommandLine,NULL,NULL,TRUE, + CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi)) + DisplayError("CreateProcess"); + + + // Set global child process handle to cause threads to exit. + hChildProcess = pi.hProcess; + + + // Close any unnecessary handles. + if (!CloseHandle(pi.hThread)) DisplayError("CloseHandle"); +} + +/////////////////////////////////////////////////////////////////////// +// ReadAndHandleOutput +// Monitors handle for input. Exits when child exits or pipe breaks. +/////////////////////////////////////////////////////////////////////// +void ReadAndHandleOutput(HANDLE hPipeRead) +{ + CHAR lpBuffer[256]; + DWORD nBytesRead; + DWORD nCharsWritten; + + while(TRUE) + { + if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer), + &nBytesRead,NULL) || !nBytesRead) + { + if (GetLastError() == ERROR_BROKEN_PIPE) + break; // pipe done - normal exit path. + else + DisplayError("ReadFile"); // Something bad happened. + } + + // Display the character read on the screen. + if (!WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer, + nBytesRead,&nCharsWritten,NULL)) + DisplayError("WriteConsole"); + } +} + + +/////////////////////////////////////////////////////////////////////// +// GetAndSendInputThread +// Thread procedure that monitors the console for input and sends input +// to the child process through the input pipe. +// This thread ends when the child application exits. +/////////////////////////////////////////////////////////////////////// +DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam) +{ + CHAR read_buff[256]; + DWORD nBytesRead,nBytesWrote; + HANDLE hPipeWrite = (HANDLE)lpvThreadParam; + + // Get input from our console and send it to child through the pipe. + while (bRunThread) + { + if(!ReadConsole(hStdIn,read_buff,1,&nBytesRead,NULL)) + DisplayError("ReadConsole"); + + read_buff[nBytesRead] = '\0'; // Follow input with a NULL. + + if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL)) + { + if (GetLastError() == ERROR_NO_DATA) + break; // Pipe was closed (normal exit path). + else + DisplayError("WriteFile"); + } + } + + return 1; +} + +/////////////////////////////////////////////////////////////////////// +// DisplayError +// Displays the error number and corresponding message. +/////////////////////////////////////////////////////////////////////// +void DisplayError(const char *pszAPI) +{ + LPVOID lpvMessageBuffer; + CHAR szPrintBuffer[512]; + DWORD nCharsWritten; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpvMessageBuffer, 0, NULL); + + wsprintf(szPrintBuffer, + "ERROR: API = %s.\n error code = %d.\n message = %s.\n", + pszAPI, GetLastError(), (char *)lpvMessageBuffer); + + WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),szPrintBuffer, + lstrlen(szPrintBuffer),&nCharsWritten,NULL); + + LocalFree(lpvMessageBuffer); + ExitProcess(GetLastError()); +} diff --git a/modules/rosapps/applications/devutils/gdb2/gdb2.rbuild b/modules/rosapps/applications/devutils/gdb2/gdb2.rbuild new file mode 100644 index 00000000000..c427711f6ef --- /dev/null +++ b/modules/rosapps/applications/devutils/gdb2/gdb2.rbuild @@ -0,0 +1,5 @@ + + . + user32 + gdb2.cpp + diff --git a/modules/rosapps/applications/devutils/gdb2/ph.h b/modules/rosapps/applications/devutils/gdb2/ph.h new file mode 100644 index 00000000000..54c6bee392e --- /dev/null +++ b/modules/rosapps/applications/devutils/gdb2/ph.h @@ -0,0 +1,10 @@ +#ifndef PH_H___b210ed20_5d0f_4038_abd3_d42ff283c9d0__INCLUDED +#define PH_H___b210ed20_5d0f_4038_abd3_d42ff283c9d0__INCLUDED + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include + +#include + +#endif // #ifndef PH_H___b210ed20_5d0f_4038_abd3_d42ff283c9d0__INCLUDED diff --git a/modules/rosapps/applications/devutils/gdihv/gdi.h b/modules/rosapps/applications/devutils/gdihv/gdi.h new file mode 100644 index 00000000000..60eed9d18fc --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/gdi.h @@ -0,0 +1,66 @@ +typedef struct _GDI_TABLE_ENTRY +{ + PVOID KernelData; /* Points to the kernel mode structure */ + HANDLE ProcessId; /* process id that created the object, 0 for stock objects */ + LONG Type; /* the first 16 bit is the object type including the stock obj flag, the last 16 bits is just the object type */ + PVOID UserData; /* Points to the user mode structure, usually NULL though */ +} GDI_TABLE_ENTRY, *PGDI_TABLE_ENTRY; + +typedef PGDI_TABLE_ENTRY (CALLBACK * GDIQUERYPROC) (void); + +/* GDI handle table can hold 0x4000 handles */ +#define GDI_HANDLE_COUNT 0x10000 +#define GDI_GLOBAL_PROCESS (0x0) + +/* Handle Masks and shifts */ +#define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1) +#define GDI_HANDLE_TYPE_MASK 0x007f0000 +#define GDI_HANDLE_BASETYPE_MASK 0x001f0000 +#define GDI_HANDLE_STOCK_MASK 0x00800000 +#define GDI_HANDLE_REUSE_MASK 0xff000000 +#define GDI_HANDLE_REUSECNT_SHIFT 24 +#define GDI_HANDLE_UPPER_MASK 0x0000ffff + +/* Handle macros */ +#define GDI_HANDLE_CREATE(i, t) \ + ((HANDLE)(((i) & GDI_HANDLE_INDEX_MASK) | ((t) << 16))) + +#define GDI_HANDLE_GET_INDEX(h) \ + (((ULONG_PTR)(h)) & GDI_HANDLE_INDEX_MASK) + +#define GDI_HANDLE_GET_TYPE(h) \ + (((ULONG_PTR)(h)) & GDI_HANDLE_TYPE_MASK) + +#define GDI_HANDLE_IS_TYPE(h, t) \ + ((t) == (((ULONG_PTR)(h)) & GDI_HANDLE_TYPE_MASK)) + +#define GDI_HANDLE_IS_STOCKOBJ(h) \ + (0 != (((ULONG_PTR)(h)) & GDI_HANDLE_STOCK_MASK)) + +#define GDI_HANDLE_SET_STOCKOBJ(h) \ + ((h) = (HANDLE)(((ULONG_PTR)(h)) | GDI_HANDLE_STOCK_MASK)) + +#define GDI_HANDLE_GET_UPPER(h) \ + (((ULONG_PTR)(h)) & GDI_HANDLE_UPPER_MASK) + +#define GDI_OBJECT_TYPE_DC 0x00010000 +#define GDI_OBJECT_TYPE_REGION 0x00040000 +#define GDI_OBJECT_TYPE_BITMAP 0x00050000 +#define GDI_OBJECT_TYPE_PALETTE 0x00080000 +#define GDI_OBJECT_TYPE_FONT 0x000a0000 +#define GDI_OBJECT_TYPE_PFE 0x000c0000 +#define GDI_OBJECT_TYPE_BRUSH 0x00100000 +#define GDI_OBJECT_TYPE_EMF 0x00210000 +#define GDI_OBJECT_TYPE_PEN 0x00300000 +#define GDI_OBJECT_TYPE_EXTPEN 0x00500000 +#define GDI_OBJECT_TYPE_COLORSPACE 0x00090000 +#define GDI_OBJECT_TYPE_METADC 0x00660000 +#define GDI_OBJECT_TYPE_METAFILE 0x00260000 +#define GDI_OBJECT_TYPE_ENHMETAFILE 0x00460000 +/* Following object types made up for ROS */ +#define GDI_OBJECT_TYPE_ENHMETADC 0x00740000 +#define GDI_OBJECT_TYPE_MEMDC 0x00750000 +#define GDI_OBJECT_TYPE_DCE 0x00770000 +#define GDI_OBJECT_TYPE_DONTCARE 0x007f0000 +/** Not really an object type. Forces GDI_FreeObj to be silent. */ +#define GDI_OBJECT_TYPE_SILENT 0x80000000 diff --git a/modules/rosapps/applications/devutils/gdihv/gdihv.c b/modules/rosapps/applications/devutils/gdihv/gdihv.c new file mode 100644 index 00000000000..fa7b8a63575 --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/gdihv.c @@ -0,0 +1,53 @@ +/* + * Gdi handle viewer + * + * gdihv.c + * + * Copyright (C) 2007 Timo Kreuzer kreuzer reactos org> + * + * 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 "gdihv.h" + +HINSTANCE g_hInstance; +PGDI_TABLE_ENTRY GdiHandleTable = 0; + +static +PGDI_TABLE_ENTRY +MyGdiQueryTable() +{ + PTEB pTeb = NtCurrentTeb(); + PPEB pPeb = pTeb->ProcessEnvironmentBlock; + return pPeb->GdiSharedHandleTable; +} + +int WINAPI WinMain (HINSTANCE hThisInstance, + HINSTANCE hPrevInstance, + LPSTR lpszArgument, + int nStyle) + +{ + g_hInstance = hThisInstance; + + InitCommonControls(); + + GdiHandleTable = MyGdiQueryTable(); + + DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_MAINWND), HWND_DESKTOP, MainWindow_WndProc, 0); + + /* The program return value is 0 */ + return 0; +} diff --git a/modules/rosapps/applications/devutils/gdihv/gdihv.h b/modules/rosapps/applications/devutils/gdihv/gdihv.h new file mode 100644 index 00000000000..c3b412b919f --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/gdihv.h @@ -0,0 +1,22 @@ +#ifndef _GDIHV_H +#define _GDIHV_H + +#define UNICODE + +#define WIN32_NO_STATUS +#include +#include +#include +#include + +#include "gdi.h" +#include "mainwnd.h" +#include "proclist.h" +#include "handlelist.h" + +#include "resource.h" + +extern PGDI_TABLE_ENTRY GdiHandleTable; +extern HINSTANCE g_hInstance; + +#endif //_GDIHV_H diff --git a/modules/rosapps/applications/devutils/gdihv/gdihv.rbuild b/modules/rosapps/applications/devutils/gdihv/gdihv.rbuild new file mode 100644 index 00000000000..eaae6d761fd --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/gdihv.rbuild @@ -0,0 +1,11 @@ + + . + user32 + comctl32 + psapi + gdihv.c + gdihv.rc + mainwnd.c + handlelist.c + proclist.c + diff --git a/modules/rosapps/applications/devutils/gdihv/gdihv.rc b/modules/rosapps/applications/devutils/gdihv/gdihv.rc new file mode 100644 index 00000000000..9152a65c26b --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/gdihv.rc @@ -0,0 +1,16 @@ +#include +#include "resource.h" + +IDI_MAIN ICON "system.ico" + +IDD_MAINWND DIALOGEX 0, 0, 260, 250 +STYLE DS_SHELLFONT | WS_CAPTION | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX +CAPTION "HandleView" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Tasks", IDC_PROCESSLIST, "SysListView32", WS_BORDER | WS_TABSTOP | 0x00000001 | LVS_REPORT, 5, 5, 100, 200 + CONTROL "Tasks", IDC_HANDLELIST, "SysListView32", WS_BORDER | WS_TABSTOP | 0x00000001 | LVS_REPORT, 110, 5, 150, 200 + PUSHBUTTON "Refresh handles", IDC_REFRESHHANDLE, 200, 230, 80, 14, WS_CLIPSIBLINGS | WS_TABSTOP + PUSHBUTTON "Refresh processes", IDC_REFRESHPROCESS, 50, 230, 80, 14, WS_CLIPSIBLINGS | WS_TABSTOP + +END diff --git a/modules/rosapps/applications/devutils/gdihv/handlelist.c b/modules/rosapps/applications/devutils/gdihv/handlelist.c new file mode 100644 index 00000000000..63bf2419628 --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/handlelist.c @@ -0,0 +1,194 @@ +/* + * Gdi handle viewer + * + * handlelist.c + * + * Copyright (C) 2007 Timo Kreuzer kreuzer reactos org> + * + * 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 "gdihv.h" + +VOID +HandleList_Create(HWND hListCtrl) +{ + LVCOLUMN column; + + column.mask = LVCF_TEXT|LVCF_FMT|LVCF_WIDTH; + column.fmt = LVCFMT_LEFT; + + column.pszText = L"Number"; + column.cx = 50; + (void)ListView_InsertColumn(hListCtrl, 0, &column); + + column.pszText = L"Index"; + column.cx = 45; + (void)ListView_InsertColumn(hListCtrl, 1, &column); + + column.pszText = L"Handle"; + column.cx = 90; + (void)ListView_InsertColumn(hListCtrl, 2, &column); + + column.pszText = L"Type"; + column.cx = 80; + (void)ListView_InsertColumn(hListCtrl, 3, &column); + + column.pszText = L"Process"; + column.cx = 80; + (void)ListView_InsertColumn(hListCtrl, 4, &column); + + column.pszText = L"KernelData"; + column.cx = 80; + (void)ListView_InsertColumn(hListCtrl, 5, &column); + + column.pszText = L"UserData"; + column.cx = 80; + (void)ListView_InsertColumn(hListCtrl, 6, &column); + + column.pszText = L"Type"; + column.cx = 80; + (void)ListView_InsertColumn(hListCtrl, 7, &column); + + HandleList_Update(hListCtrl, 0); +} + +VOID +HandleList_Update(HWND hHandleListCtrl, HANDLE ProcessId) +{ + INT i, index; + HANDLE handle; + PGDI_TABLE_ENTRY pEntry; + LVITEM item; + TCHAR strText[80]; + TCHAR* str2; + + (void)ListView_DeleteAllItems(hHandleListCtrl); + item.mask = LVIF_TEXT|LVIF_PARAM; + item.pszText = strText; + item.cchTextMax = 80; + for (i = 0; i<= GDI_HANDLE_COUNT; i++) + { + pEntry = &GdiHandleTable[i]; + if ( ((ProcessId != (HANDLE)1) && ((pEntry->Type & GDI_HANDLE_BASETYPE_MASK) != 0)) || + ((ProcessId == (HANDLE)1) && ((pEntry->Type & GDI_HANDLE_BASETYPE_MASK) == 0)) || + (ProcessId == (HANDLE)2) ) + { + if (ProcessId == (HANDLE)1 || ProcessId == (HANDLE)2 || + ((LONG)ProcessId & 0xfffc) == ((ULONG)pEntry->ProcessId & 0xfffc)) + { + handle = GDI_HANDLE_CREATE(i, pEntry->Type); + index = ListView_GetItemCount(hHandleListCtrl); + item.iItem = index; + item.iSubItem = 0; + item.lParam = (LPARAM)handle; + + wsprintf(strText, L"%d", index); + (void)ListView_InsertItem(hHandleListCtrl, &item); + + wsprintf(strText, L"%d", i); + ListView_SetItemText(hHandleListCtrl, index, 1, strText); + + wsprintf(strText, L"%#08x", handle); + ListView_SetItemText(hHandleListCtrl, index, 2, strText); + + str2 = GetTypeName(handle); + ListView_SetItemText(hHandleListCtrl, index, 3, str2); + + wsprintf(strText, L"%#08x", (UINT)pEntry->ProcessId); + ListView_SetItemText(hHandleListCtrl, index, 4, strText); + + wsprintf(strText, L"%#08x", (UINT)pEntry->KernelData); + ListView_SetItemText(hHandleListCtrl, index, 5, strText); + + wsprintf(strText, L"%#08x", (UINT)pEntry->UserData); + ListView_SetItemText(hHandleListCtrl, index, 6, strText); + + wsprintf(strText, L"%#08x", (UINT)pEntry->Type); + ListView_SetItemText(hHandleListCtrl, index, 7, strText); + } + } + } +} + +TCHAR* +GetTypeName(HANDLE handle) +{ + TCHAR* strText; + UINT Type = GDI_HANDLE_GET_TYPE(handle); + + switch (Type) + { + case GDI_OBJECT_TYPE_DC: + strText = L"DC"; + break; + case GDI_OBJECT_TYPE_REGION: + strText = L"Region"; + break; + case GDI_OBJECT_TYPE_BITMAP: + strText = L"Bitmap"; + break; + case GDI_OBJECT_TYPE_PALETTE: + strText = L"Palette"; + break; + case GDI_OBJECT_TYPE_FONT: + strText = L"Font"; + break; + case GDI_OBJECT_TYPE_BRUSH: + strText = L"Brush"; + break; + case GDI_OBJECT_TYPE_EMF: + strText = L"EMF"; + break; + case GDI_OBJECT_TYPE_PEN: + strText = L"Pen"; + break; + case GDI_OBJECT_TYPE_EXTPEN: + strText = L"ExtPen"; + break; + case GDI_OBJECT_TYPE_COLORSPACE: + strText = L"ColSpace"; + break; + case GDI_OBJECT_TYPE_METADC: + strText = L"MetaDC"; + break; + case GDI_OBJECT_TYPE_METAFILE: + strText = L"Metafile"; + break; + case GDI_OBJECT_TYPE_ENHMETAFILE: + strText = L"EMF"; + break; + case GDI_OBJECT_TYPE_ENHMETADC: + strText = L"EMDC"; + break; + case GDI_OBJECT_TYPE_MEMDC: + strText = L"MemDC"; + break; + case GDI_OBJECT_TYPE_DCE: + strText = L"DCE"; + break; + case GDI_OBJECT_TYPE_PFE: + strText = L"PFE"; + break; + case GDI_OBJECT_TYPE_DONTCARE: + strText = L"anything"; + break; + case GDI_OBJECT_TYPE_SILENT: + default: + strText = L"unknown"; + break; + } + return strText; +} diff --git a/modules/rosapps/applications/devutils/gdihv/handlelist.h b/modules/rosapps/applications/devutils/gdihv/handlelist.h new file mode 100644 index 00000000000..648f0d63909 --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/handlelist.h @@ -0,0 +1,4 @@ + +VOID HandleList_Create(HWND hListCtrl); +VOID HandleList_Update(HWND hHandleListCtrl, HANDLE ProcessID); +TCHAR* GetTypeName(HANDLE handle); diff --git a/modules/rosapps/applications/devutils/gdihv/mainwnd.c b/modules/rosapps/applications/devutils/gdihv/mainwnd.c new file mode 100644 index 00000000000..70ddb059f0b --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/mainwnd.c @@ -0,0 +1,147 @@ +/* + * Gdi handle viewer + * + * mainwnd.c + * + * Copyright (C) 2007 Timo Kreuzer kreuzer reactos org> + * + * 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 "gdihv.h" + +INT g_Separator; + + +static LRESULT +MainWindow_OnSize(HWND hMainWnd) +{ + HWND hProcessListctrl, hHandleListCtrl, hProcessRefresh, hHandleRefresh; + RECT rect; + + hProcessListctrl = GetDlgItem(hMainWnd, IDC_PROCESSLIST); + hHandleListCtrl = GetDlgItem(hMainWnd, IDC_HANDLELIST); + hProcessRefresh = GetDlgItem(hMainWnd, IDC_REFRESHPROCESS); + hHandleRefresh = GetDlgItem(hMainWnd, IDC_REFRESHHANDLE); + + GetClientRect(hMainWnd, &rect); + +//g_Separator = (rect.right / 2); + MoveWindow(hProcessListctrl, 5, 5, g_Separator - 5, rect.bottom - 40, TRUE); + MoveWindow(hHandleListCtrl, g_Separator + 5, 5, rect.right - g_Separator - 5, rect.bottom - 40, TRUE); + MoveWindow(hProcessRefresh, g_Separator - 90, rect.bottom - 30, 90, 25, TRUE); + MoveWindow(hHandleRefresh, rect.right - 90, rect.bottom - 30, 90, 25, TRUE); + + return 0; +} + + +static LRESULT +MainWnd_OnNotify(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + LPNMHDR pnmh = (LPNMHDR)lParam; + + switch(pnmh->code) + { + case LVN_ITEMCHANGED: + { + LPNMLISTVIEW pnmlv = (LPNMLISTVIEW)pnmh; + if ((wParam == IDC_PROCESSLIST) + && (pnmlv->uNewState & LVIS_SELECTED) + && !(pnmlv->uOldState & LVIS_SELECTED)) + { + LV_ITEM item; + memset(&item, 0, sizeof(LV_ITEM)); + item.mask = LVIF_PARAM; + item.iItem = pnmlv->iItem; + (void)ListView_GetItem(GetDlgItem(hWnd, IDC_PROCESSLIST), &item); + HandleList_Update(GetDlgItem(hWnd, IDC_HANDLELIST), (HANDLE)item.lParam); + return TRUE; + } + break; + } + } + + return 0; +} + +INT_PTR CALLBACK +MainWindow_WndProc(HWND hMainWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + { + RECT rect; + + SendMessage(hMainWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_MAIN))); + (void)ListView_SetExtendedListViewStyle(GetDlgItem(hMainWnd, IDC_PROCESSLIST), LVS_EX_FULLROWSELECT); + (void)ListView_SetExtendedListViewStyle(GetDlgItem(hMainWnd, IDC_HANDLELIST), LVS_EX_FULLROWSELECT); + GetClientRect(hMainWnd, &rect); + g_Separator = (rect.right / 2); + HandleList_Create(GetDlgItem(hMainWnd, IDC_HANDLELIST)); + ProcessList_Create(GetDlgItem(hMainWnd, IDC_PROCESSLIST)); + MainWindow_OnSize(hMainWnd); + + break; + } + case WM_SIZE: + return MainWindow_OnSize(hMainWnd); + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + { + EndDialog(hMainWnd, IDOK); + break; + } + case IDC_REFRESHHANDLE: + { + LV_ITEM item; + HWND hProcessListCtrl = GetDlgItem(hMainWnd, IDC_PROCESSLIST); + memset(&item, 0, sizeof(LV_ITEM)); + item.mask = LVIF_PARAM; + item.iItem = ListView_GetSelectionMark(hProcessListCtrl); + (void)ListView_GetItem(hProcessListCtrl, &item); + HandleList_Update(GetDlgItem(hMainWnd, IDC_HANDLELIST), (HANDLE)item.lParam); + break; + } + case IDC_REFRESHPROCESS: + { + ProcessList_Update(GetDlgItem(hMainWnd, IDC_PROCESSLIST)); + break; + } + default: + { + return FALSE; + } + } + break; + } + + case WM_NOTIFY: + return MainWnd_OnNotify(hMainWnd, wParam, lParam); + + default: + { + return FALSE; + } + } + return TRUE; +} + diff --git a/modules/rosapps/applications/devutils/gdihv/mainwnd.h b/modules/rosapps/applications/devutils/gdihv/mainwnd.h new file mode 100644 index 00000000000..a41d4a2dcb8 --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/mainwnd.h @@ -0,0 +1,2 @@ + +INT_PTR CALLBACK MainWindow_WndProc(HWND, UINT, WPARAM, LPARAM); diff --git a/modules/rosapps/applications/devutils/gdihv/proclist.c b/modules/rosapps/applications/devutils/gdihv/proclist.c new file mode 100644 index 00000000000..e655f729169 --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/proclist.c @@ -0,0 +1,113 @@ +/* + * Gdi handle viewer + * + * proclist.c + * + * Copyright (C) 2007 Timo Kreuzer kreuzer reactos org> + * + * 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 "gdihv.h" + +VOID +ProcessList_Create(HWND hListCtrl) +{ + LVCOLUMN column; + + column.mask = LVCF_TEXT|LVCF_FMT|LVCF_WIDTH; + column.fmt = LVCFMT_LEFT; + + column.pszText = L"Process"; + column.cx = 90; + (void)ListView_InsertColumn(hListCtrl, 0, &column); + + column.pszText = L"ProcessID"; + column.cx = 90; + (void)ListView_InsertColumn(hListCtrl, 1, &column); + ProcessList_Update(hListCtrl); +} + +VOID +ProcessList_Update(HWND hListCtrl) +{ + LV_ITEM item; + DWORD ProcessIds[1024], BytesReturned; + UINT cProcesses; + HANDLE hProcess; + WCHAR strText[MAX_PATH] = L""; + INT i; + + (void)ListView_DeleteAllItems(hListCtrl); + memset(&item, 0, sizeof(LV_ITEM)); + item.mask = LVIF_TEXT|LVIF_PARAM; + item.pszText = strText; + + /* Insert "kernel" */ + item.iItem = 0; + item.lParam = 0; + item.pszText = L""; + (void)ListView_InsertItem(hListCtrl, &item); + item.pszText = strText; + wsprintf(strText, L"%#08x", 0); + ListView_SetItemText(hListCtrl, 0, 1, strText); + + /* Insert "deleted" */ + item.iItem = 1; + item.lParam = 1; + item.pszText = L""; + (void)ListView_InsertItem(hListCtrl, &item); + item.pszText = strText; + wsprintf(strText, L"%#08x", 1); + ListView_SetItemText(hListCtrl, 1, 1, strText); + + /* Insert "all" */ + item.iItem = 2; + item.lParam = 2; + item.pszText = L""; + (void)ListView_InsertItem(hListCtrl, &item); + item.pszText = strText; + wsprintf(strText, L"%#08x", 2); + ListView_SetItemText(hListCtrl, 1, 1, strText); + + if (!EnumProcesses(ProcessIds, sizeof(ProcessIds), &BytesReturned )) + { + return; + } + cProcesses = BytesReturned / sizeof(DWORD); + if (cProcesses <= 1) + { + return; + } + for (i = 1; i < cProcesses; i++) + { + wsprintf(strText, L""); + item.lParam = ProcessIds[i]; + item.iItem = ListView_GetItemCount(hListCtrl); + + hProcess = 0; + /* FIXME: HACK: ROS crashes when using OpenProcess with PROCESS_VM_READ */ + hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessIds[i]); + if (hProcess) + { + GetModuleBaseName(hProcess, NULL, (LPWSTR)strText, MAX_PATH ); + CloseHandle(hProcess); + } + (void)ListView_InsertItem(hListCtrl, &item); + + wsprintf(strText, L"%#08x", ProcessIds[i]); + ListView_SetItemText(hListCtrl, item.iItem, 1, strText); + } +} diff --git a/modules/rosapps/applications/devutils/gdihv/proclist.h b/modules/rosapps/applications/devutils/gdihv/proclist.h new file mode 100644 index 00000000000..b8702f50847 --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/proclist.h @@ -0,0 +1,3 @@ + +VOID ProcessList_Create(HWND hListCtrl); +VOID ProcessList_Update(HWND hListCtrl); diff --git a/modules/rosapps/applications/devutils/gdihv/resource.h b/modules/rosapps/applications/devutils/gdihv/resource.h new file mode 100644 index 00000000000..772d9d7f129 --- /dev/null +++ b/modules/rosapps/applications/devutils/gdihv/resource.h @@ -0,0 +1,8 @@ + +#define IDD_MAINWND 1000 +#define IDC_PROCESSLIST 1001 +#define IDC_HANDLELIST 1002 +#define IDC_REFRESHHANDLE 1010 +#define IDC_REFRESHPROCESS 1011 +#define IDI_MAIN 2000 +#define IDI_ARROW 2001 diff --git a/modules/rosapps/applications/devutils/gdihv/system.ico b/modules/rosapps/applications/devutils/gdihv/system.ico new file mode 100644 index 00000000000..2d8f3223187 Binary files /dev/null and b/modules/rosapps/applications/devutils/gdihv/system.ico differ diff --git a/modules/rosapps/applications/devutils/genguid/genguid.c b/modules/rosapps/applications/devutils/genguid/genguid.c new file mode 100644 index 00000000000..a6bbd8f18fa --- /dev/null +++ b/modules/rosapps/applications/devutils/genguid/genguid.c @@ -0,0 +1,83 @@ +/* + * genguid utility for WINE and ReactOS + * + * Copyright 2003 Jonathan Wilson + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include + +int main(int argc, char *argv[]) +{ + GUID m_guid = GUID_NULL; + int arg; + HRESULT result; + char *strfmt = ""; + if (argc < 2) { + printf("usage: %s n\n",argv[0]); + printf("n = format of output\n"); + printf("values are:\n"); + printf("1 = IMPLEMENT_OLECREATE defintion\n"); + printf("2 = DEFINE_GUID definition\n"); + printf("3 = static const GUID definition\n"); + printf("4 = registry format\n"); + printf("5 = uuidgen.exe format\n"); + return 1; + } + arg = atoi(argv[1]); + if ((arg > 5) || (arg <= 0)) { + printf("invalid argument\n"); + return 1; + } + if (CoInitialize(NULL) != S_OK) + { + printf("Unable to initialize OLE libraries\n"); + return 1; + } + result = CoCreateGuid(&m_guid); + if (result != S_OK) { + printf("Unable to create GUID\n"); + CoUninitialize(); + return 1; + } + switch (arg) { + case 1: + strfmt = "// {%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}\r\nIMPLEMENT_OLECREATE(<>, <>, \r\n0x%lx, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x);\r\n"; + break; + case 2: + strfmt = "// {%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}\r\nDEFINE_GUID(<>, \r\n0x%lx, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x);\r\n"; + break; + case 3: + strfmt = "// {%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}\r\nstatic const GUID <> = \r\n{ 0x%lx, 0x%x, 0x%x, { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x } };\r\n"; + break; + case 4: + strfmt = "{%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}\r\n"; + break; + case 5: + strfmt = "%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X\r\n"; + break; + } + printf(strfmt,m_guid.Data1,m_guid.Data2,m_guid.Data3,m_guid.Data4[0], + m_guid.Data4[1],m_guid.Data4[2],m_guid.Data4[3],m_guid.Data4[4],m_guid.Data4[5], + m_guid.Data4[6],m_guid.Data4[7],m_guid.Data1,m_guid.Data2,m_guid.Data3,m_guid.Data4[0], + m_guid.Data4[1],m_guid.Data4[2],m_guid.Data4[3],m_guid.Data4[4],m_guid.Data4[5], + m_guid.Data4[6],m_guid.Data4[7]); + CoUninitialize(); + return 0; +} + + diff --git a/modules/rosapps/applications/devutils/genguid/genguid.rbuild b/modules/rosapps/applications/devutils/genguid/genguid.rbuild new file mode 100644 index 00000000000..83b87a00cbd --- /dev/null +++ b/modules/rosapps/applications/devutils/genguid/genguid.rbuild @@ -0,0 +1,4 @@ + + ole32 + uuid + genguid.c diff --git a/modules/rosapps/applications/devutils/genguid/genguid.rc b/modules/rosapps/applications/devutils/genguid/genguid.rc new file mode 100644 index 00000000000..c27773ca379 --- /dev/null +++ b/modules/rosapps/applications/devutils/genguid/genguid.rc @@ -0,0 +1,5 @@ + +#define REACTOS_STR_FILE_DESCRIPTION "GUID Generator\0" +#define REACTOS_STR_INTERNAL_NAME "genguid\0" +#define REACTOS_STR_ORIGINAL_FILENAME "genguid.exe\0" +#include diff --git a/modules/rosapps/applications/devutils/symdump/symdump.c b/modules/rosapps/applications/devutils/symdump/symdump.c new file mode 100644 index 00000000000..bd56edd6aaa --- /dev/null +++ b/modules/rosapps/applications/devutils/symdump/symdump.c @@ -0,0 +1,991 @@ +/* + * PE symbol dumper + * + * symdump.c + * + * Copyright (c) 2008 Timo Kreuzer kreuzer reactos org> + * + * This program is released under the terms of the GNU GPL. + * + * TODO: + * - fix GDILoObjType + * - fix UDTKind1 + * - include the correct headers for some stuff + * - fix unions like LARGE_INTEGER + */ + +#include +#define _WINVER 0x501 +#include +#include +#include + +HANDLE hCurrentProcess; +BOOL g_bShowPos = 0; + +#define MAX_SYMBOL_NAME 1024 + +#define CV_CALL_NEAR_C 0x00 +#define CV_CALL_FAR_C 0x01 +#define CV_CALL_NEAR_PASCAL 0x02 +#define CV_CALL_FAR_PASCAL 0x03 +#define CV_CALL_NEAR_FAST 0x04 +#define CV_CALL_FAR_FAST 0x05 +#define CV_CALL_SKIPPED 0x06 +#define CV_CALL_NEAR_STD 0x07 +#define CV_CALL_FAR_STD 0x08 +#define CV_CALL_NEAR_SYS 0x09 +#define CV_CALL_FAR_SYS 0x0a +#define CV_CALL_THISCALL 0x0b +#define CV_CALL_MIPSCALL 0x0c +#define CV_CALL_GENERIC 0x0d +#define CV_CALL_ALPHACALL 0x0e +#define CV_CALL_PPCCALL 0x0f +#define CV_CALL_SHCALL 0x10 +#define CV_CALL_ARMCALL 0x11 +#define CV_CALL_AM33CALL 0x12 +#define CV_CALL_TRICALL 0x13 +#define CV_CALL_SH5CALL 0x14 +#define CV_CALL_M32RCALL 0x15 + +enum SymTagEnum +{ + SymTagNull, + SymTagExe, + SymTagCompiland, + SymTagCompilandDetails, + SymTagCompilandEnv, + SymTagFunction, + SymTagBlock, + SymTagData, + SymTagAnnotation, + SymTagLabel, + SymTagPublicSymbol, + SymTagUDT, + SymTagEnum, + SymTagFunctionType, + SymTagPointerType, + SymTagArrayType, + SymTagBaseType, + SymTagTypedef, + SymTagBaseClass, + SymTagFriend, + SymTagFunctionArgType, + SymTagFuncDebugStart, + SymTagFuncDebugEnd, + SymTagUsingNamespace, + SymTagVTableShape, + SymTagVTable, + SymTagCustom, + SymTagThunk, + SymTagCustomType, + SymTagManagedType, + SymTagDimension, + SymTagMax +}; + +enum +{ + UDTKind_Struct = 0, + UDTKind_Class = 1, /* ? */ + UDTKind_Union = 2, +}; + +enum BasicType +{ + btNoType = 0, + btVoid = 1, + btChar = 2, + btWChar = 3, + btInt = 6, + btUInt = 7, + btFloat = 8, + btBCD = 9, + btBool = 10, + btLong = 13, + btULong = 14, + btCurrency = 25, + btDate = 26, + btVariant = 27, + btComplex = 28, + btBit = 29, + btBSTR = 30, + btHresult = 31 +}; + +typedef struct +{ + HANDLE hProcess; + DWORD64 dwModuleBase; + LPSTR pszSymbolName; + BOOL bType; +} ENUMINFO, *PENUMINFO; + +VOID DumpType(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers); + +CHAR *SymTagString[] = +{ + "SymTagNull", + "SymTagExe", + "SymTagCompiland", + "SymTagCompilandDetails", + "SymTagCompilandEnv", + "SymTagFunction", + "SymTagBlock", + "SymTagData", + "SymTagAnnotation", + "SymTagLabel", + "SymTagPublicSymbol", + "SymTagUDT", + "SymTagEnum", + "SymTagFunctionType", + "SymTagPointerType", + "SymTagArrayType", + "SymTagBaseType", + "SymTagTypedef", + "SymTagBaseClass", + "SymTagFriend", + "SymTagFunctionArgType", + "SymTagFuncDebugStart", + "SymTagFuncDebugEnd", + "SymTagUsingNamespace", + "SymTagVTableShape", + "SymTagVTable", + "SymTagCustom", + "SymTagThunk", + "SymTagCustomType", + "SymTagManagedType", + "SymTagDimension", + "SymTagMax" +}; + +void +IndentPrint(INT ind) +{ + INT i; + for (i = 0; i < ind; i++) + { + printf(" "); + } +} + +#define printfi \ + IndentPrint(indent); printf + +VOID +PrintUsage() +{ + printf("Syntax:\n\n"); + printf("dumpsym [-sp=] [-p] []\n\n"); + printf(" The PE file you want to dump the symbols of\n"); + printf("-sp= Path to your symbol files.\n"); + printf(" Default is MS symbol server.\n"); + printf("-p Enable struct positions.\n"); + printf(" A name of a Symbol, you want to dump\n"); + printf(" Default is all symbols.\n"); + printf("\n"); +} + +BOOL InitDbgHelp(HANDLE hProcess, LPSTR pszSymbolPath) +{ + if (!SymInitialize(hProcess, 0, FALSE)) + return FALSE; + + SymSetOptions(SymGetOptions() | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS); + SymSetOptions(SymGetOptions() & (~SYMOPT_DEFERRED_LOADS)); + SymSetSearchPath(hProcess, pszSymbolPath); + return TRUE; +} + +VOID +DumpBaseType(DWORD dwTypeIndex, PENUMINFO pei, INT indent) +{ + ULONG64 ulSize; + DWORD dwBaseType; + + SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_LENGTH, &ulSize); + SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_BASETYPE, &dwBaseType); + + switch (dwBaseType) + { + case btVoid: + printfi("VOID"); + return; + case btChar: + printfi("CHAR"); + return; + case btWChar: + printfi("WCHAR"); + return; + case btInt: + switch (ulSize) + { + case 1: + printfi("CHAR"); + return; + case 2: + printfi("SHORT"); + return; + case 4: + printfi("INT"); + return; + case 8: + printfi("INT64"); + return; + default: + printfi("INT%ld", (ULONG)ulSize * 8); + return; + } + case btUInt: + switch (ulSize) + { + case 1: + printfi("UCHAR"); + return; + case 2: + printfi("USHORT"); + return; + case 4: + printfi("UINT"); + return; + case 8: + printfi("UINT64"); + return; + default: + printfi("UINT%ld", (ULONG)ulSize * 8); + return; + } + case btFloat: + switch (ulSize) + { + case 4: + printfi("FLOAT"); + return; + case 8: + printfi("DOUBLE"); + return; + default: + printfi("FLOAT%ld", (ULONG)ulSize * 8); + return; + } + case btBCD: + printfi("BCD%ld", (ULONG)ulSize * 8); + return; + case btBool: + switch (ulSize) + { + case 1: + printfi("BOOLEAN"); + return; + case 4: + printfi("BOOL"); + return; + default: + printfi("BOOL%ld", (ULONG)ulSize * 8); + return; + } + case btLong: + switch (ulSize) + { + case 1: + printfi("CHAR"); + return; + case 2: + printfi("SHORT"); + return; + case 4: + printfi("LONG"); + return; + case 8: + printfi("LONGLONG"); + return; + default: + printfi("LONG%ld", (ULONG)ulSize * 8); + return; + } + case btULong: + switch (ulSize) + { + case 1: + printfi("UCHAR"); + return; + case 2: + printfi("USHORT"); + return; + case 4: + printfi("ULONG"); + return; + case 8: + printfi("ULONGLONG"); + return; + default: + printfi("ULONG%ld", (ULONG)ulSize * 8); + return; + } + case btCurrency: + case btDate: + case btVariant: + case btComplex: + case btBit: + case btBSTR: + printfi("UNSUP_%ld_%ld", dwBaseType, (ULONG)ulSize); + return; + case btHresult: + if (ulSize == 4) + { + printfi("HRESULT"); + return; + } + printfi("HRESULT%ld", (ULONG)ulSize); + return; + } + + printfi("UNKNBASETYPE"); +} + +VOID +DumpArray(DWORD dwTypeIndex, PENUMINFO pei, INT indent) +{ + DWORD dwTypeId; + + SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_TYPE, &dwTypeId); + DumpType(dwTypeId, pei, indent, FALSE); +} + +VOID +DumpPointer(DWORD dwTypeIndex, PENUMINFO pei, INT indent) +{ + DWORD dwRefTypeId; + DWORD dwTag = 0; + ULONG64 ulSize; + DWORD dwBaseType; + + SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_TYPE, &dwRefTypeId); + SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwRefTypeId, TI_GET_BASETYPE, &dwBaseType); + SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwRefTypeId, TI_GET_LENGTH, &ulSize); + SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwRefTypeId, TI_GET_SYMTAG, &dwTag); + + if (dwTag == SymTagFunctionType) + { + printfi("PPROC"); + return; + } + + switch (dwBaseType) + { + case btVoid: + switch (ulSize) + { + case 0: + printfi("PVOID"); + return; + } + break; + + case btChar: + switch (ulSize) + { + case 1: + printfi("PCHAR"); + return; + } + break; + case btWChar: + switch (ulSize) + { + case 2: + printfi("PWCHAR"); + return; + } + break; + case btInt: + switch (ulSize) + { + case 4: + printfi("PINT"); + return; + } + break; + case btUInt: + switch (ulSize) + { + case 4: + printfi("PUINT"); + return; + } + break; + case btFloat: + switch (ulSize) + { + case 4: + printfi("PFLOAT"); + return; + case 8: + printfi("PDOUBLE"); + return; + } + break; + case btBCD: + break; + case btBool: + switch (ulSize) + { + case 1: + printfi("PBOOLEAN"); + return; + case 4: + printfi("PBOOL"); + return; + } + break; + case btLong: + switch (ulSize) + { + case 4: + printfi("PLONG"); + return; + case 8: + printfi("PLONGLONG"); + return; + } + break; + case btULong: + switch (ulSize) + { + case 4: + printfi("PULONG"); + return; + case 8: + printfi("PULONGLONG"); + return; + } + break; + case btCurrency: + case btDate: + case btVariant: + case btComplex: + case btBit: + case btBSTR: + case btHresult: + break; + } + + DumpType(dwRefTypeId, pei, indent, FALSE); + printf("*"); +} + +VOID +PrintVariant(VARIANT *v) +{ +// printf("", v->n1.n2.vt); + switch (v->n1.n2.vt) + { + case VT_I1: + printf("%d", (INT)v->n1.n2.n3.cVal); + break; + case VT_UI1: + printf("0x%x", (UINT)v->n1.n2.n3.cVal); + break; + case VT_I2: + printf("%d", (UINT)v->n1.n2.n3.iVal); + break; + case VT_UI2: + printf("0x%x", (UINT)v->n1.n2.n3.iVal); + break; + case VT_INT: + case VT_I4: + printf("%d", (UINT)v->n1.n2.n3.lVal); + break; + case VT_UINT: + case VT_UI4: + printf("0x%x", (UINT)v->n1.n2.n3.lVal); + break; + } +} + +BOOL +IsUnnamed(WCHAR *pszName) +{ + if ((StrStrW(pszName, L"__unnamed") != NULL) || + (StrStrW(pszName, L"") != NULL)) + { + return TRUE; + } + return FALSE; +} + +VOID +DumpEnum(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers) +{ + DWORD64 dwModuleBase = pei->dwModuleBase; + HANDLE hProcess = pei->hProcess; + INT i; + DWORD dwUDTKind; + WCHAR *pszName, *pszNameX; + struct + { + TI_FINDCHILDREN_PARAMS tfp; + ULONG TypeIds[200]; + } tfpex; + VARIANT v; + + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_SYMNAME, &pszNameX); + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_UDTKIND, &dwUDTKind); + pszName = pszNameX; + if (IsUnnamed(pszName)) + { + if (bMembers) + { + LocalFree(pszNameX); + return; + } + bMembers = TRUE; + pszName = L""; + } + printfi("enum %ls", pszName); + LocalFree(pszNameX); + + if (bMembers) + { + printf(" /* %03x */", 0); + printfi("\n{\n"); + + /* Get the children */ + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &tfpex.tfp.Count); + + tfpex.tfp.Start = 0; + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_FINDCHILDREN, &tfpex.tfp); + + for (i = 0; i < tfpex.tfp.Count; i++) + { + pszName = L""; + + SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_SYMNAME, &pszName); + SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_VALUE, &v); + + indent++; + printfi("%ls = ", pszName); + PrintVariant(&v); + printf(",\n"); + indent--; + + LocalFree(pszName); + } + printfi("}"); + } +} + +VOID +DumpUDT(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers) +{ + DWORD64 dwModuleBase = pei->dwModuleBase; + HANDLE hProcess = pei->hProcess; + INT i; + DWORD dwUDTKind; + WCHAR *pszName, *pszNameX; + struct + { + TI_FINDCHILDREN_PARAMS tfp; + ULONG TypeIds[200]; + } tfpex; + + DWORD dwDataKind; + DWORD dwTypeId; + DWORD dwCount; + WCHAR *pszTypeName; + + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_SYMNAME, &pszNameX); + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_UDTKIND, &dwUDTKind); + + pszName = pszNameX; + if (IsUnnamed(pszName)) + { + if (bMembers) + { + LocalFree(pszNameX); + return; + } + bMembers = TRUE; + pszName = L""; + } + if (dwUDTKind == UDTKind_Struct) + { + printfi("struct %ls", pszName); + } + else if (dwUDTKind == UDTKind_Union) + { + printfi("union %ls", pszName); + } + else + { + printfi("UTDKind%ld %ls", dwUDTKind, pszName); + } + LocalFree(pszNameX); + + if (bMembers) + { + ULONG64 ulLength; + + printf("\n"); + printfi("{\n"); + + /* Get the children */ + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &tfpex.tfp.Count); + + tfpex.tfp.Start = 0; + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_FINDCHILDREN, &tfpex.tfp); + + for (i = 0; i < tfpex.tfp.Count; i++) + { + DWORD dwChildTag; + DWORD dwOffset; + + pszName = L""; + pszTypeName = L""; + + SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_SYMNAME, &pszName); + SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_DATAKIND, &dwDataKind); + SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_TYPE, &dwTypeId); + SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_OFFSET, &dwOffset); + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeId, TI_GET_SYMTAG, &dwChildTag); + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeId, TI_GET_LENGTH, &ulLength); + + printf(" /* %03lx */", dwOffset); + DumpType(dwTypeId, pei, indent + 1, FALSE); + printf(" %ls", pszName); + if (dwChildTag == SymTagArrayType) + { + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeId, TI_GET_COUNT, &dwCount); + printf("[%ld]", dwCount); + } + else + { + DWORD dwCurrentBitPos; + DWORD dwNextBitPos; + + SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_BITPOSITION, &dwCurrentBitPos); + if (i < tfpex.tfp.Count - 1) + { + SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i+1], TI_GET_BITPOSITION, &dwNextBitPos); + } + else + { + dwNextBitPos = 0; + } + + if (dwNextBitPos == 0 && dwCurrentBitPos != 0) + { + dwNextBitPos = ulLength * 8; + } + + if (dwNextBitPos != dwCurrentBitPos) + { + printf(":%ld", dwNextBitPos - dwCurrentBitPos); + } + } + printf(";\n"); + LocalFree(pszName); + } + printfi("}"); + } +} + +VOID +DumpType(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers) +{ + HANDLE hProcess = pei->hProcess; + DWORD64 dwModuleBase = pei->dwModuleBase; + DWORD dwTag = 0; + + SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_SYMTAG, &dwTag); + + switch (dwTag) + { + case SymTagEnum: + DumpEnum(dwTypeIndex, pei, indent, bMembers); + break; + + case SymTagUDT: + DumpUDT(dwTypeIndex, pei, indent, bMembers); + break; + + case SymTagPointerType: + DumpPointer(dwTypeIndex, pei, indent); + break; + + case SymTagBaseType: + DumpBaseType(dwTypeIndex, pei, indent); + break; + + case SymTagArrayType: + DumpArray(dwTypeIndex, pei, indent); + break; + + case SymTagFunctionType: + printfi("function"); + break; + + default: + printfi("typeTag%ld", dwTag); + break; + } + +} + + +VOID +DumpCV(DWORD dwTypeIndex, PENUMINFO pei) +{ + DWORD cv = 0x20; + + SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_CALLING_CONVENTION, &cv); + switch (cv) + { + case CV_CALL_NEAR_C: + printf("CDECL"); + return; + case CV_CALL_FAR_C: + printf("FAR CDECL"); + return; + case CV_CALL_NEAR_PASCAL: + printf("PASCAL"); + return; + case CV_CALL_FAR_PASCAL: + printf("FAR PASCAL"); + return; + case CV_CALL_NEAR_FAST: + printf("FASTCALL"); + return; + case CV_CALL_FAR_FAST: + printf("FAR FASTCALL"); + return; + case CV_CALL_SKIPPED: + printf("SKIPPED"); + return; + case CV_CALL_NEAR_STD: + printf("STDCALL"); + return; + case CV_CALL_FAR_STD: + printf("FAR STDCALL"); + return; + case CV_CALL_NEAR_SYS: + case CV_CALL_FAR_SYS: + case CV_CALL_THISCALL: + printf("THISCALL"); + return; + case CV_CALL_MIPSCALL: + printf("MIPSCALL"); + return; + case CV_CALL_GENERIC: + case CV_CALL_ALPHACALL: + case CV_CALL_PPCCALL: + case CV_CALL_SHCALL: + case CV_CALL_ARMCALL: + case CV_CALL_AM33CALL: + case CV_CALL_TRICALL: + case CV_CALL_SH5CALL: + case CV_CALL_M32RCALL: + default: + printf("UNKNOWNCV"); + } + +} + +BOOL CALLBACK +EnumParamsProc( + PSYMBOL_INFO pSymInfo, + ULONG SymbolSize, + PVOID UserContext) +{ + printf("x, "); + (*(INT*)UserContext)++; + return TRUE; +} + +VOID +DumpParams(PSYMBOL_INFO pSymInfo, PENUMINFO pei) +{ + IMAGEHLP_STACK_FRAME sf; + BOOL bRet; + INT NumLocals = 0; // the number of local variables found + + sf.InstructionOffset = pSymInfo->Address; + + printf("("); + bRet = SymSetContext(pei->hProcess, &sf, 0); + + if (!bRet) + { + printf("\nError: SymSetContext() failed. Error code: %lu \n", GetLastError()); + return; + } + printf("Address == 0x%x, ReturnOffset = 0x%x", (UINT)pSymInfo->Address, (UINT)sf.ReturnOffset); + + // Enumerate local variables + + bRet = SymEnumSymbols(pei->hProcess, 0, 0, EnumParamsProc, &NumLocals); + + if (!bRet) + { +// printf("Error: SymEnumSymbols() failed. Error code: %lu \n", GetLastError()); + printf("?)"); + return; + } + + if (NumLocals == 0) + { +// printf("The function does not have parameters and local variables.\n"); + printf("void)"); + } + + printf(")"); +} + +VOID +DumpFunction(PSYMBOL_INFO pSymInfo, PENUMINFO pei) +{ + DWORD dwTypeId; + +//printf("Name=%s, Size=%ld, TypeId=0x%ld\n", pSymInfo->Name, pSymInfo->Size, pSymInfo->TypeIndex); + + SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, pSymInfo->TypeIndex, TI_GET_TYPEID, &dwTypeId); + +// DumpCV(pSymInfo->TypeIndex, pei); +// printf("\n"); +// DumpType(pSymInfo->TypeIndex, pei, 0, FALSE); + printf("%s", pSymInfo->Name); + DumpParams(pSymInfo, pei); +} + +BOOL CALLBACK +EnumSymbolsProc( + PSYMBOL_INFO pSymInfo, + ULONG SymbolSize, + PVOID UserContext) +{ + PENUMINFO pei = (PENUMINFO)UserContext; + + if ((pei->pszSymbolName == NULL) || + (strstr(pSymInfo->Name, pei->pszSymbolName) != 0)) + { + if (pei->bType) + { + DumpType(pSymInfo->TypeIndex, pei, 0, TRUE); + printf("\n\n"); + } + else + { +#if defined(__GNUC__) && \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400) + printf("Symbol: %s, TypeIndex=%ld, Flags=%lx, Value=0x%llx\n", +#else + printf("Symbol: %s, TypeIndex=%ld, Flags=%lx, Value=0x%I64x\n", +#endif + pSymInfo->Name, pSymInfo->TypeIndex, pSymInfo->Flags, pSymInfo->Value); + //if (pSymInfo->Flags & SYMFLAG_FUNCTION) + { +// DumpFunction(pSymInfo, pei); +// printf("\n\n"); + } + } + } + return TRUE; +} + +int main(int argc, char* argv[]) +{ + HANDLE hProcess; + CHAR szFullFileName[MAX_PATH+1]; + DWORD64 dwModuleBase; + BOOL bRet; + LPSTR pszSymbolPath, pszSymbolName; + INT i; + ENUMINFO enuminfo; + + printf("PE symbol dumper\n"); + printf("Copyright (c) Timo Kreuzer 2008\n\n"); + + if (argc < 2) + { + PrintUsage(); + return 0; + } + + /* Get the full path name of the PE file from first argument */ + GetFullPathName(argv[1], MAX_PATH, szFullFileName, NULL); + + /* Default Symbol Name (all) */ + pszSymbolName = NULL; + + /* Default to ms symbol server */ + pszSymbolPath = "srv**symbols*http://msdl.microsoft.com/download/symbols"; + + /* Check other command line arguments */ + for (i = 2; i < argc; i++) + { + if (*argv[i] == '-') + { + if (strncmp(argv[i], "-sp=", 4) == 0) + { + pszSymbolPath = argv[i] + 4; + } + else if (strcmp(argv[i], "-p") == 0) + { + g_bShowPos = 1; + } + else + { + printf("Invalid argument: %s\n", argv[i]); + PrintUsage(); + return 0; + } + } + else + { + pszSymbolName = argv[i]; + } + } + + hProcess = GetCurrentProcess(); + + printf("Trying to get symbols from: %s\n", pszSymbolPath); + + if (!InitDbgHelp(hProcess, pszSymbolPath)) + { + printf("SymInitialize() failed\n"); + goto cleanup; + } + + printf("Loading symbols for %s, please wait...\n", szFullFileName); + dwModuleBase = SymLoadModule64(hProcess, 0, szFullFileName, 0, 0, 0); + if (dwModuleBase == 0) + { + printf("SymLoadModule64() failed: %ld\n", GetLastError()); + goto cleanup; + } + + printf("\nSymbols:\n"); + enuminfo.hProcess = hProcess; + enuminfo.pszSymbolName = pszSymbolName; + enuminfo.bType = FALSE; + SetLastError(ERROR_SUCCESS); + bRet = SymEnumSymbols(hProcess, dwModuleBase, NULL, EnumSymbolsProc, &enuminfo); + if (!bRet) + { + printf("SymEnumSymbols failed: %ld\n", GetLastError()); + } + + printf("\nTypes:\n"); + enuminfo.bType = TRUE; + enuminfo.dwModuleBase = dwModuleBase; + SetLastError(ERROR_SUCCESS); + bRet = SymEnumTypes(hProcess, dwModuleBase, EnumSymbolsProc, &enuminfo); + if (!bRet) + { + printf("SymEnumTypes failed: %ld\n", GetLastError()); + } + +cleanup: + + return 0; +} diff --git a/modules/rosapps/applications/devutils/symdump/symdump.rbuild b/modules/rosapps/applications/devutils/symdump/symdump.rbuild new file mode 100644 index 00000000000..3d5184aae50 --- /dev/null +++ b/modules/rosapps/applications/devutils/symdump/symdump.rbuild @@ -0,0 +1,6 @@ + + . + dbghelp + shlwapi + symdump.c + diff --git a/modules/rosapps/applications/devutils/syscalldump/syscalldump.c b/modules/rosapps/applications/devutils/syscalldump/syscalldump.c new file mode 100644 index 00000000000..0407e685cbe --- /dev/null +++ b/modules/rosapps/applications/devutils/syscalldump/syscalldump.c @@ -0,0 +1,234 @@ +#include +#include +#include +#define _WINVER 0x501 +#include +#include +#include + +HANDLE hCurrentProcess; +BOOL bX64; + +#define MAX_SYMBOL_NAME 1024 + +BOOL InitDbgHelp(HANDLE hProcess) +{ + if (!SymInitialize(hProcess, 0, FALSE)) + return FALSE; + + SymSetOptions(SymGetOptions() | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS); + SymSetOptions(SymGetOptions() & (~SYMOPT_DEFERRED_LOADS)); + SymSetSearchPath(hProcess, "srv**symbols*http://msdl.microsoft.com/download/symbols"); + return TRUE; +} + +PVOID +ImageSymToVa(HANDLE hProcess, PSYMBOL_INFO pSym, PBYTE pModule, PCSTR Name) +{ + PIMAGE_NT_HEADERS NtHeaders; + PVOID p; + + pSym->SizeOfStruct = sizeof(SYMBOL_INFO); + pSym->MaxNameLen = MAX_SYMBOL_NAME-1; + + if (!SymFromName(hProcess, Name, pSym)) + { + printf("SymGetSymFromName64() failed: %ld\n", GetLastError()); + return 0; + } +#if defined(__GNUC__) && \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400) + printf("looking up adress for %s: 0x%llx\n", Name, pSym->Address); +#else + printf("looking up adress for %s: 0x%I64x\n", Name, pSym->Address); +#endif + + NtHeaders = ImageNtHeader(pModule); + p = ImageRvaToVa(NtHeaders, pModule, pSym->Address - pSym->ModBase, NULL); + + return p; +} + +BOOL CALLBACK EnumSymbolsProc( + PSYMBOL_INFO pSymInfo, + ULONG SymbolSize, + PVOID UserContext) +{ + if ((UINT)UserContext == -1) + { + printf("%s ", pSymInfo->Name); + } + else + { + if (!bX64) + { + printf("%s@%d ", pSymInfo->Name, (UINT)UserContext); + } + else + { + printf("%s <+ %d> ", pSymInfo->Name, (UINT)UserContext); + } + } + return TRUE; +} + +int main(int argc, char* argv[]) +{ + HANDLE hProcess; + CHAR szModuleFileName[MAX_PATH+1]; + DWORD64 dwModuleBase; + HANDLE hFile = 0, hMap = 0; + PBYTE pModule = NULL; + UINT i; + PVOID pW32pServiceTable, pW32pServiceLimit; + PBYTE pW32pArgumentTable; + PVOID pfnSimpleCall; + DWORD dwServiceLimit; + + struct + { + SYMBOL_INFO Symbol; + CHAR Name[MAX_SYMBOL_NAME]; + } Sym; + + printf("Win32k Syscall dumper\n"); + printf("Copyright (c) Timo Kreuzer 2007-08\n"); + + hProcess = GetCurrentProcess(); + + // try current dir + GetCurrentDirectory(MAX_PATH, szModuleFileName); + strcat(szModuleFileName, "\\win32k.sys"); + hFile = CreateFile(szModuleFileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + goto cont; + } + + // try system dir + GetSystemDirectory(szModuleFileName, MAX_PATH); + strcat(szModuleFileName, "\\win32k.sys"); + hFile = CreateFile(szModuleFileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + printf("CreateFile() failed: %ld!\n", GetLastError()); + goto cleanup; + } + +cont: + printf("Trying to get syscalls from: %s\n", szModuleFileName); + + if (!InitDbgHelp(hProcess)) + { + printf("SymInitialize() failed\n"); + goto cleanup; + } + + printf("Loading symbols for %s, please wait...\n", szModuleFileName); + dwModuleBase = SymLoadModule64(hProcess, 0, szModuleFileName, 0, 0, 0); + if (dwModuleBase == 0) + { + printf("SymLoadModule64() failed: %ld\n", GetLastError()); + goto cleanup; + } + + hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (!hMap) + { + printf("CreateFileMapping() failed: %ld\n", GetLastError()); + goto cleanup; + } + + pModule = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); + if(!pModule) + { + printf("MapViewOfFile() failed: %ld\n", GetLastError()); + goto cleanup; + } + + bX64 = (ImageNtHeader(pModule)->FileHeader.Machine != IMAGE_FILE_MACHINE_I386); + + pW32pServiceTable = ImageSymToVa(hProcess, &Sym.Symbol, pModule, "W32pServiceTable"); + pW32pServiceLimit = ImageSymToVa(hProcess, &Sym.Symbol, pModule, "W32pServiceLimit"); + pW32pArgumentTable = ImageSymToVa(hProcess, &Sym.Symbol, pModule, "W32pArgumentTable"); +// printf("pW32pServiceTable = %p\n", pW32pServiceTable); +// printf("pW32pServiceLimit = %p\n", pW32pServiceLimit); +// printf("pW32pArgumentTable = %p\n", pW32pArgumentTable); + + if (!pW32pServiceTable || !pW32pServiceLimit || !pW32pArgumentTable) + { + printf("Couldn't find adress!\n"); + goto cleanup; + } + + dwServiceLimit = *((DWORD*)pW32pServiceLimit); + + if (!bX64) + { + DWORD *pdwEntries32 = (DWORD*)pW32pServiceTable; + + for (i = 0; i < dwServiceLimit; i++) + { + printf("0x%x:", i+0x1000); + SymEnumSymbolsForAddr(hProcess, (DWORD64)pdwEntries32[i], EnumSymbolsProc, (PVOID)(DWORD)pW32pArgumentTable[i]); + printf("\n"); + } + } + else + { + DWORD64 *pdwEntries64 = (DWORD64*)pW32pServiceTable; + + for (i = 0; i < dwServiceLimit; i++) + { + printf("0x%x:", i+0x1000); + SymEnumSymbolsForAddr(hProcess, (DWORD64)pdwEntries64[i], EnumSymbolsProc, (PVOID)(DWORD)pW32pArgumentTable[i]); + printf("\n"); + } + } + + /* Dump apfnSimpleCall */ + printf("\nDumping apfnSimpleCall:\n"); + pfnSimpleCall = (PVOID*)ImageSymToVa(hProcess, &Sym.Symbol, pModule, "apfnSimpleCall"); + i = 0; + + if (bX64) + { + DWORD64 *pfnSC64 = (DWORD64*)pfnSimpleCall; + while (pfnSC64[i] != 0) + { + printf("0x%x:", i); + SymEnumSymbolsForAddr(hProcess, (DWORD64)pfnSC64[i], EnumSymbolsProc, (PVOID)-1); + printf("\n"); + i++; + } + } + else + { + DWORD *pfnSC32 = (DWORD*)pfnSimpleCall; + while (pfnSC32[i] != 0) + { + printf("0x%x:", i); + SymEnumSymbolsForAddr(hProcess, (DWORD64)pfnSC32[i], EnumSymbolsProc, (PVOID)-1); + printf("\n"); + i++; + } + } + +cleanup: + if (pModule) + { + UnmapViewOfFile(pModule); + } + if (hMap) + { + CloseHandle(hMap); + } + if (hFile) + { + CloseHandle(hFile); + } + + return 0; +} diff --git a/modules/rosapps/applications/devutils/syscalldump/syscalldump.rbuild b/modules/rosapps/applications/devutils/syscalldump/syscalldump.rbuild new file mode 100644 index 00000000000..ee2a2600527 --- /dev/null +++ b/modules/rosapps/applications/devutils/syscalldump/syscalldump.rbuild @@ -0,0 +1,5 @@ + + . + dbghelp + syscalldump.c + diff --git a/modules/rosapps/applications/devutils/vgafontedit/CMakeLists.txt b/modules/rosapps/applications/devutils/vgafontedit/CMakeLists.txt new file mode 100644 index 00000000000..d89ae7aa61c --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/CMakeLists.txt @@ -0,0 +1,17 @@ + +list(APPEND SOURCE + aboutdlg.c + editglyphdlg.c + fontboxeswnd.c + fontwnd.c + main.c + mainwnd.c + misc.c + opensave.c + vgafontedit.rc) + +add_pch(vgafontedit precomp.h) +add_executable(vgafontedit ${SOURCE}) +set_module_type(vgafontedit win32gui UNICODE) +add_importlibs(vgafontedit user32 gdi32 comdlg32 msvcrt kernel32) +add_cd_file(TARGET vgafontedit DESTINATION reactos/system32 FOR all) diff --git a/modules/rosapps/applications/devutils/vgafontedit/aboutdlg.c b/modules/rosapps/applications/devutils/vgafontedit/aboutdlg.c new file mode 100644 index 00000000000..a1247a5c68f --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/aboutdlg.c @@ -0,0 +1,31 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/aboutdlg.c + * PURPOSE: About dialog + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "precomp.h" + +INT_PTR CALLBACK +AboutDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + + switch(uMsg) + { + case WM_COMMAND: + if( LOWORD(wParam) == IDCANCEL ) + { + EndDialog(hwnd, 0); + return TRUE; + } + break; + + case WM_INITDIALOG: + return TRUE; + } + + return FALSE; +} diff --git a/modules/rosapps/applications/devutils/vgafontedit/customwndclasses.h b/modules/rosapps/applications/devutils/vgafontedit/customwndclasses.h new file mode 100644 index 00000000000..01f1dc75be9 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/customwndclasses.h @@ -0,0 +1,15 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/customwndclasses.h + * PURPOSE: Header for custom defined window classes (needed by "precomp.h" and the resource files) + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#ifndef __CUSTOMWNDCLASSES_H +#define __CUSTOMWNDCLASSES_H + +#define EDIT_GLYPH_EDIT_CLASSW L"VGAFontEditEditGlyphEditClass" +#define EDIT_GLYPH_PREVIEW_CLASSW L"VGAFontEditEditGlyphPreviewClass" + +#endif diff --git a/modules/rosapps/applications/devutils/vgafontedit/editglyphdlg.c b/modules/rosapps/applications/devutils/vgafontedit/editglyphdlg.c new file mode 100644 index 00000000000..acf50455516 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/editglyphdlg.c @@ -0,0 +1,307 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/editglyphdlg.c + * PURPOSE: Dialog for editing a glyph + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "precomp.h" + +static VOID +AddToolboxButton(IN HWND hToolbar, IN INT iBitmap, IN INT idCommand, IN BYTE fsState) +{ + TBBUTTON tbb = {0,}; + + tbb.fsState = fsState; + tbb.fsStyle = BTNS_CHECKGROUP; + tbb.iBitmap = iBitmap; + tbb.idCommand = idCommand; + + SendMessageW( hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)&tbb ); +} + +static VOID +InitToolbox(IN PEDIT_GLYPH_INFO Info) +{ + HWND hToolbar; + INT iBitmap; + TBADDBITMAP tbab; + + hToolbar = GetDlgItem(Info->hSelf, IDC_EDIT_GLYPH_TOOLBOX); + + // Identify the used Common Controls version + SendMessageW(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + + // Set the button size to 24x24 + SendMessageW( hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(24, 24) ); + SendMessageW( hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(24, 24) ); + + // Add the Toolbox bitmaps + tbab.hInst = hInstance; + tbab.nID = IDB_EDIT_GLYPH_TOOLBOX; + iBitmap = (INT)SendMessageW(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab); + + AddToolboxButton(hToolbar, iBitmap + TOOLBOX_PEN, ID_TOOLBOX_PEN, TBSTATE_ENABLED | TBSTATE_CHECKED); +} + +static VOID +GetBitRect(IN PEDIT_GLYPH_INFO Info, IN UINT uRow, IN UINT uColumn, OUT LPRECT BitRect) +{ + BitRect->left = uColumn * Info->lEditSpacing + 1; + BitRect->top = uRow * Info->lEditSpacing + 1; + BitRect->right = BitRect->left + Info->lEditSpacing - 1; + BitRect->bottom = BitRect->top + Info->lEditSpacing - 1; +} + +static VOID +SetPixelBit(IN PEDIT_GLYPH_INFO Info, IN UINT uRow, IN UINT uColumn, IN BOOL uBit) +{ + // Set the bit in the bitfield + if(uBit) + Info->CharacterBits[uRow] |= 1 << (7 - uColumn); + else + Info->CharacterBits[uRow] &= ~( 1 << (7 - uColumn) ); + + // Redraw everything + InvalidateRect(Info->hEdit, NULL, FALSE); + InvalidateRect(Info->hPreview, NULL, FALSE); +} + +static BOOL +EditGlyphCommand(IN INT idCommand, IN PEDIT_GLYPH_INFO Info) +{ + switch(idCommand) + { + case IDOK: + { + RECT rect; + UINT uColumn; + UINT uRow; + + RtlCopyMemory( Info->FontWndInfo->Font->Bits + Info->uCharacter * 8, Info->CharacterBits, sizeof(Info->CharacterBits) ); + + GetCharacterPosition(Info->uCharacter, &uRow, &uColumn); + GetCharacterRect(uRow, uColumn, &rect); + InvalidateRect(Info->FontWndInfo->hFontBoxesWnd, &rect, FALSE); + + Info->FontWndInfo->OpenInfo->bModified = TRUE; + + // Fall through + } + + // This is the equivalent of WM_DESTROY for dialogs + case IDCANCEL: + EndDialog(Info->hSelf, 0); + + // Remove the window from the linked list + if(Info->PrevEditGlyphWnd) + Info->PrevEditGlyphWnd->NextEditGlyphWnd = Info->NextEditGlyphWnd; + else + Info->FontWndInfo->FirstEditGlyphWnd = Info->NextEditGlyphWnd; + + if(Info->NextEditGlyphWnd) + Info->NextEditGlyphWnd->PrevEditGlyphWnd = Info->PrevEditGlyphWnd; + else + Info->FontWndInfo->LastEditGlyphWnd = Info->PrevEditGlyphWnd; + + SetWindowLongW(Info->hSelf, GWLP_USERDATA, 0); + SetWindowLongW(Info->hEdit, GWLP_USERDATA, 0); + SetWindowLongW(Info->hPreview, GWLP_USERDATA, 0 ); + + HeapFree(hProcessHeap, 0, Info); + return TRUE; + } + + return FALSE; +} + +INT_PTR CALLBACK +EditGlyphDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PEDIT_GLYPH_INFO Info; + + Info = (PEDIT_GLYPH_INFO) GetWindowLongW(hwnd, GWLP_USERDATA); + + if(Info || uMsg == WM_INITDIALOG) + { + switch(uMsg) + { + case WM_COMMAND: + return EditGlyphCommand( LOWORD(wParam), Info ); + + case WM_INITDIALOG: + Info = (PEDIT_GLYPH_INFO) lParam; + Info->hSelf = hwnd; + Info->hEdit = GetDlgItem(hwnd, IDC_EDIT_GLYPH_EDIT); + Info->hPreview = GetDlgItem(hwnd, IDC_EDIT_GLYPH_PREVIEW); + + SetWindowLongW(hwnd, GWLP_USERDATA, (LONG)Info); + SetWindowLongW(Info->hEdit, GWLP_USERDATA, (LONG)Info); + SetWindowLongW(Info->hPreview, GWLP_USERDATA, (LONG)Info); + + InitToolbox(Info); + + return TRUE; + } + } + + return FALSE; +} + +static LRESULT CALLBACK +EditGlyphEditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PEDIT_GLYPH_INFO Info; + + Info = (PEDIT_GLYPH_INFO) GetWindowLongW(hwnd, GWLP_USERDATA); + + if(Info) + { + switch(uMsg) + { + case WM_CREATE: + return 0; + + case WM_LBUTTONDOWN: + SetPixelBit(Info, GET_Y_LPARAM(lParam) / Info->lEditSpacing, GET_X_LPARAM(lParam) / Info->lEditSpacing, 1); + return 0; + + case WM_RBUTTONDOWN: + SetPixelBit(Info, GET_Y_LPARAM(lParam) / Info->lEditSpacing, GET_X_LPARAM(lParam) / Info->lEditSpacing, 0); + return 0; + + case WM_PAINT: + { + BOOL bBit; + HPEN hOldPen; + HPEN hPen; + PAINTSTRUCT ps; + RECT rect; + UINT i; + UINT j; + + BeginPaint(hwnd, &ps); + + // Draw the grid + GetClientRect(hwnd, &rect); + Info->lEditSpacing = rect.right / 8; + + hPen = CreatePen( PS_SOLID, 1, RGB(128, 128, 128) ); + hOldPen = SelectObject(ps.hdc, hPen); + + for(i = 1; i < 8; i++) + { + MoveToEx(ps.hdc, i * Info->lEditSpacing, 0, NULL); + LineTo (ps.hdc, i * Info->lEditSpacing, rect.right); + + MoveToEx(ps.hdc, 0, i * Info->lEditSpacing, NULL); + LineTo (ps.hdc, rect.right, i * Info->lEditSpacing); + } + + SelectObject(ps.hdc, hOldPen); + DeleteObject(hPen); + + // Draw all bits + for(i = 0; i < 8; i++) + { + for(j = 0; j < 8; j++) + { + bBit = (BOOL) (Info->CharacterBits[i] << j & 0x80); + + GetBitRect(Info, i, j, &rect); + FillRect( ps.hdc, &rect, (HBRUSH) GetStockObject(bBit ? BLACK_BRUSH : WHITE_BRUSH) ); + } + } + + // Draw the bounding rectangle + SelectObject( ps.hdc, GetStockObject(NULL_BRUSH) ); + Rectangle(ps.hdc, 0, 0, rect.right, rect.right); + + EndPaint(hwnd, &ps); + return 0; + } + } + } + + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +static LRESULT CALLBACK +EditGlyphPreviewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PEDIT_GLYPH_INFO Info; + + Info = (PEDIT_GLYPH_INFO) GetWindowLongW(hwnd, GWLP_USERDATA); + + if(Info) + { + switch(uMsg) + { + case WM_CREATE: + return 0; + + case WM_PAINT: + { + BOOL bBit; + INT iLeft; + INT iTop; + PAINTSTRUCT ps; + RECT rect; + UINT i; + UINT j; + + BeginPaint(hwnd, &ps); + + // Draw the bounding rectangle + GetClientRect(hwnd, &rect); + Rectangle(ps.hdc, 0, 0, rect.right, rect.bottom); + + // Draw all bits + iLeft = rect.right / 2 - 8 / 2; + iTop = rect.bottom / 2 - 8 / 2; + + for(i = 0; i < 8; i++) + { + for(j = 0; j < 8; j++) + { + bBit = (BOOL) (Info->CharacterBits[i] << j & 0x80); + SetPixel( ps.hdc, j + iLeft, i + iTop, (bBit ? 0 : 0xFFFFFF) ); + } + } + + EndPaint(hwnd, &ps); + + return 0; + } + } + } + + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +BOOL +InitEditGlyphWndClasses(VOID) +{ + WNDCLASSW wc = {0,}; + + wc.lpfnWndProc = EditGlyphEditWndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.lpszClassName = EDIT_GLYPH_EDIT_CLASSW; + + if( !RegisterClassW(&wc) ) + return FALSE; + + wc.lpfnWndProc = EditGlyphPreviewWndProc; + wc.lpszClassName = EDIT_GLYPH_PREVIEW_CLASSW; + + return RegisterClassW(&wc) != 0; +} + +VOID +UnInitEditGlyphWndClasses(VOID) +{ + UnregisterClassW(EDIT_GLYPH_EDIT_CLASSW, hInstance); + UnregisterClassW(EDIT_GLYPH_PREVIEW_CLASSW, hInstance); +} diff --git a/modules/rosapps/applications/devutils/vgafontedit/fileformats.txt b/modules/rosapps/applications/devutils/vgafontedit/fileformats.txt new file mode 100644 index 00000000000..5294982699d --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/fileformats.txt @@ -0,0 +1,55 @@ +VGA Font File Formats +===================== + +We only deal with 8x8 fonts with 256 characters, so different formats aren't described here. + +1. The binary format (*.bin) +---------------------------- +A binary font file is always 2048 bytes in size. +These bytes are divided into 256 characters, so every character is 8 bytes large. +Each byte represents a character row. Consequently, each column is represented by one bit. The most-significant bit contains the pixel of the first column from the left. + +Example: + We want to get the pixel in the third column of the second row of the seventh character. + We assume you loaded the binary font file completely into a byte array called FontBits. + + // All indexes need to be zero-based + UINT uCharacter = 6; + UINT uRow = 1; + UINT uColumn = 2; + + UCHAR uBit; + + // uBit will either contain 0 (0-bit is set) or 128 dec, 0x80 hex (1-bit is set) now + uBit = FontBits[uCharacter * 8 + uRow] << uColumn & 0x80; + +2. The PC Screen Font Version 1 format (*.psf) +---------------------------------------------- +A PC Screen Font Version 1 file is always 2052 bytes in size. + +It has the following structure: + +struct PSF1_FILE +{ + UCHAR uMagic[2]; + UCHAR uMode; + UCHAR uCharSize; + + UCHAR FontBits[2048]; +}; + +* uMagic contains two magic bytes, which identify a PSFv1 file. These are: + uMagic[0] = 0x36 + uMagic[1] = 0x04 + +* uMode specifies special modes of the font. + We only deal with fonts here, which don't have any special modes, so this value should be 0. + +* uCharSize specifies the size of a character. + In our case, this needs to be 8. + +* Finally the FontBits array contains the font bits in the same format as described above. + This way, it is very easy to convert a PSFv1 file to a binary *.bin file. + + +- Colin Finck, 2008/02/01 \ No newline at end of file diff --git a/modules/rosapps/applications/devutils/vgafontedit/fontboxeswnd.c b/modules/rosapps/applications/devutils/vgafontedit/fontboxeswnd.c new file mode 100644 index 00000000000..1dcfeee68f4 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/fontboxeswnd.c @@ -0,0 +1,356 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/fontboxeswnd.c + * PURPOSE: Implements the window showing the character boxes for a font + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "precomp.h" + +static const WCHAR szFontBoxesWndClass[] = L"VGAFontEditFontBoxesWndClass"; + +static VOID +DrawCharacterPixel(IN PAINTSTRUCT *ps, IN UINT uCharacter, IN UCHAR uRow, IN UCHAR uColumn, IN UCHAR uBit, IN COLORREF clBackground) +{ + INT x; + INT y; + + x = (uCharacter % 16) * (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING) + 24 + uColumn; + y = (uCharacter / 16) * (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING)+ 1 + CHARACTER_INFO_BOX_HEIGHT + 2 + uRow; + + SetPixel( ps->hdc, x, y, (uBit ? 0 : clBackground) ); +} + +VOID +GetCharacterRect(IN UINT uFontRow, IN UINT uFontColumn, OUT LPRECT CharacterRect) +{ + CharacterRect->left = uFontColumn * (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING); + CharacterRect->top = uFontRow * (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING); + CharacterRect->right = CharacterRect->left + CHARACTER_BOX_WIDTH; + CharacterRect->bottom = CharacterRect->top + CHARACTER_BOX_HEIGHT; +} + +__inline VOID +GetCharacterPosition(IN UINT uCharacter, OUT PUINT uFontRow, OUT PUINT uFontColumn) +{ + *uFontRow = uCharacter / 16; + *uFontColumn = uCharacter % 16; +} + +static INT +FontBoxesHitTest(IN UINT xPos, IN UINT yPos, OUT LPRECT CharacterRect) +{ + UINT uFontColumn; + UINT uFontRow; + + uFontColumn = xPos / (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING); + uFontRow = yPos / (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING); + GetCharacterRect(uFontRow, uFontColumn, CharacterRect); + + if(xPos > (UINT)CharacterRect->right || yPos > (UINT)CharacterRect->bottom) + // The user clicked on separator space, so return HITTEST_SEPARATOR + return HITTEST_SEPARATOR; + else + // Return the character number + return (uFontRow * 16 + uFontColumn); +} + +static VOID +SetSelectedCharacter(IN PFONT_WND_INFO Info, IN UINT uNewCharacter, OPTIONAL IN LPRECT NewCharacterRect) +{ + LPRECT pCharacterRect; + RECT OldCharacterRect; + UINT uFontColumn; + UINT uFontRow; + + // Remove the selection of the old character + GetCharacterPosition(Info->uSelectedCharacter, &uFontRow, &uFontColumn); + GetCharacterRect(uFontRow, uFontColumn, &OldCharacterRect); + InvalidateRect(Info->hFontBoxesWnd, &OldCharacterRect, FALSE); + + // You may pass the RECT of the new character, otherwise we'll allocate memory for one and get it ourselves + if(NewCharacterRect) + pCharacterRect = NewCharacterRect; + else + { + GetCharacterPosition(uNewCharacter, &uFontRow, &uFontColumn); + pCharacterRect = (LPRECT) HeapAlloc( hProcessHeap, 0, sizeof(RECT) ); + GetCharacterRect(uFontRow, uFontColumn, pCharacterRect); + } + + // Select the new character + Info->uSelectedCharacter = uNewCharacter; + InvalidateRect(Info->hFontBoxesWnd, pCharacterRect, FALSE); + + if(!NewCharacterRect) + HeapFree(hProcessHeap, 0, pCharacterRect); +} + +static VOID +DrawProc(IN PFONT_WND_INFO Info, IN PAINTSTRUCT* ps) +{ + COLORREF clBackground; + HBRUSH hBrush = 0; + HBRUSH hOldBrush = 0; + HDC hBoxDC; + HFONT hFont; + HFONT hOldFont; + RECT CharacterRect; + UINT uFontColumn; + UINT uStartColumn; + UINT uEndColumn; + UINT uFontRow; + UINT uStartRow; + UINT uEndRow; + UINT uCharacter; + UCHAR uCharacterColumn; + UCHAR uCharacterRow; + UCHAR uBit; + WCHAR szInfoText[9]; + HBITMAP hBitmapOld; + + // Preparations + hBoxDC = CreateCompatibleDC(NULL); + hBitmapOld = SelectObject(hBoxDC, Info->MainWndInfo->hBoxBmp); + + hFont = CreateFontW(13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L"Tahoma"); + hOldFont = SelectObject(ps->hdc, hFont); + + SetBkMode( ps->hdc, TRANSPARENT ); + + // What ranges do we have to draw? + uStartRow = ps->rcPaint.top / (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING); + uEndRow = ps->rcPaint.bottom / (CHARACTER_BOX_HEIGHT + CHARACTER_BOX_PADDING); + uStartColumn = ps->rcPaint.left / (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING); + uEndColumn = ps->rcPaint.right / (CHARACTER_BOX_WIDTH + CHARACTER_BOX_PADDING); + + for(uFontRow = uStartRow; uFontRow <= uEndRow; uFontRow++) + { + for(uFontColumn = uStartColumn; uFontColumn <= uEndColumn; uFontColumn++) + { + GetCharacterRect(uFontRow, uFontColumn, &CharacterRect); + uCharacter = uFontRow * 16 + uFontColumn; + + // Draw the Character Info Box (header) + BitBlt(ps->hdc, + CharacterRect.left, + CharacterRect.top, + CHARACTER_BOX_WIDTH, + CHARACTER_INFO_BOX_HEIGHT, + hBoxDC, + 0, + 0, + SRCCOPY); + + // Draw the header text + wsprintfW(szInfoText, L"%02u = %02X", uCharacter, uCharacter); + DrawTextW( ps->hdc, szInfoText, -1, &CharacterRect, DT_CENTER ); + + // Draw the Character Bitmap Box (rectangle with the actual character) + if(Info->uSelectedCharacter == uCharacter) + { + clBackground = RGB(255, 255, 0); + hBrush = CreateSolidBrush(clBackground); + hOldBrush = SelectObject(ps->hdc, hBrush); + } + else + { + clBackground = RGB(255, 255, 255); + SelectObject( ps->hdc, GetStockObject(WHITE_BRUSH) ); + } + + Rectangle(ps->hdc, + CharacterRect.left, + CharacterRect.top + CHARACTER_INFO_BOX_HEIGHT, + CharacterRect.right, + CharacterRect.bottom); + + // Draw the actual character into the box + for(uCharacterRow = 0; uCharacterRow < 8; uCharacterRow++) + { + for(uCharacterColumn = 0; uCharacterColumn < 8; uCharacterColumn++) + { + uBit = Info->Font->Bits[uCharacter * 8 + uCharacterRow] << uCharacterColumn & 0x80; + DrawCharacterPixel(ps, uCharacter, uCharacterRow, uCharacterColumn, uBit, clBackground); + } + } + } + } + + SelectObject(hBoxDC, hBitmapOld); + SelectObject(ps->hdc, hOldFont); + DeleteObject(hFont); + SelectObject(ps->hdc, hOldBrush); + DeleteObject(hBrush); + DeleteDC(hBoxDC); +} + +VOID +EditCurrentGlyph(PFONT_WND_INFO FontWndInfo) +{ + PEDIT_GLYPH_INFO EditGlyphInfo; + + // Has the window for this character already been opened? + EditGlyphInfo = FontWndInfo->FirstEditGlyphWnd; + + while(EditGlyphInfo) + { + if(EditGlyphInfo->uCharacter == FontWndInfo->uSelectedCharacter) + { + // Yes, it has. Bring it to the front. + SetFocus(EditGlyphInfo->hSelf); + return; + } + + EditGlyphInfo = EditGlyphInfo->NextEditGlyphWnd; + } + + // No. Then create a new one + EditGlyphInfo = (PEDIT_GLYPH_INFO) HeapAlloc( hProcessHeap, 0, sizeof(EDIT_GLYPH_INFO) ); + EditGlyphInfo->FontWndInfo = FontWndInfo; + EditGlyphInfo->uCharacter = FontWndInfo->uSelectedCharacter; + RtlCopyMemory( EditGlyphInfo->CharacterBits, FontWndInfo->Font->Bits + FontWndInfo->uSelectedCharacter * 8, sizeof(EditGlyphInfo->CharacterBits) ); + + // Add the new window to the linked list + EditGlyphInfo->PrevEditGlyphWnd = FontWndInfo->LastEditGlyphWnd; + EditGlyphInfo->NextEditGlyphWnd = NULL; + + if(FontWndInfo->LastEditGlyphWnd) + FontWndInfo->LastEditGlyphWnd->NextEditGlyphWnd = EditGlyphInfo; + else + FontWndInfo->FirstEditGlyphWnd = EditGlyphInfo; + + FontWndInfo->LastEditGlyphWnd = EditGlyphInfo; + + // Open the window as a modeless dialog, so people can edit several characters at the same time. + EditGlyphInfo->hSelf = CreateDialogParamW(hInstance, MAKEINTRESOURCEW(IDD_EDITGLYPH), FontWndInfo->hSelf, EditGlyphDlgProc, (LPARAM)EditGlyphInfo); + ShowWindow(EditGlyphInfo->hSelf, SW_SHOW); +} + +VOID +CreateFontBoxesWindow(IN PFONT_WND_INFO FontWndInfo) +{ + FontWndInfo->hFontBoxesWnd = CreateWindowExW(0, + szFontBoxesWndClass, + 0, + WS_CHILD | WS_VISIBLE, + 0, + 0, + 0, + 0, + FontWndInfo->hSelf, + NULL, + hInstance, + FontWndInfo); +} + +static LRESULT CALLBACK +FontBoxesWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PFONT_WND_INFO Info; + + Info = (PFONT_WND_INFO) GetWindowLongW(hwnd, GWLP_USERDATA); + + if(Info || uMsg == WM_CREATE) + { + switch(uMsg) + { + case WM_CREATE: + Info = (PFONT_WND_INFO)( ( (LPCREATESTRUCT)lParam )->lpCreateParams ); + SetWindowLongW(hwnd, GWLP_USERDATA, (LONG)Info); + + // Set a fixed window size + SetWindowPos(hwnd, NULL, 0, 0, FONT_BOXES_WND_WIDTH, FONT_BOXES_WND_HEIGHT, SWP_NOZORDER | SWP_NOMOVE); + + return 0; + + case WM_DESTROY: + SetWindowLongW(hwnd, GWLP_USERDATA, 0); + return 0; + + case WM_KEYDOWN: + switch(wParam) + { + case VK_DOWN: + if(Info->uSelectedCharacter < 239) + SetSelectedCharacter(Info, Info->uSelectedCharacter + 16, NULL); + return 0; + + case VK_LEFT: + if(Info->uSelectedCharacter) + SetSelectedCharacter(Info, Info->uSelectedCharacter - 1, NULL); + return 0; + + case VK_RETURN: + EditCurrentGlyph(Info); + return 0; + + case VK_RIGHT: + if(Info->uSelectedCharacter < 255) + SetSelectedCharacter(Info, Info->uSelectedCharacter + 1, NULL); + return 0; + + case VK_UP: + if(Info->uSelectedCharacter > 15) + SetSelectedCharacter(Info, Info->uSelectedCharacter - 16, NULL); + return 0; + } + + break; + + case WM_LBUTTONDBLCLK: + { + EditCurrentGlyph(Info); + return 0; + } + + case WM_LBUTTONDOWN: + { + RECT CharacterRect; + INT iRet; + + iRet = FontBoxesHitTest( GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), &CharacterRect ); + + if(iRet >= 0) + SetSelectedCharacter( Info, (UINT)iRet, &CharacterRect ); + + return 0; + } + + case WM_PAINT: + { + PAINTSTRUCT ps; + + BeginPaint(hwnd, &ps); + DrawProc(Info, &ps); + EndPaint(hwnd, &ps); + + return 0; + } + } + } + + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +BOOL +InitFontBoxesWndClass(VOID) +{ + WNDCLASSW wc = {0,}; + + wc.lpfnWndProc = FontBoxesWndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.hbrBackground = (HBRUSH)( COLOR_BTNFACE + 1 ); + wc.lpszClassName = szFontBoxesWndClass; + wc.style = CS_DBLCLKS; + + return RegisterClassW(&wc) != 0; +} + +VOID +UnInitFontBoxesWndClass(VOID) +{ + UnregisterClassW(szFontBoxesWndClass, hInstance); +} diff --git a/modules/rosapps/applications/devutils/vgafontedit/fontwnd.c b/modules/rosapps/applications/devutils/vgafontedit/fontwnd.c new file mode 100644 index 00000000000..edd6dd53dfe --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/fontwnd.c @@ -0,0 +1,440 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/fontwnd.c + * PURPOSE: Implements the MDI child window for a font + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "precomp.h" + +static const WCHAR szFontWndClass[] = L"VGAFontEditFontWndClass"; + +static BOOL +InitFont(IN PFONT_WND_INFO Info) +{ + Info->Font = (PBITMAP_FONT) HeapAlloc( hProcessHeap, 0, sizeof(BITMAP_FONT) ); + + if(Info->OpenInfo->bCreateNew) + { + ZeroMemory( Info->Font, sizeof(BITMAP_FONT) ); + return TRUE; + } + else + { + // Load a font + BOOL bRet = FALSE; + DWORD dwTemp; + HANDLE hFile; + + hFile = CreateFileW(Info->OpenInfo->pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + LocalizedError( IDS_OPENERROR, GetLastError() ); + return FALSE; + } + + // Let's first check the file size to determine the file type + dwTemp = GetFileSize(hFile, NULL); + + switch(dwTemp) + { + case 2048: + // It should be a binary font file + Info->OpenInfo->bBinaryFileOpened = TRUE; + + if( ReadFile(hFile, Info->Font, sizeof(BITMAP_FONT), &dwTemp, NULL) ) + bRet = TRUE; + else + LocalizedError( IDS_READERROR, GetLastError() ); + + break; + + case 2052: + { + PSF1_HEADER Header; + + // Probably it's a PSFv1 file, check the header to make sure + if( !ReadFile(hFile, &Header, sizeof(PSF1_HEADER) , &dwTemp, NULL) ) + { + LocalizedError( IDS_READERROR, GetLastError() ); + break; + } + else + { + if(Header.uMagic[0] == PSF1_MAGIC0 && Header.uMagic[1] == PSF1_MAGIC1) + { + // Yes, it is a PSFv1 file. + // Check the mode and character size. We only support 8x8 fonts with no special mode. + if(Header.uCharSize == 8 && Header.uMode == 0) + { + // Perfect! The file pointer is already set correctly, so we can just read the font bitmap now. + if( ReadFile(hFile, Info->Font, sizeof(BITMAP_FONT), &dwTemp, NULL) ) + bRet = TRUE; + else + LocalizedError( IDS_READERROR, GetLastError() ); + } + else + LocalizedError(IDS_UNSUPPORTEDPSF); + + break; + } + + // Fall through if the magic numbers aren't there + } + } + + default: + LocalizedError(IDS_UNSUPPORTEDFORMAT); + } + + CloseHandle(hFile); + return bRet; + } +} + +static LRESULT CALLBACK +FontWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PFONT_WND_INFO Info; + + Info = (PFONT_WND_INFO) GetWindowLongW(hwnd, GWLP_USERDATA); + + if(Info || uMsg == WM_CREATE) + { + switch(uMsg) + { + case WM_CHILDACTIVATE: + Info->MainWndInfo->CurrentFontWnd = Info; + SetToolbarFileButtonState(Info->MainWndInfo, TRUE); + SetPasteButtonState(Info->MainWndInfo); + break; + + case WM_CREATE: + Info = (PFONT_WND_INFO)( ( (LPMDICREATESTRUCT) ( (LPCREATESTRUCT)lParam )->lpCreateParams )->lParam ); + Info->hSelf = hwnd; + + SetWindowLongW(hwnd, GWLP_USERDATA, (LONG)Info); + + CreateFontBoxesWindow(Info); + + return 0; + + case WM_USER_APPCLOSE: + case WM_CLOSE: + // The user has to close all open edit dialogs first + if(Info->FirstEditGlyphWnd) + { + PWSTR pszMessage; + + AllocAndLoadString(&pszMessage, IDS_CLOSEEDIT); + MessageBoxW(hwnd, pszMessage, szAppName, MB_OK | MB_ICONEXCLAMATION); + HeapFree(hProcessHeap, 0, pszMessage); + + return 0; + } + + // Prompt if the current file has been modified + if(Info->OpenInfo->bModified) + { + INT nMsgBoxResult; + PWSTR pszPrompt; + WCHAR szFile[MAX_PATH]; + + GetWindowTextW(hwnd, szFile, MAX_PATH); + LoadAndFormatString(IDS_SAVEPROMPT, &pszPrompt, szFile); + + nMsgBoxResult = MessageBoxW(hwnd, pszPrompt, szAppName, MB_YESNOCANCEL | MB_ICONQUESTION); + LocalFree(pszPrompt); + + switch(nMsgBoxResult) + { + case IDYES: + DoFileSave(Info->MainWndInfo, FALSE); + break; + + case IDCANCEL: + // 0 = Stop the process of closing the windows (same value for both WM_CLOSE and WM_USER_APPCLOSE) + return 0; + + // IDNO is handled automatically + } + } + + // If there is another child, it will undo the following actions through its WM_CHILDACTIVATE handler. + // Otherwise CurrentFontWnd will stay NULL, so the main window knows that no more childs are opened. + Info->MainWndInfo->CurrentFontWnd = NULL; + SetToolbarFileButtonState(Info->MainWndInfo, FALSE); + SetPasteButtonState(Info->MainWndInfo); + + if(uMsg == WM_USER_APPCLOSE) + { + // First do the tasks we would do for a normal WM_CLOSE message, then return the value for WM_USER_APPCLOSE + // Anything other than 0 indicates that the application shall continue closing the windows + DefMDIChildProcW(hwnd, WM_CLOSE, 0, 0); + return 1; + } + break; + + case WM_DESTROY: + // Remove the window from the linked list + if(Info->PrevFontWnd) + Info->PrevFontWnd->NextFontWnd = Info->NextFontWnd; + else + Info->MainWndInfo->FirstFontWnd = Info->NextFontWnd; + + if(Info->NextFontWnd) + Info->NextFontWnd->PrevFontWnd = Info->PrevFontWnd; + else + Info->MainWndInfo->LastFontWnd = Info->PrevFontWnd; + + // Free memory + if(Info->Font) + HeapFree(hProcessHeap, 0, Info->Font); + + if(Info->OpenInfo->pszFileName) + HeapFree(hProcessHeap, 0, Info->OpenInfo->pszFileName); + + HeapFree(hProcessHeap, 0, Info->OpenInfo); + HeapFree(hProcessHeap, 0, Info); + + SetWindowLongW(hwnd, GWLP_USERDATA, 0); + return 0; + + case WM_SETFOCUS: + // Set the keyboard focus to the FontBoxes window every time the Font window gets the focus + SetFocus(Info->hFontBoxesWnd); + break; + + case WM_SIZE: + { + INT nHeight = HIWORD(lParam); + INT nWidth = LOWORD(lParam); + POINT pt; + RECT WndRect; + + // This ugly workaround is necessary for not setting either the Height or the Width of the window with SetWindowPos + GetWindowRect(Info->hFontBoxesWnd, &WndRect); + pt.x = WndRect.left; + pt.y = WndRect.top; + ScreenToClient(hwnd, &pt); + + if(nHeight < FONT_BOXES_WND_HEIGHT) + { + SCROLLINFO si; + + // Set the vertical scroll bar + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nMax = FONT_BOXES_WND_HEIGHT; + si.nPage = nHeight; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + } + else + { + ShowScrollBar(hwnd, SB_VERT, FALSE); + + // Store the new y coordinate in pt.y as well (needed for the SetWindowPos call for setting a new x coordinate) + pt.y = nHeight / 2 - FONT_BOXES_WND_HEIGHT / 2; + SetWindowPos(Info->hFontBoxesWnd, + NULL, + pt.x, + pt.y, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER); + } + + if(nWidth < FONT_BOXES_WND_WIDTH) + { + SCROLLINFO si; + + // Set the horizontal scroll bar + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nMax = FONT_BOXES_WND_WIDTH; + si.nPage = nWidth; + SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); + } + else + { + ShowScrollBar(hwnd, SB_HORZ, FALSE); + + SetWindowPos(Info->hFontBoxesWnd, + NULL, + nWidth / 2 - FONT_BOXES_WND_WIDTH / 2, + pt.y, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER); + } + + // We have to call DefMDIChildProcW here as well, otherwise we won't get the Minimize/Maximize/Close buttons for a maximized MDI child. + break; + } + + case WM_HSCROLL: + case WM_VSCROLL: + { + INT nBar; + INT nOrgPos; + SCROLLINFO si; + + if(uMsg == WM_HSCROLL) + nBar = SB_HORZ; + else + nBar = SB_VERT; + + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + GetScrollInfo(hwnd, nBar, &si); + + nOrgPos = si.nPos; + + switch( LOWORD(wParam) ) + { + // Constant is the same as SB_LEFT for WM_HSCROLL + case SB_TOP: + si.nPos = si.nMin; + break; + + // Constant is the same as SB_RIGHT for WM_HSCROLL + case SB_BOTTOM: + si.nPos = si.nMax; + break; + + // Constant is the same as SB_LINELEFT for WM_HSCROLL + case SB_LINEUP: + si.nPos -= 20; + break; + + // Constant is the same as SB_LINERIGHT for WM_HSCROLL + case SB_LINEDOWN: + si.nPos += 20; + break; + + // Constant is the same as SB_PAGELEFT for WM_HSCROLL + case SB_PAGEUP: + si.nPos -= si.nPage; + break; + + // Constant is the same as SB_PAGERIGHT for WM_HSCROLL + case SB_PAGEDOWN: + si.nPos += si.nPage; + break; + + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + } + + si.fMask = SIF_POS; + SetScrollInfo(hwnd, nBar, &si, TRUE); + GetScrollInfo(hwnd, nBar, &si); + + if(si.nPos != nOrgPos) + { + // This ugly workaround is necessary for not setting the x coordinate + POINT pt; + RECT WndRect; + + GetWindowRect(Info->hFontBoxesWnd, &WndRect); + pt.x = WndRect.left; + pt.y = WndRect.top; + ScreenToClient(hwnd, &pt); + + if(uMsg == WM_HSCROLL) + SetWindowPos(Info->hFontBoxesWnd, NULL, -si.nPos, pt.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + else + SetWindowPos(Info->hFontBoxesWnd, NULL, pt.x, -si.nPos, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } + + return 0; + } + } + } + + return DefMDIChildProcW(hwnd, uMsg, wParam, lParam); +} + +BOOL +CreateFontWindow(IN PMAIN_WND_INFO MainWndInfo, IN PFONT_OPEN_INFO OpenInfo) +{ + HWND hFontWnd; + PFONT_WND_INFO Info; + + Info = (PFONT_WND_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(FONT_WND_INFO) ); + + if(Info) + { + Info->MainWndInfo = MainWndInfo; + Info->OpenInfo = OpenInfo; + + if( InitFont(Info) ) + { + PWSTR pszWindowTitle; + + if(OpenInfo->pszFileName) + pszWindowTitle = wcsrchr(OpenInfo->pszFileName, '\\') + 1; + else + LoadAndFormatString(IDS_DOCNAME, &pszWindowTitle, ++MainWndInfo->uDocumentCounter); + + hFontWnd = CreateMDIWindowW( szFontWndClass, + pszWindowTitle, + 0, + CW_USEDEFAULT, + CW_USEDEFAULT, + FONT_WND_MIN_WIDTH, + FONT_WND_MIN_HEIGHT, + MainWndInfo->hMdiClient, + hInstance, + (LPARAM)Info ); + + if(!OpenInfo->pszFileName) + LocalFree(pszWindowTitle); + + if(hFontWnd) + { + // Add the new window to the linked list + Info->PrevFontWnd = Info->MainWndInfo->LastFontWnd; + + if(Info->MainWndInfo->LastFontWnd) + Info->MainWndInfo->LastFontWnd->NextFontWnd = Info; + else + Info->MainWndInfo->FirstFontWnd = Info; + + Info->MainWndInfo->LastFontWnd = Info; + + return TRUE; + } + } + + HeapFree(hProcessHeap, 0, Info); + } + + return FALSE; +} + +BOOL +InitFontWndClass(VOID) +{ + WNDCLASSW wc = {0,}; + + wc.lpfnWndProc = FontWndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.hIcon = LoadIconW( hInstance, MAKEINTRESOURCEW(IDI_DOC) ); + wc.hbrBackground = (HBRUSH)( COLOR_BTNFACE + 1 ); + wc.lpszClassName = szFontWndClass; + + return RegisterClassW(&wc) != 0; +} + +VOID +UnInitFontWndClass(VOID) +{ + UnregisterClassW(szFontWndClass, hInstance); +} diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/bg-BG.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/bg-BG.rc new file mode 100644 index 00000000000..c02919efdb6 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/bg-BG.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/en-US.rc + * PURPOSE: Bulgarian resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * TRANSLATOR: CCTAHEB + */ + +LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT + +IDD_ABOUT DIALOGEX 10, 10, 185, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "За" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "Шрифтовия обработчик на РеактОС", IDC_STATIC, 37, 10, 145, 10 + LTEXT "Възпроизводствено право 2008 Colin Finck", IDC_STATIC, 37, 20, 145, 10 + DEFPUSHBUTTON "Добре", IDCANCEL, 70, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Обработка на знак" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "Добре", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Отказ", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&Файл" + BEGIN + MENUITEM "&Нов\tCtrl+N", ID_FILE_NEW + MENUITEM "&Отваряне...\tCtrl+O", ID_FILE_OPEN + MENUITEM "Затваряне", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Запис\tCtrl+S", ID_FILE_SAVE + MENUITEM "Запис като...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Изход като\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Обработка" + BEGIN + MENUITEM "&Запомняне\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Поставяне\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Обработка на знак...", ID_EDIT_GLYPH + END + + POPUP "&Прозорец" + BEGIN + MENUITEM "&Надипляне", ID_WINDOW_CASCADE + MENUITEM "&Водоравно настелване", ID_WINDOW_TILE_HORZ + MENUITEM "&Отвесно настелване", ID_WINDOW_TILE_VERT + MENUITEM "Под&реждане на значетата", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "&Следващ\tCtrl+F6", ID_WINDOW_NEXT + END + + POPUP "Помо&щ" + BEGIN + MENUITEM "&За...", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "Всички поддържани формати (*.bin,*.psf)|*.bin;*.psf|Двоичен шрифтов файл (*.bin)|*.bin|Екранен шрифт за ЛС, версия 1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Двоични шрифтови файлове (*.bin)|*.bin|" + IDS_OPENERROR, "Грешка при отваряне на файла! (Грешка %1!u!)" + IDS_READERROR, "Грешка при четене на файла! (Грешка %1!u!)" + IDS_WRITEERROR, "Грешка при записване на файла! (Грешка %1!u!)" + IDS_UNSUPPORTEDFORMAT, "Неподдържан файлов формат!" + IDS_UNSUPPORTEDPSF, "Неподдържан формат шрифт PSF! Обработчикът поддържа само шрифтове 8x8, без раширени режими." + IDS_DOCNAME, "Шрифт %1!u!" + IDS_SAVEPROMPT, "Файлът ""%1"" е променен, но не е съхранен.\n\nискате ли да го съхрнаите?" + IDS_APPTITLE, "Обработчикът на РеактОС за VGA шрифтове" + IDS_CLOSEEDIT, "Първо затворете всички прозорци за обработка!" + + IDS_TOOLTIP_NEW, "Нов" + IDS_TOOLTIP_OPEN, "Отваряне" + IDS_TOOLTIP_SAVE, "Запис" + IDS_TOOLTIP_EDIT_GLYPH, "Обработка на знак" + IDS_TOOLTIP_COPY, "Запомняне" + IDS_TOOLTIP_PASTE, "Поставяне" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/de-DE.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/de-DE.rc new file mode 100644 index 00000000000..3ad6a357311 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/de-DE.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/de-DE.rc + * PURPOSE: German resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * TRANSLATOR: Dark_Shadow@gmx.at + */ + +LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL + +IDD_ABOUT DIALOGEX 10, 10, 130, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Info" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "ReactOS VGA Font Editor", IDC_STATIC, 37, 10, 93, 10 + LTEXT "Copyright 2008 Colin Finck", IDC_STATIC, 37, 20, 93, 10 + DEFPUSHBUTTON "OK", IDCANCEL, 40, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Schriftzeichen bearbeiten" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "OK", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Abbrechen", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&Datei" + BEGIN + MENUITEM "&Neu\tStrg+N", ID_FILE_NEW + MENUITEM "&Öffnen...\tStrg+O", ID_FILE_OPEN + MENUITEM "Schließen", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Speichern\tStrg+S", ID_FILE_SAVE + MENUITEM "Speichern unter...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Beenden\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Bearbeiten" + BEGIN + MENUITEM "Kopieren\tStrg+C", ID_EDIT_COPY + MENUITEM "Einfügen\tStrg+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Schriftzeichen bearbeiten...", ID_EDIT_GLYPH + END + + POPUP "&Fenster" + BEGIN + MENUITEM "&Überlappend", ID_WINDOW_CASCADE + MENUITEM "&Horizontal teilen", ID_WINDOW_TILE_HORZ + MENUITEM "&Vertikal teilen", ID_WINDOW_TILE_VERT + MENUITEM "&Symbole anordnen", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Nächs&tes\tStrg+F6", ID_WINDOW_NEXT + END + + POPUP "&Hilfe" + BEGIN + MENUITEM "&Info...", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "Alle unterstützten Formate (*.bin,*.psf)|*.bin;*.psf|Binäre Schriftdateien (*.bin)|*.bin|PC Screen Fonts Version 1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Binäre Schriftdateien (*.bin)|*.bin|" + IDS_OPENERROR, "Fehler beim Öffnen der Datei! (Fehlernummer %1!u!)" + IDS_READERROR, "Fehler beim Lesen der Datei! (Fehlernummer %1!u!)" + IDS_WRITEERROR, "Fehler beim Schreiben der Datei! (Fehlernummer %1!u!)" + IDS_UNSUPPORTEDFORMAT, "Nicht unterstütztes Dateiformat!" + IDS_UNSUPPORTEDPSF, "Nicht unterstütztes PSF-Format! Der Editor unterstützt nur Fonts im Format 8x8 ohne spezielle Modi." + IDS_DOCNAME, "Font %1!u!" + IDS_SAVEPROMPT, "Die Datei ""%1"" wurde geändert.\n\nMöchten Sie die Änderungen speichern?" + IDS_APPTITLE, "ReactOS VGA Font Editor" + IDS_CLOSEEDIT, "Bitte schließen Sie zuerst alle offenen Bearbeitungs-Fenster!" + + IDS_TOOLTIP_NEW, "Neu" + IDS_TOOLTIP_OPEN, "Öffnen" + IDS_TOOLTIP_SAVE, "Speichern" + IDS_TOOLTIP_EDIT_GLYPH, "Schriftzeichen bearbeiten" + IDS_TOOLTIP_COPY, "Kopieren" + IDS_TOOLTIP_PASTE, "Einfügen" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/en-US.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/en-US.rc new file mode 100644 index 00000000000..4fd7057763c --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/en-US.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/en-US.rc + * PURPOSE: English resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * TRANSLATOR: Colin Finck + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +IDD_ABOUT DIALOGEX 10, 10, 130, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "ReactOS VGA Font Editor", IDC_STATIC, 37, 10, 93, 10 + LTEXT "Copyright 2008 Colin Finck", IDC_STATIC, 37, 20, 93, 10 + DEFPUSHBUTTON "OK", IDCANCEL, 40, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit Glyph" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "OK", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Cancel", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New\tCtrl+N", ID_FILE_NEW + MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN + MENUITEM "Close", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Save\tCtrl+S", ID_FILE_SAVE + MENUITEM "Save As...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Exit\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Edit" + BEGIN + MENUITEM "Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "Paste\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Edit Glyph...", ID_EDIT_GLYPH + END + + POPUP "&Window" + BEGIN + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "Tile &Horizontally", ID_WINDOW_TILE_HORZ + MENUITEM "Tile &Vertically", ID_WINDOW_TILE_VERT + MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Nex&t\tCtrl+F6", ID_WINDOW_NEXT + END + + POPUP "&Help" + BEGIN + MENUITEM "&About...", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "All supported formats (*.bin,*.psf)|*.bin;*.psf|Binary Font Files (*.bin)|*.bin|PC Screen Fonts Version 1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Binary Font Files (*.bin)|*.bin|" + IDS_OPENERROR, "Error while opening the file! (Error number %1!u!)" + IDS_READERROR, "Error while reading the file! (Error number %1!u!)" + IDS_WRITEERROR, "Error while writing the file! (Error number %1!u!)" + IDS_UNSUPPORTEDFORMAT, "Unsupported file format!" + IDS_UNSUPPORTEDPSF, "Unsupported PSF font format! The editor only supports 8x8 fonts with no special modes." + IDS_DOCNAME, "Font %1!u!" + IDS_SAVEPROMPT, "The file ""%1"" was modified, but not saved.\n\nDo you want to save it?" + IDS_APPTITLE, "ReactOS VGA Font Editor" + IDS_CLOSEEDIT, "Please close all open Edit windows first!" + + IDS_TOOLTIP_NEW, "New" + IDS_TOOLTIP_OPEN, "Open" + IDS_TOOLTIP_SAVE, "Save" + IDS_TOOLTIP_EDIT_GLYPH, "Edit Glyph" + IDS_TOOLTIP_COPY, "Copy" + IDS_TOOLTIP_PASTE, "Paste" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/es-ES.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/es-ES.rc new file mode 100644 index 00000000000..00a6e38f97e --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/es-ES.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/en-US.rc + * PURPOSE: English resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * Traducido por: Javier Remacha 2008 + */ + +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL + +IDD_ABOUT DIALOGEX 10, 10, 130, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Acerca de" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "ReactOS VGA Font Editor", IDC_STATIC, 37, 10, 93, 10 + LTEXT "Copyright 2008 Colin Finck", IDC_STATIC, 37, 20, 93, 10 + DEFPUSHBUTTON "Aceptar", IDCANCEL, 40, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Editar Glifo" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "Aceptar", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Cancelar", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&Archivo" + BEGIN + MENUITEM "&Nuevo\tCtrl+N", ID_FILE_NEW + MENUITEM "&Abrir...\tCtrl+O", ID_FILE_OPEN + MENUITEM "Cerrar", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Guardar\tCtrl+S", ID_FILE_SAVE + MENUITEM "Guardar como...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Salir\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Edición" + BEGIN + MENUITEM "Copiar\tCtrl+C", ID_EDIT_COPY + MENUITEM "Pegar\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Editar Glifo...", ID_EDIT_GLYPH + END + + POPUP "&Ventana" + BEGIN + MENUITEM "&Cascada", ID_WINDOW_CASCADE + MENUITEM "Dividir &Horizontalmente", ID_WINDOW_TILE_HORZ + MENUITEM "Dividir &Verticalmente", ID_WINDOW_TILE_VERT + MENUITEM "&Organizar Iconos", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Siguien&te\tCtrl+F6", ID_WINDOW_NEXT + END + + POPUP "Ay&uda" + BEGIN + MENUITEM "&Acerca de...", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "Todos los formatos soportados (*.bin,*.psf)|*.bin;*.psf|Archivos binarios de Fuentes (*.bin)|*.bin|Fuente de pantalla de PC Versión 1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Archivos binarios de Fuentes (*.bin)|*.bin|" + IDS_OPENERROR, "¡Error al abrir el archivo! (Error número %1!u!)" + IDS_READERROR, "¡Error al leer el archivo! (Error número %1!u!)" + IDS_WRITEERROR, "¡Error al escribir el archivo! (Error número %1!u!)" + IDS_UNSUPPORTEDFORMAT, "¡Formato de archivo no soportado!" + IDS_UNSUPPORTEDPSF, "¡Formato de fuente PSF no soportado! El editor sólo soporta fuentes 8x8 fonts sin modos especiales." + IDS_DOCNAME, "Fuente %1!u!" + IDS_SAVEPROMPT, "El archivo ""%1"" ha sido modificado, pero no guardado.\n\n¿Quiere guardarlo ahora?" + IDS_APPTITLE, "ReactOS VGA Font Editor" + IDS_CLOSEEDIT, "¡Por favor, cierre todas las ventanas de Edición abiertas primero!" + + IDS_TOOLTIP_NEW, "Nuevo" + IDS_TOOLTIP_OPEN, "Abrir" + IDS_TOOLTIP_SAVE, "Guardar" + IDS_TOOLTIP_EDIT_GLYPH, "Editar Glifo" + IDS_TOOLTIP_COPY, "Copiar" + IDS_TOOLTIP_PASTE, "Pegar" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/fr-FR.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/fr-FR.rc new file mode 100644 index 00000000000..bd948f30a77 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/fr-FR.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/fr-FR.rc + * PURPOSE: French resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * TRANSLATOR: Pierre Schweitzer + */ + +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL + +IDD_ABOUT DIALOGEX 10, 10, 130, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "À propos de" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "Éditeur de police VGA ReactOS", IDC_STATIC, 37, 10, 93, 10 + LTEXT "Copyright 2008 Colin Finck", IDC_STATIC, 37, 20, 93, 10 + DEFPUSHBUTTON "OK", IDCANCEL, 40, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Éditer le glyphe" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "OK", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Annuler", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&Fichier" + BEGIN + MENUITEM "&Nouveau\tCtrl+N", ID_FILE_NEW + MENUITEM "&Ouvrir...\tCtrl+O", ID_FILE_OPEN + MENUITEM "Fermer", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Enregistrer\tCtrl+S", ID_FILE_SAVE + MENUITEM "Enregistrer sous...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Quitter\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Édition" + BEGIN + MENUITEM "Copier\tCtrl+C", ID_EDIT_COPY + MENUITEM "Coller\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Éditer le glyphe...", ID_EDIT_GLYPH + END + + POPUP "Fenêtres" + BEGIN + MENUITEM "En &cascade", ID_WINDOW_CASCADE + MENUITEM "Mosaïque &horizontale", ID_WINDOW_TILE_HORZ + MENUITEM "Mosaïque &verticale", ID_WINDOW_TILE_VERT + MENUITEM "&Arranger les icônes", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Suivan&te\tCtrl+F6", ID_WINDOW_NEXT + END + + POPUP "Aide" + BEGIN + MENUITEM "&À propos de...", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "Tous les formats supportés (*.bin,*.psf)|*.bin;*.psf|Fichiers police binaires (*.bin)|*.bin|PC Screen Fonts Version 1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Fichiers police binaires (*.bin)|*.bin|" + IDS_OPENERROR, "Erreur lors de l'ouverture du fichier ! (Erreur numéro %1!u!)" + IDS_READERROR, "Erreur lors de la lecture du fichier ! (Erreur numéro %1!u!)" + IDS_WRITEERROR, "Erreur lors de l'écriture du fichier ! (Erreur numéro %1!u!)" + IDS_UNSUPPORTEDFORMAT, "Format de fichier non supporté!" + IDS_UNSUPPORTEDPSF, "Format de police PSF non supporté ! L'éditeur supporte seulement les polices 8x8 sans aucun mode spécial." + IDS_DOCNAME, "Police %1!u!" + IDS_SAVEPROMPT, "Le fichier ""%1"" a été modifié mais pas enregistré.\n\nVoulez-vous l'enregistrer ?" + IDS_APPTITLE, "Éditeur de police VGA ReactOS" + IDS_CLOSEEDIT, "Veuillez d'abord fermer toutes les fenêtres d'édition !" + + IDS_TOOLTIP_NEW, "Nouveau" + IDS_TOOLTIP_OPEN, "Ouvrir" + IDS_TOOLTIP_SAVE, "Enregistrer" + IDS_TOOLTIP_EDIT_GLYPH, "Éditer le glyphe" + IDS_TOOLTIP_COPY, "Copier" + IDS_TOOLTIP_PASTE, "Coller" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/it-IT.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/it-IT.rc new file mode 100644 index 00000000000..d540d0dfaed --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/it-IT.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/en-US.rc + * PURPOSE: English resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * TRANSLATOR: Paolo Devoti + */ + +LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL + +IDD_ABOUT DIALOGEX 10, 10, 130, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Informazioni su" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "ReactOS VGA Font Editor", IDC_STATIC, 37, 10, 93, 10 + LTEXT "Copyright 2008 Colin Finck", IDC_STATIC, 37, 20, 93, 10 + DEFPUSHBUTTON "OK", IDCANCEL, 40, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit Glyph" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "OK", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Annulla", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Nuovo\tCtrl+N", ID_FILE_NEW + MENUITEM "&Apri...\tCtrl+O", ID_FILE_OPEN + MENUITEM "Chiudi", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Salva\tCtrl+S", ID_FILE_SAVE + MENUITEM "Salva come...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Esci\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Modifica" + BEGIN + MENUITEM "Copia\tCtrl+C", ID_EDIT_COPY + MENUITEM "Incolla\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Edit Glyph...", ID_EDIT_GLYPH + END + + POPUP "&Finestre" + BEGIN + MENUITEM "&Sovrapponi", ID_WINDOW_CASCADE + MENUITEM "Affianca &Orizzontalmente", ID_WINDOW_TILE_HORZ + MENUITEM "Affianca &Verticalmente", ID_WINDOW_TILE_VERT + MENUITEM "&Disponi Icone", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Succ&essiva\tCtrl+F6", ID_WINDOW_NEXT + END + + POPUP "&Aiuto" + BEGIN + MENUITEM "&Informazioni su...", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "Tutti i formati supportati (*.bin,*.psf)|*.bin;*.psf|Font binari (*.bin)|*.bin|Font per schermo PC Versione 1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Font binari (*.bin)|*.bin|" + IDS_OPENERROR, "Errore durante l'apertura del file! (Errore numero %1!u!)" + IDS_READERROR, "Errore durante la lettura del file! (Errore numero %1!u!)" + IDS_WRITEERROR, "Errore durante la scrittura del file! (Errore numero %1!u!)" + IDS_UNSUPPORTEDFORMAT, "Formato non supportato!" + IDS_UNSUPPORTEDPSF, "Formato font PSF non supportato! L'editor supporta esclusivamente i font 8x8 senza modi speciali." + IDS_DOCNAME, "Font %1!u!" + IDS_SAVEPROMPT, "Il file ""%1"" è stato modificato, ma non salvato.\n\nVolete salvarlo ora?" + IDS_APPTITLE, "ReactOS VGA Font Editor" + IDS_CLOSEEDIT, "Prima chiudere tutte le finestre di Edit!" + + IDS_TOOLTIP_NEW, "Nuovo" + IDS_TOOLTIP_OPEN, "Apri" + IDS_TOOLTIP_SAVE, "Salva" + IDS_TOOLTIP_EDIT_GLYPH, "Edit Glyph" + IDS_TOOLTIP_COPY, "Copia" + IDS_TOOLTIP_PASTE, "Incolla" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/no-NO.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/no-NO.rc new file mode 100644 index 00000000000..55fe10d354f --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/no-NO.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/en-US.rc + * PURPOSE: English resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * TRANSLATOR: Colin Finck + */ + +LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL + +IDD_ABOUT DIALOGEX 10, 10, 130, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Om" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "ReactOS VGA skriftredigering", IDC_STATIC, 37, 10, 93, 10 + LTEXT "Enerett 2008 Colin Finck", IDC_STATIC, 37, 20, 93, 10 + DEFPUSHBUTTON "OK", IDCANCEL, 40, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Rediger Glyph" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "OK", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Avbryt", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&Fil" + BEGIN + MENUITEM "&Ny\tCtrl+N", ID_FILE_NEW + MENUITEM "&Åpne...\tCtrl+O", ID_FILE_OPEN + MENUITEM "Lukk", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Lagre\tCtrl+S", ID_FILE_SAVE + MENUITEM "Lagre som...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Avslutt\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Rediger" + BEGIN + MENUITEM "Kopier\tCtrl+C", ID_EDIT_COPY + MENUITEM "Lim inn\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Rediger Glyph...", ID_EDIT_GLYPH + END + + POPUP "&Vindu" + BEGIN + MENUITEM "&Overlappet", ID_WINDOW_CASCADE + MENUITEM "Hele &Horisontalt", ID_WINDOW_TILE_HORZ + MENUITEM "Hele &Vertikalt", ID_WINDOW_TILE_VERT + MENUITEM "&Ordne ikoner", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Nes&te\tCtrl+F6", ID_WINDOW_NEXT + END + + POPUP "&Hjelp" + BEGIN + MENUITEM "&Om...", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "Alle støttet formater (*.bin,*.psf)|*.bin;*.psf|Binære skrifttype filer (*.bin)|*.bin|PC skjerm skrifttype versjon 1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Binære skrifttype filer (*.bin)|*.bin|" + IDS_OPENERROR, "Feil med Ã¥ Ã¥pne filen! (Feil nummer %1!u!)" + IDS_READERROR, "Feil med Ã¥ lese filen! (Feil nummer %1!u!)" + IDS_WRITEERROR, "Feil med Ã¥ lagre filen! (Feil nummer %1!u!)" + IDS_UNSUPPORTEDFORMAT, "Filformatet er ikke støttet!" + IDS_UNSUPPORTEDPSF, "Ikke støttet PSF filformat/skriftformat! Programmet støtter bare 8x8 skrift med ingen spesielle modus." + IDS_DOCNAME, "Skrifttype %1!u!" + IDS_SAVEPROMPT, "Filen ""%1"" har blitt endret, men har ikke blitt lagret.\n\nVil du lagre denne?" + IDS_APPTITLE, "ReactOS VGA Skriftredigering" + IDS_CLOSEEDIT, "Vennligst lukk alle Ã¥pne vinduer først!" + + IDS_TOOLTIP_NEW, "Ny" + IDS_TOOLTIP_OPEN, "Åpne" + IDS_TOOLTIP_SAVE, "Lagre" + IDS_TOOLTIP_EDIT_GLYPH, "Rediger Glyph" + IDS_TOOLTIP_COPY, "Kopier" + IDS_TOOLTIP_PASTE, "Lim inn" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/pl-PL.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/pl-PL.rc new file mode 100644 index 00000000000..5f8f6ba85ce --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/pl-PL.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: Edytor czczionek VGA dla ReactOS + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/pl-PL.rc + * PURPOSE: Polish resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * TRANSLATOR: Olaf Siejka (Feb, 2008) + */ + +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT + +IDD_ABOUT DIALOGEX 10, 10, 130, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "O programie" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "Edytor czcionek VGA dla ReactOS", IDC_STATIC, 37, 10, 93, 10 + LTEXT "Copyright 2008 Colin Finck", IDC_STATIC, 37, 20, 93, 10 + DEFPUSHBUTTON "OK", IDCANCEL, 40, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edycja Glifów" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "OK", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Anuluj", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&Plik" + BEGIN + MENUITEM "&Nowy\tCtrl+N", ID_FILE_NEW + MENUITEM "&Otwórz.\tCtrl+O", ID_FILE_OPEN + MENUITEM "Zamknij", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Zapisz\tCtrl+S", ID_FILE_SAVE + MENUITEM "Zapisz jako", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Wyjdź\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Edit" + BEGIN + MENUITEM "Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "Paste\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Edit Glyph...", ID_EDIT_GLYPH + END + + POPUP "&Okna" + BEGIN + MENUITEM "&Kaskadowo", ID_WINDOW_CASCADE + MENUITEM "Ustaw &poziomo", ID_WINDOW_TILE_HORZ + MENUITEM "Ustaw pio&nowo", ID_WINDOW_TILE_VERT + MENUITEM "&Uporządkuj ikony", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Nas&tępne\tCtrl+F6", ID_WINDOW_NEXT + END + + POPUP "&Pomoc" + BEGIN + MENUITEM "O p&rogramie", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "Wszystkie obsługiwane (*.bin,*.psf)|*.bin;*.psf|Czcionki binarne (*.bin)|*.bin|Czcionki PSF V1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Czcionki binarne (*.bin)|*.bin|" + IDS_OPENERROR, "Błąd poczas otwierania pliku! (Błąd nr. %1!u!)" + IDS_READERROR, "Błąd poczas wczytywania pliku! (Błąd nr. %1!u!)" + IDS_WRITEERROR, "Błąd podczas zapisu do pliku! (Błąd nr. %1!u!)" + IDS_UNSUPPORTEDFORMAT, "Nieobsługiwany format czcionki!" + IDS_UNSUPPORTEDPSF, "Nieobsługiwana wersja PSF! Edytor obsługuje wyłącznie czcionki rozmiaru 8x8, bez dodatków." + IDS_DOCNAME, "Czcionka %1!u!" + IDS_SAVEPROMPT, "Plik ""%1"" został zmieniony, ale nie zapisany.\n\nCzy chcesz zapisać zmiany?" + IDS_APPTITLE, "Edytor czcionek VGA dla ReactOS" + IDS_CLOSEEDIT, "Proszę najpierw zamknąć wszystkie okna Edycji!" + + IDS_TOOLTIP_NEW, "Nowy" + IDS_TOOLTIP_OPEN, "Otwórz" + IDS_TOOLTIP_SAVE, "Zapisz" + IDS_TOOLTIP_EDIT_GLYPH, "Edytuj Glify" + IDS_TOOLTIP_COPY, "Copy" + IDS_TOOLTIP_PASTE, "Paste" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/ru-RU.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/ru-RU.rc new file mode 100644 index 00000000000..5dcb7c902e0 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/ru-RU.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/ru-RU.rc + * PURPOSE: Russian resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * TRANSLATOR: Dmitry Chapyshev + */ + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +IDD_ABOUT DIALOGEX 10, 10, 130, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "О программе" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "Редактор VGA-шрифтов ReactOS", IDC_STATIC, 37, 10, 93, 10 + LTEXT "Авторские права 2008 Колин Финк", IDC_STATIC, 37, 20, 93, 17 + DEFPUSHBUTTON "OK", IDCANCEL, 40, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Редактирование символа" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "OK", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Отмена", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&Файл" + BEGIN + MENUITEM "&Новый\tCtrl+N", ID_FILE_NEW + MENUITEM "&Открыть...\tCtrl+O", ID_FILE_OPEN + MENUITEM "Закрыть", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Сохранить\tCtrl+S", ID_FILE_SAVE + MENUITEM "Сохранить как...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Выход\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Правка" + BEGIN + MENUITEM "Копировать\tCtrl+C", ID_EDIT_COPY + MENUITEM "Вставить\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Изменить символ...", ID_EDIT_GLYPH + END + + POPUP "&Окна" + BEGIN + MENUITEM "&Каскадом", ID_WINDOW_CASCADE + MENUITEM "&По горизонтали", ID_WINDOW_TILE_HORZ + MENUITEM "П&о вертикали", ID_WINDOW_TILE_VERT + MENUITEM "&Упорядочить значки", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "&Следующее\tCtrl+F6", ID_WINDOW_NEXT + END + + POPUP "&Справка" + BEGIN + MENUITEM "&О программе...", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "Все поддерживаемые форматы (*.bin,*.psf)|*.bin;*.psf|Двоичные файлы шрифтов (*.bin)|*.bin|Экранные шрифты PC версии 1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Двоичные файлы шрифтов (*.bin)|*.bin|" + IDS_OPENERROR, "Ошибка открытия файла! (Ошибка номер %1!u!)" + IDS_READERROR, "Ошибка чтения файла! (Ошибка номер %1!u!)" + IDS_WRITEERROR, "Ошибка записи файла! (Ошибка номер %1!u!)" + IDS_UNSUPPORTEDFORMAT, "Неподдерживаемый формат файла!" + IDS_UNSUPPORTEDPSF, "Неподдерживаемый PSF-формат шрифта! Редактор поддерживает только шрифты размером 8x8 без специальных режимов." + IDS_DOCNAME, "Шрифт %1!u!" + IDS_SAVEPROMPT, "Файл ""%1"" был изменен и изменения не были сохранены.\n\nСохранить?" + IDS_APPTITLE, "Редактор VGA-шрифтов ReactOS" + IDS_CLOSEEDIT, "Пожалуйста, закройте сначала все открытые окна редактирования!" + + IDS_TOOLTIP_NEW, "Новый" + IDS_TOOLTIP_OPEN, "Открыть" + IDS_TOOLTIP_SAVE, "Сохранить" + IDS_TOOLTIP_EDIT_GLYPH, "Редактировать символ" + IDS_TOOLTIP_COPY, "Копировать" + IDS_TOOLTIP_PASTE, "Вставить" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/lang/uk-UA.rc b/modules/rosapps/applications/devutils/vgafontedit/lang/uk-UA.rc new file mode 100644 index 00000000000..5aa136dfa62 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/lang/uk-UA.rc @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/lang/uk-UA.rc + * PURPOSE: Ukraianian resource file + * COPYRIGHT: Copyright 2008 Colin Finck + * TRANSLATOR: Artem Reznikov + */ + +LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT + +IDD_ABOUT DIALOGEX 10, 10, 130, 62 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Про програму" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_MAIN, IDC_STATIC, 10, 10, 20, 20 + LTEXT "Редактор VGA-шрифтів ReactOS", IDC_STATIC, 37, 10, 93, 10 + LTEXT "Copyright 2008 Colin Finck", IDC_STATIC, 37, 20, 93, 10 + DEFPUSHBUTTON "OK", IDCANCEL, 40, 44, 55, 15 +END + +IDD_EDITGLYPH DIALOGEX 32768, 32768, 246, 197 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Редагування символа" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_EDIT_GLYPH_TOOLBOX, TOOLBARCLASSNAMEA, CCS_NODIVIDER | CCS_NORESIZE, 5, 5, 24, 82 + CONTROL "", IDC_EDIT_GLYPH_EDIT, EDIT_GLYPH_EDIT_CLASSW, 0, 39, 5, 160, 160 + CONTROL "", IDC_EDIT_GLYPH_PREVIEW, EDIT_GLYPH_PREVIEW_CLASSW, 0, 209, 5, 32, 32 + + DEFPUSHBUTTON "OK", IDOK, 48, 177, 70, 14 + PUSHBUTTON "Скасувати", IDCANCEL, 125, 177, 70, 14 +END + +IDM_MAINMENU MENU +BEGIN + POPUP "&Файл" + BEGIN + MENUITEM "&Створити\tCtrl+N", ID_FILE_NEW + MENUITEM "&Відкрити...\tCtrl+O", ID_FILE_OPEN + MENUITEM "&Закрити", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "З&берегти\tCtrl+S", ID_FILE_SAVE + MENUITEM "Зберегти &як...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "В&ихід\tAlt+F4", ID_FILE_EXIT + END + + POPUP "&Правка" + BEGIN + MENUITEM "Копіювати\tCtrl+C", ID_EDIT_COPY + MENUITEM "Вставити\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "Редагувати символ...", ID_EDIT_GLYPH + END + + POPUP "&Вікно" + BEGIN + MENUITEM "&Каскадом", ID_WINDOW_CASCADE + MENUITEM "&Горизонтально", ID_WINDOW_TILE_HORZ + MENUITEM "&Вертикально", ID_WINDOW_TILE_VERT + MENUITEM "Упорядкувати &значки", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "&Наступне\tCtrl+F6", ID_WINDOW_NEXT + END + + POPUP "&Довідка" + BEGIN + MENUITEM "&Про програму...", ID_HELP_ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_OPENFILTER, "Всі підтримувані формати (*.bin,*.psf)|*.bin;*.psf|Двійкові файли шрифтів (*.bin)|*.bin|Екранні шрифти ПК версії 1 (*.psf)|*.psf|" + IDS_SAVEFILTER, "Двійкові файли шрифтів (*.bin)|*.bin|" + IDS_OPENERROR, "Помилка при відкритті файлу! (Номер помилки %1!u!)" + IDS_READERROR, "Помилка при читанні файлу! (Номер помилки %1!u!)" + IDS_WRITEERROR, "Помилка при запису файлу! (Номер помилки %1!u!)" + IDS_UNSUPPORTEDFORMAT, "Непідтримуваний формат файлу!" + IDS_UNSUPPORTEDPSF, "Непідтримуваний формат PSF шрифта! Редактор підтримує тільки шрифти 8x8 без спеціальних режимів." + IDS_DOCNAME, "Шрифт %1!u!" + IDS_SAVEPROMPT, "Файл ""%1"" був змінений, але не збережений.\n\nЗберегти його?" + IDS_APPTITLE, "Редактор VGA-шрифтів ReactOS" + IDS_CLOSEEDIT, "Будь ласка закрийте всі відкриті вікна Редагування спочатку!" + + IDS_TOOLTIP_NEW, "Створити" + IDS_TOOLTIP_OPEN, "Відкрити" + IDS_TOOLTIP_SAVE, "Зберегти" + IDS_TOOLTIP_EDIT_GLYPH, "Редагувати символ" + IDS_TOOLTIP_COPY, "Копіювати" + IDS_TOOLTIP_PASTE, "Вставити" +END diff --git a/modules/rosapps/applications/devutils/vgafontedit/main.c b/modules/rosapps/applications/devutils/vgafontedit/main.c new file mode 100644 index 00000000000..742cfc4bfa7 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/main.c @@ -0,0 +1,67 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/main.c + * PURPOSE: Main entry point of the application + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "precomp.h" + +static const WCHAR szCharacterClipboardFormat[] = L"RosVgaFontChar"; + +HINSTANCE hInstance; +HANDLE hProcessHeap; +PWSTR szAppName; +UINT uCharacterClipboardFormat; + +INT WINAPI +wWinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) +{ + HACCEL hAccel; + INT nRet = 1; + MSG msg; + PMAIN_WND_INFO Info = 0; + + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + hInstance = hInst; + hProcessHeap = GetProcessHeap(); + + AllocAndLoadString(&szAppName, IDS_APPTITLE); + + hAccel = LoadAcceleratorsW( hInstance, MAKEINTRESOURCEW(IDA_MAINACCELERATORS) ); + + uCharacterClipboardFormat = RegisterClipboardFormatW(szCharacterClipboardFormat); + if(!uCharacterClipboardFormat) + return 1; + + if( InitMainWndClass() && InitFontWndClass() && InitFontBoxesWndClass() && InitEditGlyphWndClasses() ) + { + if( CreateMainWindow(nCmdShow, &Info) ) + { + while( GetMessageW(&msg, NULL, 0, 0) ) + { + if( !TranslateMDISysAccel(Info->hMdiClient, &msg) && + !TranslateAccelerator(Info->hMainWnd, hAccel, &msg) ) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + nRet = 0; + } + } + + HeapFree(hProcessHeap, 0, szAppName); + + // Just unregister our window classes, don't care whether they were created or not + UnInitEditGlyphWndClasses(); + UnInitFontBoxesWndClass(); + UnInitFontWndClass(); + UnInitMainWndClass(); + + return nRet; +} diff --git a/modules/rosapps/applications/devutils/vgafontedit/mainwnd.c b/modules/rosapps/applications/devutils/vgafontedit/mainwnd.c new file mode 100644 index 00000000000..26fe54cbd67 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/mainwnd.c @@ -0,0 +1,586 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/mainwnd.c + * PURPOSE: Implements the main window of the application + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "precomp.h" + +static const WCHAR szMainWndClass[] = L"VGAFontEditMainWndClass"; + +static VOID +InitResources(IN PMAIN_WND_INFO Info) +{ + HDC hMemDC; + HDC hMainDC; + HPEN hPen, hPenOld; + RECT rect; + HBITMAP hBitmapOld; + + hMemDC = CreateCompatibleDC(NULL); + hMainDC = GetDC(Info->hMainWnd); + + // Create the "Box" bitmap + Info->hBoxBmp = CreateCompatibleBitmap(hMainDC, CHARACTER_BOX_WIDTH, CHARACTER_BOX_HEIGHT); + hBitmapOld = SelectObject(hMemDC, Info->hBoxBmp); + + rect.left = 0; + rect.top = 0; + rect.right = CHARACTER_INFO_BOX_WIDTH; + rect.bottom = CHARACTER_INFO_BOX_HEIGHT; + FillRect( hMemDC, &rect, (HBRUSH)(COLOR_BTNFACE + 1) ); + + hPenOld = SelectObject( hMemDC, GetStockObject(WHITE_PEN) ); + Rectangle(hMemDC, 0, 0, CHARACTER_INFO_BOX_WIDTH - 1, 2); + Rectangle(hMemDC, 0, 2, 2, CHARACTER_INFO_BOX_HEIGHT - 1); + hPen = SelectObject(hMemDC, hPenOld); + + hPen = CreatePen( PS_SOLID, 1, RGB(128, 128, 128) ); + hPenOld = SelectObject(hMemDC, hPen); + Rectangle(hMemDC, 1, CHARACTER_INFO_BOX_HEIGHT - 2, CHARACTER_INFO_BOX_WIDTH, CHARACTER_INFO_BOX_HEIGHT); + Rectangle(hMemDC, CHARACTER_INFO_BOX_WIDTH - 2, 1, CHARACTER_INFO_BOX_WIDTH, CHARACTER_INFO_BOX_HEIGHT - 2); + + SetPixel( hMemDC, CHARACTER_INFO_BOX_WIDTH - 1, 0, RGB(128, 128, 128) ); + SetPixel( hMemDC, 0, CHARACTER_INFO_BOX_HEIGHT - 1, RGB(128, 128, 128) ); + SelectObject(hMemDC, hBitmapOld); + + hPen = SelectObject(hMemDC, hPenOld); + DeleteObject(hPen); + DeleteDC(hMemDC); + ReleaseDC(Info->hMainWnd, hMainDC); +} + +static VOID +UnInitResources(IN PMAIN_WND_INFO Info) +{ + DeleteObject(Info->hBoxBmp); +} + +static VOID +AddToolbarButton(IN PMAIN_WND_INFO Info, IN INT iBitmap, IN INT idCommand, IN UINT uID) +{ + PWSTR pszTooltip; + TBBUTTON tbb = {0,}; + + if( AllocAndLoadString(&pszTooltip, uID) ) + { + tbb.fsState = TBSTATE_ENABLED; + tbb.iBitmap = iBitmap; + tbb.idCommand = idCommand; + tbb.iString = (INT_PTR)pszTooltip; + + SendMessageW( Info->hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)&tbb ); + HeapFree(hProcessHeap, 0, pszTooltip); + } +} + +static VOID +SetToolbarButtonState(IN PMAIN_WND_INFO Info, INT idCommand, BOOL bEnabled) +{ + TBBUTTONINFOW tbbi = {0,}; + + tbbi.cbSize = sizeof(tbbi); + tbbi.dwMask = TBIF_STATE; + tbbi.fsState = (bEnabled ? TBSTATE_ENABLED : 0); + + SendMessageW(Info->hToolbar, TB_SETBUTTONINFOW, idCommand, (LPARAM)&tbbi); +} + +VOID +SetToolbarFileButtonState(IN PMAIN_WND_INFO Info, BOOL bEnabled) +{ + SetToolbarButtonState(Info, ID_FILE_SAVE, bEnabled); + SetToolbarButtonState(Info, ID_EDIT_GLYPH, bEnabled); + SetToolbarButtonState(Info, ID_EDIT_COPY, bEnabled); +} + +static VOID +AddToolbarSeparator(IN PMAIN_WND_INFO Info) +{ + TBBUTTON tbb = {0,}; + + tbb.fsStyle = BTNS_SEP; + + SendMessageW( Info->hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)&tbb ); +} + +static VOID +InitMainWnd(IN PMAIN_WND_INFO Info) +{ + CLIENTCREATESTRUCT ccs; + INT iCustomBitmaps; + INT iStandardBitmaps; + TBADDBITMAP tbab; + + // Add the toolbar + Info->hToolbar = CreateWindowExW(0, + TOOLBARCLASSNAMEW, + NULL, + WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS, + 0, + 0, + 0, + 0, + Info->hMainWnd, + NULL, + hInstance, + NULL); + + // Identify the used Common Controls version + SendMessageW(Info->hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + + // Enable Tooltips + SendMessageW(Info->hToolbar, TB_SETMAXTEXTROWS, 0, 0); + + // Add the toolbar bitmaps + tbab.hInst = HINST_COMMCTRL; + tbab.nID = IDB_STD_SMALL_COLOR; + iStandardBitmaps = (INT)SendMessageW(Info->hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab); + + tbab.hInst = hInstance; + tbab.nID = IDB_MAIN_TOOLBAR; + iCustomBitmaps = (INT)SendMessageW(Info->hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab); + + // Add the toolbar buttons + AddToolbarButton(Info, iStandardBitmaps + STD_FILENEW, ID_FILE_NEW, IDS_TOOLTIP_NEW); + AddToolbarButton(Info, iStandardBitmaps + STD_FILEOPEN, ID_FILE_OPEN, IDS_TOOLTIP_OPEN); + AddToolbarButton(Info, iStandardBitmaps + STD_FILESAVE, ID_FILE_SAVE, IDS_TOOLTIP_SAVE); + AddToolbarSeparator(Info); + AddToolbarButton(Info, iCustomBitmaps + TOOLBAR_EDIT_GLYPH, ID_EDIT_GLYPH, IDS_TOOLTIP_EDIT_GLYPH); + AddToolbarSeparator(Info); + AddToolbarButton(Info, iStandardBitmaps + STD_COPY, ID_EDIT_COPY, IDS_TOOLTIP_COPY); + AddToolbarButton(Info, iStandardBitmaps + STD_PASTE, ID_EDIT_PASTE, IDS_TOOLTIP_PASTE); + + SetToolbarFileButtonState(Info, FALSE); + SetPasteButtonState(Info); + + // Add the MDI client area + ccs.hWindowMenu = GetSubMenu(Info->hMenu, 2); + ccs.idFirstChild = ID_MDI_FIRSTCHILD; + + Info->hMdiClient = CreateWindowExW(WS_EX_CLIENTEDGE, + L"MDICLIENT", + NULL, + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL, + 0, + 0, + 0, + 0, + Info->hMainWnd, + NULL, + hInstance, + &ccs); + + // Initialize the file handling + FileInitialize(Info->hMainWnd); +} + +static VOID +InitMenuPopup(IN PMAIN_WND_INFO Info) +{ + UINT uState; + + uState = MF_BYCOMMAND | !(Info->CurrentFontWnd); + + EnableMenuItem(Info->hMenu, ID_FILE_CLOSE, uState); + EnableMenuItem(Info->hMenu, ID_FILE_SAVE, uState); + EnableMenuItem(Info->hMenu, ID_FILE_SAVE_AS, uState); + + EnableMenuItem(Info->hMenu, ID_EDIT_COPY, uState); + EnableMenuItem(Info->hMenu, ID_EDIT_GLYPH, uState); + + uState = MF_BYCOMMAND | !(Info->CurrentFontWnd && IsClipboardFormatAvailable(uCharacterClipboardFormat)); + EnableMenuItem(Info->hMenu, ID_EDIT_PASTE, uState); +} + +static VOID +DoFileNew(IN PMAIN_WND_INFO Info) +{ + PFONT_OPEN_INFO OpenInfo; + + OpenInfo = (PFONT_OPEN_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(FONT_OPEN_INFO) ); + OpenInfo->bCreateNew = TRUE; + + CreateFontWindow(Info, OpenInfo); +} + +static VOID +DoFileOpen(IN PMAIN_WND_INFO Info) +{ + PFONT_OPEN_INFO OpenInfo; + + OpenInfo = (PFONT_OPEN_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(FONT_OPEN_INFO) ); + OpenInfo->pszFileName = HeapAlloc(hProcessHeap, 0, MAX_PATH); + OpenInfo->pszFileName[0] = 0; + + if( DoOpenFile(OpenInfo->pszFileName) ) + { + OpenInfo->bCreateNew = FALSE; + CreateFontWindow(Info, OpenInfo); + } +} + +VOID +DoFileSave(IN PMAIN_WND_INFO Info, IN BOOL bSaveAs) +{ + DWORD dwBytesWritten; + HANDLE hFile; + + // Show the "Save" dialog + // - if "Save As" was clicked + // - if the file was not yet saved + // - if another format than the binary format was opened + if(bSaveAs || !Info->CurrentFontWnd->OpenInfo->bBinaryFileOpened) + { + if(!Info->CurrentFontWnd->OpenInfo->pszFileName) + { + Info->CurrentFontWnd->OpenInfo->pszFileName = (PWSTR) HeapAlloc(hProcessHeap, 0, MAX_PATH); + Info->CurrentFontWnd->OpenInfo->pszFileName[0] = 0; + } + else if(!Info->CurrentFontWnd->OpenInfo->bBinaryFileOpened) + { + // For a file in another format, the user has to enter a new file name as well + Info->CurrentFontWnd->OpenInfo->pszFileName[0] = 0; + } + + if( !DoSaveFile(Info->CurrentFontWnd->OpenInfo->pszFileName) ) + return; + } + + // Save the binary font + hFile = CreateFileW(Info->CurrentFontWnd->OpenInfo->pszFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if(hFile == INVALID_HANDLE_VALUE) + { + LocalizedError( IDS_OPENERROR, GetLastError() ); + return; + } + + if( !WriteFile(hFile, Info->CurrentFontWnd->Font, sizeof(BITMAP_FONT), &dwBytesWritten, NULL) ) + LocalizedError( IDS_WRITEERROR, GetLastError() ); + + CloseHandle(hFile); +} + +static VOID +CopyCurrentGlyph(IN PFONT_WND_INFO FontWndInfo) +{ + HGLOBAL hMem; + PUCHAR pCharacterBits; + + if(!OpenClipboard(NULL)) + return; + + EmptyClipboard(); + + hMem = GlobalAlloc(GMEM_MOVEABLE, 8); + pCharacterBits = GlobalLock(hMem); + RtlCopyMemory(pCharacterBits, FontWndInfo->Font->Bits + FontWndInfo->uSelectedCharacter * 8, 8); + GlobalUnlock(hMem); + + SetClipboardData(uCharacterClipboardFormat, hMem); + + CloseClipboard(); +} + +static VOID +PasteIntoCurrentGlyph(IN PFONT_WND_INFO FontWndInfo) +{ + HGLOBAL hMem; + + if(!IsClipboardFormatAvailable(uCharacterClipboardFormat)) + return; + + if(!OpenClipboard(NULL)) + return; + + hMem = GetClipboardData(uCharacterClipboardFormat); + if(hMem) + { + PUCHAR pCharacterBits; + + pCharacterBits = GlobalLock(hMem); + if(pCharacterBits) + { + RECT CharacterRect; + UINT uFontRow; + UINT uFontColumn; + + RtlCopyMemory(FontWndInfo->Font->Bits + FontWndInfo->uSelectedCharacter * 8, pCharacterBits, 8); + GlobalUnlock(hMem); + + FontWndInfo->OpenInfo->bModified = TRUE; + + GetCharacterPosition(FontWndInfo->uSelectedCharacter, &uFontRow, &uFontColumn); + GetCharacterRect(uFontRow, uFontColumn, &CharacterRect); + InvalidateRect(FontWndInfo->hFontBoxesWnd, &CharacterRect, FALSE); + } + } + + CloseClipboard(); +} + +VOID +SetPasteButtonState(IN PMAIN_WND_INFO Info) +{ + SetToolbarButtonState(Info, + ID_EDIT_PASTE, + (Info->CurrentFontWnd && IsClipboardFormatAvailable(uCharacterClipboardFormat))); +} + +static BOOL +MenuCommand(IN INT nMenuItemID, IN PMAIN_WND_INFO Info) +{ + switch(nMenuItemID) + { + // File Menu + case ID_FILE_NEW: + DoFileNew(Info); + return TRUE; + + case ID_FILE_OPEN: + DoFileOpen(Info); + return TRUE; + + case ID_FILE_CLOSE: + SendMessageW(Info->CurrentFontWnd->hSelf, WM_CLOSE, 0, 0); + return TRUE; + + case ID_FILE_SAVE: + DoFileSave(Info, FALSE); + return TRUE; + + case ID_FILE_SAVE_AS: + DoFileSave(Info, TRUE); + return TRUE; + + case ID_FILE_EXIT: + PostMessage(Info->hMainWnd, WM_CLOSE, 0, 0); + return TRUE; + + // Edit Menu + case ID_EDIT_GLYPH: + EditCurrentGlyph(Info->CurrentFontWnd); + return TRUE; + + case ID_EDIT_COPY: + CopyCurrentGlyph(Info->CurrentFontWnd); + return TRUE; + + case ID_EDIT_PASTE: + PasteIntoCurrentGlyph(Info->CurrentFontWnd); + return TRUE; + + // Window Menu + case ID_WINDOW_TILE_HORZ: + SendMessageW(Info->hMdiClient, WM_MDITILE, MDITILE_HORIZONTAL, 0); + return TRUE; + + case ID_WINDOW_TILE_VERT: + SendMessageW(Info->hMdiClient, WM_MDITILE, MDITILE_VERTICAL, 0); + return TRUE; + + case ID_WINDOW_CASCADE: + SendMessageW(Info->hMdiClient, WM_MDICASCADE, 0, 0); + return TRUE; + + case ID_WINDOW_ARRANGE: + SendMessageW(Info->hMdiClient, WM_MDIICONARRANGE, 0, 0); + return TRUE; + + case ID_WINDOW_NEXT: + SendMessageW(Info->hMdiClient, WM_MDINEXT, 0, 0); + return TRUE; + + // Help Menu + case ID_HELP_ABOUT: + DialogBoxW( hInstance, MAKEINTRESOURCEW(IDD_ABOUT), Info->hMainWnd, AboutDlgProc ); + return TRUE; + } + + return FALSE; +} + +static VOID +MainWndSize(PMAIN_WND_INFO Info, INT cx, INT cy) +{ + HDWP dwp; + INT iMdiTop; + RECT ToolbarRect; + + iMdiTop = 0; + + dwp = BeginDeferWindowPos(2); + if(!dwp) + return; + + if(Info->hToolbar) + { + GetWindowRect(Info->hToolbar, &ToolbarRect); + iMdiTop += ToolbarRect.bottom - ToolbarRect.top; + + dwp = DeferWindowPos(dwp, Info->hToolbar, NULL, 0, 0, cx, ToolbarRect.bottom - ToolbarRect.top, SWP_NOZORDER); + if(!dwp) + return; + } + + if(Info->hMdiClient) + { + dwp = DeferWindowPos(dwp, Info->hMdiClient, NULL, 0, iMdiTop, cx, cy - iMdiTop, SWP_NOZORDER); + if(!dwp) + return; + } + + EndDeferWindowPos(dwp); +} + +static LRESULT CALLBACK +MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static HWND hNextClipboardViewer; + + PMAIN_WND_INFO Info; + + Info = (PMAIN_WND_INFO) GetWindowLongW(hwnd, GWLP_USERDATA); + + if(Info || uMsg == WM_CREATE) + { + switch(uMsg) + { + case WM_COMMAND: + if( MenuCommand( LOWORD(wParam), Info ) ) + return 0; + + break; + + case WM_CHANGECBCHAIN: + if((HWND)wParam == hNextClipboardViewer) + hNextClipboardViewer = (HWND)lParam; + else + SendMessage(hNextClipboardViewer, uMsg, wParam, lParam); + + return 0; + + case WM_CLOSE: + if(Info->FirstFontWnd) + { + // Send WM_CLOSE to all subwindows, so they can prompt for saving unsaved files + PFONT_WND_INFO pNextWnd; + PFONT_WND_INFO pWnd; + + pWnd = Info->FirstFontWnd; + + do + { + // The pWnd structure might already be destroyed after the WM_CLOSE, so we have to preserve the address of the next window here + pNextWnd = pWnd->NextFontWnd; + + // Send WM_USER_APPCLOSE, so we can check for a custom return value + // In this case, we check if the user clicked the "Cancel" button in one of the prompts and if so, we don't close the app + if( !SendMessage(pWnd->hSelf, WM_USER_APPCLOSE, 0, 0) ) + return 0; + } + while( (pWnd = pNextWnd) ); + } + break; + + case WM_CREATE: + Info = (PMAIN_WND_INFO)( ( (LPCREATESTRUCT)lParam )->lpCreateParams ); + Info->hMainWnd = hwnd; + Info->hMenu = GetMenu(hwnd); + SetWindowLongW(hwnd, GWLP_USERDATA, (LONG)Info); + + hNextClipboardViewer = SetClipboardViewer(hwnd); + + InitMainWnd(Info); + InitResources(Info); + + ShowWindow(hwnd, Info->nCmdShow); + return 0; + + case WM_DESTROY: + UnInitResources(Info); + + HeapFree(hProcessHeap, 0, Info); + SetWindowLongW(hwnd, GWLP_USERDATA, 0); + PostQuitMessage(0); + return 0; + + case WM_DRAWCLIPBOARD: + SetPasteButtonState(Info); + + // Pass the message to the next clipboard window in the chain + SendMessage(hNextClipboardViewer, uMsg, wParam, lParam); + return 0; + + case WM_INITMENUPOPUP: + InitMenuPopup(Info); + break; + + case WM_SIZE: + MainWndSize( Info, LOWORD(lParam), HIWORD(lParam) ); + return 0; + } + } + + if(Info && Info->hMdiClient) + return DefFrameProcW(hwnd, Info->hMdiClient, uMsg, wParam, lParam); + else + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +BOOL +CreateMainWindow(IN INT nCmdShow, OUT PMAIN_WND_INFO* Info) +{ + HWND hMainWnd; + + *Info = (PMAIN_WND_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(MAIN_WND_INFO) ); + + if(*Info) + { + (*Info)->nCmdShow = nCmdShow; + + hMainWnd = CreateWindowExW(0, + szMainWndClass, + szAppName, + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + LoadMenuW(hInstance, MAKEINTRESOURCEW(IDM_MAINMENU)), + hInstance, + *Info); + + if(hMainWnd) + return TRUE; + else + HeapFree(hProcessHeap, 0, *Info); + } + + return FALSE; +} + +BOOL +InitMainWndClass(VOID) +{ + WNDCLASSW wc = {0,}; + + wc.lpfnWndProc = MainWndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.hIcon = LoadIconW( hInstance, MAKEINTRESOURCEW(IDI_MAIN) ); + wc.hbrBackground = (HBRUSH)( COLOR_BTNFACE + 1 ); + wc.lpszClassName = szMainWndClass; + + return RegisterClassW(&wc) != 0; +} + +VOID +UnInitMainWndClass(VOID) +{ + UnregisterClassW(szMainWndClass, hInstance); +} diff --git a/modules/rosapps/applications/devutils/vgafontedit/misc.c b/modules/rosapps/applications/devutils/vgafontedit/misc.c new file mode 100644 index 00000000000..1d256b75a4b --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/misc.c @@ -0,0 +1,118 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 only + * FILE: devutils/vgafontedit/misc.c + * PURPOSE: Some miscellaneous resource functions (copied from "devmgmt") and modified + * COPYRIGHT: Copyright 2006 Ged Murphy + * Copyright 2008 Colin Finck + */ + +#include "precomp.h" + +static INT +LengthOfStrResource(IN UINT uID) +{ + HRSRC hrSrc; + HGLOBAL hRes; + PWSTR lpName, lpStr; + + /* There are always blocks of 16 strings */ + lpName = (PWSTR) MAKEINTRESOURCEW((uID >> 4) + 1); + + /* Find the string table block */ + if ((hrSrc = FindResourceW(hInstance, lpName, (PWSTR)RT_STRING)) != 0 && + (hRes = LoadResource(hInstance, hrSrc)) != 0 && + (lpStr = (PWSTR)LockResource(hRes)) != 0) + { + UINT x; + + /* Find the string we're looking for */ + uID &= 0xF; /* position in the block, same as % 16 */ + + for (x = 0; x < uID; x++) + lpStr += (*lpStr) + 1; + + /* Found the string */ + return (int)(*lpStr); + } + + return -1; +} + +INT +AllocAndLoadString(OUT PWSTR *lpTarget, IN UINT uID) +{ + INT ln; + + ln = LengthOfStrResource(uID); + + if (ln++ > 0) + { + (*lpTarget) = (PWSTR) HeapAlloc( hProcessHeap, 0, ln * sizeof(WCHAR) ); + + if (*lpTarget) + { + INT nRet; + + nRet = LoadStringW(hInstance, uID, *lpTarget, ln); + + if (!nRet) + HeapFree(hProcessHeap, 0, *lpTarget); + + return nRet; + } + } + + return 0; +} + +static DWORD +VarListLoadAndFormatString(IN UINT uID, OUT PWSTR *lpTarget, IN va_list* Args) +{ + DWORD Ret = 0; + PWSTR lpFormat; + + if (AllocAndLoadString(&lpFormat, uID) > 0) + { + /* let's use FormatMessage to format it because it has the ability to allocate + memory automatically */ + Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + lpFormat, + 0, + 0, + (LPWSTR)lpTarget, + 0, + Args); + + HeapFree(hProcessHeap, 0, lpFormat); + } + + return Ret; +} + +DWORD +LoadAndFormatString(IN UINT uID, OUT PWSTR *lpTarget, ...) +{ + DWORD Ret; + va_list Args; + + va_start(Args, lpTarget); + Ret = VarListLoadAndFormatString(uID, lpTarget, &Args); + va_end(Args); + + return Ret; +} + +VOID +LocalizedError(IN UINT uID, ...) +{ + PWSTR pszError; + va_list Args; + + va_start(Args, uID); + VarListLoadAndFormatString(uID, &pszError, &Args); + va_end(Args); + + MessageBoxW(NULL, pszError, szAppName, MB_ICONERROR); + HeapFree(hProcessHeap, 0, pszError); +} diff --git a/modules/rosapps/applications/devutils/vgafontedit/opensave.c b/modules/rosapps/applications/devutils/vgafontedit/opensave.c new file mode 100644 index 00000000000..a5c54f71453 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/opensave.c @@ -0,0 +1,77 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/opensave.c + * PURPOSE: Functions for opening and saving files + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "precomp.h" + +static OPENFILENAMEW ofn; + +VOID +FileInitialize(IN HWND hwnd) +{ + ZeroMemory( &ofn, sizeof(ofn) ); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrDefExt = L"bin"; +} + +static __inline VOID +PrepareFilter(IN PWSTR pszFilter) +{ + // RC strings can't be double-null terminated, so we use | instead to separate the entries. + // Convert them back to null characters here. + do + { + if(*pszFilter == '|') + *pszFilter = 0; + } + while(*++pszFilter); +} + +BOOL +DoOpenFile(OUT PWSTR pszFileName) +{ + BOOL bRet; + PWSTR pszFilter; + + if( AllocAndLoadString(&pszFilter, IDS_OPENFILTER) ) + { + PrepareFilter(pszFilter); + ofn.lpstrFilter = pszFilter; + ofn.lpstrFile = pszFileName; + ofn.Flags = OFN_FILEMUSTEXIST; + + bRet = GetOpenFileNameW(&ofn); + HeapFree(hProcessHeap, 0, pszFilter); + + return bRet; + } + + return FALSE; +} + +BOOL +DoSaveFile(IN OUT PWSTR pszFileName) +{ + BOOL bRet; + PWSTR pszFilter; + + if( AllocAndLoadString(&pszFilter, IDS_SAVEFILTER) ) + { + PrepareFilter(pszFilter); + ofn.lpstrFilter = pszFilter; + ofn.lpstrFile = pszFileName; + + bRet = GetSaveFileNameW(&ofn); + HeapFree(hProcessHeap, 0, pszFilter); + + return bRet; + } + + return FALSE; +} diff --git a/modules/rosapps/applications/devutils/vgafontedit/precomp.h b/modules/rosapps/applications/devutils/vgafontedit/precomp.h new file mode 100644 index 00000000000..c86441e2142 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/precomp.h @@ -0,0 +1,170 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/precomp.h + * PURPOSE: Main header + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#ifndef __PRECOMP_H +#define __PRECOMP_H + +#include +#include +#include +#include "resource.h" +#include "customwndclasses.h" + +// Forward declarations +typedef struct _FONT_WND_INFO FONT_WND_INFO, *PFONT_WND_INFO; +typedef struct _EDIT_GLYPH_INFO EDIT_GLYPH_INFO, *PEDIT_GLYPH_INFO; + +// Structure declarations +typedef struct _BITMAP_FONT +{ + UCHAR Bits[2048]; +} BITMAP_FONT, *PBITMAP_FONT; + +typedef struct _MAIN_WND_INFO +{ + HWND hMainWnd; + HWND hMdiClient; + HMENU hMenu; + HWND hToolbar; + INT nCmdShow; + + HBITMAP hBoxBmp; + PFONT_WND_INFO CurrentFontWnd; + ULONG uDocumentCounter; + + PFONT_WND_INFO FirstFontWnd; + PFONT_WND_INFO LastFontWnd; +} MAIN_WND_INFO, *PMAIN_WND_INFO; + +typedef struct _FONT_OPEN_INFO +{ + BOOL bCreateNew; + BOOL bBinaryFileOpened; + BOOL bModified; + PWSTR pszFileName; +} FONT_OPEN_INFO, *PFONT_OPEN_INFO; + +struct _FONT_WND_INFO +{ + PMAIN_WND_INFO MainWndInfo; + PFONT_OPEN_INFO OpenInfo; + PBITMAP_FONT Font; + + HWND hSelf; + HWND hFontBoxesWnd; + UINT uSelectedCharacter; + + PFONT_WND_INFO PrevFontWnd; + PFONT_WND_INFO NextFontWnd; + + PEDIT_GLYPH_INFO FirstEditGlyphWnd; + PEDIT_GLYPH_INFO LastEditGlyphWnd; +}; + +struct _EDIT_GLYPH_INFO +{ + PFONT_WND_INFO FontWndInfo; + + UINT uCharacter; + UCHAR CharacterBits[8]; + + HWND hSelf; + HWND hEdit; + HWND hPreview; + LONG lEditSpacing; + + PEDIT_GLYPH_INFO PrevEditGlyphWnd; + PEDIT_GLYPH_INFO NextEditGlyphWnd; +}; + +#define ID_MDI_FIRSTCHILD 50000 + +// Dimensions of the visual elements +#define CHARACTER_INFO_BOX_WIDTH 55 +#define CHARACTER_INFO_BOX_HEIGHT 16 +#define CHARACTER_BITMAP_BOX_HEIGHT 14 +#define CHARACTER_BOX_WIDTH (CHARACTER_INFO_BOX_WIDTH) +#define CHARACTER_BOX_HEIGHT (CHARACTER_INFO_BOX_HEIGHT + CHARACTER_BITMAP_BOX_HEIGHT) +#define CHARACTER_BOX_PADDING 5 +#define FONT_BOXES_WND_WIDTH (CHARACTER_BOX_WIDTH * 16 + CHARACTER_BOX_PADDING * 15) +#define FONT_BOXES_WND_HEIGHT (CHARACTER_BOX_HEIGHT * 16 + CHARACTER_BOX_PADDING * 15) +#define FONT_WND_MIN_WIDTH (FONT_BOXES_WND_WIDTH + 25) +#define FONT_WND_MIN_HEIGHT (FONT_BOXES_WND_HEIGHT + GetSystemMetrics(SM_CYCAPTION) + 25) + +// Custom return values +#define HITTEST_SEPARATOR -1 + +// Custom window messages +#define WM_USER_APPCLOSE (WM_USER + 1) + +// Bitmap numbers +#define TOOLBAR_EDIT_GLYPH 0 +#define TOOLBOX_PEN 0 + +// PSFv1 file handling +#define PSF1_MAGIC0 0x36 +#define PSF1_MAGIC1 0x04 + +typedef struct _PSF1_HEADER +{ + UCHAR uMagic[2]; + UCHAR uMode; + UCHAR uCharSize; +} PSF1_HEADER, *PPSF1_HEADER; + + +// +// Function prototypes +// + +// aboutdlg.c +INT_PTR CALLBACK AboutDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +// editglyphdlg.c +INT_PTR CALLBACK EditGlyphDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +BOOL InitEditGlyphWndClasses(VOID); +VOID UnInitEditGlyphWndClasses(VOID); + +// fontboxeswnd.c +VOID CreateFontBoxesWindow(PFONT_WND_INFO FontWndInfo); +BOOL InitFontBoxesWndClass(VOID); +VOID UnInitFontBoxesWndClass(VOID); +VOID GetCharacterRect(IN UINT uFontRow, IN UINT uFontColumn, OUT LPRECT CharacterRect); +__inline VOID GetCharacterPosition(IN UINT uCharacter, OUT PUINT uFontRow, OUT PUINT uFontColumn); +VOID EditCurrentGlyph(PFONT_WND_INFO FontWndInfo); + +// fontwnd.c +BOOL CreateFontWindow(PMAIN_WND_INFO MainWndInfo, PFONT_OPEN_INFO OpenInfo); +BOOL InitFontWndClass(VOID); +VOID UnInitFontWndClass(VOID); + +// main.c +extern PWSTR szAppName; +extern HINSTANCE hInstance; +extern HANDLE hProcessHeap; +extern UINT uCharacterClipboardFormat; + +// mainwnd.c +BOOL CreateMainWindow(IN INT nCmdShow, OUT PMAIN_WND_INFO* Info); +BOOL InitMainWndClass(VOID); +VOID UnInitMainWndClass(VOID); +VOID DoFileSave(IN PMAIN_WND_INFO Info, IN BOOL bSaveAs); +VOID SetToolbarFileButtonState(IN PMAIN_WND_INFO Info, BOOL bEnabled); +VOID SetPasteButtonState(IN PMAIN_WND_INFO Info); + +// misc.c +INT AllocAndLoadString(OUT PWSTR *lpTarget, IN UINT uID); +DWORD LoadAndFormatString(IN UINT uID, OUT PWSTR *lpTarget, ...); +VOID LocalizedError(IN UINT uID, ...); + +// opensave.c +VOID FileInitialize(HWND hwnd); +BOOL DoOpenFile(OUT PWSTR pszFileName); +BOOL DoSaveFile(IN PWSTR pszFileName); + +#endif diff --git a/modules/rosapps/applications/devutils/vgafontedit/res/doc.ico b/modules/rosapps/applications/devutils/vgafontedit/res/doc.ico new file mode 100644 index 00000000000..3c4eaf6e6ac Binary files /dev/null and b/modules/rosapps/applications/devutils/vgafontedit/res/doc.ico differ diff --git a/modules/rosapps/applications/devutils/vgafontedit/res/main.ico b/modules/rosapps/applications/devutils/vgafontedit/res/main.ico new file mode 100644 index 00000000000..bb7ca2bc8b2 Binary files /dev/null and b/modules/rosapps/applications/devutils/vgafontedit/res/main.ico differ diff --git a/modules/rosapps/applications/devutils/vgafontedit/res/toolbar.bmp b/modules/rosapps/applications/devutils/vgafontedit/res/toolbar.bmp new file mode 100644 index 00000000000..df58307b34b Binary files /dev/null and b/modules/rosapps/applications/devutils/vgafontedit/res/toolbar.bmp differ diff --git a/modules/rosapps/applications/devutils/vgafontedit/res/toolbox.bmp b/modules/rosapps/applications/devutils/vgafontedit/res/toolbox.bmp new file mode 100644 index 00000000000..481b5e19f54 Binary files /dev/null and b/modules/rosapps/applications/devutils/vgafontedit/res/toolbox.bmp differ diff --git a/modules/rosapps/applications/devutils/vgafontedit/resource.h b/modules/rosapps/applications/devutils/vgafontedit/resource.h new file mode 100644 index 00000000000..a4e1f347574 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/resource.h @@ -0,0 +1,79 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/resource.h + * PURPOSE: Header containing resource IDs + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#ifndef __RESOURCE_H +#define __RESOURCE_H + +#define IDC_STATIC -1 + +// Icons +#define IDI_MAIN 100 +#define IDI_DOC 101 + +// Accelerator Tables +#define IDA_MAINACCELERATORS 201 + +// Menus +#define IDM_MAINMENU 301 + +// Bitmaps +#define IDB_MAIN_TOOLBAR 401 +#define IDB_EDIT_GLYPH_TOOLBOX 402 + +// Dialogs +#define IDD_ABOUT 501 +#define IDD_EDITGLYPH 502 + +// Dialog Controls +#define IDC_EDIT_GLYPH_TOOLBOX 601 +#define IDC_EDIT_GLYPH_EDIT 602 +#define IDC_EDIT_GLYPH_PREVIEW 603 + +// Command IDs +#define ID_FILE_NEW 1001 +#define ID_FILE_OPEN 1002 +#define ID_FILE_CLOSE 1003 +#define ID_FILE_SAVE 1004 +#define ID_FILE_SAVE_AS 1005 +#define ID_FILE_EXIT 1006 + +#define ID_EDIT_GLYPH 2001 +#define ID_EDIT_COPY 2002 +#define ID_EDIT_PASTE 2003 + +#define ID_WINDOW_TILE_HORZ 3001 +#define ID_WINDOW_TILE_VERT 3002 +#define ID_WINDOW_CASCADE 3003 +#define ID_WINDOW_NEXT 3004 +#define ID_WINDOW_ARRANGE 3005 + +#define ID_HELP_ABOUT 4001 + +#define ID_TOOLBOX_PEN 5001 + +// Strings +#define IDS_OPENFILTER 10001 +#define IDS_SAVEFILTER 10002 +#define IDS_OPENERROR 10003 +#define IDS_READERROR 10004 +#define IDS_WRITEERROR 10005 +#define IDS_UNSUPPORTEDFORMAT 10006 +#define IDS_UNSUPPORTEDPSF 10007 +#define IDS_DOCNAME 10008 +#define IDS_SAVEPROMPT 10009 +#define IDS_APPTITLE 10010 +#define IDS_CLOSEEDIT 10011 + +#define IDS_TOOLTIP_NEW 11001 +#define IDS_TOOLTIP_OPEN 11002 +#define IDS_TOOLTIP_SAVE 11003 +#define IDS_TOOLTIP_EDIT_GLYPH 11004 +#define IDS_TOOLTIP_COPY 11005 +#define IDS_TOOLTIP_PASTE 11006 + +#endif diff --git a/modules/rosapps/applications/devutils/vgafontedit/rsrc.rc b/modules/rosapps/applications/devutils/vgafontedit/rsrc.rc new file mode 100644 index 00000000000..826608bddb9 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/rsrc.rc @@ -0,0 +1,45 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/rsrc.rc + * PURPOSE: Localized resource file + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include +#include "resource.h" +#include "customwndclasses.h" + +/* include localised resources */ +// UTF-8 +#pragma code_page(65001) +#ifdef LANGUAGE_BG_BG + #include "lang/bg-BG.rc" +#endif +#ifdef LANGUAGE_DE_DE + #include "lang/de-DE.rc" +#endif +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif +#ifdef LANGUAGE_ES_ES + #include "lang/es-ES.rc" +#endif +#ifdef LANGUAGE_FR_FR + #include "lang/fr-FR.rc" +#endif +#ifdef LANGUAGE_IT_IT + #include "lang/it-IT.rc" +#endif +#ifdef LANGUAGE_NO_NO + #include "lang/no-NO.rc" +#endif +#ifdef LANGUAGE_PL_PL + #include "lang/pl-PL.rc" +#endif +#ifdef LANGUAGE_RU_RU + #include "lang/ru-RU.rc" +#endif +#ifdef LANGUAGE_UK_UA + #include "lang/uk-UA.rc" +#endif diff --git a/modules/rosapps/applications/devutils/vgafontedit/vgafontedit.rbuild b/modules/rosapps/applications/devutils/vgafontedit/vgafontedit.rbuild new file mode 100644 index 00000000000..801d2a6157a --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/vgafontedit.rbuild @@ -0,0 +1,18 @@ + + . + + user32 + gdi32 + comdlg32 + + aboutdlg.c + editglyphdlg.c + fontboxeswnd.c + fontwnd.c + main.c + vgafontedit.rc + mainwnd.c + misc.c + opensave.c + precomp.h + diff --git a/modules/rosapps/applications/devutils/vgafontedit/vgafontedit.rc b/modules/rosapps/applications/devutils/vgafontedit/vgafontedit.rc new file mode 100644 index 00000000000..154ae24fe82 --- /dev/null +++ b/modules/rosapps/applications/devutils/vgafontedit/vgafontedit.rc @@ -0,0 +1,35 @@ +/* + * PROJECT: ReactOS VGA Font Editor + * LICENSE: GNU General Public License Version 2.0 or any later version + * FILE: devutils/vgafontedit/vgafontedit.rc + * PURPOSE: Main resource file + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include +#include +#include "resource.h" + +/* define language neutral resources */ +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS VGA Font Editor" +#define REACTOS_STR_INTERNAL_NAME "vgafontedit" +#define REACTOS_STR_ORIGINAL_FILENAME "vgafontedit.exe" +#include + +IDA_MAINACCELERATORS ACCELERATORS +BEGIN + "N", ID_FILE_NEW, VIRTKEY, CONTROL + "O", ID_FILE_OPEN, VIRTKEY, CONTROL + "S", ID_FILE_SAVE, VIRTKEY, CONTROL + "C", ID_EDIT_COPY, VIRTKEY, CONTROL + "V", ID_EDIT_PASTE, VIRTKEY, CONTROL +END + +IDB_MAIN_TOOLBAR BITMAP "res/toolbar.bmp" +IDB_EDIT_GLYPH_TOOLBOX BITMAP "res/toolbox.bmp" +IDI_MAIN ICON "res/main.ico" +IDI_DOC ICON "res/doc.ico" + +#include "rsrc.rc" diff --git a/modules/rosapps/applications/fraginator/DefragDialog.cpp b/modules/rosapps/applications/fraginator/DefragDialog.cpp new file mode 100644 index 00000000000..10b5663fa31 --- /dev/null +++ b/modules/rosapps/applications/fraginator/DefragDialog.cpp @@ -0,0 +1,38 @@ +#include "DefragDialog.h" +#include "Defragment.h" +#include "resource.h" + + +void UpdateDefragInfo (HWND Dlg) +{ + Defragment *Defrag; + HWND PercentItem; + char PercentText[100]; + + Defrag = (Defragment *) GetWindowLongPtr (Dlg, GWLP_USERDATA); + + sprintf (PercentText, "%6.2f%%", Defrag->GetStatusPercent()); + PercentItem = GetDlgItem (Dlg, IDC_PERCENT); + SendMessage (GetDlgItem (Dlg, IDC_PERCENT), WM_SETTEXT, 0, (LPARAM) PercentText); + SendMessage (GetDlgItem (Dlg, IDC_STATUS_TEXT), WM_SETTEXT, 0, (LPARAM) Defrag->GetStatusString().c_str()); + + return; +} + + +INT_PTR CALLBACK DefragDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam) +{ + switch (Msg) + { + case WM_INITDIALOG: + SetWindowLongPtr (Dlg, GWLP_USERDATA, (LONG_PTR)LParam); + UpdateDefragInfo (Dlg); + return (1); + + case WM_UPDATEINFO: + UpdateDefragInfo (Dlg); + return (1); + } + + return (0); +} diff --git a/modules/rosapps/applications/fraginator/Defragment.cpp b/modules/rosapps/applications/fraginator/Defragment.cpp new file mode 100644 index 00000000000..dffde1319e9 --- /dev/null +++ b/modules/rosapps/applications/fraginator/Defragment.cpp @@ -0,0 +1,458 @@ +#include "Defragment.h" + + +// Ahh yes I ripped this from my old Findupes project :) +// Fits a path name, composed of a path (i.e. "c:\blah\blah\cha\cha") and a filename ("stuff.txt") +// and fits it to a given length. If it has to truncate it will first truncate from the path, +// substituting in periods. So you might end up with something like: +// C:\Program Files\Micro...\Register.exe +int FitName (wchar_t *destination, const wchar_t *path, const wchar_t *filename, uint32 totalWidth) +{ + uint32 pathLen=0; + uint32 fnLen=0; + uint32 halfTotLen=0; + uint32 len4fn=0; /* number of chars remaining for filename after path is applied */ + uint32 len4path=0; /* number of chars for path before filename is applied */ + wchar_t fmtStrPath[20]=L""; + wchar_t fmtStrFile[20]=L""; + wchar_t fmtString[40]=L""; + + /* + assert (destination != NULL); + assert (path != NULL); + assert (filename != NULL); + assert (totalWidth != 0); + */ + + pathLen = wcslen(path); + fnLen = wcslen(filename); + if (!(totalWidth % 2)) + halfTotLen=totalWidth / 2; + else + halfTotLen=(totalWidth-1) / 2; /* -1 because otherwise (halfTotLen*2) == +(totalWidth+1) which wouldn't be good */ + + /* determine how much width the path and filename each get */ + if ( (pathLen >= halfTotLen) && (fnLen < halfTotLen) ) + { + len4fn = fnLen; + len4path = (totalWidth - len4fn); + } + + if ( (pathLen < halfTotLen) && (fnLen < halfTotLen) ) + { + len4fn = fnLen; + len4path = pathLen; + } + + if ( (pathLen >= halfTotLen) && (fnLen >= halfTotLen) ) + { + len4fn = halfTotLen; + len4path = halfTotLen; + } + + if ( (pathLen < halfTotLen) && (fnLen >= halfTotLen) ) + { + len4path = pathLen; + len4fn = (totalWidth - len4path); + } + /* + if halfTotLen was adjusted above to avoid a rounding error, give the + extra wchar_t to the filename + */ + if (halfTotLen < (totalWidth/2)) len4path++; + + if (pathLen > len4path) swprintf (fmtStrPath, L"%%.%ds...\\", len4path-4); + else + swprintf (fmtStrPath, L"%%s"); + + if (fnLen > len4fn) swprintf (fmtStrFile, L"%%.%ds...", len4fn-3); + else + swprintf (fmtStrFile, L"%%s"); + + wcscpy (fmtString, fmtStrPath); + wcscat (fmtString, fmtStrFile); + /*swprintf (fmtString, L"%s%s", fmtStrPath, fmtStrFile);*/ + swprintf (destination, fmtString, path,filename); + + return (1); +} + +Defragment::Defragment (wstring Name, DefragType DefragMethod) +{ + Method = DefragMethod; + DoLimitLength = true; + Error = false; + Done = false; + PleaseStop = false; + PleasePause = false; + DriveName = Name; + StatusPercent = 0.0f; + LastBMPUpdate = GetTickCount (); + + SetStatusString (L"Opening volume " + Name); + if (!Volume.Open (Name)) + { + SetStatusString (L"Error opening volume " + Name); + Error = true; + Done = true; + StatusPercent = 100.0f; + } + + return; +} + + +Defragment::~Defragment () +{ + if (!IsDoneYet ()) + { + Stop (); + while (!IsDoneYet() && !HasError()) + { + SetStatusString (L"Waiting for thread to stop ..."); + Sleep (150); + } + } + + Volume.Close (); + return; +} + + +void Defragment::SetStatusString (wstring NewStatus) +{ + Lock (); + StatusString = NewStatus; + Unlock (); + + return; +} + + +wstring Defragment::GetStatusString (void) +{ + wstring ReturnVal; + + Lock (); + ReturnVal = StatusString; + Unlock (); + + return (ReturnVal); +} + + +double Defragment::GetStatusPercent (void) +{ + return (StatusPercent); +} + + +bool Defragment::IsDoneYet (void) +{ + return (Done); +} + + +void Defragment::Start (void) +{ + uint32 i; + uint64 FirstFreeLCN; + uint64 TotalClusters; + uint64 ClustersProgress; + wchar_t PrintName[80]; + int Width = 70; + + if (Error) + goto DoneDefrag; + + // First thing: build a file list. + SetStatusString (L"Getting volume bitmap"); + if (!Volume.GetBitmap()) + { + SetStatusString (L"Could not get volume " + DriveName + L" bitmap"); + Error = true; + goto DoneDefrag; + } + + LastBMPUpdate = GetTickCount (); + + if (PleaseStop) + goto DoneDefrag; + + SetStatusString (L"Obtaining volume geometry"); + if (!Volume.ObtainInfo ()) + { + SetStatusString (L"Could not obtain volume " + DriveName + L" geometry"); + Error = true; + goto DoneDefrag; + } + + if (PleaseStop) + goto DoneDefrag; + + SetStatusString (L"Building file database for volume " + DriveName); + if (!Volume.BuildFileList (PleaseStop, StatusPercent)) + { + SetStatusString (L"Could not build file database for volume " + DriveName); + Error = true; + goto DoneDefrag; + } + + if (PleaseStop) + goto DoneDefrag; + + SetStatusString (L"Analyzing database for " + DriveName); + TotalClusters = 0; + for (i = 0; i < Volume.GetDBFileCount(); i++) + { + TotalClusters += Volume.GetDBFile(i).Clusters; + } + + // Defragment! + ClustersProgress = 0; + + // Find first free LCN for speedier searches ... + Volume.FindFreeRange (0, 1, FirstFreeLCN); + + if (PleaseStop) + goto DoneDefrag; + + // Analyze? + if (Method == DefragAnalyze) + { + uint32 j; + + Report.RootPath = Volume.GetRootPath (); + + Report.FraggedFiles.clear (); + Report.UnfraggedFiles.clear (); + Report.UnmovableFiles.clear (); + + Report.FilesCount = Volume.GetDBFileCount () - Volume.GetDBDirCount (); + Report.DirsCount = Volume.GetDBDirCount (); + Report.DiskSizeBytes = Volume.GetVolumeInfo().TotalBytes; + + Report.FilesSizeClusters = 0; + Report.FilesSlackBytes = 0; + Report.FilesSizeBytes = 0; + Report.FilesFragments = 0; + + for (j = 0; j < Volume.GetDBFileCount(); j++) + { + FileInfo Info; + + Info = Volume.GetDBFile (j); + + Report.FilesFragments += max ((size_t)1, Info.Fragments.size()); // add 1 fragment even for 0 bytes/0 cluster files + + if (Info.Attributes.Process == 0) + continue; + + SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name); + + Report.FilesSizeClusters += Info.Clusters; + Report.FilesSizeBytes += Info.Size; + + if (Info.Attributes.Unmovable == 1) + Report.UnmovableFiles.push_back (j); + + if (Info.Fragments.size() > 1) + Report.FraggedFiles.push_back (j); + else + Report.UnfraggedFiles.push_back (j); + + StatusPercent = ((double)j / (double)Report.FilesCount) * 100.0f; + } + + Report.FilesSizeOnDisk = Report.FilesSizeClusters * (uint64)Volume.GetVolumeInfo().ClusterSize; + Report.FilesSlackBytes = Report.FilesSizeOnDisk - Report.FilesSizeBytes; + Report.AverageFragments = (double)Report.FilesFragments / (double)Report.FilesCount; + Report.PercentFragged = 100.0f * ((double)(signed)Report.FraggedFiles.size() / (double)(signed)Report.FilesCount); + + uint64 Percent; + Percent = (10000 * Report.FilesSlackBytes) / Report.FilesSizeOnDisk; + Report.PercentSlack = (double)(signed)Percent / 100.0f; + } + else + // Go through all the files and ... defragment them! + for (i = 0; i < Volume.GetDBFileCount(); i++) + { + FileInfo Info; + bool Result; + uint64 TargetLCN; + uint64 PreviousClusters; + + // What? They want us to pause? Oh ok. + if (PleasePause) + { + SetStatusString (L"Paused"); + PleasePause = false; + + while (PleasePause == false) + { + Sleep (50); + } + + PleasePause = false; + } + + if (PleaseStop) + { + SetStatusString (L"Stopping"); + break; + } + + // + Info = Volume.GetDBFile (i); + + PreviousClusters = ClustersProgress; + ClustersProgress += Info.Clusters; + + if (Info.Attributes.Process == 0) + continue; + + if (!DoLimitLength) + SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name); + else + { + FitName (PrintName, Volume.GetDBDir (Info.DirIndice).c_str(), Info.Name.c_str(), Width); + SetStatusString (PrintName); + } + + // Calculate percentage complete + StatusPercent = 100.0f * double((double)PreviousClusters / (double)TotalClusters); + + // Can't defrag directories yet + if (Info.Attributes.Directory == 1) + continue; + + // Can't defrag 0 byte files :) + if (Info.Fragments.empty()) + continue; + + // If doing fast defrag, skip non-fragmented files + // Note: This assumes that the extents stored in Info.Fragments + // are consolidated. I.e. we assume it is NOT the case that + // two extents account for a sequential range of (non- + // fragmented) clusters. + if (Info.Fragments.size() == 1 && Method == DefragFast) + continue; + + // Otherwise, defrag0rize it! + int Retry = 3; // retry a few times + while (Retry > 0) + { + // Find a place that can fit the file + Result = Volume.FindFreeRange (FirstFreeLCN, Info.Clusters, TargetLCN); + + // If yes, try moving it + if (Result) + { + // If we're doing an extensive defrag and the file is already defragmented + // and if its new location would be after its current location, don't + // move it. + if (Method == DefragExtensive && Info.Fragments.size() == 1 && + TargetLCN > Info.Fragments[0].StartLCN) + { + Retry = 1; + } + else + { + if (Volume.MoveFileDumb (i, TargetLCN)) + { + Retry = 1; // yay, all done with this file. + Volume.FindFreeRange (0, 1, FirstFreeLCN); + } + } + } + + // New: Only update bitmap if it's older than 15 seconds + if ((GetTickCount() - LastBMPUpdate) < 15000) + Retry = 1; + else + if (!Result || Retry != 1) + { // hmm. Wait for a moment, then update the drive bitmap + //SetStatusString (L"(Reobtaining volume " + DriveName + L" bitmap)"); + + if (!DoLimitLength) + { + SetStatusString (GetStatusString() + wstring (L" .")); + } + + if (Volume.GetBitmap ()) + { + LastBMPUpdate = GetTickCount (); + + if (!DoLimitLength) + SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name); + else + SetStatusString (PrintName); + + Volume.FindFreeRange (0, 1, FirstFreeLCN); + } + else + { + SetStatusString (L"Could not re-obtain volume " + DriveName + L" bitmap"); + Error = true; + } + } + + Retry--; + } + + if (Error == true) + break; + } + +DoneDefrag: + wstring OldStatus; + + OldStatus = GetStatusString (); + StatusPercent = 99.999999f; + SetStatusString (L"Closing volume " + DriveName); + Volume.Close (); + StatusPercent = 100.0f; + + // If there was an error then the wstring has already been set + if (Error) + SetStatusString (OldStatus); + else + if (PleaseStop) + SetStatusString (L"Volume " + DriveName + L" defragmentation was stopped"); + else + SetStatusString (L"Finished defragmenting " + DriveName); + + Done = true; + + return; +} + + +void Defragment::TogglePause (void) +{ + Lock (); + SetStatusString (L"Pausing ..."); + PleasePause = true; + Unlock (); + + return; +} + + +void Defragment::Stop (void) +{ + Lock (); + SetStatusString (L"Stopping ..."); + PleaseStop = true; + Unlock (); + + return; +} + + +bool Defragment::HasError (void) +{ + return (Error); +} + diff --git a/modules/rosapps/applications/fraginator/Defragment.h b/modules/rosapps/applications/fraginator/Defragment.h new file mode 100644 index 00000000000..b5db6afbdf2 --- /dev/null +++ b/modules/rosapps/applications/fraginator/Defragment.h @@ -0,0 +1,92 @@ +/***************************************************************************** + + Defragment + +*****************************************************************************/ + + +#ifndef DEFRAGMENT_H +#define DEFRAGMENT_H + + +#include "Unfrag.h" +#include "DriveVolume.h" +#include "Mutex.h" + + +extern int FitName (wchar_t *destination, const wchar_t *path, const wchar_t *filename, uint32 totalWidth); + + +typedef struct DefragReport +{ + wstring RootPath; + uint64 DiskSizeBytes; + uint64 DirsCount; + uint64 FilesCount; + uint64 FilesSizeBytes; + uint64 FilesSizeOnDisk; + uint64 FilesSizeClusters; + uint64 FilesSlackBytes; + uint32 FilesFragments; + double AverageFragments; // = FilesFragments / FilesCount + double PercentFragged; + double PercentSlack; + + vector FraggedFiles; + vector UnfraggedFiles; + vector UnmovableFiles; +} DefragReport; + + +class Defragment +{ +public: + Defragment (wstring Name, DefragType DefragMethod); + ~Defragment (); + + // Commands + void Start (void); + void TogglePause (void); + void Stop (void); + + // Info + bool IsDoneYet (void); + bool HasError (void); + wstring GetStatusString (void); + double GetStatusPercent (void); + DefragType GetDefragType (void) { return (Method); } + DefragReport &GetDefragReport (void) { return (Report); } + DriveVolume &GetVolume (void) { return (Volume); } + + // Mutex + void Lock (void) { DefragMutex.Lock (); } + void Unlock (void) { DefragMutex.Unlock (); } + + // Limit length of status string to 70 chars? + bool GetDoLimitLength (void) { return (DoLimitLength); } + void SetDoLimitLength (bool L) { DoLimitLength = L; } + +private: + void FastDefrag (void); + void ExtensiveDefrag (void); + void SetStatusString (wstring NewStatus); + + DWORD LastBMPUpdate; // Last time volume bitmap was updated + DefragReport Report; + bool DoLimitLength; + DefragType Method; + wstring DriveName; + DriveVolume Volume; + wstring StatusString; + wstring ErrorString; + double StatusPercent; + Mutex DefragMutex; + bool Error; + bool Done; + bool PleaseStop; + bool PleasePause; + DefragType DefragMethod; +}; + + +#endif // DEFRAGMENT_H diff --git a/modules/rosapps/applications/fraginator/DriveVolume.cpp b/modules/rosapps/applications/fraginator/DriveVolume.cpp new file mode 100644 index 00000000000..072b1d98e7a --- /dev/null +++ b/modules/rosapps/applications/fraginator/DriveVolume.cpp @@ -0,0 +1,806 @@ +#include "DriveVolume.h" + + +DriveVolume::DriveVolume () +{ + Handle = INVALID_HANDLE_VALUE; + BitmapDetail = NULL; + return; +} + + +DriveVolume::~DriveVolume () +{ + Close (); + Directories.clear (); + Files.clear (); + return; +} + + +void DriveVolume::Close (void) +{ + if (Handle != INVALID_HANDLE_VALUE) + { + CloseHandle (Handle); + Handle = INVALID_HANDLE_VALUE; + } + + if (BitmapDetail != NULL) + { + free (BitmapDetail); + BitmapDetail = NULL; + } + + return; +} + + +// "Name" should be the drive letter followed by a colon. ie, "c:" +// It's a string to allow for further expansion (ie, defragging over the network?) +// or some other baloney reason +bool DriveVolume::Open (wstring Name) +{ + wchar_t FileName[100]; + bool ReturnVal; + + swprintf (FileName, L"\\\\.\\%s", Name.c_str()); + RootPath = Name.c_str(); + RootPath += L"\\"; + + Handle = CreateFileW + ( + FileName, + MAXIMUM_ALLOWED, // access + FILE_SHARE_READ | FILE_SHARE_WRITE, // share type + NULL, // security descriptor + OPEN_EXISTING, // open type + 0, // attributes (none) + NULL // template + ); + + if (Handle == INVALID_HANDLE_VALUE) + ReturnVal = false; + else + { + wchar_t VolName[64]; + DWORD VolSN; + DWORD VolMaxFileLen; + DWORD FSFlags; + wchar_t FSName[64]; + BOOL Result; + + ReturnVal = true; + Result = GetVolumeInformationW + ( + RootPath.c_str(), + VolName, + sizeof (VolName), + &VolSN, + &VolMaxFileLen, + &FSFlags, + FSName, + sizeof (FSName) + ); + + if (Result) + { + wchar_t SerialText[10]; + + VolInfo.FileSystem = FSName; + VolInfo.MaxNameLen = VolMaxFileLen; + VolInfo.Name = VolName; + + swprintf (SerialText, L"%x-%x", (VolSN & 0xffff0000) >> 16, + VolSN & 0x0000ffff); + + wcsupr (SerialText); + VolInfo.Serial = SerialText; + } + else + { + VolInfo.FileSystem = L"(Unknown)"; + VolInfo.MaxNameLen = 255; + VolInfo.Name = L"(Unknown)"; + VolInfo.Serial = L"(Unknown)"; + } + } + + return (ReturnVal); +} + + +bool DriveVolume::ObtainInfo (void) +{ + BOOL Result; + DWORD BytesGot; + uint64 nan; + + BytesGot = 0; + ZeroMemory (&Geometry, sizeof (Geometry)); + Result = DeviceIoControl + ( + Handle, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &Geometry, + sizeof (Geometry), + &BytesGot, + NULL + ); + + // Call failed? Aww :( + if (!Result) + return (false); + + // Get cluster size + DWORD SectorsPerCluster; + DWORD BytesPerSector; + DWORD FreeClusters; + DWORD TotalClusters; + + Result = GetDiskFreeSpaceW + ( + RootPath.c_str(), + &SectorsPerCluster, + &BytesPerSector, + &FreeClusters, + &TotalClusters + ); + + // Failed? Weird. + if (!Result) + return (false); + + VolInfo.ClusterSize = SectorsPerCluster * BytesPerSector; + + Result = GetDiskFreeSpaceExW + ( + RootPath.c_str(), + (PULARGE_INTEGER)&nan, + (PULARGE_INTEGER)&VolInfo.TotalBytes, + (PULARGE_INTEGER)&VolInfo.FreeBytes + ); + + return (true); +} + + +// Get bitmap, several clusters at a time ... +#define CLUSTERS 4096 +bool DriveVolume::GetBitmap (void) +{ + STARTING_LCN_INPUT_BUFFER StartingLCN; + VOLUME_BITMAP_BUFFER *Bitmap = NULL; + uint32 BitmapSize; + DWORD BytesReturned; + BOOL Result; + + StartingLCN.StartingLcn.QuadPart = 0; + + // Allocate buffer + // Call FSCTL_GET_VOLUME_BITMAP once with a very small buffer + // This will leave the total number of clusters in Bitmap->BitmapSize and we can + // then correctly allocate based off that + // I suppose this won't work if your drive has only 40 clusters on it or so :) + BitmapSize = sizeof (VOLUME_BITMAP_BUFFER) + 4; + Bitmap = (VOLUME_BITMAP_BUFFER *) malloc (BitmapSize); + + Result = DeviceIoControl + ( + Handle, + FSCTL_GET_VOLUME_BITMAP, + &StartingLCN, + sizeof (StartingLCN), + Bitmap, + BitmapSize, + &BytesReturned, + NULL + ); + + // Bad result? + if (Result == FALSE && GetLastError () != ERROR_MORE_DATA) + { + //wprintf ("\nDeviceIoControl returned false, GetLastError() was not ERROR_MORE_DATA\n"); + free (Bitmap); + return (false); + } + + // Otherwise, we're good + BitmapSize = sizeof (VOLUME_BITMAP_BUFFER) + (Bitmap->BitmapSize.QuadPart / 8) + 1; + Bitmap = (VOLUME_BITMAP_BUFFER *) realloc (Bitmap, BitmapSize); + Result = DeviceIoControl + ( + Handle, + FSCTL_GET_VOLUME_BITMAP, + &StartingLCN, + sizeof (StartingLCN), + Bitmap, + BitmapSize, + &BytesReturned, + NULL + ); + + //DWORD LastError = GetLastError (); + + if (Result == FALSE) + { + wprintf (L"\nCouldn't properly read volume bitmap\n"); + free (Bitmap); + return (false); + } + + // Convert to a L'quick use' bitmap + //const int BitShift[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; + + VolInfo.ClusterCount = Bitmap->BitmapSize.QuadPart; + + if (BitmapDetail != NULL) + free (BitmapDetail); + + BitmapDetail = (uint32 *) malloc (sizeof(uint32) * (1 + (VolInfo.ClusterCount / 32))); + memcpy (BitmapDetail, Bitmap->Buffer, sizeof(uint32) * (1 + (VolInfo.ClusterCount / 32))); + + /* + BitmapDetail = (Cluster *) malloc (VolInfo.ClusterCount * sizeof (Cluster)); + for (uint64 i = 0; i < VolInfo.ClusterCount; i++) + { + if (Bitmap->Buffer[i / 8] & BitShift[i % 8]) + BitmapDetail[i].Allocated = true; + else + BitmapDetail[i].Allocated = false; + } + */ + + free (Bitmap); + return (true); +} + + +bool DriveVolume::IsClusterUsed (uint64 Cluster) +{ + return ((BitmapDetail[Cluster / 32] & (1 << (Cluster % 32))) ? true : false); + //return (BitmapDetail[Cluster].Allocated); +} + + +void DriveVolume::SetClusterUsed (uint64 Cluster, bool Used) +{ + if (Used) + BitmapDetail[Cluster / 32] |= (1 << (Cluster % 32)); + else + BitmapDetail[Cluster / 32] &= ~(1 << (Cluster % 32)); + + return; +} + + +typedef struct +{ + DriveVolume *Volume; + double *Percent; + bool *QuitMonitor; + uint64 ClusterCount; + uint64 ClusterProgress; +} BuildDBInfo; + + +bool DriveVolume::BuildFileList (bool &QuitMonitor, double &Percent) +{ + BuildDBInfo Info; + + Files.clear (); + Directories.clear (); + Directories.push_back (RootPath); + + Info.Volume = this; + Info.QuitMonitor = &QuitMonitor; + Info.ClusterCount = (GetVolumeInfo().TotalBytes - GetVolumeInfo().FreeBytes) / (uint64)GetVolumeInfo().ClusterSize; + Info.ClusterProgress = 0; + Info.Percent = &Percent; + + ScanDirectory (RootPath, BuildDBCallback, &Info); + + if (QuitMonitor == true) + { + Directories.resize (0); + Files.resize (0); + } + + return (true); +} + + +// UserData = pointer to BuildDBInfo instance +bool BuildDBCallback (FileInfo &Info, HANDLE &FileHandle, void *UserData) +{ + BuildDBInfo *DBInfo = (BuildDBInfo *) UserData; + DriveVolume *Vol = DBInfo->Volume; + + Vol->Files.push_back (Info); + + if (*(DBInfo->QuitMonitor) == true) + return (false); + + DBInfo->ClusterProgress += (uint64)Info.Clusters; + *(DBInfo->Percent) = + ((double)DBInfo->ClusterProgress / (double)DBInfo->ClusterCount) * 100.0f; + + return (true); +} + + +wstring &DriveVolume::GetDBDir (uint32 Indice) +{ + return (Directories[Indice]); +} + + +uint32 DriveVolume::GetDBDirCount (void) +{ + return (Directories.size()); +} + + +FileInfo &DriveVolume::GetDBFile (uint32 Indice) +{ + return (Files[Indice]); +} + + +uint32 DriveVolume::GetDBFileCount (void) +{ + return (Files.size()); +} + + +uint32 DriveVolume::RemoveDBFile (uint32 Indice) +{ + vector::iterator it; + + it = Files.begin() + Indice; + Files.erase (it); + return (GetDBFileCount()); +} + + +bool DriveVolume::ScanDirectory (wstring DirPrefix, ScanCallback Callback, void *UserData) +{ + WIN32_FIND_DATAW FindData; + HANDLE FindHandle; + wstring SearchString; + uint32 DirIndice; + + DirIndice = Directories.size() - 1; + + SearchString = DirPrefix; + SearchString += L"*.*"; + ZeroMemory (&FindData, sizeof (FindData)); + FindHandle = FindFirstFileW (SearchString.c_str(), &FindData); + + if (FindHandle == INVALID_HANDLE_VALUE) + return (false); + + do + { + FileInfo Info; + HANDLE Handle; + bool CallbackResult; + + Handle = INVALID_HANDLE_VALUE; + + // First copy over the easy stuff. + Info.Name = FindData.cFileName; + + // DonLL't ever include '.L' and '..' + if (Info.Name == L"." || Info.Name == L"..") + continue; + + //Info.FullName = DirPrefix + Info.Name; + Info.Size = (uint64)FindData.nFileSizeLow + ((uint64)FindData.nFileSizeHigh << (uint64)32); + Info.DirIndice = DirIndice; + + Info.Attributes.Archive = (FindData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? 1 : 0; + Info.Attributes.Compressed = (FindData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ? 1 : 0; + Info.Attributes.Directory = (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0; + Info.Attributes.Encrypted = (FindData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) ? 1 : 0; + Info.Attributes.Hidden = (FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? 1 : 0; + Info.Attributes.Normal = (FindData.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ? 1 : 0; + Info.Attributes.Offline = (FindData.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) ? 1 : 0; + Info.Attributes.ReadOnly = (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 1 : 0; + Info.Attributes.Reparse = (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; + Info.Attributes.Sparse = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) ? 1 : 0; + Info.Attributes.System = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? 1 : 0; + Info.Attributes.Temporary = (FindData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? 1 : 0; + Info.Attributes.AccessDenied = 0; + Info.Attributes.Unmovable = 0; + Info.Attributes.Process = 1; + + Info.Clusters = 0; + if (GetClusterInfo (Info, Handle)) + { + uint64 TotalClusters = 0; + + for (size_t i = 0; i < Info.Fragments.size(); i++) + { + TotalClusters += Info.Fragments[i].Length; + } + + Info.Clusters = TotalClusters; + } + else + { + Info.Attributes.Unmovable = 1; + Info.Attributes.Process = 0; + } + + if (Info.Attributes.Process == 1) + Info.Attributes.Process = ShouldProcess (Info.Attributes) ? 1 : 0; + + // Run the user-defined callback function + CallbackResult = Callback (Info, Handle, UserData); + + if (Handle != INVALID_HANDLE_VALUE) + CloseHandle (Handle); + + if (!CallbackResult) + break; + + // If directory, perform recursion + if (Info.Attributes.Directory == 1) + { + wstring Dir; + + Dir = GetDBDir (Info.DirIndice); + Dir += Info.Name; + Dir += L"\\"; + + Directories.push_back (Dir); + ScanDirectory (Dir, Callback, UserData); + } + + } while (FindNextFileW (FindHandle, &FindData) == TRUE); + + FindClose (FindHandle); + return (false); +} + + +bool DriveVolume::ShouldProcess (FileAttr Attr) +{ + if (Attr.Offline == 1 || Attr.Reparse == 1 || Attr.Temporary == 1) + { + return (false); + } + + return (true); +} + + +// Gets info on a file and returns a valid handle for read/write access +// Name, FullName, Clusters, Attributes, and Size should already be filled out. +// This function fills in the Fragments vector +bool DriveVolume::GetClusterInfo (FileInfo &Info, HANDLE &HandleResult) +{ + BOOL Result; + HANDLE Handle; + wstring FullName; + BY_HANDLE_FILE_INFORMATION FileInfo; + + Info.Fragments.resize (0); + + /* + if (Info.Attributes.Directory == 1) + return (false); + */ + + FullName = GetDBDir (Info.DirIndice) + Info.Name; + + Handle = CreateFileW + ( + FullName.c_str(), + 0, //GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + (Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0, + NULL + ); + + if (Handle == INVALID_HANDLE_VALUE) + { + LPVOID lpMsgBuf; + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL ); + + + Info.Attributes.AccessDenied = 1; + LocalFree( lpMsgBuf ); + return (false); + } + + ZeroMemory (&FileInfo, sizeof (FileInfo)); + Result = GetFileInformationByHandle (Handle, &FileInfo); + + if (Result == FALSE) + { + Info.Attributes.AccessDenied = 1; + wprintf (L"GetFileInformationByHandle ('%s%s') failed\n", GetDBDir (Info.DirIndice).c_str(), + Info.Name.c_str()); + + CloseHandle (Handle); + return (false); + } + + // Get cluster allocation information + STARTING_VCN_INPUT_BUFFER StartingVCN; + RETRIEVAL_POINTERS_BUFFER *Retrieval; + uint64 RetSize; + uint64 Extents; + DWORD BytesReturned; + + // Grab info one extent at a time, until it's done grabbing all the extent data + // Yeah, well it doesn't give us a way to ask L"how many extents?" that I know of ... + // btw, the Extents variable tends to only reflect memory usage, so when we have + // all the extents we look at the structure Win32 gives us for the REAL count! + Extents = 10; + Retrieval = NULL; + RetSize = 0; + StartingVCN.StartingVcn.QuadPart = 0; + + do + { + Extents *= 2; + RetSize = sizeof (RETRIEVAL_POINTERS_BUFFER) + ((Extents - 1) * sizeof (LARGE_INTEGER) * 2); + + if (Retrieval != NULL) + Retrieval = (RETRIEVAL_POINTERS_BUFFER *) realloc (Retrieval, RetSize); + else + Retrieval = (RETRIEVAL_POINTERS_BUFFER *) malloc (RetSize); + + Result = DeviceIoControl + ( + Handle, + FSCTL_GET_RETRIEVAL_POINTERS, + &StartingVCN, + sizeof (StartingVCN), + Retrieval, + RetSize, + &BytesReturned, + NULL + ); + + if (Result == FALSE) + { + if (GetLastError() != ERROR_MORE_DATA) + { + Info.Clusters = 0; + Info.Attributes.AccessDenied = 1; + Info.Attributes.Process = 0; + Info.Fragments.clear (); + CloseHandle (Handle); + free (Retrieval); + + return (false); + } + + Extents++; + } + } while (Result == FALSE); + + // Readjust extents, as it only reflects how much memory was allocated and may not + // be accurate + Extents = Retrieval->ExtentCount; + + // Ok, we have the info. Now translate it. hrmrmr + + Info.Fragments.clear (); + for (uint64 i = 0; i < Extents; i++) + { + Extent Add; + + Add.StartLCN = Retrieval->Extents[i].Lcn.QuadPart; + if (i != 0) + Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->Extents[i - 1].NextVcn.QuadPart; + else + Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->StartingVcn.QuadPart; + + Info.Fragments.push_back (Add); + } + + free (Retrieval); + HandleResult = Handle; + return (true); +} + + +bool DriveVolume::FindFreeRange (uint64 StartLCN, uint64 ReqLength, uint64 &LCNResult) +{ + uint64 Max; + uint64 i; + uint64 j; + + // Make sure we don't spill over our array + Max = VolInfo.ClusterCount - ReqLength; + + for (i = StartLCN; i < Max; i++) + { + bool Found = true; + + // First check the first cluster + if (IsClusterUsed (i)) + Found = false; + else + // THen check the last cluster + if (IsClusterUsed (i + ReqLength - 1)) + Found = false; + else + // Check the whole darn range. + for (j = (i + 1); j < (i + ReqLength - 2); j++) + { + if (IsClusterUsed (j) == true) + { + Found = false; + break; + } + } + + if (!Found) + continue; + else + { + LCNResult = i; + return (true); + } + } + + return (false); +} + + +// btw we have to move each fragment of the file, as per the Win32 API +bool DriveVolume::MoveFileDumb (uint32 FileIndice, uint64 NewLCN) +{ + bool ReturnVal = false; + FileInfo Info; + HANDLE FileHandle; + wstring FullName; + MOVE_FILE_DATA MoveData; + uint64 CurrentLCN; + uint64 CurrentVCN; + + // Set up variables + Info = GetDBFile (FileIndice); + FullName = GetDBDir (Info.DirIndice); + FullName += Info.Name; + CurrentLCN = NewLCN; + CurrentVCN = 0; + + /* + if (Info.Attributes.Directory == 1) + { + // + } + */ + + // Open file + FileHandle = CreateFileW + ( + FullName.c_str (), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + (Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0, + NULL + ); + + if (FileHandle == INVALID_HANDLE_VALUE) + { + // + LPVOID lpMsgBuf; + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL ); + + + LocalFree (lpMsgBuf); + // + + ReturnVal = false; + } + else + { + ReturnVal = true; // innocent until proven guilty ... + + for (uint32 i = 0; i < Info.Fragments.size(); i++) + { + BOOL Result; + DWORD BytesReturned; + + //wprintf (L"%3u", i); + + MoveData.ClusterCount = Info.Fragments[i].Length; + MoveData.StartingLcn.QuadPart = CurrentLCN; + MoveData.StartingVcn.QuadPart = CurrentVCN; + + MoveData.FileHandle = FileHandle; + + /* + wprintf (L"\n"); + wprintf (L"StartLCN: %I64u\n", MoveData.StartingLcn.QuadPart); + wprintf (L"StartVCN: %I64u\n", MoveData.StartingVcn.QuadPart); + wprintf (L"Clusters: %u (%I64u-%I64u --> %I64u-%I64u)\n", MoveData.ClusterCount, + Info.Fragments[i].StartLCN, + Info.Fragments[i].StartLCN + MoveData.ClusterCount, + MoveData.StartingLcn.QuadPart, + MoveData.StartingLcn.QuadPart + MoveData.ClusterCount - 1); + wprintf (L"\n"); + */ + + Result = DeviceIoControl + ( + Handle, + FSCTL_MOVE_FILE, + &MoveData, + sizeof (MoveData), + NULL, + 0, + &BytesReturned, + NULL + ); + + //wprintf (L"\b\b\b"); + + if (Result == FALSE) + { + // + LPVOID lpMsgBuf; + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL ); + + + LocalFree( lpMsgBuf ); + // + + ReturnVal = false; + goto FinishUp; // yeah, bite me + } + + // Ok good. Now update our drive bitmap and file infos. + uint64 j; + for (j = 0; + j < Info.Fragments[i].Length; + j++) + { + SetClusterUsed (Info.Fragments[i].StartLCN + j, false); + SetClusterUsed (CurrentLCN + j, true); + //BitmapDetail[Info.Fragments[i].StartLCN + j].Allocated = false; + //BitmapDetail[CurrentLCN + j].Allocated = true; + } + + CurrentLCN += Info.Fragments[i].Length; + CurrentVCN += Info.Fragments[i].Length; + } + + // Update file info either way + FinishUp: + CloseHandle (FileHandle); + FileHandle = INVALID_HANDLE_VALUE; + GetClusterInfo (Files[FileIndice], FileHandle); + CloseHandle (FileHandle); + } + + return (ReturnVal); +} + + diff --git a/modules/rosapps/applications/fraginator/DriveVolume.h b/modules/rosapps/applications/fraginator/DriveVolume.h new file mode 100644 index 00000000000..1af8221c3a1 --- /dev/null +++ b/modules/rosapps/applications/fraginator/DriveVolume.h @@ -0,0 +1,157 @@ +/***************************************************************************** + + DriveVolume + + Class for opening a volume and getting information on it and defragging it + and stuff. + +*****************************************************************************/ + + +#ifndef DRIVEVOLUME_H +#define DRIVEVOLUME_H + + +#include "Unfrag.h" +#include +#include + + +using namespace std; + +#pragma pack (push, 1) +typedef struct +{ + unsigned int Archive : 1; + unsigned int Compressed : 1; + unsigned int Directory : 1; + unsigned int Encrypted : 1; + unsigned int Hidden : 1; + unsigned int Normal : 1; + unsigned int Offline : 1; + unsigned int ReadOnly : 1; + unsigned int Reparse : 1; + unsigned int Sparse : 1; + unsigned int System : 1; + unsigned int Temporary : 1; + + // For defragmenting purposes and other information + unsigned int Unmovable : 1; // can we even touch it? + unsigned int Process : 1; // should we process it? + unsigned int AccessDenied : 1; // could we not open it? +} FileAttr; + + +typedef struct +{ + uint64 StartLCN; + uint64 Length; +} Extent; + + +typedef struct +{ + wstring Name; + uint32 DirIndice; // indice into directory list + uint64 Size; + uint64 Clusters; + FileAttr Attributes; + vector Fragments; +} FileInfo; + + +typedef vector FileList; + + +typedef struct +{ + wstring Name; + wstring Serial; + DWORD MaxNameLen; + wstring FileSystem; + uint64 ClusterCount; + uint32 ClusterSize; + uint64 TotalBytes; + uint64 FreeBytes; +} VolumeInfo; +#pragma pack (pop) + + +// Callback function for Scan() +// NOTE: Do *NOT* close the HANDLE given to you. It is provided for convenience, +// and is closed automatically by the function that calls you! +typedef bool (*ScanCallback) (FileInfo &Info, HANDLE &FileHandle, void *UserData); + + +extern bool BuildDBCallback (FileInfo &Info, HANDLE &FileHandle, void *UserData); + + +class DriveVolume +{ +public: + DriveVolume (); + ~DriveVolume (); + + bool Open (wstring Name); // opens the volume + void Close (void); + bool ObtainInfo (void); // retrieves drive geometry + bool GetBitmap (void); // gets drive bitmap + + // builds list of files on drive + // if QuitMonitor ever becomes true (ie from a separate thread) it will clean up and return + bool BuildFileList (bool &QuitMonitor, double &Progress); + + // Functions for accessing the volume bitmap + bool IsClusterUsed (uint64 Cluster); + void SetClusterUsed (uint64 Cluster, bool Used); + + DISK_GEOMETRY GetGeometry (void) { return (Geometry); } + VolumeInfo GetVolumeInfo (void) { return (VolInfo); } + + wstring GetRootPath (void) { return (RootPath); } + + // Scans drive starting from the root dir and calls a user defined function + // for each file/directory encountered. void* UserData is passed to this + // function so you can give it some good ol' fashioned context. + bool Scan (ScanCallback Callback, void *UserData); + + // Retrieve a directory string from the file database + wstring &GetDBDir (uint32 Indice); + uint32 GetDBDirCount (void); + // Retrieve file strings/info from the file database + FileInfo &GetDBFile (uint32 Indice); + uint32 GetDBFileCount (void); + // Kill it! + uint32 RemoveDBFile (uint32 Indice); + + // This is for actual defragmenting! It will automatically update the drive bitmap. + // Will not move any other files out of the way. + // Failure (return value of false) means that something is in the way. + bool MoveFileDumb (uint32 FileIndice, uint64 NewLCN); + + // Look for a range of sequential free clusters + // Returns true if one could be found, false if not + bool FindFreeRange (uint64 StartLCN, uint64 ReqLength, uint64 &LCNResult); + +private: + friend bool BuildDBCallback (FileInfo &Info, HANDLE &FileHandle, void *UserData); + + // DirPrefix should be in the form "drive:\\path\\" ie, C:\CRAP\ . + bool ScanDirectory (wstring DirPrefix, ScanCallback Callback, void *UserData); + + // given a file's attributes, should it be processed or not? + bool ShouldProcess (FileAttr Attr); + + bool GetClusterInfo (FileInfo &Info, HANDLE &HandleResult); + + VolumeInfo VolInfo; + FileList Files; + vector Directories; // Directories[Files[x].DirIndice] + wstring RootPath; // ie, C:\ . + HANDLE Handle; + DISK_GEOMETRY Geometry; + uint32 *BitmapDetail; +}; + + +#endif // DRIVEVOLUME_H diff --git a/modules/rosapps/applications/fraginator/Fraginator Motif Icon.bmp b/modules/rosapps/applications/fraginator/Fraginator Motif Icon.bmp new file mode 100644 index 00000000000..b8d412e8227 Binary files /dev/null and b/modules/rosapps/applications/fraginator/Fraginator Motif Icon.bmp differ diff --git a/modules/rosapps/applications/fraginator/Fraginator.cpp b/modules/rosapps/applications/fraginator/Fraginator.cpp new file mode 100644 index 00000000000..11908cd9451 --- /dev/null +++ b/modules/rosapps/applications/fraginator/Fraginator.cpp @@ -0,0 +1,64 @@ +/***************************************************************************** + + Fraginator + +*****************************************************************************/ + +#define NDEBUG + +#include "Fraginator.h" +#include "Mutex.h" +#include "DriveVolume.h" +#include "Defragment.h" +#include "MainDialog.h" +#include "resource.h" +#ifdef _MSC_VER +#include +#endif + +HINSTANCE GlobalHInstance = NULL; +Defragment *Defrag = NULL; + +INT WINAPI +wWinMain(HINSTANCE HInstance, + HINSTANCE hPrev, + LPWSTR Cmd, + int iCmd) +{ + INITCOMMONCONTROLSEX InitControls; + + // debugging crap +#ifndef NDEBUG + _CrtSetDbgFlag (_CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG)); + _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDOUT); + _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDOUT); + _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDOUT); +#endif + + GlobalHInstance = HInstance; + + // We want our progress bar! NOW! + InitControls.dwSize = sizeof (InitControls); + InitControls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx (&InitControls); + + if (!CheckWinVer()) + { + MessageBox (GetDesktopWindow(), L"Sorry, this program requires Windows 2000.", L"Error", MB_OK); + return (0); + } + + DialogBox (HInstance, MAKEINTRESOURCE (IDD_MAIN), GetDesktopWindow(), MainDialogProc); + +#if 0 + AllocConsole (); + if (_CrtDumpMemoryLeaks ()) + MessageBox (NULL, L"Click OK to quit", L"Leaks", MB_OK); +#endif + + return (0); +} + diff --git a/modules/rosapps/applications/fraginator/Fraginator.h b/modules/rosapps/applications/fraginator/Fraginator.h new file mode 100644 index 00000000000..5e764ede5bd --- /dev/null +++ b/modules/rosapps/applications/fraginator/Fraginator.h @@ -0,0 +1,25 @@ +/***************************************************************************** + + Fraginator !!! + +*****************************************************************************/ + + +#ifndef FRAGINATOR_H +#define FRAGINATOR_H + + +#include "Unfrag.h" +#include + + +//int WINAPI WinMain (HINSTANCE HInstance, HINSTANCE HPrevInstance, LPSTR CmdLine, int ShowCmd); +Defragment *StartDefragBox (wstring Drive, DefragType Method); + + +extern HINSTANCE GlobalHInstance; +extern Defragment *Defrag; + +//extern INT PASCAL wWinMain (HINSTANCE HInstance, HINSTANCE HPrevInstance, LPCWSTR CmdLine, INT ShowCmd); + +#endif // FRAGINATOR_H diff --git a/modules/rosapps/applications/fraginator/Fraginator.rc b/modules/rosapps/applications/fraginator/Fraginator.rc new file mode 100644 index 00000000000..463454098d9 --- /dev/null +++ b/modules/rosapps/applications/fraginator/Fraginator.rc @@ -0,0 +1,21 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + + +#include "lang/en-US.rc" +#include "lang/es-ES.rc" +#include "lang/fr-FR.rc" +#include "lang/no-NO.rc" +#include "lang/sk-SK.rc" +#include "lang/uk-UA.rc" diff --git a/modules/rosapps/applications/fraginator/MainDialog.cpp b/modules/rosapps/applications/fraginator/MainDialog.cpp new file mode 100644 index 00000000000..b91e56631b9 --- /dev/null +++ b/modules/rosapps/applications/fraginator/MainDialog.cpp @@ -0,0 +1,574 @@ +#include "Unfrag.h" +#include "MainDialog.h" +#include "resource.h" +#include "Fraginator.h" +#include "Defragment.h" +#include "ReportDialog.h" + + +vector DrivesList; +LRESULT AnalyzeID; +LRESULT FastID; +LRESULT ExtensiveID; +bool QuitWhenDone; +bool Stopping; + + +LRESULT PriHighID; +LRESULT PriAboveNormID; +LRESULT PriNormalID; +LRESULT PriBelowNormID; +LRESULT PriIdleID; + + +static void InitDialog (HWND Dlg); +void UpdateDefragInfo (HWND Dlg); +void UpdatePriority (HWND Dlg); +wstring GetDefaultTitle (void); +wstring GetDefragTitle (void); +void SetDisables (HWND Dlg); +INT_PTR CALLBACK MainDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam); + + +static void InitDialog (HWND Dlg) +{ + // Make internal list + DWORD DriveMask; + HWND DlgItem; + size_t d; + + // Clear out wisecracks line for now + SetDlgItemText (Dlg, IDC_WISECRACKS, L"\"Defrag, baby!\""); + + // Make list of logical drives + DrivesList.resize (0); + DriveMask = GetLogicalDrives (); + + for (d = 0; d < 26; d++) + { + if (DriveMask & (1 << d)) + { + wstring Name; + + Name = (wchar_t)(L'A' + d); + Name += L':'; + DrivesList.push_back (Name); + } + } + + // Give list to dropdown list + DlgItem = GetDlgItem (Dlg, IDC_DRIVES_LIST); + SendMessage (DlgItem, CB_RESETCONTENT, 0, 0); + for (d = 0; d < DrivesList.size(); d++) + { + SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) DrivesList[d].c_str()); + } + + // Put in defrag methods + DlgItem = GetDlgItem (Dlg, IDC_METHODS_LIST); + SendMessage (DlgItem, CB_RESETCONTENT, 0, 0); + AnalyzeID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Analyze Only"); + FastID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Fast Defrag"); + ExtensiveID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Extensive Defrag"); + + // Set up process priorities + DlgItem = GetDlgItem (Dlg, IDC_PRIORITY_LIST); + SendMessage (Dlg, CB_RESETCONTENT, 0, 0); + PriHighID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"High"); + PriAboveNormID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Above Normal"); + PriNormalID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Normal"); + PriBelowNormID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Below Normal"); + PriIdleID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Idle"); + UpdatePriority (Dlg); + + // Reset texts and progress meters + SendDlgItemMessage (Dlg, IDC_STATUS, WM_SETTEXT, 0, (LPARAM) L""); + SendDlgItemMessage (Dlg, IDC_PERCENT, WM_SETTEXT, 0, (LPARAM) L""); + SendDlgItemMessage (Dlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM (0, 10000)); + SendDlgItemMessage (Dlg, IDC_PROGRESS, PBM_SETPOS, 0, 0); + + return; +} + + +void UpdateDefragInfo (HWND Dlg) +{ + wchar_t PercentText[100]; + static double OldPercent = 200.0f; + static wstring OldStatus = L"Non"; + wstring NewStatus; + double NewPercent; + + if (Defrag == NULL) + return; + + NewPercent = Defrag->GetStatusPercent (); + if (NewPercent > 100.0f) + NewPercent = 100.0f; + if (NewPercent < 0.0f) + NewPercent = 0.0f; + if (NewPercent != OldPercent) + { + swprintf (PercentText, L"%6.2f%%", NewPercent); + SendDlgItemMessage (Dlg, IDC_PERCENT, WM_SETTEXT, 0, (LPARAM) PercentText); + SendDlgItemMessage (Dlg, IDC_PROGRESS, PBM_SETPOS, + (WPARAM) (int)(NewPercent * 100.0f), 0); + OldPercent = NewPercent; + } + + NewStatus = Defrag->GetStatusString (); + if (NewStatus != OldStatus) + { // Change & characters to && to avoid underlining + wstring Status; + wstring::iterator it; + + Status = NewStatus; + it = Status.begin (); + while (it < Status.end()) + { + if (*it == L'&') + { + Status.insert (it, 1, L'&'); + it++; + } + + it++; + } + + SendDlgItemMessage (Dlg, IDC_STATUS, WM_SETTEXT, 0, + (LPARAM) Status.c_str()); + + OldStatus = NewStatus; + } + + return; +} + + +wstring GetDefaultTitle (void) +{ + wstring DefaultText; + + DefaultText = wstring(wstring(APPNAME_GUI) + wstring(L" v") + wstring(APPVER_STR) + + wstring(L" (C) 2000 by Rick Brewster")); + + return (DefaultText); +} + + +wstring GetDefragTitle (void) +{ + wstring DefragText; + wchar_t Percent[10]; + + swprintf (Percent, L"%.2f%%", Defrag->GetStatusPercent()); + + DefragText = GetDefaultTitle (); + if (Defrag != NULL) + { + DefragText = wstring(Percent) + wstring (L" - ") + Defrag->GetVolume().GetRootPath() + + wstring (L" - ") + DefragText; + } + + return (DefragText); +} + + +void SetDisables (HWND Dlg) +{ + // If a defrag is in process, set L'Start' button to say L'Stop' and disable + // the Select Drive and Select Action controls + if (Defrag != NULL && !Defrag->IsDoneYet() && !Defrag->HasError()) + { + SendMessage (GetDlgItem (Dlg, IDC_STARTSTOP), WM_SETTEXT, 0, (LPARAM) L"Stop"); + EnableWindow (GetDlgItem (Dlg, IDC_DRIVES_LIST), FALSE); + EnableWindow (GetDlgItem (Dlg, IDC_METHODS_LIST), FALSE); + } + else + { + SendMessage (GetDlgItem (Dlg, IDC_STARTSTOP), WM_SETTEXT, 0, (LPARAM) L"Start"); + EnableWindow (GetDlgItem (Dlg, IDC_STARTSTOP), TRUE); + EnableWindow (GetDlgItem (Dlg, IDC_QUIT), TRUE); + EnableWindow (GetDlgItem (Dlg, IDC_DRIVES_LIST), TRUE); + EnableWindow (GetDlgItem (Dlg, IDC_METHODS_LIST), TRUE); + } + + return; +} + + +void UpdatePriority (HWND Dlg) +{ + LRESULT Id; + DWORD Priority; + + Id = SendDlgItemMessage (Dlg, IDC_PRIORITY_LIST, CB_GETCURSEL, 0, 0); + + if (Id == PriHighID) + Priority = HIGH_PRIORITY_CLASS; + else + if (Id == PriAboveNormID) + Priority = ABOVE_NORMAL_PRIORITY_CLASS; + else + if (Id == PriNormalID) + Priority = NORMAL_PRIORITY_CLASS; + else + if (Id == PriBelowNormID) + Priority = BELOW_NORMAL_PRIORITY_CLASS; + else + if (Id == PriIdleID) + Priority = IDLE_PRIORITY_CLASS; + else + return; + + SetPriorityClass (GetCurrentProcess(), Priority); + return; +} + + +// Save settings (ie, process priority and defrag type options) +bool GetRegKeys (HKEY *RegKeyResult) +{ + HKEY RegKey; + LONG Error; + + Error = RegCreateKeyEx + ( + HKEY_CURRENT_USER, + L"Software\\Fraginator", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &RegKey, + NULL + ); + + if (Error != ERROR_SUCCESS) + return (false); + + *RegKeyResult = RegKey; + return (true); +} + + +bool DoneRegKey (HKEY RegKey) +{ + RegCloseKey (RegKey); + return (true); +} + + +void SaveSettings (HWND Dlg) +{ + LRESULT DefragID; + DWORD DefragVal; + LRESULT PriID; + DWORD PriVal; + HKEY RegKey; + + DefragID = SendDlgItemMessage (Dlg, IDC_METHODS_LIST, CB_GETCURSEL, 0, 0); + PriID = SendDlgItemMessage (Dlg, IDC_PRIORITY_LIST, CB_GETCURSEL, 0, 0); + + // Action + if (DefragID == AnalyzeID) + DefragVal = (DWORD) DefragAnalyze; + else + if (DefragID == FastID) + DefragVal = (DWORD) DefragFast; + else + if (DefragID == ExtensiveID) + DefragVal = (DWORD) DefragExtensive; + + // Process Priority + if (PriID == PriHighID) + PriVal = HIGH_PRIORITY_CLASS; + else + if (PriID == PriAboveNormID) + PriVal = ABOVE_NORMAL_PRIORITY_CLASS; + else + if (PriID == PriNormalID) + PriVal = NORMAL_PRIORITY_CLASS; + else + if (PriID == PriBelowNormID) + PriVal = BELOW_NORMAL_PRIORITY_CLASS; + else + if (PriID == PriIdleID) + PriVal = IDLE_PRIORITY_CLASS; + + if (!GetRegKeys (&RegKey)) + return; + + RegSetValueEx + ( + RegKey, + L"Default Action", + 0, + REG_DWORD, + (CONST BYTE *)&DefragVal, + sizeof (DefragVal) + ); + + RegSetValueEx + ( + RegKey, + L"Process Priority", + 0, + REG_DWORD, + (CONST BYTE *)&PriVal, + sizeof (PriVal) + ); + + DoneRegKey (RegKey); + return; +} + + +void LoadSettings (HWND Dlg) +{ + DefragType DType; + DWORD DTypeVal; + LRESULT DefragID; + DWORD PriVal; + LRESULT PriID; + HKEY RegKey; + DWORD RegType; + DWORD RegSize; + LONG Error; + + if (!GetRegKeys (&RegKey)) + return; + + RegSize = sizeof (DTypeVal); + RegType = REG_DWORD; + + Error = RegQueryValueEx + ( + RegKey, + L"Default Action", + 0, + &RegType, + (BYTE *)&DTypeVal, + &RegSize + ); + + if (Error != ERROR_SUCCESS) + DTypeVal = DefragAnalyze; + + Error = RegQueryValueEx + ( + RegKey, + L"Process Priority", + 0, + &RegType, + (BYTE *)&PriVal, + &RegSize + ); + + DoneRegKey (RegKey); + + if (Error != ERROR_SUCCESS) + PriVal = NORMAL_PRIORITY_CLASS; + + DType = (DefragType) DTypeVal; + switch (DType) + { + default: + case DefragAnalyze: + DefragID = AnalyzeID; + break; + + case DefragFast: + DefragID = FastID; + break; + + case DefragExtensive: + DefragID = ExtensiveID; + break; + } + + switch (PriVal) + { + case HIGH_PRIORITY_CLASS: + PriID = PriHighID; + break; + + case ABOVE_NORMAL_PRIORITY_CLASS: + PriID = PriAboveNormID; + break; + + default: + case NORMAL_PRIORITY_CLASS: + PriID = PriNormalID; + break; + + case BELOW_NORMAL_PRIORITY_CLASS: + PriID = PriBelowNormID; + break; + + case IDLE_PRIORITY_CLASS: + PriID = PriIdleID; + break; + } + + SendDlgItemMessage (Dlg, IDC_PRIORITY_LIST, CB_SETCURSEL, PriID, 0); + SendDlgItemMessage (Dlg, IDC_METHODS_LIST, CB_SETCURSEL, DefragID, 0); + return; +} + + +#define IDLETIME 25 +wstring OldWindowText = L""; + +INT_PTR CALLBACK MainDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam) +{ + static bool ReEntrance = false; + + switch (Msg) + { + case WM_INITDIALOG: + Stopping = false; + SetWindowText (Dlg, GetDefaultTitle().c_str()); + SetDisables (Dlg); + InitDialog (Dlg); + SetTimer (Dlg, 1, IDLETIME, NULL); + SetClassLong (Dlg, GCL_HICON, (LONG) LoadIcon (GlobalHInstance, MAKEINTRESOURCE(IDI_ICON))); + QuitWhenDone = false; + LoadSettings (Dlg); + UpdatePriority (Dlg); + return (1); + + + case WM_TIMER: + if (Defrag != NULL && !ReEntrance) + { + wstring NewTitle; + + SendMessage (Dlg, WM_UPDATEINFO, 0, 0); + + NewTitle = GetDefragTitle (); + if (NewTitle != OldWindowText) + { + OldWindowText = NewTitle; + SetWindowText (Dlg, NewTitle.c_str()); + } + + if (Defrag->IsDoneYet() || Defrag->HasError()) + { // This is the code executed when defragging is finished (or stopped :) + if (Defrag->GetDefragType() == DefragAnalyze && + !Defrag->HasError() && + !Stopping) + { // Show report + ReEntrance = true; + + DialogBoxParam (GlobalHInstance, MAKEINTRESOURCE (IDD_REPORT), + Dlg, ReportDialogProc, (LPARAM) Defrag); + + ReEntrance = false; + } + + delete Defrag; + Defrag = NULL; + SetDisables (Dlg); + SetWindowText (Dlg, GetDefaultTitle().c_str()); + + Stopping = false; + + if (QuitWhenDone) + SendMessage (GetDlgItem (Dlg, IDC_QUIT), BM_CLICK, 0, 0); + } + } + + SetTimer (Dlg, 1, IDLETIME, NULL); + return (0); + + + case WM_UPDATEINFO: + UpdateDefragInfo (Dlg); + return (1); + + + case WM_CLOSE: + SendMessage (GetDlgItem (Dlg, IDC_QUIT), BM_CLICK, 0, 0); + return (1); + + + case WM_COMMAND: + switch (LOWORD(WParam)) + { + case IDC_PRIORITY_LIST: + UpdatePriority (Dlg); + return (1); + + + case ID_MAIN_HELP: + ShellExecute (Dlg, L"open", L"Fraginator.chm", L"", L".", SW_SHOW); + return (1); + + + case IDC_QUIT: + if (Defrag == NULL) + { // This is the code executing when quitting + SaveSettings (Dlg); + EndDialog (Dlg, 0); + } + else + { // Tell defragging to finish and disable our button + QuitWhenDone = true; + SendMessage (GetDlgItem (Dlg, IDC_STARTSTOP), BM_CLICK, 0, 0); + EnableWindow (GetDlgItem (Dlg, IDC_QUIT), FALSE); + } + return (1); + + + case IDC_STARTSTOP: + if (Defrag == NULL) + { // L"Start" + wchar_t Drive[10]; + LRESULT ID; + DefragType Method; + HANDLE H; + + if (Defrag != NULL) + return (1); + + SendMessage (GetDlgItem (Dlg, IDC_DRIVES_LIST), WM_GETTEXT, + sizeof (Drive) - 1, (LPARAM) Drive); + + if (wcslen(Drive) != 2 || Drive[1] != L':') + return (1); + + ID = SendMessage (GetDlgItem (Dlg, IDC_METHODS_LIST), CB_GETCURSEL, 0, 0); + Method = DefragInvalid; + if (ID == AnalyzeID) + Method = DefragAnalyze; + else + if (ID == FastID) + Method = DefragFast; + else + if (ID == ExtensiveID) + Method = DefragExtensive; + + if (Method != DefragInvalid) + { + Defrag = StartDefragThread (Drive, Method, H); + Defrag->SetDoLimitLength (false); + SetWindowText (Dlg, GetDefragTitle().c_str()); + SetDisables (Dlg); + } + } + else + { // L"Stop" + Stopping = true; + Defrag->Stop (); + EnableWindow (GetDlgItem (Dlg, IDC_STARTSTOP), FALSE); + EnableWindow (GetDlgItem (Dlg, IDC_QUIT), FALSE); + } + return (1); + } + } + + // Otherwise, return 0 to say we did not process the message. + return (0); +} diff --git a/modules/rosapps/applications/fraginator/MainDialog.h b/modules/rosapps/applications/fraginator/MainDialog.h new file mode 100644 index 00000000000..073512c21b4 --- /dev/null +++ b/modules/rosapps/applications/fraginator/MainDialog.h @@ -0,0 +1,14 @@ +#ifndef MAINDIALOG_H +#define MAINDIALOG_H + + +#include + + +#define WM_UPDATEINFO (WM_USER + 1) + + +INT_PTR CALLBACK MainDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam); + + +#endif // MAINDIALOG_H diff --git a/modules/rosapps/applications/fraginator/Mutex.h b/modules/rosapps/applications/fraginator/Mutex.h new file mode 100644 index 00000000000..d646c34856c --- /dev/null +++ b/modules/rosapps/applications/fraginator/Mutex.h @@ -0,0 +1,78 @@ +/***************************************************************************** + + Mutex + +*****************************************************************************/ + + +#ifndef MUTEX_H +#define MUTEX_H + + +#include "Unfrag.h" + + +class Mutex +{ +public: + Mutex () + { + // NT only code begin ... Win9x disregards this part + SECURITY_ATTRIBUTES MutexAttribs; + + memset (&MutexAttribs, 0, sizeof (SECURITY_ATTRIBUTES)); + + MutexAttribs.bInheritHandle = false; + MutexAttribs.nLength = sizeof (SECURITY_ATTRIBUTES); + MutexAttribs.lpSecurityDescriptor = NULL; + // NT only code end + + Locked = false; + LockCount = 0; + MutexHandle = CreateMutex (&MutexAttribs, Locked, NULL); + + return; + } + + ~Mutex () + { + Lock (); + CloseHandle (MutexHandle); + } + + void Lock (void) + { + Locked = true; + WaitForSingleObject (MutexHandle, INFINITE); + LockCount += 1; + return; + } + + + void Unlock (void) + { + LockCount -= 1; + if (LockCount <= 0) + { + LockCount = 0; + Locked = false; + } + + ReleaseMutex (MutexHandle); + return; + } + + + bool IsLocked (void) + { + return (Locked); + } + +protected: + uint32 LockCount; + HANDLE MutexHandle; + bool Locked; +}; + + +#endif // MUTEX_H diff --git a/modules/rosapps/applications/fraginator/ReportDialog.cpp b/modules/rosapps/applications/fraginator/ReportDialog.cpp new file mode 100644 index 00000000000..b3f34e34f19 --- /dev/null +++ b/modules/rosapps/applications/fraginator/ReportDialog.cpp @@ -0,0 +1,231 @@ +#include "ReportDialog.h" +#include "Unfrag.h" +#include "Fraginator.h" +#include "DriveVolume.h" +#include "Defragment.h" +#include "resource.h" + + +void SetReportInfo (HWND Dlg, DefragReport &Report, uint32 BytesDivisor, wchar_t *BytesUnits, bool Fractional) +{ + wchar_t Text[1000]; + wchar_t Text2[1000]; + wchar_t Text3[1000]; + + memset (Text, 0, sizeof (Text)); + + // Volume name + SetDlgItemText (Dlg, IDC_DRIVELETTER, Report.RootPath.c_str()); + + // Volume label + SetDlgItemText (Dlg, IDC_VOLUMELABEL, Defrag->GetVolume().GetVolumeInfo().Name.c_str()); + + // Volume Serial + SetDlgItemText (Dlg, IDC_VOLUMESERIAL, Defrag->GetVolume().GetVolumeInfo().Serial.c_str()); + + // File System + SetDlgItemText (Dlg, IDC_FILESYSTEM, Defrag->GetVolume().GetVolumeInfo().FileSystem.c_str()); + + // DiskSizeBytes + if (Fractional) + { + swprintf (Text, L"%.2f %s", (double)(signed)(Report.DiskSizeBytes / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, Report.DiskSizeBytes / BytesDivisor); + wcscat (Text, L" "); + wcscat (Text, BytesUnits); + } + + SetDlgItemText (Dlg, IDC_DISKSIZEBYTES, Text); + + // DiskFreeBytes + if (Fractional) + { + swprintf (Text, L"%.2f %s", (double)(signed)(Defrag->GetVolume().GetVolumeInfo().FreeBytes / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, Defrag->GetVolume().GetVolumeInfo().FreeBytes / BytesDivisor); + wcscat (Text, L" "); + wcscat (Text, BytesUnits); + } + SetDlgItemText (Dlg, IDC_DISKFREEBYTES, Text); + + // DiskSizeClusters + AddCommas (Text, Defrag->GetVolume().GetVolumeInfo().ClusterCount); + wcscat (Text, L" clusters"); + SetDlgItemText (Dlg, IDC_DISKSIZECLUSTERS, Text); + + // DiskClusterSize + swprintf (Text, L"%u bytes", Defrag->GetVolume().GetVolumeInfo().ClusterSize); + SetDlgItemText (Dlg, IDC_DISKCLUSTERSIZE, Text); + + // DirsCount + AddCommas (Text, Report.DirsCount); + SetDlgItemText (Dlg, IDC_DIRSCOUNT, Text); + + // FilesCount + AddCommas (Text, Report.FilesCount); + SetDlgItemText (Dlg, IDC_FILESCOUNT, Text); + + // FilesFragged + swprintf (Text, L"(%.2f%%)", Report.PercentFragged); + AddCommas (Text2, Report.FraggedFiles.size()); + swprintf (Text3, L"%s %s", Text, Text2); + SetDlgItemText (Dlg, IDC_FILESFRAGGED, Text3); + + // Average Frags + swprintf (Text, L"%.2f", Report.AverageFragments); + SetDlgItemText (Dlg, IDC_AVERAGEFRAGS, Text); + + // FilesSizeBytes + if (Fractional) + { + swprintf (Text, L"%.2f %s", (double)(signed)(Report.FilesSizeBytes / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, Report.FilesSizeBytes / (uint64)BytesDivisor); + wcscat (Text, L" "); + wcscat (Text, BytesUnits); + } + SetDlgItemText (Dlg, IDC_FILESSIZEBYTES, Text); + + // Files SizeOnDisk + if (Fractional) + { + swprintf (Text, L"%.2f %s", (double)(signed)((Report.FilesSizeBytes + Report.FilesSlackBytes) / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, (Report.FilesSizeBytes + Report.FilesSlackBytes) / (uint64)BytesDivisor); + wcscat (Text, L" "); + wcscat (Text, BytesUnits); + + } + SetDlgItemText (Dlg, IDC_FILESSIZEONDISK, Text); + + // FilesSlackBytes + if (Fractional) + { + swprintf (Text, L"%.2f %s", (double)(signed)(Report.FilesSlackBytes / + (BytesDivisor / 1024)) / 1024.0, BytesUnits); + } + else + { + AddCommas (Text, Report.FilesSlackBytes / BytesDivisor); + wcscat (Text, L" "); + wcscat (Text, BytesUnits); + } + swprintf (Text2, L"(%.2f%%)", Report.PercentSlack); + swprintf (Text3, L"%s %s", Text2, Text); + SetDlgItemText (Dlg, IDC_FILESSLACKBYTES, Text3); + + // Recommendation + bool PFRec = false; // Recommend based off percent fragged files? + bool AFRec = false; // Recommend based off average fragments per file? + + if (Report.PercentFragged >= 5.0f) + PFRec = true; + + if (Report.AverageFragments >= 1.1f) + AFRec = true; + + wcscpy (Text, L"* "); + + if (PFRec) + { + swprintf + ( + Text2, + L"%.2f%% of the files on this volume are fragmented. ", + Report.PercentFragged + ); + + wcscat (Text, Text2); + } + + if (AFRec) + { + swprintf + ( + Text2, + L"The average fragments per file (%.2f) indicates a high degree of fragmentation. ", + Report.AverageFragments + ); + + wcscat (Text, Text2); + } + + if (Report.PercentFragged < 5.0f && Report.AverageFragments < 1.1f) + swprintf (Text, L"* No defragmentation is necessary at this point."); + else + if (Report.PercentFragged < 15.0f && Report.AverageFragments < 1.3f) + wcscat (Text, L"It is recommended that you perform a Fast Defrag."); + else + wcscat (Text, L"It is recommended that you perform an Extensive Defrag."); + + // Should we recommend a smaller cluster size? + if (Report.PercentSlack >= 10.0f) + { + swprintf + ( + Text2, + L"\n* A large amount of disk space (%.2f%%) is being lost " + L"due to a large (%u bytes) cluster size. It is recommended " + L"that you use a disk utility such as Partition Magic to " + L"reduce the cluster size of this volume.", + Report.PercentSlack, + Defrag->GetVolume().GetVolumeInfo().ClusterSize + ); + + wcscat (Text, Text2); + } + + SetDlgItemText (Dlg, IDC_RECOMMEND, Text); + + return; +} + + +INT_PTR CALLBACK ReportDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam) +{ + switch (Msg) + { + case WM_INITDIALOG: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1, L"bytes", false); + return (1); + + case WM_COMMAND: + switch (LOWORD(WParam)) + { + case IDC_REPORTOK: + EndDialog (Dlg, 0); + return (1); + + case IDC_GIGABYTES: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1024*1024*1024, L"GB", true); + return (1); + + case IDC_MEGABYTES: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1024*1024, L"MB", false); + return (1); + + case IDC_KILOBYTES: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1024, L"KB", false); + return (1); + + case IDC_BYTES: + SetReportInfo (Dlg, Defrag->GetDefragReport (), 1, L"bytes", false); + return (1); + } + } + + return (0); +} diff --git a/modules/rosapps/applications/fraginator/ReportDialog.h b/modules/rosapps/applications/fraginator/ReportDialog.h new file mode 100644 index 00000000000..930dbd430c0 --- /dev/null +++ b/modules/rosapps/applications/fraginator/ReportDialog.h @@ -0,0 +1,18 @@ +/***************************************************************************** + + ReportDialog + +*****************************************************************************/ + + +#ifndef REPORTDIALOG_H +#define REPORTDIALOG_H + + +#include + + +INT_PTR CALLBACK ReportDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam); + + +#endif // REPORTDIALOG_H diff --git a/modules/rosapps/applications/fraginator/Unfrag.cpp b/modules/rosapps/applications/fraginator/Unfrag.cpp new file mode 100644 index 00000000000..12df42a2291 --- /dev/null +++ b/modules/rosapps/applications/fraginator/Unfrag.cpp @@ -0,0 +1,463 @@ +/***************************************************************************** + + Unfrag + +*****************************************************************************/ + + +#include "Unfrag.h" +#include "DriveVolume.h" +#include "Defragment.h" +#include + + +bool QuietMode = false; +bool VerboseMode = false; + + +// Makes sure we're in Windows 2000 +bool CheckWinVer (void) +{ + OSVERSIONINFO OSVersion; + + ZeroMemory (&OSVersion, sizeof (OSVersion)); + OSVersion.dwOSVersionInfoSize = sizeof (OSVersion); + GetVersionEx (&OSVersion); + + // Need Windows 2000! + + // Check for NT first + // Actually what we do is check that weLL're not on Win31+Win32s and that we're + // not in Windows 9x. It's possible that there could be more Windows "platforms" + // in the future and there's no sense in claiming incompatibility. + if (OSVersion.dwPlatformId == VER_PLATFORM_WIN32s || + OSVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + return (false); + } + + // Ok weLL're in Windows NT, now make sure we're in 2000 + if (OSVersion.dwMajorVersion < 5) + return (false); + + // Kew, we're in at least Windows 2000 ("NT 5.0") + return (true); +} + + +wchar_t *AddCommas (wchar_t *Result, uint64 Number) +{ + wchar_t Temp[128]; + int TempLen; + //wchar_t *p = NULL; + int AddCommas = 0; + wchar_t *StrPosResult = NULL; + wchar_t *StrPosOrig = NULL; + + // we get the string form of the number, then we count down w/ AddCommas + // while copying the string from Temp1 to Result. when AddCommas % 3 == 1, + // slap in a commas as well, before the #. + swprintf (Temp, L"%I64u", Number); + AddCommas = TempLen = wcslen (Temp); + StrPosOrig = Temp; + StrPosResult = Result; + while (AddCommas) + { + if ((AddCommas % 3) == 0 && AddCommas != TempLen) // avoid stuff like ",345" + { + *StrPosResult = L','; + StrPosResult++; + } + + *StrPosResult = *StrPosOrig; + StrPosResult++; + StrPosOrig++; + + *StrPosResult = 0; + + AddCommas--; + } + + return (Result); +} + + +void PrintBanner (void) +{ + wprintf (L"%s v%s\n", APPNAME_CLI, APPVER_STR); + wprintf (L"%s\n", APPCOPYRIGHT); + wprintf (L"\n"); + + return; +} + + +void FraggerHelp (void) +{ + wprintf (L"Usage: unfrag drive: [...] <-f | -e>\n"); + wprintf (L"\n"); + wprintf (L"drive: : The drive to defrag. Should be two characters long, ie 'c:' or 'd:'.\n"); + wprintf (L" Multiple drives may be given, and all will be simultaneously\n"); + wprintf (L" defragmented using the same options.\n"); + wprintf (L"-f : Do a fast defragmentation. Files that are not fragmented will not be\n"); + wprintf (L" moved. Only one pass is made over the file list. Using this option\n"); + wprintf (L" may result in not all files being defragmented, depending on\n"); + wprintf (L" available disk space.\n"); + wprintf (L"-e : Do an extensive defragmention. Files will be moved in an attempt to\n"); + wprintf (L" defragment both files and free space.\n"); + + if (!CheckWinVer()) + { + wprintf (L"\n"); + wprintf (L"NOTE: This program requires Windows 2000, which is not presently running on\n"); + wprintf (L"this system.\n"); + } + + return; +} + + +void __cdecl DefragThread (LPVOID parm) +{ + Defragment *Defrag; + + Defrag = (Defragment *) parm; + Defrag->Start (); + + _endthread (); + return; +} + + +Defragment *StartDefragThread (wstring Drive, DefragType Method, HANDLE &Handle) +{ + Defragment *Defragger; + unsigned long Thread; + + Defragger = new Defragment (Drive, Method); + //Thread = /*CreateThread*/ _beginthreadex (NULL, 0, DefragThread, Defragger, 0, &ThreadID); + Thread = _beginthread (DefragThread, 0, Defragger); + Handle = *((HANDLE *)&Thread); + return (Defragger); +} + + +// Main Initialization +int wmain (int argc, wchar_t **argv) +{ + vector Drives; + vector Defrags; + DefragType DefragMode = DefragInvalid; + + PrintBanner (); + + // Parse command line arguments + bool ValidCmdLine = false; + for (int c = 0; c < argc; c++) + { + if (wcslen(argv[c]) == 2 && argv[c][1] == L':') + { + Drives.push_back (wcsupr(argv[c])); + } + else + if (argv[c][0] == L'-' || argv[c][0] == L'/' && wcslen(argv[c]) == 2) + { + switch (tolower(argv[c][1])) + { + case L'?' : + case L'h' : + FraggerHelp (); + return (0); + + case L'f' : + if (DefragMode != DefragInvalid) + { + ValidCmdLine = false; + break; + } + DefragMode = DefragFast; + ValidCmdLine = true; + break; + + case L'e' : + if (DefragMode != DefragInvalid) + { + ValidCmdLine = false; + break; + } + DefragMode = DefragExtensive; + ValidCmdLine = true; + break; + + } + } + } + + if (DefragMode == DefragInvalid) + ValidCmdLine = false; + + if (!ValidCmdLine) + { + wprintf (L"Invalid command-line options. Use '%s -?' for help.\n", argv[0]); + return (0); + } + + // Check OS requirements + if (!CheckWinVer()) + { + wprintf (L"Fatal Error: This program requires Windows 2000.\n"); + return (0); + } + + for (size_t d = 0; d < Drives.size (); d++) + { + HANDLE TossMe; + Defrags.push_back (StartDefragThread (Drives[d], DefragMode, TossMe)); + } + + for (size_t d = 0; d < Drives.size () - 1; d++) + wprintf (L"\n "); + + bool Continue = true; + HANDLE Screen; + + Screen = GetStdHandle (STD_OUTPUT_HANDLE); + while (Continue) + { + Sleep (25); + + // Get current screen coords + CONSOLE_SCREEN_BUFFER_INFO ScreenInfo; + + GetConsoleScreenBufferInfo (Screen, &ScreenInfo); + + // Now set back to the beginning + ScreenInfo.dwCursorPosition.X = 0; + ScreenInfo.dwCursorPosition.Y -= Drives.size(); + SetConsoleCursorPosition (Screen, ScreenInfo.dwCursorPosition); + + for (size_t d = 0; d < Drives.size (); d++) + { + wprintf (L"\n%6.2f%% %-70s", Defrags[d]->GetStatusPercent(), Defrags[d]->GetStatusString().c_str()); + } + + // Determine if we should keep going + Continue = false; + for (size_t d = 0; d < Drives.size (); d++) + { + if (!Defrags[d]->IsDoneYet() && !Defrags[d]->HasError()) + Continue = true; + } + } + +#if 0 + // Loop through the drives list + for (int d = 0; d < Drives.size(); d++) + { + DriveVolume *Drive; + + Drive = new DriveVolume; + + // First thing: build a file list. + wprintf (L"Opening volume %s ...", Drives[d].c_str()); + if (!Drive->Open (Drives[d])) + { + wprintf (L"FAILED\n\n"); + delete Drive; + continue; + } + wprintf (L"\n"); + + wprintf (L" Getting drive bitmap ..."); + if (!Drive->GetBitmap ()) + { + wprintf (L"FAILED\n\n"); + delete Drive; + continue; + } + wprintf (L"\n"); + + wprintf (L" Obtaining drive geometry ..."); + if (!Drive->ObtainInfo ()) + { + wprintf (L"FAILED\n\n"); + delete Drive; + continue; + } + wprintf (L"\n"); + + wprintf (L" Building file database for drive %s ...", Drives[d].c_str()); + if (!Drive->BuildFileList ()) + { + wprintf (L"FAILED\n\n"); + delete Drive; + continue; + } + wprintf (L"\n"); + + wprintf (L" %u files\n", Drive->GetDBFileCount ()); + + // Analyze only? + if (DefragMode == DefragAnalyze) + { + uint64 UsedBytes = 0; // total bytes used, with cluster size considerations + uint64 TotalBytes = 0; // total bytes used + uint64 SlackBytes = 0; // wasted space due to slack + uint32 Fragged = 0; // fragmented files + + wprintf (L" Analyzing ..."); + if (VerboseMode) + wprintf (L"\n"); + + for (int i = 0; i < Drive->GetDBFileCount(); i++) + { + uint64 Used; + uint64 Slack; + FileInfo Info; + + Info = Drive->GetDBFile (i); + + // Compute total used disk space + Used = ((Info.Size + Drive->GetClusterSize() - 1) / Drive->GetClusterSize()) * Drive->GetClusterSize(); + Slack = Used - Info.Size; + + UsedBytes += Used; + SlackBytes += Slack; + TotalBytes += Info.Size; + + if (VerboseMode) + { + wprintf (L" %s%s, ", Drive->GetDBDir (Info.DirIndice).c_str(), Info.Name.c_str()); + + if (Info.Attributes.AccessDenied) + wprintf (L"access was denied\n"); + else + { + if (Info.Attributes.Unmovable == 1) + wprintf (L"unmovable, "); + + wprintf (L"%I64u bytes, %I64u bytes on disk, %I64u bytes slack, %u fragments\n", + Info.Size, Used, Slack, Info.Fragments.size()); + } + } + + if (Info.Fragments.size() > 1) + Fragged++; + } + + if (!VerboseMode) + wprintf (L"\n"); + + // TODO: Make it not look like ass + wprintf (L"\n"); + wprintf (L" Overall Analysis\n"); + wprintf (L" ----------------\n"); + wprintf (L" %u clusters\n", Drive->GetClusterCount ()); + wprintf (L" %u bytes per cluster\n", Drive->GetClusterSize()); + wprintf (L" %I64u total bytes on drive\n", (uint64)Drive->GetClusterCount() * (uint64)Drive->GetClusterSize()); + wprintf (L"\n"); + wprintf (L" %u files\n", Drive->GetDBFileCount ()); + wprintf (L" %u contiguous files\n", Drive->GetDBFileCount () - Fragged); + wprintf (L" %u fragmented files\n", Fragged); + wprintf (L"\n"); + wprintf (L" %I64u bytes\n", TotalBytes); + wprintf (L" %I64u bytes on disk\n", UsedBytes); + wprintf (L" %I64u bytes slack\n", SlackBytes); + } + + // Fast defragment! + if (DefragMode == DefragFast || DefragMode == DefragExtensive) + { + uint32 i; + uint64 FirstFreeLCN; + wchar_t PrintName[80]; + int Width = 66; + + if (DefragMode == DefragFast) + wprintf (L" Performing fast file defragmentation ...\n"); + else + if (DefragMode == DefragExtensive) + wprintf (L" Performing extensive file defragmentation\n"); + + // Find first free LCN for speedier searches ... + Drive->FindFreeRange (0, 1, FirstFreeLCN); + + for (i = 0; i < Drive->GetDBFileCount(); i++) + { + FileInfo Info; + bool Result; + uint64 TargetLCN; + + wprintf (L"\r"); + + Info = Drive->GetDBFile (i); + + FitName (PrintName, Drive->GetDBDir (Info.DirIndice).c_str(), Info.Name.c_str(), Width); + wprintf (L" %6.2f%% %-66s", (float)i / (float)Drive->GetDBFileCount() * 100.0f, PrintName); + + // Can't defrag 0 byte files :) + if (Info.Fragments.size() == 0) + continue; + + // If doing fast defrag, skip non-fragmented files + if (Info.Fragments.size() == 1 && DefragMode == DefragFast) + continue; + + // Find a place that can fit the file + Result = Drive->FindFreeRange (FirstFreeLCN, Info.Clusters, TargetLCN); + + // If we're doing an extensive defrag and the file is already defragmented + // and if its new location would be after its current location, don't + // move it. + if (DefragMode == DefragExtensive && Info.Fragments.size() == 1) + { + if (TargetLCN > Info.Fragments[0].StartLCN) + continue; + } + + // Otherwise, defrag0rize it! + if (Result) + { + bool Success = false; + + if (Drive->MoveFileDumb (i, TargetLCN)) + Success = true; + else + { // hmm, look for another area to move it to + Result = Drive->FindFreeRange (TargetLCN + 1, Info.Clusters, TargetLCN); + if (Result) + { + if (Drive->MoveFileDumb (i, TargetLCN)) + Success = true; + else + { // Try updating the drive bitmap + if (Drive->GetBitmap ()) + { + Result = Drive->FindFreeRange (0, Info.Clusters, TargetLCN); + if (Result) + { + if (Drive->MoveFileDumb (i, TargetLCN)) + Success = true; + } + } + } + } + } + + if (!Success) + wprintf (L"\n -> failed\n"); + + Drive->FindFreeRange (0, 1, FirstFreeLCN); + } + } + + wprintf (L"\n"); + } + wprintf (L"Closing volume %s ...", Drives[d].c_str()); + delete Drive; + wprintf (L"\n"); + } +#endif + + return (0); +} diff --git a/modules/rosapps/applications/fraginator/Unfrag.h b/modules/rosapps/applications/fraginator/Unfrag.h new file mode 100644 index 00000000000..274e59d0ae2 --- /dev/null +++ b/modules/rosapps/applications/fraginator/Unfrag.h @@ -0,0 +1,86 @@ +/***************************************************************************** + + Unfrag + +*****************************************************************************/ + + +#ifndef UNFRAG_H +#define UNFRAG_H + + +// Blah blah blah your template name is too long ... SO WHAT +#ifdef _MSC_VER +#pragma warning (disable: 4786) +#endif + +// I forget what this disables +#ifdef __ICL +#pragma warning (disable: 268) +#endif + + +// Hello Mr. Platform SDK, please let us use Windows 2000 only features +#if 0 +#ifndef WINVER +#define WINVER 0x0500 +#define _WIN32_WINNT 0x0500 +#endif +#endif + +#include +#include +#include +#include +//#include +#include + +#define APPNAME_CLI L"Unfrag" +#define APPNAME_GUI L"Fraginator" +#define APPVER_STR L"1.03" +#define APPVER_NUM 1.03f +#define APPAUTHOR L"Rick Brewster" +#define APPCOPYRIGHT L"Copyright 2000-2002 Rick Brewster" + + +#include +#include +using namespace std; + + +typedef unsigned __int8 uint8; +typedef signed __int8 sint8; +typedef unsigned __int16 uint16; +typedef signed __int16 sint16; +typedef unsigned __int32 uint32; +typedef signed __int32 sint32; +typedef unsigned __int64 uint64; +typedef signed __int64 sint64; +typedef unsigned char uchar; + + +extern bool QuietMode; +extern bool VerboseMode; + + +typedef enum +{ + DefragInvalid, + DefragFast, + DefragExtensive, + DefragAnalyze +} DefragType; + + +extern bool CheckWinVer (void); + + +class Defragment; +extern Defragment *StartDefragThread (wstring Drive, DefragType Method, HANDLE &Handle); + + +extern wchar_t *AddCommas (wchar_t *Result, uint64 Number); + + +#endif // UNFRAG_H + diff --git a/modules/rosapps/applications/fraginator/fraginator.rbuild b/modules/rosapps/applications/fraginator/fraginator.rbuild new file mode 100644 index 00000000000..bba34e4c537 --- /dev/null +++ b/modules/rosapps/applications/fraginator/fraginator.rbuild @@ -0,0 +1,26 @@ + + + + + . + advapi32 + ntdll + comctl32 + msvcrt + Fraginator.cpp + MainDialog.cpp + Defragment.cpp + DriveVolume.cpp + ReportDialog.cpp + Unfrag.cpp + + + + . + advapi32 + ntdll + Unfrag.cpp + Defragment.cpp + DriveVolume.cpp + + diff --git a/modules/rosapps/applications/fraginator/icon1.ico b/modules/rosapps/applications/fraginator/icon1.ico new file mode 100644 index 00000000000..4acbd2ca4a6 Binary files /dev/null and b/modules/rosapps/applications/fraginator/icon1.ico differ diff --git a/modules/rosapps/applications/fraginator/lang/en-US.rc b/modules/rosapps/applications/fraginator/lang/en-US.rc new file mode 100644 index 00000000000..2e9e0cfb279 --- /dev/null +++ b/modules/rosapps/applications/fraginator/lang/en-US.rc @@ -0,0 +1,230 @@ +// Microsoft Visual C++ generated resource script. +// + +///////////////////////////////////////////////////////////////////////////// +// 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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MAIN DIALOGEX 0, 0, 346, 103 +STYLE DS_SHELLFONT | DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_DRIVES_LIST,78,52,29,111,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_METHODS_LIST,135,52,77,79,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_PRIORITY_LIST,223,52,59,91,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Start",IDC_STARTSTOP,294,7,45,15 + PUSHBUTTON "Help",ID_MAIN_HELP,294,28,45,15 + PUSHBUTTON "Exit",IDC_QUIT,294,49,45,15 + CONTROL 110,-1,"Static",SS_BITMAP | SS_SUNKEN | + WS_BORDER,7,7,63,58 + LTEXT "Choose a drive:",-1,78,40,50,8 + LTEXT "Choose an action:",-1,135,40,58,8 + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER | + 0x1,7,71,299,10 + CONTROL "Static",IDC_STATUS,"Static",SS_LEFTNOWORDWRAP | + SS_SUNKEN | WS_GROUP,7,86,332,10 + LTEXT "I am a monkey, hear me eeK",IDC_WISECRACKS,78,15,91,8 + LTEXT "100.00%",IDC_PERCENT,311,71,28,8,0,WS_EX_RIGHT + LTEXT "Process Priority:",-1,223,40,51,8 +END + +IDD_REPORT DIALOGEX 0, 0, 391, 169 +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION +CAPTION "Report" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "Bytes",IDC_BYTES,7,148,50,14 + DEFPUSHBUTTON "Kilobytes",IDC_KILOBYTES,61,148,50,14 + DEFPUSHBUTTON "Megabytes",IDC_MEGABYTES,115,148,50,14 + DEFPUSHBUTTON "Gigabytes",IDC_GIGABYTES,169,148,50,14 + DEFPUSHBUTTON "OK",IDC_REPORTOK,334,148,50,14 + RTEXT "Volume",-1,7,7,24,8 + LTEXT "Capacity",-1,7,51,28,8 + RTEXT "(Drive Letter)",IDC_DRIVELETTER,63,7,117,10,SS_SUNKEN + RTEXT "(Disk Size, Bytes)",IDC_DISKSIZEBYTES,63,51,117,10, + SS_SUNKEN + RTEXT "(Disk Size, Clusters)",IDC_DISKSIZECLUSTERS,63,73,117, + 10,SS_SUNKEN + LTEXT "Total clusters",-1,7,73,43,8 + RTEXT "(Cluster size)",IDC_DISKCLUSTERSIZE,63,84,117,10, + SS_SUNKEN + LTEXT "Cluster size",-1,7,84,36,8 + RTEXT "(Files count)",IDC_FILESCOUNT,267,18,117,10,SS_SUNKEN + RTEXT "(Files size, bytes)",IDC_FILESSIZEBYTES,267,29,117,10, + SS_SUNKEN + LTEXT "# of files",-1,194,18,28,8 + LTEXT "Total size",-1,194,29,31,8 + LTEXT "Size on disk",-1,194,40,39,8 + RTEXT "(Total size, bytes)",IDC_FILESSIZEONDISK,267,40,117,10, + SS_SUNKEN + RTEXT "(Files slack bytes)",IDC_FILESSLACKBYTES,267,51,117,10, + SS_SUNKEN + LTEXT "Wasted slack",-1,194,51,44,8 + RTEXT "(Disk Free, Bytes)",IDC_DISKFREEBYTES,63,62,117,10, + SS_SUNKEN + LTEXT "Free space",-1,7,62,36,8 + RTEXT "(Files fragmented, count)",IDC_FILESFRAGGED,267,62,117, + 10,SS_SUNKEN + LTEXT "Fragmented files",-1,194,62,52,8 + RTEXT "(Dirs count)",IDC_DIRSCOUNT,267,7,117,10,SS_SUNKEN + LTEXT "# of directories",-1,194,7,48,8 + RTEXT "File System",-1,7,40,36,8 + RTEXT "(File System Name)",IDC_FILESYSTEM,63,40,117,10, + SS_SUNKEN + RTEXT "Volume Label",-1,7,18,44,8 + RTEXT "(Volume Name)",IDC_VOLUMELABEL,63,18,117,10,SS_SUNKEN + RTEXT "Serial",-1,7,29,18,8 + RTEXT "(Volume Serial)",IDC_VOLUMESERIAL,63,29,117,10, + SS_SUNKEN + RTEXT "(Average Frags Per File)",IDC_AVERAGEFRAGS,267,73,117, + 10,SS_SUNKEN + LTEXT "Average fragments per file",-1,194,73,60,20 + LTEXT "XX.X% of the files on this drive are fragmented. It is recommended that you perform a SSSSSSS defragmentation.", + IDC_RECOMMEND,7,106,377,38,SS_SUNKEN + LTEXT "Recommendations:",-1,7,96,62,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_MAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 339 + TOPMARGIN, 7 + BOTTOMMARGIN, 96 + END + + IDD_REPORT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 384 + TOPMARGIN, 7 + BOTTOMMARGIN, 162 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", " " + VALUE "FileDescription", "Fraginator" + VALUE "FileVersion", "1.03" + VALUE "InternalName", "Fraginator" + VALUE "LegalCopyright", "Copyright © 2000-2002 Rick Brewster" + VALUE "OriginalFilename", "Fraginator.exe" + VALUE "ProductName", "Fraginator" + VALUE "ProductVersion", "1.03" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_LOGO BITMAP "Fraginator Motif Icon.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST "default1.bin" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/modules/rosapps/applications/fraginator/lang/es-ES.rc b/modules/rosapps/applications/fraginator/lang/es-ES.rc new file mode 100644 index 00000000000..2c37d3371c8 --- /dev/null +++ b/modules/rosapps/applications/fraginator/lang/es-ES.rc @@ -0,0 +1,229 @@ +// Microsoft Visual C++ generated resource script. +// + +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MAIN DIALOGEX 0, 0, 346, 103 +STYLE DS_SHELLFONT | DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_DRIVES_LIST,78,52,29,111,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_METHODS_LIST,135,52,77,79,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_PRIORITY_LIST,223,52,59,91,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Comenzar",IDC_STARTSTOP,294,7,45,15 + PUSHBUTTON "Ayuda",ID_MAIN_HELP,294,28,45,15 + PUSHBUTTON "Salir",IDC_QUIT,294,49,45,15 + CONTROL 110,-1,"Static",SS_BITMAP | SS_SUNKEN | + WS_BORDER,7,7,63,58 + LTEXT "Seleccione una unidad:",-1,78,40,50,8 + LTEXT "Seleccione una acción:",-1,135,40,58,8 + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER | + 0x1,7,71,299,10 + CONTROL "Static",IDC_STATUS,"Static",SS_LEFTNOWORDWRAP | + SS_SUNKEN | WS_GROUP,7,86,332,10 + LTEXT "I am a monkey, hear me eeK",IDC_WISECRACKS,78,15,91,8 + LTEXT "100.00%",IDC_PERCENT,311,71,28,8,0,WS_EX_RIGHT + LTEXT "Prioridad del proceso:",-1,223,40,51,8 +END + +IDD_REPORT DIALOGEX 0, 0, 391, 169 +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION +CAPTION "Informe" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "Bytes",IDC_BYTES,7,148,50,14 + DEFPUSHBUTTON "Kilobytes",IDC_KILOBYTES,61,148,50,14 + DEFPUSHBUTTON "Megabytes",IDC_MEGABYTES,115,148,50,14 + DEFPUSHBUTTON "Gigabytes",IDC_GIGABYTES,169,148,50,14 + DEFPUSHBUTTON "Aceptar",IDC_REPORTOK,334,148,50,14 + RTEXT "Volumen",-1,7,7,24,8 + LTEXT "Capacidad",-1,7,51,28,8 + RTEXT "(Letra de la unidad)",IDC_DRIVELETTER,63,7,117,10,SS_SUNKEN + RTEXT "(Tamaño del disco, Bytes)",IDC_DISKSIZEBYTES,63,51,117,10, + SS_SUNKEN + RTEXT "(Tamaño del disco, Clusters)",IDC_DISKSIZECLUSTERS,63,73,117, + 10,SS_SUNKEN + LTEXT "Clusters totales",-1,7,73,43,8 + RTEXT "(Tamaño del Cluster)",IDC_DISKCLUSTERSIZE,63,84,117,10, + SS_SUNKEN + LTEXT "Tamaño del Cluster",-1,7,84,36,8 + RTEXT "(Cantidad de archivos)",IDC_FILESCOUNT,267,18,117,10,SS_SUNKEN + RTEXT "(Tamaño de archivos, bytes)",IDC_FILESSIZEBYTES,267,29,117,10, + SS_SUNKEN + LTEXT "# de archivos",-1,194,18,28,8 + LTEXT "Tamaño total",-1,194,29,31,8 + LTEXT "Tamaño en disco",-1,194,40,39,8 + RTEXT "(Tamaño total, bytes)",IDC_FILESSIZEONDISK,267,40,117,10, + SS_SUNKEN + RTEXT "(Files slack bytes)",IDC_FILESSLACKBYTES,267,51,117,10, + SS_SUNKEN + LTEXT "Wasted slack",-1,194,51,44,8 + RTEXT "(Espacio libre, Bytes)",IDC_DISKFREEBYTES,63,62,117,10, + SS_SUNKEN + LTEXT "Espacio libre",-1,7,62,36,8 + RTEXT "(Archivos fragmentados, cantidad)",IDC_FILESFRAGGED,267,62,117, + 10,SS_SUNKEN + LTEXT "Archivos fragmentados",-1,194,62,52,8 + RTEXT "(Cantidad de directorios)",IDC_DIRSCOUNT,267,7,117,10,SS_SUNKEN + LTEXT "# de directorios",-1,194,7,48,8 + RTEXT "Sistema de archivos",-1,7,40,36,8 + RTEXT "(Nombre del sistema de archivos)",IDC_FILESYSTEM,63,40,117,10, + SS_SUNKEN + RTEXT "Etiqueta del volumen",-1,7,18,44,8 + RTEXT "(Etiqueta del volumen)",IDC_VOLUMELABEL,63,18,117,10,SS_SUNKEN + RTEXT "Serie",-1,7,29,18,8 + RTEXT "(Serie del volumen)",IDC_VOLUMESERIAL,63,29,117,10, + SS_SUNKEN + RTEXT "(Media de fragmentos por archivo)",IDC_AVERAGEFRAGS,267,73,117, + 10,SS_SUNKEN + LTEXT "Media de fragmentos por archivo",-1,194,73,60,20 + LTEXT "XX.X% de los archivos de esta unidad están fragmentados. Es recomendable que realice una SSSSSSS defragmentación.", + IDC_RECOMMEND,7,106,377,38,SS_SUNKEN + LTEXT "Recomendaciones:",-1,7,96,62,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_MAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 339 + TOPMARGIN, 7 + BOTTOMMARGIN, 96 + END + + IDD_REPORT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 384 + TOPMARGIN, 7 + BOTTOMMARGIN, 162 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Organización", " " + VALUE "FileDescription", "Fraginator" + VALUE "Versión del archivo", "1.03" + VALUE "Nombre interno", "Fraginator" + VALUE "Copyright", "Copyright © 2000-2002 Rick Brewster" + VALUE "Nombre original del archivo", "Fraginator.exe" + VALUE "Nombre del producto", "Fraginator" + VALUE "Versión del producto", "1.03" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_LOGO BITMAP "Fraginator Motif Icon.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST "default1.bin" +#endif // Spanish resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/modules/rosapps/applications/fraginator/lang/fr-FR.rc b/modules/rosapps/applications/fraginator/lang/fr-FR.rc new file mode 100644 index 00000000000..be1f3795566 --- /dev/null +++ b/modules/rosapps/applications/fraginator/lang/fr-FR.rc @@ -0,0 +1,230 @@ +// Microsoft Visual C++ generated resource script. +// + +///////////////////////////////////////////////////////////////////////////// +// French resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MAIN DIALOGEX 0, 0, 346, 103 +STYLE DS_SHELLFONT | DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_DRIVES_LIST,78,52,29,111,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_METHODS_LIST,135,52,77,79,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_PRIORITY_LIST,223,52,59,91,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Démarrer",IDC_STARTSTOP,294,7,45,15 + PUSHBUTTON "Aide",ID_MAIN_HELP,294,28,45,15 + PUSHBUTTON "Quitter",IDC_QUIT,294,49,45,15 + CONTROL 110,-1,"Static",SS_BITMAP | SS_SUNKEN | + WS_BORDER,7,7,63,58 + LTEXT "Choisissez un lecteur :",-1,78,40,50,8 + LTEXT "Choisissez une action :",-1,135,40,58,8 + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER | + 0x1,7,71,299,10 + CONTROL "Static",IDC_STATUS,"Static",SS_LEFTNOWORDWRAP | + SS_SUNKEN | WS_GROUP,7,86,332,10 + LTEXT "Je suis un singe, ententez-moi eeK",IDC_WISECRACKS,78,15,91,8 + LTEXT "100.00%",IDC_PERCENT,311,71,28,8,0,WS_EX_RIGHT + LTEXT "Priorité du processus :",-1,223,40,51,8 +END + +IDD_REPORT DIALOGEX 0, 0, 391, 169 +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION +CAPTION "Rapport" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "Octets",IDC_BYTES,7,148,50,14 + DEFPUSHBUTTON "Kilooctets",IDC_KILOBYTES,61,148,50,14 + DEFPUSHBUTTON "Mégaoctets",IDC_MEGABYTES,115,148,50,14 + DEFPUSHBUTTON "Gigaoctets",IDC_GIGABYTES,169,148,50,14 + DEFPUSHBUTTON "OK",IDC_REPORTOK,334,148,50,14 + RTEXT "Volume",-1,7,7,24,8 + LTEXT "Capacité",-1,7,51,28,8 + RTEXT "(Lettre du lecteur)",IDC_DRIVELETTER,63,7,117,10,SS_SUNKEN + RTEXT "(Taille du disque, Octets)",IDC_DISKSIZEBYTES,63,51,117,10, + SS_SUNKEN + RTEXT "(Taille du disque, Clusters)",IDC_DISKSIZECLUSTERS,63,73,117, + 10,SS_SUNKEN + LTEXT "Nombre de clusters",-1,7,73,43,8 + RTEXT "(Taille d'un Cluster)",IDC_DISKCLUSTERSIZE,63,84,117,10, + SS_SUNKEN + LTEXT "Taille d'un cluster",-1,7,84,36,8 + RTEXT "(Nombre de fichiers)",IDC_FILESCOUNT,267,18,117,10,SS_SUNKEN + RTEXT "(Taille des fichiers, octets)",IDC_FILESSIZEBYTES,267,29,117,10, + SS_SUNKEN + LTEXT "# des fichiers",-1,194,18,28,8 + LTEXT "Taille totale",-1,194,29,31,8 + LTEXT "Taille sur le disque",-1,194,40,39,8 + RTEXT "(Taille totale, octets)",IDC_FILESSIZEONDISK,267,40,117,10, + SS_SUNKEN + RTEXT "(Octets perdus par les fichiers)",IDC_FILESSLACKBYTES,267,51,117,10, + SS_SUNKEN + LTEXT "Espace perdu",-1,194,51,44,8 + RTEXT "(Espace libre, octets)",IDC_DISKFREEBYTES,63,62,117,10, + SS_SUNKEN + LTEXT "Espace libre",-1,7,62,36,8 + RTEXT "(Fichiers fragmentés, nombre)",IDC_FILESFRAGGED,267,62,117, + 10,SS_SUNKEN + LTEXT "Fichiers fragmentés",-1,194,62,52,8 + RTEXT "(Nombre de répertoires)",IDC_DIRSCOUNT,267,7,117,10,SS_SUNKEN + LTEXT "# répertoires",-1,194,7,48,8 + RTEXT "Système de fichiers",-1,7,40,36,8 + RTEXT "(Nom du système de fichiers)",IDC_FILESYSTEM,63,40,117,10, + SS_SUNKEN + RTEXT "Nom du volume",-1,7,18,44,8 + RTEXT "(Nom du volume)",IDC_VOLUMELABEL,63,18,117,10,SS_SUNKEN + RTEXT "Numéro de série",-1,7,29,18,8 + RTEXT "(Numéro de série du volume)",IDC_VOLUMESERIAL,63,29,117,10, + SS_SUNKEN + RTEXT "(Fragements par fichier en moyenne)",IDC_AVERAGEFRAGS,267,73,117, + 10,SS_SUNKEN + LTEXT "Fragements par fichier en moyenne",-1,194,73,60,20 + LTEXT "XX.X% des fichiers sur ce lecteur sont fragmentés. Il est recommandé que vous effectuiez une défragmentation.", + IDC_RECOMMEND,7,106,377,38,SS_SUNKEN + LTEXT "Recommandations :",-1,7,96,62,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_MAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 339 + TOPMARGIN, 7 + BOTTOMMARGIN, 96 + END + + IDD_REPORT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 384 + TOPMARGIN, 7 + BOTTOMMARGIN, 162 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", " " + VALUE "FileDescription", "Fraginator" + VALUE "FileVersion", "1.03" + VALUE "InternalName", "Fraginator" + VALUE "LegalCopyright", "Copyright © 2000-2002 Rick Brewster" + VALUE "OriginalFilename", "Fraginator.exe" + VALUE "ProductName", "Fraginator" + VALUE "ProductVersion", "1.03" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_LOGO BITMAP "Fraginator Motif Icon.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST "default1.bin" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/modules/rosapps/applications/fraginator/lang/no-NO.rc b/modules/rosapps/applications/fraginator/lang/no-NO.rc new file mode 100644 index 00000000000..86a12cd7377 --- /dev/null +++ b/modules/rosapps/applications/fraginator/lang/no-NO.rc @@ -0,0 +1,230 @@ +// Microsoft Visual C++ generated resource script. +// + +///////////////////////////////////////////////////////////////////////////// +// Norwegian (N.O.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MAIN DIALOGEX 0, 0, 346, 103 +STYLE DS_SHELLFONT | DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_DRIVES_LIST,78,52,29,111,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_METHODS_LIST,135,52,77,79,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_PRIORITY_LIST,223,52,59,91,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Start",IDC_STARTSTOP,294,7,45,15 + PUSHBUTTON "Hjelp",ID_MAIN_HELP,294,28,45,15 + PUSHBUTTON "Avslutt",IDC_QUIT,294,49,45,15 + CONTROL 110,-1,"Static",SS_BITMAP | SS_SUNKEN | + WS_BORDER,7,7,63,58 + LTEXT "Velg en stasjon:",-1,78,40,50,8 + LTEXT "Velg en handling:",-1,135,40,58,8 + CONTROL "Prosess1",IDC_PROGRESS,"msctls_progress32",WS_BORDER | + 0x1,7,71,299,10 + CONTROL "Statisk",IDC_STATUS,"Statisk",SS_LEFTNOWORDWRAP | + SS_SUNKEN | WS_GROUP,7,86,332,10 + LTEXT "Jeg er en ape, hør meg eeK",IDC_WISECRACKS,78,15,91,8 + LTEXT "100.00%",IDC_PERCENT,311,71,28,8,0,WS_EX_RIGHT + LTEXT "Prosess proritet:",-1,223,40,51,8 +END + +IDD_REPORT DIALOGEX 0, 0, 391, 169 +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION +CAPTION "Rapport" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "Byte",IDC_BYTES,7,148,50,14 + DEFPUSHBUTTON "KB",IDC_KILOBYTES,61,148,50,14 + DEFPUSHBUTTON "MB",IDC_MEGABYTES,115,148,50,14 + DEFPUSHBUTTON "GB",IDC_GIGABYTES,169,148,50,14 + DEFPUSHBUTTON "OK",IDC_REPORTOK,334,148,50,14 + RTEXT "Stasjon",-1,7,7,24,8 + LTEXT "Kapasitet",-1,7,51,28,8 + RTEXT "(Stasjon bokstav)",IDC_DRIVELETTER,63,7,117,10,SS_SUNKEN + RTEXT "(Disk størrelse, Byte)",IDC_DISKSIZEBYTES,63,51,117,10, + SS_SUNKEN + RTEXT "(Disk størrelse, Cluster)",IDC_DISKSIZECLUSTERS,63,73,117, + 10,SS_SUNKEN + LTEXT "Total clusters",-1,7,73,43,8 + RTEXT "(Cluster størrelse)",IDC_DISKCLUSTERSIZE,63,84,117,10, + SS_SUNKEN + LTEXT "Cluster størrelse",-1,7,84,36,8 + RTEXT "(Files count)",IDC_FILESCOUNT,267,18,117,10,SS_SUNKEN + RTEXT "(Fil størrelse, byte)",IDC_FILESSIZEBYTES,267,29,117,10, + SS_SUNKEN + LTEXT "# filer",-1,194,18,28,8 + LTEXT "Total størrelse",-1,194,29,31,8 + LTEXT "diskstørrelse",-1,194,40,39,8 + RTEXT "(Total størrelse, byte)",IDC_FILESSIZEONDISK,267,40,117,10, + SS_SUNKEN + RTEXT "(Fil slack byte)",IDC_FILESSLACKBYTES,267,51,117,10, + SS_SUNKEN + LTEXT "Wasted slack",-1,194,51,44,8 + RTEXT "(Ledig plass, Byte)",IDC_DISKFREEBYTES,63,62,117,10, + SS_SUNKEN + LTEXT "Ledig plass",-1,7,62,36,8 + RTEXT "(Filer fragmentert, count)",IDC_FILESFRAGGED,267,62,117, + 10,SS_SUNKEN + LTEXT "Fragmenterte filer",-1,194,62,52,8 + RTEXT "(Dirs count)",IDC_DIRSCOUNT,267,7,117,10,SS_SUNKEN + LTEXT "# mapper",-1,194,7,48,8 + RTEXT "Filsystem",-1,7,40,36,8 + RTEXT "(Filsystem navn)",IDC_FILESYSTEM,63,40,117,10, + SS_SUNKEN + RTEXT "Volume Label",-1,7,18,44,8 + RTEXT "(Stasjon navn)",IDC_VOLUMELABEL,63,18,117,10,SS_SUNKEN + RTEXT "Serial",-1,7,29,18,8 + RTEXT "(Volume Serial)",IDC_VOLUMESERIAL,63,29,117,10, + SS_SUNKEN + RTEXT "(Average Frags Per File)",IDC_AVERAGEFRAGS,267,73,117, + 10,SS_SUNKEN + LTEXT "Average fragments per file",-1,194,73,60,20 + LTEXT "XX.X% av disse filene på denne stasjonen er fragmentert. Det er anbefalt at du utfører en SSSSSSS defragmentasjon.", + IDC_RECOMMEND,7,106,377,38,SS_SUNKEN + LTEXT "Anbefalinger:",-1,7,96,62,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_MAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 339 + TOPMARGIN, 7 + BOTTOMMARGIN, 96 + END + + IDD_REPORT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 384 + TOPMARGIN, 7 + BOTTOMMARGIN, 162 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Bedriftnavn", " " + VALUE "Filbeskrivelse", "Fraginator" + VALUE "Filversjon", "1.03" + VALUE "Internasjonaltnavn", "Fraginator" + VALUE "LegalCopyright", "enerett © 2000-2002 Rick Brewster" + VALUE "Originalfilnavn", "Fraginator.exe" + VALUE "Produktnavn", "Fraginator" + VALUE "ProduktVersjon", "1.03" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_LOGO BITMAP "Fraginator Motif Icon.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST "default1.bin" +#endif // Norwegian (N.O.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/modules/rosapps/applications/fraginator/lang/sk-SK.rc b/modules/rosapps/applications/fraginator/lang/sk-SK.rc new file mode 100644 index 00000000000..ad07d82382f --- /dev/null +++ b/modules/rosapps/applications/fraginator/lang/sk-SK.rc @@ -0,0 +1,234 @@ +/* TRANSLATOR : Mário Kaèmár /Mario Kacmar/ aka Kario (kario@szm.sk) + * DATE OF TR.: 04-09-2008 + */ + +// Microsoft Visual C++ generated resource script. +// + +///////////////////////////////////////////////////////////////////////////// +// Slovak resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MAIN DIALOGEX 0, 0, 346, 103 +STYLE DS_SHELLFONT | DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_DRIVES_LIST,78,52,29,111,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_METHODS_LIST,135,52,77,79,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_PRIORITY_LIST,223,52,59,91,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Zaèa",IDC_STARTSTOP,294,7,45,15 + PUSHBUTTON "Pomocník",ID_MAIN_HELP,294,28,45,15 + PUSHBUTTON "Ukonèi",IDC_QUIT,294,49,45,15 + CONTROL 110,-1,"Static",SS_BITMAP | SS_SUNKEN | + WS_BORDER,7,7,63,58 + LTEXT "Vyberte jednotku:",-1,78,40,50,8 + LTEXT "Vyberte akciu:",-1,135,40,58,8 + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER | + 0x1,7,71,299,10 + CONTROL "Static",IDC_STATUS,"Static",SS_LEFTNOWORDWRAP | + SS_SUNKEN | WS_GROUP,7,86,332,10 + LTEXT "I am a monkey, hear me eeK",IDC_WISECRACKS,78,15,91,8 + LTEXT "100.00%",IDC_PERCENT,311,71,28,8,0,WS_EX_RIGHT + LTEXT "Priorita procesu:",-1,223,40,51,8 +END + +IDD_REPORT DIALOGEX 0, 0, 391, 169 +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION +CAPTION "Hlásenie" //Report +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "Bajty",IDC_BYTES,7,148,50,14 + DEFPUSHBUTTON "Kilobajty",IDC_KILOBYTES,61,148,50,14 + DEFPUSHBUTTON "Megabajty",IDC_MEGABYTES,115,148,50,14 + DEFPUSHBUTTON "Gigabajty",IDC_GIGABYTES,169,148,50,14 + DEFPUSHBUTTON "OK",IDC_REPORTOK,334,148,50,14 + RTEXT "Médium",-1,7,7,24,8 //Volume + LTEXT "Kapacita",-1,7,51,28,8 + RTEXT "(Písmeno jednotky)",IDC_DRIVELETTER,63,7,117,10,SS_SUNKEN + RTEXT "(Ve¾kos disku, bajty)",IDC_DISKSIZEBYTES,63,51,117,10, + SS_SUNKEN + RTEXT "(Ve¾kos disku, klastre)",IDC_DISKSIZECLUSTERS,63,73,117, + 10,SS_SUNKEN + LTEXT "Klastrov spolu",-1,7,73,43,8 //Total clusters, Súèet klastrov, Klastrov celkom + RTEXT "(Ve¾kos klastra)",IDC_DISKCLUSTERSIZE,63,84,117,10, + SS_SUNKEN + LTEXT "Ve¾kos klastra",-1,7,84,36,8 + RTEXT "(Poèe súborov)",IDC_FILESCOUNT,267,18,117,10,SS_SUNKEN + RTEXT "(Poèe súborov, bajty)",IDC_FILESSIZEBYTES,267,29,117,10, + SS_SUNKEN + LTEXT "# súborov",-1,194,18,28,8 + LTEXT "Celková ve¾kos",-1,194,29,31,8 + LTEXT "Ve¾kos disku",-1,194,40,39,8 + RTEXT "(Celková ve¾kos, bajty)",IDC_FILESSIZEONDISK,267,40,117,10, + SS_SUNKEN + RTEXT "(Files slack bytes)",IDC_FILESSLACKBYTES,267,51,117,10, + SS_SUNKEN + LTEXT "Wasted slack",-1,194,51,44,8 + RTEXT "(Disk Free, Bytes)",IDC_DISKFREEBYTES,63,62,117,10, + SS_SUNKEN + LTEXT "Vo¾né miesto",-1,7,62,36,8 + RTEXT "(Fragmentované súbory, poèet)",IDC_FILESFRAGGED,267,62,117, + 10,SS_SUNKEN + LTEXT "Fragmentované súbory",-1,194,62,52,8 + RTEXT "(Poèet adresárov)",IDC_DIRSCOUNT,267,7,117,10,SS_SUNKEN + LTEXT "# adresárov",-1,194,7,48,8 + RTEXT "Systém súborov",-1,7,40,36,8 + RTEXT "(Názov systému súborov)",IDC_FILESYSTEM,63,40,117,10, + SS_SUNKEN + RTEXT "Volume Label",-1,7,18,44,8 + RTEXT "(Volume Name)",IDC_VOLUMELABEL,63,18,117,10,SS_SUNKEN + RTEXT "Serial",-1,7,29,18,8 + RTEXT "(Volume Serial)",IDC_VOLUMESERIAL,63,29,117,10, + SS_SUNKEN + RTEXT "(Priemerne fragmentov na súbor)",IDC_AVERAGEFRAGS,267,73,117, + 10,SS_SUNKEN + LTEXT "Priemerne fragmentov na súbor",-1,194,73,60,20 + LTEXT "XX.X% súborov na tejto jednotke je fragmentovaných. Odporúèa sa, aby ste vykonali SSSSSSS defragmentáciu.", + IDC_RECOMMEND,7,106,377,38,SS_SUNKEN + LTEXT "Odporúèania:",-1,7,96,62,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_MAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 339 + TOPMARGIN, 7 + BOTTOMMARGIN, 96 + END + + IDD_REPORT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 384 + TOPMARGIN, 7 + BOTTOMMARGIN, 162 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Názov spoloènosti", " " + VALUE "Popis súboru", "Fraginator" + VALUE "Verzia súboru", "1.03" + VALUE "Vnútorný názov", "Fraginator" + VALUE "Autorské práva", "Copyright © 2000-2002 Rick Brewster" + VALUE "Pôvodný názov súboru", "Fraginator.exe" + VALUE "Názov produktu", "Fraginator" + VALUE "Verzia produktu", "1.03" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_LOGO BITMAP "Fraginator Motif Icon.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST "default1.bin" +#endif // Slovak resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/modules/rosapps/applications/fraginator/lang/uk-UA.rc b/modules/rosapps/applications/fraginator/lang/uk-UA.rc new file mode 100644 index 00000000000..d078206c092 --- /dev/null +++ b/modules/rosapps/applications/fraginator/lang/uk-UA.rc @@ -0,0 +1,230 @@ +// Microsoft Visual C++ generated resource script. +// + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MAIN DIALOGEX 0, 0, 346, 103 +STYLE DS_SHELLFONT | DS_CENTERMOUSE | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_DRIVES_LIST,78,52,29,111,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_METHODS_LIST,135,52,77,79,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_PRIORITY_LIST,223,52,59,91,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Ñòàðò",IDC_STARTSTOP,294,7,45,15 + PUSHBUTTON "Äîïîìîãà",ID_MAIN_HELP,294,28,45,15 + PUSHBUTTON "Âèõ³ä",IDC_QUIT,294,49,45,15 + CONTROL 110,-1,"Static",SS_BITMAP | SS_SUNKEN | + WS_BORDER,7,7,63,58 + LTEXT "Âèáåð³òü äèñê:",-1,78,40,50,8 + LTEXT "Âèáåð³òü ä³þ:",-1,135,40,58,8 + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER | + 0x1,7,71,299,10 + CONTROL "Static",IDC_STATUS,"Static",SS_LEFTNOWORDWRAP | + SS_SUNKEN | WS_GROUP,7,86,332,10 + LTEXT "I am a monkey, hear me eeK",IDC_WISECRACKS,78,15,91,8 + LTEXT "100.00%",IDC_PERCENT,311,71,28,8,0,WS_EX_RIGHT + LTEXT "Ïð³îðèòåò Ïðîöåñó:",-1,223,40,51,8 +END + +IDD_REPORT DIALOGEX 0, 0, 391, 169 +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION +CAPTION "Ðàïîðò" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "Áàéò",IDC_BYTES,7,148,50,14 + DEFPUSHBUTTON "ʳëîáàéò",IDC_KILOBYTES,61,148,50,14 + DEFPUSHBUTTON "Ìåãàáàéò",IDC_MEGABYTES,115,148,50,14 + DEFPUSHBUTTON "óãàáàéò",IDC_GIGABYTES,169,148,50,14 + DEFPUSHBUTTON "Òàê",IDC_REPORTOK,334,148,50,14 + RTEXT "Òîì",-1,7,7,24,8 + LTEXT "Îá'ºì",-1,7,51,28,8 + RTEXT "(Áóêâà Äèñêó)",IDC_DRIVELETTER,63,7,117,10,SS_SUNKEN + RTEXT "(Ðîçì³ð Äèñêó, Áàéò³â)",IDC_DISKSIZEBYTES,63,51,117,10, + SS_SUNKEN + RTEXT "(Ðîçì³ð äèñêó, Êëàñòåð³â)",IDC_DISKSIZECLUSTERS,63,73,117, + 10,SS_SUNKEN + LTEXT "Âñüîãî êëàñòåð³â",-1,7,73,43,8 + RTEXT "(Ðîçì³ð êëàñòåðà)",IDC_DISKCLUSTERSIZE,63,84,117,10, + SS_SUNKEN + LTEXT "Ðîçì³ð êëàñòåðà",-1,7,84,36,8 + RTEXT "(ʳëü-ñòü ôàéë³â)",IDC_FILESCOUNT,267,18,117,10,SS_SUNKEN + RTEXT "(Ðîçì³ð ôàéë³â, áàéò³â)",IDC_FILESSIZEBYTES,267,29,117,10, + SS_SUNKEN + LTEXT "# ôàéë³â",-1,194,18,28,8 + LTEXT "Çàãàëüíèé ðîçì³ð",-1,194,29,31,8 + LTEXT "Ðîçì³ð íà äèñêó",-1,194,40,39,8 + RTEXT "(Çàãàëüíèé ðîçì³ð, áàéò³â)",IDC_FILESSIZEONDISK,267,40,117,10, + SS_SUNKEN + RTEXT "(Files slack bytes)",IDC_FILESSLACKBYTES,267,51,117,10, + SS_SUNKEN + LTEXT "Wasted slack",-1,194,51,44,8 + RTEXT "(Disk Free, Áàéò³â)",IDC_DISKFREEBYTES,63,62,117,10, + SS_SUNKEN + LTEXT "³ëüíå ì³ñöå",-1,7,62,36,8 + RTEXT "(Ôðàãìåíòîâàí³ ôàéëè, ê³ëüê³ñòü)",IDC_FILESFRAGGED,267,62,117, + 10,SS_SUNKEN + LTEXT "Ôðàãìåíòîâàí³ ôàéëè",-1,194,62,52,8 + RTEXT "(ʳëü-ñòü äèðåêòîð³é)",IDC_DIRSCOUNT,267,7,117,10,SS_SUNKEN + LTEXT "# äèðåêòîð³é",-1,194,7,48,8 + RTEXT "Ôàéëîâà Ñèñòåìà",-1,7,40,36,8 + RTEXT "(Íàçâà Ôàéëîâî¿ Ñèñòåìè)",IDC_FILESYSTEM,63,40,117,10, + SS_SUNKEN + RTEXT "̳òêà Òîìó",-1,7,18,44,8 + RTEXT "(Íàçâà Òîìó)",IDC_VOLUMELABEL,63,18,117,10,SS_SUNKEN + RTEXT "Serial",-1,7,29,18,8 + RTEXT "(Volume Serial)",IDC_VOLUMESERIAL,63,29,117,10, + SS_SUNKEN + RTEXT "(Average Frags Per File)",IDC_AVERAGEFRAGS,267,73,117, + 10,SS_SUNKEN + LTEXT "Ôðàãìåòí³â â ôàéë³ â ñåðåäíüîìó",-1,194,73,60,20 + LTEXT "XX.X% ôàéë³â íà öüîìó äèñêó ôðàãìåíòîâàí³. Áàæàíî ïðîâåñòè SSSSSSS äåôðàãìåíòàö³þ.", + IDC_RECOMMEND,7,106,377,38,SS_SUNKEN + LTEXT "Ðåêîìåíäàö³¿:",-1,7,96,62,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_MAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 339 + TOPMARGIN, 7 + BOTTOMMARGIN, 96 + END + + IDD_REPORT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 384 + TOPMARGIN, 7 + BOTTOMMARGIN, 162 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", " " + VALUE "FileDescription", "Fraginator" + VALUE "FileVersion", "1.03" + VALUE "InternalName", "Fraginator" + VALUE "LegalCopyright", "Copyright © 2000-2002 Rick Brewster" + VALUE "OriginalFilename", "Fraginator.exe" + VALUE "ProductName", "Fraginator" + VALUE "ProductVersion", "1.03" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_LOGO BITMAP "Fraginator Motif Icon.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "icon1.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST "default1.bin" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/modules/rosapps/applications/fraginator/resource.h b/modules/rosapps/applications/fraginator/resource.h new file mode 100644 index 00000000000..5fb3744986a --- /dev/null +++ b/modules/rosapps/applications/fraginator/resource.h @@ -0,0 +1,51 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Fraginator.rc +// +#define IDD_DIALOG1 101 +#define IDD_MAIN 101 +#define IDD_REPORT 106 +#define IDB_LOGO 110 +#define IDI_ICON 114 +#define IDC_QUIT 1010 +#define IDC_STARTSTOP 1014 +#define IDC_METHODS_LIST 1016 +#define IDC_DRIVES_LIST 1019 +#define IDC_PROGRESS 1021 +#define IDC_PERCENT 1022 +#define IDC_STATUS 1023 +#define IDC_DISKSIZEBYTES 1027 +#define IDC_DRIVELETTER 1028 +#define IDC_REPORTOK 1029 +#define IDC_DISKSIZECLUSTERS 1030 +#define IDC_DISKCLUSTERSIZE 1031 +#define IDC_FILESYSTEM 1032 +#define IDC_WISECRACKS 1033 +#define IDC_VOLUMELABEL 1033 +#define IDC_VOLUMESERIAL 1034 +#define IDC_BYTES 1035 +#define IDC_KILOBYTES 1036 +#define IDC_RECOMMEND 1037 +#define IDC_FILESCOUNT 1038 +#define IDC_FILESSIZEBYTES 1039 +#define IDC_FILESSIZEONDISK 1040 +#define IDC_FILESSLACKBYTES 1041 +#define IDC_GIGABYTES 1043 +#define IDC_DISKFREEBYTES 1044 +#define IDC_MEGABYTES 1045 +#define IDC_FILESFRAGGED 1047 +#define IDC_DIRSCOUNT 1048 +#define IDC_AVERAGEFRAGS 1049 +#define ID_MAIN_HELP 1054 +#define IDC_PRIORITY_LIST 1057 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 118 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1058 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/modules/rosapps/applications/imagesoft/CMakeLists.txt b/modules/rosapps/applications/imagesoft/CMakeLists.txt new file mode 100644 index 00000000000..d6661b85267 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/CMakeLists.txt @@ -0,0 +1,22 @@ + +list(APPEND SOURCE + about.c + adjust.c + brightness.c + contrast.c + custcombo.c + floatwindow.c + font.c + imagesoft.c + imgedwnd.c + mainwnd.c + misc.c + opensave.c + tooldock.c + imagesoft.rc) + +add_pch(imagesoft precomp.h) +add_executable(imagesoft ${SOURCE}) +set_module_type(imagesoft win32gui UNICODE) +add_importlibs(imagesoft gdi32 user32 advapi32 version comctl32 shell32 comdlg32 msvcrt kernel32) +add_cd_file(TARGET imagesoft DESTINATION reactos/system32 FOR all) diff --git a/modules/rosapps/applications/imagesoft/about.c b/modules/rosapps/applications/imagesoft/about.c new file mode 100644 index 00000000000..a53af44d64e --- /dev/null +++ b/modules/rosapps/applications/imagesoft/about.c @@ -0,0 +1,54 @@ +#include + +INT_PTR CALLBACK +AboutDialogProc(HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + HWND hLicenseEditWnd; + HICON hIcon = NULL; + TCHAR strLicense[700]; + + switch (message) + { + case WM_INITDIALOG: + + hIcon = (HICON) LoadImage(hInstance, + MAKEINTRESOURCE(IDI_IMAGESOFTICON), + IMAGE_ICON, + 16, + 16, + 0); + + SendMessage(hDlg, + WM_SETICON, + ICON_SMALL, + (LPARAM)hIcon); + + hLicenseEditWnd = GetDlgItem(hDlg, + IDC_LICENSE_EDIT); + + LoadString(hInstance, + IDS_LICENSE, + strLicense, + sizeof(strLicense) / sizeof(TCHAR)); + + SetWindowText(hLicenseEditWnd, + strLicense); + return TRUE; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL)) + { + DestroyIcon(hIcon); + EndDialog(hDlg, + LOWORD(wParam)); + return TRUE; + } + + break; + } + + return FALSE; +} diff --git a/modules/rosapps/applications/imagesoft/adjust.c b/modules/rosapps/applications/imagesoft/adjust.c new file mode 100644 index 00000000000..90ca2bf3f8a --- /dev/null +++ b/modules/rosapps/applications/imagesoft/adjust.c @@ -0,0 +1,525 @@ +#include + + +BOOL +DisplayBlackAndWhite(HWND hwnd, + HDC hdcMem, + HBITMAP hBitmap) +{ + BITMAPINFO bi; + BITMAP bitmap; + BOOL bRes; + DWORD Count = 0; + INT i, j; + PBYTE pBits; + RECT rc; + + GetObject(hBitmap, + sizeof(BITMAP), + &bitmap); + + /* Bitmap header */ + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = bitmap.bmWidth; + bi.bmiHeader.biHeight = bitmap.bmHeight; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * 4; + bi.bmiHeader.biClrUsed = 0; + bi.bmiHeader.biClrImportant = 0; + + /* Buffer */ + pBits = (PBYTE)HeapAlloc(ProcessHeap, + 0, + bitmap.bmWidth * bitmap.bmHeight * 4); + if (!pBits) + return FALSE; + + /* get the bits from the original bitmap */ + bRes = GetDIBits(hdcMem, + hBitmap, + 0, + bitmap.bmHeight, + pBits, + &bi, + DIB_RGB_COLORS); + + for (i = 0; i < bitmap.bmHeight; i++) + { + for (j = 0; j < bitmap.bmWidth; j++) + { + DWORD Val = 0; + INT b, g, r; + + CopyMemory(&Val, + &pBits[Count], + 4); + + /* Get pixels in reverse order */ + b = GetRValue(Val); + g = GetGValue(Val); + r = GetBValue(Val); + + /* get the average color value */ + Val = (r + g + b) / 3; + + /* assign to RGB color */ + Val = RGB(Val, Val, Val); + CopyMemory(&pBits[Count], + &Val, + 4); + + Count+=4; + } + } + + /* Set the new pixel bits */ + SetDIBits(hdcMem, + hBitmap, + 0, + bRes, + pBits, + &bi, + DIB_RGB_COLORS); + + HeapFree(ProcessHeap, + 0, + pBits); + + GetClientRect(hwnd, + &rc); + + InvalidateRect(hwnd, + &rc, + FALSE); + + return TRUE; +} + + +BOOL +DisplayInvertedColors(HWND hwnd, + HDC hdcMem, + HBITMAP hBitmap) +{ + BITMAPINFO bi; + BITMAP bitmap; + BOOL bRes; + DWORD Count = 0; + INT i, j; + PBYTE pBits; + RECT rc; + + GetObject(hBitmap, + sizeof(BITMAP), + &bitmap); + + /* Bitmap header */ + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = bitmap.bmWidth; + bi.bmiHeader.biHeight = bitmap.bmHeight; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * 4; + bi.bmiHeader.biClrUsed = 0; + bi.bmiHeader.biClrImportant = 0; + + /* Buffer */ + pBits = (PBYTE)HeapAlloc(ProcessHeap, + 0, + bitmap.bmWidth * bitmap.bmHeight * 4); + if (!pBits) + return FALSE; + + /* get the bits from the original bitmap */ + bRes = GetDIBits(hdcMem, + hBitmap, + 0, + bitmap.bmHeight, + pBits, + &bi, + DIB_RGB_COLORS); + + for (i = 0; i < bitmap.bmHeight; i++) + { + for (j = 0; j < bitmap.bmWidth; j++) + { + DWORD Val = 0; + INT b, g, r; + + CopyMemory(&Val, + &pBits[Count], + 4); + + b = 255 - GetRValue(Val); + g = 255 - GetGValue(Val); + r = 255 - GetBValue(Val); + + Val = RGB(b, g, r); + + CopyMemory(&pBits[Count], + &Val, + 4); + + Count+=4; + } + } + + /* Set the new pixel bits */ + SetDIBits(hdcMem, + hBitmap, + 0, + bRes, + pBits, + &bi, + DIB_RGB_COLORS); + + HeapFree(ProcessHeap, + 0, + pBits); + + GetClientRect(hwnd, + &rc); + + InvalidateRect(hwnd, + &rc, + FALSE); + + return TRUE; +} + + + +BOOL +DisplayBlur(HWND hwnd, + HDC hdcMem, + HBITMAP hBitmap) +{ + BITMAPINFO bi; + BITMAP bitmap; + BOOL bRes; + DWORD Count = 0; + INT i, j; + PBYTE pBits, pBitsTemp; + RECT rc; + + GetObject(hBitmap, + sizeof(BITMAP), + &bitmap); + + /* Bitmap header */ + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = bitmap.bmWidth; + bi.bmiHeader.biHeight = bitmap.bmHeight; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * 4; + bi.bmiHeader.biClrUsed = 0; + bi.bmiHeader.biClrImportant = 0; + + /* Buffer */ + pBits = (PBYTE)HeapAlloc(ProcessHeap, + 0, + bitmap.bmWidth * bitmap.bmHeight * 4); + pBitsTemp = (PBYTE)HeapAlloc(ProcessHeap, + 0, + bitmap.bmWidth * bitmap.bmHeight * 4); + if (!pBits || !pBitsTemp) + return FALSE; + + /* get the bits from the original bitmap */ + bRes = GetDIBits(hdcMem, + hBitmap, + 0, + bitmap.bmHeight, + pBits, + &bi, + DIB_RGB_COLORS); + + for (i = 0; i < bitmap.bmHeight; i++) + { + for (j = 0; j < bitmap.bmWidth; j++) + { + LONG Val = 0; + INT b, g, r; + INT c1, c2, c3, c4, c5; + + CopyMemory(&Val, + &pBits[Count], + 4); + + b = GetRValue(Val); + g = GetGValue(Val); + r = GetBValue(Val); + + c1 = r; + /* Red */ + if ((Count < ((bitmap.bmHeight - 1) * bitmap.bmWidth * 4lu)) && + (Count > (bitmap.bmWidth * 4lu))) + { + CopyMemory(&Val, &pBits[Count - (bitmap.bmWidth * 4)], 4); + c2 = GetBValue(Val); + + CopyMemory(&Val, &pBits[Count + 4], 4); + c3 = GetBValue(Val); + + CopyMemory(&Val, &pBits[(Count + (bitmap.bmWidth * 4))], 4); + c4 = GetBValue(Val); + + CopyMemory(&Val, &pBits[Count - 4], 4); + c5 = GetBValue(Val); + + r = (c1 + c2 + c3 + c4 + c5) / 5; + } + + /* Green */ + c1 = g; + if ((Count < ((bitmap.bmHeight - 1) * bitmap.bmWidth * 4lu)) && + (Count > (bitmap.bmWidth * 4lu))) + { + CopyMemory(&Val, &pBits[(Count - (bitmap.bmWidth * 4lu))], 4); + c2 = GetGValue(Val); + + CopyMemory(&Val, &pBits[Count + 4], 4); + c3 = GetGValue(Val); + + CopyMemory(&Val, &pBits[(Count + (bitmap.bmWidth * 4lu))], 4); + c4 = GetGValue(Val); + + CopyMemory(&Val, &pBits[Count-4], 4); + c5 = GetGValue(Val); + + g = (c1 + c2 + c3 + c4 + c5) / 5; + } + + /* Blue */ + c1 = b; + if ((Count < ((bitmap.bmHeight - 1) * bitmap.bmWidth * 4lu)) && + (Count > (bitmap.bmWidth * 4lu))) + { + CopyMemory(&Val, &pBits[(Count - (bitmap.bmWidth * 4l))], 4); + c2 = GetRValue(Val); + + CopyMemory(&Val, &pBits[Count + 4], 4); + c3 = GetRValue(Val); + + CopyMemory(&Val, &pBits[(Count + (bitmap.bmWidth * 4l))], 4); + c4 = GetRValue(Val); + + CopyMemory(&Val, &pBits[Count-4], 4); + c5 = GetRValue(Val); + + b = (c1 + c2 + c3 + c4 + c5) / 5; + } + + Val = RGB(b, g, r); + + CopyMemory(&pBitsTemp[Count], + &Val, + 4); + + Count+=4; + } + } + + /* Set the new pixel bits */ + SetDIBits(hdcMem, + hBitmap, + 0, + bRes, + pBitsTemp, + &bi, + DIB_RGB_COLORS); + + HeapFree(ProcessHeap, + 0, + pBits); + HeapFree(ProcessHeap, + 0, + pBitsTemp); + + GetClientRect(hwnd, + &rc); + + InvalidateRect(hwnd, + &rc, + FALSE); + + return TRUE; +} + + + +BOOL +DisplaySharpness(HWND hwnd, + HDC hdcMem, + HBITMAP hBitmap) +{ + BITMAPINFO bi; + BITMAP bitmap; + BOOL bRes; + DWORD Count = 0; + INT i, j; + PBYTE pBits, pBitsTemp; + RECT rc; + + GetObject(hBitmap, + sizeof(BITMAP), + &bitmap); + + /* Bitmap header */ + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = bitmap.bmWidth; + bi.bmiHeader.biHeight = bitmap.bmHeight; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * 4; + bi.bmiHeader.biClrUsed = 0; + bi.bmiHeader.biClrImportant = 0; + + /* Buffer */ + pBits = (PBYTE)HeapAlloc(ProcessHeap, + 0, + bitmap.bmWidth * bitmap.bmHeight * 4); + pBitsTemp = (PBYTE)HeapAlloc(ProcessHeap, + 0, + bitmap.bmWidth * bitmap.bmHeight * 4); + if (!pBits || !pBitsTemp) + return FALSE; + + /* get the bits from the original bitmap */ + bRes = GetDIBits(hdcMem, + hBitmap, + 0, + bitmap.bmHeight, + pBits, + &bi, + DIB_RGB_COLORS); + + for (i = 0; i < bitmap.bmHeight; i++) + { + for (j = 0; j < bitmap.bmWidth; j++) + { + LONG Val = 0; + INT b, g, r; + INT c1, c2, c3, c4, c5; + + CopyMemory(&Val, + &pBits[Count], + 4); + + b = GetRValue(Val); + g = GetGValue(Val); + r = GetBValue(Val); + + c1 = r; + /* Red */ + if ((Count < ((bitmap.bmHeight - 1) * bitmap.bmWidth * 4lu)) && + (Count > (bitmap.bmWidth * 4lu))) + { + CopyMemory(&Val, &pBits[Count - (bitmap.bmWidth * 4l)], 4); + c2 = GetBValue(Val); + + CopyMemory(&Val, &pBits[Count + 4], 4); + c3 = GetBValue(Val); + + CopyMemory(&Val, &pBits[(Count + (bitmap.bmWidth * 4l))], 4); + c4 = GetBValue(Val); + + CopyMemory(&Val, &pBits[Count - 4], 4); + c5 = GetBValue(Val); + + r = (c1 * 5) - (c2 + c3 + c4 + c5); + } + + /* Green */ + c1 = g; + if ((Count < ((bitmap.bmHeight - 1)* bitmap.bmWidth * 4lu)) && + (Count > (bitmap.bmWidth * 4lu))) + { + CopyMemory(&Val, &pBits[(Count - (bitmap.bmWidth * 4l))], 4); + c2 = GetGValue(Val); + + CopyMemory(&Val, &pBits[Count + 4], 4); + c3 = GetGValue(Val); + + CopyMemory(&Val, &pBits[(Count + (bitmap.bmWidth * 4l))], 4); + c4 = GetGValue(Val); + + CopyMemory(&Val, &pBits[Count - 4], 4); + c5 = GetGValue(Val); + + g = (c1 * 5) - (c2 + c3 + c4 + c5); + } + + /* Blue */ + c1 = b; + if ((Count < ((bitmap.bmHeight - 1) * bitmap.bmWidth * 4lu)) && + (Count > (bitmap.bmWidth * 4lu))) + { + CopyMemory(&Val, &pBits[(Count - (bitmap.bmWidth * 4l))], 4); + c2 = GetRValue(Val); + + CopyMemory(&Val, &pBits[Count + 4], 4); + c3 = GetRValue(Val); + + CopyMemory(&Val, &pBits[(Count+(bitmap.bmWidth * 4l))], 4); + c4 = GetRValue(Val); + + CopyMemory(&Val, &pBits[Count - 4], 4); + c5 = GetRValue(Val); + + b = (c1 * 5) - (c2 + c3 + c4 + c5); + } + + /* Red */ + if (r > 255) r = 255; + if (r < 0) r = 0; + + /* Green */ + if (g > 255) g = 255; + if (g < 0)g = 0; + + /* Blue */ + if (b > 255) b = 255; + if (b < 0) b = 0; + + Val = RGB(b, g, r); + + CopyMemory(&pBitsTemp[Count], + &Val, + 4); + + Count+=4; + } + } + + /* Set the new pixel bits */ + SetDIBits(hdcMem, + hBitmap, + 0, + bRes, + pBitsTemp, + &bi, + DIB_RGB_COLORS); + + HeapFree(ProcessHeap, + 0, + pBits); + HeapFree(ProcessHeap, + 0, + pBitsTemp); + + GetClientRect(hwnd, + &rc); + + InvalidateRect(hwnd, + &rc, + FALSE); + + return TRUE; +} diff --git a/modules/rosapps/applications/imagesoft/brightness.c b/modules/rosapps/applications/imagesoft/brightness.c new file mode 100644 index 00000000000..265237ea446 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/brightness.c @@ -0,0 +1,379 @@ +#include "precomp.h" + +#define BASECOLOUR 100 + + +VOID +AdjustBrightness(HBITMAP hOrigBitmap, + HBITMAP hNewBitmap, + HWND hwnd, + HDC hdcMem, + INT RedVal, + INT GreenVal, + INT BlueVal) +{ + BITMAPINFO bi; + BITMAP bitmap; + BOOL bRes; + DWORD Count = 0; + INT i, j; + PBYTE pBits; + RECT rc; + + GetObject(hNewBitmap, + sizeof(BITMAP), + &bitmap); + + /* Bitmap header */ + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = bitmap.bmWidth; + bi.bmiHeader.biHeight = bitmap.bmHeight; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * 4; + bi.bmiHeader.biClrUsed = 0; + bi.bmiHeader.biClrImportant = 0; + + /* Buffer */ + pBits = (PBYTE)HeapAlloc(ProcessHeap, + 0, + bitmap.bmWidth * bitmap.bmHeight * 4); + if (!pBits) + return; + + /* get the bits from the original bitmap */ + bRes = GetDIBits(hdcMem, + hOrigBitmap, + 0, + bitmap.bmHeight, + pBits, + &bi, + DIB_RGB_COLORS); + + for (i = 0; i < bitmap.bmHeight; i++) + { + for (j = 0; j < bitmap.bmWidth; j++) + { + DWORD Val = 0; + INT b, g, r; + + CopyMemory(&Val, + &pBits[Count], + 4); + + /* Get pixels in reverse order */ + b = GetRValue(Val); + g = GetGValue(Val); + r = GetBValue(Val); + + /* Red */ + r += RedVal; + if (r > 255) r = 255; + else if (r < 0) r = 0; + + /* Green */ + g += GreenVal; + if (g > 255) g = 255; + else if (g < 0) g = 0; + + /* Blue */ + b += BlueVal; + if (b > 255) b = 255; + else if (b < 0) b = 0; + + /* Store in reverse order */ + Val = RGB(b, g, r); + CopyMemory(&pBits[Count], + &Val, + 4); + + /* RGB color take 4 bytes.The high-order byte must be zero */ + Count += 4; + } + } + + /* Set the new pixel bits */ + SetDIBits(hdcMem, + hNewBitmap, + 0, + bRes, + pBits, + &bi, + DIB_RGB_COLORS); + + HeapFree(ProcessHeap, + 0, + pBits); + + GetClientRect(hwnd, + &rc); + + InvalidateRect(hwnd, + &rc, + FALSE); +} + + +static PIMAGEADJUST +Bri_OnInitDialog(PIMAGEADJUST pImgAdj, + HWND hDlg, + LPARAM lParam) +{ + pImgAdj = (IMAGEADJUST*) HeapAlloc(ProcessHeap, + 0, + sizeof(IMAGEADJUST)); + if (!pImgAdj) + return NULL; + + + pImgAdj->Info = (PMAIN_WND_INFO)lParam; + if (!pImgAdj->Info->ImageEditors) + goto fail; + + + pImgAdj->hPicPrev = GetDlgItem(hDlg, IDC_PICPREVIEW); + GetClientRect(pImgAdj->hPicPrev, + &pImgAdj->ImageRect); + + /* Make a static copy of the main image */ + pImgAdj->hBitmap = (HBITMAP) CopyImage(pImgAdj->Info->ImageEditors->hBitmap, + IMAGE_BITMAP, + pImgAdj->ImageRect.right, + pImgAdj->ImageRect.bottom, + LR_CREATEDIBSECTION); + if (!pImgAdj->hBitmap) + goto fail; + + /* Make a copy which will be updated */ + pImgAdj->hPreviewBitmap = (HBITMAP) CopyImage(pImgAdj->Info->ImageEditors->hBitmap, + IMAGE_BITMAP, + pImgAdj->ImageRect.right, + pImgAdj->ImageRect.bottom, + LR_CREATEDIBSECTION); + if (!pImgAdj->hPreviewBitmap) + goto fail; + + + pImgAdj->RedVal = pImgAdj->BlueVal = pImgAdj->GreenVal = 0; + + /* setup dialog */ + SendDlgItemMessage(hDlg, + IDC_BRI_FULL, + BM_SETCHECK, + BST_CHECKED, + 0); + SendDlgItemMessage(hDlg, + IDC_BRI_TRACKBAR, + TBM_SETRANGE, + TRUE, + (LPARAM)MAKELONG(0, 200)); + SendDlgItemMessage(hDlg, + IDC_BRI_TRACKBAR, + TBM_SETPOS, + TRUE, + (LPARAM)BASECOLOUR); + SetDlgItemText(hDlg, + IDC_BRI_EDIT, + _T("100")); + + return pImgAdj; + +fail: + HeapFree(ProcessHeap, + 0, + pImgAdj); + return NULL; +} + + +static VOID +Bri_OnDrawItem(PIMAGEADJUST pImgAdj, + LPARAM lParam) +{ + LPDRAWITEMSTRUCT lpDrawItem; + HDC hdcMem; + + lpDrawItem = (LPDRAWITEMSTRUCT)lParam; + + hdcMem = CreateCompatibleDC(lpDrawItem->hDC); + + if(lpDrawItem->CtlID == IDC_PICPREVIEW) + { + SelectObject(hdcMem, + pImgAdj->hPreviewBitmap); + + BitBlt(lpDrawItem->hDC, + pImgAdj->ImageRect.left, + pImgAdj->ImageRect.top, + pImgAdj->ImageRect.right, + pImgAdj->ImageRect.bottom, + hdcMem, + 0, + 0, + SRCCOPY); + + DeleteDC(hdcMem); + } +} + + +static VOID +Bri_OnTrackBar(PIMAGEADJUST pImgAdj, + HWND hDlg) +{ + HDC hdcMem; + DWORD TrackPos; + + TrackPos = (DWORD)SendDlgItemMessage(hDlg, + IDC_BRI_TRACKBAR, + TBM_GETPOS, + 0, + 0); + + SetDlgItemInt(hDlg, + IDC_BRI_EDIT, + TrackPos, + FALSE); + + if (IsDlgButtonChecked(hDlg, IDC_BRI_FULL) == BST_CHECKED) + { + pImgAdj->RedVal = pImgAdj->GreenVal = pImgAdj->BlueVal = TrackPos - BASECOLOUR; + } + else if (IsDlgButtonChecked(hDlg, IDC_BRI_RED) == BST_CHECKED) + { + pImgAdj->RedVal = TrackPos - BASECOLOUR; + } + else if (IsDlgButtonChecked(hDlg, IDC_BRI_GREEN) == BST_CHECKED) + { + pImgAdj->GreenVal = TrackPos - BASECOLOUR; + } + else if (IsDlgButtonChecked(hDlg, IDC_BRI_BLUE) == BST_CHECKED) + { + pImgAdj->BlueVal = TrackPos - BASECOLOUR; + } + + hdcMem = GetDC(pImgAdj->hPicPrev); + + AdjustBrightness(pImgAdj->hBitmap, + pImgAdj->hPreviewBitmap, + pImgAdj->hPicPrev, + hdcMem, + pImgAdj->RedVal, + pImgAdj->GreenVal, + pImgAdj->BlueVal); + + ReleaseDC(pImgAdj->hPicPrev, hdcMem); +} + + +static BOOL +Bri_OnCommand(PIMAGEADJUST pImgAdj, + HWND hDlg, + UINT uID) +{ + switch (uID) + { + case IDOK: + { + HDC hdcMem; + + hdcMem = GetDC(pImgAdj->Info->ImageEditors->hSelf); + + AdjustBrightness(pImgAdj->Info->ImageEditors->hBitmap, + pImgAdj->Info->ImageEditors->hBitmap, + pImgAdj->Info->ImageEditors->hSelf, + hdcMem, + pImgAdj->RedVal, + pImgAdj->GreenVal, + pImgAdj->BlueVal); + + ReleaseDC(pImgAdj->Info->ImageEditors->hSelf, + hdcMem); + + EndDialog(hDlg, + uID); + + return TRUE; + } + + case IDCANCEL: + { + EndDialog(hDlg, + uID); + return TRUE; + } + } + + return FALSE; +} + + +INT_PTR CALLBACK +BrightnessProc(HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + static PIMAGEADJUST pImgAdj = NULL; + + switch (message) + { + case WM_INITDIALOG: + { + pImgAdj = Bri_OnInitDialog(pImgAdj, + hDlg, + lParam); + if (!pImgAdj) + { + EndDialog(hDlg, -1); + return FALSE; + } + + return TRUE; + } + + case WM_DRAWITEM: + { + Bri_OnDrawItem(pImgAdj, + lParam); + return TRUE; + } + + case WM_HSCROLL: + { + if (LOWORD(wParam) == TB_THUMBTRACK || + LOWORD(wParam) == TB_ENDTRACK) + { + Bri_OnTrackBar(pImgAdj, + hDlg); + } + + return TRUE; + } + + case WM_COMMAND: + { + return Bri_OnCommand(pImgAdj, + hDlg, + LOWORD(wParam)); + } + + case WM_DESTROY: + { + if (pImgAdj) + { + if (pImgAdj->hBitmap) + DeleteObject(pImgAdj->hBitmap); + if (pImgAdj->hPreviewBitmap) + DeleteObject(pImgAdj->hPreviewBitmap); + + HeapFree(ProcessHeap, + 0, + pImgAdj); + } + } + } + + return FALSE; +} diff --git a/modules/rosapps/applications/imagesoft/contrast.c b/modules/rosapps/applications/imagesoft/contrast.c new file mode 100644 index 00000000000..7a885358d99 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/contrast.c @@ -0,0 +1,380 @@ +#include "precomp.h" + +#define BASECOLOUR 100 + + +VOID +AdjustContrast(HBITMAP hOrigBitmap, + HBITMAP hNewBitmap, + HWND hwnd, + HDC hdcMem, + INT RedVal, + INT GreenVal, + INT BlueVal) +{ + BITMAPINFO bi; + BITMAP bitmap; + BOOL bRes; + DWORD Count = 0; + INT i, j; + PBYTE pBits; + RECT rc; + + GetObject(hNewBitmap, + sizeof(BITMAP), + &bitmap); + + /* Bitmap header */ + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = bitmap.bmWidth; + bi.bmiHeader.biHeight = bitmap.bmHeight; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * 4; + bi.bmiHeader.biClrUsed = 0; + bi.bmiHeader.biClrImportant = 0; + + /* Buffer */ + pBits = (PBYTE)HeapAlloc(ProcessHeap, + 0, + bitmap.bmWidth * bitmap.bmHeight * 4); + if (!pBits) + return; + + /* get the bits from the original bitmap */ + bRes = GetDIBits(hdcMem, + hOrigBitmap, + 0, + bitmap.bmHeight, + pBits, + &bi, + DIB_RGB_COLORS); + + for (i = 0; i < bitmap.bmHeight; i++) + { + for (j = 0; j < bitmap.bmWidth; j++) + { + DWORD Val = 0; + INT b, g, r; + + CopyMemory(&Val, + &pBits[Count], + 4); + + /* Get pixels in reverse order */ + b = GetRValue(Val); + g = GetGValue(Val); + r = GetBValue(Val); + + r = ((r - 128) * RedVal) / 100 + 128; + g = ((g - 128) * GreenVal) / 100 + 128; + b = ((b - 128) * BlueVal) / 100 + 128; + + /* Red */ + if (r > 255) r = 255; + else if (r < 0) r = 0; + + /* Green */ + if (g > 255) g = 255; + else if (g < 0) g = 0; + + /* Blue */ + if (b > 255) b = 255; + else if (b < 0) b = 0; + + /* Store in reverse order */ + Val = RGB(b, g, r); + CopyMemory(&pBits[Count], + &Val, + 4); + + /* RGB color take 4 bytes.The high-order byte must be zero */ + Count += 4; + } + } + + /* Set the new pixel bits */ + SetDIBits(hdcMem, + hNewBitmap, + 0, + bRes, + pBits, + &bi, + DIB_RGB_COLORS); + + HeapFree(ProcessHeap, + 0, + pBits); + + GetClientRect(hwnd, + &rc); + + InvalidateRect(hwnd, + &rc, + FALSE); +} + + +static PIMAGEADJUST +Cont_OnInitDialog(PIMAGEADJUST pImgAdj, + HWND hDlg, + LPARAM lParam) +{ + pImgAdj = (IMAGEADJUST*) HeapAlloc(ProcessHeap, + 0, + sizeof(IMAGEADJUST)); + if (!pImgAdj) + return NULL; + + + pImgAdj->Info = (PMAIN_WND_INFO)lParam; + if (!pImgAdj->Info->ImageEditors) + goto fail; + + + pImgAdj->hPicPrev = GetDlgItem(hDlg, IDC_PICPREVIEW); + GetClientRect(pImgAdj->hPicPrev, + &pImgAdj->ImageRect); + + /* Make a static copy of the main image */ + pImgAdj->hBitmap = (HBITMAP) CopyImage(pImgAdj->Info->ImageEditors->hBitmap, + IMAGE_BITMAP, + pImgAdj->ImageRect.right, + pImgAdj->ImageRect.bottom, + LR_CREATEDIBSECTION); + if (!pImgAdj->hBitmap) + goto fail; + + /* Make a copy which will be updated */ + pImgAdj->hPreviewBitmap = (HBITMAP) CopyImage(pImgAdj->Info->ImageEditors->hBitmap, + IMAGE_BITMAP, + pImgAdj->ImageRect.right, + pImgAdj->ImageRect.bottom, + LR_CREATEDIBSECTION); + if (!pImgAdj->hPreviewBitmap) + goto fail; + + + pImgAdj->RedVal = pImgAdj->BlueVal = pImgAdj->GreenVal = 100; + + /* setup dialog */ + SendDlgItemMessage(hDlg, + IDC_BRI_FULL, + BM_SETCHECK, + BST_CHECKED, + 0); + SendDlgItemMessage(hDlg, + IDC_BRI_TRACKBAR, + TBM_SETRANGE, + TRUE, + (LPARAM)MAKELONG(0, 200)); + SendDlgItemMessage(hDlg, + IDC_BRI_TRACKBAR, + TBM_SETPOS, + TRUE, + (LPARAM)BASECOLOUR); + SetDlgItemText(hDlg, + IDC_BRI_EDIT, + _T("100")); + + return pImgAdj; + +fail: + HeapFree(ProcessHeap, + 0, + pImgAdj); + return NULL; +} + + +static VOID +Cont_OnDrawItem(PIMAGEADJUST pImgAdj, + LPARAM lParam) +{ + LPDRAWITEMSTRUCT lpDrawItem; + HDC hdcMem; + + lpDrawItem = (LPDRAWITEMSTRUCT)lParam; + + hdcMem = CreateCompatibleDC(lpDrawItem->hDC); + + if(lpDrawItem->CtlID == IDC_PICPREVIEW) + { + SelectObject(hdcMem, + pImgAdj->hPreviewBitmap); + + BitBlt(lpDrawItem->hDC, + pImgAdj->ImageRect.left, + pImgAdj->ImageRect.top, + pImgAdj->ImageRect.right, + pImgAdj->ImageRect.bottom, + hdcMem, + 0, + 0, + SRCCOPY); + + DeleteDC(hdcMem); + } +} + + +static VOID +Cont_OnTrackBar(PIMAGEADJUST pImgAdj, + HWND hDlg) +{ + HDC hdcMem; + DWORD TrackPos; + + TrackPos = (DWORD)SendDlgItemMessage(hDlg, + IDC_BRI_TRACKBAR, + TBM_GETPOS, + 0, + 0); + + SetDlgItemInt(hDlg, + IDC_BRI_EDIT, + TrackPos, + FALSE); + + if (IsDlgButtonChecked(hDlg, IDC_BRI_FULL) == BST_CHECKED) + { + pImgAdj->RedVal = pImgAdj->GreenVal = pImgAdj->BlueVal = TrackPos - BASECOLOUR + 100; + } + else if (IsDlgButtonChecked(hDlg, IDC_BRI_RED) == BST_CHECKED) + { + pImgAdj->RedVal = TrackPos - BASECOLOUR + 100; + } + else if (IsDlgButtonChecked(hDlg, IDC_BRI_GREEN) == BST_CHECKED) + { + pImgAdj->GreenVal = TrackPos - BASECOLOUR + 100; + } + else if (IsDlgButtonChecked(hDlg, IDC_BRI_BLUE) == BST_CHECKED) + { + pImgAdj->BlueVal = TrackPos - BASECOLOUR + 100; + } + + hdcMem = GetDC(pImgAdj->hPicPrev); + + AdjustContrast(pImgAdj->hBitmap, + pImgAdj->hPreviewBitmap, + pImgAdj->hPicPrev, + hdcMem, + pImgAdj->RedVal, + pImgAdj->GreenVal, + pImgAdj->BlueVal); + + ReleaseDC(pImgAdj->hPicPrev, hdcMem); +} + + +static BOOL +Cont_OnCommand(PIMAGEADJUST pImgAdj, + HWND hDlg, + UINT uID) +{ + switch (uID) + { + case IDOK: + { + HDC hdcMem; + + hdcMem = GetDC(pImgAdj->Info->ImageEditors->hSelf); + + AdjustContrast(pImgAdj->Info->ImageEditors->hBitmap, + pImgAdj->Info->ImageEditors->hBitmap, + pImgAdj->Info->ImageEditors->hSelf, + hdcMem, + pImgAdj->RedVal, + pImgAdj->GreenVal, + pImgAdj->BlueVal); + + ReleaseDC(pImgAdj->Info->ImageEditors->hSelf, + hdcMem); + + EndDialog(hDlg, + uID); + + return TRUE; + } + + case IDCANCEL: + { + EndDialog(hDlg, + uID); + return TRUE; + } + } + + return FALSE; +} + + +INT_PTR CALLBACK +ContrastProc(HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + static PIMAGEADJUST pImgAdj = NULL; + + switch (message) + { + case WM_INITDIALOG: + { + pImgAdj = Cont_OnInitDialog(pImgAdj, + hDlg, + lParam); + if (!pImgAdj) + { + EndDialog(hDlg, -1); + return FALSE; + } + + return TRUE; + } + + case WM_DRAWITEM: + { + Cont_OnDrawItem(pImgAdj, + lParam); + return TRUE; + } + + case WM_HSCROLL: + { + if (LOWORD(wParam) == TB_THUMBTRACK || + LOWORD(wParam) == TB_ENDTRACK) + { + Cont_OnTrackBar(pImgAdj, + hDlg); + } + + return TRUE; + } + + case WM_COMMAND: + { + return Cont_OnCommand(pImgAdj, + hDlg, + LOWORD(wParam)); + } + + case WM_DESTROY: + { + if (pImgAdj) + { + if (pImgAdj->hBitmap) + DeleteObject(pImgAdj->hBitmap); + if (pImgAdj->hPreviewBitmap) + DeleteObject(pImgAdj->hPreviewBitmap); + + HeapFree(ProcessHeap, + 0, + pImgAdj); + } + } + } + + return FALSE; +} diff --git a/modules/rosapps/applications/imagesoft/custcombo.c b/modules/rosapps/applications/imagesoft/custcombo.c new file mode 100644 index 00000000000..6ae88e3d0cf --- /dev/null +++ b/modules/rosapps/applications/imagesoft/custcombo.c @@ -0,0 +1,213 @@ +#include + + +LRESULT WINAPI +FlatComboProc(HWND hwnd, + UINT msg, + WPARAM wParam, + LPARAM lParam) +{ + HDC hdc; + PAINTSTRUCT ps; + RECT rect, rect2; + POINT pt; + + WNDPROC OldComboProc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + static BOOL fMouseDown = FALSE; + static BOOL fButtonDown = FALSE; + + switch(msg) + { + case WM_PAINT: + { + if(wParam == 0) hdc = BeginPaint(hwnd, &ps); + else hdc = (HDC)wParam; + + /* mask off the borders and draw ComboBox normally */ + GetClientRect(hwnd, &rect); + + InflateRect(&rect, + -GetSystemMetrics(SM_CXEDGE)*2, + -GetSystemMetrics(SM_CYEDGE)*2); + + rect.right -= GetSystemMetrics(SM_CXVSCROLL); + + IntersectClipRect(hdc, + rect.left, + rect.top, + rect.right, + rect.bottom); + + /* Draw the ComboBox */ + CallWindowProc(OldComboProc, + hwnd, + msg, + (WPARAM)hdc, + lParam); + + /* Now mask off inside and draw the borders */ + SelectClipRgn(hdc, + NULL); + rect.right += GetSystemMetrics(SM_CXVSCROLL); + + ExcludeClipRect(hdc, + rect.left, + rect.top, + rect.right, + rect.bottom); + + /* draw borders */ + GetClientRect(hwnd, + &rect2); + FillRect(hdc, + &rect2, + //CreateSolidBrush(RGB(0,0,0))); + GetSysColorBrush(COLOR_3DFACE)); + + /* now draw the button */ + SelectClipRgn(hdc, + NULL); + rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL); + + if(fButtonDown) + { + HBRUSH oldBrush; + HPEN oldPen; + POINT pt[3]; + + FillRect(hdc, &rect, CreateSolidBrush(RGB(182,189,210))); + rect.top -= 1; + rect.bottom += 1; + FrameRect(hdc, &rect, GetStockBrush(WHITE_BRUSH)); + + pt[0].x = rect.right - ((GetSystemMetrics(SM_CXVSCROLL) / 2) + 2); + pt[0].y = rect.bottom / 2; + pt[1].x = pt[0].x + 4; + pt[1].y = pt[0].y; + pt[2].x = pt[1].x - 2; + pt[2].y = pt[1].y + 2; + + oldPen = (HPEN) SelectObject(hdc, GetStockPen(WHITE_PEN)); + oldBrush = (HBRUSH) SelectObject(hdc, GetStockBrush(WHITE_BRUSH)); + Polygon(hdc, pt, 3); + + SelectObject(hdc, oldPen); + SelectObject(hdc, oldBrush); + } + else + { + HBRUSH oldBrush; + POINT pt[3]; + + FillRect(hdc, &rect, GetSysColorBrush(COLOR_3DFACE)); + rect.top -= 1; + rect.bottom += 1; + FrameRect(hdc, &rect, GetStockBrush(WHITE_BRUSH)); + + pt[0].x = rect.right - ((GetSystemMetrics(SM_CXVSCROLL) / 2) + 2); + pt[0].y = rect.bottom / 2; + pt[1].x = pt[0].x + 4; + pt[1].y = pt[0].y; + pt[2].x = pt[1].x - 2; + pt[2].y = pt[1].y + 2; + + oldBrush = (HBRUSH) SelectObject(hdc, GetStockBrush(BLACK_BRUSH)); + Polygon(hdc, pt, 3); + + SelectObject(hdc, oldBrush); + } + + + if(wParam == 0) + EndPaint(hwnd, &ps); + + return 0; + } + + /* check if mouse is within drop-arrow area, toggle + * a flag to say if the mouse is up/down. Then invalidate + * the window so it redraws to show the changes. */ + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + { + + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + + GetClientRect(hwnd, &rect); + + InflateRect(&rect, + -GetSystemMetrics(SM_CXEDGE), + -GetSystemMetrics(SM_CYEDGE)); + rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL); + + if(PtInRect(&rect, pt)) + { + /* we *should* call SetCapture, but the ComboBox does it for us */ + fMouseDown = TRUE; + fButtonDown = TRUE; + InvalidateRect(hwnd, 0, 0); + } + } + break; + + /* mouse has moved. Check to see if it is in/out of the drop-arrow */ + case WM_MOUSEMOVE: + { + + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + + if(fMouseDown && (wParam & MK_LBUTTON)) + { + GetClientRect(hwnd, &rect); + + InflateRect(&rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE)); + rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL); + + if(fButtonDown != PtInRect(&rect, pt)) + { + fButtonDown = PtInRect(&rect, pt); + InvalidateRect(hwnd, 0, 0); + } + } + } + break; + + case WM_LBUTTONUP: + { + + if(fMouseDown) + { + /* No need to call ReleaseCapture, the ComboBox does it for us */ + fMouseDown = FALSE; + fButtonDown = FALSE; + InvalidateRect(hwnd, 0, 0); + } + } + break; + } + + return CallWindowProc(OldComboProc, + hwnd, + msg, + wParam, + lParam); +} + +VOID MakeFlatCombo(HWND hwndCombo) +{ + LONG_PTR OldComboProc; + + /* Remember old window procedure */ + OldComboProc = GetWindowLongPtr(hwndCombo, GWLP_WNDPROC); + SetWindowLongPtr(hwndCombo, + GWLP_USERDATA, + OldComboProc); + + /* Perform the subclass */ + SetWindowLongPtr(hwndCombo, + GWLP_WNDPROC, + (LONG_PTR)FlatComboProc); +} diff --git a/modules/rosapps/applications/imagesoft/floatwindow.c b/modules/rosapps/applications/imagesoft/floatwindow.c new file mode 100644 index 00000000000..28b393747c1 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/floatwindow.c @@ -0,0 +1,629 @@ +#include "precomp.h" + +static const TCHAR szFloatWndClass[] = TEXT("ImageSoftFloatWndClass"); + +#define ID_TIMER1 1 +#define ID_TIMER2 2 +#define ID_TIMER3 3 + +TBBUTTON ToolsButtons[] = { +/* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */ + {TBICON_RECTSEL, ID_RECTSEL, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* rectangle select */ + {TBICON_MOVESEL, ID_MOVESEL, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* move selected pixels */ + {TBICON_LASOO, ID_LASOO, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* lasso select */ + {TBICON_MOVE, ID_MOVE, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* move selection */ + {TBICON_ECLIPSESEL, ID_ECLIPSESEL, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* elipse select */ + {TBICON_ZOOM, ID_ZOOM, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* zoom */ + {TBICON_MAGICWAND, ID_MAGICWAND, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* magic wand */ + {TBICON_TEXT, ID_TEXT, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* text */ + {TBICON_PAINTBRUSH, ID_PAINTBRUSH, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* paintbrush */ + {TBICON_ERASER, ID_ERASER, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* eraser */ + {TBICON_PENCIL, ID_PENCIL, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* pencil */ + {TBICON_COLORPICKER, ID_COLORPICKER, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* color picker */ + {TBICON_CLONESTAMP, ID_CLONESTAMP, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* clone stamp */ + {TBICON_RECOLORING, ID_RECOLORING, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* recolor */ + {TBICON_PAINTBUCKET, ID_PAINTBUCKET, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* paint bucket */ + {TBICON_LINE, ID_LINE, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* line */ + {TBICON_RECTANGLE, ID_RECTANGLE, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* rectangle */ + {TBICON_ROUNDRECT, ID_ROUNDRECT, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* round rectangle */ + {TBICON_ECLIPSE, ID_ECLIPSE, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* elipse */ + {TBICON_FREEFORM, ID_FREEFORM, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0}, /* free form */ + + {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, +}; + +TBBUTTON HistoryButtons[] = { + {TBICON_BACKSM, ID_BACK, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* back */ + {TBICON_UNDOSM, ID_UNDO, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* undo */ + {TBICON_REDOSM, ID_REDO, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* redo */ + {TBICON_FORWARDSM, ID_FORWARD, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* forward */ + {TBICON_DELETESM, ID_DELETE, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* delete */ +}; + + +BOOL +ShowHideWindow(HWND hwnd) +{ + if (IsWindowVisible(hwnd)) + return ShowWindow(hwnd, SW_HIDE); + else + return ShowWindow(hwnd, SW_SHOW); +} + + +BOOL +FloatToolbarCreateToolsGui(PMAIN_WND_INFO Info) +{ + HWND hTb; + HIMAGELIST hImageList; + INT NumButtons; + + NumButtons = sizeof(ToolsButtons) / sizeof(ToolsButtons[0]); + + hTb = CreateWindowEx(0, + TOOLBARCLASSNAME, + NULL, + WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_WRAPABLE | CCS_NODIVIDER, + 0, 0, 32, 200, + Info->fltTools->hSelf, + NULL, + hInstance, + NULL); + if (hTb != NULL) + { + SendMessage(hTb, + TB_SETEXTENDEDSTYLE, + 0, + TBSTYLE_EX_HIDECLIPPEDBUTTONS); + + SendMessage(hTb, + TB_BUTTONSTRUCTSIZE, + sizeof(ToolsButtons[0]), + 0); + + SendMessage(hTb, + TB_SETBITMAPSIZE, + 0, + (LPARAM)MAKELONG(16, 16)); + + hImageList = InitImageList(NumButtons, + IDB_TOOLSRECTSEL); + + ImageList_Destroy((HIMAGELIST)SendMessage(hTb, + TB_SETIMAGELIST, + 0, + (LPARAM)hImageList)); + + SendMessage(hTb, + TB_ADDBUTTONS, + NumButtons, + (LPARAM)ToolsButtons); + + SendMessage(hTb, + TB_AUTOSIZE, + 0, + 0); + + return TRUE; + } + + return FALSE; +} + + +VOID +FloatWindowPaintColorPicker(HWND hColorPicker) +{ + HDC hdc; + RECT rect; + + InvalidateRect(hColorPicker, + NULL, + TRUE); + UpdateWindow(hColorPicker); + + hdc = GetDC(hColorPicker); + + GetClientRect(hColorPicker, + &rect); + + Ellipse(hdc, + rect.left, + rect.top, + rect.right, + rect.bottom); + + ReleaseDC(hColorPicker, + hdc); + +} + +VOID +FloatWindowPaintHueSlider(HWND hHueSlider) +{ + HDC hdc; + RECT rect; + + InvalidateRect(hHueSlider, + NULL, + TRUE); + UpdateWindow(hHueSlider); + + hdc = GetDC(hHueSlider); + + GetClientRect(hHueSlider, + &rect); + + Rectangle(hdc, + rect.left, + rect.top, + rect.right, + rect.bottom); + + ReleaseDC(hHueSlider, + hdc); + +} + + +BOOL +FloatToolbarCreateColorsGui(PMAIN_WND_INFO Info) +{ + HWND hColorPicker; + HWND hHueSlider; + HWND hMouseButton; + HWND hMore; + RECT rect; + HBITMAP hMoreBitmap; + + GetClientRect(Info->fltColors->hSelf, + &rect); + + hColorPicker = CreateWindowEx(0, + WC_STATIC, + NULL, + WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, + 2, + 2, + (int) (rect.right * 0.65), + rect.bottom - 2, + Info->fltColors->hSelf, + NULL, + hInstance, + NULL); + if (hColorPicker == NULL) + return FALSE; + + hHueSlider = CreateWindowEx(0, + WC_STATIC, + NULL, + WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, + 145, + 35, + 25, + 135, + Info->fltColors->hSelf, + NULL, + hInstance, + NULL); + if (hHueSlider == NULL) + return FALSE; + + hMouseButton = CreateWindowEx(0, + WC_COMBOBOX, + NULL, + WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, + 118, 5, 75, 25, + Info->fltColors->hSelf, + NULL, + hInstance, + NULL); + if (hMouseButton == NULL) + return FALSE; + + MakeFlatCombo(hMouseButton); + + /* temp, just testing */ + SendMessage(hMouseButton, CB_ADDSTRING, 0, (LPARAM)_T("Primary")); + SendMessage(hMouseButton, CB_ADDSTRING, 0, (LPARAM)_T("Secondary")); + SendMessage(hMouseButton, CB_SETCURSEL, 0, 0); + + + hMore = CreateWindowEx(WS_EX_STATICEDGE, + WC_BUTTON, + NULL, + WS_CHILD | WS_VISIBLE | BS_BITMAP, + rect.right - 15, + rect.bottom - 15, + 15, 15, + Info->fltColors->hSelf, + NULL, + hInstance, + NULL); + if (hMore == NULL) + return FALSE; + + hMoreBitmap = (HBITMAP)LoadImage(hInstance, + MAKEINTRESOURCE(IDB_COLORSMORE), + IMAGE_BITMAP, + 12, + 11, + LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS); + if (hMoreBitmap != NULL) + { + SendMessage(hMore, + BM_SETIMAGE, + IMAGE_BITMAP, + (LPARAM)hMoreBitmap); + } + + + /* temp functions for playing about with possible layouts */ + FloatWindowPaintHueSlider(hHueSlider); + FloatWindowPaintColorPicker(hColorPicker); + + if (hColorPicker != NULL) + { + HDC hDc = GetDC(hColorPicker); + TextOut(hDc, 8, 75, _T("Possible layout?"), 16); + ReleaseDC(hColorPicker, hDc); + } + + return TRUE; + +} + + +BOOL +FloatToolbarCreateHistoryGui(PMAIN_WND_INFO Info) +{ + HWND hList; + HWND hButtons; + HIMAGELIST hImageList; + INT NumButtons; + + hList = CreateWindowEx(0, + WC_LISTBOX, + NULL, + WS_CHILD | WS_VISIBLE | LBS_EXTENDEDSEL, + 0, 0, 143, 100, + Info->fltHistory->hSelf, + NULL, + hInstance, + NULL); + if (hList == NULL) + return FALSE; + + NumButtons = sizeof(HistoryButtons) / sizeof(HistoryButtons[0]); + hButtons = CreateWindowEx(0, + TOOLBARCLASSNAME, + NULL, + WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | CCS_BOTTOM | CCS_NODIVIDER, + 0, 0, 0, 0, + Info->fltHistory->hSelf, + NULL, + hInstance, + NULL); + if (hButtons != NULL) + { + SendMessage(hButtons, + TB_BUTTONSTRUCTSIZE, + sizeof(ToolsButtons[0]), + 0); + + SendMessage(hButtons, + TB_SETBITMAPSIZE, + 0, + (LPARAM)MAKELONG(10, 10)); + + hImageList = InitImageList(NumButtons, + IDB_HISTBACK); + + ImageList_Destroy((HIMAGELIST)SendMessage(hButtons, + TB_SETIMAGELIST, + 0, + (LPARAM)hImageList)); + + SendMessage(hButtons, + TB_SETBUTTONSIZE, + 0, + MAKELONG(18, 16)); + + SendMessage(hButtons, + TB_ADDBUTTONS, + NumButtons, + (LPARAM)HistoryButtons); + + return TRUE; + } + + return FALSE; +} + + +static VOID +DoTimer(PFLT_WND FltInfo, + UINT_PTR idTimer) +{ + switch (idTimer) + { + /* timer to check if cursor is in toolbar coords */ + case ID_TIMER1: + { + POINT pt; + + /* kill timer if toobar is not opaque */ + if (FltInfo->bOpaque != TRUE) + { + KillTimer(FltInfo->hSelf, + ID_TIMER1); + break; + } + + if (GetCursorPos(&pt)) + { + RECT rect; + + if (GetWindowRect(FltInfo->hSelf, + &rect)) + { + if (!PtInRect(&rect, + pt)) + { + KillTimer(FltInfo->hSelf, + ID_TIMER1); + KillTimer(FltInfo->hSelf, + ID_TIMER2); + + /* timer to fade out toolbar */ + SetTimer(FltInfo->hSelf, + ID_TIMER3, + 50, + NULL); + } + } + } + } + break; + + /* timer to fade in toolbar */ + case ID_TIMER2: + { + SetLayeredWindowAttributes(FltInfo->hSelf, + 0, + (255 * FltInfo->Transparancy) / 100, + LWA_ALPHA); + + /* increment transparancy until it is opaque (100) */ + FltInfo->Transparancy += 5; + + if (FltInfo->Transparancy == 100) + { + SetWindowLongPtr(FltInfo->hSelf, + GWL_EXSTYLE, + GetWindowLongPtr(FltInfo->hSelf, + GWL_EXSTYLE) & ~WS_EX_LAYERED); + + FltInfo->bOpaque = TRUE; + + KillTimer(FltInfo->hSelf, + ID_TIMER2); + } + } + break; + + case ID_TIMER3: + { + LONG_PTR Style; + + Style = GetWindowLongPtr(FltInfo->hSelf, + GWL_EXSTYLE); + + if (Style & ~WS_EX_LAYERED) + { + SetWindowLongPtr(FltInfo->hSelf, + GWL_EXSTYLE, + Style | WS_EX_LAYERED); + } + + FltInfo->Transparancy -= 5; + + if (FltInfo->Transparancy >= 60) + { + /* set the tranclucency to 60% */ + SetLayeredWindowAttributes(FltInfo->hSelf, + 0, + (255 * FltInfo->Transparancy) / 100, + LWA_ALPHA); + + if (FltInfo->Transparancy == 60) + { + FltInfo->bOpaque = FALSE; + + KillTimer(FltInfo->hSelf, + ID_TIMER3); + } + + } + } + break; + } +} + +LRESULT CALLBACK +FloatToolbarWndProc(HWND hwnd, + UINT Message, + WPARAM wParam, + LPARAM lParam) +{ + PFLT_WND FltInfo; + + /* Get the window context */ + FltInfo = (PFLT_WND)GetWindowLongPtr(hwnd, + GWLP_USERDATA); + if (FltInfo == NULL && Message != WM_CREATE) + { + goto HandleDefaultMessage; + } + + switch(Message) + { + case WM_CREATE: + { + FltInfo = (PFLT_WND)(((LPCREATESTRUCT)lParam)->lpCreateParams); + + /*FIXME: read this from registry */ +// FltInfo->bShow = TRUE; + + SetWindowLongPtr(hwnd, + GWLP_USERDATA, + (LONG_PTR)FltInfo); + + FltInfo->bOpaque = FALSE; + + SetWindowLongPtr(hwnd, + GWL_EXSTYLE, + GetWindowLongPtr(hwnd, + GWL_EXSTYLE) | WS_EX_LAYERED); + + /* set the tranclucency to 60% */ + FltInfo->Transparancy = 60; + SetLayeredWindowAttributes(hwnd, + 0, + (255 * FltInfo->Transparancy) / 100, + LWA_ALPHA); + } + break; + + case WM_TIMER: + { + DoTimer(FltInfo, + wParam); + } + break; + + case WM_NCMOUSEMOVE: + case WM_MOUSEMOVE: + { + if (FltInfo->bOpaque == FALSE) + { + + RedrawWindow(hwnd, + NULL, + NULL, + RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN); + + FltInfo->bOpaque = TRUE; + //MessageBox(NULL, _T("in"), _T("Hit test"), MB_OK | MB_ICONEXCLAMATION); + + /* timer to check if cursor is in toolbar coords */ + SetTimer(hwnd, + ID_TIMER1, + 200, + NULL); + + /* timer to fade in the toolbars */ + SetTimer(hwnd, + ID_TIMER2, + 50, + NULL); + } + } + break; + + case WM_CLOSE: + ShowHideWindow(FltInfo->hSelf); + break; + + case WM_COMMAND: + { + if (LOWORD(wParam) == IDCANCEL) + ShowHideWindow(FltInfo->hSelf); + + switch(LOWORD(wParam)) + { + case ID_NEW: + MessageBox(hwnd, _T("Kapow!"), _T("Hit test"), MB_OK | MB_ICONEXCLAMATION); + break; + + case ID_CLONESTAMP: + case ID_COLORPICKER: + case ID_ECLIPSE: + case ID_ECLIPSESEL: + case ID_ERASER: + case ID_FREEFORM: + case ID_LASOO: + case ID_LINE: + case ID_MAGICWAND: + case ID_MOVE: + case ID_MOVESEL: + case ID_PAINTBRUSH: + case ID_PAINTBUCKET: + case ID_PENCIL: + case ID_RECOLORING: + case ID_RECTANGLE: + case ID_ROUNDRECT: + case ID_TEXT: + case ID_ZOOM: + /*SendMessage(Info->hSelf, + LOWORD(wParam), + wParam, + lParam);*/ + break; + } + } + break; + + case WM_NCACTIVATE: + /* FIXME: needs fully implementing */ + return DefWindowProc(hwnd, + Message, + TRUE, + lParam); + break; + + case WM_DESTROY: + SetWindowLongPtr(hwnd, + GWLP_USERDATA, + 0); + break; + + default: +HandleDefaultMessage: + return DefWindowProc(hwnd, + Message, + wParam, + lParam); + } + + return 0; +} + + +BOOL +InitFloatWndClass(VOID) +{ + WNDCLASSEX wc = {0}; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = FloatToolbarWndProc; + wc.hInstance = hInstance; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, + IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wc.lpszClassName = szFloatWndClass; + wc.hIconSm = NULL; + + return RegisterClassEx(&wc) != (ATOM)0; +} + +VOID +UninitFloatWndImpl(VOID) +{ + UnregisterClass(szFloatWndClass, + hInstance); +} + + diff --git a/modules/rosapps/applications/imagesoft/font.c b/modules/rosapps/applications/imagesoft/font.c new file mode 100644 index 00000000000..72350ff6d42 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/font.c @@ -0,0 +1,179 @@ +#include + +int CALLBACK +EnumFontSizes(ENUMLOGFONTEX *lpelfe, + NEWTEXTMETRICEX *lpntme, + DWORD FontType, + LPARAM lParam) +{ + static int ttsizes[] = { 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 }; + TCHAR ach[100]; + + BOOL fTrueType = (lpelfe->elfLogFont.lfOutPrecision == OUT_STROKE_PRECIS) ? TRUE : FALSE; + + HWND hwndCombo = (HWND)lParam; + INT i, idx; + + if (fTrueType) + { + for (i = 0; i < (sizeof(ttsizes) / sizeof(ttsizes[0])); i++) + { + wsprintf(ach, _T("%d"), ttsizes[i]); + + idx = (INT)SendMessage(hwndCombo, + CB_ADDSTRING, + 0, + (LPARAM)ach); + + SendMessage(hwndCombo, + CB_SETITEMDATA, + idx, + ttsizes[i]); + } + + return 0; + } + + return 1; +} + + +/* Font-enumeration callback */ +int CALLBACK +EnumFontNames(ENUMLOGFONTEX *lpelfe, + NEWTEXTMETRICEX *lpntme, + DWORD FontType, + LPARAM lParam) +{ + HWND hwndCombo = (HWND)lParam; + TCHAR *pszName = lpelfe->elfLogFont.lfFaceName; + + /* make sure font doesn't already exist in our list */ + if(SendMessage(hwndCombo, + CB_FINDSTRING, + 0, + (LPARAM)pszName) == CB_ERR) + { + INT idx; + BOOL fFixed; + BOOL fTrueType; + + /* add the font */ + idx = (INT)SendMessage(hwndCombo, + CB_ADDSTRING, + 0, + (LPARAM)pszName); + + /* record the font's attributes (Fixedwidth and Truetype) */ + fFixed = (lpelfe->elfLogFont.lfPitchAndFamily & FIXED_PITCH) ? TRUE : FALSE; + fTrueType = (lpelfe->elfLogFont.lfOutPrecision == OUT_STROKE_PRECIS) ? TRUE : FALSE; + + /* store this information in the list-item's userdata area */ + SendMessage(hwndCombo, + CB_SETITEMDATA, + idx, + MAKEWPARAM(fFixed, fTrueType)); + } + + return 1; +} + + +VOID +FillFontSizeComboList(HWND hwndCombo) +{ + LOGFONT lf = { 0 }; + HDC hdc = GetDC(hwndCombo); + + /* default size */ + INT cursize = 12; + INT i, count, nearest = 0; + + HFONT hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); + + SendMessage(hwndCombo, + WM_SETFONT, + (WPARAM)hFont, + 0); + + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfPitchAndFamily = 0; + + /* empty the list */ + SendMessage(hwndCombo, + CB_RESETCONTENT, + 0, + 0); + + /* enumerate font sizes */ + EnumFontFamiliesEx(hdc, + &lf, + (FONTENUMPROC)EnumFontSizes, + (LPARAM)hwndCombo, + 0); + + /* set selection to first item */ + count = (INT)SendMessage(hwndCombo, + CB_GETCOUNT, + 0, + 0); + + for(i = 0; i < count; i++) + { + INT n = (INT)SendMessage(hwndCombo, + CB_GETITEMDATA, + i, + 0); + + if (n <= cursize) + nearest = i; + } + + SendMessage(hwndCombo, + CB_SETCURSEL, + nearest, + 0); + + ReleaseDC(hwndCombo, + hdc); +} + + +/* Initialize the font-list by enumeration all system fonts */ +VOID +FillFontStyleComboList(HWND hwndCombo) +{ + HDC hdc = GetDC(hwndCombo); + LOGFONT lf; + + /* FIXME: draw each font in its own style */ + HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + SendMessage(hwndCombo, + WM_SETFONT, + (WPARAM)hFont, + 0); + + /* FIXME: set this in relation to the widest string */ + SendMessage(hwndCombo, CB_SETDROPPEDWIDTH, 150, 0); + + lf.lfCharSet = ANSI_CHARSET; // DEFAULT_CHARSET; + lf.lfFaceName[0] = _T('\0'); // all fonts + lf.lfPitchAndFamily = 0; + + /* store the list of fonts in the combo */ + EnumFontFamiliesEx(hdc, + &lf, + (FONTENUMPROC)EnumFontNames, + (LPARAM)hwndCombo, 0); + + ReleaseDC(hwndCombo, + hdc); + + /* set default to Arial */ + SendMessage(hwndCombo, + CB_SELECTSTRING, + -1, + (LPARAM)_T("Arial")); + + +} diff --git a/modules/rosapps/applications/imagesoft/imageprop.h b/modules/rosapps/applications/imagesoft/imageprop.h new file mode 100644 index 00000000000..ac0246479a0 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/imageprop.h @@ -0,0 +1,49 @@ + +typedef struct _IMAGEADJUST +{ + PMAIN_WND_INFO Info; + HWND hPicPrev; + HBITMAP hBitmap; + HBITMAP hPreviewBitmap; + RECT ImageRect; + INT RedVal; + INT GreenVal; + INT BlueVal; +} IMAGEADJUST, *PIMAGEADJUST; + + +INT_PTR CALLBACK ImagePropDialogProc(HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK BrightnessProc(HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK ContrastProc(HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam); + +VOID AdjustBrightness(HBITMAP hOrigBitmap, + HBITMAP hNewBitmap, + HWND hwnd, + HDC hdcMem, + INT RedVal, + INT GreenVal, + INT BlueVal); + +BOOL DisplayBlackAndWhite(HWND hwnd, + HDC hdcMem, + HBITMAP hBitmap); +BOOL DisplayInvertedColors(HWND hwnd, + HDC hdcMem, + HBITMAP hBitmap); +BOOL DisplayBlur(HWND hwnd, + HDC hdcMem, + HBITMAP hBitmap); +BOOL DisplaySharpness(HWND hwnd, + HDC hdcMem, + HBITMAP hBitmap); diff --git a/modules/rosapps/applications/imagesoft/imagesoft.c b/modules/rosapps/applications/imagesoft/imagesoft.c new file mode 100644 index 00000000000..e673a3405d2 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/imagesoft.c @@ -0,0 +1,101 @@ +#include + +HINSTANCE hInstance; +HANDLE ProcessHeap; + +int WINAPI +_tWinMain(HINSTANCE hThisInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ + LPTSTR lpAppName, lpVersion, lpTitle; + HWND hMainWnd; + MSG Msg; + BOOL bRet; + int Ret = 1; + size_t len; + INITCOMMONCONTROLSEX icex; + + hInstance = hThisInstance; + ProcessHeap = GetProcessHeap(); + + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_BAR_CLASSES | ICC_COOL_CLASSES; + InitCommonControlsEx(&icex); + + if ( !AllocAndLoadString(&lpAppName, hInstance, IDS_APPNAME) || + !AllocAndLoadString(&lpVersion, hInstance, IDS_VERSION) ) + { + return Ret; + } + + len = _tcslen(lpAppName) + _tcslen(lpVersion); + lpTitle = HeapAlloc(ProcessHeap, + 0, + (len + 2) * sizeof(TCHAR)); + if (lpTitle == NULL) + { + LocalFree((HLOCAL)lpAppName); + LocalFree((HLOCAL)lpVersion); + return Ret; + } + + wsprintf(lpTitle, + _T("%s %s"), + lpAppName, + lpVersion); + + LocalFree((HLOCAL)lpAppName); + LocalFree((HLOCAL)lpVersion); + + if (TbdInitImpl()) + { + if (InitMainWindowImpl()) + { + if (InitImageEditWindowImpl()) + { + if (InitFloatWndClass()) + { + hMainWnd = CreateMainWindow(lpTitle, + nCmdShow); + if (hMainWnd != NULL) + { + /* pump the message queue */ + while ((bRet = GetMessage(&Msg, + NULL, + 0, + 0) != 0)) + { + if (bRet != (BOOL)-1) + { + if (!MainWndTranslateMDISysAccel(hMainWnd, + &Msg)) + { + TranslateMessage(&Msg); + DispatchMessage(&Msg); + } + } + } + + Ret = 0; + } + + UninitImageEditWindowImpl(); + } + + UninitFloatWndImpl(); + } + + UninitMainWindowImpl(); + } + + TbdUninitImpl(); + } + + HeapFree(GetProcessHeap(), + 0, + lpTitle); + + return Ret; +} diff --git a/modules/rosapps/applications/imagesoft/imagesoft.rbuild b/modules/rosapps/applications/imagesoft/imagesoft.rbuild new file mode 100644 index 00000000000..479c5a542ab --- /dev/null +++ b/modules/rosapps/applications/imagesoft/imagesoft.rbuild @@ -0,0 +1,30 @@ + + + + . + gdi32 + user32 + advapi32 + version + comctl32 + shell32 + comdlg32 + + about.c + adjust.c + brightness.c + contrast.c + custcombo.c + floatwindow.c + font.c + imagesoft.c + imgedwnd.c + mainwnd.c + misc.c + opensave.c + tooldock.c + + imagesoft.rc + precomp.h + + diff --git a/modules/rosapps/applications/imagesoft/imagesoft.rc b/modules/rosapps/applications/imagesoft/imagesoft.rc new file mode 100644 index 00000000000..c1b7c8d9ef0 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/imagesoft.rc @@ -0,0 +1,72 @@ +#include +#include +#include "resource.h" + +/* define language neutral resources */ +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Image Editor" +#define REACTOS_STR_INTERNAL_NAME "imagesoft" +#define REACTOS_STR_ORIGINAL_FILENAME "imagesoft.exe" +#include + +IDI_IMAGESOFTICON ICON "res/imagesoft.ico" + +/* main toolbar icons */ +IDB_MAINCOPYICON BITMAP DISCARDABLE "res/icons/std/MainCopyIcon.bmp" +IDB_MAINCUTICON BITMAP DISCARDABLE "res/icons/std/MainCutIcon.bmp" +IDB_MAINPASTEICON BITMAP DISCARDABLE "res/icons/std/MainPasteIcon.bmp" +IDB_MAINREDOICON BITMAP DISCARDABLE "res/icons/std/MainRedoIcon.bmp" +IDB_MAINUNDOICON BITMAP DISCARDABLE "res/icons/std/MainUndoIcon.bmp" +IDB_MAINNEWICON BITMAP DISCARDABLE "res/icons/std/MainNewIcon.bmp" +IDB_MAINOPENICON BITMAP DISCARDABLE "res/icons/std/MainOpenIcon.bmp" +IDB_MAINPRINTICON BITMAP DISCARDABLE "res/icons/std/MainPrintIcon.bmp" +IDB_MAINPRINTPREICON BITMAP DISCARDABLE "res/icons/std/MainPrintPreIcon.bmp" +IDB_MAINSAVEICON BITMAP DISCARDABLE "res/icons/std/MainSaveIcon.bmp" + +/* text toolbar icons */ +IDB_TEXTBOLD BITMAP DISCARDABLE "res/icons/text/TextBoldIcon.bmp" +IDB_TEXTITALIC BITMAP DISCARDABLE "res/icons/text/TextItalicIcon.bmp" +IDB_TEXTULINE BITMAP DISCARDABLE "res/icons/text/TextUnderlineIcon.bmp" +IDB_TEXTLEFT BITMAP DISCARDABLE "res/icons/text/TextAlignLeftIcon.bmp" +IDB_TEXTCENTER BITMAP DISCARDABLE "res/icons/text/TextAlignCenterIcon.bmp" +IDB_TEXTRIGHT BITMAP DISCARDABLE "res/icons/text/TextAlignRightIcon.bmp" + +/* tools window icons */ +IDB_TOOLSCLONESTAMP BITMAP DISCARDABLE "res/icons/tools/ToolsCloneStamp.bmp" +IDB_TOOLSCOLORPICKER BITMAP DISCARDABLE "res/icons/tools/ToolsColorPicker.bmp" +IDB_TOOLSECLIPSE BITMAP DISCARDABLE "res/icons/tools/ToolsEllipse.bmp" +IDB_TOOLSECLIPSESEL BITMAP DISCARDABLE "res/icons/tools/ToolsEllipseSelect.bmp" +IDB_TOOLSERASER BITMAP DISCARDABLE "res/icons/tools/ToolsEraser.bmp" +IDB_TOOLSFREEFORM BITMAP DISCARDABLE "res/icons/tools/ToolsFreeformShape.bmp" +IDB_TOOLSLASOO BITMAP DISCARDABLE "res/icons/tools/ToolsLassoSelect.bmp" +IDB_TOOLSLINE BITMAP DISCARDABLE "res/icons/tools/ToolsLine.bmp" +IDB_TOOLSMAGICWAND BITMAP DISCARDABLE "res/icons/tools/ToolsMagicWand.bmp" +IDB_TOOLSMOVE BITMAP DISCARDABLE "res/icons/tools/ToolsMove.bmp" +IDB_TOOLSMOVESEL BITMAP DISCARDABLE "res/icons/tools/ToolsMoveSelection.bmp" +IDB_TOOLSPAINTBRUSH BITMAP DISCARDABLE "res/icons/tools/ToolsPaintBrush.bmp" +IDB_TOOLSPAINTBUCKET BITMAP DISCARDABLE "res/icons/tools/ToolsPaintBucket.bmp" +IDB_TOOLSPENCIL BITMAP DISCARDABLE "res/icons/tools/ToolsPencil.bmp" +IDB_TOOLSRECOLORING BITMAP DISCARDABLE "res/icons/tools/ToolsRecoloring.bmp" +IDB_TOOLSRECTANGLE BITMAP DISCARDABLE "res/icons/tools/ToolsRectangle.bmp" +IDB_TOOLSRECTSEL BITMAP DISCARDABLE "res/icons/tools/ToolsRectangleSelect.bmp" +IDB_TOOLSROUNDRECT BITMAP DISCARDABLE "res/icons/tools/ToolsRoundedRectangle.bmp" +IDB_TOOLSTEXT BITMAP DISCARDABLE "res/icons/tools/ToolsText.bmp" +IDB_TOOLSZOOM BITMAP DISCARDABLE "res/icons/tools/ToolsZoom.bmp" + +/* history window icons */ +IDB_HISTBACK BITMAP DISCARDABLE "res/icons/hist/HistBack.bmp" +IDB_HISTUNDO BITMAP DISCARDABLE "res/icons/hist/HistUndo.bmp" +IDB_HISTREDO BITMAP DISCARDABLE "res/icons/hist/HistRedo.bmp" +IDB_HISTFORWARD BITMAP DISCARDABLE "res/icons/hist/HistForward.bmp" +IDB_HISTDELETE BITMAP DISCARDABLE "res/icons/hist/HistDelete.bmp" + +/* colors window icons */ +IDB_COLORSMORE BITMAP DISCARDABLE "res/icons/color/ColorMore.bmp" +IDB_COLORSLESS BITMAP DISCARDABLE "res/icons/color/ColorLess.bmp" + +/* cursors */ +IDC_PAINTBRUSHCURSOR CURSOR DISCARDABLE "res/cursors/PaintBrushToolCursor.cur" +IDC_PAINTBRUSHCURSORMOUSEDOWN CURSOR DISCARDABLE "res/cursors/PaintBrushToolCursorMouseDown.cur" + +#include "rsrc.rc" diff --git a/modules/rosapps/applications/imagesoft/imgedwnd.c b/modules/rosapps/applications/imagesoft/imgedwnd.c new file mode 100644 index 00000000000..c9342080461 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/imgedwnd.c @@ -0,0 +1,542 @@ +#include "precomp.h" + +static const TCHAR szImageEditWndClass[] = TEXT("ImageSoftEditWndClass"); + +#define IMAGE_FRAME_SIZE 1 + +static VOID +EditWndUpdateScrollInfo(PEDIT_WND_INFO Info) +{ + SCROLLINFO si; + RECT rcClient; + + GetClientRect(Info->hSelf, + &rcClient); + + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE; + si.nPage = rcClient.right - (2 * IMAGE_FRAME_SIZE); + si.nMin = 0; + si.nMax = Info->Width; + + SetScrollInfo(Info->hSelf, + SB_HORZ, + &si, + TRUE); + + si.nPage = rcClient.bottom - (2 * IMAGE_FRAME_SIZE); + si.nMax = Info->Height; + SetScrollInfo(Info->hSelf, + SB_VERT, + &si, + TRUE); +} + + +static BOOL +LoadBlankCanvas(PEDIT_WND_INFO Info) +{ + /* FIXME: convert this to a DIB Section */ + /* set bitmap dimensions */ + Info->Width = Info->OpenInfo->New.Width; + Info->Height = Info->OpenInfo->New.Height; + + return TRUE; +} + +static BOOL +LoadDIBImage(PEDIT_WND_INFO Info) +{ + BITMAPFILEHEADER bmfh; + HANDLE hFile; + BITMAP bitmap; + DWORD BytesRead; + BOOL bSuccess, bRet = FALSE; + + hFile = CreateFile(Info->OpenInfo->Open.lpImagePath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + return bRet; + + bSuccess = ReadFile(hFile, + &bmfh, + sizeof(BITMAPFILEHEADER), + &BytesRead, + NULL); + + if (bSuccess && (BytesRead == sizeof(BITMAPFILEHEADER)) + && (bmfh.bfType == *(WORD *)"BM")) + { + DWORD InfoSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER); + + Info->pbmi = HeapAlloc(ProcessHeap, + 0, + InfoSize); + if (Info->pbmi) + { + bSuccess = ReadFile(hFile, + Info->pbmi, + InfoSize, + &BytesRead, + NULL); + + if (bSuccess && (BytesRead == InfoSize)) + { + Info->hBitmap = CreateDIBSection(NULL, + Info->pbmi, + DIB_RGB_COLORS, + (VOID *)&Info->pBits, + NULL, + 0); + if (Info->hBitmap != NULL) + { + ReadFile(hFile, + Info->pBits, + bmfh.bfSize - bmfh.bfOffBits, + &BytesRead, + NULL); + + GetObject(Info->hBitmap, + sizeof(BITMAP), + &bitmap); + + Info->Width = bitmap.bmWidth; + Info->Height = bitmap.bmHeight; + + bRet = TRUE; + } + } + } + } + else if (!bSuccess) + { + GetError(0); + } + + CloseHandle(hFile); + + return bRet; +} + + +static BOOL +InitEditWnd(PEDIT_WND_INFO Info) +{ + //BOOL bRet = FALSE; + + Info->Zoom = 100; + + if (Info->OpenInfo != NULL) + { + HDC hDC; + + if (Info->hDCMem) + { + DeleteObject(Info->hDCMem); + Info->hDCMem = NULL; + } + + hDC = GetDC(Info->hSelf); + Info->hDCMem = CreateCompatibleDC(hDC); + ReleaseDC(Info->hSelf, hDC); + + if (Info->OpenInfo->CreateNew) + { + LoadBlankCanvas(Info); + } + else + { + LoadDIBImage(Info); + } + + Info->OpenInfo = NULL; + } + + EditWndUpdateScrollInfo(Info); + + /* Add image editor to the list */ + Info->Next = Info->MainWnd->ImageEditors; + Info->MainWnd->ImageEditors = Info; + + InvalidateRect(Info->hSelf, + NULL, + TRUE); + + /* FIXME - if returning FALSE, remove the image editor from the list! */ + return TRUE; +} + +static VOID +DestroyEditWnd(PEDIT_WND_INFO Info) +{ + PEDIT_WND_INFO *PrevEditor; + PEDIT_WND_INFO Editor; + + DeleteDC(Info->hDCMem); + + /* FIXME - free resources and run down editor */ + HeapFree(ProcessHeap, + 0, + Info->pbmi); + HeapFree(ProcessHeap, + 0, + Info->pBits); + + /* Remove the image editor from the list */ + PrevEditor = &Info->MainWnd->ImageEditors; + Editor = Info->MainWnd->ImageEditors; + do + { + if (Editor == Info) + { + *PrevEditor = Info->Next; + break; + } + PrevEditor = &Editor->Next; + Editor = Editor->Next; + } while (Editor != NULL); +} + +static VOID +ImageEditWndRepaint(PEDIT_WND_INFO Info, + HDC hDC, + LPPAINTSTRUCT lpps) +{ + HBITMAP hOldBitmap; + + if (Info->hBitmap) + { + hOldBitmap = (HBITMAP) SelectObject(Info->hDCMem, + Info->hBitmap); + + BitBlt(hDC, + lpps->rcPaint.left, + lpps->rcPaint.top, + lpps->rcPaint.right - lpps->rcPaint.left, + lpps->rcPaint.bottom - lpps->rcPaint.top, + Info->hDCMem, + lpps->rcPaint.left, + lpps->rcPaint.top, + SRCCOPY); + + Info->hBitmap = SelectObject(Info->hDCMem, hOldBitmap); + } +} + +static LRESULT CALLBACK +ImageEditWndProc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + PEDIT_WND_INFO Info; + LRESULT Ret = 0; + HDC hDC; + static INT xMouse, yMouse; + static BOOL bLeftButtonDown, bRightButtonDown; + + /* Get the window context */ + Info = (PEDIT_WND_INFO)GetWindowLongPtr(hwnd, + GWLP_USERDATA); + if (Info == NULL && uMsg != WM_CREATE) + { + goto HandleDefaultMessage; + } + + switch (uMsg) + { + case WM_CREATE: + { + Info = (PEDIT_WND_INFO)(((LPMDICREATESTRUCT)((LPCREATESTRUCT)lParam)->lpCreateParams)->lParam); + Info->hSelf = hwnd; + + SetWindowLongPtr(hwnd, + GWLP_USERDATA, + (LONG_PTR)Info); + + if (!InitEditWnd(Info)) + { + Ret = (LRESULT)-1; + break; + } + break; + } +/* + case WM_ERASEBKGND: + if (Info->Width != 0 && Info->Height != 0) + { + Ret = TRUE; + } + break; +*/ + case WM_LBUTTONDOWN: + if (! bRightButtonDown) + SetCapture(Info->hSelf); + + bLeftButtonDown = TRUE; + xMouse = LOWORD(lParam); + yMouse = HIWORD(lParam); + + SetCursor(LoadCursor(hInstance, + MAKEINTRESOURCE(IDC_PAINTBRUSHCURSORMOUSEDOWN))); + break; + + case WM_LBUTTONUP: + if (bLeftButtonDown) + SetCapture(NULL); + + bLeftButtonDown = FALSE; + + break; + + case WM_RBUTTONDOWN: + if (! bLeftButtonDown) + SetCapture(Info->hSelf); + + bRightButtonDown = TRUE; + xMouse = LOWORD(lParam); + yMouse = HIWORD(lParam); + + SetCursor(LoadCursor(hInstance, + MAKEINTRESOURCE(IDC_PAINTBRUSHCURSORMOUSEDOWN))); + break; + + case WM_RBUTTONUP: + if (bRightButtonDown) + SetCapture(NULL); + + bRightButtonDown = FALSE; + + break; + + case WM_MOUSEMOVE: + { + HPEN hPen, hPenOld; + + if (!bLeftButtonDown && !bRightButtonDown) + break; + + hDC = GetDC(Info->hSelf); + + SelectObject(Info->hDCMem, + Info->hBitmap); + + if (bLeftButtonDown) + hPen = CreatePen(PS_SOLID, + 3, + RGB(0, 0, 0)); + else + hPen = CreatePen(PS_SOLID, + 3, + RGB(255, 255, 255)); + + hPenOld = SelectObject(hDC, + hPen); + SelectObject(Info->hDCMem, + hPen); + + MoveToEx(hDC, + xMouse, + yMouse, + NULL); + + MoveToEx(Info->hDCMem, + xMouse, + yMouse, + NULL); + + xMouse = LOWORD(lParam); + yMouse = HIWORD(lParam); + + LineTo(hDC, + xMouse, + yMouse); + + LineTo(Info->hDCMem, + xMouse, + yMouse); + + SelectObject(hDC, + hPenOld); + DeleteObject(SelectObject(Info->hDCMem, + hPenOld)); + + ReleaseDC(Info->hSelf, + hDC); + } + break; + + case WM_PAINT: + { + if (Info->Width != 0 && Info->Height != 0) + { + PAINTSTRUCT ps; + HDC hDC; + + hDC = BeginPaint(hwnd, + &ps); + if (hDC != NULL) + { + ImageEditWndRepaint(Info, + hDC, + &ps); + + EndPaint(hwnd, + &ps); + } + } + break; + } + + case WM_SIZE: + { + EditWndUpdateScrollInfo(Info); + goto HandleDefaultMessage; + } + + case WM_MENUSELECT: + case WM_ENTERMENULOOP: + case WM_EXITMENULOOP: + /* forward these messages to the main window procedure */ + Ret = SendMessage(Info->MainWnd->hSelf, + uMsg, + wParam, + lParam); + break; + + case WM_MDIACTIVATE: + /* Switch the main window context if neccessary */ + MainWndSwitchEditorContext(Info->MainWnd, + (HWND)wParam, + (HWND)lParam); + break; + + case WM_DESTROY: + { + DestroyEditWnd(Info); + + HeapFree(ProcessHeap, + 0, + Info); + SetWindowLongPtr(hwnd, + GWLP_USERDATA, + 0); + break; + } + + default: +HandleDefaultMessage: + Ret = DefMDIChildProc(hwnd, + uMsg, + wParam, + lParam); + break; + } + + return Ret; +} + +VOID +SetImageEditorEnvironment(PEDIT_WND_INFO Info, + BOOL Setup) +{ + if (Setup) + { + /* FIXME - setup editor environment (e.g. show toolbars, enable menus etc) */ + } + else + { + /* FIXME - cleanup editor environment (e.g. hide toolbars, disable menus etc) */ + } +} + +BOOL +CreateImageEditWindow(PMAIN_WND_INFO MainWnd, + POPEN_IMAGE_EDIT_INFO OpenInfo) +{ + PEDIT_WND_INFO Info; + HWND hWndEditor; + LONG Width, Height; + + Info = HeapAlloc(ProcessHeap, + 0, + sizeof(EDIT_WND_INFO)); + if (Info != NULL) + { + ZeroMemory(Info, + sizeof(EDIT_WND_INFO)); + Info->MainWnd = MainWnd; + Info->MdiEditorType = metImageEditor; + Info->OpenInfo = OpenInfo; + + if (OpenInfo->CreateNew) + { + Width = OpenInfo->New.Width; + Height = OpenInfo->New.Height; + } + else + { + Width = CW_USEDEFAULT; + Height = CW_USEDEFAULT; + } + + hWndEditor = CreateMDIWindow(szImageEditWndClass, + OpenInfo->lpImageName, + WS_HSCROLL | WS_VSCROLL | WS_MAXIMIZE, + 200, + 200, + Width, + Height, + MainWnd->hMdiClient, + hInstance, + (LPARAM)Info); + + if (hWndEditor != NULL) + { + return TRUE; + } + + HeapFree(ProcessHeap, + 0, + Info); + } + + return FALSE; +} + +BOOL +InitImageEditWindowImpl(VOID) +{ + WNDCLASSEX wc = {0}; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = ImageEditWndProc; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(hInstance, + MAKEINTRESOURCE(IDI_IMAGESOFTICON)); + wc.hCursor = LoadCursor(hInstance, + MAKEINTRESOURCE(IDC_PAINTBRUSHCURSOR)); + wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wc.lpszClassName = szImageEditWndClass; + wc.hIconSm = (HICON)LoadImage(hInstance, + MAKEINTRESOURCE(IDI_IMAGESOFTICON), + IMAGE_ICON, + 16, + 16, + LR_SHARED); + + return RegisterClassEx(&wc) != (ATOM)0; +} + +VOID +UninitImageEditWindowImpl(VOID) +{ + UnregisterClass(szImageEditWndClass, + hInstance); +} diff --git a/modules/rosapps/applications/imagesoft/imgedwnd.h b/modules/rosapps/applications/imagesoft/imgedwnd.h new file mode 100644 index 00000000000..55b203fef4f --- /dev/null +++ b/modules/rosapps/applications/imagesoft/imgedwnd.h @@ -0,0 +1,94 @@ +#define MONOCHROMEBITS 1 +#define GREYSCALEBITS 8 +#define PALLETEBITS 8 +#define TRUECOLORBITS 24 + +#define PIXELS 0 +#define CENTIMETERS 1 +#define INCHES 2 + + +/* generic definitions and forward declarations */ +struct _MAIN_WND_INFO; +struct _EDIT_WND_INFO; + + +typedef enum _MDI_EDITOR_TYPE { + metUnknown = 0, + metImageEditor, +} MDI_EDITOR_TYPE, *PMDI_EDITOR_TYPE; + +typedef enum +{ + tSelect = 0, + tMove, + tLasso, + tZoom, + tMagicWand, + tBrush, + tEraser, + tPencil, + tColorPick, + tStamp, + tFill, + tLine, + tPolyline, + tRectangle, + tRoundRectangle, + tPolygon, + tElipse, +} TOOL; + +typedef struct _OPEN_IMAGE_EDIT_INFO +{ + BOOL CreateNew; + union + { + struct + { + LONG Width; + LONG Height; + } New; + struct + { + LPTSTR lpImagePath; + } Open; + }; + LPTSTR lpImageName; + USHORT Type; + LONG Resolution; +} OPEN_IMAGE_EDIT_INFO, *POPEN_IMAGE_EDIT_INFO; + +typedef struct _EDIT_WND_INFO +{ + MDI_EDITOR_TYPE MdiEditorType; /* Must be first member! */ + + HWND hSelf; + HBITMAP hBitmap; + HDC hDCMem; + PBITMAPINFO pbmi; + PBYTE pBits; + struct _MAIN_WND_INFO *MainWnd; + struct _EDIT_WND_INFO *Next; + POINT ScrollPos; + USHORT Zoom; + DWORD Tool; + + POPEN_IMAGE_EDIT_INFO OpenInfo; /* Only valid during initialization */ + + /* Canvas properties */ + USHORT Type; + LONG Resolution; + /* size of drawing area */ + LONG Width; + LONG Height; + +} EDIT_WND_INFO, *PEDIT_WND_INFO; + + +BOOL CreateImageEditWindow(struct _MAIN_WND_INFO *MainWnd, + POPEN_IMAGE_EDIT_INFO OpenInfo); +VOID SetImageEditorEnvironment(PEDIT_WND_INFO Info, + BOOL Setup); +BOOL InitImageEditWindowImpl(VOID); +VOID UninitImageEditWindowImpl(VOID); diff --git a/modules/rosapps/applications/imagesoft/lang/bg-BG.rc b/modules/rosapps/applications/imagesoft/lang/bg-BG.rc new file mode 100644 index 00000000000..2ab3f5faf92 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/bg-BG.rc @@ -0,0 +1,237 @@ +LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "в0,1" +END + +IDR_MAINMENU MENU + +BEGIN + POPUP "&Файл" + BEGIN + MENUITEM "&Нов...", ID_NEW + MENUITEM "&Отваряне...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Затваряне\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "Затваряне на всички", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "&Запис", ID_SAVE, GRAYED + MENUITEM "Запис &като...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Печатен изглед", ID_PRINTPRE,GRAYED + MENUITEM "&Разпечатване...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Свойства", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "Из&ход\tAlt+F4", ID_EXIT + END + + POPUP "&Обработка" + BEGIN + MENUITEM "&Отмяна", ID_UNDO, GRAYED + MENUITEM "&Връщане", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "От&рязване", ID_CUT, GRAYED + MENUITEM "За&помняне", ID_COPY, GRAYED + MENUITEM "&Поставяне", ID_PASTE, GRAYED + MENUITEM "Поставяне като ново из&ображение", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Избор на вси&чки", ID_SELALL, GRAYED + END + + POPUP "Из&глед" + BEGIN + MENUITEM "&Средства", ID_TOOLS + MENUITEM "&Цветове", ID_COLOR + MENUITEM "&Дневник", ID_HISTORY + MENUITEM "Лента състояние", ID_STATUSBAR + END + + POPUP "&Настройка" + BEGIN + MENUITEM "Яркост...", ID_BRIGHTNESS + MENUITEM "Контраст...", ID_CONTRAST + MENUITEM "Оттенък/Насищане", -1, GRAYED + POPUP "Цвят" + BEGIN + MENUITEM "Черно- бяло", ID_BLACKANDWHITE + MENUITEM "Обръщане на цветовете", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Размиване", ID_BLUR + MENUITEM "Изостряне", ID_SHARPEN + MENUITEM "Заобляне на ръбовете", -1, GRAYED + MENUITEM "Добавяне на сянка", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Размер на изображението", -1, GRAYED + MENUITEM "Обръщане", -1, GRAYED + MENUITEM "Огледало", -1, GRAYED + MENUITEM "Завъртане", -1, GRAYED + + END + + POPUP "&Цветове" + BEGIN + MENUITEM "&Обработка на цветовете...", ID_EDITCOLOURS + END + POPUP "&Прозорец" + BEGIN + MENUITEM "На&дипляне", ID_WINDOW_CASCADE + MENUITEM "Водоравно настелване", ID_WINDOW_TILE_HORZ + MENUITEM "&Отвесно настелване", ID_WINDOW_TILE_VERT + MENUITEM "Под&реждане на значетата", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "&Следващ\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "Помо&щ" + BEGIN + MENUITEM "&За...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 220, 120 +CAPTION "Яркост" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Цветова форма:", IDC_STATIC, 135, 5, 60, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 77, 48 + CONTROL "Пълноцветно (ЧЗС)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 80, 9 + CONTROL "Червено", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 55, 9 + CONTROL "Зелено", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 55, 9 + CONTROL "Синьо", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 55, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "Добре", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Отказ", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "За ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Затваряне", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 170, 163 +CAPTION "Свойства на изображението" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Име:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 68, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Свойства на платното", IDC_STATIC, 4, 22, 162, 98 + LTEXT "Вид:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Ширина:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 68, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Височина:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 68, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Разделителна способност:", IDC_STATIC, 12, 82, 46, 18 + EDITTEXT IDC_RES_EDIT, 68, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Единици:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Размери:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 68, 125, 54, 9 + PUSHBUTTON "Добре", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Отказ", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "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.\r\n\r\nThis 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.\r\n\r\nYou 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." + IDS_READY " Готово." + IDS_TOOLBAR_STANDARD "Стандартно" + IDS_TOOLBAR_TEST "Проба" + IDS_IMAGE_NAME "Изображение %1!u!" + IDS_FLT_TOOLS "Средства" + IDS_FLT_COLORS "Цветове" + IDS_FLT_HISTORY "История (дневник)" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Едноцветно (1 разряд)" + IDS_IMAGE_GREYSCALE "Сиво- бяло (8 разряда)" + IDS_IMAGE_PALETTE "Палитра от 256 цвята" + IDS_IMAGE_TRUECOLOR "Истинска цветност (24 разряда)" + + IDS_UNIT_PIXELS "Точки" + IDS_UNIT_CM "см" + IDS_UNIT_INCHES "Цола" + IDS_UNIT_DOTSCM "Точки/ см" + IDS_UNIT_DPI "Т/Ц" + IDS_UNIT_KB "%d КБ" + IDS_UNIT_MB "%d МБ" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Нов" + IDS_TOOLTIP_OPEN "Отваряне" + IDS_TOOLTIP_SAVE "Запис" + IDS_TOOLTIP_PRINTPRE "Печатен изглед" + IDS_TOOLTIP_PRINT "Разпечатване" + IDS_TOOLTIP_CUT "Отрязване" + IDS_TOOLTIP_COPY "Запомняне" + IDS_TOOLTIP_PASTE "Поставяне" + IDS_TOOLTIP_UNDO "Отмяна" + IDS_TOOLTIP_REDO "Връщане" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Създава нов документ." + IDS_HINT_OPEN " Отваря съществуващ документ." + IDS_HINT_CLOSE " Затваря този прозорец." + IDS_HINT_CLOSEALL " Затваря всички прозорци." + IDS_HINT_SAVE " Затваря дейния документ." + IDS_HINT_SAVEAS " Затваря дейния документ под ново име." + IDS_HINT_PRINTPRE " Показва печатен изглед на документа." + IDS_HINT_PRINT " Разпечатва дейния документ." + IDS_HINT_PROP " Показва свойствата на дейното изображение." + IDS_HINT_EXIT " Излиза от приложението" + + IDS_HINT_TOOLS " Показва или скрива плаващия прозорец на средствата." + IDS_HINT_COLORS " Показва ли скрива плаващия прозорец на цветовете." + IDS_HINT_HISTORY " Показва или скрива плаващия прозорец на историята." + IDS_HINT_STATUS " Показва или скрива лентата на състоянието." + + IDS_HINT_CASCADE " Подрежда прозорците така, че да се застъпват." + IDS_HINT_TILE_HORZ " Подрежда прозорците като незастъпващи се плочки." + IDS_HINT_TILE_VERT " Подрежда прозорците като незастъпващи се плочки." + IDS_HINT_ARRANGE " Подрежда значетата на дъното на прозореца." + IDS_HINT_NEXT " Задейства следващия прозорец." + + IDS_HINT_SYS_RESTORE " Възстановява прозореца до обичайните му размери." + IDS_HINT_SYS_MOVE " Мести прозореца." + IDS_HINT_SYS_SIZE " Преоразмерява прозореца." + IDS_HINT_SYS_MINIMIZE " Смалява прозореца в значе." + IDS_HINT_SYS_MAXIMIZE " Разгръща прозореца на цял екран." +END diff --git a/modules/rosapps/applications/imagesoft/lang/en-GB.rc b/modules/rosapps/applications/imagesoft/lang/en-GB.rc new file mode 100644 index 00000000000..7f665a1ab0e --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/en-GB.rc @@ -0,0 +1,232 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New...", ID_NEW + MENUITEM "&Open...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Close\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "C&lose all", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "&Save", ID_SAVE, GRAYED + MENUITEM "Save &As...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Print Pre&view", ID_PRINTPRE,GRAYED + MENUITEM "&Print...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "Pr&operties...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+F4", ID_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo", ID_UNDO, GRAYED + MENUITEM "&Redo", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Cu&t", ID_CUT, GRAYED + MENUITEM "&Copy", ID_COPY, GRAYED + MENUITEM "&Paste", ID_PASTE, GRAYED + MENUITEM "Paste as new &image", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Select &All", ID_SELALL, GRAYED + END + POPUP "&View" + BEGIN + MENUITEM "&Tools", ID_TOOLS + MENUITEM "&Colours", ID_COLOR + MENUITEM "&History", ID_HISTORY + MENUITEM "&Status Bar", ID_STATUSBAR + END + POPUP "&Adjust" + BEGIN + MENUITEM "Brightness...", ID_BRIGHTNESS + MENUITEM "Contrast...", ID_CONTRAST + MENUITEM "Hue/Saturation...", -1, GRAYED + POPUP "Colour" + BEGIN + MENUITEM "Black and White", ID_BLACKANDWHITE + MENUITEM "Invert Colours", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Blur", ID_BLUR + MENUITEM "Sharpen", ID_SHARPEN + MENUITEM "Smooth Edges", -1, GRAYED + MENUITEM "Add Shadow", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Image Size...", -1, GRAYED + MENUITEM "Flip", -1, GRAYED + MENUITEM "Mirror", -1, GRAYED + MENUITEM "Rotate", -1, GRAYED + + END + POPUP "&Colours" + BEGIN + MENUITEM "&Edit Colours...", ID_EDITCOLOURS + END + POPUP "&Window" + BEGIN + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "Tile &Horizontally", ID_WINDOW_TILE_HORZ + MENUITEM "Tile &Vertically", ID_WINDOW_TILE_VERT + MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Nex&t\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&Help" + BEGIN + MENUITEM "&About...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Brightness" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Colour form:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Full (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Red", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Green", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Blue", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Cancel", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "About ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Close", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Image Properties" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Name:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Canvas properties", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Image type:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Width:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Height:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Resolution:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Unit:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Image size:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Cancel", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "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.\r\n\r\nThis 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.\r\n\r\nYou 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." + IDS_READY " Ready." + IDS_TOOLBAR_STANDARD "Standard" + IDS_TOOLBAR_TEST "Test" + IDS_IMAGE_NAME "Image %1!u!" + IDS_FLT_TOOLS "Tools" + IDS_FLT_COLORS "Colours" + IDS_FLT_HISTORY "History" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Monochrome (1 bit)" + IDS_IMAGE_GREYSCALE "Greyscale (8 bit)" + IDS_IMAGE_PALETTE "Palette or 256 colour (8 bit)" + IDS_IMAGE_TRUECOLOR "True colour (24 bit)" + + IDS_UNIT_PIXELS "Pixels" + IDS_UNIT_CM "Cm" + IDS_UNIT_INCHES "Inches" + IDS_UNIT_DOTSCM "Dots / Cm" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d KB" + IDS_UNIT_MB "%d MB" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "New" + IDS_TOOLTIP_OPEN "Open" + IDS_TOOLTIP_SAVE "Save" + IDS_TOOLTIP_PRINTPRE "Print preview" + IDS_TOOLTIP_PRINT "Print" + IDS_TOOLTIP_CUT "Cut" + IDS_TOOLTIP_COPY "Copy" + IDS_TOOLTIP_PASTE "Paste" + IDS_TOOLTIP_UNDO "Undo" + IDS_TOOLTIP_REDO "Redo" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Creates a new document." + IDS_HINT_OPEN " Opens an existing document." + IDS_HINT_CLOSE " Closes this window." + IDS_HINT_CLOSEALL " Closes all windows." + IDS_HINT_SAVE " Saves the active document." + IDS_HINT_SAVEAS " Saves the active document with a new name." + IDS_HINT_PRINTPRE " Previews the printed document." + IDS_HINT_PRINT " Prints the active document." + IDS_HINT_PROP " Shows the properties of the active image." + IDS_HINT_EXIT " Exits this application." + + IDS_HINT_TOOLS " Shows or hides the tools floating window." + IDS_HINT_COLORS " Shows or hides the colours floating window." + IDS_HINT_HISTORY " Shows or hides the history floating window." + IDS_HINT_STATUS " Shows or hides the status bar." + + IDS_HINT_CASCADE " Arrange windows so they overlap." + IDS_HINT_TILE_HORZ " Arrange windows as non-overlapping tiles." + IDS_HINT_TILE_VERT " Arrange windows as non-overlapping tiles." + IDS_HINT_ARRANGE " Arrange icons at the bottom of the window." + IDS_HINT_NEXT " Activates the next window." + + IDS_HINT_SYS_RESTORE " Restores this window to normal size." + IDS_HINT_SYS_MOVE " Moves this window." + IDS_HINT_SYS_SIZE " Resizes this window." + IDS_HINT_SYS_MINIMIZE " Collapses this window to an icon." + IDS_HINT_SYS_MAXIMIZE " Expands this window to fill this screen." +END diff --git a/modules/rosapps/applications/imagesoft/lang/en-US.rc b/modules/rosapps/applications/imagesoft/lang/en-US.rc new file mode 100644 index 00000000000..c3b9a3ced28 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/en-US.rc @@ -0,0 +1,232 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New...", ID_NEW + MENUITEM "&Open...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Close\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "C&lose all", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "&Save", ID_SAVE, GRAYED + MENUITEM "Save &As...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Print Pre&view", ID_PRINTPRE,GRAYED + MENUITEM "&Print...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "Pr&operties...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+F4", ID_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo", ID_UNDO, GRAYED + MENUITEM "&Redo", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Cu&t", ID_CUT, GRAYED + MENUITEM "&Copy", ID_COPY, GRAYED + MENUITEM "&Paste", ID_PASTE, GRAYED + MENUITEM "Paste as new &image", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Select &All", ID_SELALL, GRAYED + END + POPUP "&View" + BEGIN + MENUITEM "&Tools", ID_TOOLS + MENUITEM "&Colors", ID_COLOR + MENUITEM "&History", ID_HISTORY + MENUITEM "&Status Bar", ID_STATUSBAR + END + POPUP "&Adjust" + BEGIN + MENUITEM "Brightness...", ID_BRIGHTNESS + MENUITEM "Contrast...", ID_CONTRAST + MENUITEM "Hue/Saturation...", -1, GRAYED + POPUP "Color" + BEGIN + MENUITEM "Black and White", ID_BLACKANDWHITE + MENUITEM "Invert Colors", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Blur", ID_BLUR + MENUITEM "Sharpen", ID_SHARPEN + MENUITEM "Smooth Edges", -1, GRAYED + MENUITEM "Add Shadow", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Image Size...", -1, GRAYED + MENUITEM "Flip", -1, GRAYED + MENUITEM "Mirror", -1, GRAYED + MENUITEM "Rotate", -1, GRAYED + + END + POPUP "&Colors" + BEGIN + MENUITEM "&Edit Colors...", ID_EDITCOLOURS + END + POPUP "&Window" + BEGIN + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "Tile &Horizontally", ID_WINDOW_TILE_HORZ + MENUITEM "Tile &Vertically", ID_WINDOW_TILE_VERT + MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Nex&t\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&Help" + BEGIN + MENUITEM "&About...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Brightness" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Color form:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Full (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Red", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Green", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Blue", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Cancel", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "About ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Close", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Image Properties" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Name:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Canvas properties", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Image type:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Width:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Height:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Resolution:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Unit:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Image size:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Cancel", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "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.\r\n\r\nThis 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.\r\n\r\nYou 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." + IDS_READY " Ready." + IDS_TOOLBAR_STANDARD "Standard" + IDS_TOOLBAR_TEST "Test" + IDS_IMAGE_NAME "Image %1!u!" + IDS_FLT_TOOLS "Tools" + IDS_FLT_COLORS "Colors" + IDS_FLT_HISTORY "History" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Monochrome (1 bit)" + IDS_IMAGE_GREYSCALE "Grayscale (8 bit)" + IDS_IMAGE_PALETTE "Palette or 256 color (8 bit)" + IDS_IMAGE_TRUECOLOR "True color (24 bit)" + + IDS_UNIT_PIXELS "Pixels" + IDS_UNIT_CM "Cm" + IDS_UNIT_INCHES "Inches" + IDS_UNIT_DOTSCM "Dots / Cm" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d KB" + IDS_UNIT_MB "%d MB" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "New" + IDS_TOOLTIP_OPEN "Open" + IDS_TOOLTIP_SAVE "Save" + IDS_TOOLTIP_PRINTPRE "Print preview" + IDS_TOOLTIP_PRINT "Print" + IDS_TOOLTIP_CUT "Cut" + IDS_TOOLTIP_COPY "Copy" + IDS_TOOLTIP_PASTE "Paste" + IDS_TOOLTIP_UNDO "Undo" + IDS_TOOLTIP_REDO "Redo" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Creates a new document." + IDS_HINT_OPEN " Opens an existing document." + IDS_HINT_CLOSE " Closes this window." + IDS_HINT_CLOSEALL " Closes all windows." + IDS_HINT_SAVE " Saves the active document." + IDS_HINT_SAVEAS " Saves the active document with a new name." + IDS_HINT_PRINTPRE " Previews the printed document." + IDS_HINT_PRINT " Prints the active document." + IDS_HINT_PROP " Shows the properties of the active image." + IDS_HINT_EXIT " Exits this application." + + IDS_HINT_TOOLS " Shows or hides the tools floating window." + IDS_HINT_COLORS " Shows or hides the colors floating window." + IDS_HINT_HISTORY " Shows or hides the history floating window." + IDS_HINT_STATUS " Shows or hides the status bar." + + IDS_HINT_CASCADE " Arrange windows so they overlap." + IDS_HINT_TILE_HORZ " Arrange windows as non-overlapping tiles." + IDS_HINT_TILE_VERT " Arrange windows as non-overlapping tiles." + IDS_HINT_ARRANGE " Arrange icons at the bottom of the window." + IDS_HINT_NEXT " Activates the next window." + + IDS_HINT_SYS_RESTORE " Restores this window to normal size." + IDS_HINT_SYS_MOVE " Moves this window." + IDS_HINT_SYS_SIZE " Resizes this window." + IDS_HINT_SYS_MINIMIZE " Collapses this window to an icon." + IDS_HINT_SYS_MAXIMIZE " Expands this window to fill this screen." +END diff --git a/modules/rosapps/applications/imagesoft/lang/es-ES.rc b/modules/rosapps/applications/imagesoft/lang/es-ES.rc new file mode 100644 index 00000000000..244f621b8e2 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/es-ES.rc @@ -0,0 +1,232 @@ +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&Archivo" + BEGIN + MENUITEM "&Nuevo...", ID_NEW + MENUITEM "&Abrir...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Cerrar\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "C&errar todo", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "&Guardar", ID_SAVE, GRAYED + MENUITEM "G&uardar Como...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Vista Preliminar", ID_PRINTPRE,GRAYED + MENUITEM "&Imprimir...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "Pr&opiedades...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Salir\tAlt+F4", ID_EXIT + END + POPUP "&Editar" + BEGIN + MENUITEM "&Deshacer", ID_UNDO, GRAYED + MENUITEM "&Rehacer", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Cor&tar", ID_CUT, GRAYED + MENUITEM "&Copiar", ID_COPY, GRAYED + MENUITEM "&Pegar", ID_PASTE, GRAYED + MENUITEM "Pegar como nueva &imagen", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Seleccionar t&odo", ID_SELALL, GRAYED + END + POPUP "&Ver" + BEGIN + MENUITEM "H&erramientas", ID_TOOLS + MENUITEM "&Colores", ID_COLOR + MENUITEM "&Historia", ID_HISTORY + MENUITEM "&Barra de estado", ID_STATUSBAR + END + POPUP "&Ajuste" + BEGIN + MENUITEM "Brillo...", ID_BRIGHTNESS + MENUITEM "Contraste...", ID_CONTRAST + MENUITEM "Matiz/Saturación...", -1, GRAYED + POPUP "Color" + BEGIN + MENUITEM "Blanco y negro", ID_BLACKANDWHITE + MENUITEM "Invertir Colores", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Contorno", ID_BLUR + MENUITEM "Afilar", ID_SHARPEN + MENUITEM "Suavizar bordes", -1, GRAYED + MENUITEM "Añadir Sombra", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Tamaño de la Imagen...", -1, GRAYED + MENUITEM "Voltear", -1, GRAYED + MENUITEM "Espejo", -1, GRAYED + MENUITEM "Rotar", -1, GRAYED + + END + POPUP "&Colores" + BEGIN + MENUITEM "&Editar Colores...", ID_EDITCOLOURS + END + POPUP "&Ventana" + BEGIN + MENUITEM "&Cascada", ID_WINDOW_CASCADE + MENUITEM "Dividir &Horizontalmente", ID_WINDOW_TILE_HORZ + MENUITEM "Dividir &Verticalmente", ID_WINDOW_TILE_VERT + MENUITEM "&Organizar Iconos", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Siguien&te\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "Ay&uda" + BEGIN + MENUITEM "&Acerca de...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Brillo" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Color de:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Completo (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Rojo", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Verde", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Azul", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "Aceptar", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Cancelar", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "Acerca de ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Cerrar", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Propiedades de la Imagen" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Nombre:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Propiedades de la imagen ", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Tipo de Imagen:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Anchura:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Altura:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Resolución:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Unidades:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Tamaño de la imagen:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "Aceptar", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Cancelar", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "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.\r\n\r\nThis 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.\r\n\r\nYou 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." + IDS_READY " Preparado." + IDS_TOOLBAR_STANDARD "Estándar" + IDS_TOOLBAR_TEST "Prueba" + IDS_IMAGE_NAME "Imagen %1!u!" + IDS_FLT_TOOLS "Herramientas" + IDS_FLT_COLORS "Colores" + IDS_FLT_HISTORY "Historial" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Monocromo (1 bit)" + IDS_IMAGE_GREYSCALE "Escala de Grises (8 bit)" + IDS_IMAGE_PALETTE "Paleta o 256 colores (8 bit)" + IDS_IMAGE_TRUECOLOR "Color verdadero (24 bit)" + + IDS_UNIT_PIXELS "Pixels" + IDS_UNIT_CM "Cm" + IDS_UNIT_INCHES "Pulgadas" + IDS_UNIT_DOTSCM "Puntos / Cm" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d KB" + IDS_UNIT_MB "%d MB" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Nuevo" + IDS_TOOLTIP_OPEN "Abrir" + IDS_TOOLTIP_SAVE "Guardar" + IDS_TOOLTIP_PRINTPRE "Vista preliminar" + IDS_TOOLTIP_PRINT "Imprimir" + IDS_TOOLTIP_CUT "Cortar" + IDS_TOOLTIP_COPY "Copiar" + IDS_TOOLTIP_PASTE "Pegar" + IDS_TOOLTIP_UNDO "Deshacer" + IDS_TOOLTIP_REDO "Rehacer" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Crear un documento nuevo." + IDS_HINT_OPEN " Abrir un documento existente." + IDS_HINT_CLOSE " Cerrar esta ventana." + IDS_HINT_CLOSEALL " Cerrar todas las ventanas." + IDS_HINT_SAVE " Guardar el documento activo." + IDS_HINT_SAVEAS " Guardar el documento activo con un nuevo nombre." + IDS_HINT_PRINTPRE " Previsualizar impresión." + IDS_HINT_PRINT " Imprimir el documento activo." + IDS_HINT_PROP " Mostrar las propiedades de la imagen activa." + IDS_HINT_EXIT " Cerrar esta aplicación." + + IDS_HINT_TOOLS " Mostrar u ocultar la ventana flotante de herramientas." + IDS_HINT_COLORS " Mostrar u ocultar la ventana flotante de colores." + IDS_HINT_HISTORY " Mostrar u ocultar la ventana flotande de historial." + IDS_HINT_STATUS " Mostrar u ocultar la barra de estado." + + IDS_HINT_CASCADE " Colocar las ventanas superpuestas." + IDS_HINT_TILE_HORZ " Colocar las ventanas sin superponer los títulos." + IDS_HINT_TILE_VERT " Colocar las ventanas sin superponer los títulos." + IDS_HINT_ARRANGE " Colocar los iconos en la parte baja de la ventana." + IDS_HINT_NEXT " Activar la siguiente ventana." + + IDS_HINT_SYS_RESTORE " Restaurar esta ventana al tamaño normal." + IDS_HINT_SYS_MOVE " Mover esta ventana." + IDS_HINT_SYS_SIZE " Redimensionar esta ventana." + IDS_HINT_SYS_MINIMIZE " Minimizar esta ventana a un icono." + IDS_HINT_SYS_MAXIMIZE " Expandir esta ventana para llenar la pantalla." +END diff --git a/modules/rosapps/applications/imagesoft/lang/fr-FR.rc b/modules/rosapps/applications/imagesoft/lang/fr-FR.rc new file mode 100644 index 00000000000..1d31b417d91 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/fr-FR.rc @@ -0,0 +1,232 @@ +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&Fichier" + BEGIN + MENUITEM "&Nouveau...", ID_NEW + MENUITEM "&Ouvrir...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "Fermer\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "Fermer tout", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "Enregistrer", ID_SAVE, GRAYED + MENUITEM "Enregistrer sous...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Aperçu a&vant impression", ID_PRINTPRE,GRAYED + MENUITEM "Im&primer...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "Pr&opriétés...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "Quitter\tAlt+F4", ID_EXIT + END + POPUP "&Édition" + BEGIN + MENUITEM "Annuler", ID_UNDO, GRAYED + MENUITEM "&Rétablir", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Couper", ID_CUT, GRAYED + MENUITEM "&Copier", ID_COPY, GRAYED + MENUITEM "Coller", ID_PASTE, GRAYED + MENUITEM "Coller en tant qu'&image", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Tout sélectionner", ID_SELALL, GRAYED + END + POPUP "Affichage" + BEGIN + MENUITEM "Ou&tils", ID_TOOLS + MENUITEM "&Couleurs", ID_COLOR + MENUITEM "&Historique", ID_HISTORY + MENUITEM "Barre de &status", ID_STATUSBAR + END + POPUP "Régl&age" + BEGIN + MENUITEM "Luminosité...", ID_BRIGHTNESS + MENUITEM "Contraste...", ID_CONTRAST + MENUITEM "Teinte/Saturation...", -1, GRAYED + POPUP "Couleur" + BEGIN + MENUITEM "Noir et blanc", ID_BLACKANDWHITE + MENUITEM "Inverser les couleurs", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Rendre flou", ID_BLUR + MENUITEM "Accentuer", ID_SHARPEN + MENUITEM "Lisser les bords", -1, GRAYED + MENUITEM "Ajouter une ombre", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Taille de l'image...", -1, GRAYED + MENUITEM "Retourner", -1, GRAYED + MENUITEM "Inverser", -1, GRAYED // FIXME : Pourrait-être amélioré pour mieux dégager le sens de "mirror" + MENUITEM "Tourner", -1, GRAYED + + END + POPUP "&Couleurs" + BEGIN + MENUITEM "&Éditer les couleurs...", ID_EDITCOLOURS + END + POPUP "Fenêtre" + BEGIN + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "Mosaïque &horizontale", ID_WINDOW_TILE_HORZ + MENUITEM "Mosaïque &verticale", ID_WINDOW_TILE_VERT + MENUITEM "&Arranger les icônes", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Suivan&te\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "Aide" + BEGIN + MENUITEM "&À propos...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Luminosité" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Composante de la couleur:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Complète (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Rouge", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Vert", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Bleu", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Annuler", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "À propos d'ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Fermer", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Propriétés de l'image" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Nom:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Propriétés du support", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Type de l'image:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Largeur:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Hauteur:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Résolution:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Unité:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Taille de l'image:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Annuler", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "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.\r\n\r\nThis 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.\r\n\r\nYou 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." + IDS_READY " Prêt." + IDS_TOOLBAR_STANDARD "Standard" + IDS_TOOLBAR_TEST "Test" + IDS_IMAGE_NAME "Image %1!u!" + IDS_FLT_TOOLS "Outils" + IDS_FLT_COLORS "Couleurs" + IDS_FLT_HISTORY "Historique" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Monochrome (1 bit)" + IDS_IMAGE_GREYSCALE "Variantes de gris (8 bit)" + IDS_IMAGE_PALETTE "Palette ou 256 couleurs (8 bit)" + IDS_IMAGE_TRUECOLOR "Couleurs vraies (24 bit)" + + IDS_UNIT_PIXELS "Pixels" + IDS_UNIT_CM "Cm" + IDS_UNIT_INCHES "Pouces" + IDS_UNIT_DOTSCM "Points / Cm" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d Ko" + IDS_UNIT_MB "%d Mo" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Nouveau" + IDS_TOOLTIP_OPEN "Ouvrir" + IDS_TOOLTIP_SAVE "Enregistrer" + IDS_TOOLTIP_PRINTPRE "Aperçu avant impression" + IDS_TOOLTIP_PRINT "Imprimer" + IDS_TOOLTIP_CUT "Couper" + IDS_TOOLTIP_COPY "Copier" + IDS_TOOLTIP_PASTE "Coller" + IDS_TOOLTIP_UNDO "Annuler" + IDS_TOOLTIP_REDO "Rétablir" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Créé un nouveau document." + IDS_HINT_OPEN " Ouvre un document existant." + IDS_HINT_CLOSE " Ferme cette fenêtre." + IDS_HINT_CLOSEALL " Ferme toutes les fenêtres." + IDS_HINT_SAVE " Enregistre le document courant." + IDS_HINT_SAVEAS " Enregistre le document courant sous un nouveau nom." + IDS_HINT_PRINTPRE " Aperçu avant impression." + IDS_HINT_PRINT " Imprime le document courant." + IDS_HINT_PROP " Montre les propriétés de l'image courante." + IDS_HINT_EXIT " Quitte cette application." + + IDS_HINT_TOOLS " Montre ou cache la fenêtre flottante des outils." + IDS_HINT_COLORS " Montre ou cache la fenêtre flottante des couleurs." + IDS_HINT_HISTORY " Montre ou cache la fenêtre flottante de l'historique." + IDS_HINT_STATUS " Montre ou cache la barre de status." + + IDS_HINT_CASCADE " Arrange les fenêtres en cascade." + IDS_HINT_TILE_HORZ " Arrange les fenêtres en mosaïque horizontale." + IDS_HINT_TILE_VERT " Arrange les fenêtres en mosaïque verticale." + IDS_HINT_ARRANGE " Arrange les icônes en bas de la fenêtre." + IDS_HINT_NEXT " Active la prochaine fenêtre." + + IDS_HINT_SYS_RESTORE " Restaure la taille normale de la fenêtre." + IDS_HINT_SYS_MOVE " Bouge la fenêtre." + IDS_HINT_SYS_SIZE " Retaille la fenêtre." + IDS_HINT_SYS_MINIMIZE " Réduit la fenêtre." + IDS_HINT_SYS_MAXIMIZE " Affiche la fenêtre en plein écran." +END diff --git a/modules/rosapps/applications/imagesoft/lang/id-ID.rc b/modules/rosapps/applications/imagesoft/lang/id-ID.rc new file mode 100644 index 00000000000..09713985ae2 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/id-ID.rc @@ -0,0 +1,232 @@ +LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Baru...", ID_NEW + MENUITEM "B&uka...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Tutup\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "Tutup s&emua", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "&Simpan", ID_SAVE, GRAYED + MENUITEM "Simpan Seb&agai...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Tin&jau Cetakan", ID_PRINTPRE,GRAYED + MENUITEM "&Cetak...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "Pr&operti...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Keluar\tAlt+F4", ID_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo", ID_UNDO, GRAYED + MENUITEM "&Redo", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Cu&t", ID_CUT, GRAYED + MENUITEM "&Copy", ID_COPY, GRAYED + MENUITEM "&Paste", ID_PASTE, GRAYED + MENUITEM "Paste sebagai gambar &baru", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Pilih &Semua", ID_SELALL, GRAYED + END + POPUP "&Lihat" + BEGIN + MENUITEM "&Piranti", ID_TOOLS + MENUITEM "&Warna", ID_COLOR + MENUITEM "&Histori", ID_HISTORY + MENUITEM "Bar &Status", ID_STATUSBAR + END + POPUP "Sesu&aikan" + BEGIN + MENUITEM "Kecerahan...", ID_BRIGHTNESS + MENUITEM "Kontras...", ID_CONTRAST + MENUITEM "Hue/Saturasi...", -1, GRAYED + POPUP "Warna" + BEGIN + MENUITEM "Hitam dan Putih", ID_BLACKANDWHITE + MENUITEM "Balikkan Warna", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Blur", ID_BLUR + MENUITEM "Sharpen", ID_SHARPEN + MENUITEM "Lembutkan Sisi", -1, GRAYED + MENUITEM "Tambah Bayangan", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Ukuran Gambar...", -1, GRAYED + MENUITEM "Flip", -1, GRAYED + MENUITEM "Cermin", -1, GRAYED + MENUITEM "Rotasi", -1, GRAYED + + END + POPUP "&Warna" + BEGIN + MENUITEM "&Edit Warna...", ID_EDITCOLOURS + END + POPUP "&Jendela" + BEGIN + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "Tile &Horisontal", ID_WINDOW_TILE_HORZ + MENUITEM "Tile &Vertikal", ID_WINDOW_TILE_VERT + MENUITEM "&Atur Ikon", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Beriku&t\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&Bantuan" + BEGIN + MENUITEM "&Tentang...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Kecerahan" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Form warna:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Penuh (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Merah", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Hijau", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Biru", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Batal", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "Tentang ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nHak Cipta (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Tutup", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Properti Gambar" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Nama:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Properti Kanvas", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Tipe gambar:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Panjang:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Tinggi:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Resolusi:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Unit:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Besar gambar:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Batal", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "Program ini adalah software bebas; anda dapat mendistribusikan dan/atau mengubahnya di bawah term GNU General Public License seperti dipublikasikan oleh Free Software Foundation; baik Lisensi versi 2, atau (menurut opini anda) setiap versi berikutnya.\r\n\r\nProgram ini didistribusikan dengan harapan ia akan berguna, tetapi TANPA JAMINAN APAPUN; bahkan tanpa jaminan berarti dari MERCANTABILITAS atau KECUKUPAN UNTUK KEPERLUAN TERTENTU. Lihat GNU General Public License untuk lebih jelasnya.\r\n\r\nAnda seharusnya menerima duplikat GNU General Public License bersamaan dengan program ini; jika tidak, tulis ke Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA." + IDS_READY " Siap." + IDS_TOOLBAR_STANDARD "Standar" + IDS_TOOLBAR_TEST "Uji" + IDS_IMAGE_NAME "Gambar %1!u!" + IDS_FLT_TOOLS "Piranti" + IDS_FLT_COLORS "Warna" + IDS_FLT_HISTORY "Histori" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Monokrom (1 bit)" + IDS_IMAGE_GREYSCALE "Abu-abu (8 bit)" + IDS_IMAGE_PALETTE "Palet atau 256 warna (8 bit)" + IDS_IMAGE_TRUECOLOR "Warna asli (24 bit)" + + IDS_UNIT_PIXELS "Pixel" + IDS_UNIT_CM "Cm" + IDS_UNIT_INCHES "Inci" + IDS_UNIT_DOTSCM "Dot / Cm" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d KB" + IDS_UNIT_MB "%d MB" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Baru" + IDS_TOOLTIP_OPEN "Buka" + IDS_TOOLTIP_SAVE "Simpan" + IDS_TOOLTIP_PRINTPRE "Tinjau cetakan" + IDS_TOOLTIP_PRINT "Cetak" + IDS_TOOLTIP_CUT "Cut" + IDS_TOOLTIP_COPY "Copy" + IDS_TOOLTIP_PASTE "Paste" + IDS_TOOLTIP_UNDO "Undo" + IDS_TOOLTIP_REDO "Redo" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Membuat dokumen baru." + IDS_HINT_OPEN " Membuka dokumen yang sudah ada." + IDS_HINT_CLOSE " Menutup jendela ini." + IDS_HINT_CLOSEALL " Menutup semua jendela." + IDS_HINT_SAVE " Menyimpan dokumen aktif." + IDS_HINT_SAVEAS " Menyimpan dokumen aktif dengan nama baru." + IDS_HINT_PRINTPRE " Meninjau dulu dokumen yang dicetak." + IDS_HINT_PRINT " Mencetak dokumen aktif." + IDS_HINT_PROP " Menampilkan properti gambar yang aktif." + IDS_HINT_EXIT " Keluar aplikasi ini." + + IDS_HINT_TOOLS " Menampilkan atau menyembunyikan jendela layang piranti." + IDS_HINT_COLORS " Menampilkan atau menyembunyikan jendela layang warna." + IDS_HINT_HISTORY " Menampilkan atau menyembunyikan jendela layang histori." + IDS_HINT_STATUS " Menampilkan atau menyembunyikan bar status." + + IDS_HINT_CASCADE " Mengatur jendela agar saling tindih." + IDS_HINT_TILE_HORZ " Mengatur jendela seperti ubin tidak saling tindih." + IDS_HINT_TILE_VERT " Mengatur jendela seperti ubin tidak saling tindih." + IDS_HINT_ARRANGE " Mengatur ikon di bawah jendela." + IDS_HINT_NEXT " Mengaktifkan jendela berikutnya." + + IDS_HINT_SYS_RESTORE " Mengembalikan jendela ini ke ukuran normal." + IDS_HINT_SYS_MOVE " Memindahkan jendela ini." + IDS_HINT_SYS_SIZE " Mengukur ulang jendela ini." + IDS_HINT_SYS_MINIMIZE " Menyempitkan jendela ini menjadi ikon." + IDS_HINT_SYS_MAXIMIZE " Melebarkan jendela ini memenuhi layar ini." +END diff --git a/modules/rosapps/applications/imagesoft/lang/it-IT.rc b/modules/rosapps/applications/imagesoft/lang/it-IT.rc new file mode 100644 index 00000000000..984149bf1a8 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/it-IT.rc @@ -0,0 +1,232 @@ +LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Nuovo...", ID_NEW + MENUITEM "&Apri...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Chiudi\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "C&hiudi tutto", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "&Salva", ID_SAVE, GRAYED + MENUITEM "Salva co&n nome...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Ant&eprima di stampa", ID_PRINTPRE,GRAYED + MENUITEM "S&tampa...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "Pr&oprietà...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Esci\tAlt+F4", ID_EXIT + END + POPUP "&Modifica" + BEGIN + MENUITEM "&Annulla", ID_UNDO, GRAYED + MENUITEM "&Ripeti", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Taglia", ID_CUT, GRAYED + MENUITEM "&Copia", ID_COPY, GRAYED + MENUITEM "&Incolla", ID_PASTE, GRAYED + MENUITEM "Incolla come &nuova immagine", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Seleziona tutto", ID_SELALL, GRAYED + END + POPUP "&Visualizza" + BEGIN + MENUITEM "&Strumenti", ID_TOOLS + MENUITEM "&Colori", ID_COLOR + MENUITEM "&Azioni", ID_HISTORY + MENUITEM "&Barra di stato", ID_STATUSBAR + END + POPUP "Co&rreggi" + BEGIN + MENUITEM "Luminosità...", ID_BRIGHTNESS + MENUITEM "Contrasto...", ID_CONTRAST + MENUITEM "Tonalità/Saturazione...", -1, GRAYED + POPUP "Colore" + BEGIN + MENUITEM "Bianco e nero", ID_BLACKANDWHITE + MENUITEM "Inverti i colori", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Soffuso", ID_BLUR + MENUITEM "Nitido", ID_SHARPEN + MENUITEM "Bordi arrotondati", -1, GRAYED + MENUITEM "Ombra", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Dimensione immagine...", -1, GRAYED + MENUITEM "Ribalta", -1, GRAYED + MENUITEM "Specchio", -1, GRAYED + MENUITEM "Ruota", -1, GRAYED + + END + POPUP "&Colori" + BEGIN + MENUITEM "&Modifica i colori...", ID_EDITCOLOURS + END + POPUP "&Finestre" + BEGIN + MENUITEM "&Sovrapponi", ID_WINDOW_CASCADE + MENUITEM "Affianca &Orizzontalmente", ID_WINDOW_TILE_HORZ + MENUITEM "Affianca &Verticalmente", ID_WINDOW_TILE_VERT + MENUITEM "&Disponi Icone", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Succ&essiva\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&Aiuto" + BEGIN + MENUITEM "&Informazioni...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Luminosità" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Tipo colore:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Full (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Rosso", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Verde", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Blu", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Annulla", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "Informazioni su ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Chiudi", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Proprietà dell'immagine" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Nome:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Proprietà Canvas", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Tipo immagine:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Larghezza:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Altezza:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Risoluzione:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Unità:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Dimensione:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Annulla", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "Questo programma è software libero; puoi distribuirlo e/o modificarlo nei termini di licenza di 'GNU General Public License' come pubblicata dalla 'Free Software Foundation'; entrambe le versioni 2 della Licenza, o (a vostra scelta) qualunque versione successiva.\r\n\r\nQuesto programma è distribuito con l'augurio che sia utile, ma PRIVO DI OGNI GARANZIA; privo anche della garanzia implicita di VENDIBILITA' o ADEGUATEZZA PER UNO SPECIFICO USO. Vedi la 'GNU General Public License' per ulteriori dettagli.\r\n\r\nVoi dovreste aver ricevuto una copia della 'GNU General Public License' assieme a questo programma; se non è cosi' scrivete a 'Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA'." + IDS_READY "Pronto." + IDS_TOOLBAR_STANDARD "Standard" + IDS_TOOLBAR_TEST "Test" + IDS_IMAGE_NAME "Immagine %1!u!" + IDS_FLT_TOOLS "Strumenti" + IDS_FLT_COLORS "Colori" + IDS_FLT_HISTORY "Azioni" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Monocromatico (1 bit)" + IDS_IMAGE_GREYSCALE "Toni di grigio (8 bit)" + IDS_IMAGE_PALETTE "Palette o 256 colori (8 bit)" + IDS_IMAGE_TRUECOLOR "True color (24 bit)" + + IDS_UNIT_PIXELS "Pixel" + IDS_UNIT_CM "Cm" + IDS_UNIT_INCHES "Inches" + IDS_UNIT_DOTSCM "Dots / Cm" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d KB" + IDS_UNIT_MB "%d MB" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Nuova" + IDS_TOOLTIP_OPEN "Apri" + IDS_TOOLTIP_SAVE "Salva" + IDS_TOOLTIP_PRINTPRE "Anteprima di stampa" + IDS_TOOLTIP_PRINT "stampa" + IDS_TOOLTIP_CUT "Taglia" + IDS_TOOLTIP_COPY "Copia" + IDS_TOOLTIP_PASTE "Incolla" + IDS_TOOLTIP_UNDO "Annulla" + IDS_TOOLTIP_REDO "Ripeti" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Crea un nuovo documento." + IDS_HINT_OPEN " Apre un documento esistente." + IDS_HINT_CLOSE " Chiude questa finestra." + IDS_HINT_CLOSEALL " Chiude tutte le finestre." + IDS_HINT_SAVE " Salva il documento attivo." + IDS_HINT_SAVEAS " Salva il documento attivo con un nuovo nome." + IDS_HINT_PRINTPRE " Anteprima del documento stampato." + IDS_HINT_PRINT " Stampa il documento attivo." + IDS_HINT_PROP " Mostra le proprieta' dell'immagine attiva." + IDS_HINT_EXIT " Chiude il programma." + + IDS_HINT_TOOLS " Mostra o nasconde la finestra mobile degli strumenti." + IDS_HINT_COLORS " Mostra o nasconde la finestra mobile dei colori." + IDS_HINT_HISTORY " Mostra o nasconde la finestra mobile delle azioni." + IDS_HINT_STATUS " Mostra o nasconde la barra di stato." + + IDS_HINT_CASCADE " Dispone le finestre in modo che siano sovrapposte." + IDS_HINT_TILE_HORZ " Dispone le finestre in modo che non siano sovrapposte." + IDS_HINT_TILE_VERT " Dispone le finestre in modo che non siano sovrapposte." + IDS_HINT_ARRANGE " Dispone le icone in basso nella finestra." + IDS_HINT_NEXT " Attiva la finestra successiva." + + IDS_HINT_SYS_RESTORE " Ripristina la dimensione normale della finestra." + IDS_HINT_SYS_MOVE " Sposta la finestra." + IDS_HINT_SYS_SIZE " Modifica la dimensione della finestra." + IDS_HINT_SYS_MINIMIZE " Riduce la finestra ad una icona." + IDS_HINT_SYS_MAXIMIZE " Espande la finestra fino a riempire lo schermo." +END diff --git a/modules/rosapps/applications/imagesoft/lang/no-NO.rc b/modules/rosapps/applications/imagesoft/lang/no-NO.rc new file mode 100644 index 00000000000..570fd57853d --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/no-NO.rc @@ -0,0 +1,231 @@ +LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&Fil" + BEGIN + MENUITEM "&Ny...", ID_NEW + MENUITEM "&Åpne...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Lukk\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "L&ukk alt", ID_CLOSEALL, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Lagre", ID_SAVE, GRAYED + MENUITEM "Lagre &som...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Utskrift &ForhÃ¥ndsvisning", ID_PRINTPRE, GRAYED + MENUITEM "&Utskrift...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "E&genskaper...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "A&vslutt\tAlt+F4", ID_EXIT + END + POPUP "&Rediger" + BEGIN + MENUITEM "&Angre", ID_UNDO, GRAYED + MENUITEM "&Gjenta", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Klipp &ut", ID_CUT, GRAYED + MENUITEM "&Kopier", ID_COPY, GRAYED + MENUITEM "&Lim inn", ID_PASTE, GRAYED + MENUITEM "lim inn som ny &bilde", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Velg Alt", ID_SELALL, GRAYED + END + POPUP "&Vis" + BEGIN + MENUITEM "&Vertøy", ID_TOOLS, CHECKED + MENUITEM "&Farger", ID_COLOR, CHECKED + MENUITEM "&Historie", ID_HISTORY, CHECKED + MENUITEM "&Statuslinje", ID_STATUSBAR, CHECKED + END + POPUP "&Still" + BEGIN + MENUITEM "Lysstyrke...", ID_BRIGHTNESS + MENUITEM "Kontrast...", ID_CONTRAST + MENUITEM "Fargetone/metning...", -1, GRAYED + POPUP "Farger" + BEGIN + MENUITEM "Svart og hvit", ID_BLACKANDWHITE + MENUITEM "Inverter farger", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Uskarphet", ID_BLUR + MENUITEM "Sharpen", ID_SHARPEN + MENUITEM "Jevne kantlinje", -1, GRAYED + MENUITEM "Legg til skygger", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Bilde størrelse...", -1, GRAYED + MENUITEM "Flip", -1, GRAYED + MENUITEM "Speil", -1, GRAYED + MENUITEM "Rotere", -1, GRAYED + + END + POPUP "&Farger" + BEGIN + MENUITEM "&Rediger farger...", ID_EDITCOLOURS + END + POPUP "&vindu" + BEGIN + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "Sorter &horisontalt", ID_WINDOW_TILE_HORZ + MENUITEM "Sorter &vertikalt", ID_WINDOW_TILE_VERT + MENUITEM "&Ordne Ikoner", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Nes&te\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&Hjelp" + BEGIN + MENUITEM "&Om...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Lysstyrke" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Farge form:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Full (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Rød", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Grønn", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "BlÃ¥", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Avbryt", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "Om ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nEnerett (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Lukk", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Bilde egenskaper" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Navn:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "maleri egenskaper", IDC_STATIC, 4, 22, 148, 98 + LTEXT "bilde type:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Lengde:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Høyde:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Oppløsning:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Enhet:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "bilde størrelse:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Avbryt", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "Dette programmet er gratis programvare; du kan distribuere det og/eller endre det under betingelsene av GNU General Public License som er utgitt av Free Software Foundation; version 2 av lisensen, eller (etter din mening) alle senere versjoner.\r\n\r\nDette programmet er utgitt i hÃ¥p for at det skal kunne brukes, men DET ER INGEN GARANTIER; uten heller forutsatt garantier av SALGBARHET eller SIKKETHET FOR EN ENKELTHET FORMÅL. Se pÃ¥ GNU General Public Lisensen for mere detaljer.\r\n\r\nDu skal ha motatt en kopi av GNU General Public Lisensen sammen med denne programmet; hvis du ikke har motatt det, skriv til Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA." + IDS_READY " Klart." + IDS_TOOLBAR_STANDARD "Standard" + IDS_TOOLBAR_TEST "Test" + IDS_IMAGE_NAME "Bilde %1!u!" + IDS_FLT_TOOLS "Verktøy" + IDS_FLT_COLORS "Farger" + IDS_FLT_HISTORY "Historie" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Monokromt (1 bit)" + IDS_IMAGE_GREYSCALE "GrÃ¥verdiskala (8 bit)" + IDS_IMAGE_PALETTE "Palett eller 256 farger (8 bit)" + IDS_IMAGE_TRUECOLOR "Nøyaktig farger (24 bit)" + + IDS_UNIT_PIXELS "pikseler" + IDS_UNIT_CM "Cm" + IDS_UNIT_INCHES "tommer" + IDS_UNIT_DOTSCM "Tommer / Cm" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d KB" + IDS_UNIT_MB "%d MB" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Ny" + IDS_TOOLTIP_OPEN "Åpne" + IDS_TOOLTIP_SAVE "Lagre" + IDS_TOOLTIP_PRINTPRE "Utskrift &ForhÃ¥ndsvisning" + IDS_TOOLTIP_PRINT "Utskrift" + IDS_TOOLTIP_CUT "Klipp ut" + IDS_TOOLTIP_COPY "Kopier" + IDS_TOOLTIP_PASTE "Lim inn" + IDS_TOOLTIP_UNDO "Angre" + IDS_TOOLTIP_REDO "Gjenta" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Åpne et nytt dokument." + IDS_HINT_OPEN " Åpene en eksisterende dokument." + IDS_HINT_CLOSE " Lukk dette vinduet." + IDS_HINT_CLOSEALL " Lukk alle vinduer." + IDS_HINT_SAVE " Lagre aktive dokument." + IDS_HINT_SAVEAS " Lagre aktive dokument med nytt navn." + IDS_HINT_PRINTPRE " ForhÃ¥ndsvis utskrift." + IDS_HINT_PRINT " Skriv ut aktive dokument." + IDS_HINT_PROP " Vis egenskaper for aktive bilde." + IDS_HINT_EXIT " Avslutt denne applikasjonen." + + IDS_HINT_TOOLS " Vis eller skjul verktøy floating vindu." + IDS_HINT_COLORS " Vis eller skjul fargene floating vindu." + IDS_HINT_HISTORY " Vis eller skjul historie floating vindu." + IDS_HINT_STATUS " Vis eller skjul statuslinje." + + IDS_HINT_CASCADE " Ordne vinduer sÃ¥ de overlapper." + IDS_HINT_TILE_HORZ " Ordne vinduer sÃ¥ ingen-overlapper tittelen." + IDS_HINT_TILE_VERT " Ordne vinduer sÃ¥ ingen-overlapper tittelen." + IDS_HINT_ARRANGE " Ordne ikoner ved knappen av vinduet." + IDS_HINT_NEXT " Aktivere neste vinduet." + + IDS_HINT_SYS_RESTORE " Endre vinduet til normal størrelse." + IDS_HINT_SYS_MOVE " Flytt vinduet." + IDS_HINT_SYS_SIZE " Endre størrelse pÃ¥ dette vinduet." + IDS_HINT_SYS_MINIMIZE " Minimer vinduet til en ikon." + IDS_HINT_SYS_MAXIMIZE " Expands dette vindu for Ã¥ fylle skjermen." +END diff --git a/modules/rosapps/applications/imagesoft/lang/pl-PL.rc b/modules/rosapps/applications/imagesoft/lang/pl-PL.rc new file mode 100644 index 00000000000..08fce06541b --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/pl-PL.rc @@ -0,0 +1,239 @@ +/* + * translated by Caemyr - Olaf Siejka (Feb, 2008) + * Use ReactOS forum PM or IRC to contact me + * http://www.reactos.org + * IRC: irc.freenode.net #reactos-pl; + */ + +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&Plik" + BEGIN + MENUITEM "&Nowy...", ID_NEW + MENUITEM "&Otwórz...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Zamknij\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "Za&knij wszystko", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "Za&pisz", ID_SAVE, GRAYED + MENUITEM "Zapisz &jako...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Pod&gląd drukowania", ID_PRINTPRE,GRAYED + MENUITEM "&Drukuj...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Właściwości", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "W&yjście\tAlt+F4", ID_EXIT + END + POPUP "&Edycja" + BEGIN + MENUITEM "&Cofnij", ID_UNDO, GRAYED + MENUITEM "&Ponów", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Wy&tnij", ID_CUT, GRAYED + MENUITEM "&Kopiuj", ID_COPY, GRAYED + MENUITEM "Wk&lej", ID_PASTE, GRAYED + MENUITEM "Wklej jako nowy &obraz", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Wybierz w&szystko", ID_SELALL, GRAYED + END + POPUP "&Podgląd" + BEGIN + MENUITEM "&Narzędzia", ID_TOOLS + MENUITEM "&Kolory", ID_COLOR + MENUITEM "&Historia", ID_HISTORY + MENUITEM "&Pasek stanu", ID_STATUSBAR + END + POPUP "&Zmień" + BEGIN + MENUITEM "Jasność...", ID_BRIGHTNESS + MENUITEM "Kontrast...", ID_CONTRAST + MENUITEM "Barwa/Nasycenie...", -1, GRAYED + POPUP "Kolor" + BEGIN + MENUITEM "Czarnobiały", ID_BLACKANDWHITE + MENUITEM "Odwróć kolory", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Zmiękczenie", ID_BLUR + MENUITEM "Wyostrzenie", ID_SHARPEN + MENUITEM "Zmiękcz kontury", -1, GRAYED + MENUITEM "Dodaj cień", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Rozmiar obrazu...", -1, GRAYED + MENUITEM "Odwróć", -1, GRAYED + MENUITEM "Lustrzane odbicie", -1, GRAYED + MENUITEM "Obrót", -1, GRAYED + + END + POPUP "&Kolory" + BEGIN + MENUITEM "&Edytuj kolory...", ID_EDITCOLOURS + END + POPUP "&Okna" + BEGIN + MENUITEM "&Kaskadowo", ID_WINDOW_CASCADE + MENUITEM "Ustaw &poziomo", ID_WINDOW_TILE_HORZ + MENUITEM "Ustaw pio&nowo", ID_WINDOW_TILE_VERT + MENUITEM "&Uporządkuj ikony", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Nas&tępne\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&Pomoc" + BEGIN + MENUITEM "&O programie...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Jasność" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Układ kolorów:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Pełny (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Czerwony", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Zielony", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Niebieski", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Anuluj", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "O ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Zamknij", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Właściwości obrazu" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Nazwa:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Właściwości", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Typ obrazu:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Szerokość:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Wysokość:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Rozdzielczość:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Jednostka:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Rozmiar obrazu:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Anuluj", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "Ten program jest darmowy; możesz go redystrybuować i/lub modyfikować zgodnie z warunkami licencji GNU General Public, publikowanymi przez Free Software Foundation; albo wersję 2, albo dowolną późniejszą.\r\n\r\nMamy nadzieję, że ten program będzie użyteczny, ale nie dajemy na niego Å»ADNEJ GWARANCJI; nawet bez gwarancji jego KOMERCYJNOŚCI czy też PRZYDATNOŚCI DO OKREŚLONEGO CELU. Szczegóły w tekście Licencji GNU General Public.\r\n\r\nKopie licencji GNU GP powinieneś otrzymać z niniejszym programem; jeśli nie, skontaktuj się z Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA." + IDS_READY " Gotów." + IDS_TOOLBAR_STANDARD "Standardowy" + IDS_TOOLBAR_TEST "Test" + IDS_IMAGE_NAME "Obraz %1!u!" + IDS_FLT_TOOLS "Narzędzia" + IDS_FLT_COLORS "Kolory" + IDS_FLT_HISTORY "Historia" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Monochromatyczny (1 bit)" + IDS_IMAGE_GREYSCALE "256 odcieni szarości (8 bitów)" + IDS_IMAGE_PALETTE "256 kolorów (8 bitów)" + IDS_IMAGE_TRUECOLOR "True color (24 bity)" + + IDS_UNIT_PIXELS "Pikseli" + IDS_UNIT_CM "Cm" + IDS_UNIT_INCHES "Cali" + IDS_UNIT_DOTSCM "Punktów / Cm" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d KB" + IDS_UNIT_MB "%d MB" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Nowy" + IDS_TOOLTIP_OPEN "Otwórz" + IDS_TOOLTIP_SAVE "Zapisz" + IDS_TOOLTIP_PRINTPRE "Podgląd drukowania" + IDS_TOOLTIP_PRINT "Drukuj" + IDS_TOOLTIP_CUT "Wytnij" + IDS_TOOLTIP_COPY "Kopiuj" + IDS_TOOLTIP_PASTE "Wklej" + IDS_TOOLTIP_UNDO "Cofnij" + IDS_TOOLTIP_REDO "Ponów" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Tworzy nowy dokument." + IDS_HINT_OPEN " Otwiera istniejący dokument." + IDS_HINT_CLOSE " Zamyka bierzące okno." + IDS_HINT_CLOSEALL " Zamyka wszystkie okno." + IDS_HINT_SAVE " Zapisuje bierzący dokument." + IDS_HINT_SAVEAS " Zapisuje bierzący dokument z nową nazwą." + IDS_HINT_PRINTPRE " Podgląd dokumentu do wydrukowania." + IDS_HINT_PRINT " Drukuje bierzący dokument." + IDS_HINT_PROP " Pokazuje właściwości danego obrazu." + IDS_HINT_EXIT " Wyjście z programu." + + IDS_HINT_TOOLS " Pokazuje lub chowa pasek narzędzi." + IDS_HINT_COLORS " Pokazuje lub chowa pasek kolorów." + IDS_HINT_HISTORY " Pokazuje lub chowa okno historii ." + IDS_HINT_STATUS " Pokazuje lub chowa pasek stanu." + + IDS_HINT_CASCADE " Ustawia okna tak by wszystkie były widoczne." + IDS_HINT_TILE_HORZ " Ustawia okna jeden obok drugiego." + IDS_HINT_TILE_VERT " Ustawia okna jeden pod drugim." + IDS_HINT_ARRANGE " Ustawia ikony w kolejności, na spodzie okna." + IDS_HINT_NEXT " Uaktywnia następne okno." + + IDS_HINT_SYS_RESTORE " Przywraca okno do normalnego rozmiaru." + IDS_HINT_SYS_MOVE " Przesuwa okno." + IDS_HINT_SYS_SIZE " Zmienia wielkość okna." + IDS_HINT_SYS_MINIMIZE " Zamyka okno do ikony." + IDS_HINT_SYS_MAXIMIZE " Rozszerza okno na pełen ekran." +END diff --git a/modules/rosapps/applications/imagesoft/lang/ru-RU.rc b/modules/rosapps/applications/imagesoft/lang/ru-RU.rc new file mode 100644 index 00000000000..50bbe0debab --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/ru-RU.rc @@ -0,0 +1,234 @@ +// Russian language resource file (Dmitry Chapyshev, 2007-07-05) + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&Файл" + BEGIN + MENUITEM "&Новый...", ID_NEW + MENUITEM "&Открыть...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Закрыть\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "З&акрыть все", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "&Сохранить", ID_SAVE, GRAYED + MENUITEM "Сохранить &как...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Предварительный &просмотр", ID_PRINTPRE,GRAYED + MENUITEM "П&ечать...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "Сво&йства...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Выход\tAlt+F4", ID_EXIT + END + POPUP "&Правка" + BEGIN + MENUITEM "&Отменить", ID_UNDO, GRAYED + MENUITEM "&Вернуть", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "В&ырезать", ID_CUT, GRAYED + MENUITEM "&Копировать", ID_COPY, GRAYED + MENUITEM "В&ставить", ID_PASTE, GRAYED + MENUITEM "Вставить как новое &изображение", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Вы&делить все", ID_SELALL, GRAYED + END + POPUP "&Вид" + BEGIN + MENUITEM "&Инструменты", ID_TOOLS + MENUITEM "&Цвета", ID_COLOR + MENUITEM "И&стория", ID_HISTORY + MENUITEM "С&трока состояния", ID_STATUSBAR + END + POPUP "&Коррекция" + BEGIN + MENUITEM "Яркость...", ID_BRIGHTNESS + MENUITEM "Контрастность...", ID_CONTRAST + MENUITEM "Hue/Saturation...", -1, GRAYED + POPUP "Цвет" + BEGIN + MENUITEM "Черный и белый", ID_BLACKANDWHITE + MENUITEM "Инвертировать цвета", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Blur", ID_BLUR + MENUITEM "Sharpen", ID_SHARPEN + MENUITEM "Smooth Edges", -1, GRAYED + MENUITEM "Add Shadow", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Размер изображения...", -1, GRAYED + MENUITEM "Flip", -1, GRAYED + MENUITEM "Зеркало", -1, GRAYED + MENUITEM "Повернуть", -1, GRAYED + + END + POPUP "&Цвета" + BEGIN + MENUITEM "&Изменить цвет...", ID_EDITCOLOURS + END + POPUP "&Окно" + BEGIN + MENUITEM "&Каскадом", ID_WINDOW_CASCADE + MENUITEM "&По горизонтали", ID_WINDOW_TILE_HORZ + MENUITEM "П&о вертикали", ID_WINDOW_TILE_VERT + MENUITEM "&Упорядочить значки", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "С&ледущее\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&Справка" + BEGIN + MENUITEM "&О программе...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Яркость" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Форма цвета:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Полный (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Красный", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Зеленый", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Голубой", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Отмена", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "О программе ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Закрыть", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Свойства изображения" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Имя:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Свойства холста", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Тип изображения:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Ширина:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Высота:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Разрешние:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Unit:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Размер изображения:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Отмена", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "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.\r\n\r\nThis 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.\r\n\r\nYou 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." + IDS_READY " Готов." + IDS_TOOLBAR_STANDARD "Стандартная" + IDS_TOOLBAR_TEST "Тест" + IDS_IMAGE_NAME "Изображение %1!u!" + IDS_FLT_TOOLS "Инструменты" + IDS_FLT_COLORS "Цвета" + IDS_FLT_HISTORY "История" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Монохромный (1 бит)" + IDS_IMAGE_GREYSCALE "Чернобелый (8 бит)" + IDS_IMAGE_PALETTE "Palette or 256 color (8 бит)" + IDS_IMAGE_TRUECOLOR "True color (24 бит)" + + IDS_UNIT_PIXELS "Пекселов" + IDS_UNIT_CM "См" + IDS_UNIT_INCHES "Дюймов" + IDS_UNIT_DOTSCM "Точек / См" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d Кб" + IDS_UNIT_MB "%d Мб" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Новый" + IDS_TOOLTIP_OPEN "Открыть" + IDS_TOOLTIP_SAVE "Сохранить" + IDS_TOOLTIP_PRINTPRE "Предварительный просмотр" + IDS_TOOLTIP_PRINT "Печать" + IDS_TOOLTIP_CUT "Вырезать" + IDS_TOOLTIP_COPY "Копировать" + IDS_TOOLTIP_PASTE "Вставить" + IDS_TOOLTIP_UNDO "Отменить" + IDS_TOOLTIP_REDO "Вернуть" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Создать новый документ." + IDS_HINT_OPEN " Opens an existing document." + IDS_HINT_CLOSE " Закрыть это окно." + IDS_HINT_CLOSEALL " Закрыть все окна." + IDS_HINT_SAVE " Сохранить текущий документ." + IDS_HINT_SAVEAS " Сохранить текущий документ с новым именем." + IDS_HINT_PRINTPRE " Предварительный просмотр печатаемого документа." + IDS_HINT_PRINT " Напечатать текущий документ." + IDS_HINT_PROP " Просмотр свойств текущего изображения." + IDS_HINT_EXIT " Выйти из этого приложения." + + IDS_HINT_TOOLS " Shows or hides the tools floating window." + IDS_HINT_COLORS " Shows or hides the colors floating window." + IDS_HINT_HISTORY " Shows or hides the history floating window." + IDS_HINT_STATUS " Показать или скрыть строку состояния." + + IDS_HINT_CASCADE " Arrange windows so they overlap." + IDS_HINT_TILE_HORZ " Arrange windows as non-overlapping tiles." + IDS_HINT_TILE_VERT " Arrange windows as non-overlapping tiles." + IDS_HINT_ARRANGE " Arrange icons at the bottom of the window." + IDS_HINT_NEXT " Сделать активным следущее окно." + + IDS_HINT_SYS_RESTORE " Востановить нормальный размер этого окна." + IDS_HINT_SYS_MOVE " Переместить это окно." + IDS_HINT_SYS_SIZE " Изменить размер этого окна." + IDS_HINT_SYS_MINIMIZE " Collapses this window to an icon." + IDS_HINT_SYS_MAXIMIZE " Развернуть это окно на весь экран." +END diff --git a/modules/rosapps/applications/imagesoft/lang/sk-SK.rc b/modules/rosapps/applications/imagesoft/lang/sk-SK.rc new file mode 100644 index 00000000000..f53fd7252ba --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/sk-SK.rc @@ -0,0 +1,239 @@ +/* TRANSLATOR : Mário Kačmár /Mario Kacmar/ aka Kario (kario@szm.sk) + * DATE OF TR.: 02-02-2008 + * LAST CHANGE: 29-08-2008 + * ______________________________________________ + * NOTE: this file is not fully translated + */ + +LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&Súbor" + BEGIN + MENUITEM "&Nový...", ID_NEW + MENUITEM "&OtvoriÅ¥...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&ZatvoriÅ¥\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "ZatvoriÅ¥ &vÅ¡etky", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "&UložiÅ¥", ID_SAVE, GRAYED + MENUITEM "UložiÅ¥ &ako...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Náhľa&d pred tlačou", ID_PRINTPRE,GRAYED + MENUITEM "&TlačiÅ¥...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "V&lastnosti...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "&SkončiÅ¥\tAlt+F4", ID_EXIT + END + POPUP "&Úpravy" + BEGIN + MENUITEM "&Späť", ID_UNDO, GRAYED + MENUITEM "&Znova", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Vystrihnúť", ID_CUT, GRAYED + MENUITEM "&KopírovaÅ¥", ID_COPY, GRAYED + MENUITEM "&Paste", ID_PASTE, GRAYED + MENUITEM "Paste as new &image", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Vy&braÅ¥ vÅ¡etko", ID_SELALL, GRAYED + END + POPUP "&ZobraziÅ¥" + BEGIN + MENUITEM "&Nástroje", ID_TOOLS + MENUITEM "&Farby", ID_COLOR + MENUITEM "&História", ID_HISTORY + MENUITEM "Stavový &riadok", ID_STATUSBAR + END + POPUP "&Adjust" + BEGIN + MENUITEM "Jas...", ID_BRIGHTNESS + MENUITEM "Kontrast...", ID_CONTRAST + MENUITEM "Odtieň/Nasýtenie...", -1, GRAYED + POPUP "Color" + BEGIN + MENUITEM "Čierna a biela", ID_BLACKANDWHITE + MENUITEM "InvertovaÅ¥ farby", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "RozmazaÅ¥", ID_BLUR + MENUITEM "ZaostriÅ¥", ID_SHARPEN + MENUITEM "VyhladiÅ¥ hrany", -1, GRAYED + MENUITEM "PridaÅ¥ tieň", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Image Size...", -1, GRAYED + MENUITEM "PreklopiÅ¥", -1, GRAYED + MENUITEM "ZrkadliÅ¥", -1, GRAYED + MENUITEM "OtočiÅ¥", -1, GRAYED + + END + POPUP "&Farby" + BEGIN + MENUITEM "&UpraviÅ¥ farby...", ID_EDITCOLOURS + END + POPUP "&Okná" + BEGIN + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "Tile &Horizontally", ID_WINDOW_TILE_HORZ + MENUITEM "Tile &Vertically", ID_WINDOW_TILE_VERT + MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "Nex&t\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&Pomocník" + BEGIN + MENUITEM "Č&o je...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Jas" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Color form:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Plné (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Červená", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Zelená", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Modrá", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "ZruÅ¡iÅ¥", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "Čo je ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "ZavrieÅ¥", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Vlastnosti obrázka" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Názov:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Canvas properties", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Typ obrázka:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Šírka:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Výška:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Rozlíšenie:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Unit:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "VeľkosÅ¥ obrázka:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "ZruÅ¡iÅ¥", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "Tento program je voľný softvér; môžete ho šíriÅ¥ a/alebo modifikovaÅ¥ podľa podmienok GNU VÅ¡eobecnej verejnej licencie (GNU General Public License) ako bola zverejnená nadáciou Free Software Foundation; buď verzie 2 tejto licencie, alebo (podľa Vášho uváženia) niektorej neskorÅ¡ej verzie.\r\n\r\nTento program je distribuovaný v nádeji, že bude užitočný, avÅ¡ak BEZ AKEJKOĽVEK ZÁRUKY; rovnako bez záruky PREDAJNOSTI alebo VHODNOSTI PRE URČITÝ ÚČEL. Pre viac detailov si pozrite GNU VÅ¡eobecnú verejnú licenciu (GNU General Public License).\r\n\r\nKópiu VÅ¡eobecnej verejnej licencie GNU ste mali dostaÅ¥ spolu s týmto programom; ak nie, napíšte si o ňu na Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA." + IDS_READY " Hotovo." + IDS_TOOLBAR_STANDARD "Standard" + IDS_TOOLBAR_TEST "Test" + IDS_IMAGE_NAME "Obrázok %1!u!" + IDS_FLT_TOOLS "Nástroje" + IDS_FLT_COLORS "Farby" + IDS_FLT_HISTORY "História" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Čierno-bielo (1 bit)" + IDS_IMAGE_GREYSCALE "Odtiene Å¡edej (8 bitov)" + IDS_IMAGE_PALETTE "Paleta alebo 256 farieb (8 bitov)" + IDS_IMAGE_TRUECOLOR "Pravé farby (24 bitov)" + + IDS_UNIT_PIXELS "Pixely" + IDS_UNIT_CM "Centimetre" + IDS_UNIT_INCHES "Palce" + IDS_UNIT_DOTSCM "Body na cm" + IDS_UNIT_DPI "DPI" + IDS_UNIT_KB "%d KB" + IDS_UNIT_MB "%d MB" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Nový" + IDS_TOOLTIP_OPEN "OtvoriÅ¥" + IDS_TOOLTIP_SAVE "UložiÅ¥" + IDS_TOOLTIP_PRINTPRE "Náhľad pred tlačou" + IDS_TOOLTIP_PRINT "TlačiÅ¥" + IDS_TOOLTIP_CUT "Vystrihnúť" + IDS_TOOLTIP_COPY "KopírovaÅ¥" + IDS_TOOLTIP_PASTE "VložiÅ¥" + IDS_TOOLTIP_UNDO "Späť" + IDS_TOOLTIP_REDO "Znova" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Vytvorí nový dokument." + IDS_HINT_OPEN " Otvorí existujúci dokument." + IDS_HINT_CLOSE " Zatvorí toto okno." + IDS_HINT_CLOSEALL " Zatvorí vÅ¡etke okná." + IDS_HINT_SAVE " Uloží aktívny dokument." + IDS_HINT_SAVEAS " Uloží aktívny dokument pod novým názvom." + IDS_HINT_PRINTPRE " Zobrazí náhľad dokumentu pred tlačou." + IDS_HINT_PRINT " Vytlačí aktívny dokument." + IDS_HINT_PROP " Zobrazí vlastnosti aktívneho obrázka." + IDS_HINT_EXIT " Ukončí program." + + IDS_HINT_TOOLS " Zobrazí alebo skryje plávajúce okno nástrojov." + IDS_HINT_COLORS " Zobrazí alebo skryje plávajúce okno farieb." + IDS_HINT_HISTORY " Zobrazí alebo skryje plávajúce okno histórie." + IDS_HINT_STATUS " Zobrazí alebo skryje stavový riadok." + + IDS_HINT_CASCADE " Arrange windows so they overlap." + IDS_HINT_TILE_HORZ " Arrange windows as non-overlapping tiles." + IDS_HINT_TILE_VERT " Arrange windows as non-overlapping tiles." + IDS_HINT_ARRANGE " Arrange icons at the bottom of the window." + IDS_HINT_NEXT " Aktivuje ďalÅ¡ie okno v poradí." + + IDS_HINT_SYS_RESTORE " Obnoví okno na normálnu veľkosÅ¥." + IDS_HINT_SYS_MOVE " Premiestni okno." + IDS_HINT_SYS_SIZE " Zmení veľkosÅ¥ okna." + IDS_HINT_SYS_MINIMIZE " Zbalí okno do veľkosti ikony." + IDS_HINT_SYS_MAXIMIZE " Zväčsí okno tak, aby zaplnilo obrazovku." +END diff --git a/modules/rosapps/applications/imagesoft/lang/th-TH.rc b/modules/rosapps/applications/imagesoft/lang/th-TH.rc new file mode 100644 index 00000000000..a9054d35073 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/th-TH.rc @@ -0,0 +1,232 @@ +LANGUAGE LANG_THAI, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "แ&ฟ้ม" + BEGIN + MENUITEM "ใ&หม่...", ID_NEW + MENUITEM "เ&ปิด...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "ปิ&ด\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "ปิด&ทั้งหมด", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "&บันทึก", ID_SAVE, GRAYED + MENUITEM "บัน&ทึก เป็น...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "&ภาพก่อนพิมพ์", ID_PRINTPRE,GRAYED + MENUITEM "&พิมพ์...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "&คุณสมบัติ...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "&ออกจากโปรแกรม\tAlt+F4", ID_EXIT + END + POPUP "แ&ก้ไข" + BEGIN + MENUITEM "เ&ลิกทำ", ID_UNDO, GRAYED + MENUITEM "&ย้อนกลับ", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "&ตัด", ID_CUT, GRAYED + MENUITEM "&คัดลอก", ID_COPY, GRAYED + MENUITEM "&วาง", ID_PASTE, GRAYED + MENUITEM "วา&งเป็นภาพใหม่", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "เลือกทั้งหม&ด", ID_SELALL, GRAYED + END + POPUP "&มุมมอง" + BEGIN + MENUITEM "เครื่องมื&อ", ID_TOOLS + MENUITEM "&สี", ID_COLOR + MENUITEM "&ประวัติ", ID_HISTORY + MENUITEM "แ&ถบสถานะ", ID_STATUSBAR + END + POPUP "&ปรับแต่ง" + BEGIN + MENUITEM "ความสว่าง...", ID_BRIGHTNESS + MENUITEM "ความชัด...", ID_CONTRAST + MENUITEM "ความเข้มแสง/ความอิ่มตัว...", -1, GRAYED + POPUP "สี" + BEGIN + MENUITEM "ภาพขาวดำ", ID_BLACKANDWHITE + MENUITEM "แปลงสี", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "ทำให้มัว", ID_BLUR + MENUITEM "ทำให้คมชัด", ID_SHARPEN + MENUITEM "ทำให้ขอบนุ่ม", -1, GRAYED + MENUITEM "เพิ่มเงา", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "ขนาดภาพ...", -1, GRAYED + MENUITEM "กลับทิศทาง", -1, GRAYED + MENUITEM "กลับด้าน", -1, GRAYED + MENUITEM "หมุน", -1, GRAYED + + END + POPUP "&สี" + BEGIN + MENUITEM "แก้ไ&ขสี...", ID_EDITCOLOURS + END + POPUP "&หน้าต่าง" + BEGIN + MENUITEM "&ซ้อนกัน", ID_WINDOW_CASCADE + MENUITEM "วางเรียงแนว&นอน", ID_WINDOW_TILE_HORZ + MENUITEM "วางเรียงแนว&ตั้ง", ID_WINDOW_TILE_VERT + MENUITEM "จัดเรียงสัญ&รูป", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "&ถัดไป\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&ช่วยเหลือ" + BEGIN + MENUITEM "&เกี่ยวกับ...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "เปิดหน้าต่างใหม่" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "ความสว่าง" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "รูปแบบสี:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "ทุกสี (RGB)", IDC_BRI_FULL, "ปุ่มกด", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "แดง", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "เขียว", IDC_BRI_GREEN, "ปุ่มกด", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "น้ำเงิน", IDC_BRI_BLUE, "ปุ่มกด", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "ตกลง", IDOK, 142, 88, 48, 13 + PUSHBUTTON "ยกเลิก", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "เกี่ยวกับโปรแกรม ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "ปิด", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "คุณสมบัติของภาพ" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "ชื่อ:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "คุณสมบัติของขนาดพื้นที่ภาพ", IDC_STATIC, 4, 22, 148, 98 + LTEXT "ประเภทรูปภาพ:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "กล่องเครื่องมือ", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "ความกว้าง:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "ความสูง:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "ความละเอียดของภาพ:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "หน่วย:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "กล่องเครื่องมือ", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "ขนาดภาพ:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "ตกลง", IDOK, 50, 144, 48, 13 + PUSHBUTTON "ยกเลิก", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "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.\r\n\r\nThis 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.\r\n\r\nYou 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." + IDS_READY " เสร็จแล้ว." + IDS_TOOLBAR_STANDARD "มาตรฐาน" + IDS_TOOLBAR_TEST "ทดสอบ" + IDS_IMAGE_NAME "ภาพ %1!u!" + IDS_FLT_TOOLS "เครื่องมือ" + IDS_FLT_COLORS "สี" + IDS_FLT_HISTORY "ประวัติ" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "สีเดียว (1 bit)" + IDS_IMAGE_GREYSCALE "ภาพขาวดำ (8 bit)" + IDS_IMAGE_PALETTE "แถบสี 256 สี (8 bit)" + IDS_IMAGE_TRUECOLOR "สีจริง (24 bit)" + + IDS_UNIT_PIXELS "เม็ดสี" + IDS_UNIT_CM "เซนติเมตร" + IDS_UNIT_INCHES "นิ้ว" + IDS_UNIT_DOTSCM "จุด / เซนติเมตร" + IDS_UNIT_DPI "จุดต่อนิ้ว" + IDS_UNIT_KB "%d กิโลไบต์" + IDS_UNIT_MB "%d เมกกะไบต์" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "ใหม่" + IDS_TOOLTIP_OPEN "เปิด" + IDS_TOOLTIP_SAVE "บันทึก" + IDS_TOOLTIP_PRINTPRE "ภาพก่อนพิมพ์" + IDS_TOOLTIP_PRINT "พิมพ์" + IDS_TOOLTIP_CUT "ตัด" + IDS_TOOLTIP_COPY "คัดลอก" + IDS_TOOLTIP_PASTE "วาง" + IDS_TOOLTIP_UNDO "เลิกทำ" + IDS_TOOLTIP_REDO "ย้อนกลับ" +END + + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " สร้างเอกสารใหม่." + IDS_HINT_OPEN " เปิดเอกสารที่มีอยู่." + IDS_HINT_CLOSE " ปิดหน้าต่างนี้." + IDS_HINT_CLOSEALL " ปิดหน้าต่างทั้งหมด." + IDS_HINT_SAVE " บันทึกเอกสารที่เก็บไว้." + IDS_HINT_SAVEAS " บันทึกเอกสารที่กำลังทำอยู่ด้วยชื่อใหม่." + IDS_HINT_PRINTPRE " มองภาพก่อนพิมพ์ของเอกสาร." + IDS_HINT_PRINT " พิมพ์เอกสารที่กำลังทำอยู่นี้." + IDS_HINT_PROP " แสดงคุณสมบัติของภาพที่กำลังทำอยู่นี้." + IDS_HINT_EXIT " ออกจากการทำงาน." + + IDS_HINT_TOOLS " แสดงหน้าซ่อนหน้าต่างของแถบเครื่องมือ." + IDS_HINT_COLORS " แสดงหน้าซ่อนหน้าต่างของแถบสี." + IDS_HINT_HISTORY " แสดงหน้าซ่อนหน้าต่างของแถบประวัติ." + IDS_HINT_STATUS " แสดงหน้าซ่อนหน้าต่างของแถบสถานะ." + + IDS_HINT_CASCADE " เรียงหน้าต่างวางซ้อนกัน." + IDS_HINT_TILE_HORZ " เรียงหน้าต่างตามแนวนอน." + IDS_HINT_TILE_VERT " เรียงหน้าต่างตามแนวตั้ง." + IDS_HINT_ARRANGE " จัดเรียงสัญรูปที่ด้านล่างของหน้าต่าง." + IDS_HINT_NEXT " เริ่มทำงานหน้าต่างถัดไป." + + IDS_HINT_SYS_RESTORE " คืนสภาพหน้าต่างสู่ขนาดปกติ." + IDS_HINT_SYS_MOVE " เคลื่อนย้ายหน้าต่างนี้." + IDS_HINT_SYS_SIZE " เปลี่ยนขนาดหน้าต่างนี้." + IDS_HINT_SYS_MINIMIZE " ย่อหน้าต่างนี้ให้เป็นสัญรูป." + IDS_HINT_SYS_MAXIMIZE " ขยายหน้าต่างนี้จนเต็มหน้าจอ." +END diff --git a/modules/rosapps/applications/imagesoft/lang/uk-UA.rc b/modules/rosapps/applications/imagesoft/lang/uk-UA.rc new file mode 100644 index 00000000000..a006cbfcab7 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/lang/uk-UA.rc @@ -0,0 +1,240 @@ +/* + * PROJECT: ReactOS ImageSoft + * LICENSE: GPL - See COPYING in the top level directory + * FILE: rosapps/imagesoft/lang/uk-UA.rc + * PURPOSE: Ukraianian Language File for ImageSoft + * TRANSLATOR: Rostislav Zabolotny, Artem Reznikov + */ + +LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ImageSoft" + IDS_VERSION "v0.1" +END + +IDR_MAINMENU MENU +BEGIN + POPUP "&Файл" + BEGIN + MENUITEM "&Створити...", ID_NEW + MENUITEM "&Відкрити...", ID_OPEN + MENUITEM SEPARATOR + MENUITEM "&Закрити\tCtrl+F4", ID_CLOSE, GRAYED + MENUITEM "З&акрити все", ID_CLOSEALL,GRAYED + MENUITEM SEPARATOR + MENUITEM "Зб&ерегти", ID_SAVE, GRAYED + MENUITEM "Зберегти &як...", ID_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "Попе&редній Перегляд",ID_PRINTPRE,GRAYED + MENUITEM "&Друкувати...", ID_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "В&ластивості...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "Ви&ід\tAlt+F4", ID_EXIT + END + POPUP "&Правка" + BEGIN + MENUITEM "Повер&нути", ID_UNDO, GRAYED + MENUITEM "По&вторити", ID_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Вирі&зати", ID_CUT, GRAYED + MENUITEM "Ко&піювати", ID_COPY, GRAYED + MENUITEM "Вс&тавити", ID_PASTE, GRAYED + MENUITEM "Вставити новим &малюнком", ID_PASTENEWIMAGE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Виділити &Все", ID_SELALL, GRAYED + END + POPUP "&Вигляд" + BEGIN + MENUITEM "&Інструменти", ID_TOOLS + MENUITEM "&Кольори", ID_COLOR + MENUITEM "Іс&торія", ID_HISTORY + MENUITEM "&Рядок стану", ID_STATUSBAR + END + POPUP "&Редагування" + BEGIN + MENUITEM "Яскравість...", ID_BRIGHTNESS + MENUITEM "Контраст...", ID_CONTRAST + MENUITEM "Відтінки/Насичення...", -1, GRAYED + POPUP "Колір" + BEGIN + MENUITEM "Чорно-білий", ID_BLACKANDWHITE + MENUITEM "Обернути Кольори", ID_INVERTCOLORS + END + MENUITEM SEPARATOR + MENUITEM "Затемнити", ID_BLUR + MENUITEM "Зробити Різкіше", ID_SHARPEN + MENUITEM "Згладити краї", -1, GRAYED + MENUITEM "Додати тінь", -1, GRAYED + MENUITEM SEPARATOR + MENUITEM "Розмір малюнка...", -1, GRAYED + MENUITEM "Рухати", -1, GRAYED + MENUITEM "Відобразити", -1, GRAYED + MENUITEM "Обернути", -1, GRAYED + + END + POPUP "&Кольори" + BEGIN + MENUITEM "&Редагувати кольори...", ID_EDITCOLOURS + END + POPUP "&Вікно" + BEGIN + MENUITEM "&Каскадом", ID_WINDOW_CASCADE + MENUITEM "Викласти &Горизонтально", ID_WINDOW_TILE_HORZ + MENUITEM "Викласти &Вертикально", ID_WINDOW_TILE_VERT + MENUITEM "Впарядкувати &Іконки", ID_WINDOW_ARRANGE + MENUITEM SEPARATOR + MENUITEM "На&ступний\tCtrl+F6", ID_WINDOW_NEXT + END + POPUP "&Довідка" + BEGIN + MENUITEM "&Про редактор...", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM SEPARATOR + END +END + + +IDD_BRIGHTNESS DIALOGEX 6, 5, 193, 120 +CAPTION "Яскравість" +FONT 8,"MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "", IDC_PICPREVIEW, 0, 1, 132, 96, SS_OWNERDRAW | SS_SUNKEN + LTEXT "Кольори:", IDC_STATIC, 135, 5, 36, 9 + GROUPBOX "", IDC_BRI_GROUP, 138 ,30, 50, 48 + CONTROL "Всі (RGB)", IDC_BRI_FULL, "Button", BS_AUTORADIOBUTTON, 138, 18, 46, 9 + CONTROL "Червоний", IDC_BRI_RED, "Button", BS_AUTORADIOBUTTON, 142, 38, 42, 9 + CONTROL "Зелений", IDC_BRI_GREEN, "Button", BS_AUTORADIOBUTTON, 142, 51, 42, 9 + CONTROL "Блакитний", IDC_BRI_BLUE, "Button", BS_AUTORADIOBUTTON, 142, 64, 42, 9 + EDITTEXT IDC_BRI_EDIT, 98, 103, 28, 13 + CONTROL "", IDC_BRI_TRACKBAR, "msctls_trackbar32", TBS_BOTH | TBS_NOTICKS | WS_TABSTOP, 2, 105, 90, 11 + PUSHBUTTON "OK", IDOK, 142, 88, 48, 13 + PUSHBUTTON "Скасувати", IDCANCEL, 142, 105, 48, 13 +END + +IDD_ABOUTBOX DIALOGEX 22,16,210,182 +CAPTION "Про ImageSoft" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +//EXSTYLE WS_EX_LAYERED +BEGIN + LTEXT "ImageSoft v0.1\nCopyright (C) 2006\nThomas Weidenmueller (w3seek@reactos.org)\nGed Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 150, 36 + PUSHBUTTON "Закрити", IDOK, 75, 162, 44, 15 + ICON IDI_IMAGESOFTICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 194, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + + +IDD_IMAGE_PROP DIALOGEX 6, 5, 156, 163 +CAPTION "Властивості зображення" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Назва:", IDC_STATIC, 12, 5, 38, 9 + EDITTEXT IDC_IMAGE_NAME_EDIT, 58, 3, 94, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + GROUPBOX "Властивості полотна", IDC_STATIC, 4, 22, 148, 98 + LTEXT "Тип малюнка:", IDC_STATIC, 12, 36, 42, 9 + CONTROL "", IDC_IMAGETYPE, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 35, 88, 54 + LTEXT "Ширина:", IDC_STATIC, 12, 51, 42, 9 + EDITTEXT IDC_WIDTH_EDIT, 58, 49, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_WIDTH_STAT, 94, 51, 40, 9 + LTEXT "Висота:", IDC_STATIC, 12, 68, 42, 9 + EDITTEXT IDC_HEIGHT_EDIT, 58, 66, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_HEIGHT_STAT, 94, 68, 40, 9 + LTEXT "Роздільна здатність:", IDC_STATIC, 12, 84, 42, 9 + EDITTEXT IDC_RES_EDIT, 58, 83, 32, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER + LTEXT "", IDC_RES_STAT, 94, 84, 40, 9 + LTEXT "Одиниці:", IDC_STATIC, 12, 99, 42, 9 + CONTROL "", IDC_UNIT, "ComboBox", WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST, 58, 99, 54, 50 + LTEXT "Розмір малюнка:", IDC_STATIC, 12, 125, 42, 9 + LTEXT "", IDC_IMAGE_SIZE, 58, 125, 54, 9 + PUSHBUTTON "OK", IDOK, 50, 144, 48, 13 + PUSHBUTTON "Скасувати", IDCANCEL, 102, 144, 48, 13 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "Ця програма належить до безкоштовного програмного забезпечення; Ви можете поширювати чи(і) змінювати її на правах GNU Загальною публічною ліцензією (GPL) опублікованими Фундацією Безкоштовного програмного забезпечення (Free Software Foundation); або другою версією Ліцензії, чи (на Ваш вибір) будь-якою іншою версією.\r\n\r\nЦя програма була створена з надією що буде корисна, але БЕЗ БУДЬ-ЯКИХ ГАРАНТІЙ; навіть без включених гарантій ліквідності чи можливості пристосування до конкретних вимог. За детальнішою інформацією дивіться GNU Загальну публічну ліцензію.\r\n\r\nКопію GNU Загальної Публічної Ліцензії Ви мали б отримати разом з цією програмою; якщо так не сталося, пишіть Фундації Безкоштовного Програмного Забезпечення: Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA." + IDS_READY "Готово" + IDS_TOOLBAR_STANDARD "Стандартно" + IDS_TOOLBAR_TEST "Тест" + IDS_IMAGE_NAME "Малюнок %1!u!" + IDS_FLT_TOOLS "Інструменти" + IDS_FLT_COLORS "Кольори" + IDS_FLT_HISTORY "Історія" +END + +/* imageprop.c */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_IMAGE_MONOCHROME "Монохромний (1 біт)" + IDS_IMAGE_GREYSCALE "Відтінки сірого (8 біт)" + IDS_IMAGE_PALETTE "256 кольорів (8 біт)" + IDS_IMAGE_TRUECOLOR "Справжні кольори (24 біт)" + + IDS_UNIT_PIXELS "Пікселі" + IDS_UNIT_CM "См" + IDS_UNIT_INCHES "Дюйми" + IDS_UNIT_DOTSCM "Точок на См" + IDS_UNIT_DPI "Точок на Дюйм" + IDS_UNIT_KB "%d КБ" + IDS_UNIT_MB "%d МБ" +END + +/* Tooltips */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_NEW "Новий" + IDS_TOOLTIP_OPEN "Відкрити" + IDS_TOOLTIP_SAVE "Зберегти" + IDS_TOOLTIP_PRINTPRE "Попередній перегляд" + IDS_TOOLTIP_PRINT "Друк" + IDS_TOOLTIP_CUT "Вирізати" + IDS_TOOLTIP_COPY "Копіювати" + IDS_TOOLTIP_PASTE "Вставити" + IDS_TOOLTIP_UNDO "Скасувати" + IDS_TOOLTIP_REDO "Повторити" +END + + +/* Підказки */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_NEW " Створює новий документ." + IDS_HINT_OPEN " Відкриває існуючий документ." + IDS_HINT_CLOSE " Закриває поточне вікно." + IDS_HINT_CLOSEALL " Закриває всі вікна." + IDS_HINT_SAVE " Зберігає активний документ." + IDS_HINT_SAVEAS " Зберігає поточний документ під іншим іменем." + IDS_HINT_PRINTPRE " Перегляд документа перед друком." + IDS_HINT_PRINT " Друкує поточний документ." + IDS_HINT_PROP " Показує властивості поточного малюнка." + IDS_HINT_EXIT " Виходить з цієї програми." + + IDS_HINT_TOOLS " Показує чи ховає рухоме віконце інструментів." + IDS_HINT_COLORS " Показує чи ховає рухоме віконце кольорів." + IDS_HINT_HISTORY " Показує чи ховає рухоме віконце Історії." + IDS_HINT_STATUS " Показує чи ховає рядок стану." + + IDS_HINT_CASCADE " Впорядковує вікна так, щоб вони послідовно накладалися." + IDS_HINT_TILE_HORZ " Впорядковує вікна горизонтально так, щоб заголовки не накладалися." + IDS_HINT_TILE_VERT " Впорядковує вікна вертикально так, щоб заголовки не накладалися." + IDS_HINT_ARRANGE " Впорядковує іконки знизу вікна." + IDS_HINT_NEXT " Активізує наступне вікно." + + IDS_HINT_SYS_RESTORE " Відновлює вихідні розміри вікна." + IDS_HINT_SYS_MOVE " Змінює розташування вікна" + IDS_HINT_SYS_SIZE " Змінює розміри вікна." + IDS_HINT_SYS_MINIMIZE " Згортає вікно до значка." + IDS_HINT_SYS_MAXIMIZE " Розгортає вікно до розмірів екрана." +END diff --git a/modules/rosapps/applications/imagesoft/mainwnd.c b/modules/rosapps/applications/imagesoft/mainwnd.c new file mode 100644 index 00000000000..07597022998 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/mainwnd.c @@ -0,0 +1,1454 @@ +#include + +static const TCHAR szMainWndClass[] = TEXT("ImageSoftWndClass"); + +#define ID_MDI_FIRSTCHILD 50000 +#define ID_MDI_WINDOWMENU 5 +#define NUM_FLT_WND 3 + +/* toolbar buttons */ +TBBUTTON StdButtons[] = { +/* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */ + {TBICON_NEW, ID_NEW, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* new */ + {TBICON_OPEN, ID_OPEN, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* open */ + {TBICON_SAVE, ID_SAVE, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* save */ + + {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */ + + {TBICON_PRINT, ID_PRINTPRE, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* print */ + {TBICON_PRINTPRE, ID_PRINT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* print preview */ + + {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */ + + {TBICON_CUT, ID_CUT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* cut */ + {TBICON_COPY, ID_COPY, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* copy */ + {TBICON_PASTE, ID_PASTE, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* paste */ + + {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */ + + {TBICON_UNDO, ID_UNDO, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* undo */ + {TBICON_REDO, ID_REDO, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* redo */ + + {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, +}; + +TBBUTTON TextButtons[] = { + {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */ + + {TBICON_BOLD, ID_BOLD, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_CHECK, {0}, 0, 0}, /* bold */ + {TBICON_ITALIC, ID_ITALIC, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_CHECK, {0}, 0, 0}, /* italic */ + {TBICON_ULINE, ID_ULINE, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_CHECK, {0}, 0, 0}, /* underline */ + + {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */ + + {TBICON_TXTLEFT, ID_TXTLEFT, TBSTATE_ENABLED | TBSTATE_CHECKED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0 }, /* left justified */ + {TBICON_TXTCENTER,ID_TXTCENTER,TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0 }, /* centered */ + {TBICON_TXTRIGHT, ID_TXTRIGHT, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0 }, /* right justified */ + + {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */ +}; + + + +/* menu hints */ +static const MENU_HINT MainMenuHintTable[] = { + /* File Menu */ + {ID_BLANK, IDS_HINT_BLANK}, + {ID_NEW, IDS_HINT_NEW}, + {ID_OPEN, IDS_HINT_OPEN}, + {ID_CLOSE, IDS_HINT_CLOSE}, + {ID_CLOSEALL, IDS_HINT_CLOSEALL}, + {ID_SAVE, IDS_HINT_SAVE}, + {ID_SAVEAS, IDS_HINT_SAVEAS}, + {ID_PRINTPRE, IDS_HINT_PRINTPRE}, + {ID_PRINT, IDS_HINT_PRINT}, + {ID_PROP, IDS_HINT_PROP}, + {ID_EXIT, IDS_HINT_EXIT}, + + /* view menu */ + {ID_TOOLS, IDS_HINT_TOOLS}, + {ID_COLOR, IDS_HINT_COLORS}, + {ID_HISTORY, IDS_HINT_HISTORY}, + {ID_STATUSBAR, IDS_HINT_STATUS}, + + /* Window Menu */ + {ID_WINDOW_NEXT, IDS_HINT_NEXT}, + {ID_WINDOW_CASCADE, IDS_HINT_CASCADE}, + {ID_WINDOW_TILE_HORZ, IDS_HINT_TILE_HORZ}, + {ID_WINDOW_TILE_VERT, IDS_HINT_TILE_VERT}, + {ID_WINDOW_ARRANGE, IDS_HINT_ARRANGE} +}; + +static const MENU_HINT SystemMenuHintTable[] = { + {SC_RESTORE, IDS_HINT_SYS_RESTORE}, + {SC_MOVE, IDS_HINT_SYS_MOVE}, + {SC_SIZE, IDS_HINT_SYS_SIZE}, + {SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE}, + {SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE}, + {SC_CLOSE, IDS_HINT_CLOSE}, + {SC_NEXTWINDOW, IDS_HINT_NEXT}, +}; + + +/* Toolbars */ +#define ID_TOOLBAR_STANDARD 0 +#define ID_TOOLBAR_TEXT 1 +static const TCHAR szToolbarStandard[] = TEXT("STANDARD"); +static const TCHAR szToolbarText[] = TEXT("TEXT"); + + +/* Test Toolbar */ +#define ID_TOOLBAR_TEST 5 +static const TCHAR szToolbarTest[] = TEXT("TEST"); + +/* Toolbars table */ +static const DOCKBAR MainDockBars[] = { + {ID_TOOLBAR_STANDARD, szToolbarStandard, IDS_TOOLBAR_STANDARD, TOP_DOCK}, + {ID_TOOLBAR_TEST, szToolbarTest, IDS_TOOLBAR_TEST, TOP_DOCK}, + {ID_TOOLBAR_TEXT, szToolbarText, IDS_TOOLBAR_TEXT, TOP_DOCK}, +}; + + +static BOOL CALLBACK +MainWndCreateToolbarClient(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + HWND hParent, + HWND *hwnd) +{ + const TBBUTTON *Buttons = NULL; + UINT NumButtons = 0; + UINT StartImageRes = 0; + HWND hWndClient = NULL; + + UNREFERENCED_PARAMETER(Context); + + switch (Dockbar->BarId) + { + case ID_TOOLBAR_STANDARD: + { + Buttons = StdButtons; + NumButtons = sizeof(StdButtons) / sizeof(StdButtons[0]); + StartImageRes = IDB_MAINNEWICON; + break; + } + + case ID_TOOLBAR_TEXT: + { + Buttons = TextButtons; + NumButtons = sizeof(TextButtons) / sizeof(TextButtons[0]); + StartImageRes = IDB_TEXTBOLD; + break; + } + + case ID_TOOLBAR_TEST: + {/* + hWndClient = CreateWindowEx(WS_EX_TOOLWINDOW, + TEXT("BUTTON"), + TEXT("Test Button"), + WS_CHILD | WS_VISIBLE, + 0, + 0, + 150, + 25, + hParent, + NULL, + hInstance, + NULL);*/ + break; + } + } + + if (Buttons != NULL) + { + hWndClient = CreateWindowEx(0, + TOOLBARCLASSNAME, + NULL, + WS_CHILD | WS_CLIPSIBLINGS | + CCS_NOPARENTALIGN | CCS_NOMOVEY | CCS_NORESIZE | CCS_NODIVIDER | + TBSTYLE_FLAT | TBSTYLE_TOOLTIPS, + 0, + 0, + 0, + 0, + hParent, + NULL, + hInstance, + NULL); + if (hWndClient != NULL) + { + HIMAGELIST hImageList; + + SendMessage(hWndClient, + TB_SETEXTENDEDSTYLE, + 0, + TBSTYLE_EX_HIDECLIPPEDBUTTONS); + + SendMessage(hWndClient, + TB_BUTTONSTRUCTSIZE, + sizeof(Buttons[0]), + 0); + + SendMessage(hWndClient, + TB_SETBITMAPSIZE, + 0, + (LPARAM)MAKELONG(TB_BMP_WIDTH, TB_BMP_HEIGHT)); + + hImageList = InitImageList(NumButtons, + StartImageRes); + + ImageList_Destroy((HIMAGELIST)SendMessage(hWndClient, + TB_SETIMAGELIST, + 0, + (LPARAM)hImageList)); + + SendMessage(hWndClient, + TB_ADDBUTTONS, + NumButtons, + (LPARAM)Buttons); + + } + } + + switch (Dockbar->BarId) + { + case ID_TOOLBAR_TEXT: + { + HWND hFontType; + HWND hFontSize; + + /* font selection combo */ + hFontType = CreateWindowEx(0, + WC_COMBOBOX, + NULL, + WS_CHILD | WS_VISIBLE | WS_VSCROLL | + CBS_DROPDOWN | CBS_SORT | CBS_HASSTRINGS, //| CBS_OWNERDRAWFIXED, + 0, 0, 120, 0, + hParent, + NULL, + hInstance, + NULL); + + if (hFontType != NULL) + { + MakeFlatCombo(hFontType); + + SetParent(hFontType, + hWndClient); + + if (!ToolbarInsertSpaceForControl(hWndClient, + hFontType, + 0, + ID_TXTFONTNAME, + TRUE)) + { + DestroyWindow(hFontType); + } + + /* Create the list of fonts */ + FillFontStyleComboList(hFontType); + } + + /* font size combo */ + hFontSize = CreateWindowEx(0, + WC_COMBOBOX, + NULL, + WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, + 0, 0, 50, 0, + hParent, + NULL, + hInstance, + NULL); + if (hFontSize != NULL) + { + MakeFlatCombo(hFontSize); + + SetParent(hFontSize, + hWndClient); + + if (!ToolbarInsertSpaceForControl(hWndClient, + hFontSize, + 1, + ID_TXTFONTSIZE, + TRUE)) + { + DestroyWindow(hFontSize); + } + + /* Update the font-size-list */ + FillFontSizeComboList(hFontSize); + } + break; + } + } + + if (hWndClient != NULL) + { + *hwnd = hWndClient; + return TRUE; + } + + return FALSE; +} + +static BOOL CALLBACK +MainWndDestroyToolbarClient(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + HWND hwnd) +{ + UNREFERENCED_PARAMETER(TbDocks); + UNREFERENCED_PARAMETER(Dockbar); + UNREFERENCED_PARAMETER(Context); + + DestroyWindow(hwnd); + return TRUE; +} + +static BOOL CALLBACK +MainWndToolbarInsertBand(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + UINT *Index, + LPREBARBANDINFO rbi) +{ + switch (rbi->wID) + { + case ID_TOOLBAR_TEXT: + case ID_TOOLBAR_STANDARD: + { + SIZE Size; + + if (SendMessage(rbi->hwndChild, + TB_GETMAXSIZE, + 0, + (LPARAM)&Size)) + { + rbi->fStyle |= RBBS_USECHEVRON | RBBS_HIDETITLE; + rbi->fMask |= RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE; + rbi->cx = rbi->cxIdeal = Size.cx; + rbi->cxMinChild = 0; + rbi->cyMinChild = Size.cy; + } + break; + } + + case ID_TOOLBAR_TEST: + { + RECT rcBtn; + + if (GetWindowRect(rbi->hwndChild, + &rcBtn)) + { + rbi->fStyle |= RBBS_HIDETITLE; + rbi->fMask |= RBBIM_SIZE | RBBIM_CHILDSIZE; + rbi->cx = rcBtn.right - rcBtn.left; + rbi->cxMinChild = 0; + rbi->cyMinChild = rcBtn.bottom - rcBtn.top; + } + break; + } + } + return TRUE; +} + +static VOID +TbCustomControlChange(HWND hWndToolbar, + HWND hWndControl, + BOOL Vert) +{ + /* the toolbar changed from horizontal to vertical or vice versa... */ + return; +} + +static VOID CALLBACK +MainWndToolbarDockBand(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + DOCK_POSITION DockFrom, + DOCK_POSITION DockTo, + LPREBARBANDINFO rbi) +{ + if (rbi->fMask & RBBIM_CHILD && rbi->hwndChild != NULL) + { + switch (rbi->wID) + { + case ID_TOOLBAR_TEXT: + case ID_TOOLBAR_STANDARD: + { + SIZE Size; + BOOL Vert; + DWORD dwStyle = (DWORD)SendMessage(rbi->hwndChild, + TB_GETSTYLE, + 0, + 0); + switch (DockTo) + { + case LEFT_DOCK: + case RIGHT_DOCK: + dwStyle |= CCS_VERT | TBSTYLE_WRAPABLE; + Vert = TRUE; + break; + + default: + dwStyle &= ~(CCS_VERT | TBSTYLE_WRAPABLE); + Vert = FALSE; + break; + } + + SendMessage(rbi->hwndChild, + TB_SETSTYLE, + 0, + (LPARAM)dwStyle); + + ToolbarUpdateControlSpaces(rbi->hwndChild, + TbCustomControlChange); + + if (SendMessage(rbi->hwndChild, + TB_GETMAXSIZE, + 0, + (LPARAM)&Size)) + { + rbi->fMask |= RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE; + rbi->cx = rbi->cxIdeal = (Vert ? Size.cy : Size.cx); + rbi->cxMinChild = 0; + rbi->cyMinChild = (Vert ? Size.cx : Size.cy); + } + break; + } + + case ID_TOOLBAR_TEST: + { + if (DockTo == NO_DOCK) + { + rbi->fMask |= RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE; + rbi->cx = rbi->cxIdeal = 150; + rbi->cxMinChild = 0; + rbi->cyMinChild = 40; + } + break; + } + } + } +} + +static VOID CALLBACK +MainWndToolbarChevronPushed(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + HWND hwndChild, + LPNMREBARCHEVRON lpnm) +{ + switch (lpnm->wID) + { + case ID_TOOLBAR_STANDARD: + { + MapWindowPoints(lpnm->hdr.hwndFrom, + HWND_DESKTOP, + (LPPOINT)&lpnm->rc, + 2); + /* Create a popup menu for all toolbar icons hidden */ + break; + } + } +} + +static VOID +MainWndMoveFloatingWindows(PMAIN_WND_INFO Info, + PRECT wndOldPos) +{ + RECT wndNewPos, TbRect; + INT i, xMoved, yMoved; + PFLT_WND WndArr[NUM_FLT_WND]; + + if (GetWindowRect(Info->hSelf, + &wndNewPos)) + { + + xMoved = wndNewPos.left - wndOldPos->left; + yMoved = wndNewPos.top - wndOldPos->top; + + /* store the pointers in an array */ + WndArr[0] = Info->fltTools; + WndArr[1] = Info->fltColors; + WndArr[2] = Info->fltHistory; + + for (i = 0; i < NUM_FLT_WND; i++) + { + GetWindowRect(WndArr[i]->hSelf, + &TbRect); + + WndArr[i]->x = TbRect.left + xMoved; + WndArr[i]->y = TbRect.top + yMoved; + + MoveWindow(WndArr[i]->hSelf, + WndArr[i]->x, + WndArr[i]->y, + WndArr[i]->Width, + WndArr[i]->Height, + TRUE); + } + + CopyMemory(wndOldPos, + &wndNewPos, + sizeof(RECT)); + } +} + + +static VOID +MainWndResetFloatingWindows(PMAIN_WND_INFO Info) +{ + RECT rect; + + if (GetWindowRect(Info->hMdiClient, + &rect)) + { + + /* tools datum */ + MoveWindow(Info->fltTools->hSelf, + rect.left + 5, + rect.top + 5, + Info->fltTools->Width, + Info->fltTools->Height, + TRUE); + + /* colors datum */ + MoveWindow(Info->fltColors->hSelf, + rect.left + 5, + rect.bottom - Info->fltColors->Height - 5, + Info->fltColors->Width, + Info->fltColors->Height, + TRUE); + + /* history datum */ + MoveWindow(Info->fltHistory->hSelf, + rect.right - Info->fltHistory->Width - 5, + rect.top + 5, + Info->fltHistory->Width, + Info->fltHistory->Height, + TRUE); + } +} + +static VOID +MainWndCreateFloatWindows(PMAIN_WND_INFO Info) +{ + RECT rect; + HMENU hMenu; + UINT Res; + PFLT_WND WndArr[NUM_FLT_WND]; /* temp array for looping */ + INT i; + + Info->fltTools = HeapAlloc(ProcessHeap, + HEAP_ZERO_MEMORY, + sizeof(FLT_WND)); + Info->fltColors = HeapAlloc(ProcessHeap, + HEAP_ZERO_MEMORY, + sizeof(FLT_WND)); + Info->fltHistory = HeapAlloc(ProcessHeap, + HEAP_ZERO_MEMORY, + sizeof(FLT_WND)); + + /* set window dimensions */ + Info->fltTools->Width = 53; + Info->fltTools->Height = 300; + Info->fltColors->Width = 200; + Info->fltColors->Height = 200; + Info->fltHistory->Width = 150; + Info->fltHistory->Height = 150; + + if (! GetWindowRect(Info->hMdiClient, + &rect)) + { + return; + } + + /* Set window datums */ + Info->fltTools->x = rect.left + 5; + Info->fltTools->y = rect.top + 5; + + Info->fltColors->x = rect.left + 5; + Info->fltColors->y = rect.bottom - Info->fltColors->Height - 5; + + Info->fltHistory->x = rect.right - Info->fltHistory->Width - 5; + Info->fltHistory->y = rect.top + 5; + + /* save pointers into array incrementing within the loop*/ + WndArr[0] = Info->fltTools; + WndArr[1] = Info->fltColors; + WndArr[2] = Info->fltHistory; + + for (i = 0, Res = IDS_FLT_TOOLS; Res < IDS_FLT_TOOLS + NUM_FLT_WND; Res++, i++) + { + if (! AllocAndLoadString(&WndArr[i]->lpName, + hInstance, + Res)) + { + WndArr[i]->lpName = NULL; + } + + WndArr[i]->hSelf = CreateWindowEx(WS_EX_TOOLWINDOW, + TEXT("ImageSoftFloatWndClass"), + WndArr[i]->lpName, + WS_POPUPWINDOW | WS_DLGFRAME | WS_VISIBLE, + WndArr[i]->x, + WndArr[i]->y, + WndArr[i]->Width, + WndArr[i]->Height, + Info->hSelf, + NULL, + hInstance, + WndArr[i]); + ShowWindow(WndArr[i]->hSelf, SW_HIDE); + } + + hMenu = GetMenu(Info->hSelf); + + if (Info->fltTools->hSelf != NULL) + { + if (FloatToolbarCreateToolsGui(Info)) + { + CheckMenuItem(hMenu, + ID_TOOLS, + MF_CHECKED); + + ShowHideWindow(Info->fltTools->hSelf); + } + } + + if (Info->fltColors->hSelf != NULL) + { + if (FloatToolbarCreateColorsGui(Info)) + { + + } + } + + if (Info->fltHistory->hSelf != NULL) + { + if (FloatToolbarCreateHistoryGui(Info)) + { + + } + } + +} + +static VOID +MainWndDestroyFloatWindows(PMAIN_WND_INFO Info) +{ + if (Info->fltTools != NULL) + HeapFree(ProcessHeap, 0, Info->fltTools); + + if (Info->fltColors != NULL) + HeapFree(ProcessHeap, 0, Info->fltColors); + + if (Info->fltHistory != NULL) + HeapFree(ProcessHeap, 0, Info->fltHistory); +} + + + +static const DOCKBAR_ITEM_CALLBACKS MainWndDockBarCallbacks = { + MainWndCreateToolbarClient, + MainWndDestroyToolbarClient, + MainWndToolbarInsertBand, + MainWndToolbarDockBand, + MainWndToolbarChevronPushed, +}; + +static VOID +CreateToolbars(PMAIN_WND_INFO Info) +{ + UINT i; + + for (i = 0; i < sizeof(MainDockBars) / sizeof(MainDockBars[0]); i++) + { + /* FIXME - lookup whether to display the toolbar */ + TbdAddToolbar(&Info->ToolDocks, + &MainDockBars[i], + Info, + &MainWndDockBarCallbacks); + } + + MainWndCreateFloatWindows(Info); +} + +static VOID CALLBACK +MainWndResize(PVOID Context, + LONG cx, + LONG cy) +{ + RECT rcClient = {0}; + RECT rcStatus = {0}; + HDWP dwp; + INT DocksVisible; + PMAIN_WND_INFO Info = (PMAIN_WND_INFO)Context; + + /* Calculate the MDI client rectangle */ + rcClient.right = cx; + rcClient.bottom = cy; + + if (Info->hStatus != NULL) + { + GetWindowRect(Info->hStatus, + &rcStatus); + rcClient.bottom -= (rcStatus.bottom - rcStatus.top); + } + + /* Adjust the client rect if docked toolbars are visible */ + DocksVisible = TbdAdjustUpdateClientRect(&Info->ToolDocks, + &rcClient); + + dwp = BeginDeferWindowPos(2 + DocksVisible); + if (dwp != NULL) + { + /* Update the toolbar docks */ + if (DocksVisible != 0) + { + dwp = TbdDeferDocks(dwp, + &Info->ToolDocks); + if (dwp == NULL) + return; + } + + /* Update the MDI client */ + if (Info->hMdiClient != NULL) + { + dwp = DeferWindowPos(dwp, + Info->hMdiClient, + NULL, + rcClient.left, + rcClient.top, + rcClient.right - rcClient.left, + rcClient.bottom - rcClient.top, + SWP_NOZORDER); + if (dwp == NULL) + return; + } + + /* Update the status bar */ + if (Info->hStatus != NULL) + { + dwp = DeferWindowPos(dwp, + Info->hStatus, + NULL, + 0, + cy - (rcStatus.bottom - rcStatus.top), + cx, + rcStatus.bottom - rcStatus.top, + SWP_NOZORDER); + if (dwp == NULL) + return; + } + + EndDeferWindowPos(dwp); + } +} + +static VOID +InitMainWnd(PMAIN_WND_INFO Info) +{ + CLIENTCREATESTRUCT ccs; + INT statwidths[] = {110, -1}; + + /* FIXME - create controls and initialize the application */ + + /* create the status bar */ + Info->hStatus = CreateWindowEx(0, + STATUSCLASSNAME, + NULL, + WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | CCS_NOPARENTALIGN | SBARS_SIZEGRIP, + 0, + 0, + 0, + 0, + Info->hSelf, + (HMENU)IDC_STATUSBAR, + hInstance, + NULL); + + if (Info->hStatus != NULL) + SendMessage(Info->hStatus, + SB_SETPARTS, + sizeof(statwidths)/sizeof(int), + (LPARAM)statwidths); + + /* create the MDI client window */ + ccs.hWindowMenu = GetSubMenu(GetMenu(Info->hSelf), + ID_MDI_WINDOWMENU); + ccs.idFirstChild = ID_MDI_FIRSTCHILD; + Info->hMdiClient = CreateWindowEx(WS_EX_ACCEPTFILES | WS_EX_CLIENTEDGE, + TEXT("MDICLIENT"), + NULL, + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL, + 0, + 0, + 0, + 0, + Info->hSelf, + NULL, + hInstance, + &ccs); + + TbdInitializeDocks(&Info->ToolDocks, + Info->hSelf, + Info, + MainWndResize); + + CreateToolbars(Info); + + /* initialize file open/save structure */ + FileInitialize(Info->hSelf); +} + +static VOID +MainWndCommand(PMAIN_WND_INFO Info, + WORD CmdId, + HWND hControl) +{ + static TCHAR szFileName[MAX_PATH]; + static TCHAR szImageName[MAX_PATH]; + + UNREFERENCED_PARAMETER(hControl); + + switch (CmdId) + { + case ID_NEW: + { + MessageBox(NULL, _T("Not yet implemented"), NULL, 0); + } + break; + + case ID_OPEN: + { + OPEN_IMAGE_EDIT_INFO OpenInfo; + + if (DoOpenFile(Info->hSelf, + szFileName, /* full file path */ + szImageName)) /* file name */ + { + OpenInfo.CreateNew = FALSE; + + OpenInfo.Open.lpImagePath = szFileName; + OpenInfo.lpImageName = szImageName; + + CreateImageEditWindow(Info, + &OpenInfo); + + /* FIXME: move flt wnd's if scroll bars show + MainWndResetFloatingWindows(Info->hMdiClient); */ + } + + } + break; + + case ID_TOOLS: + { + HMENU hMenu = GetMenu(Info->hSelf); + + if (hMenu != NULL) + { + UINT uCheck = MF_CHECKED; + + if (ShowHideWindow(Info->fltTools->hSelf)) + uCheck = MF_UNCHECKED; + + CheckMenuItem(hMenu, + ID_TOOLS, + uCheck); + } + } + break; + + case ID_COLOR: + { + HMENU hMenu = GetMenu(Info->hSelf); + + if (hMenu != NULL) + { + UINT uCheck = MF_CHECKED; + + if (ShowHideWindow(Info->fltColors->hSelf)) + uCheck = MF_UNCHECKED; + + CheckMenuItem(hMenu, + ID_COLOR, + uCheck); + } + } + break; + + case ID_HISTORY: + { + HMENU hMenu = GetMenu(Info->hSelf); + + if (hMenu != NULL) + { + UINT uCheck = MF_CHECKED; + + if (ShowHideWindow(Info->fltHistory->hSelf)) + uCheck = MF_UNCHECKED; + + CheckMenuItem(hMenu, + ID_HISTORY, + uCheck); + } + } + break; + + case ID_BRIGHTNESS: + DialogBoxParam(hInstance, + MAKEINTRESOURCE(IDD_BRIGHTNESS), + Info->hSelf, + BrightnessProc, + (LPARAM)Info); + break; + + case ID_CONTRAST: + /* FIXME : Create a window for contrast */ + break; + + case ID_BLACKANDWHITE: + { + if (Info->ImageEditors) + { + DisplayBlackAndWhite(Info->ImageEditors->hSelf, + Info->ImageEditors->hDCMem, + Info->ImageEditors->hBitmap); + } + } + break; + + case ID_INVERTCOLORS: + { + if (Info->ImageEditors) + { + DisplayInvertedColors(Info->ImageEditors->hSelf, + Info->ImageEditors->hDCMem, + Info->ImageEditors->hBitmap); + } + } + break; + + case ID_BLUR: + { + if (Info->ImageEditors) + { + DisplayBlur(Info->ImageEditors->hSelf, + Info->ImageEditors->hDCMem, + Info->ImageEditors->hBitmap); + } + } + break; + + case ID_SHARPEN: + { + if (Info->ImageEditors) + { + DisplaySharpness(Info->ImageEditors->hSelf, + Info->ImageEditors->hDCMem, + Info->ImageEditors->hBitmap); + } + } + break; + + case ID_EXIT: + SendMessage(Info->hSelf, + WM_CLOSE, + 0, + 0); + break; + + /* Window Menu */ + case ID_WINDOW_TILE_HORZ: + SendMessage(Info->hMdiClient, + WM_MDITILE, + MDITILE_HORIZONTAL, + 0); + break; + + case ID_WINDOW_TILE_VERT: + SendMessage(Info->hMdiClient, + WM_MDITILE, + MDITILE_VERTICAL, + 0); + break; + + case ID_WINDOW_CASCADE: + SendMessage(Info->hMdiClient, + WM_MDICASCADE, + 0, + 0); + break; + + case ID_WINDOW_ARRANGE: + SendMessage(Info->hMdiClient, + WM_MDIICONARRANGE, + 0, + 0); + break; + + case ID_WINDOW_NEXT: + SendMessage(Info->hMdiClient, + WM_MDINEXT, + 0, + 0); + break; + + /* Help Menu */ + case ID_ABOUT: + DialogBox(hInstance, + MAKEINTRESOURCE(IDD_ABOUTBOX), + Info->hSelf, + AboutDialogProc); + break; + } +} + +static VOID +DestroyMainWnd(PMAIN_WND_INFO Info) +{ + /* FIXME - cleanup allocated resources */ + + MainWndDestroyFloatWindows(Info); +} + + +static VOID +UpdateMainStatusBar(PMAIN_WND_INFO Info) +{ + if (Info->hStatus != NULL) + { + SendMessage(Info->hStatus, + SB_SIMPLE, + (WPARAM)Info->InMenuLoop, + 0); + } +} + +static BOOL +MainWndMenuHint(PMAIN_WND_INFO Info, + WORD CmdId, + const MENU_HINT *HintArray, + DWORD HintsCount, + UINT DefHintId) +{ + BOOL Found = FALSE; + const MENU_HINT *LastHint; + UINT HintId = DefHintId; + + LastHint = HintArray + HintsCount; + while (HintArray != LastHint) + { + if (HintArray->CmdId == CmdId) + { + HintId = HintArray->HintId; + Found = TRUE; + break; + } + HintArray++; + } + + StatusBarLoadString(Info->hStatus, + SB_SIMPLEID, + hInstance, + HintId); + + return Found; +} + +static LRESULT CALLBACK +MainWndProc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + PMAIN_WND_INFO Info; + LRESULT Ret = 0; + static BOOL bLBMouseDown = FALSE; + static RECT wndOldPos; + + /* Get the window context */ + Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd, + GWLP_USERDATA); + if (Info == NULL && uMsg != WM_CREATE) + { + goto HandleDefaultMessage; + } + + switch (uMsg) + { + case WM_SIZE: + { + MainWndResize(Info, + LOWORD(lParam), + HIWORD(lParam)); + /* NOTE - do *not* forward this message to DefFrameProc! Otherwise the MDI client + will attempt to resize itself */ + + /* reposition the floating toolbars */ + if ((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED)) + MainWndResetFloatingWindows(Info); + + break; + } + + case WM_NCLBUTTONDOWN: + bLBMouseDown = TRUE; + DefWindowProc(hwnd, + uMsg, + wParam, + lParam); + break; + + case WM_NCLBUTTONUP: + + bLBMouseDown = FALSE; + DefWindowProc(hwnd, + uMsg, + wParam, + lParam); + break; + + case WM_MOVE: + { + /* if the main window is moved, move the toolbars too */ + if (bLBMouseDown) + MainWndMoveFloatingWindows(Info, &wndOldPos); + } + break; + + case WM_NOTIFY: + { + UINT BarId; + LPNMHDR pnmhdr = (LPNMHDR)lParam; + if (!TbdHandleNotifications(&Info->ToolDocks, + pnmhdr, + &Ret)) + { + if (TbdDockBarIdFromClientWindow(&Info->ToolDocks, + pnmhdr->hwndFrom, + &BarId)) + { + switch (BarId) + { + case ID_TOOLBAR_TEXT: + switch (pnmhdr->code) + { + case TBN_DELETINGBUTTON: + { + LPNMTOOLBAR lpnmtb = (LPNMTOOLBAR)lParam; + + ToolbarDeleteControlSpace(pnmhdr->hwndFrom, + &lpnmtb->tbButton); + break; + } + } + break; + } + } + } + break; + } + + case WM_COMMAND: + { + MainWndCommand(Info, + LOWORD(wParam), + (HWND)lParam); + goto HandleDefaultMessage; + } + + case WM_MENUSELECT: + { + if (Info->hStatus != NULL) + { + if (!MainWndMenuHint(Info, + LOWORD(wParam), + MainMenuHintTable, + sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]), + IDS_HINT_BLANK)) + { + MainWndMenuHint(Info, + LOWORD(wParam), + SystemMenuHintTable, + sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]), + IDS_HINT_BLANK); + } + } + break; + } + + case WM_ENTERMENULOOP: + { + Info->InMenuLoop = TRUE; + UpdateMainStatusBar(Info); + break; + } + + case WM_EXITMENULOOP: + { + Info->InMenuLoop = FALSE; + UpdateMainStatusBar(Info); + break; + } + + case WM_CLOSE: + { + DestroyWindow(hwnd); + break; + } + + case WM_ENABLE: + { + TbdHandleEnabling(&Info->ToolDocks, + hwnd, + (BOOL)wParam); + goto HandleDefaultMessage; + } + + case WM_NCACTIVATE: + { + TbdHandleActivation(&Info->ToolDocks, + hwnd, + &wParam, + &lParam); + goto HandleDefaultMessage; + } + + case WM_ACTIVATEAPP: + { + //TbdShowFloatingToolbars(&Info->ToolDocks, + // (BOOL)wParam); + goto HandleDefaultMessage; + } + + case WM_CREATE: + { + Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams); + + /* Initialize the main window context */ + Info->hSelf = hwnd; + + SetWindowLongPtr(hwnd, + GWLP_USERDATA, + (LONG_PTR)Info); + + InitMainWnd(Info); + + /* Show the window */ + ShowWindow(hwnd, + Info->nCmdShow); + /* get the windows position */ + GetWindowRect(hwnd, + &wndOldPos); + + break; + } + + case WM_DESTROY: + { + DestroyMainWnd(Info); + + HeapFree(ProcessHeap, + 0, + Info); + SetWindowLongPtr(hwnd, + GWLP_USERDATA, + 0); + + /* Break the message queue loop */ + PostQuitMessage(0); + break; + } + + default: + { +HandleDefaultMessage: + if (Info != NULL && Info->hMdiClient != NULL) + { + Ret = DefFrameProc(hwnd, + Info->hMdiClient, + uMsg, + wParam, + lParam); + } + else + { + Ret = DefWindowProc(hwnd, + uMsg, + wParam, + lParam); + } + break; + } + } + + return Ret; +} + +MDI_EDITOR_TYPE +MainWndGetCurrentEditor(PMAIN_WND_INFO MainWnd, + PVOID *Info) +{ + MDI_EDITOR_TYPE EditorType; + + if (MainWnd->ActiveEditor != NULL) + { + EditorType = *((PMDI_EDITOR_TYPE)MainWnd->ActiveEditor); + *Info = MainWnd->ActiveEditor; + } + else + { + EditorType = metUnknown; + *Info = NULL; + } + + return EditorType; +} + +VOID +MainWndSwitchEditorContext(PMAIN_WND_INFO Info, + HWND hDeactivate, + HWND hActivate) +{ + PMDI_EDITOR_TYPE EditorType; + + /* FIXME - optimize light weight switching + when switching from and to an editor of same type */ + + if (hDeactivate != NULL) + { + EditorType = (PMDI_EDITOR_TYPE)GetWindowLongPtr(hDeactivate, + GWLP_USERDATA); + if (EditorType != NULL) + { + switch (*EditorType) + { + case metImageEditor: + SetImageEditorEnvironment((PEDIT_WND_INFO)EditorType, + FALSE); + break; + + default: + break; + } + + Info->ActiveEditor = NULL; + } + } + + if (hActivate != NULL) + { + EditorType = (PMDI_EDITOR_TYPE)GetWindowLongPtr(hActivate, + GWLP_USERDATA); + if (EditorType != NULL) + { + Info->ActiveEditor = EditorType; + + switch (*EditorType) + { + case metImageEditor: + SetImageEditorEnvironment((PEDIT_WND_INFO)EditorType, + TRUE); + break; + + default: + break; + } + } + } +} + +HWND +CreateMainWindow(LPCTSTR lpCaption, + int nCmdShow) +{ + PMAIN_WND_INFO Info; + HWND hMainWnd = NULL; + + Info = HeapAlloc(ProcessHeap, + 0, + sizeof(MAIN_WND_INFO)); + if (Info != NULL) + { + ZeroMemory(Info, + sizeof(MAIN_WND_INFO)); + Info->nCmdShow = nCmdShow; + + /* FIXME - load the window position from the registry */ + + hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE, + szMainWndClass, + lpCaption, + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + hInstance, + Info); + if (hMainWnd == NULL) + { + HeapFree(ProcessHeap, + 0, + Info); + } + } + + return hMainWnd; +} + +BOOL +MainWndTranslateMDISysAccel(HWND hwnd, + LPMSG lpMsg) +{ + PMAIN_WND_INFO Info; + + /* Get the window context */ + Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd, + GWLP_USERDATA); + if (Info != NULL && Info->hMdiClient != NULL) + { + return TranslateMDISysAccel(Info->hMdiClient, + lpMsg); + } + + return FALSE; +} + +BOOL +InitMainWindowImpl(VOID) +{ + WNDCLASSEX wc = {0}; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.lpfnWndProc = MainWndProc; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(hInstance, + MAKEINTRESOURCE(IDI_IMAGESOFTICON)); + wc.hCursor = LoadCursor(NULL, + IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU); + wc.lpszClassName = szMainWndClass; + wc.hIconSm = (HICON)LoadImage(hInstance, + MAKEINTRESOURCE(IDI_IMAGESOFTICON), + IMAGE_ICON, + 16, + 16, + LR_SHARED); + + return RegisterClassEx(&wc) != (ATOM)0; +} + +VOID +UninitMainWindowImpl(VOID) +{ + UnregisterClass(szMainWndClass, + hInstance); +} diff --git a/modules/rosapps/applications/imagesoft/mainwnd.h b/modules/rosapps/applications/imagesoft/mainwnd.h new file mode 100644 index 00000000000..84262f8d86d --- /dev/null +++ b/modules/rosapps/applications/imagesoft/mainwnd.h @@ -0,0 +1,41 @@ + +typedef struct _MENU_HINT +{ + WORD CmdId; + UINT HintId; +} MENU_HINT, *PMENU_HINT; + +typedef struct _MAIN_WND_INFO +{ + HWND hSelf; + HWND hMdiClient; + HWND hStatus; + int nCmdShow; + + struct _FLT_WND *fltTools; + struct _FLT_WND *fltColors; + struct _FLT_WND *fltHistory; + + struct _TOOLBAR_DOCKS ToolDocks; + + /* Editors */ + PEDIT_WND_INFO ImageEditors; + UINT ImagesCreated; + + PVOID ActiveEditor; + + /* status flags */ + BOOL InMenuLoop : 1; +} MAIN_WND_INFO, *PMAIN_WND_INFO; + +BOOL InitMainWindowImpl(VOID); +VOID UninitMainWindowImpl(VOID); +HWND CreateMainWindow(LPCTSTR lpCaption, + int nCmdShow); +BOOL MainWndTranslateMDISysAccel(HWND hwnd, + LPMSG lpMsg); +VOID MainWndSwitchEditorContext(PMAIN_WND_INFO Info, + HWND hDeactivate, + HWND hActivate); +MDI_EDITOR_TYPE MainWndGetCurrentEditor(PMAIN_WND_INFO MainWnd, + PVOID *Info); diff --git a/modules/rosapps/applications/imagesoft/misc.c b/modules/rosapps/applications/imagesoft/misc.c new file mode 100644 index 00000000000..709042b6e65 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/misc.c @@ -0,0 +1,422 @@ +#include + +static INT +LengthOfStrResource(IN HINSTANCE hInst, + IN UINT uID) +{ + HRSRC hrSrc; + HGLOBAL hRes; + LPWSTR lpName, lpStr; + + if (hInst == NULL) + { + return -1; + } + + /* There are always blocks of 16 strings */ + lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1); + + /* Find the string table block */ + if ((hrSrc = FindResourceW(hInst, lpName, (LPWSTR)RT_STRING)) && + (hRes = LoadResource(hInst, hrSrc)) && + (lpStr = LockResource(hRes))) + { + UINT x; + + /* Find the string we're looking for */ + uID &= 0xF; /* position in the block, same as % 16 */ + for (x = 0; x < uID; x++) + { + lpStr += (*lpStr) + 1; + } + + /* Found the string */ + return (int)(*lpStr); + } + return -1; +} + +INT +AllocAndLoadString(OUT LPTSTR *lpTarget, + IN HINSTANCE hInst, + IN UINT uID) +{ + INT ln; + + ln = LengthOfStrResource(hInst, + uID); + if (ln++ > 0) + { + (*lpTarget) = (LPTSTR)LocalAlloc(LMEM_FIXED, + ln * sizeof(TCHAR)); + if ((*lpTarget) != NULL) + { + INT Ret; + if (!(Ret = LoadString(hInst, uID, *lpTarget, ln))) + { + LocalFree((HLOCAL)(*lpTarget)); + } + return Ret; + } + } + return 0; +} + +DWORD +LoadAndFormatString(IN HINSTANCE hInstance, + IN UINT uID, + OUT LPTSTR *lpTarget, + ...) +{ + DWORD Ret = 0; + LPTSTR lpFormat; + va_list lArgs; + + if (AllocAndLoadString(&lpFormat, + hInstance, + uID) > 0) + { + va_start(lArgs, lpTarget); + /* let's use FormatMessage to format it because it has the ability to allocate + memory automatically */ + Ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + lpFormat, + 0, + 0, + (LPTSTR)lpTarget, + 0, + &lArgs); + va_end(lArgs); + + LocalFree((HLOCAL)lpFormat); + } + + return Ret; +} + +BOOL +StatusBarLoadAndFormatString(IN HWND hStatusBar, + IN INT PartId, + IN HINSTANCE hInstance, + IN UINT uID, + ...) +{ + BOOL Ret = FALSE; + LPTSTR lpFormat, lpStr; + va_list lArgs; + + if (AllocAndLoadString(&lpFormat, + hInstance, + uID) > 0) + { + va_start(lArgs, uID); + /* let's use FormatMessage to format it because it has the ability to allocate + memory automatically */ + Ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + lpFormat, + 0, + 0, + (LPTSTR)&lpStr, + 0, + &lArgs); + va_end(lArgs); + + if (lpStr != NULL) + { + Ret = (BOOL)SendMessage(hStatusBar, + SB_SETTEXT, + (WPARAM)PartId, + (LPARAM)lpStr); + LocalFree((HLOCAL)lpStr); + } + + LocalFree((HLOCAL)lpFormat); + } + + return Ret; +} + +BOOL +StatusBarLoadString(IN HWND hStatusBar, + IN INT PartId, + IN HINSTANCE hInstance, + IN UINT uID) +{ + BOOL Ret = FALSE; + LPTSTR lpStr; + + if (AllocAndLoadString(&lpStr, + hInstance, + uID) > 0) + { + Ret = (BOOL)SendMessage(hStatusBar, + SB_SETTEXT, + (WPARAM)PartId, + (LPARAM)lpStr); + LocalFree((HLOCAL)lpStr); + } + + return Ret; +} + + +INT +GetTextFromEdit(OUT LPTSTR lpString, + IN HWND hDlg, + IN UINT Res) +{ + INT len = GetWindowTextLength(GetDlgItem(hDlg, Res)); + if(len > 0) + { + GetDlgItemText(hDlg, + Res, + lpString, + len + 1); + } + else + lpString = NULL; + + return len; +} + + +VOID GetError(DWORD err) +{ + LPVOID lpMsgBuf; + + if (err == 0) + err = GetLastError(); + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL ); + + MessageBox(NULL, lpMsgBuf, _T("Error!"), MB_OK | MB_ICONERROR); + + LocalFree(lpMsgBuf); +} + + + +/* + * Toolbar custom control routines + */ + +typedef struct _TBCUSTCTL +{ + HWND hWndControl; + INT iCommand; + BOOL HideVertical : 1; + BOOL IsVertical : 1; +} TBCUSTCTL, *PTBCUSTCTL; + +BOOL +ToolbarDeleteControlSpace(HWND hWndToolbar, + const TBBUTTON *ptbButton) +{ + if ((ptbButton->fsStyle & TBSTYLE_SEP) && + ptbButton->dwData != 0) + { + PTBCUSTCTL cctl = (PTBCUSTCTL)ptbButton->dwData; + + DestroyWindow(cctl->hWndControl); + + HeapFree(ProcessHeap, + 0, + cctl); + return TRUE; + } + + return FALSE; +} + +VOID +ToolbarUpdateControlSpaces(HWND hWndToolbar, + ToolbarChangeControlCallback ChangeCallback) +{ + BOOL Vert; + DWORD nButtons, i; + TBBUTTON tbtn; + + Vert = ((SendMessage(hWndToolbar, + TB_GETSTYLE, + 0, + 0) & CCS_VERT) != 0); + + nButtons = (DWORD)SendMessage(hWndToolbar, + TB_BUTTONCOUNT, + 0, + 0); + + for (i = 0; + i != nButtons; + i++) + { + if (SendMessage(hWndToolbar, + TB_GETBUTTON, + (WPARAM)i, + (LPARAM)&tbtn)) + { + if ((tbtn.fsStyle & TBSTYLE_SEP) && tbtn.dwData != 0) + { + PTBCUSTCTL cctl = (PTBCUSTCTL)tbtn.dwData; + + cctl->IsVertical = Vert; + + if (cctl->HideVertical) + { + ShowWindow(cctl->hWndControl, + (Vert ? SW_HIDE : SW_SHOW)); + goto ShowHideSep; + } + else if (cctl->IsVertical != Vert) + { + ChangeCallback(hWndToolbar, + cctl->hWndControl, + Vert); + +ShowHideSep: + /* show/hide the separator */ + SendMessage(hWndToolbar, + TB_HIDEBUTTON, + (WPARAM)cctl->iCommand, + (LPARAM)Vert && cctl->HideVertical); + } + } + } + } +} + +BOOL +ToolbarInsertSpaceForControl(HWND hWndToolbar, + HWND hWndControl, + INT Index, + INT iCmd, + BOOL HideVertical) +{ + PTBCUSTCTL cctl; + RECT rcControl, rcItem; + + cctl = HeapAlloc(ProcessHeap, + 0, + sizeof(TBCUSTCTL)); + if (cctl == NULL) + return FALSE; + + cctl->HideVertical = HideVertical; + cctl->hWndControl = hWndControl; + cctl->iCommand = iCmd; + + if (GetWindowRect(hWndControl, + &rcControl)) + { + TBBUTTON tbtn = {0}; + + tbtn.iBitmap = rcControl.right - rcControl.left; + tbtn.idCommand = iCmd; + tbtn.fsStyle = TBSTYLE_SEP; + tbtn.dwData = (DWORD_PTR)cctl; + + if (SendMessage(hWndToolbar, + TB_GETSTYLE, + 0, + 0) & CCS_VERT) + { + if (HideVertical) + tbtn.fsState |= TBSTATE_HIDDEN; + + cctl->IsVertical = TRUE; + } + else + cctl->IsVertical = FALSE; + + if (SendMessage(hWndToolbar, + TB_INSERTBUTTON, + (WPARAM)Index, + (LPARAM)&tbtn)) + { + if (SendMessage(hWndToolbar, + TB_GETITEMRECT, + (WPARAM)Index, + (LPARAM)&rcItem)) + { + SetWindowPos(hWndControl, + NULL, + rcItem.left, + rcItem.top, + rcItem.right - rcItem.left, + rcItem.bottom - rcItem.top, + SWP_NOZORDER); + + ShowWindow(hWndControl, + SW_SHOW); + + return TRUE; + } + else if (tbtn.fsState & TBSTATE_HIDDEN) + { + ShowWindow(hWndControl, + SW_HIDE); + } + } + } + + return FALSE; +} + + +HIMAGELIST +InitImageList(UINT NumImages, UINT StartResource) +{ + HBITMAP hBitmap; + HIMAGELIST hImageList; + UINT i, k; + INT Ret; + + + /* Create the toolbar icon image list */ + hImageList = ImageList_Create(TB_BMP_WIDTH, + TB_BMP_HEIGHT, + ILC_MASK | ILC_COLOR24, + NumImages, + 0); + if (! hImageList) + return NULL; + + /* Add all icons to the image list */ + for (i = StartResource, k = 0; k < NumImages; i++, k++) + { + hBitmap = LoadImage(hInstance, + MAKEINTRESOURCE(i), + IMAGE_BITMAP, + TB_BMP_WIDTH, + TB_BMP_HEIGHT, + LR_LOADTRANSPARENT); + + Ret = ImageList_AddMasked(hImageList, + hBitmap, + RGB(255, 255, 254)); + + DeleteObject(hBitmap); + } + + return hImageList; + +} + +/* +static BOOL +DestroyImageList(HIMAGELIST hImageList) +{ + if (! ImageList_Destroy(hImageList)) + return FALSE; + else + return TRUE; +} +*/ diff --git a/modules/rosapps/applications/imagesoft/misc.h b/modules/rosapps/applications/imagesoft/misc.h new file mode 100644 index 00000000000..05d48307963 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/misc.h @@ -0,0 +1,44 @@ + +INT AllocAndLoadString(OUT LPTSTR *lpTarget, + IN HINSTANCE hInst, + IN UINT uID); + +DWORD LoadAndFormatString(IN HINSTANCE hInstance, + IN UINT uID, + OUT LPTSTR *lpTarget, + ...); + +BOOL StatusBarLoadAndFormatString(IN HWND hStatusBar, + IN INT PartId, + IN HINSTANCE hInstance, + IN UINT uID, + ...); + +BOOL StatusBarLoadString(IN HWND hStatusBar, + IN INT PartId, + IN HINSTANCE hInstance, + IN UINT uID); + +INT GetTextFromEdit(OUT LPTSTR lpString, + IN HWND hDlg, + IN UINT Res); + +VOID GetError(DWORD err); + +BOOL ToolbarDeleteControlSpace(HWND hWndToolbar, + const TBBUTTON *ptbButton); + +typedef VOID (*ToolbarChangeControlCallback)(HWND hWndToolbar, + HWND hWndControl, + BOOL Vert); +VOID ToolbarUpdateControlSpaces(HWND hWndToolbar, + ToolbarChangeControlCallback ChangeCallback); + +BOOL ToolbarInsertSpaceForControl(HWND hWndToolbar, + HWND hWndControl, + INT Index, + INT iCmd, + BOOL HideVertical); + +HIMAGELIST InitImageList(UINT NumButtons, + UINT StartResource); diff --git a/modules/rosapps/applications/imagesoft/opensave.c b/modules/rosapps/applications/imagesoft/opensave.c new file mode 100644 index 00000000000..9fccbb8b64b --- /dev/null +++ b/modules/rosapps/applications/imagesoft/opensave.c @@ -0,0 +1,87 @@ +#include + +static OPENFILENAME ofn; + +/* + * Initialize file open / save structure + */ +VOID FileInitialize(HWND hwnd) +{ + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hwnd; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = _T("bmp"); +} + + +static BOOL +DoWriteFile(LPCTSTR pszFileName) +{ + return TRUE; +} + + +BOOL +DoOpenFile(HWND hwnd, + LPTSTR szFileName, + LPTSTR szTitleName) +{ + DWORD err; + /*static TCHAR Filter[] = _T("All image files (*.gif,*.bmp,*.jpg,*.jpeg,*.tif,*.png)\0*.gif,*.bmp,*.jpg,*.jpeg,*.tif,*.png\0") \ + _T("All files (*.*)\0*.*\0") \ + _T("Graphics Interchange format (*gif)\0*.gif\0") \ + _T("Windows Bitmap (*bmp)\0*.bmp\0") \ + _T("JPEG File Interchange Format (*jpg,*.jpeg)\0*.jpg,*.jpeg\0") \ + _T("TAG Image File Format (*tif)\0*.tif\0") \ + _T("Portable Network Graphics (*png)\0*.png\0\0");*/ + + static TCHAR Filter[] = _T("Windows Bitmap (*.bmp)\0*.bmp\0"); + + ofn.lpstrFilter = Filter; + ofn.lpstrFile = szFileName; + ofn.lpstrFileTitle = szTitleName; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + + if (GetOpenFileName(&ofn)) + { + return TRUE; + } + + err = CommDlgExtendedError(); + + if (err != CDERR_GENERALCODES) + MessageBox(NULL, _T("Open file failed"), NULL, 0); + + return FALSE; +} + + + +BOOL +DoSaveFile(HWND hwnd) +{ + TCHAR szFileName[MAX_PATH] = _T(""); + static TCHAR Filter[] = _T("Graphics Interchange format (*gif)\0*.gif\0") \ + _T("Windows Bitmap (*bmp)\0*.bmp\0") \ + _T("JPEG File Interchange Format (*jpg,*.jpeg)\0*.jpg,*.jpeg\0") \ + _T("TAG Image File Format (*tif)\0*.tif\0") \ + _T("Portable Network Graphics (*png)\0*.png\0\0"); + + ofn.lpstrFilter = Filter; + ofn.lpstrFile = szFileName; + ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + + if (GetSaveFileName(&ofn)) + { + if (DoWriteFile(szFileName)) + return TRUE; + } + + if (CommDlgExtendedError() != CDERR_GENERALCODES) + MessageBox(NULL, _T("Save to file failed"), NULL, 0); + + return FALSE; +} + diff --git a/modules/rosapps/applications/imagesoft/precomp.h b/modules/rosapps/applications/imagesoft/precomp.h new file mode 100644 index 00000000000..bada1909ec2 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/precomp.h @@ -0,0 +1,70 @@ +#ifndef __IMAGESOFT_PRECOMP_H +#define __IMAGESOFT_PRECOMP_H + +//#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include "resource.h" + +#include "tooldock.h" +#include "imgedwnd.h" +#include "mainwnd.h" +#include "imageprop.h" +#include "misc.h" + +#define MAX_KEY_LENGTH 256 +#define NUM_MAINTB_IMAGES 10 +#define TB_BMP_WIDTH 16 +#define TB_BMP_HEIGHT 16 + +#define TOOLS 0 +#define COLORS 1 +#define HISTORY 2 + +extern HINSTANCE hInstance; +extern HANDLE ProcessHeap; + +/* about.c */ +INT_PTR CALLBACK AboutDialogProc(HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam); + +/* opensave.c */ +VOID FileInitialize(HWND hwnd); +BOOL DoOpenFile(HWND hwnd, + LPTSTR lpFileName, + LPTSTR lpName); +BOOL DoSaveFile(HWND hwnd); + +/* floattoolbar.c */ +typedef struct _FLT_WND +{ + HWND hSelf; + LPTSTR lpName; + INT x; + INT y; + INT Width; + INT Height; + INT Transparancy; + BOOL bOpaque; +} FLT_WND, *PFLT_WND; + +BOOL FloatToolbarCreateToolsGui(PMAIN_WND_INFO Info); +BOOL FloatToolbarCreateColorsGui(PMAIN_WND_INFO Info); +BOOL FloatToolbarCreateHistoryGui(PMAIN_WND_INFO Info); +BOOL InitFloatWndClass(VOID); +VOID UninitFloatWndImpl(VOID); +BOOL ShowHideWindow(HWND hwnd); + +/* font.c */ +VOID FillFontStyleComboList(HWND hwndCombo); +VOID FillFontSizeComboList(HWND hwndCombo); + +/* custcombo.c */ +VOID MakeFlatCombo(HWND hwndCombo); + +#endif /* __IMAGESOFT_PRECOMP_H */ diff --git a/modules/rosapps/applications/imagesoft/res/cursors/PaintBrushToolCursor.cur b/modules/rosapps/applications/imagesoft/res/cursors/PaintBrushToolCursor.cur new file mode 100644 index 00000000000..d4fec205f38 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/cursors/PaintBrushToolCursor.cur differ diff --git a/modules/rosapps/applications/imagesoft/res/cursors/PaintBrushToolCursorMouseDown.cur b/modules/rosapps/applications/imagesoft/res/cursors/PaintBrushToolCursorMouseDown.cur new file mode 100644 index 00000000000..c338fec11be Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/cursors/PaintBrushToolCursorMouseDown.cur differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/color/ColorLess.bmp b/modules/rosapps/applications/imagesoft/res/icons/color/ColorLess.bmp new file mode 100644 index 00000000000..df9d9f32e38 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/color/ColorLess.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/color/ColorMore.bmp b/modules/rosapps/applications/imagesoft/res/icons/color/ColorMore.bmp new file mode 100644 index 00000000000..9020fd895df Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/color/ColorMore.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/hist/HistBack.bmp b/modules/rosapps/applications/imagesoft/res/icons/hist/HistBack.bmp new file mode 100644 index 00000000000..4faa2262710 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/hist/HistBack.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/hist/HistDelete.bmp b/modules/rosapps/applications/imagesoft/res/icons/hist/HistDelete.bmp new file mode 100644 index 00000000000..117ed95d2e9 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/hist/HistDelete.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/hist/HistForward.bmp b/modules/rosapps/applications/imagesoft/res/icons/hist/HistForward.bmp new file mode 100644 index 00000000000..3cc7666c049 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/hist/HistForward.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/hist/HistRedo.bmp b/modules/rosapps/applications/imagesoft/res/icons/hist/HistRedo.bmp new file mode 100644 index 00000000000..b7c7db787df Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/hist/HistRedo.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/hist/HistUndo.bmp b/modules/rosapps/applications/imagesoft/res/icons/hist/HistUndo.bmp new file mode 100644 index 00000000000..da8326e8cf3 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/hist/HistUndo.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainCopyIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainCopyIcon.bmp new file mode 100644 index 00000000000..8ac3547d6e7 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainCopyIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainCutIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainCutIcon.bmp new file mode 100644 index 00000000000..6ffe6fde2d8 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainCutIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainNewIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainNewIcon.bmp new file mode 100644 index 00000000000..e3d27bebd19 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainNewIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainOpenIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainOpenIcon.bmp new file mode 100644 index 00000000000..2114f19176c Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainOpenIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainPasteIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainPasteIcon.bmp new file mode 100644 index 00000000000..1936b3bd0e0 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainPasteIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainPrintIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainPrintIcon.bmp new file mode 100644 index 00000000000..1e50040a4cd Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainPrintIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainPrintPreIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainPrintPreIcon.bmp new file mode 100644 index 00000000000..6ffeafad197 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainPrintPreIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainRedoIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainRedoIcon.bmp new file mode 100644 index 00000000000..b7c7db787df Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainRedoIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainSaveIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainSaveIcon.bmp new file mode 100644 index 00000000000..b9d93cbad2e Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainSaveIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/std/MainUndoIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/std/MainUndoIcon.bmp new file mode 100644 index 00000000000..da8326e8cf3 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/std/MainUndoIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/text/TextAlignCenterIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/text/TextAlignCenterIcon.bmp new file mode 100644 index 00000000000..6392a820d8c Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/text/TextAlignCenterIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/text/TextAlignLeftIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/text/TextAlignLeftIcon.bmp new file mode 100644 index 00000000000..dffc785b9d9 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/text/TextAlignLeftIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/text/TextAlignRightIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/text/TextAlignRightIcon.bmp new file mode 100644 index 00000000000..064f09b5270 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/text/TextAlignRightIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/text/TextBoldIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/text/TextBoldIcon.bmp new file mode 100644 index 00000000000..ffb0b3ab290 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/text/TextBoldIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/text/TextItalicIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/text/TextItalicIcon.bmp new file mode 100644 index 00000000000..604273dd132 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/text/TextItalicIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/text/TextUnderlineIcon.bmp b/modules/rosapps/applications/imagesoft/res/icons/text/TextUnderlineIcon.bmp new file mode 100644 index 00000000000..25de8272d0c Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/text/TextUnderlineIcon.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsCloneStamp.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsCloneStamp.bmp new file mode 100644 index 00000000000..2dceb3b5335 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsCloneStamp.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsColorPicker.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsColorPicker.bmp new file mode 100644 index 00000000000..b7b4f29e47a Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsColorPicker.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsEllipse.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsEllipse.bmp new file mode 100644 index 00000000000..740288ce0bf Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsEllipse.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsEllipseSelect.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsEllipseSelect.bmp new file mode 100644 index 00000000000..76c8d9437df Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsEllipseSelect.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsEraser.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsEraser.bmp new file mode 100644 index 00000000000..05ec19f9889 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsEraser.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsFreeformShape.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsFreeformShape.bmp new file mode 100644 index 00000000000..c6e671b2988 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsFreeformShape.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsLassoSelect.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsLassoSelect.bmp new file mode 100644 index 00000000000..4375d50b7ad Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsLassoSelect.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsLine.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsLine.bmp new file mode 100644 index 00000000000..949615def46 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsLine.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsMagicWand.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsMagicWand.bmp new file mode 100644 index 00000000000..f41bc862879 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsMagicWand.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsMove.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsMove.bmp new file mode 100644 index 00000000000..356149296ad Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsMove.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsMoveSelection.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsMoveSelection.bmp new file mode 100644 index 00000000000..6dbcbe37a61 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsMoveSelection.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsPaintBrush.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsPaintBrush.bmp new file mode 100644 index 00000000000..e5a99eeed82 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsPaintBrush.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsPaintBucket.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsPaintBucket.bmp new file mode 100644 index 00000000000..7359751e428 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsPaintBucket.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsPencil.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsPencil.bmp new file mode 100644 index 00000000000..8f1a4c9171e Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsPencil.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRecoloring.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRecoloring.bmp new file mode 100644 index 00000000000..63b817470af Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRecoloring.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRectangle.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRectangle.bmp new file mode 100644 index 00000000000..8fa788b6a49 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRectangle.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRectangleSelect.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRectangleSelect.bmp new file mode 100644 index 00000000000..1d4975beedb Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRectangleSelect.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRoundedRectangle.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRoundedRectangle.bmp new file mode 100644 index 00000000000..1c360f0be4f Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsRoundedRectangle.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsText.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsText.bmp new file mode 100644 index 00000000000..03943f4fdde Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsText.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsZoom.bmp b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsZoom.bmp new file mode 100644 index 00000000000..2662eafa281 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/icons/tools/ToolsZoom.bmp differ diff --git a/modules/rosapps/applications/imagesoft/res/imagesoft.ico b/modules/rosapps/applications/imagesoft/res/imagesoft.ico new file mode 100644 index 00000000000..7f0af5194c2 Binary files /dev/null and b/modules/rosapps/applications/imagesoft/res/imagesoft.ico differ diff --git a/modules/rosapps/applications/imagesoft/resource.h b/modules/rosapps/applications/imagesoft/resource.h new file mode 100644 index 00000000000..43baef251f9 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/resource.h @@ -0,0 +1,297 @@ +#define IDC_STATIC -1 + +/* Main Windows */ +#define IDC_TOOLBAR 10 +#define IDC_STATUSBAR 11 +#define IDC_MAIN_MDI 12 +/* these need to be kept consecutive */ +#define IDS_FLT_TOOLS 20 +#define IDS_FLT_COLORS 21 +#define IDS_FLT_HISTORY 22 + +/* Program icon */ +#define IDI_IMAGESOFTICON 50 + +/* Menus */ +#define IDR_MAINMENU 102 +#define IDR_POPUP 103 + +/* COMMANDS */ +/* main */ +#define ID_NEW 2000 +#define ID_OPEN 2001 +#define ID_CLOSE 2002 +#define ID_CLOSEALL 2003 +#define ID_SAVE 2004 +#define ID_SAVEAS 2005 +#define ID_PRINTPRE 2006 +#define ID_PRINT 2007 +#define ID_PROP 2008 +#define ID_CUT 2009 +#define ID_COPY 2010 +#define ID_PASTE 2011 +#define ID_PASTENEWIMAGE 2012 +#define ID_UNDO 2013 +#define ID_REDO 2014 +#define ID_SELALL 2015 +#define ID_EXIT 2016 +#define ID_EDITCOLOURS 2017 +#define ID_TOOLS 2018 +#define ID_COLOR 2019 +#define ID_HISTORY 2020 +#define ID_STATUSBAR 2021 +#define ID_BLANK 2022 + +#define ID_BACK 2025 +#define ID_FORWARD 2026 +#define ID_DELETE 2027 + +/* text */ +#define ID_BOLD 2030 +#define ID_ITALIC 2031 +#define ID_ULINE 2032 +#define ID_TXTLEFT 2033 +#define ID_TXTCENTER 2034 +#define ID_TXTRIGHT 2035 +#define ID_TXTFONTNAME 2036 +#define ID_TXTFONTSIZE 2037 + +/* tools */ +#define ID_CLONESTAMP 2050 +#define ID_COLORPICKER 2051 +#define ID_ECLIPSE 2052 +#define ID_ECLIPSESEL 2053 +#define ID_ERASER 2054 +#define ID_FREEFORM 2055 +#define ID_LASOO 2056 +#define ID_LINE 2057 +#define ID_MAGICWAND 2058 +#define ID_MOVE 2059 +#define ID_MOVESEL 2060 +#define ID_PAINTBRUSH 2061 +#define ID_PAINTBUCKET 2062 +#define ID_PENCIL 2063 +#define ID_RECOLORING 2064 +#define ID_RECTANGLE 2065 +#define ID_RECTSEL 2066 +#define ID_ROUNDRECT 2067 +#define ID_TEXT 2068 +#define ID_ZOOM 2069 + +/* Adjust */ +#define ID_BRIGHTNESS 2100 +#define ID_CONTRAST 2101 +#define ID_BLACKANDWHITE 2102 +#define ID_INVERTCOLORS 2103 +#define ID_BLUR 2104 +#define ID_SHARPEN 2105 + +#define ID_ABOUT 2400 + +#define ID_REFRESH 3000 +#define ID_HELP 3001 +#define ID_WINDOW_TILE_HORZ 3002 +#define ID_WINDOW_TILE_VERT 3003 +#define ID_WINDOW_CASCADE 3004 +#define ID_WINDOW_NEXT 3005 +#define ID_WINDOW_ARRANGE 3006 + +/* menu hints */ +#define IDS_HINT_BLANK 20000 +#define IDS_HINT_NEW 20001 +#define IDS_HINT_OPEN 20002 +#define IDS_HINT_CLOSE 21006 +#define IDS_HINT_CLOSEALL 21007 +#define IDS_HINT_SAVE 20003 +#define IDS_HINT_SAVEAS 20004 +#define IDS_HINT_PRINT 20005 +#define IDS_HINT_PRINTPRE 20006 +#define IDS_HINT_PROP 20007 +#define IDS_HINT_EXIT 20008 + +#define IDS_HINT_TOOLS 20020 +#define IDS_HINT_COLORS 20021 +#define IDS_HINT_HISTORY 20022 +#define IDS_HINT_STATUS 20023 + +#define IDS_HINT_CASCADE 21009 +#define IDS_HINT_TILE_HORZ 21010 +#define IDS_HINT_TILE_VERT 21011 +#define IDS_HINT_ARRANGE 21012 +#define IDS_HINT_NEXT 21013 + +/* system menu hints */ +#define IDS_HINT_SYS_RESTORE 21001 +#define IDS_HINT_SYS_MOVE 21002 +#define IDS_HINT_SYS_SIZE 21003 +#define IDS_HINT_SYS_MINIMIZE 21004 +#define IDS_HINT_SYS_MAXIMIZE 21005 +#define IDS_HINT_SYS_CLOSE 21006 + + +/* Toolbar button bitmaps. + * These must be numbered consecutively + * See loop in InitImageList (misc.c) + */ +#define IDB_MAINNEWICON 10000 +#define IDB_MAINOPENICON 10001 +#define IDB_MAINSAVEICON 10002 +#define IDB_MAINPRINTICON 10003 +#define IDB_MAINPRINTPREICON 10004 +#define IDB_MAINCUTICON 10005 +#define IDB_MAINCOPYICON 10006 +#define IDB_MAINPASTEICON 10007 +#define IDB_MAINUNDOICON 10008 +#define IDB_MAINREDOICON 10009 + +#define IDB_TEXTBOLD 10020 +#define IDB_TEXTITALIC 10021 +#define IDB_TEXTULINE 10022 +#define IDB_TEXTLEFT 10023 +#define IDB_TEXTCENTER 10024 +#define IDB_TEXTRIGHT 10025 + +#define IDB_TOOLSRECTSEL 10030 +#define IDB_TOOLSMOVESEL 10031 +#define IDB_TOOLSLASOO 10032 +#define IDB_TOOLSMOVE 10033 +#define IDB_TOOLSECLIPSESEL 10034 +#define IDB_TOOLSZOOM 10035 +#define IDB_TOOLSMAGICWAND 10036 +#define IDB_TOOLSTEXT 10037 +#define IDB_TOOLSPAINTBRUSH 10038 +#define IDB_TOOLSERASER 10039 +#define IDB_TOOLSPENCIL 10040 +#define IDB_TOOLSCOLORPICKER 10041 +#define IDB_TOOLSCLONESTAMP 10042 +#define IDB_TOOLSRECOLORING 10043 +#define IDB_TOOLSPAINTBUCKET 10044 +#define IDB_TOOLSLINE 10045 +#define IDB_TOOLSRECTANGLE 10046 +#define IDB_TOOLSROUNDRECT 10047 +#define IDB_TOOLSECLIPSE 10048 +#define IDB_TOOLSFREEFORM 10049 + +#define IDB_HISTBACK 10060 +#define IDB_HISTUNDO 10061 +#define IDB_HISTREDO 10062 +#define IDB_HISTFORWARD 10063 +#define IDB_HISTDELETE 10064 + +#define IDB_COLORSMORE 10080 +#define IDB_COLORSLESS 10081 + +/* TOOLBAR BITMAPS */ + +/* standard */ +#define TBICON_NEW 0 +#define TBICON_OPEN 1 +#define TBICON_SAVE 2 +#define TBICON_PRINT 3 +#define TBICON_PRINTPRE 4 +#define TBICON_CUT 5 +#define TBICON_COPY 6 +#define TBICON_PASTE 7 +#define TBICON_UNDO 8 +#define TBICON_REDO 9 +/* text */ +#define TBICON_BOLD 0 +#define TBICON_ITALIC 1 +#define TBICON_ULINE 2 +#define TBICON_TXTLEFT 3 +#define TBICON_TXTCENTER 4 +#define TBICON_TXTRIGHT 5 +/* tools */ +#define TBICON_RECTSEL 0 +#define TBICON_MOVESEL 1 +#define TBICON_LASOO 2 +#define TBICON_MOVE 3 +#define TBICON_ECLIPSESEL 4 +#define TBICON_ZOOM 5 +#define TBICON_MAGICWAND 6 +#define TBICON_TEXT 7 +#define TBICON_PAINTBRUSH 8 +#define TBICON_ERASER 9 +#define TBICON_PENCIL 10 +#define TBICON_COLORPICKER 11 +#define TBICON_CLONESTAMP 12 +#define TBICON_RECOLORING 13 +#define TBICON_PAINTBUCKET 14 +#define TBICON_LINE 15 +#define TBICON_RECTANGLE 16 +#define TBICON_ROUNDRECT 17 +#define TBICON_ECLIPSE 18 +#define TBICON_FREEFORM 19 +/* history */ +#define TBICON_BACKSM 0 +#define TBICON_UNDOSM 1 +#define TBICON_REDOSM 2 +#define TBICON_FORWARDSM 3 +#define TBICON_DELETESM 4 + + +/* tooltips */ +#define IDS_TOOLTIP_NEW 6000 +#define IDS_TOOLTIP_OPEN 6001 +#define IDS_TOOLTIP_SAVE 6002 +#define IDS_TOOLTIP_PRINTPRE 6003 +#define IDS_TOOLTIP_PRINT 6004 +#define IDS_TOOLTIP_CUT 6005 +#define IDS_TOOLTIP_COPY 6006 +#define IDS_TOOLTIP_PASTE 6007 +#define IDS_TOOLTIP_UNDO 6008 +#define IDS_TOOLTIP_REDO 6009 + +/* cursors */ +#define IDC_PAINTBRUSHCURSOR 20001 +#define IDC_PAINTBRUSHCURSORMOUSEDOWN 20002 + + +/* DIALOGS */ +#define IDC_PICPREVIEW 2999 + +/* brightness dialog */ +#define IDD_BRIGHTNESS 3000 +#define IDC_BRI_GROUP 3001 +#define IDC_BRI_FULL 3002 +#define IDC_BRI_RED 3003 +#define IDC_BRI_GREEN 3004 +#define IDC_BRI_BLUE 3005 +#define IDC_BRI_EDIT 3006 +#define IDC_BRI_TRACKBAR 3007 + +/* image property dialog */ +#define IDD_IMAGE_PROP 4000 +#define IDC_IMAGE_NAME_EDIT 4001 +#define IDC_IMAGETYPE 4003 +#define IDC_WIDTH_EDIT 4004 +#define IDC_WIDTH_STAT 4005 +#define IDC_HEIGHT_EDIT 4006 +#define IDC_HEIGHT_STAT 4007 +#define IDC_RES_EDIT 4008 +#define IDC_RES_STAT 4009 +#define IDC_UNIT 4010 +#define IDC_IMAGE_SIZE 4011 +#define IDS_IMAGE_MONOCHROME 4100 +#define IDS_IMAGE_GREYSCALE 4101 +#define IDS_IMAGE_PALETTE 4102 +#define IDS_IMAGE_TRUECOLOR 4103 +#define IDS_UNIT_CM 4104 +#define IDS_UNIT_INCHES 4105 +#define IDS_UNIT_PIXELS 4106 +#define IDS_UNIT_DOTSCM 4107 +#define IDS_UNIT_DPI 4108 +#define IDS_UNIT_MB 4109 +#define IDS_UNIT_KB 4110 + +/* about box info */ +#define IDD_ABOUTBOX 4200 +#define IDC_LICENSE_EDIT 4201 +#define IDS_APPNAME 4202 +#define IDS_VERSION 4203 +#define IDS_LICENSE 4204 +#define IDS_READY 42050 +#define IDS_TOOLBAR_STANDARD 4206 +#define IDS_TOOLBAR_TEST 4207 +#define IDS_TOOLBAR_TEXT 4205 +#define IDS_IMAGE_NAME 4209 diff --git a/modules/rosapps/applications/imagesoft/rsrc.rc b/modules/rosapps/applications/imagesoft/rsrc.rc new file mode 100644 index 00000000000..e7b3a382145 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/rsrc.rc @@ -0,0 +1,45 @@ +#include +#include "resource.h" + +/* include localised resources */ +// UTF-8 +#pragma code_page(65001) +#ifdef LANGUAGE_BG_BG + #include "lang/bg-BG.rc" +#endif +#ifdef LANGUAGE_EN_GB + #include "lang/en-GB.rc" +#endif +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif +#ifdef LANGUAGE_ES_ES + #include "lang/es-ES.rc" +#endif +#ifdef LANGUAGE_FR_FR + #include "lang/fr-FR.rc" +#endif +#ifdef LANGUAGE_ID_ID + #include "lang/id-ID.rc" +#endif +#ifdef LANGUAGE_IT_IT + #include "lang/it-IT.rc" +#endif +#ifdef LANGUAGE_NO_NO + #include "lang/no-NO.rc" +#endif +#ifdef LANGUAGE_PL_PL + #include "lang/pl-PL.rc" +#endif +#ifdef LANGUAGE_RU_RU + #include "lang/ru-RU.rc" +#endif +#ifdef LANGUAGE_SK_SK + #include "lang/sk-SK.rc" +#endif +#ifdef LANGUAGE_TH_TH + #include "lang/th-TH.rc" +#endif +#ifdef LANGUAGE_UK_UA + #include "lang/uk-UA.rc" +#endif diff --git a/modules/rosapps/applications/imagesoft/tooldock.c b/modules/rosapps/applications/imagesoft/tooldock.c new file mode 100644 index 00000000000..84c513b27a4 --- /dev/null +++ b/modules/rosapps/applications/imagesoft/tooldock.c @@ -0,0 +1,1138 @@ +#include + +static const TCHAR szToolDockWndClass[] = TEXT("ImageSoftToolDockWndClass"); + +typedef struct _TOOLDOCKWND_INIT +{ + PTOOLBAR_DOCKS TbDocks; + PDOCKBAR_ITEM Item; +} TOOLDOCKWND_INIT, *PTOOLDOCKWND_INIT; + +static UINT +TbdCalculateInsertIndex(PTOOLBAR_DOCKS TbDocks, + DOCK_POSITION Position, + POINT pt) +{ + RECT rcRebar; + UINT Ret = 0; + + GetWindowRect(TbDocks->hRebar[Position], + &rcRebar); + + switch (Position) + { + case TOP_DOCK: + case BOTTOM_DOCK: + if (pt.y > rcRebar.top + ((rcRebar.bottom - rcRebar.top) / 2)) + Ret = (UINT)-1; + break; + + case LEFT_DOCK: + case RIGHT_DOCK: + if (pt.x > rcRebar.left + ((rcRebar.right - rcRebar.left) / 2)) + Ret = (UINT)-1; + break; + + default: + break; + } + + return Ret; +} + +INT +TbdAdjustUpdateClientRect(PTOOLBAR_DOCKS TbDocks, + PRECT rcClient) +{ + INT i, DocksVisible = 0; + + for (i = 0; i < DOCKS_COUNT; i++) + { + if (TbDocks->hRebar[i] != NULL) + { + DocksVisible++; + } + } + + if (DocksVisible != 0) + { + rcClient->top += TbDocks->rcRebar[TOP_DOCK].bottom; + rcClient->left += TbDocks->rcRebar[LEFT_DOCK].right; + rcClient->right -= TbDocks->rcRebar[RIGHT_DOCK].right; + rcClient->bottom -= TbDocks->rcRebar[BOTTOM_DOCK].bottom; + } + + TbDocks->rcClient = *rcClient; + + return DocksVisible; +} + +HDWP +TbdDeferDocks(HDWP hWinPosInfo, + PTOOLBAR_DOCKS TbDocks) +{ + LONG cx, cy; + HDWP hRet = hWinPosInfo; + + cx = TbDocks->rcClient.right - TbDocks->rcClient.left; + cy = TbDocks->rcClient.bottom - TbDocks->rcClient.top; + + /* Top dock */ + if (TbDocks->hRebar[TOP_DOCK] != NULL) + { + hRet = DeferWindowPos(hRet, + TbDocks->hRebar[TOP_DOCK], + NULL, + TbDocks->rcClient.left - TbDocks->rcRebar[LEFT_DOCK].right, + TbDocks->rcClient.top - TbDocks->rcRebar[TOP_DOCK].bottom, + cx + TbDocks->rcRebar[LEFT_DOCK].right + TbDocks->rcRebar[RIGHT_DOCK].right, + TbDocks->rcRebar[TOP_DOCK].bottom, + SWP_NOZORDER); + if (hRet == NULL) + return NULL; + } + + /* Left dock */ + if (TbDocks->hRebar[LEFT_DOCK] != NULL) + { + hRet = DeferWindowPos(hRet, + TbDocks->hRebar[LEFT_DOCK], + NULL, + TbDocks->rcClient.left - TbDocks->rcRebar[LEFT_DOCK].right, + TbDocks->rcClient.top, + TbDocks->rcRebar[LEFT_DOCK].right, + cy, + SWP_NOZORDER); + if (hRet == NULL) + return NULL; + } + + /* Right dock */ + if (TbDocks->hRebar[RIGHT_DOCK] != NULL) + { + hRet = DeferWindowPos(hRet, + TbDocks->hRebar[RIGHT_DOCK], + NULL, + TbDocks->rcClient.right, + TbDocks->rcClient.top, + TbDocks->rcRebar[RIGHT_DOCK].right, + cy, + SWP_NOZORDER); + if (hRet == NULL) + return NULL; + } + + /* Bottom dock */ + if (TbDocks->hRebar[BOTTOM_DOCK] != NULL) + { + hRet = DeferWindowPos(hRet, + TbDocks->hRebar[BOTTOM_DOCK], + NULL, + TbDocks->rcClient.left - TbDocks->rcRebar[LEFT_DOCK].right, + TbDocks->rcClient.bottom, + cx + TbDocks->rcRebar[LEFT_DOCK].right + TbDocks->rcRebar[RIGHT_DOCK].right, + TbDocks->rcRebar[BOTTOM_DOCK].bottom, + SWP_NOZORDER); + if (hRet == NULL) + return NULL; + } + + return hRet; +} + +static PDOCKBAR_ITEM +TbnDockbarItemFromBandId(PTOOLBAR_DOCKS TbDocks, + DOCK_POSITION Position, + UINT uBand) +{ + REBARBANDINFO rbi = {0}; + + rbi.cbSize = sizeof(rbi); + rbi.fMask = RBBIM_LPARAM; + + if (SendMessage(TbDocks->hRebar[Position], + RB_GETBANDINFO, + (WPARAM)uBand, + (LPARAM)&rbi)) + { + return (PDOCKBAR_ITEM)rbi.lParam; + } + + return NULL; +} + +static VOID +TbnRebarChangeSize(PTOOLBAR_DOCKS TbDocks, + DOCK_POSITION Position) +{ + LONG cRebar; + + TbDocks->rcRebar[Position].left = 0; + TbDocks->rcRebar[Position].top = 0; + + cRebar = (LONG)SendMessage(TbDocks->hRebar[Position], + RB_GETBARHEIGHT, + 0, + 0); + + switch (Position) + { + case TOP_DOCK: + case BOTTOM_DOCK: + TbDocks->rcRebar[Position].bottom = cRebar; + break; + + case LEFT_DOCK: + case RIGHT_DOCK: + TbDocks->rcRebar[Position].right = cRebar; + break; + + default: + break; + } + + if (TbDocks->ParentResize != NULL) + { + RECT rcClient = {0}; + + GetClientRect(TbDocks->hParent, + &rcClient); + + TbDocks->ParentResize(TbDocks->Context, + rcClient.right - rcClient.left, + rcClient.bottom - rcClient.top); + } +} + +static VOID +TbnRebarChevronPushed(PTOOLBAR_DOCKS TbDocks, + DOCK_POSITION Position, + LPNMREBARCHEVRON lpnm) +{ + PDOCKBAR_ITEM Item; + + Item = TbnDockbarItemFromBandId(TbDocks, + Position, + lpnm->uBand); + + if (Item != NULL && Item->Callbacks->ChevronPushed) + { + Item->Callbacks->ChevronPushed(TbDocks, + &Item->DockBar, + Item->Context, + Item->hWndClient, + lpnm); + } +} + +static LRESULT +TbnRebarBeginDrag(PTOOLBAR_DOCKS TbDocks, + DOCK_POSITION Position, + LPNMREBAR lpnmrb) +{ + PDOCKBAR_ITEM Item; + + Item = TbnDockbarItemFromBandId(TbDocks, + Position, + lpnmrb->uBand); + + if (Item != NULL) + { + TbDocks->Dragging = Item; + TbDocks->DraggingBandId = lpnmrb->wID; + return FALSE; + } + + return TRUE; +} + +static VOID +TbnRebarEndDrag(PTOOLBAR_DOCKS TbDocks, + DOCK_POSITION Position, + LPNMREBAR lpnmrb) +{ + PDOCKBAR_ITEM Item; + + Item = TbnDockbarItemFromBandId(TbDocks, + Position, + lpnmrb->uBand); + + if (Item != NULL) + { + /* Nothing to do */ + } +} + +BOOL +TbdDockBarIdFromClientWindow(PTOOLBAR_DOCKS TbDocks, + HWND hWndClient, + UINT *Id) +{ + PDOCKBAR_ITEM Item; + BOOL Ret = FALSE; + + Item = TbDocks->Items; + while (Item != NULL) + { + if (Item->hWndClient == hWndClient) + { + *Id = Item->DockBar.BarId; + Ret = TRUE; + break; + } + + Item = Item->Next; + } + + return Ret; +} + +BOOL +TbdHandleNotifications(PTOOLBAR_DOCKS TbDocks, + LPNMHDR pnmh, + LRESULT *Result) +{ + BOOL Handled = FALSE; + + if (pnmh->hwndFrom != NULL) + { + DOCK_POSITION Position; + + for (Position = TOP_DOCK; Position < NO_DOCK; Position++) + { + if (pnmh->hwndFrom == TbDocks->hRebar[Position]) + { + switch (pnmh->code) + { + case RBN_HEIGHTCHANGE: + { + TbnRebarChangeSize(TbDocks, + Position); + break; + } + + case RBN_BEGINDRAG: + { + *Result = TbnRebarBeginDrag(TbDocks, + Position, + (LPNMREBAR)pnmh); + break; + } + + case RBN_ENDDRAG: + { + TbnRebarEndDrag(TbDocks, + Position, + (LPNMREBAR)pnmh); + break; + } + + case RBN_CHEVRONPUSHED: + { + TbnRebarChevronPushed(TbDocks, + Position, + (LPNMREBARCHEVRON)pnmh); + break; + } + } + + Handled = TRUE; + break; + } + } + } + + return Handled; +} + +static BOOL +TbdCreateToolbarWnd(PTOOLBAR_DOCKS TbDocks, + PDOCKBAR_ITEM Item, + DOCK_POSITION PrevPosition, + UINT PrevBandIndex, + LPREBARBANDINFO rbi, + POINT pt, + HWND hRebar, + UINT uBand, + BOOL Drag) +{ + LPCTSTR lpCaption = NULL; + TOOLDOCKWND_INIT Init; + HWND hToolbar; + + Init.TbDocks = TbDocks; + Init.Item = Item; + + if (rbi->fMask & RBBIM_TEXT) + { + lpCaption = rbi->lpText; + } + + Item->Callbacks->DockBand(TbDocks, + &Item->DockBar, + Item->Context, + PrevPosition, + NO_DOCK, + rbi); + + if (rbi->fMask & RBBIM_CHILD) + Item->hWndClient = rbi->hwndChild; + else + Item->hWndClient = NULL; + + + if ((rbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) == (RBBIM_CHILDSIZE | RBBIM_SIZE)) + { + RECT rcWnd; + static const DWORD dwStyle = WS_POPUPWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DLGFRAME; + static const DWORD dwExStyle = WS_EX_TOOLWINDOW; + + rcWnd.left = pt.x - GetSystemMetrics(SM_CXFIXEDFRAME) - (GetSystemMetrics(SM_CYSMCAPTION) / 2); + rcWnd.top = pt.y + GetSystemMetrics(SM_CYFIXEDFRAME) + (GetSystemMetrics(SM_CYSMCAPTION) / 2); + rcWnd.right = rcWnd.left + rbi->cx; + rcWnd.bottom = rcWnd.top + rbi->cyMinChild; + + if (AdjustWindowRectEx(&rcWnd, + dwStyle, + FALSE, + dwExStyle)) + { + hToolbar = CreateWindowEx(dwExStyle, + szToolDockWndClass, + lpCaption, + dwStyle, + rcWnd.left, + rcWnd.top, + rcWnd.right - rcWnd.left, + rcWnd.bottom - rcWnd.top, + TbDocks->hParent, + NULL, + hInstance, + &Init); + if (hToolbar != NULL) + { + RECT rcClient; + + if (uBand != (UINT)-1) + { + /* delete the band before showing the client window, + otherwise deleting the band will cause the client + window to be hidden, regardless of whether the band + was hidden before being deleted or not */ + SendMessage(hRebar, + RB_DELETEBAND, + (WPARAM)uBand, + 0); + } + + if (Item->hWndClient != NULL) + { + GetClientRect(hToolbar, + &rcClient); + + SetParent(Item->hWndClient, + hToolbar); + + SetWindowPos(Item->hWndClient, + NULL, + 0, + 0, + rcClient.right, + rcClient.bottom, + SWP_NOZORDER); + + SetWindowPos(Item->hWndClient, + HWND_TOP, + 0, + 0, + 0, + 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + } + + SetWindowPos(hToolbar, + HWND_TOP, + 0, + 0, + 0, + 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + + if (Drag) + { + SetCursor(LoadCursor(NULL, IDC_ARROW)); + SendMessage(hToolbar, + WM_NCLBUTTONDOWN, + HTCAPTION, + MAKELPARAM(pt.x, + pt.y)); + } + + return TRUE; + } + } + } + + return FALSE; +} + +static BOOL +TdbInsertToolbar(PTOOLBAR_DOCKS TbDocks, + PDOCKBAR_ITEM Item, + DOCK_POSITION Position) +{ + LPTSTR lpCaption = NULL; + REBARBANDINFO rbi = {0}; + BOOL Ret = FALSE; + + rbi.cbSize = sizeof(rbi); + rbi.fMask = RBBIM_ID | RBBIM_STYLE | RBBIM_LPARAM; + rbi.wID = Item->DockBar.BarId; + rbi.fStyle = RBBS_GRIPPERALWAYS; + rbi.lParam = (LPARAM)Item; + + if (Item->DockBar.DisplayTextId != 0) + { + if (AllocAndLoadString(&lpCaption, + hInstance, + Item->DockBar.DisplayTextId)) + { + rbi.fMask |= RBBIM_TEXT; + rbi.lpText = lpCaption; + } + } + + if (Item->hWndClient != NULL) + { + rbi.fMask |= RBBIM_CHILD; + rbi.hwndChild = Item->hWndClient; + } + + switch (Item->DockBar.Position) + { + case NO_DOCK: + { + POINT pt = {0}; + + /* FIXME - calculate size */ + Ret = TbdCreateToolbarWnd(TbDocks, + Item, + Item->DockBar.Position, + (UINT)-1, + &rbi, + pt, + NULL, + (UINT)-1, + FALSE); + break; + } + + default: + { + UINT Index = -1; + BOOL AddBand = TRUE; + + if (Item->Callbacks->InsertBand != NULL) + { + AddBand = Item->Callbacks->InsertBand(TbDocks, + &Item->DockBar, + Item->Context, + &Index, + &rbi); + } + + if (AddBand) + { + Item->Callbacks->DockBand(TbDocks, + &Item->DockBar, + Item->Context, + NO_DOCK, + Item->DockBar.Position, + &rbi); + + if (rbi.fMask & RBBIM_CHILD) + Item->hWndClient = rbi.hwndChild; + else + Item->hWndClient = NULL; + + Ret = SendMessage(TbDocks->hRebar[Position], + RB_INSERTBAND, + (WPARAM)Index, + (LPARAM)&rbi) != 0; + if (Ret) + { + Item->PrevDock = Position; + Item->PrevBandIndex = (UINT)SendMessage(TbDocks->hRebar[Position], + RB_IDTOINDEX, + (WPARAM)Item->DockBar.BarId, + 0); + } + } + + break; + } + } + + if (lpCaption != NULL) + { + LocalFree((HLOCAL)lpCaption); + } + + return Ret; +} + +BOOL +TbdAddToolbar(PTOOLBAR_DOCKS TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + const DOCKBAR_ITEM_CALLBACKS *Callbacks) +{ + PDOCKBAR_ITEM Item; + HWND hRebar; + + hRebar = TbDocks->hRebar[Dockbar->Position]; + if (hRebar != NULL) + { + Item = HeapAlloc(ProcessHeap, + 0, + sizeof(DOCKBAR_ITEM)); + if (Item != NULL) + { + /* Initialize the item */ + Item->DockBar = *Dockbar; + Item->Context = Context; + Item->hWndTool = NULL; + Item->PrevDock = Dockbar->Position; + + Item->Callbacks = Callbacks; + + /* Create the client control */ + if (Callbacks->CreateClient != NULL && + !Callbacks->CreateClient(TbDocks, + &Item->DockBar, + Context, + hRebar, + &Item->hWndClient)) + { + HeapFree(ProcessHeap, + 0, + Item); + + return FALSE; + } + + /* Insert the item into the list */ + Item->Next = TbDocks->Items; + TbDocks->Items = Item; + + return TdbInsertToolbar(TbDocks, + Item, + Dockbar->Position); + } + } + + return FALSE; +} + +#define GWLP_TBDOCKS 0 +#define GWLP_DOCKITEM (GWLP_TBDOCKS + sizeof(PTOOLBAR_DOCKS)) +#define TD_EXTRA_BYTES (GWLP_DOCKITEM + sizeof(PDOCKBAR_ITEM)) + +static LRESULT CALLBACK +ToolDockWndProc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + PTOOLBAR_DOCKS TbDocks; + PDOCKBAR_ITEM Item; + LRESULT Ret = 0; + + /* Get the window context */ + TbDocks = (PTOOLBAR_DOCKS)GetWindowLongPtr(hwnd, + GWLP_TBDOCKS); + Item = (PDOCKBAR_ITEM)GetWindowLongPtr(hwnd, + GWLP_DOCKITEM); + + if ((TbDocks == NULL || Item == NULL) && uMsg != WM_CREATE) + { + goto HandleDefaultMessage; + } + + switch (uMsg) + { + case WM_NCACTIVATE: + { + TbdHandleActivation(TbDocks, + hwnd, + &wParam, + &lParam); + goto HandleDefaultMessage; + } + + case WM_CREATE: + { + TbDocks = ((PTOOLDOCKWND_INIT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->TbDocks; + Item = ((PTOOLDOCKWND_INIT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->Item; + Item->hWndTool = hwnd; + + SetWindowLongPtr(hwnd, + GWLP_TBDOCKS, + (LONG_PTR)TbDocks); + SetWindowLongPtr(hwnd, + GWLP_DOCKITEM, + (LONG_PTR)Item); + + Ret = TRUE; + break; + } + + case WM_DESTROY: + { + Item->hWndTool = NULL; + + SetWindowLongPtr(hwnd, + GWLP_USERDATA, + 0); + SetWindowLongPtr(hwnd, + GWLP_DOCKITEM, + 0); + break; + } + + default: + { +HandleDefaultMessage: + Ret = DefWindowProc(hwnd, + uMsg, + wParam, + lParam); + break; + } + } + + return Ret; +} + +static LRESULT CALLBACK +RebarSubclassProc(HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam, + UINT_PTR uIdSubclass, + DWORD_PTR dwRefData) +{ + LRESULT Ret; + + Ret = DefSubclassProc(hWnd, + uMsg, + wParam, + lParam); + + if (uMsg == WM_MOUSEMOVE && (wParam & MK_LBUTTON)) + { + DOCK_POSITION Position, DragTo = NO_DOCK; + RECT rcClient; + POINT pt; + PTOOLBAR_DOCKS TbDocks = (PTOOLBAR_DOCKS)dwRefData; + SIZE szTearOff; + + szTearOff.cx = GetSystemMetrics(SM_CXCURSOR); + szTearOff.cy = GetSystemMetrics(SM_CYCURSOR); + + /* + * Check if we're dragging and if it's time to remove the band + */ + if (TbDocks->Dragging != NULL && GetCapture() == hWnd) + { + GetClientRect(hWnd, + &rcClient); + InflateRect(&rcClient, + szTearOff.cx, + szTearOff.cy); + + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + + if (!PtInRect(&rcClient, + pt)) + { + REBARBANDINFO rbi; + UINT uBand; + RECT rc; + + /* Save all rebar band information, don't query RBBIM_HEADERSIZE because it + seems to cause problems with toolbars*/ + rbi.cbSize = sizeof(rbi); + rbi.fMask = RBBIM_BACKGROUND | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_COLORS | + RBBIM_IDEALSIZE | RBBIM_ID | RBBIM_IMAGE | RBBIM_LPARAM | RBBIM_SIZE | + RBBIM_STYLE | RBBIM_TEXT; + rbi.lpText = TbDocks->szTempText; + rbi.cch = sizeof(TbDocks->szTempText); + + uBand = (UINT)SendMessage(hWnd, + RB_IDTOINDEX, + (WPARAM)TbDocks->DraggingBandId, + 0); + + if (uBand != (UINT)-1 && + SendMessage(hWnd, + RB_GETBANDINFO, + (WPARAM)uBand, + (LPARAM)&rbi)) + { + MapWindowPoints(hWnd, + HWND_DESKTOP, + &pt, + 1); + + /* Check if the user is trying to drag it into another dock */ + for (Position = TOP_DOCK; Position < NO_DOCK; Position++) + { + if (TbDocks->hRebar[Position] != NULL && + TbDocks->hRebar[Position] != hWnd && + GetWindowRect(TbDocks->hRebar[Position], + &rc)) + { + InflateRect(&rc, + szTearOff.cx, + szTearOff.cy); + + if (PtInRect(&rc, + pt)) + { + DragTo = Position; + break; + } + } + } + + /* Get the current dock */ + for (Position = TOP_DOCK; Position < NO_DOCK; Position++) + { + if (TbDocks->hRebar[Position] == hWnd) + { + break; + } + } + + ReleaseCapture(); + + if (SendMessage(hWnd, + RB_SHOWBAND, + (WPARAM)uBand, + FALSE)) + { + /* Change the parent to the new rebar control */ + if (TbDocks->Dragging->hWndClient != NULL) + { + SetWindowPos(TbDocks->Dragging->hWndClient, + NULL, + 0, + 0, + 0, + 0, + SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER); + + SetParent(TbDocks->Dragging->hWndClient, + TbDocks->hRebar[DragTo]); + + SetWindowPos(TbDocks->Dragging->hWndClient, + NULL, + 0, + 0, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER); + } + + if (DragTo == NO_DOCK) + { + if (!TbdCreateToolbarWnd(TbDocks, + TbDocks->Dragging, + Position, + uBand, + &rbi, + pt, + hWnd, + uBand, + TRUE)) + { + goto MoveFailed; + } + } + else + { + BOOL Moved = FALSE; + + /* Remove the band from the current rebar control */ + if (SendMessage(hWnd, + RB_DELETEBAND, + (WPARAM)uBand, + 0)) + { + UINT uIndex; + + /* Calculate where to insert the new bar */ + uIndex = TbdCalculateInsertIndex(TbDocks, + DragTo, + pt); + + SetActiveWindow(TbDocks->hRebar[DragTo]); + + TbDocks->Dragging->Callbacks->DockBand(TbDocks, + &TbDocks->Dragging->DockBar, + TbDocks->Dragging->Context, + Position, + DragTo, + &rbi); + + if (rbi.fMask & RBBIM_CHILD) + TbDocks->Dragging->hWndClient = rbi.hwndChild; + else + TbDocks->Dragging->hWndClient = NULL; + + /* Insert the toolbar into the new rebar */ + rbi.fMask |= RBBIM_STYLE; + rbi.fStyle |= RBBS_HIDDEN; + if (SendMessage(TbDocks->hRebar[DragTo], + RB_INSERTBAND, + (WPARAM)uIndex, + (LPARAM)&rbi)) + { + uBand = (UINT)SendMessage(TbDocks->hRebar[DragTo], + RB_IDTOINDEX, + (WPARAM)TbDocks->DraggingBandId, + 0); + + SendMessage(TbDocks->hRebar[DragTo], + RB_SHOWBAND, + (WPARAM)uBand, + TRUE); + + /* Simulate a mouse click to continue dragging */ + if (uBand != (UINT)-1 && + TbDocks->Dragging->hWndClient != NULL && + GetWindowRect(TbDocks->Dragging->hWndClient, + &rc)) + { + switch (DragTo) + { + case LEFT_DOCK: + case RIGHT_DOCK: + pt.x = rc.left + ((rc.right - rc.left) / 2); + pt.y = rc.top - 1; + break; + + default: + pt.x = rc.left - 1; + pt.y = rc.top + ((rc.bottom - rc.top) / 2); + break; + } + + MapWindowPoints(HWND_DESKTOP, + TbDocks->hRebar[DragTo], + &pt, + 1); + + SetCursor(LoadCursor(NULL, IDC_SIZEALL)); + + SendMessage(TbDocks->hRebar[DragTo], + WM_LBUTTONDOWN, + wParam, + MAKELPARAM(pt.x, + pt.y)); + + Moved = TRUE; + } + } + } + + if (!Moved) + { +MoveFailed: + TbDocks->Dragging = NULL; + + SendMessage(hWnd, + RB_SHOWBAND, + (WPARAM)uBand, + TRUE); + } + } + } + } + } + } + } + + return Ret; +} + +VOID +TbdHandleEnabling(PTOOLBAR_DOCKS TbDocks, + HWND hWnd, + BOOL Enable) +{ + PDOCKBAR_ITEM Item; + + Item = TbDocks->Items; + while (Item != NULL) + { + if (Item->hWndTool != NULL && + Item->hWndTool != hWnd) + { + EnableWindow(Item->hWndTool, + Enable); + } + Item = Item->Next; + } +} + +VOID +TbdHandleActivation(PTOOLBAR_DOCKS TbDocks, + HWND hWnd, + WPARAM *wParam, + LPARAM *lParam) +{ + BOOL SynchronizeSiblings = TRUE; + BOOL KeepActive = *(BOOL*)wParam; + HWND hWndActivate = *(HWND*)lParam; + PDOCKBAR_ITEM Item; + + Item = TbDocks->Items; + while (Item != NULL) + { + if (Item->hWndTool != NULL && + Item->hWndTool == hWndActivate) + { + KeepActive = TRUE; + SynchronizeSiblings = FALSE; + break; + } + Item = Item->Next; + } + + if (hWndActivate != (HWND)-1) + { + if (SynchronizeSiblings) + { + Item = TbDocks->Items; + while (Item != NULL) + { + if (Item->hWndTool != NULL && + Item->hWndTool != hWnd && + Item->hWndTool != hWndActivate) + { + SendMessage(Item->hWndTool, + WM_NCACTIVATE, + (WPARAM)KeepActive, + (LPARAM)-1); + } + Item = Item->Next; + } + } + } + else + *lParam = 0; + + *wParam = (WPARAM)KeepActive; +} + +VOID +TbdShowFloatingToolbars(PTOOLBAR_DOCKS TbDocks, + BOOL Show) +{ + PDOCKBAR_ITEM Item; + + Item = TbDocks->Items; + while (Item != NULL) + { + if (Item->hWndTool != NULL) + { + if ((Show && !IsWindowVisible(Item->hWndTool)) || + (!Show && IsWindowVisible(Item->hWndTool))) + { + ShowWindow(Item->hWndTool, + (Show ? SW_SHOW : SW_HIDE)); + } + } + Item = Item->Next; + } +} + +VOID +TbdInitializeDocks(PTOOLBAR_DOCKS TbDocks, + HWND hWndParent, + PVOID Context, + PDOCKBAR_PARENTRESIZE ParentResizeProc) +{ + DWORD rbStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | + CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NOMOVEY | CCS_NOMOVEX | + RBS_VARHEIGHT | RBS_AUTOSIZE; + + DOCK_POSITION Position; + + TbDocks->hParent = hWndParent; + TbDocks->Context = Context; + TbDocks->ParentResize = ParentResizeProc; + + for (Position = TOP_DOCK; Position < NO_DOCK; Position++) + { + switch (Position) + { + case LEFT_DOCK: + case RIGHT_DOCK: + rbStyle |= CCS_VERT; + break; + default: + rbStyle &= ~CCS_VERT; + break; + } + + TbDocks->hRebar[Position] = CreateWindowEx(WS_EX_TOOLWINDOW, + REBARCLASSNAME, + NULL, + rbStyle, + 0, + 0, + 0, + 0, + TbDocks->hParent, + NULL, + hInstance, + NULL); + + if (TbDocks->hRebar[Position] != NULL) + { + SetWindowSubclass(TbDocks->hRebar[Position], + RebarSubclassProc, + 1, + (DWORD_PTR)TbDocks); + } + } +} + +BOOL +TbdInitImpl(VOID) +{ + WNDCLASSEX wc = {0}; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = ToolDockWndProc; + wc.cbWndExtra = TD_EXTRA_BYTES; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, + IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wc.lpszClassName = szToolDockWndClass; + + return RegisterClassEx(&wc) != (ATOM)0; +} + +VOID +TbdUninitImpl(VOID) +{ + UnregisterClass(szToolDockWndClass, + hInstance); +} diff --git a/modules/rosapps/applications/imagesoft/tooldock.h b/modules/rosapps/applications/imagesoft/tooldock.h new file mode 100644 index 00000000000..f96c8c7257c --- /dev/null +++ b/modules/rosapps/applications/imagesoft/tooldock.h @@ -0,0 +1,115 @@ + +typedef enum +{ + TOP_DOCK = 0, + LEFT_DOCK, + RIGHT_DOCK, + BOTTOM_DOCK, + NO_DOCK +} DOCK_POSITION; + +typedef struct _DOCKBAR +{ + UINT BarId; + LPCTSTR lpName; + UINT DisplayTextId; + DOCK_POSITION Position; +} DOCKBAR, *PDOCKBAR; + +struct _TOOLBAR_DOCKS; + +typedef BOOL (CALLBACK *PDOCKBAR_CREATECLIENT)(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + HWND hParent, + HWND *hwnd); +typedef BOOL (CALLBACK *PDOCKBAR_DESTROYCLIENT)(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + HWND hwnd); +typedef BOOL (CALLBACK *PDOCKBAR_INSERTBAND)(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + UINT *Index, + LPREBARBANDINFO rbi); +typedef VOID (CALLBACK *PDOCKBAR_DOCKBAND)(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + DOCK_POSITION DockFrom, + DOCK_POSITION DockTo, + LPREBARBANDINFO rbi); +typedef VOID (CALLBACK *PDOCKBAR_CHEVRONPUSHED)(struct _TOOLBAR_DOCKS *TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + HWND hwndChild, + LPNMREBARCHEVRON lpnm); + +typedef struct _DOCKBAR_ITEM_CALLBACKS +{ + PDOCKBAR_CREATECLIENT CreateClient; + PDOCKBAR_DESTROYCLIENT DestroyClient; + PDOCKBAR_INSERTBAND InsertBand; + PDOCKBAR_DOCKBAND DockBand; + PDOCKBAR_CHEVRONPUSHED ChevronPushed; +} DOCKBAR_ITEM_CALLBACKS, *PDOCKBAR_ITEM_CALLBACKS; + +typedef struct _DOCKBAR_ITEM +{ + struct _DOCKBAR_ITEM *Next; + DOCKBAR DockBar; + PVOID Context; + HWND hWndTool; + HWND hWndClient; + DOCK_POSITION PrevDock; + UINT PrevBandIndex; + const DOCKBAR_ITEM_CALLBACKS *Callbacks; +} DOCKBAR_ITEM, *PDOCKBAR_ITEM; + +typedef VOID (CALLBACK *PDOCKBAR_PARENTRESIZE)(PVOID Context, + LONG cx, + LONG cy); + +#define DOCKS_COUNT 4 +typedef struct _TOOLBAR_DOCKS +{ + HWND hParent; + PVOID Context; + HWND hRebar[DOCKS_COUNT]; + RECT rcRebar[DOCKS_COUNT]; + RECT rcClient; + PDOCKBAR_ITEM Items; + PDOCKBAR_PARENTRESIZE ParentResize; + PDOCKBAR_ITEM Dragging; + UINT DraggingBandId; + TCHAR szTempText[255]; +} TOOLBAR_DOCKS, *PTOOLBAR_DOCKS; + +VOID TbdInitializeDocks(PTOOLBAR_DOCKS TbDocks, + HWND hWndParent, + PVOID Context, + PDOCKBAR_PARENTRESIZE ParentResizeProc); +INT TbdAdjustUpdateClientRect(PTOOLBAR_DOCKS TbDocks, + PRECT rcClient); +HDWP TbdDeferDocks(HDWP hWinPosInfo, + PTOOLBAR_DOCKS TbDocks); +BOOL TbdAddToolbar(PTOOLBAR_DOCKS TbDocks, + const DOCKBAR *Dockbar, + PVOID Context, + const DOCKBAR_ITEM_CALLBACKS *DockbarCallbacks); +BOOL TbdDockBarIdFromClientWindow(PTOOLBAR_DOCKS TbDocks, + HWND hWndClient, + UINT *Id); +BOOL TbdHandleNotifications(PTOOLBAR_DOCKS TbDocks, + LPNMHDR pnmh, + LRESULT *Result); +VOID TbdHandleEnabling(PTOOLBAR_DOCKS TbDocks, + HWND hWnd, + BOOL Enable); +VOID TbdHandleActivation(PTOOLBAR_DOCKS TbDocks, + HWND hWnd, + WPARAM *wParam, + LPARAM *lParam); +VOID TbdShowFloatingToolbars(PTOOLBAR_DOCKS TbDocks, + BOOL Show); +BOOL TbdInitImpl(VOID); +VOID TbdUninitImpl(VOID); diff --git a/modules/rosapps/applications/net/dhcpd/AUTHORS b/modules/rosapps/applications/net/dhcpd/AUTHORS new file mode 100644 index 00000000000..6102d1615e6 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/AUTHORS @@ -0,0 +1,3 @@ +Carlos Duclos Vergara, +Pablo Bleyer Kocik, +Manuel Jander, diff --git a/modules/rosapps/applications/net/dhcpd/COPYING b/modules/rosapps/applications/net/dhcpd/COPYING new file mode 100644 index 00000000000..3f061137320 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/COPYING @@ -0,0 +1,222 @@ + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/modules/rosapps/applications/net/dhcpd/ChangeLog b/modules/rosapps/applications/net/dhcpd/ChangeLog new file mode 100644 index 00000000000..5c1dd5ed88d --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/ChangeLog @@ -0,0 +1,18 @@ +2002020701: +- I rewrite completely the code to get an ip. +- I delete threads beacuse of some deadlocks. +- I add _finally_ support for static ip host. + +2002013002: +- After some web surf and some hack there is (i hope so!) a windows port, please BE CAREFULL because i have no way to test it. + +2002013001: +- After a lot of work, this is finally working and now is being ported to auto GNU tools. +- I will add the routines to compile it under MSW boxes with winsock. + +20020121: +- Well, we have a working version with configuration file and with reduced functionality. If you find bugs, please report them. This version is the last and i'm accepting patches for this version. +20020117: +- Finally there is an alpha release. From now i will start logging what i'm doing. +This alpha release was compiled in a SuSE Linux 7.2 box, i've tested it with my embedded device +and it works. I've tested with one MS Windows 98 workstations and it doesn't work. diff --git a/modules/rosapps/applications/net/dhcpd/INSTALL b/modules/rosapps/applications/net/dhcpd/INSTALL new file mode 100644 index 00000000000..f12c2e64949 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/INSTALL @@ -0,0 +1,188 @@ +NOTE: +->*nix Systems: use the configure script and everything should work without problems. +->MSW: FIRST you need the mingw compiler (i think cygwin must work too, but you will have to modify the configure.in and change MINGW32 for CYGWIN) +Then, run configure and pray. If it finds everything it needs (the only thing missed may be the pthreads library) is ready to compile. + + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/modules/rosapps/applications/net/dhcpd/Makefile.am b/modules/rosapps/applications/net/dhcpd/Makefile.am new file mode 100644 index 00000000000..af437a64d6d --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/modules/rosapps/applications/net/dhcpd/Makefile.in b/modules/rosapps/applications/net/dhcpd/Makefile.in new file mode 100644 index 00000000000..b3d2e5465b5 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/Makefile.in @@ -0,0 +1,352 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SUBDIRS = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \ +Makefile.am Makefile.in NEWS TODO aclocal.m4 config.h.in config.h.top \ +configure configure.in install-sh missing mkinstalldirs + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): configure.in + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +config.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=config.h \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/config.h.in: $(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) config.h.top + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f config.h + +maintainer-clean-hdr: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +all-recursive-am: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: +uninstall: uninstall-recursive +all-am: Makefile config.h +all-redirect: all-recursive-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-hdr clean-tags clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-hdr distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +install-data-recursive uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \ +install-exec-am install-exec install-data-am install-data install-am \ +install uninstall-am uninstall all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/modules/rosapps/applications/net/dhcpd/NEWS b/modules/rosapps/applications/net/dhcpd/NEWS new file mode 100644 index 00000000000..fb68d6ca6f2 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/NEWS @@ -0,0 +1,2 @@ +20020130: +Finally autoconf and company are working. Now i will work on windows port. diff --git a/modules/rosapps/applications/net/dhcpd/README b/modules/rosapps/applications/net/dhcpd/README new file mode 100644 index 00000000000..5ecb78ff7ed --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/README @@ -0,0 +1,19 @@ +Disclaimer: +This project is released under GPL, see COPYING to get an idea of what this means. + +Building: +To build this you need a C compiler (i used gcc 2.95-3), and some luck. +Just type make, i'm working on autoconf and automake but is not finished yet. + +Running: +For some reason in some circumstances you have to add the following to your route table: +route add -host 255.255.255.255 dev eth0 +That is needed to allow the distribution of packets to the address 255.255.255.255 (as said in RFC 1531). + +NOTE FOR WINDOWS USERS: +I don't know how to add that route in MSW systems, looku yourself for help on that. + + +Comments: +Well, comments are always welcome. It doesn't matter if you want to tell me that i suck. If you find some bug and want to report it please do it to my email at: +carlos@embedded.cl with subject [ecl-dhcp]. If the circumstances allow that i will create a mail list. diff --git a/modules/rosapps/applications/net/dhcpd/README.ROS b/modules/rosapps/applications/net/dhcpd/README.ROS new file mode 100644 index 00000000000..779f20e988d --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/README.ROS @@ -0,0 +1,6 @@ +Embedded DHCP Server for ReactOS - Carlos Manuel Duclos Vergara + +TODO: +Make it a real Windows Service +Use the registry rather than a config file +Fix a few races and check to see how it can scale. \ No newline at end of file diff --git a/modules/rosapps/applications/net/dhcpd/TODO b/modules/rosapps/applications/net/dhcpd/TODO new file mode 100644 index 00000000000..b29327ffdac --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/TODO @@ -0,0 +1,8 @@ +There are two kind of things, the essentials and the optionals. + +Optionals: +- Implement a way to bypass the IP stack and send packets directly. +- Sort and beauty the code, maybe rewritting in C++. + +Essentials: +- Compile it and test it in MS Windows platforms(work in progress). diff --git a/modules/rosapps/applications/net/dhcpd/aclocal.m4 b/modules/rosapps/applications/net/dhcpd/aclocal.m4 new file mode 100644 index 00000000000..9f8add8f0d9 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/aclocal.m4 @@ -0,0 +1,104 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4 + +dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + diff --git a/modules/rosapps/applications/net/dhcpd/config.cache b/modules/rosapps/applications/net/dhcpd/config.cache new file mode 100644 index 00000000000..665b5b63b1e --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/config.cache @@ -0,0 +1,26 @@ +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +ac_cv_func_socket=${ac_cv_func_socket=yes} +ac_cv_header_stdc=${ac_cv_header_stdc=yes} +ac_cv_header_unistd_h=${ac_cv_header_unistd_h=yes} +ac_cv_mingw32=${ac_cv_mingw32=no} +ac_cv_path_install=${ac_cv_path_install='$/usr/bin/install -c'} +ac_cv_prog_CC=${ac_cv_prog_CC=gcc} +ac_cv_prog_CPP=${ac_cv_prog_CPP='$gcc -E'} +ac_cv_prog_cc_cross=${ac_cv_prog_cc_cross=no} +ac_cv_prog_cc_g=${ac_cv_prog_cc_g=yes} +ac_cv_prog_cc_works=${ac_cv_prog_cc_works=yes} +ac_cv_prog_gcc=${ac_cv_prog_gcc=yes} +ac_cv_prog_make_make_set=${ac_cv_prog_make_make_set=yes} diff --git a/modules/rosapps/applications/net/dhcpd/config.h b/modules/rosapps/applications/net/dhcpd/config.h new file mode 100644 index 00000000000..a78c0d4614b --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/config.h @@ -0,0 +1,25 @@ +/* config.h. Generated automatically by configure. */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ +/* #undef MINGW32 */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the header file. */ +/* #undef HAVE_PTHREAD_H */ + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the pthread library (-lpthread). */ +/* #undef HAVE_LIBPTHREAD */ + +/* Name of package */ +#define PACKAGE "dhcptool" + +/* Version number of package */ +#define VERSION "0.0.1-alpha" + diff --git a/modules/rosapps/applications/net/dhcpd/config.h.in b/modules/rosapps/applications/net/dhcpd/config.h.in new file mode 100644 index 00000000000..3dd9ff0f414 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/config.h.in @@ -0,0 +1,24 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ +#undef MINGW32 + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you have the socket function. */ +#undef HAVE_SOCKET + +/* Define if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the pthread library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Name of package */ +#undef PACKAGE + +/* Version number of package */ +#undef VERSION + diff --git a/modules/rosapps/applications/net/dhcpd/config.h.top b/modules/rosapps/applications/net/dhcpd/config.h.top new file mode 100644 index 00000000000..a5c8595f4db --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/config.h.top @@ -0,0 +1 @@ +#undef MINGW32 diff --git a/modules/rosapps/applications/net/dhcpd/config.log b/modules/rosapps/applications/net/dhcpd/config.log new file mode 100644 index 00000000000..7f48064b6eb --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/config.log @@ -0,0 +1,22 @@ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +configure:557: checking for a BSD compatible install +configure:610: checking whether build environment is sane +configure:667: checking whether make sets ${MAKE} +configure:713: checking for working aclocal +configure:726: checking for working autoconf +configure:739: checking for working automake +configure:752: checking for working autoheader +configure:765: checking for working makeinfo +configure:783: checking for gcc +configure:896: checking whether the C compiler (gcc ) works +configure:912: gcc -o conftest conftest.c 1>&5 +configure:938: checking whether the C compiler (gcc ) is a cross-compiler +configure:943: checking whether we are using GNU C +configure:971: checking whether gcc accepts -g +configure:1005: checking how to run the C preprocessor +configure:1085: checking for ANSI C header files +configure:1192: checking for unistd.h +configure:1230: checking for mingw32 environment +configure:1262: checking for socket diff --git a/modules/rosapps/applications/net/dhcpd/config.status b/modules/rosapps/applications/net/dhcpd/config.status new file mode 100644 index 00000000000..2592d8efae5 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/config.status @@ -0,0 +1,251 @@ +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host steven: +# +# ./configure +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: ./config.status [--recheck] [--version] [--help]" +for ac_option +do + case "$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running ${CONFIG_SHELL-/bin/sh} ./configure --no-create --no-recursion" + exec ${CONFIG_SHELL-/bin/sh} ./configure --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "./config.status generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "$ac_cs_usage"; exit 0 ;; + *) echo "$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=. +ac_given_INSTALL="$/usr/bin/install -c" + +trap 'rm -fr Makefile src/Makefile config.h conftest*; exit 1' 1 2 15 + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\&%]/\\&/g; + s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF +/^[ ]*VPATH[ ]*=[^:]*$/d + +s%@SHELL@%/bin/sh%g +s%@CFLAGS@%-g -O2%g +s%@CPPFLAGS@%%g +s%@CXXFLAGS@%%g +s%@FFLAGS@%%g +s%@DEFS@%-DHAVE_CONFIG_H%g +s%@LDFLAGS@%%g +s%@LIBS@%%g +s%@exec_prefix@%${prefix}%g +s%@prefix@%/usr/local%g +s%@program_transform_name@%s,x,x,%g +s%@bindir@%${exec_prefix}/bin%g +s%@sbindir@%${exec_prefix}/sbin%g +s%@libexecdir@%${exec_prefix}/libexec%g +s%@datadir@%${prefix}/share%g +s%@sysconfdir@%${prefix}/etc%g +s%@sharedstatedir@%${prefix}/com%g +s%@localstatedir@%${prefix}/var%g +s%@libdir@%${exec_prefix}/lib%g +s%@includedir@%${prefix}/include%g +s%@oldincludedir@%/usr/include%g +s%@infodir@%${prefix}/info%g +s%@mandir@%${prefix}/man%g +s%@INSTALL_PROGRAM@%${INSTALL}%g +s%@INSTALL_SCRIPT@%${INSTALL_PROGRAM}%g +s%@INSTALL_DATA@%${INSTALL} -m 644%g +s%@PACKAGE@%dhcptool%g +s%@VERSION@%0.0.1-alpha%g +s%@ACLOCAL@%aclocal%g +s%@AUTOCONF@%autoconf%g +s%@AUTOMAKE@%automake%g +s%@AUTOHEADER@%autoheader%g +s%@MAKEINFO@%makeinfo%g +s%@SET_MAKE@%%g +s%@CC@%gcc%g +s%@CPP@%$gcc -E%g + +CEOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi + +CONFIG_FILES=${CONFIG_FILES-"Makefile src/Makefile"} +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then + CONFIG_HEADERS="config.h" +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + + cat > conftest.frag < conftest.out + rm -f conftest.in + mv conftest.out conftest.in + + cat > conftest.frag < conftest.out + rm -f conftest.in + mv conftest.out conftest.in + + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + + + +exit 0 diff --git a/modules/rosapps/applications/net/dhcpd/configure b/modules/rosapps/applications/net/dhcpd/configure new file mode 100644 index 00000000000..e2f1eca4a6d --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/configure @@ -0,0 +1,1678 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=src/main.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:557: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:610: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:667: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=dhcptool + +VERSION=0.0.1-alpha + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <> confdefs.h <&6 +echo "configure:713: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:726: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:739: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:752: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:765: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:783: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:813: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:864: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:896: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 907 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:912: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:938: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:943: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:971: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1005: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1026: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1043: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1060: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1085: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1098: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1165: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1192: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1202: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 +echo "configure:1230: checking for mingw32 environment" >&5 +if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_mingw32=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_mingw32=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_mingw32" 1>&6 +MINGW32= +test "$ac_cv_mingw32" = yes && MINGW32=yes + +for ac_func in socket +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1262: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile src/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/modules/rosapps/applications/net/dhcpd/configure.in b/modules/rosapps/applications/net/dhcpd/configure.in new file mode 100644 index 00000000000..3effb635278 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/configure.in @@ -0,0 +1,24 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(src/main.c) + +AM_INIT_AUTOMAKE( dhcptool, 0.0.1-alpha) + +AC_CONFIG_HEADER(config.h) +dnl Checks for programs. +AC_PROG_CC + +dnl Checks for libraries. +dnl AC_CHECK_LIB(pthread, pthread_create, ,exit) + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(unistd.h) +dnl AC_CHECK_HEADERS(pthread.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_MINGW32 + +dnl Checks for library functions. +AC_CHECK_FUNCS(socket) + +AC_OUTPUT(Makefile src/Makefile) diff --git a/modules/rosapps/applications/net/dhcpd/dhcpd.rc b/modules/rosapps/applications/net/dhcpd/dhcpd.rc new file mode 100644 index 00000000000..b7058f50b6f --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/dhcpd.rc @@ -0,0 +1,5 @@ + +#define REACTOS_STR_FILE_DESCRIPTION "DHCP server service\0" +#define REACTOS_STR_INTERNAL_NAME "dhcpd\0" +#define REACTOS_STR_ORIGINAL_FILENAME "dhcpd.exe\0" +#include diff --git a/modules/rosapps/applications/net/dhcpd/install-sh b/modules/rosapps/applications/net/dhcpd/install-sh new file mode 100644 index 00000000000..e9de23842dc --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/modules/rosapps/applications/net/dhcpd/missing b/modules/rosapps/applications/net/dhcpd/missing new file mode 100644 index 00000000000..7789652e877 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/missing @@ -0,0 +1,190 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Franc,ois Pinard , 1996. + +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`configure.in'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`configure.in'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`configure.in'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/modules/rosapps/applications/net/dhcpd/mkinstalldirs b/modules/rosapps/applications/net/dhcpd/mkinstalldirs new file mode 100644 index 00000000000..5e17cd39fb7 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/mkinstalldirs @@ -0,0 +1,38 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/modules/rosapps/applications/net/dhcpd/samples/dhcp.conf b/modules/rosapps/applications/net/dhcpd/samples/dhcp.conf new file mode 100644 index 00000000000..9e7a6aec4e2 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/samples/dhcp.conf @@ -0,0 +1,8 @@ +# DHCP CONFIGURATION, DO NOT ERASE OR MOVE THIS LINE! +subnet 192.168.2.0 +lease 30 +range 2 5 +mask 255.255.255.0 +router 192.168.2.1 +server 192.168.2.1 +# DHCP CONFIGURATION, DO NOT ERASE OR MOVE THIS LINE! diff --git a/modules/rosapps/applications/net/dhcpd/src/Makefile.am b/modules/rosapps/applications/net/dhcpd/src/Makefile.am new file mode 100644 index 00000000000..25d3fbe1e25 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/Makefile.am @@ -0,0 +1,6 @@ +SUBDIRS = display leases parsing utils +INCLUDES = -Iinclude +CFLAGS = display.o leases.o parser.o utils.o -Wall +bin_PROGRAMS = dhcp +dhcp_SOURCES = main.c +dhcp_OBJS = display.o leases.o parser.o utils.o diff --git a/modules/rosapps/applications/net/dhcpd/src/Makefile.in b/modules/rosapps/applications/net/dhcpd/src/Makefile.in new file mode 100644 index 00000000000..e46b8499152 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/Makefile.in @@ -0,0 +1,388 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SUBDIRS = display leases parsing utils +INCLUDES = -Iinclude +CFLAGS = display.o leases.o parser.o utils.o -Wall +bin_PROGRAMS = dhcp +dhcp_SOURCES = main.c +dhcp_OBJS = display.o leases.o parser.o utils.o +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(bin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +dhcp_OBJECTS = main.o +dhcp_LDADD = $(LDADD) +dhcp_DEPENDENCIES = +dhcp_LDFLAGS = +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/main.P +SOURCES = $(dhcp_SOURCES) +OBJECTS = $(dhcp_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +dhcp: $(dhcp_OBJECTS) $(dhcp_DEPENDENCIES) + @rm -f dhcp + $(LINK) $(dhcp_LDFLAGS) $(dhcp_OBJECTS) $(dhcp_LDADD) $(LIBS) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = src + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-exec-am: install-binPROGRAMS +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: uninstall-binPROGRAMS +uninstall: uninstall-recursive +all-am: Makefile $(PROGRAMS) +all-redirect: all-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(bindir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-binPROGRAMS clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \ + distclean-depend distclean-generic clean-am + +distclean: distclean-recursive + +maintainer-clean-am: maintainer-clean-binPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + +.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile install-data-recursive \ +uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir \ +mostlyclean-depend distclean-depend clean-depend \ +maintainer-clean-depend info-am info dvi-am dvi check check-am \ +installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all installdirs-am installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/modules/rosapps/applications/net/dhcpd/src/dhcp.conf b/modules/rosapps/applications/net/dhcpd/src/dhcp.conf new file mode 100644 index 00000000000..e2e3803721f --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/dhcp.conf @@ -0,0 +1,9 @@ +# DHCP CONFIGURATION, DO NOT ERASE OR MOVE THIS LINE! +subnet 192.168.2.0 +lease 30 +range 2 5 +mask 255.255.255.0 +router 192.168.2.1 +server 192.168.2.1 +host 52:54:40:22:65:BD 192.168.2.200 +# DHCP CONFIGURATION, DO NOT ERASE OR MOVE THIS LINE! diff --git a/modules/rosapps/applications/net/dhcpd/src/display/display.c b/modules/rosapps/applications/net/dhcpd/src/display/display.c new file mode 100644 index 00000000000..d2de8a5aa1d --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/display/display.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +int display_dhcp_packet( DHCPMESSAGE *dhcpm, DHCPOPTIONS *dhcpo ) +{ + char *mtype; + if( dhcpm == NULL ) + return -1; + + fprintf( stdout, "op: %s\t|htype: %s\t|hlen: %u\t|hops: %u\n", (dhcpm->op == 1)?"BOOTREQUEST":"BOOTREPLY", (dhcpm->htype==1)?"Ethernet 10Mb":"unknown", dhcpm->hlen, dhcpm->hops); + fprintf( stdout, "xid: %u \n", dhcpm->xid ); + fprintf( stdout, "secs: %u\t\t|flags: %u\n", dhcpm->secs, dhcpm->flags ); + fprintf( stdout, "ciaddr: %u.%u.%u.%u \n", (dhcpm->ciaddr >> 24), ((dhcpm->ciaddr>>16)&0xFF), ((dhcpm->ciaddr>>8)&0xFF), ((dhcpm->ciaddr)&0xFF)); + fprintf( stdout, "yiaddr: %u.%u.%u.%u \n", (dhcpm->yiaddr >> 24), ((dhcpm->yiaddr>>16)&0xFF), ((dhcpm->yiaddr>>8)&0xFF), ((dhcpm->yiaddr)&0xFF)); + fprintf( stdout, "siaddr: %u.%u.%u.%u \n", (dhcpm->siaddr >> 24), ((dhcpm->siaddr>>16)&0xFF), ((dhcpm->siaddr>>8)&0xFF), ((dhcpm->siaddr)&0xFF)); + fprintf( stdout, "giaddr: %u.%u.%u.%u \n", (dhcpm->giaddr >> 24), ((dhcpm->giaddr>>16)&0xFF), ((dhcpm->giaddr>>8)&0xFF), ((dhcpm->giaddr)&0xFF)); + fprintf( stdout, "chaddr: %X::%X::%X::%X::%X::%X \n", dhcpm->chaddr[0], dhcpm->chaddr[1], dhcpm->chaddr[2], dhcpm->chaddr[3], dhcpm->chaddr[4], dhcpm->chaddr[5] ); + fprintf( stdout, "sname: %s \n", dhcpm->sname ); + fprintf( stdout, "file: %s \n", dhcpm->file ); + /* options come here */ + switch( dhcpo->type ) + { + case DHCPDISCOVER: + mtype = (char *)malloc( strlen( "DHCPDISCOVER" ) +1); + strcpy( mtype, "DHCPDISCOVER" ); + break; + case DHCPREQUEST: + mtype = (char *)malloc( strlen( "DHCPREQUEST" ) +1); + strcpy( mtype, "DHCPREQUEST" ); + break; + case DHCPACK: + mtype = (char *)malloc( strlen( "DHCPACK" ) +1); + strcpy( mtype, "DHCPACK" ); + break; + case DHCPNAK: + mtype = (char *)malloc( strlen( "DHCPNAK" ) +1); + strcpy( mtype, "DHCPNAK" ); + break; + case DHCPRELEASE: + mtype = (char *)malloc( strlen( "DHCPRELEASE" ) +1); + strcpy( mtype, "DHCPRELEASE" ); + break; + case DHCPDECLINE: + mtype = (char *)malloc( strlen( "DHCPDECLINE" ) +1); + strcpy( mtype, "DHCPDECLINE" ); + break; + case DHCPOFFER: + mtype = (char *)malloc( strlen( "DHCPOFFER" ) +1); + strcpy( mtype, "DHCPOFFER" ); + break; + default: + mtype = (char *)malloc( strlen("Unknown Type") +1); + strcpy( mtype, "Unknown Type" ); + break; + } + fprintf( stdout, "Message Type: %s \n", mtype ); + return 0; +} + diff --git a/modules/rosapps/applications/net/dhcpd/src/include/datatypes.h b/modules/rosapps/applications/net/dhcpd/src/include/datatypes.h new file mode 100644 index 00000000000..a99a10d1261 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/datatypes.h @@ -0,0 +1,56 @@ +#ifndef DATATYPES_H +#define DATATYPES_H + +typedef unsigned char u8b; +typedef unsigned short u16b; +typedef unsigned int u32b; + +typedef struct{ + u8b op; + u8b htype; + u8b hlen; + u8b hops; + u32b xid; + u16b secs; + u16b flags; + u32b ciaddr; + u32b yiaddr; + u32b siaddr; + u32b giaddr; + u8b chaddr[16]; + u8b sname[64]; + u8b file[128]; + u8b options[312]; +} DHCPMESSAGE; + +typedef struct{ + u8b type; + u32b r_ip; + u32b r_mask; + u32b r_router; + u32b r_lease; + char *hostname; +} DHCPOPTIONS; + +typedef struct{ + u32b ip; + u32b router; + u32b mask; + u32b lease; + u32b siaddr; +} DHCPLEASE; + +struct _DHCPLIST{ + u8b available; + u32b xid; + u8b chaddr[16]; + u8b type; + u32b ltime; + DHCPLEASE data; + struct _DHCPLIST *next; + struct _DHCPLIST *back; +}; + +typedef struct _DHCPLIST DHCPLIST; + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/display.h b/modules/rosapps/applications/net/dhcpd/src/include/display.h new file mode 100644 index 00000000000..833ab988ae6 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/display.h @@ -0,0 +1,6 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +int display_dhcp_packet( DHCPMESSAGE *, DHCPOPTIONS *); + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/headers.h b/modules/rosapps/applications/net/dhcpd/src/include/headers.h new file mode 100644 index 00000000000..e4ca9e7aa68 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/headers.h @@ -0,0 +1,25 @@ +#ifndef HEADERS_H +#define HEADERS_H + +#ifdef __MINGW32__ + +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/iputils.h b/modules/rosapps/applications/net/dhcpd/src/include/iputils.h new file mode 100644 index 00000000000..6ab028540a2 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/iputils.h @@ -0,0 +1,7 @@ +#ifndef IPUTILS_H +#define IPUTILS_H + +int split_ip( char *, u8b *, int ); +int get_ip( char *, u32b * ); + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/leases.h b/modules/rosapps/applications/net/dhcpd/src/include/leases.h new file mode 100644 index 00000000000..577be67b84d --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/leases.h @@ -0,0 +1,10 @@ +#ifndef LEASES_H +#define LEASES_H + +extern DHCPLIST *list; +int find_lease( DHCPLEASE *, u32b, u8b * ); +int init_leases_list(); +int confirm_lease( DHCPLEASE *, u32b ); +int release_lease( DHCPLEASE *, u32b, u8b * ); + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/lock.h b/modules/rosapps/applications/net/dhcpd/src/include/lock.h new file mode 100644 index 00000000000..6d1e36e2905 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/lock.h @@ -0,0 +1,11 @@ +#ifndef LOCK_H +#define LOCK_H + +extern DHCPLIST *leased_list; + +int check_leased_list(); +static int test_and_set(); +int lock_list(); +int unlock_list(); + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/macutils.h b/modules/rosapps/applications/net/dhcpd/src/include/macutils.h new file mode 100644 index 00000000000..471c52e9e76 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/macutils.h @@ -0,0 +1,7 @@ +#ifndef MACUTILS_H +#define MACUTILS_H + +int maccmp( u8b *, u8b *); +int maccpy( u8b *, u8b *); + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/options.h b/modules/rosapps/applications/net/dhcpd/src/include/options.h new file mode 100644 index 00000000000..d89176c4f5c --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/options.h @@ -0,0 +1,118 @@ +/* This software is GPL, see http://www.gnu.org to see exactly what it means */ + +/* This file contains some useful constant declarations */ + +#ifndef OPTIONS_H +#define OPTIONS_H + +#define VERSION "ecl-dhcp-0.0.2-snoopy" + +#define MAX_PROCESS_TIME 15 + +#define FALSE 0 +#define TRUE 1 + +#define BOOTREQUEST 0x1 +#define BOOTREPLY 0x2 + + /* Message types */ + +#define DHCPDISCOVER 0x1 +#define DHCPOFFER 0x2 +#define DHCPREQUEST 0x3 +#define DHCPDECLINE 0x4 +#define DHCPACK 0x5 +#define DHCPNAK 0x6 +#define DHCPRELEASE 0x7 +#define DHCPINFORM 0x8 + + +#define PAD 0x00 +#define MASK 0x01 +#define TOFFSET 0x02 +#define ROUTER 0x03 +#define TIMESERVER 0x04 +#define NS 0x05 +#define DNS 0x06 +#define LOGSERVER 0x07 +#define COOKIESERVER 0x08 +#define LPRSERVER 0x09 +#define IMPSERVER 0x0A +#define RESLOCSERVER 0x0B +#define HOSTNAME 0x0C +#define BOOTFILESIZE 0x0D +#define MERITDUMPFILE 0x0E +#define DOMAINNAME 0x0F +#define SWAPSERVER 0x10 +#define ROOTPATH 0x11 +#define EXTENSIONPATH 0x12 +#define IPFORWARD 0x13 +#define NONLOCAL 0x14 +#define POLICYFILTER 0x15 +#define MAXIMUMDATAG 0x16 +#define DEFAULTTTL 0x17 +#define PATHMTUATO 0x18 +#define PATHMTUPTO 0x19 +#define IMTU 0x1A +#define ALLSUBLOCAL 0x1B +#define BROADCAST 0x1C +#define PMASKDISCOVERY 0x1D +#define MASKSUPPLIER 0x1E +#define PROUTERDISCOVE 0x1F +#define RSOLICIADDRESS 0x20 +#define STATICROUTE 0x21 +#define TENCAPSULATION 0x22 +#define ARPCACHE 0x23 +#define ETHENCAPSUL 0x24 +#define TCPDEFTTL 0x25 +#define TCPKAI 0x26 +#define TCPKAG 0x27 +#define NISDOMAIN 0x28 +#define NISSERVER 0x29 +#define NTPSERVER 0x2A +#define VENDORSP 0x2B +#define NBTCPIPNS 0x2C +#define NBTCPIPDDS 0x2D +#define NBTCPIPNT 0x2E +#define NBTCPIPSC 0x2F +#define XWINFONTSERVER 0x30 +#define XWINDISPLAY 0x31 +#define IP 0x32 +#define LEASE 0x33 +#define OVERLOAD 0x34 +#define MESSAGETYPE 0x35 +#define SERVER 0x36 +#define PREQUEST 0x37 +#define MESSAGE 0x38 +#define MAXIMUMDHCP 0x39 +#define RENEWALTIME 0x3A +#define REBINDING 0x3B +#define VENDORCLASS 0x3C +#define CLIENT 0x3D +#define NISPLUSDOMAIN 0x40 +#define NISPLUSSERVER 0x41 +#define TFTPSERVER 0x42 +#define BOOTFILE 0x43 +#define MOBILEIP 0x44 +#define SMTPSERVER 0x45 +#define POP3SERVER 0x46 +#define NNTPSERVER 0x47 +#define HTTPSERVER 0x48 +#define FINGERSERVER 0x49 +#define IRCSERVER 0x4A +#define STREETTALKSE 0x4B +#define STREETTALKDA 0x4C +#define END 0xFF + + /* Constants */ +#define FREE 0x01 +#define PROCESSING 0x02 +#define BUSY 0x00 + +#define DYNAMIC 0x00 +#ifdef STATIC +#undef STATIC +#endif +#define STATIC 0x01 + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/parser.h b/modules/rosapps/applications/net/dhcpd/src/include/parser.h new file mode 100644 index 00000000000..6ecc47d3b47 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/parser.h @@ -0,0 +1,8 @@ +#ifndef PARSER_H +#define PARSER_H + +int parse_dhcp_options( DHCPMESSAGE *, DHCPOPTIONS *); +int process_dhcp_packet( DHCPMESSAGE *, DHCPOPTIONS *); +int write_packet( DHCPMESSAGE *, char *); + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/utils.h b/modules/rosapps/applications/net/dhcpd/src/include/utils.h new file mode 100644 index 00000000000..2c00a9d1ac5 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/utils.h @@ -0,0 +1,7 @@ +#ifndef UTILS_H +#define UTILS_H + +#include +#include + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/include/wutils.h b/modules/rosapps/applications/net/dhcpd/src/include/wutils.h new file mode 100644 index 00000000000..b9f150fbadb --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/include/wutils.h @@ -0,0 +1,6 @@ +#ifndef WUTILS_H +#define WUTILS_H + +u8b try_lock( u8b * ); + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/leases/leases.c b/modules/rosapps/applications/net/dhcpd/src/leases/leases.c new file mode 100644 index 00000000000..de56f3f0d69 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/leases/leases.c @@ -0,0 +1,231 @@ +#include +#include +#include +#include +#include +#include + +int init_leases_list() +{ + DHCPLIST *temp; + int i, j; + u8b chaddr[16]; + FILE *config; + char line[80]; + char textsubnet[16]; + char textlease[5]; + char textrouter[16]; + char textmask[16]; + char textlowrange[4], texthighrange[4]; + char textserver[16]; + u8b ip0, ip1, ip2, ip3; + u8b lowrange, highrange; + u8b textmac[17], textip[16]; + u32b lease; + + /* Be nice variables and behave yourselves */ + + for( j = 0; j < 16; j++ ) + { + chaddr[j] = 0; + textsubnet[j] = 0; + textrouter[j] = 0; + textmask[j] = 0; + textip[j] = 0; + textmac[j] = 0; + } + + textlease[0] = 0; + textlowrange[0] = 0; + texthighrange[0] = 0; + + /* Now we can read our configuration file */ + + config = fopen( "dhcp.conf", "r" ); + if( !config ) + { + perror("Reading config files"); + exit( 0 ); + } + + /* We _DO_ need a better parser */ + list = (DHCPLIST *)malloc( sizeof( DHCPLIST )); + temp = list; + temp->back = NULL; + + while( (!feof( config )) && ( line )) + { + fscanf( config, "%s", line); + if( !strcmp( line, "subnet" )) + /* Read subnet parameters */ + fscanf( config, "%s", textsubnet ); + + if( !strcmp( line, "lease" )) + /* read lease parameters */ + fscanf( config, "%s", textlease ); + + if( !strcmp( line, "router" )) + fscanf( config, "%s", textrouter ); + + if( !strcmp( line, "mask" )) + fscanf( config, "%s", textmask ); + + if( !strcmp( line, "range" )) + fscanf( config, "%s %s", textlowrange, texthighrange ); + if( !strcmp( line, "server" )) + fscanf( config, "%s", textserver ); + if( !strcmp( line, "host" )) + { + /* Host Specific Configuration */ + fscanf( config, "%s %s", textmac, textip ); + str2mac( textmac, temp->chaddr ); + temp->type = STATIC; + temp->data.ip = inet_addr( textip ); + temp->next = (DHCPLIST *)malloc( sizeof( DHCPLIST )); + temp->next->back = temp; + temp = temp->next; + temp->next =NULL; + } + } + fclose( config ); + + lowrange = (u8b)atoi( textlowrange ); + highrange = (u8b)atoi( texthighrange ); + lease = (u32b)atoi( textlease ); + + /* Creating Static IP */ + + for( temp = list; temp->next; temp = temp->next ) + { + temp->available = FREE; + temp->xid = 0; + temp->data.router = inet_addr( textrouter ); + temp->data.mask = inet_addr( textmask ); + temp->data.lease = lease; + temp->data.siaddr = inet_addr( textserver ); + } + + /* Creating Dynamic IP */ + + for( i = lowrange; i < (highrange + 1); i++ ) + { + temp->available = FREE; + temp->xid = 0; + temp->type = DYNAMIC; + maccpy( temp->chaddr, chaddr ); + split_ip( textsubnet, &ip0, 0 ); + split_ip( textsubnet, &ip1, 1 ); + split_ip( textsubnet, &ip2, 2 ); + temp->data.ip = i; + temp->data.ip = temp->data.ip << 8; + temp->data.ip += ip2; + temp->data.ip = temp->data.ip << 8; + temp->data.ip += ip1; + temp->data.ip = temp->data.ip << 8; + temp->data.ip += ip0; + temp->data.router = inet_addr( textrouter ); + temp->data.mask = inet_addr( textmask ); + temp->data.lease = lease; + temp->data.siaddr = inet_addr( textserver ); + temp->next = (DHCPLIST *)malloc( sizeof( DHCPLIST )); + temp->next->back = temp; + temp = temp->next; + } + return 0; +} + +int find_lease( DHCPLEASE *dhcpl, u32b xid, u8b chaddr[] ) +{ + int result = -2; + DHCPLIST *temp; + + if( !dhcpl ) + return -1; + + for( temp = list; temp; temp=temp->next ) + if( !maccmp( temp->chaddr, chaddr ) ) + release_lease( dhcpl, xid, chaddr); + + for( temp = list; temp; temp=temp->next ) + if( ( !maccmp( temp->chaddr, chaddr )) && ( temp->type == STATIC )) + { + dhcpl->ip = temp->data.ip; + dhcpl->router = temp->data.router; + dhcpl->mask = temp->data.mask; + dhcpl->lease = temp->data.lease; + dhcpl->siaddr = temp->data.siaddr; + fprintf( stdout, "Assigning Static IP! \n"); + temp->available = PROCESSING; + temp->xid = xid; + temp->ltime = MAX_PROCESS_TIME; + maccpy( temp->chaddr, chaddr); + result = 0; + return result; + } + else if( ( temp->available & FREE ) && ( temp->type == DYNAMIC )) + { + dhcpl->ip = temp->data.ip; + dhcpl->router = temp->data.router; + dhcpl->mask = temp->data.mask; + dhcpl->lease = temp->data.lease; + dhcpl->siaddr = temp->data.siaddr; + fprintf( stdout, "Assigning Dynamic IP! \n"); + temp->available = PROCESSING; + temp->xid = xid; + temp->ltime = MAX_PROCESS_TIME; + maccpy( temp->chaddr, chaddr); + result = 0; + return result; + } + return result; +} + +int confirm_lease( DHCPLEASE *dhcpl, u32b xid ) +{ + int result = -1; + DHCPLIST *temp; + + for( temp = list; temp; temp=temp->next ) + if( temp->xid == xid ) + { + dhcpl->ip = temp->data.ip; + dhcpl->router = temp->data.router; + dhcpl->mask = temp->data.mask; + dhcpl->lease = temp->data.lease; + dhcpl->siaddr = temp->data.siaddr; + temp->available = BUSY; + temp->ltime = temp->data.lease; + result = 0; + return result; + } + return result; +} + +int release_lease( DHCPLEASE *dhcpl, u32b xid, u8b chaddr[16] ) +{ + int result = -1, i; + DHCPLIST *temp; + u8b nchaddr[16]; + + for( i = 0; i < 16; i++ ) + nchaddr[i] = 0; + + if( !dhcpl ) + return -1; + + for( temp = list; temp; temp=temp->next ) + if( !maccmp( temp->chaddr, chaddr ) ) + { + /* We found the address */ + result = 0; + fprintf( stdout, "Deleting %X::%X::%X::%X::%X::%X \n", temp->chaddr[0], temp->chaddr[1], temp->chaddr[2], temp->chaddr[3], temp->chaddr[4], temp->chaddr[5] ); + temp->available = FREE; + temp->xid = 0; + /* maccpy( temp->chaddr, nchaddr ); */ + } else { + /* No such address */ + result = -1; + } + + return result; +} diff --git a/modules/rosapps/applications/net/dhcpd/src/lock/locker.c b/modules/rosapps/applications/net/dhcpd/src/lock/locker.c new file mode 100644 index 00000000000..3998a82437d --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/lock/locker.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +int check_leased_list() +{ + DHCPLIST *temp, *ntemp; + int count = 1, i; + + /* fprintf( stdout, "checking list! \n" ); */ + + return 0; +} + +static int test_and_set() +{ + /* Test lock, if it's locked return FALSE */ + + return TRUE; +} + +int lock_list() +{ + int count = 1; + + while( !test_and_set() ) + { + sleep( 1 ); + count++; + } + + return count; +} + +int unlock_list() +{ + return TRUE; +} diff --git a/modules/rosapps/applications/net/dhcpd/src/main.c b/modules/rosapps/applications/net/dhcpd/src/main.c new file mode 100644 index 00000000000..da7d52fa190 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/main.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include + +#define MYPORT 67 +DHCPLIST *list; +/*DHCPLIST *leased_list;*/ + +int main( int argc, char *argv[] ) +{ +#ifdef __MINGW32__ + WSADATA wsaData; + int nCode; +#endif + int sockfd; + struct sockaddr_in my_addr; + struct sockaddr_in their_addr; + int addr_len, numbytes; + DHCPMESSAGE dhcpm; + DHCPOPTIONS dhcpo; + +#ifdef __MINGW32__ + if ((nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0) + { + perror("WSAStartup"); + return 0; + } +#endif + + if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + perror("socket"); + exit(1); + } + + init_leases_list(); + + my_addr.sin_family = AF_INET; + my_addr.sin_port = htons(MYPORT); + my_addr.sin_addr.s_addr = INADDR_ANY; + memset(&(my_addr.sin_zero), '\0', 8); + + if (bind(sockfd, (struct sockaddr *)&my_addr, + sizeof(struct sockaddr)) == -1) { + perror("bind"); + exit(1); + } + + addr_len = sizeof(struct sockaddr); + while((numbytes=recvfrom(sockfd,&dhcpm, sizeof( DHCPMESSAGE ), 0, + (struct sockaddr *)&their_addr, &addr_len)) != -1) { + /* Parse DHCP */ + display_dhcp_packet( &dhcpm, &dhcpo ); + if( parse_dhcp_options( &dhcpm, &dhcpo ) < 0 ) + continue; + if( display_dhcp_packet( &dhcpm, &dhcpo ) < 0 ) + continue; + if( process_dhcp_packet( &dhcpm, &dhcpo ) < 0 ) + continue; + } + + close(sockfd); + +#ifdef __MINGW32__ + WSACleanup(); +#endif + + return 0; + +} diff --git a/modules/rosapps/applications/net/dhcpd/src/parsing/parser.c b/modules/rosapps/applications/net/dhcpd/src/parsing/parser.c new file mode 100644 index 00000000000..80adda1ad97 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/parsing/parser.c @@ -0,0 +1,402 @@ +#include +#include +#include +#include +#include +#include + +int parse_dhcp_options( DHCPMESSAGE *dhcpm, DHCPOPTIONS *dhcpo ) +{ + int pointer, opointer; + int olength; + + pointer = 0; + + fprintf( stdout, "parse_dhcp_options [begin]!\n"); + + /* Options Initialization */ + /* No message type */ + dhcpo->type = 0; + /* No ip address, 0.0.0.0 */ + dhcpo->r_ip = 0; + /* No mask address, 0.0.0.0 */ + dhcpo->r_mask = 0; + /* No router, 0.0.0.0 */ + dhcpo->r_router = 0; + /* No lease 0 */ + dhcpo->r_lease = 0; + /* No name '\n' */ + dhcpo->hostname = NULL; + + while( pointer< 312 ) + { + if(( dhcpm->options[0] != 99 ) && (dhcpm->options[1]!=130) && (dhcpm->options[2]!=83) && (dhcpm->options[3]!= 99)) + { + fprintf( stdout, "No magic cookie! Aborting! \n" ); + return -1; + } + switch( dhcpm->options[pointer] ){ + case PAD: + pointer++; + break; + case MESSAGETYPE: + /* Try to figure out the kind of message and start the configuring process */ + pointer += 2; + dhcpo->type = dhcpm->options[pointer++]; + break; + case PREQUEST: + /* Take note of the requested parameters */ + opointer = pointer + 2; + olength = pointer + dhcpm->options[pointer + 1]; + while( opointer < olength ) + { + switch( dhcpm->options[opointer] ){ + case IP: + /* Take note of the requested ip */ + opointer += 2; + dhcpo->r_ip += dhcpm->options[opointer++]; + dhcpo->r_ip = dhcpo->r_ip << 8; + dhcpo->r_ip += dhcpm->options[opointer++]; + dhcpo->r_ip = dhcpo->r_ip << 8; + dhcpo->r_ip += dhcpm->options[opointer++]; + dhcpo->r_ip = dhcpo->r_ip << 8; + dhcpo->r_ip += dhcpm->options[opointer++]; + break; + case MASK: + /* Take note of the requested mask */ + opointer += 2; + dhcpo->r_mask += dhcpm->options[opointer++]; + dhcpo->r_mask = dhcpo->r_ip << 8; + dhcpo->r_mask += dhcpm->options[opointer++]; + dhcpo->r_mask = dhcpo->r_ip << 8; + dhcpo->r_mask += dhcpm->options[opointer++]; + dhcpo->r_mask = dhcpo->r_ip << 8; + dhcpo->r_mask += dhcpm->options[opointer++]; + break; + case ROUTER: + /* Take note of the requested router */ + opointer += 2; + dhcpo->r_router += dhcpm->options[opointer++]; + dhcpo->r_router = dhcpo->r_ip << 8; + dhcpo->r_router += dhcpm->options[opointer++]; + dhcpo->r_router = dhcpo->r_ip << 8; + dhcpo->r_router += dhcpm->options[opointer++]; + dhcpo->r_router = dhcpo->r_ip << 8; + dhcpo->r_router += dhcpm->options[opointer++]; + break; + case LEASE: + opointer += 2; + dhcpo->r_lease += dhcpm->options[opointer++]; + dhcpo->r_lease = dhcpo->r_ip << 8; + dhcpo->r_lease += dhcpm->options[opointer++]; + dhcpo->r_lease = dhcpo->r_ip << 8; + dhcpo->r_lease += dhcpm->options[opointer++]; + dhcpo->r_lease = dhcpo->r_ip << 8; + dhcpo->r_lease += dhcpm->options[opointer++]; + break; + case HOSTNAME: + opointer += 1; + dhcpo->hostname = (char *)malloc( dhcpm->options[opointer] + 1); + strncpy( dhcpo->hostname, &dhcpm->options[opointer+1], dhcpm->options[opointer] ); + opointer += dhcpm->options[opointer] + 1; + default: + /* Ignore option */ + opointer++; + break; + } + } + pointer = opointer; + break; + case TOFFSET: + case TIMESERVER: + case NS: + case DNS: + case LOGSERVER: + case COOKIESERVER: + case LPRSERVER: + case IMPSERVER: + case RESLOCSERVER: + case BOOTFILESIZE: + case MERITDUMPFILE: + case DOMAINNAME: + case SWAPSERVER: + case ROOTPATH: + case EXTENSIONPATH: + case IPFORWARD: + case NONLOCAL: + case POLICYFILTER: + case MAXIMUMDATAG: + case DEFAULTTTL: + case PATHMTUATO: + case PATHMTUPTO: + case IMTU: + case ALLSUBLOCAL: + case BROADCAST: + case PMASKDISCOVERY: + case MASKSUPPLIER: + case PROUTERDISCOVE: + case RSOLICIADDRESS: + case STATICROUTE: + case TENCAPSULATION: + case ARPCACHE: + case ETHENCAPSUL: + case TCPDEFTTL: + case TCPKAI: + case TCPKAG: + case NISDOMAIN: + case NISSERVER: + case NTPSERVER: + case VENDORSP: + case NBTCPIPNS: + case NBTCPIPDDS: + case NBTCPIPNT: + case NBTCPIPSC: + case XWINFONTSERVER: + case XWINDISPLAY: + case OVERLOAD: + case SERVER: + case MESSAGE: + case MAXIMUMDHCP: + case RENEWALTIME: + case REBINDING: + case VENDORCLASS: + case NISPLUSDOMAIN: + case NISPLUSSERVER: + case TFTPSERVER: + case BOOTFILE: + case MOBILEIP: + case SMTPSERVER: + case POP3SERVER: + case NNTPSERVER: + case HTTPSERVER: + case FINGERSERVER: + case IRCSERVER: + case STREETTALKSE: + case STREETTALKDA: + case CLIENT: + pointer++; + pointer += dhcpm->options[pointer]; + case END: + /* return to the calling functions because this is over */ + fprintf( stdout, "parse_dhcp_options: END option found! [end]!\n"); + return 0; + default: + /* ignored */ + pointer++; + break; + } + } + fprintf( stdout, "parse_dhcp_options [end]!\n"); + return 0; +} + +int process_dhcp_packet( DHCPMESSAGE *dhcpm, DHCPOPTIONS *dhcpo ) +{ + int pointer = 4; + DHCPLEASE dhcpl; + char *name; + + fprintf( stdout, "process_dhcp_packet [begin]!\n"); + + if( (!dhcpm) || (!dhcpo) ) + return -1; + + name = (char *)malloc( 16 ); + switch( dhcpo->type ){ + + case DHCPDISCOVER: + /* We need to send a DHCPOFFER */ + if( find_lease( &dhcpl, dhcpm->xid, dhcpm->chaddr ) < 0 ) + { + fprintf( stdout, "No free leases! \n" ); + return -1; + } + dhcpm->op = BOOTREPLY; + dhcpm->yiaddr = dhcpl.ip; + dhcpm->siaddr = dhcpl.siaddr; + strcpy(dhcpm->sname, VERSION); + dhcpm->options[pointer++] = MESSAGETYPE; + dhcpm->options[pointer++] = 1; + dhcpm->options[pointer++] = DHCPOFFER; + dhcpm->options[pointer++] = ROUTER; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.router & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.router >> 8) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.router >> 16) &0xFF); + dhcpm->options[pointer++] = (dhcpl.router >> 24); + dhcpm->options[pointer++] = MASK; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.mask & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.mask >> 8) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.mask >> 16) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.mask >> 24); + dhcpm->options[pointer++] = SERVER; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.siaddr & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.siaddr >> 8) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.siaddr >> 16) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.siaddr >> 24); + dhcpm->options[pointer++] = LEASE; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.lease >> 24); + dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.lease & 0xFF); + dhcpm->options[pointer++] = REBINDING; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.lease >> 24); + dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.lease & 0xFF) - 5; + dhcpm->options[pointer++] = RENEWALTIME; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.lease >> 24); + dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.lease & 0xFF) - 5; + dhcpm->options[pointer++] = PAD; + dhcpm->options[pointer++] = PAD; + dhcpm->options[pointer++] = PAD; + dhcpm->options[pointer++] = END; + for( ; pointer < 312; pointer++ ) + dhcpm->options[pointer] = PAD; + dhcpo->type = DHCPOFFER; + strcpy( name, "255.255.255.255" ); + break; + + case DHCPREQUEST: + /* We need to send an DHCPACK */ + dhcpm->op = BOOTREPLY; + dhcpm->yiaddr = dhcpm->ciaddr; + strcpy(dhcpm->sname, VERSION); + if( confirm_lease( &dhcpl, dhcpm->xid ) < 0) + { + dhcpm->options[pointer++] = MESSAGETYPE; + dhcpm->options[pointer++] = 1; + dhcpm->options[pointer++] = DHCPNAK; + dhcpm->options[pointer++] = PAD; + dhcpm->options[pointer++] = END; + for( ; pointer < 312; pointer++ ) + dhcpm->options[pointer] = PAD; + sprintf( name, "%u.%u.%u.%u", (dhcpm->ciaddr &0xFF), ((dhcpm->ciaddr>>8)&0xFF), ((dhcpm->ciaddr>>16)&0xFF), ((dhcpm->ciaddr>>24)&0xFF)); + display_dhcp_packet( dhcpm, dhcpo ); + write_packet( dhcpm, name ); + return -1; + } + dhcpm->siaddr = dhcpl.siaddr; + dhcpm->options[pointer++] = MESSAGETYPE; + dhcpm->options[pointer++] = 1; + dhcpm->options[pointer++] = DHCPACK; + dhcpm->options[pointer++] = ROUTER; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.router >> 24); + dhcpm->options[pointer++] = ((dhcpl.router >> 16) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.router >> 8) &0xFF); + dhcpm->options[pointer++] = (dhcpl.router & 0xFF); + dhcpm->options[pointer++] = MASK; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.mask >> 24); + dhcpm->options[pointer++] = ((dhcpl.mask >> 16) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.mask >> 8) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.mask & 0xFF); + dhcpm->options[pointer++] = SERVER; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = dhcpl.siaddr >> 24; + dhcpm->options[pointer++] = ((dhcpl.siaddr >> 16) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.siaddr >> 8) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.siaddr & 0xFF); + dhcpm->options[pointer++] = LEASE; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.lease >> 24); + dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.lease & 0xFF); + dhcpm->options[pointer++] = REBINDING; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.lease >> 24); + dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.lease & 0xFF); + dhcpm->options[pointer++] = RENEWALTIME; + dhcpm->options[pointer++] = 4; + dhcpm->options[pointer++] = (dhcpl.lease >> 24); + dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF); + dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF); + dhcpm->options[pointer++] = (dhcpl.lease & 0xFF); + dhcpm->options[pointer++] = PAD; + dhcpm->options[pointer++] = PAD; + dhcpm->options[pointer++] = PAD; + dhcpm->options[pointer++] = END; + for( ; pointer < 312; pointer++ ) + dhcpm->options[pointer] = PAD; + dhcpo->type = DHCPACK; + sprintf( name, "%u.%u.%u.%u", (dhcpl.ip & 0xFF), ((dhcpl.ip>>8) & 0xFF), ((dhcpl.ip>>16)&0xFF), (dhcpl.ip>>24)); + break; + + default: + break; + } + display_dhcp_packet( dhcpm, dhcpo ); + write_packet( dhcpm, name ); + fprintf( stdout, "process_dhcp_packet [end]!\n"); + return 0; +} + +int write_packet( DHCPMESSAGE *dhcpm, char *name ) +{ + int sockfd; + struct sockaddr_in their_addr; // connector's address information + struct hostent *he; + int numbytes; + int enable = 1; + + fprintf( stdout, "write_packet [begin]\n" ); + + if( !dhcpm ) + return -1; + + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + perror("socket"); + exit(1); + } + + if( setsockopt( sockfd, SOL_SOCKET, SO_BROADCAST, &enable, sizeof( enable )) == -1 ) + { + perror("setsockopt"); + exit(1); + } + + if( strcmp( "255.255.255.255", name ) ) + { + if ((he=gethostbyname(name)) == NULL) { // get the host info + perror("gethostbyname"); + fprintf( stdout, "Unknown host %s \n", name ); + return -1; + } + their_addr.sin_family = AF_INET; // host byte order + their_addr.sin_port = htons(68); // short, network byte order + their_addr.sin_addr = *((struct in_addr *)he->h_addr); + } else { + their_addr.sin_family = AF_INET; // host byte order + their_addr.sin_port = htons(68); // short, network byte order + their_addr.sin_addr.s_addr = 0xFFFFFFFF; + } + + fprintf( stdout, "IP a buscar: %s \n", name ); + memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct + + if ((numbytes=sendto(sockfd, dhcpm, sizeof(DHCPMESSAGE), 0, + (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) { + perror("sendto"); + exit(1); + } + + printf("sent %d bytes to %s\n", numbytes, + inet_ntoa(their_addr.sin_addr)); + + close(sockfd); + + fprintf( stdout, "write_packet [end]\n" ); + + return 0; +} diff --git a/modules/rosapps/applications/net/dhcpd/src/utils/iputils.c b/modules/rosapps/applications/net/dhcpd/src/utils/iputils.c new file mode 100644 index 00000000000..1b605c3bc60 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/utils/iputils.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +int split_ip( char *text, u8b *dest, int place ) +{ + int dotcount; + + /* Don't touch this, unless you like pointer aritmethic */ + + *dest = 0; + + if( !text ) + return -1; + + for( dotcount = 0; (dotcount < place) && ( text ); text++ ) + if( *text == '.' ) + dotcount++; + + if( !text ) + return -2; + + while(( *text != '.' ) && ( *text != '\0' )) + { + *dest *= 10; + *dest += (u8b)(*text-48); + /* 48 is not a hack, is just the code of 0 */ + text++; + } + + return 0; +} + +int get_ip( char *text, u32b *dest ) +{ + /* Don't touch this, unless you like pointer aritmethic */ + + *dest = 0; + + if( !text ) + return -1; + + while( *text != '\0' ) + { + if( *text == '.' ) + { + *dest = *dest << 8; + text++; + continue; + } + *dest *= 10; + *dest += (u8b)(*text-48); + /* 48 is not a hack, is just the code of 0 */ + text++; + } + + return 0; +} diff --git a/modules/rosapps/applications/net/dhcpd/src/utils/macutils.c b/modules/rosapps/applications/net/dhcpd/src/utils/macutils.c new file mode 100644 index 00000000000..e4601348c9e --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/utils/macutils.c @@ -0,0 +1,46 @@ +#include +#include + +int maccpy( u8b dest[16], u8b source[16] ) +{ + int i; + for( i = 0; i < 16; i++ ) + dest[i] = source[i]; + return 0; +} + +int maccmp( u8b dest[16], u8b source[16] ) +{ + int i; + char equal = 0; + + for( i = 0; i < 16; i++ ) + if( dest[i] != source[i] ) + equal = -1; + + return equal; +} + +int str2mac( u8b from[17], u8b to[16] ) +{ + int i, j, length; + u8b buffer; + u8b dif; + + length = (int)strlen( from ); + + for( i = 0, j = 0; i < length; ) + { + buffer = 0; + while( (from[i] != ':' ) && (from[i]!= '\0' )) + { + buffer = buffer << 4; + (from[i]>57)?(dif=55):(dif=48); + buffer += (from[i] - dif); + i++; + } + to[j++] = buffer; + i++; + } + return 0; +} diff --git a/modules/rosapps/applications/net/dhcpd/src/utils/macutils.h b/modules/rosapps/applications/net/dhcpd/src/utils/macutils.h new file mode 100644 index 00000000000..2c80dc6ad5b --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/utils/macutils.h @@ -0,0 +1,8 @@ +#ifndef MACUTILS_H +#define MACUTILS_H + +int maccmp( u8b *, u8b *); +int maccpy( u8b *, u8b *); +int str2mac( u8b *, u8b * ); + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/utils/utils.h b/modules/rosapps/applications/net/dhcpd/src/utils/utils.h new file mode 100644 index 00000000000..74200279361 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/utils/utils.h @@ -0,0 +1,6 @@ +#ifndef UTILS_H +#define UTILS_H + +#include + +#endif diff --git a/modules/rosapps/applications/net/dhcpd/src/utils/wutils.c b/modules/rosapps/applications/net/dhcpd/src/utils/wutils.c new file mode 100644 index 00000000000..f684544f836 --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/src/utils/wutils.c @@ -0,0 +1,9 @@ +#include +#include + +u8b try_lock( u8b *key ) +{ + if( *key == TRUE ) + return FALSE; + return TRUE; +} diff --git a/modules/rosapps/applications/net/dhcpd/stamp-h b/modules/rosapps/applications/net/dhcpd/stamp-h new file mode 100644 index 00000000000..9788f70238c --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/stamp-h @@ -0,0 +1 @@ +timestamp diff --git a/modules/rosapps/applications/net/dhcpd/stamp-h.in b/modules/rosapps/applications/net/dhcpd/stamp-h.in new file mode 100644 index 00000000000..9788f70238c --- /dev/null +++ b/modules/rosapps/applications/net/dhcpd/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/modules/rosapps/applications/net/directory.rbuild b/modules/rosapps/applications/net/directory.rbuild new file mode 100644 index 00000000000..e9035a459e9 --- /dev/null +++ b/modules/rosapps/applications/net/directory.rbuild @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/rosapps/applications/net/ncftp/LICENSE.txt b/modules/rosapps/applications/net/ncftp/LICENSE.txt new file mode 100644 index 00000000000..04a3311f536 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/LICENSE.txt @@ -0,0 +1,137 @@ + The Clarified Artistic License + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Distribution fee" is a fee you charge for providing a copy + of this Package to another party. + + "Freely Available" means that no fee is charged for the right to + use the item, though there may be fees involved in handling the + item. It also means that recipients of the item may redistribute + it under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain, or those made Freely Available, or from +the Copyright Holder. A Package modified in such a way shall still be +considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major network + archive site allowing unrestricted access to them, or by allowing the + Copyright Holder to include your modifications in the Standard Version + of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + + e) permit and encourge anyone who receives a copy of the modified Package + permission to make your modifications Freely Available + in some specific way. + + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + + e) offer the machine-readable source of the Package, with your + modifications, by mail order. + +5. You may charge a distribution fee for any distribution of this Package. +If you offer support for this Package, you may charge any fee you choose +for that support. You may not charge a license fee for the right to use +this Package itself. You may distribute this Package in aggregate with +other (possibly commercial and possibly nonfree) programs as part of a +larger (possibly commercial and possibly nonfree) software distribution, +and charge license fees for other parts of that software distribution, +provided that you do not advertise this Package as a product of your own. +If the Package includes an interpreter, You may embed this Package's +interpreter within an executable of yours (by linking); this shall be +construed as a mere form of aggregation, provided that the complete +Standard Version of the interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of the Standard Version of the Package with a commercial +distribution is always permitted provided that the use of this Package +is embedded; that is, when no overt attempt is made to make this Package's +interfaces visible to the end user of the commercial distribution. +Such use shall not be construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End + diff --git a/modules/rosapps/applications/net/ncftp/Strn/Dynscat.c b/modules/rosapps/applications/net/ncftp/Strn/Dynscat.c new file mode 100644 index 00000000000..a34137995f8 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/Strn/Dynscat.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include "Strn.h" + +/*VARARGS*/ +char * +Dynscat(char **dst, ...) +{ + va_list ap; + const char *src; + char *newdst, *dcp; + size_t curLen, catLen, srcLen; + + if (dst == (char **) 0) + return NULL; + + catLen = 0; + va_start(ap, dst); + src = va_arg(ap, char *); + while (src != NULL) { + catLen += strlen(src); + src = va_arg(ap, char *); + } + va_end(ap); + + if ((*dst == NULL) || (**dst == '\0')) + curLen = 0; + else + curLen = strlen(*dst); + + if (*dst == NULL) + newdst = malloc(curLen + catLen + 2); + else + newdst = realloc(*dst, curLen + catLen + 2); + if (newdst == NULL) + return NULL; + + dcp = newdst + curLen; + va_start(ap, dst); + src = va_arg(ap, char *); + while (src != NULL) { + srcLen = strlen(src); + memcpy(dcp, src, srcLen); + dcp += srcLen; + src = va_arg(ap, char *); + } + va_end(ap); + *dcp = '\0'; + + *dst = newdst; + return (newdst); +} /* Dynscat */ diff --git a/modules/rosapps/applications/net/ncftp/Strn/Makefile.in b/modules/rosapps/applications/net/ncftp/Strn/Makefile.in new file mode 100644 index 00000000000..e7135490ff2 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/Strn/Makefile.in @@ -0,0 +1,115 @@ +# +# Strn makefile +# +VER=2.2.0 +PREFIX=@prefix@ +MAN=@prefix@/man +SHELL=/bin/sh +.SUFFIXES: .c .o .so +LIB=libStrn.a +LIBSO=libStrn.so.1 +LIBSOS=libStrn.so +CC=@CC@ +CPPFLAGS= +#CFLAGS=-O2 +CFLAGS=@CFLAGS@ +DEFS=-DSTRNP_ZERO_PAD=0 -DSTRN_ZERO_PAD=1 + +OBJS=Dynscat.o Strncpy.o Strncat.o Strntok.o Strnpcpy.o Strnpcat.o strtokc.o version.o +SOBJS=Dynscat.so Strncpy.so Strncat.so Strntok.so Strnpcpy.so Strnpcat.so strtokc.so version.so + +all: static + -@echo "Done making Strn." + +static: $(LIB) + +$(LIB): $(OBJS) + ar rv $(LIB) $(OBJS) + chmod 644 "$(LIB)" + -ranlib "$(LIB)" + echo "$(VER)" > Strn.version + -@/bin/ls -l "$(LIB)" + +.c.o: + $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c + +.c.so: + $(CC) -fpic $(CFLAGS) $(CPPFLAGS) $(DEFS) $*.c -c -o $*.so + +dynamic: $(LIBSO) + +shared: $(LIBSO) + +so: $(LIBSO) + +$(LIBSO): $(SOBJS) + /bin/rm -f "$(LIBSO)" + gcc -shared "-Wl,-soname,$(LIBSO)" -o "$(LIBSO)" $(SOBJS) + /bin/ln -s "$(LIBSO)" "$(LIBSOS)" + -@/bin/ls -l "$(LIBSOS)" "$(LIBSO)" + +soinstall: $(LIBSO) + cp "$(LIBSO)" "$(PREFIX)/lib/$(LIBSO)" + ( cd "$(PREFIX)/lib" ; /bin/ln -s "$(LIBSO)" "$(LIBSOS)" ) + cp Strn.h "$(PREFIX)/include/Strn.h" + -chmod a+r "$(PREFIX)/lib/$(LIBSO)" "$(PREFIX)/include/Strn.h" + +tester: $(LIB) tester.c + $(CC) $(CFLAGS) tester.c -o tester -I. -L. -lStrn + +clean: + /bin/rm -f "$(LIB)" "$(LIBSO)" $(OBJS) $(SOBJS) + +install: + if test ! -d $(PREFIX)/include ; then mkdir -p "$(PREFIX)/include" ; fi + if test ! -d $(PREFIX)/lib ; then mkdir -p "$(PREFIX)/lib" ; fi + cp "$(LIB)" Strn.version "$(PREFIX)/lib" + cp Strn.h "$(PREFIX)/include/Strn.h" + -chmod 664 "$(PREFIX)/include/Strn.h" "$(PREFIX)/lib/Strn.version" "$(PREFIX)/lib/$(LIB)" + -cp Strn.3 "$(MAN)/man3/Strn.3" + -chmod 664 "$(MAN)/man3/Strn.3" + -ln "$(MAN)/man3/Strn.3" "$(MAN)/man3/Strncpy.3" + -ln "$(MAN)/man3/Strn.3" "$(MAN)/man3/Strncat.3" + +uninstall: + /bin/rm -f "$(PREFIX)/lib/$(LIB)" "$(PREFIX)/include/Strn.h" + +PACKAGE=configure Makefile.in configure.in Strn.dsp Strn.dsw Dynscat.c Strncpy.c Strncat.c Strnpcpy.c Strnpcat.c Strntok.c strtokc.c Strn.h Strn.3 tester.c version.c Strn.version + +TMPDIR=/tmp +TARDIR=Strn +TARFILE=$(TARDIR).tar +TGZFILE=$(TARDIR).tgz + +tarcp: + -@mkdir -p $(TMPDIR)/TAR/$(TARDIR) + -@chmod ga+r $(PACKAGE) + -@chmod 755 $(TMPDIR)/TAR/$(TARDIR) + cp -pr $(PACKAGE) $(TMPDIR)/TAR/$(TARDIR) + +tar: $(PACKAGE) + -@mkdir $(TMPDIR)/TAR + -@mkdir $(TMPDIR)/TAR/$(TARDIR) + -@chmod ga+r $(PACKAGE) + -@chmod 755 $(TMPDIR)/TAR/$(TARDIR) + cp -pr $(PACKAGE) $(TMPDIR)/TAR/$(TARDIR) + ( cd $(TMPDIR)/TAR ; tar cf $(TARFILE) ./$(TARDIR) ) + cp $(TMPDIR)/TAR/$(TARFILE) . + -@chmod 644 $(TARFILE) + -@rm -rf $(TMPDIR)/TAR + -@ls -l $(TARFILE) + +gz: tar + gzip -c $(TARFILE) > $(TGZFILE) + -@rm $(TARFILE) + -@chmod 644 $(TGZFILE) + -@ls -l $(TGZFILE) + +Dynscat.o: Dynscat.c Strn.h +Strncat.o: Strncat.c Strn.h +Strncpy.o: Strncpy.c Strn.h +Strnpcat.o: Strnpcat.c Strn.h +Strnpcpy.o: Strnpcpy.c Strn.h +Strntok.o: Strntok.c Strn.h +strtokc.o: strtokc.c Strn.h +version.o: version.c diff --git a/modules/rosapps/applications/net/ncftp/Strn/Strn.h b/modules/rosapps/applications/net/ncftp/Strn/Strn.h new file mode 100644 index 00000000000..3f8be368340 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/Strn/Strn.h @@ -0,0 +1,52 @@ +/* Strn.h */ + +#ifndef _Strn_h_ +#define _Strn_h_ 1 + +/* You should define this from the Makefile. */ +#ifndef STRN_ZERO_PAD +# define STRN_ZERO_PAD 1 +#endif + +/* You should define this from the Makefile. */ +#ifndef STRNP_ZERO_PAD +# define STRNP_ZERO_PAD 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Strncat.c */ +char *Strncat(char *const, const char *const, const size_t); + +/* Strncpy.c */ +char *Strncpy(char *const, const char *const, const size_t); + +/* Strnpcat.c */ +char *Strnpcat(char *const, const char *const, size_t); + +/* Strnpcpy.c */ +char *Strnpcpy(char *const, const char *const, size_t); + +/* Strntok.c */ +char *Strtok(char *, const char *); +int Strntok(char *, size_t, char *, const char *); + +/* strtokc.c */ +char *strtokc(char *, const char *, char **); +int strntokc(char *, size_t, char *, const char *, char **); + +/* Dynscat.c */ +char * Dynscat(char **dst, ...); + +#ifdef __cplusplus +} +#endif + +#define STRNCPY(d,s) Strncpy((d), (s), (size_t) sizeof(d)) +#define STRNCAT(d,s) Strncat((d), (s), (size_t) sizeof(d)) + +#endif /* _Strn_h_ */ + +/* eof Strn.h */ diff --git a/modules/rosapps/applications/net/ncftp/Strn/Strncat.c b/modules/rosapps/applications/net/ncftp/Strn/Strncat.c new file mode 100644 index 00000000000..051555588f6 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/Strn/Strncat.c @@ -0,0 +1,44 @@ +#include +#include +#include "Strn.h" + +/* + * Concatenate src on the end of dst. The resulting string will have at most + * n-1 characters, not counting the NUL terminator which is always appended + * unlike strncat. The other big difference is that strncpy uses n as the + * max number of characters _appended_, while this routine uses n to limit + * the overall length of dst. + */ +char * +Strncat(char *const dst, const char *const src, const size_t n) +{ + register size_t i; + register char *d; + register const char *s; + + if (n != 0 && ((i = strlen(dst)) < (n - 1))) { + d = dst + i; + s = src; + /* If they specified a maximum of n characters, use n - 1 chars to + * hold the copy, and the last character in the array as a NUL. + * This is the difference between the regular strncpy routine. + * strncpy doesn't guarantee that your new string will have a + * NUL terminator, but this routine does. + */ + for (++i; i +#include +#include "Strn.h" + + +/* + * Copy src to dst, truncating or null-padding to always copy n-1 bytes. + * Return dst. + */ +char * +Strncpy(char *const dst, const char *const src, const size_t n) +{ + register char *d; + register const char *s; + register size_t i; + + d = dst; + *d = 0; + if (n != 0) { + s = src; + /* If they specified a maximum of n characters, use n - 1 chars to + * hold the copy, and the last character in the array as a NUL. + * This is the difference between the regular strncpy routine. + * strncpy doesn't guarantee that your new string will have a + * NUL terminator, but this routine does. + */ + for (i=1; i +#include +#include "Strn.h" + +/* + * Concatenate src on the end of dst. The resulting string will have at most + * n-1 characters, not counting the NUL terminator which is always appended + * unlike strncat. The other big difference is that strncpy uses n as the + * max number of characters _appended_, while this routine uses n to limit + * the overall length of dst. + * + * This routine also differs in that it returns a pointer to the end + * of the buffer, instead of strncat which returns a pointer to the start. + */ +char * +Strnpcat(char *const dst, const char *const src, size_t n) +{ + register size_t i; + register char *d; + register const char *s; + register char c; + char *ret; + + if (n != 0 && ((i = strlen(dst)) < (n - 1))) { + d = dst + i; + s = src; + /* If they specified a maximum of n characters, use n - 1 chars to + * hold the copy, and the last character in the array as a NUL. + * This is the difference between the regular strncpy routine. + * strncpy doesn't guarantee that your new string will have a + * NUL terminator, but this routine does. + */ + for (++i; i +#include +#include "Strn.h" + +/* + * Copy src to dst, truncating or null-padding to always copy n-1 bytes. + * + * This routine differs from strncpy in that it returns a pointer to the end + * of the buffer, instead of strncat which returns a pointer to the start. + */ +char * +Strnpcpy(char *const dst, const char *const src, size_t n) +{ + register char *d; + register const char *s; + register char c; + char *ret; + register size_t i; + + d = dst; + if (n != 0) { + s = src; + /* If they specified a maximum of n characters, use n - 1 chars to + * hold the copy, and the last character in the array as a NUL. + * This is the difference between the regular strncpy routine. + * strncpy doesn't guarantee that your new string will have a + * NUL terminator, but this routine does. + */ + for (i=1; i +#include "Strn.h" + +/* This version of Strtok differs from the regular ANSI strtok in that + * an empty token can be returned, and consecutive delimiters are not + * ignored like ANSI does. Example: + * + * Parse String = ",,mike,gleason,-West Interactive,402-573-1000" + * Delimiters = ",-" + * + * (ANSI strtok:) + * strtok 1=[mike] length=4 + * strtok 2=[gleason] length=7 + * strtok 3=[West Interactive] length=16 + * strtok 4=[402] length=3 + * strtok 5=[573] length=3 + * strtok 6=[1000] length=4 + * + * (Strtok:) + * Strtok 1=[] length=0 + * Strtok 2=[] length=0 + * Strtok 3=[mike] length=4 + * Strtok 4=[gleason] length=7 + * Strtok 5=[] length=0 + * Strtok 6=[West Interactive] length=16 + * Strtok 7=[402] length=3 + * Strtok 8=[573] length=3 + * Strtok 9=[1000] length=4 + * + */ + +char * +Strtok(char *buf, const char *delims) +{ + static char *p = NULL; + char *start, *end; + + if (buf != NULL) { + p = buf; + } else { + if (p == NULL) + return (NULL); /* No more tokens. */ + } + for (start = p, end = p; ; end++) { + if (*end == '\0') { + p = NULL; /* This is the last token. */ + break; + } + if (strchr(delims, (int) *end) != NULL) { + *end++ = '\0'; + p = end; + break; + } + } + return (start); +} /* Strtok */ + + + + +/* This is a bounds-safe version of Strtok, where you also pass a pointer + * to the token to write into, and its size. Using the example above, + * with a char token[8], you get the following. Notice that the token + * is not overrun, and is always nul-terminated: + * + * Strntok 1=[] length=0 + * Strntok 2=[] length=0 + * Strntok 3=[mike] length=4 + * Strntok 4=[gleason] length=7 + * Strntok 5=[] length=0 + * Strntok 6=[West In] length=7 + * Strntok 7=[402] length=3 + * Strntok 8=[573] length=3 + * Strntok 9=[1000] length=4 + */ + +int +Strntok(char *dstTokenStart, size_t tokenSize, char *buf, const char *delims) +{ + static char *p = NULL; + char *end; + char *lim; + char *dst; + int len; + + dst = dstTokenStart; + lim = dst + tokenSize - 1; /* Leave room for nul byte. */ + + if (buf != NULL) { + p = buf; + } else { + if (p == NULL) { + *dst = '\0'; + return (-1); /* No more tokens. */ + } + } + + for (end = p; ; end++) { + if (*end == '\0') { + p = NULL; /* This is the last token. */ + break; + } + if (strchr(delims, (int) *end) != NULL) { + ++end; + p = end; + break; + } + if (dst < lim) /* Don't overrun token size. */ + *dst++ = *end; + } + *dst = '\0'; + len = (int) (dst - dstTokenStart); /* Return length of token. */ + +#if (STRN_ZERO_PAD == 1) + /* Pad with zeros. */ + for (++dst; dst <= lim; ) + *dst++ = 0; +#endif /* STRN_ZERO_PAD */ + + return (len); +} /* Strntok */ + + + +#ifdef TESTING_STRTOK +#include + +void +main(int argc, char **argv) +{ + char buf[256]; + int i; + char *t; + char token[8]; + int tokenLen; + + if (argc < 3) { + fprintf(stderr, "Usage: test \"buffer,with,delims\" \n"); + exit(1); + } + strcpy(buf, argv[1]); + i = 1; + t = strtok(buf, argv[2]); + if (t == NULL) + exit(0); + do { + printf("strtok %d=[%s] length=%d\n", i, t, (int) strlen(t)); + t = strtok(NULL, argv[2]); + ++i; + } while (t != NULL); + + printf("------------------------------------------------\n"); + strcpy(buf, argv[1]); + i = 1; + t = Strtok(buf, argv[2]); + if (t == NULL) + exit(0); + do { + printf("Strtok %d=[%s] length=%d\n", i, t, (int) strlen(t)); + t = Strtok(NULL, argv[2]); + ++i; + } while (t != NULL); + + printf("------------------------------------------------\n"); + strcpy(buf, argv[1]); + i = 1; + tokenLen = Strntok(token, sizeof(token), buf, argv[2]); + if (tokenLen < 0) + exit(0); + do { + printf("Strntok %d=[%s] length=%d\n", i, token, tokenLen); + tokenLen = Strntok(token, sizeof(token), NULL, argv[2]); + ++i; + } while (tokenLen >= 0); + exit(0); +} +#endif diff --git a/modules/rosapps/applications/net/ncftp/Strn/config.h.in b/modules/rosapps/applications/net/ncftp/Strn/config.h.in new file mode 100644 index 00000000000..2122b45102e --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/Strn/config.h.in @@ -0,0 +1,10 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS diff --git a/modules/rosapps/applications/net/ncftp/Strn/configure.in b/modules/rosapps/applications/net/ncftp/Strn/configure.in new file mode 100644 index 00000000000..be5b9460009 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/Strn/configure.in @@ -0,0 +1,19 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(Strn.h) +wi_ARG_ENABLE_DEBUG + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_LN_S +AC_PROG_RANLIB + +dnl Checks for header files. +AC_HEADER_STDC + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +dnl Checks for library functions. + +AC_OUTPUT(Makefile) diff --git a/modules/rosapps/applications/net/ncftp/Strn/strtokc.c b/modules/rosapps/applications/net/ncftp/Strn/strtokc.c new file mode 100644 index 00000000000..ee1841d2869 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/Strn/strtokc.c @@ -0,0 +1,240 @@ +/* strtokc.c */ + +#include +#include "Strn.h" + +char * +strtokc(char *parsestr, const char *delims, char **context) +{ + char *cp; + const char *cp2; + char c, c2; + char *start; + + if (parsestr == NULL) + start = *context; + else + start = parsestr; + + if ((start == NULL) || (delims == NULL)) { + *context = NULL; + return NULL; + } + + /* Eat leading delimiters. */ + for (cp = start; ; ) { +next1: + c = *cp++; + if (c == '\0') { + /* No more tokens. */ + *context = NULL; + return (NULL); + } + for (cp2 = delims; ; ) { + c2 = (char) *cp2++; + if (c2 == '\0') { + /* This character was not a delimiter. + * The token starts here. + */ + start = cp - 1; + goto starttok; + } + if (c2 == c) { + /* This char was a delimiter. */ + /* Skip it, look at next character. */ + goto next1; + } + } + /*NOTREACHED*/ + } + +starttok: + for ( ; ; cp++) { + c = *cp; + if (c == '\0') { + /* Token is finished. */ + *context = cp; + break; + } + for (cp2 = delims; ; ) { + c2 = (char) *cp2++; + if (c2 == '\0') { + /* This character was not a delimiter. + * Keep it as part of current token. + */ + break; + } + if (c2 == c) { + /* This char was a delimiter. */ + /* End of token. */ + *cp++ = '\0'; + *context = cp; + return (start); + } + } + } + return (start); +} /* strtokc */ + + + + +/* Same as strtokc, only you specify the destination buffer to write + * the token in along with its size. strntokc will write to the dst + * buffer, always nul-terminating it. + * + * It also returns the length of the token, or zero if there was no + * token. This differs from strtokc, which returns a pointer to the + * token or NULL for no token. + */ + +int +strntokc(char *dstTokenStart, size_t tokenSize, char *parsestr, const char *delims, char **context) +{ + char *cp; + const char *cp2; + char c, c2; + char *start; + int len; + char *dst, *lim; + + dst = dstTokenStart; + lim = dst + tokenSize - 1; /* Leave room for nul byte. */ + + if (parsestr == NULL) + start = *context; + else + start = parsestr; + + if ((start == NULL) || (delims == NULL)) { + *context = NULL; + goto done; + } + + /* Eat leading delimiters. */ + for (cp = start; ; ) { +next1: + c = *cp++; + if (c == '\0') { + /* No more tokens. */ + *context = NULL; + goto done; + } + for (cp2 = delims; ; ) { + c2 = (char) *cp2++; + if (c2 == '\0') { + /* This character was not a delimiter. + * The token starts here. + */ + start = cp - 1; + if (dst < lim) + *dst++ = c; + goto starttok; + } + if (c2 == c) { + /* This char was a delimiter. */ + /* Skip it, look at next character. */ + goto next1; + } + } + /*NOTREACHED*/ + } + +starttok: + for ( ; ; cp++) { + c = *cp; + if (c == '\0') { + /* Token is finished. */ + *context = cp; + break; + } + for (cp2 = delims; ; ) { + c2 = (char) *cp2++; + if (c2 == '\0') { + /* This character was not a delimiter. + * Keep it as part of current token. + */ + break; + } + if (c2 == c) { + /* This char was a delimiter. */ + /* End of token. */ + *cp++ = '\0'; + *context = cp; + goto done; + } + } + if (dst < lim) /* Don't overrun token size. */ + *dst++ = c; + } + +done: + *dst = '\0'; + len = (int) (dst - dstTokenStart); /* Return length of token. */ + +#if (STRN_ZERO_PAD == 1) + /* Pad with zeros. */ + for (++dst; dst <= lim; ) + *dst++ = 0; +#endif /* STRN_ZERO_PAD */ + + return (len); +} /* strntokc */ + + + + +#ifdef TESTING_STRTOK +#include + +void +main(int argc, char **argv) +{ + char buf[256]; + int i; + char *t; + char token[8]; + int tokenLen; + char *context; + + if (argc < 3) { + fprintf(stderr, "Usage: test \"buffer,with,delims\" \n"); + exit(1); + } + strcpy(buf, argv[1]); + i = 1; + t = strtok(buf, argv[2]); + if (t == NULL) + exit(0); + do { + printf("strtok %d=[%s] length=%d\n", i, t, (int) strlen(t)); + t = strtok(NULL, argv[2]); + ++i; + } while (t != NULL); + + printf("------------------------------------------------\n"); + strcpy(buf, argv[1]); + i = 1; + t = strtokc(buf, argv[2], &context); + if (t == NULL) + exit(0); + do { + printf("strtokc %d=[%s] length=%d\n", i, t, (int) strlen(t)); + t = strtokc(NULL, argv[2], &context); + ++i; + } while (t != NULL); + + printf("------------------------------------------------\n"); + strcpy(buf, argv[1]); + i = 1; + tokenLen = strntokc(token, sizeof(token), buf, argv[2], &context); + if (tokenLen <= 0) + exit(0); + do { + printf("strntokc %d=[%s] length=%d\n", i, token, tokenLen); + tokenLen = strntokc(token, sizeof(token), NULL, argv[2], &context); + ++i; + } while (tokenLen > 0); + exit(0); +} +#endif diff --git a/modules/rosapps/applications/net/ncftp/Strn/tester.c b/modules/rosapps/applications/net/ncftp/Strn/tester.c new file mode 100644 index 00000000000..66e3034f53d --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/Strn/tester.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + char a[8]; + char pad1[32]; + char *b; + char c[37]; + char pad2[23]; + int i; + int len1, len2; + + b = Strncpy(a, "hello", sizeof(a)); + b = Strncat(b, "world", sizeof(a)); + printf("1: result=[%s] should be=[%s]\n", + b, + "hellowo" + ); + + for (i=0; i. */ +#undef DGUX + +/* Define if you have . */ +#undef DIRENT + +/* Define to the type of elements in the array set by `getgroups'. + Usually this is either `int' or `gid_t'. */ +#undef GETGROUPS_T + +/* Define if the `getloadavg' function needs to be run setuid or setgid. */ +#undef GETLOADAVG_PRIVILEGED + +/* Define if the `getpgrp' function takes no argument. */ +#undef GETPGRP_VOID + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if your curses library has this functionality. */ +#undef HAVE_BEEP + +#undef HAVE_CURSES_H + +/* Define if you don't have vprintf but do have _doprnt. */ +#undef HAVE_DOPRNT + +/* Define if your system has a working fnmatch function. */ +#undef HAVE_FNMATCH + +/* Define if your curses library has this functionality. */ +#undef HAVE_GETBEGX + +/* Define if your system has its own `getloadavg' function. */ +#undef HAVE_GETLOADAVG + +/* Define if your curses library has this functionality. */ +#undef HAVE_GETMAXX + +/* Define if your curses library has this functionality. */ +#undef HAVE_GETMAXYX + +/* Define if you have the getmntent function. */ +#undef HAVE_GETMNTENT + +/* Define if you have . */ +#undef HAVE_HPSECURITY_H + +/* Define if you have the curses library. */ +#undef HAVE_LIBCURSES + +/* Define if you want to use the Hpwd library, and you also have it's corresponding database library (such as *dbm). */ +#undef HAVE_LIBHPWD + +/* Define if you have the ncurses library. */ +#undef HAVE_LIBNCURSES + +/* Define if you have the readline library, version 2.0 or higher. */ +#undef HAVE_LIBREADLINE + +/* Define if the `long double' type works. */ +#undef HAVE_LONG_DOUBLE + +/* Define if you support file names longer than 14 characters. */ +#undef HAVE_LONG_FILE_NAMES + +/* Define if your compiler supports the "long long" integral type. */ +#undef HAVE_LONG_LONG + +/* Most system's curses library uses a _maxx field instead of maxx. */ +#undef HAVE__MAXX + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +#undef HAVE_MSGHDR_ACCRIGHTS + +#undef HAVE_MSGHDR_CONTROL + +#undef HAVE_PR_PASSWD_FG_OLDCRYPT + +/* Define if you have a _res global variable used by resolve routines. */ +#undef HAVE__RES_DEFDNAME + +/* Define if system calls automatically restart after interruption + by a signal. */ +#undef HAVE_RESTARTABLE_SYSCALLS + +/* Define if you have sigsetjmp and siglongjmp. */ +#undef HAVE_SIGSETJMP + +#undef HAVE_SOCKADDR_UN_SUN_LEN + +#undef HAVE_STATFS_F_BAVAIL + +/* Define if your struct stat has st_blksize. */ +#undef HAVE_ST_BLKSIZE + +/* Define if your struct stat has st_blocks. */ +#undef HAVE_ST_BLOCKS + +/* Define if you have the strcoll function and it is properly defined. */ +#undef HAVE_STRCOLL + +/* Define if your struct stat has st_rdev. */ +#undef HAVE_ST_RDEV + +/* Define if you have the strftime function. */ +#undef HAVE_STRFTIME + +/* Define if you have the ANSI # stringizing operator in cpp. */ +#undef HAVE_STRINGIZE + +#undef HAVE_STRUCT_CMSGDHR + +#undef HAVE_STRUCT_STAT64 + +/* Define if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define if your curses library has this functionality. */ +#undef HAVE_TOUCHWIN + +/* Define if your struct tm has tm_zone. */ +#undef HAVE_TM_ZONE + +/* Define if you don't have tm_zone but do have the external array + tzname. */ +#undef HAVE_TZNAME + +/* Define if you have . */ +#undef HAVE_UNISTD_H + +/* Define if utime(file, NULL) sets file's timestamp to the present. */ +#undef HAVE_UTIME_NULL + +/* Define if you have a ut_host field in your struct utmp. */ +#undef HAVE_UTMP_UT_HOST + +#undef HAVE_UTMP_UT_NAME + +#undef HAVE_UTMP_UT_USER + +#undef HAVE_UTMP_UT_PID + +#undef HAVE_UTMP_UT_TIME + +#undef HAVE_UTMPX_UT_SYSLEN + +/* Define if you have . */ +#undef HAVE_VFORK_H + +/* Define if you have the vprintf function. */ +#undef HAVE_VPRINTF + +/* Define if you have the wait3 system call. */ +#undef HAVE_WAIT3 + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define if chown is promiscuous (regular user can give away ownership) */ +#undef INSECURE_CHOWN + +/* Define if int is 16 bits instead of 32. */ +#undef INT_16_BITS + +/* Define if long int is 64 bits. */ +#undef LONG_64_BITS + +/* Define if major, minor, and makedev are declared in . */ +#undef MAJOR_IN_MKDEV + +/* Define if major, minor, and makedev are declared in . */ +#undef MAJOR_IN_SYSMACROS + +/* Define if on MINIX. */ +#undef _MINIX + +/* Define to `int' if doesn't define. */ +#undef mode_t + +/* Define if you don't have , but have . */ +#undef NDIR + +/* Define if you have , and doesn't declare the + mem* functions. */ +#undef NEED_MEMORY_H + +/* Define if your struct nlist has an n_un member. */ +#undef NLIST_NAME_UNION + +/* Define if you have . */ +#undef NLIST_STRUCT + +/* Define if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Define if your Fortran 77 compiler doesn't accept -c and -o together. */ +#undef F77_NO_MINUS_C_MINUS_O + +/* Define to `long' if doesn't define. */ +#undef off_t + +#undef OS + +/* Define to `int' if doesn't define. */ +#undef pid_t + +/* Define if the system does not provide POSIX.1 features except + with this defined. */ +#undef _POSIX_1_SOURCE + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Format string for the printf() family for 64 bit integers. */ +#undef PRINTF_LONG_LONG + +/* Define if printing a "long long" with "%lld" works . */ +#undef PRINTF_LONG_LONG_LLD + +/* Define if printing a "long long" with "%qd" works . */ +#undef PRINTF_LONG_LONG_QD + +/* Define if your C compiler supports ANSI C function prototyping. */ +#undef PROTOTYPES + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Format string for the scanf() family for 64 bit integers. */ +#undef SCANF_LONG_LONG + +/* Define if scanning a "long long" with "%lld" works. */ +#undef SCANF_LONG_LONG_LLD + +/* Define if scanning a "long long" with "%qd" works. */ +#undef SCANF_LONG_LONG_QD + +/* Define to the type of arg1 for select(). */ +#undef SELECT_TYPE_ARG1 + +/* Define to the type of args 2, 3 and 4 for select(). */ +#undef SELECT_TYPE_ARG234 + +/* Define to the type of arg5 for select(). */ +#undef SELECT_TYPE_ARG5 + +/* Define if the `setpgrp' function takes no argument. */ +#undef SETPGRP_VOID + +/* Define if the setvbuf function takes the buffering type as its second + argument and the buffer pointer as the third, as on System V + before release 3. */ +#undef SETVBUF_REVERSED + +/* Define to `int' if doesn't define. */ +#undef sig_atomic_t + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +#undef SNPRINTF_TERMINATES + +#undef SPRINTF_RETURNS_PTR + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define on System V Release 4. */ +#undef SVR4 + +/* Define if you don't have , but have . */ +#undef SYSDIR + +/* Define if you don't have , but have . */ +#undef SYSNDIR + +/* Define if `sys_siglist' is declared by . */ +#undef SYS_SIGLIST_DECLARED + +/* Define to the full path of the Tar program, if you have it. */ +#undef TAR + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define if your declares struct tm. */ +#undef TM_IN_SYS_TIME + +/* Define to `int' if doesn't define. */ +#undef uid_t + +/* Define for Encore UMAX. */ +#undef UMAX + +/* Result of "uname -a" */ +#undef UNAME + +/* Define for Encore UMAX 4.3 that has + instead of . */ +#undef UMAX4_3 + +/* Define if you do not have , index, bzero, etc.. */ +#undef USG + +/* Define vfork as fork if vfork does not work. */ +#undef vfork + +/* Define if the closedir function returns void instead of int. */ +#undef VOID_CLOSEDIR + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Define if the X Window System is missing or not being used. */ +#undef X_DISPLAY_MISSING + +/* Define if lex declares yytext as a char * by default, not a char[]. */ +#undef YYTEXT_POINTER + + +/* Leave that blank line there!! Autoheader needs it. + If you're adding to this file, keep in mind: + The entries are in sort -df order: alphabetical, case insensitive, + ignoring punctuation (such as underscores). */ diff --git a/modules/rosapps/applications/net/ncftp/autoconf/aclocal.m4 b/modules/rosapps/applications/net/ncftp/autoconf/aclocal.m4 new file mode 100644 index 00000000000..1c5a95ee2d5 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/autoconf/aclocal.m4 @@ -0,0 +1,2391 @@ +AC_DEFUN(wi_ARG_ENABLE_DEBUG, [ +# if DEBUGBUILD is yes, other macros try to set up a compilation environment +# with debugging symbols enabled. Example macros which are affected are +# wi_CFLAGS and wi_SFLAG. +# +DEBUGBUILD=no +DEBUGCONFIGUREFLAG="" +AC_ARG_ENABLE(debug, +[ --enable-debug enable debugging symbols], +[ + DEBUGBUILD=yes + DEBUGCONFIGUREFLAG="--enable-debug" +],[ + DEBUGBUILD=no + DEBUGCONFIGUREFLAG="" +]) +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_EXTRA_IDIR, [ +incdir="$1" +if test -r $incdir ; then + case "$CPPFLAGS" in + *${incdir}*) + # echo " + already had $incdir" 1>&6 + ;; + *) + if test "$CPPFLAGS" = "" ; then + CPPFLAGS="-I$incdir" + else + CPPFLAGS="$CPPFLAGS -I$incdir" + fi + echo " + found $incdir" 1>&6 + ;; + esac +fi +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_PROG_TAR, [ +TAR="" +AC_PATH_PROG(TAR, "tar") +if test -x "$TAR" ; then + AC_DEFINE_UNQUOTED(TAR, "$TAR") +fi +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_EXTRA_LDIR, [ +libdir="$1" +if test -r $libdir ; then + case "$LDFLAGS" in + *${libdir}*) + # echo " + already had $libdir" 1>&6 + ;; + *) + if test "$LDFLAGS" = "" ; then + LDFLAGS="-L$libdir" + else + LDFLAGS="$LDFLAGS -L$libdir" + fi + echo " + found $libdir" 1>&6 + ;; + esac +fi +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_GNU_LD, [ +AC_MSG_CHECKING([for GNU ld]) +wi_cv_prog_ld="ld" +result="no" +x=`ld --version 2>/dev/null | fgrep GNU` +if test "$x" != "" ; then + wi_cv_prog_ld="gld" + result="yes" +fi +AC_MSG_RESULT($result) +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_LD_READONLY_TEXT, [ +if test "$SYS$wi_cv_prog_ld" = "linuxgld" ; then + LDFLAGS="$LDFLAGS -Xlinker -n" +fi +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_EXTRA_SYSV_SUNOS_DIRS, [ +AC_MSG_CHECKING([for System V compatibility directories]) +AC_MSG_RESULT([]) +wi_EXTRA_IDIR("/usr/5include") +wi_EXTRA_LDIR("/usr/5lib") +]) +dnl +dnl +dnl If you want to also look for include and lib subdirectories in the +dnl $HOME tree, you supply "yes" as the first argument to this macro. +dnl +dnl If you want to look for subdirectories in include/lib directories, +dnl you pass the names in argument 3, otherwise pass a dash. +dnl +AC_DEFUN(wi_EXTRA_DIRS, [ +AC_MSG_CHECKING([for extra include and lib directories]) +AC_MSG_RESULT([]) +ifelse([$1], yes, [dnl +b1=`cd .. ; pwd` +b2=`cd ../.. ; pwd` +exdirs="$HOME $j $b1 $b2 $prefix $2" +if test -x "$HOME/bin/OS" ; then + b3=`$HOME/bin/OS` + b3="$HOME/$b3" + if test -d "$b3" ; then + exdirs="$b3 $exdirs" + fi +fi +],[dnl +exdirs="$prefix $2" +]) +subexdirs="$3" +if test "$subexdirs" = "" ; then + subexdirs="-" +fi +for subexdir in $subexdirs ; do +if test "$subexdir" = "-" ; then + subexdir="" +else + subexdir="/$subexdir" +fi +for exdir in $exdirs ; do + case "$exdir" in + "/usr"|"/"|"//") + if test "$exdir" = "//" ; then exdir="/" ; fi + if test "$subexdir" != ""; then + incdir="${exdir}/include${subexdir}" + wi_EXTRA_IDIR($incdir) + + libdir="${exdir}/lib${subexdir}" + wi_EXTRA_LDIR($libdir) + fi + ;; + *) + if test "$subexdir" = ""; then + incdir="${exdir}/include${subexdir}" + wi_EXTRA_IDIR($incdir) + + libdir="${exdir}/lib${subexdir}" + wi_EXTRA_LDIR($libdir) + fi + ;; + esac +done +done +]) +dnl +dnl +dnl +AC_DEFUN(wi_HPUX_CFLAGS, +[AC_MSG_CHECKING(if HP-UX ansi C compiler flags are needed) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([wi_OS_VAR]) +ac_cv_hpux_flags=no +if test "$os" = hp-ux ; then + if test "$ac_cv_prog_gcc" = yes ; then + if test "$CFLAGS" != "" ; then + # Shouldn't be in there. +changequote(<<, >>)dnl + CFLAGS=`echo "$CFLAGS" | sed 's/-A[ae]//g'` +changequote([, ])dnl + case "$CFLAGS" in + *_HPUX_SOURCE*) + ;; + *) + # This is required for the extended + # namespace. + # + CFLAGS="-D_HPUX_SOURCE $CFLAGS" + ;; + esac + fi + else + # If you're not using gcc, then you better have a cc/c89 + # that is usable. If you have the barebones compiler, it + # won't work. The good compiler uses -Aa for the ANSI + # compatible stuff. +changequote(<<, >>)dnl + x=`echo "$CFLAGS" | grep 'A[ae]' 2>/dev/null` +changequote([, ])dnl + if test "$x" = "" ; then + CFLAGS="$CFLAGS -Ae" + fi + fi + ac_cv_hpux_flags=yes +fi +AC_MSG_RESULT($ac_cv_hpux_flags) +]) +dnl +dnl +dnl +AC_DEFUN(wi_SFLAG, [AC_REQUIRE([AC_PROG_CC]) +STRIP="strip" +if test "$SFLAG" = "" ; then + SFLAG="-s" + case "$OS" in + macosx*) + SFLAG='-Wl,-x' + ;; + esac +fi +# +# Was it ./configure --enable-debug ? +# +if test "$DEBUGBUILD" = yes ; then + SFLAG="" + STRIP=":" +fi +case "$CFLAGS" in + "-g"|"-g "*|*" -g"|*" -g "*|*"-g"[0-9]*) + # SFLAG="# $SFLAG" + SFLAG="" + STRIP=":" + ;; +esac +STRIPFLAG="$SFLAG" +]) +dnl +dnl +dnl +AC_DEFUN(wi_REQUEST_NO_Y2K_WARNINGS, [ + wi_cv_request_no_y2k=yes +]) +dnl +dnl +dnl +AC_DEFUN(wi_CFLAGS_NO_Y2K_WARNINGS, [AC_REQUIRE([AC_PROG_CC]) +if test "$ac_cv_prog_gcc" = yes ; then + case "$CFLAGS" in + *-Wno-format-y2k*) + ;; + *) + oldCFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wno-format-y2k" + # + # Now check if this version of GCC + # accepts this flag... + # +AC_TRY_COMPILE([],[int junk;],[],[CFLAGS="$oldCFLAGS"]) + unset oldCFLAGS + ;; + esac +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_CFLAGS, [AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE_CPP() +wi_HPUX_CFLAGS + if test "$CFLAGS" = "" ; then + AC_MSG_WARN([Your CFLAGS environment variable was not set. A default of \"-g\" will be used.]) + CFLAGS="-g" + fi + if test "x$wi_cv_request_no_y2k" = xyes ; then + wi_CFLAGS_NO_Y2K_WARNINGS + fi + if test "$NOOPTCFLAGS" = "" ; then +changequote(<<, >>)dnl + NOOPTCFLAGS=`echo "$CFLAGS" | sed 's/[-+]O[0-9A-Za-z]*//g;s/-xO[0-9]//g;s/-Wc,-O3//g;s/-IPA//g;s/\ \ */ /g;s/^\ *//;s/\ *$//;'` +changequote([, ])dnl + fi + if test "$DEBUGCFLAGS" = "" ; then + DEBUGCFLAGS="-g $NOOPTCFLAGS" + fi + # + # Was it ./configure --enable-debug ? + # + AC_MSG_CHECKING([if this is a debug build]) + if test "$DEBUGBUILD" = yes ; then + AC_MSG_RESULT(yes) + CFLAGS="$DEBUGCFLAGS" + SFLAG="" + STRIPFLAG="" + STRIP=":" + else + AC_MSG_RESULT(no) + fi + AC_MSG_CHECKING([NOOPTCFLAGS]) + AC_MSG_RESULT($NOOPTCFLAGS) + AC_MSG_CHECKING([DEBUGCFLAGS]) + AC_MSG_RESULT($DEBUGCFLAGS) + AC_MSG_CHECKING([CFLAGS]) + AC_MSG_RESULT($CFLAGS) +]) +dnl +dnl +dnl +AC_DEFUN(wi_CFLAGS_LFS64, [AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([wi_OS_VAR]) +wi_CFLAGS +if test "os_${os}_gcc_${ac_cv_prog_gcc}" = os_hp-ux_gcc_yes ; then + case "$CFLAGS" in + *__STDC_EXT__*) + ;; + *) + # This is required for the extended + # namespace symbols for Large Files. + # + CFLAGS="-D__STDC_EXT__ $CFLAGS" + ;; + esac +fi +case "$CFLAGS" in + *-D_LARGEFILE64_SOURCE*) + ;; + *) + CFLAGS="-D_LARGEFILE64_SOURCE $CFLAGS" + ;; +esac +AC_MSG_CHECKING([additional CFLAGS for LFS64 support]) +AC_MSG_RESULT($CFLAGS) +]) +dnl +dnl +dnl +AC_DEFUN(wi_PROTOTYPES, [ +AC_MSG_CHECKING(if the compiler supports function prototypes) +AC_TRY_COMPILE(,[extern void exit(int status);],[wi_cv_prototypes=yes +AC_DEFINE(PROTOTYPES)],wi_cv_prototypes=no) +AC_MSG_RESULT($wi_cv_prototypes) +]) +dnl +dnl +dnl +AC_DEFUN(wi_INSECURE_CHOWN, [ +AC_MSG_CHECKING(if chown can be used to subvert security) +AC_TRY_RUN([ +#include +#include +#include + +main() +{ + int result; + char fn[64]; + FILE *fp; + struct stat st; + + setuid(1); /* if you're root, try set to someone else. */ + sprintf(fn, "/tmp/fu%06ld", (long) getpid()); + unlink(fn); + fp = fopen(fn, "w"); + if (fp == NULL) + exit(1); /* assume the worst */ + fprintf(fp, "%s\n", "hello world"); + fclose(fp); + + result = chown(fn, 0, 0); + if (stat(fn, &st) < 0) { + unlink(fn); + exit((result == 0) ? 0 : 1); + } + unlink(fn); + + /* exit(0) if the insecure chown to uid 0 succeeded. */ + exit((st.st_uid == 0) ? 0 : 1); +}],[ + # action if true + wi_cv_insecure_chown=yes + AC_DEFINE(INSECURE_CHOWN) +],[ + # action if false + wi_cv_insecure_chown=no +],[ + # action if cross-compiling, guess + wi_cv_insecure_chown=no +]) + +AC_MSG_RESULT($wi_cv_insecure_chown) +]) +dnl +dnl +dnl +AC_DEFUN(wi_LIB_SNPRINTF, [ +if test "$ac_cv_func_snprintf" = "no" ; then + AC_CHECK_LIB(snprintf,snprintf) + if test "$ac_cv_lib_snprintf_snprintf" = yes ; then + unset ac_cv_func_snprintf + AC_CHECK_FUNCS(snprintf) + fi +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_SNPRINTF_TERMINATES, [ +if test "$ac_cv_func_snprintf" != "no" ; then +AC_MSG_CHECKING(if snprintf always NUL terminates) + if test "$ac_cv_func_snprintf" = "no" ; then + AC_CHECK_LIB(snprintf,snprintf) + fi +AC_TRY_RUN([ + /* program */ +#include +#include + +main() +{ + char s[10]; + int i, result; + + for (i=0; i<(int)(sizeof(s)/sizeof(char)); i++) + s[i] = 'x'; + result = (int) snprintf(s, sizeof(s), "%s %s!", "hello", "world"); + if (s[sizeof(s) - 1] == '\0') + exit(0); + exit(1); + +} +],[ + # action if true + wi_cv_snprintf_terminates=no + AC_DEFINE(SNPRINTF_TERMINATES) + x="yes"; +],[ + # action if false + wi_cv_snprintf_terminates=yes + x="no"; +],[ + # action if cross compiling + wi_cv_snprintf_terminates=no + x="unknown"; +]) +AC_MSG_RESULT($x) +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_SNPRINTF, [ +wi_SPRINTF_RETVAL +dnl Uncache these -- config.cache doesn't cache it right for this case. +unset ac_cv_func_snprintf +unset ac_cv_func_vsnprintf + +AC_CHECK_FUNCS(snprintf vsnprintf) +wi_SNPRINTF_TERMINATES + +AC_CHECK_HEADERS(snprintf.h) +wi_LIB_SNPRINTF +]) +dnl +dnl +dnl +AC_DEFUN(wi_HEADER_HPSECURITY_H, [ +AC_MSG_CHECKING(for hpsecurity.h) +wi_cv_header_hpsecurity_h=no +if test -f /usr/include/hpsecurity.h ; then + wi_cv_header_hpsecurity_h=yes + AC_DEFINE(HAVE_HPSECURITY_H) +fi +AC_MSG_RESULT($wi_cv_header_hpsecurity_h) +]) +dnl +dnl +dnl +AC_DEFUN(wi_HEADER_SYS_SELECT_H, [ +# See if is includable after +if test "$ac_cv_header_sys_time_h" = no ; then +AC_CHECK_HEADERS(sys/time.h sys/select.h) +else +AC_CHECK_HEADERS(sys/select.h) +fi +if test "$ac_cv_header_sys_select_h" = yes ; then + AC_MSG_CHECKING([if is compatible with ]) + selecth=yes + if test "$ac_cv_header_sys_time_h" = yes ; then + AC_TRY_COMPILE([ +#if defined(_AIX) || defined(__aix) || defined(__AIX) +# define _ALL_SOURCE 1 +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include ],[ + fd_set a; + struct timeval tmval; + + tmval.tv_sec = 0;],selecth=yes,selecth=no) + fi + if test "$selecth" = yes ; then + AC_DEFINE(CAN_USE_SYS_SELECT_H) + fi + AC_MSG_RESULT($selecth) +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_LIB_44BSD, [ +AC_CHECK_FUNC(strerror,[a=yes],[a=no]) +if test "$a" = no ; then + # Not in libc, try lib44bsd. + AC_CHECK_LIB(44bsd,strerror) +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_LIB_NSL, [ +dnl Note: Check for socket lib first, then nsl. + +case "$OS" in + hpux1[123456789]*) + # HP-UX 11 uses NSL for YP services + AC_CHECK_LIB(nsl,getpwent) + ;; + + *) + AC_CHECK_FUNC(gethostbyname,[a=yes],[a=no]) + if test "$a" = no ; then + # Not in libc, try libnsl. + AC_CHECK_LIB(nsl,gethostbyname) + fi + ;; +esac + +]) +dnl +dnl +dnl +AC_DEFUN(wi_LIB_SOCKET, [ +AC_CHECK_FUNC(socket,[a=yes],[a=no]) +if test "$a" = no ; then + # Not in libc, try libsocket. + AC_CHECK_LIB(socket,socket) +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_LIB_RESOLV, [ +# See if we could access two well-known sites without help of any special +# libraries, like resolv. +dnl +AC_MSG_WARN([the following check may take several minutes if networking is not up. You may want to bring it up now and restart configure, otherwise please be patient.]) +dnl +AC_MSG_CHECKING([if we need to look for -lresolv]) +AC_TRY_RUN([ +#include +#include +#include +#include + +main() +{ + struct hostent *hp1, *hp2; + int result; + + hp1 = gethostbyname("gatekeeper.dec.com"); + hp2 = gethostbyname("ftp.ncsa.uiuc.edu"); + result = ((hp1 != (struct hostent *) 0) && (hp2 != (struct hostent *) 0)); + exit(! result); +}],look_for_resolv=no,look_for_resolv=yes,look_for_resolv=yes) + +AC_MSG_RESULT($look_for_resolv) +if test "$look_for_resolv" = yes ; then +AC_CHECK_LIB(resolv,main) +else + ac_cv_lib_resolv=no +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_LIB_TCP_WRAPPERS, [ +AC_MSG_CHECKING([for tcp wrappers library (libwrap)]) + +AC_TRY_LINK([ + /* includes */ +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include + +/* These are needed if libwrap.a was compiled with + * PROCESS_OPTIONS defined. + */ +int allow_severity = 1; /* arbitrary for this test */ +int deny_severity = 2; /* arbitrary for this test */ + +],[ + /* function-body */ + exit((allow_severity == deny_severity) ? 1 : 0); +],[ +dnl ...Don't bother defining this symbol... +dnl ...Check for tcpd.h instead... +dnl AC_DEFINE(HAVE_LIBWRAP) +dnl +dnl ...Don't modify LIBS, instead set WRAPLIB... +dnl LIBS="-lwrap $LIBS" +dnl + WRAPLIB="-lwrap" + wi_cv_lib_wrap_hosts_access=yes +],[ + WRAPLIB="" + wi_cv_lib_wrap_hosts_access=no +]) +AC_MSG_RESULT($wi_cv_lib_wrap_hosts_access) +]) +dnl +dnl +dnl +AC_DEFUN(wi_NET_LIBS, [ +# Mostly for SunOS 4 -- needs to come first because other libs depend on it +wi_LIB_44BSD + +wi_LIB_SOCKET + +if test "$SYS" = unixware ; then + # So far, only UnixWare needs this. + AC_CHECK_LIB(gen,syslog) + + case "$OS" in + unixware2*) + if test -f /usr/ucblib/libucb.a ; then + LDFLAGS="$LDFLAGS -L/usr/ucblib" + LIBS="$LIBS -lucb" + fi + if test -f /usr/include/unistd.h ; then + ac_cv_header_unistd_h=yes + fi + + # UnixWare 2 needs both lsocket and lnsl, and configure + # script won't detect this condition properly because + # the libraries are interdependent. + # + LIBS="$LIBS -lsocket -lnsl" + + # Now look for socket() + # + # AC_CHECK_FUNC(socket,[a=yes],[a=no]) + # + AC_CHECK_FUNC(socket,[a=yes],[a=no]) + ;; + *) + ;; + esac +fi + +dnl AC_CHECK_LIB(inet,main) + +wi_LIB_NSL +wi_LIB_RESOLV + +if test "$SYS" = dynixptx ; then + LIBS="$LIBS -lsocket -lnsl" +fi + +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_DEFINE_UNAME, [ +# Get first 127 chars of all uname information. Some folks have +# way too much stuff there, so grab only the first 127. +unam=`uname -a 2>/dev/null | cut -c1-127` +if test "$unam" != "" ; then + AC_DEFINE_UNQUOTED(UNAME, "$unam") +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_FUNC_SIGSETJMP, [ +AC_MSG_CHECKING([for sigsetjmp and siglongjmp]) + +AC_TRY_LINK([ + /* includes */ +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include +],[ + /* function-body */ + sigjmp_buf sjb; + + if (sigsetjmp(sjb, 1) != 0) + siglongjmp(sjb, 1); /* bogus code, of course. */ + exit(0); +],[ + AC_DEFINE(HAVE_SIGSETJMP) + wi_cv_func_sigsetjmp=yes +],[ + wi_cv_func_sigsetjmp=no +]) +AC_MSG_RESULT($wi_cv_func_sigsetjmp) +]) +dnl +dnl +dnl +AC_DEFUN(wi_UTMP_UT_NAME, [ +AC_MSG_CHECKING([for ut_name field in struct utmp]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +],[ +struct utmp u; + +u.ut_name[0] = '\0'; +exit(((int) &u.ut_name) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_utmp_ut_name=yes + AC_DEFINE(HAVE_UTMP_UT_NAME) +],[ + wi_cv_utmp_ut_name=no +]) +AC_MSG_RESULT($wi_cv_utmp_ut_name) +]) +dnl +dnl +dnl +AC_DEFUN(wi_UTMPX_UT_SYSLEN, [ +AC_MSG_CHECKING([for ut_syslen field in struct utmpx]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +],[ +struct utmpx u; + +u.ut_syslen = 0; +exit(((int) &u.ut_syslen) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_utmpx_ut_syslen=yes + AC_DEFINE(HAVE_UTMPX_UT_SYSLEN) +],[ + wi_cv_utmpx_ut_syslen=no +]) +AC_MSG_RESULT($wi_cv_utmpx_ut_syslen) +]) +dnl +dnl +dnl +AC_DEFUN(wi_UTMP_UT_USER, [ +AC_MSG_CHECKING([for ut_user field in struct utmp]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +],[ +struct utmp u; + +u.ut_user[0] = '\0'; +exit(((int) &u.ut_user) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_utmp_ut_user=yes + AC_DEFINE(HAVE_UTMP_UT_USER) +],[ + wi_cv_utmp_ut_user=no +]) +AC_MSG_RESULT($wi_cv_utmp_ut_user) +]) +dnl +dnl +dnl +AC_DEFUN(wi_UTMP_UT_PID, [ +AC_MSG_CHECKING([for ut_pid field in struct utmp]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +],[ +struct utmp u; + +u.ut_pid = 1; +exit(((int) &u.ut_pid) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_utmp_ut_pid=yes + AC_DEFINE(HAVE_UTMP_UT_PID) +],[ + wi_cv_utmp_ut_pid=no +]) +AC_MSG_RESULT($wi_cv_utmp_ut_pid) +]) + +dnl +dnl +dnl +AC_DEFUN(wi_UTMP_UT_TIME, [ +AC_MSG_CHECKING([for ut_time field in struct utmp]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +],[ +struct utmp u; + +u.ut_time = 1; +exit(((int) &u.ut_time) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_utmp_ut_time=yes + AC_DEFINE(HAVE_UTMP_UT_TIME) +],[ + wi_cv_utmp_ut_time=no +]) +AC_MSG_RESULT($wi_cv_utmp_ut_time) +]) +dnl +dnl +dnl +AC_DEFUN(wi_UTMP_UT_HOST, [ +AC_MSG_CHECKING([for ut_host field in struct utmp]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +],[ +struct utmp u; + +u.ut_host[0] = '\0'; +exit(((int) &u.ut_host) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_utmp_ut_host=yes + AC_DEFINE(HAVE_UTMP_UT_HOST) +],[ + wi_cv_utmp_ut_host=no +]) +AC_MSG_RESULT($wi_cv_utmp_ut_host) +]) +dnl +dnl +dnl +AC_DEFUN(wi_STRUCT_STAT64, [ +AC_MSG_CHECKING([for struct stat64]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +],[ +struct stat64 st; + +st.st_size = 0; +exit(((int) &st.st_size) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_struct_stat64=yes + AC_DEFINE(HAVE_STRUCT_STAT64) +],[ + wi_cv_struct_stat64=no +]) +AC_MSG_RESULT($wi_cv_struct_stat64) +]) +dnl +dnl +dnl +AC_DEFUN(wi_STRUCT_CMSGHDR, [ +AC_MSG_CHECKING([for struct cmsghdr]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +#include +#include +],[ +struct cmsghdr cm; + +cm.cmsg_len = 0; +cm.cmsg_level = 0; +cm.cmsg_type = 0; +exit(((int) &cm.cmsg_type) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_struct_cmsghdr=yes + AC_DEFINE(HAVE_STRUCT_CMSGDHR) +],[ + wi_cv_struct_cmsghdr=no +]) +AC_MSG_RESULT($wi_cv_struct_cmsghdr) +]) +dnl +dnl +dnl +AC_DEFUN(wi_MSGHDR_CONTROL, [ +AC_MSG_CHECKING([for msg_control field in struct msghdr]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +#include +#include +],[ +struct msghdr m; + +m.msg_control = &m; +m.msg_controllen = sizeof(m); +exit(((int) &m.msg_control) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_msghdr_control=yes + AC_DEFINE(HAVE_MSGHDR_CONTROL) +],[ + wi_cv_msghdr_control=no +]) +AC_MSG_RESULT($wi_cv_msghdr_control) +]) +dnl +dnl +dnl +AC_DEFUN(wi_MSGHDR_ACCRIGHTS, [ +AC_MSG_CHECKING([for msg_accrights field in struct msghdr]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +#include +#include +],[ +struct msghdr m; + +m.msg_accrights = &m; +m.msg_accrightslen = sizeof(m); +exit(((int) &m.msg_accrights) & 0xff); /* bogus code, of course. */ +],[ + wi_cv_msghdr_accrights=yes + AC_DEFINE(HAVE_MSGHDR_ACCRIGHTS) +],[ + wi_cv_msghdr_accrights=no +]) +AC_MSG_RESULT($wi_cv_msghdr_accrights) +]) +dnl +dnl +dnl +AC_DEFUN(wi_PR_PASSWD_FG_OLDCRYPT, [ +AC_MSG_CHECKING([for fg_oldcrypt field in struct pr_passwd]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_USERPW_H) && defined(HAVE_GETUSERPW) /* AIX */ +# include +#elif defined(HAVE_PWDADJ_H) && defined(HAVE_GETPWANAM) /* SunOS */ +# include +# ifdef HAVE_SYS_AUDIT_H +# include +# endif +# include +#elif defined(HAVE_GETESPWNAM) /* Digital UNIX 4 */ +# ifdef HAVE_SYS_SECDEFINES_H +# include +# endif +# ifdef HAVE_SYS_SECURITY_H +# include +# endif +# ifdef HAVE_SYS_AUDIT_H +# include +# endif +# ifdef HAVE_KRB_H +# include +# endif +# ifdef HAVE_PROT_H +# include +# endif +#elif defined(HAVE_GETPRPWNAM) /* SCO Open Server V, Digital UNIX 3, HP-UX 10 */ +# ifdef HAVE_SYS_SECDEFINES_H +# include +# endif +# ifdef HAVE_SYS_SECURITY_H +# include +# endif +# ifdef HAVE_SYS_AUDIT_H +# include +# endif +# ifdef HAVE_HPSECURITY_H +# include +# endif +# ifdef HAVE_KRB_H +# include +# endif +# ifdef HAVE_PROT_H +# include +# endif +#endif +],[ + struct pr_passwd xu; + memset(&xu, 0, sizeof(xu)); + if (xu.uflg.fg_oldcrypt != 0) + xu.uflg.fg_oldcrypt++; /* bogus code, of course */ + exit(0); +],[ + wi_cv_pr_passwd_fg_oldcrypt=yes + AC_DEFINE(HAVE_PR_PASSWD_FG_OLDCRYPT) +],[ + wi_cv_pr_passwd_fg_oldcrypt=no +]) +AC_MSG_RESULT($wi_cv_pr_passwd_fg_oldcrypt) +]) +dnl +dnl +dnl +AC_DEFUN(wi_SOCKADDR_UN_SUN_LEN, [ +AC_MSG_CHECKING([for sun_len field in struct sockaddr_un]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +#include +#include +],[ +struct sockaddr_un uaddr; + +uaddr.sun_len = strlen("/tmp/test.sock"); +exit(((int) uaddr.sun_len); /* bogus code, of course. */ +],[ + wi_cv_sockaddr_un_sun_len=yes + AC_DEFINE(HAVE_SOCKADDR_UN_SUN_LEN) +],[ + wi_cv_sockaddr_un_sun_len=no +]) +AC_MSG_RESULT($wi_cv_sockaddr_un_sun_len) +]) +dnl +dnl +dnl +AC_DEFUN(wi_STATFS_F_BAVAIL, [ +AC_MSG_CHECKING([for f_bavail field in struct statfs]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#ifdef HAVE_SYS_STATFS_H +# include +#elif defined(HAVE_SYS_VFS_H) +# include +#endif +],[ +struct statfs st; + +st.f_bavail = 1; +exit((int) st.f_bavail); /* bogus code, of course. */ +],[ + wi_cv_statfs_f_bavail=yes + AC_DEFINE(HAVE_STATFS_F_BAVAIL) +],[ + wi_cv_statfs_f_bavail=no +]) +AC_MSG_RESULT($wi_cv_statfs_f_bavail) +]) +dnl +dnl +dnl +AC_DEFUN(wi_SPRINTF_RETVAL, [ +AC_MSG_CHECKING([what sprintf() returns]) +AC_TRY_RUN([ + /* program */ +#include +#include + +main() +{ + int result; + char s[8]; + + result = (int) sprintf(s, "%d", 22); + if (result == 2) + exit(0); + exit(1); + +} +],[ + # action if true + wi_cv_sprintf_returns_ptr=no + x="length of data written"; +],[ + # action if false + wi_cv_sprintf_returns_ptr=yes + AC_DEFINE(SPRINTF_RETURNS_PTR) + x="pointer to data"; +],[ + # action if cross compiling + wi_cv_sprintf_returns_ptr=no + x="unknown"; +]) +AC_MSG_RESULT($x) +]) +dnl +dnl +dnl +AC_DEFUN(wi_LIB_CRYPT, [ +AC_MSG_CHECKING([which library has usable crypt() function]) +ac_save_LIBS="$LIBS" +crypt_lib=NONE + +for lib in "c" "crypt" "descrypt" "des" +do + +if test "$lib" = "c" ; then + LIBS="$ac_save_LIBS" +else + LIBS="$ac_save_LIBS -l${lib}" +fi + +AC_TRY_RUN([ + /* program */ +#include +#include + +extern char *crypt(const char *key, const char *salt); + +main() +{ + char cleartext[256]; + char *cp; + + memset(cleartext, 0, sizeof(cleartext)); + strcpy(cleartext, "password"); + + cp = crypt(cleartext, "xx"); + if ((cp != NULL) && (strcmp(cp, "xxj31ZMTZzkVA") == 0)) { + /* printf("PASS\n"); */ + exit(0); + } + /* printf("FAIL\n"); */ + exit(1); +} +],[ + # action if true + crypt_lib="$lib" +],[ + # action if false + : +],[ + # action if cross compiling + : +]) + + +if test "$crypt_lib" != NONE ; then + break +fi + +done + + +LIBS="$ac_save_LIBS" + +if test "$crypt_lib" = NONE ; then + crypt_lib=c + AC_MSG_RESULT([none?]) +else + AC_MSG_RESULT([lib${crypt_lib}]) +fi +if test "$crypt_lib" != c ; then + AC_CHECK_LIB(${lib},crypt) +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_TEST, [ +changequote(<^, ^>)dnl +changequote([, ])dnl +]) +dnl +dnl +dnl +AC_DEFUN(wi__RES_DEFDNAME, [ +AC_MSG_CHECKING([for useable _res global variable]) +AC_TRY_LINK([ + /* includes */ +#include +#include +#include +#include +#include +#include +#ifdef HAVE_ARPA_NAMESER_H +# include +#endif +#ifdef HAVE_RESOLV_H +# include +#endif +],[ + /* function-body */ + int len; + + res_init(); + len = (int) strlen(_res.defdname); +],[ + wi_cv__res_defdname=yes + AC_DEFINE(HAVE__RES_DEFDNAME) +],[ + wi_cv__res_defdname=no +]) +AC_MSG_RESULT($wi_cv__res_defdname) +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_TYPE_SIG_ATOMIC_T, [ +AC_MSG_CHECKING([for sig_atomic_t]) +AC_TRY_LINK([ + /* includes */ +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include /* MG: for IRIX */ +#if STDC_HEADERS +#include +#include +#endif +],[ + /* function-body */ + sig_atomic_t sample; + + sample = (sig_atomic_t) getpid(); /* bogus code, of course */ + exit((sample > 0) ? 0 : 1); +],[ + ac_cv_type_sig_atomic_t=yes +],[ + ac_cv_type_sig_atomic_t=no +]) +AC_MSG_RESULT($ac_cv_type_sig_atomic_t) +if test $ac_cv_type_sig_atomic_t = no ; then + AC_DEFINE(sig_atomic_t, int) +fi +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_LIB_READLINE, [ +AC_MSG_CHECKING([for GNU Readline library, version 2.0 or newer]) + +wi_cv_lib_readline=no +wi_cv_lib_readline_result=no +ac_save_LIBS="$LIBS" +# Note: $LIBCURSES is permitted to be empty. +for LIBREADLINE in "-lreadline" "-lreadline $LIBCURSES" "-lreadline -ltermcap" "-lreadline -lncurses" "-lreadline -lcurses" +do + LIBS="$ac_save_LIBS $LIBREADLINE" + AC_TRY_RUN([ + /* program */ +#include +#include + +main(int argc, char **argv) +{ + /* Note: don't actually call readline, since it may block; + * We just want to see if it (dynamic) linked in okay. + */ + if (argc == 0) /* never true */ + readline(0); + exit(0); +} +],[ + # action if true + wi_cv_lib_readline=yes +],[ + # action if false + wi_cv_lib_readline=no +],[ + # action if cross compiling + wi_cv_lib_readline=no +]) + + if test "$wi_cv_lib_readline" = yes ; then break ; fi +done + +# Now try it again, to be sure it is recent enough. +# rl_function_of_keyseq appeared in version 2.0 +# +dnl AC_CHECK_FUNC(rl_function_of_keyseq, [wi_cv_lib_readline=yes],[ +dnl wi_cv_lib_readline=no;wi_cv_lib_readline_result="no (it is present but too old to use)" +dnl ]) + AC_TRY_LINK([ + /* includes */ + ],[ + /* function-body */ + readline(0); + rl_function_of_keyseq(0); + ],[ + wi_cv_lib_readline=yes + ],[ + wi_cv_lib_readline=no + wi_cv_lib_readline_result="no (it is present but too old to use)" + ]) + +if test "$wi_cv_lib_readline" = no ; then + LIBREADLINE="" + # restore LIBS + LIBS="$ac_save_LIBS" +else + /bin/rm -f readline.ver + touch readline.ver + + AC_TRY_RUN([ + /* program */ +#include +#include +#include + +extern char *rl_library_version; + +main() +{ + FILE *fp; + double d; + + sscanf(rl_library_version, "%lf", &d); + fp = fopen("readline.ver", "w"); + if (fp == NULL) exit(1); + if (fprintf(fp, "%s\n", rl_library_version) < 0) exit(1); + if (fprintf(fp, "%03d\n", (int) (d * 100.0)) < 0) exit(1); + if (fclose(fp) < 0) exit(1); + exit(0); +} + ],[ + # action if true + rl_library_version=`sed -n 1,1p readline.ver 2>/dev/null` + rlver=`sed -n 2,2p readline.ver 2>/dev/null` + /bin/rm -f readline.ver + ],[ + # action if false + rl_library_version='' + rlver='' + /bin/rm -f readline.ver + ],[ + # action if cross compiling + rl_library_version='' + rlver='' + /bin/rm -f readline.ver + ]) + + case "$rlver" in + ???) + wi_cv_lib_readline_result="yes, installed version is $rl_library_version" + ;; + *) + # Test using current LIBS. + AC_TRY_LINK([ + /* includes */ + extern int rl_completion_append_character; + ],[ + /* function-body */ + readline(0); + rl_completion_append_character = 0; + ],[ + rlver="210" + ],[ + rlver="200" + ]) + + if test "$rlver" = "210" ; then + wi_cv_lib_readline_result="yes, version 2.1 or higher" + else + wi_cv_lib_readline_result="yes, version 2.0" + fi + ;; + esac + + wi_cv_lib_readline=yes + # restore LIBS + LIBS="$ac_save_LIBS" +fi +AC_MSG_RESULT($wi_cv_lib_readline_result) +AC_SUBST(LIBREADLINE) + +if test "$wi_cv_lib_readline" = yes ; then + # Now verify that all the headers are installed. + # + AC_REQUIRE_CPP() + unset ac_cv_header_readline_chardefs_h + unset ac_cv_header_readline_history_h + unset ac_cv_header_readline_keymaps_h + unset ac_cv_header_readline_readline_h + unset ac_cv_header_readline_tilde_h + AC_CHECK_HEADERS([readline/chardefs.h readline/history.h readline/keymaps.h readline/readline.h readline/tilde.h]) + + for xxwi in \ + "$ac_cv_header_readline_chardefs_h" \ + "$ac_cv_header_readline_history_h" \ + "$ac_cv_header_readline_keymaps_h" \ + "$ac_cv_header_readline_readline_h" \ + "$ac_cv_header_readline_tilde_h" + do + if test "$xxwi" = no ; then + break + fi + done + + if test "$xxwi" = no ; then + AC_MSG_WARN([GNU Readline headers are not installed or could not be found -- GNU Readline will not be used.]) + wi_cv_lib_readline=no + wi_cv_lib_readline_result="no (headers not installed)" + else + AC_DEFINE_UNQUOTED(HAVE_LIBREADLINE, $rlver) + fi +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_USE_LONG_LONG, [ +AC_MSG_CHECKING([for 64-bit integral type: long long]) +LONGEST_INT="long" +AC_TRY_RUN([ + /* program */ +#include +#include +#include + +long long hugeNumvar = 1; + +main() +{ + long long hugeNumtoo = 2; + + if (hugeNumtoo > hugeNumvar) + hugeNumvar++; + if (sizeof(hugeNumvar) < 8) + exit(1); + exit(0); +} + +],[ + # action if true + wi_cv_type_long_long=yes + LONGEST_INT="long long" +],[ + # action if false + wi_cv_type_long_long=no +],[ + # action if cross compiling + wi_cv_type_long_long=no +]) +AC_MSG_RESULT($wi_cv_type_long_long) + +if test "$wi_cv_type_long_long" = yes ; then + +AC_MSG_CHECKING([how to print a 64-bit integral type]) +wi_cv_printf_long_long=fail + +AC_TRY_RUN([ + /* program */ +#include +#include +#include +#include +#include + +main() +{ + char s[80]; + long long hugeNum; + + hugeNum = (long long) 1000000000; + hugeNum = hugeNum * (long long) 99; + hugeNum = hugeNum + (long long) 1; + + (void) sprintf(s, "%lld", hugeNum); + exit((strcmp(s, "99000000001") == 0) ? 0 : 1); +} +],[ + # action if true + wi_cv_printf_long_long="%lld" +],[ + # action if false + : +],[ + # action if cross compiling + : +]) + + +if test "$wi_cv_printf_long_long" = fail ; then + +AC_TRY_RUN([ + /* program */ +#include +#include +#include +#include +#include + +main() +{ + char s[80]; + long long hugeNum; + + hugeNum = (long long) 1000000000; + hugeNum = hugeNum * (long long) 99; + hugeNum = hugeNum + (long long) 1; + + (void) sprintf(s, "%qd", hugeNum); + exit((strcmp(s, "99000000001") == 0) ? 0 : 1); +} +],[ + # action if true + wi_cv_printf_long_long="%qd" +],[ + # action if false + : +],[ + # action if cross compiling + : +]) +fi + +if test "$wi_cv_printf_long_long" = fail ; then + wi_cv_printf_long_long_msg_result='cannot print' +else + wi_cv_printf_long_long_msg_result="$wi_cv_printf_long_long" +fi + +AC_MSG_RESULT($wi_cv_printf_long_long_msg_result) + + +AC_MSG_CHECKING([how to scan a 64-bit integral type]) +wi_cv_scanf_long_long=fail + +AC_TRY_RUN([ + /* program */ +#include +#include +#include +#include +#include + +main() +{ + long long hugeNum, justAsHugeNum; + + hugeNum = (long long) 1000000000; + hugeNum = hugeNum * (long long) 99; + hugeNum = hugeNum + (long long) 1; + + justAsHugeNum = (long long) 0; + --justAsHugeNum; + sscanf("99000000001", "%lld", &justAsHugeNum); + if (memcmp(&hugeNum, &justAsHugeNum, sizeof(hugeNum)) == 0) + exit(0); + exit(1); +} +],[ + # action if true + wi_cv_scanf_long_long="%lld" +],[ + # action if false + : +],[ + # action if cross compiling + : +]) + + +if test "$wi_cv_scanf_long_long" = fail ; then + +AC_TRY_RUN([ + /* program */ +#include +#include +#include +#include +#include + +main() +{ + long long hugeNum, justAsHugeNum; + + hugeNum = (long long) 1000000000; + hugeNum = hugeNum * (long long) 99; + hugeNum = hugeNum + (long long) 1; + + justAsHugeNum = (long long) 0; + --justAsHugeNum; + sscanf("99000000001", "%qd", &justAsHugeNum); + if (memcmp(&hugeNum, &justAsHugeNum, sizeof(hugeNum)) == 0) + exit(0); + exit(1); +} +],[ + # action if true + wi_cv_scanf_long_long="%qd" +],[ + # action if false + : +],[ + # action if cross compiling + : +]) +fi + +if test "$wi_cv_scanf_long_long" = fail ; then + wi_cv_scanf_long_long_msg_result='cannot scan' +else + wi_cv_scanf_long_long_msg_result="$wi_cv_scanf_long_long" +fi + +AC_MSG_RESULT($wi_cv_scanf_long_long_msg_result) + +fi + +AC_MSG_CHECKING([if everything was available to use the 64-bit integral type]) + +if test "$wi_cv_type_long_long" = no ; then + wi_cv_use_long_long_msg_result="no (long long type not available)" + wi_cv_use_long_long="no" + wi_cv_scanf_long_long="fail" + wi_cv_prihtf_long_long="fail" + LONGEST_INT="long" +elif test "$wi_cv_printf_long_long" = fail ; then + wi_cv_use_long_long_msg_result="no (libc printf() does not support them)" + wi_cv_use_long_long="no" + wi_cv_scanf_long_long="fail" + wi_cv_prihtf_long_long="fail" + LONGEST_INT="long" +elif test "$wi_cv_scanf_long_long" = fail ; then + wi_cv_use_long_long_msg_result="no (libc scanf() does not support them)" + wi_cv_use_long_long="no" + wi_cv_scanf_long_long="fail" + wi_cv_prihtf_long_long="fail" + LONGEST_INT="long" +else + AC_DEFINE(HAVE_LONG_LONG) + if test "$wi_cv_printf_long_long$wi_cv_scanf_long_long" = "%lld%qd" ; then + # FreeBSD 3.2 has %lld and %qd, but we want to + # run on 3.1 and 3.0. + # + wi_cv_printf_long_long="%qd" + fi + AC_DEFINE_UNQUOTED(PRINTF_LONG_LONG, "$wi_cv_printf_long_long") + AC_DEFINE_UNQUOTED(SCANF_LONG_LONG , "$wi_cv_scanf_long_long") + if test "$wi_cv_printf_long_long" = "%qd" ; then + AC_DEFINE(PRINTF_LONG_LONG_QD) + else + AC_DEFINE(PRINTF_LONG_LONG_LLD) + fi + if test "$wi_cv_scanf_long_long" = "%qd" ; then + AC_DEFINE(SCANF_LONG_LONG_QD) + else + AC_DEFINE(SCANF_LONG_LONG_LLD) + fi + wi_cv_use_long_long="yes" + wi_cv_use_long_long_msg_result="yes" +fi +AC_MSG_RESULT($wi_cv_use_long_long_msg_result) +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_CREATE_TAR_FILES, [ +AC_MSG_CHECKING([how to create TAR files]) +changequote(<<, >>)dnl +TAR=/usr/bin/tar +if [ ! -f /usr/bin/tar ] && [ -f /bin/tar ] ; then + TAR=/bin/tar +fi +x="" +if [ -x /usr/bin/what ] ; then + x=`/usr/bin/what "$TAR" 2>&1 | sed -n 's/.*pax.*/pax/g;/pax/p'` +elif [ -x /bin/what ] ; then + x=`/bin/what "$TAR" 2>&1 | sed -n 's/.*pax.*/pax/g;/pax/p'` +fi +if [ "x$x" != "xpax" ] ; then + # The junk above is because Mac OS X Server's tar freaks out + # and does not exit if you do "tar --help". + # + x=`$TAR --help 2>&1 | sed -n 's/.*owner=NAME.*/owner=NAME/g;/owner=NAME/p'` +fi +case "$x" in + *owner=NAME*) + TARFLAGS="-c --owner=root --group=bin --verbose -f" + ;; + *) + TARFLAGS="cvf" + x2=`gtar --help 2>&1 | sed -n 's/.*owner=NAME.*/owner=NAME/g;/owner=NAME/p'` + case "$x2" in + *owner=NAME*) + TARFLAGS="-c --owner=root --group=bin --verbose -f" + TAR=gtar + ;; + esac + ;; +esac +changequote([, ])dnl +AC_SUBST(TARFLAGS) +AC_SUBST(TAR) +AC_MSG_RESULT([$TAR $TARFLAGS]) +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_HEADER_CURSES, [ +AC_MSG_CHECKING([for curses library headers]) +if test "$nc_cv_ncurses" != "no" ; then + AC_CHECK_HEADERS(ncurses.h curses.h) +else + AC_CHECK_HEADERS(curses.h) +fi +dnl needed for Solaris 7 +if test "$ac_cv_header_curses_h" = no ; then + if test -f /usr/include/curses.h ; then + AC_DEFINE(HAVE_CURSES_H) + ac_cv_header_curses_h=yes + fi +fi +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_LIB_CURSES, [ +wi_HEADER_CURSES +AC_MSG_CHECKING([for curses library]) + +wi_cv_lib_curses=no +wi_cv_lib_curses_result=no +ac_save_LIBS="$LIBS" +for LIBCURSES in "-lncurses" "-lcurses" "-lcurses -ltermcap" "-ltermcap -lcurses" +do + if test "x$LIBCURSES-$nc_cv_ncurses" = "x-lncurses-no" ; then + # This should never work + LIBCURSES="-lkdfjkdjfs" + fi + LIBS="$ac_save_LIBS $LIBCURSES" + AC_TRY_RUN([ + /* program */ +#include +#include + +#ifdef HAVE_NCURSES_H +# include +#else +# include +#endif + + +main(int argc, char **argv) +{ + /* Note: don't actually call curses, since it may block; + * We just want to see if it (dynamic) linked in okay. + */ + if (argc == 4) + initscr(); + exit(0); +} +],[ + # action if true + wi_cv_lib_curses=yes + wi_cv_lib_curses_result="yes" +],[ + # action if false + wi_cv_lib_curses=no +],[ + # action if cross compiling + wi_cv_lib_curses=no +]) + + if test "$wi_cv_lib_curses" = yes ; then break ; fi +done + +# restore LIBS +LIBS="$ac_save_LIBS" + +if test "$wi_cv_lib_curses_result" != "no" ; then + case "$LIBCURSES" in + "-lncurses") + AC_DEFINE(HAVE_LIBNCURSES) + ;; + "-lcurses") + AC_DEFINE(HAVE_LIBCURSES) + ;; + "-lcurses -ltermcap") + AC_DEFINE(HAVE_LIBCURSES) + ;; + "-ltermcap -lcurses") + AC_DEFINE(HAVE_LIBCURSES) + ;; + esac +else + LIBCURSES='' +fi + +AC_SUBST(LIBCURSES) +AC_MSG_RESULT([$wi_cv_lib_curses_result]) +]) +dnl +dnl +dnl +dnl +AC_DEFUN(wi_CURSES_FEATURES, [ +if test "$wi_cv_lib_curses" = "yes" ; then + # Then $LIBCURSES is a list of curses and support libraries. + ac_save_LIBS="$LIBS"; + LIBS="$LIBS $LIBCURSES"; + + + # maxx or _maxx + AC_MSG_CHECKING([whether curses structure has maxx or _maxx field]) + AC_TRY_COMPILE([ + /* includes */ +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#ifdef HAVE_NCURSES_H +# include +#else +# include +#endif +],[ + WINDOW *w; + + w = newwin(10, 10, 1, 1); + w->maxx = 0; +],[ +AC_MSG_RESULT([maxx]) +],[ +AC_DEFINE(HAVE__MAXX) +AC_MSG_RESULT([_maxx]) +]) + + AC_CHECK_FUNCS(__getmaxx __getmaxy __getbegx __getbegy) + + # getbegx + AC_MSG_CHECKING([for getbegx() functionality in curses library]) + AC_TRY_LINK([ + /* includes */ +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#ifdef HAVE_NCURSES_H +# include +#else +# include +#endif + +],[ + /* function-body */ + WINDOW *junk = 0; + int mx = 0; + + mx = getbegx(junk); + exit(0); +],[ + AC_DEFINE(HAVE_GETBEGX) + AC_MSG_RESULT([yes]) +],[ + AC_MSG_RESULT([no]) +]) + + + # getmaxx + AC_MSG_CHECKING([for getmaxx() functionality in curses library]) + AC_TRY_LINK([ + /* includes */ +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#ifdef HAVE_NCURSES_H +# include +#else +# include +#endif +],[ + /* function-body */ + WINDOW *junk = 0; + int mx = 0; + + mx = getmaxx(junk); + exit(0); +],[ + AC_DEFINE(HAVE_GETMAXX) + AC_MSG_RESULT([yes]) +],[ + AC_MSG_RESULT([no]) +]) + + # getmaxyx + AC_MSG_CHECKING([for getmaxyx() functionality in curses library]) + AC_TRY_LINK([ + /* includes */ +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#ifdef HAVE_NCURSES_H +# include +#else +# include +#endif +],[ + /* function-body */ + WINDOW *junk = 0; + int mx = 0, my = 0; + + getmaxyx(junk, my, mx); + exit(my < 0 ? my : 0); +],[ + AC_DEFINE(HAVE_GETMAXYX) + AC_MSG_RESULT([yes]) +],[ + AC_MSG_RESULT([no]) +]) + + # touchwin + AC_MSG_CHECKING([for touchwin() functionality in curses library]) + AC_TRY_LINK([ + /* includes */ +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#ifdef HAVE_NCURSES_H +# include +#else +# include +#endif +],[ + /* function-body */ + WINDOW *junk = 0; + touchwin(junk); + exit(0); +],[ + AC_DEFINE(HAVE_TOUCHWIN) + AC_MSG_RESULT([yes]) +],[ + AC_MSG_RESULT([no]) +]) + + # beep + AC_MSG_CHECKING([for beep() functionality in curses library]) + AC_TRY_LINK([ + /* includes */ +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#ifdef HAVE_NCURSES_H +# include +#else +# include +#endif +],[ + /* function-body */ + beep(); + exit(getpid() & 1); +],[ + AC_DEFINE(HAVE_BEEP) + AC_MSG_RESULT([yes]) +],[ + AC_MSG_RESULT([no]) +]) + + AC_CHECK_FUNCS(keypad nodelay curs_set doupdate wnoutrefresh) + + LIBS="$ac_save_LIBS"; +fi +]) +dnl +dnl +dnl +AC_DEFUN(wi_SHADOW_FUNCS, [ +AC_CHECK_FUNCS(md5_crypt md5crypt bcrypt getspnam) + +# UnixWare 7 +if test "$ac_cv_func_getspnam" = no ; then + unset ac_cv_func_getspnam + AC_CHECK_LIB(gen,getspnam) + if test "$ac_cv_lib_gen_getspnam" = yes ; then + AC_CHECK_FUNCS(getspnam) + fi +fi + +# AIX +# +case "$SYS" in + "aix"|"") + AC_CHECK_FUNCS(getuserpw) + ;; + *) + ;; +esac + +# C2: SCO Open Server 5; Digital UNIX +AC_CHECK_FUNCS(set_auth_parameters bigcrypt) + +# C2: Digital UNIX 3.2, 4.0; SCO Open Server 5; HP-UX 11 +AC_CHECK_FUNCS(getprpwnam) + +# Digital UNIX 4.0 +AC_CHECK_FUNCS(getespwnam get_num_crypts get_crypt_name) + +# Digital Unix 4.0 +AC_CHECK_FUNCS(dispcrypt) + +# SunOS +AC_CHECK_FUNCS(getpwanam) +]) +dnl +dnl +dnl +AC_DEFUN(wi_SHADOW_HEADERS, [ +AC_CHECK_HEADERS(shadow.h crypt.h) + +# AIX +AC_CHECK_HEADERS(userpw.h) + +# SunOS +AC_CHECK_HEADERS(pwdadj.h) + +# HP-UX +# +# Bug in header on these version 10 which cause is it not +# to get detected. +# +wi_HEADER_HPSECURITY_H + +# SCO Open Server, Digital UNIX +AC_CHECK_HEADERS(sys/security.h sys/audit.h krb.h prot.h) + +# Digital UNIX +AC_CHECK_HEADERS(sys/secdefines.h) + +# Digital UNIX +wi_PR_PASSWD_FG_OLDCRYPT +]) +dnl +dnl +dnl +AC_DEFUN(wi_SHADOW_LIBS, [ +check_for_libcrypt=yes + +# AIX security library is libs.a +AC_CHECK_LIB(s,getuserpw) +if test "$ac_cv_lib_s" = yes ; then + check_for_libcrypt=no +elif test "$ac_cv_lib_s_getuserpw" = yes ; then + check_for_libcrypt=no +fi + +# SCO OpenServer 5 stuff for shadow password +AC_CHECK_LIB(x,nap) +AC_CHECK_LIB(prot,getprpwnam) + +# Digital UNIX +AC_CHECK_LIB(security,endprpwent) + +# HP-UX +AC_CHECK_LIB(sec,getprpwnam) + +if test "$ac_cv_lib_sec_getprpwnam" = no ; then + # DYNIX/ptx + AC_CHECK_LIB(sec,getspnam) +fi + +if test "$check_for_libcrypt" = yes ; then + wi_LIB_CRYPT +fi +AC_CHECK_FUNCS(crypt) +]) +dnl +dnl +dnl +AC_DEFUN(wi_OS_VAR, [ +changequote(!@, @!)dnl +if [ -x "$HOME/bin/OS" ] ; then + HOME_OS=`$HOME/bin/OS` + HOME_OS="$HOME/$HOME_OS" +fi +host=`uname -n 2>/dev/null | tr '[A-Z]' '[a-z]'` +os=`uname -s 2>/dev/null | tr '[A-Z]' '[a-z]'` +dnl work around inability to use $1 +os_v=`uname -v 2>/dev/null | sed 's/^[^0-9.]*//;s/[^0-9.]*$//;s/pre.*//;s/test.*//' | awk '-F[-/: ]' '{n = 1; print $n; }'` +os_r=`uname -r 2>/dev/null | sed 's/^[^0-9.]*//;s/[^0-9.]*$//;s/pre.*//;s/test.*//' | awk '-F[-/: ]' '{n = 1; print $n; }'` +os_r1=`echo "${os_r}" | cut -c1` +arch=`uname -m 2>/dev/null | tr '[A-Z]' '[a-z]'` +archp=`uname -p 2>/dev/null | tr '[A-Z]' '[a-z]'` +OS='' +SYS='' +NDEFS='' + +# Special case a few systems where if your CFLAGS appear +# to want to generate for 32 bit, use that mode rather +# than 64 bit. +# +case "$os,$CFLAGS" in + irix64,*-n32*) + os=irix + # then go to regular "irix" instead of "irix64" below. + ;; +esac + +case "$os" in + osf1) + case "$os_r" in + 3*|4*) + OS="digitalunix${os_r}-$arch" + SYS=digitalunix + ;; + *) + OS="tru64unix${os_r}-$arch" + SYS=tru64unix + ;; + esac + NDEFS="$NDEFS -DDIGITAL_UNIX=$os_r1" + ;; + aix) + OS="aix${os_v}.${os_r}" + SYS=aix + NDEFS="$NDEFS -DAIX=${os_v}" + ;; + irix) + OS="irix${os_r}" + SYS=irix + NDEFS="$NDEFS -DIRIX=$os_r1" + ;; + irix64) + OS="irix64_${os_r}" + SYS=irix64 + NDEFS="$NDEFS -DIRIX=$os_r1 -DIRIX64=$os_r1" + ;; + hp-ux) + os_r=`echo "${os_r}" | cut -d. -f2-` + os_r1=`echo "$os_r" | cut -d. -f1` + os_r2=`echo "${os_r}" | cut -d. -f2` + os_int=`expr "$os_r1" '*' 100 + "$os_r2"` + OS="hpux${os_r}" + SYS=hpux + NDEFS="$NDEFS -DHPUX=$os_int" + ;; + freebsd) + OS="freebsd${os_r}-$arch" + os_r1=`echo "$os_r" | cut -d. -f1` + os_r2=`echo "$os_r" | cut -d. -f2` + os_r3=`echo "$os_r" | cut -d. -f3` + if [ "$os_r3" = "" ] ; then os_r3=0 ; fi + os_int=`expr "$os_r1" '*' 100 + "$os_r2" '*' 10 + "$os_r3"` + SYS=freebsd + NDEFS="$NDEFS -DFREEBSD=$os_int" + ;; + netbsd) + OS="netbsd${os_r}-$arch" + NDEFS="$NDEFS -DNETBSD=$os_r1" + SYS=netbsd + ;; + openbsd) + OS="openbsd${os_r}-$arch" + SYS=openbsd + NDEFS="$NDEFS -DOPENBSD=$os_r1" + ;; + sco*) + OS=scosv + SYS=sco + NDEFS="$NDEFS -DSCO=$os_r1" + ;; + dynix*) + OS="dynixptx${os_v}" + SYS=dynixptx + os_v1=`echo "$os_v" | cut -d. -f1` + os_v2=`echo "$os_v" | cut -d. -f2` + os_v3=`echo "$os_v" | cut -d. -f3` + if [ "$os_v3" = "" ] ; then os_v3=0 ; fi + os_int=`expr "$os_v1" '*' 100 + "$os_v2" '*' 10 + "$os_v3"` + NDEFS="$NDEFS -DDYNIX=$os_int" + ;; + linux) + case "$arch" in + *86) + arch=x86 + ;; + esac + + libc="" + os_r1=`echo "$os_r" | cut -d. -f1` + os_r2=`echo "$os_r" | cut -d. -f2` + os_r3=`echo "$os_r" | cut -d- -f1 | cut -d. -f3` + os_int=`expr "$os_r1" '*' 10000 + "$os_r2" '*' 1000 + "$os_r3"` + NDEFS="$NDEFS -DLINUX=$os_int" + + vertest="./vertest.$$" + /bin/rm -f "$vertest" "$vertest.c" + cat < "$vertest.c" +#include +#include + +main() +{ + const char *ver = gnu_get_libc_version(); + const char *rel = gnu_get_libc_release(); + + fprintf(stdout, "glibc%s\n", ver); + exit(0); +} +EOF + echo $ac_n "checking version of C library""... $ac_c" 1>&6 + echo "configure:: checking version of C library" >&5 + ${CC-cc} $DEFS $CPPFLAGS $CFLAGS "$vertest.c" -o "$vertest" >/dev/null 2>&1 + if [ -x "$vertest" ] ; then libc=`$vertest` ; fi + /bin/rm -f "$vertest" "$vertest.c" + + case "$libc" in + glibc*) + echo "$libc" 1>&6 + glibc_r=`echo "$libc" | sed 's/glibc//'` + glibc_r1=`echo "$glibc_r" | cut -d. -f1` + glibc_r2=`echo "$glibc_r" | cut -d. -f2` + glibc_r3=`echo "$glibc_r" | cut -d- -f1 | cut -d. -f3` + glibc_int=`expr "$glibc_r1" '*' 10000 + "$glibc_r2" '*' 1000 + "$glibc_r3"` + NDEFS="$NDEFS -DLINUX_GLIBC=$glibc_int" + libc="glibc${glibc_r1}.${glibc_r2}" + OS="linux-$arch" + ;; + *) + if test -f /lib/libc-2.2.2.so ; then + NDEFS="$NDEFS -DLINUX_GLIBC=22002" + libc="glibc2.2" + OS="linux-$arch" + elif test -f /lib/libc-2.2.1.so ; then + NDEFS="$NDEFS -DLINUX_GLIBC=22001" + libc="glibc2.2" + OS="linux-$arch" + elif test -f /lib/libc-2.2.0.so ; then + NDEFS="$NDEFS -DLINUX_GLIBC=22000" + libc="glibc2.1" + OS="linux-$arch" + elif test -f /lib/libc-2.1.3.so ; then + NDEFS="$NDEFS -DLINUX_GLIBC=21003" + libc="glibc2.1" + OS="linux-$arch" + elif test -f /lib/libc-2.1.2.so ; then + NDEFS="$NDEFS -DLINUX_GLIBC=21002" + libc="glibc2.1" + OS="linux-$arch" + elif test -f /lib/libc-2.1.1.so ; then + NDEFS="$NDEFS -DLINUX_GLIBC=21001" + libc="glibc2.1" + OS="linux-$arch" + elif test -f /lib/libc.so.6 ; then + NDEFS="$NDEFS -DLINUX_GLIBC=20000" + libc="glibc2.0" + OS="linux-$arch" + elif test -f /lib/libc.so.6.1 ; then + NDEFS="$NDEFS -DLINUX_GLIBC=20001" + libc="glibc2.0" + OS="linux-$arch" + else + NDEFS="$NDEFS -DLINUX_LIBC=5" + libc="libc5" + OS="linux-$arch" + fi + echo "$libc" 1>&6 + ;; + esac + SYS=linux + ;; + bsd/os) + OS="bsdos${os_r}" + SYS=bsdos + NDEFS="$NDEFS -DBSDOS=$os_r1" + ;; + ultrix) + OS="ultrix-$arch" + SYS=ultrix + ;; + unixware|eeyore) + OS="unixware${os_v}" + SYS=unixware + ;; + macos*|darwin|rhapsody) + OS="macosx" + SYS="macosx" + ;; + sunos) + if [ "$arch" = "" ] ; then arch="sparc" ; fi + if [ "$archp" = "" ] ; then archp="$arch" ; fi + case "$os_r" in + 5.[789]*) + os_r=`echo "$os_r" | cut -c3-` + OS="solaris${os_r}-$archp" + NDEFS="$NDEFS -DSOLARIS=\\\"$os_r\\\"" + SYS=solaris + ;; + 5.[0123456]*) + maj=`echo "$os_r" | cut -c1-1` + maj=`expr "$maj" - 3` + os_r=`echo "$os_r" | cut -c2-` + os_r="${maj}${os_r}" + OS="solaris${os_r}-$archp" + NDEFS="$NDEFS -DSOLARIS=\\\"$os_r\\\"" + SYS=solaris + ;; + 4.*) + OS="sunos${os_r}-sparc" + NDEFS="$NDEFS -DSUNOS=\\\"$os_r\\\"" + SYS=sunos + ;; + *) + OS="solaris${os_r}-$archp" + NDEFS="$NDEFS -DSOLARIS=\\\"$os_r\\\"" + SYS=solaris + ;; + esac + ;; + *) + OS="$os" + SYS="$os" + + if grep Novell /usr/include/sys/types.h ; then + OS="unixware${os_v}" + SYS="unixware" + fi + ;; +esac + +changequote([, ]) + +AC_SUBST(NDEFS) +AC_SUBST(OS) +AC_SUBST(host) +AC_SUBST(SYS) +AC_SUBST(HOME_OS) +]) diff --git a/modules/rosapps/applications/net/ncftp/libncftp/Makefile.in b/modules/rosapps/applications/net/ncftp/libncftp/Makefile.in new file mode 100644 index 00000000000..4810f0abd2e --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/Makefile.in @@ -0,0 +1,144 @@ +#----------------------------------------------------------------------------- +# +# LibNcFTP makefile for the platform @OS@, on the host @host@. +# +#----------------------------------------------------------------------------- +PKGNAME=libncftp +VERSION=3.0.1 +PREFIX=@prefix@ + +CC=@CC@ +CFLAGS=@CFLAGS@ +#CC=gcc +#CFLAGS=-g -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wbad-function-cast -Wwrite-strings -Wconversion +VPATH=@srcdir@ +CPPFLAGS=-I. -I../Strn -I../sio @CPPFLAGS@ + +LIB=libncftp.a +LIBSO=libncftp.so.2 +LIBSOS=libncftp.so + +# Any -D definitions: +DEFS=@DEFS@@NDEFS@ + +CFILES=open.c cmds.c util.c rcmd.c ftp.c io.c errno.c linelist.c glob.c +OBJS=open.o cmds.o util.o rcmd.o ftp.o io.o errno.o linelist.o glob.o +SOBJS=open.so cmds.so util.so rcmd.so ftp.so io.so errno.so linelist.so glob.so + +# LIBSET=@LIBSET@ +LIBSET=$(LIB) + +SHELL=/bin/sh +.SUFFIXES: .c .o .so + +all: $(LIBSET) + ( cd ../sio ; $(MAKE) ) + ( cd ../Strn ; $(MAKE) ) + -[ -d ./samples/minincftp ] && cd ./samples/minincftp && $(MAKE) + -[ -d ./samples/misc ] && cd ./samples/misc && $(MAKE) + -[ -d ./samples/monkey ] && cd ./samples/monkey && $(MAKE) + -[ -d ./samples/ncftpget ] && cd ./samples/ncftpget && $(MAKE) + -[ -d ./samples/ncftpls ] && cd ./samples/ncftpls && $(MAKE) + -[ -d ./samples/ncftpput ] && cd ./samples/ncftpput && $(MAKE) + -[ -d ./samples/ncftpsyncput ] && cd ./samples/ncftpsyncput && $(MAKE) + @echo 'Done.' + +$(LIB): $(OBJS) + -@/bin/rm -f $(LIB) + ar rv $(LIB) $(OBJS) + -@chmod 644 $(LIB) + -@@RANLIB@ $(LIB) + @/bin/ls -l $(LIB) + +shared: $(LIBSO) + +so: $(LIBSO) + +$(LIBSO): $(SOBJS) + /bin/rm -f $(LIBSO) $(LIBSOS) + gcc -shared -Wl,-soname,$(LIBSO) -o $(LIBSO) $(SOBJS) + /bin/ln -s $(LIBSO) $(LIBSOS) + -@/bin/ls -l $(LIBSOS) $(LIBSO) + +soinstall: $(LIBSO) + [ -d "$(PREFIX)/lib" ] || mkdir -m 755 "$(PREFIX)/lib" + [ -d "$(PREFIX)/include" ] || mkdir -m 755 "$(PREFIX)/include" + cp $(LIBSO) $(PREFIX)/lib/$(LIBSO) + ( cd $(PREFIX)/lib ; /bin/rm -f $(LIBSOS) ; /bin/ln -s $(LIBSO) $(LIBSOS) ) + cp ncftp.h ncftp_errno.h $(PREFIX)/include + -chmod a+r $(PREFIX)/lib/$(LIBSO) $(PREFIX)/include/ncftp.h $(PREFIX)/include/ncftp_errno.h + +install: $(LIB) + [ -d "$(PREFIX)/lib" ] || mkdir -m 755 "$(PREFIX)/lib" + [ -d "$(PREFIX)/include" ] || mkdir -m 755 "$(PREFIX)/include" + cp $(LIB) $(PREFIX)/lib/$(LIB) + cp ncftp.h ncftp_errno.h $(PREFIX)/include + -chmod a+r $(LIB) $(PREFIX)/lib/$(LIB) $(PREFIX)/include/ncftp.h $(PREFIX)/include/ncftp_errno.h + ( cd ../sio ; $(MAKE) "PREFIX=$(PREFIX)" install ) + ( cd ../Strn ; $(MAKE) "PREFIX=$(PREFIX)" install ) + +install_samples: + ( cd ./samples ; $(MAKE) install ) + +.c.o: + $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c + +.c.so: + $(CC) -fpic $(CFLAGS) $(CPPFLAGS) $(DEFS) $*.c -c -o $*.so + +test: test.c $(OBJS) + $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) test.c $(OBJS) -o test $(LDFLAGS) $(LIBS) + +### Archiving ################################################################# + +TARDIR=libncftp-$(VERSION) +TMPDIR=/tmp +STGZFILE=libncftp-$(VERSION)-src.tar.gz + +gz sgz: $(PACKAGE) + ./mksrctar.sh $(TARDIR) $(STGZFILE) + +### Cleaning supplies ######################################################## + +clean: + -/bin/rm -f $(OBJS) $(SOBJS) core $(LIB) $(LIBSO) $(LIBSOS) + -[ -d ./samples/minincftp ] && cd ./samples/minincftp && $(MAKE) clean + -[ -d ./samples/monkey ] && cd ./samples/monkey && $(MAKE) clean + -[ -d ./samples/ncftpget ] && cd ./samples/ncftpget && $(MAKE) clean + -[ -d ./samples/ncftpls ] && cd ./samples/ncftpls && $(MAKE) clean + -[ -d ./samples/ncftpput ] && cd ./samples/ncftpput && $(MAKE) clean + -[ -d ./samples/ncftpsyncput ] && cd ./samples/ncftpsyncput && $(MAKE) clean + ( sleep 2 ; cd ../sio ; $(MAKE) clean ) + ( sleep 2 ; cd ../Strn ; $(MAKE) clean ) + +### Dependencies ############################################################# + +dep: + gcc -MM $(CPPFLAGS) $(CFILES) + +open.o: open.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h +open.so: open.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h + +cmds.o: cmds.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h +cmds.so: cmds.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h + +util.o: util.c syshdrs.h ncftp.h ncftp_errno.h util.h +util.so: util.c syshdrs.h ncftp.h ncftp_errno.h util.h + +rcmd.o: rcmd.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h +rcmd.so: rcmd.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h + +ftp.o: ftp.c syshdrs.h ncftp.h ncftp_errno.h ftp.h util.h +ftp.so: ftp.c syshdrs.h ncftp.h ncftp_errno.h ftp.h util.h + +io.o: io.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h +io.so: io.c syshdrs.h ncftp.h ncftp_errno.h util.h ftp.h + +errno.o: errno.c syshdrs.h ncftp.h ncftp_errno.h +errno.so: errno.c syshdrs.h ncftp.h ncftp_errno.h + +linelist.o: linelist.c syshdrs.h ncftp.h ncftp_errno.h util.h +linelist.so: linelist.c syshdrs.h ncftp.h ncftp_errno.h util.h + +glob.o: glob.c syshdrs.h ncftp.h ncftp_errno.h util.h +glob.so: glob.c syshdrs.h ncftp.h ncftp_errno.h util.h diff --git a/modules/rosapps/applications/net/ncftp/libncftp/Readme.txt b/modules/rosapps/applications/net/ncftp/libncftp/Readme.txt new file mode 100644 index 00000000000..265ea888f26 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/Readme.txt @@ -0,0 +1,73 @@ +Since you have the source distribution, you will need to compile the +libraries before you can install them. + +UNIX INSTRUCTIONS: +------------------ + +Go to the source directory you extracted (here). There is a script you +must run which will checks your system for certain features, so that the +library can be compiled on a variety of UNIX systems. Run this script +by typing "./configure" in that directory. After that, you can look at +the Makefile it made if you like, and then you run "make" to create the +"libncftp.a" and "libStrn.a" library files. + +Finally, install the libraries and headers, by doing "make install". + +View the libncftp.html file for the rest of the documentation. An easy +way to do that is use a URL of file://Localhost/path/to/libncftp.html +with your favorite browser. + + +WINDOWS INSTRUCTIONS: +--------------------- + +You will need Visual C++ 6.0 or greater to build the library and sample +programs. This version includes two supplementary libraries which you +must build and link with your applications: a string utility library +(Strn) and a Winsock utility library (sio). Unlike the UNIX version of +LibNcFTP, where the library can be built with or without the sio library, +the sio library is required for the Windows version. + +Keep the source hierarchy intact, so that the samples and libraries +build without problems. Build the Strn library first, then the sio +library, and then the LibNcFTP library. To do that, open the appropriate +.dsw file within Visual Studio, and then select "Rebuild All" from the +"Build" menu. Be sure to build both the Debug and the Release versions +for each library. + +When that is complete you should be able to build the sample programs, +which are in the libncftp\samples directory. + +View the libncftp.html file for the rest of the documentation. An easy +way to do that is use a URL of file://Localhost/path/to/libncftp.html +with your favorite browser. Note that there may be UNIX-specific +instructions which you should ignore. + +To build your own applications using LibNcFTP, you'll need to make sure +you configure your project to find the header files and library files. + +Your application may not use the sio or Strn libraries directly, but +you still need to link with them. For example, the "simpleget" sample +uses "..\..\Debug,..\..\..\Strn\Debug,..\..\..\sio\Debug" in the +project option for additional library paths for the linker, and +"kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib + ws2_32.lib Strn.lib sio.lib libncftp.lib" for the list of libraries +to link with. Note that LibNcFTP uses advapi32 and shell32, in +addition to the usual "kernel32.lib user32.lib gdi32.lib". Of course, +it also needs to link with Winsock (ws2_32.lib). + +Similarly, you'll need to make sure one of your additional include +directories points to the LibNcFTP directory containing ncftp.h. The +"simpleget" sample uses "..\.." since it is in a subdirectory of the +library itself. If you actually use functions from Strn or sio (as +some of the samples do), you'll need to have your project look in +their directories for their headers as well. + +About Winsock2: This version of the library was designed for use with +Winsock version 2. Note that older versions of Windows 95 do not include +Winsock version 2, but can be upgraded by getting the updater from +Microsoft: http://www.microsoft.com/windows95/downloads/contents/wuadmintools/s_wunetworkingtools/w95sockets2/default.asp + +However, the library should also work with Winsock 1.1. That is left as +an exercise to the coder to change the Winsock initialization to use 1.1 +and to link with the 1.1 library (wsock32.lib). \ No newline at end of file diff --git a/modules/rosapps/applications/net/ncftp/libncftp/cmds.c b/modules/rosapps/applications/net/ncftp/libncftp/cmds.c new file mode 100644 index 00000000000..1430736af9e --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/cmds.c @@ -0,0 +1,1700 @@ +/* cmds.c + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#include "syshdrs.h" + +int +FTPChdir(const FTPCIPtr cip, const char *const cdCwd) +{ + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (cdCwd == NULL) { + result = kErrInvalidDirParam; + cip->errNo = kErrInvalidDirParam; + } else { + if (cdCwd[0] == '\0') /* But allow FTPChdir(cip, ".") to go through. */ + result = 2; + else if (strcmp(cdCwd, "..") == 0) + result = FTPCmd(cip, "CDUP"); + else + result = FTPCmd(cip, "CWD %s", cdCwd); + if (result >= 0) { + if (result == 2) { + result = kNoErr; + } else { + result = kErrCWDFailed; + cip->errNo = kErrCWDFailed; + } + } + } + return (result); +} /* FTPChdir */ + + + + +int +FTPChmod(const FTPCIPtr cip, const char *const pattern, const char *const mode, const int doGlob) +{ + LineList fileList; + LinePtr filePtr; + char *file; + int onceResult, batchResult; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob); + if (batchResult != kNoErr) + return (batchResult); + + for (batchResult = kNoErr, filePtr = fileList.first; + filePtr != NULL; + filePtr = filePtr->next) + { + file = filePtr->line; + if (file == NULL) { + batchResult = kErrBadLineList; + cip->errNo = kErrBadLineList; + break; + } + onceResult = FTPCmd(cip, "SITE CHMOD %s %s", mode, file); + if (onceResult < 0) { + batchResult = onceResult; + break; + } + if (onceResult != 2) { + batchResult = kErrChmodFailed; + cip->errNo = kErrChmodFailed; + } + } + DisposeLineListContents(&fileList); + return (batchResult); +} /* FTPChmod */ + + + + +static int +FTPRmdirRecursiveL2(const FTPCIPtr cip) +{ + LineList fileList; + LinePtr filePtr; + char *file; + int result; + + result = FTPRemoteGlob(cip, &fileList, "**", kGlobYes); + if (result != kNoErr) { + return (result); + } + + for (filePtr = fileList.first; + filePtr != NULL; + filePtr = filePtr->next) + { + file = filePtr->line; + if (file == NULL) { + cip->errNo = kErrBadLineList; + break; + } + + if ((file[0] == '.') && ((file[1] == '\0') || ((file[1] == '.') && (file[2] == '\0')))) + continue; /* Skip . and .. */ + + if (FTPChdir(cip, file) == kNoErr) { + /* It was a directory. + * Go in and wax it. + */ + result = FTPRmdirRecursiveL2(cip); + + if (FTPChdir(cip, "..") != kNoErr) { + /* Panic -- we can no longer + * cd back to the directory + * we were in before. + */ + result = kErrCannotGoToPrevDir; + cip->errNo = kErrCannotGoToPrevDir; + return (result); + } + + if ((result < 0) && (result != kErrGlobNoMatch)) + return (result); + + result = FTPRmdir(cip, file, kRecursiveNo, kGlobNo); + if (result != kNoErr) { + /* Well, we couldn't remove the empty + * directory. Perhaps we screwed up + * and the directory wasn't empty. + */ + return (result); + } + } else { + /* Assume it was a file -- remove it. */ + result = FTPDelete(cip, file, kRecursiveNo, kGlobNo); + /* Try continuing to remove the rest, + * even if this failed. + */ + } + } + DisposeLineListContents(&fileList); + + return (result); +} /* FTPRmdirRecursiveL2 */ + + + +static int +FTPRmdirRecursive(const FTPCIPtr cip, const char *const dir) +{ + int result, result2; + + /* Preserve old working directory. */ + (void) FTPGetCWD(cip, cip->buf, cip->bufSize); + + result = FTPChdir(cip, dir); + if (result != kNoErr) { + return (result); + } + + result = FTPRmdirRecursiveL2(cip); + + if (FTPChdir(cip, cip->buf) != kNoErr) { + /* Could not cd back to the original user directory -- bad. */ + if (result != kNoErr) { + result = kErrCannotGoToPrevDir; + cip->errNo = kErrCannotGoToPrevDir; + } + return (result); + } + + /* Now rmdir the last node, the root of the tree + * we just went through. + */ + result2 = FTPRmdir(cip, dir, kRecursiveNo, kGlobNo); + if ((result2 != kNoErr) && (result == kNoErr)) + result = result2; + + return (result); +} /* FTPRmdirRecursive */ + + + + +int +FTPDelete(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob) +{ + LineList fileList; + LinePtr filePtr; + char *file; + int onceResult, batchResult; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob); + if (batchResult != kNoErr) + return (batchResult); + + for (batchResult = kNoErr, filePtr = fileList.first; + filePtr != NULL; + filePtr = filePtr->next) + { + file = filePtr->line; + if (file == NULL) { + batchResult = kErrBadLineList; + cip->errNo = kErrBadLineList; + break; + } + onceResult = FTPCmd(cip, "DELE %s", file); + if (onceResult < 0) { + batchResult = onceResult; + break; + } + if (onceResult != 2) { + if (recurse != kRecursiveYes) { + batchResult = kErrDELEFailed; + cip->errNo = kErrDELEFailed; + } else { + onceResult = FTPCmd(cip, "RMD %s", file); + if (onceResult < 0) { + batchResult = onceResult; + break; + } + if (onceResult != 2) { + onceResult = FTPRmdirRecursive(cip, file); + if (onceResult < 0) { + batchResult = kErrRMDFailed; + cip->errNo = kErrRMDFailed; + } + } + } + } + } + DisposeLineListContents(&fileList); + return (batchResult); +} /* FTPDelete */ + + + + +int +FTPGetCWD(const FTPCIPtr cip, char *const newCwd, const size_t newCwdSize) +{ + ResponsePtr rp; + char *l, *r; + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((newCwd == NULL) || (newCwdSize == 0)) { + result = kErrInvalidDirParam; + cip->errNo = kErrInvalidDirParam; + } else { + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + } else { + result = RCmd(cip, rp, "PWD"); + if (result == 2) { + if ((r = strrchr(rp->msg.first->line, '"')) != NULL) { + /* "xxxx" is current directory. + * Strip out just the xxxx to copy into the remote cwd. + */ + l = strchr(rp->msg.first->line, '"'); + if ((l != NULL) && (l != r)) { + *r = '\0'; + ++l; + (void) Strncpy(newCwd, l, newCwdSize); + *r = '"'; /* Restore, so response prints correctly. */ + } + } else { + /* xxxx is current directory. + * Mostly for VMS. + */ + if ((r = strchr(rp->msg.first->line, ' ')) != NULL) { + *r = '\0'; + (void) Strncpy(newCwd, (rp->msg.first->line), newCwdSize); + *r = ' '; /* Restore, so response prints correctly. */ + } + } + result = kNoErr; + } else if (result > 0) { + result = kErrPWDFailed; + cip->errNo = kErrPWDFailed; + } + DoneWithResponse(cip, rp); + } + } + return (result); +} /* FTPGetCWD */ + + + + +int +FTPChdirAndGetCWD(const FTPCIPtr cip, const char *const cdCwd, char *const newCwd, const size_t newCwdSize) +{ + ResponsePtr rp; + char *l, *r; + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((newCwd == NULL) || (cdCwd == NULL)) { + result = kErrInvalidDirParam; + cip->errNo = kErrInvalidDirParam; + } else { + if (cdCwd[0] == '\0') { /* But allow FTPChdir(cip, ".") to go through. */ + result = FTPGetCWD(cip, newCwd, newCwdSize); + return (result); + } + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + } else { + if (strcmp(cdCwd, "..") == 0) + result = RCmd(cip, rp, "CDUP"); + else + result = RCmd(cip, rp, "CWD %s", cdCwd); + if (result == 2) { + l = strchr(rp->msg.first->line, '"'); + if ((l == rp->msg.first->line) && ((r = strrchr(rp->msg.first->line, '"')) != NULL) && (l != r)) { + /* "xxxx" is current directory. + * Strip out just the xxxx to copy into the remote cwd. + * + * This is nice because we didn't have to do a PWD. + */ + *r = '\0'; + ++l; + (void) Strncpy(newCwd, l, newCwdSize); + *r = '"'; /* Restore, so response prints correctly. */ + DoneWithResponse(cip, rp); + result = kNoErr; + } else { + DoneWithResponse(cip, rp); + result = FTPGetCWD(cip, newCwd, newCwdSize); + } + } else if (result > 0) { + result = kErrCWDFailed; + cip->errNo = kErrCWDFailed; + DoneWithResponse(cip, rp); + } else { + DoneWithResponse(cip, rp); + } + } + } + return (result); +} /* FTPChdirAndGetCWD */ + + + + +int +FTPChdir3(FTPCIPtr cip, const char *const cdCwd, char *const newCwd, const size_t newCwdSize, int flags) +{ + char *cp, *startcp; + int result; + int lastSubDir; + int mkd, pwd; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (cdCwd == NULL) { + result = kErrInvalidDirParam; + cip->errNo = kErrInvalidDirParam; + return result; + } + + if (flags == kChdirOnly) + return (FTPChdir(cip, cdCwd)); + if (flags == kChdirAndGetCWD) { + return (FTPChdirAndGetCWD(cip, cdCwd, newCwd, newCwdSize)); + } else if (flags == kChdirAndMkdir) { + result = FTPMkdir(cip, cdCwd, kRecursiveYes); + if (result == kNoErr) + result = FTPChdir(cip, cdCwd); + return result; + } else if (flags == (kChdirAndMkdir|kChdirAndGetCWD)) { + result = FTPMkdir(cip, cdCwd, kRecursiveYes); + if (result == kNoErr) + result = FTPChdirAndGetCWD(cip, cdCwd, newCwd, newCwdSize); + return result; + } + + /* else: (flags | kChdirOneSubdirAtATime) == true */ + + cp = cip->buf; + cp[cip->bufSize - 1] = '\0'; + (void) Strncpy(cip->buf, cdCwd, cip->bufSize); + if (cp[cip->bufSize - 1] != '\0') + return (kErrBadParameter); + + mkd = (flags & kChdirAndMkdir); + pwd = (flags & kChdirAndGetCWD); + + if ((cdCwd[0] == '\0') || (strcmp(cdCwd, ".") == 0)) { + result = 0; + if (flags == kChdirAndGetCWD) + result = FTPGetCWD(cip, newCwd, newCwdSize); + return (result); + } + + lastSubDir = 0; + do { + startcp = cp; + cp = StrFindLocalPathDelim(cp); + if (cp != NULL) { + /* If this is the first slash in an absolute + * path, then startcp will be empty. We will + * use this below to treat this as the root + * directory. + */ + *cp++ = '\0'; + } else { + lastSubDir = 1; + } + if (strcmp(startcp, ".") == 0) { + result = 0; + if ((lastSubDir != 0) && (pwd != 0)) + result = FTPGetCWD(cip, newCwd, newCwdSize); + } else if ((lastSubDir != 0) && (pwd != 0)) { + result = FTPChdirAndGetCWD(cip, (*startcp != '\0') ? startcp : "/", newCwd, newCwdSize); + } else { + result = FTPChdir(cip, (*startcp != '\0') ? startcp : "/"); + } + if (result < 0) { + if ((mkd != 0) && (*startcp != '\0')) { + if (FTPCmd(cip, "MKD %s", startcp) == 2) { + result = FTPChdir(cip, startcp); + } else { + /* couldn't change nor create */ + cip->errNo = result; + } + } else { + cip->errNo = result; + } + } + } while ((!lastSubDir) && (result == 0)); + + return (result); +} /* FTPChdir3 */ + + + + +int +FTPMkdir2(const FTPCIPtr cip, const char *const newDir, const int recurse, const char *const curDir) +{ + int result, result2; + char *cp, *newTreeStart, *cp2; + char dir[512]; + char dir2[512]; + char c; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((newDir == NULL) || (newDir[0] == '\0')) { + cip->errNo = kErrInvalidDirParam; + return (kErrInvalidDirParam); + } + + /* Preserve old working directory. */ + if ((curDir == NULL) || (curDir[0] == '\0')) { + /* This hack is nice so you can eliminate an + * unnecessary "PWD" command on the server, + * since if you already knew what directory + * you're in. We want to minimize the number + * of client-server exchanges when feasible. + */ + (void) FTPGetCWD(cip, cip->buf, cip->bufSize); + } + + result = FTPChdir(cip, newDir); + if (result == kNoErr) { + /* Directory already exists -- but we + * must now change back to where we were. + */ + result2 = FTPChdir(cip, ((curDir == NULL) || (curDir[0] == '\0')) ? cip->buf : curDir); + if (result2 < 0) { + result = kErrCannotGoToPrevDir; + cip->errNo = kErrCannotGoToPrevDir; + return (result); + } + + /* Don't need to create it. */ + return (kNoErr); + } + + if (recurse == kRecursiveNo) { + result = FTPCmd(cip, "MKD %s", newDir); + if (result > 0) { + if (result != 2) { + Error(cip, kDontPerror, "MKD %s failed; [%s]\n", newDir, cip->lastFTPCmdResultStr); + result = kErrMKDFailed; + cip->errNo = kErrMKDFailed; + return (result); + } else { + result = kNoErr; + } + } + } else { + (void) STRNCPY(dir, newDir); + + /* Strip trailing slashes. */ + cp = dir + strlen(dir) - 1; + for (;;) { + if (cp <= dir) { + if ((newDir == NULL) || (newDir[0] == '\0')) { + cip->errNo = kErrInvalidDirParam; + result = kErrInvalidDirParam; + return (result); + } + } + if ((*cp != '/') && (*cp != '\\')) { + cp[1] = '\0'; + break; + } + --cp; + } + (void) STRNCPY(dir2, dir); + + if ((strrchr(dir, '/') == dir) || (strrchr(dir, '\\') == dir)) { + /* Special case "mkdir /subdir" */ + result = FTPCmd(cip, "MKD %s", dir); + if (result < 0) { + return (result); + } + if (result != 2) { + Error(cip, kDontPerror, "MKD %s failed; [%s]\n", dir, cip->lastFTPCmdResultStr); + result = kErrMKDFailed; + cip->errNo = kErrMKDFailed; + return (result); + } + /* Haven't chdir'ed, don't need to goto goback. */ + return (kNoErr); + } + + for (;;) { + cp = strrchr(dir, '/'); + if (cp == NULL) + cp = strrchr(dir, '\\'); + if (cp == NULL) { + cp = dir + strlen(dir) - 1; + if (dir[0] == '\0') { + result = kErrMKDFailed; + cip->errNo = kErrMKDFailed; + return (result); + } + /* Note: below we will refer to cp + 1 + * which is why we set cp to point to + * the byte before the array begins! + */ + cp = dir - 1; + break; + } + if (cp == dir) { + result = kErrMKDFailed; + cip->errNo = kErrMKDFailed; + return (result); + } + *cp = '\0'; + result = FTPChdir(cip, dir); + if (result == 0) { + break; /* Found a valid parent dir. */ + /* from this point, we need to preserve old dir. */ + } + } + + newTreeStart = dir2 + ((cp + 1) - dir); + for (cp = newTreeStart; ; ) { + cp2 = cp; + cp = strchr(cp2, '/'); + c = '/'; + if (cp == NULL) + cp = strchr(cp2, '\\'); + if (cp != NULL) { + c = *cp; + *cp = '\0'; + if (cp[1] == '\0') { + /* Done, if they did "mkdir /tmp/dir/" */ + break; + } + } + result = FTPCmd(cip, "MKD %s", newTreeStart); + if (result < 0) { + return (result); + } + if (result != 2) { + Error(cip, kDontPerror, "Cwd=%s; MKD %s failed; [%s]\n", cip->buf, newTreeStart, cip->lastFTPCmdResultStr); + result = kErrMKDFailed; + cip->errNo = kErrMKDFailed; + goto goback; + } + if (cp == NULL) + break; /* No more to make, done. */ + *cp++ = c; + } + result = kNoErr; + +goback: + result2 = FTPChdir(cip, ((curDir == NULL) || (curDir[0] == '\0')) ? cip->buf : curDir); + if ((result == 0) && (result2 < 0)) { + result = kErrCannotGoToPrevDir; + cip->errNo = kErrCannotGoToPrevDir; + } + } + return (result); +} /* FTPMkdir2 */ + + + +int +FTPMkdir(const FTPCIPtr cip, const char *const newDir, const int recurse) +{ + return (FTPMkdir2(cip, newDir, recurse, NULL)); +} /* FTPMkdir */ + + + +int +FTPFileModificationTime(const FTPCIPtr cip, const char *const file, time_t *const mdtm) +{ + int result; + ResponsePtr rp; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((mdtm == NULL) || (file == NULL)) + return (kErrBadParameter); + *mdtm = kModTimeUnknown; + + if (cip->hasMDTM == kCommandNotAvailable) { + cip->errNo = kErrMDTMNotAvailable; + result = kErrMDTMNotAvailable; + } else { + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + } else { + result = RCmd(cip, rp, "MDTM %s", file); + if (result < 0) { + DoneWithResponse(cip, rp); + return (result); + } else if (strncmp(rp->msg.first->line, "19100", 5) == 0) { + Error(cip, kDontPerror, "Warning: Server has Y2K Bug in \"MDTM\" command.\n"); + cip->errNo = kErrMDTMFailed; + result = kErrMDTMFailed; + } else if (result == 2) { + *mdtm = UnMDTMDate(rp->msg.first->line); + cip->hasMDTM = kCommandAvailable; + result = kNoErr; + } else if (UNIMPLEMENTED_CMD(rp->code)) { + cip->hasMDTM = kCommandNotAvailable; + cip->errNo = kErrMDTMNotAvailable; + result = kErrMDTMNotAvailable; + } else { + cip->errNo = kErrMDTMFailed; + result = kErrMDTMFailed; + } + DoneWithResponse(cip, rp); + } + } + return (result); +} /* FTPFileModificationTime */ + + + + +int +FTPRename(const FTPCIPtr cip, const char *const oldname, const char *const newname) +{ + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + if ((oldname == NULL) || (oldname[0] == '\0')) + return (kErrBadParameter); + if ((newname == NULL) || (oldname[0] == '\0')) + return (kErrBadParameter); + + + result = FTPCmd(cip, "RNFR %s", oldname); + if (result < 0) + return (result); + if (result != 3) { + cip->errNo = kErrRenameFailed; + return (cip->errNo); + } + + result = FTPCmd(cip, "RNTO %s", newname); + if (result < 0) + return (result); + if (result != 2) { + cip->errNo = kErrRenameFailed; + return (cip->errNo); + } + return (kNoErr); +} /* FTPRename */ + + + + +int +FTPRemoteHelp(const FTPCIPtr cip, const char *const pattern, const LineListPtr llp) +{ + int result; + ResponsePtr rp; + + if ((cip == NULL) || (llp == NULL)) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + InitLineList(llp); + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + } else { + if ((pattern == NULL) || (*pattern == '\0')) + result = RCmd(cip, rp, "HELP"); + else + result = RCmd(cip, rp, "HELP %s", pattern); + if (result < 0) { + DoneWithResponse(cip, rp); + return (result); + } else if (result == 2) { + if (CopyLineList(llp, &rp->msg) < 0) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + } else { + result = kNoErr; + } + } else { + cip->errNo = kErrHELPFailed; + result = kErrHELPFailed; + } + DoneWithResponse(cip, rp); + } + return (result); +} /* FTPRemoteHelp */ + + + + +int +FTPRmdir(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob) +{ + LineList fileList; + LinePtr filePtr; + char *file; + int onceResult, batchResult; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob); + if (batchResult != kNoErr) + return (batchResult); + + for (batchResult = kNoErr, filePtr = fileList.first; + filePtr != NULL; + filePtr = filePtr->next) + { + file = filePtr->line; + if (file == NULL) { + batchResult = kErrBadLineList; + cip->errNo = kErrBadLineList; + break; + } + onceResult = FTPCmd(cip, "RMD %s", file); + if (onceResult < 0) { + batchResult = onceResult; + break; + } + if (onceResult != 2) { + if (recurse == kRecursiveYes) { + onceResult = FTPRmdirRecursive(cip, file); + if (onceResult < 0) { + batchResult = kErrRMDFailed; + cip->errNo = kErrRMDFailed; + } + } else { + batchResult = kErrRMDFailed; + cip->errNo = kErrRMDFailed; + } + } + } + DisposeLineListContents(&fileList); + return (batchResult); +} /* FTPRmdir */ + + + + +int +FTPSetTransferType(const FTPCIPtr cip, int type) +{ + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (cip->curTransferType != type) { + switch (type) { + case kTypeAscii: + case kTypeBinary: + case kTypeEbcdic: + break; + case 'i': + case 'b': + case 'B': + type = kTypeBinary; + break; + case 'e': + type = kTypeEbcdic; + break; + case 'a': + type = kTypeAscii; + break; + default: + /* Yeah, we don't support Tenex. Who cares? */ + Error(cip, kDontPerror, "Bad transfer type [%c].\n", type); + cip->errNo = kErrBadTransferType; + return (kErrBadTransferType); + } + result = FTPCmd(cip, "TYPE %c", type); + if (result != 2) { + result = kErrTYPEFailed; + cip->errNo = kErrTYPEFailed; + return (result); + } + cip->curTransferType = type; + } + return (kNoErr); +} /* FTPSetTransferType */ + + + + +/* If the remote host supports the SIZE command, we can find out the exact + * size of a remote file, depending on the transfer type in use. SIZE + * returns different values for ascii and binary modes! + */ +int +FTPFileSize(const FTPCIPtr cip, const char *const file, longest_int *const size, const int type) +{ + int result; + ResponsePtr rp; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((size == NULL) || (file == NULL)) + return (kErrBadParameter); + *size = kSizeUnknown; + + result = FTPSetTransferType(cip, type); + if (result < 0) + return (result); + + if (cip->hasSIZE == kCommandNotAvailable) { + cip->errNo = kErrSIZENotAvailable; + result = kErrSIZENotAvailable; + } else { + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + } else { + result = RCmd(cip, rp, "SIZE %s", file); + if (result < 0) { + DoneWithResponse(cip, rp); + return (result); + } else if (result == 2) { +#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG) + (void) sscanf(rp->msg.first->line, SCANF_LONG_LONG, size); +#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ) + *size = (longest_int) strtoq(rp->msg.first->line, NULL, 0); +#else + (void) sscanf(rp->msg.first->line, "%ld", size); +#endif + cip->hasSIZE = kCommandAvailable; + result = kNoErr; + } else if (UNIMPLEMENTED_CMD(rp->code)) { + cip->hasSIZE = kCommandNotAvailable; + cip->errNo = kErrSIZENotAvailable; + result = kErrSIZENotAvailable; + } else { + cip->errNo = kErrSIZEFailed; + result = kErrSIZEFailed; + } + DoneWithResponse(cip, rp); + } + } + return (result); +} /* FTPFileSize */ + + + + +int +FTPMListOneFile(const FTPCIPtr cip, const char *const file, const MLstItemPtr mlip) +{ + int result; + ResponsePtr rp; + + /* We do a special check for older versions of NcFTPd which + * are based off of an incompatible previous version of IETF + * extensions. + * + * Roxen also seems to be way outdated, where MLST was on the + * data connection among other things. + * + */ + if ( + (cip->hasMLST == kCommandNotAvailable) || + ((cip->serverType == kServerTypeNcFTPd) && (cip->ietfCompatLevel < 19981201)) || + (cip->serverType == kServerTypeRoxen) + ) { + cip->errNo = kErrMLSTNotAvailable; + return (cip->errNo); + } + + rp = InitResponse(); + if (rp == NULL) { + result = cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + } else { + result = RCmd(cip, rp, "MLST %s", file); + if ( + (result == 2) && + (rp->msg.first->line != NULL) && + (rp->msg.first->next != NULL) && + (rp->msg.first->next->line != NULL) + ) { + result = UnMlsT(rp->msg.first->next->line, mlip); + if (result < 0) { + cip->errNo = result = kErrInvalidMLSTResponse; + } + } else if (UNIMPLEMENTED_CMD(rp->code)) { + cip->hasMLST = kCommandNotAvailable; + cip->errNo = kErrMLSTNotAvailable; + result = kErrMLSTNotAvailable; + } else { + cip->errNo = kErrMLSTFailed; + result = kErrMLSTFailed; + } + DoneWithResponse(cip, rp); + } + + return (result); +} /* FTPMListOneFile */ + + + + +/* We only use STAT to see if files or directories exist. + * But since it is so rarely used in the wild, we need to + * make sure the server supports the use where we pass + * a pathname as a parameter. + */ +int +FTPFileExistsStat(const FTPCIPtr cip, const char *const file) +{ + int result; + ResponsePtr rp; + LineList fileList; + char savedCwd[512]; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (file == NULL) + return (kErrBadParameter); + + if (cip->STATfileParamWorks == kCommandNotAvailable) { + cip->errNo = result = kErrSTATwithFileNotAvailable; + return (result); + } + + if (cip->STATfileParamWorks == kCommandAvailabilityUnknown) { + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + return (result); + + } + + /* First, make sure that when we STAT a pathname + * that does not exist, that we get an error back. + * + * We also assume that a valid STAT response has + * at least 3 lines of response text, typically + * a "start" line, intermediate data, and then + * a trailing line. + * + * We also can see a one-line case. + */ + result = RCmd(cip, rp, "STAT %s", "NoSuchFile"); + if ((result == 2) && ((rp->msg.nLines >= 3) || (rp->msg.nLines == 1))) { + /* Hmmm.... it gave back a positive + * response. So STAT does not + * work correctly. + */ + if ( + (rp->msg.first->next != NULL) && + (rp->msg.first->next->line != NULL) && + ( + (strstr(rp->msg.first->next->line, "o such file") != NULL) || + (strstr(rp->msg.first->next->line, "ot found") != NULL) + ) + ) { + /* OK, while we didn't want a 200 + * level response, some servers, + * like wu-ftpd print an error + * message "No such file or + * directory" which we can special + * case. + */ + result = kNoErr; + } else { + cip->STATfileParamWorks = kCommandNotAvailable; + cip->errNo = result = kErrSTATwithFileNotAvailable; + DoneWithResponse(cip, rp); + return (result); + } + } + DoneWithResponse(cip, rp); + + /* We can't assume that we can simply say STAT rootdir/firstfile, + * since the remote host may not be using / as a directory + * delimiter. So we have to change to the root directory + * and then do the STAT on that file. + */ + if ( + (FTPGetCWD(cip, savedCwd, sizeof(savedCwd)) != kNoErr) || + (FTPChdir(cip, cip->startingWorkingDirectory) != kNoErr) + ) { + return (cip->errNo); + } + + /* OK, we get an error when we stat + * a non-existant file, but now we need to + * see if we get a positive reply when + * we stat a file that does exist. + * + * To do this, we list the root directory, + * which we assume has one or more items. + * If it doesn't, the user can't do anything + * anyway. Then we stat the first item + * we found to see if STAT says it exists. + */ + if ( + ((result = FTPListToMemory2(cip, "", &fileList, "", 0, (int *) 0)) < 0) || + (fileList.last == NULL) || + (fileList.last->line == NULL) + ) { + /* Hmmm... well, in any case we can't use STAT. */ + cip->STATfileParamWorks = kCommandNotAvailable; + cip->errNo = result = kErrSTATwithFileNotAvailable; + DisposeLineListContents(&fileList); + (void) FTPChdir(cip, savedCwd); + return (result); + } + + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + DisposeLineListContents(&fileList); + (void) FTPChdir(cip, savedCwd); + return (result); + + } + + result = RCmd(cip, rp, "STAT %s", fileList.last->line); + DisposeLineListContents(&fileList); + + if ((result != 2) || (rp->msg.nLines == 2)) { + /* Hmmm.... it gave back a negative + * response. So STAT does not + * work correctly. + */ + cip->STATfileParamWorks = kCommandNotAvailable; + cip->errNo = result = kErrSTATwithFileNotAvailable; + DoneWithResponse(cip, rp); + (void) FTPChdir(cip, savedCwd); + return (result); + } else if ( + (rp->msg.first->next != NULL) && + (rp->msg.first->next->line != NULL) && + ( + (strstr(rp->msg.first->next->line, "o such file") != NULL) || + (strstr(rp->msg.first->next->line, "ot found") != NULL) + ) + ) { + /* Same special-case of the second line of STAT response. */ + cip->STATfileParamWorks = kCommandNotAvailable; + cip->errNo = result = kErrSTATwithFileNotAvailable; + DoneWithResponse(cip, rp); + (void) FTPChdir(cip, savedCwd); + return (result); + } + DoneWithResponse(cip, rp); + cip->STATfileParamWorks = kCommandAvailable; + + /* Don't forget to change back to the original directory. */ + (void) FTPChdir(cip, savedCwd); + } + + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + return (result); + } + + result = RCmd(cip, rp, "STAT %s", file); + if (result == 2) { + result = kNoErr; + if (((rp->msg.nLines >= 3) || (rp->msg.nLines == 1))) { + if ( + (rp->msg.first->next != NULL) && + (rp->msg.first->next->line != NULL) && + ( + (strstr(rp->msg.first->next->line, "o such file") != NULL) || + (strstr(rp->msg.first->next->line, "ot found") != NULL) + ) + ) { + cip->errNo = kErrSTATFailed; + result = kErrSTATFailed; + } else { + result = kNoErr; + } + } else if (rp->msg.nLines == 2) { + cip->errNo = kErrSTATFailed; + result = kErrSTATFailed; + } else { + result = kNoErr; + } + } else { + cip->errNo = kErrSTATFailed; + result = kErrSTATFailed; + } + DoneWithResponse(cip, rp); + return (result); +} /* FTPFileExistsStat */ + + + + +/* We only use STAT to see if files or directories exist. + * But since it is so rarely used in the wild, we need to + * make sure the server supports the use where we pass + * a pathname as a parameter. + */ +int +FTPFileExistsNlst(const FTPCIPtr cip, const char *const file) +{ + int result; + LineList fileList, rootFileList; + char savedCwd[512]; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (file == NULL) + return (kErrBadParameter); + + if (cip->NLSTfileParamWorks == kCommandNotAvailable) { + cip->errNo = result = kErrNLSTwithFileNotAvailable; + return (result); + } + + if (cip->NLSTfileParamWorks == kCommandAvailabilityUnknown) { + /* First, make sure that when we NLST a pathname + * that does not exist, that we get an error back. + * + * We also assume that a valid NLST response has + * at least 3 lines of response text, typically + * a "start" line, intermediate data, and then + * a trailing line. + * + * We also can see a one-line case. + */ + if ( + ((FTPListToMemory2(cip, "NoSuchFile", &fileList, "", 0, (int *) 0)) == kNoErr) && + (fileList.nLines >= 1) && + (strstr(fileList.last->line, "o such file") == NULL) && + (strstr(fileList.last->line, "ot found") == NULL) && + (strstr(fileList.last->line, "o Such File") == NULL) && + (strstr(fileList.last->line, "ot Found") == NULL) + + ) { + cip->NLSTfileParamWorks = kCommandNotAvailable; + cip->errNo = result = kErrNLSTwithFileNotAvailable; + DisposeLineListContents(&fileList); + return (result); + } + DisposeLineListContents(&fileList); + + /* We can't assume that we can simply say NLST rootdir/firstfile, + * since the remote host may not be using / as a directory + * delimiter. So we have to change to the root directory + * and then do the NLST on that file. + */ + if ( + (FTPGetCWD(cip, savedCwd, sizeof(savedCwd)) != kNoErr) || + (FTPChdir(cip, cip->startingWorkingDirectory) != kNoErr) + ) { + return (cip->errNo); + } + + /* OK, we get an error when we list + * a non-existant file, but now we need to + * see if we get a positive reply when + * we stat a file that does exist. + * + * To do this, we list the root directory, + * which we assume has one or more items. + * If it doesn't, the user can't do anything + * anyway. Then we do the first item + * we found to see if NLST says it exists. + */ + if ( + ((result = FTPListToMemory2(cip, "", &rootFileList, "", 0, (int *) 0)) < 0) || + (rootFileList.last == NULL) || + (rootFileList.last->line == NULL) + ) { + /* Hmmm... well, in any case we can't use NLST. */ + cip->NLSTfileParamWorks = kCommandNotAvailable; + cip->errNo = result = kErrNLSTwithFileNotAvailable; + DisposeLineListContents(&rootFileList); + (void) FTPChdir(cip, savedCwd); + return (result); + } + + if ( + ((FTPListToMemory2(cip, rootFileList.last->line, &fileList, "", 0, (int *) 0)) == kNoErr) && + (fileList.nLines >= 1) && + (strstr(fileList.last->line, "o such file") == NULL) && + (strstr(fileList.last->line, "ot found") == NULL) && + (strstr(fileList.last->line, "o Such File") == NULL) && + (strstr(fileList.last->line, "ot Found") == NULL) + + ) { + /* Good. We listed the item. */ + DisposeLineListContents(&fileList); + DisposeLineListContents(&rootFileList); + cip->NLSTfileParamWorks = kCommandAvailable; + + /* Don't forget to change back to the original directory. */ + (void) FTPChdir(cip, savedCwd); + } else { + cip->NLSTfileParamWorks = kCommandNotAvailable; + cip->errNo = result = kErrNLSTwithFileNotAvailable; + DisposeLineListContents(&fileList); + DisposeLineListContents(&rootFileList); + (void) FTPChdir(cip, savedCwd); + return (result); + } + } + + /* Check the requested item. */ + InitLineList(&fileList); + if ( + ((FTPListToMemory2(cip, file, &fileList, "", 0, (int *) 0)) == kNoErr) && + (fileList.nLines >= 1) && + (strstr(fileList.last->line, "o such file") == NULL) && + (strstr(fileList.last->line, "ot found") == NULL) && + (strstr(fileList.last->line, "o Such File") == NULL) && + (strstr(fileList.last->line, "ot Found") == NULL) + + ) { + /* The item existed. */ + result = kNoErr; + } else { + cip->errNo = kErrNLSTFailed; + result = kErrNLSTFailed; + } + + DisposeLineListContents(&fileList); + return (result); +} /* FTPFileExistsNlst*/ + + + + +/* This functions goes to a great deal of trouble to try and determine if the + * remote file specified exists. Newer servers support commands that make + * it relatively inexpensive to find the answer, but older servers do not + * provide a standard way. This means we may try a whole bunch of things, + * but the good news is that the library saves information about which things + * worked so if you do this again it uses the methods that work. + */ +int +FTPFileExists2(const FTPCIPtr cip, const char *const file, const int tryMDTM, const int trySIZE, const int tryMLST, const int trySTAT, const int tryNLST) +{ + int result; + time_t mdtm; + longest_int size; + MLstItem mlsInfo; + + if (tryMDTM != 0) { + result = FTPFileModificationTime(cip, file, &mdtm); + if (result == kNoErr) + return (kNoErr); + if (result == kErrMDTMFailed) { + cip->errNo = kErrNoSuchFileOrDirectory; + return (kErrNoSuchFileOrDirectory); + } + /* else keep going */ + } + + if (trySIZE != 0) { + result = FTPFileSize(cip, file, &size, kTypeBinary); + if (result == kNoErr) + return (kNoErr); + /* SIZE could fail if the server does + * not support it for directories. + * + * if (result == kErrSIZEFailed) + * return (kErrNoSuchFileOrDirectory); + */ + /* else keep going */ + } + + + if (tryMLST != 0) { + result = FTPMListOneFile(cip, file, &mlsInfo); + if (result == kNoErr) + return (kNoErr); + if (result == kErrMLSTFailed) { + cip->errNo = kErrNoSuchFileOrDirectory; + return (kErrNoSuchFileOrDirectory); + } + /* else keep going */ + } + + if (trySTAT != 0) { + result = FTPFileExistsStat(cip, file); + if (result == kNoErr) + return (kNoErr); + if (result == kErrSTATFailed) { + cip->errNo = kErrNoSuchFileOrDirectory; + return (kErrNoSuchFileOrDirectory); + } + /* else keep going */ + } + + if (tryNLST != 0) { + result = FTPFileExistsNlst(cip, file); + if (result == kNoErr) + return (kNoErr); + if (result == kErrNLSTFailed) { + cip->errNo = kErrNoSuchFileOrDirectory; + return (kErrNoSuchFileOrDirectory); + } + /* else keep going */ + } + + cip->errNo = kErrCantTellIfFileExists; + return (kErrCantTellIfFileExists); +} /* FTPFileExists2 */ + + + + +int +FTPFileExists(const FTPCIPtr cip, const char *const file) +{ + return (FTPFileExists2(cip, file, 1, 1, 1, 1, 1)); +} /* FTPFileExists */ + + + + + +int +FTPFileSizeAndModificationTime(const FTPCIPtr cip, const char *const file, longest_int *const size, const int type, time_t *const mdtm) +{ + MLstItem mlsInfo; + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((mdtm == NULL) || (size == NULL) || (file == NULL)) + return (kErrBadParameter); + + *mdtm = kModTimeUnknown; + *size = kSizeUnknown; + + result = FTPSetTransferType(cip, type); + if (result < 0) + return (result); + + result = FTPMListOneFile(cip, file, &mlsInfo); + if (result < 0) { + /* Do it the regular way, where + * we do a SIZE and then a MDTM. + */ + result = FTPFileSize(cip, file, size, type); + if (result < 0) + return (result); + result = FTPFileModificationTime(cip, file, mdtm); + return (result); + } else { + *mdtm = mlsInfo.ftime; + *size = mlsInfo.fsize; + } + + return (result); +} /* FTPFileSizeAndModificationTime */ + + + + +int +FTPFileType(const FTPCIPtr cip, const char *const file, int *const ftype) +{ + int result; + MLstItem mlsInfo; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((file == NULL) || (file[0] == '\0')) { + cip->errNo = kErrBadParameter; + return (kErrBadParameter); + } + + if (ftype == NULL) { + cip->errNo = kErrBadParameter; + return (kErrBadParameter); + } + + *ftype = 0; + result = FTPMListOneFile(cip, file, &mlsInfo); + if (result == kNoErr) { + *ftype = mlsInfo.ftype; + return (kNoErr); + } + + /* Preserve old working directory. */ + (void) FTPGetCWD(cip, cip->buf, cip->bufSize); + + result = FTPChdir(cip, file); + if (result == kNoErr) { + *ftype = 'd'; + /* Yes it was a directory, now go back to + * where we were. + */ + (void) FTPChdir(cip, cip->buf); + + /* Note: This improperly assumes that we + * will be able to chdir back, which is + * not guaranteed. + */ + return (kNoErr); + } + + result = FTPFileExists2(cip, file, 1, 1, 0, 1, 1); + if (result != kErrNoSuchFileOrDirectory) + result = kErrFileExistsButCannotDetermineType; + + return (result); +} /* FTPFileType */ + + + + +int +FTPIsDir(const FTPCIPtr cip, const char *const dir) +{ + int result, ftype; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((dir == NULL) || (dir[0] == '\0')) { + cip->errNo = kErrInvalidDirParam; + return (kErrInvalidDirParam); + } + + result = FTPFileType(cip, dir, &ftype); + if ((result == kNoErr) || (result == kErrFileExistsButCannotDetermineType)) { + result = 0; + if (ftype == 'd') + result = 1; + } + return (result); +} /* FTPIsDir */ + + + + +int +FTPIsRegularFile(const FTPCIPtr cip, const char *const file) +{ + int result, ftype; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((file == NULL) || (file[0] == '\0')) { + cip->errNo = kErrBadParameter; + return (kErrBadParameter); + } + + result = FTPFileType(cip, file, &ftype); + if ((result == kNoErr) || (result == kErrFileExistsButCannotDetermineType)) { + result = 1; + if (ftype == 'd') + result = 0; + } + return (result); +} /* FTPIsRegularFile */ + + + + +int +FTPSymlink(const FTPCIPtr cip, const char *const lfrom, const char *const lto) +{ + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + if ((cip == NULL) || (lfrom == NULL) || (lto == NULL)) + return (kErrBadParameter); + if ((lfrom[0] == '\0') || (lto[0] == '\0')) + return (kErrBadParameter); + if (FTPCmd(cip, "SITE SYMLINK %s %s", lfrom, lto) == 2) + return (kNoErr); + return (kErrSYMLINKFailed); +} /* FTPSymlink */ + + + + +int +FTPUmask(const FTPCIPtr cip, const char *const umsk) +{ + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + if ((umsk == NULL) || (umsk[0] == '\0')) + return (kErrBadParameter); + if (FTPCmd(cip, "SITE UMASK %s", umsk) == 2) + return (kNoErr); + return (kErrUmaskFailed); +} /* FTPUmask */ + + + + +static void +GmTimeStr(char *const dst, const size_t dstsize, time_t t) +{ + char buf[64]; + struct tm *gtp; + + gtp = gmtime(&t); + if (gtp == NULL) { + dst[0] = '\0'; + } else { +#ifdef HAVE_SNPRINTF + buf[sizeof(buf) - 1] = '\0'; + (void) snprintf(buf, sizeof(buf) - 1, "%04d%02d%02d%02d%02d%02d", +#else + (void) sprintf(buf, "%04d%02d%02d%02d%02d%02d", +#endif + gtp->tm_year + 1900, + gtp->tm_mon + 1, + gtp->tm_mday, + gtp->tm_hour, + gtp->tm_min, + gtp->tm_sec + ); + (void) Strncpy(dst, buf, dstsize); + } +} /* GmTimeStr */ + + + + +int +FTPUtime(const FTPCIPtr cip, const char *const file, time_t actime, time_t modtime, time_t crtime) +{ + char mstr[64], astr[64], cstr[64]; + int result; + ResponsePtr rp; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (cip->hasUTIME == kCommandNotAvailable) { + cip->errNo = kErrUTIMENotAvailable; + result = kErrUTIMENotAvailable; + } else { + if ((actime == (time_t) 0) || (actime == (time_t) -1)) + (void) time(&actime); + if ((modtime == (time_t) 0) || (modtime == (time_t) -1)) + (void) time(&modtime); + if ((crtime == (time_t) 0) || (crtime == (time_t) -1)) + crtime = modtime; + + (void) GmTimeStr(astr, sizeof(astr), actime); + (void) GmTimeStr(mstr, sizeof(mstr), modtime); + (void) GmTimeStr(cstr, sizeof(cstr), crtime); + + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + } else { + result = RCmd(cip, rp, "SITE UTIME %s %s %s %s UTC", file, astr, mstr, cstr); + if (result < 0) { + DoneWithResponse(cip, rp); + return (result); + } else if (result == 2) { + cip->hasUTIME = kCommandAvailable; + result = kNoErr; + } else if (UNIMPLEMENTED_CMD(rp->code)) { + cip->hasUTIME = kCommandNotAvailable; + cip->errNo = kErrUTIMENotAvailable; + result = kErrUTIMENotAvailable; + } else { + cip->errNo = kErrUTIMEFailed; + result = kErrUTIMEFailed; + } + DoneWithResponse(cip, rp); + } + } + return (result); +} /* FTPUtime */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/config.h.in b/modules/rosapps/applications/net/ncftp/libncftp/config.h.in new file mode 100644 index 00000000000..33351917a5c --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/config.h.in @@ -0,0 +1,207 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +#undef CAN_USE_SYS_SELECT_H + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define if your compiler supports the "long long" integral type. */ +#undef HAVE_LONG_LONG + +/* Define if you have a _res global variable used by resolve routines. */ +#undef HAVE__RES_DEFDNAME + +/* Define if you have sigsetjmp and siglongjmp. */ +#undef HAVE_SIGSETJMP + +/* Define to `int' if doesn't define. */ +#undef mode_t + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define to `int' if doesn't define. */ +#undef pid_t + +/* Format string for the printf() family for 64 bit integers. */ +#undef PRINTF_LONG_LONG + +/* Define if printing a "long long" with "%lld" works . */ +#undef PRINTF_LONG_LONG_LLD + +/* Define if printing a "long long" with "%qd" works . */ +#undef PRINTF_LONG_LONG_QD + +/* Format string for the scanf() family for 64 bit integers. */ +#undef SCANF_LONG_LONG + +/* Define if scanning a "long long" with "%lld" works. */ +#undef SCANF_LONG_LONG_LLD + +/* Define if scanning a "long long" with "%qd" works. */ +#undef SCANF_LONG_LONG_QD + + +/* Define to the type of arg1 for select(). */ +#undef SELECT_TYPE_ARG1 + +/* Define to the type of args 2, 3 and 4 for select(). */ +#undef SELECT_TYPE_ARG234 + +/* Define to the type of arg5 for select(). */ +#undef SELECT_TYPE_ARG5 + +/* Define if the setvbuf function takes the buffering type as its second + argument and the buffer pointer as the third, as on System V + before release 3. */ +#undef SETVBUF_REVERSED + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to the full path of the Tar program, if you have it. */ +#undef TAR + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to `int' if doesn't define. */ +#undef uid_t + +/* Result of "uname -a" */ +#undef UNAME + +/* Define if you have the fstat64 function. */ +#undef HAVE_FSTAT64 + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getdomainname function. */ +#undef HAVE_GETDOMAINNAME + +/* Define if you have the gethostname function. */ +#undef HAVE_GETHOSTNAME + +/* Define if you have the getpass function. */ +#undef HAVE_GETPASS + +/* Define if you have the getwd function. */ +#undef HAVE_GETWD + +/* Define if you have the inet_ntop function. */ +#undef HAVE_INET_NTOP + +/* Define if you have the llseek function. */ +#undef HAVE_LLSEEK + +/* Define if you have the lseek64 function. */ +#undef HAVE_LSEEK64 + +/* Define if you have the lstat64 function. */ +#undef HAVE_LSTAT64 + +/* Define if you have the mktime function. */ +#undef HAVE_MKTIME + +/* Define if you have the open64 function. */ +#undef HAVE_OPEN64 + +/* Define if you have the res_init function. */ +#undef HAVE_RES_INIT + +/* Define if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define if you have the snprintf function. */ +#undef HAVE_SNPRINTF + +/* Define if you have the socket function. */ +#undef HAVE_SOCKET + +/* Define if you have the stat64 function. */ +#undef HAVE_STAT64 + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strerror function. */ +#undef HAVE_STRERROR + +/* Define if you have the strstr function. */ +#undef HAVE_STRSTR + +/* Define if you have the strtoq function. */ +#undef HAVE_STRTOQ + +/* Define if you have the symlink function. */ +#undef HAVE_SYMLINK + +/* Define if you have the vsnprintf function. */ +#undef HAVE_VSNPRINTF + +/* Define if you have the waitpid function. */ +#undef HAVE_WAITPID + +/* Define if you have the header file. */ +#undef HAVE_ARPA_NAMESER_H + +/* Define if you have the header file. */ +#undef HAVE_NSERVE_H + +/* Define if you have the header file. */ +#undef HAVE_RESOLV_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define if you have the 44bsd library (-l44bsd). */ +#undef HAVE_LIB44BSD + +/* Define if you have the com_err library (-lcom_err). */ +#undef HAVE_LIBCOM_ERR + +/* Define if you have the crypto library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define if you have the db library (-ldb). */ +#undef HAVE_LIBDB + +/* Define if you have the gen library (-lgen). */ +#undef HAVE_LIBGEN + +/* Define if you have the gssapi_krb5 library (-lgssapi_krb5). */ +#undef HAVE_LIBGSSAPI_KRB5 + +/* Define if you have the isode library (-lisode). */ +#undef HAVE_LIBISODE + +/* Define if you have the krb5 library (-lkrb5). */ +#undef HAVE_LIBKRB5 + +/* Define if you have the nsl library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the resolv library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define if you have the socket library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if you have the socks5 library (-lsocks5). */ +#undef HAVE_LIBSOCKS5 diff --git a/modules/rosapps/applications/net/ncftp/libncftp/configure.in b/modules/rosapps/applications/net/ncftp/libncftp/configure.in new file mode 100644 index 00000000000..778db859833 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/configure.in @@ -0,0 +1,292 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(rcmd.c) +AC_PREREQ(2.4) +AC_CONFIG_HEADER(config.h) + +nc_cv_socks5=no +no_signals=yes + +AC_ARG_ENABLE(socks5,[ --enable-socks5 try to find and use the socks5 library],nc_cv_socks5=yes,nc_cv_socks5=no) +AC_ARG_ENABLE(signals,[ --enable-signals allow use of signal handling],[no_signals=no]) + + +wi_OS_VAR + +changequote(<<, >>)dnl +MAINDIR=`pwd` +if test -f "$MAINDIR/dos2unix.sh" ; then + chmod u+rwx $MAINDIR/dos2unix.sh + for dir in . ../sio ../Strn ; do + if [ -d "$dir" ] ; then + dir=`cd "$dir" ; pwd` + find "$dir" -name '*.in' -exec "$MAINDIR/dos2unix.sh" {} \; + find "$dir" -name '*.h' -exec "$MAINDIR/dos2unix.sh" {} \; + find "$dir" -name '*.c' -exec "$MAINDIR/dos2unix.sh" {} \; + fi + done +fi +MAKE=make +STATIC="" +BDYNAMIC="# -Wl,-Bdynamic" +BSTATIC="# -Wl,-Bstatic" +LIBSET='$(LIB)' +Z31='' +Z32='' +Z33='' +Z34='' +REDWING='no' +SFLAG='-s' + +case "$host" in + redwing*) CC=cc + LDFLAGS='' + STATIC='' + Z31=' -@mv $(STGZFILE) newbin/' + Z32=' -@mv $(DTGZFILE) newbin/' + Z33=' -@mv $(MTGZFILE) newbin/' + Z34=' -@mv $(PTGZFILE) newbin/' + REDWING='yes' + ;; +esac + +case "$os" in + linux) + BDYNAMIC="-Wl,-Bdynamic" + BSTATIC="-Wl,-Bstatic" + if [ "$MAKEWORLD_SH" = "" ] ; then + LIBSET='$(LIBSO) $(LIB)' + fi + ;; + freebsd) + BDYNAMIC="-Wl,-Bdynamic" + BSTATIC="-Wl,-Bstatic" + ;; + macosx*|rhapsody) + SFLAG='-Wl,-x' + ;; +esac + +changequote([, ])dnl + +AC_SUBST(CC) +AC_SUBST(CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(LDFLAGS) +AC_SUBST(STATIC) +AC_SUBST(SFLAG) +AC_SUBST(LIBS) +AC_SUBST(DEFS) +AC_SUBST(MAKE) +AC_SUBST(Z31) +AC_SUBST(Z32) +AC_SUBST(Z33) +AC_SUBST(Z34) +AC_SUBST(LIBSET) +AC_SUBST(BDYNAMIC) +AC_SUBST(BSTATIC) +AC_SUBST(MAINDIR) + +if test -f ./samples/ncftpput2probe.c ; then + PROBE="ncftpget2probe ncftpput2probe" +else + PROBE="" +fi +AC_SUBST(PROBE) + +AC_PROG_CC +wi_REQUEST_NO_Y2K_WARNINGS +wi_CFLAGS_LFS64 +wi_DEFINE_UNAME + +if test -f /usr/src/include/eos.h ; then + if test "$REDWING" = no ; then + prefix=/usr/src + fi +fi + +if test "$wi_cv_prototypes" = no ; then + AC_WARN([Your compiler is probably won't be able to compile the package.]) + AC_WARN([Get gcc, or any compiler that supports function prototypes.]) +fi + +dnl # See if we should add -I/usr/local/include -L/usr/local/lib, etc. +dnl wi_EXTRA_DIRS(yes, /usr/local /usr/ccs, -) + +dnl For the sample programs. +wi_NET_LIBS + +if test "$nc_cv_socks5" = yes ; then +# Look for the "SOCKS" library for use with Firewalls/Gateways. +savelibs="$LIBS" +AC_CHECK_LIB(db, main) +AC_CHECK_LIB(isode, main) +AC_CHECK_LIB(com_err, main) +AC_CHECK_LIB(crypto, main) +AC_CHECK_LIB(krb5, main) +AC_CHECK_LIB(gssapi_krb5, main) +AC_CHECK_LIB(socks5,SOCKSinit) + if test "$ac_cv_lib_socks5" = yes ; then + nc_cv_socks=no + else + LIBS="$savelibs" + fi +else +ac_cv_lib_socks5=no +fi + + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(sys/time.h unistd.h utime.h nserve.h resolv.h arpa/nameser.h) +AC_TIME_WITH_SYS_TIME + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T +AC_TYPE_OFF_T +AC_TYPE_MODE_T +AC_TYPE_PID_T +AC_TYPE_UID_T +wi__RES_DEFDNAME +wi_USE_LONG_LONG + +dnl Checks for library functions. +if test "$SYS" != sunos ; then + # Use getwd on SunOS -- getcwd does a "popen("/bin/pwd")" -- aaaccck. + # + AC_CHECK_FUNCS(getcwd) +fi +AC_CHECK_FUNCS(getwd gethostname socket strerror strstr) +AC_CHECK_FUNCS(getpass strcasecmp getdomainname mktime symlink inet_ntop) +AC_CHECK_FUNCS(res_init snprintf vsnprintf strtoq sigaction waitpid) +AC_CHECK_FUNCS(open64 stat64 fstat64 lstat64 lseek64 llseek) +wi_FUNC_SIGSETJMP +AC_FUNC_SETVBUF_REVERSED + +wi_HEADER_SYS_SELECT_H +AC_FUNC_SELECT_ARGTYPES + +if test -f ../sio/sio.h ; then + ldir=`cd ../sio ; pwd` + LDFLAGS="$LDFLAGS -L${ldir}" + CPPFLAGS="$CPPFLAGS -I${ldir}" + LIBS="$LIBS -lsio" +fi + +if test -f ../Strn/Strn.h ; then + ldir=`cd ../Strn ; pwd` + LDFLAGS="$LDFLAGS -L${ldir}" + CPPFLAGS="$CPPFLAGS -I${ldir}" + LIBS="$LIBS -lStrn" +fi + +if test $ac_cv_func_getcwd = no && test $ac_cv_func_getwd = no ; then +AC_WARN(This system does not have either getwd or getcwd?) +AC_WARN(I find that a little hard to believe.) +AC_WARN(You may want to try -DHAVE_GETWD anyway.) +AC_WARN([ +This could also mean that your compiler isn't working]) +AC_WARN(with this configure script. Check the ./config.log) +AC_WARN(and look for anomalies.) +fi + +wi_PROG_TAR +AC_PROG_RANLIB + +if test "$LONGEST_INT" = "long long" ; then + if sed 's/^#define longest_int.*/#define longest_int long long/; +s/^#define longest_uint.*/#define longest_uint unsigned long long/' ncftp.h > temp.h ; then + mv temp.h ncftp.h + chmod a+r ncftp.h + fi +else + if sed 's/^#define longest_int.*/#define longest_int long/; +s/^#define longest_uint.*/#define longest_uint unsigned long/' ncftp.h > temp.h ; then + mv temp.h ncftp.h + chmod a+r ncftp.h + fi +fi + +CPPFLAGS="-I$MAINDIR $CPPFLAGS" + +if test "$no_signals" = no ; then + dv1='# if 0' + dv2='#if 0' +else + dv1='# if 1' + dv2='#if 1' +fi + +if sed "s!^.*/. %config1!${dv1} /* %config1!;s!^.*/. %config2!${dv2} /* %config2!" ncftp.h > temp.h ; then + mv temp.h ncftp.h + chmod a+r ncftp.h +fi + +if sed "s!^.*/. %config1!${dv1} /* %config1!;s!^.*/. %config2!${dv2} /* %config2!" syshdrs.h > temp.h ; then + mv temp.h syshdrs.h + chmod a+r syshdrs.h +fi + +changequote(<<, >>)dnl +# +# Configure sio specially, like it would do. +# +if [ -d ../sio ] ; then + if sed "s!^.*/. %config1!${dv1} /* %config1!;s!^.*/. %config2!${dv2} /* %config2!" ../sio/sio.h > temp.h ; then + mv temp.h ../sio/sio.h + chmod a+r ../sio/sio.h + fi + if sed "s!^.*/. %config1!${dv1} /* %config1!;s!^.*/. %config2!${dv2} /* %config2!" ../sio/usio.h > temp.h ; then + mv temp.h ../sio/usio.h + chmod a+r ../sio/usio.h + fi + + patterns1="" + patterns2="" + if [ "$SYS" = solaris ] ; then + patterns1='s!/. %configure%.*!#define SAccept SAcceptS!' + patterns2='s!/. %configure%.*!#define UAccept UAcceptS!' + fi + + if [ "$patterns1" != "" ] ; then + sed "$patterns1" < ../sio/sio.h > tmpfile + if [ $? -eq 0 ] ; then + mv tmpfile ../sio/sio.h + chmod 644 ../sio/sio.h + else + /bin/rm tmpfile + fi + fi + + if [ "$patterns2" != "" ] ; then + sed "$patterns2" < ../sio/usio.h > tmpfile + if [ $? -eq 0 ] ; then + mv tmpfile ../sio/usio.h + chmod 644 ../sio/usio.h + else + /bin/rm tmpfile + fi + fi +fi +changequote([, ])dnl + +if test -d bin.only ; then + binonly="bin.only/Makefile bin.only/samples/Makefile" +else + binonly="" +fi + +LIBS=`echo "$LIBS" | sed 's/^ *//;s/ *$//;s/ */ /g'` +LDFLAGS=`echo "$LDFLAGS" | sed 's/^ *//;s/ *$//;s/ */ /g'` +CPPFLAGS=`echo "$CPPFLAGS" | sed 's/^ *//;s/ *$//;s/ */ /g'` +CFLAGS=`echo "$CFLAGS" | sed 's/^ *//;s/ *$//;s/ */ /g'` +DEFS=`echo "$DEFS" | sed 's/^ *//;s/ *$//;s/ */ /g'` + +samples='' +for sample in minincftp monkey ncftpget ncftpput ncftpls simpleget ncftpsyncput misc ; do + if test -f samples/$sample/Makefile.in ; then + samples="$samples samples/$sample/Makefile" + fi +done + +AC_OUTPUT([Makefile ../Strn/Makefile ../sio/Makefile $samples $binonly]) diff --git a/modules/rosapps/applications/net/ncftp/libncftp/dos2unix.sh b/modules/rosapps/applications/net/ncftp/libncftp/dos2unix.sh new file mode 100644 index 00000000000..0959d5e4f2d --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/dos2unix.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +es=1 +if [ $# -eq 0 ] ; then + exec tr -d '\015\032' +elif [ ! -f "$1" ] ; then + echo "Not found: $1" 1>&2 +else + for f in "$@" ; do + if tr -d '\015\032' < "$f" > "$f.tmp" ; then + if cmp "$f" "$f.tmp" > /dev/null ; then + rm -f "$f.tmp" + else + touch -r "$f" "$f.tmp" + if mv "$f" "$f.bak" ; then + if mv "$f.tmp" "$f" ; then + rm -f "$f.bak" + es=$? + echo " converted $f" + else + rm -f "$f.tmp" + fi + else + rm -f "$f.tmp" + fi + fi + else + rm -f "$f.tmp" + fi + done +fi + +exit $es diff --git a/modules/rosapps/applications/net/ncftp/libncftp/errno.c b/modules/rosapps/applications/net/ncftp/libncftp/errno.c new file mode 100644 index 00000000000..e5b6ee5c46f --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/errno.c @@ -0,0 +1,163 @@ +/* errno.c + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#define _libncftp_errno_c_ 1 +#include "syshdrs.h" + +static const char *gErrList[kErrLast - kErrFirst + 2] = { + "gethostname() failed", /* -100 */ + "hostname does not include domain name", /* -101 */ + "could not set linger mode", /* -102 */ + "could not set type of service", /* -103 */ + "could not enable out-of-band data inline", /* -104 */ + "unknown host", /* -105 */ + "could not get a new stream socket", /* -106 */ + "could not duplicate a socket", /* -107 */ + "fdopen for reading failed", /* -108 */ + "fdopen for writing failed", /* -109 */ + "getsockname failed", /* -110 */ + "could not bind the data socket", /* -111 */ + "could not listen on the data socket", /* -112 */ + "passive mode failed", /* -113 */ + "server sent bogus port number", /* -114 */ + "could not connect data socket", /* -115 */ + "could not accept data socket", /* -116 */ + "could not set restart point", /* -117 */ + "could not connect to remote host", /* -118 */ + "could not connect to remote host, but can try again", /* -119 */ + "remote host refused connection", /* -120 */ + "bad transfer type", /* -121 */ + "invalid directory parameter", /* -122 */ + "malloc failed", /* -123 */ + "PWD failed", /* -124 */ + "remote chdir failed", /* -125 */ + "remote rmdir failed", /* -126 */ + "bad line list", /* -127 */ + "unimplemented option", /* -128 */ + "unimplemented function", /* -129 */ + "remote directory listing failed", /* -130 */ + "could not retrieve remote file", /* -131 */ + "could not send file to remote host", /* -132 */ + "file write error", /* -133 */ + "file read error", /* -134 */ + "socket write error", /* -135 */ + "socket read error", /* -136 */ + "could not open file", /* -137 */ + "bad magic number in FTP library structure", /* -138 */ + "bad parameter given to library", /* -139 */ + "remote mkdir failed", /* -140 */ + "remote cd .. failed", /* -141 */ + "remote chmod failed", /* -142 */ + "remote umask failed", /* -143 */ + "remote delete failed", /* -144 */ + "remote file size inquiry failed", /* -145 */ + "remote file timestamp inquiry failed", /* -146 */ + "remote transfer type change failed", /* -147 */ + "file size inquiries not understood by remote server", /* -148 */ + "file timestamp inquiries not understood by remote server", /* -149 */ + "could not rename remote file", /* -150 */ + "could not do remote wildcard expansion", /* -151 */ + "could not set keepalive option", /* -152 */ + "remote host disconnected during login", /* -153 */ + "username was not accepted for login", /* -154 */ + "username and/or password was not accepted for login", /* -155 */ + "login failed", /* -156 */ + "invalid reply from server", /* -157 */ + "remote host closed control connection", /* -158 */ + "not connected", /* -159 */ + "could not start data transfer", /* -160 */ + "data transfer failed", /* -161 */ + "PORT failed", /* -162 */ + "PASV failed", /* -163 */ + "UTIME failed", /* -164 */ + "utime requests not understood by remote server", /* -165 */ + "HELP failed", /* -166 */ + "file deletion on local host failed", /* -167 */ + "lseek failed", /* -168 */ + "data transfer aborted by local user", /* -169 */ + "SYMLINK failed", /* -170 */ + "symlink requests not understood by remote server", /* -171 */ + "no match", /* -172 */ + "server features request failed", /* -173 */ + "no valid files were specified", /* -174 */ + "file transfer buffer has not been allocated", /* -175 */ + "will not overwrite local file with older remote file", /* -176 */ + "will not overwrite remote file with older local file", /* -177 */ + "local file appears to be the same as the remote file, no transfer necessary", /* -178 */ + "could not get extended directory information (MLSD)", /* -179 */ + "could not get extended file or directory information (MLST)", /* -180 */ + "could not parse extended file or directory information", /* -181 */ + "server does not support extended file or directory information", /* -182 */ + "server does not support extended directory information", /* -183 */ + "could not get information about specified file", /* -184 */ + "server does not support file or directory information", /* -185 */ + "could not get directory information about specified file", /* -186 */ + "server does not support directory information", /* -187 */ + "no such file or directory", /* -188 */ + "server provides no way to determine file existence", /* -189 */ + "item exists, but cannot tell if it is a file or directory", /* -190 */ + "not a directory", /* -191 */ + "directory recursion limit reached", /* -192 */ + "timed out while waiting for server response", /* -193 */ + "data transfer timed out", /* -194 */ + "canceled by user", /* -195 */ + NULL, +}; + +int gLibNcFTP_Uses_Me_To_Quiet_Variable_Unused_Warnings = 0; + +const char * +FTPStrError(int e) +{ + if (e == kErrGeneric) { + return ("miscellaneous error"); + } else if (e == kNoErr) { + return ("no error"); + } else { + if (e < 0) + e = -e; + if ((e >= kErrFirst) && (e <= kErrLast)) { + return (gErrList[e - kErrFirst]); + } + } + return ("unrecognized error number"); +} /* FTPStrError */ + + + + +void +FTPPerror(const FTPCIPtr cip, const int err, const int eerr, const char *const s1, const char *const s2) +{ + if (err != kNoErr) { + if (err == eerr) { + if ((s2 == NULL) || (s2[0] == '\0')) { + if ((s1 == NULL) || (s1[0] == '\0')) { + (void) fprintf(stderr, "server said: %s\n", cip->lastFTPCmdResultStr); + } else { + (void) fprintf(stderr, "%s: server said: %s\n", s1, cip->lastFTPCmdResultStr); + } + } else if ((s1 == NULL) || (s1[0] == '\0')) { + (void) fprintf(stderr, "%s: server said: %s\n", s2, cip->lastFTPCmdResultStr); + } else { + (void) fprintf(stderr, "%s %s: server said: %s\n", s1, s2, cip->lastFTPCmdResultStr); + } + } else { + if ((s2 == NULL) || (s2[0] == '\0')) { + if ((s1 == NULL) || (s1[0] == '\0')) { + (void) fprintf(stderr, "%s.\n", FTPStrError(cip->errNo)); + } else { + (void) fprintf(stderr, "%s: %s.\n", s1, FTPStrError(cip->errNo)); + } + } else if ((s1 == NULL) || (s1[0] == '\0')) { + (void) fprintf(stderr, "%s: %s.\n", s2, FTPStrError(cip->errNo)); + } else { + (void) fprintf(stderr, "%s %s: %s.\n", s1, s2, FTPStrError(cip->errNo)); + } + } + } +} /* FTPPerror */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/ftp.c b/modules/rosapps/applications/net/ncftp/libncftp/ftp.c new file mode 100644 index 00000000000..43f415689ff --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/ftp.c @@ -0,0 +1,1362 @@ +/* ftp.c + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#define _libncftp_ftp_c_ +#include "syshdrs.h" + +char gLibNcFTPVersion[64] = kLibraryVersion; + +#ifdef NO_SIGNALS +static char gNoSignalsMarker[] = "@(#) LibNcFTP - NO_SIGNALS"; +#else + +static int gGotSig = 0; +#ifdef HAVE_SIGSETJMP +static sigjmp_buf gCancelConnectJmp; +#else +static jmp_buf gCancelConnectJmp; +#endif /* HAVE_SIGSETJMP */ + +#endif /* NO_SIGNALS */ + + +#ifndef lint +static char gCopyright[] = "@(#) LibNcFTP Copyright 1995-2000, by Mike Gleason. All rights reserved."; +#endif + +#ifdef HAVE_LIBSOCKS5 +# define SOCKS 5 +# include +#else +# ifdef HAVE_LIBSOCKS +# define accept Raccept +# define connect Rconnect +# define getsockname Rgetsockname +# define listen Rlisten +# endif +#endif + + + + +/* On entry, you should have 'host' be set to a symbolic name (like + * cse.unl.edu), or set to a numeric address (like 129.93.3.1). + * If the function fails, it will return NULL, but if the host was + * a numeric style address, you'll have the ip_address to fall back on. + */ + +static struct hostent * +GetHostEntry(char *host, struct in_addr *ip_address) +{ + struct in_addr ip; + struct hostent *hp; + + /* See if the host was given in the dotted IP format, like "36.44.0.2." + * If it was, inet_addr will convert that to a 32-bit binary value; + * it not, inet_addr will return (-1L). + */ + ip.s_addr = inet_addr(host); + if (ip.s_addr != INADDR_NONE) { + hp = NULL; + } else { + /* No IP address, so it must be a hostname, like ftp.wustl.edu. */ + hp = gethostbyname(host); + if (hp != NULL) + (void) memcpy(&ip.s_addr, hp->h_addr_list[0], (size_t) hp->h_length); + } + if (ip_address != NULL) + *ip_address = ip; + return (hp); +} /* GetHostEntry */ + + + + +/* Makes every effort to return a fully qualified domain name. */ +int +GetOurHostName(char *host, size_t siz) +{ +#ifdef HOSTNAME + /* You can hardcode in the name if this routine doesn't work + * the way you want it to. + */ + Strncpy(host, HOSTNAME, siz); + return (1); /* Success */ +#else + struct hostent *hp; + int result; + char **curAlias; + char domain[64]; + char *cp; + int rc; + + host[0] = '\0'; + result = gethostname(host, (int) siz); + if ((result < 0) || (host[0] == '\0')) { + return (-1); + } + + if (strchr(host, '.') != NULL) { + /* gethostname returned full name (like "cse.unl.edu"), instead + * of just the node name (like "cse"). + */ + return (2); /* Success */ + } + + hp = gethostbyname(host); + if (hp != NULL) { + /* Maybe the host entry has the full name. */ + cp = strchr((char *) hp->h_name, '.'); + if ((cp != NULL) && (cp[1] != '\0')) { + /* The 'name' field for the host entry had full name. */ + (void) Strncpy(host, (char *) hp->h_name, siz); + return (3); /* Success */ + } + + /* Now try the list of aliases, to see if any of those look real. */ + for (curAlias = hp->h_aliases; *curAlias != NULL; curAlias++) { + cp = strchr(*curAlias, '.'); + if ((cp != NULL) && (cp[1] != '\0')) { + (void) Strncpy(host, *curAlias, siz); + return (4); /* Success */ + } + } + } + + /* Otherwise, we just have the node name. See if we can get the + * domain name ourselves. + */ +#ifdef DOMAINNAME + (void) STRNCPY(domain, DOMAINNAME); + rc = 5; +#else + rc = -1; + domain[0] = '\0'; +# if defined(HAVE_RES_INIT) && defined(HAVE__RES_DEFDNAME) + if (domain[0] == '\0') { + (void) res_init(); + if ((_res.defdname != NULL) && (_res.defdname[0] != '\0')) { + (void) STRNCPY(domain, _res.defdname); + rc = 6; + } + } +# endif /* HAVE_RES_INIT && HAVE__RES_DEFDNAME */ + + if (domain[0] == '\0') { + FILE *fp; + char line[256]; + char *tok; + + fp = fopen("/etc/resolv.conf", "r"); + if (fp != NULL) { + (void) memset(line, 0, sizeof(line)); + while (fgets(line, sizeof(line) - 1, fp) != NULL) { + if (!isalpha((int) line[0])) + continue; /* Skip comment lines. */ + tok = strtok(line, " \t\n\r"); + if (tok == NULL) + continue; /* Impossible */ + if (strcmp(tok, "domain") == 0) { + tok = strtok(NULL, " \t\n\r"); + if (tok == NULL) + continue; /* syntax error */ + (void) STRNCPY(domain, tok); + rc = 7; + break; /* Done. */ + } + } + (void) fclose(fp); + } + } +#endif /* DOMAINNAME */ + + if (domain[0] != '\0') { + /* Supposedly, it's legal for a domain name with + * a period at the end. + */ + cp = domain + strlen(domain) - 1; + if (*cp == '.') + *cp = '\0'; + if (domain[0] != '.') + (void) Strncat(host, ".", siz); + (void) Strncat(host, domain, siz); + } + if (rc < 0) + host[0] = '\0'; + return(rc); /* Success */ +#endif /* !HOSTNAME */ +} /* GetOurHostName */ + + + +void +CloseControlConnection(const FTPCIPtr cip) +{ + /* This will close each file, if it was open. */ +#ifdef NO_SIGNALS + SClose(cip->ctrlSocketR, 3); + cip->ctrlSocketR = kClosedFileDescriptor; + cip->ctrlSocketW = kClosedFileDescriptor; + DisposeSReadlineInfo(&cip->ctrlSrl); +#else /* NO_SIGNALS */ + if (cip->ctrlTimeout > 0) + (void) alarm(cip->ctrlTimeout); + CloseFile(&cip->cin); + CloseFile(&cip->cout); + cip->ctrlSocketR = kClosedFileDescriptor; + cip->ctrlSocketW = kClosedFileDescriptor; + if (cip->ctrlTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + cip->connected = 0; + cip->loggedIn = 0; +} /* CloseControlConnection */ + + + +static int +GetSocketAddress(const FTPCIPtr cip, int sockfd, struct sockaddr_in *saddr) +{ + int len = (int) sizeof (struct sockaddr_in); + int result = 0; + + if (getsockname(sockfd, (struct sockaddr *)saddr, &len) < 0) { + Error(cip, kDoPerror, "Could not get socket name.\n"); + cip->errNo = kErrGetSockName; + result = kErrGetSockName; + } + return (result); +} /* GetSocketAddress */ + + + + +int +SetKeepAlive(const FTPCIPtr cip, int sockfd) +{ +#ifndef SO_KEEPALIVE + cip->errNo = kErrSetKeepAlive; + return (kErrSetKeepAlive); +#else + int opt; + + opt = 1; + + if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, (int) sizeof(opt)) < 0) { + /* Error(cip, kDoPerror, "Could not set keep-alive mode.\n"); */ + cip->errNo = kErrSetKeepAlive; + return (kErrSetKeepAlive); + } + return (kNoErr); +#endif /* SO_KEEPALIVE */ +} /* SetKeepAlive */ + + + + +int +SetLinger(const FTPCIPtr cip, int sockfd, int onoff) +{ +#ifndef SO_LINGER + cip->errNo = kErrSetLinger; + return (kErrSetLinger); +#else + struct linger li; + + if (onoff != 0) { + li.l_onoff = 1; + li.l_linger = 120; /* 2 minutes, but system ignores field. */ + } else { + li.l_onoff = 0; + li.l_linger = 0; + } + /* Have the system make an effort to deliver any unsent data, + * even after we close the connection. + */ + if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (char *) &li, (int) sizeof(li)) < 0) { + /* Error(cip, kDoPerror, "Could not set linger mode.\n"); */ + cip->errNo = kErrSetLinger; + return (kErrSetLinger); + } + return (kNoErr); +#endif /* SO_LINGER */ +} /* SetLinger */ + + + + +#ifdef IP_TOS +int +SetTypeOfService(const FTPCIPtr cip, int sockfd, int tosType) +{ + /* Specify to the router what type of connection this is, so it + * can prioritize packets. + */ + if (setsockopt(sockfd, IPPROTO_IP, IP_TOS, (char *) &tosType, (int) sizeof(tosType)) < 0) { + /* Error(cip, kDoPerror, "Could not set type of service.\n"); */ + cip->errNo = kErrSetTypeOfService; + return (kErrSetTypeOfService); + } + return (kNoErr); +} /* SetTypeOfService */ +#endif /* IP_TOS */ + + + + +#ifdef SO_OOBINLINE +int +SetInlineOutOfBandData(const FTPCIPtr cip, int sockfd) +{ + int on = 1; + + if (setsockopt(sockfd, SOL_SOCKET, SO_OOBINLINE, (char *) &on, (int) sizeof(on)) < 0) { + Error(cip, kDoPerror, "Could not set out of band inline mode.\n"); + cip->errNo = kErrSetOutOfBandInline; + return (kErrSetOutOfBandInline); + } + return (kNoErr); +} /* SetInlineOutOfBandData */ +#endif /* SO_OOBINLINE */ + + + + +#ifndef NO_SIGNALS + +static void +CancelConnect(int signum) +{ + gGotSig = signum; +#ifdef HAVE_SIGSETJMP + siglongjmp(gCancelConnectJmp, 1); +#else + longjmp(gCancelConnectJmp, 1); +#endif /* HAVE_SIGSETJMP */ +} /* CancelConnect */ + +#endif /* NO_SIGNALS */ + + + +int +OpenControlConnection(const FTPCIPtr cip, char *host, unsigned int port) +{ + struct in_addr ip_address; + int err = 0; + int result; + int oerrno; + volatile int sockfd = -1; + volatile int sock2fd = -1; + ResponsePtr rp; + char **volatile curaddr; + struct hostent *hp; + char *volatile fhost; + unsigned int fport; +#ifndef NO_SIGNALS + volatile FTPSigProc osigint; + volatile FTPSigProc osigalrm; + volatile FTPCIPtr vcip; + int sj; +#endif /* NO_SIGNALS */ + const char *firstLine, *secondLine, *srvr; + + LIBNCFTP_USE_VAR(gLibNcFTPVersion); + LIBNCFTP_USE_VAR(gCopyright); +#ifdef NO_SIGNALS + LIBNCFTP_USE_VAR(gNoSignalsMarker); +#endif /* NO_SIGNALS */ + + if (cip->firewallType == kFirewallNotInUse) { + fhost = host; + fport = port; + } else { + fhost = cip->firewallHost; + fport = cip->firewallPort; + } + if (fport == 0) + fport = cip->lip->defaultPort; + + /* Since we're the client, we just have to get a socket() and + * connect() it. + */ + (void) ZERO(cip->servCtlAddr); + cip->cin = NULL; + cip->cout = NULL; + + /* Make sure we use network byte-order. */ + fport = (unsigned int) htons((unsigned short) fport); + + cip->servCtlAddr.sin_port = (unsigned short) fport; + + hp = GetHostEntry(fhost, &ip_address); + + if (hp == NULL) { + /* Okay, no Host entry, but maybe we have a numeric address + * in ip_address we can try. + */ + if (ip_address.s_addr == INADDR_NONE) { + Error(cip, kDontPerror, "%s: unknown host.\n", fhost); + cip->errNo = kErrHostUnknown; + return (kErrHostUnknown); + } + cip->servCtlAddr.sin_family = AF_INET; + cip->servCtlAddr.sin_addr.s_addr = ip_address.s_addr; + } else { + cip->servCtlAddr.sin_family = hp->h_addrtype; + /* We'll fill in the rest of the structure below. */ + } + + /* After obtaining a socket, try to connect it to a remote + * address. If we didn't get a host entry, we will only have + * one thing to try (ip_address); if we do have one, we can try + * every address in the list from the host entry. + */ + + if (hp == NULL) { + /* Since we're given a single raw address, and not a host entry, + * we can only try this one address and not any other addresses + * that could be present for a site with a host entry. + */ + + if ((sockfd = socket(cip->servCtlAddr.sin_family, SOCK_STREAM, 0)) < 0) { + Error(cip, kDoPerror, "Could not get a socket.\n"); + cip->errNo = kErrNewStreamSocket; + return (kErrNewStreamSocket); + } + + /* This doesn't do anything if you left these + * at their defaults (zero). Otherwise it + * tries to set the buffer size to the + * size specified. + */ + (void) SetSockBufSize(sockfd, cip->ctrlSocketRBufSize, cip->ctrlSocketSBufSize); + +#ifdef NO_SIGNALS + err = SConnect(sockfd, &cip->servCtlAddr, (int) cip->connTimeout); + + if (err < 0) { + oerrno = errno; + (void) SClose(sockfd, 3); + errno = oerrno; + sockfd = -1; + } +#else /* NO_SIGNALS */ + osigint = (volatile FTPSigProc) signal(SIGINT, CancelConnect); + if (cip->connTimeout > 0) { + osigalrm = (volatile FTPSigProc) signal(SIGALRM, CancelConnect); + (void) alarm(cip->connTimeout); + } + + vcip = cip; + +#ifdef HAVE_SIGSETJMP + sj = sigsetjmp(gCancelConnectJmp, 1); +#else + sj = setjmp(gCancelConnectJmp); +#endif /* HAVE_SIGSETJMP */ + + if (sj != 0) { + /* Interrupted by a signal. */ + (void) closesocket(sockfd); + (void) signal(SIGINT, (FTPSigProc) osigint); + if (vcip->connTimeout > 0) { + (void) alarm(0); + (void) signal(SIGALRM, (FTPSigProc) osigalrm); + } + if (gGotSig == SIGINT) { + result = vcip->errNo = kErrConnectMiscErr; + Error(vcip, kDontPerror, "Connection attempt canceled.\n"); + (void) kill(getpid(), SIGINT); + } else if (gGotSig == SIGALRM) { + result = vcip->errNo = kErrConnectRetryableErr; + Error(vcip, kDontPerror, "Connection attempt timed-out.\n"); + (void) kill(getpid(), SIGALRM); + } else { + result = vcip->errNo = kErrConnectMiscErr; + Error(vcip, kDontPerror, "Connection attempt failed due to an unexpected signal (%d).\n", gGotSig); + } + return (result); + } else { + err = connect(sockfd, (struct sockaddr *) &cip->servCtlAddr, + (int) sizeof (cip->servCtlAddr)); + if (cip->connTimeout > 0) { + (void) alarm(0); + (void) signal(SIGALRM, (FTPSigProc) osigalrm); + } + (void) signal(SIGINT, (FTPSigProc) osigint); + } + + if (err < 0) { + oerrno = errno; + (void) closesocket(sockfd); + errno = oerrno; + sockfd = -1; + } +#endif /* NO_SIGNALS */ + } else { + /* We can try each address in the list. We'll quit when we + * run out of addresses to try or get a successful connection. + */ + for (curaddr = hp->h_addr_list; *curaddr != NULL; curaddr++) { + if ((sockfd = socket(cip->servCtlAddr.sin_family, SOCK_STREAM, 0)) < 0) { + Error(cip, kDoPerror, "Could not get a socket.\n"); + cip->errNo = kErrNewStreamSocket; + return (kErrNewStreamSocket); + } + /* This could overwrite the address field in the structure, + * but this is okay because the structure has a junk field + * just for this purpose. + */ + (void) memcpy(&cip->servCtlAddr.sin_addr, *curaddr, (size_t) hp->h_length); + + /* This doesn't do anything if you left these + * at their defaults (zero). Otherwise it + * tries to set the buffer size to the + * size specified. + */ + (void) SetSockBufSize(sockfd, cip->ctrlSocketRBufSize, cip->ctrlSocketSBufSize); + +#ifdef NO_SIGNALS + err = SConnect(sockfd, &cip->servCtlAddr, (int) cip->connTimeout); + + if (err == 0) + break; + oerrno = errno; + (void) SClose(sockfd, 3); + errno = oerrno; + sockfd = -1; +#else /* NO_SIGNALS */ + + osigint = (volatile FTPSigProc) signal(SIGINT, CancelConnect); + if (cip->connTimeout > 0) { + osigalrm = (volatile FTPSigProc) signal(SIGALRM, CancelConnect); + (void) alarm(cip->connTimeout); + } + + vcip = cip; +#ifdef HAVE_SIGSETJMP + sj = sigsetjmp(gCancelConnectJmp, 1); +#else + sj = setjmp(gCancelConnectJmp); +#endif /* HAVE_SIGSETJMP */ + + if (sj != 0) { + /* Interrupted by a signal. */ + (void) closesocket(sockfd); + (void) signal(SIGINT, (FTPSigProc) osigint); + if (vcip->connTimeout > 0) { + (void) alarm(0); + (void) signal(SIGALRM, (FTPSigProc) osigalrm); + } + if (gGotSig == SIGINT) { + result = vcip->errNo = kErrConnectMiscErr; + Error(vcip, kDontPerror, "Connection attempt canceled.\n"); + (void) kill(getpid(), SIGINT); + } else if (gGotSig == SIGALRM) { + result = vcip->errNo = kErrConnectRetryableErr; + Error(vcip, kDontPerror, "Connection attempt timed-out.\n"); + (void) kill(getpid(), SIGALRM); + } else { + result = vcip->errNo = kErrConnectMiscErr; + Error(vcip, kDontPerror, "Connection attempt failed due to an unexpected signal (%d).\n", gGotSig); + } + return (result); + } else { + err = connect(sockfd, (struct sockaddr *) &cip->servCtlAddr, + (int) sizeof (cip->servCtlAddr)); + if (cip->connTimeout > 0) { + (void) alarm(0); + (void) signal(SIGALRM, (FTPSigProc) osigalrm); + } + (void) signal(SIGINT, (FTPSigProc) osigint); + } + + if (err == 0) + break; + oerrno = errno; + (void) closesocket(sockfd); + errno = oerrno; + sockfd = -1; +#endif /* NO_SIGNALS */ + } + } + + if (err < 0) { + /* Could not connect. Close up shop and go home. */ + + /* If possible, tell the caller if they should bother + * calling back later. + */ + switch (errno) { +#ifdef ENETDOWN + case ENETDOWN: +#elif defined(WSAENETDOWN) + case WSAENETDOWN: +#endif +#ifdef ENETUNREACH + case ENETUNREACH: +#elif defined(WSAENETUNREACH) + case WSAENETUNREACH: +#endif +#ifdef ECONNABORTED + case ECONNABORTED: +#elif defined(WSAECONNABORTED) + case WSAECONNABORTED: +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: +#elif defined(WSAETIMEDOUT) + case WSAETIMEDOUT: +#endif +#ifdef EHOSTDOWN + case EHOSTDOWN: +#elif defined(WSAEHOSTDOWN) + case WSAEHOSTDOWN: +#endif +#ifdef ECONNRESET + case ECONNRESET: +#elif defined(WSAECONNRESET) + case WSAECONNRESET: +#endif + Error(cip, kDoPerror, "Could not connect to %s -- try again later.\n", fhost); + result = cip->errNo = kErrConnectRetryableErr; + break; +#ifdef ECONNREFUSED + case ECONNREFUSED: +#elif defined(WSAECONNREFUSED) + case WSAECONNREFUSED: +#endif + Error(cip, kDoPerror, "Could not connect to %s.\n", fhost); + result = cip->errNo = kErrConnectRefused; + break; + default: + Error(cip, kDoPerror, "Could not connect to %s.\n", fhost); + result = cip->errNo = kErrConnectMiscErr; + } + goto fatal; + } + + /* Get our end of the socket address for later use. */ + if ((result = GetSocketAddress(cip, sockfd, &cip->ourCtlAddr)) < 0) + goto fatal; + +#ifdef SO_OOBINLINE + /* We want Out-of-band data to appear in the regular stream, + * since we can handle TELNET. + */ + (void) SetInlineOutOfBandData(cip, sockfd); +#endif + (void) SetKeepAlive(cip, sockfd); + (void) SetLinger(cip, sockfd, 0); /* Don't need it for ctrl. */ + +#if defined(IP_TOS) && defined(IPTOS_LOWDELAY) + /* Control connection is somewhat interactive, so quick response + * is desired. + */ + (void) SetTypeOfService(cip, sockfd, IPTOS_LOWDELAY); +#endif + +#ifdef NO_SIGNALS + cip->ctrlSocketR = sockfd; + cip->ctrlSocketW = sockfd; + cip->cout = NULL; + cip->cin = NULL; + sock2fd = kClosedFileDescriptor; + + if (InitSReadlineInfo(&cip->ctrlSrl, sockfd, cip->srlBuf, sizeof(cip->srlBuf), (int) cip->ctrlTimeout, 1) < 0) { + result = kErrFdopenW; + cip->errNo = kErrFdopenW; + Error(cip, kDoPerror, "Could not fdopen.\n"); + goto fatal; + } +#else /* NO_SIGNALS */ + if ((sock2fd = dup(sockfd)) < 0) { + result = kErrDupSocket; + cip->errNo = kErrDupSocket; + Error(cip, kDoPerror, "Could not duplicate a file descriptor.\n"); + goto fatal; + } + + /* Now setup the FILE pointers for use with the Std I/O library + * routines. + */ + if ((cip->cin = fdopen(sockfd, "r")) == NULL) { + result = kErrFdopenR; + cip->errNo = kErrFdopenR; + Error(cip, kDoPerror, "Could not fdopen.\n"); + goto fatal; + } + + if ((cip->cout = fdopen(sock2fd, "w")) == NULL) { + result = kErrFdopenW; + cip->errNo = kErrFdopenW; + Error(cip, kDoPerror, "Could not fdopen.\n"); + CloseFile(&cip->cin); + sockfd = kClosedFileDescriptor; + goto fatal; + } + + cip->ctrlSocketR = sockfd; + cip->ctrlSocketW = sockfd; + + /* We'll be reading and writing lines, so use line buffering. This + * is necessary since the stdio library will use full buffering + * for all streams not associated with the tty. + */ +#ifdef HAVE_SETLINEBUF + setlinebuf(cip->cin); + setlinebuf(cip->cout); +#else + (void) SETVBUF(cip->cin, NULL, _IOLBF, (size_t) BUFSIZ); + (void) SETVBUF(cip->cout, NULL, _IOLBF, (size_t) BUFSIZ); +#endif +#endif /* NO_SIGNALS */ + +#ifdef HAVE_INET_NTOP /* Mostly to workaround bug in IRIX 6.5's inet_ntoa */ + (void) memset(cip->ip, 0, sizeof(cip->ip)); + (void) inet_ntop(AF_INET, &cip->servCtlAddr.sin_addr, cip->ip, sizeof(cip->ip) - 1); +#else + (void) STRNCPY(cip->ip, inet_ntoa(cip->servCtlAddr.sin_addr)); +#endif + if ((hp == NULL) || (hp->h_name == NULL)) + (void) STRNCPY(cip->actualHost, fhost); + else + (void) STRNCPY(cip->actualHost, (char *) hp->h_name); + + /* Read the startup message from the server. */ + rp = InitResponse(); + if (rp == NULL) { + Error(cip, kDontPerror, "Malloc failed.\n"); + cip->errNo = kErrMallocFailed; + result = cip->errNo; + goto fatal; + } + + result = GetResponse(cip, rp); + if ((result < 0) && (rp->msg.first == NULL)) { + goto fatal; + } + if (rp->msg.first != NULL) { + cip->serverType = kServerTypeUnknown; + srvr = NULL; + firstLine = rp->msg.first->line; + secondLine = NULL; + if (rp->msg.first->next != NULL) + secondLine = rp->msg.first->next->line; + + if (strstr(firstLine, "Version wu-") != NULL) { + cip->serverType = kServerTypeWuFTPd; + srvr = "wu-ftpd"; + } else if (strstr(firstLine, "NcFTPd") != NULL) { + cip->serverType = kServerTypeNcFTPd; + srvr = "NcFTPd Server"; + } else if (STRNEQ("ProFTPD", firstLine, 7)) { + cip->serverType = kServerTypeProFTPD; + srvr = "ProFTPD"; + } else if (strstr(firstLine, "Microsoft FTP Service") != NULL) { + cip->serverType = kServerTypeMicrosoftFTP; + srvr = "Microsoft FTP Service"; + } else if (strstr(firstLine, "(NetWare ") != NULL) { + cip->serverType = kServerTypeNetWareFTP; + srvr = "NetWare FTP Service"; + } else if (STRNEQ("WFTPD", firstLine, 5)) { + cip->serverType = kServerTypeWFTPD; + srvr = "WFTPD"; + } else if (STRNEQ("Serv-U FTP", firstLine, 10)) { + cip->serverType = kServerTypeServ_U; + srvr = "Serv-U FTP-Server"; + } else if (strstr(firstLine, "VFTPD") != NULL) { + cip->serverType = kServerTypeVFTPD; + srvr = "VFTPD"; + } else if (STRNEQ("FTP-Max", firstLine, 7)) { + cip->serverType = kServerTypeFTP_Max; + srvr = "FTP-Max"; + } else if (strstr(firstLine, "Roxen") != NULL) { + cip->serverType = kServerTypeRoxen; + srvr = "Roxen"; + } else if (strstr(firstLine, "WS_FTP") != NULL) { + cip->serverType = kServerTypeWS_FTP; + srvr = "WS_FTP Server"; + } else if ((secondLine != NULL) && (strstr(secondLine, "WarFTP") != NULL)) { + cip->serverType = kServerTypeWarFTPd; + srvr = "WarFTPd"; + } + + if (srvr != NULL) + PrintF(cip, "Remote server is running %s.\n", srvr); + + /* Do the application's connect message callback, if present. */ + if ((cip->onConnectMsgProc != 0) && (rp->codeType < 4)) + (*cip->onConnectMsgProc)(cip, rp); + } + + if (rp->codeType >= 4) { + /* They probably hung up on us right away. That's too bad, + * but we can tell the caller that they can call back later + * and try again. + */ + DoneWithResponse(cip, rp); + result = kErrConnectRetryableErr; + Error(cip, kDontPerror, "Server hungup immediately after connect.\n"); + cip->errNo = kErrConnectRetryableErr; + goto fatal; + } + if (result < 0) /* Some other error occurred during connect message */ + goto fatal; + cip->connected = 1; + DoneWithResponse(cip, rp); + return (kNoErr); + +fatal: + if (sockfd > 0) + (void) closesocket(sockfd); + if (sock2fd > 0) + (void) closesocket(sock2fd); + CloseFile(&cip->cin); + CloseFile(&cip->cout); + cip->ctrlSocketR = kClosedFileDescriptor; + cip->ctrlSocketW = kClosedFileDescriptor; + return (result); +} /* OpenControlConnection */ + + + + +void +CloseDataConnection(const FTPCIPtr cip) +{ + if (cip->dataSocket != kClosedFileDescriptor) { +#ifdef NO_SIGNALS + SClose(cip->dataSocket, 3); +#else /* NO_SIGNALS */ + if (cip->xferTimeout > 0) + (void) alarm(cip->xferTimeout); + (void) closesocket(cip->dataSocket); + if (cip->xferTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + cip->dataSocket = kClosedFileDescriptor; + } + memset(&cip->ourDataAddr, 0, sizeof(cip->ourDataAddr)); + memset(&cip->servDataAddr, 0, sizeof(cip->servDataAddr)); +} /* CloseDataConnection */ + + + + +int +SetStartOffset(const FTPCIPtr cip, longest_int restartPt) +{ + ResponsePtr rp; + int result; + + if (restartPt != (longest_int) 0) { + rp = InitResponse(); + if (rp == NULL) { + Error(cip, kDontPerror, "Malloc failed.\n"); + cip->errNo = kErrMallocFailed; + return (cip->errNo); + } + + /* Force reset to offset zero. */ + if (restartPt == (longest_int) -1) + restartPt = (longest_int) 0; +#ifdef PRINTF_LONG_LONG + result = RCmd(cip, rp, + "REST " PRINTF_LONG_LONG, + restartPt); +#else + result = RCmd(cip, rp, "REST %ld", (long) restartPt); +#endif + + if (result < 0) { + return (result); + } else if (result == 3) { + cip->hasREST = kCommandAvailable; + DoneWithResponse(cip, rp); + } else if (UNIMPLEMENTED_CMD(rp->code)) { + cip->hasREST = kCommandNotAvailable; + DoneWithResponse(cip, rp); + cip->errNo = kErrSetStartPoint; + return (kErrSetStartPoint); + } else { + DoneWithResponse(cip, rp); + cip->errNo = kErrSetStartPoint; + return (kErrSetStartPoint); + } + } + return (0); +} /* SetStartOffset */ + + + +static int +SendPort(const FTPCIPtr cip, struct sockaddr_in *saddr) +{ + char *a, *p; + int result; + ResponsePtr rp; + + rp = InitResponse(); + if (rp == NULL) { + Error(cip, kDontPerror, "Malloc failed.\n"); + cip->errNo = kErrMallocFailed; + return (cip->errNo); + } + + /* These will point to data in network byte order. */ + a = (char *) &saddr->sin_addr; + p = (char *) &saddr->sin_port; +#define UC(x) (int) (((int) x) & 0xff) + + /* Need to tell the other side which host (the address) and + * which process (port) on that host to send data to. + */ + result = RCmd(cip, rp, "PORT %d,%d,%d,%d,%d,%d", + UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); + + if (result < 0) { + return (result); + } else if (result != 2) { + /* A 500'ish response code means the PORT command failed. */ + DoneWithResponse(cip, rp); + cip->errNo = kErrPORTFailed; + return (cip->errNo); + } + DoneWithResponse(cip, rp); + return (kNoErr); +} /* SendPort */ + + + + +static int +Passive(const FTPCIPtr cip, struct sockaddr_in *saddr, int *weird) +{ + ResponsePtr rp; + int i[6], j; + unsigned char n[6]; + char *cp; + int result; + + rp = InitResponse(); + if (rp == NULL) { + Error(cip, kDontPerror, "Malloc failed.\n"); + cip->errNo = kErrMallocFailed; + return (cip->errNo); + } + + result = RCmd(cip, rp, "PASV"); + if (result < 0) + goto done; + + if (rp->codeType != 2) { + /* Didn't understand or didn't want passive port selection. */ + cip->errNo = result = kErrPASVFailed; + goto done; + } + + /* The other side returns a specification in the form of + * an internet address as the first four integers (each + * integer stands for 8-bits of the real 32-bit address), + * and two more integers for the port (16-bit port). + * + * It should give us something like: + * "Entering Passive Mode (129,93,33,1,10,187)", so look for + * digits with sscanf() starting 24 characters down the string. + */ + for (cp = rp->msg.first->line; ; cp++) { + if (*cp == '\0') { + Error(cip, kDontPerror, "Cannot parse PASV response: %s\n", rp->msg.first->line); + goto done; + } + if (isdigit((int) *cp)) + break; + } + + if (sscanf(cp, "%d,%d,%d,%d,%d,%d", + &i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6) { + Error(cip, kDontPerror, "Cannot parse PASV response: %s\n", rp->msg.first->line); + goto done; + } + + for (j=0, *weird = 0; j<6; j++) { + /* Some ftp servers return bogus port octets, such as + * boombox.micro.umn.edu. Let the caller know if we got a + * weird looking octet. + */ + if ((i[j] < 0) || (i[j] > 255)) + *weird = *weird + 1; + n[j] = (unsigned char) (i[j] & 0xff); + } + + (void) memcpy(&saddr->sin_addr, &n[0], (size_t) 4); + (void) memcpy(&saddr->sin_port, &n[4], (size_t) 2); + + result = kNoErr; +done: + DoneWithResponse(cip, rp); + return (result); +} /* Passive */ + + + + +static int +BindToEphemeralPortNumber(int sockfd, struct sockaddr_in *addrp, int ephemLo, int ephemHi) +{ + int i; + int result; + int rangesize; + unsigned short port; + + addrp->sin_family = AF_INET; + if (((int) ephemLo == 0) || ((int) ephemLo >= (int) ephemHi)) { + /* Do it the normal way. System will + * pick one, typically in the range + * of 1024-4999. + */ + addrp->sin_port = 0; /* Let system pick one. */ + + result = bind(sockfd, (struct sockaddr *) addrp, sizeof(struct sockaddr_in)); + } else { + rangesize = (int) ((int) ephemHi - (int) ephemLo); + result = 0; + for (i=0; i<10; i++) { + port = (unsigned short) (((int) rand() % rangesize) + (int) ephemLo); + addrp->sin_port = port; + + result = bind(sockfd, (struct sockaddr *) addrp, sizeof(struct sockaddr_in)); + if (result == 0) + break; + if ((errno != 999) + /* This next line is just fodder to + * shut the compiler up about variable + * not being used. + */ + && (gCopyright[0] != '\0')) + break; + } + } + return (result); +} /* BindToEphemeralPortNumber */ + + + + +int +OpenDataConnection(const FTPCIPtr cip, int mode) +{ + int dataSocket; + int weirdPort; + int result; + + /* Before we can transfer any data, and before we even ask the + * remote server to start transferring via RETR/NLST/etc, we have + * to setup the connection. + */ + +tryPort2: + weirdPort = 0; + result = 0; + CloseDataConnection(cip); /* In case we didn't before... */ + + dataSocket = socket(AF_INET, SOCK_STREAM, 0); + if (dataSocket < 0) { + Error(cip, kDoPerror, "Could not get a data socket.\n"); + result = kErrNewStreamSocket; + cip->errNo = kErrNewStreamSocket; + return result; + } + + /* This doesn't do anything if you left these + * at their defaults (zero). Otherwise it + * tries to set the buffer size to the + * size specified. + */ + (void) SetSockBufSize(dataSocket, cip->dataSocketRBufSize, cip->dataSocketSBufSize); + + if ((cip->hasPASV == kCommandNotAvailable) || (mode == kSendPortMode)) { +tryPort: + cip->ourDataAddr = cip->ourCtlAddr; + cip->ourDataAddr.sin_family = AF_INET; + +#ifdef HAVE_LIBSOCKS + cip->ourDataAddr.sin_port = 0; + if (Rbind(dataSocket, (struct sockaddr *) &cip->ourDataAddr, + (int) sizeof (cip->ourDataAddr), + cip->servCtlAddr.sin_addr.s_addr) < 0) +#else + if (BindToEphemeralPortNumber(dataSocket, &cip->ourDataAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0) +#endif + { + Error(cip, kDoPerror, "Could not bind the data socket"); + result = kErrBindDataSocket; + cip->errNo = kErrBindDataSocket; + goto bad; + } + + /* Need to do this so we can figure out which port the system + * gave to us. + */ + if ((result = GetSocketAddress(cip, dataSocket, &cip->ourDataAddr)) < 0) + goto bad; + + if (listen(dataSocket, 1) < 0) { + Error(cip, kDoPerror, "listen failed"); + result = kErrListenDataSocket; + cip->errNo = kErrListenDataSocket; + goto bad; + } + + if ((result = SendPort(cip, &cip->ourDataAddr)) < 0) + goto bad; + + cip->dataPortMode = kSendPortMode; + } else { + /* Passive mode. Let the other side decide where to send. */ + + cip->servDataAddr = cip->servCtlAddr; + cip->servDataAddr.sin_family = AF_INET; + cip->ourDataAddr = cip->ourCtlAddr; + cip->ourDataAddr.sin_family = AF_INET; + + if (Passive(cip, &cip->servDataAddr, &weirdPort) < 0) { + Error(cip, kDontPerror, "Passive mode refused.\n"); + cip->hasPASV = kCommandNotAvailable; + + /* We can try using regular PORT commands, which are required + * by all FTP protocol compliant programs, if you said so. + * + * We don't do this automatically, because if your host + * is running a firewall you (probably) do not want SendPort + * FTP for security reasons. + */ + if (mode == kFallBackToSendPortMode) + goto tryPort; + result = kErrPassiveModeFailed; + cip->errNo = kErrPassiveModeFailed; + goto bad; + } + +#ifdef HAVE_LIBSOCKS + cip->ourDataAddr.sin_port = 0; + if (Rbind(dataSocket, (struct sockaddr *) &cip->ourDataAddr, + (int) sizeof (cip->ourDataAddr), + cip->servCtlAddr.sin_addr.s_addr) < 0) +#else + if (BindToEphemeralPortNumber(dataSocket, &cip->ourDataAddr, (int) cip->ephemLo, (int) cip->ephemHi) < 0) +#endif + { + Error(cip, kDoPerror, "Could not bind the data socket"); + result = kErrBindDataSocket; + cip->errNo = kErrBindDataSocket; + goto bad; + } + +#ifdef NO_SIGNALS + result = SConnect(dataSocket, &cip->servDataAddr, (int) cip->connTimeout); +#else /* NO_SIGNALS */ + if (cip->connTimeout > 0) + (void) alarm(cip->connTimeout); + + result = connect(dataSocket, (struct sockaddr *) &cip->servDataAddr, (int) sizeof(cip->servDataAddr)); + if (cip->connTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + +#ifdef NO_SIGNALS + if (result == kTimeoutErr) { + if (mode == kFallBackToSendPortMode) { + Error(cip, kDontPerror, "Data connection timed out.\n"); + Error(cip, kDontPerror, "Falling back to PORT instead of PASV mode.\n"); + (void) closesocket(dataSocket); + cip->hasPASV = kCommandNotAvailable; + goto tryPort2; + } + Error(cip, kDontPerror, "Data connection timed out.\n"); + result = kErrConnectDataSocket; + cip->errNo = kErrConnectDataSocket; + } else +#endif /* NO_SIGNALS */ + + if (result < 0) { +#ifdef ECONNREFUSED + if ((weirdPort > 0) && (errno == ECONNREFUSED)) { +#elif defined(WSAECONNREFUSED) + if ((weirdPort > 0) && (errno == WSAECONNREFUSED)) { +#endif + Error(cip, kDontPerror, "Server sent back a bogus port number.\nI will fall back to PORT instead of PASV mode.\n"); + if (mode == kFallBackToSendPortMode) { + (void) closesocket(dataSocket); + cip->hasPASV = kCommandNotAvailable; + goto tryPort2; + } + result = kErrServerSentBogusPortNumber; + cip->errNo = kErrServerSentBogusPortNumber; + goto bad; + } + if (mode == kFallBackToSendPortMode) { + Error(cip, kDoPerror, "connect failed.\n"); + Error(cip, kDontPerror, "Falling back to PORT instead of PASV mode.\n"); + (void) closesocket(dataSocket); + cip->hasPASV = kCommandNotAvailable; + goto tryPort2; + } + Error(cip, kDoPerror, "connect failed.\n"); + result = kErrConnectDataSocket; + cip->errNo = kErrConnectDataSocket; + goto bad; + } + + /* Need to do this so we can figure out which port the system + * gave to us. + */ + if ((result = GetSocketAddress(cip, dataSocket, &cip->ourDataAddr)) < 0) + goto bad; + + cip->dataPortMode = kPassiveMode; + cip->hasPASV = kCommandAvailable; + } + + (void) SetLinger(cip, dataSocket, 1); + (void) SetKeepAlive(cip, dataSocket); + +#if defined(IP_TOS) && defined(IPTOS_THROUGHPUT) + /* Data connection is a non-interactive data stream, so + * high throughput is desired, at the expense of low + * response time. + */ + (void) SetTypeOfService(cip, dataSocket, IPTOS_THROUGHPUT); +#endif + + cip->dataSocket = dataSocket; + return (0); +bad: + (void) closesocket(dataSocket); + return (result); +} /* OpenDataConnection */ + + + + +int +AcceptDataConnection(const FTPCIPtr cip) +{ + int newSocket; +#ifndef NO_SIGNALS + int len; +#endif + unsigned short remoteDataPort; + unsigned short remoteCtrlPort; + + /* If we did a PORT, we have some things to finish up. + * If we did a PASV, we're ready to go. + */ + if (cip->dataPortMode == kSendPortMode) { + /* Accept will give us back the server's data address; at the + * moment we don't do anything with it though. + */ + memset(&cip->servDataAddr, 0, sizeof(cip->servDataAddr)); + +#ifdef NO_SIGNALS + newSocket = SAccept(cip->dataSocket, &cip->servDataAddr, (int) cip->connTimeout); +#else /* NO_SIGNALS */ + len = (int) sizeof(cip->servDataAddr); + if (cip->connTimeout > 0) + (void) alarm(cip->connTimeout); + newSocket = accept(cip->dataSocket, (struct sockaddr *) &cip->servDataAddr, &len); + if (cip->connTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + + (void) closesocket(cip->dataSocket); + if (newSocket < 0) { + Error(cip, kDoPerror, "Could not accept a data connection.\n"); + cip->dataSocket = kClosedFileDescriptor; + cip->errNo = kErrAcceptDataSocket; + return (kErrAcceptDataSocket); + } + + if (cip->require20 != 0) { + remoteDataPort = ntohs(cip->servDataAddr.sin_port); + remoteCtrlPort = ntohs(cip->servCtlAddr.sin_port); + if ((int) remoteDataPort != ((int) remoteCtrlPort - 1)) { + Error(cip, kDontPerror, "Data connection did not originate on correct port!\n"); + (void) closesocket(newSocket); + cip->dataSocket = kClosedFileDescriptor; + cip->errNo = kErrAcceptDataSocket; + return (kErrAcceptDataSocket); + } else if (memcmp(&cip->servDataAddr.sin_addr.s_addr, &cip->servCtlAddr.sin_addr.s_addr, sizeof(cip->servDataAddr.sin_addr.s_addr)) != 0) { + Error(cip, kDontPerror, "Data connection did not originate from remote server!\n"); + (void) closesocket(newSocket); + cip->dataSocket = kClosedFileDescriptor; + cip->errNo = kErrAcceptDataSocket; + return (kErrAcceptDataSocket); + } + } + + cip->dataSocket = newSocket; + } + + return (0); +} /* AcceptDataConnection */ + + + + +void +HangupOnServer(const FTPCIPtr cip) +{ + /* Since we want to close both sides of the connection for each + * socket, we can just have them closed with close() instead of + * using shutdown(). + */ + CloseControlConnection(cip); + CloseDataConnection(cip); +} /* HangupOnServer */ + + + + +void +SendTelnetInterrupt(const FTPCIPtr cip) +{ + char msg[4]; + + /* 1. User system inserts the Telnet "Interrupt Process" (IP) signal + * in the Telnet stream. + */ + + if (cip->cout != NULL) + (void) fflush(cip->cout); + + msg[0] = (char) (unsigned char) IAC; + msg[1] = (char) (unsigned char) IP; + (void) send(cip->ctrlSocketW, msg, 2, 0); + + /* 2. User system sends the Telnet "Sync" signal. */ +#if 1 + msg[0] = (char) (unsigned char) IAC; + msg[1] = (char) (unsigned char) DM; + if (send(cip->ctrlSocketW, msg, 2, MSG_OOB) != 2) + Error(cip, kDoPerror, "Could not send an urgent message.\n"); +#else + /* "Send IAC in urgent mode instead of DM because UNIX places oob mark + * after urgent byte rather than before as now is protocol," says + * the BSD ftp code. + */ + msg[0] = (char) (unsigned char) IAC; + if (send(cip->ctrlSocketW, msg, 1, MSG_OOB) != 1) + Error(cip, kDoPerror, "Could not send an urgent message.\n"); + (void) fprintf(cip->cout, "%c", DM); + (void) fflush(cip->cout); +#endif +} /* SendTelnetInterrupt */ + +/* eof FTP.c */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/ftp.h b/modules/rosapps/applications/net/ncftp/libncftp/ftp.h new file mode 100644 index 00000000000..f91d9503bf3 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/ftp.h @@ -0,0 +1,22 @@ +/* FTP.h + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +/* FTP.c */ +void MyInetAddr(char *, size_t, char **, int); +int GetOurHostName(char *, size_t); +void CloseControlConnection(const FTPCIPtr); +int SetKeepAlive(const FTPCIPtr, int); +int SetLinger(const FTPCIPtr, int, int); +int SetTypeOfService(const FTPCIPtr, int, int); +int SetInlineOutOfBandData(const FTPCIPtr, int); +int OpenControlConnection(const FTPCIPtr, char *, unsigned int); +void CloseDataConnection(const FTPCIPtr); +int SetStartOffset(const FTPCIPtr, longest_int); +int OpenDataConnection(const FTPCIPtr, int); +int AcceptDataConnection(const FTPCIPtr); +void HangupOnServer(const FTPCIPtr); +void SendTelnetInterrupt(const FTPCIPtr); diff --git a/modules/rosapps/applications/net/ncftp/libncftp/glob.c b/modules/rosapps/applications/net/ncftp/libncftp/glob.c new file mode 100644 index 00000000000..152d3c42ec9 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/glob.c @@ -0,0 +1,1760 @@ +/* glob.c + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#include "syshdrs.h" + +static const char *rwx[9] = { "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx", NULL }; + + + +/* We need to use this because using NLST gives us more stuff than + * we want back sometimes. For example, say we have: + * + * /a (directory) + * /a/b (directory) + * /a/b/b1 + * /a/b/b2 + * /a/b/b3 + * /a/c (directory) + * /a/c/c1 + * /a/c/c2 + * /a/c/c3 + * /a/file + * + * If you did an "echo /a/" in a normal unix shell, you would expect + * to get back /a/b /a/c /a/file. But NLST gives back: + * + * /a/b/b1 + * /a/b/b2 + * /a/b/b3 + * /a/c/c1 + * /a/c/c2 + * /a/c/c3 + * /a/file + * + * So we use the following routine to convert into the format I expect. + */ + +static void +RemoteGlobCollapse(const char *pattern, LineListPtr fileList) +{ + LinePtr lp, nextLine; + string patPrefix; + string cur, prev; + char *endp, *cp, *dp; + const char *pp; + int wasGlobChar; + size_t plen; + + /* Copy all characters before the first glob-char. */ + dp = patPrefix; + endp = dp + sizeof(patPrefix) - 1; + wasGlobChar = 0; + for (cp = (char *) pattern; dp < endp; ) { + for (pp=kGlobChars; *pp != '\0'; pp++) { + if (*pp == *cp) { + wasGlobChar = 1; + break; + } + } + if (wasGlobChar) + break; + *dp++ = *cp++; + } + *dp = '\0'; + plen = (size_t) (dp - patPrefix); + + *prev = '\0'; + for (lp=fileList->first; lp != NULL; lp = nextLine) { + nextLine = lp->next; + if (strncmp(lp->line, patPrefix, plen) == 0) { + (void) STRNCPY(cur, lp->line + plen); + cp = strchr(cur, '/'); + if (cp == NULL) + cp = strchr(cur, '\\'); + if (cp != NULL) + *cp = '\0'; + if ((*prev != '\0') && (STREQ(cur, prev))) { + nextLine = RemoveLine(fileList, lp); + } else { + (void) STRNCPY(prev, cur); + /* We are playing with a dynamically + * allocated string, but since the + * following expression is guaranteed + * to be the same or shorter, we won't + * overwrite the bounds. + */ + (void) sprintf(lp->line, "%s%s", patPrefix, cur); + } + } + } +} /* RemoteGlobCollapse */ + + + + +#if 0 +/* May need this later. */ +static void +CheckForLS_d(FTPCIPtr cip) +{ + LineList lines; + char *cp; + + if (cip->hasNLST_d == kCommandAvailabilityUnknown) { + if (FTPListToMemory2(cip, ".", &lines, "-d ", 0, (int *) 0) == kNoErr) { + if ((lines.first != NULL) && (lines.first == lines.last)) { + /* If we have only one item in the list, see if it really was + * an error message we would recognize. + */ + cp = strchr(lines.first->line, ':'); + if ((cp != NULL) && STREQ(cp, ": No such file or directory")) { + cip->hasNLST_d = kCommandNotAvailable; + } else { + cip->hasNLST_d = kCommandAvailable; + } + } else { + cip->hasNLST_d = kCommandNotAvailable; + } + } else { + cip->hasNLST_d = kCommandNotAvailable; + } + DisposeLineListContents(&lines); + } +} /* CheckForLS_d */ +#endif + + + + +static int +LsMonthNameToNum(char *cp) +{ + int mon; /* 0..11 */ + + switch (*cp++) { + case 'A': + mon = (*cp == 'u') ? 7 : 3; + break; + case 'D': + mon = 11; + break; + case 'F': + mon = 1; + break; + default: + case 'J': + if (*cp++ == 'u') + mon = (*cp == 'l') ? 6 : 5; + else + mon = 0; + break; + case 'M': + mon = (*++cp == 'r') ? 2 : 4; + break; + case 'N': + mon = 10; + break; + case 'O': + mon = 9; + break; + case 'S': + mon = 8; + } + return (mon); +} /* LsMonthNameToNum */ + + + + +static int +UnDosLine( char *const line, + const char *const curdir, + size_t curdirlen, + char *fname, + size_t fnamesize, + int *ftype, + longest_int *fsize, + time_t *ftime) +{ + char *cp; + int hour, year; + char *filestart; + char *sizestart; + struct tm ftm; + + /* + * +0123456789012345678901234567890123456789012345678901234567890123456789 +04-27-99 10:32PM 270158 Game booklet.pdf +03-11-99 10:03PM Get A3d Banner + +We also try to parse the format from CMD.EXE, which is similar: + +03/22/2001 06:23p 62,325 cls.pdf + + * + */ + cp = line; + if ( + isdigit((int) cp[0]) + && isdigit((int) cp[1]) + && ispunct((int) cp[2]) + && isdigit((int) cp[3]) + && isdigit((int) cp[4]) + && ispunct((int) cp[5]) + && isdigit((int) cp[6]) + && isdigit((int) cp[7]) + ) { + (void) memset(&ftm, 0, sizeof(struct tm)); + ftm.tm_isdst = -1; + cp[2] = '\0'; + ftm.tm_mon = atoi(cp + 0); + if (ftm.tm_mon > 0) + ftm.tm_mon -= 1; + cp[5] = '\0'; + ftm.tm_mday = atoi(cp + 3); + if ((isdigit((int) cp[8])) && (isdigit((int) cp[9]))) { + /* Four-digit year */ + cp[10] = '\0'; + year = atoi(cp + 6); + if (year > 1900) + year -= 1900; + ftm.tm_year = year; /* years since 1900 */ + cp += 11; + } else { + /* Two-digit year */ + cp[8] = '\0'; + year = atoi(cp + 6); + if (year < 98) + year += 100; + ftm.tm_year = year; /* years since 1900 */ + cp += 9; + } + + for (;;) { + if (*cp == '\0') + return (-1); + if (isdigit(*cp)) + break; + cp++; + } + + cp[2] = '\0'; + hour = atoi(cp); + if (((cp[5] == 'P') || (cp[5] == 'p')) && (hour < 12)) + hour += 12; + else if (((cp[5] == 'A') || (cp[5] == 'a')) && (hour == 12)) + hour -= 12; + ftm.tm_hour = hour; + cp[5] = '\0'; + ftm.tm_min = atoi(cp + 3); + *ftime = mktime(&ftm); + if (*ftype == (time_t) -1) + return (-1); + + cp += 6; + *ftype = '-'; + for (;;) { + if (*cp == '\0') + return (-1); + if ((*cp == '<') && (cp[1] == 'D')) { + /* found */ + *ftype = 'd'; + cp += 5; + break; /* size field will end up being empty string */ + } else if ((*cp == '<') && (cp[1] == 'J')) { + /* found + * + * Will we ever really see this? + * IIS from Win2000sp1 sends + * for FTP, but CMD.EXE prints + * . + */ + *ftype = 'd'; + cp += 10; + break; + } else if (isdigit(*cp)) { + break; + } else { + cp++; + } + } + + sizestart = cp; + for (;;) { + if (*cp == '\0') + return (-1); +#ifdef HAVE_MEMMOVE + if (*cp == ',') { + /* Yuck -- US Locale dependency */ + memmove(cp, cp + 1, strlen(cp + 1) + 1); + } +#endif + if (!isdigit(*cp)) { + *cp++ = '\0'; + break; + } + cp++; + } + + if (fsize != NULL) { +#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG) + if (*ftype == 'd') + *fsize = 0; + else + (void) sscanf(sizestart, SCANF_LONG_LONG, fsize); +#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ) + if (*ftype == 'd') + *fsize = 0; + else + *fsize = (longest_int) strtoq(sizestart, NULL, 0); +#else + *fsize = (longest_int) 0; + if (*ftype != 'd') { + long fsize2 = 0L; + + (void) sscanf(sizestart, "%ld", &fsize2); + *fsize = (longest_int) fsize2; + } +#endif + } + + for (;;) { + if (*cp == '\0') + return (-1); + if (!isspace(*cp)) { + break; + } + cp++; + } + + filestart = cp; + if (curdirlen == 0) { + (void) Strncpy(fname, filestart, fnamesize); + } else { + (void) Strncpy(fname, curdir, fnamesize); + (void) Strncat(fname, filestart, fnamesize); + } + + return (0); + } + return (-1); +} /* UnDosLine */ + + + + +static int +UnLslRLine( char *const line, + const char *const curdir, + size_t curdirlen, + char *fname, + size_t fnamesize, + char *linkto, + size_t linktosize, + int *ftype, + longest_int *fsize, + time_t *ftime, + time_t now, + int thisyear, + int *plugend) +{ + char *cp; + int mon = 0, dd = 0, hr = 0, min = 0, year = 0; + char *monstart, *ddstart, *hrstart, *minstart, *yearstart; + char *linktostart, *filestart = NULL; + char *sizestart; + char *pe; + struct tm ftm; + + /* + * Look for the digit just before the space + * before the month name. + * +-rw-rw---- 1 gleason sysdev 33404 Mar 24 01:29 RCmd.o +-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README +-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README +-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README +-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README + * + *------------------------------^ + * 0123456789012345 + *------plugend--------^ + * 9876543210 + * + */ + for (cp = line; *cp != '\0'; cp++) { + if ( (isdigit((int) *cp)) + && (isspace((int) cp[1])) + && (isupper((int) cp[2])) + && (islower((int) cp[3])) + /* && (islower((int) cp[4])) */ + && (isspace((int) cp[5])) + && ( +((isdigit((int) cp[6])) && (isdigit((int) cp[7]))) +|| ((isdigit((int) cp[6])) && (isspace((int) cp[7]))) +|| ((isspace((int) cp[6])) && (isdigit((int) cp[7]))) + ) + && (isspace((int) cp[8])) + ) { + monstart = cp + 2; + ddstart = cp + 6; + if ( ((isspace((int) cp[9])) || (isdigit((int) cp[9]))) + && (isdigit((int) cp[10])) + && (isdigit((int) cp[11])) + && (isdigit((int) cp[12])) + && ((isdigit((int) cp[13])) || (isspace((int) cp[13]))) + ) { + /* "Mon DD YYYY" form */ + yearstart = cp + 9; + if (isspace((int) *yearstart)) + yearstart++; + hrstart = NULL; + minstart = NULL; + filestart = cp + 15; + cp[1] = '\0'; /* end size */ + cp[5] = '\0'; /* end mon */ + cp[8] = '\0'; /* end dd */ + cp[14] = '\0'; /* end year */ + mon = LsMonthNameToNum(monstart); + dd = atoi(ddstart); + hr = 23; + min = 59; + year = atoi(yearstart); + + pe = cp; + while (isdigit((int) *pe)) + pe--; + while (isspace((int) *pe)) + pe--; + *plugend = (int) (pe - line) + 1; + break; + } else if ( /* + * Windows NT does not 0 pad. + (isdigit((int) cp[9])) && + */ + (isdigit((int) cp[10])) + && (cp[11] == ':') + && (isdigit((int) cp[12])) + && (isdigit((int) cp[13])) + ) { + /* "Mon DD HH:MM" form */ + yearstart = NULL; + hrstart = cp + 9; + minstart = cp + 12; + filestart = cp + 15; + cp[1] = '\0'; /* end size */ + cp[5] = '\0'; /* end mon */ + cp[8] = '\0'; /* end dd */ + cp[11] = '\0'; /* end hr */ + cp[14] = '\0'; /* end min */ + mon = LsMonthNameToNum(monstart); + dd = atoi(ddstart); + hr = atoi(hrstart); + min = atoi(minstart); + year = 0; + + pe = cp; + while (isdigit((int) *pe)) + pe--; + while (isspace((int) *pe)) + pe--; + *plugend = (int) (pe - line) + 1; + break; + } + } + } + + if (*cp == '\0') + return (-1); + + linktostart = strstr(filestart, " -> "); + if (linktostart != NULL) { + *linktostart = '\0'; + linktostart += 4; + (void) Strncpy(linkto, linktostart, linktosize); + } else { + *linkto = '\0'; + } + + if (curdirlen == 0) { + (void) Strncpy(fname, filestart, fnamesize); + } else { + (void) Strncpy(fname, curdir, fnamesize); + (void) Strncat(fname, filestart, fnamesize); + } + + if (ftime != NULL) { + (void) memset(&ftm, 0, sizeof(struct tm)); + ftm.tm_mon = mon; + ftm.tm_mday = dd; + ftm.tm_hour = hr; + ftm.tm_min = min; + ftm.tm_isdst = -1; + if (year == 0) { + /* We guess the year, based on what the + * current year is. We know the file + * on the remote server is either less + * than six months old or less than + * one hour into the future. + */ + ftm.tm_year = thisyear - 1900; + *ftime = mktime(&ftm); + if (*ftime == (time_t) -1) { + /* panic */ + } else if (*ftime > (now + (15552000L + 86400L))) { + --ftm.tm_year; + *ftime = mktime(&ftm); + } else if (*ftime < (now - (15552000L + 86400L))) { + ++ftm.tm_year; + *ftime = mktime(&ftm); + } + } else { + ftm.tm_year = year - 1900; + *ftime = mktime(&ftm); + } + } + + if (fsize != NULL) { + while ((cp > line) && (isdigit((int) *cp))) + --cp; + sizestart = cp + 1; +#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG) + (void) sscanf(sizestart, SCANF_LONG_LONG, fsize); +#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ) + *fsize = (longest_int) strtoq(sizestart, NULL, 0); +#else + { + long fsize2 = 0L; + + (void) sscanf(sizestart, "%ld", &fsize2); + *fsize = (longest_int) fsize2; + } +#endif + } + + switch (line[0]) { + case 'd': + case 'l': + *ftype = (int) line[0]; + break; + case 'b': + case 'c': + case 's': + *ftype = (int) line[0]; + return (-1); + default: + *ftype = '-'; + } + + return (0); +} /* UnLslRLine */ + + + +int +UnLslR(FileInfoListPtr filp, LineListPtr llp, int serverType) +{ + char curdir[256]; + char line[256]; + int hadblankline = 0; + int len; + size_t curdirlen = 0; + char fname[256]; + char linkto[256]; + char *cp; + longest_int fsize; + int ftype; + time_t ftime, now; + int thisyear; + struct tm *nowtm; + int rc; + LinePtr lp; + FileInfo fi; + int linesread = 0; + int linesconverted = 0; + size_t maxFileLen = 0; + size_t maxPlugLen = 0; + size_t fileLen; + int plugend; + + (void) time(&now); + nowtm = localtime(&now); + if (nowtm == NULL) + thisyear = 1970; /* should never happen */ + else + thisyear = nowtm->tm_year + 1900; + + curdir[0] = '\0'; + + InitFileInfoList(filp); + for (lp = llp->first; lp != NULL; lp = lp->next) { + len = (int) strlen(STRNCPY(line, lp->line)); + if ((line[0] == 't') && (strncmp(line, "total", 5) == 0)) { + /* total XX line? */ + if (line[len - 1] != ':') { + hadblankline = 0; + continue; + } + /* else it was a subdir named total */ + } else { + for (cp = line; ; cp++) { + if ((*cp == '\0') || (!isspace((int) *cp))) + break; + } + if (*cp == '\0') { + /* Entire line was blank. */ + /* separator line between dirs */ + hadblankline = 1; + continue; + } + } + + if ((hadblankline != 0) && (line[len - 1] == ':')) { + /* newdir */ + hadblankline = 0; + if ((line[0] == '.') && (line[1] == '/')) { + line[len - 1] = '/'; + (void) memcpy(curdir, line + 2, (size_t) len + 1 - 2); + curdirlen = (size_t) (len - 2); + } else if ((line[0] == '.') && (line[1] == '\\')) { + line[len - 1] = '\\'; + (void) memcpy(curdir, line + 2, (size_t) len + 1 - 2); + curdirlen = (size_t) (len - 2); + } else { + line[len - 1] = '/'; + (void) memcpy(curdir, line, (size_t) len + 1); + curdirlen = (size_t) len; + } + continue; + } + + linesread++; + rc = UnLslRLine(line, curdir, curdirlen, fname, sizeof(fname), linkto, sizeof(linkto), &ftype, &fsize, &ftime, now, thisyear, &plugend); + if ((rc < 0) && (serverType == kServerTypeMicrosoftFTP)) { + rc = UnDosLine(line, curdir, curdirlen, fname, sizeof(fname), &ftype, &fsize, &ftime); + if (rc == 0) { + *linkto = '\0'; + plugend = 0; + } + } + if (rc == 0) { + linesconverted++; + fileLen = strlen(fname); + if (fileLen > maxFileLen) + maxFileLen = fileLen; + fi.relnameLen = fileLen; + fi.relname = StrDup(fname); + fi.rname = NULL; + fi.lname = NULL; + fi.rlinkto = (linkto[0] == '\0') ? NULL : StrDup(linkto); + fi.mdtm = ftime; + fi.size = (longest_int) fsize; + fi.type = ftype; + if (plugend > 0) { + fi.plug = (char *) malloc((size_t) plugend + 1); + if (fi.plug != NULL) { + (void) memcpy(fi.plug, line, (size_t) plugend); + fi.plug[plugend] = '\0'; + if ((size_t) plugend > maxPlugLen) + maxPlugLen = (size_t) plugend; + } + } else { + fi.plug = (char *) malloc(32); + if (fi.plug != NULL) { + strcpy(fi.plug, "---------- 1 ftpuser ftpusers"); + fi.plug[0] = (char) ftype; + if (30 > maxPlugLen) + maxPlugLen = (size_t) 30; + } + } + (void) AddFileInfo(filp, &fi); + } + + hadblankline = 0; + } + + filp->maxFileLen = maxFileLen; + filp->maxPlugLen = maxPlugLen; + if (linesread == 0) + return (0); + return ((linesconverted > 0) ? linesconverted : (-1)); +} /* UnLslR */ + + + + +int +UnMlsT(const char *const line0, const MLstItemPtr mlip) +{ + char *cp, *val, *fact; + int ec; + size_t len; + char line[1024]; + + memset(mlip, 0, sizeof(MLstItem)); + mlip->mode = -1; + mlip->fsize = kSizeUnknown; + mlip->ftype = '-'; + mlip->ftime = kModTimeUnknown; + + len = strlen(line0); + if (len > (sizeof(line) - 1)) + return (-1); /* Line too long, sorry. */ + /* This should be re-coded so does not need to make a + * copy of the buffer; it could be done in place. + */ + memcpy(line, line0, len + 1); + + /* Skip leading whitespace. */ + for (cp = line; *cp != '\0'; cp++) { + if (! isspace(*cp)) + break; + } + + while (*cp != '\0') { + for (fact = cp; ; cp++) { + if ((*cp == '\0') || (*cp == ' ')) { + /* protocol violation */ + return (-1); + } + if (*cp == '=') { + /* End of fact name. */ + *cp++ = '\0'; + break; + } + } + for (val = cp; ; cp++) { + if (*cp == '\0') { + /* protocol violation */ + return (-1); + } + if (*cp == ' ') { + ec = ' '; + *cp++ = '\0'; + break; + } else if (*cp == ';') { + if (cp[1] == ' ') { + ec = ' '; + *cp++ = '\0'; + *cp++ = '\0'; + } else { + ec = ';'; + *cp++ = '\0'; + } + break; + } + } + if (ISTRNEQ(fact, "OS.", 3)) + fact += 3; + if (ISTREQ(fact, "type")) { + if (ISTREQ(val, "file")) { + mlip->ftype = '-'; + } else if (ISTREQ(val, "dir")) { + mlip->ftype = 'd'; + } else if (ISTREQ(val, "cdir")) { + /* not supported: current directory */ + return (-2); + } else if (ISTREQ(val, "pdir")) { + /* not supported: parent directory */ + return (-2); + } else { + /* ? */ + return (-1); + } + } else if (ISTREQ(fact, "UNIX.mode")) { + if (val[0] == '0') + sscanf(val, "%o", &mlip->mode); + else + sscanf(val, "%i", &mlip->mode); + if (mlip->mode != (-1)) + mlip->mode &= 00777; + } else if (ISTREQ(fact, "perm")) { + STRNCPY(mlip->perm, val); + } else if (ISTREQ(fact, "size")) { +#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG) + (void) sscanf(val, SCANF_LONG_LONG, &mlip->fsize); +#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ) + mlip->fsize = (longest_int) strtoq(val, NULL, 0); +#else + { + long fsize2 = 0L; + + (void) sscanf(val, "%ld", &fsize2); + mlip->fsize = (longest_int) fsize2; + } +#endif + } else if (ISTREQ(fact, "modify")) { + mlip->ftime = UnMDTMDate(val); + } else if (ISTREQ(fact, "UNIX.owner")) { + STRNCPY(mlip->owner, val); + } else if (ISTREQ(fact, "UNIX.group")) { + STRNCPY(mlip->group, val); + } else if (ISTREQ(fact, "UNIX.uid")) { + mlip->uid = atoi(val); + } else if (ISTREQ(fact, "UNIX.gid")) { + mlip->gid = atoi(val); + } else if (ISTREQ(fact, "perm")) { + STRNCPY(mlip->perm, val); + } + + /* End of facts? */ + if (ec == ' ') + break; + } + + len = strlen(cp); + if (len > (sizeof(mlip->fname) - 1)) { + /* Filename too long */ + return (-1); + } + memcpy(mlip->fname, cp, len); + + /* also set linkto here if used */ + + return (0); +} /* UnMlsT */ + + + + +int +UnMlsD(FileInfoListPtr filp, LineListPtr llp) +{ + MLstItem mli; + char plug[64]; + char og[32]; + int rc; + LinePtr lp; + FileInfo fi; + int linesread = 0; + int linesconverted = 0; + int linesignored = 0; + size_t maxFileLen = 0; + size_t maxPlugLen = 0; + size_t fileLen, plugLen; + int m1, m2, m3; + const char *cm1, *cm2, *cm3; + + InitFileInfoList(filp); + for (lp = llp->first; lp != NULL; lp = lp->next) { + linesread++; + rc = UnMlsT(lp->line, &mli); + if (rc == 0) { + linesconverted++; + fileLen = strlen(mli.fname); + if (fileLen > maxFileLen) + maxFileLen = fileLen; + fi.relnameLen = fileLen; + fi.relname = StrDup(mli.fname); + fi.rname = NULL; + fi.lname = NULL; + fi.rlinkto = (mli.linkto[0] == '\0') ? NULL : StrDup(mli.linkto); + fi.mdtm = mli.ftime; + fi.size = (longest_int) mli.fsize; + fi.type = mli.ftype; + plug[0] = (char) mli.ftype; + plug[1] = '\0'; + m1 = 0; + m2 = 0; + m3 = -1; + if (mli.mode != (-1)) { + m1 = (mli.mode & 00700) >> 6; + m2 = (mli.mode & 00070) >> 3; + m3 = (mli.mode & 00007); + } + if (mli.perm[0] != '\0') { + m3 = 0; + if (fi.type == 'd') { + if (strchr(mli.perm, 'e') != NULL) { + /* execute -> execute */ + m3 |= 00001; + } + if (strchr(mli.perm, 'c') != NULL) { + /* create -> write */ + m3 |= 00002; + } + if (strchr(mli.perm, 'l') != NULL) { + /* list -> read */ + m3 |= 00004; + } + } else { + if (strchr(mli.perm, 'w') != NULL) { + /* write -> write */ + m3 |= 00002; + } + if (strchr(mli.perm, 'r') != NULL) { + /* read -> read */ + m3 |= 00004; + } + } + } + if (m3 != (-1)) { + cm1 = rwx[m1]; + cm2 = rwx[m2]; + cm3 = rwx[m3]; + sprintf(plug + 1, "%s%s%s", cm1, cm2, cm3); + } + if (mli.owner[0] != '\0') { + if (mli.group[0] != '\0') { +#ifdef HAVE_SNPRINTF + snprintf(og, sizeof(og) - 1, +#else + sprintf(og, +#endif /* HAVE_SNPRINTF */ + " %-8.8s %s", + mli.owner, mli.group + ); + STRNCAT(plug, og); + } else { + STRNCAT(plug, " "); + STRNCAT(plug, mli.owner); + } + } + fi.plug = StrDup(plug); + if (fi.plug != NULL) { + plugLen = strlen(plug); + if (plugLen > maxPlugLen) + maxPlugLen = plugLen; + } + (void) AddFileInfo(filp, &fi); + } else if (rc == (-2)) { + linesignored++; + } + } + + filp->maxFileLen = maxFileLen; + filp->maxPlugLen = maxPlugLen; + if (linesread == 0) + return (0); + linesconverted += linesignored; + return ((linesconverted > 0) ? linesconverted : (-1)); +} /* UnMlsD */ + + + +#if 0 +static void +print1(FileInfoListPtr list) +{ + FileInfoPtr fip; + int i; + + for (i = 1, fip = list->first; fip != NULL; fip = fip->next, i++) + printf("%d: %s\n", i, fip->relname == NULL ? "NULL" : fip->relname); +} + + + +static void +print2(FileInfoListPtr list) +{ + FileInfoPtr fip; + int i, n; + + n = list->nFileInfos; + for (i=0; ivec[i]; + printf("%d: %s\n", i + 1, fip->relname == NULL ? "NULL" : fip->relname); + } +} + + + + +static void +SortRecursiveFileList(FileInfoListPtr files) +{ + VectorizeFileInfoList(files); + SortFileInfoList(files, 'b', '?'); + UnvectorizeFileInfoList(files); +} /* SortRecursiveFileList */ +#endif + + + + +int +FTPRemoteRecursiveFileList1(FTPCIPtr cip, char *const rdir, FileInfoListPtr files) +{ + LineList dirContents; + FileInfoList fil; + char cwd[512]; + int result; + + if ((result = FTPGetCWD(cip, cwd, sizeof(cwd))) < 0) + return (result); + + InitFileInfoList(files); + + if (rdir == NULL) + return (-1); + + if (FTPChdir(cip, rdir) < 0) { + /* Probably not a directory. + * Just add it as a plain file + * to the list. + */ + (void) ConcatFileToFileInfoList(files, rdir); + return (kNoErr); + } + + /* Paths collected must be relative. */ + if ((result = FTPListToMemory2(cip, "", &dirContents, "-lRa", 1, (int *) 0)) < 0) { + if ((result = FTPChdir(cip, cwd)) < 0) { + return (result); + } + } + + (void) UnLslR(&fil, &dirContents, cip->serverType); + DisposeLineListContents(&dirContents); + /* Could sort it to breadth-first here. */ + /* (void) SortRecursiveFileList(&fil); */ + (void) ComputeRNames(&fil, rdir, 1, 1); + (void) ConcatFileInfoList(files, &fil); + DisposeFileInfoListContents(&fil); + + if ((result = FTPChdir(cip, cwd)) < 0) { + return (result); + } + return (kNoErr); +} /* FTPRemoteRecursiveFileList1 */ + + + + +int +FTPRemoteRecursiveFileList(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files) +{ + LinePtr filePtr, nextFilePtr; + LineList dirContents; + FileInfoList fil; + char cwd[512]; + int result; + char *rdir; + + if ((result = FTPGetCWD(cip, cwd, sizeof(cwd))) < 0) + return (result); + + InitFileInfoList(files); + + for (filePtr = fileList->first; + filePtr != NULL; + filePtr = nextFilePtr) + { + nextFilePtr = filePtr->next; + + rdir = filePtr->line; + if (rdir == NULL) + continue; + + if (FTPChdir(cip, rdir) < 0) { + /* Probably not a directory. + * Just add it as a plain file + * to the list. + */ + (void) ConcatFileToFileInfoList(files, rdir); + continue; + } + + /* Paths collected must be relative. */ + if ((result = FTPListToMemory2(cip, "", &dirContents, "-lRa", 1, (int *) 0)) < 0) { + goto goback; + } + + (void) UnLslR(&fil, &dirContents, cip->serverType); + DisposeLineListContents(&dirContents); + (void) ComputeRNames(&fil, rdir, 1, 1); + (void) ConcatFileInfoList(files, &fil); + DisposeFileInfoListContents(&fil); + +goback: + if ((result = FTPChdir(cip, cwd)) < 0) { + return (result); + } + } + return (kNoErr); +} /* FTPRemoteRecursiveFileList */ + + + +#if defined(WIN32) || defined(_WINDOWS) + +static void +Traverse(FTPCIPtr cip, char *fullpath, struct Stat *st, char *relpath, FileInfoListPtr filp) +{ + WIN32_FIND_DATA ffd; + HANDLE searchHandle; + DWORD dwErr; + char *cp, *c2; + const char *file; + FileInfo fi; + + /* Handle directory entry first. */ + if (relpath[0] != '\0') { + fi.relname = StrDup(relpath); + fi.rname = NULL; + fi.lname = StrDup(fullpath); + fi.rlinkto = NULL; + fi.plug = NULL; + fi.mdtm = st->st_mtime; + fi.size = (longest_int) st->st_size; + fi.type = 'd'; + (void) AddFileInfo(filp, &fi); + } + + cp = fullpath + strlen(fullpath); + *cp++ = LOCAL_PATH_DELIM; + strcpy(cp, "*.*"); + + c2 = relpath + strlen(relpath); + *c2++ = LOCAL_PATH_DELIM; + *c2 = '\0'; + + memset(&ffd, 0, sizeof(ffd)); + + /* "Open" the directory. */ + searchHandle = FindFirstFile(fullpath, &ffd); + if (searchHandle == INVALID_HANDLE_VALUE) { + return; + } + + for (;;) { + + file = ffd.cFileName; + if ((*file == '.') && ((file[1] == '\0') || ((file[1] == '.') && (file[2] == '\0')))) { + /* It was "." or "..", so skip it. */ + goto next; + } + + (void) strcpy(cp, file); /* append name after slash */ + (void) strcpy(c2, file); + + if (Lstat(fullpath, st) < 0) { + Error(cip, kDoPerror, "could not stat %s.\n", fullpath); + goto next; + } + + fi.relname = StrDup(relpath + (((relpath[0] == '/') || (relpath[0] == '\\')) ? 1 : 0)); + fi.rname = NULL; + fi.lname = StrDup(fullpath); + fi.mdtm = st->st_mtime; + fi.size = (longest_int) st->st_size; + fi.rlinkto = NULL; + fi.plug = NULL; + + if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + Traverse(cip, fullpath, st, relpath, filp); + } else { + /* file */ + fi.type = '-'; + (void) AddFileInfo(filp, &fi); + } + +next: +#if _DEBUG + memset(&ffd, 0, sizeof(ffd)); +#endif + if (!FindNextFile(searchHandle, &ffd)) { + dwErr = GetLastError(); + if (dwErr != ERROR_NO_MORE_FILES) { + FindClose(searchHandle); + return; + } + break; + } + } + FindClose(searchHandle); +} // Traverse + +#else + +static void +Traverse(FTPCIPtr cip, char *fullpath, struct Stat *st, char *relpath, FileInfoListPtr filp) +{ + char *dname; + struct dirent *dirp; + mode_t m; + DIR *dp; + char *cp; + char *c2; + FileInfo fi; + + if (relpath[0] != '\0') { + fi.relname = StrDup(relpath); + fi.rname = NULL; + fi.lname = StrDup(fullpath); + fi.rlinkto = NULL; + fi.plug = NULL; + fi.mdtm = st->st_mtime; + fi.size = (longest_int) st->st_size; + fi.type = 'd'; + (void) AddFileInfo(filp, &fi); + } + + /* Handle directory entry first. */ + cp = fullpath + strlen(fullpath); + *cp++ = '/'; + *cp = '\0'; + + c2 = relpath + strlen(relpath); + *c2++ = '/'; + *c2 = '\0'; + + if ((dp = opendir(fullpath)) == NULL) { + cp[-1] = '\0'; + c2[-1] = '\0'; + Error(cip, kDoPerror, "could not opendir %s.\n", fullpath); + return; + } + + while ((dirp = readdir(dp)) != NULL) { + dname = dirp->d_name; + if ((dname[0] == '.') && ((dname[1] == '\0') || ((dname[1] == '.') && (dname[2] == '\0')))) + continue; /* skip "." and ".." directories. */ + + (void) strcpy(cp, dirp->d_name); /* append name after slash */ + (void) strcpy(c2, dirp->d_name); + if (Lstat(fullpath, st) < 0) { + Error(cip, kDoPerror, "could not stat %s.\n", fullpath); + continue; + } + + fi.relname = StrDup(relpath + (((relpath[0] == '/') || (relpath[0] == '\\')) ? 1 : 0)); + fi.rname = NULL; + fi.lname = StrDup(fullpath); + fi.mdtm = st->st_mtime; + fi.size = (longest_int) st->st_size; + fi.rlinkto = NULL; + fi.plug = NULL; + + m = st->st_mode; + if (S_ISREG(m) != 0) { + /* file */ + fi.type = '-'; + (void) AddFileInfo(filp, &fi); + } else if (S_ISDIR(m)) { + Traverse(cip, fullpath, st, relpath, filp); +#ifdef S_ISLNK + } else if (S_ISLNK(m)) { + fi.type = 'l'; + fi.rlinkto = calloc(128, 1); + if (fi.rlinkto != NULL) { + if (readlink(fullpath, fi.rlinkto, 127) < 0) { + free(fi.rlinkto); + } else { + (void) AddFileInfo(filp, &fi); + } + } +#endif /* S_ISLNK */ + } + } + cp[-1] = '\0'; + c2[-1] = '\0'; + + (void) closedir(dp); +} /* Traverse */ + +#endif + + + + + +int +FTPLocalRecursiveFileList2(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files, int erelative) +{ + LinePtr filePtr, nextFilePtr; +#if defined(WIN32) || defined(_WINDOWS) + char fullpath[_MAX_PATH + 1]; + char relpath[_MAX_PATH + 1]; +#else + char fullpath[512]; + char relpath[512]; +#endif + struct Stat st; + FileInfo fi; + char *cp; + + InitFileInfoList(files); + + for (filePtr = fileList->first; + filePtr != NULL; + filePtr = nextFilePtr) + { + nextFilePtr = filePtr->next; + + (void) STRNCPY(fullpath, filePtr->line); /* initialize fullpath */ + if ((erelative != 0) || (strcmp(filePtr->line, ".") == 0) || (filePtr->line[0] == '\0')) + (void) STRNCPY(relpath, ""); + else if ((cp = StrRFindLocalPathDelim(filePtr->line)) == NULL) + (void) STRNCPY(relpath, filePtr->line); + else + (void) STRNCPY(relpath, cp + 1); + if (Lstat(fullpath, &st) < 0) { + Error(cip, kDoPerror, "could not stat %s.\n", fullpath); + continue; + } + + if (S_ISDIR(st.st_mode) == 0) { + fi.relname = StrDup(relpath); + fi.rname = NULL; + fi.lname = StrDup(fullpath); + fi.mdtm = st.st_mtime; + fi.size = (longest_int) st.st_size; + fi.rlinkto = NULL; + fi.plug = NULL; + fi.type = '-'; + (void) AddFileInfo(files, &fi); + continue; /* wasn't a directory */ + } + + /* Paths collected must be relative. */ + Traverse(cip, fullpath, &st, relpath, files); + } + return (kNoErr); +} /* FTPLocalRecursiveFileList */ + + + + +int +FTPLocalRecursiveFileList(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files) +{ + return (FTPLocalRecursiveFileList2(cip, fileList, files, 0)); +} /* FTPLocalRecursiveFileList */ + + + +int +FTPRemoteGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob) +{ + char *cp; + const char *lsflags; + LinePtr lp; + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (fileList == NULL) + return (kErrBadParameter); + InitLineList(fileList); + + if ((pattern == NULL) || (pattern[0] == '\0')) + return (kErrBadParameter); + + /* Note that we do attempt to use glob characters even if the remote + * host isn't UNIX. Most non-UNIX remote FTP servers look for UNIX + * style wildcards. + */ + if ((doGlob == 1) && (GLOBCHARSINSTR(pattern))) { + /* Use NLST, which lists files one per line. */ + lsflags = ""; + + /* Optimize for "NLST *" case which is same as "NLST". */ + if (strcmp(pattern, "*") == 0) { + pattern = ""; + } else if (strcmp(pattern, "**") == 0) { + /* Hack; Lets you try "NLST -a" if you're daring. */ + pattern = ""; + lsflags = "-a"; + } + + if ((result = FTPListToMemory2(cip, pattern, fileList, lsflags, 0, (int *) 0)) < 0) { + if (*lsflags == '\0') + return (result); + /* Try again, without "-a" */ + lsflags = ""; + if ((result = FTPListToMemory2(cip, pattern, fileList, lsflags, 0, (int *) 0)) < 0) { + return (result); + } + } + if (fileList->first == NULL) { + cip->errNo = kErrGlobNoMatch; + return (kErrGlobNoMatch); + } + if (fileList->first == fileList->last) { +#define glberr(a) (ISTRNEQ(cp, a, strlen(a))) + /* If we have only one item in the list, see if it really was + * an error message we would recognize. + */ + cp = strchr(fileList->first->line, ':'); + if (cp != NULL) { + if (glberr(": No such file or directory")) { + (void) RemoveLine(fileList, fileList->first); + cip->errNo = kErrGlobFailed; + return (kErrGlobFailed); + } else if (glberr(": No match")) { + cip->errNo = kErrGlobNoMatch; + return (kErrGlobNoMatch); + } + } + } + RemoteGlobCollapse(pattern, fileList); + for (lp=fileList->first; lp != NULL; lp = lp->next) + PrintF(cip, " Rglob [%s]\n", lp->line); + } else { + /* Or, if there were no globbing characters in 'pattern', then the + * pattern is really just a filename. So for this case the + * file list is really just a single file. + */ + fileList->first = fileList->last = NULL; + (void) AddLine(fileList, pattern); + } + return (kNoErr); +} /* FTPRemoteGlob */ + + + + +/* This does "tilde-expansion." Examples: + * ~/pub --> /usr/gleason/pub + * ~pdietz/junk --> /usr/pdietz/junk + */ +static void +ExpandTilde(char *pattern, size_t siz) +{ + string pat; + char *cp, *rest, *firstent; +#if defined(WIN32) || defined(_WINDOWS) +#else + struct passwd *pw; +#endif + string hdir; + + if ((pattern[0] == '~') && + (isalnum((int) pattern[1]) || IsLocalPathDelim(pattern[1]) || (pattern[1] == '\0'))) { + (void) STRNCPY(pat, pattern); + if ((cp = StrFindLocalPathDelim(pat)) != NULL) { + *cp = 0; + rest = cp + 1; /* Remember stuff after the ~/ part. */ + } else { + rest = NULL; /* Was just a ~ or ~username. */ + } + if (pat[1] == '\0') { + /* Was just a ~ or ~/rest type. */ + GetHomeDir(hdir, sizeof(hdir)); + firstent = hdir; + } else { +#if defined(WIN32) || defined(_WINDOWS) + return; +#else + /* Was just a ~username or ~username/rest type. */ + pw = getpwnam(pat + 1); + if (pw != NULL) + firstent = pw->pw_dir; + else + return; /* Bad user -- leave it alone. */ +#endif + } + + (void) Strncpy(pattern, firstent, siz); + if (rest != NULL) { + (void) Strncat(pattern, LOCAL_PATH_DELIM_STR, siz); + (void) Strncat(pattern, rest, siz); + } + } +} /* ExpandTilde */ + + + + + +#if defined(WIN32) || defined(_WINDOWS) + +static int +WinLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *const srcpat) +{ + char pattern[_MAX_PATH]; + WIN32_FIND_DATA ffd; + HANDLE searchHandle; + DWORD dwErr; + char *cp; + const char *file; + int result; + + STRNCPY(pattern, srcpat); + + /* Get rid of trailing slashes. */ + cp = pattern + strlen(pattern) - 1; + while ((cp >= pattern) && IsLocalPathDelim(*cp)) + *cp-- = '\0'; + + memset(&ffd, 0, sizeof(ffd)); + + /* "Open" the directory. */ + searchHandle = FindFirstFile(pattern, &ffd); + if (searchHandle == INVALID_HANDLE_VALUE) { + dwErr = GetLastError(); + return ((dwErr == 0) ? 0 : -1); + } + + /* Get rid of basename. */ + cp = StrRFindLocalPathDelim(pattern); + if (cp == NULL) + cp = pattern; + else + cp++; + *cp = '\0'; + + for (result = 0;;) { + file = ffd.cFileName; + if ((file[0] == '.') && ((file[1] == '\0') || ((file[1] == '.') && (file[2] == '\0')))) { + /* skip */ + } else { + Strncpy(cp, ffd.cFileName, sizeof(pattern) - (cp - pattern)); + PrintF(cip, " Lglob [%s]\n", pattern); + (void) AddLine(fileList, pattern); + } + + if (!FindNextFile(searchHandle, &ffd)) { + dwErr = GetLastError(); + if (dwErr != ERROR_NO_MORE_FILES) { + result = ((dwErr == 0) ? 0 : -1); + } + break; + } + } + + return (result); +} // WinLocalGlob + +#else + +static int +LazyUnixLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *const pattern) +{ + string cmd; + longstring gfile; + FILE *fp; + FTPSigProc sp; + + /* Do it the easy way and have the shell do the dirty + * work for us. + */ +#ifdef HAVE_SNPRINTF + (void) snprintf(cmd, sizeof(cmd) - 1, "%s -c \"%s %s %s\"", "/bin/sh", "/bin/ls", + "-d", pattern); + cmd[sizeof(cmd) - 1] = '\0'; +#else + (void) sprintf(cmd, "%s -c \"%s %s %s\"", "/bin/sh", "/bin/ls", + "-d", pattern); +#endif + + fp = (FILE *) popen(cmd, "r"); + if (fp == NULL) { + Error(cip, kDoPerror, "Could not Lglob: [%s]\n", cmd); + cip->errNo = kErrGlobFailed; + return (kErrGlobFailed); + } + sp = NcSignal(SIGPIPE, (FTPSigProc) SIG_IGN); + while (FGets(gfile, sizeof(gfile), (FILE *) fp) != NULL) { + PrintF(cip, " Lglob [%s]\n", gfile); + (void) AddLine(fileList, gfile); + } + (void) pclose(fp); + (void) NcSignal(SIGPIPE, sp); + return (kNoErr); +} /* LazyUnixLocalGlob */ + +#endif + + + + +int +FTPLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob) +{ + string pattern2; + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (fileList == NULL) + return (kErrBadParameter); + InitLineList(fileList); + + if ((pattern == NULL) || (pattern[0] == '\0')) + return (kErrBadParameter); + + (void) STRNCPY(pattern2, pattern); /* Don't nuke the original. */ + + /* Pre-process for ~'s. */ + ExpandTilde(pattern2, sizeof(pattern2)); + InitLineList(fileList); + result = kNoErr; + + if ((doGlob == 1) && (GLOBCHARSINSTR(pattern2))) { +#if defined(WIN32) || defined(_WINDOWS) + result = WinLocalGlob(cip, fileList, pattern2); +#else + result = LazyUnixLocalGlob(cip, fileList, pattern2); +#endif + } else { + /* Or, if there were no globbing characters in 'pattern', then + * the pattern is really just a single pathname. + */ + (void) AddLine(fileList, pattern2); + } + + return (result); +} /* FTPLocalGlob */ + + + + +static int +FTPFtwL2(const FTPCIPtr cip, char *dir, char *end, size_t dirsize, FTPFtwProc proc, int maxdepth) +{ + LineList fileList; + LinePtr filePtr; + char *file, *cp; + int result; + + if (maxdepth <= 0) { + result = cip->errNo = kErrRecursionLimitReached; + return (result); + } + + result = FTPRemoteGlob(cip, &fileList, "**", kGlobYes); + if (result != kNoErr) { + if (result == kErrGlobNoMatch) + result = kNoErr; /* empty directory is okay. */ + return (result); + } + + for (filePtr = fileList.first; + filePtr != NULL; + filePtr = filePtr->next) + { + file = filePtr->line; + if (file == NULL) { + cip->errNo = kErrBadLineList; + break; + } + + if ((file[0] == '.') && ((file[1] == '\0') || ((file[1] == '.') && (file[2] == '\0')))) + continue; /* Skip . and .. */ + + result = FTPIsDir(cip, file); + if (result < 0) { + /* error */ + /* could be just a stat error, so continue */ + continue; + } else if (result == 1) { + /* directory */ + cp = Strnpcat(dir, file, dirsize); + result = (*proc)(cip, dir, kFtwDir); + if (result != kNoErr) + break; + + if ((strchr(dir, '/') == NULL) && (strrchr(dir, '\\') != NULL)) + *cp++ = '\\'; + else + *cp++ = '/'; + *cp = '\0'; + + result = FTPChdir(cip, file); + if (result == kNoErr) { + result = FTPFtwL2(cip, dir, cp, dirsize, proc, maxdepth - 1); + if (result != kNoErr) + break; + if (FTPChdir(cip, "..") < 0) { + result = kErrCannotGoToPrevDir; + cip->errNo = kErrCannotGoToPrevDir; + break; + } + } + + *end = '\0'; + if (result != 0) + break; + } else { + /* file */ + cp = Strnpcat(dir, file, dirsize); + result = (*proc)(cip, dir, kFtwFile); + *end = '\0'; + if (result != 0) + break; + } + } + DisposeLineListContents(&fileList); + + return (result); +} /* FTPFtwL2 */ + + + +int +FTPFtw(const FTPCIPtr cip, const char *const dir, FTPFtwProc proc, int maxdepth) +{ + int result, result2; + char *cp; + char savedcwd[1024]; + char curcwd[2048]; + + result = FTPIsDir(cip, dir); + if (result < 0) { + /* error */ + return result; + } else if (result == 0) { + result = cip->errNo = kErrNotADirectory; + return (result); + } + + /* Preserve old working directory. */ + (void) FTPGetCWD(cip, savedcwd, sizeof(savedcwd)); + + result = FTPChdir(cip, dir); + if (result != kNoErr) { + return (result); + } + + /* Get full working directory we just changed to. */ + result = FTPGetCWD(cip, curcwd, sizeof(curcwd) - 3); + if (result != kNoErr) { + if (FTPChdir(cip, savedcwd) != kNoErr) { + result = kErrCannotGoToPrevDir; + cip->errNo = kErrCannotGoToPrevDir; + } + return (result); + } + + result2 = (*proc)(cip, curcwd, kFtwDir); + if (result2 == kNoErr) { + cp = curcwd + strlen(curcwd); + + if ((strchr(curcwd, '/') == NULL) && (strrchr(curcwd, '\\') != NULL)) + *cp++ = '\\'; + else + *cp++ = '/'; + *cp = '\0'; + result = FTPFtwL2(cip, curcwd, cp, sizeof(curcwd), proc, maxdepth - 1); + } + + + if (FTPChdir(cip, savedcwd) != kNoErr) { + /* Could not cd back to the original user directory -- bad. */ + result = kErrCannotGoToPrevDir; + cip->errNo = kErrCannotGoToPrevDir; + return (result); + } + + if ((result2 != kNoErr) && (result == kNoErr)) + result = result2; + + return (result); +} /* FTPFtw */ + +/* eof */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/io.c b/modules/rosapps/applications/net/ncftp/libncftp/io.c new file mode 100644 index 00000000000..b92dd04cc98 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/io.c @@ -0,0 +1,2824 @@ +/* io.c + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#include "syshdrs.h" + +static int gGotBrokenData = 0; + +#if defined(WIN32) || defined(_WINDOWS) +# define ASCII_TRANSLATION 0 +#endif + +#ifndef ASCII_TRANSLATION +# define ASCII_TRANSLATION 1 +#endif + +#if !defined(NO_SIGNALS) && (USE_SIO || !defined(SIGALRM) || !defined(SIGPIPE) || !defined(SIGINT)) +# define NO_SIGNALS 1 +#endif + +#ifndef NO_SIGNALS + +#ifdef HAVE_SIGSETJMP +static sigjmp_buf gBrokenDataJmp; +#else +static jmp_buf gBrokenDataJmp; +#endif /* HAVE_SIGSETJMP */ +static int gCanBrokenDataJmp = 0; + +#endif /* NO_SIGNALS */ + + +#ifndef O_BINARY + /* Needed for platforms using different EOLN sequence (i.e. DOS) */ +# ifdef _O_BINARY +# define O_BINARY _O_BINARY +# else +# define O_BINARY 0 +# endif +#endif + +static int WaitForRemoteInput(const FTPCIPtr cip); +static int WaitForRemoteOutput(const FTPCIPtr cip); + + +#ifndef NO_SIGNALS + +static void +BrokenData(int signum) +{ + gGotBrokenData = signum; + if (gCanBrokenDataJmp != 0) { + gCanBrokenDataJmp = 0; +#ifdef HAVE_SIGSETJMP + siglongjmp(gBrokenDataJmp, 1); +#else + longjmp(gBrokenDataJmp, 1); +#endif /* HAVE_SIGSETJMP */ + } +} /* BrokenData */ + +#endif /* NO_SIGNALS */ + + + + +void +FTPInitIOTimer(const FTPCIPtr cip) +{ + cip->bytesTransferred = (longest_int) 0; + cip->expectedSize = kSizeUnknown; + cip->mdtm = kModTimeUnknown; + cip->rname = NULL; + cip->lname = NULL; + cip->kBytesPerSec = -1.0; + cip->percentCompleted = -1.0; + cip->sec = -1.0; + cip->secLeft = -1.0; + cip->nextProgressUpdate = 0; + cip->stalled = 0; + cip->dataTimedOut = 0; + cip->useProgressMeter = 1; + (void) gettimeofday(&cip->t0, NULL); +} /* FTPInitIOTimer */ + + + + +void +FTPStartIOTimer(const FTPCIPtr cip) +{ + (void) gettimeofday(&cip->t0, NULL); + if (cip->progress != (FTPProgressMeterProc) 0) + (*cip->progress)(cip, kPrInitMsg); +} /* FTPStartIOTimer */ + + + + +void +FTPUpdateIOTimer(const FTPCIPtr cip) +{ + double sec; + struct timeval *t0, t1; + time_t now; + + (void) time(&now); + if (now < cip->nextProgressUpdate) + return; + now += 1; + cip->nextProgressUpdate = now; + + (void) gettimeofday(&t1, NULL); + t0 = &cip->t0; + + if (t0->tv_usec > t1.tv_usec) { + t1.tv_usec += 1000000; + t1.tv_sec--; + } + sec = ((double) (t1.tv_usec - t0->tv_usec) * 0.000001) + + (t1.tv_sec - t0->tv_sec); + if (sec > 0.0) { + cip->kBytesPerSec = ((double) cip->bytesTransferred) / (1024.0 * sec); + } else { + cip->kBytesPerSec = -1.0; + } + if (cip->expectedSize == kSizeUnknown) { + cip->percentCompleted = -1.0; + cip->secLeft = -1.0; + } else if (cip->expectedSize <= 0) { + cip->percentCompleted = 100.0; + cip->secLeft = 0.0; + } else { + cip->percentCompleted = ((double) (100.0 * (cip->bytesTransferred + cip->startPoint))) / ((double) cip->expectedSize); + if (cip->percentCompleted >= 100.0) { + cip->percentCompleted = 100.0; + cip->secLeft = 0.0; + } else if (cip->percentCompleted <= 0.0) { + cip->secLeft = 999.0; + } + if (cip->kBytesPerSec > 0.0) { + cip->secLeft = ((cip->expectedSize - cip->bytesTransferred - cip->startPoint) / 1024.0) / cip->kBytesPerSec; + if (cip->secLeft < 0.0) + cip->secLeft = 0.0; + } + } + cip->sec = sec; + if ((cip->progress != (FTPProgressMeterProc) 0) && (cip->useProgressMeter != 0)) + (*cip->progress)(cip, kPrUpdateMsg); +} /* FTPUpdateIOTimer */ + + + + +void +FTPStopIOTimer(const FTPCIPtr cip) +{ + cip->nextProgressUpdate = 0; /* force last update */ + FTPUpdateIOTimer(cip); + if (cip->progress != (FTPProgressMeterProc) 0) + (*cip->progress)(cip, kPrEndMsg); +} /* FTPStopIOTimer */ + + + + +/* This isn't too useful -- it mostly serves as an example so you can write + * your own function to do what you need to do with the listing. + */ +int +FTPList(const FTPCIPtr cip, const int outfd, const int longMode, const char *const lsflag) +{ + const char *cmd; + char line[512]; + char secondaryBuf[768]; +#ifndef NO_SIGNALS + char *secBufPtr, *secBufLimit; + int nread; + volatile int result; +#else /* NO_SIGNALS */ + SReadlineInfo lsSrl; + int result; +#endif /* NO_SIGNALS */ + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + cmd = (longMode != 0) ? "LIST" : "NLST"; + if ((lsflag == NULL) || (lsflag[0] == '\0')) { + result = FTPStartDataCmd(cip, kNetReading, kTypeAscii, (longest_int) 0, "%s", cmd); + } else { + result = FTPStartDataCmd(cip, kNetReading, kTypeAscii, (longest_int) 0, "%s %s", cmd, lsflag); + } + + +#ifdef NO_SIGNALS + + if (result == 0) { + if (InitSReadlineInfo(&lsSrl, cip->dataSocket, secondaryBuf, sizeof(secondaryBuf), (int) cip->xferTimeout, 1) < 0) { + /* Not really fdopen, but close in what we're trying to do. */ + result = kErrFdopenR; + cip->errNo = kErrFdopenR; + Error(cip, kDoPerror, "Could not fdopen.\n"); + return (result); + } + + for (;;) { + result = SReadline(&lsSrl, line, sizeof(line) - 2); + if (result == kTimeoutErr) { + /* timeout */ + Error(cip, kDontPerror, "Could not directory listing data -- timed out.\n"); + cip->errNo = kErrDataTimedOut; + return (cip->errNo); + } else if (result == 0) { + /* end of listing -- done */ + cip->numListings++; + break; + } else if (result < 0) { + /* error */ + Error(cip, kDoPerror, "Could not read directory listing data"); + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + break; + } + + (void) write(outfd, line, strlen(line)); + } + + DisposeSReadlineInfo(&lsSrl); + if (FTPEndDataCmd(cip, 1) < 0) { + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + } + } else if (result == kErrGeneric) { + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + } + + +#else /* NO_SIGNALS */ + + if (result == 0) { + /* This line sets the buffer pointer so that the first thing + * BufferGets will do is reset and fill the buffer using + * real I/O. + */ + secBufPtr = secondaryBuf + sizeof(secondaryBuf); + secBufLimit = (char *) 0; + + for (;;) { + if (cip->xferTimeout > 0) + (void) alarm(cip->xferTimeout); + nread = BufferGets(line, sizeof(line), cip->dataSocket, secondaryBuf, &secBufPtr, &secBufLimit, sizeof(secondaryBuf)); + if (nread <= 0) { + if (nread < 0) + break; + } else { + cip->bytesTransferred += (longest_int) nread; + (void) STRNCAT(line, "\n"); + (void) write(outfd, line, strlen(line)); + } + } + if (cip->xferTimeout > 0) + (void) alarm(0); + result = FTPEndDataCmd(cip, 1); + if (result < 0) { + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + } + result = kNoErr; + cip->numListings++; + } else if (result == kErrGeneric) { + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + } +#endif /* NO_SIGNALS */ + return (result); +} /* FTPList */ + + + + +static void +FTPRequestMlsOptions(const FTPCIPtr cip) +{ + int f; + char optstr[128]; + size_t optstrlen; + + if (cip->usedMLS == 0) { + /* First MLSD/MLST ? */ + cip->usedMLS = 1; + + f = cip->mlsFeatures & kPreferredMlsOpts; + optstr[0] = '\0'; + + /* TYPE */ + if ((f & kMlsOptType) != 0) { + STRNCAT(optstr, "type;"); + } + + /* SIZE */ + if ((f & kMlsOptSize) != 0) { + STRNCAT(optstr, "size;"); + } + + /* MODTIME */ + if ((f & kMlsOptModify) != 0) { + STRNCAT(optstr, "modify;"); + } + + /* MODE */ + if ((f & kMlsOptUNIXmode) != 0) { + STRNCAT(optstr, "UNIX.mode;"); + } + + /* PERM */ + if ((f & kMlsOptPerm) != 0) { + STRNCAT(optstr, "perm;"); + } + + /* OWNER */ + if ((f & kMlsOptUNIXowner) != 0) { + STRNCAT(optstr, "UNIX.owner;"); + } + + /* UID */ + if ((f & kMlsOptUNIXuid) != 0) { + STRNCAT(optstr, "UNIX.uid;"); + } + + /* GROUP */ + if ((f & kMlsOptUNIXgroup) != 0) { + STRNCAT(optstr, "UNIX.group;"); + } + + /* GID */ + if ((f & kMlsOptUNIXgid) != 0) { + STRNCAT(optstr, "UNIX.gid;"); + } + + /* UNIQUE */ + if ((f & kMlsOptUnique) != 0) { + STRNCAT(optstr, "unique;"); + } + + /* Tell the server what we prefer. */ + optstrlen = strlen(optstr); + if (optstrlen > 0) { + if (optstr[optstrlen - 1] == ';') + optstr[optstrlen - 1] = '\0'; + (void) FTPCmd(cip, "OPTS MLST %s", optstr); + } + } +} /* FTPRequestMlsOptions */ + + + + +int +FTPListToMemory2(const FTPCIPtr cip, const char *const pattern, const LineListPtr llines, const char *const lsflags, const int blankLines, int *const tryMLSD) +{ + char secondaryBuf[768]; + char line[512]; + char lsflags1[128]; + const char *command = "NLST"; + const char *scp; + char *dcp, *lim; +#ifndef NO_SIGNALS + char *secBufPtr, *secBufLimit; + volatile FTPSigProc osigpipe; + volatile FTPCIPtr vcip; + int sj; + int nread; + volatile int result; +#else /* NO_SIGNALS */ + SReadlineInfo lsSrl; + int result; +#endif /* NO_SIGNALS */ + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((llines == NULL) || (pattern == NULL) || (lsflags == NULL)) + return (kErrBadParameter); + + if ((tryMLSD != (int *) 0) && (*tryMLSD != 0) && (cip->hasMLSD == kCommandAvailable)) { + command = "MLSD"; + if ((lsflags[0] == '-') && (strchr(lsflags, 'd') != NULL) && (cip->hasMLST == kCommandAvailable)) + command = "MLST"; + lsflags1[0] = '\0'; + FTPRequestMlsOptions(cip); + } else { + /* Not using MLSD. */ + if (tryMLSD != (int *) 0) + *tryMLSD = 0; + if (lsflags[0] == '-') { + /* See if we should use LIST instead. */ + scp = lsflags + 1; + dcp = lsflags1; + lim = lsflags1 + sizeof(lsflags1) - 2; + for (; *scp != '\0'; scp++) { + if (*scp == 'l') { + /* do not add the 'l' */ + command = "LIST"; + } else if (dcp < lim) { + if (dcp == lsflags1) + *dcp++ = '-'; + *dcp++ = *scp; + } + } + *dcp = '\0'; + } else { + (void) STRNCPY(lsflags1, lsflags); + } + } + + InitLineList(llines); + + result = FTPStartDataCmd( + cip, + kNetReading, + kTypeAscii, + (longest_int) 0, + "%s%s%s%s%s", + command, + (lsflags1[0] == '\0') ? "" : " ", + lsflags1, + (pattern[0] == '\0') ? "" : " ", + pattern + ); + +#ifdef NO_SIGNALS + + if (result == 0) { + if (InitSReadlineInfo(&lsSrl, cip->dataSocket, secondaryBuf, sizeof(secondaryBuf), (int) cip->xferTimeout, 1) < 0) { + /* Not really fdopen, but close in what we're trying to do. */ + result = kErrFdopenR; + cip->errNo = kErrFdopenR; + Error(cip, kDoPerror, "Could not fdopen.\n"); + return (result); + } + + for (;;) { + result = SReadline(&lsSrl, line, sizeof(line) - 1); + if (result == kTimeoutErr) { + /* timeout */ + Error(cip, kDontPerror, "Could not directory listing data -- timed out.\n"); + cip->errNo = kErrDataTimedOut; + return (cip->errNo); + } else if (result == 0) { + /* end of listing -- done */ + cip->numListings++; + break; + } else if (result < 0) { + /* error */ + Error(cip, kDoPerror, "Could not read directory listing data"); + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + break; + } + + if (line[result - 1] == '\n') + line[result - 1] = '\0'; + + if ((blankLines == 0) && (result <= 1)) + continue; + + /* Valid directory listing line of output */ + if ((line[0] == '.') && ((line[1] == '\0') || ((line[1] == '.') && ((line[2] == '\0') || (iscntrl(line[2])))))) + continue; /* Skip . and .. */ + + (void) AddLine(llines, line); + } + + DisposeSReadlineInfo(&lsSrl); + if (FTPEndDataCmd(cip, 1) < 0) { + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + } + } else if (result == kErrGeneric) { + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + } + + +#else /* NO_SIGNALS */ + vcip = cip; + osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenData); + + gGotBrokenData = 0; + gCanBrokenDataJmp = 0; + +#ifdef HAVE_SIGSETJMP + sj = sigsetjmp(gBrokenDataJmp, 1); +#else + sj = setjmp(gBrokenDataJmp); +#endif /* HAVE_SIGSETJMP */ + + if (sj != 0) { + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); + FTPShutdownHost(vcip); + vcip->errNo = kErrRemoteHostClosedConnection; + return(vcip->errNo); + } + gCanBrokenDataJmp = 1; + + if (result == 0) { + /* This line sets the buffer pointer so that the first thing + * BufferGets will do is reset and fill the buffer using + * real I/O. + */ + secBufPtr = secondaryBuf + sizeof(secondaryBuf); + secBufLimit = (char *) 0; + memset(secondaryBuf, 0, sizeof(secondaryBuf)); + + for (;;) { + memset(line, 0, sizeof(line)); + if (cip->xferTimeout > 0) + (void) alarm(cip->xferTimeout); + nread = BufferGets(line, sizeof(line), cip->dataSocket, secondaryBuf, &secBufPtr, &secBufLimit, sizeof(secondaryBuf)); + if (nread <= 0) { + if (nread < 0) + break; + if (blankLines != 0) + (void) AddLine(llines, line); + } else { + cip->bytesTransferred += (longest_int) nread; + + if ((line[0] == '.') && ((line[1] == '\0') || ((line[1] == '.') && ((line[2] == '\0') || (iscntrl(line[2])))))) + continue; /* Skip . and .. */ + + (void) AddLine(llines, line); + } + } + if (cip->xferTimeout > 0) + (void) alarm(0); + result = FTPEndDataCmd(cip, 1); + if (result < 0) { + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + } + result = kNoErr; + cip->numListings++; + } else if (result == kErrGeneric) { + result = kErrLISTFailed; + cip->errNo = kErrLISTFailed; + } + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif /* NO_SIGNALS */ + return (result); +} /* FTPListToMemory2 */ + + + + +static void +AutomaticallyUseASCIIModeDependingOnExtension(const FTPCIPtr cip, const char *const pathName, int *const xtype) +{ + if ((*xtype == kTypeBinary) && (cip->asciiFilenameExtensions != NULL)) { + if (FilenameExtensionIndicatesASCII(pathName, cip->asciiFilenameExtensions)) { + /* Matched -- send this file in ASCII mode + * instead of binary since it's extension + * appears to be that of a text file. + */ + *xtype = kTypeAscii; + } + } +} /* AutomaticallyUseASCIIModeDependingOnExtension */ + + + + +/* The purpose of this is to provide updates for the progress meters + * during lags. Return zero if the operation timed-out. + */ +static int +WaitForRemoteOutput(const FTPCIPtr cip) +{ + fd_set ss, ss2; + struct timeval tv; + int result; + int fd; + int wsecs; + int xferTimeout; + int ocancelXfer; + + xferTimeout = cip->xferTimeout; + if (xferTimeout < 1) + return (1); + + fd = cip->dataSocket; + if (fd < 0) + return (1); + + ocancelXfer = cip->cancelXfer; + wsecs = 0; + cip->stalled = 0; + + while ((xferTimeout <= 0) || (wsecs < xferTimeout)) { + if ((cip->cancelXfer != 0) && (ocancelXfer == 0)) { + /* leave cip->stalled -- could have been stalled and then canceled. */ + return (1); + } + FD_ZERO(&ss); + FD_SET(fd, &ss); + ss2 = ss; + tv.tv_sec = 1; + tv.tv_usec = 0; + result = select(fd + 1, NULL, SELECT_TYPE_ARG234 &ss, SELECT_TYPE_ARG234 &ss2, &tv); + if (result == 1) { + /* ready */ + cip->stalled = 0; + return (1); + } else if (result < 0) { + if (errno != EINTR) { + perror("select"); + cip->stalled = 0; + return (1); + } + } else { + wsecs++; + cip->stalled = wsecs; + } + FTPUpdateIOTimer(cip); + } + +#if !defined(NO_SIGNALS) + /* Shouldn't get here -- alarm() should have + * went off by now. + */ + (void) kill(getpid(), SIGALRM); +#endif /* NO_SIGNALS */ + + cip->dataTimedOut = 1; + return (0); /* timed-out */ +} /* WaitForRemoteOutput */ + + + + +static int +FTPPutOneF( + const FTPCIPtr cip, + const char *const file, + const char *volatile dstfile, + int xtype, + const int fdtouse, + const int appendflag, + const char *volatile tmppfx, + const char *volatile tmpsfx, + const int resumeflag, + const int deleteflag, + const ConfirmResumeUploadProc resumeProc) +{ + char *buf, *cp; + const char *cmd; + const char *odstfile; + size_t bufSize; + size_t l; + int tmpResult, result; + int nread, nwrote; + volatile int fd; + char dstfile2[512]; +#if ASCII_TRANSLATION + char *src, *srclim, *dst; + int ntowrite; + char inbuf[256]; +#endif + int fstatrc, statrc; + longest_int startPoint = 0; + struct Stat st; + time_t mdtm; +#if !defined(NO_SIGNALS) + int sj; + volatile FTPSigProc osigpipe; + volatile FTPCIPtr vcip; + volatile int vfd, vfdtouse; +#endif /* NO_SIGNALS */ + volatile int vzaction; + int zaction = kConfirmResumeProcSaidBestGuess; + + if (cip->buf == NULL) { + Error(cip, kDoPerror, "Transfer buffer not allocated.\n"); + cip->errNo = kErrNoBuf; + return (cip->errNo); + } + + cip->usingTAR = 0; + if (fdtouse < 0) { + fd = Open(file, O_RDONLY|O_BINARY, 0); + if (fd < 0) { + Error(cip, kDoPerror, "Cannot open local file %s for reading.\n", file); + cip->errNo = kErrOpenFailed; + return (cip->errNo); + } + } else { + fd = fdtouse; + } + + fstatrc = Fstat(fd, &st); + if ((fstatrc == 0) && (S_ISDIR(st.st_mode))) { + if (fdtouse < 0) { + (void) close(fd); + } + Error(cip, kDontPerror, "%s is a directory.\n", (file != NULL) ? file : "that"); + cip->errNo = kErrOpenFailed; + return (cip->errNo); + } + + /* For Put, we can't recover very well if it turns out restart + * didn't work, so check beforehand. + */ + if (cip->hasREST == kCommandAvailabilityUnknown) { + (void) FTPSetTransferType(cip, kTypeBinary); + if (SetStartOffset(cip, (longest_int) 1) == kNoErr) { + /* Now revert -- we still may not end up + * doing it. + */ + SetStartOffset(cip, (longest_int) -1); + } + } + + if (fdtouse < 0) { + AutomaticallyUseASCIIModeDependingOnExtension(cip, dstfile, &xtype); + (void) FTPFileSizeAndModificationTime(cip, dstfile, &startPoint, xtype, &mdtm); + + if (appendflag == kAppendYes) { + zaction = kConfirmResumeProcSaidAppend; + } else if ( + (cip->hasREST == kCommandNotAvailable) || + (xtype != kTypeBinary) || + (fstatrc < 0) + ) { + zaction = kConfirmResumeProcSaidOverwrite; + } else if (resumeflag == kResumeYes) { + zaction = kConfirmResumeProcSaidBestGuess; + } else { + zaction = kConfirmResumeProcSaidOverwrite; + } + + statrc = -1; + if ((mdtm != kModTimeUnknown) || (startPoint != kSizeUnknown)) { + /* Then we know the file exists. We will + * ask the user what to do, if possible, below. + */ + statrc = 0; + } else if ((resumeProc != NoConfirmResumeUploadProc) && (cip->hasMDTM != kCommandAvailable) && (cip->hasSIZE != kCommandAvailable)) { + /* We already checked if the file had a filesize + * or timestamp above, but if the server indicated + * it did not support querying those directly, + * we now need to try to determine if the file + * exists in a few other ways. + */ + statrc = FTPFileExists2(cip, dstfile, 0, 0, 0, 1, 1); + } + + if ( + (resumeProc != NoConfirmResumeUploadProc) && + (statrc == 0) + ) { + zaction = (*resumeProc)(file, (longest_int) st.st_size, st.st_mtime, &dstfile, startPoint, mdtm, &startPoint); + } + + if (zaction == kConfirmResumeProcSaidCancel) { + /* User wants to cancel this file and any + * remaining in batch. + */ + cip->errNo = kErrUserCanceled; + return (cip->errNo); + } + + if (zaction == kConfirmResumeProcSaidBestGuess) { + if ((mdtm != kModTimeUnknown) && (st.st_mtime > (mdtm + 1))) { + /* Local file is newer than remote, + * overwrite the remote file instead + * of trying to resume it. + * + * Note: Add one second fudge factor + * for Windows' file timestamps being + * imprecise to one second. + */ + zaction = kConfirmResumeProcSaidOverwrite; + } else if ((longest_int) st.st_size == startPoint) { + /* Already sent file, done. */ + zaction = kConfirmResumeProcSaidSkip; + } else if ((startPoint != kSizeUnknown) && ((longest_int) st.st_size > startPoint)) { + zaction = kConfirmResumeProcSaidResume; + } else { + zaction = kConfirmResumeProcSaidOverwrite; + } + } + + if (zaction == kConfirmResumeProcSaidSkip) { + /* Nothing done, but not an error. */ + if (fdtouse < 0) { + (void) close(fd); + } + if (deleteflag == kDeleteYes) { + if (unlink(file) < 0) { + cip->errNo = kErrLocalDeleteFailed; + return (cip->errNo); + } + } + return (kNoErr); + } else if (zaction == kConfirmResumeProcSaidResume) { + /* Resume; proc set the startPoint. */ + if ((longest_int) st.st_size == startPoint) { + /* Already sent file, done. */ + if (fdtouse < 0) { + (void) close(fd); + } + + if (deleteflag == kDeleteYes) { + if (unlink(file) < 0) { + cip->errNo = kErrLocalDeleteFailed; + return (cip->errNo); + } + } + return (kNoErr); + } else if (Lseek(fd, (off_t) startPoint, SEEK_SET) != (off_t) -1) { + cip->startPoint = startPoint; + } + } else if (zaction == kConfirmResumeProcSaidAppend) { + /* append: leave startPoint at zero, we will append everything. */ + cip->startPoint = startPoint = 0; + } else /* if (zaction == kConfirmResumeProcSaidOverwrite) */ { + /* overwrite: leave startPoint at zero */ + cip->startPoint = startPoint = 0; + } + } + + if ((cip->numUploads == 0) && (cip->dataSocketSBufSize > 0)) { + /* If dataSocketSBufSize is non-zero, it means you + * want to explicitly try to set the size of the + * socket's I/O buffer. + * + * If it is zero, it means you want to just use the + * TCP stack's default value, which is typically + * between 8 and 64 kB. + * + * If you try to set the buffer larger than 64 kB, + * the TCP stack should try to use RFC 1323 to + * negotiate "TCP Large Windows" which may yield + * significant performance gains. + */ + if (cip->hasSTORBUFSIZE == kCommandAvailable) + (void) FTPCmd(cip, "SITE STORBUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize); + else if (cip->hasSBUFSIZ == kCommandAvailable) + (void) FTPCmd(cip, "SITE SBUFSIZ %lu", (unsigned long) cip->dataSocketSBufSize); + else if (cip->hasSBUFSZ == kCommandAvailable) + (void) FTPCmd(cip, "SITE SBUFSZ %lu", (unsigned long) cip->dataSocketSBufSize); + /* At least one server implemenation has RBUFSZ but not + * SBUFSZ and instead uses RBUFSZ for both. + */ + else if ((cip->hasSBUFSZ != kCommandAvailable) && (cip->hasRBUFSZ == kCommandAvailable)) + (void) FTPCmd(cip, "SITE RBUFSZ %lu", (unsigned long) cip->dataSocketSBufSize); + else if (cip->hasBUFSIZE == kCommandAvailable) + (void) FTPCmd(cip, "SITE BUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize); + } + +#ifdef NO_SIGNALS + vzaction = zaction; +#else /* NO_SIGNALS */ + vcip = cip; + vfdtouse = fdtouse; + vfd = fd; + vzaction = zaction; + osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenData); + + gGotBrokenData = 0; + gCanBrokenDataJmp = 0; + +#ifdef HAVE_SIGSETJMP + sj = sigsetjmp(gBrokenDataJmp, 1); +#else + sj = setjmp(gBrokenDataJmp); +#endif /* HAVE_SIGSETJMP */ + + if (sj != 0) { + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); + if (vfdtouse < 0) { + (void) close(vfd); + } + FTPShutdownHost(vcip); + vcip->errNo = kErrRemoteHostClosedConnection; + return(vcip->errNo); + } + gCanBrokenDataJmp = 1; +#endif /* NO_SIGNALS */ + + if (vzaction == kConfirmResumeProcSaidAppend) { + cmd = "APPE"; + tmppfx = ""; /* Can't use that here. */ + tmpsfx = ""; + } else { + cmd = "STOR"; + if (tmppfx == NULL) + tmppfx = ""; + if (tmpsfx == NULL) + tmpsfx = ""; + } + + odstfile = dstfile; + if ((tmppfx[0] != '\0') || (tmpsfx[0] != '\0')) { + cp = strrchr(dstfile, '/'); + if (cp == NULL) + cp = strrchr(dstfile, '\\'); + if (cp == NULL) { + (void) STRNCPY(dstfile2, tmppfx); + (void) STRNCAT(dstfile2, dstfile); + (void) STRNCAT(dstfile2, tmpsfx); + } else { + cp++; + l = (size_t) (cp - dstfile); + (void) STRNCPY(dstfile2, dstfile); + dstfile2[l] = '\0'; /* Nuke stuff after / */ + (void) STRNCAT(dstfile2, tmppfx); + (void) STRNCAT(dstfile2, cp); + (void) STRNCAT(dstfile2, tmpsfx); + } + dstfile = dstfile2; + } + + tmpResult = FTPStartDataCmd( + cip, + kNetWriting, + xtype, + startPoint, + "%s %s", + cmd, + dstfile + ); + + if (tmpResult < 0) { + cip->errNo = tmpResult; + if (fdtouse < 0) { + (void) close(fd); + } +#if !defined(NO_SIGNALS) + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif /* NO_SIGNALS */ + return (cip->errNo); + } + + if ((startPoint != 0) && (cip->startPoint == 0)) { + /* Remote could not or would not set the start offset + * to what we wanted. + * + * So now we have to undo our seek. + */ + if (Lseek(fd, (off_t) 0, SEEK_SET) != (off_t) 0) { + cip->errNo = kErrLseekFailed; + if (fdtouse < 0) { + (void) close(fd); + } +#if !defined(NO_SIGNALS) + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif /* NO_SIGNALS */ + return (cip->errNo); + } + startPoint = 0; + } + + result = kNoErr; + buf = cip->buf; + bufSize = cip->bufSize; + + FTPInitIOTimer(cip); + if ((fstatrc == 0) && (S_ISREG(st.st_mode) != 0)) { + cip->expectedSize = (longest_int) st.st_size; + cip->mdtm = st.st_mtime; + } + cip->lname = file; /* could be NULL */ + cip->rname = odstfile; + if (fdtouse >= 0) + cip->useProgressMeter = 0; + FTPStartIOTimer(cip); + + /* Note: On Windows, we don't have to do anything special + * for ASCII mode, since Net ASCII's end-of-line sequence + * corresponds to the same thing used for DOS/Windows. + */ + +#if ASCII_TRANSLATION + if (xtype == kTypeAscii) { + /* ascii */ + for (;;) { +#if !defined(NO_SIGNALS) + gCanBrokenDataJmp = 0; +#endif /* NO_SIGNALS */ + nread = read(fd, inbuf, sizeof(inbuf)); + if (nread < 0) { + if (errno == EINTR) { + continue; + } else { + result = kErrReadFailed; + cip->errNo = kErrReadFailed; + Error(cip, kDoPerror, "Local read failed.\n"); + } + break; + } else if (nread == 0) { + break; + } + cip->bytesTransferred += (longest_int) nread; + +#if !defined(NO_SIGNALS) + gCanBrokenDataJmp = 1; +#endif /* NO_SIGNALS */ + src = inbuf; + srclim = src + nread; + dst = cip->buf; /* must be 2x sizeof inbuf or more. */ + while (src < srclim) { + if (*src == '\n') + *dst++ = '\r'; + *dst++ = *src++; + } + ntowrite = (size_t) (dst - cip->buf); + cp = cip->buf; + +#if !defined(NO_SIGNALS) + if (cip->xferTimeout > 0) + (void) alarm(cip->xferTimeout); +#endif /* NO_SIGNALS */ + do { + if (! WaitForRemoteOutput(cip)) { /* could set cancelXfer */ + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote write timed out.\n"); + goto brk; + } + if (cip->cancelXfer > 0) { + FTPAbortDataTransfer(cip); + result = cip->errNo = kErrDataTransferAborted; + goto brk; + } + +#ifdef NO_SIGNALS + nwrote = SWrite(cip->dataSocket, cp, (size_t) ntowrite, (int) cip->xferTimeout, kNoFirstSelect); + if (nwrote < 0) { + if (nwrote == kTimeoutErr) { + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote write timed out.\n"); + } else if ((gGotBrokenData != 0) || (errno == EPIPE)) { + cip->errNo = result = kErrSocketWriteFailed; + errno = EPIPE; + Error(cip, kDoPerror, "Lost data connection to remote host.\n"); + } else if (errno == EINTR) { + continue; + } else { + cip->errNo = result = kErrSocketWriteFailed; + Error(cip, kDoPerror, "Remote write failed.\n"); + } + (void) shutdown(cip->dataSocket, 2); + goto brk; + } +#else /* NO_SIGNALS */ + nwrote = write(cip->dataSocket, cp, ntowrite); + if (nwrote < 0) { + if ((gGotBrokenData != 0) || (errno == EPIPE)) { + cip->errNo = result = kErrSocketWriteFailed; + errno = EPIPE; + Error(cip, kDoPerror, "Lost data connection to remote host.\n"); + } else if (errno == EINTR) { + continue; + } else { + cip->errNo = result = kErrSocketWriteFailed; + Error(cip, kDoPerror, "Remote write failed.\n"); + } + (void) shutdown(cip->dataSocket, 2); + goto brk; + } +#endif /* NO_SIGNALS */ + cp += nwrote; + ntowrite -= nwrote; + } while (ntowrite > 0); + FTPUpdateIOTimer(cip); + } + } else +#endif /* ASCII_TRANSLATION */ + { + /* binary */ + for (;;) { +#if !defined(NO_SIGNALS) + gCanBrokenDataJmp = 0; +#endif /* NO_SIGNALS */ + cp = buf; + nread = read(fd, cp, bufSize); + if (nread < 0) { + if (errno == EINTR) { + continue; + } else { + result = kErrReadFailed; + cip->errNo = kErrReadFailed; + Error(cip, kDoPerror, "Local read failed.\n"); + } + break; + } else if (nread == 0) { + break; + } + cip->bytesTransferred += (longest_int) nread; + +#if !defined(NO_SIGNALS) + gCanBrokenDataJmp = 1; + if (cip->xferTimeout > 0) + (void) alarm(cip->xferTimeout); +#endif /* NO_SIGNALS */ + do { + if (! WaitForRemoteOutput(cip)) { /* could set cancelXfer */ + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote write timed out.\n"); + goto brk; + } + if (cip->cancelXfer > 0) { + FTPAbortDataTransfer(cip); + result = cip->errNo = kErrDataTransferAborted; + goto brk; + } + +#ifdef NO_SIGNALS + nwrote = SWrite(cip->dataSocket, cp, (size_t) nread, (int) cip->xferTimeout, kNoFirstSelect); + if (nwrote < 0) { + if (nwrote == kTimeoutErr) { + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote write timed out.\n"); + } else if ((gGotBrokenData != 0) || (errno == EPIPE)) { + cip->errNo = result = kErrSocketWriteFailed; + errno = EPIPE; + Error(cip, kDoPerror, "Lost data connection to remote host.\n"); + } else if (errno == EINTR) { + continue; + } else { + cip->errNo = result = kErrSocketWriteFailed; + Error(cip, kDoPerror, "Remote write failed.\n"); + } + (void) shutdown(cip->dataSocket, 2); + cip->dataSocket = -1; + goto brk; + } +#else /* NO_SIGNALS */ + nwrote = write(cip->dataSocket, cp, nread); + if (nwrote < 0) { + if ((gGotBrokenData != 0) || (errno == EPIPE)) { + cip->errNo = result = kErrSocketWriteFailed; + errno = EPIPE; + Error(cip, kDoPerror, "Lost data connection to remote host.\n"); + } else if (errno == EINTR) { + continue; + } else { + cip->errNo = result = kErrSocketWriteFailed; + Error(cip, kDoPerror, "Remote write failed.\n"); + } + (void) shutdown(cip->dataSocket, 2); + cip->dataSocket = -1; + goto brk; + } +#endif /* NO_SIGNALS */ + cp += nwrote; + nread -= nwrote; + } while (nread > 0); + FTPUpdateIOTimer(cip); + } + } +brk: + + if (fdtouse < 0) { + (void) Fstat(fd, &st); + } + + if (fdtouse < 0) { + if (shutdown(fd, 1) == 0) { + /* This looks very bizarre, since + * we will be checking the socket + * for readability here! + * + * The reason for this is that we + * want to be able to timeout a + * small put. So, we close the + * write end of the socket first, + * which tells the server we're + * done writing. We then wait + * for the server to close down + * the whole socket, which tells + * us that the file was completed. + */ + (void) WaitForRemoteInput(cip); /* Close could block. */ + } + } + +#if !defined(NO_SIGNALS) + gCanBrokenDataJmp = 0; + if (cip->xferTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + tmpResult = FTPEndDataCmd(cip, 1); + if ((tmpResult < 0) && (result == kNoErr)) { + cip->errNo = result = kErrSTORFailed; + } + FTPStopIOTimer(cip); + + if (fdtouse < 0) { + /* If they gave us a descriptor (fdtouse >= 0), + * leave it open, otherwise we opened it, so + * we need to dispose of it. + */ + (void) close(fd); + fd = -1; + } + + if (result == kNoErr) { + /* The store succeeded; If we were + * uploading to a temporary file, + * move the new file to the new name. + */ + cip->numUploads++; + + if ((tmppfx[0] != '\0') || (tmpsfx[0] != '\0')) { + if ((result = FTPRename(cip, dstfile, odstfile)) < 0) { + /* May fail if file was already there, + * so delete the old one so we can move + * over it. + */ + if (FTPDelete(cip, odstfile, kRecursiveNo, kGlobNo) == kNoErr) { + result = FTPRename(cip, dstfile, odstfile); + if (result < 0) { + Error(cip, kDontPerror, "Could not rename %s to %s: %s.\n", dstfile, odstfile, FTPStrError(cip->errNo)); + } + } else { + Error(cip, kDontPerror, "Could not delete old %s, so could not rename %s to that: %s\n", odstfile, dstfile, FTPStrError(cip->errNo)); + } + } + } + + if (FTPUtime(cip, odstfile, st.st_atime, st.st_mtime, st.st_ctime) != kNoErr) { + if (cip->errNo != kErrUTIMENotAvailable) + Error(cip, kDontPerror, "Could not preserve times for %s: %s.\n", odstfile, FTPStrError(cip->errNo)); + } + + if (deleteflag == kDeleteYes) { + if (unlink(file) < 0) { + result = cip->errNo = kErrLocalDeleteFailed; + } + } + } + +#if !defined(NO_SIGNALS) + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif /* NO_SIGNALS */ + return (result); +} /* FTPPutOneF */ + + + + +int +FTPPutOneFile3( + const FTPCIPtr cip, + const char *const file, + const char *const dstfile, + const int xtype, + const int fdtouse, + const int appendflag, + const char *const tmppfx, + const char *const tmpsfx, + const int resumeflag, + const int deleteflag, + const ConfirmResumeUploadProc resumeProc, + int UNUSED(reserved)) +{ + int result; + + LIBNCFTP_USE_VAR(reserved); + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((dstfile == NULL) || (dstfile[0] == '\0')) + return (kErrBadParameter); + if (fdtouse < 0) { + if ((file == NULL) || (file[0] == '\0')) + return (kErrBadParameter); + } + result = FTPPutOneF(cip, file, dstfile, xtype, fdtouse, appendflag, tmppfx, tmpsfx, resumeflag, deleteflag, resumeProc); + return (result); +} /* FTPPutOneFile3 */ + + + + +int +FTPPutFiles3( + const FTPCIPtr cip, + const char *const pattern, + const char *const dstdir1, + const int recurse, + const int doGlob, + const int xtype, + int appendflag, + const char *const tmppfx, + const char *const tmpsfx, + const int resumeflag, + const int deleteflag, + const ConfirmResumeUploadProc resumeProc, + int UNUSED(reserved)) +{ + LineList globList; + FileInfoList files; + FileInfoPtr filePtr; + int batchResult; + int result; + const char *dstdir; + char dstdir2[512]; + + LIBNCFTP_USE_VAR(reserved); + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (dstdir1 == NULL) { + dstdir = NULL; + } else { + dstdir = STRNCPY(dstdir2, dstdir1); + StrRemoveTrailingLocalPathDelim(dstdir2); + } + + (void) FTPLocalGlob(cip, &globList, pattern, doGlob); + if (recurse == kRecursiveYes) { + appendflag = kAppendNo; + (void) FTPLocalRecursiveFileList(cip, &globList, &files); + if (files.first == NULL) { + cip->errNo = kErrNoValidFilesSpecified; + return (kErrNoValidFilesSpecified); + } + (void) ComputeRNames(&files, dstdir, 0, 1); + } else { + (void) LineListToFileInfoList(&globList, &files); + (void) ComputeLNames(&files, NULL, NULL, 1); + (void) ComputeRNames(&files, dstdir, 0, 0); + } + DisposeLineListContents(&globList); + +#if 0 + for (filePtr = files.first; filePtr != NULL; filePtr = filePtr->next) { + PrintF(cip, " R=%s, L=%s, 2=%s, size=%d, mdtm=%u, type=%c\n", + filePtr->rname, + filePtr->lname, + filePtr->rlinkto ? filePtr->rlinkto : "", + filePtr->size, + (unsigned int) filePtr->mdtm, + filePtr->type + ); + } +#endif + + batchResult = kNoErr; + for (filePtr = files.first; filePtr != NULL; filePtr = filePtr->next) { + if (cip->connected == 0) { + if (batchResult == kNoErr) + batchResult = kErrRemoteHostClosedConnection; + break; + } + if (filePtr->type == 'd') { + /* mkdir */ + StrRemoveTrailingLocalPathDelim(filePtr->rname); + result = FTPMkdir(cip, filePtr->rname, kRecursiveNo); + if (result != kNoErr) + batchResult = result; +#ifdef HAVE_SYMLINK + } else if (filePtr->type == 'l') { + /* symlink */ + /* no RFC way to create the link, though. */ + if ((filePtr->rlinkto != NULL) && (filePtr->rlinkto[0] != '\0')) + (void) FTPSymlink(cip, filePtr->rname, filePtr->rlinkto); +#endif + } else if (recurse != kRecursiveYes) { + result = FTPPutOneF(cip, filePtr->lname, filePtr->rname, xtype, -1, appendflag, tmppfx, tmpsfx, resumeflag, deleteflag, resumeProc); + if (files.nFileInfos == 1) { + if (result != kNoErr) + batchResult = result; + } else { + if ((result != kNoErr) && (result != kErrLocalFileNewer) && (result != kErrRemoteFileNewer) && (result != kErrLocalSameAsRemote)) + batchResult = result; + } + if (result == kErrUserCanceled) + cip->cancelXfer = 1; + if (cip->cancelXfer > 0) + break; + } else { + result = FTPPutOneF(cip, filePtr->lname, filePtr->rname, xtype, -1, appendflag, tmppfx, tmpsfx, resumeflag, deleteflag, resumeProc); + if (files.nFileInfos == 1) { + if (result != kNoErr) + batchResult = result; + } else { + if ((result != kNoErr) && (result != kErrLocalFileNewer) && (result != kErrRemoteFileNewer) && (result != kErrLocalSameAsRemote)) + batchResult = result; + } + if (result == kErrUserCanceled) + cip->cancelXfer = 1; + if (cip->cancelXfer > 0) + break; + } + } + DisposeFileInfoListContents(&files); + if (batchResult < 0) + cip->errNo = batchResult; + return (batchResult); +} /* FTPPutFiles3 */ + + + + +/* The purpose of this is to provide updates for the progress meters + * during lags. Return zero if the operation timed-out. + */ +static int +WaitForRemoteInput(const FTPCIPtr cip) +{ + fd_set ss, ss2; + struct timeval tv; + int result; + int fd; + int wsecs; + int xferTimeout; + int ocancelXfer; + + xferTimeout = cip->xferTimeout; + if (xferTimeout < 1) + return (1); + + fd = cip->dataSocket; + if (fd < 0) + return (1); + + ocancelXfer = cip->cancelXfer; + wsecs = 0; + cip->stalled = 0; + + while ((xferTimeout <= 0) || (wsecs < xferTimeout)) { + if ((cip->cancelXfer != 0) && (ocancelXfer == 0)) { + /* leave cip->stalled -- could have been stalled and then canceled. */ + return (1); + } + FD_ZERO(&ss); + FD_SET(fd, &ss); + ss2 = ss; + tv.tv_sec = 1; + tv.tv_usec = 0; + result = select(fd + 1, SELECT_TYPE_ARG234 &ss, NULL, SELECT_TYPE_ARG234 &ss2, &tv); + if (result == 1) { + /* ready */ + cip->stalled = 0; + return (1); + } else if (result < 0) { + if (result != EINTR) { + perror("select"); + cip->stalled = 0; + return (1); + } + } else { + wsecs++; + cip->stalled = wsecs; + } + FTPUpdateIOTimer(cip); + } + +#if !defined(NO_SIGNALS) + /* Shouldn't get here -- alarm() should have + * went off by now. + */ + (void) kill(getpid(), SIGALRM); +#endif /* NO_SIGNALS */ + + cip->dataTimedOut = 1; + return (0); /* timed-out */ +} /* WaitForRemoteInput */ + + + + +/* Nice for UNIX, but not necessary otherwise. */ +#ifdef TAR + +static int +OpenTar(const FTPCIPtr cip, const char *const dstdir, int *const pid) +{ + int pipe1[2]; + int pid1; + int i; + char *argv[8]; + + *pid = -1; + + if (access(TAR, X_OK) < 0) { + /* Path to TAR is invalid. */ + return (-1); + } + + if (pipe(pipe1) < 0) { + Error(cip, kDoPerror, "pipe to Tar failed"); + return (-1); + } + + pid1 = (int) fork(); + if (pid1 < 0) { + (void) close(pipe1[0]); + (void) close(pipe1[1]); + return (-1); + } else if (pid1 == 0) { + /* Child */ + if ((dstdir != NULL) && (dstdir[0] != '\0') && (chdir(dstdir) < 0)) { + Error(cip, kDoPerror, "tar chdir to %s failed", dstdir); + exit(1); + } + (void) close(pipe1[1]); /* close write end */ + (void) dup2(pipe1[0], 0); /* use read end on stdin */ + (void) close(pipe1[0]); + + for (i=3; i<256; i++) + (void) close(i); + + argv[0] = (char *) "tar"; + argv[1] = (char *) "xpf"; + argv[2] = (char *) "-"; + argv[3] = NULL; + + (void) execv(TAR, argv); + exit(1); + } + + /* Parent */ + *pid = pid1; + + (void) close(pipe1[0]); /* close read end */ + return (pipe1[1]); /* use write end */ +} /* OpenTar */ + + + + +static int +FTPGetOneTarF(const FTPCIPtr cip, const char *file, const char *const dstdir) +{ + char *buf; + size_t bufSize; + int tmpResult; + volatile int result; + int nread, nwrote; + volatile int fd; + volatile int vfd; + const char *volatile vfile; +#ifndef NO_SIGNALS + int sj; + volatile FTPSigProc osigpipe; + volatile FTPCIPtr vcip; +#endif + int pid, status; + char savedCwd[512]; + char *volatile basecp; + + result = kNoErr; + cip->usingTAR = 0; + + if ((file[0] == '\0') || ((file[0] == '/') && (file[1] == '\0'))) { + /* It was "/" + * We can't do that, because "get /.tar" + * or "get .tar" does not work. + */ + result = kErrOpenFailed; + cip->errNo = kErrOpenFailed; + return (result); + } + + if (FTPCmd(cip, "MDTM %s.tar", file) == 2) { + /* Better not use this method since there is + * no way to tell if the server would use the + * existing .tar or do a new one on the fly. + */ + result = kErrOpenFailed; + cip->errNo = kErrOpenFailed; + return (result); + } + + basecp = strrchr(file, '/'); + if (basecp != NULL) + basecp = strrchr(file, '\\'); + if (basecp != NULL) { + /* Need to cd to the parent directory and get it + * from there. + */ + if (FTPGetCWD(cip, savedCwd, sizeof(savedCwd)) != 0) { + result = kErrOpenFailed; + cip->errNo = kErrOpenFailed; + return (result); + } + result = FTPChdir(cip, file); + if (result != kNoErr) { + return (result); + } + result = FTPChdir(cip, ".."); + if (result != kNoErr) { + (void) FTPChdir(cip, savedCwd); + return (result); + } + file = basecp + 1; + } + + fd = OpenTar(cip, dstdir, &pid); + if (fd < 0) { + result = kErrOpenFailed; + cip->errNo = kErrOpenFailed; + if (basecp != NULL) + (void) FTPChdir(cip, savedCwd); + return (result); + } + + vfd = fd; + vfile = file; + +#ifndef NO_SIGNALS + vcip = cip; + osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenData); + + gGotBrokenData = 0; + gCanBrokenDataJmp = 0; + +#ifdef HAVE_SIGSETJMP + sj = sigsetjmp(gBrokenDataJmp, 1); +#else + sj = setjmp(gBrokenDataJmp); +#endif /* HAVE_SIGSETJMP */ + + if (sj != 0) { + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); + FTPShutdownHost(vcip); + + (void) signal(SIGPIPE, SIG_IGN); + (void) close(vfd); + for (;;) { +#ifdef HAVE_WAITPID + if ((waitpid(pid, &status, 0) < 0) && (errno != EINTR)) + break; +#else + if ((wait(&status) < 0) && (errno != EINTR)) + break; +#endif + if (WIFEXITED(status) || WIFSIGNALED(status)) + break; /* done */ + } + if (basecp != NULL) + (void) FTPChdir(cip, savedCwd); + vcip->errNo = kErrRemoteHostClosedConnection; + return(vcip->errNo); + } + gCanBrokenDataJmp = 1; + +#endif /* NO_SIGNALS */ + + tmpResult = FTPStartDataCmd(cip, kNetReading, kTypeBinary, (longest_int) 0, "RETR %s.tar", vfile); + + if (tmpResult < 0) { + result = tmpResult; + if (result == kErrGeneric) + result = kErrRETRFailed; + cip->errNo = result; + +#ifndef NO_SIGNALS + (void) signal(SIGPIPE, SIG_IGN); +#endif + (void) close(vfd); + for (;;) { +#ifdef HAVE_WAITPID + if ((waitpid(pid, &status, 0) < 0) && (errno != EINTR)) + break; +#else + if ((wait(&status) < 0) && (errno != EINTR)) + break; +#endif + if (WIFEXITED(status) || WIFSIGNALED(status)) + break; /* done */ + } + +#ifndef NO_SIGNALS + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif + if (basecp != NULL) + (void) FTPChdir(cip, savedCwd); + return (result); + } + + cip->usingTAR = 1; + buf = cip->buf; + bufSize = cip->bufSize; + + FTPInitIOTimer(cip); + cip->lname = vfile; /* could be NULL */ + cip->rname = vfile; + FTPStartIOTimer(cip); + + /* Binary */ + for (;;) { + if (! WaitForRemoteInput(cip)) { /* could set cancelXfer */ + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote read timed out.\n"); + break; + } + if (cip->cancelXfer > 0) { + FTPAbortDataTransfer(cip); + result = cip->errNo = kErrDataTransferAborted; + break; + } +#if !defined(NO_SIGNALS) + gCanBrokenDataJmp = 1; + if (cip->xferTimeout > 0) + (void) alarm(cip->xferTimeout); +#endif /* NO_SIGNALS */ +#ifdef NO_SIGNALS + nread = SRead(cip->dataSocket, buf, bufSize, (int) cip->xferTimeout, kFullBufferNotRequired|kNoFirstSelect); + if (nread == kTimeoutErr) { + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote read timed out.\n"); + break; + } else if (nread < 0) { + if (errno == EINTR) + continue; + Error(cip, kDoPerror, "Remote read failed.\n"); + result = kErrSocketReadFailed; + cip->errNo = kErrSocketReadFailed; + break; + } else if (nread == 0) { + break; + } +#else + nread = read(cip->dataSocket, buf, bufSize); + if (nread < 0) { + if (errno == EINTR) + continue; + Error(cip, kDoPerror, "Remote read failed.\n"); + result = kErrSocketReadFailed; + cip->errNo = kErrSocketReadFailed; + break; + } else if (nread == 0) { + break; + } + gCanBrokenDataJmp = 0; +#endif + + nwrote = write(fd, buf, nread); + if (nwrote != nread) { + if ((gGotBrokenData != 0) || (errno == EPIPE)) { + result = kErrWriteFailed; + cip->errNo = kErrWriteFailed; + errno = EPIPE; + } else { + Error(cip, kDoPerror, "Local write failed.\n"); + result = kErrWriteFailed; + cip->errNo = kErrWriteFailed; + } + break; + } + cip->bytesTransferred += (longest_int) nread; + FTPUpdateIOTimer(cip); + } + +#if !defined(NO_SIGNALS) + if (cip->xferTimeout > 0) + (void) alarm(0); + gCanBrokenDataJmp = 0; +#endif /* NO_SIGNALS */ + + (void) close(fd); + for (;;) { +#ifdef HAVE_WAITPID + if ((waitpid(pid, &status, 0) < 0) && (errno != EINTR)) + break; +#else + if ((wait(&status) < 0) && (errno != EINTR)) + break; +#endif + if (WIFEXITED(status) || WIFSIGNALED(status)) + break; /* done */ + } + + tmpResult = FTPEndDataCmd(cip, 1); + if ((tmpResult < 0) && (result == 0)) { + result = kErrRETRFailed; + cip->errNo = kErrRETRFailed; + } + FTPStopIOTimer(cip); +#if !defined(NO_SIGNALS) + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif + + if ((result == 0) && (cip->bytesTransferred == 0)) { + result = kErrOpenFailed; + cip->errNo = kErrOpenFailed; + } + if (basecp != NULL) + (void) FTPChdir(cip, savedCwd); + return (result); +} /* FTPGetOneTarF */ + +#endif /* TAR */ + + + + + +static int +FTPGetOneF( + const FTPCIPtr cip, + const char *const file, + const char *dstfile, + int xtype, + const int fdtouse, + longest_int expectedSize, + time_t mdtm, + const int resumeflag, + const int appendflag, + const int deleteflag, + const ConfirmResumeDownloadProc resumeProc) +{ + char *buf; + size_t bufSize; + int tmpResult; + volatile int result; + int nread, nwrote; + volatile int fd; +#if ASCII_TRANSLATION + char *src, *srclim; + char *dst, *dstlim; + char outbuf[512]; +#endif + volatile longest_int startPoint = 0; + struct utimbuf ut; + struct Stat st; +#if !defined(NO_SIGNALS) + volatile FTPSigProc osigpipe; + volatile FTPCIPtr vcip; + volatile int vfd, vfdtouse; + int sj; +#endif /* NO_SIGNALS */ + volatile int created = 0; + int zaction = kConfirmResumeProcSaidBestGuess; + int statrc; + int noMdtmCheck; + time_t now; + + if (cip->buf == NULL) { + Error(cip, kDoPerror, "Transfer buffer not allocated.\n"); + cip->errNo = kErrNoBuf; + return (cip->errNo); + } + + result = kNoErr; + cip->usingTAR = 0; + + if (fdtouse < 0) { + /* Only ask for extended information + * if we have the name of the file + * and we didn't already have the + * info. + * + * Always ask for the modification time, + * because even if it was passed in it + * may not be accurate. This is often + * the case when it came from an ls + * listing, in which the local time + * zone could be a factor. + * + */ + + AutomaticallyUseASCIIModeDependingOnExtension(cip, file, &xtype); + if (expectedSize == kSizeUnknown) { + (void) FTPFileSizeAndModificationTime(cip, file, &expectedSize, xtype, &mdtm); + } else { + (void) FTPFileModificationTime(cip, file, &mdtm); + } + + /* For Get, we can't recover very well if it turns out restart + * didn't work, so check beforehand. + */ + if ((resumeflag == kResumeYes) || (resumeProc != NoConfirmResumeDownloadProc)) { + if (cip->hasREST == kCommandAvailabilityUnknown) { + (void) FTPSetTransferType(cip, kTypeBinary); + if (SetStartOffset(cip, (longest_int) 1) == kNoErr) { + /* Now revert -- we still may not end up + * doing it. + */ + SetStartOffset(cip, (longest_int) -1); + } + } + } + + if (appendflag == kAppendYes) { + zaction = kConfirmResumeProcSaidAppend; + } else if (cip->hasREST == kCommandNotAvailable) { + zaction = kConfirmResumeProcSaidOverwrite; + } else if (resumeflag == kResumeYes) { + zaction = kConfirmResumeProcSaidBestGuess; + } else { + zaction = kConfirmResumeProcSaidOverwrite; + } + + statrc = Stat(dstfile, &st); + if (statrc == 0) { + if (resumeProc != NULL) { + zaction = (*resumeProc)( + &dstfile, + (longest_int) st.st_size, + st.st_mtime, + file, + expectedSize, + mdtm, + &startPoint + ); + } + + if (zaction == kConfirmResumeProcSaidBestGuess) { + if (expectedSize != kSizeUnknown) { + /* We know the size of the remote file, + * and we have a local file too. + * + * Try and decide if we need to get + * the entire file, or just part of it. + */ + + startPoint = (longest_int) st.st_size; + zaction = kConfirmResumeProcSaidResume; + + /* If the local file exists and has a recent + * modification time (< 12 hours) and + * the remote file's modtime is not recent, + * then heuristically conclude that the + * local modtime should not be trusted + * (i.e. user killed the process before + * the local modtime could be preserved). + */ + noMdtmCheck = 0; + if (mdtm != kModTimeUnknown) { + time(&now); + if ((st.st_mtime > now) || (((now - st.st_mtime) < 46200) && ((now - mdtm) >= 46200))) + noMdtmCheck = 1; + } + + if ((mdtm == kModTimeUnknown) || (noMdtmCheck != 0)) { + /* Can't use the timestamps as an aid. */ + if (startPoint == expectedSize) { + /* Don't go to all the trouble of downloading nothing. */ + cip->errNo = kErrLocalSameAsRemote; + if (deleteflag == kDeleteYes) + (void) FTPDelete(cip, file, kRecursiveNo, kGlobNo); + return (cip->errNo); + } else if (startPoint > expectedSize) { + /* Panic; odds are the file we have + * was a different file altogether, + * since it is larger than the + * remote copy. Re-do it all. + */ + zaction = kConfirmResumeProcSaidOverwrite; + } /* else resume at startPoint */ + } else if ((mdtm == st.st_mtime) || (mdtm == (st.st_mtime - 1)) || (mdtm == (st.st_mtime + 1))) { + /* File has the same time. + * Note: Windows' file timestamps can be off by one second! + */ + if (startPoint == expectedSize) { + /* Don't go to all the trouble of downloading nothing. */ + cip->errNo = kErrLocalSameAsRemote; + if (deleteflag == kDeleteYes) + (void) FTPDelete(cip, file, kRecursiveNo, kGlobNo); + return (cip->errNo); + } else if (startPoint > expectedSize) { + /* Panic; odds are the file we have + * was a different file altogether, + * since it is larger than the + * remote copy. Re-do it all. + */ + zaction = kConfirmResumeProcSaidOverwrite; + } else { + /* We have a file by the same time, + * but smaller start point. Leave + * the startpoint as is since it + * is most likely valid. + */ + } + } else if (mdtm < st.st_mtime) { + /* Remote file is older than + * local file. Don't overwrite + * our file. + */ + cip->errNo = kErrLocalFileNewer; + return (cip->errNo); + } else /* if (mdtm > st.st_mtime) */ { + /* File has a newer timestamp + * altogether, assume the remote + * file is an entirely new file + * and replace ours with it. + */ + zaction = kConfirmResumeProcSaidOverwrite; + } + } else { + zaction = kConfirmResumeProcSaidOverwrite; + } + } + } else { + zaction = kConfirmResumeProcSaidOverwrite; + } + + if (zaction == kConfirmResumeProcSaidCancel) { + /* User wants to cancel this file and any + * remaining in batch. + */ + cip->errNo = kErrUserCanceled; + return (cip->errNo); + } else if (zaction == kConfirmResumeProcSaidSkip) { + /* Nothing done, but not an error. */ + if (deleteflag == kDeleteYes) + (void) FTPDelete(cip, file, kRecursiveNo, kGlobNo); + return (kNoErr); + } else if (zaction == kConfirmResumeProcSaidResume) { + /* Resume; proc set the startPoint. */ + if (startPoint == expectedSize) { + /* Don't go to all the trouble of downloading nothing. */ + /* Nothing done, but not an error. */ + if (deleteflag == kDeleteYes) + (void) FTPDelete(cip, file, kRecursiveNo, kGlobNo); + return (kNoErr); + } else if (startPoint > expectedSize) { + /* Cannot set start point past end of remote file */ + cip->errNo = result = kErrSetStartPoint; + return (result); + } + fd = Open(dstfile, O_WRONLY|O_APPEND|O_BINARY, 00666); + } else if (zaction == kConfirmResumeProcSaidAppend) { + /* leave startPoint at zero, we will append everything. */ + startPoint = (longest_int) 0; + fd = Open(dstfile, O_WRONLY|O_CREAT|O_APPEND|O_BINARY, 00666); + } else /* if (zaction == kConfirmResumeProcSaidOverwrite) */ { + created = 1; + startPoint = (longest_int) 0; + fd = Open(dstfile, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 00666); + } + + if (fd < 0) { + Error(cip, kDoPerror, "Cannot open local file %s for writing.\n", dstfile); + result = kErrOpenFailed; + cip->errNo = kErrOpenFailed; + return (result); + } + + if ((expectedSize == (longest_int) 0) && (startPoint <= (longest_int) 0) && (zaction != kConfirmResumeProcSaidOverwrite)) { + /* Don't go to all the trouble of downloading nothing. */ +#if defined(WIN32) || defined(_WINDOWS) + /* Note: Windows doesn't allow zero-size files. */ + (void) write(fd, "\r\n", 2); +#endif + (void) close(fd); + if (mdtm != kModTimeUnknown) { + cip->mdtm = mdtm; + (void) time(&ut.actime); + ut.modtime = mdtm; + (void) utime(dstfile, &ut); + } + if (deleteflag == kDeleteYes) + (void) FTPDelete(cip, file, kRecursiveNo, kGlobNo); + return (kNoErr); + } + } else { + fd = fdtouse; + } + + if ((cip->numDownloads == 0) && (cip->dataSocketRBufSize > 0)) { + /* If dataSocketSBufSize is non-zero, it means you + * want to explicitly try to set the size of the + * socket's I/O buffer. + * + * If it is zero, it means you want to just use the + * TCP stack's default value, which is typically + * between 8 and 64 kB. + * + * If you try to set the buffer larger than 64 kB, + * the TCP stack should try to use RFC 1323 to + * negotiate "TCP Large Windows" which may yield + * significant performance gains. + */ + if (cip->hasRETRBUFSIZE == kCommandAvailable) + (void) FTPCmd(cip, "SITE RETRBUFSIZE %lu", (unsigned long) cip->dataSocketRBufSize); + else if (cip->hasRBUFSIZ == kCommandAvailable) + (void) FTPCmd(cip, "SITE RBUFSIZ %lu", (unsigned long) cip->dataSocketRBufSize); + else if (cip->hasRBUFSZ == kCommandAvailable) + (void) FTPCmd(cip, "SITE RBUFSZ %lu", (unsigned long) cip->dataSocketRBufSize); + else if (cip->hasBUFSIZE == kCommandAvailable) + (void) FTPCmd(cip, "SITE BUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize); + } + +#ifdef NO_SIGNALS +#else /* NO_SIGNALS */ + vcip = cip; + vfdtouse = fdtouse; + vfd = fd; + osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenData); + + gGotBrokenData = 0; + gCanBrokenDataJmp = 0; + +#ifdef HAVE_SIGSETJMP + sj = sigsetjmp(gBrokenDataJmp, 1); +#else + sj = setjmp(gBrokenDataJmp); +#endif /* HAVE_SIGSETJMP */ + + if (sj != 0) { + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); + if (vfdtouse < 0) { + (void) close(vfd); + } + FTPShutdownHost(vcip); + vcip->errNo = kErrRemoteHostClosedConnection; + return(vcip->errNo); + } + gCanBrokenDataJmp = 1; +#endif /* NO_SIGNALS */ + + tmpResult = FTPStartDataCmd(cip, kNetReading, xtype, startPoint, "RETR %s", file); + + if (tmpResult < 0) { + result = tmpResult; + if (result == kErrGeneric) + result = kErrRETRFailed; + cip->errNo = result; + if (fdtouse < 0) { + (void) close(fd); + if ((created != 0) && (appendflag == kAppendNo) && (cip->startPoint == 0)) + (void) unlink(dstfile); + } +#if !defined(NO_SIGNALS) + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif /* NO_SIGNALS */ + return (result); + } + + if ((startPoint != 0) && (cip->startPoint == 0)) { + /* Remote could not or would not set the start offset + * to what we wanted. + * + * So now we have to undo our seek. + */ + if (Lseek(fd, (off_t) 0, SEEK_SET) != (off_t) 0) { + cip->errNo = kErrLseekFailed; + if (fdtouse < 0) { + (void) close(fd); + } +#if !defined(NO_SIGNALS) + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif /* NO_SIGNALS */ + return (cip->errNo); + } + startPoint = 0; + } + + buf = cip->buf; + bufSize = cip->bufSize; + + FTPInitIOTimer(cip); + cip->mdtm = mdtm; + (void) time(&ut.actime); + ut.modtime = mdtm; + cip->expectedSize = expectedSize; + cip->lname = dstfile; /* could be NULL */ + cip->rname = file; + if (fdtouse >= 0) + cip->useProgressMeter = 0; + FTPStartIOTimer(cip); + +#if ASCII_TRANSLATION + if (xtype == kTypeAscii) { + /* Ascii */ + for (;;) { + if (! WaitForRemoteInput(cip)) { /* could set cancelXfer */ + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote read timed out.\n"); + break; + } + if (cip->cancelXfer > 0) { + FTPAbortDataTransfer(cip); + result = cip->errNo = kErrDataTransferAborted; + break; + } +#ifdef TESTING_ABOR + if (cip->bytesTransferred > 0) { + cip->cancelXfer = 1; + FTPAbortDataTransfer(cip); + result = cip->errNo = kErrDataTransferAborted; + break; + } +#endif /* TESTING_ABOR */ +#ifdef NO_SIGNALS + nread = SRead(cip->dataSocket, buf, bufSize, (int) cip->xferTimeout, kFullBufferNotRequired|kNoFirstSelect); + if (nread == kTimeoutErr) { + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote read timed out.\n"); + break; + } else if (nread < 0) { + if ((gGotBrokenData != 0) || (errno == EPIPE)) { + result = cip->errNo = kErrSocketReadFailed; + errno = EPIPE; + Error(cip, kDoPerror, "Lost data connection to remote host.\n"); + } else if (errno == EINTR) { + continue; + } else { + Error(cip, kDoPerror, "Remote read failed.\n"); + result = kErrSocketReadFailed; + cip->errNo = kErrSocketReadFailed; + } + break; + } else if (nread == 0) { + break; + } +#else + gCanBrokenDataJmp = 1; + if (cip->xferTimeout > 0) + (void) alarm(cip->xferTimeout); + nread = read(cip->dataSocket, buf, bufSize); + if (nread < 0) { + if ((gGotBrokenData != 0) || (errno == EPIPE)) { + result = cip->errNo = kErrSocketReadFailed; + errno = EPIPE; + Error(cip, kDoPerror, "Lost data connection to remote host.\n"); + (void) shutdown(cip->dataSocket, 2); + } else if (errno == EINTR) { + continue; + } else { + result = cip->errNo = kErrSocketReadFailed; + Error(cip, kDoPerror, "Remote read failed.\n"); + (void) shutdown(cip->dataSocket, 2); + } + break; + } else if (nread == 0) { + break; + } + + gCanBrokenDataJmp = 0; +#endif /* NO_SIGNALS */ + + src = buf; + srclim = src + nread; + dst = outbuf; + dstlim = dst + sizeof(outbuf); + while (src < srclim) { + if (*src == '\r') { + src++; + continue; + } + if (dst >= dstlim) { + nwrote = write(fd, outbuf, (size_t) (dst - outbuf)); + if (nwrote == (int) (dst - outbuf)) { + /* Success. */ + dst = outbuf; + } else if ((gGotBrokenData != 0) || (errno == EPIPE)) { + result = kErrWriteFailed; + cip->errNo = kErrWriteFailed; + errno = EPIPE; + (void) shutdown(cip->dataSocket, 2); + goto brk; + } else { + Error(cip, kDoPerror, "Local write failed.\n"); + result = kErrWriteFailed; + cip->errNo = kErrWriteFailed; + (void) shutdown(cip->dataSocket, 2); + goto brk; + } + } + *dst++ = *src++; + } + if (dst > outbuf) { + nwrote = write(fd, outbuf, (size_t) (dst - outbuf)); + if (nwrote != (int) (dst - outbuf)) { + if ((gGotBrokenData != 0) || (errno == EPIPE)) { + result = kErrWriteFailed; + cip->errNo = kErrWriteFailed; + errno = EPIPE; + (void) shutdown(cip->dataSocket, 2); + goto brk; + } else { + Error(cip, kDoPerror, "Local write failed.\n"); + result = kErrWriteFailed; + cip->errNo = kErrWriteFailed; + (void) shutdown(cip->dataSocket, 2); + goto brk; + } + } + } + + if (mdtm != kModTimeUnknown) { + (void) utime(dstfile, &ut); + } + cip->bytesTransferred += (longest_int) nread; + FTPUpdateIOTimer(cip); + } + } else +#endif /* ASCII_TRANSLATION */ + { + /* Binary */ + for (;;) { + if (! WaitForRemoteInput(cip)) { /* could set cancelXfer */ + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote read timed out.\n"); + break; + } + if (cip->cancelXfer > 0) { + FTPAbortDataTransfer(cip); + result = cip->errNo = kErrDataTransferAborted; + break; + } +#ifdef TESTING_ABOR + if (cip->bytesTransferred > 0) { + cip->cancelXfer = 1; + FTPAbortDataTransfer(cip); + result = cip->errNo = kErrDataTransferAborted; + break; + } +#endif /* TESTING_ABOR */ +#ifdef NO_SIGNALS + nread = SRead(cip->dataSocket, buf, bufSize, (int) cip->xferTimeout, kFullBufferNotRequired|kNoFirstSelect); + if (nread == kTimeoutErr) { + cip->errNo = result = kErrDataTimedOut; + Error(cip, kDontPerror, "Remote read timed out.\n"); + break; + } else if (nread < 0) { + if ((gGotBrokenData != 0) || (errno == EPIPE)) { + result = cip->errNo = kErrSocketReadFailed; + errno = EPIPE; + Error(cip, kDoPerror, "Lost data connection to remote host.\n"); + } else if (errno == EINTR) { + continue; + } else { + Error(cip, kDoPerror, "Remote read failed.\n"); + result = kErrSocketReadFailed; + cip->errNo = kErrSocketReadFailed; + } + break; + } else if (nread == 0) { + break; + } +#else + gCanBrokenDataJmp = 1; + if (cip->xferTimeout > 0) + (void) alarm(cip->xferTimeout); + nread = read(cip->dataSocket, buf, bufSize); + if (nread < 0) { + if ((gGotBrokenData != 0) || (errno == EPIPE)) { + result = cip->errNo = kErrSocketReadFailed; + errno = EPIPE; + Error(cip, kDoPerror, "Lost data connection to remote host.\n"); + } else if (errno == EINTR) { + continue; + } else { + result = cip->errNo = kErrSocketReadFailed; + Error(cip, kDoPerror, "Remote read failed.\n"); + } + (void) shutdown(cip->dataSocket, 2); + break; + } else if (nread == 0) { + break; + } + gCanBrokenDataJmp = 0; +#endif /* NO_SIGNALS */ + + nwrote = write(fd, buf, nread); + if (nwrote != nread) { + if ((gGotBrokenData != 0) || (errno == EPIPE)) { + result = kErrWriteFailed; + cip->errNo = kErrWriteFailed; + errno = EPIPE; + } else { + Error(cip, kDoPerror, "Local write failed.\n"); + result = kErrWriteFailed; + cip->errNo = kErrWriteFailed; + } + (void) shutdown(cip->dataSocket, 2); + break; + } + + /* Ugggh... do this after each write operation + * so it minimizes the chance of a user killing + * the process before we reset the timestamps. + */ + if (mdtm != kModTimeUnknown) { + (void) utime(dstfile, &ut); + } + cip->bytesTransferred += (longest_int) nread; + FTPUpdateIOTimer(cip); + } + } + +#if ASCII_TRANSLATION +brk: +#endif + +#if !defined(NO_SIGNALS) + if (cip->xferTimeout > 0) + (void) alarm(0); + gCanBrokenDataJmp = 0; +#endif /* NO_SIGNALS */ + + if (fdtouse < 0) { + /* If they gave us a descriptor (fdtouse >= 0), + * leave it open, otherwise we opened it, so + * we need to close it. + */ + (void) close(fd); + fd = -1; + } + + tmpResult = FTPEndDataCmd(cip, 1); + if ((tmpResult < 0) && (result == 0)) { + result = kErrRETRFailed; + cip->errNo = kErrRETRFailed; + } + FTPStopIOTimer(cip); +#if !defined(NO_SIGNALS) + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif /* NO_SIGNALS */ + + if ((mdtm != kModTimeUnknown) && (cip->bytesTransferred > 0)) { + (void) utime(dstfile, &ut); + } + + if (result == kNoErr) { + cip->numDownloads++; + + if (deleteflag == kDeleteYes) { + result = FTPDelete(cip, file, kRecursiveNo, kGlobNo); + } + } + + return (result); +} /* FTPGetOneF */ + + + + +int +FTPGetOneFile3( + const FTPCIPtr cip, + const char *const file, + const char *const dstfile, + const int xtype, + const int fdtouse, + const int resumeflag, + const int appendflag, + const int deleteflag, + const ConfirmResumeDownloadProc resumeProc, + int UNUSED(reserved)) +{ + int result; + + LIBNCFTP_USE_VAR(reserved); + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if ((file == NULL) || (file[0] == '\0')) + return (kErrBadParameter); + if (fdtouse < 0) { + if ((dstfile == NULL) || (dstfile[0] == '\0')) + return (kErrBadParameter); + } + + result = FTPGetOneF(cip, file, dstfile, xtype, fdtouse, kSizeUnknown, kModTimeUnknown, resumeflag, appendflag, deleteflag, resumeProc); + return (result); +} /* FTPGetOneFile3 */ + + + + +int +FTPGetFiles3( + const FTPCIPtr cip, + const char *pattern1, + const char *const dstdir1, + const int recurse, + int doGlob, + const int xtype, + const int resumeflag, + int appendflag, + const int deleteflag, + const int tarflag, + const ConfirmResumeDownloadProc resumeProc, + int UNUSED(reserved)) +{ + LineList globList; + LinePtr itemPtr; + FileInfoList files; + FileInfoPtr filePtr; + int batchResult; + int result; + char *ldir; + char *cp; + const char *dstdir; + const char *pattern; + char *pattern2, *dstdir2; + char c; + int recurse1; + int errRc; + + LIBNCFTP_USE_VAR(reserved); + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + if (pattern1 == NULL) + return (kErrBadParameter); + + dstdir2 = NULL; + pattern2 = NULL; + + if (dstdir1 == NULL) { + dstdir = NULL; + } else { + dstdir2 = StrDup(dstdir1); + if (dstdir2 == NULL) { + errRc = kErrMallocFailed; + goto return_err; + } + StrRemoveTrailingLocalPathDelim(dstdir2); + dstdir = dstdir2; + } + + pattern2 = StrDup(pattern1); + if (pattern2 == NULL) { + errRc = kErrMallocFailed; + goto return_err; + } + StrRemoveTrailingSlashes(pattern2); + pattern = pattern2; + + if (pattern[0] == '\0') { + if (recurse == kRecursiveNo) { + errRc = kErrBadParameter; + goto return_err; + } + pattern = "."; + doGlob = kGlobNo; + } else if (strcmp(pattern, ".") == 0) { + if (recurse == kRecursiveNo) { + errRc = kErrBadParameter; + goto return_err; + } + doGlob = kGlobNo; + } + if (recurse == kRecursiveYes) + appendflag = kAppendNo; + + batchResult = FTPRemoteGlob(cip, &globList, pattern, doGlob); + if (batchResult != kNoErr) { + errRc = batchResult; + goto return_err; + } + + cip->cancelXfer = 0; /* should already be zero */ + + for (itemPtr = globList.first; itemPtr != NULL; itemPtr = itemPtr->next) { + if ((recurse == kRecursiveYes) && (FTPIsDir(cip, itemPtr->line) > 0)) { +#ifdef TAR + if ((tarflag == kTarYes) && (xtype == kTypeBinary) && (appendflag == kAppendNo) && (deleteflag == kDeleteNo) && (FTPGetOneTarF(cip, itemPtr->line, dstdir) == kNoErr)) { + /* Great! */ + continue; + } +#endif /* TAR */ + (void) FTPRemoteRecursiveFileList1(cip, itemPtr->line, &files); + (void) ComputeLNames(&files, itemPtr->line, dstdir, 1); + recurse1 = recurse; + } else { + recurse1 = kRecursiveNo; + (void) LineToFileInfoList(itemPtr, &files); + (void) ComputeRNames(&files, ".", 0, 1); + (void) ComputeLNames(&files, NULL, dstdir, 0); + } + if (cip->cancelXfer > 0) { + DisposeFileInfoListContents(&files); + break; + } + +#if 0 + for (filePtr = files.first; filePtr != NULL; filePtr = filePtr->next) { + PrintF(cip, " R=%s, L=%s, 2=%s, size=%d, mdtm=%u, type=%c\n", + filePtr->rname, + filePtr->lname, + filePtr->rlinkto ? filePtr->rlinkto : "", + filePtr->size, + (unsigned int) filePtr->mdtm, + filePtr->type + ); + } +#endif + + + for (filePtr = files.first; filePtr != NULL; filePtr = filePtr->next) { + if (cip->connected == 0) { + if (batchResult == kNoErr) + batchResult = kErrRemoteHostClosedConnection; + break; + } + if (filePtr->type == 'd') { +#if defined(WIN32) || defined(_WINDOWS) + (void) MkDirs(filePtr->lname, 00777); +#else + (void) mkdir(filePtr->lname, 00777); +#endif + } else if (filePtr->type == 'l') { + /* skip it -- we do that next pass. */ + } else if (recurse1 != kRecursiveYes) { + result = FTPGetOneF(cip, filePtr->rname, filePtr->lname, xtype, -1, filePtr->size, filePtr->mdtm, resumeflag, appendflag, deleteflag, resumeProc); + if (files.nFileInfos == 1) { + if (result != kNoErr) + batchResult = result; + } else { + if ((result != kNoErr) && (result != kErrLocalFileNewer) && (result != kErrRemoteFileNewer) && (result != kErrLocalSameAsRemote)) + batchResult = result; + } + if (result == kErrUserCanceled) + cip->cancelXfer = 1; + if (cip->cancelXfer > 0) + break; + } else { + ldir = filePtr->lname; + cp = StrRFindLocalPathDelim(ldir); + if (cp != NULL) { + while (cp > ldir) { + if (! IsLocalPathDelim(*cp)) { + ++cp; + break; + } + --cp; + } + if (cp > ldir) { + c = *cp; + *cp = '\0'; + if (MkDirs(ldir, 00777) < 0) { + Error(cip, kDoPerror, "Could not create local directory \"%s\"\n", ldir); + batchResult = kErrGeneric; + *cp = c; + continue; + } + *cp = c; + } + } + result = FTPGetOneF(cip, filePtr->rname, filePtr->lname, xtype, -1, filePtr->size, filePtr->mdtm, resumeflag, appendflag, deleteflag, resumeProc); + + if (files.nFileInfos == 1) { + if (result != kNoErr) + batchResult = result; + } else { + if ((result != kNoErr) && (result != kErrLocalFileNewer) && (result != kErrRemoteFileNewer) && (result != kErrLocalSameAsRemote)) + batchResult = result; + } + if (result == kErrUserCanceled) + cip->cancelXfer = 1; + if (cip->cancelXfer > 0) + break; + } + } + if (cip->cancelXfer > 0) { + DisposeFileInfoListContents(&files); + break; + } + +#ifdef HAVE_SYMLINK + for (filePtr = files.first; filePtr != NULL; filePtr = filePtr->next) { + if (filePtr->type == 'l') { + (void) unlink(filePtr->lname); + if (symlink(filePtr->rlinkto, filePtr->lname) < 0) { + Error(cip, kDoPerror, "Could not symlink %s to %s\n", filePtr->rlinkto, filePtr->lname); + /* Note: not worth setting batchResult */ + } + } + } +#endif /* HAVE_SYMLINK */ + + + DisposeFileInfoListContents(&files); + } + + DisposeLineListContents(&globList); + if (batchResult < 0) + cip->errNo = batchResult; + errRc = batchResult; + +return_err: + if (dstdir2 != NULL) + free(dstdir2); + if (pattern2 != NULL) + free(pattern2); + return (errRc); +} /* FTPGetFiles3 */ + + + + +/*------------------------- wrappers for old routines ----------------------*/ + +int +FTPGetOneFile(const FTPCIPtr cip, const char *const file, const char *const dstfile) +{ + return (FTPGetOneFile3(cip, file, dstfile, kTypeBinary, -1, kResumeNo, kAppendNo, kDeleteNo, (ConfirmResumeDownloadProc) 0, 0)); +} /* FTPGetOneFile */ + + + + +int +FTPGetOneFile2(const FTPCIPtr cip, const char *const file, const char *const dstfile, const int xtype, const int fdtouse, const int resumeflag, const int appendflag) +{ + return (FTPGetOneFile3(cip, file, dstfile, xtype, fdtouse, resumeflag, appendflag, kDeleteNo, (ConfirmResumeDownloadProc) 0, 0)); +} /* FTPGetOneFile2 */ + + + + +int +FTPGetFiles(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob) +{ + return (FTPGetFiles3(cip, pattern, dstdir, recurse, doGlob, kTypeBinary, kResumeNo, kAppendNo, kDeleteNo, kTarYes, (ConfirmResumeDownloadProc) 0, 0)); +} /* FTPGetFiles */ + + + + +int +FTPGetFiles2(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob, const int xtype, const int resumeflag, const int appendflag) +{ + return (FTPGetFiles3(cip, pattern, dstdir, recurse, doGlob, xtype, resumeflag, appendflag, kDeleteNo, kTarYes, (ConfirmResumeDownloadProc) 0, 0)); +} /* FTPGetFiles2 */ + + + + +int +FTPGetOneFileAscii(const FTPCIPtr cip, const char *const file, const char *const dstfile) +{ + return (FTPGetOneFile3(cip, file, dstfile, kTypeAscii, -1, kResumeNo, kAppendNo, kDeleteNo, (ConfirmResumeDownloadProc) 0, 0)); +} /* FTPGetOneFileAscii */ + + + + +int +FTPGetFilesAscii(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob) +{ + return (FTPGetFiles3(cip, pattern, dstdir, recurse, doGlob, kTypeAscii, kResumeNo, kAppendNo, kDeleteNo, kTarNo, (ConfirmResumeDownloadProc) 0, 0)); +} /* FTPGetFilesAscii */ + + + + +int +FTPPutOneFile(const FTPCIPtr cip, const char *const file, const char *const dstfile) +{ + return (FTPPutOneFile3(cip, file, dstfile, kTypeBinary, -1, 0, NULL, NULL, kResumeNo, kDeleteNo, NoConfirmResumeUploadProc, 0)); +} /* FTPPutOneFile */ + + + + +int +FTPPutOneFile2(const FTPCIPtr cip, const char *const file, const char *const dstfile, const int xtype, const int fdtouse, const int appendflag, const char *const tmppfx, const char *const tmpsfx) +{ + return (FTPPutOneFile3(cip, file, dstfile, xtype, fdtouse, appendflag, tmppfx, tmpsfx, kResumeNo, kDeleteNo, NoConfirmResumeUploadProc, 0)); +} /* FTPPutOneFile2 */ + + + + +int +FTPPutFiles(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob) +{ + return (FTPPutFiles3(cip, pattern, dstdir, recurse, doGlob, kTypeBinary, 0, NULL, NULL, kResumeNo, kDeleteNo, NoConfirmResumeUploadProc, 0)); +} /* FTPPutFiles */ + + + + +int +FTPPutFiles2(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob, const int xtype, const int appendflag, const char *const tmppfx, const char *const tmpsfx) +{ + return (FTPPutFiles3(cip, pattern, dstdir, recurse, doGlob, xtype, appendflag, tmppfx, tmpsfx, kResumeNo, kDeleteNo, NoConfirmResumeUploadProc, 0)); +} /* FTPPutFiles2 */ + + + + +int +FTPPutOneFileAscii(const FTPCIPtr cip, const char *const file, const char *const dstfile) +{ + return (FTPPutOneFile3(cip, file, dstfile, kTypeAscii, -1, 0, NULL, NULL, kResumeNo, kDeleteNo, NoConfirmResumeUploadProc, 0)); +} /* FTPPutOneFileAscii */ + + + + +int +FTPPutFilesAscii(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob) +{ + return (FTPPutFiles3(cip, pattern, dstdir, recurse, doGlob, kTypeAscii, 0, NULL, NULL, kResumeNo, kDeleteNo, NoConfirmResumeUploadProc, 0)); +} /* FTPPutFilesAscii */ + + + +int +FTPListToMemory(const FTPCIPtr cip, const char *const pattern, const LineListPtr llines, const char *const lsflags) +{ + return (FTPListToMemory2(cip, pattern, llines, lsflags, 1, (int *) 0)); +} /* FTPListToMemory */ + +/* eof IO.c */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/libncftp.dsp b/modules/rosapps/applications/net/ncftp/libncftp/libncftp.dsp new file mode 100644 index 00000000000..0b2bcf18fb9 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/libncftp.dsp @@ -0,0 +1,160 @@ +# Microsoft Developer Studio Project File - Name="libncftp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libncftp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libncftp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libncftp.mak" CFG="libncftp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libncftp - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libncftp - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libncftp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W4 /GX /O2 /Ob1 /I "..\Strn" /I "..\sio" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libncftp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\Strn" /I "..\sio" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "libncftp - Win32 Release" +# Name "libncftp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\cmds.c +# End Source File +# Begin Source File + +SOURCE=.\errno.c +# End Source File +# Begin Source File + +SOURCE=.\ftp.c +# End Source File +# Begin Source File + +SOURCE=.\glob.c +# End Source File +# Begin Source File + +SOURCE=.\io.c +# End Source File +# Begin Source File + +SOURCE=.\linelist.c +# End Source File +# Begin Source File + +SOURCE=.\mksrczip.bat +# End Source File +# Begin Source File + +SOURCE=.\open.c +# End Source File +# Begin Source File + +SOURCE=.\rcmd.c +# End Source File +# Begin Source File + +SOURCE=.\util.c +# End Source File +# Begin Source File + +SOURCE=.\util2.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\ftp.h +# End Source File +# Begin Source File + +SOURCE=.\ncftp.h +# End Source File +# Begin Source File + +SOURCE=.\ncftp_errno.h +# End Source File +# Begin Source File + +SOURCE=.\syshdrs.h +# End Source File +# Begin Source File + +SOURCE=.\util.h +# End Source File +# Begin Source File + +SOURCE=.\wincfg.h +# End Source File +# End Group +# End Target +# End Project diff --git a/modules/rosapps/applications/net/ncftp/libncftp/libncftp.dsw b/modules/rosapps/applications/net/ncftp/libncftp/libncftp.dsw new file mode 100644 index 00000000000..d02da5713cb --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/libncftp.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "libncftp"=.\libncftp.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/modules/rosapps/applications/net/ncftp/libncftp/linelist.c b/modules/rosapps/applications/net/ncftp/libncftp/linelist.c new file mode 100644 index 00000000000..a6e109208e8 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/linelist.c @@ -0,0 +1,783 @@ +/* linelist.c + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#include "syshdrs.h" + +/* Dynamically make a copy of a string. */ +char * +StrDup(const char *buf) +{ + char *cp; + size_t len; + + if (buf == NULL) + return (NULL); + + len = strlen(buf) + 1; + cp = (char *) malloc(len); + if (cp != NULL) + (void) memcpy(cp, buf, len); + return (cp); +} /* StrDup */ + + + +/* Disposes each node of a LineList. Does a few extra things + * so the disposed memory won't be very useful after it is freed. + */ +void +DisposeLineListContents(LineListPtr list) +{ + LinePtr lp, lp2; + + for (lp = list->first; lp != NULL; ) { + lp2 = lp; + lp = lp->next; + if (lp2->line != NULL) { + lp2->line[0] = '\0'; + free(lp2->line); + } + free(lp2); + } + /* Same as InitLineList. */ + (void) memset(list, 0, sizeof(LineList)); +} /* DisposeLineListContents */ + + + + +void +InitLineList(LineListPtr list) +{ + (void) memset(list, 0, sizeof(LineList)); +} /* InitLineList */ + + + + +LinePtr +RemoveLine(LineListPtr list, LinePtr killMe) +{ + LinePtr nextLine, prevLine; + + nextLine = killMe->next; + prevLine = killMe->prev; + if (killMe->line != NULL) { + killMe->line[0] = '\0'; /* Make it useless just in case. */ + free(killMe->line); + } + + if (list->first == killMe) + list->first = nextLine; + if (list->last == killMe) + list->last = prevLine; + + if (nextLine != NULL) + nextLine->prev = prevLine; + if (prevLine != NULL) + prevLine->next = nextLine; + + free(killMe); + list->nLines--; + return (nextLine); +} /* RemoveLine */ + + + + +/* Adds a string to the LineList specified. */ +LinePtr +AddLine(LineListPtr list, const char *buf1) +{ + LinePtr lp; + char *buf; + + lp = (LinePtr) malloc(sizeof(Line)); + if (lp != NULL) { + buf = StrDup(buf1); + if (buf == NULL) { + free(lp); + lp = NULL; + } else { + lp->line = buf; + lp->next = NULL; + if (list->first == NULL) { + list->first = list->last = lp; + lp->prev = NULL; + list->nLines = 1; + } else { + lp->prev = list->last; + list->last->next = lp; + list->last = lp; + list->nLines++; + } + } + } + return lp; +} /* AddLine */ + + + + +int +CopyLineList(LineListPtr dst, LineListPtr src) +{ + LinePtr lp, lp2; + + InitLineList(dst); + for (lp = src->first; lp != NULL; ) { + lp2 = lp; + lp = lp->next; + if (lp2->line != NULL) { + if (AddLine(dst, lp2->line) == NULL) { + DisposeLineListContents(dst); + return (-1); + } + } + } + return (0); +} /* CopyLineList */ + + + + +/* Disposes each node of a FileInfoList. Does a few extra things + * so the disposed memory won't be very useful after it is freed. + */ +void +DisposeFileInfoListContents(FileInfoListPtr list) +{ + FileInfoPtr lp, lp2; + + for (lp = list->first; lp != NULL; ) { + lp2 = lp; + lp = lp->next; + if (lp2->relname != NULL) { + lp2->relname[0] = '\0'; + free(lp2->relname); + } + if (lp2->lname != NULL) { + lp2->lname[0] = '\0'; + free(lp2->lname); + } + if (lp2->rname != NULL) { + lp2->rname[0] = '\0'; + free(lp2->rname); + } + if (lp2->rlinkto != NULL) { + lp2->rlinkto[0] = '\0'; + free(lp2->rlinkto); + } + if (lp2->plug != NULL) { + lp2->plug[0] = '\0'; + free(lp2->plug); + } + free(lp2); + } + + if (list->vec != NULL) + free(list->vec); + + /* Same as InitFileInfoList. */ + (void) memset(list, 0, sizeof(FileInfoList)); +} /* DisposeFileInfoListContents */ + + + + +void +InitFileInfoList(FileInfoListPtr list) +{ + (void) memset(list, 0, sizeof(FileInfoList)); +} /* InitFileInfoList */ + + + + +static int +TimeCmp(const void *a, const void *b) +{ + FileInfoPtr *fipa, *fipb; + + fipa = (FileInfoPtr *) a; + fipb = (FileInfoPtr *) b; + if ((**fipb).mdtm == (**fipa).mdtm) + return (0); + else if ((**fipb).mdtm < (**fipa).mdtm) + return (-1); + return (1); +} /* TimeCmp */ + + + + +static int +ReverseTimeCmp(const void *a, const void *b) +{ + FileInfoPtr *fipa, *fipb; + + fipa = (FileInfoPtr *) a; + fipb = (FileInfoPtr *) b; + if ((**fipa).mdtm == (**fipb).mdtm) + return (0); + else if ((**fipa).mdtm < (**fipb).mdtm) + return (-1); + return (1); +} /* ReverseTimeCmp */ + + + + +static int +SizeCmp(const void *a, const void *b) +{ + FileInfoPtr *fipa, *fipb; + + fipa = (FileInfoPtr *) a; + fipb = (FileInfoPtr *) b; + if ((**fipb).size == (**fipa).size) + return (0); + else if ((**fipb).size < (**fipa).size) + return (-1); + return (1); +} /* SizeCmp */ + + + + +static int +ReverseSizeCmp(const void *a, const void *b) +{ + FileInfoPtr *fipa, *fipb; + + fipa = (FileInfoPtr *) a; + fipb = (FileInfoPtr *) b; + if ((**fipa).size == (**fipb).size) + return (0); + else if ((**fipa).size < (**fipb).size) + return (-1); + return (1); +} /* ReverseSizeCmp */ + + + + +static int +ReverseNameCmp(const void *a, const void *b) +{ + FileInfoPtr *fipa, *fipb; + + fipa = (FileInfoPtr *) a; + fipb = (FileInfoPtr *) b; +#ifdef HAVE_SETLOCALE + return (strcoll((**fipb).relname, (**fipa).relname)); +#else + return (strcmp((**fipb).relname, (**fipa).relname)); +#endif +} /* ReverseNameCmp */ + + + + +static int +NameCmp(const void *a, const void *b) +{ + FileInfoPtr *fipa, *fipb; + + fipa = (FileInfoPtr *) a; + fipb = (FileInfoPtr *) b; +#ifdef HAVE_SETLOCALE + return (strcoll((**fipa).relname, (**fipb).relname)); +#else + return (strcmp((**fipa).relname, (**fipb).relname)); +#endif +} /* NameCmp */ + + + + +static int +BreadthFirstCmp(const void *a, const void *b) +{ + FileInfoPtr *fipa, *fipb; + char *cp, *cpa, *cpb; + int depth, deptha, depthb; + int c; + + fipa = (FileInfoPtr *) a; + fipb = (FileInfoPtr *) b; + + cpa = (**fipa).relname; + cpb = (**fipb).relname; + + for (cp = cpa, depth = 0;;) { + c = *cp++; + if (c == '\0') + break; + if ((c == '/') || (c == '\\')) { + depth++; + } + } + deptha = depth; + + for (cp = cpb, depth = 0;;) { + c = *cp++; + if (c == '\0') + break; + if ((c == '/') || (c == '\\')) { + depth++; + } + } + depthb = depth; + + if (deptha < depthb) + return (-1); + else if (deptha > depthb) + return (1); + +#ifdef HAVE_SETLOCALE + return (strcoll(cpa, cpb)); +#else + return (strcmp(cpa, cpb)); +#endif +} /* BreadthFirstCmp */ + + + + +void +SortFileInfoList(FileInfoListPtr list, int sortKey, int sortOrder) +{ + FileInfoVec fiv; + FileInfoPtr fip; + int i, j, n, n2; + + fiv = list->vec; + if (fiv == NULL) + return; + + if (list->sortKey == sortKey) { + if (list->sortOrder == sortOrder) + return; /* Already sorted they you want. */ + + /* Reverse the sort. */ + n = list->nFileInfos; + if (n > 1) { + n2 = n / 2; + for (i=0; isortOrder = sortOrder; + } else if ((sortKey == 'n') && (sortOrder == 'a')) { + qsort(fiv, (size_t) list->nFileInfos, sizeof(FileInfoPtr), + NameCmp); + list->sortKey = sortKey; + list->sortOrder = sortOrder; + } else if ((sortKey == 'n') && (sortOrder == 'd')) { + qsort(fiv, (size_t) list->nFileInfos, sizeof(FileInfoPtr), + ReverseNameCmp); + list->sortKey = sortKey; + list->sortOrder = sortOrder; + } else if ((sortKey == 't') && (sortOrder == 'a')) { + qsort(fiv, (size_t) list->nFileInfos, sizeof(FileInfoPtr), + TimeCmp); + list->sortKey = sortKey; + list->sortOrder = sortOrder; + } else if ((sortKey == 't') && (sortOrder == 'd')) { + qsort(fiv, (size_t) list->nFileInfos, sizeof(FileInfoPtr), + ReverseTimeCmp); + list->sortKey = sortKey; + list->sortOrder = sortOrder; + } else if ((sortKey == 's') && (sortOrder == 'a')) { + qsort(fiv, (size_t) list->nFileInfos, sizeof(FileInfoPtr), + SizeCmp); + list->sortKey = sortKey; + list->sortOrder = sortOrder; + } else if ((sortKey == 's') && (sortOrder == 'd')) { + qsort(fiv, (size_t) list->nFileInfos, sizeof(FileInfoPtr), + ReverseSizeCmp); + list->sortKey = sortKey; + list->sortOrder = sortOrder; + } else if (sortKey == 'b') { + /* This is different from the rest. */ + list->sortKey = sortKey; + list->sortOrder = sortOrder; + qsort(fiv, (size_t) list->nFileInfos, sizeof(FileInfoPtr), + BreadthFirstCmp); + } +} /* SortFileInfoList */ + + + + +void +VectorizeFileInfoList(FileInfoListPtr list) +{ + FileInfoVec fiv; + FileInfoPtr fip; + int i; + + fiv = (FileInfoVec) calloc((size_t) (list->nFileInfos + 1), sizeof(FileInfoPtr)); + if (fiv != (FileInfoVec) 0) { + for (i = 0, fip = list->first; fip != NULL; fip = fip->next, i++) + fiv[i] = fip; + list->vec = fiv; + } +} /* VectorizeFileInfoList */ + + + + +void +UnvectorizeFileInfoList(FileInfoListPtr list) +{ + FileInfoVec fiv; + FileInfoPtr fip; + int i, n; + + fiv = list->vec; + if (fiv != (FileInfoVec) 0) { + list->first = fiv[0]; + n = list->nFileInfos; + if (n > 0) { + list->last = fiv[n - 1]; + fip = fiv[0]; + fip->prev = NULL; + fip->next = fiv[1]; + for (i = 1; i < n; i++) { + fip = fiv[i]; + fip->prev = fiv[i - 1]; + fip->next = fiv[i + 1]; + } + } + free(fiv); + list->vec = (FileInfoVec) 0; + } +} /* UnvectorizeFileInfoList */ + + + + +void +InitFileInfo(FileInfoPtr fip) +{ + (void) memset(fip, 0, sizeof(FileInfo)); + fip->type = '-'; + fip->size = kSizeUnknown; + fip->mdtm = kModTimeUnknown; +} /* InitFileInfoList */ + + + + +FileInfoPtr +RemoveFileInfo(FileInfoListPtr list, FileInfoPtr killMe) +{ + FileInfoPtr nextFileInfo, prevFileInfo; + + nextFileInfo = killMe->next; + prevFileInfo = killMe->prev; + if (killMe->lname != NULL) { + killMe->lname[0] = '\0'; /* Make it useless just in case. */ + free(killMe->lname); + } + if (killMe->relname != NULL) { + killMe->relname[0] = '\0'; + free(killMe->relname); + } + if (killMe->rname != NULL) { + killMe->rname[0] = '\0'; + free(killMe->rname); + } + if (killMe->rlinkto != NULL) { + killMe->rlinkto[0] = '\0'; + free(killMe->rlinkto); + } + if (killMe->plug != NULL) { + killMe->plug[0] = '\0'; + free(killMe->plug); + } + + if (list->first == killMe) + list->first = nextFileInfo; + if (list->last == killMe) + list->last = prevFileInfo; + + if (nextFileInfo != NULL) + nextFileInfo->prev = prevFileInfo; + if (prevFileInfo != NULL) + prevFileInfo->next = nextFileInfo; + + free(killMe); + list->nFileInfos--; + return (nextFileInfo); +} /* RemoveFileInfo */ + + + + +/* Adds a string to the FileInfoList specified. */ +FileInfoPtr +AddFileInfo(FileInfoListPtr list, FileInfoPtr src) +{ + FileInfoPtr lp; + + lp = (FileInfoPtr) malloc(sizeof(FileInfo)); + if (lp != NULL) { + (void) memcpy(lp, src, sizeof(FileInfo)); + lp->next = NULL; + if (list->first == NULL) { + list->first = list->last = lp; + lp->prev = NULL; + list->nFileInfos = 1; + } else { + lp->prev = list->last; + list->last->next = lp; + list->last = lp; + list->nFileInfos++; + } + } + return lp; +} /* AddFileInfo */ + + + + +int +ConcatFileInfoList(FileInfoListPtr dst, FileInfoListPtr src) +{ + FileInfoPtr lp, lp2; + FileInfo newfi; + + for (lp = src->first; lp != NULL; lp = lp2) { + lp2 = lp->next; + newfi = *lp; + newfi.relname = StrDup(lp->relname); + newfi.lname = StrDup(lp->lname); + newfi.rname = StrDup(lp->rname); + newfi.rlinkto = StrDup(lp->rlinkto); + newfi.plug = StrDup(lp->plug); + if (AddFileInfo(dst, &newfi) == NULL) + return (-1); + } + return (0); +} /* ConcatFileInfoList */ + + + + +int +ComputeRNames(FileInfoListPtr dst, const char *dstdir, int pflag, int nochop) +{ + FileInfoPtr lp, lp2; + char *buf; + char *cp; + + if (dstdir == NULL) + dstdir = "."; + + for (lp = dst->first; lp != NULL; lp = lp2) { + lp2 = lp->next; + + buf = NULL; + if (nochop != 0) { + if ((dstdir[0] != '\0') && (strcmp(dstdir, "."))) { + if (Dynscat(&buf, dstdir, "/", lp->relname, 0) == NULL) + goto memerr; + + if (pflag != 0) { + /* Init lname to parent dir name of remote dir */ + cp = strrchr(dstdir, '/'); + if (cp == NULL) + cp = strrchr(dstdir, '\\'); + if (cp != NULL) { + if (Dynscat(&lp->lname, cp + 1, 0) == NULL) + goto memerr; + TVFSPathToLocalPath(lp->lname); + } + } + } else { + if (Dynscat(&buf, lp->relname, 0) == NULL) + goto memerr; + } + } else { + if ((dstdir[0] != '\0') && (strcmp(dstdir, "."))) { + cp = strrchr(lp->relname, '/'); + if (cp == NULL) + cp = strrchr(lp->relname, '\\'); + if (cp != NULL) { + cp++; + } else { + cp = lp->relname; + } + if (Dynscat(&buf, dstdir, "/", cp, 0) == NULL) + goto memerr; + + if (pflag != 0) { + /* Init lname to parent dir name of remote dir */ + cp = strrchr(dstdir, '/'); + if (cp == NULL) + cp = strrchr(dstdir, '\\'); + if (cp != NULL) { + if (Dynscat(&lp->lname, cp + 1, 0) == NULL) + goto memerr; + TVFSPathToLocalPath(lp->lname); + } + } + } else { + cp = strrchr(lp->relname, '/'); + if (cp == NULL) + cp = strrchr(lp->relname, '\\'); + if (cp != NULL) { + cp++; + } else { + cp = lp->relname; + } + if (Dynscat(&buf, cp, 0) == NULL) + goto memerr; + } + } + lp->rname = buf; + if (lp->rname == NULL) { +memerr: + return (-1); + } + LocalPathToTVFSPath(lp->rname); + } + return (0); +} /* ComputeRNames */ + + + + +int +ComputeLNames(FileInfoListPtr dst, const char *srcdir, const char *dstdir, int nochop) +{ + FileInfoPtr lp, lp2; + char *buf; + char *cp; + + if (srcdir != NULL) { + cp = strrchr(srcdir, '/'); + if (cp == NULL) + cp = strrchr(srcdir, '\\'); + if (cp != NULL) + srcdir = cp + 1; + } + if (dstdir == NULL) + dstdir = "."; + + for (lp = dst->first; lp != NULL; lp = lp2) { + lp2 = lp->next; + + buf = NULL; + if (nochop != 0) { + if ((dstdir[0] != '\0') && (strcmp(dstdir, "."))) { + if (Dynscat(&buf, dstdir, "/", 0) == NULL) + goto memerr; + } + if (lp->lname != NULL) { + if (Dynscat(&buf, lp->lname, "/", 0) == NULL) + goto memerr; + } else if (srcdir != NULL) { + if (Dynscat(&buf, srcdir, "/", 0) == NULL) + goto memerr; + } + if (Dynscat(&buf, lp->relname, 0) == NULL) + goto memerr; + } else { + if ((dstdir[0] != '\0') && (strcmp(dstdir, "."))) { + cp = strrchr(lp->relname, '/'); + if (cp == NULL) + cp = strrchr(lp->relname, '\\'); + if (cp == NULL) { + cp = lp->relname; + } else { + cp++; + } + if (Dynscat(&buf, dstdir, "/", cp, 0) == NULL) + goto memerr; + } else { + cp = strrchr(lp->relname, '/'); + if (cp == NULL) + cp = strrchr(lp->relname, '\\'); + if (cp == NULL) { + cp = lp->relname; + } else { + cp++; + } + if (Dynscat(&buf, cp, 0) == NULL) + goto memerr; + } + } + if (buf == NULL) { +memerr: + return (-1); + } + if (lp->lname != NULL) { + free(lp->lname); + lp->lname = NULL; + } + lp->lname = buf; + TVFSPathToLocalPath(lp->lname); + } + return (0); +} /* ComputeLNames */ + + + + +int +ConcatFileToFileInfoList(FileInfoListPtr dst, char *rfile) +{ + FileInfo newfi; + + InitFileInfo(&newfi); /* Use defaults. */ + newfi.relname = StrDup(rfile); + newfi.rname = NULL; + newfi.lname = NULL; + + if (AddFileInfo(dst, &newfi) == NULL) + return (-1); + return (0); +} /* ConcatFileToFileInfoList */ + + + + +int +LineListToFileInfoList(LineListPtr src, FileInfoListPtr dst) +{ + LinePtr lp, lp2; + + InitFileInfoList(dst); + for (lp = src->first; lp != NULL; lp = lp2) { + lp2 = lp->next; + if (ConcatFileToFileInfoList(dst, lp->line) < 0) + return (-1); + } + return (0); +} /* LineListToFileList */ + + + + +int +LineToFileInfoList(LinePtr lp, FileInfoListPtr dst) +{ + InitFileInfoList(dst); + if (ConcatFileToFileInfoList(dst, lp->line) < 0) + return (-1); + return (0); +} /* LineToFileInfoList */ + +/* eof */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/mksrctar.sh b/modules/rosapps/applications/net/ncftp/libncftp/mksrctar.sh new file mode 100644 index 00000000000..4d3f36db151 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/mksrctar.sh @@ -0,0 +1,97 @@ +#!/bin/sh + +if [ -f rcmd.c ] ; then + cd .. +fi +wd=`pwd` +for f in libncftp sio Strn doc ; do + if [ ! -f "$f" ] && [ ! -d "$f" ] ; then + echo "Missing directory $f ?" 1>&2 + exit 1 + fi +done + +( cd libncftp ; make clean ) + +TMPDIR=/tmp +if [ "$#" -lt 2 ] ; then + TARDIR="libncftp" + STGZFILE="$TARDIR.tar.gz" +else + TARDIR="$1" + STGZFILE="$2" +fi + +rm -rf $TMPDIR/TAR +mkdir -p -m755 $TMPDIR/TAR/$TARDIR 2>/dev/null + +chmod 755 configure sh/* install-sh 2>/dev/null + +find . -depth -follow -type f | sed ' +/sio\/configure$/d +/Strn\/configure$/d +/\.o$/d +/\.so$/d +/\.a$/d +/\.lib$/d +/\.ncb$/d +/\.pdb$/d +/\.idb$/d +/\.pch$/d +/\.ilk$/d +/\.res$/d +/\.aps$/d +/\.opt$/d +/\.plg$/d +/\.obj$/d +/\.exe$/d +/\.zip$/d +/\.gz$/d +/\.tgz$/d +/\.tar$/d +/\.swp$/d +/\.orig$/d +/\.rej$/d +/\/Makefile\.bin$/p +/\.bin$/d +/\/bin/d +/\/core$/d +/\/^[Rr]elease$/d +/\/^[Dd]ebug$/d +/\/sio\/.*\//d +/shit/d +/\/upload/d +/\/config\.h\.in$/p +/\/config\./d +/\/Makefile$/d +/\/OLD/d +/\/old/d' | cut -c3- | tee "$wd/doc/manifest.txt" | cpio -Lpdm $TMPDIR/TAR/$TARDIR + +( cd "$TMPDIR/TAR/$TARDIR" ; ln -s doc/README.txt README ) + +x=`tar --help 2>&1 | sed -n 's/.*owner=NAME.*/owner=NAME/g;/owner=NAME/p'` +case "$x" in + *owner=NAME*) + TARFLAGS="-c --owner=bin --group=bin --verbose -f" + TAR=tar + ;; + *) + TARFLAGS="cvf" + TAR=tar + x2=`gtar --help 2>&1 | sed -n 's/.*owner=NAME.*/owner=NAME/g;/owner=NAME/p'` + case "$x2" in + *owner=NAME*) + TARFLAGS="-c --owner=bin --group=bin --verbose -f" + TAR=gtar + ;; + esac + ;; +esac + +( cd $TMPDIR/TAR ; $TAR $TARFLAGS - $TARDIR | gzip -c > $STGZFILE ) +cp $TMPDIR/TAR/$STGZFILE . +chmod 644 $STGZFILE +rm -rf $TMPDIR/TAR +ls -l $STGZFILE 2>/dev/null +mv $TGZFILE newbin/ 2>/dev/null +exit 0 diff --git a/modules/rosapps/applications/net/ncftp/libncftp/mksrczip.bat b/modules/rosapps/applications/net/ncftp/libncftp/mksrczip.bat new file mode 100644 index 00000000000..2d73d39d6c0 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/mksrczip.bat @@ -0,0 +1,19 @@ +@echo off + +IF NOT EXIST ncftp.h GOTO ERR: + +cd .. +erase \temp\libncftp.zip >NUL +pkzip25.exe -add -204 -dir=current -excl=*.lib -excl=*.exe -excl=*.zip -excl=*.gz -excl=*.tar -excl=*.o -excl=*.obj -excl=*.pch -excl=*.ilk -excl=*.ncb -excl=*.opt -excl=*.pdb -excl=*.idb -excl=*.plg -excl=config.* -excl=*.so -excl=*.a -excl=Makefile -excl=core \temp\libncftp.zip libncftp\*.* +pkzip25.exe -add -204 -dir=current -excl=*.lib -excl=*.exe -excl=*.zip -excl=*.gz -excl=*.tar -excl=*.o -excl=*.obj -excl=*.pch -excl=*.ilk -excl=*.ncb -excl=*.opt -excl=*.pdb -excl=*.idb -excl=*.plg -excl=config.* -excl=*.so -excl=*.a -excl=Makefile -excl=core \temp\libncftp.zip sio\*.* +pkzip25.exe -add -204 -dir=current -excl=*.lib -excl=*.exe -excl=*.zip -excl=*.gz -excl=*.tar -excl=*.o -excl=*.obj -excl=*.pch -excl=*.ilk -excl=*.ncb -excl=*.opt -excl=*.pdb -excl=*.idb -excl=*.plg -excl=config.* -excl=*.so -excl=*.a -excl=Makefile -excl=core \temp\libncftp.zip Strn\*.* + +cd libncftp +dir \temp\libncftp.zip + +GOTO DONE: + +:ERR +echo Please cd to the source directory and then run this script. + +:DONE \ No newline at end of file diff --git a/modules/rosapps/applications/net/ncftp/libncftp/ncftp.h b/modules/rosapps/applications/net/ncftp/libncftp/ncftp.h new file mode 100644 index 00000000000..28b2e208720 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/ncftp.h @@ -0,0 +1,691 @@ +/* ncftp.h + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#ifndef _ncftp_h_ +#define _ncftp_h_ 1 + +#define kLibraryVersion "@(#) LibNcFTP 3.0.6 (April 14, 2001)" + +#if defined(WIN32) || defined(_WINDOWS) +# define longest_int LONGLONG +# define longest_uint ULONGLONG +# ifndef HAVE_LONG_LONG +# define HAVE_LONG_LONG 1 +# endif +# ifndef SCANF_LONG_LONG +# define SCANF_LONG_LONG "%I64d" +# endif +# ifndef PRINTF_LONG_LONG +# define PRINTF_LONG_LONG "%I64d" +# endif +# ifndef PRINTF_LONG_LONG_I64D +# define PRINTF_LONG_LONG_I64D 1 +# endif +# ifndef SCANF_LONG_LONG_I64D +# define SCANF_LONG_LONG_I64D 1 +# endif +# ifndef USE_SIO +# define USE_SIO 1 +# endif +# ifndef NO_SIGNALS +# define NO_SIGNALS 1 +# endif +#else +# include +# include +# if !defined(__ultrix) || !defined(XTI) +# include +# endif +# include +# if 1 /* %config1% -- set by configure script -- do not modify */ +# ifndef USE_SIO +# define USE_SIO 1 +# endif +# ifndef NO_SIGNALS +# define NO_SIGNALS 1 +# endif +# else +# ifndef USE_SIO +# define USE_SIO 0 +# endif + /* #undef NO_SIGNALS */ +# endif +#endif + +#include "ncftp_errno.h" + +/* This is used to verify validty of the data passed in. + * It also specifies the minimum version that is binary-compatibile with + * this version. (So this may not necessarily be kLibraryVersion.) + */ +#define kLibraryMagic "LibNcFTP 3.0.6" + +#ifndef longest_int +#define longest_int long long +#define longest_uint unsigned long long +#endif + +#ifndef forever +# define forever for ( ; ; ) +#endif + +typedef void (*FTPSigProc)(int); + +typedef struct Line *LinePtr; +typedef struct Line { + LinePtr prev, next; + char *line; +} Line; + +typedef struct LineList { + LinePtr first, last; + int nLines; +} LineList, *LineListPtr; + +typedef struct Response { + LineList msg; + int codeType; + int code; + int printMode; + int eofOkay; + int hadEof; +} Response, *ResponsePtr; + +#if USE_SIO && !defined(_SReadlineInfo_) +#define _SReadlineInfo_ 1 +typedef struct SReadlineInfo { + char *buf; /* Pointer to beginning of buffer. */ + char *bufPtr; /* Pointer to current position in buffer. */ + char *bufLim; /* Pointer to end of buffer. */ + size_t bufSize; /* Current size of buffer block. */ + size_t bufSizeMax; /* Maximum size available for buffer. */ + int malloc; /* If non-zero, malloc() was used for buf. */ + int fd; /* File descriptor to use for I/O. */ + int timeoutLen; /* Timeout to use, in seconds. */ + int requireEOLN; /* When buffer is full, continue reading and discarding until \n? */ +} SReadlineInfo; +#endif + +typedef struct FTPLibraryInfo { + char magic[16]; /* Don't modify this field. */ + int init; /* Don't modify this field. */ + int socksInit; /* Don't modify this field. */ + unsigned int defaultPort; /* Don't modify this field. */ + char ourHostName[64]; /* Don't modify this field. */ + int hresult; /* Don't modify this field. */ + int htried; /* Don't modify this field. */ + char defaultAnonPassword[80]; /* You may set this after init. */ +} FTPLibraryInfo, *FTPLIPtr; + +typedef struct FTPConnectionInfo *FTPCIPtr; +typedef void (*FTPProgressMeterProc)(const FTPCIPtr, int); +typedef void (*FTPLogProc)(const FTPCIPtr, char *); +typedef void (*FTPConnectMessageProc)(const FTPCIPtr, ResponsePtr); +typedef void (*FTPLoginMessageProc)(const FTPCIPtr, ResponsePtr); +typedef void (*FTPRedialStatusProc)(const FTPCIPtr, int, int); +typedef void (*FTPPrintResponseProc)(const FTPCIPtr, ResponsePtr); +typedef int (*FTPFtwProc)(const FTPCIPtr cip, const char *fn, int flag); +typedef void (*FTPGetPassphraseProc)(const FTPCIPtr, LineListPtr pwPrompt, char *pass, size_t dsize); + +typedef struct FTPConnectionInfo { + char magic[16]; /* Don't modify this field. */ + char host[64]; /* REQUIRED input parameter. */ + char user[64]; /* OPTIONAL input parameter. */ + char pass[64]; /* OPTIONAL input parameter. */ + char acct[64]; /* OPTIONAL input parameter. */ + unsigned int port; /* OPTIONAL input parameter. */ + unsigned int xferTimeout; /* OPTIONAL input parameter. */ + unsigned int connTimeout; /* OPTIONAL input parameter. */ + unsigned int ctrlTimeout; /* OPTIONAL input parameter. */ + unsigned int abortTimeout; /* OPTIONAL input parameter. */ + FILE *debugLog; /* OPTIONAL input parameter. */ + FILE *errLog; /* OPTIONAL input parameter. */ + FTPLogProc debugLogProc; /* OPTIONAL input parameter. */ + FTPLogProc errLogProc; /* OPTIONAL input parameter. */ + FTPLIPtr lip; /* Do not modify this field. */ + int maxDials; /* OPTIONAL input parameter. */ + int redialDelay; /* OPTIONAL input parameter. */ + int dataPortMode; /* OPTIONAL input parameter. */ + char actualHost[64]; /* Do not modify this field. */ + char ip[32]; /* Do not modify this field. */ + int connected; /* Do not modify this field. */ + int loggedIn; /* Do not modify this field. */ + int curTransferType; /* Do not modify this field. */ + char *startingWorkingDirectory; /* Use, but do not modify. */ + longest_int startPoint; /* Do not modify this field. */ + int hasPASV; /* Do not modify this field. */ + int hasSIZE; /* Do not modify this field. */ + int hasMDTM; /* Do not modify this field. */ + int hasREST; /* Do not modify this field. */ + int hasNLST_d; /* Do not modify this field. */ + int hasUTIME; /* Do not modify this field. */ + int hasFEAT; /* Do not modify this field. */ + int hasMLSD; /* Do not modify this field. */ + int hasMLST; /* Do not modify this field. */ + int usedMLS; /* Do not modify this field. */ + int hasCLNT; /* Do not modify this field. */ + int hasRETRBUFSIZE; /* Do not modify this field. */ + int hasRBUFSIZ; /* Do not modify this field. */ + int hasRBUFSZ; /* Do not modify this field. */ + int hasSTORBUFSIZE; /* Do not modify this field. */ + int hasSBUFSIZ; /* Do not modify this field. */ + int hasSBUFSZ; /* Do not modify this field. */ + int hasBUFSIZE; /* Do not modify this field. */ + int mlsFeatures; /* Do not modify this field. */ + int STATfileParamWorks; /* Do not modify this field. */ + int NLSTfileParamWorks; /* Do not modify this field. */ + struct sockaddr_in servCtlAddr; /* Do not modify this field. */ + struct sockaddr_in servDataAddr; /* Do not modify this field. */ + struct sockaddr_in ourCtlAddr; /* Do not modify this field. */ + struct sockaddr_in ourDataAddr; /* Do not modify this field. */ + int netMode; /* Do not use or modify. */ + char *buf; /* Do not modify this field. */ + size_t bufSize; /* Do not modify this field. */ + FILE *cin; /* Do not use or modify. */ + FILE *cout; /* Do not use or modify. */ + int ctrlSocketR; /* You may use but not modify/close. */ + int ctrlSocketW; /* You may use but not modify/close. */ + int dataSocket; /* You may use but not modify/close. */ + int errNo; /* You may modify this if you want. */ + unsigned short ephemLo; /* You may modify this if you want. */ + unsigned short ephemHi; /* You may modify this if you want. */ + int cancelXfer; /* You may modify this. */ + longest_int bytesTransferred; /* Do not modify this field. */ + FTPProgressMeterProc progress; /* You may modify this if you want. */ + int useProgressMeter; /* Used internally. */ + int leavePass; /* You may modify this. */ + double sec; /* Do not modify this field. */ + double secLeft; /* Do not modify this field. */ + double kBytesPerSec; /* Do not modify this field. */ + double percentCompleted; /* Do not modify this field. */ + longest_int expectedSize; /* Do not modify this field. */ + time_t mdtm; /* Do not modify this field. */ + time_t nextProgressUpdate; /* Do not modify this field. */ + const char *rname; /* Do not modify this field. */ + const char *lname; /* Do not modify this field. */ + struct timeval t0; /* Do not modify this field. */ + int stalled; /* Do not modify this field. */ + int dataTimedOut; /* Do not modify this field. */ + int eofOkay; /* Do not use or modify. */ + char lastFTPCmdResultStr[128]; /* You may modify this if you want. */ + LineList lastFTPCmdResultLL; /* Use, but do not modify. */ + int lastFTPCmdResultNum; /* You may modify this if you want. */ + char firewallHost[64]; /* You may modify this. */ + char firewallUser[64]; /* You may modify this. */ + char firewallPass[64]; /* You may modify this. */ + unsigned int firewallPort; /* You may modify this. */ + int firewallType; /* You may modify this. */ + int require20; /* You may modify this. */ + int usingTAR; /* Use, but do not modify. */ + FTPConnectMessageProc onConnectMsgProc; /* You may modify this. */ + FTPRedialStatusProc redialStatusProc; /* You may modify this. */ + FTPPrintResponseProc printResponseProc; /* You may modify this. */ + FTPLoginMessageProc onLoginMsgProc; /* You may modify this. */ + size_t ctrlSocketRBufSize; /* You may modify this. */ + size_t ctrlSocketSBufSize; /* You may modify this. */ + size_t dataSocketRBufSize; /* You may modify this. */ + size_t dataSocketSBufSize; /* You may modify this. */ + int serverType; /* Do not use or modify. */ + int ietfCompatLevel; /* Do not use or modify. */ + int numDownloads; /* Do not use or modify. */ + int numUploads; /* Do not use or modify. */ + int numListings; /* Do not use or modify. */ + int doNotGetStartingWorkingDirectory; /* You may modify this. */ +#if USE_SIO + char srlBuf[768]; + SReadlineInfo ctrlSrl; /* Do not use or modify. */ +#endif + FTPGetPassphraseProc passphraseProc; /* You may modify this. */ + int iUser; /* Scratch integer field you can use. */ + void *pUser; /* Scratch pointer field you can use. */ + longest_int llUser; /* Scratch long long field you can use. */ + const char *asciiFilenameExtensions; /* You may assign this. */ + int reserved[32]; /* Do not use or modify. */ +} FTPConnectionInfo; + +typedef struct FileInfo *FileInfoPtr, **FileInfoVec; +typedef struct FileInfo { + FileInfoPtr prev, next; + char *relname; + char *rname; + char *rlinkto; + char *lname; + char *plug; /* permissions, links, user, group */ + int type; + time_t mdtm; + longest_int size; + size_t relnameLen; +} FileInfo; + +typedef struct FileInfoList { + FileInfoPtr first, last; + FileInfoVec vec; + size_t maxFileLen; + size_t maxPlugLen; + int nFileInfos; + int sortKey; + int sortOrder; +} FileInfoList, *FileInfoListPtr; + +/* Used with UnMlsT() */ +typedef struct MLstItem{ + char fname[512]; + char linkto[512]; + int ftype; + longest_int fsize; + time_t ftime; + int mode; /* "UNIX.mode" fact */ + int uid; /* "UNIX.uid" fact */ + int gid; /* "UNIX.gid" fact */ + char perm[16]; /* "perm" fact */ + char owner[16]; /* "UNIX.owner" fact */ + char group[16]; /* "UNIX.group" fact */ +} MLstItem, *MLstItemPtr; + +/* Messages we pass to the current progress meter function. */ +#define kPrInitMsg 1 +#define kPrUpdateMsg 2 +#define kPrEndMsg 3 + +/* Parameter for OpenDataConnection() */ +#define kSendPortMode 0 +#define kPassiveMode 1 +#define kFallBackToSendPortMode 2 + +/* Parameter for AcceptDataConnection() */ +#define kAcceptForWriting 00100 +#define kAcceptForReading 00101 +#define kNetWriting kAcceptForWriting +#define kNetReading kAcceptForReading + +/* Value for printMode field of Response structure. + * Generally, don't worry about this. + */ +#define kResponseNoPrint 00001 +#define kResponseNoSave 00002 +#define kResponseNoProc 00002 + +#define kDefaultFTPPort 21 + +#define kDefaultFTPBufSize 32768 + +#ifdef USE_SIO +/* This version of the library can handle timeouts without + * a user-installed signal handler. + */ +#define kDefaultXferTimeout 600 +#define kDefaultConnTimeout 30 +#define kDefaultCtrlTimeout 135 +#define kDefaultAbortTimeout 10 +#else +/* The library doesn't use timeouts by default because it would + * break apps that don't have a SIGALRM handler. + */ +#define kDefaultXferTimeout (0) /* No timeout. */ +#define kDefaultConnTimeout (0) /* No timeout. */ +#define kDefaultCtrlTimeout (0) /* No timeout. */ +#define kDefaultAbortTimeout 10 +#endif + + +/* Suggested timeout values, in seconds, if you use timeouts. */ +#define kSuggestedDefaultXferTimeout (0) /* No timeout on data blocks. */ +#define kSuggestedDefaultConnTimeout 30 +#define kSuggestedDefaultCtrlTimeout 135 /* 2*MSL, + slop */ +#define kSuggestedAbortTimeout 10 + +#define kDefaultMaxDials 3 +#define kDefaultRedialDelay 20 /* seconds */ + +#define kDefaultDataPortMode kSendPortMode + +#define kRedialStatusDialing 0 +#define kRedialStatusSleeping 1 + +#ifndef INADDR_NONE +# define INADDR_NONE (0xffffffff) /* should have it. */ +#endif + +#define kTypeAscii 'A' +#define kTypeBinary 'I' +#define kTypeEbcdic 'E' + +#define kGlobChars "[*?" +#define GLOBCHARSINSTR(a) (strpbrk(a, kGlobChars) != NULL) + +#define kGlobYes 1 +#define kGlobNo 0 +#define kRecursiveYes 1 +#define kRecursiveNo 0 +#define kAppendYes 1 +#define kAppendNo 0 +#define kResumeYes 1 +#define kResumeNo 0 +#define kDeleteYes 1 +#define kDeleteNo 0 +#define kTarYes 1 +#define kTarNo 0 + +#define UNIMPLEMENTED_CMD(a) ((a == 500) || (a == 502) || (a == 504)) + +/* Possible values returned by GetDateAndTime. */ +#define kSizeUnknown ((longest_int) (-1)) +#define kModTimeUnknown ((time_t) (-1)) + +#define kCommandAvailabilityUnknown (-1) +#define kCommandAvailable 1 +#define kCommandNotAvailable 0 + +/* Values returned by FTPDecodeURL. */ +#define kNotURL (-1) +#define kMalformedURL (-2) + +/* Values for the firewall/proxy open. */ +#define kFirewallNotInUse 0 +#define kFirewallUserAtSite 1 +#define kFirewallLoginThenUserAtSite 2 +#define kFirewallSiteSite 3 +#define kFirewallOpenSite 4 +#define kFirewallUserAtUserPassAtPass 5 +#define kFirewallFwuAtSiteFwpUserPass 6 +#define kFirewallUserAtSiteFwuPassFwp 7 +#define kFirewallLastType kFirewallUserAtSiteFwuPassFwp + +/* For MLSD, MLST, and STAT. */ +#define kPreferredMlsOpts (kMlsOptType | kMlsOptSize | kMlsOptModify | kMlsOptUNIXmode | kMlsOptUNIXowner | kMlsOptUNIXgroup | kMlsOptUNIXuid | kMlsOptUNIXgid | kMlsOptPerm) + +#define kMlsOptType 00001 +#define kMlsOptSize 00002 +#define kMlsOptModify 00004 +#define kMlsOptUNIXmode 00010 +#define kMlsOptUNIXowner 00020 +#define kMlsOptUNIXgroup 00040 +#define kMlsOptPerm 00100 +#define kMlsOptUNIXuid 00200 +#define kMlsOptUNIXgid 00400 +#define kMlsOptUnique 01000 + +/* For FTPFtw(). */ +#define kFtwFile 0 +#define kFtwDir 1 + +/* For FTPChdir3(). */ +#define kChdirOnly 00000 +#define kChdirAndMkdir 00001 +#define kChdirAndGetCWD 00002 +#define kChdirOneSubdirAtATime 00004 + +/* Return codes for custom ConfirmResumeDownloadProcs. */ +#define kConfirmResumeProcNotUsed 0 +#define kConfirmResumeProcSaidSkip 1 +#define kConfirmResumeProcSaidResume 2 +#define kConfirmResumeProcSaidOverwrite 3 +#define kConfirmResumeProcSaidAppend 4 +#define kConfirmResumeProcSaidBestGuess 5 +#define kConfirmResumeProcSaidCancel 6 + +typedef int (*ConfirmResumeDownloadProc)( + const char *volatile *localpath, + volatile longest_int localsize, + volatile time_t localmtime, + const char *volatile remotepath, + volatile longest_int remotesize, + volatile time_t remotetime, + volatile longest_int *volatile startPoint +); + +typedef int (*ConfirmResumeUploadProc)( + const char *volatile localpath, + volatile longest_int localsize, + volatile time_t localmtime, + const char *volatile *remotepath, + volatile longest_int remotesize, + volatile time_t remotetime, + volatile longest_int *volatile startPoint +); + +#define NoConfirmResumeDownloadProc ((ConfirmResumeDownloadProc) 0) +#define NoConfirmResumeUploadProc ((ConfirmResumeUploadProc) 0) +#define NoGetPassphraseProc ((FTPGetPassphraseProc) 0) + +/* Types of FTP server software. + * + * We try to recognize a few of these, for information + * only, and occasional uses to determine some additional + * or broken functionality. + */ +#define kServerTypeUnknown 0 +#define kServerTypeWuFTPd 1 +#define kServerTypeNcFTPd 2 +#define kServerTypeProFTPD 3 +#define kServerTypeMicrosoftFTP 4 +#define kServerTypeWarFTPd 5 +#define kServerTypeServ_U 6 +#define kServerTypeWFTPD 7 +#define kServerTypeVFTPD 8 +#define kServerTypeFTP_Max 9 +#define kServerTypeRoxen 10 +#define kServerTypeNetWareFTP 11 +#define kServerTypeWS_FTP 12 + + +#if !defined(WIN32) && !defined(_WINDOWS) && !defined(closesocket) +# define closesocket close +#endif + +#if !defined(WIN32) && !defined(_WINDOWS) && !defined(ioctlsocket) +# define ioctlsocket ioctl +#endif + +#if defined(WIN32) || defined(_WINDOWS) +# define LOCAL_PATH_DELIM '\\' +# define LOCAL_PATH_DELIM_STR "\\" +# define LOCAL_PATH_ALTDELIM '/' +# define IsLocalPathDelim(c) ((c == LOCAL_PATH_DELIM) || (c == LOCAL_PATH_ALTDELIM)) +# define UNC_PATH_PREFIX "\\\\" +# define IsUNCPrefixed(s) (IsLocalPathDelim(s[0]) && IsLocalPathDelim(s[1])) +#else +# define LOCAL_PATH_DELIM '/' +# define LOCAL_PATH_DELIM_STR "/" +# define StrFindLocalPathDelim(a) strchr(a, LOCAL_PATH_DELIM) +# define StrRFindLocalPathDelim(a) strrchr(a, LOCAL_PATH_DELIM) +# define StrRemoveTrailingLocalPathDelim StrRemoveTrailingSlashes +# define IsLocalPathDelim(c) (c == LOCAL_PATH_DELIM) +# define TVFSPathToLocalPath(s) +# define LocalPathToTVFSPath(s) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef _libncftp_ftp_c_ +extern char gLibNcFTPVersion[64]; +#endif + +#ifndef _libncftp_errno_c_ +extern int gLibNcFTP_Uses_Me_To_Quiet_Variable_Unused_Warnings; +#endif + +#if (defined(__GNUC__)) && (__GNUC__ >= 2) +# ifndef UNUSED +# define UNUSED(a) a __attribute__ ((unused)) +# endif +# define LIBNCFTP_USE_VAR(a) +#else +# define LIBNCFTP_USE_VAR(a) gLibNcFTP_Uses_Me_To_Quiet_Variable_Unused_Warnings = (a == 0) +# ifndef UNUSED +# define UNUSED(a) a +# endif +#endif + +/* Public routines */ +void FTPAbortDataTransfer(const FTPCIPtr cip); +int FTPChdir(const FTPCIPtr cip, const char *const cdCwd); +int FTPChdirAndGetCWD(const FTPCIPtr cip, const char *const cdCwd, char *const newCwd, const size_t newCwdSize); +int FTPChdir3(FTPCIPtr cip, const char *const cdCwd, char *const newCwd, const size_t newCwdSize, int flags); +int FTPChmod(const FTPCIPtr cip, const char *const pattern, const char *const mode, const int doGlob); +int FTPCloseHost(const FTPCIPtr cip); +int FTPCmd(const FTPCIPtr cip, const char *const cmdspec, ...) +#if (defined(__GNUC__)) && (__GNUC__ >= 2) +__attribute__ ((format (printf, 2, 3))) +#endif +; +int FTPDecodeURL(const FTPCIPtr cip, char *const url, LineListPtr cdlist, char *const fn, const size_t fnsize, int *const xtype, int *const wantnlst); +int FTPDelete(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob); +int FTPFileExists(const FTPCIPtr cip, const char *const file); +int FTPFileModificationTime(const FTPCIPtr cip, const char *const file, time_t *const mdtm); +int FTPFileSize(const FTPCIPtr cip, const char *const file, longest_int *const size, const int type); +int FTPFileSizeAndModificationTime(const FTPCIPtr cip, const char *const file, longest_int *const size, const int type, time_t *const mdtm); +int FTPFileType(const FTPCIPtr cip, const char *const file, int *const ftype); +int FTPGetCWD(const FTPCIPtr cip, char *const newCwd, const size_t newCwdSize); +int FTPGetFiles3(const FTPCIPtr cip, const char *pattern, const char *const dstdir, const int recurse, int doGlob, const int xtype, const int resumeflag, int appendflag, const int deleteflag, const int tarflag, const ConfirmResumeDownloadProc resumeProc, int reserved); +int FTPGetOneFile3(const FTPCIPtr cip, const char *const file, const char *const dstfile, const int xtype, const int fdtouse, const int resumeflag, const int appendflag, const int deleteflag, const ConfirmResumeDownloadProc resumeProc, int reserved); +int FTPInitConnectionInfo(const FTPLIPtr lip, const FTPCIPtr cip, size_t bufsize); +int FTPInitLibrary(const FTPLIPtr lip); +int FTPIsDir(const FTPCIPtr cip, const char *const dir); +int FTPIsRegularFile(const FTPCIPtr cip, const char *const file); +int FTPList(const FTPCIPtr cip, const int outfd, const int longMode, const char *const lsflag); +int FTPListToMemory(const FTPCIPtr cip, const char *const pattern, const LineListPtr llines, const char *const lsflags); +int FTPLocalGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob); +int FTPLoginHost(const FTPCIPtr cip); +int FTPMkdir(const FTPCIPtr cip, const char *const newDir, const int recurse); +int FTPMkdir2(const FTPCIPtr cip, const char *const newDir, const int recurse, const char *const curDir); +int FTPOpenHost(const FTPCIPtr cip); +int FTPOpenHostNoLogin(const FTPCIPtr cip); +void FTPPerror(const FTPCIPtr cip, const int err, const int eerr, const char *const s1, const char *const s2); +int FTPPutOneFile3(const FTPCIPtr cip, const char *const file, const char *const dstfile, const int xtype, const int fdtouse, const int appendflag, const char *const tmppfx, const char *const tmpsfx, const int resumeflag, const int deleteflag, const ConfirmResumeUploadProc resumeProc, int reserved); +int FTPPutFiles3(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob, const int xtype, int appendflag, const char *const tmppfx, const char *const tmpsfx, const int resumeflag, const int deleteflag, const ConfirmResumeUploadProc resumeProc, int reserved); +int FTPRemoteGlob(FTPCIPtr cip, LineListPtr fileList, const char *pattern, int doGlob); +int FTPRename(const FTPCIPtr cip, const char *const oldname, const char *const newname); +int FTPRmdir(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob); +void FTPShutdownHost(const FTPCIPtr cip); +const char *FTPStrError(int e); +int FTPSymlink(const FTPCIPtr cip, const char *const lfrom, const char *const lto); +int FTPUmask(const FTPCIPtr cip, const char *const umsk); +int FTPUtime(const FTPCIPtr cip, const char *const file, time_t actime, time_t modtime, time_t crtime); + +/* LineList routines */ +int CopyLineList(LineListPtr, LineListPtr); +void DisposeLineListContents(LineListPtr); +void InitLineList(LineListPtr); +LinePtr RemoveLine(LineListPtr, LinePtr); +LinePtr AddLine(LineListPtr, const char *); + +/* Other routines that might be useful. */ +char *StrDup(const char *); +char *FGets(char *, size_t, FILE *); +void GetHomeDir(char *, size_t); +void GetUsrName(char *, size_t); +void Scramble(unsigned char *dst, size_t dsize, unsigned char *src, char *key); +time_t UnMDTMDate(char *); +int MkDirs(const char *const, int mode1); +char *GetPass(const char *const prompt); +int FilenameExtensionIndicatesASCII(const char *const pathName, const char *const extnList); +void StrRemoveTrailingSlashes(char *dst); +#if defined(WIN32) || defined(_WINDOWS) +char *StrFindLocalPathDelim(const char *src); +char *StrRFindLocalPathDelim(const char *src); +void StrRemoveTrailingLocalPathDelim(char *dst); +void TVFSPathToLocalPath(char *dst); +void LocalPathToTVFSPath(char *dst); +int gettimeofday(struct timeval *const tp, void *junk); +void WinSleep(unsigned int seconds); +#endif + +#ifdef HAVE_SIGACTION +void (*NcSignal(int signum, void (*handler)(int)))(int); +#elif !defined(NcSignal) +# define NcSignal signal +#endif + +/* Obselete routines. */ +int FTPGetOneFile(const FTPCIPtr cip, const char *const file, const char *const dstfile); +int FTPGetOneFile2(const FTPCIPtr cip, const char *const file, const char *const dstfile, const int xtype, const int fdtouse, const int resumeflag, const int appendflag); +int FTPGetFiles(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob); +int FTPGetFiles2(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob, const int xtype, const int resumeflag, const int appendflag); +int FTPGetOneFileAscii(const FTPCIPtr cip, const char *const file, const char *const dstfile); +int FTPGetFilesAscii(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob); +int FTPPutOneFile(const FTPCIPtr cip, const char *const file, const char *const dstfile); +int FTPPutOneFile2(const FTPCIPtr cip, const char *const file, const char *const dstfile, const int xtype, const int fdtouse, const int appendflag, const char *const tmppfx, const char *const tmpsfx); +int FTPPutFiles(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob); +int FTPPutFiles2(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob, const int xtype, const int appendflag, const char *const tmppfx, const char *const tmpsfx); +int FTPPutOneFileAscii(const FTPCIPtr cip, const char *const file, const char *const dstfile); +int FTPPutFilesAscii(const FTPCIPtr cip, const char *const pattern, const char *const dstdir, const int recurse, const int doGlob); + +/* Private routines, or stuff for testing */ +char *FTPGetLocalCWD(char *buf, size_t size); +int FTPQueryFeatures(const FTPCIPtr); +int FTPMListOneFile(const FTPCIPtr cip, const char *const file, const MLstItemPtr mlip); +void FTPInitializeOurHostName(const FTPLIPtr); +void FTPInitializeAnonPassword(const FTPLIPtr); +int FTPListToMemory2(const FTPCIPtr cip, const char *const pattern, const LineListPtr llines, const char *const lsflags, const int blanklines, int *const tryMLSD); +void FTPInitIOTimer(const FTPCIPtr); +int FTPStartDataCmd(const FTPCIPtr, int, int, longest_int, const char *,...) +#if (defined(__GNUC__)) && (__GNUC__ >= 2) +__attribute__ ((format (printf, 5, 6))) +#endif +; +void FTPStartIOTimer(const FTPCIPtr); +void FTPStopIOTimer(const FTPCIPtr); +void FTPUpdateIOTimer(const FTPCIPtr); +int FTPSetTransferType(const FTPCIPtr, int); +int FTPEndDataCmd(const FTPCIPtr, int); +int FTPRemoteHelp(const FTPCIPtr, const char *const, const LineListPtr); +int FTPCmdNoResponse(const FTPCIPtr, const char *const cmdspec,...) +#if (defined(__GNUC__)) && (__GNUC__ >= 2) +__attribute__ ((format (printf, 2, 3))) +#endif +; +int WaitResponse(const FTPCIPtr, unsigned int); +int FTPLocalRecursiveFileList(FTPCIPtr, LineListPtr, FileInfoListPtr); +int FTPLocalRecursiveFileList2(FTPCIPtr cip, LineListPtr fileList, FileInfoListPtr files, int erelative); +int FTPRemoteRecursiveFileList(FTPCIPtr, LineListPtr, FileInfoListPtr); +int FTPRemoteRecursiveFileList1(FTPCIPtr, char *const, FileInfoListPtr); +int FTPRebuildConnectionInfo(const FTPLIPtr lip, const FTPCIPtr cip); +int FTPFileExistsStat(const FTPCIPtr cip, const char *const file); +int FTPFileExistsNlst(const FTPCIPtr cip, const char *const file); +int FTPFileExists2(const FTPCIPtr cip, const char *const file, const int tryMDTM, const int trySIZE, const int tryMLST, const int trySTAT, const int tryNLST); +int FTPFtw(const FTPCIPtr cip, const char *const dir, FTPFtwProc proc, int maxdepth); +int BufferGets(char *, size_t, int, char *, char **, char **, size_t); +void DisposeFileInfoListContents(FileInfoListPtr); +void InitFileInfoList(FileInfoListPtr); +void InitFileInfo(FileInfoPtr); +FileInfoPtr RemoveFileInfo(FileInfoListPtr, FileInfoPtr); +FileInfoPtr AddFileInfo(FileInfoListPtr, FileInfoPtr); +void SortFileInfoList(FileInfoListPtr, int, int); +void VectorizeFileInfoList(FileInfoListPtr); +void UnvectorizeFileInfoList(FileInfoListPtr); +int ComputeRNames(FileInfoListPtr, const char *, int, int); +int ComputeLNames(FileInfoListPtr, const char *, const char *, int); +int ConcatFileInfoList(FileInfoListPtr, FileInfoListPtr); +int ConcatFileToFileInfoList(FileInfoListPtr, char *); +int LineListToFileInfoList(LineListPtr, FileInfoListPtr); +int LineToFileInfoList(LinePtr, FileInfoListPtr); +void URLCopyToken(char *, size_t, const char *, size_t); +int UnMlsT(const char *const, const MLstItemPtr); +int UnMlsD(FileInfoListPtr, LineListPtr); +int UnLslR(FileInfoListPtr, LineListPtr, int); +void TraceResponse(const FTPCIPtr, ResponsePtr); +void PrintResponse(const FTPCIPtr, LineListPtr); +void DoneWithResponse(const FTPCIPtr, ResponsePtr); +ResponsePtr InitResponse(void); +void ReInitResponse(const FTPCIPtr, ResponsePtr); +int GetTelnetString(const FTPCIPtr, char *, size_t, FILE *, FILE *); +int GetResponse(const FTPCIPtr, ResponsePtr); +int RCmd(const FTPCIPtr, ResponsePtr, const char *, ...) +#if (defined(__GNUC__)) && (__GNUC__ >= 2) +__attribute__ ((format (printf, 3, 4))) +#endif +; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _ncftp_h_ */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/ncftp_errno.h b/modules/rosapps/applications/net/ncftp/libncftp/ncftp_errno.h new file mode 100644 index 00000000000..21ab09d1111 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/ncftp_errno.h @@ -0,0 +1,113 @@ +/* ncftp_errno.h + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#ifndef kNoErr +# define kNoErr 0 +#endif + +#ifndef kErrGeneric +# define kErrGeneric (-1) +#endif + +#define kErrFirst (100) +#define kErrGetHostNameFailed (-100) +#define kErrHostWithoutDomain (-101) +#define kErrSetLinger (-102) +#define kErrSetTypeOfService (-103) +#define kErrSetOutOfBandInline (-104) +#define kErrHostUnknown (-105) +#define kErrNewStreamSocket (-106) +#define kErrDupSocket (-107) +#define kErrFdopenR (-108) +#define kErrFdopenW (-109) +#define kErrGetSockName (-110) +#define kErrBindDataSocket (-111) +#define kErrListenDataSocket (-112) +#define kErrPassiveModeFailed (-113) +#define kErrServerSentBogusPortNumber (-114) +#define kErrConnectDataSocket (-115) +#define kErrAcceptDataSocket (-116) +#define kErrSetStartPoint (-117) +#define kErrConnectMiscErr (-118) +#define kErrConnectRetryableErr (-119) +#define kErrConnectRefused (-120) +#define kErrBadTransferType (-121) +#define kErrInvalidDirParam (-122) +#define kErrMallocFailed (-123) +#define kErrPWDFailed (-124) +#define kErrCWDFailed (-125) +#define kErrRMDFailed (-126) +#define kErrBadLineList (-127) +#define kErrUnimplementedOption (-128) +#define kErrUnimplementedFunction (-129) +#define kErrLISTFailed (-130) +#define kErrRETRFailed (-131) +#define kErrSTORFailed (-132) +#define kErrWriteFailed (-133) +#define kErrReadFailed (-134) +#define kErrSocketWriteFailed (-135) +#define kErrSocketReadFailed (-136) +#define kErrOpenFailed (-137) +#define kErrBadMagic (-138) +#define kErrBadParameter (-139) +#define kErrMKDFailed (-140) +#define kErrCannotGoToPrevDir (-141) +#define kErrChmodFailed (-142) +#define kErrUmaskFailed (-143) +#define kErrDELEFailed (-144) +#define kErrSIZEFailed (-145) +#define kErrMDTMFailed (-146) +#define kErrTYPEFailed (-147) +#define kErrSIZENotAvailable (-148) +#define kErrMDTMNotAvailable (-149) +#define kErrRenameFailed (-150) +#define kErrGlobFailed (-151) +#define kErrSetKeepAlive (-152) +#define kErrHostDisconnectedDuringLogin (-153) +#define kErrBadRemoteUser (-154) +#define kErrBadRemoteUserOrPassword (-155) +#define kErrLoginFailed (-156) +#define kErrInvalidReplyFromServer (-157) +#define kErrRemoteHostClosedConnection (-158) +#define kErrNotConnected (-159) +#define kErrCouldNotStartDataTransfer (-160) +#define kErrDataTransferFailed (-161) +#define kErrPORTFailed (-162) +#define kErrPASVFailed (-163) +#define kErrUTIMEFailed (-164) +#define kErrUTIMENotAvailable (-165) +#define kErrHELPFailed (-166) +#define kErrLocalDeleteFailed (-167) +#define kErrLseekFailed (-168) +#define kErrDataTransferAborted (-169) +#define kErrSYMLINKFailed (-170) +#define kErrSYMLINKNotAvailable (-171) +#define kErrGlobNoMatch (-172) +#define kErrFEATNotAvailable (-173) +#define kErrNoValidFilesSpecified (-174) +#define kErrNoBuf (-175) +#define kErrLocalFileNewer (-176) +#define kErrRemoteFileNewer (-177) +#define kErrLocalSameAsRemote (-178) +#define kErrMLSDFailed (-179) +#define kErrMLSTFailed (-180) +#define kErrInvalidMLSTResponse (-181) +#define kErrMLSTNotAvailable (-182) +#define kErrMLSDNotAvailable (-183) +#define kErrSTATFailed (-184) +#define kErrSTATwithFileNotAvailable (-185) +#define kErrNLSTFailed (-186) +#define kErrNLSTwithFileNotAvailable (-187) +#define kErrNoSuchFileOrDirectory (-188) +#define kErrCantTellIfFileExists (-189) +#define kErrFileExistsButCannotDetermineType (-190) +#define kErrNotADirectory (-191) +#define kErrRecursionLimitReached (-192) +#define kErrControlTimedOut (-193) +#define kErrDataTimedOut (-194) +#define kErrUserCanceled (-195) +#define kErrLast (195) diff --git a/modules/rosapps/applications/net/ncftp/libncftp/open.c b/modules/rosapps/applications/net/ncftp/libncftp/open.c new file mode 100644 index 00000000000..f3854edd5fc --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/open.c @@ -0,0 +1,1137 @@ +/* open.c + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#include "syshdrs.h" + +static void +FTPDeallocateHost(const FTPCIPtr cip) +{ + /* Requires the cip->bufSize field set, + * and the cip->buf set if the + * buffer is allocated. + */ + if (cip->buf != NULL) { + (void) memset(cip->buf, 0, cip->bufSize); + free(cip->buf); + cip->buf = NULL; + } + + if (cip->startingWorkingDirectory != NULL) { + free(cip->startingWorkingDirectory); + cip->startingWorkingDirectory = NULL; + } + +#if USE_SIO + DisposeSReadlineInfo(&cip->ctrlSrl); +#endif + DisposeLineListContents(&cip->lastFTPCmdResultLL); +} /* FTPDeallocateHost */ + + + + + +static int +FTPAllocateHost(const FTPCIPtr cip) +{ + char *buf; + + /* Requires the cip->bufSize field set, + * and the cip->buf cleared if the + * buffer is not allocated. + */ + if (cip->buf == NULL) { + buf = (char *) calloc((size_t) 1, cip->bufSize); + if (buf == NULL) { + Error(cip, kDontPerror, "Malloc failed.\n"); + cip->errNo = kErrMallocFailed; + return (kErrMallocFailed); + } + cip->buf = buf; + } + return (kNoErr); +} /* FTPAllocateHost */ + + + + +void +FTPInitializeOurHostName(const FTPLIPtr lip) +{ + if (lip == NULL) + return; + if (strcmp(lip->magic, kLibraryMagic)) + return; + + if (lip->htried == 0) { + (void) memset(lip->ourHostName, 0, sizeof(lip->ourHostName)); + lip->hresult = GetOurHostName(lip->ourHostName, sizeof(lip->ourHostName)); + } + lip->htried++; +} /* FTPInitializeOurHostName */ + + + + +void +FTPInitializeAnonPassword(const FTPLIPtr lip) +{ + if (lip == NULL) + return; + if (strcmp(lip->magic, kLibraryMagic)) + return; + + FTPInitializeOurHostName(lip); + + if (lip->defaultAnonPassword[0] == '\0') { +#ifdef SPAM_PROBLEM_HAS_BEEN_SOLVED_FOREVER + GetUsrName(lip->defaultAnonPassword, sizeof(lip->defaultAnonPassword)); + (void) STRNCAT(lip->defaultAnonPassword, "@"); + + /* Default to the "user@" notation + * supported by NcFTPd and wu-ftpd. + */ + if (lip->htried > 0) + (void) STRNCAT(lip->defaultAnonPassword, lip->ourHostName); +#else + (void) STRNCPY(lip->defaultAnonPassword, "NcFTP@"); +#endif + } +} /* FTPInitializeAnonPassword */ + + + + +int +FTPLoginHost(const FTPCIPtr cip) +{ + ResponsePtr rp; + int result = kErrLoginFailed; + int anonLogin; + int sentpass = 0; + int fwloggedin; + int firstTime; + char cwd[512]; + + if (cip == NULL) + return (kErrBadParameter); + if ((cip->firewallType < kFirewallNotInUse) || (cip->firewallType > kFirewallLastType)) + return (kErrBadParameter); + + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + anonLogin = 0; + if (cip->user[0] == '\0') + (void) STRNCPY(cip->user, "anonymous"); + if ((strcmp(cip->user, "anonymous") == 0) || (strcmp(cip->user, "ftp") == 0)) { + anonLogin = 1; + /* Try to get the email address if you didn't specify + * a password when the user is anonymous. + */ + if (cip->pass[0] == '\0') { + FTPInitializeAnonPassword(cip->lip); + (void) STRNCPY(cip->pass, cip->lip->defaultAnonPassword); + } + } + + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + goto done2; + } + + for (firstTime = 1, fwloggedin = 0; ; ) { + /* Here's a mini finite-automaton for the login process. + * + * Originally, the FTP protocol was designed to be entirely + * implementable from a FA. It could be done, but I don't think + * it's something an interactive process could be the most + * effective with. + */ + + if (firstTime != 0) { + rp->code = 220; + firstTime = 0; + } else if (result < 0) { + goto done; + } + + switch (rp->code) { + case 220: /* Welcome, ready for new user. */ + if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "USER %s", cip->user); + } else if (cip->firewallType == kFirewallUserAtSite) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "USER %s@%s", cip->user, cip->host); + } else if (cip->firewallType == kFirewallUserAtUserPassAtPass) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "USER %s@%s@%s", cip->user, cip->firewallUser, cip->host); + } else if (cip->firewallType == kFirewallUserAtSiteFwuPassFwp) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "USER %s@%s %s", cip->user, cip->host, cip->firewallUser); + } else if (cip->firewallType == kFirewallFwuAtSiteFwpUserPass) { + /* only reached when !fwloggedin */ + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "USER %s@%s", cip->firewallUser, cip->host); + } else if (cip->firewallType > kFirewallNotInUse) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "USER %s", cip->firewallUser); + } else { + goto unknown; + } + break; + + case 230: /* 230 User logged in, proceed. */ + case 231: /* User name accepted. */ + case 202: /* Command not implemented, superfluous at this site. */ + if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) + goto okay; + + /* Now logged in to the firewall. */ + fwloggedin++; + + if (cip->firewallType == kFirewallLoginThenUserAtSite) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "USER %s@%s", cip->user, cip->host); + } else if (cip->firewallType == kFirewallUserAtUserPassAtPass) { + goto okay; + } else if (cip->firewallType == kFirewallOpenSite) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "OPEN %s", cip->host); + } else if (cip->firewallType == kFirewallSiteSite) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "SITE %s", cip->host); + } else if (cip->firewallType == kFirewallFwuAtSiteFwpUserPass) { + /* only reached when !fwloggedin */ + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "USER %s", cip->user); + } else /* kFirewallUserAtSite */ { + goto okay; + } + break; + + case 421: /* 421 Service not available, closing control connection. */ + result = kErrHostDisconnectedDuringLogin; + goto done; + + case 331: /* 331 User name okay, need password. */ + if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) { + if ((cip->pass[0] == '\0') && (cip->passphraseProc != NoGetPassphraseProc)) + (*cip->passphraseProc)(cip, &rp->msg, cip->pass, sizeof(cip->pass)); + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "PASS %s", cip->pass); + } else if (cip->firewallType == kFirewallUserAtSite) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "PASS %s", cip->pass); + } else if (cip->firewallType == kFirewallUserAtUserPassAtPass) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "PASS %s@%s", cip->pass, cip->firewallPass); + } else if (cip->firewallType == kFirewallUserAtSiteFwuPassFwp) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "PASS %s", cip->pass); + } else if (cip->firewallType == kFirewallFwuAtSiteFwpUserPass) { + /* only reached when !fwloggedin */ + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "PASS %s", cip->firewallPass); + } else if (cip->firewallType > kFirewallNotInUse) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "PASS %s", cip->firewallPass); + } else { + goto unknown; + } + sentpass++; + break; + + case 332: /* 332 Need account for login. */ + case 532: /* 532 Need account for storing files. */ + if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "ACCT %s", cip->acct); + } else if (cip->firewallType == kFirewallUserAtSiteFwuPassFwp) { + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "ACCT %s", cip->firewallPass); + } else { + /* ACCT not supported on firewall. */ + goto unknown; + } + break; + + case 530: /* Not logged in. */ + result = (sentpass != 0) ? kErrBadRemoteUserOrPassword : kErrBadRemoteUser; + goto done; + + case 501: /* Syntax error in parameters or arguments. */ + case 503: /* Bad sequence of commands. */ + case 550: /* Can't set guest privileges. */ + goto done; + + default: + unknown: + if (rp->msg.first == NULL) { + Error(cip, kDontPerror, "Lost connection during login.\n"); + } else { + Error(cip, kDontPerror, "Unexpected response: %s\n", + rp->msg.first->line + ); + } + goto done; + } + } + +okay: + /* Do the application's connect message callback, if present. */ + if (cip->onLoginMsgProc != 0) + (*cip->onLoginMsgProc)(cip, rp); + DoneWithResponse(cip, rp); + result = 0; + cip->loggedIn = 1; + + /* Make a note of what our root directory is. + * This is often different from "/" when not + * logged in anonymously. + */ + if (cip->startingWorkingDirectory != NULL) { + free(cip->startingWorkingDirectory); + cip->startingWorkingDirectory = NULL; + } + if ((cip->doNotGetStartingWorkingDirectory == 0) && + (FTPGetCWD(cip, cwd, sizeof(cwd)) == kNoErr)) + { + cip->startingWorkingDirectory = StrDup(cwd); + } + + /* When a new site is opened, ASCII mode is assumed (by protocol). */ + cip->curTransferType = 'A'; + PrintF(cip, "Logged in to %s as %s.\n", cip->host, cip->user); + + /* Don't leave cleartext password in memory. */ + if ((anonLogin == 0) && (cip->leavePass == 0)) + (void) memset(cip->pass, '*', strlen(cip->pass)); + + if (result < 0) + cip->errNo = result; + return result; + +done: + DoneWithResponse(cip, rp); + +done2: + /* Don't leave cleartext password in memory. */ + if ((anonLogin == 0) && (cip->leavePass == 0)) + (void) memset(cip->pass, '*', strlen(cip->pass)); + if (result < 0) + cip->errNo = result; + return result; +} /* FTPLoginHost */ + + + + +static void +FTPExamineMlstFeatures(const FTPCIPtr cip, const char *features) +{ + char buf[256], *feat; + int flags; + + flags = 0; + STRNCPY(buf, features); + feat = strtok(buf, ";*"); + while (feat != NULL) { + if (ISTRNEQ(feat, "OS.", 3)) + feat += 3; + if (ISTREQ(feat, "type")) { + flags |= kMlsOptType; + } else if (ISTREQ(feat, "size")) { + flags |= kMlsOptSize; + } else if (ISTREQ(feat, "modify")) { + flags |= kMlsOptModify; + } else if (ISTREQ(feat, "UNIX.mode")) { + flags |= kMlsOptUNIXmode; + } else if (ISTREQ(feat, "UNIX.owner")) { + flags |= kMlsOptUNIXowner; + } else if (ISTREQ(feat, "UNIX.group")) { + flags |= kMlsOptUNIXgroup; + } else if (ISTREQ(feat, "perm")) { + flags |= kMlsOptPerm; + } else if (ISTREQ(feat, "UNIX.uid")) { + flags |= kMlsOptUNIXuid; + } else if (ISTREQ(feat, "UNIX.gid")) { + flags |= kMlsOptUNIXgid; + } else if (ISTREQ(feat, "UNIX.gid")) { + flags |= kMlsOptUnique; + } + feat = strtok(NULL, ";*"); + } + + cip->mlsFeatures = flags; +} /* FTPExamineMlstFeatures */ + + + + +int +FTPQueryFeatures(const FTPCIPtr cip) +{ + ResponsePtr rp; + int result; + LinePtr lp; + char *cp, *p; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (cip->serverType == kServerTypeNetWareFTP) { + /* NetWare 5.00 server freaks out when + * you give it a command it doesn't + * recognize, so cheat here and return. + */ + cip->hasPASV = kCommandAvailable; + cip->hasSIZE = kCommandNotAvailable; + cip->hasMDTM = kCommandNotAvailable; + cip->hasREST = kCommandNotAvailable; + cip->NLSTfileParamWorks = kCommandAvailable; + cip->hasUTIME = kCommandNotAvailable; + cip->hasCLNT = kCommandNotAvailable; + cip->hasMLST = kCommandNotAvailable; + cip->hasMLSD = kCommandNotAvailable; + return (kNoErr); + } + + rp = InitResponse(); + if (rp == NULL) { + cip->errNo = kErrMallocFailed; + result = cip->errNo; + } else { + rp->printMode = (kResponseNoPrint|kResponseNoSave); + result = RCmd(cip, rp, "FEAT"); + if (result < kNoErr) { + DoneWithResponse(cip, rp); + return (result); + } else if (result != 2) { + /* We cheat here and pre-populate some + * fields when the server is wu-ftpd. + * This server is very common and we + * know it has always had these. + */ + if (cip->serverType == kServerTypeWuFTPd) { + cip->hasPASV = kCommandAvailable; + cip->hasSIZE = kCommandAvailable; + cip->hasMDTM = kCommandAvailable; + cip->hasREST = kCommandAvailable; + cip->NLSTfileParamWorks = kCommandAvailable; + } else if (cip->serverType == kServerTypeNcFTPd) { + cip->hasPASV = kCommandAvailable; + cip->hasSIZE = kCommandAvailable; + cip->hasMDTM = kCommandAvailable; + cip->hasREST = kCommandAvailable; + cip->NLSTfileParamWorks = kCommandAvailable; + } + + /* Newer commands are only shown in FEAT, + * so we don't have to do the "try it, + * then save that it didn't work" thing. + */ + cip->hasMLST = kCommandNotAvailable; + cip->hasMLSD = kCommandNotAvailable; + } else { + cip->hasFEAT = kCommandAvailable; + + for (lp = rp->msg.first; lp != NULL; lp = lp->next) { + /* If first character was not a space it is + * either: + * + * (a) The header line in the response; + * (b) The trailer line in the response; + * (c) A protocol violation. + */ + cp = lp->line; + if (*cp++ != ' ') + continue; + if (ISTRNCMP(cp, "PASV", 4) == 0) { + cip->hasPASV = kCommandAvailable; + } else if (ISTRNCMP(cp, "SIZE", 4) == 0) { + cip->hasSIZE = kCommandAvailable; + } else if (ISTRNCMP(cp, "MDTM", 4) == 0) { + cip->hasMDTM = kCommandAvailable; + } else if (ISTRNCMP(cp, "REST", 4) == 0) { + cip->hasREST = kCommandAvailable; + } else if (ISTRNCMP(cp, "UTIME", 5) == 0) { + cip->hasUTIME = kCommandAvailable; + } else if (ISTRNCMP(cp, "MLST", 4) == 0) { + cip->hasMLST = kCommandAvailable; + cip->hasMLSD = kCommandAvailable; + FTPExamineMlstFeatures(cip, cp + 5); + } else if (ISTRNCMP(cp, "CLNT", 4) == 0) { + cip->hasCLNT = kCommandAvailable; + } else if (ISTRNCMP(cp, "Compliance Level: ", 18) == 0) { + /* Probably only NcFTPd will ever implement this. + * But we use it internally to differentiate + * between different NcFTPd implementations of + * IETF extensions. + */ + cip->ietfCompatLevel = atoi(cp + 18); + } + } + } + + ReInitResponse(cip, rp); + result = RCmd(cip, rp, "HELP SITE"); + if (result == 2) { + for (lp = rp->msg.first; lp != NULL; lp = lp->next) { + cp = lp->line; + if (strstr(cp, "RETRBUFSIZE") != NULL) + cip->hasRETRBUFSIZE = kCommandAvailable; + if (strstr(cp, "RBUFSZ") != NULL) + cip->hasRBUFSZ = kCommandAvailable; + /* See if RBUFSIZ matches (but not STORBUFSIZE) */ + if ( + ((p = strstr(cp, "RBUFSIZ")) != NULL) && + ( + (p == cp) || + ((p > cp) && (!isupper(p[-1]))) + ) + ) + cip->hasRBUFSIZ = kCommandAvailable; + if (strstr(cp, "STORBUFSIZE") != NULL) + cip->hasSTORBUFSIZE = kCommandAvailable; + if (strstr(cp, "SBUFSIZ") != NULL) + cip->hasSBUFSIZ = kCommandAvailable; + if (strstr(cp, "SBUFSZ") != NULL) + cip->hasSBUFSZ = kCommandAvailable; + if (strstr(cp, "BUFSIZE") != NULL) + cip->hasBUFSIZE = kCommandAvailable; + } + } + DoneWithResponse(cip, rp); + } + + return (kNoErr); +} /* FTPQueryFeatures */ + + + +int +FTPCloseHost(const FTPCIPtr cip) +{ + ResponsePtr rp; + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + /* Data connection shouldn't be open normally. */ + if (cip->dataSocket != kClosedFileDescriptor) + FTPAbortDataTransfer(cip); + + result = kNoErr; + if (cip->connected != 0) { + rp = InitResponse(); + if (rp == NULL) { + cip->errNo = kErrMallocFailed; + result = cip->errNo; + } else { + rp->eofOkay = 1; /* We are expecting EOF after this cmd. */ + cip->eofOkay = 1; + (void) RCmd(cip, rp, "QUIT"); + DoneWithResponse(cip, rp); + } + } + + CloseControlConnection(cip); + + /* Dispose dynamic data structures, so you won't leak + * if you OpenHost with this again. + */ + FTPDeallocateHost(cip); + return (result); +} /* FTPCloseHost */ + + + + +void +FTPShutdownHost(const FTPCIPtr cip) +{ +#ifdef SIGPIPE + FTPSigProc osigpipe; +#endif + + if (cip == NULL) + return; + if (strcmp(cip->magic, kLibraryMagic)) + return; + +#ifdef SIGPIPE + osigpipe = signal(SIGPIPE, (FTPSigProc) SIG_IGN); +#endif + + /* Linger could cause close to block, so unset it. */ + if (cip->dataSocket != kClosedFileDescriptor) + (void) SetLinger(cip, cip->dataSocket, 0); + CloseDataConnection(cip); /* Shouldn't be open normally. */ + + /* Linger should already be turned off for this. */ + CloseControlConnection(cip); + + FTPDeallocateHost(cip); + +#ifdef SIGPIPE + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); +#endif +} /* FTPShutdownHost */ + + + + +void +URLCopyToken(char *dst, size_t dsize, const char *src, size_t howmuch) +{ + char *dlim; + const char *slim; + unsigned int hc; + int c; + char h[4]; + + dlim = dst + dsize - 1; /* leave room for \0 */ + slim = src + howmuch; + while (src < slim) { + c = *src++; + if (c == '\0') + break; + if (c == '%') { + /* hex representation */ + if (src < slim + 2) { + h[0] = *src++; + h[1] = *src++; + h[2] = '\0'; + hc = 0xeeff; + if ((sscanf(h, "%x", &hc) >= 0) && (hc != 0xeeff)) { + if (dst < dlim) { + *(unsigned char *)dst = (unsigned char) hc; + dst++; + } + } + } else { + break; + } + } else { + *dst++ = (char) c; + } + } + *dst = '\0'; +} /* URLCopyToken */ + + + + +int +FTPDecodeURL( + const FTPCIPtr cip, /* area pointed to may be modified */ + char *const url, /* always modified */ + LineListPtr cdlist, /* always modified */ + char *const fn, /* always modified */ + const size_t fnsize, + int *const xtype, /* optional; may be modified */ + int *const wantnlst /* optional; always modified */ +) +{ + char *cp; + char *hstart, *hend; + char *h2start; + char *at1; + char portstr[32]; + int port; + int sc; + char *lastslash; + char *parsestr; + char *tok; + char subdir[128]; + char *semi; + + InitLineList(cdlist); + *fn = '\0'; + if (wantnlst != NULL) + *wantnlst = 0; + if (xtype != NULL) + *xtype = kTypeBinary; + + cp = NULL; /* shut up warnings */ +#ifdef HAVE_STRCASECMP + if (strncasecmp(url, " */ + *cp = '\0'; + cp = url + 11; + } else if (strncasecmp(url, "ftp://", 6) == 0) { + cp = url + 6; + } else { + return (-1); /* not a RFC 1738 URL */ + } +#else /* HAVE_STRCASECMP */ + if (strncmp(url, " */ + *cp = '\0'; + cp = url + 11; + } else if (strncmp(url, "ftp://", 6) == 0) { + cp = url + 6; + } else { + return (-1); /* not a RFC 1738 URL */ + } +#endif /* HAVE_STRCASECMP */ + + /* //:@:/ */ + + at1 = NULL; + for (hstart = cp; ; cp++) { + if (*cp == '@') { + if (at1 == NULL) + at1 = cp; + else + return (kMalformedURL); + } else if ((*cp == '\0') || (*cp == '/')) { + hend = cp; + break; + } + } + + sc = *hend; + *hend = '\0'; + if (at1 == NULL) { + /* no user or password */ + h2start = hstart; + } else { + *at1 = '\0'; + cp = strchr(hstart, ':'); + if (cp == NULL) { + /* whole thing is the user name then */ + URLCopyToken(cip->user, sizeof(cip->user), hstart, (size_t) (at1 - hstart)); + } else if (strchr(cp + 1, ':') != NULL) { + /* Too many colons */ + return (kMalformedURL); + } else { + URLCopyToken(cip->user, sizeof(cip->user), hstart, (size_t) (cp - hstart)); + URLCopyToken(cip->pass, sizeof(cip->pass), cp + 1, (size_t) (at1 - (cp + 1))); + } + *at1 = '@'; + h2start = at1 + 1; + } + + cp = strchr(h2start, ':'); + if (cp == NULL) { + /* whole thing is the host then */ + URLCopyToken(cip->host, sizeof(cip->host), h2start, (size_t) (hend - h2start)); + } else if (strchr(cp + 1, ':') != NULL) { + /* Too many colons */ + return (kMalformedURL); + } else { + URLCopyToken(cip->host, sizeof(cip->host), h2start, (size_t) (cp - h2start)); + URLCopyToken(portstr, sizeof(portstr), cp + 1, (size_t) (hend - (cp + 1))); + port = atoi(portstr); + if (port > 0) + cip->port = port; + } + + *hend = (char) sc; + if ((*hend == '\0') || ((*hend == '/') && (hend[1] == '\0'))) { + /* no path, okay */ + return (0); + } + + lastslash = strrchr(hend, '/'); + if (lastslash == NULL) { + /* no path, okay */ + return (0); + } + *lastslash = '\0'; + + if ((semi = strchr(lastslash + 1, ';')) != NULL) { + *semi++ = '\0'; +#ifdef HAVE_STRCASECMP + if (strcasecmp(semi, "type=i") == 0) { + if (xtype != NULL) + *xtype = kTypeBinary; + } else if (strcasecmp(semi, "type=a") == 0) { + if (xtype != NULL) + *xtype = kTypeAscii; + } else if (strcasecmp(semi, "type=b") == 0) { + if (xtype != NULL) + *xtype = kTypeBinary; + } else if (strcasecmp(semi, "type=d") == 0) { + if (wantnlst != NULL) { + *wantnlst = 1; + if (xtype != NULL) + *xtype = kTypeAscii; + } else { + /* You didn't want these. */ + return (kMalformedURL); + } + } +#else /* HAVE_STRCASECMP */ + if (strcmp(semi, "type=i") == 0) { + if (xtype != NULL) + *xtype = kTypeBinary; + } else if (strcmp(semi, "type=a") == 0) { + if (xtype != NULL) + *xtype = kTypeAscii; + } else if (strcmp(semi, "type=b") == 0) { + if (xtype != NULL) + *xtype = kTypeBinary; + } else if (strcmp(semi, "type=d") == 0) { + if (wantnlst != NULL) { + *wantnlst = 1; + if (xtype != NULL) + *xtype = kTypeAscii; + } else { + /* You didn't want these. */ + return (kMalformedURL); + } + } +#endif /* HAVE_STRCASECMP */ + } + URLCopyToken(fn, fnsize, lastslash + 1, strlen(lastslash + 1)); + for (parsestr = hend; (tok = strtok(parsestr, "/")) != NULL; parsestr = NULL) { + URLCopyToken(subdir, sizeof(subdir), tok, strlen(tok)); + (void) AddLine(cdlist, subdir); + } + *lastslash = '/'; + return (kNoErr); +} /* FTPDecodeURL */ + + + + +int +FTPOpenHost(const FTPCIPtr cip) +{ + int result; + time_t t0, t1; + int elapsed; + int dials; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (cip->host[0] == '\0') { + cip->errNo = kErrBadParameter; + return (kErrBadParameter); + } + + for ( result = kErrConnectMiscErr, dials = 0; + cip->maxDials < 0 || dials < cip->maxDials; + dials++) + { + /* Allocate (or if the host was closed, reallocate) + * the transfer data buffer. + */ + result = FTPAllocateHost(cip); + if (result < 0) + return (result); + + if (dials > 0) + PrintF(cip, "Retry Number: %d\n", dials); + if (cip->redialStatusProc != 0) + (*cip->redialStatusProc)(cip, kRedialStatusDialing, dials); + (void) time(&t0); + result = OpenControlConnection(cip, cip->host, cip->port); + (void) time(&t1); + if (result == kNoErr) { + /* We were hooked up successfully. */ + PrintF(cip, "Connected to %s.\n", cip->host); + + result = FTPLoginHost(cip); + if (result == kNoErr) { + (void) FTPQueryFeatures(cip); + break; + } + + /* Close and try again. */ + (void) FTPCloseHost(cip); + + /* Originally we also stopped retyring if + * we got kErrBadRemoteUser and non-anonymous, + * but some FTP servers apparently do their + * max user check after the username is sent. + */ + if (result == kErrBadRemoteUserOrPassword /* || (result == kErrBadRemoteUser) */) { + if (strcmp(cip->user, "anonymous") != 0) { + /* Non-anonymous login was denied, and + * retrying is not going to help. + */ + break; + } + } + } else if ((result != kErrConnectRetryableErr) && (result != kErrConnectRefused) && (result != kErrRemoteHostClosedConnection)) { + /* Irrecoverable error, so don't bother redialing. + * The error message should have already been printed + * from OpenControlConnection(). + */ + PrintF(cip, "Cannot recover from miscellaneous open error %d.\n", result); + return result; + } + + /* Retryable error, wait and then redial. */ + if (cip->redialDelay > 0) { + /* But don't sleep if this is the last loop. */ + if ((cip->maxDials < 0) || (dials < (cip->maxDials - 1))) { + elapsed = (int) (t1 - t0); + if (elapsed < cip->redialDelay) { + PrintF(cip, "Sleeping %u seconds.\n", + (unsigned) cip->redialDelay - elapsed); + if (cip->redialStatusProc != 0) + (*cip->redialStatusProc)(cip, kRedialStatusSleeping, cip->redialDelay - elapsed); + (void) sleep((unsigned) cip->redialDelay - elapsed); + } + } + } + } + return (result); +} /* FTPOpenHost */ + + + + +int +FTPOpenHostNoLogin(const FTPCIPtr cip) +{ + int result; + time_t t0, t1; + int elapsed; + int dials; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + if (cip->host[0] == '\0') { + cip->errNo = kErrBadParameter; + return (kErrBadParameter); + } + + for ( result = kErrConnectMiscErr, dials = 0; + cip->maxDials < 0 || dials < cip->maxDials; + dials++) + { + + /* Allocate (or if the host was closed, reallocate) + * the transfer data buffer. + */ + result = FTPAllocateHost(cip); + if (result < 0) + return (result); + + if (dials > 0) + PrintF(cip, "Retry Number: %d\n", dials); + if (cip->redialStatusProc != 0) + (*cip->redialStatusProc)(cip, kRedialStatusDialing, dials); + (void) time(&t0); + result = OpenControlConnection(cip, cip->host, cip->port); + (void) time(&t1); + if (result == kNoErr) { + /* We were hooked up successfully. */ + PrintF(cip, "Connected to %s.\n", cip->host); + + /* Not logging in... */ + if (result == kNoErr) + break; + } else if ((result != kErrConnectRetryableErr) && (result != kErrConnectRefused) && (result != kErrRemoteHostClosedConnection)) { + /* Irrecoverable error, so don't bother redialing. + * The error message should have already been printed + * from OpenControlConnection(). + */ + PrintF(cip, "Cannot recover from miscellaneous open error %d.\n", result); + return result; + } + + /* Retryable error, wait and then redial. */ + if (cip->redialDelay > 0) { + /* But don't sleep if this is the last loop. */ + if ((cip->maxDials < 0) || (dials < (cip->maxDials - 1))) { + elapsed = (int) (t1 - t0); + if (elapsed < cip->redialDelay) { + PrintF(cip, "Sleeping %u seconds.\n", + (unsigned) cip->redialDelay - elapsed); + if (cip->redialStatusProc != 0) + (*cip->redialStatusProc)(cip, kRedialStatusSleeping, cip->redialDelay - elapsed); + (void) sleep((unsigned) cip->redialDelay - elapsed); + } + } + } + } + return (result); +} /* FTPOpenHostNoLogin */ + + + + +int +FTPInitConnectionInfo(const FTPLIPtr lip, const FTPCIPtr cip, size_t bufSize) +{ + size_t siz; + + if ((lip == NULL) || (cip == NULL) || (bufSize == 0)) + return (kErrBadParameter); + + siz = sizeof(FTPConnectionInfo); + (void) memset(cip, 0, siz); + + if (strcmp(lip->magic, kLibraryMagic)) + return (kErrBadMagic); + + cip->buf = NULL; /* denote that it needs to be allocated. */ + cip->bufSize = bufSize; + cip->port = lip->defaultPort; + cip->firewallPort = lip->defaultPort; + cip->maxDials = kDefaultMaxDials; + cip->redialDelay = kDefaultRedialDelay; + cip->xferTimeout = kDefaultXferTimeout; + cip->connTimeout = kDefaultConnTimeout; + cip->ctrlTimeout = kDefaultCtrlTimeout; + cip->abortTimeout = kDefaultAbortTimeout; + cip->ctrlSocketR = kClosedFileDescriptor; + cip->ctrlSocketW = kClosedFileDescriptor; + cip->dataPortMode = kSendPortMode; + cip->dataSocket = kClosedFileDescriptor; + cip->lip = lip; + cip->hasPASV = kCommandAvailabilityUnknown; + cip->hasSIZE = kCommandAvailabilityUnknown; + cip->hasMDTM = kCommandAvailabilityUnknown; + cip->hasREST = kCommandAvailabilityUnknown; + cip->hasNLST_d = kCommandAvailabilityUnknown; + cip->hasUTIME = kCommandAvailabilityUnknown; + cip->hasFEAT = kCommandAvailabilityUnknown; + cip->hasMLSD = kCommandAvailabilityUnknown; + cip->hasMLST = kCommandAvailabilityUnknown; + cip->hasCLNT = kCommandAvailabilityUnknown; + cip->hasRETRBUFSIZE = kCommandAvailabilityUnknown; + cip->hasRBUFSIZ = kCommandAvailabilityUnknown; + cip->hasRBUFSZ = kCommandAvailabilityUnknown; + cip->hasSTORBUFSIZE = kCommandAvailabilityUnknown; + cip->hasSBUFSIZ = kCommandAvailabilityUnknown; + cip->hasSBUFSZ = kCommandAvailabilityUnknown; + cip->STATfileParamWorks = kCommandAvailabilityUnknown; + cip->NLSTfileParamWorks = kCommandAvailabilityUnknown; + cip->firewallType = kFirewallNotInUse; + cip->startingWorkingDirectory = NULL; + (void) STRNCPY(cip->magic, kLibraryMagic); + (void) STRNCPY(cip->user, "anonymous"); + return (kNoErr); +} /* FTPInitConnectionInfo */ + + + + +int +FTPRebuildConnectionInfo(const FTPLIPtr lip, const FTPCIPtr cip) +{ + char *buf; + + cip->lip = lip; + cip->debugLog = NULL; + cip->errLog = NULL; + cip->debugLogProc = NULL; + cip->errLogProc = NULL; + cip->buf = NULL; + cip->cin = NULL; + cip->cout = NULL; + cip->errNo = 0; + cip->progress = NULL; + cip->rname = NULL; + cip->lname = NULL; + cip->onConnectMsgProc = NULL; + cip->redialStatusProc = NULL; + cip->printResponseProc = NULL; + cip->onLoginMsgProc = NULL; + cip->passphraseProc = NULL; + cip->startingWorkingDirectory = NULL; + cip->asciiFilenameExtensions = NULL; + + (void) memset(&cip->lastFTPCmdResultLL, 0, sizeof(LineList)); + + /* Allocate a new buffer. */ + buf = (char *) calloc((size_t) 1, cip->bufSize); + if (buf == NULL) { + cip->errNo = kErrMallocFailed; + return (kErrMallocFailed); + } + cip->buf = buf; + + /* Reattach the FILE pointers for use with the Std I/O library + * routines. + */ + if ((cip->cin = _fdopen(cip->ctrlSocketR, "r")) == NULL) { + cip->errNo = kErrFdopenR; + cip->ctrlSocketR = kClosedFileDescriptor; + cip->ctrlSocketW = kClosedFileDescriptor; + return (kErrFdopenR); + } + + if ((cip->cout = _fdopen(cip->ctrlSocketW, "w")) == NULL) { + CloseFile(&cip->cin); + cip->errNo = kErrFdopenW; + cip->ctrlSocketR = kClosedFileDescriptor; + cip->ctrlSocketW = kClosedFileDescriptor; + return (kErrFdopenW); + } + +#if USE_SIO + if (InitSReadlineInfo(&cip->ctrlSrl, cip->ctrlSocketR, cip->srlBuf, sizeof(cip->srlBuf), (int) cip->ctrlTimeout, 1) < 0) { + cip->errNo = kErrFdopenW; + CloseFile(&cip->cin); + cip->errNo = kErrFdopenW; + cip->ctrlSocketR = kClosedFileDescriptor; + cip->ctrlSocketW = kClosedFileDescriptor; + return (kErrFdopenW); + } +#endif + return (kNoErr); +} /* FTPRebuildConnectionInfo */ + + + + +int +FTPInitLibrary(const FTPLIPtr lip) +{ + struct servent *ftp; + + if (lip == NULL) + return (kErrBadParameter); + + (void) memset(lip, 0, sizeof(FTPLibraryInfo)); + if ((ftp = getservbyname("ftp", "tcp")) == NULL) + lip->defaultPort = (unsigned int) kDefaultFTPPort; + else + lip->defaultPort = (unsigned int) ntohs(ftp->s_port); + + lip->init = 1; + (void) STRNCPY(lip->magic, kLibraryMagic); + + /* We'll initialize the defaultAnonPassword field + * later when we try the first anon ftp connection. + */ + +#ifdef HAVE_LIBSOCKS + SOCKSinit("libncftp"); + lip->socksInit = 1; +#endif + return (kNoErr); +} /* FTPInitLibrary */ + +/* Open.c */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/rcmd.c b/modules/rosapps/applications/net/ncftp/libncftp/rcmd.c new file mode 100644 index 00000000000..d26864064e2 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/rcmd.c @@ -0,0 +1,1038 @@ +/* rcmd.c + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#include "syshdrs.h" + +#if !defined(NO_SIGNALS) && (USE_SIO || !defined(SIGALRM) || !defined(SIGPIPE) || !defined(SIGINT)) +# define NO_SIGNALS 1 +#endif + +#ifndef NO_SIGNALS + +#ifdef HAVE_SIGSETJMP +static sigjmp_buf gBrokenCtrlJmp; +#else +static jmp_buf gBrokenCtrlJmp; +#endif /* HAVE_SIGSETJMP */ + +static void +BrokenCtrl(int UNUSED(signumIgnored)) +{ + LIBNCFTP_USE_VAR(signumIgnored); /* Shut up gcc */ +#ifdef HAVE_SIGSETJMP + siglongjmp(gBrokenCtrlJmp, 1); +#else + longjmp(gBrokenCtrlJmp, 1); +#endif /* HAVE_SIGSETJMP */ +} /* BrokenCtrl */ + +#endif /* NO_SIGNALS */ + + +/* A 'Response' parameter block is simply zeroed to be considered init'ed. */ +ResponsePtr +InitResponse(void) +{ + ResponsePtr rp; + + rp = (ResponsePtr) calloc(SZ(1), sizeof(Response)); + if (rp != NULL) + InitLineList(&rp->msg); + return (rp); +} /* InitResponse */ + + + + +/* If we don't print it to the screen, we may want to save it to our + * trace log. + */ +void +TraceResponse(const FTPCIPtr cip, ResponsePtr rp) +{ + LinePtr lp; + + if (rp != NULL) { + lp = rp->msg.first; + if (lp != NULL) { + PrintF(cip, "%3d: %s\n", rp->code, lp->line); + for (lp = lp->next; lp != NULL; lp = lp->next) + PrintF(cip, " %s\n", lp->line); + } + } +} /* TraceResponse */ + + + + + +void +PrintResponse(const FTPCIPtr cip, LineListPtr llp) +{ + LinePtr lp; + + if (llp != NULL) { + for (lp = llp->first; lp != NULL; lp = lp->next) + PrintF(cip, "%s\n", lp->line); + } +} /* PrintResponse */ + + + + + +static void +SaveLastResponse(const FTPCIPtr cip, ResponsePtr rp) +{ + if (rp == NULL) { + cip->lastFTPCmdResultStr[0] = '\0'; + cip->lastFTPCmdResultNum = -1; + DisposeLineListContents(&cip->lastFTPCmdResultLL); + } else if ((rp->msg.first == NULL) || (rp->msg.first->line == NULL)) { + cip->lastFTPCmdResultStr[0] = '\0'; + cip->lastFTPCmdResultNum = rp->code; + DisposeLineListContents(&cip->lastFTPCmdResultLL); + } else { + (void) STRNCPY(cip->lastFTPCmdResultStr, rp->msg.first->line); + cip->lastFTPCmdResultNum = rp->code; + + /* Dispose previous command's line list. */ + DisposeLineListContents(&cip->lastFTPCmdResultLL); + + /* Save this command's line list. */ + cip->lastFTPCmdResultLL = rp->msg; + } +} /* SaveLastResponse */ + + + +void +DoneWithResponse(const FTPCIPtr cip, ResponsePtr rp) +{ + /* Dispose space taken up by the Response, and clear it out + * again. For some reason, I like to return memory to zeroed + * when not in use. + */ + if (rp != NULL) { + TraceResponse(cip, rp); + if (cip->printResponseProc != 0) { + if ((rp->printMode & kResponseNoProc) == 0) + (*cip->printResponseProc)(cip, rp); + } + if ((rp->printMode & kResponseNoSave) == 0) + SaveLastResponse(cip, rp); + else + DisposeLineListContents(&rp->msg); + (void) memset(rp, 0, sizeof(Response)); + free(rp); + } +} /* DoneWithResponse */ + + + + +/* This takes an existing Response and recycles it, by clearing out + * the current contents. + */ +void +ReInitResponse(const FTPCIPtr cip, ResponsePtr rp) +{ + if (rp != NULL) { + TraceResponse(cip, rp); + if (cip->printResponseProc != 0) { + if ((rp->printMode & kResponseNoProc) == 0) + (*cip->printResponseProc)(cip, rp); + } + if ((rp->printMode & kResponseNoSave) == 0) + SaveLastResponse(cip, rp); + else + DisposeLineListContents(&rp->msg); + (void) memset(rp, 0, sizeof(Response)); + } +} /* ReInitResponse */ + + + + +#ifndef NO_SIGNALS + +/* Since the control stream is defined by the Telnet protocol (RFC 854), + * we follow Telnet rules when reading the control stream. We use this + * routine when we want to read a response from the host. + */ +int +GetTelnetString(const FTPCIPtr cip, char *str, size_t siz, FILE *cin, FILE *cout) +{ + int c; + size_t n; + int eofError; + char *cp; + + cp = str; + --siz; /* We'll need room for the \0. */ + + if ((cin == NULL) || (cout == NULL)) { + eofError = -1; + goto done; + } + + for (n = (size_t)0, eofError = 0; ; ) { + c = fgetc(cin); +checkChar: + if (c == EOF) { +eof: + eofError = -1; + break; + } else if (c == '\r') { + /* A telnet string can have a CR by itself. But to denote that, + * the protocol uses \r\0; an end of line is denoted \r\n. + */ + c = fgetc(cin); + if (c == '\n') { + /* Had \r\n, so done. */ + goto done; + } else if (c == EOF) { + goto eof; + } else if (c == '\0') { + c = '\r'; + goto addChar; + } else { + /* Telnet protocol violation! */ + goto checkChar; + } + } else if (c == '\n') { + /* Really shouldn't get here. If we do, the other side + * violated the TELNET protocol, since eoln's are CR/LF, + * and not just LF. + */ + PrintF(cip, "TELNET protocol violation: raw LF.\n"); + goto done; + } else if (c == IAC) { + /* Since the control connection uses the TELNET protocol, + * we have to handle some of its commands ourselves. + * IAC is the protocol's escape character, meaning that + * the next character after the IAC (Interpret as Command) + * character is a telnet command. But, if there just + * happened to be a character in the text stream with the + * same numerical value of IAC, 255, the sender denotes + * that by having an IAC followed by another IAC. + */ + + /* Get the telnet command. */ + c = fgetc(cin); + + switch (c) { + case WILL: + case WONT: + /* Get the option code. */ + c = fgetc(cin); + + /* Tell the other side that we don't want + * to do what they're offering to do. + */ + (void) fprintf(cout, "%c%c%c",IAC,DONT,c); + (void) fflush(cout); + break; + case DO: + case DONT: + /* Get the option code. */ + c = fgetc(cin); + + /* The other side said they are DOing (or not) + * something, which would happen if our side + * asked them to. Since we didn't do that, + * ask them to not do this option. + */ + (void) fprintf(cout, "%c%c%c",IAC,WONT,c); + (void) fflush(cout); + break; + + case EOF: + goto eof; + + default: + /* Just add this character, since it was most likely + * just an escaped IAC character. + */ + goto addChar; + } + } else { +addChar: + /* If the buffer supplied has room, add this character to it. */ + if (n < siz) { + *cp++ = c; + ++n; + } + } + } + +done: + *cp = '\0'; + return (eofError); +} /* GetTelnetString */ + +#endif /* NO_SIGNALS */ + + + +/* Returns 0 if a response was read, or (-1) if an error occurs. + * This reads the entire response text into a LineList, which is kept + * in the 'Response' structure. + */ +int +GetResponse(const FTPCIPtr cip, ResponsePtr rp) +{ + longstring str; + int eofError; + str16 code; + char *cp; + int continuation; + volatile FTPCIPtr vcip; +#ifdef NO_SIGNALS + int result; +#else /* NO_SIGNALS */ + volatile FTPSigProc osigpipe; + int sj; +#endif /* NO_SIGNALS */ + + /* RFC 959 states that a reply may span multiple lines. A single + * line message would have the 3-digit code then the msg. + * A multi-line message would have the code and the first + * line of the msg, then additional lines, until the last line, + * which has the code and last line of the msg. + * + * For example: + * 123-First line + * Second line + * 234 A line beginning with numbers + * 123 The last line + */ + +#ifdef NO_SIGNALS + vcip = cip; +#else /* NO_SIGNALS */ + osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenCtrl); + vcip = cip; + +#ifdef HAVE_SIGSETJMP + sj = sigsetjmp(gBrokenCtrlJmp, 1); +#else + sj = setjmp(gBrokenCtrlJmp); +#endif /* HAVE_SIGSETJMP */ + + if (sj != 0) { + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); + FTPShutdownHost(vcip); + vcip->errNo = kErrRemoteHostClosedConnection; + return(vcip->errNo); + } +#endif /* NO_SIGNALS */ + +#ifdef NO_SIGNALS + cp = str; + eofError = 0; + if (cip->dataTimedOut > 0) { + /* Give up immediately unless the server had already + * sent a message. Odds are since the data is timed + * out, so is the control. + */ + if (SWaitUntilReadyForReading(cip->ctrlSocketR, 0) == 0) { + /* timeout */ + Error(cip, kDontPerror, "Could not read reply from control connection -- timed out.\n"); + FTPShutdownHost(vcip); + cip->errNo = kErrControlTimedOut; + return (cip->errNo); + } + } + result = SReadline(&cip->ctrlSrl, str, sizeof(str) - 1); + if (result == kTimeoutErr) { + /* timeout */ + Error(cip, kDontPerror, "Could not read reply from control connection -- timed out.\n"); + FTPShutdownHost(vcip); + cip->errNo = kErrControlTimedOut; + return (cip->errNo); + } else if (result == 0) { + /* eof */ + eofError = 1; + rp->hadEof = 1; + if (rp->eofOkay == 0) + Error(cip, kDontPerror, "Remote host has closed the connection.\n"); + FTPShutdownHost(vcip); + cip->errNo = kErrRemoteHostClosedConnection; + return (cip->errNo); + } else if (result < 0) { + /* error */ + Error(cip, kDoPerror, "Could not read reply from control connection"); + FTPShutdownHost(vcip); + cip->errNo = kErrInvalidReplyFromServer; + return (cip->errNo); + } + + if (str[result - 1] == '\n') + str[result - 1] = '\0'; + +#else /* NO_SIGNALS */ + /* Get the first line of the response. */ + eofError = GetTelnetString(cip, str, sizeof(str), cip->cin, cip->cout); + + cp = str; + if (*cp == '\0') { + if (eofError < 0) { + /* No bytes read for reply, and EOF detected. */ + rp->hadEof = 1; + if (rp->eofOkay == 0) + Error(cip, kDontPerror, "Remote host has closed the connection.\n"); + FTPShutdownHost(vcip); + cip->errNo = kErrRemoteHostClosedConnection; + (void) signal(SIGPIPE, osigpipe); + return(cip->errNo); + } + } +#endif /* NO_SIGNALS */ + + if (!isdigit((int) *cp)) { + Error(cip, kDontPerror, "Invalid reply: \"%s\"\n", cp); + cip->errNo = kErrInvalidReplyFromServer; +#ifndef NO_SIGNALS + (void) signal(SIGPIPE, osigpipe); +#endif + return (cip->errNo); + } + + rp->codeType = *cp - '0'; + cp += 3; + continuation = (*cp == '-'); + *cp++ = '\0'; + (void) STRNCPY(code, str); + rp->code = atoi(code); + (void) AddLine(&rp->msg, cp); + if (eofError < 0) { + /* Read reply, but EOF was there also. */ + rp->hadEof = 1; + } + + while (continuation) { + +#ifdef NO_SIGNALS + result = SReadline(&cip->ctrlSrl, str, sizeof(str) - 1); + if (result == kTimeoutErr) { + /* timeout */ + Error(cip, kDontPerror, "Could not read reply from control connection -- timed out.\n"); + FTPShutdownHost(vcip); + cip->errNo = kErrControlTimedOut; + return (cip->errNo); + } else if (result == 0) { + /* eof */ + eofError = 1; + rp->hadEof = 1; + if (rp->eofOkay == 0) + Error(cip, kDontPerror, "Remote host has closed the connection.\n"); + FTPShutdownHost(vcip); + cip->errNo = kErrRemoteHostClosedConnection; + return (cip->errNo); + } else if (result < 0) { + /* error */ + Error(cip, kDoPerror, "Could not read reply from control connection"); + FTPShutdownHost(vcip); + cip->errNo = kErrInvalidReplyFromServer; + return (cip->errNo); + } + + if (str[result - 1] == '\n') + str[result - 1] = '\0'; +#else /* NO_SIGNALS */ + eofError = GetTelnetString(cip, str, sizeof(str), cip->cin, cip->cout); + if (eofError < 0) { + /* Read reply, but EOF was there also. */ + rp->hadEof = 1; + continuation = 0; + } +#endif /* NO_SIGNALS */ + cp = str; + if (strncmp(code, cp, SZ(3)) == 0) { + cp += 3; + if (*cp == ' ') + continuation = 0; + ++cp; + } + (void) AddLine(&rp->msg, cp); + } + + if (rp->code == 421) { + /* + * 421 Service not available, closing control connection. + * This may be a reply to any command if the service knows it + * must shut down. + */ + if (rp->eofOkay == 0) + Error(cip, kDontPerror, "Remote host has closed the connection.\n"); + FTPShutdownHost(vcip); + cip->errNo = kErrRemoteHostClosedConnection; +#ifndef NO_SIGNALS + (void) signal(SIGPIPE, osigpipe); +#endif + return(cip->errNo); + } + +#ifndef NO_SIGNALS + (void) signal(SIGPIPE, osigpipe); +#endif + return (kNoErr); +} /* GetResponse */ + + + + +/* This creates the complete command text to send, and writes it + * on the stream. + */ +#ifdef NO_SIGNALS + +static int +SendCommand(const FTPCIPtr cip, const char *cmdspec, va_list ap) +{ + longstring command; + int result; + + if (cip->ctrlSocketW != kClosedFileDescriptor) { +#ifdef HAVE_VSNPRINTF + (void) vsnprintf(command, sizeof(command) - 1, cmdspec, ap); + command[sizeof(command) - 1] = '\0'; +#else + (void) vsprintf(command, cmdspec, ap); +#endif + if ((strncmp(command, "PASS", SZ(4)) != 0) || ((strcmp(cip->user, "anonymous") == 0) && (cip->firewallType == kFirewallNotInUse))) + PrintF(cip, "Cmd: %s\n", command); + else + PrintF(cip, "Cmd: %s\n", "PASS xxxxxxxx"); + (void) STRNCAT(command, "\r\n"); /* Use TELNET end-of-line. */ + cip->lastFTPCmdResultStr[0] = '\0'; + cip->lastFTPCmdResultNum = -1; + + result = SWrite(cip->ctrlSocketW, command, strlen(command), (int) cip->ctrlTimeout, 0); + + if (result < 0) { + cip->errNo = kErrSocketWriteFailed; + Error(cip, kDoPerror, "Could not write to control stream.\n"); + return (cip->errNo); + } + return (kNoErr); + } + return (kErrNotConnected); +} /* SendCommand */ + +#else /* NO_SIGNALS */ + +static int +SendCommand(const FTPCIPtr cip, const char *cmdspec, va_list ap) +{ + longstring command; + int result; + volatile FTPCIPtr vcip; + volatile FTPSigProc osigpipe; + int sj; + + if (cip->cout != NULL) { +#ifdef HAVE_VSNPRINTF + (void) vsnprintf(command, sizeof(command) - 1, cmdspec, ap); + command[sizeof(command) - 1] = '\0'; +#else + (void) vsprintf(command, cmdspec, ap); +#endif + if ((strncmp(command, "PASS", SZ(4)) != 0) || ((strcmp(cip->user, "anonymous") == 0) && (cip->firewallType == kFirewallNotInUse))) + PrintF(cip, "Cmd: %s\n", command); + else + PrintF(cip, "Cmd: %s\n", "PASS xxxxxxxx"); + (void) STRNCAT(command, "\r\n"); /* Use TELNET end-of-line. */ + cip->lastFTPCmdResultStr[0] = '\0'; + cip->lastFTPCmdResultNum = -1; + + osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenCtrl); + vcip = cip; + +#ifdef HAVE_SIGSETJMP + sj = sigsetjmp(gBrokenCtrlJmp, 1); +#else + sj = setjmp(gBrokenCtrlJmp); +#endif /* HAVE_SIGSETJMP */ + + if (sj != 0) { + (void) signal(SIGPIPE, (FTPSigProc) osigpipe); + FTPShutdownHost(vcip); + if (vcip->eofOkay == 0) { + Error(cip, kDontPerror, "Remote host has closed the connection.\n"); + vcip->errNo = kErrRemoteHostClosedConnection; + return(vcip->errNo); + } + return (kNoErr); + } + + result = fputs(command, cip->cout); + if (result < 0) { + (void) signal(SIGPIPE, osigpipe); + cip->errNo = kErrSocketWriteFailed; + Error(cip, kDoPerror, "Could not write to control stream.\n"); + return (cip->errNo); + } + result = fflush(cip->cout); + if (result < 0) { + (void) signal(SIGPIPE, osigpipe); + cip->errNo = kErrSocketWriteFailed; + Error(cip, kDoPerror, "Could not write to control stream.\n"); + return (cip->errNo); + } + (void) signal(SIGPIPE, osigpipe); + return (kNoErr); + } + return (kErrNotConnected); +} /* SendCommand */ +#endif /* NO_SIGNALS */ + + + +/* For "simple" (i.e. not data transfer) commands, this routine is used + * to send the command and receive one response. It returns the codeType + * field of the 'Response' as the result, or a negative number upon error. + */ +/*VARARGS*/ +int +FTPCmd(const FTPCIPtr cip, const char *const cmdspec, ...) +{ + va_list ap; + int result; + ResponsePtr rp; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + rp = InitResponse(); + if (rp == NULL) { + result = kErrMallocFailed; + cip->errNo = kErrMallocFailed; + Error(cip, kDontPerror, "Malloc failed.\n"); + return (cip->errNo); + } + + va_start(ap, cmdspec); +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(cip->ctrlTimeout); +#endif /* NO_SIGNALS */ + result = SendCommand(cip, cmdspec, ap); + va_end(ap); + if (result < 0) { +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + return (result); + } + + /* Get the response to the command we sent. */ + result = GetResponse(cip, rp); +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + + if (result == kNoErr) + result = rp->codeType; + DoneWithResponse(cip, rp); + return (result); +} /* FTPCmd */ + + + + +/* This is for debugging the library -- don't use. */ +/*VARARGS*/ +int +FTPCmdNoResponse(const FTPCIPtr cip, const char *const cmdspec, ...) +{ + va_list ap; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + va_start(ap, cmdspec); +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(cip->ctrlTimeout); +#endif /* NO_SIGNALS */ + (void) SendCommand(cip, cmdspec, ap); +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + va_end(ap); + + return (kNoErr); +} /* FTPCmdNoResponse */ + + + + +int +WaitResponse(const FTPCIPtr cip, unsigned int sec) +{ + int result; + fd_set ss; + struct timeval tv; + int fd; + +#ifdef NO_SIGNALS + fd = cip->ctrlSocketR; +#else /* NO_SIGNALS */ + if (cip->cin == NULL) + return (-1); + fd = fileno(cip->cin); +#endif /* NO_SIGNALS */ + if (fd < 0) + return (-1); + FD_ZERO(&ss); + FD_SET(fd, &ss); + tv.tv_sec = (unsigned long) sec; + tv.tv_usec = 0; + result = select(fd + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, &tv); + return (result); +} /* WaitResponse */ + + + + +/* For "simple" (i.e. not data transfer) commands, this routine is used + * to send the command and receive one response. It returns the codeType + * field of the 'Response' as the result, or a negative number upon error. + */ + +/*VARARGS*/ +int +RCmd(const FTPCIPtr cip, ResponsePtr rp, const char *cmdspec, ...) +{ + va_list ap; + int result; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + va_start(ap, cmdspec); +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(cip->ctrlTimeout); +#endif /* NO_SIGNALS */ + result = SendCommand(cip, cmdspec, ap); + va_end(ap); + if (result < 0) { +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + return (result); + } + + /* Get the response to the command we sent. */ + result = GetResponse(cip, rp); +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + + if (result == kNoErr) + result = rp->codeType; + return (result); +} /* RCmd */ + + + +/* Returns -1 if an error occurred, or 0 if not. + * This differs from RCmd, which returns the code class of a response. + */ + +/*VARARGS*/ +int +FTPStartDataCmd(const FTPCIPtr cip, int netMode, int type, longest_int startPoint, const char *cmdspec, ...) +{ + va_list ap; + int result; + int respCode; + ResponsePtr rp; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + result = FTPSetTransferType(cip, type); + if (result < 0) + return (result); + + /* Re-set the cancellation flag. */ + cip->cancelXfer = 0; + + /* To transfer data, we do these things in order as specifed by + * the RFC. + * + * First, we tell the other side to set up a data line. This + * is done below by calling OpenDataConnection(), which sets up + * the socket. When we do that, the other side detects a connection + * attempt, so it knows we're there. Then tell the other side + * (by using listen()) that we're willing to receive a connection + * going to our side. + */ + + if ((result = OpenDataConnection(cip, cip->dataPortMode)) < 0) + goto done; + + /* If asked, attempt to start at a later position in the remote file. */ + if (startPoint != (longest_int) 0) { + if ((startPoint == kSizeUnknown) || ((result = SetStartOffset(cip, startPoint)) != 0)) + startPoint = (longest_int) 0; + } + cip->startPoint = startPoint; + + /* Now we tell the server what we want to do. This sends the + * the type of transfer we want (RETR, STOR, LIST, etc) and the + * parameters for that (files to send, directories to list, etc). + */ + va_start(ap, cmdspec); +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(cip->ctrlTimeout); +#endif /* NO_SIGNALS */ + result = SendCommand(cip, cmdspec, ap); + va_end(ap); + if (result < 0) { +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + goto done; + } + + /* Get the response to the transfer command we sent, to see if + * they can accomodate the request. If everything went okay, + * we will get a preliminary response saying that the transfer + * initiation was successful and that the data is there for + * reading (for retrieves; for sends, they will be waiting for + * us to send them something). + */ + rp = InitResponse(); + if (rp == NULL) { + Error(cip, kDontPerror, "Malloc failed.\n"); + cip->errNo = kErrMallocFailed; + result = cip->errNo; + goto done; + } + result = GetResponse(cip, rp); +#ifndef NO_SIGNALS + if (cip->ctrlTimeout > 0) + (void) alarm(0); +#endif /* NO_SIGNALS */ + + if (result < 0) + goto done; + respCode = rp->codeType; + DoneWithResponse(cip, rp); + + if (respCode > 2) { + cip->errNo = kErrCouldNotStartDataTransfer; + result = cip->errNo; + goto done; + } + + /* Now we accept the data connection that the other side is offering + * to us. Then we can do the actual I/O on the data we want. + */ + cip->netMode = netMode; + if ((result = AcceptDataConnection(cip)) < 0) + goto done; + return (kNoErr); + +done: + (void) FTPEndDataCmd(cip, 0); + return (result); +} /* FTPStartDataCmd */ + + + + +void +FTPAbortDataTransfer(const FTPCIPtr cip) +{ + ResponsePtr rp; + int result; + + if (cip->dataSocket != kClosedFileDescriptor) { + PrintF(cip, "Starting abort sequence.\n"); + SendTelnetInterrupt(cip); /* Probably could get by w/o doing this. */ + + result = FTPCmdNoResponse(cip, "ABOR"); + if (result != kNoErr) { + /* Linger could cause close to block, so unset it. */ + (void) SetLinger(cip, cip->dataSocket, 0); + CloseDataConnection(cip); + PrintF(cip, "Could not send abort command.\n"); + return; + } + + if (cip->abortTimeout > 0) { + result = WaitResponse(cip, (unsigned int) cip->abortTimeout); + if (result <= 0) { + /* Error or no response received to ABOR in time. */ + (void) SetLinger(cip, cip->dataSocket, 0); + CloseDataConnection(cip); + PrintF(cip, "No response received to abort request.\n"); + return; + } + } + + rp = InitResponse(); + if (rp == NULL) { + Error(cip, kDontPerror, "Malloc failed.\n"); + cip->errNo = kErrMallocFailed; + result = cip->errNo; + return; + } + + result = GetResponse(cip, rp); + if (result < 0) { + /* Shouldn't happen, and doesn't matter if it does. */ + (void) SetLinger(cip, cip->dataSocket, 0); + CloseDataConnection(cip); + PrintF(cip, "Invalid response to abort request.\n"); + DoneWithResponse(cip, rp); + return; + } + DoneWithResponse(cip, rp); + + /* A response to the abort request has been received. + * Now the only thing left to do is close the data + * connection, making sure to turn off linger mode + * since we don't care about straggling data bits. + */ + (void) SetLinger(cip, cip->dataSocket, 0); + CloseDataConnection(cip); /* Must close (by protocol). */ + PrintF(cip, "End abort.\n"); + } +} /* FTPAbortDataTransfer */ + + + + +int +FTPEndDataCmd(const FTPCIPtr cip, int didXfer) +{ + int result; + int respCode; + ResponsePtr rp; + + if (cip == NULL) + return (kErrBadParameter); + if (strcmp(cip->magic, kLibraryMagic)) + return (kErrBadMagic); + + CloseDataConnection(cip); + result = kNoErr; + if (didXfer) { + /* Get the response to the data transferred. Most likely a message + * saying that the transfer completed succesfully. However, if + * we tried to abort the transfer using ABOR, we will have a response + * to that command instead. + */ + rp = InitResponse(); + if (rp == NULL) { + Error(cip, kDontPerror, "Malloc failed.\n"); + cip->errNo = kErrMallocFailed; + result = cip->errNo; + return (result); + } + result = GetResponse(cip, rp); + if (result < 0) + return (result); + respCode = rp->codeType; + DoneWithResponse(cip, rp); + if (respCode != 2) { + cip->errNo = kErrDataTransferFailed; + result = cip->errNo; + } else { + result = kNoErr; + } + } + return (result); +} /* FTPEndDataCmd */ + + + + +int +BufferGets(char *buf, size_t bufsize, int inStream, char *secondaryBuf, char **secBufPtr, char **secBufLimit, size_t secBufSize) +{ + int err; + char *src; + char *dst; + char *dstlim; + int len; + int nr; + int haveEof = 0; + + err = 0; + dst = buf; + dstlim = dst + bufsize - 1; /* Leave room for NUL. */ + src = (*secBufPtr); + for ( ; dst < dstlim; ) { + if (src >= (*secBufLimit)) { + /* Fill the buffer. */ + +/* Don't need to poll it here. The routines that use BufferGets don't + * need any special processing during timeouts (i.e. progress reports), + * so go ahead and just let it block until there is data to read. + */ + nr = (int) read(inStream, secondaryBuf, secBufSize); + if (nr == 0) { + /* EOF. */ + haveEof = 1; + goto done; + } else if (nr < 0) { + /* Error. */ + err = -1; + goto done; + } + (*secBufPtr) = secondaryBuf; + (*secBufLimit) = secondaryBuf + nr; + src = (*secBufPtr); + if (nr < (int) secBufSize) + src[nr] = '\0'; + } + if (*src == '\r') { + ++src; + } else { + if (*src == '\n') { + /* *dst++ = *src++; */ ++src; + goto done; + } + *dst++ = *src++; + } + } + +done: + (*secBufPtr) = src; + *dst = '\0'; + len = (int) (dst - buf); + if (err < 0) + return (err); + if ((len == 0) && (haveEof == 1)) + return (-1); + return (len); /* May be zero, if a blank line. */ +} /* BufferGets */ + +/* eof */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/syshdrs.h b/modules/rosapps/applications/net/ncftp/libncftp/syshdrs.h new file mode 100644 index 00000000000..344db2ec41c --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/syshdrs.h @@ -0,0 +1,239 @@ +/* syshdrs.h + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#if defined(HAVE_CONFIG_H) +# include +#endif + +#if defined(WIN32) || defined(_WINDOWS) +# include "wincfg.h" +# include /* Includes */ +//# include +# ifdef HAVE_UNISTD_H +# include +# endif +# include +# include +# include +# ifdef HAVE_STRINGS_H +# include +# endif +# include +# include +# include +# include +# include +# include +# include +# include +# include +# undef strcasecmp +# define strcasecmp stricmp +# undef strncasecmp +# define strncasecmp strnicmp +# define sleep WinSleep +# ifndef S_ISREG +# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) +# define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) +# endif +# ifndef open +# define open _open +# define write _write +# define read _read +# define close _close +# define lseek _lseek +# define stat _stat +# define lstat _stat +# define fstat _fstat +# define dup _dup +# define utime _utime +# define utimbuf _utimbuf +# endif +# ifndef unlink +# define unlink remove +# endif +# define NO_SIGNALS 1 +# define USE_SIO 1 +#else /* UNIX */ + +#if defined(AIX) || defined(_AIX) +# define _ALL_SOURCE 1 +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include +#include +#include +#if !defined(HAVE_GETCWD) && defined(HAVE_GETWD) +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STRINGS_H +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_NET_ERRNO_H +# include +#endif +#ifdef HAVE_ARPA_NAMESER_H +# include +#endif +#ifdef HAVE_NSERVE_H +# include +#endif +#ifdef HAVE_RESOLV_H +# include +#endif +#ifdef CAN_USE_SYS_SELECT_H +# include +#endif + +#ifdef HAVE_GETCWD +# ifndef HAVE_UNISTD_H + extern char *getcwd(); +# endif +#else +# ifdef HAVE_GETWD +# include +# ifndef MAXPATHLEN +# define MAXPATHLEN 1024 +# endif + extern char *getwd(char *); +# endif +#endif + +#endif /* UNIX */ + + +#if defined(HAVE_LONG_LONG) && defined(HAVE_OPEN64) +# define Open open64 +#else +# define Open open +#endif + +#if defined(HAVE_LONG_LONG) && defined(HAVE_STAT64) && defined(HAVE_STRUCT_STAT64) +# define Stat stat64 +# ifdef HAVE_FSTAT64 +# define Fstat fstat64 +# else +# define Fstat fstat +# endif +# ifdef HAVE_LSTAT64 +# define Lstat lstat64 +# else +# define Lstat lstat +# endif +#else +# define Stat stat +# define Fstat fstat +# define Lstat lstat +#endif + +#if defined(HAVE_LONG_LONG) && defined(HAVE_LSEEK64) +# define Lseek(a,b,c) lseek64(a, (longest_int) b, c) +#elif defined(HAVE_LONG_LONG) && defined(HAVE_LLSEEK) +# if 1 +# if defined(LINUX) && (LINUX <= 23000) +# define Lseek(a,b,c) lseek(a, (off_t) b, c) +# else +# define Lseek(a,b,c) llseek(a, (longest_int) b, c) +# endif +# else +# define Lseek(a,b,c) lseek(a, (off_t) b, c) +# endif +#else +# define Lseek(a,b,c) lseek(a, (off_t) b, c) +#endif + + +#ifndef IAC + +/* + * Definitions for the TELNET protocol. + */ +#define IAC 255 /* interpret as command: */ +#define DONT 254 /* you are not to use option */ +#define DO 253 /* please, you use option */ +#define WONT 252 /* I won't use option */ +#define WILL 251 /* I will use option */ +#define SB 250 /* interpret as subnegotiation */ +#define GA 249 /* you may reverse the line */ +#define EL 248 /* erase the current line */ +#define EC 247 /* erase the current character */ +#define AYT 246 /* are you there */ +#define AO 245 /* abort output--but let prog finish */ +#define IP 244 /* interrupt process--permanently */ +#define BREAK 243 /* break */ +#define DM 242 /* data mark--for connect. cleaning */ +#define NOP 241 /* nop */ +#define SE 240 /* end sub negotiation */ +#define EOR 239 /* end of record (transparent mode) */ +#define ABORT 238 /* Abort process */ +#define SUSP 237 /* Suspend process */ +#define xEOF 236 /* End of file: EOF is already used... */ + +#define SYNCH 242 /* for telfunc calls */ +#endif + +#ifdef HAVE_UTIME_H +# include +#else + struct utimbuf { time_t actime, modtime; }; +#endif + + +#ifdef HAVE_LIBSOCKS5 +# define SOCKS 5 +# include +#endif + +#if 1 /* %config2% -- set by configure script -- do not modify */ +# ifndef USE_SIO +# define USE_SIO 1 +# endif +# ifndef NO_SIGNALS +# define NO_SIGNALS 1 +# endif +#else +# ifndef USE_SIO +# define USE_SIO 0 +# endif + /* #undef NO_SIGNALS */ +#endif + +#if USE_SIO +# include "sio/sio.h" /* Library header. */ +#endif + +#include "Strn/Strn.h" /* Library header. */ +#include "ncftp.h" /* Library header. */ + +#include "util.h" +#include "ftp.h" + +/* eof */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/util.c b/modules/rosapps/applications/net/ncftp/libncftp/util.c new file mode 100644 index 00000000000..914fe56a4b5 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/util.c @@ -0,0 +1,1048 @@ +/* util.c + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#include "syshdrs.h" + +#if defined(WIN32) || defined(_WINDOWS) +#include +extern void GetSpecialDir(char *dst, size_t size, int whichDir); +#endif + + +static void * +Realloc(void *ptr, size_t siz) +{ + if (ptr == NULL) + return (void *) malloc(siz); + return ((void *) realloc(ptr, siz)); +} /* Realloc */ + + +/* Use getcwd/getwd to get the full path of the current local + * working directory. + */ +char * +FTPGetLocalCWD(char *buf, size_t size) +{ +#ifdef HAVE_GETCWD + static char *cwdBuf = NULL; + static size_t cwdBufSize = 0; + + if (cwdBufSize == 0) { + cwdBufSize = (size_t) 128; + cwdBuf = (char *) malloc(cwdBufSize); + } + + for (errno = 0; ; ) { + if (cwdBuf == NULL) { + return NULL; + } + + if (getcwd(cwdBuf, cwdBufSize) != NULL) + break; + if (errno != ERANGE) { + (void) Strncpy(buf, ".", size); + return NULL; + } + cwdBufSize *= 2; + cwdBuf = (char *) Realloc(cwdBuf, cwdBufSize); + } + + return (Strncpy(buf, cwdBuf, size)); +#else +#ifdef HAVE_GETWD + static char *cwdBuf = NULL; + char *dp; + + /* Due to the way getwd is usually implemented, it's + * important to have a buffer large enough to hold the + * whole thing. getwd usually starts at the end of the + * buffer, and works backwards, returning you a pointer + * to the beginning of it when it finishes. + */ + if (size < MAXPATHLEN) { + /* Buffer not big enough, so use a temporary one, + * and then copy the first 'size' bytes of the + * temporary buffer to your 'buf.' + */ + if (cwdBuf == NULL) { + cwdBuf = (char *) malloc((size_t) MAXPATHLEN); + if (cwdBuf == NULL) { + return NULL; + } + } + dp = cwdBuf; + } else { + /* Buffer is big enough already. */ + dp = buf; + } + *dp = '\0'; + if (getwd(dp) == NULL) { + /* getwd() should write the reason why in the buffer then, + * according to the man pages. + */ + (void) Strncpy(buf, ".", size); + return (NULL); + } + return (Strncpy(buf, dp, size)); + +#elif defined(WIN32) || defined(_WINDOWS) + if (GetCurrentDirectory((DWORD) size - 1, buf) < 1) + return NULL; + buf[size - 1] = '\0'; + return buf; +#else + /* Not a solution, but does anybody not have either of + * getcwd or getwd? + */ + --Error--; +#endif +#endif +} /* GetCWD */ + + + +/* Read a line, and axe the end-of-line. */ +char * +FGets(char *str, size_t size, FILE *fp) +{ + char *cp, *nlptr; + + cp = fgets(str, ((int) size) - 1, fp); + if (cp != NULL) { + cp[((int) size) - 1] = '\0'; /* ensure terminator */ + nlptr = cp + strlen(cp) - 1; + if (*nlptr == '\n') + *nlptr = '\0'; + } else { + memset(str, 0, size); + } + return cp; +} /* FGets */ + + + + +#if defined(WIN32) || defined(_WINDOWS) + +int gettimeofday(struct timeval *const tp, void *junk) +{ + SYSTEMTIME systemTime; + + GetSystemTime(&systemTime); + + /* Create an arbitrary second counter; + * Note that this particular one creates + * a problem at the end of the month. + */ + tp->tv_sec = + systemTime.wSecond + + systemTime.wMinute * 60 + + systemTime.wHour * 3600 + + systemTime.wDay * 86400; + + tp->tv_usec = systemTime.wMilliseconds * 1000; + + return 0; +} /* gettimeofday */ + +#endif + + + + +#if defined(WIN32) || defined(_WINDOWS) +#else +/* This looks up the user's password entry, trying to look by the username. + * We have a couple of extra hacks in place to increase the probability + * that we can get the username. + */ +struct passwd * +GetPwByName(void) +{ + char *cp; + struct passwd *pw; + + cp = getlogin(); + if (cp == NULL) { + cp = (char *) getenv("LOGNAME"); + if (cp == NULL) + cp = (char *) getenv("USER"); + } + pw = NULL; + if (cp != NULL) + pw = getpwnam(cp); + return (pw); +} /* GetPwByName */ +#endif + + + +char * +GetPass(const char *const prompt) +{ +#ifdef HAVE_GETPASS + return getpass(prompt); +#elif defined(_CONSOLE) && (defined(WIN32) || defined(_WINDOWS)) + static char pwbuf[128]; + char *dst, *dlim; + int c; + + (void) memset(pwbuf, 0, sizeof(pwbuf)); + if (! _isatty(_fileno(stdout))) + return (pwbuf); + (void) fputs(prompt, stdout); + (void) fflush(stdout); + + for (dst = pwbuf, dlim = dst + sizeof(pwbuf) - 1;;) { + c = _getch(); + if ((c == 0) || (c == 0xe0)) { + /* The key is a function or arrow key; read and discard. */ + (void) _getch(); + } + if ((c == '\r') || (c == '\n')) + break; + if (dst < dlim) + *dst++ = c; + } + *dst = '\0'; + + (void) fflush(stdout); + (void) fflush(stdin); + return (pwbuf); +#else + static char pwbuf[128]; + + (void) memset(pwbuf, 0, sizeof(pwbuf)); +#if defined(WIN32) || defined(_WINDOWS) + if (! _isatty(_fileno(stdout))) +#else + if (! isatty(1)) +#endif + return (pwbuf); + (void) fputs(prompt, stdout); + (void) fflush(stdout); + (void) FGets(pwbuf, sizeof(pwbuf), stdin); + (void) fflush(stdout); + (void) fflush(stdin); + return (pwbuf); +#endif +} /* GetPass */ + + + + +void +GetHomeDir(char *dst, size_t size) +{ +#if defined(WIN32) || defined(_WINDOWS) + const char *homedrive, *homepath; + + homedrive = getenv("HOMEDRIVE"); + homepath = getenv("HOMEPATH"); + if ((homedrive != NULL) && (homepath != NULL)) { + (void) Strncpy(dst, homedrive, size); + (void) Strncat(dst, homepath, size); + return; + } + +// GetSpecialDir(dst, size, CSIDL_PERSONAL /* "My Documents" */); +// if (dst[0] != '\0') +// return; +// +// dst[0] = '\0'; +// if (GetWindowsDirectory(dst, size - 1) < 1) +// (void) Strncpy(dst, ".", size); +// else if (dst[1] == ':') { +// dst[2] = '\\'; +// dst[3] = '\0'; +// } +#else + const char *cp; + struct passwd *pw; + + pw = NULL; +#if defined(USE_GETPWUID) + /* Try to use getpwuid(), but if we have to, fall back to getpwnam(). */ + if ((pw = getpwuid(getuid())) == NULL) + pw = GetPwByName(); /* Oh well, try getpwnam() then. */ +#else + /* Try to use getpwnam(), but if we have to, fall back to getpwuid(). */ + if ((pw = GetPwByName()) == NULL) + pw = getpwuid(getuid()); /* Try getpwnam() then. */ +#endif + if (pw != NULL) + cp = pw->pw_dir; + else if ((cp = (const char *) getenv("LOGNAME")) == NULL) + cp = "."; + (void) Strncpy(dst, cp, size); +#endif +} /* GetHomeDir */ + + + + +void +GetUsrName(char *dst, size_t size) +{ +#if defined(WIN32) || defined(_WINDOWS) + DWORD size1; + + size1 = size - 1; + if (! GetUserName(dst, &size1)) + (void) strncpy(dst, "unknown", size); + dst[size - 1] = '\0'; +#else + const char *cp; + struct passwd *pw; + + pw = NULL; +#ifdef USE_GETPWUID + /* Try to use getpwuid(), but if we have to, fall back to getpwnam(). */ + if ((pw = getpwuid(getuid())) == NULL) + pw = GetPwByName(); /* Oh well, try getpwnam() then. */ +#else + /* Try to use getpwnam(), but if we have to, fall back to getpwuid(). */ + if ((pw = GetPwByName()) == NULL) + pw = getpwuid(getuid()); /* Try getpwnam() then. */ +#endif + if (pw != NULL) + cp = pw->pw_name; + else if ((cp = (const char *) getenv("LOGNAME")) == NULL) + cp = "UNKNOWN"; + (void) Strncpy(dst, cp, size); +#endif +} /* GetUserName */ + + + + + +/* Closes the file supplied, if it isn't a std stream. */ +void +CloseFile(FILE **f) +{ + if (*f != NULL) { + if ((*f != stdout) && (*f != stdin) && (*f != stderr)) + (void) fclose(*f); + *f = NULL; + } +} /* CloseFile */ + + + +/*VARARGS*/ +void +PrintF(const FTPCIPtr cip, const char *const fmt, ...) +{ + va_list ap; + char buf[256]; + + va_start(ap, fmt); + if (cip->debugLog != NULL) { + (void) vfprintf(cip->debugLog, fmt, ap); + (void) fflush(cip->debugLog); + } + if (cip->debugLogProc != NULL) { +#ifdef HAVE_VSNPRINTF + (void) vsnprintf(buf, sizeof(buf) - 1, fmt, ap); + buf[sizeof(buf) - 1] = '\0'; +#else + (void) vsprintf(buf, fmt, ap); +#endif + (*cip->debugLogProc)(cip, buf); + } + va_end(ap); +} /* PrintF */ + + + + + +/*VARARGS*/ +void +Error(const FTPCIPtr cip, const int pError, const char *const fmt, ...) +{ + va_list ap; + int errnum; + size_t len; + char buf[256]; + int endsinperiod; + int endsinnewline; +#ifndef HAVE_STRERROR + char errnostr[16]; +#endif + + errnum = errno; + va_start(ap, fmt); +#ifdef HAVE_VSNPRINTF + vsnprintf(buf, sizeof(buf) - 1, fmt, ap); + buf[sizeof(buf) - 1] = '\0'; +#else + (void) vsprintf(buf, fmt, ap); +#endif + va_end(ap); + + if (pError != 0) { + len = strlen(buf); + endsinperiod = 0; + endsinnewline = 0; + if (len > 2) { + if (buf[len - 1] == '\n') { + endsinnewline = 1; + buf[len - 1] = '\0'; + if (buf[len - 2] == '.') { + endsinperiod = 1; + buf[len - 2] = '\0'; + } + } else if (buf[len - 1] == '.') { + endsinperiod = 1; + buf[len - 1] = '\0'; + } + } +#ifdef HAVE_STRERROR + (void) STRNCAT(buf, ": "); + (void) STRNCAT(buf, strerror(errnum)); +#else +# ifdef HAVE_SNPRINTF + sprintf(errnostr, sizeof(errnostr) - 1, " (errno = %d)", errnum); + errnostr[sizeof(errnostr) - 1] = '\0'; +# else + sprintf(errnostr, " (errno = %d)", errnum); +# endif + STRNCAT(buf, errnostr); +#endif + if (endsinperiod != 0) + (void) STRNCAT(buf, "."); + if (endsinnewline != 0) + (void) STRNCAT(buf, "\n"); + } + + if (cip->errLog != NULL) { + (void) fprintf(cip->errLog, "%s", buf); + (void) fflush(cip->errLog); + } + if ((cip->debugLog != NULL) && (cip->debugLog != cip->errLog)) { + if ((cip->errLog != stderr) || (cip->debugLog != stdout)) { + (void) fprintf(cip->debugLog, "%s", buf); + (void) fflush(cip->debugLog); + } + } + if (cip->errLogProc != NULL) { + (*cip->errLogProc)(cip, buf); + } + if ((cip->debugLogProc != NULL) && (cip->debugLogProc != cip->errLogProc)) { + (*cip->debugLogProc)(cip, buf); + } +} /* Error */ + + + + +/* Cheezy, but somewhat portable way to get GMT offset. */ +#ifdef HAVE_MKTIME +static +time_t GetUTCOffset(int mon, int mday) +{ + struct tm local_tm, utc_tm, *utc_tmptr; + time_t local_t, utc_t, utcOffset; + + ZERO(local_tm); + ZERO(utc_tm); + utcOffset = 0; + + local_tm.tm_year = 94; /* Doesn't really matter. */ + local_tm.tm_mon = mon; + local_tm.tm_mday = mday; + local_tm.tm_hour = 12; + local_tm.tm_isdst = -1; + local_t = mktime(&local_tm); + + if (local_t != (time_t) -1) { + utc_tmptr = gmtime(&local_t); + utc_tm.tm_year = utc_tmptr->tm_year; + utc_tm.tm_mon = utc_tmptr->tm_mon; + utc_tm.tm_mday = utc_tmptr->tm_mday; + utc_tm.tm_hour = utc_tmptr->tm_hour; + utc_tm.tm_isdst = -1; + utc_t = mktime(&utc_tm); + + if (utc_t != (time_t) -1) + utcOffset = (local_t - utc_t); + } + return (utcOffset); +} /* GetUTCOffset */ +#endif /* HAVE_MKTIME */ + + + +/* Converts a MDTM date, like "19930602204445" + * format to a time_t. + */ +time_t UnMDTMDate(char *dstr) +{ +#ifndef HAVE_MKTIME + return (kModTimeUnknown); +#else + struct tm ut, *t; + time_t mt, now; + time_t result = kModTimeUnknown; + + if (strncmp(dstr, "19100", 5) == 0) { + /* Server Y2K bug! */ + return (result); + } + + (void) time(&now); + t = localtime(&now); + + /* Copy the whole structure of the 'tm' pointed to by t, so it will + * also set all fields we don't specify explicitly to be the same as + * they were in t. That way we copy non-standard fields such as + * tm_gmtoff, if it exists or not. + */ + ut = *t; + + /* The time we get back from the server is (should be) in UTC. */ + if (sscanf(dstr, "%04d%02d%02d%02d%02d%02d", + &ut.tm_year, + &ut.tm_mon, + &ut.tm_mday, + &ut.tm_hour, + &ut.tm_min, + &ut.tm_sec) == 6) + { + --ut.tm_mon; + ut.tm_year -= 1900; + mt = mktime(&ut); + if (mt != (time_t) -1) { + mt += GetUTCOffset(ut.tm_mon, ut.tm_mday); + result = (time_t) mt; + } + } + return result; +#endif /* HAVE_MKTIME */ +} /* UnMDTMDate */ + + + +int +GetSockBufSize(int sockfd, size_t *rsize, size_t *ssize) +{ +#ifdef SO_SNDBUF + int rc = -1; + int opt; + int optsize; + + if (ssize != NULL) { + opt = 0; + optsize = sizeof(opt); + rc = getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, &optsize); + if (rc == 0) + *ssize = (size_t) opt; + else + *ssize = 0; + } + if (rsize != NULL) { + opt = 0; + optsize = sizeof(opt); + rc = getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, &optsize); + if (rc == 0) + *rsize = (size_t) opt; + else + *rsize = 0; + } + return (rc); +#else + if (ssize != NULL) + *ssize = 0; + if (rsize != NULL) + *rsize = 0; + return (-1); +#endif +} /* GetSockBufSize */ + + + +int +SetSockBufSize(int sockfd, size_t rsize, size_t ssize) +{ +#ifdef SO_SNDBUF + int rc = -1; + int opt; + int optsize; + +#ifdef TCP_RFC1323 + /* This is an AIX-specific socket option to do RFC1323 large windows */ + if (ssize > 0 || rsize > 0) { + opt = 1; + optsize = sizeof(opt); + rc = setsockopt(sockfd, IPPROTO_TCP, TCP_RFC1323, &opt, optsize); + } +#endif + + if (ssize > 0) { + opt = (int) ssize; + optsize = sizeof(opt); + rc = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, optsize); + } + if (rsize > 0) { + opt = (int) rsize; + optsize = sizeof(opt); + rc = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, optsize); + } + return (rc); +#else + return (-1); +#endif +} /* SetSockBufSize */ + + + +void +Scramble(unsigned char *dst, size_t dsize, unsigned char *src, char *key) +{ + int i; + unsigned int ch; + unsigned char *k2; + size_t keyLen; + + keyLen = strlen(key); + k2 = (unsigned char *) key; + for (i=0; i < (int) dsize - 1; i++) { + ch = src[i]; + if (ch == 0) + break; + dst[i] = (unsigned char) (ch ^ (int) (k2[i % (int) keyLen])); + } + dst[i] = '\0'; +} /* Scramble */ + + + + + +#if defined(WIN32) || defined(_WINDOWS) +void WinSleep(unsigned int seconds) +{ + DWORD now, deadline; + DWORD milliseconds = seconds * 1000; + + if (milliseconds > 0) { + now = GetTickCount(); + deadline = now + milliseconds; + if (now < deadline) { + /* Typical case */ + do { + milliseconds = deadline - now; + Sleep(milliseconds); + now = GetTickCount(); + } while (now < deadline); + } else { + /* Overflow case */ + deadline = now - 1; + milliseconds -= (0xFFFFFFFF - now); + do { + Sleep(0xFFFFFFFF - now); + now = GetTickCount(); + } while (now > deadline); + /* Counter has now wrapped around */ + deadline = now + milliseconds; + do { + milliseconds = deadline - now; + Sleep(milliseconds); + now = GetTickCount(); + } while (now < deadline); + } + } +} /* WinSleep */ + + + + +char * +StrFindLocalPathDelim(const char *src) /* TODO: optimize */ +{ + const char *first; + int c; + + first = NULL; + for (;;) { + c = *src++; + if (c == '\0') + break; + if (IsLocalPathDelim(c)) { + first = src - 1; + break; + } + } + + return ((char *) first); +} /* StrFindLocalPathDelim */ + + + +char * +StrRFindLocalPathDelim(const char *src) /* TODO: optimize */ +{ + const char *last; + int c; + + last = NULL; + for (;;) { + c = *src++; + if (c == '\0') + break; + if (IsLocalPathDelim(c)) + last = src - 1; + } + + return ((char *) last); +} /* StrRFindLocalPathDelim */ + + + + +void +StrRemoveTrailingLocalPathDelim(char *dst) +{ + char *cp; + + cp = StrRFindLocalPathDelim(dst); + if ((cp == NULL) || (cp[1] != '\0')) + return; + + /* Note: Do not destroy a path of "/" */ + while ((cp > dst) && (IsLocalPathDelim(*cp))) + *cp-- = '\0'; +} /* StrRemoveTrailingLocalPathDelim */ + + + +void +TVFSPathToLocalPath(char *dst) +{ + int c; + + /* Note: Technically we don't need to do this, + * since Win32 accepts a / as equivalent to a \ + * in a pathname. + */ + if (dst != NULL) { + for (;;) { + c = *dst++; + if (c == '\0') + break; + if (c == '/') + dst[-1] = LOCAL_PATH_DELIM; + } + } +} /* TVFSPathToLocalPath */ + + +void +LocalPathToTVFSPath(char *dst) +{ + int c; + + if (dst != NULL) { + for (;;) { + c = *dst++; + if (c == '\0') + break; + if (c == LOCAL_PATH_DELIM) + dst[-1] = '/'; + } + } +} /* LocalPathToTVFSPath */ +#endif /* WINDOWS */ + + + + +void +StrRemoveTrailingSlashes(char *dst) +{ + char *cp; + + cp = strrchr(dst, '/'); + if ((cp == NULL) || (cp[1] != '\0')) + return; + + /* Note: Do not destroy a path of "/" */ + while ((cp > dst) && (*cp == '/')) + *cp-- = '\0'; +} /* StrRemoveTrailingSlashes */ + + + + +int +MkDirs(const char *const newdir, int mode1) +{ + char s[512]; + int rc; + char *cp, *sl; +#if defined(WIN32) || defined(_WINDOWS) + struct _stat st; + char *share; +#else + struct Stat st; + mode_t mode = (mode_t) mode1; +#endif + +#if defined(WIN32) || defined(_WINDOWS) + if ((isalpha(newdir[0])) && (newdir[1] == ':')) { + if (! IsLocalPathDelim(newdir[2])) { + /* Special case "c:blah", and errout. + * "c:\blah" must be used or _access GPFs. + */ + errno = EINVAL; + return (-1); + } else if (newdir[3] == '\0') { + /* Special case root directory, which cannot be made. */ + return (0); + } + } else if (IsUNCPrefixed(newdir)) { + share = StrFindLocalPathDelim(newdir + 2); + if ((share == NULL) || (StrFindLocalPathDelim(share + 1) == NULL)) + return (-1); + } + + if (_access(newdir, 00) == 0) { + if (_stat(newdir, &st) < 0) + return (-1); + if (! S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + return (-1); + } + return 0; + } +#else + if (access(newdir, F_OK) == 0) { + if (Stat(newdir, &st) < 0) + return (-1); + if (! S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + return (-1); + } + return 0; + } +#endif + + (void) strncpy(s, newdir, sizeof(s)); + if (s[sizeof(s) - 1] != '\0') { +#ifdef ENAMETOOLONG + errno = ENAMETOOLONG; +#else + errno = EINVAL; + return (-1); +#endif + } + + cp = StrRFindLocalPathDelim(s); + if (cp == NULL) { +#if defined(WIN32) || defined(_WINDOWS) + if (! CreateDirectory(newdir, (LPSECURITY_ATTRIBUTES) 0)) + return (-1); + return (0); +#else + rc = mkdir(newdir, mode); + return (rc); +#endif + } else if (cp[1] == '\0') { + /* Remove trailing slashes from path. */ + --cp; + while (cp > s) { + if (! IsLocalPathDelim(*cp)) + break; + --cp; + } + cp[1] = '\0'; + cp = StrRFindLocalPathDelim(s); + if (cp == NULL) { +#if defined(WIN32) || defined(_WINDOWS) + if (! CreateDirectory(s, (LPSECURITY_ATTRIBUTES) 0)) + return (-1); +#else + rc = mkdir(s, mode); + return (rc); +#endif + } + } + + /* Find the deepest directory in this + * path that already exists. When + * we do, we want to have the 's' + * string as it was originally, but + * with 'cp' pointing to the first + * slash in the path that starts the + * part that does not exist. + */ + sl = NULL; + for (;;) { + *cp = '\0'; +#if defined(WIN32) || defined(_WINDOWS) + rc = _access(s, 00); +#else + rc = access(s, F_OK); +#endif + if (sl != NULL) + *sl = LOCAL_PATH_DELIM; + if (rc == 0) { + *cp = LOCAL_PATH_DELIM; + break; + } + sl = cp; + cp = StrRFindLocalPathDelim(s); + if (cp == NULL) { + /* We do not have any more + * slashes, so none of the + * new directory's components + * existed before, so we will + * have to make everything + * starting at the first node. + */ + if (sl != NULL) + *sl = LOCAL_PATH_DELIM; + + /* We refer to cp + 1 below, + * so this is why we can + * set "cp" to point to the + * byte before the array starts. + */ + cp = s - 1; + break; + } + } + + for (;;) { + /* Extend the path we have to + * include the next component + * to make. + */ + sl = StrFindLocalPathDelim(cp + 1); + if (sl == s) { + /* If the next slash is pointing + * to the start of the string, then + * the path is an absolute path and + * we don't need to make the root node, + * and besides the next mkdir would + * try an empty string. + */ + ++cp; + sl = StrFindLocalPathDelim(cp + 1); + } + if (sl != NULL) { + *sl = '\0'; + } +#if defined(WIN32) || defined(_WINDOWS) + if (! CreateDirectory(s, (LPSECURITY_ATTRIBUTES) 0)) + return (-1); +#else + rc = mkdir(s, mode); + if (rc < 0) + return rc; +#endif + if (sl == NULL) + break; + *sl = LOCAL_PATH_DELIM; + cp = sl; + } + return (0); +} /* MkDirs */ + + + + +int +FilenameExtensionIndicatesASCII(const char *const pathName, const char *const extnList) +{ + const char *extn; + char *cp; + int c; + char extnPattern[16]; + + extn = pathName + strlen(pathName) - 1; + forever { + if (extn <= pathName) + return (0); /* End of pathname, no extension. */ + c = (int) *--extn; + if (IsLocalPathDelim(c)) + return (0); /* End of filename, no extension. */ + if (c == '.') { + extn += 1; + break; + } + } + if (strlen(extn) > (sizeof(extnPattern) - 2 - 1 - 1)) { + return (0); + } +#ifdef HAVE_SNPRINTF + snprintf(extnPattern, sizeof(extnPattern), +#else + sprintf(extnPattern, +#endif + "|.%s|", + extn + ); + + cp = extnPattern; + forever { + c = *cp; + if (c == '\0') + break; + if (isupper(c)) { + c = tolower(c); + *cp++ = (char) c; + } else { + cp++; + } + } + + /* Extension list is specially formatted, like this: + * + * |ext1|ext2|ext3|...|extN| + * + * I.e, each filename extension is delimited with + * a pipe, and we always begin and end the string + * with a pipe. + */ + if (strstr(extnList, extnPattern) != NULL) { + return (1); + } + return (0); +} /* FilenameExtensionIndicatesASCII */ + + + + + +#ifdef HAVE_SIGACTION +void (*NcSignal(int signum, void (*handler)(int)))(int) +{ + struct sigaction sa, osa; + + (void) sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = handler; + if (signum == SIGALRM) { +#ifdef SA_INTERRUPT + sa.sa_flags |= SA_INTERRUPT; +#endif + } else { +#ifdef SA_RESTART + sa.sa_flags |= SA_RESTART; +#endif + } + if (sigaction(signum, &sa, &osa) < 0) + return ((FTPSigProc) SIG_ERR); + return (osa.sa_handler); +} +#endif /* HAVE_SIGACTION */ + +/* eof */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/util.h b/modules/rosapps/applications/net/ncftp/libncftp/util.h new file mode 100644 index 00000000000..061a6ecef0a --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/util.h @@ -0,0 +1,108 @@ +/* Util.h + * + * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft. + * All rights reserved. + * + */ + +#ifndef _util_h_ +#define _util_h_ 1 + +typedef char string[160], str16[16], str32[32], str64[64]; +typedef char longstring[512]; +typedef char pathname[512]; + +#ifndef PTRZERO +# define PTRZERO(p,siz) (void) memset(p, 0, (size_t) (siz)) +#endif + +#define ZERO(a) PTRZERO(&(a), sizeof(a)) +#define STREQ(a,b) (strcmp(a,b) == 0) +#define STRNEQ(a,b,s) (strncmp(a,b,(size_t)(s)) == 0) + +#ifndef ISTRCMP +# ifdef HAVE_STRCASECMP +# define ISTRCMP strcasecmp +# define ISTRNCMP strncasecmp +# else +# define ISTRCMP strcmp +# define ISTRNCMP strncmp +# endif +#endif + +#define ISTREQ(a,b) (ISTRCMP(a,b) == 0) +#define ISTRNEQ(a,b,s) (ISTRNCMP(a,b,(size_t)(s)) == 0) + +typedef int (*cmp_t)(const void *, const void *); +#define QSORT(base,n,s,cmp) \ + qsort(base, (size_t)(n), (size_t)(s), (cmp_t)(cmp)) + +#define BSEARCH(key,base,n,s,cmp) \ + bsearch(key, base, (size_t)(n), (size_t)(s), (cmp_t)(cmp)) + +/* For Error(): */ +#define kDoPerror 1 +#define kDontPerror 0 + +#define kClosedFileDescriptor (-1) + +#define SZ(a) ((size_t) (a)) + +#ifndef F_OK +# define F_OK 0 +#endif + +#ifdef HAVE_REMOVE +# define UNLINK remove +#else +# define UNLINK unlink +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif /* SEEK_SET */ + +#ifdef SETVBUF_REVERSED +# define SETVBUF(a,b,c,d) setvbuf(a,c,b,d) +#else +# define SETVBUF setvbuf +#endif + + +/* Util.c */ +char *FGets(char *, size_t, FILE *); +struct passwd *GetPwByName(void); +void GetHomeDir(char *, size_t); +void GetUsrName(char *, size_t); +void CloseFile(FILE **); +void PrintF(const FTPCIPtr cip, const char *const fmt, ...) +#if (defined(__GNUC__)) && (__GNUC__ >= 2) +__attribute__ ((format (printf, 2, 3))) +#endif +; +void Error(const FTPCIPtr cip, const int pError, const char *const fmt, ...) +#if (defined(__GNUC__)) && (__GNUC__ >= 2) +__attribute__ ((format (printf, 3, 4))) +#endif +; +int GetSockBufSize(int sockfd, size_t *rsize, size_t *ssize); +int SetSockBufSize(int sockfd, size_t rsize, size_t ssize); +time_t UnMDTMDate(char *); +void Scramble(unsigned char *dst, size_t dsize, unsigned char *src, char *key); +#if defined(WIN32) || defined(_WINDOWS) +char *StrFindLocalPathDelim(const char *src); +char *StrRFindLocalPathDelim(const char *src); +void TVFSPathToLocalPath(char *dst); +void LocalPathToTVFSPath(char *dst); +int gettimeofday(struct timeval *const tp, void *junk); +#endif + +#ifdef HAVE_SIGACTION +void (*NcSignal(int signum, void (*handler)(int)))(int); +#elif !defined(NcSignal) +# define NcSignal signal +#endif + +#endif /* _util_h_ */ diff --git a/modules/rosapps/applications/net/ncftp/libncftp/util2.cpp b/modules/rosapps/applications/net/ncftp/libncftp/util2.cpp new file mode 100644 index 00000000000..499fcf7aa9b --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/util2.cpp @@ -0,0 +1,34 @@ +#include "syshdrs.h" + +#if defined(WIN32) || defined(_WINDOWS) + +extern "C" void +GetSpecialDir(char *dst, size_t size, int whichDir) +{ + LPITEMIDLIST idl; + LPMALLOC shl; + char path[MAX_PATH + 1]; + HRESULT hResult; + + memset(dst, 0, size); + hResult = SHGetMalloc(&shl); + if (SUCCEEDED(hResult)) { + hResult = SHGetSpecialFolderLocation( + NULL, + CSIDL_PERSONAL, + &idl + ); + + if (SUCCEEDED(hResult)) { + if(SHGetPathFromIDList(idl, path)) { + (void) strncpy(dst, path, size - 1); + dst[size - 1] = '\0'; + } + shl->Free(idl); + } + shl->Release(); + } +} // GetSpecialDir + + +#endif diff --git a/modules/rosapps/applications/net/ncftp/libncftp/wincfg.h b/modules/rosapps/applications/net/ncftp/libncftp/wincfg.h new file mode 100644 index 00000000000..c6afc4ddfcb --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/libncftp/wincfg.h @@ -0,0 +1,33 @@ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select(). */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg5 for select(). */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define if you have the mktime function. */ +#define HAVE_MKTIME 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* #define HAVE_STRCASECMP 1 */ + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the header file. */ +/* #define HAVE_UNISTD_H 1 */ + +#define HAVE_LONG_LONG 1 +#define SCANF_LONG_LONG "%I64d" +#define PRINTF_LONG_LONG "%I64d" +#define PRINTF_LONG_LONG_I64D 1 +#define SCANF_LONG_LONG_I64D 1 diff --git a/modules/rosapps/applications/net/ncftp/ncftp.rbuild b/modules/rosapps/applications/net/ncftp/ncftp.rbuild new file mode 100644 index 00000000000..b2b35a8c764 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/ncftp.rbuild @@ -0,0 +1,91 @@ + + . + sio + Strn + libncftp + ncftp + + + user32 + advapi32 + ws2_32 + + + PRead.c + PWrite.c + SAcceptA.c + SAcceptS.c + SBind.c + SClose.c + SConnect.c + SConnectByName.c + SNew.c + SRead.c + SReadline.c + SRecv.c + SRecvfrom.c + SRecvmsg.c + SSelect.c + SSend.c + SSendto.c + SSendtoByName.c + SWrite.c + SocketUtil.c + StrAddr.c + UAcceptA.c + UAcceptS.c + UBind.c + UConnect.c + UConnectByName.c + UNew.c + URecvfrom.c + USendto.c + USendtoByName.c + SError.c + SWait.c + main.c + + + + Dynscat.c + Strncpy.c + Strncat.c + Strntok.c + Strnpcpy.c + Strnpcat.c + strtokc.c + version.c + + + + open.c + cmds.c + util.c + rcmd.c + ftp.c + io.c + errno.c + linelist.c + glob.c + + + + cmds.c + cmdlist.c + getopt.c + ls.c + main.c + version.c + shell.c + util.c + readln.c + progress.c + bookmark.c + pref.c + preffw.c + trace.c + spool.c + log.c + getline.c + + diff --git a/modules/rosapps/applications/net/ncftp/ncftp.rc b/modules/rosapps/applications/net/ncftp/ncftp.rc new file mode 100644 index 00000000000..026d1733115 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/ncftp.rc @@ -0,0 +1,6 @@ + +#define REACTOS_STR_FILE_DESCRIPTION "Ncftp for Win32\0" +#define REACTOS_STR_INTERNAL_NAME "ncftp\0" +#define REACTOS_STR_ORIGINAL_FILENAME "ncftp.exe\0" +#define REACTOS_STR_ORIGINAL_COPYRIGHT "Anonymous sources found at http://www.ncftp.org/\0" +#include diff --git a/modules/rosapps/applications/net/ncftp/ncftp/Makefile.in b/modules/rosapps/applications/net/ncftp/ncftp/Makefile.in new file mode 100644 index 00000000000..2a603c27f68 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/ncftp/Makefile.in @@ -0,0 +1,89 @@ +#----------------------------------------------------------------------------- +# +# NcFTP makefile for the platform @OS@, on the host @host@. +# +#----------------------------------------------------------------------------- + +CC=@CC@ +CFLAGS=@CFLAGS@ +#CC=gcc +#CFLAGS=-O2 -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wbad-function-cast -Wwrite-strings -Wconversion +VPATH=@srcdir@ +CPPFLAGS=@CPPFLAGS@ -I. -I../libncftp -I../Strn -I../sio +prefix=@prefix@ +exec_prefix=@exec_prefix@ +BINDIR=@bindir@ + +LIBS=@LIBS@ +STRIP=strip +LDFLAGS=-L../libncftp -L../Strn -L../sio @LDFLAGS@ + +# Any -D definitions: +BETA=# -DBETA=20 +DEFS=-Dncftp $(BETA) -DBINDIR=\"$(BINDIR)\" @DEFS@ + +OBJS=cmds.@OBJEXT@ cmdlist.@OBJEXT@ getopt.@OBJEXT@ ls.@OBJEXT@ main.@OBJEXT@ version.@OBJEXT@ shell.@OBJEXT@ util.@OBJEXT@ readln.@OBJEXT@ progress.@OBJEXT@ bookmark.@OBJEXT@ pref.@OBJEXT@ preffw.@OBJEXT@ trace.@OBJEXT@ spool.@OBJEXT@ log.@OBJEXT@ getline.@OBJEXT@ + +DPROGS=../bin/ncftp@EXEEXT@ + +all: $(DPROGS) + -@echo 'Done making NcFTP.' + +../bin/ncftp@EXEEXT@: $(OBJS) ../libncftp/libncftp.a +@Z30@ + $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $(OBJS) -o ../bin/ncftp@EXEEXT@ $(LDFLAGS) -lncftp -lStrn -lsio $(LIBS) + -@$(STRIP) ../bin/ncftp@EXEEXT@ + +clean: + /bin/rm -f $(DPROGS) $(OBJS) + +SHELL=/bin/sh +.SUFFIXES: .c .@OBJEXT@ + +.c.@OBJEXT@: + $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c + +PACKAGE=Makefile.in bookmark.c bookmark.h cmdlist.c \ + cmds.c cmds.h getopt.c getopt.h \ + ls.c ls.h main.c main.h \ + pref.c pref.h progress.c progress.h \ + readln.c readln.h shell.c shell.h \ + spool.c spool.h syshdrs.h trace.c \ + trace.h util.c util.h version.c \ + preffw.c log.c log.h getline.c \ + getline.h + +TMPDIR=/tmp +TARDIR=ncftp + +tarcp: + -@mkdir -p $(TMPDIR)/TAR/$(TARDIR) + -@chmod ga+r $(PACKAGE) + -@chmod 755 $(TMPDIR)/TAR/$(TARDIR) + cp -pr $(PACKAGE) $(TMPDIR)/TAR/$(TARDIR) + +### Dependencies ############################################################# + +version.@OBJEXT@: version.c + $(CC) $(CFLAGS) -DOS=\"@OS@\" $< -c + +bookmark.@OBJEXT@: bookmark.c syshdrs.h bookmark.h util.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +cmdlist.@OBJEXT@: cmdlist.c syshdrs.h shell.h bookmark.h cmds.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +cmds.@OBJEXT@: cmds.c syshdrs.h shell.h util.h ls.h bookmark.h cmds.h main.h \ + trace.h pref.h spool.h getopt.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +getopt.@OBJEXT@: getopt.c getopt.h +ls.@OBJEXT@: ls.c syshdrs.h util.h ls.h trace.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +main.@OBJEXT@: main.c syshdrs.h ls.h bookmark.h cmds.h main.h shell.h \ + getopt.h progress.h pref.h readln.h trace.h spool.h util.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +pref.@OBJEXT@: pref.c syshdrs.h pref.h util.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +preffw.@OBJEXT@: preffw.c syshdrs.h pref.h util.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +progress.@OBJEXT@: progress.c syshdrs.h util.h progress.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +readln.@OBJEXT@: readln.c syshdrs.h shell.h util.h bookmark.h cmds.h ls.h \ + readln.h getline.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +shell.@OBJEXT@: shell.c syshdrs.h shell.h util.h bookmark.h cmds.h readln.h \ + trace.h main.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +spool.@OBJEXT@: spool.c syshdrs.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +trace.@OBJEXT@: trace.c syshdrs.h trace.h util.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +util.@OBJEXT@: util.c syshdrs.h shell.h trace.h util.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +log.@OBJEXT@: log.c syshdrs.h log.h util.h ../libncftp/ncftp.h ../libncftp/ncftp_errno.h +getline.@OBJEXT@: getline.c syshdrs.h getline.h diff --git a/modules/rosapps/applications/net/ncftp/ncftp/bookmark.c b/modules/rosapps/applications/net/ncftp/ncftp/bookmark.c new file mode 100644 index 00000000000..e42eaee52e2 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/ncftp/bookmark.c @@ -0,0 +1,845 @@ +/* bookmark.c + * + * Copyright (c) 1992-2001 by Mike Gleason. + * All rights reserved. + * + */ + +#include "syshdrs.h" + +#include "bookmark.h" +#include "util.h" + +/* + * The ~/.ncftp/bookmarks file contains a list of sites + * the user wants to remember. + * + * Unlike previous versions of the program, we now open/close + * the file every time we need it; That way we can have + * multiple ncftp processes changing the file. There is still + * a possibility that two different processes could be modifying + * the file at the same time. + */ + +Bookmark gBm; +int gLoadedBm = 0; +int gBookmarkMatchMode = 0; +int gNumBookmarks = 0; +BookmarkPtr gBookmarkTable = NULL; + +extern char gOurDirectoryPath[]; + +/* Converts a pre-loaded Bookmark structure into a RFC 1738 + * Uniform Resource Locator. + */ +void +BookmarkToURL(BookmarkPtr bmp, char *url, size_t urlsize) +{ + char pbuf[32]; + + /* //:@:/ */ + /* Note that if an absolute path is given, + * you need to escape the first entry, i.e. /pub -> %2Fpub + */ + (void) Strncpy(url, "ftp://", urlsize); + if (bmp->user[0] != '\0') { + (void) Strncat(url, bmp->user, urlsize); + if (bmp->pass[0] != '\0') { + (void) Strncat(url, ":", urlsize); + (void) Strncat(url, "PASSWORD", urlsize); + } + (void) Strncat(url, "@", urlsize); + } + (void) Strncat(url, bmp->name, urlsize); + if (bmp->port != 21) { + (void) sprintf(pbuf, ":%u", (unsigned int) bmp->port); + (void) Strncat(url, pbuf, urlsize); + } + if (bmp->dir[0] == '/') { + /* Absolute URL path, must escape first slash. */ + (void) Strncat(url, "/%2F", urlsize); + (void) Strncat(url, bmp->dir + 1, urlsize); + (void) Strncat(url, "/", urlsize); + } else if (bmp->dir[0] != '\0') { + (void) Strncat(url, "/", urlsize); + (void) Strncat(url, bmp->dir, urlsize); + (void) Strncat(url, "/", urlsize); + } +} /* BookmarkToURL */ + + + + +void +SetBookmarkDefaults(BookmarkPtr bmp) +{ + (void) memset(bmp, 0, sizeof(Bookmark)); + + bmp->xferType = 'I'; + bmp->xferMode = 'S'; /* Use FTP protocol default as ours too. */ + bmp->hasSIZE = kCommandAvailabilityUnknown; + bmp->hasMDTM = kCommandAvailabilityUnknown; + bmp->hasUTIME = kCommandAvailabilityUnknown; + bmp->hasPASV = kCommandAvailabilityUnknown; + bmp->isUnix = 1; + bmp->lastCall = (time_t) 0; + bmp->deleted = 0; +} /* SetBookmarkDefaults */ + + + + +/* Used when converting hex strings to integral types. */ +static int +HexCharToNibble(int c) +{ + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return (c - '0'); + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + return (c - 'a' + 10); + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + return (c - 'A' + 10); + + } + return (-1); /* Error. */ +} /* HexCharToNibble */ + + + + + +/* Fills in a Bookmark structure based off of a line from the NcFTP + * "bookmarks" file. + */ +int +ParseHostLine(char *line, BookmarkPtr bmp) +{ + char token[128]; + char pass[128]; + char *s, *d; + char *tokenend; + long L; + int i; + int result; + int n, n1, n2; + + SetBookmarkDefaults(bmp); + s = line; + tokenend = token + sizeof(token) - 1; + result = -1; + for (i=1; ; i++) { + if (*s == '\0') + break; + /* Some tokens may need to have a comma in them. Since this is a + * field delimiter, these fields use \, to represent a comma, and + * \\ for a backslash. This chunk gets the next token, paying + * attention to the escaped stuff. + */ + for (d = token; *s != '\0'; ) { + if ((*s == '\\') && (s[1] != '\0')) { + if (d < tokenend) + *d++ = s[1]; + s += 2; + } else if (*s == ',') { + ++s; + break; + } else if ((*s == '$') && (s[1] != '\0') && (s[2] != '\0')) { + n1 = HexCharToNibble(s[1]); + n2 = HexCharToNibble(s[2]); + if ((n1 >= 0) && (n2 >= 0)) { + n = (n1 << 4) | n2; + if (d < tokenend) + *(unsigned char *)d++ = (unsigned int) n; + } + s += 3; + } else { + if (d < tokenend) + *d++ = *s; + ++s; + } + } + *d = '\0'; + switch(i) { + case 1: (void) STRNCPY(bmp->bookmarkName, token); break; + case 2: (void) STRNCPY(bmp->name, token); break; + case 3: (void) STRNCPY(bmp->user, token); break; + case 4: (void) STRNCPY(bmp->pass, token); break; + case 5: (void) STRNCPY(bmp->acct, token); break; + case 6: (void) STRNCPY(bmp->dir, token); + result = 0; /* Good enough to have these fields. */ + break; + case 7: + if (token[0] != '\0') + bmp->xferType = (int) token[0]; + break; + case 8: + /* Most of the time, we won't have a port. */ + if (token[0] == '\0') + bmp->port = (unsigned int) kDefaultFTPPort; + else + bmp->port = (unsigned int) atoi(token); + break; + case 9: + (void) sscanf(token, "%lx", &L); + bmp->lastCall = (time_t) L; + break; + case 10: bmp->hasSIZE = atoi(token); break; + case 11: bmp->hasMDTM = atoi(token); break; + case 12: bmp->hasPASV = atoi(token); break; + case 13: bmp->isUnix = atoi(token); + result = 3; /* Version 3 had all fields to here. */ + break; + case 14: (void) STRNCPY(bmp->lastIP, token); break; + case 15: (void) STRNCPY(bmp->comment, token); break; + case 16: + case 17: + case 18: + case 19: + break; + case 20: bmp->xferMode = token[0]; + result = 7; /* Version 7 has all fields to here. */ + break; + case 21: bmp->hasUTIME = atoi(token); + break; + case 22: (void) STRNCPY(bmp->ldir, token); + result = 8; /* Version 8 has all fields to here. */ + break; + default: + result = 99; /* Version >8 ? */ + goto done; + } + } +done: + + /* Decode password, if it was base-64 encoded. */ + if (strncmp(bmp->pass, kPasswordMagic, kPasswordMagicLen) == 0) { + FromBase64(pass, bmp->pass + kPasswordMagicLen, strlen(bmp->pass + kPasswordMagicLen), 1); + (void) STRNCPY(bmp->pass, pass); + } + return (result); +} /* ParseHostLine */ + + + + +void +CloseBookmarkFile(FILE *fp) +{ + if (fp != NULL) + (void) fclose(fp); +} /* CloseBookmarkFile */ + + + + + +int +GetNextBookmark(FILE *fp, Bookmark *bmp) +{ + char line[512]; + + while (FGets(line, sizeof(line), fp) != NULL) { + if (ParseHostLine(line, bmp) >= 0) + return (0); + } + return (-1); +} /* GetNextBookmark */ + + + + +/* Opens a NcFTP 2.x or 3.x style bookmarks file, and sets the file pointer + * so that it is ready to read the first data line. + */ +FILE * +OpenBookmarkFile(int *numBookmarks0) +{ + char pathName[256], path2[256]; + char line[256]; + FILE *fp; + int version; + int numBookmarks; + Bookmark junkbm; + + if (gOurDirectoryPath[0] == '\0') + return NULL; /* Don't create in root directory. */ + (void) OurDirectoryPath(pathName, sizeof(pathName), kBookmarkFileName); + fp = fopen(pathName, FOPEN_READ_TEXT); + if (fp == NULL) { + /* See if it exists under the old name. */ + (void) OurDirectoryPath(path2, sizeof(path2), kOldBookmarkFileName); + if (rename(path2, pathName) == 0) { + /* Rename succeeded, now open it. */ + fp = fopen(pathName, FOPEN_READ_TEXT); + if (fp == NULL) + return NULL; + } + return NULL; /* Okay to not have one yet. */ + } + + (void) _chmod(pathName, 00600); + if (FGets(line, sizeof(line), fp) == NULL) { + (void) fprintf(stderr, "%s: invalid format.\n", pathName); + (void) fclose(fp); + return NULL; + } + + /* Sample line we're looking for: + * "NcFTP bookmark-file version: 8" + */ + version = -1; + (void) sscanf(line, "%*s %*s %*s %d", &version); + if (version < kBookmarkMinVersion) { + if (version < 0) { + (void) fprintf(stderr, "%s: invalid format, or bad version.\n", pathName); + (void) fclose(fp); + return NULL; + } + (void) STRNCPY(path2, pathName); + (void) sprintf(line, ".v%d", version); + (void) STRNCAT(path2, line); + (void) rename(pathName, path2); + (void) fprintf(stderr, "%s: old version.\n", pathName); + (void) fclose(fp); + return NULL; + } + + /* Sample line we're looking for: + * "Number of entries: 28" or "# # # 1" + */ + numBookmarks = -1; + + /* At the moment, we can't trust the number stored in the + * file. It's there for future use. + */ + if (FGets(line, sizeof(line), fp) == NULL) { + (void) fprintf(stderr, "%s: invalid format.\n", pathName); + (void) fclose(fp); + return NULL; + } + + if (numBookmarks0 == (int *) 0) { + /* If the caller doesn't care how many bookmarks are *really* + * in the file, then we can return now. + */ + return(fp); + } + + /* Otherwise, we have to read through the whole file because + * unfortunately the header line can't be trusted. + */ + for (numBookmarks = 0; ; numBookmarks++) { + if (GetNextBookmark(fp, &junkbm) < 0) + break; + } + + /* Now we have to re-open and re-position the file. + * We don't use rewind() because it doesn't always work. + * This introduces a race condition, but the bookmark + * functionality wasn't designed to be air-tight. + */ + CloseBookmarkFile(fp); + fp = fopen(pathName, FOPEN_READ_TEXT); + if (fp == NULL) + return (NULL); + if (FGets(line, sizeof(line), fp) == NULL) { + (void) fprintf(stderr, "%s: invalid format.\n", pathName); + (void) fclose(fp); + return NULL; + } + + if (FGets(line, sizeof(line), fp) == NULL) { + (void) fprintf(stderr, "%s: invalid format.\n", pathName); + (void) fclose(fp); + return NULL; + } + + /* NOW we're done. */ + *numBookmarks0 = numBookmarks; + return (fp); +} /* OpenBookmarkFile */ + + + + +/* Looks for a saved bookmark by the abbreviation given. */ +int +GetBookmark(const char *const bmabbr, Bookmark *bmp) +{ + FILE *fp; + char line[512]; + Bookmark byHostName; + Bookmark byHostAbbr; + Bookmark byBmAbbr; + size_t byBmNameFlag = 0; + size_t byBmAbbrFlag = 0; + size_t byHostNameFlag = 0; + size_t byHostAbbrFlag = 0; + int result = -1; + int exactMatch = 0; + size_t bmabbrLen; + char *cp; + + fp = OpenBookmarkFile(NULL); + if (fp == NULL) + return (-1); + + bmabbrLen = strlen(bmabbr); + while (FGets(line, sizeof(line), fp) != NULL) { + if (ParseHostLine(line, bmp) < 0) + continue; + if (ISTREQ(bmp->bookmarkName, bmabbr)) { + /* Exact match, done. */ + byBmNameFlag = bmabbrLen; + exactMatch = 1; + break; + } else if (ISTRNEQ(bmp->bookmarkName, bmabbr, bmabbrLen)) { + /* Remember this one, it matched an abbreviated + * bookmark name. + */ + byBmAbbr = *bmp; + byBmAbbrFlag = bmabbrLen; + } else if (ISTREQ(bmp->name, bmabbr)) { + /* Remember this one, it matched a full + * host name. + */ + byHostName = *bmp; + byHostNameFlag = bmabbrLen; + } else if ((cp = strchr(bmp->name, '.')) != NULL) { + /* See if it matched part of the hostname. */ + if (ISTRNEQ(bmp->name, "ftp", 3)) { + cp = cp + 1; + } else if (ISTRNEQ(bmp->name, "www", 3)) { + cp = cp + 1; + } else { + cp = bmp->name; + } + if (ISTRNEQ(cp, bmabbr, bmabbrLen)) { + /* Remember this one, it matched a full + * host name. + */ + byHostAbbr = *bmp; + byHostAbbrFlag = bmabbrLen; + } + } + } + + if (gBookmarkMatchMode == 0) { + /* Only use a bookmark when the exact + * bookmark name was used. + */ + if (exactMatch != 0) { + result = 0; + } + } else { + /* Pick the best match, if any. */ + if (byBmNameFlag != 0) { + /* *bmp is already set. */ + result = 0; + } else if (byBmAbbrFlag != 0) { + result = 0; + *bmp = byBmAbbr; + } else if (byHostNameFlag != 0) { + result = 0; + *bmp = byHostName; + } else if (byHostAbbrFlag != 0) { + result = 0; + *bmp = byHostAbbr; + } + } + + if (result != 0) + memset(bmp, 0, sizeof(Bookmark)); + + CloseBookmarkFile(fp); + return (result); +} /* GetBookmark */ + + + + +static int +BookmarkSortProc(const void *a, const void *b) +{ + return (ISTRCMP((*(Bookmark *)a).bookmarkName, (*(Bookmark *)b).bookmarkName)); +} /* BookmarkSortProc */ + + + +static int +BookmarkSearchProc(const void *key, const void *b) +{ + return (ISTRCMP((char *) key, (*(Bookmark *)b).bookmarkName)); +} /* BookmarkSearchProc */ + + + +BookmarkPtr +SearchBookmarkTable(const char *key) +{ + return ((BookmarkPtr) bsearch(key, gBookmarkTable, (size_t) gNumBookmarks, sizeof(Bookmark), BookmarkSearchProc)); +} /* SearchBookmarkTable */ + + + + +void +SortBookmarks(void) +{ + if ((gBookmarkTable == NULL) || (gNumBookmarks < 2)) + return; + + /* Sorting involves swapping entire Bookmark structures. + * Normally the proper thing to do is to use an array + * of pointers to Bookmarks and sort them, but even + * these days a large bookmark list can be sorted in + * the blink of an eye. + */ + qsort(gBookmarkTable, (size_t) gNumBookmarks, sizeof(Bookmark), BookmarkSortProc); +} /* SortBookmarks */ + + + +int +LoadBookmarkTable(void) +{ + int i, nb; + FILE *infp; + + infp = OpenBookmarkFile(&nb); + if (infp == NULL) { + nb = 0; + } + if ((nb != gNumBookmarks) && (gBookmarkTable != NULL)) { + /* Re-loading the table from disk. */ + gBookmarkTable = (Bookmark *) realloc(gBookmarkTable, (size_t) (nb + 1) * sizeof(Bookmark)); + memset(gBookmarkTable, 0, (nb + 1) * sizeof(Bookmark)); + } else { + gBookmarkTable = calloc((size_t) (nb + 1), (size_t) sizeof(Bookmark)); + } + + if (gBookmarkTable == NULL) { + CloseBookmarkFile(infp); + return (-1); + } + + for (i=0; ibookmarkName) < 0) return (-1) ;/*1*/ + if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->name)) < 0) return (-1) ;/*2*/ + if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->user)) < 0) return (-1) ;/*3*/ + if ((bmp->pass[0] != '\0') && (savePassword == 1)) { + (void) memcpy(pass, kPasswordMagic, kPasswordMagicLen); + ToBase64(pass + kPasswordMagicLen, bmp->pass, strlen(bmp->pass), 1); + if (fprintf(outfp, ",%s", pass) < 0) return (-1) ;/*4*/ + } else { + if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*4*/ + } + if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->acct)) < 0) return (-1) ;/*5*/ + if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->dir)) < 0) return (-1) ;/*6*/ + if (fprintf(outfp, ",%c", bmp->xferType) < 0) return (-1) ;/*7*/ + if (fprintf(outfp, ",%u", (unsigned int) bmp->port) < 0) return (-1) ;/*8*/ + if (fprintf(outfp, ",%lu", (unsigned long) bmp->lastCall) < 0) return (-1) ;/*9*/ + if (fprintf(outfp, ",%d", bmp->hasSIZE) < 0) return (-1) ;/*10*/ + if (fprintf(outfp, ",%d", bmp->hasMDTM) < 0) return (-1) ;/*11*/ + if (fprintf(outfp, ",%d", bmp->hasPASV) < 0) return (-1) ;/*12*/ + if (fprintf(outfp, ",%d", bmp->isUnix) < 0) return (-1) ;/*13*/ + if (fprintf(outfp, ",%s", bmp->lastIP) < 0) return (-1) ;/*14*/ + if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->comment)) < 0) return (-1) ;/*15*/ + if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*16*/ + if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*17*/ + if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*18*/ + if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*19*/ + if (fprintf(outfp, ",%c", bmp->xferMode) < 0) return (-1) ;/*20*/ + if (fprintf(outfp, ",%d", bmp->hasUTIME) < 0) return (-1) ;/*21*/ + if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->ldir)) < 0) return (-1) ;/*22*/ + if (fprintf(outfp, "\n") < 0) return (-1) ; + if (fflush(outfp) < 0) return (-1); + return (0); +} /* WriteBmLine */ + + + +static int +SwapBookmarkFiles(void) +{ + char pidStr[32]; + char pathName[256], path2[256]; + + (void) OurDirectoryPath(path2, sizeof(path2), kBookmarkFileName); + (void) OurDirectoryPath(pathName, sizeof(pathName), kTmpBookmarkFileName); + (void) sprintf(pidStr, "-%u.txt", (unsigned int) getpid()); + (void) STRNCAT(pathName, pidStr); + + (void) remove(path2); + if (rename(pathName, path2) < 0) { + return (-1); + } + return (0); +} /* SwapBookmarkFiles */ + + + + + + +/* Saves a Bookmark structure into the bookmarks file. */ +FILE * +OpenTmpBookmarkFile(int nb) +{ + FILE *outfp; + char pidStr[32]; + char pathName[256], path2[256]; + + if (gOurDirectoryPath[0] == '\0') + return (NULL); /* Don't create in root directory. */ + + (void) OurDirectoryPath(path2, sizeof(path2), kBookmarkFileName); + (void) OurDirectoryPath(pathName, sizeof(pathName), kTmpBookmarkFileName); + (void) sprintf(pidStr, "-%u.txt", (unsigned int) getpid()); + (void) STRNCAT(pathName, pidStr); + + outfp = fopen(pathName, FOPEN_WRITE_TEXT); + if (outfp == NULL) { + (void) fprintf(stderr, "Could not save bookmark.\n"); + perror(pathName); + return (NULL); + } + (void) _chmod(pathName, 00600); + if (nb > 0) { + if (fprintf(outfp, "NcFTP bookmark-file version: %d\nNumber of bookmarks: %d\n", kBookmarkVersion, nb) < 0) { + (void) fprintf(stderr, "Could not save bookmark.\n"); + perror(pathName); + (void) fclose(outfp); + return (NULL); + } + } else { + if (fprintf(outfp, "NcFTP bookmark-file version: %d\nNumber of bookmarks: ??\n", kBookmarkVersion) < 0) { + (void) fprintf(stderr, "Could not save bookmark.\n"); + perror(pathName); + (void) fclose(outfp); + return (NULL); + } + } + + return (outfp); +} /* OpenTmpBookmarkFile */ + + + + +int +SaveBookmarkTable(void) +{ + int i; + FILE *outfp; + int nb; + + if ((gNumBookmarks < 1) || (gBookmarkTable == NULL)) + return (0); /* Nothing to save. */ + + /* Get a count of live bookmarks. */ + for (i=0, nb=0; ibookmarkName); + (void) STRNCAT(bmAbbr, ","); + len = strlen(bmAbbr); + + /* This may fail the first time we ever save a bookmark. */ + infp = OpenBookmarkFile(NULL); + if (infp != NULL) { + while (FGets(line, sizeof(line), infp) != NULL) { + if (strncmp(line, bmAbbr, len) == 0) { + /* Replace previous entry. */ + if (WriteBmLine(bmp, outfp, savePassword) < 0) { + (void) fprintf(stderr, "Could not save bookmark.\n"); + perror("reason"); + (void) fclose(outfp); + } + replaced = 1; + } else { + if (fprintf(outfp, "%s\n", line) < 0) { + (void) fprintf(stderr, "Could not save bookmark.\n"); + perror("reason"); + (void) fclose(outfp); + return (-1); + } + } + } + CloseBookmarkFile(infp); + } + + if (replaced == 0) { + /* Add it as a new bookmark. */ + if (WriteBmLine(bmp, outfp, savePassword) < 0) { + (void) fprintf(stderr, "Could not save bookmark.\n"); + perror("reason"); + (void) fclose(outfp); + return (-1); + } + } + + if (fclose(outfp) < 0) { + (void) fprintf(stderr, "Could not save bookmark.\n"); + perror("reason"); + return (-1); + } + + if (SwapBookmarkFiles() < 0) { + (void) fprintf(stderr, "Could not rename bookmark file.\n"); + perror("reason"); + return (-1); + } + return (0); +} /* PutBookmark */ + + + + +/* Tries to generate a bookmark abbreviation based off of the hostname. */ +void +DefaultBookmarkName(char *dst, size_t siz, char *src) +{ + char str[128]; + const char *token; + const char *cp; + + (void) STRNCPY(str, src); + + /* Pick the first "significant" part of the hostname. Usually + * this is the first word in the name, but if it's something like + * ftp.unl.edu, we would want to choose "unl" and not "ftp." + */ + token = str; + if ((token = strtok(str, ".")) == NULL) + token = str; + else if ((ISTRNEQ(token, "ftp", 3)) || (ISTRNEQ(token, "www", 3))) { + if ((token = strtok(NULL, ".")) == NULL) + token = ""; + } + for (cp = token; ; cp++) { + if (*cp == '\0') { + /* Token was all digits, like an IP address perhaps. */ + token = ""; + } + if (!isdigit((int) *cp)) + break; + } + (void) Strncpy(dst, token, siz); +} /* DefaultBookmarkName */ diff --git a/modules/rosapps/applications/net/ncftp/ncftp/bookmark.h b/modules/rosapps/applications/net/ncftp/ncftp/bookmark.h new file mode 100644 index 00000000000..35dd9ae2a91 --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/ncftp/bookmark.h @@ -0,0 +1,59 @@ +/* bookmark.h + * + * Copyright (c) 1992-2001 by Mike Gleason. + * All rights reserved. + * + */ + +typedef struct Bookmark *BookmarkPtr; +typedef struct Bookmark { + char bookmarkName[16]; + char name[64]; + char user[64]; + char pass[64]; + char acct[64]; + char dir[160]; + char ldir[160]; + int xferType; + unsigned int port; + time_t lastCall; + int hasSIZE; + int hasMDTM; + int hasPASV; + int isUnix; + char lastIP[32]; + char comment[128]; + int xferMode; + int hasUTIME; + + int deleted; +} Bookmark; + +#define kBookmarkVersion 8 +#define kBookmarkMinVersion 3 +#if defined(WIN32) || defined(_WINDOWS) +# define kBookmarkFileName "bookmarks.txt" +#else +# define kBookmarkFileName "bookmarks" +#endif +#define kTmpBookmarkFileName "bookmarks-tmp" +#define kOldBookmarkFileName "hosts" +#define kBookmarkBupFileName "bookmarks.old" + +#define BMTINDEX(p) ((int) ((char *) p - (char *) gBookmarkTable) / (int) sizeof(Bookmark)) + +/* bookmark.c */ +void BookmarkToURL(BookmarkPtr, char *, size_t); +void SetBookmarkDefaults(BookmarkPtr); +int ParseHostLine(char *, BookmarkPtr); +void CloseBookmarkFile(FILE *); +FILE *OpenBookmarkFile(int *); +FILE *OpenTmpBookmarkFile(int); +int SaveBookmarkTable(void); +int GetNextBookmark(FILE *, Bookmark *); +int GetBookmark(const char *const, Bookmark *); +int PutBookmark(Bookmark *, int); +int LoadBookmarkTable(void); +BookmarkPtr SearchBookmarkTable(const char *); +void SortBookmarks(void); +void DefaultBookmarkName(char *, size_t, char *); diff --git a/modules/rosapps/applications/net/ncftp/ncftp/cmdlist.c b/modules/rosapps/applications/net/ncftp/ncftp/cmdlist.c new file mode 100644 index 00000000000..52f3dc9f76e --- /dev/null +++ b/modules/rosapps/applications/net/ncftp/ncftp/cmdlist.c @@ -0,0 +1,527 @@ +/* cmdlist.c + * + * Copyright (c) 1992-2001 by Mike Gleason. + * All rights reserved. + * + */ + +#include "syshdrs.h" +#include "shell.h" +#include "bookmark.h" +#include "cmds.h" + +/* These will be sorted lexiographically when the program is run, but + * they should already be listed that way. + */ +Command gCommands[] = { +#if defined(WIN32) || defined(_WINDOWS) +#else + { "!", + ShellCmd, + "[arguments]", + "Runs a subshell", + kCmdHidden, + kNoMin, kNoMax, + }, +#endif + { "?", + HelpCmd, + "[optional commands]", + "shows commands, or detailed help on specified commands", + kCmdHidden, + kNoMin, kNoMax, + }, + { "ascii", + TypeCmd, + "", + "sets the file transfer type to ASCII text", + kCmdMustBeConnected, + 0, 0, + }, + { "bgget", + SpoolGetCmd, +"[-flags] file1 [file2...]\n\ +Flags:\n\ + -R : Recursive. Useful for fetching whole directories.\n\ + -z : Get the remote file X, and name it to Y.\n\ + -@