Main 70 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* 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                                 */
17 18 19
/*                                                 */
/* Purpose: To run.                                */
/*                                                 */
20
/* Author : A.D.Hodgkinson                         */
21 22
/*                                                 */
/* History: 12-Nov-96: Created.                    */
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
/***************************************************/

#include "setjmp.h"
#include "signal.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#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"
57
#include "TBEvents.h" /* Which includes loads of stuff... */
58 59 60
#include "Utils.h"

#include "Browser.h"
61 62
#include "ChoiceDefs.h"
#include "CtrlDefs.h"
63
#include "Encoding.h"
64 65
#include "FontManage.h"
#include "Handlers.h"
66
#include "History.h"
67
#include "ImgHistory.h"
68 69
#include "MiscDefs.h"
#include "Mouse.h"
70
#include "PlugIn.h"
71
#include "Protocols.h"
72
#include "RMA.h"
73
#include "Save.h"
74 75 76
#include "URLutils.h"
#include "Windows.h"

77 78 79 80 81 82 83 84 85
/* 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
86

87 88 89 90
#ifdef INCLUDE_HIERPROF
  #define HierProf_PROFILE
  #include "HierProf:HierProf.h"
#endif
91

92 93
#ifdef INCLUDE_MEMCHECK
  #include "MemCheck:MemCheck.h"
94 95 96 97 98 99 100 101
#endif

/* Finally, Main.h itself */

#include "Main.h"

/* Static function prototypes */

102 103 104 105 106 107
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);

108 109 110 111
#ifdef TRACE
  static void            self_test           (void);
#endif

112
static void              termination         (void);
113
static void              catch_errors        (int signum);
114 115 116 117 118 119 120 121 122 123 124

/* 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;

// /*************************************************/
// /* attach_event_handlers()                       */
// /*                                               */
// /* Called when an object is autocreated by the   */
125
// /* toolbox (see initialise_app). Used to get at  */
126
// /* the ObjectID of things without needing a      */
127
// /* specifically generated event to deliver it.   */
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
// /*************************************************/
//
// 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)
{
169
  int module_version;
170 171 172

  show_error(event_initialise(&idb));

173 174 175 176 177 178
  /* First handler registered is called last. This is a net to catch */
  /* miscellaneous events that might occur. Useful when there is a   */
  /* range of event codes defined for something, rather than just    */
  /* one code, for example.                                          */

  show_error(event_register_toolbox_handler(-1, -1, handle_miscellaneous_event, NULL));
179 180 181

  /* Register fundamental handlers and initialise as a Toolbox task */

182 183
  show_error(event_register_message_handler(Wimp_MQuit, handle_messages, NULL));
  show_error(event_register_toolbox_handler(-1, Toolbox_Error, report_toolbox_error, NULL));
184 185 186 187 188 189 190 191 192 193 194 195 196 197

  /* 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,
198
                                task_dir,
199 200 201 202 203 204
                                &meb,
                                &idb,
                                &wimp_version,
                                &task_handle,
                                (void *) &sprite_block));

205 206
  /* Open the Choices and Controls files */

207 208
  cob = NULL;
  chb = NULL;
209 210 211 212

  show_error(open_messages_file(0));
  show_error(open_messages_file(1));

213 214 215 216 217
  /* If either failed, bomb out. Can't raise a custom error as we have no */
  /* messages file to read it from...                                     */

  if (!cob || !chb) exit(EXIT_FAILURE);

218 219 220 221
  /* 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.     */

222 223 224 225
  {
    char combuf[96];

    sprintf(combuf, "If \"<Browse$IssueDesktopCommand>\" = \"yes\" Then WimpTask Desktop\r\n");
226

227 228
    _swix(OS_CLI, /* Don't want to hear about any errors */
          _IN(0),
229

230 231
          combuf);
  }
232

233 234 235
  /* 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.                                              */
236

237
  show_error(event_register_toolbox_handler(-1, Quit_Quit, handle_quit, NULL));
238 239 240

  /* Called before the application's Info box is shown */

241
  show_error(event_register_toolbox_handler(-1, ProgInfo_AboutToBeShown, handle_show_info, NULL));
242

243
  /* Opening and closing windows */
244

245 246
  show_error(event_register_toolbox_handler(-1, EOpenNewWindow, windows_new_browser,  NULL));
  show_error(event_register_toolbox_handler(-1, ECloseWindow,   windows_shut_browser, NULL));
247

248
  /* Opening the Open URL dialogue */
249

250 251
  show_error(event_register_toolbox_handler(-1, EOpenToBeShownMisc, openurl_to_be_shown,       NULL));
  show_error(event_register_toolbox_handler(-1, EOpenToBeShownMenu, openurl_to_show_from_menu, NULL));
252

253 254 255
  /* Opening and closing the Choices dialogue */

  show_error(event_register_toolbox_handler(-1, ECDToBeShown, choices_to_be_shown, NULL));
256
  show_error(event_register_toolbox_handler(-1, ECDHidden,    choices_hidden,      NULL));
257

258
  /* For the Find dialogue */
259

260
  show_error(event_register_toolbox_handler(-1, EFindToBeShown, find_to_be_shown, NULL));
261
  show_error(event_register_toolbox_handler(-1, EFindHidden,    find_hidden,      NULL));
262

263
  /* Print and Print Style dialogues */
264

265 266
  show_error(event_register_toolbox_handler(-1, EPSToBeShown,             printstyle_to_be_shown, NULL));
  show_error(event_register_toolbox_handler(-1, PrintDbox_AboutToBeShown, print_to_be_shown,      NULL));
267

268
  /* Called whenever a menu item is selected */
269

270
  show_error(event_register_toolbox_handler(-1, Menu_Selection, menus_item_selected, NULL));
271

272 273 274 275 276 277
  /* Support the Help menu */

  show_error(event_register_toolbox_handler(-1, EHelpFromHelpString, menus_help_from_help_string, NULL));
  show_error(event_register_toolbox_handler(-1, EHelpReleaseNotes,   menus_help_release_notes,    NULL));
  show_error(event_register_toolbox_handler(-1, EHelpAboutPage,      menus_help_about_page,       NULL));

278
  /* Before showing and after closing menus */
279

280
  show_error(event_register_toolbox_handler(-1, EMainToBeShown,     menus_show_main,     NULL));
281 282 283 284 285
  show_error(event_register_toolbox_handler(-1, EUtilsToBeShown,    menus_show_utils,    NULL));
  show_error(event_register_toolbox_handler(-1, EExportToBeShown,   menus_show_export,   NULL));
  show_error(event_register_toolbox_handler(-1, EChoicesToBeShown,  menus_show_choices,  NULL));
  show_error(event_register_toolbox_handler(-1, EFileToBeShown,     menus_show_file,     NULL));
  show_error(event_register_toolbox_handler(-1, ENavigateToBeShown, menus_show_navigate, NULL));
286 287
  show_error(event_register_toolbox_handler(-1, EDocumentToBeShown, menus_show_document, NULL));
  show_error(event_register_toolbox_handler(-1, EDocumentHidden,    menus_hide_document, NULL));
288
  show_error(event_register_toolbox_handler(-1, EEncodingToBeShown, encoding_show_menu,  NULL));
289
  show_error(event_register_toolbox_handler(-1, EHistoryToBeShown,  menus_show_history,  NULL));
290

291 292 293 294
  /* Called when the 'Cache' option is chosen from the main menu. */

  show_error(event_register_toolbox_handler(-1, EMainCache, menus_item_selected, NULL));

295 296
  /* Called when a selection is made from the Encoding menu. */

297
  show_error(event_register_toolbox_handler(-1, EEncodingSelect, encoding_select, NULL));
298 299 300 301

  /* Called when the user selects "From document" in the */
  /* Encoding menu.                                      */

302
  show_error(event_register_toolbox_handler(-1, EEncodingFromDocument, encoding_from_document_select, NULL));
303 304 305

  /* General key press handler */

306
  show_error(event_register_wimp_handler(-1, Wimp_EKeyPressed, handle_keys, NULL));
307

308
  /* Wimp handler for menu selections in forms etc. */
309

310
  show_error(event_register_wimp_handler(-1, Wimp_EMenuSelection, handle_menus, NULL));
311

312
  /* LoseCaret event handler for grabbing the caret back */
313

314
  show_error(event_register_wimp_handler(-1, Wimp_ELoseCaret, handle_lose_caret, NULL));
315 316 317 318 319 320

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

321 322 323 324
  /* Related to that, end of drag handling */

  show_error(event_register_wimp_handler(-1, Wimp_EUserDrag, (WimpEventHandler *) handle_drags, NULL));

325 326 327 328
  /* 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));
329
  show_error(event_register_message_handler(Wimp_MDataLoadAck,  handle_messages, NULL));
330
  show_error(event_register_message_handler(Wimp_MDataSave,     handle_messages, NULL));
331
  /* (DataSaveAck is registered in the Printing section below) */
332
  show_error(event_register_message_handler(Wimp_MDataOpen,     handle_messages, NULL));
333
  show_error(event_register_message_handler(Wimp_MRAMFetch,     handle_messages, NULL));
334
  show_error(event_register_message_handler(Wimp_MRAMTransmit,  handle_messages, NULL));
335 336
  show_error(event_register_message_handler(Wimp_MMenusDeleted, handle_messages, NULL));

337 338 339 340
  /* ANT protocols */

  show_error(event_register_message_handler(Message_ANTOpenURL, handle_messages, NULL));

341 342
  /* Plug-In protocol */

343 344 345 346 347 348 349 350 351
  show_error(event_register_message_handler(Message_PlugIn_Open,           handle_messages, NULL));
  show_error(event_register_message_handler(Message_PlugIn_Opening,        handle_messages, NULL));
  show_error(event_register_message_handler(Message_PlugIn_Close,          handle_messages, NULL));
  show_error(event_register_message_handler(Message_PlugIn_Closed,         handle_messages, NULL));
  show_error(event_register_message_handler(Message_PlugIn_URLAccess,      handle_messages, NULL));
  show_error(event_register_message_handler(Message_PlugIn_StreamNew,      handle_messages, NULL));
  show_error(event_register_message_handler(Message_PlugIn_ReshapeRequest, handle_messages, NULL));
  show_error(event_register_message_handler(Message_PlugIn_Status,         handle_messages, NULL));
  show_error(event_register_message_handler(Message_PlugIn_Busy,           handle_messages, NULL));
352

353 354
  /* URI handler message handling */

355
  show_error(event_register_message_handler(URI_MDying,        handle_messages, NULL));
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
  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));

