/* -*- 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 * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); }