/* Copyright 1997 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /***************************************************/ /* File : Main.c */ /* */ /* Purpose: To run. */ /* */ /* Author : A.D.Hodgkinson */ /* */ /* History: 12-Nov-96: Created. */ /***************************************************/ #include "setjmp.h" #include "signal.h" #include #include #include #include #include #include "swis.h" #include "kernel.h" #include "flex.h" #include "HTMLLib.h" /* HTML library API, Which will include html2_ext.h, tags.h and struct.h */ #include "URI.h" /* URI handler API, in URILib:h */ #include "wimp.h" #include "wimplib.h" #include "event.h" #include "toolbox.h" #include "quit.h" #include "proginfo.h" #include "window.h" #include "menu.h" #include "saveas.h" #include "printdbox.h" #include "gadgets.h" #include "svcprint.h" #include "Global.h" #include "FromROSLib.h" #include "TBEvents.h" /* Which includes loads of stuff... */ #include "Utils.h" #include "Browser.h" #include "FontManage.h" #include "Handlers.h" #include "History.h" #include "MiscDefs.h" #include "Mouse.h" #include "Protocols.h" #include "URLutils.h" #include "Windows.h" /* The following three are defined or undefined locally */ #undef INCLUDE_HEAPGRAPH #undef INCLUDE_HIERPROF #undef INCLUDE_MEMCHECK #ifdef INCLUDE_HEAPGRAPH #include "HeapGraph.HeapGraph.h" #endif #ifdef INCLUDE_HIERPROF #define HierProf_PROFILE #include "HierProf:HierProf.h" #endif #ifdef INCLUDE_MEMCHECK #include "MemCheck:MemCheck.h" #endif /* Finally, Main.h itself */ #include "Main.h" /* Static function prototypes */ static void initialise_app (void); static _kernel_oserror * open_messages_file (int which); static void close_messages_file (void * control); static void load_choices (void); static void catch_errors (int signum); static void termination (void); /* Make sure the stack starts at a reasonable size to prevent frequent */ /* stack extensions - this is a directive to the C run time system and */ /* can be removed on other systems which have no equivalent. */ int __root_stack_size = 16384; /* To hold where the task is coming from (malloced in main) */ static char * task_dir = NULL; // /*************************************************/ // /* attach_event_handlers() */ // /* */ // /* Called when an object is autocreated by the */ // /* toolbox (see initialise_app). Used to get at */ // /* the ObjectID of things without needing a */ // /* specifically generated event to deliver it. */ // /*************************************************/ // // int attach_event_handlers(int eventcode,ToolboxEvent *event,IdBlock *idb,void *handle) // { // ObjectId temp; // // ToolboxObjectAutoCreatedEvent *c=(ToolboxObjectAutoCreatedEvent *) event; // // /* We extract the relevant object Id by comparing the template name */ // /* given in the event structure with something we know about and */ // /* proceeding as is relevant. */ // // if (!strcmp(c->template_name,"Browser")) // { // main_window_id = idb->self_id; // show_centred(main_window_id); // } // else if (!strcmp(c->template_name,"ButtonBar")) // { // temp = idb->self_id; // { // BBox b; // b.xmin=0; // b.ymin=-144; // b.xmax=16384; // b.ymax=0; // set_corrected_extent(0,temp,&b); // } // } // // return 1; // } /*************************************************/ /* initialise_app() */ /* */ /* Initialises application as a Toolbox task. */ /*************************************************/ static void initialise_app(void) { int module_version; show_error(event_initialise(&idb)); // show_error(event_register_toolbox_handler(-1, // Toolbox_ObjectAutoCreated, // attach_event_handlers, // NULL)); /* Register fundamental handlers and initialise as a Toolbox task */ show_error(event_register_message_handler(Wimp_MQuit, handle_messages, NULL)); /* Check the Wimp version; for window managers of 3.8 and above, */ /* declare a minimum version of 3.80 so borderless windows can */ /* still have tools. Otherwise, only ask for 3.1. */ _swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 7, &module_version); if (module_version >= 387) nested_wimp = 1; else nested_wimp = 0; show_error(toolbox_initialise(0, nested_wimp ? WIMPMINH : WIMPMINL, messages_list, event_code_list, task_dir, &meb, &idb, &wimp_version, &task_handle, (void *) &sprite_block)); /* Register a handler for Toolbox errors */ show_error(event_register_toolbox_handler(-1, Toolbox_Error, report_toolbox_error, NULL)); /* Open the Choices and Controls files */ cob = chb = NULL; show_error(open_messages_file(0)); show_error(open_messages_file(1)); /* If the system variable 'Browse$IssueDesktopCommand' is set to 'yes', */ /* then the AcornURI and/or TaskModule modules were started in !Run and */ /* we must issue a *Desktop command to start their task components. */ { char combuf[96]; sprintf(combuf, "If \"\" = \"yes\" Then WimpTask Desktop\r\n"); _swix(OS_CLI, /* Don't want to hear about any errors */ _IN(0), combuf); } /* Quit menu items are set to give the Quit_Quit event type, as well as */ /* this event possibly being delivered by the Toolbox from elsewhere. */ show_error(event_register_toolbox_handler(-1, Quit_Quit, handle_quit, NULL)); /* Called before the application's Info box is shown */ show_error(event_register_toolbox_handler(-1, ProgInfo_AboutToBeShown, handle_show_info, NULL)); /* Called when the icon bar is clicked upon with Select */ show_error(event_register_toolbox_handler(-1, EOpenNewWindow, windows_new_browser, NULL)); /* Called to close the browser window */ show_error(event_register_toolbox_handler(-1, ECloseWindow, windows_shut_browser, NULL)); /* Called when the Open URL dialogue is to be shown */ show_error(event_register_toolbox_handler(-1, EOpenToBeShownMisc, openurl_to_be_shown, NULL)); /* Called when the Open URL dialogue is to be shown from a menu */ show_error(event_register_toolbox_handler(-1, EOpenToBeShownMenu, openurl_to_show_from_menu, NULL)); /* Called when the Find dialogue is to be shown */ show_error(event_register_toolbox_handler(-1, EFindToBeShown, find_to_be_shown, NULL)); /* Called when the Print Style dialogue is to be shown */ show_error(event_register_toolbox_handler(-1, EPSToBeShown, printstyle_to_be_shown, NULL)); /* Called when the Print dialogue is to be shown */ show_error(event_register_toolbox_handler(-1, PrintDbox_AboutToBeShown, print_to_be_shown, NULL)); /* Called when the Utils submenu is to be opened from the */ /* main menu in a browser window. */ show_error(event_register_toolbox_handler(-1, EUtilsToBeShown, menus_show_utils, NULL)); /* Called when the Export submenu is to be opened */ show_error(event_register_toolbox_handler(-1, EExportToBeShown, menus_show_export, NULL)); /* Called when the Choices submenu is to be opened */ /* from the icon bar menu */ show_error(event_register_toolbox_handler(-1, EChoicesToBeShown, menus_show_choices, NULL)); /* Called when the File submenu is to be opened from */ /* a browser window's main menu */ show_error(event_register_toolbox_handler(-1, EFileToBeShown, menus_show_file, NULL)); /* Called whenever the main menu is to be opened */ /* from a browser window, or closed. */ show_error(event_register_toolbox_handler(-1, EDocumentToBeShown, menus_show_main, NULL)); show_error(event_register_toolbox_handler(-1, EDocumentHidden, menus_hide_main, NULL)); /* Called whenever a menu item is selected */ show_error(event_register_toolbox_handler(-1, Menu_Selection, menus_item_selected, NULL)); /* General key press handler */ show_error(event_register_wimp_handler(-1, Wimp_EKeyPressed, handle_keys, NULL)); /* Menu handler for forms etc. */ show_error(event_register_wimp_handler(-1, Wimp_EMenuSelection, handle_menus, NULL)); /* LoseCaret event handler for grabbing the caret back, etc. */ show_error(event_register_wimp_handler(-1, Wimp_ELoseCaret, handle_lose_caret, NULL)); /* Pointer checking */ show_error(event_register_wimp_handler(-1, Wimp_EPointerEnteringWindow, browser_pointer_entering, NULL)); show_error(event_register_wimp_handler(-1, Wimp_EPointerLeavingWindow, browser_pointer_leaving, NULL)); /* Related to that, end of drag handling */ show_error(event_register_wimp_handler(-1, Wimp_EUserDrag, (WimpEventHandler *) handle_drags, NULL)); /* General Wimp message handling */ show_error(event_register_message_handler(Wimp_MModeChange, handle_messages, NULL)); show_error(event_register_message_handler(Wimp_MDataLoad, handle_messages, NULL)); show_error(event_register_message_handler(Wimp_MDataLoadAck, handle_messages, NULL)); show_error(event_register_message_handler(Wimp_MDataSave, handle_messages, NULL)); /* (DataSaveAck is registered in the Printing section below) */ show_error(event_register_message_handler(Wimp_MDataOpen, handle_messages, NULL)); show_error(event_register_message_handler(Wimp_MRAMFetch, handle_messages, NULL)); show_error(event_register_message_handler(Wimp_MRAMTransmit, handle_messages, NULL)); show_error(event_register_message_handler(Wimp_MMenusDeleted, handle_messages, NULL)); /* URI handler message handling */ show_error(event_register_message_handler(URI_MProcess, handle_messages, NULL)); show_error(event_register_message_handler(URI_MReturnResult, handle_messages, NULL)); /* AppControl message handling */ show_error(event_register_message_handler(Wimp_MAppControl, handle_messages, NULL)); /* Printing related message handlers */ show_error(event_register_message_handler(Browser_Message_PrintError, handle_messages, NULL)); show_error(event_register_message_handler(Browser_Message_PrintSave, handle_messages, NULL)); show_error(event_register_message_handler(Browser_Message_PrintTypeOdd, handle_messages, NULL)); show_error(event_register_message_handler(Wimp_MDataSaveAck, handle_messages, NULL)); /* For message bounces */ show_error(event_register_wimp_handler(-1, Wimp_EUserMessageAcknowledge, handle_ack, NULL)); /* Debug build event handlers */ #ifdef TRACE show_error(event_register_toolbox_handler(-1, ETraceTokenDumpByLine, trace_dump_tokens_by_line, NULL)); show_error(event_register_toolbox_handler(-1, ETraceTokenDumpByStream, trace_dump_tokens_by_stream, NULL)); #endif /* Event handlers for menu items that relate to toolbar buttons. */ /* This list needs to be kept in sync with the specific list in */ /* Windows.c, which allows buttons in specific windows to use */ /* the same event codes. */ show_error(event_register_toolbox_handler(-1, EButtonBarHome, handle_home, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarBack, handle_back, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarForward, handle_forwards, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarReload, handle_reload, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarStop, handle_stop, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarViewHotlist, handle_view_hotlist, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarAddToHotlist, handle_add_hotlist, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarViewResources, handle_view_resources, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarLoadImages, handle_load_images, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarViewSource, handle_view_source, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarGoTo, handle_go_to, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarGo, handle_go, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarCancel, handle_cancel, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarBistate, handle_bistate, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarTristate, handle_tristate, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarSaveSource, handle_save_src, NULL)); show_error(event_register_toolbox_handler(-1, EButtonBarPrint, handle_print, NULL)); /* Miscellaneous event handlers for keyboard control of some functions */ show_error(event_register_toolbox_handler(-1, EURLBarClearURL, handle_clear_url, NULL)); show_error(event_register_toolbox_handler(-1, EURLBarToggleHistory, handle_show_history_menu, NULL)); /* Event handlers for saving (most are registered when the dialogue opens) */ show_error(event_register_toolbox_handler(-1, ESaveFileToBeShown, savefile_to_be_shown, NULL)); show_error(event_register_toolbox_handler(-1, ESaveObjectToBeShown, saveobject_to_be_shown, NULL)); /* Wake up flex */ strncpy(program_name, lookup_token("_TaskName", 1, 0), sizeof(program_name)); program_name[sizeof(program_name) - 1] = 0; flex_init(program_name, NULL); flex_set_budge(1); /* Initialise the HTML library. This is to set up some initial */ /* data which can't be initialised in headers due to ROM build */ /* considerations. */ HtmlInit(); /* Similarly, initialise ImageLib */ ImageLib_Init(); /* Initialise FromROSLib routines */ wimpt_read(); /* Initialise Utils routines */ read_os_to_points(); #ifndef REMOTE_HOTLIST /* Initialise the hotlist */ show_error(hotlist_initialise()); hotlist_load(lookup_choice("HotlistPath:Browse:User.Hotlist",0,0)); #endif /* Load the history */ show_error(history_load(lookup_choice("HistoryPath:Browse:User.History",0,0))); /* Find the total number of animation frames for the status bar */ animation_frames = 0; { char v[10]; /* SpriteOp 40 is Read Info; it's just something that will give */ /* an error if the sprite doesn't exist. */ do { sprintf(v, "a%d\0", animation_frames ++); } while ( animation_frames < Limits_Misc_AnimFrames && !(_swix(OS_SpriteOp, _INR(0,2), 296, sprite_block, v)) ); /* animation_frames is incremented for every sprite looked at, */ /* including the last one, which must not be found. So need to */ /* subtract 1 now, to make it equal the number of frames. */ animation_frames --; } /* Similarly, find the number of bullets available */ bullets = 0; { char v[10]; do { sprintf(v,"b%d\0",bullets++); } while ( bullets < Limits_Misc_Bullets && !(_swix(OS_SpriteOp, _INR(0,2), 296, sprite_block, v)) ); bullets --; } /* Is the URI handler available? */ { int version; if (uri_version(0, &version)) uri_module_present = 0; else if (version >= 5) uri_module_present = 1; } /* Try and set the user agent string for HTTP fetches. */ show_error(utils_set_http_agent()); /* Find out window tool sizes */ ChkError(windows_initialise_tool_sizes()); } /*************************************************/ /* open_messages_file() */ /* */ /* Asks MessageTrans to open a Messages file. */ /* Looks through a system variable for the path */ /* to find the file in before going to a */ /* default - see the code comments for more */ /* information. */ /* */ /* Parameters: 0 to load the Choices file, or 1 */ /* to load the Controls file. */ /*************************************************/ static _kernel_oserror * open_messages_file(int which) { _kernel_oserror * e; MessagesFD * control; char * sysvar; char * defpath; char * path = NULL; int len, exists; /* Work out what to open. */ /* */ /* If you extend this switch statement, don't */ /* forget to extend the one later in the */ /* function too... */ switch (which) { case 0: { sysvar = "Browse$ChoicesFile"; defpath = ".Choices"; } break; case 1: { sysvar = "Browse$ControlsFile"; defpath = ".Controls"; } break; default: { #ifdef TRACE erb.errnum = Utils_Error_Custom_Fatal; sprintf(erb.errmess, "In open_choices_file, passed unrecognised parameter value '%d'", which); return &erb; #else return NULL; #endif } } /* Equivalent to getenv(), but the RISC OS implementation evaluates */ /* the system variable as an expression which we don't want; hence */ /* the direct use of the SWI. */ /* First, find the system variable length. Must use _kernel_swi */ /* here for various reasons. */ { _kernel_swi_regs r; r.r[0] = (int) sysvar; r.r[1] = (int) NULL; r.r[2] = -1; r.r[3] = 0; r.r[4] = 0; _kernel_swi(OS_ReadVarVal, &r, &r); len = -r.r[2]; /* This includes a terminator */ } if (!len) { /* Variable doesn't exist */ len = strlen(task_dir) + strlen(defpath) + 1; exists = 0; } else exists = 1; /* Allocate space */ path = malloc(len + 1); if (!path) { erb.errnum = Utils_Error_Custom_Fatal; strcpy(erb.errmess, "There is insufficient memory to start the browser."); show_error(&erb); } /* Read the variable or copy the data in */ if (exists) _swix(OS_ReadVarVal, _INR(0,4), sysvar, /* Variable name */ path, /* Buffer */ len, /* Size of buffer */ 0, /* Name pointer (0 for 1st call) */ 4); /* Variable type (4 = literal string) */ else { strcpy(path, task_dir); strcat(path, defpath); } /* Claim RMA for the control block and pathname */ e = _swix(OS_Module, _IN(0) | _IN(3) | _OUT(2), 6, sizeof(MessagesFD) + strlen(path) + 1, &control); if (e) { free(path); return e; } /* Update the relevant variable. No need for a default case */ /* as the first switch statement must have caught that one. */ switch (which) { case 0: chb = control; break; case 1: cob = control; break; } /* Register the block with MemCheck if required, and copy */ /* the pathname into it. */ #ifdef INCLUDE_MEMCHECK MemCheck_RegisterMiscBlock((void *) control, sizeof(MessagesFD) + strlen(path) + 1); #endif strcpy((char *) ((int) control + sizeof(MessagesFD)), path); /* Don't need the path now */ free(path); /* Open the file */ return _swix(MessageTrans_OpenFile, _INR(0,2), control, /* Pointer to control block */ (int) control + sizeof(MessagesFD), /* Filename */ 0); /* 0 to buffer data in RMA */ } /*************************************************/ /* close_messages_file() */ /* */ /* Closes a messges file and releases the RMA */ /* space claimed for it. */ /* */ /* Parameters: Pointer to the allocated chunk of */ /* RMA space holding the */ /* MessageTrans control block and */ /* Messages file pathname. */ /*************************************************/ static void close_messages_file(void * control) { /* If the file won't close for some reason, */ /* MessageTrans may still want to access it */ /* - so safest *not* to release the RMA */ /* holding the control block and filename. */ if ( _swix(MessageTrans_CloseFile, _IN(0), control) ) return; /* Release the claimed RMA space holding the */ /* control block and messages file name. */ _swix(OS_Module, _IN(0) | _IN(2), 7, control); } /*************************************************/ /* load_choices() */ /* */ /* Reads in the choices from the Messages file, */ /* filling in the global_choices structure, */ /* 'choices' (see Global.c and Global.h). */ /*************************************************/ static void load_choices(void) { /* Set the default window size and position */ choices.width = atoi(lookup_choice("DefWidth:1024",0,0)); choices.height = atoi(lookup_choice("DefHeight:1280",0,0)); choices.overridex = atoi(lookup_choice("OverrideX:0",0,0)); choices.overridey = atoi(lookup_choice("OverrideY:0",0,0)); /* If compiling for a multiuser environment, these will */ /* exist and need setting to null values. */ #ifndef SINGLE_USER choices.username[0] = 0; choices.password[0] = 0; #endif /* Set the various default colours */ choices.col_back = (unsigned int) strtoul(lookup_choice("BackColour:0xdddddd00",0,0),NULL,16); choices.col_text = (unsigned int) strtoul(lookup_choice("TextColour:0x00000000",0,0),NULL,16); choices.col_link = (unsigned int) strtoul(lookup_choice("LinkColour:0xff000000",0,0),NULL,16); choices.col_used = (unsigned int) strtoul(lookup_choice("UsedColour:0xbb008800",0,0),NULL,16); choices.col_foll = (unsigned int) strtoul(lookup_choice("FollColour:0x0000ff00",0,0),NULL,16); choices.col_sele = (unsigned int) strtoul(lookup_choice("SeleColour:0x00bb0000",0,0),NULL,16); /* Default fonts */ choices.fontsize = atoi(lookup_choice("FontSize:12",0,0)); if (choices.fontsize < 6) choices.fontsize = 6; if (choices.fontsize > 24) choices.fontsize = 24; choices.fontsize *= 16; if (!strcmp(lookup_choice("SystemFont:no",0,0),"yes")) choices.systemfont = 1; if (choices.systemfont) choices.fontsize = FM_Standard_Size; /* None user-configurable options from the Controls file */ fixed.poll_delay = atoi(lookup_control("AnimSpeed:4", 0,0)); fixed.minimum_convergence = atoi(lookup_control("MinConvergence:480",0,0)); fixed.show_dstat_for = atoi(lookup_control("ShowDStatFor:300", 0,0)); fixed.quantise = atoi(lookup_control("Quantise:5", 0,0)); fixed.dontgrey = atoi(lookup_control("DontGrey:0", 0,0)); /* Pointer active point offsets */ { int offset; offset = atoi(lookup_control("PtrLnkActvX:5", 0,0)); fixed.ptrlnkactvx = (char) offset; offset = atoi(lookup_control("PtrLnkActvY:1", 0,0)); fixed.ptrlnkactvy = (char) offset; offset = atoi(lookup_control("PtrMapActvX:7", 0,0)); fixed.ptrmapactvx = (char) offset; offset = atoi(lookup_control("PtrMapActvY:7", 0,0)); fixed.ptrmapactvy = (char) offset; offset = atoi(lookup_control("PtrUDActvX:5", 0,0)); fixed.ptrudactvx = (char) offset; offset = atoi(lookup_control("PtrUDActvY:8", 0,0)); fixed.ptrudactvy = (char) offset; offset = atoi(lookup_control("PtrLRActvX:8", 0,0)); fixed.ptrlractvx = (char) offset; offset = atoi(lookup_control("PtrLRActvY:5", 0,0)); fixed.ptrlractvy = (char) offset; offset = atoi(lookup_control("PtrUDLRActvX:8",0,0)); fixed.ptrudlractvx = (char) offset; offset = atoi(lookup_control("PtrUDLRActvY:5",0,0)); fixed.ptrudlractvy = (char) offset; offset = atoi(lookup_control("PtrNoRActvX:7", 0,0)); fixed.ptrnoractvx = (char) offset; offset = atoi(lookup_control("PtrNoRActvY:7", 0,0)); fixed.ptrnoractvy = (char) offset; offset = atoi(lookup_control("PtrToSActvX:0", 0,0)); fixed.ptrtosactvx = (char) offset; offset = atoi(lookup_control("PtrToSActvY:0", 0,0)); fixed.ptrtosactvy = (char) offset; offset = atoi(lookup_control("PtrScrActvX:8", 0,0)); fixed.ptrscractvx = (char) offset; offset = atoi(lookup_control("PtrScrActvY:8", 0,0)); fixed.ptrscractvy = (char) offset; } fixed.backoffat = atoi(lookup_control("BackOffAt:128",0,0)); if (!strcmp(lookup_choice("UseSmall:yes",0,0),"yes")) choices.use_small = 1; if (!strcmp(lookup_control("SwapBars:no" ,0,0),"yes")) fixed.swapbars = 1; if (!strcmp(lookup_control("DBoxAnims:no" ,0,0),"yes")) fixed.dboxanims = 1; if (!strcmp(lookup_control("AppendStatus:no" ,0,0),"yes")) fixed.appendstatus = 1; if (!strcmp(lookup_control("UseBrackets:yes" ,0,0),"yes")) fixed.usebrackets = 1; if (!strcmp(lookup_control("AppendURLs:no" ,0,0),"yes")) fixed.appendurls = 1; if (!strcmp(lookup_control("KeepCaret:no" ,0,0),"yes")) fixed.keepcaret = 1; if (!strcmp(lookup_control("ClaimHelp:no" ,0,0),"yes")) fixed.claimhelp = 1; if (!strcmp(lookup_control("StopWebServ:no" ,0,0),"yes")) fixed.stopwebserv = 1; if (!strcmp(lookup_control("BackWindow:no" ,0,0),"yes")) fixed.backwindow = 1; if (!strcmp(lookup_control("IgnoreAdjust:no" ,0,0),"yes")) fixed.ignoreadjust = 1; if (!strcmp(lookup_control("LockToLine:no" ,0,0),"yes")) fixed.locktoline = 1; /* The ColourProgress option in Messages is a little unusual; it holds */ /* 'no' or a Wimp colour number. Default to 11 (red, in the standard */ /* Wimp palette). */ if (!strcmp(lookup_control("ColourProgress:11",0,0),"no")) fixed.colour_progress = 255; else { fixed.colour_progress = atoi(lookup_control("ColourProgress:11",0,0)); if (fixed.colour_progress > 15) fixed.colour_progress = 11; } /* Maximum global history size in K, maximum */ /* view history size in entires, and maximum */ /* number of images to simultaneously fetch. */ /* Limit the number of simultaneous image fetches (I recommend */ /* a minimum of 2, rather than 1, as most efficient). */ choices.maximages = atoi(lookup_choice("MaxImages:5" ,0,0)); if (choices.maximages <= 0) choices.maximages = 1; /* History list choices */ choices.maxghistory = atoi(lookup_choice("GHistSize:8" ,0,0)); choices.maxvhistory = atoi(lookup_choice("VhistSize:50",0,0)); if (choices.maxghistory < 1) choices.maxghistory = 1; if (choices.maxvhistory < 4) choices.maxvhistory = 4; if (!strcmp(lookup_choice("SaveHistory:once",0,0),"always")) choices.save_history = 2; else if (!strcmp(lookup_choice("SaveHistory:once",0,0),"once")) choices.save_history = 1; /* Hotlist options */ if (!strcmp(lookup_choice("SaveHotlist:always",0,0),"always")) choices.save_hotlist = 2; else if (!strcmp(lookup_choice("SaveHotlist:always",0,0),"once")) choices.save_hotlist = 1; if (!strcmp(lookup_choice("AddHotlist:top",0,0),"bottom")) choices.add_hotlist = 1; if (!strcmp(lookup_choice("HotlistType:descriptions",0,0),"urls")) choices.hotlist_show = 1; choices.autoopen_delay = atoi(lookup_choice("AutoOpenDelay:100",0,0)); if (choices.autoopen_delay > 1000) choices.autoopen_delay = 1000; if (choices.autoopen_delay < 0) choices.autoopen_delay = 0; /* Page layout */ choices.leftmargin = atoi(lookup_control("LeftMargin:1600" ,0,0)); choices.rightmargin = atoi(lookup_control("RightMargin:6400" ,0,0)); choices.quotemargin = atoi(lookup_control("QuoteMargin:19200",0,0)); choices.leading = atoi(lookup_control("Leading:4" ,0,0)); choices.leftindent = atoi(lookup_control("LeftIndent:12800" ,0,0)); choices.minfrmheight = atoi(lookup_control("MinFrmHeight:48" ,0,0)); choices.minfrmwidth = atoi(lookup_control("MinFrmWidth:48" ,0,0)); /* Reformatter options */ if (!strcmp(lookup_control("RefoWait:no",0,0),"yes")) choices.refowait = 1; if (!strcmp(lookup_control("RefoHang:no",0,0),"yes")) choices.refohang = 1; choices.refotime = atoi(lookup_control("RefoTime:500",0,0)); if (choices.refotime < 25) choices.refotime = 25; if (choices.refotime > 2000) choices.refotime = 2000; /* Miscellaneous options */ if (!strcmp(lookup_control("BrickWall:no" ,0,0),"yes")) choices.brickwall = 1; if (!strcmp(lookup_control("ClearFirst:yes" ,0,0),"yes")) choices.clearfirst = 1; if (!strcmp(lookup_control("KeepHighlight:no",0,0),"yes")) choices.keephighlight = 1; if (!strcmp(lookup_choice("DelayImage:yes" ,0,0),"yes")) choices.delayimages = 1; if (!strcmp(lookup_choice("DisplayBgs:yes" ,0,0),"yes")) choices.displaybgs = 1; if (!strcmp(lookup_choice("UnderlineLks:yes" ,0,0),"yes")) choices.underlinelks = 1; if (!strcmp(lookup_choice("OverrideCols:no" ,0,0),"yes")) choices.overridecols = 1; if (!strcmp(lookup_choice("ShowURLs:no" ,0,0),"yes")) choices.show_urls = 1; if (!strcmp(lookup_choice("FixedPtr:yes" ,0,0),"yes")) choices.fixedptr = 1; if (!strcmp(lookup_choice("HighlightLks:no" ,0,0),"yes")) choices.highlightlks = 1; if (!strcmp(lookup_choice("KeyboardCtl:no" ,0,0),"yes")) choices.keyboardctl = 1; if (!strcmp(lookup_choice("UseProxy:no" ,0,0),"yes")) choices.use_proxy = 1; if (!strcmp(lookup_choice("FullScreen:no" ,0,0),"yes")) choices.full_screen = 1; if (!strcmp(lookup_choice("HScroll:no" ,0,0),"no")) choices.h_scroll = 0; else if (!strcmp(lookup_choice("HScroll:no" ,0,0),"yes")) choices.h_scroll = 2; else choices.h_scroll = 1; /* Auto */ if (!strcmp(lookup_choice("VScroll:yes",0,0),"no")) choices.v_scroll = 0; else if (!strcmp(lookup_choice("VScroll:yes",0,0),"yes")) choices.v_scroll = 2; else choices.v_scroll = 1; /* Auto */ /* Set toolbar options */ if (!strcmp(lookup_choice("DefURLbar:yes" ,0,0),"yes")) choices.url_bar = 1; if (!strcmp(lookup_choice("DefButtonBar:yes",0,0),"yes")) choices.button_bar = 1; if (!strcmp(lookup_choice("DefStatusBar:yes",0,0),"yes")) choices.status_bar = 1; if (!strcmp(lookup_choice("MoveGadgets" ,0,0),"0")) choices.move_gadgets = 0; if (!strcmp(lookup_choice("MoveGadgets" ,0,0),"1")) choices.move_gadgets = 1; if (!strcmp(lookup_choice("MoveGadgets:2",0,0),"2")) choices.move_gadgets = 2; if (!strcmp(lookup_control("AnimDrift:no", 0,0),"yes")) choices.anim_drift = 1; else if (!strcmp(lookup_control("AnimDrift:no", 0,0),"always")) choices.anim_drift = 2; if (!strcmp(lookup_choice("SolidResize:yes",0,0),"yes")) choices.solid_resize = 1; else if (!strcmp(lookup_choice("SolidResize:yes",0,0),"always")) choices.solid_resize = 2; #ifdef TRACE /* This list is somewhat out of date...! Still, it served */ /* its purpose in the early days of the above routines, */ /* and gives a useful overview for the Rout debug option */ /* during startup. */ if (tl & (1u<<5)) { Printf("\nWidth: %d\n" "Height: %d\n", choices.width, choices.height); Printf("\nBack colour: %p\n" "Text colour: %p\n" "Link colour: %p\n" "Used colour: %p\n", (void *) choices.col_back, (void *) choices.col_text, (void *) choices.col_link, (void *) choices.col_used); Printf("\nSystem font: %d\n" "Delay images: %d\n" "Display backgrounds: %d\n" "Fixed pointer: %d\n" "Underline links: %d\n" "Override colours: %d\n" "URL bar: %d\n" "Button bar: %d\n" "Status bar: %d\n" "Move gadgets: %d\n" "Use a proxy: %d\n\n", choices.systemfont, choices.delayimages, choices.displaybgs, choices.fixedptr, choices.underlinelks, choices.overridecols, choices.url_bar, choices.button_bar, choices.status_bar, choices.move_gadgets, choices.use_proxy); } #endif /* Wake up the font library */ fm_init(choices.systemfont, choices.fontsize); show_error(fm_define_default_typefaces()); fm_claim_basic_typefaces(choices.fontsize); /* Install any general handlers that might be needed as a */ /* result of the choices just loaded. */ show_error(event_register_wimp_handler(-1, Wimp_ELoseCaret, handle_lose_caret, NULL)); if (fixed.claimhelp) { /* Interactive help support for showing help in the status bar */ register_null_claimant(Wimp_ENull, protocols_ih_send_help_request, NULL); show_error(event_register_message_handler(Wimp_MHelpReply, handle_messages, NULL)); } } /*************************************************/ /* catch_errors() */ /* */ /* Catch OS errors and report them with the */ /* opportunity to continue or quit. */ /* */ /* Parameters: The signal number (ignored). */ /*************************************************/ static void catch_errors(int signum) { _kernel_oserror * e = _kernel_last_oserror(); if (e) erb = *e; print_abort_print(); if (e) show_error_cont(&erb); exit(EXIT_FAILURE); } /*************************************************/ /* termination() */ /* */ /* Called by registration through the atexit */ /* function. Shuts down core functions prior to */ /* the browser exitting (e.g. the Font Manager */ /* can get very tetchy about having font handles */ /* left claimed, so must release them). */ /*************************************************/ void termination(void) { #ifdef TRACE if (tl & (1u<<5)) Printf("termination() called\n"); #endif if (taskmodule_ds_registered) { /* Not interested in any errors, if it fails we can't really */ /* do anything about it at this stage. */ _swix(TaskModule_DeRegisterService, _INR(0,2), 0, 0, task_handle); } close_messages_file(cob); cob = NULL; close_messages_file(chb); chb = NULL; fm_shutdown(); } /*************************************************/ /* main() */ /* */ /* That which runs before all others. */ /*************************************************/ int main(int argc, char * argv[]) { WimpPollBlock b; int eventcode, time; int argp = 1, done_one = 0; #ifdef INCLUDE_HEAPGRAPH HeapGraph_RedirectAllocFns(NULL); #endif #ifdef INCLUDE_HIERPROF HierProf_ProfileAllFunctions(); #endif #ifdef INCLUDE_MEMCHECK MemCheck_Init(); MemCheck_InterceptSCLStringFunctions(); MemCheck_RegisterArgs(argc, argv); MemCheck_SetStoreMallocFunctions(1); MemCheck_SetReportFrees(1); MemCheck_SetAutoOutputBlocksInfo(0); #endif #ifndef TRACE /* Prevent postmortems; instead, report errors in a standard window. */ /* If backtraces are needed, use the debugger... */ /* */ /* If compiling a version for the debugger, ensure TRACE is defined */ /* or the code is commented out. The code below can mess up the */ /* debugger as default handlers are not beng used, and trying to */ /* install them tramples on the debugger's environment setup. */ { int loop, ret1, ret2, ret3; /* Loop over the undefined instruction, prefetch abort, data abort */ /* and address exception handlers, resetting them to the RISC OS */ /* defaults. The RISC OS default handlers raise a standard RISC OS */ /* error, having filled in the *ShowRegs register dump. (See PRM */ /* volume 1 page 315 onwards). */ for (loop = 1; loop <= 4; loop ++) { _swix(OS_ReadDefaultHandler, _IN(0) | _OUTR(1,3), loop, &ret1, &ret2, &ret3); _swix(OS_ChangeEnvironment, _INR(0,3), loop, ret1, ret2, ret3); } } #endif signal(SIGOSERROR, catch_errors); /* OS error */ signal(SIGILL, catch_errors); /* Illegal instruction */ signal(SIGSEGV, catch_errors); /* Segment violation */ signal(SIGSTAK, catch_errors); /* Stack overflow */ signal(SIGFPE, catch_errors); /* FPE error */ /* Before initialisation, find out where we ran from - this */ /* software can support different application names, so the */ /* existance of a specific system variable cannot be relied */ /* upon (with the exception of ROM builds). */ { int len; char * item; /* Work out what path to go through */ #ifdef ROM item = "Resources:$.Resources.Browse"; len = strlen(item); #else item = argv[0]; len = strlen(item) - strlen(".!RunImage"); #endif /* Allocate the space, bomb out if it fails */ task_dir = malloc(len + 1); if (!task_dir) { erb.errnum = Utils_Error_Custom_Fatal; strcpy(erb.errmess, "There is insufficient memory to start the browser."); show_error(&erb); } /* Copy the information and ensure it is terminated correctly */ strncpy(task_dir, item, len); task_dir[len] = 0; } #ifdef TRACE malloccount = flexcount = 0; /* Handle -d[ebug] CLI switch; see Global.c for more information. */ /* This must be the first command line argument. */ if (argc >= argp + 1) { if (!strcmp(argv[argp],"-debug") | !strcmp(argv[argp],"-d")) { if (strstr(argv[argp + 1], "MsgT")) tl |= (1u<<0); if (strstr(argv[argp + 1], "TBar")) tl |= (1u<<1); if (strstr(argv[argp + 1], "Null")) tl |= (1u<<2); if (strstr(argv[argp + 1], "Wind")) tl |= (1u<<3); if (strstr(argv[argp + 1], "Menu")) tl |= (1u<<4); if (strstr(argv[argp + 1], "Rout")) tl |= (1u<<5); if (strstr(argv[argp + 1], "Fetc")) tl |= (1u<<6); if (strstr(argv[argp + 1], "Memo")) tl |= (1u<<7); if (strstr(argv[argp + 1], "Refo")) tl |= (1u<<8); if (strstr(argv[argp + 1], "Redr")) tl |= (1u<<9); if (strstr(argv[argp + 1], "Font")) tl |= (1u<<10); if (strstr(argv[argp + 1], "BBox")) tl |= (1u<<11); if (strstr(argv[argp + 1], "LMem")) tl |= (1u<<12); if (strstr(argv[argp + 1], "CMal")) tl |= (1u<<13); if (strstr(argv[argp + 1], "CFle")) tl |= (1u<<14); if (strstr(argv[argp + 1], "Imag")) tl |= (1u<<15); if (strstr(argv[argp + 1], "Hist")) tl |= (1u<<16); if (strstr(argv[argp + 1], "Fram")) tl |= (1u<<17); if (strstr(argv[argp + 1], "Stre")) tl |= (1u<<18); if (strstr(argv[argp + 1], "Circ")) tl |= (1u<<19); if (strstr(argv[argp + 1], "Tabl")) tl |= (1u<<20); if (strstr(argv[argp + 1], "URIH")) tl |= (1u<<21); if (strstr(argv[argp + 1], "KeyC")) tl |= (1u<<22); if (strstr(argv[argp + 1], "RBox")) tl |= (1u<<23); if (strstr(argv[argp + 1], "JScr")) tl |= (1u<<24); if (strstr(argv[argp + 1], "Hotl")) tl |= (1u<<25); if (strstr(argv[argp + 1], "Save")) tl |= (1u<<26); if (strstr(argv[argp + 1], "Drag")) tl |= (1u<<27); if (strstr(argv[argp + 1], "MsgP")) tl |= (1u<<28); if (strstr(argv[argp + 1], "All")) tl = 0xffffffff; argp += 2; } } if (tl & (1u<<5)) Printf("\nmain: Initialising\n"); #endif /* Now do the bulk of application initialisation */ initialise_app(); #ifdef TRACE if (tl & (1u<<5)) Printf("main: Loading choices\n"); #endif load_choices(); #ifdef TRACE if (tl & (1u<<5)) Printf("main: Handling CLI arguments\n"); #endif /* If using keyboard control, watch the pointer for movement, */ /* turning it off if not moved for 5 seconds. */ if (choices.keyboardctl) mouse_watch_pointer_control(1); /* Keep advancing argp if the arguments are dealt with; */ /* only continue to check the arguments if we haven't */ /* pushed argp past argc, the total number of arguments. */ done_one = 1; while (argc >= argp && done_one) { done_one = 0; /* Handle -html (HTML files) */ if (argc >= argp + 1) { if (!strcmp(argv[argp], "-html")) { char url[Limits_URL]; #ifdef TRACE if (tl & (1u<<5)) Printf("main: Handling -html CLI argument\n"); #endif StrNCpy0(url, argv[argp + 1]); urlutils_pathname_to_url(url, sizeof(url)); windows_create_browser(url, NULL, NULL, NULL, 0); argp += 2, done_one = 1; } } /* Handle -uri (URI files) */ if (argc >= argp + 1) { if (!strcmp(argv[argp], "-uri")) { char url[Limits_URL]; #ifdef TRACE if (tl & (1u<<5)) Printf("main: Handling -uri CLI argument\n"); #endif urlutils_load_uri_file(url, sizeof(url), argv[argp + 1]); windows_create_browser(url, NULL, NULL, NULL, 0); argp += 2, done_one = 1; } } /* Handle -url (URL strings) */ if (argc >= argp + 1) { if (!strcmp(argv[argp],"-url") || !strcmp(argv[argp],"-u")) { #ifdef TRACE if (tl & (1u<<5)) Printf("main: Handling -url CLI argument\n"); #endif windows_create_browser(argv[argp+1], NULL, NULL, NULL, 0); argp += 2, done_one = 1; } } } #ifdef TRACE if (tl & (1u<<5)) Printf("main: Polling\n"); #endif atexit(termination); setjmp(env); while(!quit) { _swix(OS_ReadMonotonicTime, _OUT(0), &time); /* Use PollIdle, but want drag events to be as responsive as possible */ ChkError(event_poll_idle(&eventcode, &b, time + (drag_in_progress ? 0 : fixed.poll_delay), NULL)); } #ifdef TRACE if (tl & (1u<<5)) Printf("\nmain: Calling exit()\n\n"); if (tl & (1u<<13)) Printf("Near exit, malloccount: \0216%d\0217\n",malloccount); if (tl & (1u<<14)) Printf("Near exit, flexcount : %d\n",flexcount); #endif #ifndef REMOTE_HOTLIST /* Save the hotlist */ #ifdef TRACE if (tl & (1u<<5)) Printf("main: Calling hotlist_save\n"); #endif if (choices.save_hotlist) show_error_ret(hotlist_save(lookup_choice("HotlistPath:Browse:User.Hotlist",0,0))); #endif /* Save the global history */ #ifdef TRACE if (tl & (1u<<5)) Printf("main: Calling history_save\n"); #endif if (choices.save_history) history_save(lookup_choice("HistoryPath:Browse:User.History",0,0)); /* This will call the termination() function in passing */ exit(EXIT_SUCCESS); }