371 372
  /* For message bounces */

373 374 375 376 377 378
  show_error(event_register_wimp_handler(-1, Wimp_EUserMessageAcknowledge, handle_ack, NULL));

  /* Debug build event handlers */

  #ifdef TRACE

379 380
    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));
381 382 383 384 385 386 387 388

  #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.                                         */

389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
  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));

406
  show_error(event_register_toolbox_handler(-1, EButtonBarSaveSource,    handle_save_source,    NULL));
407
  show_error(event_register_toolbox_handler(-1, EButtonBarPrint,         handle_print,          NULL));
408 409
  show_error(event_register_toolbox_handler(-1, EButtonBarSaveAsText,    handle_save_as_text,   NULL));
  show_error(event_register_toolbox_handler(-1, EButtonBarSaveAsDraw,    handle_save_as_draw,   NULL));
410

411 412
  /* Miscellaneous event handlers for keyboard control of some functions */

413 414
  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));
415

416
  /* Event handlers for saving (most are registered when the dialogue opens) */
417

418 419
  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));
420

421
  /* Event handlers for the Item Information dialogue */
422

423 424 425
  show_error(event_register_toolbox_handler(-1, EIIToBeShown,  iteminfo_to_be_shown, NULL));
  show_error(event_register_toolbox_handler(-1, EIIFollowLink, iteminfo_follow_link, NULL));
  show_error(event_register_toolbox_handler(-1, EIIExportItem, iteminfo_export_item, NULL));
426

427 428
  /* Wake up flex */

429 430 431 432 433
  strncpy(program_name,
          lookup_token("_TaskName", 1, 0),
          sizeof(program_name));

  program_name[sizeof(program_name) - 1] = 0;
434

435
  flex_init(program_name, NULL, 0x3000000);
436

437
  flex_set_budge(1);
438
  flex_set_deferred_compaction(1);
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457

  /* 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();

458 459 460 461 462 463 464 465
  #ifndef REMOTE_HOTLIST

    /* Initialise the hotlist */

    show_error(hotlist_initialise());

  #endif

466 467 468 469
  /* Initialise the encoding menu handler */

  show_error(encoding_init());

470 471 472 473
  /* Find the total number of animation frames for the status bar */

  animation_frames = 0;
  {
474
    char v[10];
475 476 477 478 479 480

    /* SpriteOp 40 is Read Info; it's just something that will give   */
    /* an error if the sprite doesn't exist.                          */

    do
    {
481
      sprintf(v, "a%d\0", animation_frames ++);
482
    }
483 484 485 486 487 488 489 490 491
    while (
            animation_frames < Limits_Misc_AnimFrames &&
            !(_swix(OS_SpriteOp,
                    _INR(0,2),

                    296,
                    sprite_block,
                    v))
          );
492 493 494 495 496 497 498 499 500 501 502 503

    /* 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;
  {
504
    char v[10];
505 506 507

    do
    {
508
      sprintf(v,"b%d\0",bullets++);
509
    }
510 511 512 513 514 515 516 517 518
    while (
            bullets < Limits_Misc_Bullets &&
            !(_swix(OS_SpriteOp,
                    _INR(0,2),

                    296,
                    sprite_block,
                    v))
          );
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533

    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;
  }

  /* Find out window tool sizes */

534
  show_error(windows_initialise_tool_sizes());
535 536 537
}

/*************************************************/
538
/* open_messages_file()                          */
539
/*                                               */
540
/* Asks MessageTrans to open a Messages file.    */
541
/* Looks through a system variable for the path  */
542 543 544 545 546 547
/* 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.        */
548 549
/*************************************************/

550
static _kernel_oserror * open_messages_file(int which)
551 552
{
  _kernel_oserror * e;
553
  MessagesFD      * control;
554
  char            * path = NULL;
555

556
  /* Work out what to open. */
557

558
  path = save_build_messages_path(which);
559

560
  if (!path) goto open_messages_file_no_memory;
561 562 563

  /* Claim RMA for the control block and pathname */

564
  e = rma_claim(NULL, sizeof(MessagesFD) + strlen(path) + 1, (void *) &control);
565

566 567 568 569 570 571
  if (e)
  {
    free(path);

    return e;
  }
572

573 574
  /* Update the relevant global. No need for a default case as */
  /* save_build_messages_path will have caught that.           */
575 576 577 578 579 580 581 582 583 584

  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.                                  */

585
  #ifdef INCLUDE_MEMCHECK
586
    MemCheck_RegisterMiscBlock((void *) control, sizeof(MessagesFD) + strlen(path) + 1);
587
  #endif
588

589
  strcpy((char *) ((int) control + sizeof(MessagesFD)), path);
590

591 592 593
  /* Don't need the path now */

  free(path);
594 595
  path = NULL;

596 597 598 599 600
  /* Open the file */

  return _swix(MessageTrans_OpenFile,
               _INR(0,2),

601 602
               control,                            /* Pointer to control block */
               (int) control + sizeof(MessagesFD), /* Filename                 */
603
               0);                                 /* Buffer in RMA            */
604 605 606 607 608

  /* Error condition exit */

open_messages_file_no_memory:

609
  if (control) rma_release(NULL, control);
610 611 612 613

  if (path) free(path);

  return NULL;
614 615 616
}

/*************************************************/
617 618 619 620
/* close_messages_file()                         */
/*                                               */
/* Closes a messges file and releases the RMA    */
/* space claimed for it.                         */
621
/*                                               */
622 623 624 625
/* Parameters: Pointer to the allocated chunk of */
/*             RMA space holding the             */
/*             MessageTrans control block and    */
/*             Messages file pathname.           */
626 627
/*************************************************/

628
static void close_messages_file(void * control)
629 630 631 632 633 634 635 636 637 638
{
  /* 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),

639
             control)
640 641 642 643 644 645
     )
     return;

  /* Release the claimed RMA space holding the */
  /* control block and messages file name.     */

646
  rma_release(NULL, control);
647 648
}

649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
/*************************************************/
/* colour_table_leaf_to_path()                   */
/*                                               */
/* Called by ImageLib. Print a full lookup table */
/* file pathname into path given the leafname.   */
/*                                               */
/* Parameters: Pointer to output buffer for full */
/*             pathname;                         */
/*                                               */
/*             Pointer to leaf name.             */
/*                                               */
/* Assumes:    Output buffer big enough :)       */
/*************************************************/

