Files
Mozilla/mozilla/lib/mac/NSStdLib/src/MacOSX_Console.cpp
ccarlen%netscape.com 1731924479 Adding new files for conversion to CW7 and XML project files. Bug 98349 r=pink/sr=sfraser.
git-svn-id: svn://10.0.0.236/trunk@110182 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-10 21:58:15 +00:00

333 lines
10 KiB
C++

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Patrick C. Beard <beard@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
////////////////////////////////////////////////////////////////////////////////
// Console stubs that send all console output to the Mac OS X Console.app, or
// to the terminal, if Mozilla is launched from the command line.
////////////////////////////////////////////////////////////////////////////////
#include <console.h>
#include <size_t.h>
#include <string.h>
#include <CFURL.h>
#include <CFBundle.h>
#include <CFString.h>
#include <MacErrors.h>
#include <Gestalt.h>
#include <CodeFragments.h>
#include <Fonts.h>
#include <TextEdit.h>
#include <Controls.h>
#include <SIOUX.h>
#include <SIOUXWindows.h>
#include <console_io.h>
#include <stdlib.h>
static CFBundleRef getBundle(CFStringRef frameworkPath)
{
CFBundleRef bundle = NULL;
// Make a CFURLRef from the CFString representation of the bundle's path.
// See the Core Foundation URL Services chapter for details.
CFURLRef bundleURL = CFURLCreateWithFileSystemPath(NULL, frameworkPath, kCFURLPOSIXPathStyle, true);
if (bundleURL != NULL) {
bundle = CFBundleCreate(NULL, bundleURL);
if (bundle != NULL)
CFBundleLoadExecutable(bundle);
CFRelease(bundleURL);
}
return bundle;
}
static void* getSystemFunction(CFStringRef functionName)
{
static CFBundleRef systemBundle = getBundle(CFSTR("/System/Library/Frameworks/System.framework"));
if (systemBundle) return CFBundleGetFunctionPointerForName(systemBundle, functionName);
return NULL;
}
// Useful Carbon-CFM debugging tool, printf that goes to the system console.
typedef int (*io_proc_ptr) (int fd, void* buffer, long count);
#if TARGET_CARBON
static io_proc_ptr system_read = (io_proc_ptr) getSystemFunction(CFSTR("read"));
static io_proc_ptr system_write = (io_proc_ptr) getSystemFunction(CFSTR("write"));
#else
static io_proc_ptr system_read = 0;
static io_proc_ptr system_write = 0;
#endif
/*
* The following four functions provide the UI for the console package.
* Users wishing to replace SIOUX with their own console package need
* only provide the four functions below in a library.
*/
static CFragConnectionID gConsoleLibrary;
static void* find_symbol(CFragConnectionID connection, StringPtr symName)
{
Ptr symAddr;
if (FindSymbol(gConsoleLibrary, symName, &symAddr, NULL) == noErr)
return symAddr;
return NULL;
}
/*
* extern short InstallConsole(short fd);
*
* Installs the Console package, this function will be called right
* before any read or write to one of the standard streams.
*
* short fd: The stream which we are reading/writing to/from.
* returns short: 0 no error occurred, anything else error.
*/
short InstallConsole(short fd)
{
long version;
OSErr err = Gestalt(gestaltSystemVersion, &version);
if (err == noErr && version < 0x00001000) {
// load the "NSConsole" library.
err = GetSharedLibrary("\pNSConsole", kCompiledCFragArch, kReferenceCFrag,
&gConsoleLibrary, NULL, NULL);
if (err == noErr) {
atexit(&RemoveConsole);
// transfer the SIOUX settings.
tSIOUXSettings *sioux_settings = (tSIOUXSettings*) find_symbol(gConsoleLibrary, "\pSIOUXSettings");
if (sioux_settings) {
*sioux_settings = SIOUXSettings;
short (*install_console) (short) = (short (*) (short)) find_symbol(gConsoleLibrary, "\pInstallConsole");
if (install_console)
return install_console(fd);
}
}
}
return 0;
}
/*
* extern void RemoveConsole(void);
*
* Removes the console package. It is called after all other streams
* are closed and exit functions (installed by either atexit or _atexit)
* have been called. Since there is no way to recover from an error,
* this function doesn't need to return any.
*/
void RemoveConsole()
{
if (gConsoleLibrary) {
void (*remove_console) (void) = (void (*) (void)) find_symbol(gConsoleLibrary, "\pInstallConsole");
if (remove_console)
remove_console();
CloseConnection(&gConsoleLibrary);
gConsoleLibrary = NULL;
}
}
/*
* extern long WriteCharsToConsole(char *buffer, long n);
*
* Writes a stream of output to the Console window. This function is
* called by write.
*
* char *buffer: Pointer to the buffer to be written.
* long n: The length of the buffer to be written.
* returns short: Actual number of characters written to the stream,
* -1 if an error occurred.
*/
long WriteCharsToConsole(char *buffer, long n)
{
if (gConsoleLibrary) {
static long (*write_chars) (char*, long) = (long (*) (char*, long)) find_symbol(gConsoleLibrary, "\pWriteCharsToConsole");
if (write_chars)
return write_chars(buffer, n);
} else {
for (char* cr = strchr(buffer, '\r'); cr; cr = strchr(cr + 1, '\r'))
*cr = '\n';
if (system_write) return system_write(1, buffer, n);
}
return 0;
}
/*
* extern long ReadCharsFromConsole(char *buffer, long n);
*
* Reads from the Console into a buffer. This function is called by
* read.
*
* char *buffer: Pointer to the buffer which will recieve the input.
* long n: The maximum amount of characters to be read (size of
* buffer).
* returns short: Actual number of characters read from the stream,
* -1 if an error occurred.
*/
long ReadCharsFromConsole(char *buffer, long n)
{
if (gConsoleLibrary) {
static long (*read_chars) (char*, long) = (long (*) (char*, long)) find_symbol(gConsoleLibrary, "\pReadCharsFromConsole");
if (read_chars)
return read_chars(buffer, n);
} else {
if (system_read) return system_read(0, buffer, n);
}
return -1;
}
extern char *__ttyname(long fildes)
{
if (fildes >= 0 && fildes <= 2)
return "console";
return (0L);
}
int kbhit(void)
{
return 0;
}
int getch(void)
{
return 0;
}
void clrscr()
{
/* Could send the appropriate VT100 sequence here... */
}
tSIOUXSettings SIOUXSettings = {
true, true, true, false, true, false, NULL,
4, 80, 24, 0, 0, kFontIDMonaco,
9, normal, true, true, false
};
short SIOUXHandleOneEvent(EventRecord *userevent)
{
if (gConsoleLibrary) {
static short (*handle_event) (EventRecord*) = (short (*) (EventRecord*)) find_symbol(gConsoleLibrary, "\pSIOUXHandleOneEvent");
if (handle_event)
return handle_event(userevent);
}
return false;
}
Boolean SIOUXIsAppWindow(WindowPtr window)
{
if (gConsoleLibrary) {
static Boolean (*is_app_window) (WindowPtr) = (Boolean (*) (WindowPtr)) find_symbol(gConsoleLibrary, "\pSIOUXIsAppWindow");
if (is_app_window)
return is_app_window(window);
}
return false;
}
/**
* Lower level console implementation. Let's us distinguish stdout from stderr.
*/
static int check_console()
{
static short status = (InstallConsole(0) == 0);
return status;
}
using namespace std;
int __read_console(__file_handle handle, unsigned char * buffer, size_t * count, __idle_proc idle_proc)
{
if (!check_console())
return(__io_error);
fflush(stdout);
long n = *count;
if (gConsoleLibrary) {
static long (*read_chars) (char*, long) = (long (*) (char*, long)) find_symbol(gConsoleLibrary, "\pReadCharsFromConsole");
if (read_chars)
n = read_chars((char*)buffer, n);
else
n = -1;
} else {
if (system_read)
n = system_read(handle, buffer, n);
else
n = -1;
}
*count = n;
return (n == -1 ? __io_error : __no_io_error);
}
int __write_console(__file_handle handle, unsigned char * buffer, size_t * count, __idle_proc idle_proc)
{
if (!check_console())
return(__io_error);
long n = *count;
if (gConsoleLibrary) {
static long (*write_chars) (char*, long) = (long (*) (char*, long)) find_symbol(gConsoleLibrary, "\pWriteCharsToConsole");
if (write_chars)
n = write_chars((char*)buffer, n);
else
n = -1;
} else {
if (system_write) {
for (char* cr = strchr((char*)buffer, '\r'); cr; cr = strchr(cr + 1, '\r'))
*cr = '\n';
n = system_write(handle, buffer, n);
} else {
n = -1;
}
}
*count = n;
return (n == -1 ? __io_error : __no_io_error);
}
int __close_console(__file_handle handle)
{
return(__no_io_error);
}