Module: environment-framework Synopsis: Environment Framework Author: Jason Trenouth Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND /// Useful constants define constant $environment-user-exit-code = 1; /// ENVIRONMENT-HANDLER define method environment-handler (condition :: , next-handler :: ) block () do-environment-handler(condition, next-handler); exception (condition :: ) debug-message("Internal error in environment error handler: %s", safe-condition-to-string(condition)); if (release-internal?()) // Internally go straight into the debugger, so we can track down the bug! default-handler(condition) else // Give the next handler a crack at this condition. next-handler() end; end block; end method environment-handler; /// DO-ENVIRONMENT-HANDLER define method do-environment-handler (condition :: , next-handler :: ) => () let (dialog, ok?) = choose-condition-action(condition); if (ok?) select (dialog.handler-dialog-action-pane.gadget-value) #"abort" => abort(); #"exit" => exit-application($environment-user-exit-code); #"debug" => default-handler(condition); // Cut out the other handlers now and invoke the debugger immediately. end select; else // If user manages to cancel dialog somehow, just abort I presume? abort(); end if; end method do-environment-handler; /// DO-ENVIRONMENT-HANDLER define method do-environment-handler (condition :: , next-handler :: ) => () let product-name = safe-release-product-name(); let message = format-to-string ("%s is running very low on memory, so unsaved data may be lost.\n" "Please close any unused projects or applications.", product-name); let owner = current-frame(); apply(notify-user, message, title: product-name, style: #"error", owner: frame-mapped?(owner) & owner) end method do-environment-handler; /// CHOOSE-CONDITION-ACTION define method choose-condition-action (condition :: ) => (dialog :: , ok? :: ) let framem = find-frame-manager(); with-frame-manager (framem) let dialog = make(, owner: current-frame(), condition: condition); values(dialog, start-dialog(dialog) & #t); end; end method choose-condition-action; /// $INTERNAL-ERROR-BITMAP define variable $internal-error-bitmap = #f; /// SAFE-RELEASE-PRODUCT-NAME // // Unfortunately, release-product-name isn't available until the edition // specific DLL has been initialized, and this error handler can kick in // before then. So just use "Functional Developer" if we can't do better, // because we really shouldn't be crashing here. define constant $product-name = "Functional Developer"; define function safe-release-product-name () => (name :: ) block () release-product-name() exception (error :: ) $product-name end end function safe-release-product-name; /// SAFE-CONDITION-TO-STRING // // Be sure that we never crash trying to display a condition message. define method safe-condition-to-string (condition :: ) => (string :: ) block () block () format-to-string("%s", condition); exception (print-error :: ) format-to-string("%=\nsignalled while trying to print an instance of %=", print-error, object-class(condition)); end block; exception (error :: ) "*** Crashed trying to print condition ***" end end method safe-condition-to-string; /// define frame () keyword title: = safe-release-product-name(); keyword cancel-callback: = #f; constant slot handler-dialog-condition :: , required-init-keyword: condition:; pane handler-dialog-message-pane (dialog) make(, read-only?: #t, tab-stop?: #t, border: #"sunken", scroll-bars: #"vertical", lines: 6, columns: 80); pane handler-dialog-action-pane (dialog) make(, items: compute-handler-action-items(), label-key: tail, value-key: head, orientation: #"vertical", selection: vector(0)); layout (dialog) horizontally (spacing: 8, y-alignment: #"top") make(