void colour_table_leaf_to_path(char *path, const char *leaf)
{
  sprintf(path, "%s.%s", task_dir, leaf);
}

668 669 670 671 672 673 674 675 676 677
/*************************************************/
/* 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)
{
678
  /* First, the user-configurable options from the Choices file. */
679

680 681
  /* Set the default home page */

682
  choices.home_page = malloc(strlen(lookup_choice("HomePage:http://www.acorn.co.uk/", 0, 0)) + 1);
683

684 685
  if (choices.home_page) strcpy(choices.home_page, tokens);
  else show_error(make_no_memory_error(32));
686

687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
  /* Get the visit history, image history and hotlist paths */
  /* by a similar mechanism.                                */

  /* Image history */

  choices.image_history_path = malloc(strlen(lookup_choice("ImageHistoryPath:Browse:User.Images", 0, 0)) + 1);

  if (choices.image_history_path) strcpy(choices.image_history_path, tokens);
  else show_error(make_no_memory_error(32));

  /* Visit history */

  choices.history_path = malloc(strlen(lookup_choice("HistoryPath:Browse:User.History", 0, 0)) + 1);

  if (choices.history_path) strcpy(choices.history_path, tokens);
  else show_error(make_no_memory_error(32));

  /* Hotlist */

  choices.hotlist_path = malloc(strlen(lookup_choice("HotlistPath:Browse:User.Hotlist",0,0)) + 1);

  if (choices.hotlist_path) strcpy(choices.hotlist_path, tokens);
  else show_error(make_no_memory_error(32));
710

711
  /* Set the various default colours */
712

713 714 715 716 717 718
  choices.background_colour = (unsigned int) strtoul(lookup_choice("BackColour:0xdddddd00", 0, 0), NULL, 16);
  choices.text_colour       = (unsigned int) strtoul(lookup_choice("TextColour:0x00000000", 0, 0), NULL, 16);
  choices.link_colour       = (unsigned int) strtoul(lookup_choice("LinkColour:0xff000000", 0, 0), NULL, 16);
  choices.used_colour       = (unsigned int) strtoul(lookup_choice("UsedColour:0xbb008800", 0, 0), NULL, 16);
  choices.followed_colour   = (unsigned int) strtoul(lookup_choice("FollColour:0x0000ff00", 0, 0), NULL, 16);
  choices.selected_colour   = (unsigned int) strtoul(lookup_choice("SeleColour:0x00bb0000", 0, 0), NULL, 16);
719

720
  /* Tables */
721

722
  if      (!strcmp(lookup_choice("SupportTables:yes", 0, 0),"yes"))    choices.support_tables = 1;
723

724 725 726 727 728 729 730 731 732
  if      (!strcmp(lookup_choice("TableOuter",        0, 0), "2d"))    choices.table_outer    = Choices_TableOuter_Always2D;
  else if (!strcmp(lookup_choice("TableOuter",        0, 0), "3d"))    choices.table_outer    = Choices_TableOuter_Always3D;
  else if (!strcmp(lookup_choice("TableOuter",        0, 0), "never")) choices.table_outer    = Choices_TableOuter_Never;
  else                                                                 choices.table_outer    = Choices_TableOuter_Auto;

  if      (!strcmp(lookup_choice("TableInner",        0, 0), "2d"))    choices.table_inner    = Choices_TableInner_Always2D;
  else if (!strcmp(lookup_choice("TableInner",        0, 0), "3d"))    choices.table_inner    = Choices_TableInner_Always3D;
  else if (!strcmp(lookup_choice("TableInner",        0, 0), "never")) choices.table_inner    = Choices_TableInner_Never;
  else                                                                 choices.table_inner    = Choices_TableInner_Auto;
733

734
  /* Font usage */
735

736
  choices.font_size = atoi(lookup_choice("FontSize:12", 0, 0));
737

738 739
  if (choices.font_size < 6  * 16) choices.font_size = 6  * 16;
  if (choices.font_size > 24 * 16) choices.font_size = 24 * 16;
740

741 742 743 744 745
  choices.tt_aspect = atoi(lookup_choice("TTAspect:90", 0, 0));

  if (choices.tt_aspect < 50)  choices.tt_aspect = 50;
  if (choices.tt_aspect > 150) choices.tt_aspect = 150;

746 747 748
  if (!strcmp(lookup_choice("SystemFont:no", 0, 0),"yes")) choices.system_font = 1;
  if (choices.system_font) choices.font_size = FM_Standard_Size;

749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
  /* Wake up the font library */

  fm_init(choices.system_font, choices.font_size);

  show_error(fm_define_default_typefaces());

  /* Look up the typeface definitions */

  {
    int  face;
    char tokenname[12];

    /* Arbitrary limit... Typeface1 to Typeface99 */

    for (face = 1; face < 100; face ++)
    {
      sprintf(tokenname, "Typeface%d", face);

      /* Look up the token, exit if it fails */

      lookup_choice(tokenname, 0, 0);
      if (*tokens == '!') break;

      /* Otherwise, define the typeface */

      show_error(fm_define_typeface(tokens));
    }
  }

778 779 780 781 782
  /* Claim basic typefaces based on the above */

  fm_claim_basic_typefaces(choices.font_size);

  /* Default document encoding */
783

784
  choices.encoding = atoi(lookup_choice("Encoding:4",  0, 0));
785

786
  /* Page display */
787

788 789 790 791
  if (!strcmp(lookup_choice("UnderlineLinks:yes", 0, 0), "yes")) choices.underline_links = 1;
  if (!strcmp(lookup_choice("UseSourceCols:yes",  0, 0), "yes")) choices.use_source_cols = 1;
  if (!strcmp(lookup_choice("ShowForeground:yes", 0, 0), "yes")) choices.show_foreground = 1;
  if (!strcmp(lookup_choice("ShowBackground:yes", 0, 0), "yes")) choices.show_background = 1;
792

793
  /* Page layout */
794

795 796 797 798 799
  choices.left_margin  = atoi(lookup_choice("LeftMargin:1600",   0, 0));
  choices.right_margin = atoi(lookup_choice("RightMargin:6400",  0, 0));
  choices.quote_margin = atoi(lookup_choice("QuoteMargin:19200", 0, 0));
  choices.leading      = atoi(lookup_choice("Leading:4",         0, 0));
  choices.left_indent  = atoi(lookup_choice("LeftIndent:12800",  0, 0));
800

801
  /* Fetch controls */
802

803 804
  /* Limit the number of simultaneous image fetches (I recommend */
  /* a minimum of 2, rather than 1, as most efficient).          */
805

806 807
  choices.maximages = atoi(lookup_choice("MaxImages:5", 0, 0));
  if (choices.maximages <= 0) choices.maximages = 1;
808

809 810 811
  if (!strcmp(lookup_choice("ClientPull:yes",    0, 0), "yes")) choices.client_pull    = 1;
  if (!strcmp(lookup_choice("SupportFrames:yes", 0, 0), "yes")) choices.support_frames = 1;
  if (!strcmp(lookup_choice("SupportObject:yes", 0, 0), "yes")) choices.support_object = 1;
812

813 814 815 816
  if      (!strcmp(lookup_choice("PlugInControl", 0, 0), "never"))  choices.plugin_control = Choices_PlugIns_Never;
  else if (!strcmp(lookup_choice("PlugInControl", 0, 0), "viewed")) choices.plugin_control = Choices_PlugIns_Viewed;
  else                                                              choices.plugin_control = Choices_PlugIns_ASAP;

817 818
  if (!strcmp(lookup_choice("SeeFetches:no", 0, 0), "yes")) choices.see_fetches = 1;

819
  /* Hotlist controls */
820

821 822 823
  if      (!strcmp(lookup_choice("SaveHotlist", 0, 0), "never"))  choices.save_hotlist = Choices_SaveHotlist_Never;
  else if (!strcmp(lookup_choice("SaveHotlist", 0, 0), "always")) choices.save_hotlist = Choices_SaveHotlist_Always;
  else                                                            choices.save_hotlist = Choices_SaveHotlist_Once;
824

825 826
  if (!strcmp(lookup_choice("AddHotlist", 0, 0), "bottom")) choices.add_hotlist  = Choices_AddHotlist_Bottom;
  else                                                      choices.add_hotlist  = Choices_AddHotlist_Top;
827

828 829
  if (!strcmp(lookup_choice("HotlistType", 0, 0), "urls"))  choices.hotlist_show = Choices_HotlistType_URLs;
  else                                                      choices.hotlist_show = Choices_HotlistType_Descriptions;
830

831 832 833
  choices.auto_open_delay = atoi(lookup_choice("AutoOpenDelay:100", 0, 0));
  if (choices.auto_open_delay > 1000) choices.auto_open_delay = 1000;
  if (choices.auto_open_delay < 0)    choices.auto_open_delay = 0;
834

835 836 837
  choices.auto_scroll_delay = atoi(lookup_choice("AutoScrollDelay:50", 0, 0));
  if (choices.auto_scroll_delay > 1000) choices.auto_scroll_delay = 1000;
  if (choices.auto_scroll_delay < 0)    choices.auto_scroll_delay = 0;
838

839 840 841
  choices.auto_scroll_margin = atoi(lookup_choice("AutoScrollMargin:48", 0, 0));
  if (choices.auto_scroll_margin > 256) choices.auto_scroll_margin = 256;
  if (choices.auto_scroll_margin < 0)   choices.auto_scroll_margin = 0;
842

843
  /* History limits */
844

845 846 847 848
  choices.max_size         = atoi(lookup_choice("MaxSize:16",             0, 0));
  choices.image_max_size   = atoi(lookup_choice("ImageMaxSize:0",         0, 0));
  choices.expiry_age       = atoi(lookup_choice("ExpiryAge:604800",       0, 0));
  choices.image_expiry_age = atoi(lookup_choice("ImageExpiryAge:1209600", 0, 0));
849

850 851
  choices.max_size         *= 1024; /* (Convert K to bytes)       */
  choices.image_max_size   *= 1024;
852

853
  if (choices.max_size   < 2048 && choices.max_size)   choices.max_size   = 2048; /* (NB, Note that there's no lower limit placed on image history details) */
854
  if (choices.expiry_age < 60   && choices.expiry_age) choices.expiry_age = 60;
855

856
  if (!strcmp(lookup_choice("ShowURLs:no", 0, 0), "yes")) choices.show_urls = 1;
857

858 859 860
  if      (!strcmp(lookup_choice("SaveHistory", 0, 0), "never"))  choices.save_history = Choices_SaveHistory_Never;
  else if (!strcmp(lookup_choice("SaveHistory", 0, 0), "always")) choices.save_history = Choices_SaveHistory_Always;
  else                                                            choices.save_history = Choices_SaveHistory_Once;
861

862 863 864 865
  if      (!strcmp(lookup_choice("SaveImageHistory", 0, 0), "never"))  choices.save_image_history = Choices_SaveImageHistory_Never;
  else if (!strcmp(lookup_choice("SaveImageHistory", 0, 0), "always")) choices.save_image_history = Choices_SaveImageHistory_Always;
  else                                                                 choices.save_image_history = Choices_SaveImageHistory_Once;

866
  /* Toolbar controls */
867

868 869 870
  if (!strcmp(lookup_choice("URLbar:yes",    0, 0), "yes")) choices.url_bar    = 1;
  if (!strcmp(lookup_choice("ButtonBar:yes", 0, 0), "yes")) choices.button_bar = 1;
  if (!strcmp(lookup_choice("StatusBar:yes", 0, 0), "yes")) choices.status_bar = 1;
871

872 873 874
  if      (!strcmp(lookup_choice("MoveGadgets", 0, 0), "never"))  choices.move_gadgets = Choices_MoveGadgets_Never;
  else if (!strcmp(lookup_choice("MoveGadgets", 0, 0), "at end")) choices.move_gadgets = Choices_MoveGadgets_AtEnd;
  else                                                            choices.move_gadgets = Choices_MoveGadgets_During;
875

876
  /* Window controls */
877

878 879
  choices.width      = atoi(lookup_choice("Width:1024",  0, 0));
  choices.height     = atoi(lookup_choice("Height:1280", 0, 0));
880 881 882 883 884 885
  choices.override_x = atoi(lookup_choice("OverrideX:0",    0, 0));
  choices.override_y = atoi(lookup_choice("OverrideY:0",    0, 0));

  if      (!strcmp(lookup_choice("SolidResize", 0, 0), "no"))     choices.solid_resize = Choices_SolidResize_No;
  else if (!strcmp(lookup_choice("SolidResize", 0, 0), "always")) choices.solid_resize = Choices_SolidResize_Always;
  else                                                            choices.solid_resize = Choices_SolidResize_Yes;
886

887
  if (!strcmp(lookup_choice("FullScreen:no", 0, 0), "yes")) choices.full_screen = 1;
888

889 890 891
  if      (!strcmp(lookup_choice("HScroll", 0, 0), "no"))  choices.h_scroll = Choices_HScroll_No;
  else if (!strcmp(lookup_choice("HScroll", 0, 0), "yes")) choices.h_scroll = Choices_HScroll_Yes;
  else                                                     choices.h_scroll = Choices_HScroll_Auto;
892

893 894 895
  if      (!strcmp(lookup_choice("VScroll", 0, 0), "no"))  choices.v_scroll = Choices_HScroll_No;
  else if (!strcmp(lookup_choice("VScroll", 0, 0), "yes")) choices.v_scroll = Choices_HScroll_Yes;
  else                                                     choices.v_scroll = Choices_HScroll_Auto;
896

897
  /* Reformatter controls */
898

899 900
  if (!strcmp(lookup_choice("RefoWait:no", 0, 0), "yes")) choices.refo_wait = 1;
  if (!strcmp(lookup_choice("RefoHang:no", 0, 0), "yes")) choices.refo_hang = 1;
901

902 903 904
  choices.refo_time = atoi(lookup_choice("RefoTime:500", 0, 0));
  if (choices.refo_time < 25)   choices.refo_time = 25;
  if (choices.refo_time > 2000) choices.refo_time = 2000;
905

906
  /* Input device controls */
907

908 909 910
  if (!strcmp(lookup_choice("FixedPtr:yes",    0, 0), "yes")) choices.fixed_pointer     = 1;
  if (!strcmp(lookup_choice("HighlightLks:no", 0, 0), "yes")) choices.highlight_links = 1;
  if (!strcmp(lookup_choice("KeyboardCtl:no",  0, 0), "yes")) choices.keyboard_ctrl  = 1;
911

912
  /* Multiuser environments and proxying */
913

914 915
  if (!strcmp(lookup_choice("UseProxy:no",   0, 0), "yes")) choices.use_proxy   = 1;
  if (!strcmp(lookup_choice("StartProxy:no", 0, 0), "yes")) choices.start_proxy = 1;
David Brown's avatar
David Brown committed
916 917 918 919 920 921 922 923 924 925 926 927

  lookup_choice("ProxyAddress:http://127.0.0.1/", 0, 0);
  choices.proxy_address = malloc(strlen(tokens) + 1);
  if (choices.proxy_address)
  {
    strcpy(choices.proxy_address, tokens);
  }
  else
  {
    show_error(make_no_memory_error(103));
  }

928
  if (!strcmp(lookup_choice("Clone:yes",   0, 0), "yes")) choices.clone     = 1;
929

930
  #ifndef SINGLE_USER
931

932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950
    /* If compiling for a multiuser environment, set up */
    /* a post_in and a post_out path.                   */

    choices.post_in = malloc(strlen(lookup_choice("PostIn:<none>", 0, 0)) + 1);

    if (choices.post_in) strcpy(choices.post_in, tokens);
    else show_error(make_no_memory_error(32));

    choices.post_out = malloc(strlen(lookup_choice("PostOut:<none>", 0, 0)) + 1);

    if (choices.post_out) strcpy(choices.post_out, tokens);
    else show_error(make_no_memory_error(32));

    /* Set also the server timeout */

    choices.log_in_timeout = atoi(lookup_choice("LITimeout:30", 0, 0));

    if (choices.log_in_timeout < 20)  choices.log_in_timeout = 20;
    if (choices.log_in_timeout > 120) choices.log_in_timeout = 120;
951 952

  #endif
953

954
  /* Non user-configurable options from the Controls file */
955

956
  /* Animation controls */
957

958
  controls.anim_delay = atoi(lookup_control("AnimSpeed:4", 0, 0));
959

960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
  if (!strcmp(lookup_control("AnimDrift:no", 0, 0), "yes")) controls.anim_drift = 1;
  if (!strcmp(lookup_control("DBoxAnims:no", 0, 0), "yes")) controls.dbox_anims = 1;

  /* Main window and general toolbar controls */

  controls.minimum_convergence = atoi(lookup_control("MinConvergence:480", 0, 0));

  if      (!strcmp(lookup_control("DontGrey", 0, 0), "none"))    controls.dont_grey = Controls_DontGrey_GreyNone;
  else if (!strcmp(lookup_control("DontGrey", 0, 0), "history")) controls.dont_grey = Controls_DontGrey_GreyHistoryOnly;
  else                                                           controls.dont_grey = Controls_DontGrey_GreyAll;

  if (!strcmp(lookup_control("SwapBars:no",   0, 0), "yes")) controls.swap_bars   = 1;
  if (!strcmp(lookup_control("BackWindow:no", 0, 0), "yes")) controls.back_window = 1;
  if (!strcmp(lookup_control("UseSmall:yes",  0, 0), "yes")) controls.use_small   = 1;

  /* Main and dialler status controls */

  if (!strcmp(lookup_control("ClaimHelp:no", 0, 0), "yes")) controls.claim_help = 1;

  controls.show_help_for         = atoi(lookup_control("ShowHelpFor:600",   0, 0));
  controls.show_dstat_for        = atoi(lookup_control("ShowDStatFor:300",  0, 0));
  controls.show_links_for        = atoi(lookup_control("ShowLinksFor:200",  0, 0));
  controls.show_misc_for         = atoi(lookup_control("ShowMiscFor:50",    0, 0));
  controls.quantise              = atoi(lookup_control("Quantise:5",        0, 0));
  controls.progress_update_delay = atoi(lookup_control("ProgressDelay:50",  0, 0));

  /* Progress indicator controls */

  if (!strcmp(lookup_control("AppendStatus:no", 0, 0), "yes")) controls.append_status = 1;
  if (!strcmp(lookup_control("UseBrackets:yes", 0, 0), "yes")) controls.use_brackets  = 1;

  /* The ColourProgress option in Controls is a little unusual; it holds */
  /* 'no' (NotAColour, see CtrlDefs.h) or a Wimp colour number. Default  */
  /* to 11 (red, in the standard Wimp palette).                          */

  if (!strcmp(lookup_control("ColourProgress:11", 0, 0), "no")) controls.colour_progress = Controls_ColourProgress_NotAColour;
  else
  {
    controls.colour_progress = atoi(lookup_control("ColourProgress:11", 0, 0));
    if (controls.colour_progress > 15) controls.colour_progress = 11;
  }

  /* Frame controls */

  controls.minimum_frame_height = atoi(lookup_control("MinFrmHeight:48", 0, 0));
  controls.minimum_frame_width  = atoi(lookup_control("MinFrmWidth:48",  0, 0));

  if (!strcmp(lookup_control("KeepHighlight:no", 0, 0), "yes")) controls.keep_highlight = 1;

  /* Input device controls */

  if (!strcmp(lookup_control("KeepCaret:no",    0, 0), "yes")) controls.keep_caret    = 1;
  if (!strcmp(lookup_control("ClearFirst:yes",  0, 0), "yes")) controls.clear_first   = 1;
  if (!strcmp(lookup_control("LockToLine:no",   0, 0), "yes")) controls.lock_to_line  = 1;
  if (!strcmp(lookup_control("IgnoreAdjust:no", 0, 0), "yes")) controls.ignore_adjust = 1;

  /* Remote hotlist support */

  if (!strcmp(lookup_control("AppendURLs:no", 0, 0), "yes")) controls.append_urls = 1;

  /* Fetch controls */

1022 1023 1024
  if (!strcmp(lookup_control("BrickWall:no",    0, 0), "yes")) controls.brick_wall  = 1;
  if (!strcmp(lookup_control("StopWebProxy:no", 0, 0), "yes")) controls.stop_proxy  = 1;
  if (!strcmp(lookup_control("RefoSingle:no",   0, 0), "yes")) controls.refo_single = 1;
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049

  controls.back_off_at = atoi(lookup_control("BackOffAt:128", 0, 0));

  /* Mouse pointer active point offsets */

  {
    int offset;

    offset = atoi(lookup_control("PtrLnkActvX:5", 0,0)); controls.ptrlnkactvx  = (char) offset;
    offset = atoi(lookup_control("PtrLnkActvY:1", 0,0)); controls.ptrlnkactvy  = (char) offset;
    offset = atoi(lookup_control("PtrMapActvX:7", 0,0)); controls.ptrmapactvx  = (char) offset;
    offset = atoi(lookup_control("PtrMapActvY:7", 0,0)); controls.ptrmapactvy  = (char) offset;
    offset = atoi(lookup_control("PtrUDActvX:5",  0,0)); controls.ptrudactvx   = (char) offset;
    offset = atoi(lookup_control("PtrUDActvY:8",  0,0)); controls.ptrudactvy   = (char) offset;
    offset = atoi(lookup_control("PtrLRActvX:8",  0,0)); controls.ptrlractvx   = (char) offset;
    offset = atoi(lookup_control("PtrLRActvY:5",  0,0)); controls.ptrlractvy   = (char) offset;
    offset = atoi(lookup_control("PtrUDLRActvX:8",0,0)); controls.ptrudlractvx = (char) offset;
    offset = atoi(lookup_control("PtrUDLRActvY:5",0,0)); controls.ptrudlractvy = (char) offset;
    offset = atoi(lookup_control("PtrNoRActvX:7", 0,0)); controls.ptrnoractvx  = (char) offset;
    offset = atoi(lookup_control("PtrNoRActvY:7", 0,0)); controls.ptrnoractvy  = (char) offset;
    offset = atoi(lookup_control("PtrToSActvX:0", 0,0)); controls.ptrtosactvx  = (char) offset;
    offset = atoi(lookup_control("PtrToSActvY:0", 0,0)); controls.ptrtosactvy  = (char) offset;
    offset = atoi(lookup_control("PtrScrActvX:8", 0,0)); controls.ptrscractvx  = (char) offset;
    offset = atoi(lookup_control("PtrScrActvY:8", 0,0)); controls.ptrscractvy  = (char) offset;
  }
1050 1051

  #ifdef TRACE
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
    self_test();
  #endif

  /* 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 (controls.claim_help)
  {
    /* 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));
  }
}

#ifdef TRACE

  /*************************************************/
  /* self_test()                                   */
  /*                                               */
  /* Run through a few standard startup trace      */
  /* build output routines.                        */
  /*************************************************/

  static void self_test(void)
  {
1080 1081 1082 1083 1084 1085 1086 1087
    /* 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"
1088
               "Height: %d\n",
1089
                choices.width,
1090
                choices.height);
1091 1092 1093 1094 1095

      Printf("\nBack colour: %p\n"
               "Text colour: %p\n"
               "Link colour: %p\n"
               "Used colour: %p\n",
1096 1097 1098 1099
                (void *) choices.background_colour,
                (void *) choices.text_colour,
                (void *) choices.link_colour,
                (void *) choices.used_colour);
1100 1101

      Printf("\nSystem font: %d\n"
1102 1103
               "Show foreground images: %d\n"
               "Show background images: %d\n"
1104 1105
               "Fixed pointer: %d\n"
               "Underline links: %d\n"
1106
               "Use document colours: %d\n"
1107 1108 1109 1110 1111
               "URL bar: %d\n"
               "Button bar: %d\n"
               "Status bar: %d\n"
               "Move gadgets: %d\n"
               "Use a proxy: %d\n\n",
1112 1113 1114 1115 1116 1117
                choices.system_font,
                choices.show_foreground,
                choices.show_background,
                choices.fixed_pointer,
                choices.underline_links,
                choices.use_source_cols,
1118 1119 1120 1121 1122 1123 1124
                choices.url_bar,
                choices.button_bar,
                choices.status_bar,
                choices.move_gadgets,
                choices.use_proxy);
    }

1125
    /* Test URL to leafname translation */
1126

1127 1128
    if (tl & (1<<26))
    {
1129 1130
      char   leafname[1024];
      char * canonicalised = NULL;
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363

      #define TestLeaf(str) {urlutils_leafname_from_url((str), leafname, sizeof(leafname)); Printf("%s ", leafname);}

      Printf("Checking URL to Leafname translation\n");
      Printf("====================================\n\n");

      /* First, with protocols */

      TestLeaf("http://www.acorn.com/");
      TestLeaf("http://www.acorn.com");
      TestLeaf("http:/www.acorn.com/");
      TestLeaf("http:www.acorn.com/");
      TestLeaf("http:www.acorn.com");
      TestLeaf("http://www.acorn.com:80/");
      TestLeaf("http://www.acorn.com:80");
      TestLeaf("http:/www.acorn.com:80/");
      TestLeaf("http:www.acorn.com:80/");
      TestLeaf("http:www.acorn.com:80");

      Printf("\n");

      TestLeaf("http://www.acorn.com/thing1.html");
      TestLeaf("http:/www.acorn.com/thing2.html");
      TestLeaf("http:www.acorn.com/thing3.html");
      TestLeaf("http://www.acorn.com:80/thing4.html");
      TestLeaf("http:/www.acorn.com:80/thing5.html");
      TestLeaf("http:www.acorn.com:80/thing6.html");

      Printf("\n");

      TestLeaf("http://www.acorn.com/dir/dthing1.html");
      TestLeaf("http:/www.acorn.com/dir/dthing2.html");
      TestLeaf("http:www.acorn.com/dir/dthing3.html");
      TestLeaf("http://www.acorn.com:80/dir/dthing4.html");
      TestLeaf("http:/www.acorn.com:80/dir/dthing5.html");
      TestLeaf("http:www.acorn.com:80/dir/dthing6.html");

      Printf("\n");

      TestLeaf("http://www.acorn.com/dir/dthing1.tz.html");
      TestLeaf("http:/www.acorn.com/dir/dthing2.tz.html");
      TestLeaf("http:www.acorn.com/dir/dthing3.tz.html");
      TestLeaf("http://www.acorn.com:80/dir/dthing4.tz.html");
      TestLeaf("http:/www.acorn.com:80/dir/dthing5.tz.html");
      TestLeaf("http:www.acorn.com:80/dir/dthing6.tz.html");

      Printf("\n");

      TestLeaf("http://www.acorn.com/dir1/");
      TestLeaf("http:/www.acorn.com/dir2/");
      TestLeaf("http:www.acorn.com/dir3/");
      TestLeaf("http://www.acorn.com:80/dir4/");
      TestLeaf("http:/www.acorn.com:80/dir5/");
      TestLeaf("http:www.acorn.com:80/dir6/");

      Printf("\n");

      TestLeaf("http://www.acorn.com/dirs1");
      TestLeaf("http:/www.acorn.com/dirs2");
      TestLeaf("http:www.acorn.com/dirs3");
      TestLeaf("http://www.acorn.com:80/dirs4");
      TestLeaf("http:/www.acorn.com:80/dirs5");
      TestLeaf("http:www.acorn.com:80/dirs6");

      Printf("\n");

      TestLeaf("http://www.acorn.com/dirs1#anc1");
      TestLeaf("http:/www.acorn.com/dirs2#anc2");
      TestLeaf("http:www.acorn.com/dirs3#anc3");
      TestLeaf("http://www.acorn.com:80/dirs4#anc4");
      TestLeaf("http:/www.acorn.com:80/dirs5#anc5");
      TestLeaf("http:www.acorn.com:80/dirs6#anc6");

      Printf("\n");

      TestLeaf("http://www.acorn.com/d/irs1#danc1");
      TestLeaf("http:/www.acorn.com/d/irs2#danc2");
      TestLeaf("http:www.acorn.com/d/irs3#danc3");
      TestLeaf("http://www.acorn.com:80/d/irs4#danc4");
      TestLeaf("http:/www.acorn.com:80/d/irs5#danc5");
      TestLeaf("http:www.acorn.com:80/d/irs6#danc6");

      Printf("\n\n");

      /* Now without protocols */

      TestLeaf("//www.acorn.com/");
      TestLeaf("//www.acorn.com");
      TestLeaf("/www.acorn.com/");
      TestLeaf("www.acorn.com/");
      TestLeaf("www.acorn.com");
      TestLeaf("//www.acorn.com:80/");
      TestLeaf("//www.acorn.com:80");
      TestLeaf("/www.acorn.com:80/");
      TestLeaf("www.acorn.com:80/");
      TestLeaf("www.acorn.com:80");

      Printf("\n");

      TestLeaf("//www.acorn.com/thing1.html");
      TestLeaf("/www.acorn.com/thing2.html");
      TestLeaf("www.acorn.com/thing3.html");
      TestLeaf("//www.acorn.com:80/thing4.html");
      TestLeaf("/www.acorn.com:80/thing5.html");
      TestLeaf("www.acorn.com:80/thing6.html");

      Printf("\n");

      TestLeaf("//www.acorn.com/dir/dthing1.html");
      TestLeaf("/www.acorn.com/dir/dthing2.html");
      TestLeaf("www.acorn.com/dir/dthing3.html");
      TestLeaf("//www.acorn.com:80/dir/dthing4.html");
      TestLeaf("/www.acorn.com:80/dir/dthing5.html");
      TestLeaf("www.acorn.com:80/dir/dthing6.html");

      Printf("\n");

      TestLeaf("//www.acorn.com/dir/dthing1.tz.html");
      TestLeaf("/www.acorn.com/dir/dthing2.tz.html");
      TestLeaf("www.acorn.com/dir/dthing3.tz.html");
      TestLeaf("//www.acorn.com:80/dir/dthing4.tz.html");
      TestLeaf("/www.acorn.com:80/dir/dthing5.tz.html");
      TestLeaf("www.acorn.com:80/dir/dthing6.tz.html");

      Printf("\n");

      TestLeaf("//www.acorn.com/dir1/");
      TestLeaf("/www.acorn.com/dir2/");
      TestLeaf("www.acorn.com/dir3/");
      TestLeaf("//www.acorn.com:80/dir4/");
      TestLeaf("/www.acorn.com:80/dir5/");
      TestLeaf("www.acorn.com:80/dir6/");

      Printf("\n");

      TestLeaf("//www.acorn.com/dirs1");
      TestLeaf("/www.acorn.com/dirs2");
      TestLeaf("www.acorn.com/dirs3");
      TestLeaf("//www.acorn.com:80/dirs4");
      TestLeaf("/www.acorn.com:80/dirs5");
      TestLeaf("www.acorn.com:80/dirs6");

      Printf("\n");

      TestLeaf("//www.acorn.com/dirs1#anc1");
      TestLeaf("/www.acorn.com/dirs2#anc2");
      TestLeaf("www.acorn.com/dirs3#anc3");
      TestLeaf("//www.acorn.com:80/dirs4#anc4");
      TestLeaf("/www.acorn.com:80/dirs5#anc5");
      TestLeaf("www.acorn.com:80/dirs6#anc6");

      Printf("\n");

      TestLeaf("//www.acorn.com/d/irs1#danc1");
      TestLeaf("/www.acorn.com/d/irs2#danc2");
      TestLeaf("www.acorn.com/d/irs3#danc3");
      TestLeaf("//www.acorn.com:80/d/irs4#danc4");
      TestLeaf("/www.acorn.com:80/d/irs5#danc5");
      TestLeaf("www.acorn.com:80/d/irs6#danc6");

      Printf("\n\n");

      /* Minimal URLs */

      TestLeaf("www");
      TestLeaf("www/dirs");
      TestLeaf("www:80/dirs");
      TestLeaf("http:www");
      TestLeaf("http:www/dirs");
      TestLeaf("http:www:80/dirs");
      TestLeaf("http:/www");
      TestLeaf("http:/www/dirs");
      TestLeaf("http:/www:80/dirs");

      Printf("\n");

      TestLeaf("www/");
      TestLeaf("www/dirs/");
      TestLeaf("www:80/dirs/");
      TestLeaf("http:www/");
      TestLeaf("http:www/dirs/");
      TestLeaf("http:www:80/dirs/");
      TestLeaf("http:/www/");
      TestLeaf("http:/www/dirs/");
      TestLeaf("http:/www:80/dirs/");

      Printf("\n");

      TestLeaf("http:///notahost");
      TestLeaf("http:///notahost/");
      TestLeaf("http:///notahost2.html");
      TestLeaf("http:///notahost2.dir/");
      TestLeaf("http:///notahost3/find");

      Printf("\n\n");

      /* Mixed and broken anchor specifications */

      TestLeaf("http://www.acorn.com/#d/irs1#danc1");
      TestLeaf("http:/www.acorn.com/#d/irs2#danc2");
      TestLeaf("http:www.acorn.com/#d/irs3#danc3");
      TestLeaf("http://www.acorn.com:80/#d/irs4#danc4");
      TestLeaf("http:/www.acorn.com:80/#d/irs5#danc5");
      TestLeaf("http:www.acorn.com:80/#d/irs6#danc6");

      Printf("\n");

      TestLeaf("http://www.acorn.com/#canc1");
      TestLeaf("http:/www.acorn.com/#canc2");
      TestLeaf("http:www.acorn.com/#canc3");
      TestLeaf("http://www.acorn.com:80/#canc4");
      TestLeaf("http:/www.acorn.com:80/#canc5");
      TestLeaf("http:www.acorn.com:80/#canc6");

      Printf("\n");

      TestLeaf("http://www.acorn.com/#");
      TestLeaf("http:/www.acorn.com/#");
      TestLeaf("http:www.acorn.com/#");
      TestLeaf("http://www.acorn.com:80/#");
      TestLeaf("http:/www.acorn.com:80/#");
      TestLeaf("http:www.acorn.com:80/#");

      Printf("\n");

      TestLeaf("http://www.acorn.com/pre1#");
      TestLeaf("http:/www.acorn.com/pre2#");
      TestLeaf("http:www.acorn.com/pre3#");
      TestLeaf("http://www.acorn.com:80/pre4#");
      TestLeaf("http:/www.acorn.com:80/pre5#");
      TestLeaf("http:www.acorn.com:80/pre6#");

      Printf("\n\n");
1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
      Printf("Checking pathname canonicalisation\n");
      Printf("==================================\n\n");

      #define TestCanonicalise(str) {                                                    \
                                      strcpy(leafname, (str));                           \
                                      Printf("In : '%s'\n",leafname);                    \
                                                                                         \
                                      utils_canonicalise_path(leafname, &canonicalised); \
                                                                                         \
                                      if (canonicalised)                                 \
                                      {                                                  \
                                        Printf("Out: '%s'\n\n", canonicalised);          \
                                                                                         \
                                        free(canonicalised);                             \
                                        canonicalised = NULL;                            \
                                      }                                                  \
                                      else Printf("Out: (Error)\n\n");                   \
                                    }

      TestCanonicalise("<Browse$Dir>.User.Hotlist");
      TestCanonicalise("Browse:User.Hotlist");
      TestCanonicalise("<Choices$Write>.WWW.Browser.Hotlist");
      TestCanonicalise("Choices:WWW.Browser.Hotlist");

      /*
       * Maybe we don't want this every time...!
       *
       * Printf("\n\n");
       * Printf("Checking path building\n");
       * Printf("======================\n\n");
       *
       * #define TestBuild(str) {                                                \
       *                          _kernel_oserror * e = utils_build_tree((str)); \
       *                                                                         \
       *                          if (!e) Printf("OK : '%s'\n", (str));          \
       *                          else                                           \
       *                          {                                              \
       *                            Printf("Err: '%s'\n", (str));                \
       *                            Printf("     '%s'\n", e->errmess);           \
       *                          }                                              \
       *                        }
       *
       * TestBuild("Mem::Sprites.$.This");
       * TestBuild("Mem::Sprites.$.This.That");
       * TestBuild("Mem::Sprites.$.This.That.The.Other");
       * TestBuild("ADFS::4.$.Hello.This.Is.A.Test");
       *
       */
1412
    }
1413
  }
1414 1415

#endif
1416 1417 1418 1419

/*************************************************/
/* termination()                                 */
/*                                               */
1420
/* Called by registration through the atexit     */
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445
/* 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);
  }

1446 1447 1448
  close_messages_file(cob); cob = NULL;
  close_messages_file(chb); chb = NULL;

1449
  fm_shutdown();
1450
  plugin_shutdown();
1451
  rma_shutdown();
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463
}

/*************************************************/
/* main()                                        */
/*                                               */
/* That which runs before all others.            */
/*************************************************/

int main(int argc, char * argv[])
{
  WimpPollBlock b;
  int           eventcode, time;
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474

  #ifdef SINGLE_USER

    int         argp     = 1;
    int         done_one = 0;

  #endif

  #ifdef USE_MALLOC_REPLACEMENT
    MemHeap_Initialise("Blimey, does this work?");
  #endif
1475

1476
  #ifdef INCLUDE_HEAPGRAPH
1477 1478 1479
    HeapGraph_RedirectAllocFns(NULL);
  #endif

1480 1481 1482
  #ifdef INCLUDE_HIERPROF
    HierProf_ProfileAllFunctions();
  #endif
1483

1484
  #ifdef INCLUDE_MEMCHECK
1485

1486 1487 1488 1489 1490 1491
    MemCheck_Init();
    MemCheck_InterceptSCLStringFunctions();
    MemCheck_RegisterArgs(argc, argv);
    MemCheck_SetStoreMallocFunctions(1);
    MemCheck_SetReportFrees(1);
    MemCheck_SetAutoOutputBlocksInfo(0);
1492

1493
  #endif
1494

1495
  #ifdef TRACE
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510

    /* Non-debug builds have a WimpSlot close to the actual startup */
    /* requirements. Debug builds have a huge slotsize because of   */
    /* all of the debug information, despite this being copied away */
    /* by the debugger on startup. This leaves a very large free    */
    /* chunk within the WimpSlot size in which malloc may operate,  */
    /* and thus creates a distinctly different environment for the  */
    /* memory system in a debug build.                              */
    /*                                                              */
    /* To try and get closer to the non-debug memory usage, TRACE   */
    /* builds will malloc the following large block in an attempt   */
    /* to soak up that initial free space.                          */

    malloc(2*1024*1024);

1511 1512
  #endif

1513 1514 1515
  /* NB, don't forget to echo any changes here with the duplicate code */
  /* just below the setjmp call later.                                 */

1516
  signal(SIGOSERROR, catch_errors); /* OS error            */
1517
  signal(SIGILL,     catch_errors); /* Illegal instruction */
1518 1519 1520
  signal(SIGSEGV,    catch_errors); /* Segment violation   */
  signal(SIGSTAK,    catch_errors); /* Stack overflow      */
  signal(SIGFPE,     catch_errors); /* FPE error           */
1521

1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
  /* 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;
  }

1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596
  #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);
1597
        if (strstr(argv[argp + 1], "JScr")) tl |= (1u<<24);
1598
        if (strstr(argv[argp + 1], "Hotl")) tl |= (1u<<25);
1599
        if (strstr(argv[argp + 1], "Save")) tl |= (1u<<26);
1600
        if (strstr(argv[argp + 1], "Drag")) tl |= (1u<<27);
1601
        if (strstr(argv[argp + 1], "MsgP")) tl |= (1u<<28);
1602 1603
        if (strstr(argv[argp + 1], "Choi")) tl |= (1u<<29);
        if (strstr(argv[argp + 1], "Plug")) tl |= (1u<<30);
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614

        if (strstr(argv[argp + 1], "All"))  tl  = 0xffffffff;

        argp += 2;
      }
    }

    if (tl & (1u<<5)) Printf("\nmain: Initialising\n");

  #endif

1615 1616
  /* Now do the bulk of application initialisation */

1617 1618 1619 1620 1621 1622 1623 1624
  initialise_app();

  #ifdef TRACE
    if (tl & (1u<<5)) Printf("main: Loading choices\n");
  #endif

  load_choices();

1625
  #ifndef SINGLE_USER
1626

1627 1628 1629 1630
    /* Multiuser builds need a unique filename base. Do this */
    /* checking Post_In / Post_Out as the Set Post_In /      */
    /* Post_Out dialogue box handler will expect to be able  */
    /* to go straight to multiuser_login().                  */
1631

1632
    multiuser_create_unique_postbox_filename();
1633

1634 1635 1636 1637 1638
    /* Want to check for Post_On / Post_Out exist at least */
    /* as readable directories or image files. If not, we  */
    /* should open the Set Post_In / Post_Out dialogue box */
    /* rather than log in, and let that start up the       */
    /* log-in procedure for us.                            */
1639

1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650
    {
      int in_ok  = 0;
      int out_ok = 0;

      setpboxes_check_boxes(&in_ok, &out_ok);

      if (!in_ok || !out_ok) show_error(setpboxes_show_dialogue());
      else                   show_error(multiuser_login());
    }

  #else
1651

1652 1653 1654 1655 1656 1657 1658
    /* Load the visit history, image history and hotlist  */
    /* (this will be the single user version of the login */
    /* call).                                             */

    show_error(multiuser_login());

  #endif
1659

1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689
  /* Try to start the proxy server if necessary */

  if (choices.start_proxy)
  {
    unsigned int handle = 0;

    utils_get_task_handle(lookup_token("ProxyName:Acorn WebServe",0,0), &handle);

    if (!handle)
    {
      #ifdef TRACE
        if (tl & (1u<<5)) Printf("main: Starting proxy server\n");
      #endif

      _swix(Wimp_StartTask,
            _IN(0),

            lookup_token("ProxyComm:Filer_Run WebServe:!Run",0,0));
    }

    #ifdef TRACE

      else
      {
        if (tl & (1u<<5)) Printf("main: Proxy server already running\n");
      }

    #endif
  }

1690 1691 1692 1693 1694 1695 1696
  #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.                 */

1697
  if (choices.keyboard_ctrl) mouse_watch_pointer_control(1);
1698

1699 1700 1701
  /* Command line arguments aren't of interest to a multiuser build  */
  /* because it will never have logged in by this point, so it can't */
  /* sensibly deal with fetching pages yet.                          */
1702

1703
  #ifdef SINGLE_USER
1704

1705 1706 1707
    /* 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. */
1708

1709
    done_one = 1;
1710

1711
    while (argc >= argp && done_one)
1712
    {
1713 1714 1715 1716 1717
      done_one = 0;

      /* Handle -html (HTML files) */

      if (argc >= argp + 1)
1718
      {
1719 1720 1721
        if (!strcmp(argv[argp], "-html"))
        {
          char url[Limits_URL];
1722

1723 1724 1725
          #ifdef TRACE
            if (tl & (1u<<5)) Printf("main: Handling -html CLI argument\n");
          #endif
1726

1727 1728
          StrNCpy0(url, argv[argp + 1]);
          urlutils_pathname_to_url(url, sizeof(url));
1729

1730
          windows_create_browser(url, NULL, NULL, NULL, Windows_CreateBrowser_Normal);
1731

1732 1733
          argp += 2, done_one = 1;
        }
1734 1735
      }

1736
      /* Handle -uri (URI files) */
1737

1738
      if (argc >= argp + 1)
1739
      {
1740 1741 1742
        if (!strcmp(argv[argp], "-uri"))
        {
          char url[Limits_URL];
1743

1744 1745 1746
          #ifdef TRACE
            if (tl & (1u<<5)) Printf("main: Handling -uri CLI argument\n");
          #endif
1747

1748
          urlutils_load_uri_file(url, sizeof(url), NULL, 0, argv[argp + 1]);
1749

1750
          windows_create_browser(url, NULL, NULL, NULL, Windows_CreateBrowser_Normal);
1751

1752 1753
          argp += 2, done_one = 1;
        }
1754 1755
      }

1756
      /* Handle -url (URL strings) */
1757

1758
      if (argc >= argp + 1)
1759
      {
1760 1761 1762 1763 1764
        if (!strcmp(argv[argp],"-url") || !strcmp(argv[argp],"-u"))
        {
          #ifdef TRACE
            if (tl & (1u<<5)) Printf("main: Handling -url CLI argument\n");
          #endif
1765

1766
          windows_create_browser(argv[argp+1], NULL, NULL, NULL, Windows_CreateBrowser_Normal);
1767

1768 1769
          argp += 2, done_one = 1;
        }
1770 1771
      }
    }
1772 1773

  #endif
1774 1775 1776 1777 1778 1779 1780

  #ifdef TRACE
    if (tl & (1u<<5)) Printf("main: Polling\n");
  #endif

  atexit(termination);

1781 1782 1783 1784 1785 1786 1787 1788 1789
  /* Long jump handler - most nasty or generally unexpected */
  /* errors will come back to here. The OS error abort      */
  /* handler jumps back here to deal with the error as we   */
  /* then have a clear stack; this is to avoid 'no stack    */
  /* for trap handler' errors caused by a SWI corrupting    */
  /* the value of R10.                                      */

  if (setjmp(env) == Main_FromCatchErrors)
  {
1790 1791 1792
    char         * tok        = NULL;
    unsigned int * regdump    = NULL;
    unsigned int * os_regdump = NULL;
1793 1794
    char           pc[16];

1795 1796
    print_abort_print();

1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850
    /* Sort out the register dump */

    _swix(OS_ChangeEnvironment,
          _INR(0,3) | _OUT(3),

          7, /* Call back */
          0,
          0,
          0,

          &regdump); /* Where the C library put the registers */

    _swix(OS_ChangeEnvironment,
          _INR(0,3) | _OUT(1),

          13, /* Exception registers */
          0,
          0,
          0,

          &os_regdump); /* Where *ShowRegs gets them from */

    /* Copy the C register dump into the OS space */

    if (regdump && os_regdump) memcpy(os_regdump, regdump, 4 * 16);

    /* Store a more sensible error in the error block 'erb' where possible. */

    switch (erb.errnum)
    {
      case 0x80000000: tok = "EZeros0"; break;
      case 0x80000001: tok = "EZeros1"; break;
      case 0x80000002: tok = "EZeros2"; break;
      case 0x80000003: tok = "EZeros3"; break;
      case 0x80000005: tok = "EZeros5"; break;
    }

    if (tok)
    {
      char * error;

      /* If we know the PC, put this in the message */

      if (!regdump) sprintf(pc, "&deaddead");
      else          sprintf(pc, "&%08X", os_regdump[15] &~ 0xfc000003);

      error = lookup_token(tok, 0, pc);

      /* If the message token wasn't found, use the OS error, */
      /* otherwise copy the new one into the error block.     */

      if (strcmp(error, "!")) StrNCpy0(erb.errmess, error);
    }

1851 1852 1853 1854 1855
    /* Need to reinstall the signal handlers since the run-time */
    /* system will have removed them 'for your saftey and       */
    /* convenience (TM)'. Don't forget to keep this list up to  */
    /* date with the code near the top of the function.         */

1856
    signal(SIGOSERROR, catch_errors); /* OS error            */
1857
    signal(SIGILL,     catch_errors); /* Illegal instruction */
1858 1859 1860
    signal(SIGSEGV,    catch_errors); /* Segment violation   */
    signal(SIGSTAK,    catch_errors); /* Stack overflow      */
    signal(SIGFPE,     catch_errors); /* FPE error           */
1861 1862 1863

    show_error_cont(&erb);
  }
1864

1865
  while (!quit)
1866
  {
1867 1868 1869 1870 1871 1872 1873
    /* We use flex's deferred compaction, so ensure the */
    /* heap is as small as possible.                    */

    flex_compact();

    /* What time is it? (For Wimp_PollIdle) */

1874 1875 1876 1877 1878
    _swix(OS_ReadMonotonicTime,
          _OUT(0),

          &time);

1879 1880
    /* Use PollIdle, but want drag events to be as responsive as possible */

1881 1882
    ChkError(event_poll_idle(&eventcode,
                             &b,
1883
                             time + !drag_in_progress,
1884 1885 1886 1887
                             NULL));
  }

  #ifdef TRACE
1888 1889 1890
    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);
1891 1892
  #endif

1893
  /* Save hotlist, histories etc., and logout if a multiuser build */
1894

1895
  show_error_ret(multiuser_logout());
1896

1897 1898 1899 1900
  /* This will call the termination() function in passing */

  exit(EXIT_SUCCESS);
}
1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935

/*************************************************/
/* catch_errors()                                */
/*                                               */
/* Catch OS errors and report them with the      */
/* opportunity to continue or quit (done inside  */
/* main itself).                                 */
/*                                               */
/* This is the last function in the file since   */
/* it plays around with stack checking, and you  */
/* can't read the previous state. If this was in */
/* the middle of the source and someone wrote a  */
/* #pragma above it, endless confusion could     */
/* otherwise arise as to why the instruction had */
/* no effect on some of the functions here...    */
/*                                               */
/* Parameters: The signal number (ignored).      */
/*************************************************/

#pragma no_check_stack

static void catch_errors(int signum)
{
  /* Store the error locally */

  erb = *_kernel_last_oserror();

  /* Go back to main to report the error */

  longjmp(env, Main_FromCatchErrors);

  /* Just in case... */

  exit(EXIT_FAILURE);
}